1 /* aNetHack 0.0.1 macmenu.c $ANH-Date: 1432512797 2015/05/25 00:13:17 $ $ANH-Branch: master $:$ANH-Revision: 1.13 $ */
2 /* Copyright (c) Macintosh aNetHack Port Team, 1993. */
3 /* aNetHack may be freely redistributed. See license for details. */
5 /****************************************\
6 * Extended Macintosh menu support
8 * provides access to all keyboard commands from cmd.c
9 * provides control key functionality for classic keyboards
10 * provides key equivalent references and logical menu groups
11 * supports various menu highlighting modes
12 \****************************************/
14 /****************************************\
17 * 930512 - More bug fixes and getting tty to work again, Jon W{tte
18 * 930508 - Bug fixes in-flight, Jon W{tte
19 * 04/29/93 - 1st Release Draft, David Hairston
20 * 04/11/93 - 1st Draft, David Hairston
21 \****************************************/
23 /******** Application Defines ********/
28 #include "patchlevel.h"
30 /******** Toolbox Defines ********/
31 #if !TARGET_API_MAC_CARBON
34 #include <Resources.h>
35 #include <TextUtils.h>
36 #include <ToolUtils.h>
40 /* Borrowed from the Mac tty port */
41 extern WindowPtr _mt_window
;
43 /******** Local Defines ********/
45 /* 'MNU#' (menu list record) */
46 typedef union menuRefUnn
{
47 short mresID
; /* MENU resource ID (before GetMenu) */
48 MenuHandle mhnd
; /* MENU handle (after GetMenu) */
51 typedef struct menuListRec
{
55 } menuListRec
, *menuListPtr
, **menuListHandle
;
57 /* indices and resource IDs of the menu list data */
66 /* the following mref[] indices are reserved */
77 /* the following menu items are reserved */
80 menuAppleAboutBox
= 1,
95 /* standard minimum Edit menu items */
98 menuWizardAttributes
= 1
102 * menuListRec data (preloaded and locked) specifies the number of menus in
103 * the menu bar, the number of hierarchal or submenus and the menu IDs of
104 * all of those menus. menus that go into in the menu bar are specified by
105 * 'MNU#' 128 and submenus are specified by 'MNU#' 129. the fields of the
107 * firstMenuID - the menu ID (not resource ID) of the 1st menu. subsequent
108 * menus in the list are _forced_ to have consecutively incremented IDs.
109 * numMenus - the total count of menus in a given list (and the extent of
111 * mref[] - initially the MENU resource ID is stored in the placeholder for
112 * the resource handle. after loading (GetResource), the menu handle
113 * is stored and the menu ID, in memory, is set as noted above.
115 * NOTE: a ResEdit template editor is supplied to edit the 'MNU#' resources.
117 * NOTE: the resource IDs do not need to match the menu IDs in a menu list
118 * record although they have been originally set that way.
120 * NOTE: the menu ID's of menus in the submenu list record may be reset, as
121 * noted above. it is the programmers responsibility to make sure that
122 * submenu references/IDs are valid.
124 * WARNING: the existence of the submenu list record is assumed even if the
125 * number of submenus is zero. also, no error checking is done on the
126 * extents of the menu IDs. this must be correctly setup by the programmer.
129 #define ID1_MBAR pMenuList[listMenubar]->firstMenuID
130 #define ID1_SUBM pMenuList[listSubmenu]->firstMenuID
132 #define NUM_MBAR pMenuList[listMenubar]->numMenus
133 #define NUM_SUBM pMenuList[listSubmenu]->numMenus
135 #define MHND_APPLE pMenuList[listMenubar]->mref[menuApple].mhnd
136 #define MHND_FILE pMenuList[listMenubar]->mref[menuFile].mhnd
137 #define MHND_EDIT pMenuList[listMenubar]->mref[menuEdit].mhnd
139 #define MBARHND(x) pMenuList[listMenubar]->mref[(x)].mhnd
141 #define MHND_WIZ pMenuList[listSubmenu]->mref[menuWizard].mhnd
143 /* mutually exclusive (and prioritized) menu bar states */
150 mbarSpecial
/* explore or debug mode */
153 #define WKND_MAP (WIN_BASE_KIND + NHW_MAP)
155 /* menu routine error numbers */
159 errGetANDlogTemplate
,
166 /* menu 'STR#' comment char */
167 #define mstrEndChar 0xA5 /* '\245' or option-* or "bullet" */
171 alrt_Menu_start
= 5000,
172 alrtMenuNote
= alrt_Menu_start
,
177 #define beepMenuAlertErr 1 /* # of SysBeep()'s before exitting */
178 enum { bttnMenuAlertNo
= 1, bttnMenuAlertYes
};
180 /******** Globals ********/
181 static unsigned char *menuErrStr
[err_Menu_total
] = {
182 "\pAbort: Bad \'MNU#\' resource!", /* errGetMenuList */
183 "\pAbort: Bad \'MENU\' resource!", /* errGetMenu */
184 "\pAbort: Bad \'DLOG\' resource!", /* errGetANDlogTemplate */
185 "\pAbort: Bad \'DITL\' resource!", /* errGetANDlogItems */
186 "\pAbort: Bad Dialog Allocation!", /* errGetANDialog */
187 "\pAbort: Bad Menu Allocation!", /* errANNewMenu */
189 static menuListPtr pMenuList
[2];
190 static short theMenubar
= mbarDA
; /* force initial update */
191 static short kAdjustWizardMenu
= 1;
193 /******** Prototypes ********/
194 #if !TARGET_API_MAC_CARBON
195 static void alignAD(Rect
*, short);
197 static void mustGetMenuAlerts(void);
198 static void menuError(short);
199 static void aboutaNetHack(void);
200 static void askSave(void);
201 static void askQuit(void);
203 /*** Askname dialog box ***/
205 #define RSRC_ASK 6000 /* Askname dialog and item list */
206 #define RSRC_ASK_PLAY 1 /* Play button */
207 #define RSRC_ASK_QUIT 2 /* Quit button */
208 #define RSRC_ASK_DEFAULT 3 /* Default ring */
209 #define RSRC_ASK_ROLE 4 /* Role popup menu */
210 #define RSRC_ASK_RACE 5 /* Race popup menu */
211 #define RSRC_ASK_GEND 6 /* Gender popup menu */
212 #define RSRC_ASK_ALIGN 7 /* Alignment popup menu */
213 #define RSRC_ASK_MODE 8 /* Mode popup menu */
214 #define RSRC_ASK_NAME 9 /* Name text field */
215 #define RSRC_ASK_MAX 10 /* Maximum enabled item */
217 #define KEY_MASK 0xff00
218 #define KEY_RETURN 0x2400
219 #define KEY_ENTER 0x4c00
220 #define KEY_ESCAPE 0x3500
221 #define CH_MASK 0x00ff
222 #define CH_RETURN 0x000d
223 #define CH_ENTER 0x0003
224 #define CH_ESCAPE 0x001b
226 static void ask_restring(const char *cstr
, unsigned char *pstr
);
227 static void ask_enable(DialogRef wind
, short item
, int enable
);
228 static pascal void ask_redraw(DialogRef wind
, DialogItemIndex item
);
229 static pascal Boolean
230 ask_filter(DialogRef wind
, EventRecord
*event
, DialogItemIndex
*item
);
231 #define noresource(t, n) \
242 static MenuHandle askmenu
[RSRC_ASK_MAX
];
243 static int askselect
[RSRC_ASK_MAX
];
244 #define currrole askselect[RSRC_ASK_ROLE]
245 #define currrace askselect[RSRC_ASK_RACE]
246 #define currgend askselect[RSRC_ASK_GEND]
247 #define curralign askselect[RSRC_ASK_ALIGN]
248 #define currmode askselect[RSRC_ASK_MODE]
250 static RGBColor blackcolor
= { 0x0000, 0x0000, 0x0000 },
251 // indentcolor = {0x4000, 0x4000, 0x4000},
252 darkcolor
= { 0x8000, 0x8000, 0x8000 },
253 backcolor
= { 0xdddd, 0xdddd, 0xdddd },
254 lightcolor
= { 0xffff, 0xffff, 0xffff },
255 whitecolor
= { 0xffff, 0xffff, 0xffff };
257 /* Convert a mixed-case C string to a Capitalized Pascal string */
259 ask_restring(const char *cstr
, unsigned char *pstr
)
263 for (i
= 0; *cstr
&& (i
< 255); i
++)
264 pstr
[i
+ 1] = *cstr
++;
266 if ((pstr
[1] >= 'a') && (pstr
[1] <= 'z'))
267 pstr
[1] += 'A' - 'a';
271 /* Enable the dialog item with the given index */
273 ask_enable(DialogRef wind
, short item
, int enable
)
279 /* Enable or disable the appropriate item */
280 GetDialogItem(wind
, item
, &type
, &handle
, &rect
);
282 type
&= ~itemDisable
;
285 HiliteControl((ControlHandle
) handle
, enable
? 0 : 255);
286 SetDialogItem(wind
, item
, type
, handle
, &rect
);
291 ask_redraw(DialogRef wind
, DialogItemIndex item
)
296 static char *modechar
= "NED";
298 /* Which item shall we redraw? */
299 GetDialogItem(wind
, item
, &type
, &handle
, &rect
);
301 case RSRC_ASK_DEFAULT
:
303 FrameRoundRect(&rect
, 16, 16);
311 if (macFlags
.color
) {
312 RGBForeColor(&blackcolor
);
313 RGBBackColor(&backcolor
);
319 /* Draw the frame and drop shadow */
323 MoveTo(rect
.right
, rect
.top
+ 1);
324 LineTo(rect
.right
, rect
.bottom
);
325 LineTo(rect
.left
+ 1, rect
.bottom
);
327 /* Draw the menu character */
328 MoveTo(rect
.left
+ 4, rect
.top
+ 12);
331 DrawText(roles
[askselect
[item
]].filecode
, 0, 3);
334 DrawText(races
[askselect
[item
]].filecode
, 0, 3);
337 DrawText(genders
[askselect
[item
]].filecode
, 0, 3);
340 DrawText(aligns
[askselect
[item
]].filecode
, 0, 3);
343 DrawChar(modechar
[askselect
[item
]]);
347 /* Draw the popup symbol */
348 MoveTo(rect
.right
- 16, rect
.top
+ 5);
349 LineTo(rect
.right
- 6, rect
.top
+ 5);
350 LineTo(rect
.right
- 11, rect
.top
+ 10);
351 LineTo(rect
.right
- 15, rect
.top
+ 6);
352 LineTo(rect
.right
- 8, rect
.top
+ 6);
353 LineTo(rect
.right
- 11, rect
.top
+ 9);
354 LineTo(rect
.right
- 13, rect
.top
+ 7);
355 LineTo(rect
.right
- 10, rect
.top
+ 7);
356 LineTo(rect
.right
- 11, rect
.top
+ 8);
358 /* Draw the shadow */
359 InsetRect(&rect
, 1, 1);
360 if (macFlags
.color
) {
363 /* Save the foreground color */
364 GetForeColor(&color
);
366 /* Draw the top and left */
367 RGBForeColor(&lightcolor
);
368 MoveTo(rect
.left
, rect
.bottom
- 1);
369 LineTo(rect
.left
, rect
.top
);
370 LineTo(rect
.right
- 1, rect
.top
);
372 /* Draw the bottom and right */
373 RGBForeColor(&darkcolor
);
374 MoveTo(rect
.right
- 1, rect
.top
+ 1);
375 LineTo(rect
.right
- 1, rect
.bottom
- 1);
376 LineTo(rect
.left
+ 1, rect
.bottom
- 1);
378 /* Restore the foreground color */
379 RGBForeColor(&color
);
385 if (macFlags
.color
) {
386 RGBForeColor(&whitecolor
);
387 RGBBackColor(&whitecolor
);
393 InsetRect(&rect
, -1, -1);
395 InsetRect(&rect
, -1, -1);
397 InsetRect(&rect
, -2, -2);
398 if (macFlags
.color
) {
399 /* Draw the top and left */
400 RGBForeColor(&darkcolor
);
401 MoveTo(rect
.left
, rect
.bottom
- 1);
402 LineTo(rect
.left
, rect
.top
);
403 LineTo(rect
.right
- 1, rect
.top
);
405 /* Draw the bottom and right */
406 RGBForeColor(&lightcolor
);
407 MoveTo(rect
.right
- 1, rect
.top
+ 1);
408 LineTo(rect
.right
- 1, rect
.bottom
- 1);
409 LineTo(rect
.left
+ 1, rect
.bottom
- 1);
411 /* Restore the colors */
412 RGBForeColor(&blackcolor
);
413 RGBBackColor(&backcolor
);
420 static pascal Boolean
421 ask_filter(DialogRef wind
, EventRecord
*event
, DialogItemIndex
*item
)
425 switch (event
->what
) {
428 ch
= event
->message
& CH_MASK
;
429 key
= event
->message
& KEY_MASK
;
430 /* Handle equivalents for OK */
431 if ((ch
== CH_RETURN
) || (key
== KEY_RETURN
) || (ch
== CH_ENTER
)
432 || (key
== KEY_ENTER
)) {
433 if (GetDialogTextEditHandle(wind
)[0]->teLength
) {
434 FlashButton(wind
, RSRC_ASK_PLAY
);
435 *item
= RSRC_ASK_PLAY
;
440 /* Handle equivalents for Normal/Explore/Debug */
441 if ((event
->modifiers
& cmdKey
) && (ch
== 'n')) {
443 ask_redraw(wind
, RSRC_ASK_MODE
);
444 *item
= RSRC_ASK_MODE
;
447 if ((event
->modifiers
& cmdKey
) && (ch
== 'e')) {
449 ask_redraw(wind
, RSRC_ASK_MODE
);
450 *item
= RSRC_ASK_MODE
;
453 if ((event
->modifiers
& cmdKey
) && (ch
== 'd')) {
455 ask_redraw(wind
, RSRC_ASK_MODE
);
456 *item
= RSRC_ASK_MODE
;
459 /* Handle equivalents for Cancel and Quit */
460 if ((ch
== CH_ESCAPE
) || (key
== KEY_ESCAPE
)
461 || ((event
->modifiers
& cmdKey
) && (ch
== 'q'))
462 || ((event
->modifiers
& cmdKey
) && (ch
== '.'))) {
463 FlashButton(wind
, RSRC_ASK_QUIT
);
464 *item
= RSRC_ASK_QUIT
;
469 ask_redraw(wind
, RSRC_ASK_NAME
);
481 short i
, j
, item
, type
;
486 UserItemUPP redraw
= NewUserItemUPP(ask_redraw
);
487 ModalFilterUPP filter
= NewModalFilterUPP(ask_filter
);
489 /* Create the dialog */
490 if (!(askdialog
= GetNewDialog(RSRC_ASK
, NULL
, (WindowRef
) -1)))
491 noresource('DLOG', RSRC_ASK
);
493 SetPortDialogPort(askdialog
);
495 /* Initialize the name text item */
496 ask_restring(plname
, str
);
498 GetDialogItem(askdialog
, RSRC_ASK_NAME
, &type
, &handle
, &rect
);
499 SetDialogItemText(handle
, str
);
505 if (plname
&& plname
[0]) {
506 strcpy ((char *) pName
, plname
);
507 c2pstr ((char *) pName
);
510 h
= GetResource ('STR ', -16096);
511 if (((Handle
) 0 != h
) && (GetHandleSize (h
) > 0)) {
517 BlockMove (*h
, pName
, **h
+ 1);
522 GetDialogItem(askdialog
, RSRC_ASK_NAME
, &type
, &handle
, &rect
);
523 SetDialogItemText(handle
, pName
);
524 if (pName
[0] > 2 && pName
[pName
[0] - 1] == '-') {
525 short role
= (*pANR
).anMenu
[anRole
];
526 char suffix
= (char) pName
[pName
[0]],
527 *sfxindx
= strchr(pl_classes
, suffix
);
530 role
= (short) (sfxindx
- pl_classes
);
531 else if (suffix
== '@')
532 role
= (short) rn2((int) strlen(pl_classes
));
533 (*pANR
).anMenu
[anRole
] = role
;
538 SelectDialogItemText(askdialog
, RSRC_ASK_NAME
, 0, 32767);
540 /* Initialize the role popup menu */
541 if (!(askmenu
[RSRC_ASK_ROLE
] = NewMenu(RSRC_ASK_ROLE
, "\p")))
542 fatal("\pCannot create role menu");
543 for (i
= 0; roles
[i
].name
.m
; i
++) {
544 ask_restring(roles
[i
].name
.m
, str
);
545 AppendMenu(askmenu
[RSRC_ASK_ROLE
], str
);
547 InsertMenu(askmenu
[RSRC_ASK_ROLE
], hierMenu
);
548 if (flags
.initrole
>= 0)
549 currrole
= flags
.initrole
;
550 /* Check for backward compatibility */
551 else if ((currrole
= str2role(pl_character
)) < 0)
552 currrole
= randrole();
554 /* Initialize the race popup menu */
555 if (!(askmenu
[RSRC_ASK_RACE
] = NewMenu(RSRC_ASK_RACE
, "\p")))
556 fatal("\pCannot create race menu");
557 for (i
= 0; races
[i
].noun
; i
++) {
558 ask_restring(races
[i
].noun
, str
);
559 AppendMenu(askmenu
[RSRC_ASK_RACE
], str
);
561 InsertMenu(askmenu
[RSRC_ASK_RACE
], hierMenu
);
562 if (flags
.initrace
>= 0)
563 currrace
= flags
.initrace
;
565 currrace
= randrace(currrole
);
567 /* Initialize the gender popup menu */
568 if (!(askmenu
[RSRC_ASK_GEND
] = NewMenu(RSRC_ASK_GEND
, "\p")))
569 fatal("\pCannot create gender menu");
570 for (i
= 0; i
< ROLE_GENDERS
; i
++) {
571 ask_restring(genders
[i
].adj
, str
);
572 AppendMenu(askmenu
[RSRC_ASK_GEND
], str
);
574 InsertMenu(askmenu
[RSRC_ASK_GEND
], hierMenu
);
575 if (flags
.initgend
>= 0)
576 currgend
= flags
.initgend
;
577 else if (flags
.female
)
580 currgend
= randgend(currrole
, currrace
);
582 /* Initialize the alignment popup menu */
583 if (!(askmenu
[RSRC_ASK_ALIGN
] = NewMenu(RSRC_ASK_ALIGN
, "\p")))
584 fatal("\pCannot create alignment menu");
585 for (i
= 0; i
< ROLE_ALIGNS
; i
++) {
586 ask_restring(aligns
[i
].adj
, str
);
587 AppendMenu(askmenu
[RSRC_ASK_ALIGN
], str
);
589 InsertMenu(askmenu
[RSRC_ASK_ALIGN
], hierMenu
);
590 if (flags
.initalign
>= 0)
591 curralign
= flags
.initalign
;
593 curralign
= randalign(currrole
, currrace
);
595 /* Initialize the mode popup menu */
596 if (!(askmenu
[RSRC_ASK_MODE
] = NewMenu(RSRC_ASK_MODE
, "\p")))
597 fatal("\pCannot create mode menu");
598 AppendMenu(askmenu
[RSRC_ASK_MODE
], "\pNormal");
599 AppendMenu(askmenu
[RSRC_ASK_MODE
], "\pExplore");
600 AppendMenu(askmenu
[RSRC_ASK_MODE
], "\pDebug");
601 InsertMenu(askmenu
[RSRC_ASK_MODE
], hierMenu
);
604 /* Set the redraw procedures */
605 for (item
= RSRC_ASK_DEFAULT
; item
<= RSRC_ASK_MODE
; item
++) {
606 GetDialogItem(askdialog
, item
, &type
, &handle
, &rect
);
607 SetDialogItem(askdialog
, item
, type
, (Handle
) redraw
, &rect
);
610 /* Handle dialog events */
612 /* Adjust the Play button */
613 ask_enable(askdialog
, RSRC_ASK_PLAY
,
614 GetDialogTextEditHandle(askdialog
)[0]->teLength
);
616 /* Adjust the race popup menu */
619 if (validrace(currrole
, j
)) {
620 EnableMenuItem(askmenu
[RSRC_ASK_RACE
], j
+ 1);
621 CheckMenuItem(askmenu
[RSRC_ASK_RACE
], j
+ 1, currrace
== j
);
623 DisableMenuItem(askmenu
[RSRC_ASK_RACE
], j
+ 1);
624 CheckMenuItem(askmenu
[RSRC_ASK_RACE
], j
+ 1, FALSE
);
625 if ((currrace
== j
) && !races
[++currrace
].noun
)
628 if (!races
[++j
].noun
)
632 GetDialogItem(askdialog
, RSRC_ASK_RACE
, &type
, &handle
, &rect
);
633 InvalWindowRect(GetDialogWindow(askdialog
), &rect
);
636 /* Adjust the gender popup menu */
639 if (validgend(currrole
, currrace
, j
)) {
640 EnableMenuItem(askmenu
[RSRC_ASK_GEND
], j
+ 1);
641 CheckMenuItem(askmenu
[RSRC_ASK_GEND
], j
+ 1, currgend
== j
);
643 DisableMenuItem(askmenu
[RSRC_ASK_GEND
], j
+ 1);
644 CheckMenuItem(askmenu
[RSRC_ASK_GEND
], j
+ 1, FALSE
);
645 if ((currgend
== j
) && (++currgend
>= ROLE_GENDERS
))
648 if (++j
>= ROLE_GENDERS
)
652 GetDialogItem(askdialog
, RSRC_ASK_GEND
, &type
, &handle
, &rect
);
653 InvalWindowRect(GetDialogWindow(askdialog
), &rect
);
656 /* Adjust the alignment popup menu */
659 if (validalign(currrole
, currrace
, j
)) {
660 EnableMenuItem(askmenu
[RSRC_ASK_ALIGN
], j
+ 1);
661 CheckMenuItem(askmenu
[RSRC_ASK_ALIGN
], j
+ 1, curralign
== j
);
663 DisableMenuItem(askmenu
[RSRC_ASK_ALIGN
], j
+ 1);
664 CheckMenuItem(askmenu
[RSRC_ASK_ALIGN
], j
+ 1, FALSE
);
665 if ((curralign
== j
) && (++curralign
>= ROLE_ALIGNS
))
668 if (++j
>= ROLE_ALIGNS
)
671 if (curralign
!= i
) {
672 GetDialogItem(askdialog
, RSRC_ASK_ALIGN
, &type
, &handle
, &rect
);
673 InvalWindowRect(GetDialogWindow(askdialog
), &rect
);
676 /* Adjust the role popup menu */
677 for (i
= 0; roles
[i
].name
.m
; i
++) {
678 ask_restring((currgend
&& roles
[i
].name
.f
) ? roles
[i
].name
.f
681 SetMenuItemText(askmenu
[RSRC_ASK_ROLE
], i
+ 1, str
);
682 CheckMenuItem(askmenu
[RSRC_ASK_ROLE
], i
+ 1, currrole
== i
);
685 /* Adjust the mode popup menu */
686 CheckMenuItem(askmenu
[RSRC_ASK_MODE
], 1, currmode
== 0);
687 CheckMenuItem(askmenu
[RSRC_ASK_MODE
], 2, currmode
== 1);
688 CheckMenuItem(askmenu
[RSRC_ASK_MODE
], 3, currmode
== 2);
690 /* Wait for an action on an item */
691 ModalDialog(filter
, &item
);
703 GetDialogItem(askdialog
, item
, &type
, &handle
, &rect
);
704 pt
= *(Point
*) &rect
;
706 if (!!(i
= PopUpMenuSelect(askmenu
[item
], pt
.v
, pt
.h
,
707 askselect
[item
] + 1)))
708 askselect
[item
] = LoWord(i
) - 1;
709 InvalWindowRect(GetDialogWindow(askdialog
), &rect
);
713 /* limit the data here to 25 chars */
715 short beepTEDelete
= 1;
717 while ((**dRec
.textH
).teLength
> 25)
719 if (beepTEDelete
++ <= 3)
721 TEKey('\b', dRec
.textH
);
725 /* special case filter (that doesn't plug all the holes!) */
726 if (((**dRec
.textH
).teLength
== 1) && (**((**dRec
.textH
).hText
) < 32))
727 TEKey('\b', dRec
.textH
);
731 } while ((item
!= RSRC_ASK_PLAY
) && (item
!= RSRC_ASK_QUIT
));
733 /* Process the name */
734 GetDialogItem(askdialog
, RSRC_ASK_NAME
, &type
, &handle
, &rect
);
735 GetDialogItemText(handle
, str
);
736 if (str
[0] > PL_NSIZ
- 1)
737 str
[0] = PL_NSIZ
- 1;
738 BlockMove(&str
[1], plname
, str
[0]);
739 plname
[str
[0]] = '\0';
741 /* Destroy the dialog */
742 for (i
= RSRC_ASK_ROLE
; i
<= RSRC_ASK_MODE
; i
++) {
744 DisposeMenu(askmenu
[i
]);
747 DisposeDialog(askdialog
);
748 DisposeModalFilterUPP(filter
);
749 DisposeUserItemUPP(redraw
);
751 /* Process the mode */
752 wizard
= discover
= 0;
756 case 1: /* Explore */
761 strcpy(plname
, WIZARD_NAME
);
767 /* Process the role */
768 strcpy(pl_character
, roles
[currrole
].name
.m
);
769 flags
.initrole
= currrole
;
771 /* Process the race */
772 flags
.initrace
= currrace
;
774 /* Process the gender */
775 flags
.female
= flags
.initgend
= currgend
;
777 /* Process the alignment */
778 flags
.initalign
= curralign
;
783 /*** Menu bar routines ***/
785 #if !TARGET_API_MAC_CARBON
787 alignAD(Rect
*pRct
, short vExempt
)
791 GetQDGlobalsScreenBits(&qbitmap
);
792 (*pRct
).right
-= (*pRct
).left
; /* width */
793 (*pRct
).bottom
-= (*pRct
).top
; /* height */
794 (*pRct
).left
= (qbitmap
.bounds
.right
- (*pRct
).right
) / 2;
795 (*pRct
).top
= (qbitmap
.bounds
.bottom
- (*pRct
).bottom
- vExempt
) / 2;
796 (*pRct
).top
+= vExempt
;
797 (*pRct
).right
+= (*pRct
).left
;
798 (*pRct
).bottom
+= (*pRct
).top
;
808 for (i
= alrt_Menu_start
; i
< alrt_Menu_limit
; i
++) {
809 if (!(hRct
= (Rect
**) GetResource('ALRT', i
))) /* AlertTHndl */
811 for (i
= 0; i
< beepMenuAlertErr
; i
++)
816 #if !TARGET_API_MAC_CARBON
817 alignAD(*hRct
, GetMBarHeight());
823 menuError(short menuErr
)
827 for (i
= 0; i
< beepMenuAlertErr
; i
++)
830 ParamText(menuErrStr
[menuErr
], "\p", "\p", "\p");
831 (void) Alert(alrtMenuNote
, (ModalFilterUPP
) 0L);
839 static Boolean was_inited
= 0;
841 menuListHandle mlHnd
;
850 for (i
= listMenubar
; i
<= listSubmenu
; i
++) {
852 (menuListHandle
) GetResource('MNU#', (menuBarListID
+ i
))))
853 menuError(errGetMenuList
);
855 pMenuList
[i
] = (menuListPtr
) NewPtr(GetHandleSize((Handle
) mlHnd
));
856 *pMenuList
[i
] = **mlHnd
;
858 for (j
= 0; j
< pMenuList
[i
]->numMenus
; j
++) {
859 if (!(menu
= (MenuHandle
) GetMenu((**mlHnd
).mref
[j
].mresID
))) {
861 NumToString((**mlHnd
).mref
[j
].mresID
, d
);
862 menuError(errGetMenu
);
865 pMenuList
[i
]->mref
[j
].mhnd
= menu
;
866 SetMenuID(menu
, j
+ (**mlHnd
).firstMenuID
); /* consecutive IDs */
868 /* expand apple menu */
869 if ((i
== listMenubar
) && (j
== menuApple
)) {
870 AppendResMenu(menu
, 'DRVR');
873 InsertMenu(menu
, ((i
== listSubmenu
) ? hierMenu
: 0));
881 AdjustMenus(short dimMenubar
)
883 short newMenubar
= mbarRegular
;
884 WindowRef win
= FrontWindow();
888 * if (windowprocs != mac_procs) {
892 /* determine the new menubar state */
894 newMenubar
= mbarDim
;
896 newMenubar
= mbarNoWindows
;
897 else if (GetWindowKind(win
) < 0)
899 else if (!IsWindowVisible(_mt_window
))
900 newMenubar
= mbarNoMap
;
902 if (newMenubar
!= mbarRegular
)
903 ; /* we've already found its state */
905 newMenubar
= mbarSpecial
;
907 if (kAdjustWizardMenu
) {
908 kAdjustWizardMenu
= 0;
910 SetMenuItemText(MHND_FILE
, menuFilePlayMode
, "\pDebug");
915 newMenubar
= mbarSpecial
;
917 if (kAdjustWizardMenu
) {
918 kAdjustWizardMenu
= 0;
920 SetMenuItemText(MHND_FILE
, menuFilePlayMode
, "\pExplore");
922 for (i
= CountMenuItems(MHND_WIZ
); i
> menuWizardAttributes
; i
--)
923 DeleteMenuItem(MHND_WIZ
, i
);
927 /* adjust the menubar, if there's a state change */
928 if (theMenubar
!= newMenubar
) {
929 switch (theMenubar
= newMenubar
) {
931 /* disable all menus (except the apple menu) */
932 for (i
= menuFile
; i
< NUM_MBAR
; i
++)
933 DisableMenuItem(MBARHND(i
), 0);
939 /* enable the file menu, but ... */
940 EnableMenuItem(MHND_FILE
, 0);
942 /* ... disable the window commands! */
943 for (i
= menuFileRedraw
; i
<= menuFileEnterExplore
; i
++)
944 DisableMenuItem(MHND_FILE
, i
);
946 /* ... and disable the rest of the menus */
947 for (i
= menuEdit
; i
< NUM_MBAR
; i
++)
948 DisableMenuItem(MBARHND(i
), 0);
950 if (theMenubar
== mbarDA
)
951 EnableMenuItem(MHND_EDIT
, 0);
957 /* enable all menus ... */
958 for (i
= menuFile
; i
< NUM_MBAR
; i
++)
959 EnableMenuItem(MBARHND(i
), 0);
961 /* ... except the unused Edit menu */
962 DisableMenuItem(MHND_EDIT
, 0);
964 /* ... enable the window commands */
965 for (i
= menuFileRedraw
; i
<= menuFileEnterExplore
; i
++)
966 EnableMenuItem(MHND_FILE
, i
);
968 if (theMenubar
== mbarRegular
)
969 DisableMenuItem(MHND_FILE
, menuFilePlayMode
);
971 DisableMenuItem(MHND_FILE
, menuFileEnterExplore
);
981 DoMenuEvt(long menuEntry
)
983 short menuID
= HiWord(menuEntry
);
984 short menuItem
= LoWord(menuEntry
);
986 switch (menuID
- ID1_MBAR
) /* all submenus are default case */
989 if (menuItem
== menuAppleAboutBox
)
991 #if !TARGET_API_MAC_CARBON
993 unsigned char daName
[32];
995 GetMenuItemText(MHND_APPLE
, menuItem
, *(Str255
*) daName
);
996 (void) OpenDeskAcc(daName
);
1002 * Those direct calls are ugly: they should be installed into cmd.c .
1003 * Those AddToKeyQueue() calls are also ugly: they should be put into
1004 * the 'STR#' resource.
1008 case menuFileRedraw
:
1009 AddToKeyQueue('R' & 0x1f, 1);
1012 case menuFilePrevMsg
:
1013 AddToKeyQueue('P' & 0x1f, 1);
1016 case menuFileCleanup
:
1017 (void) SanePositions();
1020 case menuFileEnterExplore
:
1021 AddToKeyQueue('X', 1);
1035 #if !TARGET_API_MAC_CARBON
1036 (void) SystemEdit(menuItem
- 1);
1040 default: /* get associated string and add to key queue */
1045 GetIndString(mstr
, menuID
, menuItem
);
1046 if (mstr
[0] > QUEUE_LEN
)
1047 mstr
[0] = QUEUE_LEN
;
1049 for (i
= 1; ((i
<= mstr
[0]) && (mstr
[i
] != mstrEndChar
)); i
++)
1050 AddToKeyQueue(mstr
[i
], false);
1060 if (theMenubar
>= mbarRegular
) {
1061 (void) doversion(); /* is this necessary? */
1063 unsigned char aboutStr
[32] = "\paNetHack 3.4.";
1065 if (PATCHLEVEL
> 10) {
1066 aboutStr
[++aboutStr
[0]] = '0' + PATCHLEVEL
/ 10;
1069 aboutStr
[++aboutStr
[0]] = '0' + (PATCHLEVEL
% 10);
1071 ParamText(aboutStr
, "\p\rdevteam@www.anethack.org", "\p", "\p");
1072 (void) Alert(alrtMenuNote
, (ModalFilterUPP
) 0L);
1083 if (theMenubar
< mbarRegular
) {
1086 ParamText("\pReally Save?", "\p", "\p", "\p");
1087 itemHit
= Alert(alrtMenu_NY
, (ModalFilterUPP
) 0L);
1090 if (itemHit
!= bttnMenuAlertYes
) {
1097 AddToKeyQueue('S', 1);
1099 AddToKeyQueue('y', 1);
1112 if (!strcmp(windowprocs
.name
, "mac"))
1117 if (theMenubar
< mbarRegular
) {
1120 ParamText("\pReally Quit?", "\p", "\p", "\p");
1121 itemHit
= Alert(alrtMenu_NY
, (ModalFilterUPP
) 0L);
1124 if (itemHit
!= bttnMenuAlertYes
) {
1131 /* MWM -- forgive me lord, an even uglier kludge to deal with
1133 in command input handling
1136 quitinput
= "#quit\r";
1140 /* KMH -- Ugly kludge */
1142 AddToKeyQueue(*quitinput
++, 1);
1145 quitinput
= "y\rq\r\r\r";
1149 AddToKeyQueue(*quitinput
++, 1);