1 /* mac/scrnmgr/ScrnMgr.c: a screen management package for the Mac
2 
3    Copyright (c) 1989-1991 Curtis McCauley, James E. Wilson
4 
5    You may copy this subroutine package freely, modify it as you desire,
6    and distribute it at will, as long as the copyright notice in the source
7    material is not disturbed, excepting that no one may use this package or
8    any part of it for commercial purposes of any kind without the express
9    written consent of its author. */
10 
11 /*	Think C port by Benjamin Schreiber, 1991.  */
12 
13 #ifndef THINK_C
14 
15 #include <Types.h>
16 #include <OSUtils.h>
17 #include <Files.h>
18 #include <Quickdraw.h>
19 #include <Windows.h>
20 #include <Memory.h>
21 #include <Controls.h>
22 #include <Resources.h>
23 #include <Desk.h>
24 #include <Dialogs.h>
25 #include <Events.h>
26 #include <Fonts.h>
27 #include <Menus.h>
28 #include <OSEvents.h>
29 #include <SegLoad.h>
30 #include <TextEdit.h>
31 #include <ToolUtils.h>
32 #include <Packages.h>
33 #include <Retrace.h>
34 #include <Script.h>
35 #include <Traps.h>
36 #include <SysEqu.h>
37 
38 #include <StdDef.h>
39 #include <String.h>
40 #include <Strings.h>
41 
42 #else
43 
44 /* defined(THINK_C) */
45 
46 #include <VRetraceMgr.h>
47 #include <ScriptMgr.h>
48 #include <MultiFinder.h>	/* This may not be necessary.  */
49 
50 #include <string.h>
51 #include <stddef.h>
52 
53 #define p2cstr	PtoCstr		/* Correct difference in names.  */
54 #define c2pstr	CtoPstr
55 
56 typedef char Str63[64];
57 
58 /* Cover up error in THINK C library.  */
59 #define ok	OK
60 #define cancel	Cancel
61 #define normal	0
62 
63 #endif
64 
65 
66 #include "ScrnMgr.h"
67 
68 #define osEvent					app4Evt
69 #define suspendResumeMessage	1
70 #define resumeMask				1
71 
72 #define infoResType			(ResType) 'INFO'
73 #define infoResID			1
74 
75 #define ABS(i)				((i < 0) ? -i : i)
76 
77 #define menuBarID1			128
78 #define menuBarID2			228
79 
80 #define appleID				128
81 #define fileID1				129
82 #define fileID2				229
83 #define editID1				130
84 #define editID2				230
85 #define screenID			131
86 #define fontSizeID			132
87 #define appID1				133
88 #define appID2				233
89 
90 #define aboutItem			1
91 
92 #define openItem			1
93 #define closeItem			2
94 #define quitItem			4
95 
96 #define undoItem			1
97 #define cutItem				3
98 #define copyItem			4
99 #define pasteItem			5
100 #define clearItem			6
101 
102 #define colorsItem			1
103 
104 #define aboutDlgID			128
105 #define aboutDfltBorder		2
106 
107 #define aboutStrID			128
108 
109 #define colorsDlgID			129
110 #define colorsDfltBorder	23
111 #define foregroundRect		19
112 #define backgroundRect		20
113 #define foreColors			3
114 #define backColors			11
115 
116 #define yesOrNoDlgID		130
117 #define yesOrNoDfltBorder	3
118 #define yesOrNoText			4
119 
120 #define fontNameID			129
121 
122 #define fontSizeCount		50
123 #define minFontSize			1
124 #define maxFontSize			100
125 #define dfltFontSize		9
126 
127 #define acurID				128
128 
129 #define titleMargin			20
130 #define titleMinHgt			8
131 #define titleMinWid			8
132 #define titleDfltLeft		32
133 #define titleDfltTop		64
134 
135 #define ESC					'\x1B'
136 #define BACKQUOTE			'\x60'
137 
138 typedef struct Info {
139 	Rect bounds;
140 	short size;
141 	long colorStdFore;
142 	long colorStdBack;
143 } Info, *InfoPtr;
144 
145 typedef struct Acur {
146 	short frames;
147 	short next;
148 	union {
149 		struct { short id; short fill; } cursID;
150 		Cursor **cursHandle;
151 	} table[1];
152 } Acur, *AcurPtr, **AcurHandle;
153 
154 typedef struct Evt {
155 	char keycode;
156 	char modifiers;
157 	char ascii;
158 	short h;
159 	short v;
160 } Evt, *EvtPtr;
161 
162 #define qSize			32
163 
164 typedef struct SaveScreenRec {
165 	struct SaveScreenRec **link;	/* link to previous saved screen		*/
166 	char **chars;					/* handle to saved character buffer		*/
167 	char **attrs;					/* handle to saved attribute buffer		*/
168 	Point cursor;					/* saved cursor location				*/
169 } SaveScreenRec, *SaveScreenPtr, **SaveScreenHandle;
170 
171 typedef struct ScreenRec {
172     WindowPtr window;				/* the screen window					*/
173 	EventRecord event;				/* the last event						*/
174 	SysEnvRec env;					/* the outside world					*/
175 	long wneImplemented;			/* do we have WaitNextEvent?			*/
176 	long backgrounding;				/* are we in the background?			*/
177 	long reconfigFlag;				/* true if user want to change options	*/
178 	long colorFlag;					/* true if multiple colors supported	*/
179 	long cmdKeyFlag;				/* true if cmd key equivalents ok		*/
180 	long mouseFlag;					/* true if mouse clicks are captured	*/
181 	long escMapFlag;				/* true if backquote maps to escape		*/
182 	long waitFlag;					/* true if in wait						*/
183 	long waitRate;					/* how fast to spin the cursor			*/
184 	long colorStdFore;				/* standard foreground color			*/
185 	long colorStdBack;				/* standard background color			*/
186 	long windowW;					/* its content width in pixels			*/
187 	long windowH;					/* its content height in pixels			*/
188 	short txFont;					/* the font number in use				*/
189 	short txSize;					/* the font size in use					*/
190 	short txNum;					/* index into fontSizes table + 1		*/
191 	short **fontSizes;				/* a table of available sizes			*/
192     FontInfo info;					/* font info for the current font		*/
193     Point cursor;					/* cursor location in char coords		*/
194     Point charPDims;				/* char cell size in pixels				*/
195     Point scrnCDims;				/* screen size in chars					*/
196 	Point origin;					/* logical origin of screen for drawing */
197 	Rect stdStateGRect;				/* original standard state				*/
198     Rect scrnCRect;					/* screen bounds in chars				*/
199     Rect scrnLRect;					/* screen bounds in pixels				*/
200     Rect scrnXLRect;				/* screen bounds in pixels plus margin	*/
201 	Rect sizeLimitPRect;			/* limits to growth						*/
202 	Rect dragLimitGRect;			/* limits to movement					*/
203 	Rect hScrollPRect;				/* horiz scroll bar bounds				*/
204 	Rect vScrollPRect;				/* vert scroll bar bounds				*/
205 	Rect growPRect;					/* grow icon bounds						*/
206 	Rect picPRect;					/* picture area bounds					*/
207 	Rect picLRect;					/* drawing is clipped here (pic area)	*/
208 	Rect drawLRect;					/* drawing is clipped here (screen area)*/
209 	Rect drawXCRect;				/* rect to draw in char coords			*/
210 	Rect drawXLRect;				/* rect to draw in pixel coords			*/
211 	Rect mouseCRect;				/* watch mouse activity in this area	*/
212 	Rect mouseLRect;				/* watch mouse activity in this area	*/
213 	ControlHandle hScrollHandle;	/* handle to horiz scroll control		*/
214 	ControlHandle vScrollHandle;	/* handle to vert scroll control		*/
215 	short infoResFile;				/* ref no of resource file				*/
216 	Handle infoHandle;				/* handle to info resource				*/
217 	Handle versHandle;				/* handle to vers. string, for about dlg */
218     char **chars;					/* handle to character buffer			*/
219     char **attrs;					/* handle to attribute buffer			*/
220 	short **updLeft;				/* handle to left margin for updates	*/
221 	short **updRight;				/* handle to right margin for updates	*/
222 	long keyFlush;					/* tick count at last key flush			*/
223 	long mouseFlush;				/* tick count at last mouse flush		*/
224 	long qBegin;					/* index to first elem in queue			*/
225 	long qEnd;						/* index to next elem to be stored		*/
226 	Evt qBuffer[qSize];				/* queue of keystrokes					*/
227 	long cursorLevel;				/* greater than zero when cursor visible*/
228 	long cursorColor;				/* color of cursor lines				*/
229 	long cursorLines;				/* number of lines in cursor			*/
230 	long cursorBlink;				/* ticks between cursor blinks			*/
231 	long cursorStatus;				/* non-zero when cursor in on screen	*/
232 	long cursorChangeTick;			/* when to change cursor status			*/
233 	void (*aboutProc)(void);		/* what to call when about is selected  */
234 	void (*quitProc)(void);			/* what to call when quit is selected   */
235 	void (*fileMenuProc)(long item);/* file menu handler					*/
236 	void (*appMenuProc)(long item);	/* app menu handler						*/
237 	long quitReturns;				/* true if quit proc will always return */
238 	AcurHandle acur;				/* table of cursors						*/
239 	VBLTask vbl;					/* for animating said cursors			*/
240 	SaveScreenHandle stack;			/* stack of saved screens				*/
241 } ScreenRec;
242 
243 ScreenRec theScreen;
244 
245 static long colors[8] = {
246 	whiteColor, blackColor,
247 	redColor, greenColor, blueColor,
248 	cyanColor, magentaColor, yellowColor
249 };
250 
DisposeStackTop()251 static void DisposeStackTop()
252 
253 {
254 	SaveScreenHandle next;
255 
256 	if (theScreen.stack != NULL) {
257 
258 		next = (*theScreen.stack)->link;
259 
260 		DisposHandle((Handle) (*theScreen.stack)->chars);
261 		DisposHandle((Handle) (*theScreen.stack)->attrs);
262 
263 		DisposHandle((Handle) theScreen.stack);
264 
265 		theScreen.stack = next;
266 
267 	}
268 
269 	return;
270 }
271 
WNETest(envp)272 static long WNETest(envp)
273 SysEnvRec *envp;
274 
275 {
276 #ifndef THINK_C
277 	long hasWNE;
278 
279 	if (envp->machineType < 0)
280 		hasWNE = false;
281 
282 	else
283 		hasWNE =
284 		NGetTrapAddress(_WaitNextEvent, ToolTrap) != GetTrapAddress(_Unimplemented);
285 
286 	return(hasWNE);
287 #else
288 	return 0;
289 #endif
290 }
291 
NoEscTest(envp)292 static long NoEscTest(envp)
293 SysEnvRec *envp;
294 
295 {
296 	long hasNoEsc;
297 
298 	switch (envp->keyBoardType) {
299 
300 		case envAExtendKbd:
301 		case envStandADBKbd:
302 			hasNoEsc = false;
303 			break;
304 
305 		default:
306 			hasNoEsc = true;
307 			break;
308 
309 	}
310 
311 	return(hasNoEsc);
312 }
313 
FlushQueue()314 static void FlushQueue()
315 
316 {
317 	theScreen.qBegin = theScreen.qEnd = 0;
318 	return;
319 }
320 
PushQueue(keycode,modifiers,ascii,h,v)321 static void PushQueue(keycode, modifiers, ascii, h, v)
322 char keycode;
323 char modifiers;
324 char ascii;
325 short h;
326 short v;
327 
328 {
329 	long end;
330 	EvtPtr next;
331 
332 	end = (theScreen.qEnd + 1) & (qSize - 1);
333 	if (end != theScreen.qBegin) {
334 		next = &theScreen.qBuffer[theScreen.qEnd];
335 		next->keycode = keycode;
336 		next->modifiers = modifiers;
337 		next->ascii = ascii;
338 		next->h = h;
339 		next->v = v;
340 		theScreen.qEnd = end;
341 	}
342 	else {
343 		/* should I beep? */
344 	}
345 
346 	return;
347 }
348 
LenQueue()349 static long LenQueue()
350 
351 {
352 	return(ABS(theScreen.qEnd - theScreen.qBegin));
353 }
354 
PopQueue(keycode,modifiers,ascii,h,v)355 static long PopQueue(keycode, modifiers, ascii, h, v)
356 char *keycode;
357 char *modifiers;
358 char *ascii;
359 short *h;
360 short *v;
361 
362 {
363 	long flag;
364 	EvtPtr next;
365 
366 	if (theScreen.qEnd != theScreen.qBegin) {
367 		flag = true;
368 		next = &theScreen.qBuffer[theScreen.qBegin];
369 		if (keycode != NULL) *keycode = next->keycode;
370 		if (modifiers != NULL) *modifiers = next->modifiers;
371 		if (ascii != NULL ) *ascii = next->ascii;
372 		if (h != NULL ) *h = next->h;
373 		if (v != NULL ) *v = next->v;
374 		theScreen.qBegin = (theScreen.qBegin + 1) & (qSize - 1);
375 	}
376 	else {
377 		flag = false;
378 	}
379 
380 	return(flag);
381 }
382 
GtoC(gh,gv,ch,cv)383 static int GtoC(gh, gv, ch, cv)
384 short gh, gv;
385 short *ch, *cv;
386 
387 {
388 	int flag;
389 	Point temp;
390 
391 	temp.h = gh;
392 	temp.v = gv;
393 
394 	SetOrigin(theScreen.origin.h, theScreen.origin.v);
395 	GlobalToLocal(&temp);
396 	SetOrigin(0, 0);
397 
398 	if ( PtInRect(temp, &theScreen.mouseLRect)
399 	    && PtInRect(temp, &theScreen.picLRect) ) {
400 		flag = true;
401 		*ch = temp.h / theScreen.charPDims.h;
402 		*cv = temp.v / theScreen.charPDims.v;
403 	}
404 	else
405 		flag = false;
406 
407 	return(flag);
408 }
409 
DefaultCursor()410 static void DefaultCursor()
411 
412 {
413 	theScreen.cursorLevel = 0;
414 	theScreen.cursorColor = attrColorBlack;
415 	theScreen.cursorLines = 2;
416 	theScreen.cursorBlink = 0;
417 	theScreen.cursorStatus = 0;
418 	theScreen.cursorChangeTick = 0;
419 
420 	return;
421 }
422 
Prolog()423 static void Prolog()
424 
425 {
426 #ifdef THINK_C
427 	InitGraf(&thePort);
428 #else
429 	InitGraf(&qd.thePort);
430 #endif
431 	InitFonts();
432 	FlushEvents(everyEvent, 0);
433 	InitWindows();
434 	InitMenus();
435 	TEInit();
436 	InitDialogs(NULL);
437 	InitCursor();
438 
439 	return;
440 }
441 
LoadCursors()442 static void LoadCursors()
443 
444 {
445 	short i, count;
446 	Cursor **c;
447 
448 	theScreen.acur = (AcurHandle) GetResource('acur', acurID);
449 
450 	count = (*theScreen.acur)->frames;
451 
452 	for (i = 0; i < count; i++) {
453 		c = GetCursor((*theScreen.acur)->table[i].cursID.id);
454 		(*theScreen.acur)->table[i].cursHandle = c;
455 	}
456 
457 	return;
458 }
459 
GetFontSizes()460 static long GetFontSizes()
461 
462 {
463 	long i, j;
464 	short fsize, sizes[fontSizeCount];
465 	char **fname;
466 
467 	fname = (char **) GetString(fontNameID);
468 
469 	if (fname == NULL)
470 		theScreen.txFont = 0;
471 	else {
472 		HLock(fname);
473 		GetFNum(*fname, &theScreen.txFont);
474 		HUnlock(fname);
475 	}
476 
477 	for (i = 0, fsize = minFontSize;
478 		 (i < fontSizeCount) && (fsize < maxFontSize);
479 		 fsize++)
480 		if (RealFont(theScreen.txFont, fsize))
481 			sizes[i++] = fsize;
482 
483 	if (i == 0)
484 		sizes[i++] = dfltFontSize;
485 
486 	theScreen.fontSizes = (short **) NewHandle(sizeof(short) * (i + 1));
487 
488 	if (theScreen.fontSizes != NULL)
489 		for (j = 0; j < i; j++)
490 			(*theScreen.fontSizes)[j] = sizes[j];
491 
492 	(*theScreen.fontSizes)[i++] = 0;
493 
494 	return(theScreen.fontSizes != NULL);
495 }
496 
SetUpMenus()497 static void SetUpMenus()
498 
499 {
500 	long i, n, offset;
501 	Handle h;
502 	MenuHandle appMenuHndl, fontMenuHndl;
503 	Str255 ftitle;
504 
505 	SetMenuBar(GetNewMBar(theScreen.cmdKeyFlag ? menuBarID1 : menuBarID2));
506 	AddResMenu(GetMHandle(appleID), (ResType) 'DRVR');
507 	if (theScreen.colorFlag || !theScreen.env.hasColorQD) {
508 		InsertMenu(GetMenu(fontSizeID), 0);
509 		fontMenuHndl = GetMHandle(fontSizeID);
510 		offset = 1;
511 	}
512 	else {
513 		InsertMenu(GetMenu(screenID), 0);
514 		fontMenuHndl = GetMHandle(screenID);
515 		offset = 3;
516 	}
517 
518 	h = (Handle) GetString(aboutStrID);
519 	if (h != NULL) {
520 		MoveHHi(h);
521 		HLock(h);
522 		SetItem(GetMHandle(appleID), aboutItem, *h);
523 		HUnlock(h);
524 	}
525 
526 	for (i = 0; n = (*theScreen.fontSizes)[i]; i++) {
527 		NumToString(n, ftitle);
528 		(void) c2pstr(strcat(p2cstr((char *)ftitle), " point"));
529 		AppendMenu(fontMenuHndl, ftitle);
530 		if (n == theScreen.txSize) {
531 			theScreen.txNum = i + offset;
532 			CheckItem(fontMenuHndl, theScreen.txNum, true);
533 		}
534 	}
535 
536 	if (theScreen.appMenuProc != NULL) {
537 		appMenuHndl = GetMenu(theScreen.cmdKeyFlag ? appID1 : appID2);
538 		if (appMenuHndl != NULL) InsertMenu(appMenuHndl, 0);
539 	}
540 
541 	DrawMenuBar();
542 
543 	return;
544 }
545 
LoadInfo(resourceFile,rfCreator,rfType)546 static void LoadInfo(resourceFile, rfCreator, rfType)
547 Str255 resourceFile;
548 OSType rfCreator, rfType;
549 
550 {
551 	ResType dfltType;
552 	short dfltID;
553 	Str63 dfltName;
554 	short saveVol;
555 
556 	(void) GetVol(NULL, &saveVol);
557 	(void) SetVol(NULL, theScreen.env.sysVRefNum);
558 
559 	(void) Create(resourceFile, 0, rfCreator, rfType);
560 	CreateResFile(resourceFile);
561 
562 	theScreen.infoResFile = OpenResFile(resourceFile);
563 
564 	theScreen.infoHandle = GetResource(infoResType, infoResID);
565 
566 	if ( (theScreen.infoResFile != -1) &&
567 	     (theScreen.infoResFile != HomeResFile(theScreen.infoHandle)) ) {
568 		GetResInfo(theScreen.infoHandle, &dfltID, &dfltType, dfltName);
569 		DetachResource(theScreen.infoHandle);
570 		AddResource(theScreen.infoHandle, dfltType, dfltID, dfltName);
571 	}
572 
573 	(void) SetVol(NULL, saveVol);
574 
575 	return;
576 }
577 
UseInfo(boundsRectPtr,sizePtr,colorStdForePtr,colorStdBackPtr)578 static void UseInfo(boundsRectPtr, sizePtr, colorStdForePtr, colorStdBackPtr)
579 Rect *boundsRectPtr;
580 short *sizePtr;
581 long *colorStdForePtr;
582 long *colorStdBackPtr;
583 
584 {
585 	InfoPtr theInfo;
586 
587 	LoadResource(theScreen.infoHandle);
588 
589 	theInfo = (InfoPtr) *theScreen.infoHandle;
590 
591 	*boundsRectPtr = theInfo->bounds;
592 	*sizePtr = theInfo->size;
593 
594 	if (theScreen.env.hasColorQD) {
595 		*colorStdForePtr = theInfo->colorStdFore;
596 		*colorStdBackPtr = theInfo->colorStdBack;
597 	}
598 	else {
599 		*colorStdForePtr = attrColorBlack;
600 		*colorStdBackPtr = attrColorWhite;
601 	}
602 
603 	return;
604 }
605 
SaveInfo()606 static void SaveInfo()
607 
608 {
609 	Point topLeft, bottomRight;
610 	InfoPtr theInfo;
611 
612 	if (theScreen.infoResFile == -1) return;
613 
614 	LoadResource(theScreen.infoHandle);
615 	HLock(theScreen.infoHandle);
616 
617 	theInfo = (InfoPtr) *theScreen.infoHandle;
618 
619 #ifdef THINK_C
620 	topLeft.h = thePort->portRect.left;
621 	topLeft.v = thePort->portRect.top;
622 
623 	bottomRight.h = thePort->portRect.right;
624 	bottomRight.v = thePort->portRect.bottom;
625 #else
626 	topLeft.h = qd.thePort->portRect.left;
627 	topLeft.v = qd.thePort->portRect.top;
628 
629 	bottomRight.h = qd.thePort->portRect.right;
630 	bottomRight.v = qd.thePort->portRect.bottom;
631 #endif
632 
633 	LocalToGlobal(&topLeft);
634 	LocalToGlobal(&bottomRight);
635 
636 	if ( (topLeft.h     != theInfo->bounds.left)   ||
637 		 (topLeft.v     != theInfo->bounds.top)    ||
638 		 (bottomRight.h != theInfo->bounds.right)  ||
639 		 (bottomRight.v != theInfo->bounds.bottom)    ) {
640 
641 		theInfo->bounds.left   = topLeft.h;
642 		theInfo->bounds.top    = topLeft.v;
643 		theInfo->bounds.right  = bottomRight.h;
644 		theInfo->bounds.bottom = bottomRight.v;
645 		ChangedResource(theScreen.infoHandle);
646 
647 	}
648 
649 	if ( theScreen.txSize != theInfo->size ) {
650 
651 		theInfo->size = theScreen.txSize;
652 		ChangedResource(theScreen.infoHandle);
653 
654 	}
655 
656 	if ( (theScreen.colorStdFore != theInfo->colorStdFore) ||
657 	     (theScreen.colorStdBack != theInfo->colorStdBack)    ) {
658 
659 		theInfo->colorStdFore = theScreen.colorStdFore;
660 		theInfo->colorStdBack = theScreen.colorStdBack;
661 		ChangedResource(theScreen.infoHandle);
662 
663 	}
664 
665 	HUnlock(theScreen.infoHandle);
666 
667 	return;
668 }
669 
AdjustPortBounds(bounds)670 static void AdjustPortBounds(bounds)
671 Rect *bounds;
672 
673 {
674 	long repos;
675 	long wid, hgt;
676 	Rect test, sect;
677 #ifndef THINK_C
678 	GDHandle gdh;
679 #endif
680 
681 	test.left = bounds->left;
682 	test.top = bounds->top - titleMargin;
683 	test.right = bounds->right;
684 	test.bottom = bounds->top;
685 
686 #ifdef THINK_C			/* Ignore color issues. -- BS  */
687 
688 	(void) SectRect (&screenBits.bounds, &test, &sect);
689 	wid = sect.right - sect.left;
690 	hgt = sect.bottom - sect.top;
691 	if ((wid < titleMinWid) || (hgt < titleMinHgt))
692 		OffsetRect (bounds,
693 			(screenBits.bounds.left + titleDfltLeft) - bounds->left\,
694 			(screenBits.bounds.top + titleDfltTop) - bounds->top);
695 
696 #else
697 
698 	repos = true;
699 
700 	if (!theScreen.env.hasColorQD) {
701 
702 		(void) SectRect(&qd.screenBits.bounds, &test, &sect);
703 		wid = sect.right - sect.left;
704 		hgt = sect.bottom - sect.top;
705 		if ( (wid >= titleMinWid) && (hgt >= titleMinHgt) ) repos = false;
706 
707 	}
708 
709 	else {
710 
711 		gdh = GetDeviceList();
712 
713 		while ( (gdh != NULL) && (repos) ) {
714 
715 			if ( ((*gdh)->gdFlags && (1 << screenDevice)) &&
716 					((*gdh)->gdFlags && (1 << screenActive)) ) {
717 
718 				(void) SectRect(&(*gdh)->gdRect, &test, &sect);
719 				wid = sect.right - sect.left;
720 				hgt = sect.bottom - sect.top;
721 				if ( (wid >= titleMinWid) && (hgt >= titleMinHgt) ) repos = false;
722 
723 			}
724 
725 			gdh = GetNextDevice(gdh);
726 
727 		}
728 
729 	}
730 
731 	if (repos)
732 		OffsetRect(bounds,
733 			(qd.screenBits.bounds.left + titleDfltLeft) - bounds->left,
734 			(qd.screenBits.bounds.top + titleDfltTop) - bounds->top);
735 #endif
736 
737 	return;
738 }
739 
SetScreenParameters()740 static void SetScreenParameters()
741 
742 {
743 	long stdWid, stdHgt;
744 	Rect stdState;
745 	WStateData **zoomInfo;
746 
747     GetFontInfo(&theScreen.info);
748     theScreen.charPDims.h = theScreen.info.widMax;
749     theScreen.charPDims.v = theScreen.info.ascent
750 						 + theScreen.info.descent
751 						 + theScreen.info.leading;
752 
753     theScreen.scrnCRect.left = 0;
754     theScreen.scrnCRect.right = theScreen.scrnCDims.h;
755     theScreen.scrnCRect.top = 0;
756     theScreen.scrnCRect.bottom = theScreen.scrnCDims.v;
757 
758     theScreen.scrnLRect = theScreen.scrnCRect;
759     theScreen.scrnLRect.right *= theScreen.charPDims.h;
760     theScreen.scrnLRect.bottom *= theScreen.charPDims.v;
761 
762     theScreen.scrnXLRect = theScreen.scrnLRect;
763     InsetRect(&theScreen.scrnXLRect, -4, -4);
764 
765 	theScreen.sizeLimitPRect.left = 64;
766 	theScreen.sizeLimitPRect.top = 64;
767 
768 	theScreen.sizeLimitPRect.right =
769 		theScreen.scrnXLRect.right - theScreen.scrnXLRect.left + 16;
770 	if (theScreen.sizeLimitPRect.right < 65) theScreen.sizeLimitPRect.right = 65;
771 
772 	theScreen.sizeLimitPRect.bottom =
773 		theScreen.scrnXLRect.bottom - theScreen.scrnXLRect.top + 16;
774 	if (theScreen.sizeLimitPRect.bottom < 65)
775 	  theScreen.sizeLimitPRect.bottom = 65;
776 
777 #ifdef THINK_C
778 	theScreen.dragLimitGRect = screenBits.bounds;
779 #else
780 	theScreen.dragLimitGRect = qd.screenBits.bounds;
781 #endif
782 	theScreen.dragLimitGRect.top += GetMBarHeight();
783 	InsetRect(&theScreen.dragLimitGRect, -4, -4);
784 
785 	stdState = theScreen.stdStateGRect;
786 	stdWid = stdState.right - stdState.left - theScreen.sizeLimitPRect.right + 1;
787 	stdHgt = stdState.bottom - stdState.top
788 	  - theScreen.sizeLimitPRect.bottom + 1;
789 
790 	if (stdWid > 0) {
791 		InsetRect(&stdState, stdWid / 2, 0);
792 		stdState.right -= stdWid % 2;
793 	}
794 
795 	if (stdHgt > 0) {
796 		InsetRect(&stdState, 0, stdHgt / 2);
797 		stdState.bottom -= stdHgt % 2;
798 	}
799 
800 	zoomInfo = (WStateData **) ((WindowPeek) theScreen.window)->dataHandle;
801 	(*zoomInfo)->stdState = stdState;
802 
803 	theScreen.mouseLRect = theScreen.mouseCRect;
804 	theScreen.mouseLRect.left *= theScreen.charPDims.h;
805 	theScreen.mouseLRect.top *= theScreen.charPDims.v;
806 	theScreen.mouseLRect.right *= theScreen.charPDims.h;
807 	theScreen.mouseLRect.bottom *= theScreen.charPDims.v;
808 
809 	return;
810 }
811 
SetScreenPortSize()812 static void SetScreenPortSize()
813 
814 {
815 	long oldW, oldH;
816 	long newW, newH;
817 
818 	oldW = theScreen.window->portRect.right;
819 	oldH = theScreen.window->portRect.bottom;
820 
821 	if (oldW > theScreen.sizeLimitPRect.right-1)
822 		newW = theScreen.sizeLimitPRect.right-1;
823 	else if (oldW < theScreen.sizeLimitPRect.left)
824 		newW = theScreen.sizeLimitPRect.left;
825 	else
826 		newW = oldW;
827 
828 	if (oldH > theScreen.sizeLimitPRect.bottom-1)
829 		newH = theScreen.sizeLimitPRect.bottom-1;
830 	else if (oldH < theScreen.sizeLimitPRect.top)
831 		newH = theScreen.sizeLimitPRect.top;
832 	else
833 		newH = oldH;
834 
835 	if ( (newW != oldW) || (newH != oldH) )
836 		SizeWindow(theScreen.window, newW, newH, true);
837 
838 	return;
839 }
840 
SetScreenPortRects()841 static void SetScreenPortRects()
842 
843 {
844 	ClipRect(&theScreen.window->portRect);
845 
846 	theScreen.windowW = theScreen.window->portRect.right;
847 	theScreen.windowH =	theScreen.window->portRect.bottom;
848 
849 	theScreen.vScrollPRect =
850 	theScreen.hScrollPRect =
851 	theScreen.growPRect    =
852 	theScreen.picPRect     = theScreen.window->portRect;
853 
854 	theScreen.vScrollPRect.right += 1;
855 	theScreen.vScrollPRect.top -= 1;
856 	theScreen.vScrollPRect.left = theScreen.vScrollPRect.right - 16;
857 	theScreen.vScrollPRect.bottom -= 14;
858 
859 	theScreen.hScrollPRect.bottom += 1;
860 	theScreen.hScrollPRect.left -= 1;
861 	theScreen.hScrollPRect.top = theScreen.hScrollPRect.bottom - 16;
862 	theScreen.hScrollPRect.right -= 14;
863 
864 	theScreen.growPRect.top = theScreen.growPRect.bottom - 15;
865 	theScreen.growPRect.left = theScreen.growPRect.right - 15;
866 	theScreen.growPRect.bottom += 1;
867 	theScreen.growPRect.right += 1;
868 
869 	theScreen.picPRect.right -= 15;
870 	theScreen.picPRect.bottom -= 15;
871 
872 	return;
873 }
874 
SetScreenDrawRects()875 static void SetScreenDrawRects()
876 
877 {
878 	theScreen.picLRect = theScreen.picPRect;
879 	OffsetRect(&theScreen.picLRect, theScreen.origin.h, theScreen.origin.v);
880 
881 	SectRect(&theScreen.picLRect, &theScreen.scrnLRect, &theScreen.drawLRect);
882 
883 	theScreen.drawXCRect = theScreen.drawLRect;
884 	theScreen.drawXCRect.right += theScreen.charPDims.h - 1;
885 	theScreen.drawXCRect.bottom += theScreen.charPDims.v - 1;
886 	theScreen.drawXCRect.left /= theScreen.charPDims.h;
887 	theScreen.drawXCRect.right /= theScreen.charPDims.h;
888 	theScreen.drawXCRect.top /= theScreen.charPDims.v;
889 	theScreen.drawXCRect.bottom /= theScreen.charPDims.v;
890 
891 	theScreen.drawXLRect = theScreen.drawXCRect;
892 	theScreen.drawXLRect.left *= theScreen.charPDims.h;
893 	theScreen.drawXLRect.right *= theScreen.charPDims.h;
894 	theScreen.drawXLRect.top *= theScreen.charPDims.v;
895 	theScreen.drawXLRect.bottom *= theScreen.charPDims.v;
896 
897 	return;
898 }
899 
RepositionScreen(deltaH,deltaV)900 static int RepositionScreen(deltaH, deltaV)
901 int deltaH, deltaV;
902 
903 {
904 	int changed;
905 	int newH, newV;
906 	int min, max;
907 	RgnHandle updtRgn;
908 
909 	newH = GetCtlValue(theScreen.hScrollHandle) + deltaH;
910 	if (newH < (min = GetCtlMin(theScreen.hScrollHandle))) newH = min;
911 	if (newH > (max = GetCtlMax(theScreen.hScrollHandle))) newH = max;
912 
913 	newV = GetCtlValue(theScreen.vScrollHandle) + deltaV;
914 	if (newV < (min = GetCtlMin(theScreen.vScrollHandle))) newV = min;
915 	if (newV > (max = GetCtlMax(theScreen.vScrollHandle))) newV = max;
916 
917 	if ( (newH != theScreen.origin.h) || (newV != theScreen.origin.v) ) {
918 		if (newH != theScreen.origin.h)
919 			SetCtlValue(theScreen.hScrollHandle, newH);
920 		if (newV != theScreen.origin.v)
921 			SetCtlValue(theScreen.vScrollHandle, newV);
922 		updtRgn = NewRgn();
923 		ScrollRect(&theScreen.picPRect,
924 			theScreen.origin.h - newH,
925 			theScreen.origin.v - newV,
926 			updtRgn);
927 		InvalRgn(updtRgn);
928 		DisposeRgn(updtRgn);
929 		theScreen.origin.h = newH;
930 		theScreen.origin.v = newV;
931 		SetScreenDrawRects();
932 		changed = true;
933 	}
934 
935 	else
936 		changed = false;
937 
938 	return(changed);
939 }
940 
941 /* ARGH!  This routine needs error checking code. */
942 
InitScreenMgr(h,v,title,resFile,rfCreator,rfType,fileMenuProc,appMenuProc,colorFlag)943 long InitScreenMgr(h, v, title, resFile, rfCreator, rfType, fileMenuProc,
944 		  appMenuProc, colorFlag)
945 long h, v;
946 char *title;
947 char *resFile;
948 OSType rfCreator, rfType;
949 void (*fileMenuProc)(long item);
950 void (*appMenuProc)(long item);
951 long colorFlag;
952 
953 {
954     long bytes, i;
955 	Rect bounds;
956 	WStateData **zoomInfo;
957 	Str63 pstrTitle, pstrResFile;
958 
959 	Prolog();
960 
961 	SysEnvirons(curSysEnvVers, &theScreen.env);
962 
963 	theScreen.wneImplemented = WNETest(&theScreen.env);
964 
965 	theScreen.escMapFlag = NoEscTest(&theScreen.env);
966 
967 	theScreen.backgrounding = false;
968 
969 #if 1
970     {
971       char keys[128];
972       GetKeys ((KeyMap *) &keys);
973       theScreen.reconfigFlag = keys[7] & 0x04;
974     }
975 #else
976 	theScreen.reconfigFlag = ((char *) KeyMapLM)[7] & 0x04;
977 #endif
978 
979 	strncpy(pstrTitle, title, 63);
980 	strncpy(pstrResFile, resFile, 63);
981 	pstrTitle[63] = '\0';
982 	pstrResFile[63] = '\0';
983 	c2pstr(pstrTitle);
984 	c2pstr(pstrResFile);
985 
986 	LoadInfo(pstrResFile, rfCreator, rfType);
987 
988 	UseInfo(&bounds,
989 		&theScreen.txSize,
990 		&theScreen.colorStdFore,
991 		&theScreen.colorStdBack);
992 
993 	theScreen.versHandle = GetResource (rfCreator, 0);
994 
995 	AdjustPortBounds(&bounds);
996 
997 	LoadCursors();
998 
999 	theScreen.waitFlag = false;
1000 
1001 	theScreen.txNum = -1;
1002 
1003 	theScreen.fileMenuProc = fileMenuProc;
1004 	theScreen.appMenuProc = appMenuProc;
1005 
1006 	theScreen.colorFlag = colorFlag;
1007 
1008 	switch (theScreen.env.keyBoardType) {
1009 
1010 		/* These are the old machines that we know.  */
1011 		case envUnknownKbd:
1012 		case envMacKbd:
1013 		case envMacAndPad:
1014 		case envMacPlusKbd:
1015 		  theScreen.cmdKeyFlag = false;
1016 		  break;
1017 
1018 		case envAExtendKbd:
1019 		case envStandADBKbd:
1020 		case 10:		/* Mac Classic.  */
1021 		  /* Anything else is probably new and has ctrl.  */
1022 		default:
1023 		  theScreen.cmdKeyFlag = true;
1024 
1025 	}
1026 
1027 	theScreen.mouseFlag = false;
1028 	theScreen.mouseCRect.left	=
1029 	theScreen.mouseCRect.top	=
1030 	theScreen.mouseCRect.right	=
1031 	theScreen.mouseCRect.bottom	= 0;
1032 
1033     bytes = h * v;
1034     theScreen.chars = (char **) NewHandle(bytes);
1035     theScreen.attrs = (char **) NewHandle(bytes);
1036 
1037     memset(*theScreen.chars, ' ', bytes);
1038     memset(*theScreen.attrs, attrNormal, bytes);
1039 
1040 	bytes = v * sizeof(short);
1041     theScreen.updLeft  = (short **) NewHandle(bytes);
1042     theScreen.updRight = (short **) NewHandle(bytes);
1043 
1044 	for (i = 0; i < v; i++) {
1045 		(*theScreen.updLeft)[i] = h;
1046 		(*theScreen.updRight)[i] = 0;
1047 	}
1048 
1049     theScreen.cursor.h = 0;
1050     theScreen.cursor.v = 0;
1051 
1052     theScreen.scrnCDims.h = h;
1053     theScreen.scrnCDims.v = v;
1054 
1055 	FlushQueue();
1056 
1057 	DefaultCursor();
1058 
1059 	GetFontSizes();
1060 
1061 	SetUpMenus();
1062 
1063     theScreen.window = NewWindow(NULL, &bounds, pstrTitle,
1064 								 false, zoomDocProc,
1065 								 (WindowPtr) -1, true, 0);
1066 
1067     SetPort(theScreen.window);
1068 
1069 	zoomInfo = (WStateData **) ((WindowPeek) theScreen.window)->dataHandle;
1070 	theScreen.stdStateGRect = (*zoomInfo)->stdState;
1071 
1072     TextFont(theScreen.txFont);
1073     TextSize(theScreen.txSize);
1074 
1075 	SetScreenParameters();
1076 	SetScreenPortSize();
1077 	SetScreenPortRects();
1078 
1079 	theScreen.origin.h = theScreen.scrnXLRect.left;
1080 	theScreen.origin.v = theScreen.scrnXLRect.top;
1081 
1082 	SetScreenDrawRects();
1083 
1084 	theScreen.hScrollHandle = NewControl(theScreen.window,
1085 		&theScreen.hScrollPRect, "", true,
1086 		theScreen.origin.h,
1087 		theScreen.scrnXLRect.left,
1088 		theScreen.scrnXLRect.right - theScreen.picPRect.right,
1089 		scrollBarProc, 0L);
1090 	theScreen.vScrollHandle = NewControl(theScreen.window,
1091 		&theScreen.vScrollPRect, "", true,
1092 		theScreen.origin.v,
1093 		theScreen.scrnXLRect.top,
1094 		theScreen.scrnXLRect.bottom - theScreen.picPRect.bottom,
1095 		scrollBarProc, 0L);
1096 
1097 	ShowWindow(theScreen.window);
1098 	EraseRect(&theScreen.picPRect);
1099 
1100 	theScreen.aboutProc = NULL;
1101 	theScreen.quitProc = NULL;
1102 
1103 	theScreen.keyFlush = theScreen.mouseFlush = TickCount();
1104 
1105 	theScreen.stack = NULL;
1106 
1107     return(scrnErrOk);
1108 }
1109 
ChangeScreenFontSize(num)1110 static void ChangeScreenFontSize(num)
1111 long num;
1112 
1113 {
1114 	Point oldCharPDims;
1115 
1116 	DisposeControl(theScreen.hScrollHandle);
1117 	DisposeControl(theScreen.vScrollHandle);
1118 
1119 	oldCharPDims = theScreen.charPDims;
1120 
1121 	theScreen.txSize = (*theScreen.fontSizes)[num];
1122 
1123     TextSize(theScreen.txSize);
1124 
1125 	SetScreenParameters();
1126 	SetScreenPortSize();
1127 	SetScreenPortRects();
1128 
1129 	theScreen.origin.h *= theScreen.charPDims.h;
1130 	theScreen.origin.h /= oldCharPDims.h;
1131 	if (theScreen.origin.h < theScreen.scrnXLRect.left)
1132 		theScreen.origin.h = theScreen.scrnXLRect.left;
1133 	if (theScreen.origin.h > theScreen.scrnXLRect.right
1134 	    - theScreen.picPRect.right)
1135 		theScreen.origin.h = theScreen.scrnXLRect.right - theScreen.picPRect.right;
1136 	theScreen.origin.v *= theScreen.charPDims.v;
1137 	theScreen.origin.v /= oldCharPDims.v;
1138 	if (theScreen.origin.v < theScreen.scrnXLRect.top)
1139 		theScreen.origin.v = theScreen.scrnXLRect.top;
1140 	if (theScreen.origin.v > theScreen.scrnXLRect.bottom -
1141 	    theScreen.picPRect.bottom)
1142 		theScreen.origin.v = theScreen.scrnXLRect.bottom
1143 		  - theScreen.picPRect.bottom;
1144 
1145 	SetScreenDrawRects();
1146 
1147 	theScreen.hScrollHandle = NewControl(theScreen.window,
1148 		&theScreen.hScrollPRect, "", true,
1149 		theScreen.origin.h,
1150 		theScreen.scrnXLRect.left,
1151 		theScreen.scrnXLRect.right - theScreen.picPRect.right,
1152 		scrollBarProc, 0L);
1153 	theScreen.vScrollHandle = NewControl(theScreen.window,
1154 		&theScreen.vScrollPRect, "", true,
1155 		theScreen.origin.v,
1156 		theScreen.scrnXLRect.top,
1157 		theScreen.scrnXLRect.bottom - theScreen.picPRect.bottom,
1158 		scrollBarProc, 0L);
1159 
1160 	InvalRect(&theScreen.picPRect);
1161 	InvalRect(&theScreen.growPRect);
1162 
1163 	return;
1164 }
1165 
CloseScreenMgr()1166 void CloseScreenMgr()
1167 
1168 {
1169 	SaveInfo();
1170 
1171 	while (theScreen.stack != NULL)
1172 		DisposeStackTop();
1173 
1174 	DisposHandle((Handle) theScreen.fontSizes);
1175 
1176     DisposHandle((Handle) theScreen.chars);
1177     DisposHandle((Handle) theScreen.attrs);
1178 
1179     DisposeWindow(theScreen.window);
1180 
1181     return;
1182 }
1183 
DrawDefaultBorder(theWindow,theItem)1184 pascal void DrawDefaultBorder(theWindow, theItem)
1185 WindowPtr theWindow;
1186 short theItem;
1187 
1188 {
1189 	short itsType;
1190 	Handle itsHandle;
1191 	Rect itsRect;
1192 
1193 	GetDItem((DialogPtr) theWindow, theItem, &itsType, &itsHandle, &itsRect);
1194 	PenSize(3, 3);
1195 	ForeColor(redColor);
1196 	FrameRoundRect(&itsRect, 16, 16);
1197 	ForeColor(blackColor);
1198 	PenSize(1, 1);
1199 
1200 	return;
1201 }
1202 
DrawGroupRect(theWindow,theItem)1203 pascal void DrawGroupRect(theWindow, theItem)
1204 WindowPtr theWindow;
1205 short theItem;
1206 
1207 {
1208 	short itsType;
1209 	Handle itsHandle;
1210 	Rect itsRect;
1211 
1212 	GetDItem((DialogPtr) theWindow, theItem, &itsType, &itsHandle, &itsRect);
1213 	FrameRect(&itsRect);
1214 
1215 	return;
1216 }
1217 
DoAboutDialog()1218 static void DoAboutDialog()
1219 
1220 {
1221 	DialogPtr theDialog;
1222 	short itemHit;
1223 	short itsType;
1224 	Handle itsHandle;
1225 	Rect itsRect;
1226 	long h, v;
1227 
1228 	theDialog = GetNewDialog(aboutDlgID, nil, (WindowPtr) -1);
1229 
1230 	CenterScreenDLOG(aboutDlgID, fixThird, fixThird, &h, &v);
1231 	MoveWindow((WindowPtr) theDialog, (short) h, (short) v, false);
1232 
1233 	GetDItem(theDialog, ok, &itsType, &itsHandle, &itsRect);
1234 	InsetRect(&itsRect, -4, -4);
1235 
1236 	SetDItem(theDialog, aboutDfltBorder, userItem,
1237 		 (Handle) DrawDefaultBorder, &itsRect);
1238 
1239 	if (theScreen.versHandle) {
1240 	  MoveHHi (theScreen.versHandle);
1241 	  HLock (theScreen.versHandle);
1242 	  ParamText(*(theScreen.versHandle), nil, nil, nil);
1243 	  }
1244 
1245 	ShowWindow((WindowPtr) theDialog);
1246 
1247 	do {
1248 		ModalDialog(nil, &itemHit);
1249 	} while (itemHit != ok);
1250 
1251 	if (theScreen.versHandle)
1252 	  HUnlock(theScreen.versHandle);
1253 
1254 	DisposDialog(theDialog);
1255 
1256 	return;
1257 }
1258 
DoColorsDialog()1259 static void DoColorsDialog()
1260 
1261 {
1262 	DialogPtr theDialog;
1263 	long saveForeColor, saveBackColor;
1264 	short itemHit;
1265 	short itsType;
1266 	Handle itsHandle, fgHandle, bgHandle;
1267 	Rect itsRect;
1268 	GrafPtr savePort;
1269 	long redrawFlag;
1270 	long h, v;
1271 
1272 	theDialog = GetNewDialog(colorsDlgID, nil, (WindowPtr) -1);
1273 
1274 	CenterScreenDLOG(colorsDlgID, fixHalf, fixThird, &h, &v);
1275 	MoveWindow((WindowPtr) theDialog, (short) h, (short) v, false);
1276 
1277 	GetDItem(theDialog, ok, &itsType, &itsHandle, &itsRect);
1278 	InsetRect(&itsRect, -4, -4);
1279 
1280 	SetDItem(theDialog, colorsDfltBorder, userItem,
1281 		 (Handle) DrawDefaultBorder, &itsRect);
1282 
1283 	GetDItem(theDialog, foregroundRect, &itsType, &itsHandle, &itsRect);
1284 	SetDItem(theDialog, foregroundRect, itsType, (Handle) DrawGroupRect,
1285 		 &itsRect);
1286 	GetDItem(theDialog, backgroundRect, &itsType, &itsHandle, &itsRect);
1287 	SetDItem(theDialog, backgroundRect, itsType, (Handle) DrawGroupRect,
1288 		 &itsRect);
1289 
1290 	GetDItem(theDialog, foreColors+theScreen.colorStdFore, &itsType,
1291 		 &fgHandle, &itsRect);
1292 	SetCtlValue((ControlHandle) fgHandle, true);
1293 
1294 	GetDItem(theDialog, backColors+theScreen.colorStdBack, &itsType,
1295 		 &bgHandle, &itsRect);
1296 	SetCtlValue((ControlHandle) bgHandle, true);
1297 
1298 	ShowWindow((WindowPtr) theDialog);
1299 
1300 	saveForeColor = theScreen.colorStdFore;
1301 	saveBackColor = theScreen.colorStdBack;
1302 
1303 	do {
1304 		redrawFlag = false;
1305 		ModalDialog(nil, &itemHit);
1306 		if ( (itemHit >= foreColors) &&
1307 			(itemHit <= (foreColors+7)) &&
1308 			(itemHit != (foreColors+theScreen.colorStdFore)) ) {
1309 				theScreen.colorStdFore = itemHit - foreColors;
1310 				SetCtlValue((ControlHandle) fgHandle, false);
1311 				GetDItem(theDialog, foreColors+theScreen.colorStdFore,
1312 					&itsType, &fgHandle, &itsRect);
1313 				SetCtlValue((ControlHandle) fgHandle, true);
1314 				redrawFlag = true;
1315 		}
1316 		else if ( (itemHit >= backColors) &&
1317 			(itemHit <= (backColors+7)) &&
1318 			(itemHit != (backColors+theScreen.colorStdBack)) ) {
1319 				theScreen.colorStdBack = itemHit - backColors;
1320 				SetCtlValue((ControlHandle) bgHandle, false);
1321 				GetDItem(theDialog, backColors+theScreen.colorStdBack,
1322 					&itsType, &bgHandle, &itsRect);
1323 				SetCtlValue((ControlHandle) bgHandle, true);
1324 				redrawFlag = true;
1325 		}
1326 		if (redrawFlag) {
1327 			GetPort(&savePort);
1328 			SetPort(theScreen.window);
1329 			InvalRect(&theScreen.picPRect);
1330 			UpdateScreen();
1331 			SetPort(savePort);
1332 		}
1333 	} while ( (itemHit != ok) && (itemHit != cancel) );
1334 
1335 	if (itemHit == cancel)
1336 		if ( (theScreen.colorStdFore != saveForeColor) ||
1337 			(theScreen.colorStdBack != saveBackColor) ) {
1338 			theScreen.colorStdFore = saveForeColor;
1339 			theScreen.colorStdBack = saveBackColor;
1340 			GetPort(&savePort);
1341 			SetPort(theScreen.window);
1342 			InvalRect(&theScreen.picPRect);
1343 			UpdateScreen();
1344 			SetPort(savePort);
1345 		}
1346 
1347 	DisposDialog(theDialog);
1348 
1349 	return;
1350 }
1351 
DoAppleMenu(item)1352 static void DoAppleMenu(item)
1353 long item;
1354 
1355 {
1356 	GrafPtr savePort;
1357 	Str255 daName;
1358 
1359 	switch (item) {
1360 
1361 		case aboutItem:		if (theScreen.aboutProc != NULL)
1362 								(*theScreen.aboutProc)();
1363 							else
1364 								DoAboutDialog();
1365 							break;
1366 
1367 		default:			GetItem(GetMHandle(appleID), item, daName);
1368 							GetPort(&savePort);
1369 							OpenDeskAcc(daName);
1370 							SetPort(savePort);
1371 							break;
1372 
1373 	}
1374 
1375 	return;
1376 }
1377 
DoFileMenu(item)1378 static void DoFileMenu(item)
1379 long item;
1380 
1381 {
1382 	switch (item) {
1383 
1384 		case closeBoxItem:	HideWindow(theScreen.window);
1385 							break;
1386 
1387 		case openItem:		ShowWindow(theScreen.window);
1388 							break;
1389 
1390 		case closeItem:		HideWindow(theScreen.window);
1391 							break;
1392 
1393 		case quitItem:		if (theScreen.quitProc != NULL) {
1394 								if (!theScreen.quitReturns) HiliteMenu(0);
1395 								(*theScreen.quitProc)();
1396 							}
1397 							break;
1398 
1399 	}
1400 
1401 	return;
1402 }
1403 
DoEditMenu(item)1404 static void DoEditMenu(item)
1405 long item;
1406 
1407 {
1408 	switch (item) {
1409 
1410 		case undoItem:
1411 		case cutItem:
1412 		case copyItem:
1413 		case pasteItem:
1414 		case clearItem:		SystemEdit(item-1);
1415 							break;
1416 
1417 	}
1418 
1419 	return;
1420 }
1421 
DoFontChange(hndl,item,offset)1422 static void DoFontChange(hndl, item, offset)
1423 MenuHandle hndl;
1424 long item, offset;
1425 
1426 {
1427 	if (item != theScreen.txNum) {
1428 		if (theScreen.txNum > 0)
1429 			CheckItem(hndl, theScreen.txNum, false);
1430 		ChangeScreenFontSize(item - offset);
1431 		theScreen.txNum = item;
1432 		CheckItem(hndl, theScreen.txNum, true);
1433 	}
1434 
1435 	return;
1436 }
1437 
DoScreenMenu(item)1438 static void DoScreenMenu(item)
1439 long item;
1440 
1441 {
1442 	switch (item) {
1443 
1444 		case colorsItem:	DoColorsDialog();
1445 							break;
1446 
1447 		default:			DoFontChange(GetMHandle(screenID), item, 3);
1448 							break;
1449 
1450 	}
1451 
1452 	return;
1453 }
1454 
DoFontSizeMenu(item)1455 static void DoFontSizeMenu(item)
1456 long item;
1457 
1458 {
1459 	DoFontChange(GetMHandle(fontSizeID), item, 1L);
1460 	return;
1461 }
1462 
DoMenuItem(select)1463 static void DoMenuItem(select)
1464 long select;
1465 
1466 {
1467 	long menuID, menuItem;
1468 
1469 	menuID = HiWord(select);
1470 	menuItem = LoWord(select);
1471 
1472 	switch (menuID) {
1473 
1474 		case appleID:		DoAppleMenu(menuItem);
1475 							break;
1476 
1477 		case fileID1:
1478 		case fileID2:		if (theScreen.fileMenuProc != NULL)
1479 								(*theScreen.fileMenuProc)(menuItem);
1480 							else
1481 								DoFileMenu(menuItem);
1482 							break;
1483 
1484 		case editID1:
1485 		case editID2:		DoEditMenu(menuItem);
1486 							break;
1487 
1488 		case screenID:		DoScreenMenu(menuItem);
1489 							break;
1490 
1491 		case fontSizeID:	DoFontSizeMenu(menuItem);
1492 							break;
1493 
1494 		case appID1:
1495 		case appID2:		if (theScreen.appMenuProc != NULL)
1496 								(*theScreen.appMenuProc)(menuItem);
1497 							break;
1498 
1499 	}
1500 
1501 	HiliteMenu(0);
1502 
1503 	return;
1504 }
1505 
DoDrag(whichWindow,cursorLoc)1506 static void DoDrag(whichWindow, cursorLoc)
1507 WindowPtr whichWindow;
1508 Point *cursorLoc;
1509 
1510 {
1511 	if (whichWindow == theScreen.window)
1512 		DragWindow(whichWindow, *cursorLoc, &theScreen.dragLimitGRect);
1513 
1514 	return;
1515 }
1516 
HandlePreGrow(oldWidth,oldHeight,newWidth,newHeight)1517 static void HandlePreGrow(oldWidth, oldHeight, newWidth, newHeight)
1518 long oldWidth, oldHeight, newWidth, newHeight;
1519 
1520 {
1521 	if (newWidth > oldWidth) {
1522 		InvalRect(&theScreen.vScrollPRect);
1523 		InvalRect(&theScreen.growPRect);
1524 	}
1525 	if (newHeight > oldHeight) {
1526 		InvalRect(&theScreen.hScrollPRect);
1527 		InvalRect(&theScreen.growPRect);
1528 	}
1529 	return;
1530 }
1531 
HandlePostGrow(oldWidth,oldHeight,newWidth,newHeight)1532 static void HandlePostGrow(oldWidth, oldHeight, newWidth, newHeight)
1533 long oldWidth, oldHeight, newWidth, newHeight;
1534 
1535 {
1536 	if ( (newWidth < oldWidth) || (newHeight < oldHeight) )
1537 		InvalRect(&theScreen.growPRect);
1538 	HideControl(theScreen.hScrollHandle);
1539 	HideControl(theScreen.vScrollHandle);
1540 	if (newWidth != oldWidth) {
1541 		MoveControl(theScreen.vScrollHandle,
1542 			theScreen.vScrollPRect.left, theScreen.vScrollPRect.top);
1543 		SizeControl(theScreen.hScrollHandle,
1544 			theScreen.hScrollPRect.right - theScreen.hScrollPRect.left,
1545 			theScreen.hScrollPRect.bottom - theScreen.hScrollPRect.top);
1546 		SetCtlMax(theScreen.hScrollHandle,
1547 			theScreen.scrnXLRect.right - theScreen.picPRect.right);
1548 	}
1549 	if (newHeight != oldHeight) {
1550 		MoveControl(theScreen.hScrollHandle,
1551 			theScreen.hScrollPRect.left, theScreen.hScrollPRect.top);
1552 		SizeControl(theScreen.vScrollHandle,
1553 			theScreen.vScrollPRect.right - theScreen.vScrollPRect.left,
1554 			theScreen.vScrollPRect.bottom - theScreen.vScrollPRect.top);
1555 		SetCtlMax(theScreen.vScrollHandle,
1556 			theScreen.scrnXLRect.bottom - theScreen.picPRect.bottom);
1557 	}
1558 	RepositionScreen(0, 0);
1559 	ShowControl(theScreen.hScrollHandle);
1560 	ShowControl(theScreen.vScrollHandle);
1561 	ValidRect(&theScreen.hScrollPRect);
1562 	ValidRect(&theScreen.vScrollPRect);
1563 	return;
1564 }
1565 
DoGrow(whichWindow,cursorLoc)1566 static void DoGrow(whichWindow, cursorLoc)
1567 WindowPtr whichWindow;
1568 Point *cursorLoc;
1569 
1570 {
1571 	long newSize;
1572 	long oldWidth, oldHeight;
1573 	long newWidth, newHeight;
1574 
1575 	if (whichWindow == theScreen.window) {
1576 		oldWidth = theScreen.windowW;
1577 		oldHeight = theScreen.windowH;
1578 		newSize = GrowWindow(whichWindow, *cursorLoc, &theScreen.sizeLimitPRect);
1579 		if (newSize) {
1580 			newWidth = LoWord(newSize);
1581 			newHeight = HiWord(newSize);
1582 			HandlePreGrow(oldWidth, oldHeight, newWidth, newHeight);
1583 			SizeWindow(whichWindow, newWidth, newHeight, true);
1584 			SetScreenPortRects();
1585 			SetScreenDrawRects();
1586 			HandlePostGrow(oldWidth, oldHeight, newWidth, newHeight);
1587 		}
1588 
1589 	}
1590 
1591 	return;
1592 }
1593 
DoZoom(whichWindow,part)1594 static void DoZoom(whichWindow, part)
1595 WindowPtr whichWindow;
1596 long part;
1597 
1598 {
1599 	WStateData **zoomInfo;
1600 	Rect newSize;
1601 	long oldWidth, oldHeight;
1602 	long newWidth, newHeight;
1603 
1604 	if (whichWindow == theScreen.window) {
1605 		oldWidth = theScreen.windowW;
1606 		oldHeight = theScreen.windowH;
1607 		zoomInfo = (WStateData **) ((WindowPeek) whichWindow)->dataHandle;
1608 		if (part == inZoomIn)
1609 			newSize = ((*zoomInfo)->userState);
1610 		else
1611 			newSize = ((*zoomInfo)->stdState);
1612 		newWidth = newSize.right - newSize.left;
1613 		newHeight = newSize.bottom - newSize.top;
1614 		HandlePreGrow(oldWidth, oldHeight, newWidth, newHeight);
1615 		EraseRect(&theScreen.window->portRect);
1616 		ZoomWindow(whichWindow, part, false);
1617 		SetScreenPortRects();
1618 		SetScreenDrawRects();
1619 		HandlePostGrow(oldWidth, oldHeight, newWidth, newHeight);
1620 	}
1621 
1622 	return;
1623 }
1624 
ActOnScroll(theControl,partCode)1625 static pascal void ActOnScroll(theControl, partCode)
1626 ControlHandle theControl;
1627 short partCode;
1628 
1629 {
1630 	int delta;
1631 
1632 	if (theControl == theScreen.hScrollHandle) {
1633 
1634 		switch (partCode) {
1635 			case inUpButton:
1636 				delta = -theScreen.charPDims.h;
1637 				break;
1638 			case inDownButton:
1639 				delta = theScreen.charPDims.h;
1640 				break;
1641 			case inPageUp:
1642 				delta = theScreen.charPDims.h - theScreen.picPRect.right;
1643 				break;
1644 			case inPageDown:
1645 				delta = theScreen.picPRect.right - theScreen.charPDims.h;
1646 				break;
1647 			default:
1648 				delta = 0;
1649 				break;
1650 		}
1651 
1652 		if (delta)
1653 			if (RepositionScreen(delta, 0)) UpdateScreen();
1654 
1655 	}
1656 
1657 	if (theControl == theScreen.vScrollHandle) {
1658 
1659 		switch (partCode) {
1660 			case inUpButton:
1661 				delta = -theScreen.charPDims.v;
1662 				break;
1663 			case inDownButton:
1664 				delta = theScreen.charPDims.v;
1665 				break;
1666 			case inPageUp:
1667 				delta = theScreen.charPDims.v - theScreen.picPRect.bottom;
1668 				break;
1669 			case inPageDown:
1670 				delta = theScreen.picPRect.bottom - theScreen.charPDims.v;
1671 				break;
1672 			default:
1673 				delta = 0;
1674 				break;
1675 		}
1676 
1677 		if (delta)
1678 			if (RepositionScreen(0, delta)) UpdateScreen();
1679 
1680 	}
1681 
1682 	return;
1683 }
1684 
DoHScroll(cursorLoc,thePart)1685 static void DoHScroll(cursorLoc, thePart)
1686 Point *cursorLoc;
1687 long thePart;
1688 
1689 {
1690 	switch (thePart) {
1691 
1692 		case inUpButton:
1693 		case inDownButton:
1694 		case inPageUp:
1695 		case inPageDown:
1696 			TrackControl(theScreen.hScrollHandle, *cursorLoc, (ProcPtr) ActOnScroll);
1697 			break;
1698 
1699 		case inThumb:
1700 			TrackControl(theScreen.hScrollHandle, *cursorLoc, NULL);
1701 			break;
1702 
1703 	}
1704 
1705 	RepositionScreen(0, 0);
1706 
1707 	return;
1708 }
1709 
DoVScroll(cursorLoc,thePart)1710 static void DoVScroll(cursorLoc, thePart)
1711 Point *cursorLoc;
1712 long thePart;
1713 
1714 {
1715 	switch (thePart) {
1716 
1717 		case inUpButton:
1718 		case inDownButton:
1719 		case inPageUp:
1720 		case inPageDown:
1721 			TrackControl(theScreen.vScrollHandle, *cursorLoc, (ProcPtr) ActOnScroll);
1722 			break;
1723 
1724 		case inThumb:
1725 			TrackControl(theScreen.vScrollHandle, *cursorLoc, NULL);
1726 			break;
1727 
1728 	}
1729 
1730 	RepositionScreen(0, 0);
1731 
1732 	return;
1733 }
1734 
DoCharClick()1735 static void DoCharClick()
1736 
1737 {
1738 	int reversed;
1739 	short h, v;
1740 	char c, an, ar;
1741 	char modifiers;
1742 	Rect charCell;
1743 	Point mouse;
1744 	void GetScreenCharAttr(), XSetScreenCharAttr(), UpdateScreen();
1745 
1746 	if ( (theScreen.event.when > theScreen.mouseFlush)		&&
1747 			(theScreen.window == FrontWindow())				&&
1748 			(((WindowPeek) theScreen.window)->visible) ) {
1749 
1750 		if (GtoC(theScreen.event.where.h, theScreen.event.where.v, &h, &v)) {
1751 
1752 			modifiers = (char) ((theScreen.event.modifiers & 0xF0) >> 8);
1753 			modifiers |= maskModMouse;
1754 
1755 			charCell.left = charCell.right = h;
1756 			charCell.top = charCell.bottom = v;
1757 			charCell.right++;
1758 			charCell.bottom++;
1759 
1760 			charCell.left *= theScreen.charPDims.h;
1761 			charCell.top *= theScreen.charPDims.v;
1762 			charCell.right *= theScreen.charPDims.h;
1763 			charCell.bottom *= theScreen.charPDims.v;
1764 
1765 			OffsetRect(&charCell, -theScreen.origin.h, -theScreen.origin.v);
1766 
1767 			GetScreenCharAttr(&c, &an, h, v);
1768 			ar = (an & maskAttrFlags) | (MakeAttr(AttrBack(an), AttrFore(an)));
1769 
1770 			XSetScreenCharAttr(false, c, ar, h, v);
1771 			UpdateScreen();
1772 			reversed = true;
1773 
1774 			while (StillDown()) {
1775 				GetMouse(&mouse);
1776 				if (reversed) {
1777 					if (!PtInRect(mouse, &charCell)) {
1778 						XSetScreenCharAttr(false, c, an, h, v);
1779 						UpdateScreen();
1780 						reversed = false;
1781 					}
1782 				}
1783 				else {
1784 					if (PtInRect(mouse, &charCell)) {
1785 						XSetScreenCharAttr(false, c, ar, h, v);
1786 						UpdateScreen();
1787 						reversed = true;
1788 					}
1789 				}
1790 			}
1791 
1792 			if (reversed) {
1793 
1794 				XSetScreenCharAttr(false, c, an, h, v);
1795 				UpdateScreen();
1796 				reversed = false;
1797 
1798 				PushQueue(0, modifiers, 0, h, v);
1799 
1800 			}
1801 
1802 		}
1803 
1804 	}
1805 
1806 	return;
1807 }
1808 
DoContentClick(whichWindow,cursorLoc)1809 static void DoContentClick(whichWindow, cursorLoc)
1810 WindowPtr whichWindow;
1811 Point *cursorLoc;
1812 
1813 {
1814 	short thePart;
1815 	ControlHandle theControl;
1816 	Point localCursor;
1817 
1818 	if (whichWindow == theScreen.window) {
1819 		localCursor = *cursorLoc;
1820 		GlobalToLocal(&localCursor);
1821 		if (thePart = FindControl(localCursor, whichWindow, &theControl)) {
1822 			if (theControl == theScreen.hScrollHandle)
1823 				DoHScroll(&localCursor, thePart);
1824 			else if (theControl == theScreen.vScrollHandle)
1825 				DoVScroll(&localCursor, thePart);
1826 		}
1827 		else
1828 			if (theScreen.mouseFlag) DoCharClick();
1829 	}
1830 
1831 	return;
1832 }
1833 
DoMouseDown(cursorLoc)1834 static void DoMouseDown(cursorLoc)
1835 Point *cursorLoc;
1836 
1837 {
1838 	long part;
1839 	WindowPtr whichWindow;
1840 
1841 	switch (part = FindWindow(*cursorLoc, &whichWindow)) {
1842 
1843 		case inMenuBar:		DoMenuItem(MenuSelect(*cursorLoc));
1844 							break;
1845 
1846 		case inDrag:		DoDrag(whichWindow, cursorLoc);
1847 							break;
1848 
1849 		case inGrow:		DoGrow(whichWindow, cursorLoc);
1850 							break;
1851 
1852 		case inSysWindow:	SystemClick(&theScreen.event, whichWindow);
1853 							break;
1854 
1855 		case inContent:		if (whichWindow != FrontWindow())
1856 								SelectWindow(whichWindow);
1857 							else
1858 								DoContentClick(whichWindow, cursorLoc);
1859 							break;
1860 
1861 		case inZoomIn:
1862 		case inZoomOut:		if (whichWindow == theScreen.window)
1863 								if (TrackBox(whichWindow, *cursorLoc, part))
1864 									DoZoom(whichWindow, part);
1865 							break;
1866 
1867 		case inGoAway:		if (whichWindow == theScreen.window)
1868 								if (TrackGoAway(whichWindow, *cursorLoc)) {
1869 									if (theScreen.fileMenuProc != NULL)
1870 										(*theScreen.fileMenuProc)(closeBoxItem);
1871 									else
1872 										DoFileMenu(closeBoxItem);
1873 								}
1874 							break;
1875 
1876 	}
1877 
1878 	return;
1879 }
1880 
DoKeyDown(cmdFlag)1881 static void DoKeyDown(cmdFlag)
1882 int cmdFlag;
1883 
1884 {
1885 	char keycode, modifiers, ascii;
1886 	char upper;
1887 
1888 	if ( (theScreen.event.when > theScreen.keyFlush)		&&
1889 			(theScreen.window == FrontWindow())		&&
1890 			(((WindowPeek) theScreen.window)->visible) ) {
1891 
1892 		ObscureCursor();
1893 
1894 		keycode = (char) ((theScreen.event.message & keyCodeMask) >> 8);
1895 
1896 		modifiers = (char) ((theScreen.event.modifiers & 0xFF00) >> 8);
1897 		modifiers &= ~maskModMouse;
1898 
1899 		ascii = (char) (theScreen.event.message & charCodeMask);
1900 		if (theScreen.escMapFlag) {
1901 			if (ascii == BACKQUOTE) ascii = ESC;
1902 		}
1903 		if (cmdFlag) {
1904 			upper = ascii;
1905 			if ( (upper >= 'a') && (upper <= 'z') )
1906 				upper = 'A' + (upper - 'a');
1907 			if ( (upper >= '@') && (upper <= '_') )
1908 				ascii = upper - '@';
1909 		}
1910 
1911 		PushQueue(keycode, modifiers, ascii, 0, 0);
1912 
1913 	}
1914 
1915 	return;
1916 }
1917 
DoUpdate(whichWindow)1918 static void DoUpdate(whichWindow)
1919 WindowPtr whichWindow;
1920 
1921 {
1922 	if (whichWindow == theScreen.window) {
1923 		UpdateScreen();
1924 	}
1925 
1926 	return;
1927 }
1928 
DoActivate(whichWindow,activated)1929 static void DoActivate(whichWindow, activated)
1930 WindowPtr whichWindow;
1931 Boolean activated;
1932 
1933 {
1934 	MenuHandle menu;
1935 
1936 	menu = GetMHandle(theScreen.cmdKeyFlag ? editID1 : editID2);
1937 
1938 	if (whichWindow == theScreen.window) {
1939 
1940 		if (activated) {
1941 			DisableItem(menu, undoItem);
1942 			DisableItem(menu, cutItem);
1943 			DisableItem(menu, copyItem);
1944 			DisableItem(menu, pasteItem);
1945 			DisableItem(menu, clearItem);
1946 			ShowControl(theScreen.vScrollHandle);
1947 			ShowControl(theScreen.hScrollHandle);
1948 			DrawGrowIcon(whichWindow);
1949 		}
1950 		else {
1951 			EnableItem(menu, undoItem);
1952 			EnableItem(menu, cutItem);
1953 			EnableItem(menu, copyItem);
1954 			EnableItem(menu, pasteItem);
1955 			EnableItem(menu, clearItem);
1956 			HideControl(theScreen.vScrollHandle);
1957 			HideControl(theScreen.hScrollHandle);
1958 			DrawGrowIcon(whichWindow);
1959 		}
1960 	}
1961 
1962 	return;
1963 }
1964 
InvalScreenRect(d,r)1965 static void InvalScreenRect(d, r)
1966 int d;
1967 Rect *r;
1968 
1969 {
1970 	register long v;
1971 	register short *left, *right;
1972 	short rl, rt, rr, rb;
1973 
1974 	if (d) {
1975 
1976 		rl = r->left;
1977 		rt = r->top;
1978 		rr = r->right;
1979 		rb = r->bottom;
1980 
1981 		left = *theScreen.updLeft + rt;
1982 		right = *theScreen.updRight + rt;
1983 
1984 		for (v = rt; v < rb; v++, left++, right++) {
1985 			if (rl < *left) *left = rl;
1986 			if (rr > *right) *right = rr;
1987 		}
1988 
1989 	}
1990 
1991 	else {
1992 
1993 		r->left *= theScreen.charPDims.h;
1994 		r->right *= theScreen.charPDims.h;
1995 		r->top *= theScreen.charPDims.v;
1996 		r->bottom *= theScreen.charPDims.v;
1997 
1998 		SetOrigin(theScreen.origin.h, theScreen.origin.v);
1999 		InvalRect(r);
2000 		SetOrigin(0, 0);
2001 
2002 	}
2003 
2004 	return;
2005 }
2006 
InvalCursor(d)2007 static void InvalCursor(d)
2008 int d;
2009 
2010 {
2011 	Rect curs;
2012 
2013 	curs.left = curs.right = theScreen.cursor.h;
2014 	curs.top = curs.bottom = theScreen.cursor.v;
2015 	curs.right += 1;
2016 	curs.bottom += 1;
2017 
2018 	if (d)
2019 		InvalScreenRect(d, &curs);
2020 
2021 	else {
2022 
2023 		curs.left *= theScreen.charPDims.h;
2024 		curs.right *= theScreen.charPDims.h;
2025 		curs.top = curs.bottom = curs.bottom * theScreen.charPDims.v;
2026 		curs.top -= theScreen.cursorLines;
2027 
2028 		SetOrigin(theScreen.origin.h, theScreen.origin.v);
2029 		InvalRect(&curs);
2030 		SetOrigin(0, 0);
2031 
2032 	}
2033 
2034 	return;
2035 }
2036 
XSetScreenChar(d,c,h,v)2037 void XSetScreenChar(d, c, h, v)
2038 int d;
2039 char c;
2040 long h, v;
2041 
2042 {
2043     long loc;
2044     Rect area;
2045 	Point pos;
2046 
2047 	pos.h = h;
2048 	pos.v = v;
2049 
2050     if (PtInRect(pos, &theScreen.scrnCRect)) {
2051 
2052 		loc = v * theScreen.scrnCDims.h + h;
2053 		(*theScreen.chars)[loc] = c;
2054 
2055 		area.left = area.right = h;
2056 		area.right += 1;
2057 		area.top = area.bottom = v;
2058 		area.bottom += 1;
2059 
2060 		InvalScreenRect(d, &area);
2061 
2062     }
2063 
2064     return;
2065 }
2066 
XSetScreenBuffer(d,c,row,bounds,h,v)2067 void XSetScreenBuffer(d, c, row, bounds, h, v)
2068 int d;
2069 char *c;
2070 long row;
2071 Rect *bounds;
2072 long h, v;
2073 
2074 {
2075     long i;
2076     long wid;
2077     long srcLoc, dstLoc;
2078     char *srcC, *dstC;
2079     Rect temp, area;
2080 
2081     temp.right = temp.left = h;
2082     temp.right += bounds->right - bounds->left;
2083     temp.bottom = temp.top = v;
2084     temp.bottom += bounds->bottom - bounds->top;
2085 
2086     if (SectRect(&temp, &theScreen.scrnCRect, &area)) {
2087 
2088 		srcLoc = (area.top + bounds->top - v) * row +
2089 			 (area.left + bounds->left - h);
2090 		dstLoc = area.top * theScreen.scrnCDims.h + area.left;
2091 
2092 		srcC = c + srcLoc;
2093 		dstC = *theScreen.chars + dstLoc;
2094 
2095 		wid = area.right - area.left;
2096 
2097 		if ( (wid == row) && (wid == theScreen.scrnCDims.h) ) {
2098 			wid *= (area.bottom - area.top);
2099 			memcpy(dstC, srcC, wid);
2100 		}
2101 
2102 		else {
2103 
2104 			for (i = area.top; i < area.bottom; i++) {
2105 				memcpy(dstC, srcC, wid);
2106 				srcC += row;
2107 				dstC += theScreen.scrnCDims.h;
2108 			}
2109 
2110 		}
2111 
2112 		InvalScreenRect(d, &area);
2113 
2114     }
2115 
2116     return;
2117 }
2118 
XSetScreenString(d,s,h,v)2119 void XSetScreenString(d, s, h, v)
2120 int d;
2121 char *s;
2122 long h, v;
2123 
2124 {
2125     Rect bounds;
2126 
2127     bounds.left = 0;
2128     bounds.right = strlen(s);
2129     bounds.top = 0;
2130     bounds.bottom = 1;
2131 
2132     XSetScreenBuffer(d, s, bounds.right, &bounds, h, v);
2133 
2134     return;
2135 }
2136 
XSetScreenCharAttr(d,c,a,h,v)2137 void XSetScreenCharAttr(d, c, a, h, v)
2138 int d;
2139 char c;
2140 char a;
2141 long h, v;
2142 
2143 {
2144     long loc;
2145     Rect area;
2146 	Point pos;
2147 
2148 	pos.h = h;
2149 	pos.v = v;
2150 
2151     if (PtInRect(pos, &theScreen.scrnCRect)) {
2152 
2153 		loc = v * theScreen.scrnCDims.h + h;
2154 		(*theScreen.chars)[loc] = c;
2155 		(*theScreen.attrs)[loc] = a;
2156 
2157 		area.left = area.right = h;
2158 		area.right += 1;
2159 		area.top = area.bottom = v;
2160 		area.bottom += 1;
2161 
2162 		InvalScreenRect(d, &area);
2163 
2164     }
2165 
2166     return;
2167 }
2168 
XSetScreenBufferAttr(d,c,a,row,bounds,h,v)2169 void XSetScreenBufferAttr(d, c, a, row, bounds, h, v)
2170 int d;
2171 char *c;
2172 char a;
2173 long row;
2174 Rect *bounds;
2175 long h, v;
2176 
2177 {
2178     long i;
2179     long wid;
2180     long srcLoc, dstLoc;
2181     char *srcC, *dstC;
2182     char *dstA;
2183     Rect temp, area;
2184 
2185     temp.right = temp.left = h;
2186     temp.right += bounds->right - bounds->left;
2187     temp.bottom = temp.top = v;
2188     temp.bottom += bounds->bottom - bounds->top;
2189 
2190     if (SectRect(&temp, &theScreen.scrnCRect, &area)) {
2191 
2192 		srcLoc = (area.top + bounds->top - v) * row +
2193 			 (area.left + bounds->left - h);
2194 		dstLoc = area.top * theScreen.scrnCDims.h + area.left;
2195 
2196 		srcC = c + srcLoc;
2197 		dstC = *theScreen.chars + dstLoc;
2198 
2199 		dstA = *theScreen.attrs + dstLoc;
2200 
2201 		wid = area.right - area.left;
2202 
2203 		if ( (wid == row) && (wid == theScreen.scrnCDims.h) ) {
2204 			wid *= (area.bottom - area.top);
2205 			memcpy(dstC, srcC, wid);
2206 			memset(dstA, a, wid);
2207 		}
2208 
2209 		else {
2210 
2211 			for (i = area.top; i < area.bottom; i++) {
2212 				memcpy(dstC, srcC, wid);
2213 				memset(dstA, a, wid);
2214 				srcC += row;
2215 				dstC += theScreen.scrnCDims.h;
2216 				dstA += theScreen.scrnCDims.h;
2217 			}
2218 
2219 		}
2220 
2221 		InvalScreenRect(d, &area);
2222 
2223     }
2224 
2225     return;
2226 }
2227 
XSetScreenStringAttr(d,s,a,h,v)2228 void XSetScreenStringAttr(d, s, a, h, v)
2229 int d;
2230 char *s;
2231 char a;
2232 long h, v;
2233 
2234 {
2235     Rect bounds;
2236 
2237     bounds.left = 0;
2238     bounds.right = strlen(s);
2239     bounds.top = 0;
2240     bounds.bottom = 1;
2241 
2242     XSetScreenBufferAttr(d, s, a, bounds.right, &bounds, h, v);
2243 
2244     return;
2245 }
2246 
XSetScreenImage(d,c,a,row,bounds,h,v)2247 void XSetScreenImage(d, c, a, row, bounds, h, v)
2248 int d;
2249 char *c;
2250 char *a;
2251 long row;
2252 Rect *bounds;
2253 long h, v;
2254 
2255 {
2256     long i;
2257     long wid;
2258     long srcLoc, dstLoc;
2259     char *srcC, *dstC;
2260     char *srcA, *dstA;
2261     Rect temp, area;
2262 
2263     temp.right = temp.left = h;
2264     temp.right += bounds->right - bounds->left;
2265     temp.bottom = temp.top = v;
2266     temp.bottom += bounds->bottom - bounds->top;
2267 
2268     if (SectRect(&temp, &theScreen.scrnCRect, &area)) {
2269 
2270 		srcLoc = (area.top + bounds->top - v) * row +
2271 			 (area.left + bounds->left - h);
2272 		dstLoc = area.top * theScreen.scrnCDims.h + area.left;
2273 
2274 		srcC = c + srcLoc;
2275 		dstC = *theScreen.chars + dstLoc;
2276 
2277 		srcA = a + srcLoc;
2278 		dstA = *theScreen.attrs + dstLoc;
2279 
2280 		wid = area.right - area.left;
2281 
2282 		if ( (wid == row) && (wid == theScreen.scrnCDims.h) ) {
2283 			wid *= (area.bottom - area.top);
2284 			memcpy(dstC, srcC, wid);
2285 			memcpy(dstA, srcA, wid);
2286 		}
2287 
2288 		else {
2289 
2290 			for (i = area.top; i < area.bottom; i++) {
2291 				memcpy(dstC, srcC, wid);
2292 				memcpy(dstA, srcA, wid);
2293 				srcC += row;
2294 				srcA += row;
2295 				dstC += theScreen.scrnCDims.h;
2296 				dstA += theScreen.scrnCDims.h;
2297 			}
2298 
2299 		}
2300 
2301 		InvalScreenRect(d, &area);
2302 
2303     }
2304 
2305     return;
2306 }
2307 
XWriteScreenChar(d,c)2308 void XWriteScreenChar(d, c)
2309 int d;
2310 char c;
2311 
2312 {
2313 	InvalCursor(d);
2314 
2315     XSetScreenChar(d, c, theScreen.cursor.h, theScreen.cursor.v);
2316     theScreen.cursor.h++;
2317 
2318 	InvalCursor(d);
2319 
2320     return;
2321 }
2322 
XWriteScreenBuffer(d,c,row,bounds)2323 void XWriteScreenBuffer(d, c, row, bounds)
2324 int d;
2325 char *c;
2326 long row;
2327 Rect *bounds;
2328 
2329 {
2330     XSetScreenBuffer(d, c, row, bounds, theScreen.cursor.h,
2331 		     theScreen.cursor.v);
2332     theScreen.cursor.h += bounds->right - bounds->left;
2333     theScreen.cursor.v += bounds->bottom - bounds->top;
2334 
2335 	InvalCursor(d);
2336 
2337     return;
2338 }
2339 
XWriteScreenString(d,s)2340 void XWriteScreenString(d, s)
2341 int d;
2342 char *s;
2343 
2344 {
2345     XSetScreenString(d, s, theScreen.cursor.h, theScreen.cursor.v);
2346     theScreen.cursor.h += strlen(s);
2347 
2348 	InvalCursor(d);
2349 
2350     return;
2351 }
2352 
XWriteScreenCharAttr(d,c,a)2353 void XWriteScreenCharAttr(d, c, a)
2354 int d;
2355 char c;
2356 char a;
2357 
2358 {
2359     XSetScreenCharAttr(d, c, a, theScreen.cursor.h, theScreen.cursor.v);
2360     theScreen.cursor.h++;
2361 
2362 	InvalCursor(d);
2363 
2364     return;
2365 }
2366 
XWriteScreenBufferAttr(d,c,a,row,bounds)2367 void XWriteScreenBufferAttr(d, c, a, row, bounds)
2368 int d;
2369 char *c;
2370 char a;
2371 long row;
2372 Rect *bounds;
2373 
2374 {
2375     XSetScreenBufferAttr(d, c, a, row, bounds, theScreen.cursor.h,
2376 			 theScreen.cursor.v);
2377     theScreen.cursor.h += bounds->right - bounds->left;
2378     theScreen.cursor.v += bounds->bottom - bounds->top;
2379 
2380 	InvalCursor(d);
2381 
2382     return;
2383 }
2384 
XWriteScreenStringAttr(d,s,a)2385 void XWriteScreenStringAttr(d, s, a)
2386 int d;
2387 char *s;
2388 char a;
2389 
2390 {
2391     XSetScreenStringAttr(d, s, a, theScreen.cursor.h, theScreen.cursor.v);
2392     theScreen.cursor.h += strlen(s);
2393 
2394 	InvalCursor(d);
2395 
2396     return;
2397 }
2398 
XWriteScreenImage(d,c,a,row,bounds)2399 void XWriteScreenImage(d, c, a, row, bounds)
2400 int d;
2401 char *c;
2402 char *a;
2403 long row;
2404 Rect *bounds;
2405 
2406 {
2407     XSetScreenImage(d, c, a, row, bounds, theScreen.cursor.h,
2408 		    theScreen.cursor.v);
2409     theScreen.cursor.h += bounds->right - bounds->left;
2410     theScreen.cursor.v += bounds->bottom - bounds->top;
2411 
2412 	InvalCursor(d);
2413 
2414     return;
2415 }
2416 
XFillScreen(d,c,a,bounds)2417 void XFillScreen(d, c, a, bounds)
2418 int d;
2419 char c;
2420 char a;
2421 Rect *bounds;
2422 
2423 {
2424     long i;
2425     long wid;
2426     long dstLoc;
2427     char *dstC;
2428     char *dstA;
2429     Rect area;
2430 
2431     if (SectRect(bounds, &theScreen.scrnCRect, &area)) {
2432 
2433 		dstLoc = area.top * theScreen.scrnCDims.h + area.left;
2434 
2435 		dstC = *theScreen.chars + dstLoc;
2436 
2437 		dstA = *theScreen.attrs + dstLoc;
2438 
2439 		wid = area.right - area.left;
2440 
2441 		if (wid == theScreen.scrnCDims.h) {
2442 			wid *= (area.bottom - area.top);
2443 			memset(dstC, c, wid);
2444 			memset(dstA, a, wid);
2445 		}
2446 
2447 		else {
2448 
2449 			for (i = area.top; i < area.bottom; i++) {
2450 				memset(dstC, c, wid);
2451 				memset(dstA, a, wid);
2452 				dstC += theScreen.scrnCDims.h;
2453 				dstA += theScreen.scrnCDims.h;
2454 			}
2455 
2456 		}
2457 
2458 		InvalScreenRect(d, &area);
2459 
2460     }
2461 
2462     return;
2463 }
2464 
XEraseScreen(d,bounds)2465 void XEraseScreen(d, bounds)
2466 int d;
2467 Rect *bounds;
2468 
2469 {
2470     XFillScreen(d, ' ', attrNormal, bounds);
2471     return;
2472 }
2473 
ScrollScreenPositive(area,offset,factor)2474 static void ScrollScreenPositive(area, offset, factor)
2475 Rect *area;
2476 long offset;
2477 short factor;
2478 
2479 {
2480     register short i, j;
2481     short loc;		/* Index of initial destination.  */
2482 	short nxt;		/* Amount to skip going from one row to the next.  */
2483     register char *srcc, *dstc;
2484     register char *srca, *dsta;
2485 
2486     loc = (area->bottom - 1) * theScreen.scrnCDims.h + area->right - 1;
2487 
2488     dstc = *theScreen.chars + loc;
2489     srcc = dstc - offset * factor;
2490 
2491     dsta = *theScreen.attrs + loc;
2492     srca = dsta - offset * factor;
2493 
2494     nxt = theScreen.scrnCDims.h - (area->right - area->left);
2495 
2496     for (j = area->bottom; j > area->top; j--) {
2497 		for (i = area->right; i > area->left; i--) {
2498 			*dstc-- = *srcc--;
2499 			*dsta-- = *srca--;
2500 		}
2501 		srcc -= nxt;
2502 		dstc -= nxt;
2503 		srca -= nxt;
2504 		dsta -= nxt;
2505     }
2506 
2507     return;
2508 }
2509 
ScrollScreenNegative(area,offset,factor)2510 static void ScrollScreenNegative(area, offset, factor)
2511 Rect *area;
2512 long offset;
2513 short factor;
2514 
2515 {
2516     register short i, j;
2517     short loc;
2518 	short nxt;
2519     register char *srcc, *dstc;
2520     register char *srca, *dsta;
2521 
2522     loc = area->top * theScreen.scrnCDims.h + area->left;
2523 
2524     dstc = *theScreen.chars + loc;
2525     srcc = dstc - offset * factor;	/* Offset is negative!  */
2526 
2527     dsta = *theScreen.attrs + loc;
2528     srca = dsta - offset * factor;
2529 
2530     nxt = theScreen.scrnCDims.h - (area->right - area->left);
2531 
2532     for (j = area->top; j < area->bottom; j++) {
2533 		for (i = area->left; i < area->right; i++) {
2534 			*dstc++ = *srcc++;
2535 			*dsta++ = *srca++;
2536 		}
2537 		srcc += nxt;
2538 		dstc += nxt;
2539 		srca += nxt;
2540 		dsta += nxt;
2541     }
2542 
2543     return;
2544 }
2545 
XScrollScreen(d,dh,dv,bounds,attr)2546 void XScrollScreen(d, dh, dv, bounds, attr)
2547 int d;
2548 long dh, dv;
2549 Rect *bounds;
2550 char attr;
2551 
2552 {
2553     long wid, dep;
2554     Rect area, clear;
2555 
2556     if (!dh && !dv) return;
2557 
2558     if (SectRect(bounds, &theScreen.scrnCRect, &area)) {
2559 
2560 		wid = area.right - area.left;
2561 		dep = area.bottom - area.top;
2562 
2563 		if ( (ABS(dh) >= wid) || (ABS(dv) >= dep) )
2564 
2565 			XFillScreen(d, ' ', attr, &area);
2566 
2567 		else {
2568 
2569 			if (dv > 0) {
2570 				clear = area;
2571 				clear.bottom = area.top += dv;
2572 				ScrollScreenPositive(&area, dv, (short)theScreen.scrnCDims.h);
2573 				XFillScreen(d, ' ', attr, &clear);
2574 			}
2575 
2576 			else if (dv < 0) {
2577 				clear = area;
2578 				clear.top = area.bottom += dv;
2579 				ScrollScreenNegative(&area, dv, (short)theScreen.scrnCDims.h);
2580 				XFillScreen(d, ' ', attr, &clear);
2581 			}
2582 
2583 			if (dh > 0) {
2584 				clear = area;
2585 				clear.right = area.left += dh;
2586 				ScrollScreenPositive(&area, dh, (short)1);
2587 				XFillScreen(d, ' ', attr, &clear);
2588 			}
2589 
2590 			else if (dh < 0) {
2591 				clear = area;
2592 				clear.left = area.right += dh;
2593 				ScrollScreenNegative(&area, dh, (short)1);
2594 				XFillScreen(d, ' ', attr, &clear);
2595 			}
2596 
2597 			InvalScreenRect(d, &area);
2598 
2599 		}
2600 
2601     }
2602 
2603     return;
2604 }
2605 
GetScreenCharAttr(c,a,h,v)2606 void GetScreenCharAttr(c, a, h, v)
2607 char *c;
2608 char *a;
2609 long h, v;
2610 
2611 {
2612     long loc;
2613 	Point pos;
2614 
2615 	pos.h = h;
2616 	pos.v = v;
2617 
2618     if (PtInRect(pos, &theScreen.scrnCRect)) {
2619 
2620 		loc = v * theScreen.scrnCDims.h + h;
2621 		*c = (*theScreen.chars)[loc];
2622 		*a = (*theScreen.attrs)[loc];
2623 
2624     }
2625 
2626     return;
2627 }
2628 
GetScreenImage(c,a,row,bounds,h,v)2629 void GetScreenImage(c, a, row, bounds, h, v)
2630 char *c;
2631 char *a;
2632 long row;
2633 Rect *bounds;
2634 long h, v;
2635 
2636 {
2637     long i;
2638     long wid;
2639     long srcLoc, dstLoc;
2640     char *srcC, *dstC;
2641     char *srcA, *dstA;
2642     Rect temp, area;
2643 
2644     temp.right = temp.left = h;
2645     temp.right += bounds->right - bounds->left;
2646     temp.bottom = temp.top = v;
2647     temp.bottom += bounds->bottom - bounds->top;
2648 
2649     if (SectRect(&temp, &theScreen.scrnCRect, &area)) {
2650 
2651 		dstLoc = (area.top + bounds->top - v) * row +
2652 			 (area.left + bounds->left - h);
2653 		srcLoc = area.top * theScreen.scrnCDims.h + area.left;
2654 
2655 		dstC = c + dstLoc;
2656 		srcC = *theScreen.chars + srcLoc;
2657 
2658 		dstA = a + dstLoc;
2659 		srcA = *theScreen.attrs + srcLoc;
2660 
2661 		wid = area.right - area.left;
2662 
2663 		if ( (wid == row) && (wid == theScreen.scrnCDims.h) ) {
2664 			wid *= (area.bottom - area.top);
2665 			memcpy(dstC, srcC, wid);
2666 			memcpy(dstA, srcA, wid);
2667 		}
2668 
2669 		else {
2670 
2671 			for (i = area.top; i < area.bottom; i++) {
2672 				memcpy(dstC, srcC, wid);
2673 				memcpy(dstA, srcA, wid);
2674 				dstC += row;
2675 				dstA += row;
2676 				srcC += theScreen.scrnCDims.h;
2677 				srcA += theScreen.scrnCDims.h;
2678 			}
2679 
2680 		}
2681 
2682     }
2683 
2684     return;
2685 }
2686 
XMoveScreenCursor(d,h,v)2687 void XMoveScreenCursor(d, h, v)
2688 int d;
2689 long h, v;
2690 
2691 {
2692 	InvalCursor(d);
2693 
2694     theScreen.cursor.h += h;
2695     theScreen.cursor.v += v;
2696 
2697 	InvalCursor(d);
2698 
2699     return;
2700 }
2701 
XSetScreenCursor(d,h,v)2702 void XSetScreenCursor(d, h, v)
2703 int d;
2704 long h, v;
2705 
2706 {
2707 	InvalCursor(d);
2708 
2709     theScreen.cursor.h = h;
2710     theScreen.cursor.v = v;
2711 
2712 	InvalCursor(d);
2713 
2714     return;
2715 }
2716 
GetScreenCursor(h,v)2717 void GetScreenCursor(h, v)
2718 long *h, *v;
2719 {
2720     *h = theScreen.cursor.h;
2721     *v = theScreen.cursor.v;
2722     return;
2723 }
2724 
CheckCursorStatus()2725 static long CheckCursorStatus()
2726 
2727 {
2728 	long oldStatus;
2729 	long changed;
2730 
2731 	oldStatus = theScreen.cursorStatus;
2732 
2733 	if (theScreen.cursorLevel <= 0)
2734 		theScreen.cursorStatus = 0;
2735 	else if (!theScreen.cursorBlink)
2736 		theScreen.cursorStatus = 1;
2737 	else if (theScreen.cursorChangeTick <= TickCount())
2738 		theScreen.cursorStatus = !oldStatus;
2739 
2740 	changed = theScreen.cursorStatus != oldStatus;
2741 
2742 	if (changed) {
2743 		theScreen.cursorChangeTick = TickCount() + theScreen.cursorBlink;
2744 		InvalCursor(0);
2745 	}
2746 
2747 	return(changed);
2748 }
2749 
InvalDelayed()2750 static void InvalDelayed()
2751 
2752 {
2753 	long v;
2754 	short *left, *right;
2755 	Rect inval;
2756 
2757 	v = 0;
2758 	left = *theScreen.updLeft;
2759 	right = *theScreen.updRight;
2760 
2761 	while (v < theScreen.scrnCDims.v) {
2762 
2763 		if (!*right) {
2764 
2765 			v++;
2766 			left++;
2767 			right++;
2768 
2769 		}
2770 
2771 		else {
2772 
2773 			inval.top = v;
2774 			inval.left = *left;
2775 			inval.right = *right;
2776 
2777 			do {
2778 				v++;
2779 				*left++ = theScreen.scrnCDims.h;
2780 				*right++ = 0;
2781 			} while ( (v < theScreen.scrnCDims.v) &&
2782 					  (*left == inval.left)		 &&
2783 					  (*right == inval.right)		);
2784 
2785 			inval.bottom = v;
2786 
2787 			InvalScreenRect(0, &inval);
2788 
2789 			left = *theScreen.updLeft + v;
2790 			right = *theScreen.updRight + v;
2791 
2792 		}
2793 
2794 	}
2795 
2796 	return;
2797 
2798 }
2799 
UpdateScreenLine(area,c,a,len)2800 static void UpdateScreenLine(area, c, a, len)
2801 Rect *area;
2802 char *c;
2803 char *a;
2804 long len;
2805 
2806 {
2807     long count;
2808     char attr;
2809     char *last, *prev;
2810 	short face;
2811 	Rect temp;
2812 
2813 	temp = *area;
2814 
2815     last = a + len;
2816 
2817     while (a < last) {
2818 
2819 		attr = *a;
2820 
2821 		prev = a;
2822 		while ( (a < last) && (*a == attr) ) a++;
2823 		count = a - prev;
2824 
2825 		temp.right = temp.left + count * theScreen.charPDims.h;
2826 
2827 		face = normal;
2828 		if (attr & attrUnderlined) face |= underline;
2829 		if (attr & attrItalicized) face |= italic;
2830 		TextFace(face);
2831 
2832 		if (theScreen.colorFlag) {
2833 			ForeColor(colors[AttrFore(attr)]);
2834 			BackColor(colors[AttrBack(attr)]);
2835 		}
2836 		else {
2837 			ForeColor(
2838 				colors[
2839 					(AttrFore(attr) == attrColorBack) ?
2840 						theScreen.colorStdBack : theScreen.colorStdFore]);
2841 			BackColor(
2842 				colors[
2843 					(AttrBack(attr) == attrColorBack) ?
2844 						theScreen.colorStdBack : theScreen.colorStdFore]);
2845 		}
2846 
2847 		EraseRect(&temp);
2848 
2849 		DrawText(c, 0, count);
2850 
2851 		temp.left = temp.right;
2852 
2853 		c += count;
2854 
2855     }
2856 
2857     return;
2858 }
2859 
UpdateScreen()2860 void UpdateScreen()
2861 
2862 {
2863     long j;
2864 	long top, dep, left, wid;
2865     Rect clear, area, curs;
2866 	RgnHandle vis;
2867     char *c, *a;
2868 	long cursorLoc;
2869 
2870 	InvalDelayed();
2871 
2872     BeginUpdate(theScreen.window);
2873 
2874 	SetOrigin(theScreen.origin.h, theScreen.origin.v);
2875 
2876 	ClipRect(&theScreen.picLRect);
2877 
2878 	if (!theScreen.colorFlag)
2879 		BackColor(colors[theScreen.colorStdBack]);
2880 
2881 	if (theScreen.picLRect.top < theScreen.scrnLRect.top) {
2882 		clear = theScreen.picLRect;
2883 		clear.bottom = theScreen.scrnLRect.top;
2884 		EraseRect(&clear);
2885 	}
2886 
2887 	if (theScreen.picLRect.left < theScreen.scrnLRect.left) {
2888 		clear = theScreen.picLRect;
2889 		clear.right = theScreen.scrnLRect.left;
2890 		EraseRect(&clear);
2891 	}
2892 
2893 	if (theScreen.picLRect.right > theScreen.scrnLRect.right) {
2894 		clear = theScreen.picLRect;
2895 		clear.left = theScreen.scrnLRect.right;
2896 		EraseRect(&clear);
2897 	}
2898 
2899 	if (theScreen.picLRect.bottom > theScreen.scrnLRect.bottom) {
2900 		clear = theScreen.picLRect;
2901 		clear.top = theScreen.scrnLRect.bottom;
2902 		EraseRect(&clear);
2903 	}
2904 
2905 	ClipRect(&theScreen.drawLRect);
2906 
2907 	vis = theScreen.window->visRgn;
2908 
2909 	top = theScreen.drawXCRect.top;
2910 	dep = theScreen.drawXCRect.bottom - top;
2911 
2912 	left = theScreen.drawXCRect.left;
2913 	wid = theScreen.drawXCRect.right - left;
2914 
2915 	HLock((Handle) theScreen.chars);
2916 	HLock((Handle) theScreen.attrs);
2917 
2918     c = *theScreen.chars + top * theScreen.scrnCDims.h + left;
2919     a = *theScreen.attrs + top * theScreen.scrnCDims.h + left;
2920 
2921 	area = theScreen.drawXLRect;
2922 	area.bottom = area.top + theScreen.charPDims.v;
2923 
2924     for (j = 0; j < dep; j++) {
2925 
2926 		if (RectInRgn(&area, vis)) {
2927 			MoveTo(area.left, area.top + theScreen.info.ascent);
2928 			UpdateScreenLine(&area, c, a, wid);
2929 		}
2930 
2931 		area.top = area.bottom;
2932 		area.bottom += theScreen.charPDims.v;
2933 
2934 		c += theScreen.scrnCDims.h;
2935 		a += theScreen.scrnCDims.h;
2936 
2937     }
2938 
2939 	HUnlock((Handle) theScreen.chars);
2940 	HUnlock((Handle) theScreen.attrs);
2941 
2942 	if (theScreen.cursorStatus) {
2943 		curs.left = curs.right = theScreen.cursor.h * theScreen.charPDims.h;
2944 		curs.right += theScreen.charPDims.h;
2945 		curs.bottom = curs.top = (theScreen.cursor.v + 1) * theScreen.charPDims.v;
2946 		if (theScreen.cursorLines <= theScreen.charPDims.v)
2947 			curs.top -= theScreen.cursorLines;
2948 		else
2949 			curs.top -= theScreen.charPDims.v;
2950 		if (theScreen.colorFlag)
2951 			BackColor(colors[theScreen.cursorColor]);
2952 		else {
2953 			cursorLoc = theScreen.cursor.v * theScreen.scrnCDims.h
2954 			  + theScreen.cursor.h;
2955 			BackColor(
2956 				colors[
2957 					(AttrFore((*theScreen.attrs)[cursorLoc]) == attrColorBack) ?
2958 						theScreen.colorStdBack : theScreen.colorStdFore]);
2959 		}
2960 		EraseRect(&curs);
2961 	}
2962 
2963 	SetOrigin(0, 0);
2964 
2965 	TextFace(normal);
2966 
2967 	ForeColor(blackColor);
2968 	BackColor(whiteColor);
2969 
2970     MoveTo(0, 0);
2971 
2972 	ClipRect(&theScreen.window->portRect);
2973 
2974 	UpdtControl(theScreen.window, theScreen.window->visRgn);
2975 	DrawGrowIcon(theScreen.window);
2976 
2977     EndUpdate(theScreen.window);
2978 
2979     return;
2980 }
2981 
IdleScreenMgr()2982 void IdleScreenMgr()
2983 
2984 {
2985 	long more;
2986 	short mask;
2987 
2988 	do {
2989 
2990 		mask = everyEvent;
2991 		if (theScreen.waitFlag) {
2992 			mask -= mDownMask;
2993 			mask -= keyDownMask;
2994 			mask -= autoKeyMask;
2995 		}
2996 
2997 		if ( (!theScreen.backgrounding) && (theScreen.window == FrontWindow()) )
2998 			CheckCursorStatus();
2999 
3000 		if (theScreen.wneImplemented) {
3001 			more = WaitNextEvent(mask, &theScreen.event, 0, NULL);
3002 		}
3003 		else {
3004 			SystemTask();
3005 			more = GetNextEvent(mask, &theScreen.event);
3006 		}
3007 
3008 		if (more)
3009 			switch (theScreen.event.what) {
3010 
3011 				case mouseDown:		DoMouseDown(&theScreen.event.where);
3012 									break;
3013 
3014 				case autoKey:
3015 				case keyDown:		if (theScreen.event.modifiers & cmdKey) {
3016 										if (theScreen.cmdKeyFlag) {
3017 											if (theScreen.event.what != autoKey)
3018 												DoMenuItem(MenuKey(theScreen.event.message & charCodeMask));
3019 										}
3020 										else
3021 											DoKeyDown(true);
3022 									}
3023 									else
3024 										DoKeyDown(false);
3025 									break;
3026 
3027 				case updateEvt:		DoUpdate((WindowPtr) theScreen.event.message);
3028 									break;
3029 
3030 				case activateEvt:	DoActivate((WindowPtr) theScreen.event.message,
3031 											   theScreen.event.modifiers & activeFlag);
3032 									break;
3033 
3034 				case osEvent:		if ((theScreen.event.message >> 24)
3035 							    == suspendResumeMessage) {
3036 										if (theScreen.event.message & resumeMask) {
3037 											theScreen.backgrounding = false;
3038 											DoActivate((WindowPtr) FrontWindow(), true);
3039 										}
3040 										else {
3041 											theScreen.backgrounding = true;
3042 											DoActivate((WindowPtr) FrontWindow(), false);
3043 										}
3044 									}
3045 
3046 			}
3047 
3048 	} while (more);
3049 
3050 	return;
3051 }
3052 
FlushScreenKeys()3053 void FlushScreenKeys()
3054 
3055 {
3056 	theScreen.keyFlush = theScreen.mouseFlush = TickCount();
3057 	FlushQueue();
3058 	return;
3059 }
3060 
CountScreenKeys()3061 long CountScreenKeys()
3062 
3063 {
3064 	return(LenQueue());
3065 }
3066 
GetScreenKeys(keycode,modifiers,ascii,h,v)3067 int GetScreenKeys(keycode, modifiers, ascii, h, v)
3068 char *keycode;
3069 char *modifiers;
3070 char *ascii;
3071 short *h;
3072 short *v;
3073 
3074 {
3075 	short flag;
3076 	short th, tv;
3077 
3078 	if (flag = PopQueue(keycode, modifiers, ascii, &th, &tv)) {
3079 		if (h != NULL) *h = th;
3080 		if (v != NULL) *v = tv;
3081 	}
3082 
3083 	return(flag);
3084 }
3085 
EnableScreenMouse(flag)3086 void EnableScreenMouse(flag)
3087 long flag;
3088 
3089 {
3090 	if ( (flag) && (!theScreen.mouseFlag) ) theScreen.mouseFlush = TickCount();
3091 	theScreen.mouseFlag = flag;
3092 	return;
3093 }
3094 
ClipScreenMouse(area)3095 void ClipScreenMouse(area)
3096 Rect *area;
3097 
3098 {
3099 	theScreen.mouseLRect = theScreen.mouseCRect = *area;
3100 	theScreen.mouseLRect.left *= theScreen.charPDims.h;
3101 	theScreen.mouseLRect.top *= theScreen.charPDims.v;
3102 	theScreen.mouseLRect.right *= theScreen.charPDims.h;
3103 	theScreen.mouseLRect.bottom *= theScreen.charPDims.v;
3104 
3105 	return;
3106 }
3107 
DefineScreenCursor(color,lines,blinkRate)3108 void DefineScreenCursor(color, lines, blinkRate)
3109 long color;
3110 long lines;
3111 long blinkRate;
3112 
3113 {
3114 	theScreen.cursorColor = color;
3115 	theScreen.cursorLines = lines;
3116 	theScreen.cursorBlink = blinkRate;
3117 
3118 	InvalCursor(0);
3119 
3120 	return;
3121 }
3122 
HideScreenCursor()3123 void HideScreenCursor()
3124 
3125 {
3126 	theScreen.cursorLevel--;
3127 	CheckCursorStatus();
3128 	return;
3129 }
3130 
ShowScreenCursor()3131 void ShowScreenCursor()
3132 
3133 {
3134 	theScreen.cursorLevel++;
3135 	CheckCursorStatus();
3136 	return;
3137 }
3138 
3139 void SetScreenAboutProc(procPtr)
3140 void (*procPtr)();
3141 
3142 {
3143 	theScreen.aboutProc = procPtr;
3144 	return;
3145 }
3146 
3147 void SetScreenQuitProc(procPtr, flag)
3148 void (*procPtr)();
3149 long flag;
3150 
3151 {
3152 	theScreen.quitProc = procPtr;
3153 	theScreen.quitReturns = flag;
3154 	return;
3155 }
3156 
YesOrNo(text)3157 long YesOrNo(text)
3158 char *text;
3159 
3160 {
3161 	DialogPtr theDialog;
3162 	short itemHit;
3163 	short itsType;
3164 	Handle itsHandle;
3165 	Rect itsRect;
3166 	Str255 ptext;
3167 	long h, v;
3168 
3169 	theDialog = GetNewDialog(yesOrNoDlgID, nil, (WindowPtr) -1);
3170 
3171 	CenterScreenDLOG(yesOrNoDlgID, fixHalf, fixThird, &h, &v);
3172 	MoveWindow((WindowPtr) theDialog, (short) h, (short) v, false);
3173 
3174 	GetDItem(theDialog, ok, &itsType, &itsHandle, &itsRect);
3175 	InsetRect(&itsRect, -4, -4);
3176 
3177 	SetDItem(theDialog, yesOrNoDfltBorder, userItem,
3178 		 (Handle) DrawDefaultBorder, &itsRect);
3179 
3180 	if (text != NULL) {
3181 		strncpy((char *)ptext, text, 255);
3182 		ptext[255] = '\0';
3183 		c2pstr((char *)ptext);
3184 		GetDItem(theDialog, yesOrNoText, &itsType, &itsHandle, &itsRect);
3185 		SetIText(itsHandle, ptext);
3186 	}
3187 
3188 	ShowWindow((WindowPtr) theDialog);
3189 
3190 	do {
3191 		ModalDialog(nil, &itemHit);
3192 	} while ( (itemHit != ok) && (itemHit != cancel) );
3193 
3194 	DisposDialog(theDialog);
3195 
3196 	return(itemHit == ok);
3197 }
3198 
ShowScreen(visible)3199 void ShowScreen(visible)
3200 long visible;
3201 
3202 {
3203 	if (visible)
3204 		ShowWindow(theScreen.window);
3205 	else
3206 		HideWindow(theScreen.window);
3207 
3208 	return;
3209 }
3210 
GetScreenBounds(bounds)3211 void GetScreenBounds(bounds)
3212 Rect *bounds;
3213 
3214 {
3215 
3216 #ifdef THINK_C
3217 
3218 	*bounds = screenBits.bounds;
3219 	bounds->top += GetMBarHeight();
3220 
3221 #else			/* I think we can live without this. -- BS  */
3222 
3223 	Point mouse;
3224 	GDHandle gdh;
3225 
3226 	if (!theScreen.env.hasColorQD) {
3227 		*bounds = qd.screenBits.bounds;
3228 		bounds->top += GetMBarHeight();
3229 	}
3230 
3231 	else {
3232 
3233 		*bounds = (*GetMainDevice())->gdRect;
3234 
3235 		GetMouse(&mouse);
3236 		LocalToGlobal(&mouse);
3237 
3238 		gdh = GetDeviceList();
3239 
3240 		while (gdh != NULL) {
3241 
3242 			if (PtInRect(mouse, &(*gdh)->gdRect)) {
3243 				*bounds = (*gdh)->gdRect;
3244 				if (gdh == GetMainDevice()) bounds->top += GetMBarHeight();
3245 				gdh = NULL;
3246 			}
3247 
3248 			else
3249 				gdh = GetNextDevice(gdh);
3250 
3251 		}
3252 
3253 	}
3254 #endif
3255 
3256 	return;
3257 }
3258 
3259 
CenterScreenDLOG(id,hRatio,vRatio,h,v)3260 void CenterScreenDLOG(id, hRatio, vRatio, h, v)
3261 long id;
3262 Fixed hRatio, vRatio;
3263 long *h, *v;
3264 
3265 {
3266 	long wid, hgt;
3267 	DialogTHndl d;
3268 	Rect bounds;
3269 
3270 	d = (DialogTHndl) GetResource('DLOG', (short) id);
3271 
3272 	if (d != NULL) {
3273 
3274 		wid = (*d)->boundsRect.right - (*d)->boundsRect.left;
3275 		hgt = (*d)->boundsRect.bottom - (*d)->boundsRect.top;
3276 
3277 		GetScreenBounds(&bounds);
3278 
3279 		wid = (bounds.right - bounds.left) - wid;
3280 		hgt = (bounds.bottom - bounds.top) - hgt;
3281 
3282 		*h = bounds.left + FixRound(hRatio * wid);
3283 		*v = bounds.top + FixRound(vRatio * hgt);
3284 
3285 	}
3286 
3287 	return;
3288 }
3289 
DoScreenALRT(id,kind,hRatio,vRatio)3290 long DoScreenALRT(id, kind, hRatio, vRatio)
3291 long id;
3292 long kind;
3293 Fixed hRatio, vRatio;
3294 
3295 {
3296 	long wid, hgt, h, v;
3297 	long item;
3298 	AlertTHndl a;
3299 	Rect bounds;
3300 
3301 	a = (AlertTHndl) GetResource('ALRT', (short) id);
3302 
3303 	if (a != NULL) {
3304 
3305 		wid = (*a)->boundsRect.right - (*a)->boundsRect.left;
3306 		hgt = (*a)->boundsRect.bottom - (*a)->boundsRect.top;
3307 
3308 		GetScreenBounds(&bounds);
3309 
3310 		wid = (bounds.right - bounds.left) - wid;
3311 		hgt = (bounds.bottom - bounds.top) - hgt;
3312 
3313 		h = bounds.left + FixRound(hRatio * wid) - (*a)->boundsRect.left;
3314 		v = bounds.top + FixRound(vRatio * hgt) - (*a)->boundsRect.top;
3315 
3316 		OffsetRect(&(*a)->boundsRect, (short) h, (short) v);
3317 
3318 		MoveHHi((Handle) a);
3319 		HLock((Handle) a);
3320 
3321 		switch (kind) {
3322 			case akNormal:		item = Alert((short) id, NULL);			break;
3323 			case akStop:		item = StopAlert((short) id, NULL);		break;
3324 			case akNote:		item = NoteAlert((short) id, NULL);		break;
3325 			case akCaution:		item = CautionAlert((short) id, NULL);	break;
3326 		}
3327 
3328 		HUnlock((Handle) a);
3329 
3330 	}
3331 
3332 	else
3333 
3334 		item = -1;
3335 
3336 	return(item);
3337 }
3338 
ConfigScreenMgr(force,theType,theID,ConfigProc)3339 void ConfigScreenMgr(force, theType, theID, ConfigProc)
3340 long force;
3341 ResType theType;
3342 long theID;
3343 long (*ConfigProc)(Handle theData);
3344 
3345 {
3346 	short saveResFile, homeResFile;
3347 	short attrs;
3348 	short itsID;
3349 	ResType itsType;
3350 	Str255 itsName;
3351 	Handle theData;
3352 
3353 	saveResFile = CurResFile();
3354 	UseResFile(theScreen.infoResFile);
3355 
3356 	theData = GetResource(theType, (short) theID);
3357 
3358 	if (theData != NULL) {
3359 
3360 		homeResFile = HomeResFile(theData);
3361 
3362 		if ( (theScreen.reconfigFlag) ||
3363 				(force) ||
3364 				(homeResFile != theScreen.infoResFile) ) {
3365 
3366 			if ((*ConfigProc)(theData)) {
3367 
3368 				if (homeResFile != theScreen.infoResFile) {
3369 					GetResInfo(theData, &itsID, &itsType, itsName);
3370 					attrs = GetResAttrs(theData);
3371 					attrs |= resChanged;
3372 					DetachResource(theData);
3373 					AddResource(theData, itsType, itsID, itsName);
3374 					SetResAttrs(theData, attrs);
3375 				}
3376 				else
3377 					ChangedResource(theData);
3378 
3379 				WriteResource(theData);
3380 
3381 			}
3382 
3383 		}
3384 
3385 	}
3386 
3387 	UseResFile(saveResFile);
3388 
3389 	return;
3390 }
3391 
AnimateCursor()3392 static pascal void AnimateCursor()
3393 
3394 {
3395 	short next;
3396 	long oldA5;
3397 
3398 	oldA5 = SetCurrentA5();
3399 
3400 	next = (*theScreen.acur)->next + 1;
3401 	if (next >= (*theScreen.acur)->frames) next = 0;
3402 	SetCursor(*((*theScreen.acur)->table[next].cursHandle));
3403 	(*theScreen.acur)->next = next;
3404 
3405 	theScreen.vbl.vblCount = (short) theScreen.waitRate;
3406 
3407 	(void) SetA5(oldA5);
3408 
3409 	return;
3410 }
3411 
BeginScreenWait(rate)3412 void BeginScreenWait(rate)
3413 long rate;
3414 
3415 {
3416 	if (!theScreen.waitFlag) {
3417 
3418 		(*theScreen.acur)->next = 0;
3419 
3420 		SetCursor(*((*theScreen.acur)->table[0].cursHandle));
3421 		ShowCursor();
3422 
3423 		theScreen.waitFlag = true;
3424 		theScreen.waitRate = rate;
3425 
3426 		theScreen.vbl.qType = vType;
3427 #ifdef THINK_C
3428 		theScreen.vbl.vblAddr = (int (*)())AnimateCursor;
3429 #else
3430 		theScreen.vbl.vblAddr = AnimateCursor;
3431 #endif
3432 		theScreen.vbl.vblCount = (short) theScreen.waitRate;
3433 		theScreen.vbl.vblPhase = 0;
3434 
3435 		(void) VInstall((QElemPtr) &theScreen.vbl);
3436 
3437 	}
3438 
3439 	return;
3440 }
3441 
EndScreenWait()3442 void EndScreenWait()
3443 
3444 {
3445 	if (theScreen.waitFlag) {
3446 
3447 		(void) VRemove((QElemPtr) &theScreen.vbl);
3448 
3449 		theScreen.waitFlag = false;
3450 
3451 		InitCursor();
3452 
3453 	}
3454 
3455 	return;
3456 }
3457 
GetFileMHandle()3458 Handle GetFileMHandle()
3459 
3460 {
3461 	return((Handle) GetMHandle(theScreen.cmdKeyFlag ? fileID1 : fileID2));
3462 }
3463 
GetAppMHandle()3464 Handle GetAppMHandle()
3465 
3466 {
3467 	return((Handle) GetMHandle(theScreen.cmdKeyFlag ? appID1 : appID2));
3468 }
3469 
PushScreen()3470 long PushScreen()
3471 
3472 {
3473 	long errcode;
3474 	char **chars, **attrs;
3475 	SaveScreenHandle next;
3476 	OSErr oops;
3477 
3478 	next = (SaveScreenHandle) NewHandle(sizeof(SaveScreenRec));
3479 
3480 	if (next != NULL) {
3481 
3482 		chars = theScreen.chars;
3483 		oops = HandToHand((Handle *) &chars);
3484 
3485 		if (oops == noErr) {
3486 
3487 			attrs = theScreen.attrs;
3488 			oops = HandToHand((Handle *) &attrs);
3489 
3490 			if (oops == noErr) {
3491 
3492 				(*next)->link = theScreen.stack;
3493 				(*next)->chars = chars;
3494 				(*next)->attrs = attrs;
3495 				(*next)->cursor = theScreen.cursor;
3496 
3497 				theScreen.stack = next;
3498 
3499 				errcode = scrnErrOk;
3500 
3501 			}
3502 
3503 			else {
3504 
3505 				DisposHandle((Handle) chars);
3506 				DisposHandle((Handle) next);
3507 
3508 				errcode = scrnErrNoMem;
3509 
3510 			}
3511 
3512 		}
3513 
3514 		else {
3515 
3516 			DisposHandle((Handle) next);
3517 
3518 			errcode = scrnErrNoMem;
3519 
3520 		}
3521 
3522 	}
3523 
3524 	else {
3525 
3526 		errcode = scrnErrNoMem;
3527 
3528 	}
3529 
3530 	return(errcode);
3531 }
3532 
PopScreen()3533 void PopScreen()
3534 
3535 {
3536 	if (theScreen.stack != NULL) {
3537 
3538 		HLock((Handle) (*theScreen.stack)->chars);
3539 		HLock((Handle) (*theScreen.stack)->attrs);
3540 
3541 		XSetScreenImage(0,
3542 			*(*theScreen.stack)->chars,
3543 			*(*theScreen.stack)->attrs,
3544 			theScreen.scrnCDims.h,
3545 			&theScreen.scrnCRect,
3546 			0, 0);
3547 
3548 		XSetScreenCursor(0, (*theScreen.stack)->cursor.h,
3549 				 (*theScreen.stack)->cursor.v);
3550 
3551 		DisposeStackTop();
3552 
3553 		UpdateScreen();
3554 
3555 	}
3556 
3557 	return;
3558 }
3559