NHDT->ANH, nethack->anethack, nhdat->anhdat
[aNetHack.git] / sys / mac / macwin.c
blobc4ef35a25dcd00f7719056b51f3703ceb2dc7014
1 /* aNetHack 0.0.1 macwin.c $ANH-Date: 1432512796 2015/05/25 00:13:16 $ $ANH-Branch: master $:$ANH-Revision: 1.26 $ */
2 /* Copyright (c) Jon W{tte, Hao-Yang Wang, Jonathan Handler 1992. */
3 /* aNetHack may be freely redistributed. See license for details. */
5 /**********************************************************************
6 * Imported variables and functions
7 */
9 #include "hack.h"
10 #include "func_tab.h"
11 #include "macwin.h"
12 #include "mactty.h"
13 #include "wintty.h"
15 #if 1 /*!TARGET_API_MAC_CARBON*/
16 #include <LowMem.h>
17 #include <AppleEvents.h>
18 #include <Gestalt.h>
19 #include <TextUtils.h>
20 #include <DiskInit.h>
21 #include <ControlDefinitions.h>
22 #endif
24 /**********************************************************************
25 * Local variables and functions
28 #if 0 // TARGET_API_MAC_CARBON
29 static EventTypeSpec baseevents[] = {
30 { kEventClassKeyboard, kEventRawKeyDown },
31 { kEventClassKeyboard, kEventRawKeyRepeat },
32 { kEventClassMouse, kEventMouseMoved },
33 { kEventClassWindow, kEventWindowDrawContent },
34 { kEventClassWindow, kEventWindowHandleContentClick },
35 { kEventClassWindow, kEventWindowClose }
38 static EventTypeSpec msgevents[] = {
39 { kEventClassControl, kEventControlHit },
40 { kEventClassKeyboard, kEventRawKeyDown },
41 { kEventClassKeyboard, kEventRawKeyRepeat },
42 { kEventClassWindow, kEventWindowDrawContent },
43 { kEventClassWindow, kEventWindowHandleContentClick },
44 { kEventClassWindow, kEventWindowClose }
47 static EventTypeSpec menwevents[] = {
48 { kEventClassControl, kEventControlHit },
49 { kEventClassKeyboard, kEventRawKeyDown },
50 { kEventClassKeyboard, kEventRawKeyRepeat },
51 { kEventClassWindow, kEventWindowDrawContent },
52 { kEventClassWindow, kEventWindowHandleContentClick },
53 { kEventClassWindow, kEventWindowClose }
56 static EventTypeSpec textevents[] = {
57 { kEventClassControl, kEventControlHit },
58 { kEventClassKeyboard, kEventRawKeyDown },
59 { kEventClassKeyboard, kEventRawKeyRepeat },
60 { kEventClassWindow, kEventWindowDrawContent },
61 { kEventClassWindow, kEventWindowClose }
64 static EventTypeSpec globalevents[] = {
65 { kEventClassCommand, kEventCommandProcess }
68 EventTargetRef dispatcher;
69 EventHandlerUPP baseupp, msgupp, menwupp, textupp;
71 static pascal OSStatus BaseEvent(EventHandlerCallRef, EventRef, void *);
72 static void MsgUpdate(NhWindow *wind);
73 static pascal OSStatus MsgEvent(EventHandlerCallRef, EventRef, void *);
74 static void MenwUpdate(NhWindow *wind);
75 static pascal OSStatus MenwEvent(EventHandlerCallRef, EventRef, void *);
76 static void TextUpdate(NhWindow *wind);
77 static pascal OSStatus TextEvent(EventHandlerCallRef, EventRef, void *);
78 static pascal OSStatus GlobalEvent(EventHandlerCallRef, EventRef, void *);
80 #else
82 static void FDECL(GeneralKey, (EventRecord *, WindowPtr));
83 static void FDECL(macKeyMenu, (EventRecord *, WindowPtr));
84 static void FDECL(macKeyText, (EventRecord *, WindowPtr));
86 static void FDECL(macClickMessage, (EventRecord *, WindowPtr));
87 static void FDECL(macClickTerm, (EventRecord *, WindowPtr));
88 static void FDECL(macClickMenu, (EventRecord *, WindowPtr));
89 static void FDECL(macClickText, (EventRecord *, WindowPtr));
91 static short FDECL(macDoNull, (EventRecord *, WindowPtr));
92 static short FDECL(macUpdateMessage, (EventRecord *, WindowPtr));
93 static short FDECL(macUpdateMenu, (EventRecord *, WindowPtr));
94 static short FDECL(GeneralUpdate, (EventRecord *, WindowPtr));
96 static void FDECL(macCursorTerm, (EventRecord *, WindowPtr, RgnHandle));
97 static void FDECL(GeneralCursor, (EventRecord *, WindowPtr, RgnHandle));
98 #endif
100 static void TextUpdate(NhWindow *wind);
102 NhWindow *theWindows = (NhWindow *) 0;
103 Cursor qdarrow;
105 /* Borrowed from the Mac tty port */
106 extern WindowPtr _mt_window;
108 /* Some useful #defines for the scroll bar width and height */
109 #define SBARWIDTH 15
110 #define SBARHEIGHT 15
113 * We put a TE on the message window for the "top line" queries.
114 * top_line is the TE that holds both the query and the user's
115 * response. The first topl_query_len characters in top_line are
116 * the query, the rests are the response. topl_resp is the valid
117 * response to a yn query, while topl_resp[topl_def_idx] is the
118 * default response to a yn query.
120 static TEHandle top_line = (TEHandle) nil;
121 static int topl_query_len;
122 static int topl_def_idx = -1;
123 static char topl_resp[10] = "";
125 #define CHAR_ANY '\n'
128 * inSelect means we have a menu window up for selection or
129 * something similar. It makes the window with win number ==
130 * inSelect a movable modal (unfortunately without the border)
131 * and clicking the close box forces an RET into the key
132 * buffer. Don't forget to set inSelect to WIN_ERR when you're
133 * done...
135 static winid inSelect = WIN_ERR;
138 * The key queue ring buffer where Read is where to take from,
139 * Write is where next char goes and count is queue depth.
141 static unsigned char keyQueue[QUEUE_LEN];
142 static int keyQueueRead = 0, keyQueueWrite = 0, keyQueueCount = 0;
144 static Boolean gClickedToMove = 0; /* For ObscureCursor */
146 static Point clicked_pos; /* For nh_poskey */
147 static int clicked_mod;
148 static Boolean cursor_locked = false;
150 static ControlActionUPP
151 MoveScrollUPP; /* scrolling callback, init'ed in InitMac */
153 void
154 lock_mouse_cursor(Boolean new_cursor_locked)
156 cursor_locked = new_cursor_locked;
160 * Add key to input queue, force means flush left and replace if full
162 void
163 AddToKeyQueue(unsigned char ch, Boolean force)
165 if (keyQueueCount < QUEUE_LEN) {
166 keyQueue[keyQueueWrite++] = ch;
167 keyQueueCount++;
168 } else if (force) {
169 keyQueue[keyQueueWrite++] = ch;
170 keyQueueRead++;
171 if (keyQueueRead >= QUEUE_LEN)
172 keyQueueRead = 0;
173 keyQueueCount = QUEUE_LEN;
175 if (keyQueueWrite >= QUEUE_LEN)
176 keyQueueWrite = 0;
180 * Get key from queue
182 unsigned char
183 GetFromKeyQueue(void)
185 unsigned char ret;
187 if (keyQueueCount) {
188 ret = keyQueue[keyQueueRead++];
189 keyQueueCount--;
190 if (keyQueueRead >= QUEUE_LEN)
191 keyQueueRead = 0;
192 } else
193 ret = 0;
194 return ret;
198 * Cursor movement
200 static RgnHandle gMouseRgn = (RgnHandle) 0;
203 * _Gestalt madness - we rely heavily on the _Gestalt glue, since we
204 * don't check for the trap...
206 MacFlags macFlags;
209 * The screen layouts on the small 512x342 screen need special cares.
211 Boolean small_screen = 0;
213 #ifdef NHW_BASE
214 #undef NHW_BASE
215 #endif
216 #define NHW_BASE 0
218 static int FDECL(filter_scroll_key, (const int, NhWindow *));
220 #if 1 //!TARGET_API_MAC_CARBON
221 static void FDECL(DoScrollBar, (Point, short, ControlHandle, NhWindow *));
222 #endif
223 static pascal void FDECL(MoveScrollBar, (ControlHandle, short));
225 #if 1 //!TARGET_API_MAC_CARBON
226 typedef void (*CbFunc)(EventRecord *, WindowPtr);
227 typedef short (*CbUpFunc)(EventRecord *, WindowPtr);
228 typedef void (*CbCursFunc)(EventRecord *, WindowPtr, RgnHandle);
230 #define NUM_FUNCS 6
231 static const CbFunc winKeyFuncs[NUM_FUNCS] = { GeneralKey, GeneralKey,
232 GeneralKey, GeneralKey,
233 macKeyMenu, macKeyText };
235 static const CbFunc winClickFuncs[NUM_FUNCS] = {
236 (CbFunc) macDoNull, macClickMessage, macClickTerm,
237 macClickTerm, macClickMenu, macClickText
240 static const CbUpFunc winUpdateFuncs[NUM_FUNCS] = {
241 macDoNull, macUpdateMessage, image_tty,
242 image_tty, macUpdateMenu, GeneralUpdate
245 static const CbCursFunc winCursorFuncs[NUM_FUNCS] = {
246 (CbCursFunc) macDoNull, GeneralCursor, macCursorTerm,
247 macCursorTerm, GeneralCursor, GeneralCursor
249 #endif
251 static NhWindow *
252 GetNhWin(WindowPtr mac_win)
254 if (mac_win == _mt_window) /* term window is still maintained by both
255 systems, and */
256 return theWindows; /* WRefCon still refers to tty struct, so we have
257 to map it */
258 else {
259 NhWindow *aWin = (NhWindow *) GetWRefCon(mac_win);
260 if (aWin >= theWindows && aWin < &theWindows[NUM_MACWINDOWS])
261 return aWin;
263 return ((NhWindow *) nil);
266 Boolean
267 CheckNhWin(WindowPtr mac_win)
269 return GetNhWin(mac_win) != nil;
272 static pascal OSErr
273 AppleEventHandler(const AppleEvent *inAppleEvent, AppleEvent *outAEReply,
274 long inRefCon)
276 #if defined(__SC__) || defined(__MRC__)
277 #pragma unused(outAEReply, inRefCon)
278 #endif
279 Size actualSize;
280 DescType typeCode;
281 AEEventID EventID;
282 OSErr err;
284 /* Get Event ID */
285 err = AEGetAttributePtr(inAppleEvent, keyEventIDAttr, typeType, &typeCode,
286 &EventID, sizeof(EventID), &actualSize);
287 if (err == noErr) {
288 switch (EventID) {
289 default:
290 case kAEOpenApplication:
291 macFlags.gotOpen = 1;
292 /* fall through */
293 case kAEPrintDocuments:
294 err = errAEEventNotHandled;
295 break;
296 case kAEQuitApplication:
297 /* Flush key queue */
298 keyQueueCount = keyQueueWrite = keyQueueRead = 0;
299 AddToKeyQueue('S', 1);
300 break;
301 case kAEOpenDocuments: {
302 FSSpec fss;
303 FInfo fndrInfo;
304 AEKeyword keywd;
305 AEDescList docList;
306 long index, itemsInList;
308 if ((err = AEGetParamDesc(inAppleEvent, keyDirectObject,
309 typeAEList, &docList)) != noErr
310 || (err = AECountItems(&docList, &itemsInList)) != noErr) {
311 if (err == errAEDescNotFound)
312 itemsInList = 0;
313 else
314 break;
317 for (index = 1; index <= itemsInList; index++) {
318 err = AEGetNthPtr(&docList, index, typeFSS, &keywd, &typeCode,
319 (Ptr) &fss, sizeof(FSSpec), &actualSize);
320 if (noErr != err)
321 break;
323 err = FSpGetFInfo(&fss, &fndrInfo);
324 if (noErr != err)
325 break;
327 if (fndrInfo.fdType != SAVE_TYPE)
328 continue; /* only look at save files */
330 process_openfile(fss.vRefNum, fss.parID, fss.name,
331 fndrInfo.fdType);
332 if (macFlags.gotOpen)
333 break; /* got our save file */
335 err = AEDisposeDesc(&docList);
336 break;
341 /* Check to see if all required parameters for this type of event are
342 * present */
343 if (err == noErr) {
344 err =
345 AEGetAttributePtr(inAppleEvent, keyMissedKeywordAttr,
346 typeWildCard, &typeCode, NULL, 0, &actualSize);
347 if (err == errAEDescNotFound)
348 err = noErr; /* got all the required parameters */
349 else if (err == noErr) /* missed a required parameter */
350 err = errAEEventNotHandled;
353 return err;
356 short win_fonts[NHW_TEXT + 1];
358 void
359 InitMac(void)
361 short i;
362 long l;
363 Str255 volName;
365 #if !TARGET_API_MAC_CARBON
366 if (LMGetDefltStack() < 50 * 1024L) {
367 SetApplLimit((void *) ((long) LMGetCurStackBase() - (50 * 1024L)));
369 MaxApplZone();
370 for (i = 0; i < 5; i++)
371 MoreMasters();
373 InitGraf(&qd.thePort);
374 InitFonts();
375 InitWindows();
376 InitMenus();
377 InitDialogs(0L);
378 TEInit();
379 #endif
381 memset(&macFlags, 0, sizeof(macFlags));
382 if (!Gestalt(gestaltOSAttr, &l)) {
383 macFlags.processes = (l & (1 << gestaltLaunchControl)) ? 1 : 0;
384 macFlags.tempMem = (l & (1 << gestaltRealTempMemory)) ? 1 : 0;
385 macFlags.hasDebugger = (l & (1 << gestaltSysDebuggerSupport)) ? 1 : 0;
387 if (!Gestalt(gestaltQuickdrawVersion, &l))
388 macFlags.color = (l >= gestalt8BitQD) ? 1 : 0;
390 if (!Gestalt(gestaltFindFolderAttr, &l))
391 macFlags.folders = (l & (1 << gestaltFindFolderPresent)) ? 1 : 0;
393 if (!Gestalt(gestaltHelpMgrAttr, &l))
394 macFlags.help = (l & (1 << gestaltHelpMgrPresent)) ? 1 : 0;
396 if (!Gestalt(gestaltFSAttr, &l))
397 macFlags.fsSpec = (l & (1 << gestaltHasFSSpecCalls)) ? 1 : 0;
399 if (!Gestalt(gestaltFontMgrAttr, &l))
400 macFlags.trueType = (l & (1 << gestaltOutlineFonts)) ? 1 : 0;
402 if (!Gestalt(gestaltAUXVersion, &l))
403 macFlags.aux = (l >= 0x200) ? 1 : 0;
405 if (!Gestalt(gestaltAliasMgrAttr, &l))
406 macFlags.alias = (l & (1 << gestaltAliasMgrPresent)) ? 1 : 0;
408 if (!Gestalt(gestaltStandardFileAttr, &l))
409 macFlags.standardFile = (l & (1 << gestaltStandardFile58)) ? 1 : 0;
411 gMouseRgn = NewRgn();
412 InitCursor();
413 GetQDGlobalsArrow(&qdarrow);
414 ObscureCursor();
416 MoveScrollUPP = NewControlActionUPP(MoveScrollBar);
418 /* Set up base fonts for all window types */
419 GetFNum("\pHackFont", &i);
420 if (i == 0)
421 i = kFontIDMonaco;
422 win_fonts[NHW_BASE] = win_fonts[NHW_MAP] = win_fonts[NHW_STATUS] = i;
423 GetFNum("\pPSHackFont", &i);
424 if (i == 0)
425 i = kFontIDGeneva;
426 win_fonts[NHW_MESSAGE] = i;
427 win_fonts[NHW_TEXT] = kFontIDGeneva;
429 macFlags.hasAE = 0;
430 if (!Gestalt(gestaltAppleEventsAttr, &l)
431 && (l & (1L << gestaltAppleEventsPresent))) {
432 if (AEInstallEventHandler(kCoreEventClass, typeWildCard,
433 NewAEEventHandlerUPP(AppleEventHandler), 0,
434 FALSE) == noErr)
435 macFlags.hasAE = 1;
438 #if TARGET_API_MAC_CARBON
439 HGetVol(volName, &theDirs.dataRefNum, &theDirs.dataDirID);
440 #else
442 * We should try to get this data from a rsrc, in the profile file
443 * the user double-clicked... This data should be saved with the
444 * save file in the resource fork, AND be saveable in "stationary"
446 GetVol(volName, &theDirs.dataRefNum);
447 GetWDInfo(theDirs.dataRefNum, &theDirs.dataRefNum, &theDirs.dataDirID,
448 &l);
449 #endif
450 if (volName[0] > 31)
451 volName[0] = 31;
452 for (l = 1; l <= volName[0]; l++) {
453 if (volName[l] == ':') {
454 volName[l] = 0;
455 volName[0] = l - 1;
456 break;
459 BlockMove(volName, theDirs.dataName, l);
460 BlockMove(volName, theDirs.saveName, l);
461 BlockMove(volName, theDirs.levelName, l);
462 theDirs.saveRefNum = theDirs.levelRefNum = theDirs.dataRefNum;
463 theDirs.saveDirID = theDirs.levelDirID = theDirs.dataDirID;
465 /* Create the "record" file, if necessary */
466 check_recordfile("");
468 #if 0 // TARGET_API_MAC_CARBON
469 /* Create event handler universal procedure pointers */
470 dispatcher = GetEventDispatcherTarget();
471 baseupp = NewEventHandlerUPP(BaseEvent);
472 msgupp = NewEventHandlerUPP(MsgEvent);
473 menwupp = NewEventHandlerUPP(MenwEvent);
474 textupp = NewEventHandlerUPP(TextEvent);
475 InstallApplicationEventHandler(NewEventHandlerUPP(GlobalEvent),
476 sizeof(globalevents)/sizeof(EventTypeSpec), globalevents, NULL, NULL);
477 #endif
478 return;
482 * Change default window fonts.
484 short
485 set_tty_font_name(int window_type, char *font_name)
487 short fnum;
488 Str255 new_font;
490 if (window_type < NHW_BASE || window_type > NHW_TEXT)
491 return general_failure;
493 C2P(font_name, new_font);
494 GetFNum(new_font, &(fnum));
495 if (!fnum)
496 return general_failure;
497 win_fonts[window_type] = fnum;
498 return noErr;
501 static void
502 DrawScrollbar(NhWindow *aWin)
504 WindowPtr theWindow = aWin->its_window;
505 Rect crect, wrect;
506 Boolean vis;
507 short val, lin, win_height;
509 if (!aWin->scrollBar)
510 return;
511 GetControlBounds(aWin->scrollBar, &crect);
512 GetWindowBounds(aWin->its_window, kWindowContentRgn, &wrect);
513 OffsetRect(&wrect, -wrect.left, -wrect.top);
514 win_height = wrect.bottom - wrect.top;
516 if (crect.top != wrect.top - 1 || crect.left != wrect.right - SBARWIDTH) {
517 MoveControl(aWin->scrollBar, wrect.right - SBARWIDTH, wrect.top - 1);
519 if (crect.bottom != wrect.bottom - SBARHEIGHT
520 || crect.right != wrect.right + 1) {
521 SizeControl(aWin->scrollBar, SBARWIDTH + 1,
522 win_height - SBARHEIGHT + 2);
524 vis = (win_height > (50 + SBARHEIGHT));
525 if (vis != IsControlVisible(aWin->scrollBar)) {
526 /* current status != control */
527 if (vis) /* if visible, show */
528 ShowControl(aWin->scrollBar);
529 else /* else hide */
530 HideControl(aWin->scrollBar);
532 lin = aWin->y_size;
533 if (aWin == theWindows + WIN_MESSAGE) {
534 /* calculate how big scroll bar is for message window */
535 lin -= (win_height - SBARHEIGHT) / aWin->row_height;
536 if (lin < 0)
537 lin = 0;
538 val = 0; /* always have message scrollbar active */
539 } else {
540 /* calculate how big scroll bar is for other windows */
541 lin -= win_height / aWin->row_height;
542 if (lin < 0)
543 lin = 0;
544 if (lin)
545 val = 0; /* if there are 1+ screen lines, activate scrollbar */
546 else
547 val = 255; /* else grey it out */
549 SetControlMaximum(aWin->scrollBar, lin);
550 HiliteControl(aWin->scrollBar, val);
551 val = GetControlValue(aWin->scrollBar);
552 if (val != aWin->scrollPos) {
553 InvalWindowRect(theWindow, &wrect);
554 aWin->scrollPos = val;
558 #define MAX_HEIGHT 100
559 #define MIN_HEIGHT 50
560 #define MIN_WIDTH 300
563 * This function could be overloaded with any amount of intelligence...
566 SanePositions(void)
568 #if TARGET_API_MAC_CARBON
569 Rect rbase, rmsg;
570 SInt16 i, width, height;
572 ConstrainWindowToScreen(_mt_window, kWindowContentRgn,
573 kWindowConstrainMoveRegardlessOfFit, NULL, NULL);
574 GetWindowBounds(_mt_window, kWindowContentRgn, &rbase);
575 if (RetrievePosition(kMapWindow, &rbase.top, &rbase.left))
576 MoveWindow(_mt_window, rbase.left, rbase.top, TRUE);
578 GetWindowBounds(theWindows[NHW_MESSAGE].its_window, kWindowContentRgn,
579 &rmsg);
580 height = rmsg.bottom - rmsg.top;
581 rmsg.top = rbase.bottom + 2;
582 rmsg.bottom = rmsg.top + height;
583 rmsg.left = rbase.left;
584 rmsg.right = rbase.right;
585 RetrievePosition(kMessageWindow, &rmsg.top, &rmsg.left);
586 if (RetrieveSize(kMessageWindow, rmsg.top, rmsg.left, &height, &width)) {
587 rmsg.right = rmsg.left + width;
588 rmsg.bottom = rmsg.top + height;
590 SetWindowBounds(theWindows[NHW_MESSAGE].its_window, kWindowContentRgn,
591 &rmsg);
592 ConstrainWindowToScreen(theWindows[NHW_MESSAGE].its_window,
593 kWindowContentRgn,
594 kWindowConstrainMoveRegardlessOfFit, NULL, NULL);
595 DrawScrollbar(&theWindows[NHW_MESSAGE]);
597 for (i = 0; i < NUM_MACWINDOWS; i++)
598 if (i != WIN_STATUS && i != WIN_MESSAGE && i != WIN_MAP
599 && i != BASE_WINDOW && theWindows[i].its_window) {
600 /* FIXME */
601 ConstrainWindowToScreen(
602 theWindows[i].its_window, kWindowContentRgn,
603 kWindowConstrainMoveRegardlessOfFit, NULL, NULL);
605 #else
606 short left, top, width, height;
607 int ix, numText = 0, numMenu = 0;
608 int mbar_height = GetMBarHeight();
609 BitMap qbitmap;
610 Rect screenArea;
611 WindowPtr theWindow;
612 NhWindow *nhWin;
614 screenArea = GetQDGlobalsScreenBits(&qbitmap)->bounds;
615 OffsetRect(&screenArea, -screenArea.left, -screenArea.top);
617 /* Map Window */
618 height = _mt_window->portRect.bottom - _mt_window->portRect.top;
619 width = _mt_window->portRect.right - _mt_window->portRect.left;
621 if (!RetrievePosition(kMapWindow, &top, &left)) {
622 top = mbar_height + (small_screen ? 2 : 20);
623 left = (screenArea.right - width) / 2;
625 MoveWindow(_mt_window, left, top, 1);
627 /* Message Window */
628 if (!RetrievePosition(kMessageWindow, &top, &left)) {
629 top += height;
630 if (!small_screen)
631 top += 20;
634 if (!RetrieveSize(kMessageWindow, top, left, &height, &width)) {
635 height =
636 screenArea.bottom - top - (small_screen ? 2 - SBARHEIGHT : 2);
637 if (height > MAX_HEIGHT) {
638 height = MAX_HEIGHT;
639 } else if (height < MIN_HEIGHT) {
640 height = MIN_HEIGHT;
641 width = MIN_WIDTH;
642 left = screenArea.right - width;
643 top = screenArea.bottom - MIN_HEIGHT;
647 /* Move these windows */
648 nhWin = theWindows + WIN_MESSAGE;
649 theWindow = nhWin->its_window;
651 MoveWindow(theWindow, left, top, 1);
652 SizeWindow(theWindow, width, height, 1);
653 if (nhWin->scrollBar)
654 DrawScrollbar(nhWin);
656 /* Handle other windows */
657 for (ix = 0; ix < NUM_MACWINDOWS; ix++) {
658 if (ix != WIN_STATUS && ix != WIN_MESSAGE && ix != WIN_MAP
659 && ix != BASE_WINDOW) {
660 theWindow = theWindows[ix].its_window;
661 if (theWindow && ((WindowPeek) theWindow)->visible) {
662 int shift;
663 if (((WindowPeek) theWindow)->windowKind
664 == WIN_BASE_KIND + NHW_MENU) {
665 if (!RetrievePosition(kMenuWindow, &top, &left)) {
666 top = mbar_height * 2;
667 left = 2;
669 top += (numMenu * mbar_height);
670 numMenu++;
671 shift = 20;
672 } else {
673 if (!RetrievePosition(kTextWindow, &top, &left)) {
674 top = mbar_height * 2;
675 left = screenArea.right - 3
676 - (theWindow->portRect.right
677 - theWindow->portRect.left);
679 top += (numText * mbar_height);
680 numText++;
681 shift = -20;
683 while (top > screenArea.bottom - MIN_HEIGHT) {
684 top -= screenArea.bottom - mbar_height * 2;
685 left += shift;
687 MoveWindow(theWindow, left, top, 1);
691 #endif
692 return (0);
695 void
696 mac_init_nhwindows(int *argcp, char **argv)
698 Rect r;
699 #if !TARGET_API_MAC_CARBON
700 Rect scr = (*GetGrayRgn())->rgnBBox;
701 small_screen =
702 scr.bottom - scr.top <= (iflags.large_font ? 12 * 40 : 9 * 40);
703 #endif
705 InitMenuRes();
707 theWindows = (NhWindow *) NewPtrClear(NUM_MACWINDOWS * sizeof(NhWindow));
708 if (MemError())
709 error("mac_init_nhwindows: Couldn't allocate memory for windows.");
711 DimMenuBar();
713 tty_init_nhwindows(argcp, argv);
714 iflags.window_inited = TRUE;
716 /* Some ugly hacks to make both interfaces happy:
717 * Mac port uses both tty interface (for main map) and extra windows. The
718 * winids need to
719 * be kept in synch for both interfaces to map. Also, the "blocked"
720 * display_nhwindow case
721 * for the map automatically calls the tty interface for the message box,
722 * so some version
723 * of the message box has to exist in the tty world to prevent a meltdown,
724 * even though most
725 * messages are handled in mac window.
727 mac_create_nhwindow(NHW_BASE);
728 tty_create_nhwindow(NHW_MESSAGE);
730 #if 1 //!TARGET_API_MAC_CARBON
731 /* Resize and reposition the message window */
732 RetrievePosition(kMessageWindow, &r.top, &r.left);
733 RetrieveSize(kMessageWindow, r.top, r.left, &r.bottom, &r.right);
734 MoveWindow(theWindows[NHW_MESSAGE].its_window, r.left, r.top, false);
735 SizeWindow(theWindows[NHW_MESSAGE].its_window, r.right, r.bottom, true);
736 #endif
737 return;
740 winid
741 mac_create_nhwindow(int kind)
743 int i;
744 NhWindow *aWin;
745 FontInfo fi;
747 if (kind < NHW_BASE || kind > NHW_TEXT) {
748 error("cre_win: Invalid kind %d.", kind);
749 return WIN_ERR;
752 for (i = 0; i < NUM_MACWINDOWS; i++) {
753 if (!theWindows[i].its_window)
754 break;
756 if (i >= NUM_MACWINDOWS) {
757 error("cre_win: Win full; freeing extras");
758 for (i = 0; i < NUM_MACWINDOWS; i++) {
759 if (IsWindowVisible(theWindows[i].its_window) || i == WIN_INVEN
760 || GetWindowKind(theWindows[i].its_window)
761 != WIN_BASE_KIND + NHW_MENU
762 && GetWindowKind(theWindows[i].its_window)
763 != WIN_BASE_KIND + NHW_TEXT)
764 continue;
765 mac_destroy_nhwindow(i);
766 goto got1;
768 error("cre_win: Out of ids!");
769 return WIN_ERR;
772 got1:
773 aWin = &theWindows[i];
774 aWin->windowTextLen = 0L;
775 aWin->scrollBar = (ControlHandle) 0;
776 aWin->menuInfo = 0;
777 aWin->menuSelected = 0;
778 aWin->miLen = 0;
779 aWin->miSize = 0;
780 aWin->menuChar = 'a';
782 dprintf("cre_win: New kind %d", kind);
784 if (kind == NHW_BASE || kind == NHW_MAP || kind == NHW_STATUS) {
785 short x_sz, x_sz_p, y_sz, y_sz_p;
786 if (kind != NHW_BASE) {
787 if (i != tty_create_nhwindow(kind)) {
788 dprintf("cre_win: error creating kind %d", kind);
790 if (kind == NHW_MAP) {
791 wins[i]->offy =
792 0; /* the message box is in a separate window */
795 aWin->its_window = _mt_window;
796 get_tty_metrics(aWin->its_window, &x_sz, &y_sz, &x_sz_p, &y_sz_p,
797 &aWin->font_number, &aWin->font_size,
798 &aWin->char_width, &aWin->row_height);
799 #if 0 // TARGET_API_MAC_CARBON
800 InstallWindowEventHandler(aWin->its_window, baseupp,
801 sizeof(baseevents)/sizeof(EventTypeSpec), baseevents,
802 (void *)aWin, NULL);
803 #endif
804 return i;
807 aWin->its_window =
808 GetNewWindow(WIN_BASE_RES + kind, (WindowPtr) 0L, (WindowPtr) -1L);
809 SetWindowKind(aWin->its_window, WIN_BASE_KIND + kind);
810 SetWRefCon(aWin->its_window, (long) aWin);
811 if (!(aWin->windowText = NewHandle(TEXT_BLOCK))) {
812 error("cre_win: NewHandle fail(%ld)", (long) TEXT_BLOCK);
813 DisposeWindow(aWin->its_window);
814 aWin->its_window = (WindowPtr) 0;
815 return WIN_ERR;
817 aWin->x_size = aWin->y_size = 0;
818 aWin->x_curs = aWin->y_curs = 0;
819 aWin->drawn = TRUE;
820 mac_clear_nhwindow(i);
821 #if 0 // TARGET_API_MAC_CARBON
822 switch (kind) {
823 case NHW_MESSAGE:
824 InstallWindowEventHandler(aWin->its_window, msgupp,
825 sizeof(msgevents)/sizeof(EventTypeSpec), msgevents,
826 (void *)aWin, NULL);
827 break;
828 case NHW_MENU:
829 InstallWindowEventHandler(aWin->its_window, menwupp,
830 sizeof(menwevents)/sizeof(EventTypeSpec), menwevents,
831 (void *)aWin, NULL);
832 break;
833 case NHW_TEXT:
834 InstallWindowEventHandler(aWin->its_window, textupp,
835 sizeof(textevents)/sizeof(EventTypeSpec), textevents,
836 (void *)aWin, NULL);
837 break;
839 #endif
841 SetPortWindowPort(aWin->its_window);
843 if (kind == NHW_MESSAGE) {
844 aWin->font_number = win_fonts[NHW_MESSAGE];
845 aWin->font_size = iflags.wc_fontsiz_message
846 ? iflags.wc_fontsiz_message
847 : iflags.large_font ? 12 : 9;
848 if (!top_line) {
849 const Rect out_of_scr = { 10000, 10000, 10100, 10100 };
850 TextFont(aWin->font_number);
851 TextSize(aWin->font_size);
852 TextFace(bold);
853 top_line = TENew(&out_of_scr, &out_of_scr);
854 TEActivate(top_line);
855 TextFace(normal);
857 } else {
858 aWin->font_number = win_fonts[NHW_TEXT];
859 aWin->font_size = iflags.wc_fontsiz_text ? iflags.wc_fontsiz_text : 9;
862 TextFont(aWin->font_number);
863 TextSize(aWin->font_size);
865 GetFontInfo(&fi);
866 aWin->ascent_height = fi.ascent + fi.leading;
867 aWin->row_height = aWin->ascent_height + fi.descent;
868 aWin->char_width = fi.widMax;
870 if (kind == NHW_MENU || kind == NHW_TEXT || kind == NHW_MESSAGE) {
871 Rect r;
873 GetWindowBounds(aWin->its_window, kWindowContentRgn, &r);
874 r.right -= (r.left - 1);
875 r.left = r.right - SBARWIDTH;
876 r.bottom -= (r.top + SBARHEIGHT);
877 r.top = -1;
878 aWin->scrollBar =
879 NewControl(aWin->its_window, &r, "\p", (r.bottom > r.top + 50), 0,
880 0, 0, 16, 0L);
881 aWin->scrollPos = 0;
883 return i;
886 void
887 mac_clear_nhwindow(winid win)
889 long l;
890 Rect r;
891 NhWindow *aWin = &theWindows[win];
892 WindowPtr theWindow = aWin->its_window;
894 if (win < 0 || win >= NUM_MACWINDOWS || !theWindow) {
895 error("clr_win: Invalid win %d.", win);
896 return;
898 if (theWindow == _mt_window) {
899 tty_clear_nhwindow(win);
900 return;
902 if (!aWin->drawn)
903 return;
905 SetPortWindowPort(theWindow);
906 GetWindowBounds(theWindow, kWindowContentRgn, &r);
907 OffsetRect(&r, -r.left, -r.top);
908 if (aWin->scrollBar)
909 r.right -= SBARWIDTH;
911 switch (GetWindowKind(theWindow) - WIN_BASE_KIND) {
912 case NHW_MESSAGE:
913 if (aWin->scrollPos
914 == aWin->y_size - 1) /* if no change since last clear */
915 return; /* don't bother with redraw */
916 r.bottom -= SBARHEIGHT;
917 for (l = 0; aWin->y_size > iflags.msg_history;) {
918 const char cr = CHAR_CR;
919 l = Munger(aWin->windowText, l, &cr, 1, nil, 0) + 1;
920 --aWin->y_size;
922 if (l) {
923 aWin->windowTextLen -= l;
924 BlockMove(*aWin->windowText + l, *aWin->windowText,
925 aWin->windowTextLen);
927 aWin->last_more_lin = aWin->y_size;
928 aWin->save_lin = aWin->y_size;
929 aWin->scrollPos = aWin->y_size ? aWin->y_size - 1 : 0;
930 break;
931 case NHW_MENU:
932 if (aWin->menuInfo) {
933 DisposeHandle((Handle) aWin->menuInfo);
934 aWin->menuInfo = NULL;
936 if (aWin->menuSelected) {
937 DisposeHandle((Handle) aWin->menuSelected);
938 aWin->menuSelected = NULL;
940 aWin->menuChar = 'a';
941 aWin->miSelLen = 0;
942 aWin->miLen = 0;
943 aWin->miSize = 0;
944 /* Fall-Through */
945 default:
946 SetHandleSize(aWin->windowText, TEXT_BLOCK);
947 aWin->windowTextLen = 0L;
948 aWin->x_size = 0;
949 aWin->y_size = 0;
950 aWin->scrollPos = 0;
951 break;
953 if (aWin->scrollBar) {
954 SetControlMaximum(aWin->scrollBar, aWin->y_size);
955 SetControlValue(aWin->scrollBar, aWin->scrollPos);
957 aWin->y_curs = 0;
958 aWin->x_curs = 0;
959 aWin->drawn = FALSE;
960 InvalWindowRect(theWindow, &r);
963 static Boolean
964 ClosingWindowChar(const int c)
966 return (c == CHAR_ESC || c == CHAR_BLANK || c == CHAR_LF || c == CHAR_CR);
969 static Boolean
970 in_topl_mode(void)
972 Rect rect;
974 GetWindowBounds(theWindows[WIN_MESSAGE].its_window, kWindowContentRgn,
975 &rect);
976 OffsetRect(&rect, -rect.left, -rect.top);
977 return (WIN_MESSAGE != WIN_ERR && top_line
978 && (*top_line)->viewRect.left < rect.right);
981 #define BTN_IND 2
982 #define BTN_W 40
983 #define BTN_H (SBARHEIGHT - 3)
985 static void
986 topl_resp_rect(int resp_idx, Rect *r)
988 Rect rect;
990 GetWindowBounds(theWindows[WIN_MESSAGE].its_window, kWindowContentRgn,
991 &rect);
992 OffsetRect(&rect, -rect.left, -rect.top);
993 r->left = (BTN_IND + BTN_W) * resp_idx + BTN_IND;
994 r->right = r->left + BTN_W;
995 r->bottom = rect.bottom - 1;
996 r->top = r->bottom - BTN_H;
997 return;
1000 void
1001 enter_topl_mode(char *query)
1003 if (in_topl_mode())
1004 return;
1006 putstr(WIN_MESSAGE, ATR_BOLD, query);
1008 topl_query_len = strlen(query);
1009 (*top_line)->selStart = topl_query_len;
1010 (*top_line)->selEnd = topl_query_len;
1011 (*top_line)->viewRect.left = 0;
1012 PtrToXHand(query, (*top_line)->hText, topl_query_len);
1013 TECalText(top_line);
1015 DimMenuBar();
1016 mac_display_nhwindow(WIN_MESSAGE, FALSE);
1019 void
1020 leave_topl_mode(char *answer)
1022 /*unsigned*/ char *ap, *bp;
1024 int ans_len = (*top_line)->teLength - topl_query_len;
1025 NhWindow *aWin = theWindows + WIN_MESSAGE;
1027 if (!in_topl_mode())
1028 return;
1030 /* Cap length of reply */
1031 if (ans_len >= BUFSZ)
1032 ans_len = BUFSZ - 1;
1034 /* remove unprintables from the answer */
1035 for (ap = *(*top_line)->hText + topl_query_len, bp = answer; ans_len > 0;
1036 ans_len--, ap++) {
1037 if (*ap >= ' ' && *ap < 128) {
1038 *bp++ = *ap;
1041 *bp = 0;
1043 if (aWin->windowTextLen
1044 && (*aWin->windowText)[aWin->windowTextLen - 1] == CHAR_CR) {
1045 --aWin->windowTextLen;
1046 --aWin->y_size;
1048 putstr(WIN_MESSAGE, ATR_BOLD, answer);
1050 (*top_line)->viewRect.left += 10000;
1051 UndimMenuBar();
1055 * TESetSelect flushes out all the pending key strokes. I hate it.
1057 static void
1058 topl_set_select(short selStart, short selEnd)
1060 TEDeactivate(top_line);
1061 (*top_line)->selStart = selStart;
1062 (*top_line)->selEnd = selEnd;
1063 TEActivate(top_line);
1066 static void
1067 topl_replace(char *new_ans)
1069 topl_set_select(topl_query_len, (*top_line)->teLength);
1070 TEDelete(top_line);
1071 TEInsert(new_ans, strlen(new_ans), top_line);
1074 Boolean
1075 topl_key(unsigned char ch, Boolean ext)
1077 switch (ch) {
1078 case CHAR_ESC:
1079 topl_replace("\x1b");
1080 case CHAR_ENTER:
1081 case CHAR_CR:
1082 case CHAR_LF:
1083 return false;
1085 case 0x1f & 'P':
1086 mac_doprev_message();
1087 return true;
1088 case '\x1e' /* up arrow */:
1089 topl_replace("");
1090 return true;
1091 case CHAR_BS:
1092 case '\x1c' /* left arrow */:
1093 if ((*top_line)->selEnd <= topl_query_len)
1094 return true;
1095 else if (ext) {
1096 topl_replace("");
1097 return true;
1099 default:
1100 TEKey(ch, top_line);
1101 if (ext) {
1102 int com_index = -1, oindex = 0;
1103 while (extcmdlist[oindex].ef_txt != (char *) 0) {
1104 if (!strncmpi(*(*top_line)->hText + topl_query_len,
1105 extcmdlist[oindex].ef_txt,
1106 (*top_line)->teLength - topl_query_len)) {
1107 if (com_index == -1) /* No matches yet*/
1108 com_index = oindex;
1109 else /* More than 1 match */ {
1110 com_index = -2;
1111 break;
1114 oindex++;
1116 if (com_index >= 0)
1117 topl_replace((char *) extcmdlist[com_index].ef_txt);
1119 return true;
1123 static void
1124 topl_flash_resp(int resp_idx)
1126 unsigned long dont_care;
1127 Rect frame;
1128 SetPortWindowPort(theWindows[WIN_MESSAGE].its_window);
1129 topl_resp_rect(resp_idx, &frame);
1130 InsetRect(&frame, 1, 1);
1131 InvertRect(&frame);
1132 Delay(GetDblTime() / 2, &dont_care);
1133 InvertRect(&frame);
1136 static void
1137 topl_set_def(int new_def_idx)
1139 Rect frame;
1140 SetPortWindowPort(theWindows[WIN_MESSAGE].its_window);
1141 topl_resp_rect(topl_def_idx, &frame);
1142 InvalWindowRect(theWindows[WIN_MESSAGE].its_window, &frame);
1143 topl_def_idx = new_def_idx;
1144 topl_resp_rect(new_def_idx, &frame);
1145 InvalWindowRect(theWindows[WIN_MESSAGE].its_window, &frame);
1148 void
1149 topl_set_resp(char *resp, char def)
1151 char *loc;
1152 Rect frame;
1153 int r_len, r_len1;
1155 if (!resp) {
1156 const char any_str[2] = { CHAR_ANY, '\0' };
1157 resp = (char *) any_str;
1158 def = CHAR_ANY;
1161 SetPortWindowPort(theWindows[WIN_MESSAGE].its_window);
1162 r_len1 = strlen(resp);
1163 r_len = strlen(topl_resp);
1164 if (r_len < r_len1)
1165 r_len = r_len1;
1166 topl_resp_rect(0, &frame);
1167 frame.right = (BTN_IND + BTN_W) * r_len;
1168 InvalWindowRect(theWindows[WIN_MESSAGE].its_window, &frame);
1170 strcpy(topl_resp, resp);
1171 loc = strchr(resp, def);
1172 topl_def_idx = loc ? loc - resp : -1;
1175 static char
1176 topl_resp_key(char ch)
1178 if (strlen(topl_resp) > 0) {
1179 char *loc = strchr(topl_resp, ch);
1181 if (!loc) {
1182 if (ch == '\x9' /* tab */) {
1183 topl_set_def(topl_def_idx <= 0 ? strlen(topl_resp) - 1
1184 : topl_def_idx - 1);
1185 ch = '\0';
1186 } else if (ch == CHAR_ESC) {
1187 loc = strchr(topl_resp, 'q');
1188 if (!loc) {
1189 loc = strchr(topl_resp, 'n');
1190 if (!loc && topl_def_idx >= 0)
1191 loc = topl_resp + topl_def_idx;
1193 } else if (ch == (0x1f & 'P')) {
1194 mac_doprev_message();
1195 ch = '\0';
1196 } else if (topl_def_idx >= 0) {
1197 if (ch == CHAR_ENTER || ch == CHAR_CR || ch == CHAR_LF
1198 || ch == CHAR_BLANK
1199 || topl_resp[topl_def_idx] == CHAR_ANY)
1200 loc = topl_resp + topl_def_idx;
1202 else if (strchr(topl_resp, '#')) {
1203 if (digit(ch)) {
1204 topl_set_def(strchr(topl_resp, '#') - topl_resp);
1205 TEKey(ch, top_line);
1206 ch = '\0';
1208 } else if (topl_resp[topl_def_idx] == '#') {
1209 if (ch == '\x1e' /* up arrow */) {
1210 topl_set_select(topl_query_len, topl_query_len);
1211 ch = '\0';
1212 } else if (ch == '\x1d' /* right arrow */
1213 || ch == '\x1f' /* down arrow */
1214 || ch == CHAR_BS
1215 || ch == '\x1c' /* left arrow */
1216 && (*top_line)->selEnd
1217 > topl_query_len) {
1218 TEKey(ch, top_line);
1219 ch = '\0';
1226 if (loc) {
1227 topl_flash_resp(loc - topl_resp);
1228 if (*loc != CHAR_ANY)
1229 ch = *loc;
1230 TEKey(ch, top_line);
1234 return ch;
1237 static void
1238 adjust_window_pos(NhWindow *aWin, short width, short height)
1240 WindowRef theWindow = aWin->its_window;
1241 #if TARGET_API_MAC_CARBON
1242 Rect r;
1244 GetWindowBounds(theWindow, kWindowContentRgn, &r);
1245 RetrieveWinPos(theWindow, &r.top, &r.left);
1246 MoveWindow(theWindow, r.left, r.top, false);
1247 SizeWindow(theWindow, width, height, true);
1248 ConstrainWindowToScreen(theWindow, kWindowStructureRgn,
1249 kWindowConstrainMayResize
1250 | kWindowConstrainMoveRegardlessOfFit,
1251 NULL, NULL);
1252 #else
1253 Rect scr_r = (*GetGrayRgn())->rgnBBox;
1254 const Rect win_ind = { 2, 2, 3, 3 };
1255 const short min_w = theWindow->portRect.right - theWindow->portRect.left,
1256 max_w =
1257 scr_r.right - scr_r.left - win_ind.left - win_ind.right;
1258 Point pos;
1259 short max_h;
1261 SetPortWindowPort(theWindow);
1262 if (!RetrieveWinPos(theWindow, &pos.v, &pos.h)) {
1263 pos.v = 0; /* take window's existing position */
1264 pos.h = 0;
1265 LocalToGlobal(&pos);
1268 max_h = scr_r.bottom - win_ind.bottom - pos.v;
1269 if (height > max_h)
1270 height = max_h;
1271 if (height < MIN_HEIGHT)
1272 height = MIN_HEIGHT;
1273 if (width < min_w)
1274 width = min_w;
1275 if (width > max_w)
1276 width = max_w;
1277 SizeWindow(theWindow, width, height, true);
1279 if (pos.v + height + win_ind.bottom > scr_r.bottom)
1280 pos.v = scr_r.bottom - height - win_ind.bottom;
1281 if (pos.h + width + win_ind.right > scr_r.right)
1282 pos.h = scr_r.right - width - win_ind.right;
1283 MoveWindow(theWindow, pos.h, pos.v, false);
1284 #endif
1285 if (aWin->scrollBar)
1286 DrawScrollbar(aWin);
1287 return;
1291 * display/select/update the window.
1292 * If f is true, this window should be "modal" - don't return
1293 * until presumed seen.
1295 void
1296 mac_display_nhwindow(winid win, BOOLEAN_P f)
1298 NhWindow *aWin = &theWindows[win];
1299 WindowPtr theWindow = aWin->its_window;
1301 if (win < 0 || win >= NUM_MACWINDOWS || !theWindow) {
1302 error("disp_win: Invalid window %d.", win);
1303 return;
1306 if (theWindow == _mt_window) {
1307 tty_display_nhwindow(win, f);
1308 return;
1311 if (f && inSelect == WIN_ERR && win == WIN_MESSAGE) {
1312 topl_set_resp((char *) 0, 0);
1313 if (aWin->windowTextLen > 0
1314 && (*aWin->windowText)[aWin->windowTextLen - 1] == CHAR_CR) {
1315 --aWin->windowTextLen;
1316 --aWin->y_size;
1318 putstr(win, flags.standout ? ATR_INVERSE : ATR_NONE, " --More--");
1321 if (!IsWindowVisible(theWindow)) {
1322 if (win != WIN_MESSAGE)
1323 adjust_window_pos(aWin, aWin->x_size + SBARWIDTH + 1,
1324 aWin->y_size * aWin->row_height);
1326 SelectWindow(theWindow);
1327 ShowWindow(theWindow);
1330 if (f && inSelect == WIN_ERR) {
1331 int ch;
1333 DimMenuBar();
1334 inSelect = win;
1335 do {
1336 ch = mac_nhgetch();
1337 } while (!ClosingWindowChar(ch));
1338 inSelect = WIN_ERR;
1339 UndimMenuBar();
1341 if (win == WIN_MESSAGE)
1342 topl_set_resp("", '\0');
1343 else
1344 HideWindow(theWindow);
1348 void
1349 mac_destroy_nhwindow(winid win)
1351 WindowPtr theWindow;
1352 NhWindow *aWin = &theWindows[win];
1353 int kind;
1355 if (win < 0 || win >= NUM_MACWINDOWS) {
1356 if (iflags.window_inited)
1357 error("dest_win: Invalid win %d.", win);
1358 return;
1360 theWindow = aWin->its_window;
1361 if (!theWindow) {
1362 error("dest_win: Not allocated win %d.", win);
1363 return;
1367 * Check special windows. The base window should never go away.
1368 * Other "standard" windows should not go away unless we've exitted
1369 * nhwindows.
1371 if (theWindow == _mt_window) {
1372 return;
1374 if (win == WIN_INVEN || win == WIN_MESSAGE) {
1375 if (iflags.window_inited) {
1376 if (flags.tombstone && killer[0]) {
1377 /* Prepare for the coming of the tombstone window. */
1378 win_fonts[NHW_TEXT] = kFontIDMonaco;
1380 return;
1382 if (win == WIN_MESSAGE)
1383 WIN_MESSAGE = WIN_ERR;
1386 kind = GetWindowKind(theWindow) - WIN_BASE_KIND;
1388 if ((!IsWindowVisible(theWindow)
1389 || (kind != NHW_MENU && kind != NHW_TEXT))) {
1390 DisposeWindow(theWindow);
1391 if (aWin->windowText) {
1392 DisposeHandle(aWin->windowText);
1394 aWin->its_window = (WindowPtr) 0;
1395 aWin->windowText = (Handle) 0;
1399 void
1400 mac_number_pad(int pad)
1401 { /* no effect */
1402 #if defined(__SC__) || defined(__MRC__)
1403 #pragma unused(pad)
1404 #endif
1405 return;
1408 void
1409 trans_num_keys(EventRecord *theEvent)
1411 #if defined(__SC__) || defined(__MRC__)
1412 #pragma unused(theEvent)
1413 #endif
1414 /* KMH -- Removed this translation.
1415 * Number pad keys should always emit digit characters.
1416 * That's consistent with the default MacOS behavior.
1417 * The number_pad option controls how digits are interpreted.
1419 #if 0
1420 if (Cmd.num_pad) {
1421 Handle h = GetResource('Nump', theEvent->modifiers & shiftKey ? 129 : 128);
1422 if (h) {
1423 short inkey = (theEvent->message & keyCodeMask), *ab = (short *)*h;
1424 int i = ab[0];
1425 for (; i; i--) {
1426 if (inkey == (ab[i] & keyCodeMask)) {
1427 theEvent->message = ab[i];
1428 break;
1433 #endif
1437 * Routine used to select and de-select elements in a menu window, used by
1438 * KeyMenu,
1439 * ClickMenu, and UpdateMenu. Takes the NhWindow and a line ref relative to
1440 * the scrollbar.
1442 static void
1443 ToggleMenuSelect(NhWindow *aWin, int line)
1445 Rect r;
1447 GetWindowBounds(aWin->its_window, kWindowContentRgn, &r);
1448 OffsetRect(&r, -r.left, -r.top);
1449 if (aWin->scrollBar)
1450 r.right -= SBARWIDTH;
1451 r.top = line * aWin->row_height;
1452 r.bottom = r.top + aWin->row_height;
1454 LMSetHiliteMode((UInt8)(LMGetHiliteMode() & 0x7F));
1455 InvertRect(&r);
1459 * Check to see if given item is selected, return index if it is
1461 static int
1462 ListItemSelected(NhWindow *aWin, int item)
1464 int i;
1466 HLock((char **) aWin->menuSelected);
1467 /* Find item in selection list */
1468 for (i = aWin->miSelLen - 1; i >= 0; i--) {
1469 if ((*aWin->menuSelected)[i] == item)
1470 break;
1472 HUnlock((char **) aWin->menuSelected);
1473 return i;
1477 * Add item to selection list if it's not selected already
1478 * If it is selected already, remove it from the list.
1480 static void
1481 ToggleMenuListItemSelected(NhWindow *aWin, short item)
1483 int i = ListItemSelected(aWin, item);
1485 HLock((char **) aWin->menuSelected);
1486 if (i < 0) { /* not there, so add */
1487 (*aWin->menuSelected)[aWin->miSelLen] = item;
1488 aWin->miSelLen++;
1489 } else { /* there, so remove */
1490 short *mi = &(*aWin->menuSelected)[i];
1491 aWin->miSelLen--;
1492 memcpy(mi, mi + 1, (aWin->miSelLen - i) * sizeof(short));
1494 HUnlock((char **) aWin->menuSelected);
1498 * Find menu item in list given a line number on the window
1500 static short
1501 ListCoordinateToItem(NhWindow *aWin, short Row)
1503 int i, item = -1;
1504 MacMHMenuItem *mi;
1506 HLock((char **) aWin->menuInfo);
1507 for (i = 0, mi = *aWin->menuInfo; i < aWin->miLen; i++, mi++) {
1508 if (mi->line == Row + aWin->scrollPos) {
1509 item = i;
1510 break;
1513 HUnlock((char **) aWin->menuInfo);
1514 return item;
1517 static pascal void
1518 MoveScrollBar(ControlHandle theBar, short part)
1520 #if 1 //!TARGET_API_MAC_CARBON
1521 EventRecord fake;
1522 #endif
1523 Rect r;
1524 RgnHandle rgn;
1525 int now, amtToScroll;
1526 WindowPtr theWin;
1527 NhWindow *winToScroll;
1529 if (!part)
1530 return;
1532 theWin = GetControlOwner(theBar);
1533 GetWindowBounds(theWin, kWindowContentRgn, &r);
1534 OffsetRect(&r, -r.left, -r.top);
1535 winToScroll = (NhWindow *) (GetWRefCon(theWin));
1536 now = GetControlValue(theBar);
1538 if (part == kControlPageUpPart || part == kControlPageDownPart)
1539 amtToScroll = (r.bottom - r.top) / winToScroll->row_height;
1540 else
1541 amtToScroll = 1;
1543 if (part == kControlPageUpPart || part == kControlUpButtonPart) {
1544 int bound = GetControlMinimum(theBar);
1545 if (now - bound < amtToScroll)
1546 amtToScroll = now - bound;
1547 amtToScroll = -amtToScroll;
1548 } else {
1549 int bound = GetControlMaximum(theBar);
1550 if (bound - now < amtToScroll)
1551 amtToScroll = bound - now;
1554 if (!amtToScroll)
1555 return;
1557 SetControlValue(theBar, now + amtToScroll);
1558 winToScroll->scrollPos = now + amtToScroll;
1559 r.right -= SBARWIDTH;
1560 if (winToScroll == theWindows + WIN_MESSAGE)
1561 r.bottom -= SBARHEIGHT;
1562 rgn = NewRgn();
1563 ScrollRect(&r, 0, -amtToScroll * winToScroll->row_height, rgn);
1564 if (rgn) {
1565 InvalWindowRgn(theWin, rgn);
1566 BeginUpdate(theWin);
1568 #if 0 // TARGET_API_MAC_CARBON
1569 switch (GetWindowKind(theWin) - WIN_BASE_KIND) {
1570 case NHW_MESSAGE:
1571 MsgUpdate(GetNhWin(theWin));
1572 break;
1573 case NHW_MENU:
1574 MenwUpdate(GetNhWin(theWin));
1575 break;
1576 case NHW_TEXT:
1577 TextUpdate(GetNhWin(theWin));
1578 break;
1580 #else
1581 winUpdateFuncs[GetWindowKind(theWin) - WIN_BASE_KIND](&fake, theWin);
1582 #endif
1583 if (rgn) {
1584 EndUpdate(theWin);
1585 DisposeRgn(rgn);
1589 #if 1 //!TARGET_API_MAC_CARBON
1590 static void
1591 DoScrollBar(Point p, short code, ControlHandle theBar, NhWindow *aWin)
1593 ControlActionUPP func = NULL;
1594 Rect rect;
1596 if (code == kControlUpButtonPart || code == kControlPageUpPart
1597 || code == kControlDownButtonPart || code == kControlPageDownPart)
1598 func = MoveScrollUPP;
1599 (void) TrackControl(theBar, p, func);
1600 if (!func) {
1601 if (aWin->scrollPos != GetControlValue(theBar)) {
1602 aWin->scrollPos = GetControlValue(theBar);
1603 GetWindowBounds(aWin->its_window, kWindowContentRgn, &rect);
1604 OffsetRect(&rect, -rect.left, -rect.top);
1605 InvalWindowRect(aWin->its_window, &rect);
1609 #endif
1611 static int
1612 filter_scroll_key(const int ch, NhWindow *aWin)
1614 if (aWin->scrollBar
1615 && GetControlValue(aWin->scrollBar)
1616 < GetControlMaximum(aWin->scrollBar)) {
1617 short part = 0;
1618 if (ch == CHAR_BLANK) {
1619 part = kControlPageDownPart;
1620 } else if (ch == CHAR_CR || ch == CHAR_LF) {
1621 part = kControlDownButtonPart;
1623 if (part) {
1624 SetPortWindowPort(aWin->its_window);
1625 MoveScrollBar(aWin->scrollBar, part);
1626 return 0;
1629 return ch;
1633 mac_doprev_message(void)
1635 if (WIN_MESSAGE) {
1636 NhWindow *winToScroll = &theWindows[WIN_MESSAGE];
1637 mac_display_nhwindow(WIN_MESSAGE, FALSE);
1638 SetPortWindowPort(winToScroll->its_window);
1639 MoveScrollBar(winToScroll->scrollBar, kControlUpButtonPart);
1641 return 0;
1644 static void
1645 draw_growicon_vert_only(WindowPtr wind)
1647 GrafPtr org_port;
1648 RgnHandle org_clip = NewRgn();
1649 Rect r;
1651 GetPort(&org_port);
1652 SetPortWindowPort(wind);
1653 GetClip(org_clip);
1654 GetWindowBounds(wind, kWindowContentRgn, &r);
1655 OffsetRect(&r, -r.left, -r.top);
1656 r.left = r.right - SBARWIDTH;
1657 ClipRect(&r);
1658 DrawGrowIcon(wind);
1659 SetClip(org_clip);
1660 DisposeRgn(org_clip);
1661 SetPort(org_port);
1664 /* NOT_IN_CARBON */
1665 static void
1666 WindowGoAway(EventRecord *theEvent, WindowPtr theWindow)
1668 NhWindow *aWin = GetNhWin(theWindow);
1670 if (!theEvent || TrackGoAway(theWindow, theEvent->where)) {
1671 if (aWin - theWindows == BASE_WINDOW && !iflags.window_inited) {
1672 AddToKeyQueue('\033', 1);
1673 } else {
1674 HideWindow(theWindow);
1675 if (aWin - theWindows != inSelect)
1676 mac_destroy_nhwindow(aWin - theWindows);
1677 else /* if this IS the inSelect window put a close char */
1678 AddToKeyQueue(CHAR_CR,
1679 1); /* in queue to exit and maintain inSelect */
1684 void
1685 mac_get_nh_event(void)
1687 EventRecord anEvent;
1689 /* KMH -- Don't proceed if the window system isn't set up */
1690 if (!iflags.window_inited)
1691 return;
1693 #if TARGET_API_MAC_CARBON
1694 QDFlushPortBuffer(GetWindowPort(_mt_window), NULL);
1695 #endif
1696 (void) WaitNextEvent(everyEvent, &anEvent, 1, gMouseRgn);
1697 HandleEvent(&anEvent);
1698 return;
1702 mac_nhgetch(void)
1704 int ch;
1705 long doDawdle = 1L;
1706 EventRecord anEvent;
1708 #if 1 //!TARGET_API_MAC_CARBON
1709 /* We want to take care of keys in the buffer as fast as
1710 * possible
1712 if (keyQueueCount)
1713 doDawdle = 0L;
1714 else {
1715 long total, contig;
1716 static char warn = 0;
1718 doDawdle = (in_topl_mode() ? GetCaretTime() : 120L);
1719 /* Since we have time, check memory */
1720 PurgeSpace(&total, &contig);
1721 if (contig < 25000L || total < 50000L) {
1722 if (!warn) {
1723 pline("Low Memory!");
1724 warn = 1;
1726 } else {
1727 warn = 0;
1730 #endif
1732 do {
1733 #if TARGET_API_MAC_CARBON
1734 QDFlushPortBuffer(GetWindowPort(_mt_window), NULL);
1735 #endif
1736 #if 0 // TARGET_API_MAC_CARBON
1737 EventRef event;
1739 if (ReceiveNextEvent(0, NULL, kEventDurationForever, TRUE, &event) == noErr) {
1740 SendEventToEventTarget(event, dispatcher);
1741 ReleaseEvent(event);
1743 #else
1744 (void) WaitNextEvent(everyEvent, &anEvent, doDawdle, gMouseRgn);
1745 HandleEvent(&anEvent);
1746 #endif
1747 ch = GetFromKeyQueue();
1748 } while (!ch && !gClickedToMove);
1750 if (!gClickedToMove)
1751 ObscureCursor();
1752 else
1753 gClickedToMove = 0;
1755 #ifdef THINK_C
1756 if (ch == '\r')
1757 ch = '\n';
1758 #endif
1760 return (ch);
1763 void
1764 mac_delay_output(void)
1766 long destTicks = TickCount() + 1;
1768 while (TickCount() < destTicks) {
1769 mac_get_nh_event();
1773 #ifdef CLIPPING
1774 static void
1775 mac_cliparound(int x, int y)
1777 #if defined(__SC__) || defined(__MRC__)
1778 #pragma unused(x, y)
1779 #endif
1780 /* TODO */
1782 #endif
1784 void
1785 mac_exit_nhwindows(const char *s)
1787 clear_screen();
1788 tty_exit_nhwindows(s);
1789 mac_destroy_nhwindow(WIN_MESSAGE);
1790 mac_destroy_nhwindow(WIN_INVEN);
1794 * Don't forget to decrease in_putstr before returning...
1796 void
1797 mac_putstr(winid win, int attr, const char *str)
1799 long len, slen;
1800 NhWindow *aWin = &theWindows[win];
1801 static char in_putstr = 0;
1802 short newWidth, maxWidth;
1803 Rect r;
1804 char *src, *sline, *dst, ch;
1806 if (win < 0 || win >= NUM_MACWINDOWS || !aWin->its_window) {
1807 error("putstr: Invalid win %d (Max %d).", win, NUM_MACWINDOWS, attr);
1808 return;
1811 if (aWin->its_window == _mt_window) {
1812 tty_putstr(win, attr, str);
1813 return;
1816 if (in_putstr > 3)
1817 return;
1819 in_putstr++;
1820 slen = strlen(str);
1822 SetPortWindowPort(aWin->its_window);
1823 GetWindowBounds(aWin->its_window, kWindowContentRgn, &r);
1824 OffsetRect(&r, -r.left, -r.top);
1825 if (win == WIN_MESSAGE) {
1826 r.right -= SBARWIDTH;
1827 r.bottom -= SBARHEIGHT;
1828 if (flags.page_wait
1829 && aWin->last_more_lin
1830 <= aWin->y_size - (r.bottom - r.top) / aWin->row_height) {
1831 aWin->last_more_lin = aWin->y_size;
1832 mac_display_nhwindow(win, TRUE);
1837 * A "default" text window - uses TETextBox
1838 * We just add the text, without attributes for now
1840 len = GetHandleSize(aWin->windowText);
1841 while (aWin->windowTextLen + slen + 1 > len) {
1842 len = (len > 2048) ? (len + 2048) : (len * 2);
1843 SetHandleSize(aWin->windowText, len);
1844 if (MemError()) {
1845 error("putstr: SetHandleSize");
1846 aWin->windowTextLen = 0L;
1847 aWin->save_lin = 0;
1848 aWin->y_curs = 0;
1849 aWin->y_size = 0;
1853 len = aWin->windowTextLen;
1854 dst = *(aWin->windowText) + len;
1855 sline = src = (char *) str;
1856 maxWidth = newWidth = 0;
1857 for (ch = *src; ch; ch = *src) {
1858 if (ch == CHAR_LF)
1859 ch = CHAR_CR;
1860 *dst++ = ch;
1861 if (ch == CHAR_CR) {
1862 aWin->y_curs++;
1863 aWin->y_size++;
1864 aWin->x_curs = 0;
1865 newWidth = TextWidth(sline, 0, src - sline);
1866 if (newWidth > maxWidth) {
1867 maxWidth = newWidth;
1869 sline = src + 1; /* keep track of where new line begins */
1870 } else
1871 aWin->x_curs++;
1872 src++;
1875 newWidth = TextWidth(sline, 0, src - sline);
1876 if (newWidth > maxWidth) {
1877 maxWidth = newWidth;
1880 aWin->windowTextLen += slen;
1882 if (ch != CHAR_CR) {
1883 (*(aWin->windowText))[len + slen] = CHAR_CR;
1884 aWin->windowTextLen++;
1885 aWin->y_curs++;
1886 aWin->y_size++;
1887 aWin->x_curs = 0;
1890 if (win == WIN_MESSAGE) {
1891 short min = aWin->y_size - (r.bottom - r.top) / aWin->row_height;
1892 if (aWin->scrollPos < min) {
1893 aWin->scrollPos = min;
1894 SetControlMaximum(aWin->scrollBar, aWin->y_size);
1895 SetControlValue(aWin->scrollBar, min);
1897 InvalWindowRect(aWin->its_window, &r);
1898 } else /* Message has a fixed width, other windows base on content */
1899 if (maxWidth > aWin->x_size)
1900 aWin->x_size = maxWidth;
1901 in_putstr--;
1904 void
1905 mac_curs(winid win, int x, int y)
1907 NhWindow *aWin = &theWindows[win];
1909 if (aWin->its_window == _mt_window) {
1910 tty_curs(win, x, y);
1911 return;
1914 SetPortWindowPort(aWin->its_window);
1915 MoveTo(x * aWin->char_width,
1916 (y * aWin->row_height) + aWin->ascent_height);
1917 aWin->x_curs = x;
1918 aWin->y_curs = y;
1922 mac_nh_poskey(int *a, int *b, int *c)
1924 int ch = mac_nhgetch();
1925 *a = clicked_pos.h;
1926 *b = clicked_pos.v;
1927 *c = clicked_mod;
1928 return ch;
1931 void
1932 mac_start_menu(winid win)
1934 HideWindow(theWindows[win].its_window);
1935 mac_clear_nhwindow(win);
1938 void
1939 mac_add_menu(winid win, int glyph, const anything *any, CHAR_P menuChar,
1940 CHAR_P groupAcc, int attr, const char *inStr, int preselected)
1942 #if defined(__SC__) || defined(__MRC__)
1943 #pragma unused(glyph)
1944 #endif
1945 NhWindow *aWin = &theWindows[win];
1946 const char *str;
1947 char locStr[4 + BUFSZ];
1948 MacMHMenuItem *item;
1950 if (!inStr)
1951 return;
1953 if (any->a_void != 0) {
1954 #define kMenuSizeBump 26
1955 if (!aWin->miSize) {
1956 aWin->menuInfo = (MacMHMenuItem **) NewHandle(
1957 sizeof(MacMHMenuItem) * kMenuSizeBump);
1958 if (!aWin->menuInfo) {
1959 error("Can't alloc menu handle");
1960 return;
1962 aWin->menuSelected =
1963 (short **) NewHandle(sizeof(short) * kMenuSizeBump);
1964 if (!aWin->menuSelected) {
1965 error("Can't alloc menu select handle");
1966 return;
1968 aWin->miSize = kMenuSizeBump;
1971 if (aWin->miLen >= aWin->miSize) {
1972 SetHandleSize((Handle) aWin->menuInfo,
1973 sizeof(MacMHMenuItem)
1974 * (aWin->miLen + kMenuSizeBump));
1975 if (MemError()) {
1976 error("Can't resize menu handle");
1977 return;
1979 SetHandleSize((Handle) aWin->menuSelected,
1980 sizeof(short) * (aWin->miLen + kMenuSizeBump));
1981 if (MemError()) {
1982 error("Can't resize menu select handle");
1983 return;
1985 aWin->miSize += kMenuSizeBump;
1988 if (menuChar == 0) {
1989 if (('a' <= aWin->menuChar && aWin->menuChar <= 'z')
1990 || ('A' <= aWin->menuChar && aWin->menuChar <= 'Z')) {
1991 menuChar = aWin->menuChar++;
1992 if (menuChar == 'z')
1993 aWin->menuChar = 'A';
1997 Sprintf(locStr, "%c - %s", (menuChar ? menuChar : ' '), inStr);
1998 str = locStr;
1999 HLock((char **) aWin->menuInfo);
2000 HLock((char **) aWin->menuSelected);
2001 (*aWin->menuSelected)[aWin->miLen] = preselected;
2002 item = &(*aWin->menuInfo)[aWin->miLen];
2003 aWin->miLen++;
2004 item->id = *any;
2005 item->accelerator = menuChar;
2006 item->groupAcc = groupAcc;
2007 item->line = aWin->y_size;
2008 HUnlock((char **) aWin->menuInfo);
2009 HUnlock((char **) aWin->menuSelected);
2010 } else
2011 str = inStr;
2013 putstr(win, attr, str);
2017 * End a menu in this window, window must a type NHW_MENU.
2018 * str is a list of cancel characters (values that may be input)
2019 * morestr is a prompt to display, rather than the default.
2020 * str and morestr might be ignored by some ports.
2022 void
2023 mac_end_menu(winid win, const char *morestr)
2025 Str255 buf;
2026 NhWindow *aWin = &theWindows[win];
2028 buf[0] = 0;
2029 if (morestr)
2030 C2P(morestr, buf);
2031 SetWTitle(aWin->its_window, buf);
2035 mac_select_menu(winid win, int how, menu_item **selected_list)
2037 int c;
2038 NhWindow *aWin = &theWindows[win];
2039 WindowPtr theWin = aWin->its_window;
2041 inSelect = win;
2043 mac_display_nhwindow(win, FALSE);
2045 aWin->how = (short) how;
2046 for (;;) {
2047 c = map_menu_cmd(mac_nhgetch());
2048 if (c == CHAR_ESC) {
2049 /* deselect everything */
2050 aWin->miSelLen = 0;
2051 break;
2052 } else if (ClosingWindowChar(c)) {
2053 break;
2054 } else {
2055 nhbell();
2059 HideWindow(theWin);
2061 if (aWin->miSelLen) {
2062 menu_item *mp;
2063 MacMHMenuItem *mi;
2064 *selected_list = mp =
2065 (menu_item *) alloc(aWin->miSelLen * sizeof(menu_item));
2066 HLock((char **) aWin->menuInfo);
2067 HLock((char **) aWin->menuSelected);
2068 for (c = 0; c < aWin->miSelLen; c++) {
2069 mi = &(*aWin->menuInfo)[(*aWin->menuSelected)[c]];
2070 mp->item = mi->id;
2071 mp->count = -1L;
2072 mp++;
2074 HUnlock((char **) aWin->menuInfo);
2075 HUnlock((char **) aWin->menuSelected);
2076 } else
2077 *selected_list = 0;
2079 inSelect = WIN_ERR;
2081 return aWin->miSelLen;
2084 #include "dlb.h"
2086 static void
2087 mac_display_file(name, complain)
2088 const char *name; /* not ANSI prototype because of boolean parameter */
2089 boolean complain;
2091 Ptr buf;
2092 int win;
2093 dlb *fp = dlb_fopen(name, "r");
2095 if (fp) {
2096 long l = dlb_fseek(fp, 0, SEEK_END);
2097 (void) dlb_fseek(fp, 0, 0L);
2098 buf = NewPtr(l + 1);
2099 if (buf) {
2100 l = dlb_fread(buf, 1, l, fp);
2101 if (l > 0) {
2102 buf[l] = '\0';
2103 win = create_nhwindow(NHW_TEXT);
2104 if (WIN_ERR == win) {
2105 if (complain)
2106 error("Cannot make window.");
2107 } else {
2108 putstr(win, 0, buf);
2109 display_nhwindow(win, FALSE);
2112 DisposePtr(buf);
2114 dlb_fclose(fp);
2115 } else if (complain)
2116 error("Cannot open %s.", name);
2119 void
2120 port_help()
2122 display_file(PORT_HELP, TRUE);
2125 static void
2126 mac_unimplemented(void)
2130 static void
2131 mac_suspend_nhwindows(const char *foo)
2133 #if defined(__SC__) || defined(__MRC__)
2134 #pragma unused(foo)
2135 #endif
2136 /* Can't really do that :-) */
2140 try_key_queue(char *bufp)
2142 if (keyQueueCount) {
2143 char ch;
2144 for (ch = GetFromKeyQueue();; ch = GetFromKeyQueue()) {
2145 if (ch == CHAR_LF || ch == CHAR_CR)
2146 ch = 0;
2147 *bufp++ = ch;
2148 if (ch == 0)
2149 break;
2151 return 1;
2153 return 0;
2156 /**********************************************************************
2157 * Base window
2160 static void
2161 BaseClick(NhWindow *wind, Point pt, UInt32 modifiers)
2163 pt.h = pt.h / wind->char_width + 1;
2164 pt.v = pt.v / wind->row_height;
2165 clicked_mod = (modifiers & shiftKey) ? CLICK_2 : CLICK_1;
2167 if (strchr(topl_resp, *click_to_cmd(pt.h, pt.v, clicked_mod)))
2168 nhbell();
2169 else {
2170 #if 1 //!TARGET_API_MAC_CARBON
2171 if (cursor_locked)
2172 while (WaitMouseUp())
2173 /*SystemTask()*/;
2174 #endif
2176 gClickedToMove = TRUE;
2177 clicked_pos = pt;
2179 return;
2182 static void
2183 BaseCursor(NhWindow *wind, Point pt)
2185 char *dir_bas, *dir;
2186 CursHandle ch;
2188 if (cursor_locked)
2189 dir = (char *) 0;
2190 else {
2191 dir_bas = (char *) Cmd.dirchars;
2192 dir =
2193 strchr(dir_bas, *click_to_cmd(pt.h / wind->char_width + 1,
2194 pt.v / wind->row_height, CLICK_1));
2196 ch = GetCursor(dir ? dir - dir_bas + 513 : 512);
2197 if (ch) {
2198 HLock((Handle) ch);
2199 SetCursor(*ch);
2200 HUnlock((Handle) ch);
2201 } else {
2202 SetCursor(&qdarrow);
2204 return;
2207 #if 0 // TARGET_API_MAC_CARBON
2208 static pascal OSStatus
2209 BaseEvent(EventHandlerCallRef nexthandler, EventRef event, void *userdata)
2211 NhWindow *wind = (NhWindow *) userdata;
2214 switch (GetEventClass(event)) {
2215 case kEventClassKeyboard: {
2216 char ch;
2217 UInt32 modifiers;
2220 GetEventParameter(event, kEventParamKeyMacCharCodes, typeChar, NULL,
2221 sizeof(char), NULL, &ch);
2222 GetEventParameter(event, kEventParamKeyModifiers, typeUInt32, NULL,
2223 sizeof(UInt32), NULL, &modifiers);
2224 if (modifiers & cmdKey)
2225 return (eventNotHandledErr);
2226 AddToKeyQueue(topl_resp_key(ch), TRUE);
2227 return (noErr);
2230 case kEventClassMouse: {
2231 CGrafPtr saveport;
2232 GDHandle savedev;
2233 Point pt;
2235 switch (GetEventKind(event)) {
2236 case kEventMouseMoved:
2237 GetEventParameter(event, kEventParamMouseLocation, typeQDPoint,
2238 NULL, sizeof(Point), NULL, &pt);
2239 GetGWorld(&saveport, &savedev);
2240 SetPortWindowPort(wind->its_window);
2241 GlobalToLocal(&pt);
2242 SetGWorld(saveport, savedev);
2243 BaseCursor(wind, pt);
2244 return (eventNotHandledErr);
2246 break;
2249 case kEventClassWindow:
2250 switch (GetEventKind(event)) {
2251 case kEventWindowDrawContent:
2252 CallNextEventHandler(nexthandler, event);
2253 image_tty(NULL, wind->its_window);
2254 return (noErr);
2256 case kEventWindowHandleContentClick: {
2257 CGrafPtr saveport;
2258 GDHandle savedev;
2259 Point pt;
2260 UInt32 modifiers;
2262 GetEventParameter(event, kEventParamMouseLocation, typeQDPoint,
2263 NULL, sizeof(Point), NULL, &pt);
2264 GetEventParameter(event, kEventParamKeyModifiers, typeUInt32, NULL,
2265 sizeof(UInt32), NULL, &modifiers);
2266 GetGWorld(&saveport, &savedev);
2267 SetPortWindowPort(wind->its_window);
2268 GlobalToLocal(&pt);
2269 SetGWorld(saveport, savedev);
2270 BaseClick(wind, pt, modifiers);
2271 return (noErr);
2274 case kEventWindowClose:
2275 /* TODO... */
2276 break;
2278 break;
2280 return (eventNotHandledErr);
2283 #else
2285 static void
2286 macClickTerm(EventRecord *theEvent, WindowPtr theWindow)
2288 Point where = theEvent->where;
2290 GlobalToLocal(&where);
2291 BaseClick(GetNhWin(theWindow), where, theEvent->modifiers);
2292 return;
2295 static void
2296 macCursorTerm(EventRecord *theEvent, WindowPtr theWindow, RgnHandle mouseRgn)
2298 GrafPtr gp;
2299 Point where = theEvent->where;
2300 Rect r = { 0, 0, 1, 1 };
2302 GetPort(&gp);
2303 SetPortWindowPort(theWindow);
2304 GlobalToLocal(&where);
2305 BaseCursor(GetNhWin(theWindow), where);
2306 OffsetRect(&r, theEvent->where.h, theEvent->where.v);
2307 RectRgn(mouseRgn, &r);
2308 SetPort(gp);
2309 return;
2312 #endif /* !TARGET_API_MAC_CARBON */
2314 /**********************************************************************
2315 * Status subwindow
2318 /**********************************************************************
2319 * Map subwindow
2322 /**********************************************************************
2323 * Message window
2326 static void
2327 MsgClick(NhWindow *wind, Point pt)
2329 int r_idx = 0;
2331 while (topl_resp[r_idx]) {
2332 Rect frame;
2333 topl_resp_rect(r_idx, &frame);
2334 InsetRect(&frame, 1, 1);
2335 if (PtInRect(pt, &frame)) {
2336 Boolean in_btn = true;
2338 InvertRect(&frame);
2339 while (WaitMouseUp()) {
2340 #if !TARGET_API_MAC_CARBON
2341 SystemTask();
2342 #endif
2343 GetMouse(&pt);
2344 if (PtInRect(pt, &frame) != in_btn) {
2345 in_btn = !in_btn;
2346 InvertRect(&frame);
2349 if (in_btn) {
2350 InvertRect(&frame);
2351 AddToKeyQueue(topl_resp[r_idx], 1);
2353 return;
2355 ++r_idx;
2357 return;
2360 static void
2361 MsgUpdate(NhWindow *wind)
2363 RgnHandle org_clip = NewRgn(), clip = NewRgn();
2364 Rect r;
2365 int l;
2367 GetClip(org_clip);
2368 GetWindowBounds(wind->its_window, kWindowContentRgn, &r);
2369 OffsetRect(&r, -r.left, -r.top);
2371 DrawControls(wind->its_window);
2372 DrawGrowIcon(wind->its_window);
2374 for (l = 0; topl_resp[l]; l++) {
2375 StringPtr name;
2376 unsigned char tmp[2];
2377 FontInfo font;
2378 Rect frame;
2379 topl_resp_rect(l, &frame);
2380 switch (topl_resp[l]) {
2381 case 'y':
2382 name = "\pyes";
2383 break;
2384 case 'n':
2385 name = "\pno";
2386 break;
2387 case 'N':
2388 name = "\pNone";
2389 break;
2390 case 'a':
2391 name = "\pall";
2392 break;
2393 case 'q':
2394 name = "\pquit";
2395 break;
2396 case CHAR_ANY:
2397 name = "\pany key";
2398 break;
2399 default:
2400 tmp[0] = 1;
2401 tmp[1] = topl_resp[l];
2402 name = tmp;
2403 break;
2405 TextFont(kFontIDGeneva);
2406 TextSize(9);
2407 GetFontInfo(&font);
2408 MoveTo((frame.left + frame.right - StringWidth(name)) / 2,
2409 (frame.top + frame.bottom + font.ascent - font.descent
2410 - font.leading - 1) / 2);
2411 DrawString(name);
2412 PenNormal();
2413 if (l == topl_def_idx)
2414 PenSize(2, 2);
2415 FrameRoundRect(&frame, 4, 4);
2418 r.right -= SBARWIDTH;
2419 r.bottom -= SBARHEIGHT;
2420 /* Clip to the portrect - scrollbar/growicon *before* adjusting the rect
2421 to be larger than the size of the window (!) */
2422 RectRgn(clip, &r);
2423 SectRgn(clip, org_clip, clip);
2424 if (r.right < MIN_RIGHT)
2425 r.right = MIN_RIGHT;
2426 r.top -= wind->scrollPos * wind->row_height;
2428 #if 0
2429 /* If you enable this band of code (and disable the next band), you will get
2430 fewer flickers but a slower performance while drawing the dot line. */
2431 { RgnHandle dotl_rgn = NewRgn();
2432 Rect dotl;
2433 dotl.left = r.left;
2434 dotl.right = r.right;
2435 dotl.bottom = r.top + aWin->save_lin * aWin->row_height;
2436 dotl.top = dotl.bottom - 1;
2437 FillRect(&dotl, &qd.gray);
2438 RectRgn(dotl_rgn, &dotl);
2439 DiffRgn(clip, dotl_rgn, clip);
2440 DisposeRgn(dotl_rgn);
2441 SetClip(clip);
2443 #endif
2445 if (in_topl_mode()) {
2446 RgnHandle topl_rgn = NewRgn();
2447 Rect topl_r = r;
2448 topl_r.top += (wind->y_size - 1) * wind->row_height;
2449 l = (*top_line)->destRect.right - (*top_line)->destRect.left;
2450 (*top_line)->viewRect = topl_r;
2451 (*top_line)->destRect = topl_r;
2452 if (l != topl_r.right - topl_r.left)
2453 TECalText(top_line);
2454 TEUpdate(&topl_r, top_line);
2455 RectRgn(topl_rgn, &topl_r);
2456 DiffRgn(clip, topl_rgn, clip);
2457 DisposeRgn(topl_rgn);
2458 SetClip(clip);
2461 DisposeRgn(clip);
2463 TextFont(wind->font_number);
2464 TextSize(wind->font_size);
2465 HLock(wind->windowText);
2466 TETextBox(*wind->windowText, wind->windowTextLen, &r, teJustLeft);
2467 HUnlock(wind->windowText);
2469 #if !TARGET_API_MAC_CARBON
2470 r.bottom = r.top + aWin->save_lin * aWin->row_height;
2471 r.top = r.bottom - 1;
2472 FillRect(&r, (void *) &qd.gray);
2473 #endif
2475 SetClip(org_clip);
2476 DisposeRgn(org_clip);
2477 return;
2480 #if 0 // TARGET_API_MAC_CARBON
2481 static pascal OSStatus
2482 MsgEvent(EventHandlerCallRef nexthandler, EventRef event, void *userdata)
2484 NhWindow *wind = (NhWindow *) userdata;
2487 switch (GetEventClass(event)) {
2488 case kEventClassControl: {
2489 ControlRef control;
2490 ControlID id;
2492 switch (GetEventKind(event)) {
2493 case kEventControlHit:
2494 GetEventParameter(event, kEventParamDirectObject,
2495 typeControlRef, NULL, sizeof(ControlRef), NULL, &control);
2496 GetControlID(control, &id);
2497 /* TODO... */
2498 return (noErr);
2500 break;
2503 case kEventClassKeyboard: {
2504 char ch;
2505 UInt32 modifiers;
2508 GetEventParameter(event, kEventParamKeyMacCharCodes, typeChar, NULL,
2509 sizeof(char), NULL, &ch);
2510 GetEventParameter(event, kEventParamKeyModifiers, typeUInt32, NULL,
2511 sizeof(UInt32), NULL, &modifiers);
2512 if (modifiers & cmdKey)
2513 return (eventNotHandledErr);
2514 AddToKeyQueue(topl_resp_key(ch), TRUE);
2515 return (noErr);
2518 case kEventClassWindow:
2519 switch (GetEventKind(event)) {
2520 case kEventWindowDrawContent:
2521 CallNextEventHandler(nexthandler, event);
2522 MsgUpdate(wind);
2523 return (noErr);
2525 case kEventWindowHandleContentClick: {
2526 CGrafPtr saveport;
2527 GDHandle savedev;
2528 Point pt;
2530 GetEventParameter(event, kEventParamMouseLocation, typeQDPoint,
2531 NULL, sizeof(Point), NULL, &pt);
2532 GetGWorld(&saveport, &savedev);
2533 SetPortWindowPort(wind->its_window);
2534 GlobalToLocal(&pt);
2535 SetGWorld(saveport, savedev);
2536 MsgClick(wind, pt);
2537 return (noErr);
2540 case kEventWindowClose:
2541 /* TODO... */
2542 break;
2544 break;
2546 return (eventNotHandledErr);
2549 #else
2551 static void
2552 macClickMessage(EventRecord *theEvent, WindowPtr theWindow)
2554 Point mouse = theEvent->where;
2556 GlobalToLocal(&mouse);
2557 MsgClick(GetNhWin(theWindow), mouse);
2558 macClickText(theEvent, theWindow);
2561 static short
2562 macUpdateMessage(EventRecord *theEvent, WindowPtr theWindow)
2564 if (!theEvent)
2565 return 0;
2566 MsgUpdate(GetNhWin(theWindow));
2567 return 0;
2570 #endif /* !TARGET_API_MAC_CARBON */
2572 /**********************************************************************
2573 * Menu windows
2576 static void
2577 MenwKey(NhWindow *wind, char ch)
2579 MacMHMenuItem *mi;
2580 int i;
2582 ch = filter_scroll_key(ch, wind);
2583 if (!ch)
2584 return;
2585 if (ClosingWindowChar(ch)) {
2586 AddToKeyQueue(CHAR_CR, 1);
2587 return;
2590 if (!wind || !wind->menuInfo)
2591 return;
2592 HLock((char **) wind->menuInfo);
2593 for (i = 0, mi = *wind->menuInfo; i < wind->miLen; i++, mi++) {
2594 if (mi->accelerator == ch) {
2595 ToggleMenuListItemSelected(wind, i);
2596 if (mi->line >= wind->scrollPos && mi->line <= wind->y_size) {
2597 SetPortWindowPort(wind->its_window);
2598 ToggleMenuSelect(wind, mi->line - wind->scrollPos);
2600 /* Dismiss window if only picking one item */
2601 if (wind->how != PICK_ANY)
2602 AddToKeyQueue(CHAR_CR, 1);
2603 break;
2606 HUnlock((char **) wind->menuInfo);
2607 /* add key if didn't find it in menu and not filtered */
2608 return;
2611 static void
2612 MenwClick(NhWindow *wind, Point pt)
2614 Rect wrect;
2616 GetWindowBounds(wind->its_window, kWindowContentRgn, &wrect);
2617 OffsetRect(&wrect, -wrect.left, -wrect.top);
2618 if (inSelect != WIN_ERR && wind->how != PICK_NONE) {
2619 short currentRow = -1, previousRow = -1;
2620 short previousItem = -1, item = -1;
2621 Boolean majorSelectState, firstRow = TRUE;
2623 do {
2624 #if !TARGET_API_MAC_CARBON
2625 SystemTask();
2626 #endif
2627 GetMouse(&pt);
2628 currentRow = pt.v / wind->row_height;
2629 if (pt.h < wrect.left || pt.h > wrect.right || pt.v < 0
2630 || pt.v > wrect.bottom || currentRow >= wind->y_size) {
2631 continue; /* not in window range */
2634 item = ListCoordinateToItem(wind, currentRow);
2636 if (item != previousItem) {
2637 /* Implement typical Mac multiple-selection behavior
2638 * (ie, not the UI implemented by the Finder)
2640 Boolean itemIsSelected = (ListItemSelected(wind, item) >= 0);
2642 if (firstRow) {
2643 /* this is first valid row, so major state is opposite of
2644 * what this row is */
2645 majorSelectState = !itemIsSelected;
2646 firstRow = FALSE;
2649 if (wind->how == PICK_ONE && previousItem != -1) {
2650 /* if previous row was selected and we're only selecting
2651 * one object,
2652 * deselect previous row!
2654 ToggleMenuListItemSelected(wind, previousItem);
2655 ToggleMenuSelect(wind, previousRow);
2656 previousItem = -1;
2659 if (item == -1)
2660 continue; /* header line */
2662 if (majorSelectState != itemIsSelected) {
2663 ToggleMenuListItemSelected(wind, item);
2664 ToggleMenuSelect(wind, currentRow);
2667 previousRow = currentRow;
2668 previousItem = item;
2670 } while (StillDown());
2672 /* Dismiss window if only picking one item */
2673 if (wind->how == PICK_ONE)
2674 AddToKeyQueue(CHAR_CR, 1);
2676 return;
2679 static void
2680 MenwUpdate(NhWindow *wind)
2682 int i, line;
2683 MacMHMenuItem *mi;
2685 TextUpdate(wind);
2686 HLock((Handle) wind->menuInfo);
2687 HLock((Handle) wind->menuSelected);
2688 for (i = 0; i < wind->miSelLen; i++) {
2689 mi = &(*wind->menuInfo)[(*wind->menuSelected)[i]];
2690 line = mi->line;
2691 if (line > wind->scrollPos && line <= wind->y_size)
2692 ToggleMenuSelect(wind, line - wind->scrollPos);
2694 HUnlock((Handle) wind->menuInfo);
2695 HUnlock((Handle) wind->menuSelected);
2696 return;
2699 #if 0 // TARGET_API_MAC_CARBON
2700 static pascal OSStatus
2701 MenwEvent(EventHandlerCallRef nexthandler, EventRef event, void *userdata)
2703 NhWindow *wind = (NhWindow *) userdata;
2706 switch (GetEventClass(event)) {
2707 case kEventClassControl: {
2708 ControlRef control;
2709 ControlID id;
2711 switch (GetEventKind(event)) {
2712 case kEventControlHit:
2713 GetEventParameter(event, kEventParamDirectObject,
2714 typeControlRef, NULL, sizeof(ControlRef), NULL, &control);
2715 GetControlID(control, &id);
2716 /* TODO... */
2717 return (noErr);
2719 break;
2722 case kEventClassKeyboard: {
2723 char ch;
2724 UInt32 modifiers;
2727 GetEventParameter(event, kEventParamKeyMacCharCodes, typeChar, NULL,
2728 sizeof(char), NULL, &ch);
2729 GetEventParameter(event, kEventParamKeyModifiers, typeUInt32, NULL,
2730 sizeof(UInt32), NULL, &modifiers);
2731 if (modifiers & cmdKey)
2732 return (eventNotHandledErr);
2733 MenwKey(wind, ch);
2734 return (noErr);
2737 case kEventClassWindow:
2738 switch (GetEventKind(event)) {
2739 case kEventWindowDrawContent:
2740 CallNextEventHandler(nexthandler, event);
2741 MenwUpdate(wind);
2742 return (noErr);
2744 case kEventWindowHandleContentClick: {
2745 CGrafPtr saveport;
2746 GDHandle savedev;
2747 Point pt;
2749 GetEventParameter(event, kEventParamMouseLocation, typeQDPoint,
2750 NULL, sizeof(Point), NULL, &pt);
2751 GetGWorld(&saveport, &savedev);
2752 SetPortWindowPort(wind->its_window);
2753 GlobalToLocal(&pt);
2754 SetGWorld(saveport, savedev);
2755 MenwClick(wind, pt);
2756 return (noErr);
2759 case kEventWindowClose:
2760 /* TODO... */
2761 break;
2763 break;
2765 return (eventNotHandledErr);
2768 #else
2770 static void
2771 macKeyMenu(EventRecord *theEvent, WindowPtr theWindow)
2773 MenwKey(GetNhWin(theWindow), theEvent->message & 0xff);
2774 return;
2777 static void
2778 macClickMenu(EventRecord *theEvent, WindowRef theWindow)
2780 Point p;
2781 NhWindow *aWin = GetNhWin(theWindow);
2783 if (aWin->scrollBar && IsControlVisible(aWin->scrollBar)) {
2784 short code;
2785 ControlHandle theBar;
2787 p = theEvent->where;
2788 GlobalToLocal(&p);
2789 code = FindControl(p, theWindow, &theBar);
2790 if (code) {
2791 DoScrollBar(p, code, theBar, aWin);
2792 return;
2795 MenwClick(aWin, theEvent->where);
2798 static short
2799 macUpdateMenu(EventRecord *theEvent, WindowPtr theWindow)
2801 MenwUpdate(GetNhWin(theWindow));
2802 return 0;
2805 #endif /* !TARGET_API_MAC_CARBON */
2807 /**********************************************************************
2808 * Text windows
2811 static void
2812 TextKey(NhWindow *wind, char ch)
2814 ch = filter_scroll_key(ch, wind);
2815 if (!ch)
2816 return;
2817 if (inSelect == WIN_ERR && ClosingWindowChar(ch)) {
2818 HideWindow(wind->its_window);
2819 mac_destroy_nhwindow(wind - theWindows);
2820 } else
2821 AddToKeyQueue(topl_resp_key(ch), TRUE);
2822 return;
2825 static void
2826 TextUpdate(NhWindow *wind)
2828 Rect r, r2;
2829 RgnHandle h;
2830 Boolean vis;
2832 GetWindowBounds(wind->its_window, kWindowContentRgn, &r);
2833 OffsetRect(&r, -r.left, -r.top);
2834 r2 = r;
2835 r2.left = r2.right - SBARWIDTH;
2836 r2.right += 1;
2837 r2.top -= 1;
2838 vis = (r2.bottom > r2.top + 50);
2840 draw_growicon_vert_only(wind->its_window);
2841 DrawControls(wind->its_window);
2843 h = (RgnHandle) 0;
2844 if (vis && (h = NewRgn())) {
2845 RgnHandle tmp = NewRgn();
2846 if (!tmp) {
2847 DisposeRgn(h);
2848 h = (RgnHandle) 0;
2849 } else {
2850 GetClip(h);
2851 RectRgn(tmp, &r2);
2852 DiffRgn(h, tmp, tmp);
2853 SetClip(tmp);
2854 DisposeRgn(tmp);
2857 if (r.right < MIN_RIGHT)
2858 r.right = MIN_RIGHT;
2859 r.top -= wind->scrollPos * wind->row_height;
2860 r.right -= SBARWIDTH;
2861 HLock(wind->windowText);
2862 TETextBox(*wind->windowText, wind->windowTextLen, &r, teJustLeft);
2863 HUnlock(wind->windowText);
2864 if (h) {
2865 SetClip(h);
2866 DisposeRgn(h);
2868 return;
2871 #if 0 // TARGET_API_MAC_CARBON
2872 static pascal OSStatus
2873 TextEvent(EventHandlerCallRef nexthandler, EventRef event, void *userdata)
2875 NhWindow *wind = (NhWindow *) userdata;
2878 switch (GetEventClass(event)) {
2879 case kEventClassControl: {
2880 ControlRef control;
2881 ControlID id;
2883 switch (GetEventKind(event)) {
2884 case kEventControlHit:
2885 GetEventParameter(event, kEventParamDirectObject,
2886 typeControlRef, NULL, sizeof(ControlRef), NULL, &control);
2887 GetControlID(control, &id);
2888 /* TODO... */
2889 return (noErr);
2891 break;
2894 case kEventClassKeyboard: {
2895 char ch;
2896 UInt32 modifiers;
2899 GetEventParameter(event, kEventParamKeyMacCharCodes, typeChar, NULL,
2900 sizeof(char), NULL, &ch);
2901 GetEventParameter(event, kEventParamKeyModifiers, typeUInt32, NULL,
2902 sizeof(UInt32), NULL, &modifiers);
2903 if (modifiers & cmdKey)
2904 return (eventNotHandledErr);
2905 TextKey(wind, ch);
2906 return (noErr);
2909 case kEventClassWindow:
2910 switch (GetEventKind(event)) {
2911 case kEventWindowDrawContent:
2912 CallNextEventHandler(nexthandler, event);
2913 TextUpdate(wind);
2914 return (noErr);
2916 case kEventWindowClose:
2917 /* TODO... */
2918 break;
2920 break;
2922 return (eventNotHandledErr);
2925 #else
2927 static void
2928 macKeyText(EventRecord *theEvent, WindowPtr theWindow)
2930 TextKey(GetNhWin(theWindow), theEvent->message & 0xff);
2931 return;
2934 static void
2935 macClickText(EventRecord *theEvent, WindowPtr theWindow)
2937 NhWindow *aWin = GetNhWin(theWindow);
2939 if (aWin->scrollBar && IsControlVisible(aWin->scrollBar)) {
2940 short code;
2941 Point p = theEvent->where;
2942 ControlHandle theBar;
2944 GlobalToLocal(&p);
2945 code = FindControl(p, theWindow, &theBar);
2946 if (code) {
2947 DoScrollBar(p, code, theBar, aWin);
2952 #endif /* !TARGET_API_MAC_CARBON */
2954 /**********************************************************************
2955 * Global events
2958 #if 0 // TARGET_API_MAC_CARBON
2959 static pascal OSStatus
2960 GlobalEvent(EventHandlerCallRef nexthandler, EventRef event, void *userdata)
2962 switch (GetEventClass(event)) {
2963 case kEventClassCommand:
2964 return (eventNotHandledErr);
2966 return (eventNotHandledErr);
2969 #else
2971 static short
2972 macDoNull(EventRecord *theEvent, WindowPtr theWindow)
2974 return 0;
2978 * Note; theWindow may very well be null here, since keyDown may call
2979 * it when theres no window !!!
2981 /* NOT_IN_CARBON */
2982 static void
2983 GeneralKey(EventRecord *theEvent, WindowPtr theWindow)
2985 #if defined(__SC__) || defined(__MRC__)
2986 #pragma unused(theWindow)
2987 #endif
2988 #if 0
2989 trans_num_keys (theEvent);
2990 #endif
2991 AddToKeyQueue(topl_resp_key(theEvent->message & 0xff), TRUE);
2994 static void
2995 HandleKey(EventRecord *theEvent)
2997 WindowPtr theWindow = FrontWindow();
2999 if (theEvent->modifiers & cmdKey) {
3000 if (theEvent->message & 0xff == '.') {
3001 /* Flush key queue */
3002 keyQueueCount = keyQueueWrite = keyQueueRead = 0;
3003 theEvent->message = '\033';
3004 goto dispatchKey;
3005 } else {
3006 UndimMenuBar();
3007 DoMenuEvt(MenuKey(theEvent->message & 0xff));
3009 } else {
3010 dispatchKey:
3011 if (theWindow) {
3012 int kind = GetWindowKind(theWindow) - WIN_BASE_KIND;
3013 winKeyFuncs[kind](theEvent, theWindow);
3014 } else {
3015 GeneralKey(theEvent, (WindowPtr) 0);
3020 #endif /* !TARGET_API_MAC_CARBON */
3022 static void
3023 HandleClick(EventRecord *theEvent)
3025 int code;
3026 unsigned long l;
3027 WindowPtr theWindow;
3028 NhWindow *aWin;
3029 Rect r;
3030 Boolean not_inSelect;
3032 InsetRect(GetRegionBounds(GetGrayRgn(), &r), 4, 4);
3034 code = FindWindow(theEvent->where, &theWindow);
3035 aWin = GetNhWin(theWindow);
3036 not_inSelect = (inSelect == WIN_ERR || aWin - theWindows == inSelect);
3038 switch (code) {
3039 case inContent:
3040 #if 1 //!TARGET_API_MAC_CARBON
3041 if (not_inSelect) {
3042 int kind = GetWindowKind(theWindow) - WIN_BASE_KIND;
3043 winCursorFuncs[kind](theEvent, theWindow, gMouseRgn);
3044 SelectWindow(theWindow);
3045 SetPortWindowPort(theWindow);
3046 winClickFuncs[kind](theEvent, theWindow);
3047 } else {
3048 nhbell();
3050 #endif
3051 break;
3053 case inDrag:
3054 if (not_inSelect) {
3055 SetCursor(&qdarrow);
3056 DragWindow(theWindow, theEvent->where, &r);
3057 SaveWindowPos(theWindow);
3058 } else {
3059 nhbell();
3061 break;
3063 case inGrow:
3064 if (not_inSelect) {
3065 SetCursor(&qdarrow);
3066 SetRect(&r, 80, 2 * aWin->row_height + 1, r.right, r.bottom);
3067 if (aWin == theWindows + WIN_MESSAGE)
3068 r.top += SBARHEIGHT;
3069 l = GrowWindow(theWindow, theEvent->where, &r);
3070 SizeWindow(theWindow, l & 0xffff, l >> 16, FALSE);
3071 SaveWindowSize(theWindow);
3072 SetPortWindowPort(theWindow);
3073 GetWindowBounds(theWindow, kWindowContentRgn, &r);
3074 OffsetRect(&r, -r.left, -r.top);
3075 InvalWindowRect(theWindow, &r);
3076 if (aWin->scrollBar) {
3077 DrawScrollbar(aWin);
3079 } else {
3080 nhbell();
3082 break;
3084 case inGoAway:
3085 WindowGoAway(theEvent, theWindow);
3086 break;
3088 case inMenuBar:
3089 DoMenuEvt(MenuSelect(theEvent->where));
3090 break;
3092 #if !TARGET_API_MAC_CARBON
3093 case inSysWindow:
3094 SystemClick(theEvent, theWindow);
3095 #endif
3096 default:
3097 break;
3101 #if 1 //!TARGET_API_MAC_CARBON
3103 static short
3104 GeneralUpdate(EventRecord *theEvent, WindowPtr theWindow)
3106 if (!theEvent)
3107 return 0;
3108 TextUpdate(GetNhWin(theWindow));
3109 return 0;
3112 #endif
3114 static void
3115 HandleUpdate(EventRecord *theEvent)
3117 WindowPtr theWindow = (WindowPtr) theEvent->message;
3118 NhWindow *aWin = GetNhWin(theWindow);
3119 Rect r;
3120 #if 1 //!TARGET_API_MAC_CARBON
3121 EventRecord fake;
3122 #endif
3124 char existing_update_region = FALSE;
3125 Rect rect;
3127 if (theWindow == _mt_window) {
3128 existing_update_region =
3129 (get_invalid_region(theWindow, &rect) == noErr);
3131 BeginUpdate(theWindow);
3132 SetPortWindowPort(theWindow);
3133 GetWindowBounds(theWindow, kWindowContentRgn, &r);
3134 OffsetRect(&r, -r.left, -r.top);
3135 EraseRect(&r);
3136 #if 0 // TARGET_API_MAC_CARBON
3137 switch (GetWindowKind(theWindow) - WIN_BASE_KIND) {
3138 case NHW_BASE:
3139 case NHW_MAP:
3140 case NHW_STATUS:
3141 image_tty(NULL, theWindow);
3142 break;
3143 case NHW_MESSAGE:
3144 MsgUpdate(GetNhWin(theWindow));
3145 break;
3146 case NHW_MENU:
3147 MenwUpdate(GetNhWin(theWindow));
3148 break;
3149 case NHW_TEXT:
3150 TextUpdate(GetNhWin(theWindow));
3151 break;
3153 #else
3154 winUpdateFuncs[GetWindowKind(theWindow) - WIN_BASE_KIND](&fake,
3155 theWindow);
3156 #endif
3158 if (theWindow == _mt_window && existing_update_region) {
3159 set_invalid_region(theWindow, &rect);
3161 aWin->drawn = TRUE;
3162 EndUpdate(theWindow);
3165 #if 1 //!TARGET_API_MAC_CARBON
3167 static void
3168 GeneralCursor(EventRecord *theEvent, WindowPtr theWindow, RgnHandle mouseRgn)
3170 #if defined(__SC__) || defined(__MRC__)
3171 #pragma unused(theWindow)
3172 #endif
3173 Rect r = { -1, -1, 2, 2 };
3175 SetCursor(&qdarrow);
3176 OffsetRect(&r, theEvent->where.h, theEvent->where.v);
3177 RectRgn(mouseRgn, &r);
3180 static void
3181 DoOsEvt(EventRecord *theEvent)
3183 WindowRef win;
3184 short code;
3186 if ((theEvent->message & 0xff000000) == 0xfa000000) {
3187 /* Mouse Moved */
3189 code = FindWindow(theEvent->where, &win);
3190 if (code != inContent) {
3191 Rect r = { -1, -1, 2, 2 };
3193 SetCursor(&qdarrow);
3194 OffsetRect(&r, theEvent->where.h, theEvent->where.v);
3195 RectRgn(gMouseRgn, &r);
3196 } else {
3197 #if 1 //!TARGET_API_MAC_CARBON
3198 int kind = GetWindowKind(win) - WIN_BASE_KIND;
3199 if (kind >= 0 && kind <= NHW_TEXT) {
3200 winCursorFuncs[kind](theEvent, win, gMouseRgn);
3202 #endif
3207 #endif /* !TARGET_API_MAC_CARBON */
3209 void
3210 HandleEvent(EventRecord *theEvent)
3212 switch (theEvent->what) {
3213 #if 1 //!TARGET_API_MAC_CARBON
3214 case autoKey:
3215 case keyDown:
3216 HandleKey(theEvent);
3217 break;
3218 #endif
3219 case updateEvt:
3220 HandleUpdate(theEvent);
3221 break;
3222 case mouseDown:
3223 HandleClick(theEvent);
3224 break;
3225 #if !TARGET_API_MAC_CARBON
3226 case diskEvt:
3227 if ((theEvent->message & 0xffff0000) != 0) {
3228 Point p = { 150, 150 };
3229 (void) DIBadMount(p, theEvent->message);
3231 break;
3232 #endif
3233 #if !TARGET_API_MAC_CARBON
3234 case osEvt:
3235 DoOsEvt(theEvent);
3236 break;
3237 #endif
3238 case kHighLevelEvent:
3239 AEProcessAppleEvent(theEvent);
3240 default:
3241 break;
3245 /**********************************************************************
3246 * Interface definition, for windows.c
3249 struct window_procs mac_procs = {
3250 "mac",
3251 WC_COLOR | WC_HILITE_PET | WC_FONT_MAP | WC_FONT_MENU | WC_FONT_MESSAGE
3252 | WC_FONT_STATUS | WC_FONT_TEXT | WC_FONTSIZ_MAP | WC_FONTSIZ_MENU
3253 | WC_FONTSIZ_MESSAGE | WC_FONTSIZ_STATUS | WC_FONTSIZ_TEXT,
3254 0L, mac_init_nhwindows,
3255 mac_unimplemented, /* see macmenu.c:mac_askname() for player selection */
3256 mac_askname, mac_get_nh_event, mac_exit_nhwindows, mac_suspend_nhwindows,
3257 mac_unimplemented, mac_create_nhwindow, mac_clear_nhwindow,
3258 mac_display_nhwindow, mac_destroy_nhwindow, mac_curs, mac_putstr,
3259 genl_putmixed, mac_display_file, mac_start_menu, mac_add_menu,
3260 mac_end_menu, mac_select_menu, genl_message_menu, mac_unimplemented,
3261 mac_get_nh_event, mac_get_nh_event,
3262 #ifdef CLIPPING
3263 mac_cliparound,
3264 #endif
3265 #ifdef POSITIONBAR
3266 donull,
3267 #endif
3268 tty_print_glyph, tty_raw_print, tty_raw_print_bold, mac_nhgetch,
3269 mac_nh_poskey, tty_nhbell, mac_doprev_message, mac_yn_function,
3270 mac_getlin, mac_get_ext_cmd, mac_number_pad, mac_delay_output,
3271 #ifdef CHANGE_COLOR
3272 tty_change_color, tty_change_background, set_tty_font_name,
3273 tty_get_color_string,
3274 #endif
3275 /* other defs that really should go away (they're tty specific) */
3276 0, // mac_start_screen,
3277 0, // mac_end_screen,
3278 genl_outrip, genl_preference_update, genl_can_suspend_no,
3281 /*macwin.c*/