1 /*	SCCS Id: @(#)macwin.c	3.4	1996/01/15	*/
2 /* Copyright (c) Jon W{tte, Hao-Yang Wang, Jonathan Handler 1992. */
3 /* NetHack may be freely redistributed.  See license for details. */
4 
5 #include "hack.h"
6 #include "func_tab.h"
7 #include "macwin.h"
8 #include "mactty.h"
9 #include "wintty.h"
10 
11 #if !TARGET_API_MAC_CARBON
12 #include <LowMem.h>
13 #include <AppleEvents.h>
14 #include <Gestalt.h>
15 #include <TextUtils.h>
16 #include <DiskInit.h>
17 #include <ControlDefinitions.h>
18 #endif
19 
20 NhWindow *theWindows = (NhWindow *) 0;
21 Cursor qdarrow;
22 
23 /* Borrowed from the Mac tty port */
24 extern WindowPtr _mt_window;
25 
26 /* Some useful #defines for the scroll bar width and height */
27 #define		SBARWIDTH	15
28 #define		SBARHEIGHT	15
29 
30 /*
31  * We put a TE on the message window for the "top line" queries.
32  * top_line is the TE that holds both the query and the user's
33  * response.  The first topl_query_len characters in top_line are
34  * the query, the rests are the response.  topl_resp is the valid
35  * response to a yn query, while topl_resp[topl_def_idx] is the
36  * default response to a yn query.
37  */
38 static TEHandle top_line = (TEHandle) nil;
39 static int	topl_query_len;
40 static int	topl_def_idx = -1;
41 static char	topl_resp[10] = "";
42 
43 #define CHAR_ANY '\n'
44 
45 /*
46  * inSelect means we have a menu window up for selection or
47  * something similar. It makes the window with win number ==
48  * inSelect a movable modal (unfortunately without the border)
49  * and clicking the close box forces an RET into the key
50  * buffer. Don't forget to set inSelect to WIN_ERR when you're
51  * done...
52  */
53 static winid inSelect = WIN_ERR;
54 
55 /*
56  * The key queue ring buffer where Read is where to take from,
57  * Write is where next char goes and count is queue depth.
58  */
59 static unsigned char keyQueue [QUEUE_LEN];
60 static int keyQueueRead = 0,
61 	keyQueueWrite = 0,
62 	keyQueueCount = 0;
63 
64 static Boolean gClickedToMove = 0;	/* For ObscureCursor */
65 
66 static Point clicked_pos;	/* For nh_poskey */
67 static int clicked_mod;
68 static Boolean cursor_locked = false;
69 
70 static ControlActionUPP MoveScrollUPP;		/* scrolling callback, init'ed in InitMac */
71 
72 void
lock_mouse_cursor(Boolean new_cursor_locked)73 lock_mouse_cursor(Boolean new_cursor_locked) {
74 	cursor_locked = new_cursor_locked;
75 }
76 
77 
78 /*
79  * Add key to input queue, force means flush left and replace if full
80  */
81 void
AddToKeyQueue(unsigned char ch,Boolean force)82 AddToKeyQueue (unsigned char ch, Boolean force) {
83 	if (keyQueueCount < QUEUE_LEN) {
84 		keyQueue [keyQueueWrite++] = ch;
85 		keyQueueCount++;
86 	}
87 	else if (force) {
88 		keyQueue [keyQueueWrite++] = ch;
89 		keyQueueRead++;
90 		if (keyQueueRead >= QUEUE_LEN)
91 			keyQueueRead = 0;
92 		keyQueueCount = QUEUE_LEN;
93 	}
94 	if (keyQueueWrite >= QUEUE_LEN)
95 		keyQueueWrite = 0;
96 }
97 
98 
99 /*
100  * Get key from queue
101  */
102 unsigned char
GetFromKeyQueue(void)103 GetFromKeyQueue (void) {
104 	unsigned char ret;
105 
106 	if (keyQueueCount) {
107 		ret = keyQueue [keyQueueRead++];
108 		keyQueueCount--;
109 		if (keyQueueRead >= QUEUE_LEN)
110 			keyQueueRead = 0;
111 	}
112 	else
113 		ret = 0;
114 	return ret;
115 }
116 
117 
118 /*
119  * Cursor movement
120  */
121 static RgnHandle gMouseRgn = (RgnHandle) 0;
122 
123 /*
124  * _Gestalt madness - we rely heavily on the _Gestalt glue, since we
125  * don't check for the trap...
126  */
127 MacFlags macFlags;
128 
129 /*
130  * The screen layouts on the small 512x342 screen need special cares.
131  */
132 Boolean small_screen = 0;
133 
134 #ifdef NHW_BASE
135 # undef NHW_BASE
136 #endif
137 #define NHW_BASE 0
138 
139 static int FDECL(filter_scroll_key,(const int, NhWindow *));
140 
141 static void FDECL(GeneralKey, (EventRecord *, WindowPtr));
142 static void FDECL(macKeyMenu, (EventRecord *, WindowPtr));
143 static void FDECL(macKeyText, (EventRecord *, WindowPtr));
144 
145 static void FDECL(macClickMessage, (EventRecord *, WindowPtr));
146 static void FDECL(macClickTerm, (EventRecord *, WindowPtr));
147 static void FDECL(macClickMenu, (EventRecord *, WindowPtr));
148 static void FDECL(macClickText, (EventRecord *, WindowPtr));
149 
150 static short FDECL(macDoNull, (EventRecord *, WindowPtr));
151 static short FDECL(macUpdateMessage, (EventRecord *, WindowPtr));
152 static short FDECL(macUpdateMenu, (EventRecord *, WindowPtr));
153 static short FDECL(GeneralUpdate, (EventRecord *, WindowPtr));
154 
155 static void FDECL(macCursorTerm, (EventRecord *, WindowPtr, RgnHandle));
156 static void FDECL(GeneralCursor, (EventRecord *, WindowPtr, RgnHandle));
157 
158 static void FDECL(DoScrollBar,(Point, short, ControlHandle, NhWindow *));
159 static pascal void FDECL(MoveScrollBar, (ControlHandle, short));
160 
161 typedef void (*CbFunc) (EventRecord *, WindowPtr);
162 typedef short (*CbUpFunc) (EventRecord *, WindowPtr);
163 typedef void (*CbCursFunc) (EventRecord *, WindowPtr, RgnHandle);
164 
165 #define NUM_FUNCS 6
166 static const CbFunc winKeyFuncs [NUM_FUNCS] = {
167 	GeneralKey, GeneralKey, GeneralKey, GeneralKey, macKeyMenu, macKeyText
168 };
169 
170 static const CbFunc winClickFuncs [NUM_FUNCS] = {
171 	(CbFunc)macDoNull, macClickMessage, macClickTerm, macClickTerm, macClickMenu,
172 	macClickText
173 };
174 
175 static const CbUpFunc winUpdateFuncs [NUM_FUNCS] = {
176 	macDoNull, macUpdateMessage, image_tty, image_tty,
177 	macUpdateMenu, GeneralUpdate
178 };
179 
180 static const CbCursFunc winCursorFuncs [NUM_FUNCS] = {
181 	(CbCursFunc) macDoNull, GeneralCursor, macCursorTerm, macCursorTerm,
182 	GeneralCursor, GeneralCursor
183 };
184 
185 
186 static NhWindow *
GetNhWin(WindowPtr mac_win)187 GetNhWin(WindowPtr mac_win) {
188 	if (mac_win == _mt_window)	/* term window is still maintained by both systems, and */
189 		return theWindows;		/* WRefCon still refers to tty struct, so we have to map it */
190 	else {
191 		NhWindow *aWin = (NhWindow *)GetWRefCon (mac_win);
192 		if (aWin >= theWindows && aWin < &theWindows[NUM_MACWINDOWS])
193 			return aWin;
194 	}
195 	return ((NhWindow *) nil);
196 }
197 
198 
CheckNhWin(WindowPtr mac_win)199 Boolean CheckNhWin (WindowPtr mac_win) {
200 	return GetNhWin (mac_win) != nil;
201 }
202 
203 
204 static pascal OSErr
AppleEventHandler(const AppleEvent * inAppleEvent,AppleEvent * outAEReply,long inRefCon)205 AppleEventHandler (const AppleEvent* inAppleEvent, AppleEvent* outAEReply, long inRefCon) {
206 #if defined(__SC__) || defined(__MRC__)
207 # pragma unused(outAEReply,inRefCon)
208 #endif
209 	Size     actualSize;
210 	DescType typeCode;
211 	AEEventID EventID;
212 	OSErr    err;
213 
214 	/* Get Event ID */
215 	err = AEGetAttributePtr (inAppleEvent, keyEventIDAttr, typeType, &typeCode,
216 								&EventID, sizeof (EventID), &actualSize);
217 	if (err == noErr) {
218 		switch (EventID) {
219 			default :
220 			case kAEOpenApplication :
221 				macFlags.gotOpen = 1;
222 				/* fall through */
223 			case kAEPrintDocuments :
224 				err = errAEEventNotHandled;
225 				break;
226 			case kAEQuitApplication :
227 				/* Flush key queue */
228 				keyQueueCount = keyQueueWrite = keyQueueRead = 0;
229 				AddToKeyQueue ('S', 1);
230 				break;
231 			case kAEOpenDocuments : {
232 				FSSpec      fss;
233 				FInfo fndrInfo;
234 				AEKeyword   keywd;
235 				AEDescList  docList;
236 				long     index, itemsInList;
237 
238 				if((err = AEGetParamDesc(inAppleEvent, keyDirectObject, typeAEList, &docList)) != noErr ||
239 					(err = AECountItems(&docList, &itemsInList)) != noErr){
240 					if (err == errAEDescNotFound)
241 						itemsInList = 0;
242 					else
243 						break;
244 				}
245 
246 				for(index = 1; index <= itemsInList; index++){
247 					err = AEGetNthPtr(&docList, index, typeFSS, &keywd, &typeCode, (Ptr)&fss,
248 								sizeof(FSSpec), &actualSize);
249 					if(noErr != err)
250 						break;
251 
252 					err = FSpGetFInfo (&fss, &fndrInfo);
253 					if (noErr != err)
254 						break;
255 
256 					if (fndrInfo.fdType != SAVE_TYPE)
257 						continue;	/* only look at save files */
258 
259 					process_openfile (fss.vRefNum, fss.parID, fss.name, fndrInfo.fdType);
260 					if (macFlags.gotOpen)
261 						break;	/* got our save file */
262 				}
263 				err = AEDisposeDesc(&docList);
264 				break;
265 			}
266 		}
267 	}
268 
269 	/* Check to see if all required parameters for this type of event are present */
270 	if (err == noErr) {
271 		err = AEGetAttributePtr (inAppleEvent, keyMissedKeywordAttr,
272 						  		typeWildCard, &typeCode, NULL, 0, &actualSize);
273 		if (err == errAEDescNotFound)
274 			err = noErr;		/* got all the required parameters */
275 		else if (err == noErr)	/* missed a required parameter */
276 			err = errAEEventNotHandled;
277 	}
278 
279 	return err;
280 }
281 
282 
283 short win_fonts [NHW_TEXT + 1];
284 
285 void
InitMac(void)286 InitMac(void) {
287 	short i;
288 	long l;
289 	Str255 volName;
290 
291 
292 #if !TARGET_API_MAC_CARBON
293 	if (LMGetDefltStack() < 50 * 1024L) {
294 		SetApplLimit ((void *) ((long) LMGetCurStackBase() - (50 * 1024L)));
295 	}
296 	MaxApplZone ();
297 	for (i = 0; i < 5; i ++)
298 		MoreMasters ();
299 
300 	InitGraf (&qd.thePort);
301 	InitFonts ();
302 	InitWindows ();
303 	InitMenus ();
304 	InitDialogs (0L);
305 	TEInit ();
306 #endif
307 
308 	memset (&macFlags, 0, sizeof(macFlags));
309 	if (!Gestalt (gestaltOSAttr, & l)) {
310 		macFlags.processes = (l & (1 << gestaltLaunchControl)) ? 1 : 0;
311 		macFlags.tempMem = (l & (1 << gestaltRealTempMemory)) ? 1 : 0;
312 		macFlags.hasDebugger = (l & (1 << gestaltSysDebuggerSupport)) ? 1 : 0;
313 	}
314 	if (!Gestalt (gestaltQuickdrawVersion, & l))
315 		macFlags.color = (l >= gestalt8BitQD) ? 1 : 0;
316 
317 	if (!Gestalt (gestaltFindFolderAttr, & l))
318 		macFlags.folders = (l & (1 << gestaltFindFolderPresent)) ? 1 : 0;
319 
320 	if (!Gestalt (gestaltHelpMgrAttr, & l))
321 		macFlags.help = (l & (1 << gestaltHelpMgrPresent)) ? 1 : 0;
322 
323 	if (!Gestalt (gestaltFSAttr, & l))
324 		macFlags.fsSpec = (l & (1 << gestaltHasFSSpecCalls)) ? 1 : 0;
325 
326 	if (!Gestalt (gestaltFontMgrAttr, & l))
327 		macFlags.trueType = (l & (1 << gestaltOutlineFonts)) ? 1 : 0;
328 
329 	if (!Gestalt (gestaltAUXVersion, & l))
330 		macFlags.aux = (l >= 0x200) ? 1 : 0;
331 
332 	if (!Gestalt (gestaltAliasMgrAttr, & l))
333 		macFlags.alias = (l & (1 << gestaltAliasMgrPresent)) ? 1 : 0;
334 
335 	if (!Gestalt (gestaltStandardFileAttr, & l))
336 		macFlags.standardFile = (l & (1 << gestaltStandardFile58)) ? 1 : 0;
337 
338 	gMouseRgn = NewRgn ();
339 	InitCursor();
340 	GetQDGlobalsArrow(&qdarrow);
341 	ObscureCursor ();
342 
343 	MoveScrollUPP = NewControlActionUPP(MoveScrollBar);
344 
345 	/* Set up base fonts for all window types */
346 	GetFNum ("\pHackFont", &i);
347 	if (i == 0)
348 		i = kFontIDMonaco;
349 	win_fonts [NHW_BASE] = win_fonts [NHW_MAP] = win_fonts [NHW_STATUS] = i;
350 	GetFNum ("\pPSHackFont", &i);
351 	if (i == 0)
352 		i = kFontIDGeneva;
353 	win_fonts [NHW_MESSAGE] = i;
354 	win_fonts [NHW_TEXT] = kFontIDGeneva;
355 
356 	macFlags.hasAE = 0;
357 	if(!Gestalt(gestaltAppleEventsAttr, &l) && (l & (1L << gestaltAppleEventsPresent))){
358 		if (AEInstallEventHandler (kCoreEventClass, typeWildCard,
359 							NewAEEventHandlerUPP(AppleEventHandler),
360 							0,
361 							FALSE) == noErr)
362 			macFlags.hasAE = 1;
363 	}
364 
365 #if TARGET_API_MAC_CARBON
366 	HGetVol(volName, &theDirs.dataRefNum, &theDirs.dataDirID);
367 #else
368 	/*
369 	 * We should try to get this data from a rsrc, in the profile file
370 	 * the user double-clicked...  This data should be saved with the
371 	 * save file in the resource fork, AND be saveable in "stationary"
372 	 */
373 	GetVol (volName, &theDirs.dataRefNum );
374 	GetWDInfo (theDirs.dataRefNum, &theDirs.dataRefNum, &theDirs.dataDirID, &l);
375 #endif
376 	if (volName [0] > 31) volName [0] = 31;
377 	for (l = 1; l <= volName [0]; l++) {
378 		if (volName [l] == ':') {
379 			volName [l] = 0;
380 			volName [0] = l - 1;
381 			break;
382 		}
383 	}
384 	BlockMove (volName, theDirs.dataName, l);
385 	BlockMove (volName, theDirs.saveName, l);
386 	BlockMove (volName, theDirs.levelName, l);
387 	theDirs.saveRefNum = theDirs.levelRefNum = theDirs.dataRefNum;
388 	theDirs.saveDirID = theDirs.levelDirID = theDirs.dataDirID;
389 
390 	/* Create the "record" file, if necessary */
391 	check_recordfile("");
392 	return;
393 }
394 
395 
396 /*
397  * Change default window fonts.
398  */
399 short
set_tty_font_name(int window_type,char * font_name)400 set_tty_font_name (int window_type, char *font_name) {
401 	short fnum;
402 	Str255 new_font;
403 
404 	if (window_type < NHW_BASE || window_type > NHW_TEXT)
405 		return general_failure;
406 
407 	C2P (font_name, new_font);
408 	GetFNum (new_font, &(fnum));
409 	if (!fnum)
410 		return general_failure;
411 	win_fonts [window_type] = fnum;
412 	return noErr;
413 }
414 
415 
416 static void
DrawScrollbar(NhWindow * aWin)417 DrawScrollbar (NhWindow *aWin)
418 {
419 	WindowPtr theWindow = aWin->its_window;
420 	Rect crect, wrect;
421 	Boolean vis;
422 	short val, lin, win_height;
423 
424 
425 	if (!aWin->scrollBar)
426 		return;
427 	GetControlBounds(aWin->scrollBar, &crect);
428 	GetWindowBounds(aWin->its_window, kWindowContentRgn, &wrect);
429 	OffsetRect(&wrect, -wrect.left, -wrect.top);
430 	win_height = wrect.bottom - wrect.top;
431 
432 	if (crect.top != wrect.top - 1 ||
433 		 crect.left != wrect.right - SBARWIDTH) {
434 		MoveControl (aWin->scrollBar, wrect.right - SBARWIDTH, wrect.top - 1);
435 	}
436 	if (crect.bottom != wrect.bottom - SBARHEIGHT ||
437 		 crect.right != wrect.right + 1) {
438 		SizeControl (aWin->scrollBar, SBARWIDTH+1, win_height - SBARHEIGHT + 2);
439 	}
440 	vis = (win_height > (50 + SBARHEIGHT));
441 	if (vis != IsControlVisible(aWin->scrollBar)) {
442 		/* current status != control */
443 		if (vis)/* if visible, show */
444 			ShowControl (aWin->scrollBar);
445 		else	/* else hide */
446 			HideControl (aWin->scrollBar);
447 	}
448 	lin = aWin->y_size;
449 	if (aWin == theWindows + WIN_MESSAGE) {
450 		/* calculate how big scroll bar is for message window */
451 		lin -= (win_height - SBARHEIGHT) / aWin->row_height;
452 		if (lin < 0)
453 			lin = 0;
454 		val = 0;			/* always have message scrollbar active */
455 	}
456 	else {
457 		/* calculate how big scroll bar is for other windows */
458 		lin -= win_height / aWin->row_height;
459 		if (lin < 0)
460 			lin = 0;
461 		if (lin) 	val = 0;	/* if there are 1+ screen lines, activate scrollbar */
462 		else		val = 255;	/* else grey it out */
463 	}
464 	SetControlMaximum (aWin->scrollBar, lin);
465 	HiliteControl (aWin->scrollBar, val);
466 	val = GetControlValue (aWin->scrollBar);
467 	if (val != aWin->scrollPos) {
468 		InvalWindowRect(theWindow, &wrect);
469 		aWin->scrollPos = val;
470 	}
471 }
472 
473 
474 #define MAX_HEIGHT 100
475 #define MIN_HEIGHT 50
476 #define MIN_WIDTH 300
477 
478 /*
479  * This function could be overloaded with any amount of intelligence...
480  */
481 int
SanePositions(void)482 SanePositions (void)
483 {
484 #if TARGET_API_MAC_CARBON
485 	ConstrainWindowToScreen(_mt_window, kWindowStructureRgn,
486 		kWindowConstrainMoveRegardlessOfFit, NULL, NULL);
487 #else
488 	short left, top, width, height;
489 	int ix, numText = 0, numMenu = 0;
490 	int mbar_height = GetMBarHeight();
491 	BitMap qbitmap;
492 	Rect screenArea;
493 	WindowPtr theWindow;
494 	NhWindow *nhWin;
495 
496 
497 	screenArea = GetQDGlobalsScreenBits(&qbitmap)->bounds;
498 	OffsetRect (&screenArea, - screenArea.left, - screenArea.top);
499 
500 /* Map Window */
501 	height = _mt_window->portRect.bottom - _mt_window->portRect.top;
502 	width = _mt_window->portRect.right - _mt_window->portRect.left;
503 
504 	if (!RetrievePosition (kMapWindow, &top, &left)) {
505 		top = mbar_height + (small_screen ? 2 : 20);
506 		left = (screenArea.right - width) / 2;
507 	}
508 	MoveWindow (_mt_window, left, top, 1);
509 
510 /* Message Window */
511 	if (!RetrievePosition (kMessageWindow, &top, &left)) {
512 		top += height;
513 		if (!small_screen)
514 			top += 20;
515 	}
516 
517 	if (!RetrieveSize (kMessageWindow, top, left, &height, &width)) {
518 		height = screenArea.bottom - top - (small_screen ? 2-SBARHEIGHT : 2);
519 		if (height > MAX_HEIGHT) {
520 			height = MAX_HEIGHT;
521 		} else if (height < MIN_HEIGHT) {
522 			height = MIN_HEIGHT;
523 			width = MIN_WIDTH;
524 			left = screenArea.right - width;
525 			top = screenArea.bottom - MIN_HEIGHT;
526 		}
527 	}
528 
529 /* Move these windows */
530 	nhWin = theWindows + WIN_MESSAGE;
531 	theWindow = nhWin->its_window;
532 
533 	MoveWindow (theWindow, left, top, 1);
534 	SizeWindow (theWindow, width, height, 1);
535 	if (nhWin->scrollBar)
536 		DrawScrollbar (nhWin);
537 
538 	/* Handle other windows */
539 	for (ix = 0; ix < NUM_MACWINDOWS; ix ++) {
540 		if (ix != WIN_STATUS && ix != WIN_MESSAGE && ix != WIN_MAP && ix != BASE_WINDOW) {
541 			theWindow = theWindows [ix].its_window;
542 			if (theWindow && ((WindowPeek) theWindow)->visible) {
543 				int shift;
544 				if (((WindowPeek)theWindow)->windowKind == WIN_BASE_KIND + NHW_MENU) {
545 					if (!RetrievePosition (kMenuWindow, &top, &left)) {
546 						top = mbar_height * 2;
547 						left = 2;
548 					}
549 					top += (numMenu * mbar_height);
550 					numMenu++;
551 					shift = 20;
552 				} else {
553 					if (!RetrievePosition (kTextWindow, &top, &left)) {
554 						top = mbar_height * 2;
555 						left = screenArea.right - 3 -
556 							(theWindow->portRect.right - theWindow->portRect.left);
557 					}
558 					top += (numText * mbar_height);
559 					numText++;
560 					shift = -20;
561 				}
562 				while (top > screenArea.bottom - MIN_HEIGHT) {
563 					top -= screenArea.bottom - mbar_height * 2;
564 					left += shift;
565 				}
566 				MoveWindow (theWindow, left, top, 1);
567 			}
568 		}
569 	}
570 #endif
571 	return (0);
572 }
573 
574 
575 winid
mac_create_nhwindow(int kind)576 mac_create_nhwindow (int kind) {
577 	int i;
578 	NhWindow *aWin;
579 	FontInfo fi;
580 
581 	if (kind < NHW_BASE || kind > NHW_TEXT) {
582 		error ("cre_win: Invalid kind %d.", kind);
583 		return WIN_ERR;
584 	}
585 
586 	for (i = 0; i < NUM_MACWINDOWS; i ++) {
587 		if (!theWindows [i].its_window)
588 			break;
589 	}
590 	if (i >= NUM_MACWINDOWS) {
591 		error ("cre_win: Win full; freeing extras");
592 		for (i = 0; i < NUM_MACWINDOWS; i ++) {
593 			if (IsWindowVisible(theWindows [i].its_window) || i == WIN_INVEN ||
594 				GetWindowKind(theWindows [i].its_window) != WIN_BASE_KIND + NHW_MENU &&
595 				GetWindowKind(theWindows [i].its_window) != WIN_BASE_KIND + NHW_TEXT)
596 				continue;
597 			mac_destroy_nhwindow(i);
598 			goto got1;
599 		}
600 		error ("cre_win: Out of ids!");
601 		return WIN_ERR;
602 	}
603 
604 got1 :
605 	aWin = &theWindows [i];
606 	aWin->windowTextLen = 0L;
607 	aWin->scrollBar = (ControlHandle) 0;
608 	aWin->menuInfo = 0;
609 	aWin->menuSelected = 0;
610 	aWin->miLen = 0;
611 	aWin->miSize = 0;
612 	aWin->menuChar = 'a';
613 
614 	dprintf ("cre_win: New kind %d", kind);
615 
616 	if (kind == NHW_BASE || kind == NHW_MAP || kind == NHW_STATUS) {
617 		short x_sz, x_sz_p, y_sz, y_sz_p;
618 		if (kind != NHW_BASE) {
619 			if (i != tty_create_nhwindow(kind)) {
620 				dprintf ("cre_win: error creating kind %d", kind);
621 			}
622 			if (kind == NHW_MAP) {
623 				wins[i]->offy = 0;	/* the message box is in a separate window */
624 			}
625 		}
626 		aWin->its_window = _mt_window;
627 		get_tty_metrics(aWin->its_window, &x_sz, &y_sz, &x_sz_p, &y_sz_p,
628 					 &aWin->font_number, &aWin->font_size,
629 					 &aWin->char_width, &aWin->row_height);
630 		return i;
631 	}
632 
633 	aWin->its_window = GetNewWindow (WIN_BASE_RES + kind, (WindowPtr) 0L, (WindowPtr) -1L);
634 	SetWindowKind(aWin->its_window, WIN_BASE_KIND + kind);
635 	SetWRefCon(aWin->its_window, (long) aWin);
636 	if (!(aWin->windowText = NewHandle (TEXT_BLOCK))) {
637 		error ("cre_win: NewHandle fail(%ld)", (long) TEXT_BLOCK);
638 		DisposeWindow (aWin->its_window);
639 		aWin->its_window = (WindowPtr) 0;
640 		return WIN_ERR;
641 	}
642 	aWin->x_size = aWin->y_size = 0;
643 	aWin->x_curs = aWin->y_curs = 0;
644 	aWin->drawn = TRUE;
645 	mac_clear_nhwindow (i);
646 
647 	SetPortWindowPort(aWin->its_window);
648 
649 	if (kind == NHW_MESSAGE) {
650 		aWin->font_number = win_fonts [NHW_MESSAGE];
651 		aWin->font_size = iflags.wc_fontsiz_message? iflags.wc_fontsiz_message :
652 			iflags.large_font ? 12 : 9;
653 		if (!top_line) {
654 			const Rect out_of_scr = {10000, 10000, 10100, 10100};
655 			TextFont(aWin->font_number);
656 			TextSize(aWin->font_size);
657 			TextFace(bold);
658 			top_line = TENew(&out_of_scr, &out_of_scr);
659 			TEActivate(top_line);
660 			TextFace(normal);
661 		}
662 	} else {
663 		aWin->font_number = win_fonts [NHW_TEXT];
664 		aWin->font_size = iflags.wc_fontsiz_text ? iflags.wc_fontsiz_text : 9;
665 	}
666 
667 	TextFont (aWin->font_number);
668 	TextSize (aWin->font_size);
669 
670 	GetFontInfo (&fi);
671 	aWin->ascent_height = fi.ascent + fi.leading;
672 	aWin->row_height = aWin->ascent_height + fi.descent;
673 	aWin->char_width = fi.widMax;
674 
675 	if (kind == NHW_MENU || kind == NHW_TEXT || kind == NHW_MESSAGE) {
676 		Rect r;
677 
678 		GetWindowBounds(aWin->its_window, kWindowContentRgn, &r);
679 		r.right -= (r.left - 1);
680 		r.left = r.right - SBARWIDTH;
681 		r.bottom -= (r.top + SBARHEIGHT);
682 		r.top = -1;
683 		aWin->scrollBar = NewControl (aWin->its_window, &r, "\p", (r.bottom > r.top + 50), 0, 0, 0, 16, 0L);
684 		aWin->scrollPos = 0;
685 	}
686 	return i;
687 }
688 
689 
690 void
mac_init_nhwindows(int * argcp,char ** argv)691 mac_init_nhwindows (int *argcp, char **argv)
692 {
693 #if !TARGET_API_MAC_CARBON
694 	Rect scr = (*GetGrayRgn())->rgnBBox;
695 	small_screen = scr.bottom - scr.top <= (iflags.large_font ? 12*40 : 9*40);
696 #endif
697 	Rect r;
698 
699 
700 	InitMenuRes ();
701 
702 	theWindows = (NhWindow *) NewPtrClear (NUM_MACWINDOWS * sizeof (NhWindow));
703 	if (MemError())
704 		error("mac_init_nhwindows: Couldn't allocate memory for windows.");
705 
706 	DimMenuBar ();
707 
708 	tty_init_nhwindows(argcp, argv);
709 	iflags.window_inited = TRUE;
710 
711 	/* Some ugly hacks to make both interfaces happy:
712 	 * Mac port uses both tty interface (for main map) and extra windows.  The winids need to
713 	 * be kept in synch for both interfaces to map.  Also, the "blocked" display_nhwindow case
714 	 * for the map automatically calls the tty interface for the message box, so some version
715 	 * of the message box has to exist in the tty world to prevent a meltdown, even though most
716 	 * messages are handled in mac window.
717 	 */
718 	mac_create_nhwindow(NHW_BASE);
719 	tty_create_nhwindow(NHW_MESSAGE);
720 	RetrievePosition(kMessageWindow, &r.top, &r.left);
721 	RetrieveSize(kMessageWindow, r.top, r.left, &r.bottom, &r.right);
722 	MoveWindow(theWindows[NHW_MESSAGE].its_window, r.left, r.top, false);
723 	SizeWindow(theWindows[NHW_MESSAGE].its_window, r.right, r.bottom, true);
724 	ConstrainWindowToScreen(theWindows[NHW_MESSAGE].its_window, kWindowStructureRgn,
725 		kWindowConstrainMoveRegardlessOfFit, NULL, NULL);
726 	return;
727 }
728 
729 
730 void
mac_clear_nhwindow(winid win)731 mac_clear_nhwindow (winid win) {
732 	long l;
733 	Rect r;
734 	NhWindow *aWin = &theWindows [win];
735 	WindowPtr theWindow = aWin->its_window;
736 
737 	if (win < 0 || win >= NUM_MACWINDOWS || !theWindow) {
738 		error ("clr_win: Invalid win %d.", win);
739 		return;
740 	}
741 	if (theWindow == _mt_window) {
742 		tty_clear_nhwindow(win);
743 		return;
744 	}
745 	if (!aWin->drawn)
746 		return;
747 
748 	SetPortWindowPort(theWindow);
749 	GetWindowBounds(theWindow, kWindowContentRgn, &r);
750 	OffsetRect(&r, -r.left, -r.top);
751 	if (aWin->scrollBar)
752 		r.right -= SBARWIDTH;
753 
754 	switch (GetWindowKind(theWindow) - WIN_BASE_KIND) {
755 	case NHW_MESSAGE :
756 		if (aWin->scrollPos == aWin->y_size - 1)	/* if no change since last clear */
757 			return;									/* don't bother with redraw */
758 		r.bottom -= SBARHEIGHT;
759 		for (l = 0; aWin->y_size > iflags.msg_history;) {
760 			const char cr = CHAR_CR;
761 			l = Munger(aWin->windowText, l, &cr, 1, nil, 0) + 1;
762 			--aWin->y_size;
763 		}
764 		if (l) {
765 			aWin->windowTextLen -= l;
766 			BlockMove(*aWin->windowText + l, *aWin->windowText, aWin->windowTextLen);
767 		}
768 		aWin->last_more_lin = aWin->y_size;
769 		aWin->save_lin	= aWin->y_size;
770 		aWin->scrollPos = aWin->y_size ? aWin->y_size - 1 : 0;
771 		break;
772 	case NHW_MENU:
773 		if (aWin->menuInfo) {
774 			DisposeHandle((Handle)aWin->menuInfo);
775 			aWin->menuInfo = NULL;
776 		}
777 		if (aWin->menuSelected) {
778 			DisposeHandle((Handle)aWin->menuSelected);
779 			aWin->menuSelected = NULL;
780 		}
781 		aWin->menuChar = 'a';
782 		aWin->miSelLen = 0;
783 		aWin->miLen = 0;
784 		aWin->miSize = 0;
785 		/* Fall-Through */
786 	default :
787 		SetHandleSize (aWin->windowText, TEXT_BLOCK);
788 		aWin->windowTextLen = 0L;
789 		aWin->x_size = 0;
790 		aWin->y_size = 0;
791 		aWin->scrollPos = 0;
792 		break;
793 	}
794 	if (aWin->scrollBar) {
795 		SetControlMaximum (aWin->scrollBar, aWin->y_size);
796 		SetControlValue(aWin->scrollBar, aWin->scrollPos);
797 	}
798 	aWin->y_curs = 0;
799 	aWin->x_curs = 0;
800 	aWin->drawn = FALSE;
801 	InvalWindowRect(theWindow, &r);
802 }
803 
804 
805 static Boolean
ClosingWindowChar(const int c)806 ClosingWindowChar(const int c) {
807 	return c == CHAR_ESC || c == CHAR_BLANK || c == CHAR_LF || c == CHAR_CR ||
808 			c == 'q';
809 }
810 
811 
812 static Boolean
in_topl_mode(void)813 in_topl_mode(void)
814 {
815 	Rect rect;
816 
817 
818 	GetWindowBounds(theWindows[WIN_MESSAGE].its_window, kWindowContentRgn, &rect);
819 	OffsetRect(&rect, -rect.left, -rect.top);
820 	return (WIN_MESSAGE != WIN_ERR && top_line &&
821 		(*top_line)->viewRect.left < rect.right);
822 }
823 
824 
825 #define BTN_IND 2
826 #define BTN_W	40
827 #define BTN_H	(SBARHEIGHT-3)
828 
829 static void
topl_resp_rect(int resp_idx,Rect * r)830 topl_resp_rect(int resp_idx, Rect *r)
831 {
832 	Rect rect;
833 
834 
835 	GetWindowBounds(theWindows[WIN_MESSAGE].its_window, kWindowContentRgn, &rect);
836 	OffsetRect(&rect, -rect.left, -rect.top);
837 	r->left	  = (BTN_IND + BTN_W) * resp_idx + BTN_IND;
838 	r->right  = r->left + BTN_W;
839 	r->bottom = rect.bottom - 1;
840 	r->top	  = r->bottom - BTN_H;
841 	return;
842 }
843 
844 
845 void
enter_topl_mode(char * query)846 enter_topl_mode(char *query) {
847 	if (in_topl_mode())
848 		return;
849 
850 	putstr(WIN_MESSAGE, ATR_BOLD, query);
851 
852 	topl_query_len = strlen(query);
853 	(*top_line)->selStart = topl_query_len;
854 	(*top_line)->selEnd = topl_query_len;
855 	(*top_line)->viewRect.left = 0;
856 	PtrToXHand(query, (*top_line)->hText, topl_query_len);
857 	TECalText(top_line);
858 
859 	DimMenuBar();
860 	mac_display_nhwindow(WIN_MESSAGE, FALSE);
861 }
862 
863 
864 void
leave_topl_mode(char * answer)865 leave_topl_mode(char *answer) {
866 	unsigned char *ap, *bp;
867 
868 	int ans_len = (*top_line)->teLength - topl_query_len;
869 	NhWindow *aWin = theWindows + WIN_MESSAGE;
870 
871 	if (!in_topl_mode())
872 		return;
873 
874 	/* Cap length of reply */
875 	if (ans_len >= BUFSZ)
876 		ans_len = BUFSZ-1;
877 
878 	/* remove unprintables from the answer */
879 	for (ap = *(*top_line)->hText + topl_query_len, bp = answer; ans_len > 0; ans_len--, ap++) {
880 		if (*ap >= ' ' && *ap < 128) {
881 			*bp++ = *ap;
882 		}
883 	}
884 	*bp = 0;
885 
886 	if (aWin->windowTextLen && (*aWin->windowText)[aWin->windowTextLen-1] == CHAR_CR) {
887 		-- aWin->windowTextLen;
888 		-- aWin->y_size;
889 	}
890 	putstr(WIN_MESSAGE, ATR_BOLD, answer);
891 
892 	(*top_line)->viewRect.left += 10000;
893 	UndimMenuBar();
894 }
895 
896 /*
897  * TESetSelect flushes out all the pending key strokes.  I hate it.
898  */
899 static void
topl_set_select(short selStart,short selEnd)900 topl_set_select(short selStart, short selEnd) {
901 	TEDeactivate(top_line);
902 	(*top_line)->selStart	= selStart;
903 	(*top_line)->selEnd	= selEnd;
904 	TEActivate(top_line);
905 }
906 
907 
908 static void
topl_replace(char * new_ans)909 topl_replace(char *new_ans) {
910 	topl_set_select(topl_query_len, (*top_line)->teLength);
911 	TEDelete(top_line);
912 	TEInsert(new_ans, strlen(new_ans), top_line);
913 }
914 
915 
916 Boolean
topl_key(unsigned char ch,Boolean ext)917 topl_key(unsigned char ch, Boolean ext) {
918 	switch (ch) {
919 		case CHAR_ESC:
920 			topl_replace("\x1b");
921 		case CHAR_ENTER: case CHAR_CR: case CHAR_LF:
922 			return false;
923 
924 		case 0x1f & 'P':
925 			mac_doprev_message();
926 			return true;
927 		case '\x1e'/* up arrow */:
928 			topl_replace ("");
929 			return true;
930 		case CHAR_BS: case '\x1c'/* left arrow */:
931 			if ((*top_line)->selEnd <= topl_query_len)
932 				return true;
933 			else if (ext) {
934 				topl_replace ("");
935 				return true;
936 			}
937 		default:
938 			TEKey(ch, top_line);
939 			if (ext) {
940 				int com_index = -1, oindex = 0;
941 				while(extcmdlist[oindex].ef_txt != (char *)0) {
942 					if(!strncmpi(*(*top_line)->hText + topl_query_len,
943 								 extcmdlist[oindex].ef_txt,
944 								 (*top_line)->teLength - topl_query_len)) {
945 						if(com_index == -1) /* No matches yet*/
946 							com_index = oindex;
947 						else /* More than 1 match */ {
948 							com_index = -2;
949 							break;
950 						}
951 					}
952 					oindex++;
953 				}
954 				if(com_index >= 0)
955 					topl_replace((char *) extcmdlist[com_index].ef_txt);
956 			}
957 			return true;
958 	}
959 }
960 
961 
962 static void
topl_flash_resp(int resp_idx)963 topl_flash_resp(int resp_idx) {
964 	unsigned long dont_care;
965 	Rect frame;
966 	SetPortWindowPort(theWindows[WIN_MESSAGE].its_window);
967 	topl_resp_rect(resp_idx, &frame);
968 	InsetRect(&frame, 1, 1);
969 	InvertRect(&frame);
970 	Delay(GetDblTime() / 2, &dont_care);
971 	InvertRect(&frame);
972 }
973 
974 
975 static void
topl_set_def(int new_def_idx)976 topl_set_def(int new_def_idx) {
977 	Rect frame;
978 	SetPortWindowPort(theWindows[WIN_MESSAGE].its_window);
979 	topl_resp_rect(topl_def_idx, &frame);
980 	InvalWindowRect(theWindows[WIN_MESSAGE].its_window, &frame);
981 	topl_def_idx = new_def_idx;
982 	topl_resp_rect(new_def_idx, &frame);
983 	InvalWindowRect(theWindows[WIN_MESSAGE].its_window, &frame);
984 }
985 
986 
987 void
topl_set_resp(char * resp,char def)988 topl_set_resp(char *resp, char def) {
989 	char *loc;
990 	Rect frame;
991 	int r_len, r_len1;
992 
993 	if (!resp) {
994 		const char any_str[2] = {CHAR_ANY, '\0'};
995 		resp = (char *) any_str;
996 		def = CHAR_ANY;
997 	}
998 
999 	SetPortWindowPort(theWindows[WIN_MESSAGE].its_window);
1000 	r_len1 = strlen(resp);
1001 	r_len  = strlen(topl_resp);
1002 	if (r_len < r_len1)
1003 		r_len = r_len1;
1004 	topl_resp_rect(0, &frame);
1005 	frame.right = (BTN_IND + BTN_W) * r_len;
1006 	InvalWindowRect(theWindows[WIN_MESSAGE].its_window, &frame);
1007 
1008 	strcpy(topl_resp, resp);
1009 	loc = strchr (resp, def);
1010 	topl_def_idx = loc ? loc - resp : -1;
1011 }
1012 
1013 
1014 static char
topl_resp_key(char ch)1015 topl_resp_key(char ch) {
1016 	if (strlen(topl_resp) > 0) {
1017 		char *loc = strchr(topl_resp, ch);
1018 
1019 		if (!loc) {
1020 			if (ch == '\x9'/* tab */) {
1021 				topl_set_def(topl_def_idx<=0 ? strlen(topl_resp)-1 : topl_def_idx-1);
1022 				ch = '\0';
1023 			} else if (ch == CHAR_ESC) {
1024 				loc = strchr(topl_resp, 'q');
1025 				if (!loc) {
1026 					loc = strchr(topl_resp, 'n');
1027 					if (!loc && topl_def_idx >= 0)
1028 						loc = topl_resp + topl_def_idx;
1029 				}
1030 			} else if (ch == (0x1f & 'P')) {
1031 				mac_doprev_message();
1032 				ch = '\0';
1033 			} else if (topl_def_idx >= 0) {
1034 				if (ch == CHAR_ENTER || ch == CHAR_CR || ch == CHAR_LF ||
1035 					 ch == CHAR_BLANK || topl_resp[topl_def_idx] == CHAR_ANY)
1036 					loc = topl_resp + topl_def_idx;
1037 
1038 				else if (strchr(topl_resp, '#')) {
1039 					if (digit(ch)) {
1040 						topl_set_def(strchr(topl_resp, '#') - topl_resp);
1041 						TEKey(ch, top_line);
1042 						ch = '\0';
1043 
1044 					} else if (topl_resp[topl_def_idx] == '#') {
1045 						if (ch == '\x1e'/* up arrow */) {
1046 							topl_set_select(topl_query_len, topl_query_len);
1047 							ch = '\0';
1048 						} else if (ch == '\x1d'/* right arrow */ ||
1049 							   ch == '\x1f'/* down arrow */ ||
1050 							   ch == CHAR_BS || ch == '\x1c'/* left arrow */ &&
1051 							   (*top_line)->selEnd > topl_query_len) {
1052 							TEKey(ch, top_line);
1053 							ch = '\0';
1054 						}
1055 					}
1056 				}
1057 			}
1058 		}
1059 
1060 		if (loc) {
1061 			topl_flash_resp(loc - topl_resp);
1062 			if (*loc != CHAR_ANY)
1063 				ch = *loc;
1064 			TEKey(ch, top_line);
1065 		}
1066 	}
1067 
1068 	return ch;
1069 }
1070 
1071 
1072 static void
adjust_window_pos(NhWindow * aWin,short width,short height)1073 adjust_window_pos(NhWindow *aWin, short width, short height)
1074 {
1075 	WindowRef theWindow = aWin->its_window;
1076 #if TARGET_API_MAC_CARBON
1077 	Rect r;
1078 
1079 
1080 	GetWindowBounds(theWindow, kWindowContentRgn, &r);
1081 	RetrieveWinPos(theWindow, &r.top, &r.left);
1082 	MoveWindow(theWindow, r.left, r.top, false);
1083 	SizeWindow(theWindow, width, height, true);
1084 	ConstrainWindowToScreen(theWindow, kWindowStructureRgn,
1085 		kWindowConstrainMoveRegardlessOfFit, NULL, NULL);
1086 #else
1087 	Rect scr_r = (*GetGrayRgn())->rgnBBox;
1088 	const Rect win_ind = {2, 2, 3, 3};
1089 	const short	min_w = theWindow->portRect.right - theWindow->portRect.left,
1090 				max_w = scr_r.right - scr_r.left - win_ind.left - win_ind.right;
1091 	Point pos;
1092 	short max_h;
1093 
1094 	SetPortWindowPort(theWindow);
1095 	if (!RetrieveWinPos(theWindow, &pos.v, &pos.h)) {
1096 		pos.v = 0;	/* take window's existing position */
1097 		pos.h = 0;
1098 		LocalToGlobal(&pos);
1099 	}
1100 
1101 	max_h = scr_r.bottom - win_ind.bottom - pos.v;
1102 	if (height > max_h)		height = max_h;
1103 	if (height < MIN_HEIGHT)	height = MIN_HEIGHT;
1104 	if (width < min_w)		width = min_w;
1105 	if (width > max_w)		width = max_w;
1106 	SizeWindow(theWindow, width, height, true);
1107 
1108 	if (pos.v + height + win_ind.bottom > scr_r.bottom)
1109 		pos.v = scr_r.bottom - height - win_ind.bottom;
1110 	if (pos.h + width + win_ind.right > scr_r.right)
1111 		pos.h = scr_r.right	 - width - win_ind.right;
1112 	MoveWindow(theWindow, pos.h, pos.v, false);
1113 	if (aWin->scrollBar)
1114 		DrawScrollbar (aWin);
1115 #endif
1116 	return;
1117 }
1118 
1119 
1120 /*
1121  * display/select/update the window.
1122  * If f is true, this window should be "modal" - don't return
1123  * until presumed seen.
1124  */
1125 void
mac_display_nhwindow(winid win,BOOLEAN_P f)1126 mac_display_nhwindow (winid win, BOOLEAN_P f) {
1127 	NhWindow *aWin = &theWindows [win];
1128 	WindowPtr theWindow = aWin->its_window;
1129 
1130 	if (win < 0 || win >= NUM_MACWINDOWS || !theWindow) {
1131 		error ("disp_win: Invalid window %d.", win);
1132 		return;
1133 	}
1134 
1135 	if (theWindow == _mt_window) {
1136 		tty_display_nhwindow(win, f);
1137 		return;
1138 	}
1139 
1140 	if (f && inSelect == WIN_ERR && win == WIN_MESSAGE) {
1141 		topl_set_resp ((char *)0, 0);
1142 		if (aWin->windowTextLen > 0 &&
1143 			 (*aWin->windowText) [aWin->windowTextLen - 1] == CHAR_CR) {
1144 			-- aWin->windowTextLen;
1145 			-- aWin->y_size;
1146 		}
1147 		putstr (win, flags.standout ? ATR_INVERSE : ATR_NONE, " --More--");
1148 	}
1149 
1150 	if (!IsWindowVisible(theWindow)) {
1151 		if (win != WIN_MESSAGE)
1152 			adjust_window_pos(aWin, aWin->x_size + SBARWIDTH+1, aWin->y_size *aWin->row_height);
1153 
1154 		SelectWindow (theWindow);
1155 		ShowWindow (theWindow);
1156 	}
1157 
1158 	if (f && inSelect == WIN_ERR) {
1159 		int ch;
1160 
1161 		DimMenuBar();
1162 		inSelect = win;
1163 		do {
1164 			ch = mac_nhgetch ();
1165 		} while (!ClosingWindowChar (ch));
1166 		inSelect = WIN_ERR;
1167 		UndimMenuBar();
1168 
1169 		if (win == WIN_MESSAGE)
1170 			topl_set_resp ("", '\0');
1171 		else
1172 			HideWindow (theWindow);
1173 
1174 	}
1175 }
1176 
1177 
1178 void
mac_destroy_nhwindow(winid win)1179 mac_destroy_nhwindow (winid win) {
1180 	WindowPtr theWindow;
1181 	NhWindow *aWin = &theWindows [win];
1182 	int kind;
1183 
1184 	if (win < 0 || win >= NUM_MACWINDOWS) {
1185 		if (iflags.window_inited) error ("dest_win: Invalid win %d.", win);
1186 		return;
1187 	}
1188 	theWindow = aWin->its_window;
1189 	if (!theWindow) {
1190 		error ("dest_win: Not allocated win %d.", win);
1191 		return;
1192 	}
1193 
1194 	/*
1195 	 * Check special windows.  The base window should never go away.
1196 	 * Other "standard" windows should not go away unless we've exitted nhwindows.
1197 	 */
1198 	if (theWindow == _mt_window) {
1199 		return;
1200 	}
1201 	if (win == WIN_INVEN || win == WIN_MESSAGE) {
1202 		if (iflags.window_inited) {
1203 			if (flags.tombstone && killer) {
1204 				/* Prepare for the coming of the tombstone window. */
1205 				win_fonts [NHW_TEXT] = kFontIDMonaco;
1206 			}
1207 			return;
1208 		}
1209 		if (win == WIN_MESSAGE)
1210 			WIN_MESSAGE = WIN_ERR;
1211 	}
1212 
1213 	kind = GetWindowKind(theWindow) - WIN_BASE_KIND;
1214 
1215 	if ((!IsWindowVisible(theWindow) || (kind != NHW_MENU && kind != NHW_TEXT))) {
1216 		DisposeWindow (theWindow);
1217 		if (aWin->windowText) {
1218 			DisposeHandle(aWin->windowText);
1219 		}
1220 		aWin->its_window = (WindowPtr) 0;
1221 		aWin->windowText = (Handle) 0;
1222 	}
1223 }
1224 
1225 
1226 void
mac_number_pad(int pad)1227 mac_number_pad (int pad) {
1228 	iflags.num_pad = pad;
1229 }
1230 
1231 
1232 void
trans_num_keys(EventRecord * theEvent)1233 trans_num_keys(EventRecord *theEvent) {
1234 #if defined(__SC__) || defined(__MRC__)
1235 # pragma unused(theEvent)
1236 #endif
1237 /* KMH -- Removed this translation.
1238  * Number pad keys should always emit digit characters.
1239  * That's consistent with the default MacOS behavior.
1240  * The number_pad option controls how digits are interpreted.
1241  */
1242 #if 0
1243 	if (iflags.num_pad) {
1244 		Handle h = GetResource('Nump', theEvent->modifiers & shiftKey ? 129 : 128);
1245 		if (h) {
1246 			short inkey = (theEvent->message & keyCodeMask), *ab = (short *)*h;
1247 			int i = ab[0];
1248 			for (; i; i--) {
1249 				if (inkey == (ab[i] & keyCodeMask)) {
1250 					theEvent->message = ab[i];
1251 					break;
1252 				}
1253 			}
1254 		}
1255 	}
1256 #endif
1257 }
1258 
1259 
1260 /*
1261  * Note; theWindow may very well be null here, since keyDown may call
1262  * it when theres no window !!!
1263  */
1264 static void
GeneralKey(EventRecord * theEvent,WindowPtr theWindow)1265 GeneralKey (EventRecord *theEvent, WindowPtr theWindow) {
1266 #if defined(__SC__) || defined(__MRC__)
1267 # pragma unused(theWindow)
1268 #endif
1269 #if 0
1270 	trans_num_keys (theEvent);
1271 #endif
1272 	AddToKeyQueue (topl_resp_key (theEvent->message & 0xff), TRUE);
1273 }
1274 
1275 
1276 /*
1277  * Routine used to select and de-select elements in a menu window, used by KeyMenu,
1278  * ClickMenu, and UpdateMenu.  Takes the NhWindow and a line ref relative to the scrollbar.
1279  */
ToggleMenuSelect(NhWindow * aWin,int line)1280 static void ToggleMenuSelect (NhWindow *aWin, int line) {
1281 	Rect r;
1282 
1283 
1284 	GetWindowBounds(aWin->its_window, kWindowContentRgn, &r);
1285 	OffsetRect(&r, -r.left, -r.top);
1286 	if (aWin->scrollBar)
1287 		r.right -= SBARWIDTH;
1288 	r.top = line * aWin->row_height;
1289 	r.bottom = r.top + aWin->row_height;
1290 
1291 	LMSetHiliteMode((UInt8) (LMGetHiliteMode() & 0x7F));
1292 	InvertRect(&r);
1293 }
1294 
1295 /*
1296  * Check to see if given item is selected, return index if it is
1297  */
1298 static int
ListItemSelected(NhWindow * aWin,int item)1299 ListItemSelected (NhWindow *aWin, int item) {
1300 	int		i;
1301 
1302 	HLock ((char**)aWin->menuSelected);
1303 	/* Find item in selection list */
1304 	for (i = aWin->miSelLen - 1; i >= 0; i--) {
1305 		if ((*aWin->menuSelected) [i] == item)
1306 			break;
1307 	}
1308 	HUnlock ((char**)aWin->menuSelected);
1309 	return i;
1310 }
1311 
1312 /*
1313  * Add item to selection list if it's not selected already
1314  * If it is selected already, remove it from the list.
1315  */
1316 static void
ToggleMenuListItemSelected(NhWindow * aWin,short item)1317 ToggleMenuListItemSelected (NhWindow *aWin, short item) {
1318 	int i = ListItemSelected (aWin, item);
1319 
1320 	HLock ((char**)aWin->menuSelected);
1321 	if (i < 0) {	/* not there, so add */
1322 		(*aWin->menuSelected) [aWin->miSelLen] = item;
1323 		aWin->miSelLen++;
1324 	}
1325 	else {			/* there, so remove */
1326 		short *mi = &(*aWin->menuSelected)[i];
1327 		aWin->miSelLen --;
1328 		memcpy (mi, mi + 1, (aWin->miSelLen - i)*sizeof(short));
1329 	}
1330 	HUnlock ((char**)aWin->menuSelected);
1331 }
1332 
1333 
1334 /*
1335  * Find menu item in list given a line number on the window
1336  */
1337 static short
ListCoordinateToItem(NhWindow * aWin,short Row)1338 ListCoordinateToItem (NhWindow *aWin, short Row) {
1339 	int					i, item = -1;
1340 	MacMHMenuItem *		mi;
1341 
1342 	HLock ((char**)aWin->menuInfo);
1343 	for (i = 0, mi = *aWin->menuInfo; i < aWin->miLen; i++, mi++) {
1344 		if (mi->line == Row + aWin->scrollPos) {
1345 			item = i;
1346 			break;
1347 		}
1348 	}
1349 	HUnlock ((char**)aWin->menuInfo);
1350 	return item;
1351 }
1352 
1353 
1354 static void
macKeyMenu(EventRecord * theEvent,WindowPtr theWindow)1355 macKeyMenu (EventRecord *theEvent, WindowPtr theWindow) {
1356 	NhWindow *aWin = GetNhWin(theWindow);
1357 	MacMHMenuItem *mi;
1358 	int l, ch = theEvent->message & 0xff;
1359 
1360 	if (aWin && aWin->menuInfo) {
1361 		HLock ((char**)aWin->menuInfo);
1362 		for (l = 0, mi = *aWin->menuInfo; l < aWin->miLen; l++, mi++) {
1363 			if (mi->accelerator == ch) {
1364 				ToggleMenuListItemSelected (aWin, l);
1365 				if (mi->line >= aWin->scrollPos && mi->line <= aWin->y_size) {
1366 					SetPortWindowPort(theWindow);
1367 					ToggleMenuSelect (aWin, mi->line - aWin->scrollPos);
1368 				}
1369 				/* Dismiss window if only picking one item */
1370 				if (aWin->how != PICK_ANY)
1371 					AddToKeyQueue(CHAR_CR, 1);
1372 				break;
1373 			}
1374 		}
1375 		HUnlock ((char**)aWin->menuInfo);
1376 		/* add key if didn't find it in menu and not filtered */
1377 		if (l == aWin->miLen && filter_scroll_key (ch, aWin))
1378 			GeneralKey (theEvent, theWindow);
1379 	}
1380 }
1381 
1382 
1383 static void
macClickMenu(EventRecord * theEvent,WindowRef theWindow)1384 macClickMenu (EventRecord *theEvent, WindowRef theWindow) {
1385 	Point p;
1386 	NhWindow *aWin = GetNhWin(theWindow);
1387 	Rect wrect;
1388 
1389 
1390 	GetWindowBounds(theWindow, kWindowContentRgn, &wrect);
1391 	OffsetRect(&wrect, -wrect.left, -wrect.top);
1392 	if (aWin->scrollBar && IsControlVisible(aWin->scrollBar)) {
1393 		short code;
1394 		ControlHandle theBar;
1395 
1396 		p = theEvent->where;
1397 		GlobalToLocal (&p);
1398 		code = FindControl (p, theWindow, &theBar);
1399 		if (code) {
1400 			DoScrollBar (p, code, theBar, aWin);
1401 			return;
1402 		}
1403 	}
1404 	if (inSelect != WIN_ERR && aWin->how != PICK_NONE) {
1405 		short		currentRow = -1, previousRow = -1;
1406 		short		previousItem = -1, item = -1;
1407 		Boolean		majorSelectState, firstRow = TRUE;
1408 
1409 		do {
1410 #if !TARGET_API_MAC_CARBON
1411 			SystemTask ();
1412 #endif
1413 			GetMouse (&p);
1414 			currentRow = p.v / aWin->row_height;
1415 			if (p.h < wrect.left || p.h > wrect.right ||
1416 				p.v < 0 || p.v > wrect.bottom || currentRow >= aWin->y_size) {
1417 				continue;	/* not in window range */
1418 			}
1419 
1420 			item = ListCoordinateToItem (aWin, currentRow);
1421 
1422 			if (item != previousItem) {
1423 				/* Implement typical Mac multiple-selection behavior
1424 				 * (ie, not the UI implemented by the Finder)
1425 				 */
1426 				Boolean	itemIsSelected = (ListItemSelected (aWin,item) >= 0);
1427 
1428 				if (firstRow) {
1429 					/* this is first valid row, so major state is opposite of what this row is */
1430 					majorSelectState = !itemIsSelected;
1431 					firstRow = FALSE;
1432 				}
1433 
1434 				if (aWin->how == PICK_ONE && previousItem != -1) {
1435 					/* if previous row was selected and we're only selecting one object,
1436 					 * deselect previous row!
1437 					 */
1438 					ToggleMenuListItemSelected (aWin, previousItem);
1439 					ToggleMenuSelect (aWin, previousRow);
1440 					previousItem = -1;
1441 				}
1442 
1443 				if (item == -1)
1444 					continue;	/* header line */
1445 
1446 				if (majorSelectState != itemIsSelected) {
1447 					ToggleMenuListItemSelected (aWin, item);
1448 					ToggleMenuSelect (aWin, currentRow);
1449 				}
1450 
1451 				previousRow		= currentRow;
1452 				previousItem	= item;
1453 			}
1454 		} while (StillDown ());
1455 
1456 		/* Dismiss window if only picking one item */
1457 		if (aWin->how == PICK_ONE)
1458 			AddToKeyQueue(CHAR_CR, 1);
1459 	}
1460 }
1461 
1462 
1463 static void
macKeyText(EventRecord * theEvent,WindowPtr theWindow)1464 macKeyText (EventRecord *theEvent, WindowPtr theWindow) {
1465 	NhWindow *aWin = GetNhWin (theWindow);
1466 	char c = filter_scroll_key (theEvent->message & 0xff, aWin);
1467 	if (c) {
1468 		if (inSelect == WIN_ERR && ClosingWindowChar (c)) {
1469 			HideWindow (theWindow);
1470 			mac_destroy_nhwindow (aWin - theWindows);
1471 		} else {
1472 			GeneralKey (theEvent, theWindow);
1473 		}
1474 	}
1475 }
1476 
1477 
1478 static void
macClickText(EventRecord * theEvent,WindowPtr theWindow)1479 macClickText (EventRecord *theEvent, WindowPtr theWindow) {
1480 	NhWindow *aWin = GetNhWin (theWindow);
1481 
1482 	if (aWin->scrollBar && IsControlVisible(aWin->scrollBar)) {
1483 		short code;
1484 		Point p = theEvent->where;
1485 		ControlHandle theBar;
1486 
1487 		GlobalToLocal (&p);
1488 		code = FindControl (p, theWindow, &theBar);
1489 		if (code) {
1490 			DoScrollBar (p, code, theBar, aWin);
1491 		}
1492 	}
1493 }
1494 
1495 
1496 static void
macClickMessage(EventRecord * theEvent,WindowPtr theWindow)1497 macClickMessage (EventRecord *theEvent, WindowPtr theWindow) {
1498 	int r_idx = 0;
1499 	Point mouse = theEvent->where;
1500 
1501 	GlobalToLocal(&mouse);
1502 	while (topl_resp[r_idx]) {
1503 		Rect frame;
1504 		topl_resp_rect(r_idx, &frame);
1505 		InsetRect(&frame, 1, 1);
1506 		if (PtInRect(mouse, &frame)) {
1507 			Boolean in_btn = true;
1508 
1509 			InvertRect(&frame);
1510 			while (WaitMouseUp()) {
1511 #if !TARGET_API_MAC_CARBON
1512 				SystemTask();
1513 #endif
1514 				GetMouse(&mouse);
1515 				if (PtInRect(mouse, &frame) != in_btn) {
1516 					in_btn = !in_btn;
1517 					InvertRect(&frame);
1518 				}
1519 			}
1520 			if (in_btn) {
1521 				InvertRect(&frame);
1522 				AddToKeyQueue (topl_resp [r_idx], 1);
1523 			}
1524 			return;
1525 
1526 		}
1527 		++r_idx;
1528 	}
1529 
1530 	macClickText(theEvent, theWindow);
1531 }
1532 
1533 
1534 static void
macClickTerm(EventRecord * theEvent,WindowPtr theWindow)1535 macClickTerm (EventRecord *theEvent, WindowPtr theWindow) {
1536 	NhWindow *nhw = GetNhWin(theWindow);
1537 	Point where = theEvent->where;
1538 
1539 	GlobalToLocal(&where);
1540 	where.h = where.h / nhw->char_width + 1;
1541 	where.v = where.v / nhw->row_height;
1542 	clicked_mod = (theEvent->modifiers & shiftKey) ? CLICK_2 : CLICK_1;
1543 
1544 	if (strchr(topl_resp, *click_to_cmd(where.h, where.v, clicked_mod)))
1545 		nhbell();
1546 	else {
1547 #if !TARGET_API_MAC_CARBON
1548 		if (cursor_locked)
1549 			while (WaitMouseUp())
1550 				SystemTask();
1551 #endif
1552 
1553 		gClickedToMove = TRUE;
1554 		clicked_pos = where;
1555 	}
1556 }
1557 
1558 static pascal void
MoveScrollBar(ControlHandle theBar,short part)1559 MoveScrollBar (ControlHandle theBar, short part) {
1560 	EventRecord fake;
1561 	Rect r;
1562 	RgnHandle rgn;
1563 	int now, amtToScroll;
1564 	WindowPtr theWin;
1565 	NhWindow *winToScroll;
1566 
1567 	if (!part)
1568 		return;
1569 
1570 	theWin = GetControlOwner(theBar);
1571 	GetWindowBounds(theWin, kWindowContentRgn, &r);
1572 	OffsetRect(&r, -r.left, -r.top);
1573 	winToScroll = (NhWindow*)(GetWRefCon(theWin));
1574 	now = GetControlValue (theBar);
1575 
1576 	if (part == kControlPageUpPart || part == kControlPageDownPart)
1577 		amtToScroll = (r.bottom - r.top) / winToScroll->row_height;
1578 	else
1579 		amtToScroll = 1;
1580 
1581 	if (part == kControlPageUpPart || part == kControlUpButtonPart) {
1582 		int bound = GetControlMinimum (theBar);
1583 		if (now - bound < amtToScroll)
1584 			amtToScroll = now - bound;
1585 		amtToScroll = -amtToScroll;
1586 	} else {
1587 		int bound = GetControlMaximum (theBar);
1588 		if (bound - now < amtToScroll)
1589 			amtToScroll = bound - now;
1590 	}
1591 
1592 	if (!amtToScroll)
1593 		return;
1594 
1595 	SetControlValue (theBar, now + amtToScroll);
1596 	winToScroll->scrollPos = now + amtToScroll;
1597 	r.right -= SBARWIDTH;
1598 	if (winToScroll == theWindows + WIN_MESSAGE)
1599 		r.bottom -= SBARHEIGHT;
1600 	rgn = NewRgn ();
1601 	ScrollRect (&r, 0, -amtToScroll * winToScroll->row_height, rgn);
1602 	if (rgn) {
1603 		InvalWindowRgn(theWin, rgn);
1604 		BeginUpdate(theWin);
1605 	}
1606 	winUpdateFuncs [GetWindowKind(theWin) - WIN_BASE_KIND] (&fake, theWin);
1607 	if (rgn) {
1608 		EndUpdate(theWin);
1609 		DisposeRgn(rgn);
1610 	}
1611 }
1612 
1613 
1614 static void
DoScrollBar(Point p,short code,ControlHandle theBar,NhWindow * aWin)1615 DoScrollBar (Point p, short code, ControlHandle theBar, NhWindow *aWin)
1616 {
1617 	ControlActionUPP func = NULL;
1618 	Rect rect;
1619 
1620 	if (code == kControlUpButtonPart || code == kControlPageUpPart ||
1621 		code == kControlDownButtonPart || code == kControlPageDownPart)
1622 		func = MoveScrollUPP;
1623 	(void) TrackControl(theBar, p, func);
1624 	if (!func) {
1625 		if (aWin->scrollPos != GetControlValue (theBar)) {
1626 			aWin->scrollPos = GetControlValue (theBar);
1627 			GetWindowBounds(aWin->its_window, kWindowContentRgn, &rect);
1628 			OffsetRect(&rect, -rect.left, -rect.top);
1629 			InvalWindowRect(aWin->its_window, &rect);
1630 		}
1631 	}
1632 }
1633 
1634 
1635 static int
filter_scroll_key(const int ch,NhWindow * aWin)1636 filter_scroll_key(const int ch, NhWindow *aWin) {
1637 	if (aWin->scrollBar && GetControlValue(aWin->scrollBar) < GetControlMaximum(aWin->scrollBar)) {
1638 		short part = 0;
1639 		if (ch == CHAR_BLANK) {
1640 			part = kControlPageDownPart;
1641 		}
1642 		else if (ch == CHAR_CR || ch == CHAR_LF) {
1643 			part = kControlDownButtonPart;
1644 		}
1645 		if (part) {
1646 			SetPortWindowPort(aWin->its_window);
1647 			MoveScrollBar(aWin->scrollBar, part);
1648 			return 0;
1649 		}
1650 	}
1651 	return ch;
1652 }
1653 
1654 
1655 int
mac_doprev_message(void)1656 mac_doprev_message(void) {
1657 	if (WIN_MESSAGE) {
1658 		NhWindow *winToScroll = &theWindows[WIN_MESSAGE];
1659 		mac_display_nhwindow(WIN_MESSAGE, FALSE);
1660 		SetPortWindowPort(winToScroll->its_window);
1661 		MoveScrollBar(winToScroll->scrollBar, kControlUpButtonPart);
1662 	}
1663 	return 0;
1664 }
1665 
1666 
1667 static short
macDoNull(EventRecord * theEvent,WindowPtr theWindow)1668 macDoNull (EventRecord *theEvent, WindowPtr theWindow) {
1669 	return 0;
1670 }
1671 
1672 
1673 static void
draw_growicon_vert_only(WindowPtr wind)1674 draw_growicon_vert_only(WindowPtr wind)
1675 {
1676 	GrafPtr org_port;
1677 	RgnHandle org_clip = NewRgn();
1678 	Rect r;
1679 
1680 	GetPort(&org_port);
1681 	SetPortWindowPort(wind);
1682 	GetClip(org_clip);
1683 	GetWindowBounds(wind, kWindowContentRgn, &r);
1684 	OffsetRect(&r, -r.left, -r.top);
1685 	r.left = r.right - SBARWIDTH;
1686 	ClipRect(&r);
1687 	DrawGrowIcon(wind);
1688 	SetClip(org_clip);
1689 	DisposeRgn(org_clip);
1690 	SetPort(org_port);
1691 }
1692 
1693 
1694 static short
macUpdateMessage(EventRecord * theEvent,WindowPtr theWindow)1695 macUpdateMessage (EventRecord *theEvent, WindowPtr theWindow)
1696 {
1697 	RgnHandle org_clip = NewRgn(), clip = NewRgn();
1698 	Rect r;
1699 	NhWindow *aWin = GetNhWin(theWindow);
1700 	int l;
1701 
1702 	if (!theEvent)
1703 		return 0;
1704 
1705 	GetClip(org_clip);
1706 	GetWindowBounds(theWindow, kWindowContentRgn, &r);
1707 	OffsetRect(&r, -r.left, -r.top);
1708 
1709 	DrawControls(theWindow);
1710 	DrawGrowIcon(theWindow);
1711 
1712 	for (l = 0; topl_resp[l]; l++) {
1713 		StringPtr name;
1714 		unsigned char tmp[2];
1715 		FontInfo font;
1716 		Rect frame;
1717 		topl_resp_rect(l, &frame);
1718 		switch (topl_resp[l]) {
1719 			case 'y':
1720 				name = "\pyes";
1721 				break;
1722 			case 'n':
1723 				name = "\pno";
1724 				break;
1725 			case 'N':
1726 				name = "\pNone";
1727 				break;
1728 			case 'a':
1729 				name = "\pall";
1730 				break;
1731 			case 'q':
1732 				name = "\pquit";
1733 				break;
1734 			case CHAR_ANY:
1735 				name = "\pany key";
1736 				break;
1737 			default:
1738 				tmp[0] = 1;
1739 				tmp[1] = topl_resp[l];
1740 				name = tmp;
1741 				break;
1742 		}
1743 		TextFont(kFontIDGeneva);
1744 		TextSize(9);
1745 		GetFontInfo(&font);
1746 		MoveTo ((frame.left + frame.right - StringWidth(name)) / 2,
1747 			(frame.top + frame.bottom + font.ascent-font.descent-font.leading-1) / 2);
1748 		DrawString(name);
1749 		PenNormal();
1750 		if (l == topl_def_idx)
1751 			PenSize(2, 2);
1752 		FrameRoundRect(&frame, 4, 4);
1753 	}
1754 
1755 	r.right -= SBARWIDTH;
1756 	r.bottom -= SBARHEIGHT;
1757 	/* Clip to the portrect - scrollbar/growicon *before* adjusting the rect
1758 		to be larger than the size of the window (!) */
1759 	RectRgn(clip, &r);
1760 	SectRgn(clip, org_clip, clip);
1761 	if (r.right < MIN_RIGHT)
1762 		r.right = MIN_RIGHT;
1763 	r.top -= aWin->scrollPos * aWin->row_height;
1764 
1765 #if 0
1766 	/* If you enable this band of code (and disable the next band), you will get
1767 	   fewer flickers but a slower performance while drawing the dot line. */
1768 	{	RgnHandle dotl_rgn = NewRgn();
1769 		Rect dotl;
1770 		dotl.left	= r.left;
1771 		dotl.right	= r.right;
1772 		dotl.bottom = r.top + aWin->save_lin * aWin->row_height;
1773 		dotl.top	= dotl.bottom - 1;
1774 		FillRect(&dotl, &qd.gray);
1775 		RectRgn(dotl_rgn, &dotl);
1776 		DiffRgn(clip, dotl_rgn, clip);
1777 		DisposeRgn(dotl_rgn);
1778 		SetClip(clip);
1779 	}
1780 #endif
1781 
1782 	if (in_topl_mode()) {
1783 		RgnHandle topl_rgn = NewRgn();
1784 		Rect topl_r = r;
1785 		topl_r.top += (aWin->y_size - 1) * aWin->row_height;
1786 		l = (*top_line)->destRect.right - (*top_line)->destRect.left;
1787 		(*top_line)->viewRect = topl_r;
1788 		(*top_line)->destRect = topl_r;
1789 		if (l != topl_r.right - topl_r.left)
1790 			TECalText(top_line);
1791 		TEUpdate(&topl_r, top_line);
1792 		RectRgn(topl_rgn, &topl_r);
1793 		DiffRgn(clip, topl_rgn, clip);
1794 		DisposeRgn(topl_rgn);
1795 		SetClip(clip);
1796 	}
1797 
1798 	DisposeRgn(clip);
1799 
1800 	TextFont (aWin->font_number);
1801 	TextSize (aWin->font_size);
1802 	HLock (aWin->windowText);
1803 	TETextBox (*aWin->windowText, aWin->windowTextLen, &r, teJustLeft);
1804 	HUnlock (aWin->windowText);
1805 
1806 #if !TARGET_API_MAC_CARBON
1807 	r.bottom = r.top + aWin->save_lin * aWin->row_height;
1808 	r.top	 = r.bottom - 1;
1809 	FillRect(&r, (void *) &qd.gray);
1810 #endif
1811 
1812 	SetClip(org_clip);
1813 	DisposeRgn(org_clip);
1814 	return 0;
1815 }
1816 
1817 
1818 static short
macUpdateMenu(EventRecord * theEvent,WindowPtr theWindow)1819 macUpdateMenu (EventRecord *theEvent, WindowPtr theWindow) {
1820 	NhWindow *aWin = GetNhWin (theWindow);
1821 	int i, line;
1822 	MacMHMenuItem *mi;
1823 
1824 	GeneralUpdate (theEvent, theWindow);
1825 	HLock ((char**)aWin->menuInfo);
1826 	HLock ((char**)aWin->menuSelected);
1827 	for (i = 0; i < aWin->miSelLen; i++) {
1828 		mi = &(*aWin->menuInfo) [(*aWin->menuSelected) [i]];
1829 		line = mi->line;
1830 		if (line > aWin->scrollPos && line <= aWin->y_size)
1831 			ToggleMenuSelect (aWin, line - aWin->scrollPos);
1832 	}
1833 	HUnlock ((char**)aWin->menuInfo);
1834 	HUnlock ((char**)aWin->menuSelected);
1835 	return 0;
1836 }
1837 
1838 
1839 static short
GeneralUpdate(EventRecord * theEvent,WindowPtr theWindow)1840 GeneralUpdate (EventRecord *theEvent, WindowPtr theWindow) {
1841 	Rect r, r2;
1842 	NhWindow *aWin = GetNhWin (theWindow);
1843 	RgnHandle h;
1844 	Boolean vis;
1845 
1846 
1847 	if (!theEvent)
1848 		return 0;
1849 
1850 	GetWindowBounds(theWindow, kWindowContentRgn, &r);
1851 	OffsetRect(&r, -r.left, -r.top);
1852 	r2 = r;
1853 	r2.left = r2.right - SBARWIDTH;
1854 	r2.right += 1;
1855 	r2.top -= 1;
1856 	vis = (r2.bottom > r2.top + 50);
1857 
1858 	draw_growicon_vert_only(theWindow);
1859 	DrawControls (theWindow);
1860 
1861 	h = (RgnHandle) 0;
1862 	if (vis && (h = NewRgn ())) {
1863 		RgnHandle tmp = NewRgn ();
1864 		if (!tmp) {
1865 			DisposeRgn (h);
1866 			h = (RgnHandle) 0;
1867 		} else {
1868 			GetClip (h);
1869 			RectRgn (tmp, &r2);
1870 			DiffRgn (h, tmp, tmp);
1871 			SetClip (tmp);
1872 			DisposeRgn (tmp);
1873 		}
1874 	}
1875 	if (r.right < MIN_RIGHT)
1876 		r.right = MIN_RIGHT;
1877 	r.top -= aWin->scrollPos * aWin->row_height;
1878 	r.right -= SBARWIDTH;
1879 	HLock (aWin->windowText);
1880 	TETextBox (*aWin->windowText, aWin->windowTextLen, &r, teJustLeft);
1881 	HUnlock (aWin->windowText);
1882 	if (h) {
1883 		SetClip (h);
1884 		DisposeRgn (h);
1885 	}
1886 	return 0;
1887 }
1888 
1889 
1890 static void
macCursorTerm(EventRecord * theEvent,WindowPtr theWindow,RgnHandle mouseRgn)1891 macCursorTerm (EventRecord *theEvent, WindowPtr theWindow, RgnHandle mouseRgn) {
1892 	char *dir_bas, *dir;
1893 	CursHandle ch;
1894 	GrafPtr gp;
1895 	NhWindow *nhw = GetNhWin (theWindow);
1896 	Rect r = {0, 0, 1, 1};
1897 
1898 	GetPort (&gp);
1899 	SetPortWindowPort(theWindow);
1900 
1901 	if (cursor_locked)
1902 		dir = (char *)0;
1903 	else {
1904 		Point where = theEvent->where;
1905 
1906 		GlobalToLocal (&where);
1907 		dir_bas = iflags.num_pad ? (char *) ndir : (char *) sdir;
1908 		dir = strchr (dir_bas, *click_to_cmd (where.h / nhw->char_width + 1 ,
1909 							where.v / nhw->row_height, CLICK_1));
1910 	}
1911 	ch = GetCursor (dir ? dir - dir_bas + 513 : 512);
1912 	if (ch) {
1913 		HLock ((Handle) ch);
1914 		SetCursor (*ch);
1915 		HUnlock ((Handle) ch);
1916 
1917 	} else {
1918 		SetCursor(&qdarrow);
1919 	}
1920 	OffsetRect (&r, theEvent->where.h, theEvent->where.v);
1921 	RectRgn (mouseRgn, &r);
1922 	SetPort (gp);
1923 }
1924 
1925 
1926 static void
GeneralCursor(EventRecord * theEvent,WindowPtr theWindow,RgnHandle mouseRgn)1927 GeneralCursor (EventRecord *theEvent, WindowPtr theWindow, RgnHandle mouseRgn) {
1928 #if defined(__SC__) || defined(__MRC__)
1929 # pragma unused(theWindow)
1930 #endif
1931 	Rect r = {-1, -1, 2, 2};
1932 
1933 	SetCursor(&qdarrow);
1934 	OffsetRect (&r, theEvent->where.h, theEvent->where.v);
1935 	RectRgn (mouseRgn, &r);
1936 }
1937 
1938 
1939 static void
HandleKey(EventRecord * theEvent)1940 HandleKey (EventRecord *theEvent) {
1941 	WindowPtr theWindow = FrontWindow ();
1942 
1943 	if (theEvent->modifiers & cmdKey) {
1944 		if (theEvent->message & 0xff == '.') {
1945 			/* Flush key queue */
1946 			keyQueueCount = keyQueueWrite = keyQueueRead = 0;
1947 			theEvent->message = '\033';
1948 			goto dispatchKey;
1949 		} else {
1950 			UndimMenuBar ();
1951 			DoMenuEvt (MenuKey (theEvent->message & 0xff));
1952 		}
1953 	} else {
1954 
1955 dispatchKey :
1956 		if (theWindow) {
1957 			int kind = GetWindowKind(theWindow) - WIN_BASE_KIND;
1958 			winKeyFuncs [kind] (theEvent, theWindow);
1959 		} else {
1960 			GeneralKey (theEvent, (WindowPtr) 0);
1961 		}
1962 	}
1963 }
1964 
1965 
1966 static void
WindowGoAway(EventRecord * theEvent,WindowPtr theWindow)1967 WindowGoAway (EventRecord *theEvent, WindowPtr theWindow) {
1968 	NhWindow *aWin = GetNhWin(theWindow);
1969 
1970 	if (!theEvent || TrackGoAway (theWindow, theEvent->where)) {
1971 		if (aWin - theWindows == BASE_WINDOW && !iflags.window_inited) {
1972 			AddToKeyQueue ('\033', 1);
1973 		} else {
1974 			HideWindow (theWindow);
1975 			if (aWin - theWindows != inSelect)
1976 				mac_destroy_nhwindow (aWin - theWindows);
1977 			else								/* if this IS the inSelect window put a close char */
1978 				AddToKeyQueue (CHAR_CR, 1);		/* in queue to exit and maintain inSelect */
1979 		}
1980 	}
1981 }
1982 
1983 
1984 static void
HandleClick(EventRecord * theEvent)1985 HandleClick (EventRecord *theEvent) {
1986 	int code;
1987 	unsigned long l;
1988 	WindowPtr theWindow;
1989 	NhWindow *aWin;
1990 	Rect r;
1991 	Boolean not_inSelect;
1992 
1993 	InsetRect(GetRegionBounds(GetGrayRgn(), &r), 4, 4);
1994 
1995 	code = FindWindow (theEvent->where, &theWindow);
1996 	aWin = GetNhWin (theWindow);
1997 	not_inSelect = (inSelect == WIN_ERR || aWin - theWindows == inSelect);
1998 
1999 	switch (code) {
2000 	case inContent :
2001 		if (not_inSelect) {
2002 			int kind = GetWindowKind(theWindow) - WIN_BASE_KIND;
2003 			winCursorFuncs [kind] (theEvent, theWindow, gMouseRgn);
2004 			SelectWindow (theWindow);
2005 			SetPortWindowPort(theWindow);
2006 			winClickFuncs [kind] (theEvent, theWindow);
2007 		} else {
2008 			nhbell ();
2009 		}
2010 		break;
2011 
2012 	case inDrag :
2013 		if (not_inSelect) {
2014 			SetCursor(&qdarrow);
2015 			DragWindow (theWindow, theEvent->where, &r);
2016 			SaveWindowPos(theWindow);
2017 		} else {
2018 			nhbell ();
2019 		}
2020 		break;
2021 
2022 	case inGrow :
2023 		if (not_inSelect) {
2024 			SetCursor(&qdarrow);
2025 			SetRect (&r, 80, 2 * aWin->row_height + 1, r.right, r.bottom);
2026 			if (aWin == theWindows + WIN_MESSAGE)
2027 				r.top += SBARHEIGHT;
2028 			l = GrowWindow (theWindow, theEvent->where, &r);
2029 			SizeWindow (theWindow, l & 0xffff, l >> 16, FALSE);
2030 			SaveWindowSize(theWindow);
2031 			SetPortWindowPort(theWindow);
2032 			GetWindowBounds(theWindow, kWindowContentRgn, &r);
2033 			OffsetRect(&r, -r.left, -r.top);
2034 			InvalWindowRect(theWindow, &r);
2035 			if (aWin->scrollBar) {
2036 				DrawScrollbar (aWin);
2037 			}
2038 		} else {
2039 			nhbell ();
2040 		}
2041 		break;
2042 
2043 	case inGoAway :
2044 		WindowGoAway(theEvent, theWindow);
2045 		break;
2046 
2047 	case inMenuBar :
2048 		DoMenuEvt (MenuSelect (theEvent->where));
2049 		break;
2050 
2051 #if !TARGET_API_MAC_CARBON
2052 	case inSysWindow :
2053 		SystemClick(theEvent, theWindow);
2054 #endif
2055 	default :
2056 		break;
2057 	}
2058 }
2059 
2060 
2061 static void
HandleUpdate(EventRecord * theEvent)2062 HandleUpdate (EventRecord *theEvent) {
2063 	WindowPtr theWindow = (WindowPtr) theEvent->message;
2064 	NhWindow *aWin = GetNhWin (theWindow);
2065 	Rect r;
2066 
2067 
2068 	char existing_update_region = FALSE;
2069 	Rect rect;
2070 
2071 	if (theWindow == _mt_window) {
2072 		existing_update_region = (get_invalid_region (theWindow, &rect) == noErr);
2073 	}
2074 	BeginUpdate (theWindow);
2075 	SetPortWindowPort(theWindow);
2076 	GetWindowBounds(theWindow, kWindowContentRgn, &r);
2077 	OffsetRect(&r, -r.left, -r.top);
2078 	EraseRect(&r);
2079 	winUpdateFuncs [GetWindowKind(theWindow) - WIN_BASE_KIND]
2080 				(theEvent, theWindow);
2081 
2082 	if (theWindow == _mt_window && existing_update_region) {
2083 		set_invalid_region (theWindow, &rect);
2084 	}
2085 	aWin->drawn = TRUE;
2086 	EndUpdate (theWindow);
2087 }
2088 
2089 
2090 static void
DoOsEvt(EventRecord * theEvent)2091 DoOsEvt (EventRecord *theEvent) {
2092 	WindowRef win;
2093 	short code;
2094 
2095 	if ((theEvent->message & 0xff000000) == 0xfa000000) {
2096 		/* Mouse Moved */
2097 
2098 		code = FindWindow (theEvent->where, &win);
2099 		if (code != inContent) {
2100 			Rect r = {-1, -1, 2, 2};
2101 
2102 			SetCursor(&qdarrow);
2103 			OffsetRect (&r, theEvent->where.h, theEvent->where.v);
2104 			RectRgn (gMouseRgn, &r);
2105 		} else {
2106 			int kind = GetWindowKind(win) - WIN_BASE_KIND;
2107 			if (kind >= 0 && kind <= NHW_TEXT) {
2108 				winCursorFuncs [kind] (theEvent, win, gMouseRgn);
2109 			}
2110 		}
2111 	}
2112 }
2113 
2114 
2115 void
HandleEvent(EventRecord * theEvent)2116 HandleEvent (EventRecord *theEvent) {
2117 	switch (theEvent->what) {
2118 	case autoKey :
2119 	case keyDown :
2120 		HandleKey (theEvent);
2121 		break;
2122 	case updateEvt :
2123 		HandleUpdate (theEvent);
2124 		break;
2125 	case mouseDown :
2126 		HandleClick (theEvent);
2127 		break;
2128 #if !TARGET_API_MAC_CARBON
2129 	case diskEvt :
2130 		if ((theEvent->message & 0xffff0000) != 0) {
2131 			Point p = {150, 150};
2132 			(void) DIBadMount (p, theEvent->message);
2133 		}
2134 		break;
2135 #endif
2136 	case osEvt :
2137 		DoOsEvt (theEvent);
2138 		break;
2139 	case kHighLevelEvent:
2140 		AEProcessAppleEvent(theEvent);
2141 	default :
2142 		break;
2143 	}
2144 }
2145 
2146 
2147 void
mac_get_nh_event(void)2148 mac_get_nh_event(void) {
2149 	EventRecord anEvent;
2150 
2151 	/* KMH -- Don't proceed if the window system isn't set up */
2152 	if (!iflags.window_inited)
2153 		return;
2154 
2155 	(void) WaitNextEvent (everyEvent, &anEvent, -1, gMouseRgn);
2156 	HandleEvent(&anEvent);
2157 }
2158 
2159 
2160 int
mac_nhgetch(void)2161 mac_nhgetch(void) {
2162 	int ch;
2163 	long doDawdle;
2164 	EventRecord anEvent;
2165 
2166 	/* We want to take care of keys in the buffer as fast as
2167 	 * possible
2168 	 */
2169 	if (keyQueueCount)
2170 		doDawdle = 0L;
2171 	else {
2172 		long total, contig;
2173 		static char warn = 0;
2174 
2175 		doDawdle = (in_topl_mode() ? GetCaretTime () : 120L);
2176 		/* Since we have time, check memory */
2177 		PurgeSpace (&total, &contig);
2178 		if (contig < 25000L || total < 50000L) {
2179 			if (!warn) {
2180 				pline ("Low Memory!");
2181 				warn = 1;
2182 			}
2183 		} else {
2184 			warn = 0;
2185 		}
2186 	}
2187 
2188 	do {
2189 		(void) WaitNextEvent (everyEvent, &anEvent, doDawdle, gMouseRgn);
2190 		HandleEvent (&anEvent);
2191 		ch = GetFromKeyQueue ();
2192 	} while (!ch && !gClickedToMove);
2193 
2194 	if (!gClickedToMove)
2195 		ObscureCursor ();
2196 	else
2197 		gClickedToMove = 0;
2198 
2199 #ifdef THINK_C
2200 	if (ch == '\r') ch = '\n';
2201 #endif
2202 
2203 	return ch;
2204 }
2205 
2206 
2207 void
mac_delay_output(void)2208 mac_delay_output(void) {
2209 	long destTicks = TickCount () + 1;
2210 
2211 	while (TickCount () < destTicks) {
2212 		mac_get_nh_event ();
2213 	}
2214 }
2215 
2216 
2217 #ifdef CLIPPING
2218 static void
mac_cliparound(int x,int y)2219 mac_cliparound (int x, int y) {
2220 #if defined(__SC__) || defined(__MRC__)
2221 # pragma unused(x,y)
2222 #endif
2223 	/* TODO */
2224 }
2225 #endif
2226 
2227 void
mac_exit_nhwindows(const char * s)2228 mac_exit_nhwindows (const char *s) {
2229 	clear_screen ();
2230 	tty_exit_nhwindows (s);
2231 	mac_destroy_nhwindow (WIN_MESSAGE);
2232 	mac_destroy_nhwindow (WIN_INVEN);
2233 }
2234 
2235 
2236 /*
2237  * Don't forget to decrease in_putstr before returning...
2238  */
2239 void
mac_putstr(winid win,int attr,const char * str)2240 mac_putstr (winid win, int attr, const char *str) {
2241 	long len, slen;
2242 	NhWindow *aWin = &theWindows [win];
2243 	static char in_putstr = 0;
2244 	short newWidth, maxWidth;
2245 	Rect r;
2246 	char *src, *sline, *dst, ch;
2247 
2248 	if (win < 0 || win >= NUM_MACWINDOWS || !aWin->its_window) {
2249 		error ("putstr: Invalid win %d (Max %d).", win, NUM_MACWINDOWS, attr);
2250 		return;
2251 	}
2252 
2253 	if (aWin->its_window == _mt_window) {
2254 		tty_putstr(win, attr, str);
2255 		return;
2256 	}
2257 
2258 	if (in_putstr > 3)
2259 		return;
2260 
2261 	in_putstr ++;
2262 	slen = strlen (str);
2263 
2264 	SetPortWindowPort(aWin->its_window);
2265 	GetWindowBounds(aWin->its_window, kWindowContentRgn, &r);
2266 	OffsetRect(&r, -r.left, -r.top);
2267 	if (win == WIN_MESSAGE) {
2268 		r.right  -= SBARWIDTH;
2269 		r.bottom -= SBARHEIGHT;
2270 		if (flags.page_wait &&
2271 			aWin->last_more_lin <= aWin->y_size - (r.bottom - r.top) / aWin->row_height) {
2272 			aWin->last_more_lin = aWin->y_size;
2273 			mac_display_nhwindow(win, TRUE);
2274 		}
2275 	}
2276 
2277 	/*
2278 	 * A "default" text window - uses TETextBox
2279 	 * We just add the text, without attributes for now
2280 	 */
2281 	len = GetHandleSize (aWin->windowText);
2282 	while (aWin->windowTextLen + slen + 1 > len) {
2283 		len = (len > 2048) ? (len + 2048) : (len * 2);
2284 		SetHandleSize (aWin->windowText, len);
2285 		if (MemError ()) {
2286 			error ("putstr: SetHandleSize");
2287 			aWin->windowTextLen = 0L;
2288 			aWin->save_lin = 0;
2289 			aWin->y_curs = 0;
2290 			aWin->y_size = 0;
2291 		}
2292 	}
2293 
2294 	len = aWin->windowTextLen;
2295 	dst = *(aWin->windowText) + len;
2296 	sline = src = (char *)str;
2297 	maxWidth = newWidth = 0;
2298 	for (ch = *src; ch; ch = *src) {
2299 		if (ch == CHAR_LF)
2300 			ch = CHAR_CR;
2301 		*dst++ = ch;
2302 		if (ch == CHAR_CR) {
2303 			aWin->y_curs ++;
2304 			aWin->y_size ++;
2305 			aWin->x_curs = 0;
2306 			newWidth = TextWidth (sline, 0, src - sline);
2307 			if (newWidth > maxWidth) {
2308 				maxWidth = newWidth;
2309 			}
2310 			sline = src+1;	/* keep track of where new line begins */
2311 		}
2312 		else
2313 			aWin->x_curs ++;
2314 		src++;
2315 	}
2316 
2317 	newWidth = TextWidth (sline, 0, src - sline);
2318 	if (newWidth > maxWidth) {
2319 		maxWidth = newWidth;
2320 	}
2321 
2322 	aWin->windowTextLen += slen;
2323 
2324 	if (ch != CHAR_CR) {
2325 		(*(aWin->windowText)) [len + slen] = CHAR_CR;
2326 		aWin->windowTextLen ++;
2327 		aWin->y_curs ++;
2328 		aWin->y_size ++;
2329 		aWin->x_curs = 0;
2330 	}
2331 
2332 	if (win == WIN_MESSAGE) {
2333 		short min = aWin->y_size - (r.bottom - r.top) / aWin->row_height;
2334 		if (aWin->scrollPos < min) {
2335 			aWin->scrollPos = min;
2336 			SetControlMaximum (aWin->scrollBar, aWin->y_size);
2337 			SetControlValue(aWin->scrollBar, min);
2338 		}
2339 		InvalWindowRect(aWin->its_window, &r);
2340 	}
2341 	else	/* Message has a fixed width, other windows base on content */
2342 		if (maxWidth > aWin->x_size)
2343 			aWin->x_size = maxWidth;
2344 	in_putstr --;
2345 }
2346 
2347 
2348 void
mac_curs(winid win,int x,int y)2349 mac_curs (winid win, int x, int y) {
2350 	NhWindow *aWin = &theWindows [win];
2351 
2352 	if (aWin->its_window == _mt_window) {
2353 		tty_curs(win, x, y);
2354 		return;
2355 	}
2356 
2357 	SetPortWindowPort(aWin->its_window);
2358 	MoveTo (x * aWin->char_width, (y * aWin->row_height) + aWin->ascent_height);
2359 	aWin->x_curs = x;
2360 	aWin->y_curs = y;
2361 }
2362 
2363 
2364 int
mac_nh_poskey(int * a,int * b,int * c)2365 mac_nh_poskey (int *a, int *b, int *c) {
2366 	int ch = mac_nhgetch();
2367 	*a = clicked_pos.h;
2368 	*b = clicked_pos.v;
2369 	*c = clicked_mod;
2370 	return ch;
2371 }
2372 
2373 
2374 void
mac_start_menu(winid win)2375 mac_start_menu (winid win) {
2376 	HideWindow (theWindows [win].its_window);
2377 	mac_clear_nhwindow (win);
2378 }
2379 
2380 
2381 void
mac_add_menu(winid win,int glyph,const anything * any,CHAR_P menuChar,CHAR_P groupAcc,int attr,const char * inStr,int preselected)2382 mac_add_menu (winid win, int glyph, const anything *any, CHAR_P menuChar, CHAR_P groupAcc, int attr, const char *inStr, int preselected) {
2383 #if defined(__SC__) || defined(__MRC__)
2384 # pragma unused(glyph)
2385 #endif
2386 	NhWindow *aWin = &theWindows [win];
2387 	const char *str;
2388 	char locStr[4+BUFSZ];
2389 	MacMHMenuItem *item;
2390 
2391 	if (!inStr) return;
2392 
2393 	if (any->a_void != 0) {
2394 
2395 #define kMenuSizeBump 26
2396 		if (!aWin->miSize) {
2397 			aWin->menuInfo = (MacMHMenuItem **)NewHandle(sizeof(MacMHMenuItem) * kMenuSizeBump);
2398 			if (!aWin->menuInfo) {
2399 				error("Can't alloc menu handle");
2400 				return;
2401 			}
2402 			aWin->menuSelected = (short **)NewHandle(sizeof(short) * kMenuSizeBump);
2403 			if (!aWin->menuSelected) {
2404 				error("Can't alloc menu select handle");
2405 				return;
2406 			}
2407 			aWin->miSize = kMenuSizeBump;
2408 		}
2409 
2410 		if (aWin->miLen >= aWin->miSize) {
2411 			SetHandleSize((Handle)aWin->menuInfo, sizeof(MacMHMenuItem) * (aWin->miLen+kMenuSizeBump));
2412 			if (MemError()) {
2413 				error("Can't resize menu handle");
2414 				return;
2415 			}
2416 			SetHandleSize((Handle)aWin->menuSelected, sizeof(short) * (aWin->miLen+kMenuSizeBump));
2417 			if (MemError()) {
2418 				error("Can't resize menu select handle");
2419 				return;
2420 			}
2421 			aWin->miSize += kMenuSizeBump;
2422 		}
2423 
2424 		if (menuChar == 0) {
2425 			if (('a' <= aWin->menuChar && aWin->menuChar <= 'z') ||
2426 				('A' <= aWin->menuChar && aWin->menuChar <= 'Z')) {
2427 				menuChar = aWin->menuChar++;
2428 				if (menuChar == 'z')
2429 					aWin->menuChar = 'A';
2430 			}
2431 		}
2432 
2433 		Sprintf(locStr, "%c - %s", (menuChar ? menuChar : ' '), inStr);
2434 		str = locStr;
2435 		HLock ((char**)aWin->menuInfo);
2436 		HLock ((char**)aWin->menuSelected);
2437 		(*aWin->menuSelected)[aWin->miLen] = preselected;
2438 		item = &(*aWin->menuInfo)[aWin->miLen];
2439 		aWin->miLen++;
2440 		item->id = *any;
2441 		item->accelerator = menuChar;
2442 		item->groupAcc = groupAcc;
2443 		item->line = aWin->y_size;
2444 		HUnlock ((char**)aWin->menuInfo);
2445 		HUnlock ((char**)aWin->menuSelected);
2446 	} else
2447 		str = inStr;
2448 
2449 	putstr (win, attr, str);
2450 }
2451 
2452 
2453 /*
2454  * End a menu in this window, window must a type NHW_MENU.
2455  * str is a list of cancel characters (values that may be input)
2456  * morestr is a prompt to display, rather than the default.
2457  * str and morestr might be ignored by some ports.
2458  */
2459 void
mac_end_menu(winid win,const char * morestr)2460 mac_end_menu (winid win, const char *morestr) {
2461 	Str255 buf;
2462 	NhWindow *aWin = &theWindows [win];
2463 
2464 	buf [0] = 0;
2465 	if (morestr)
2466 		C2P (morestr, buf);
2467 	SetWTitle (aWin->its_window, buf);
2468 }
2469 
2470 
2471 int
mac_select_menu(winid win,int how,menu_item ** selected_list)2472 mac_select_menu (winid win, int how, menu_item **selected_list) {
2473 	int c;
2474 	NhWindow *aWin = &theWindows [win];
2475 	WindowPtr theWin = aWin->its_window;
2476 
2477 	inSelect = win;
2478 
2479 	mac_display_nhwindow (win, FALSE);
2480 
2481 	aWin->how = (short) how;
2482 	for (;;) {
2483 		c = map_menu_cmd (mac_nhgetch());
2484 		if (c == CHAR_ESC) {
2485 			/* deselect everything */
2486 			aWin->miSelLen = 0;
2487 			break;
2488 		} else if (ClosingWindowChar(c)) {
2489 			break;
2490 		} else {
2491 			nhbell();
2492 		}
2493 	}
2494 
2495 	HideWindow (theWin);
2496 
2497 	if (aWin->miSelLen) {
2498 		menu_item *mp;
2499 		MacMHMenuItem *mi;
2500 		*selected_list = mp = (menu_item *) alloc(aWin->miSelLen * sizeof(menu_item));
2501 		HLock ((char**)aWin->menuInfo);
2502 		HLock ((char**)aWin->menuSelected);
2503 		for (c = 0; c < aWin->miSelLen; c++) {
2504 			mi = &(*aWin->menuInfo)[(*aWin->menuSelected) [c]];
2505 			mp->item = mi->id;
2506 			mp->count = -1L;
2507 			mp++;
2508 		}
2509 		HUnlock ((char**)aWin->menuInfo);
2510 		HUnlock ((char**)aWin->menuSelected);
2511 	} else
2512 		*selected_list = 0;
2513 
2514 	inSelect = WIN_ERR;
2515 
2516 	return aWin->miSelLen;
2517 }
2518 
2519 #include "dlb.h"
2520 
2521 static void
mac_display_file(name,complain)2522 mac_display_file (name, complain)
2523 const char *name;	/* not ANSI prototype because of boolean parameter */
2524 boolean complain;
2525 {
2526 	Ptr buf;
2527 	int win;
2528 	dlb *fp = dlb_fopen(name, "r");
2529 
2530 	if (fp) {
2531 		long l = dlb_fseek(fp, 0, SEEK_END);
2532 		(void) dlb_fseek(fp, 0, 0L);
2533 		buf = NewPtr(l+1);
2534 		if (buf) {
2535 			l = dlb_fread(buf, 1, l, fp);
2536 			if (l > 0) {
2537 				buf[l] = '\0';
2538 				win = create_nhwindow(NHW_TEXT);
2539 				if (WIN_ERR == win) {
2540 					if (complain) error ("Cannot make window.");
2541 				} else {
2542 					putstr(win, 0, buf);
2543 					display_nhwindow(win, FALSE);
2544 				}
2545 			}
2546 			DisposePtr(buf);
2547 		}
2548 		dlb_fclose(fp);
2549 	} else if (complain)
2550 		error("Cannot open %s.", name);
2551 }
2552 
2553 
2554 void
port_help()2555 port_help () {
2556 	display_file (PORT_HELP, TRUE);
2557 }
2558 
2559 
2560 static void
mac_unimplemented(void)2561 mac_unimplemented (void) {
2562 }
2563 
2564 
2565 static void
mac_suspend_nhwindows(const char * foo)2566 mac_suspend_nhwindows (const char *foo) {
2567 #if defined(__SC__) || defined(__MRC__)
2568 # pragma unused(foo)
2569 #endif
2570 	/*	Can't really do that :-)		*/
2571 }
2572 
2573 
2574 int
try_key_queue(char * bufp)2575 try_key_queue (char *bufp) {
2576 	if (keyQueueCount) {
2577 		char ch;
2578 		for (ch = GetFromKeyQueue(); ; ch = GetFromKeyQueue()) {
2579 			if (ch == CHAR_LF || ch == CHAR_CR)
2580 				ch = 0;
2581 			*bufp++ = ch;
2582 			if (ch == 0)
2583 				break;
2584 		}
2585 		return 1;
2586 	}
2587 	return 0;
2588 }
2589 
2590 /* Interface definition, for windows.c */
2591 struct window_procs mac_procs = {
2592 	"mac",
2593 	WC_COLOR | WC_HILITE_PET |
2594 	WC_FONT_MAP | WC_FONT_MENU | WC_FONT_MESSAGE | WC_FONT_STATUS | WC_FONT_TEXT |
2595 	WC_FONTSIZ_MAP | WC_FONTSIZ_MENU | WC_FONTSIZ_MESSAGE | WC_FONTSIZ_STATUS | WC_FONTSIZ_TEXT,
2596 	0L,
2597 	mac_init_nhwindows,
2598 	mac_unimplemented,	/* see macmenu.c:mac_askname() for player selection */
2599 	mac_askname,
2600 	mac_get_nh_event,
2601 	mac_exit_nhwindows,
2602 	mac_suspend_nhwindows,
2603 	mac_unimplemented,
2604 	mac_create_nhwindow,
2605 	mac_clear_nhwindow,
2606 	mac_display_nhwindow,
2607 	mac_destroy_nhwindow,
2608 	mac_curs,
2609 	mac_putstr,
2610 	mac_display_file,
2611 	mac_start_menu,
2612 	mac_add_menu,
2613 	mac_end_menu,
2614 	mac_select_menu,
2615 	genl_message_menu,
2616 	mac_unimplemented,
2617 	mac_get_nh_event,
2618 	mac_get_nh_event,
2619 #ifdef CLIPPING
2620 	mac_cliparound,
2621 #endif
2622 #ifdef POSITIONBAR
2623 	donull,
2624 #endif
2625 	tty_print_glyph,
2626 	tty_raw_print,
2627 	tty_raw_print_bold,
2628 	mac_nhgetch,
2629 	mac_nh_poskey,
2630 	tty_nhbell,
2631 	mac_doprev_message,
2632 	mac_yn_function,
2633 	mac_getlin,
2634 	mac_get_ext_cmd,
2635 	mac_number_pad,
2636 	mac_delay_output,
2637 #ifdef CHANGE_COLOR
2638 	tty_change_color,
2639 	tty_change_background,
2640 	set_tty_font_name,
2641 	tty_get_color_string,
2642 #endif
2643 /* other defs that really should go away (they're tty specific) */
2644 	0, //    mac_start_screen,
2645 	0, //    mac_end_screen,
2646 	genl_outrip,
2647 	genl_preference_update,
2648 };
2649 
2650 /*macwin.c*/
2651