1 //=============================================================================
2 // All command window updates, input, etc happen here -EAD
3 //=============================================================================
4 #include <Controls.h>
5 /* #include <ControlDefinitions.h> */
6 #include <Events.h>
7 #include <Fonts.h>
8 #include <MacWindows.h>
9 #include "MacGlobals.h"
10 #include "macint.h"
11 #include <ctype.h>
12 #define NIL ((void *) 0)
13 
14 //=============================================================================
15 // local variables
16 //=============================================================================
17 
18 ControlHandle vScroll;
19 int 		cursorPos;							/* the cursor's position on the line */
20 short		linesInView;						/* how many lines are in the window */
21 int			cmdStart;							/* where (in text record) the current command starts */
22 TextStyle 	textStyle[2];  						/* styles: bold for user input, plain for output */
23 /* output is buffered */
24 Handle hOutputBuffer = NULL;
25 enum currentStyle { plainStyle, boldStyle } currentStyle;
26 
27 static void GoStartOfLine (void);
28 static void GoEndOfLine (void);
29 static void GoBackOneWord (void);
30 static void GoForwardOneWord (void);
31 
32 //=============================================================================
33 // static void DoScrollBar (ControlHandle control, short change)
34 //=============================================================================
35 /* keep track of the user as he fiddles with the scroll bar */
36 /* This routine is called while the user has the mouse down. */
37 /* It makes sure the thumb isn't dragged out-of-bounds. */
38 //=============================================================================
39 
DoScrollBar(ControlHandle control,short change)40 static void DoScrollBar (ControlHandle control, short change) {
41     short value = GetControlValue (control), max = GetControlMaximum (control);
42     long newval = value + change;  /* this is a long in case we try to go past MAX_INT */
43     if (newval < 0) newval = 0; else if (newval > max) newval = max;
44     SetControlValue (control, (short) newval);
45     if (newval != value) TEScroll (0, (short) (value - newval) * LINEHEIGHT, hTERec);
46 }
47 
48 //=============================================================================
49 // pascal Boolean ScrollClickLoop (void)
50 //=============================================================================
51 //
52 //=============================================================================
53 
ScrollClickLoop(void)54 pascal Boolean ScrollClickLoop (void) {
55     Rect tempRect;
56     Point mouse;
57     GrafPtr oldPort;
58     RgnHandle oldClip;
59     short amount = 0;
60 
61     if (FrontWindow () != gCommandWin) return false;
62 
63     GetPort (&oldPort);
64     SetPort (gCommandWin);
65     GetClip (oldClip = NewRgn ());
66     SetRect (&tempRect, INT_MIN, INT_MIN, INT_MAX, INT_MAX);
67     ClipRect (&tempRect);
68 
69     GetMouse (&mouse);
70     if (mouse.v < TEXTREC->viewRect.top)  			DoScrollBar (vScroll, -1);
71     else if (mouse.v > TEXTREC->viewRect.bottom)	DoScrollBar (vScroll, 1);
72 
73     SetClip (oldClip);
74     DisposeRgn (oldClip);
75     SetPort (oldPort);
76     return true;
77 }
78 
79 //=============================================================================
80 // static pascal void ScrollProc (ControlHandle control, short thePart)
81 //=============================================================================
82 // for clicks in the scroll bar or arrows; update the window properly
83 //=============================================================================
84 
ScrollProc(ControlHandle control,short thePart)85 pascal void ScrollProc (ControlHandle control, short thePart) {
86     short amount;
87     WindowPtr window;
88 
89     if (!thePart) return;
90     window = (*control)->contrlOwner;
91     switch (thePart) {
92         case kControlUpButtonPart:	amount = -1;				break;
93         case kControlDownButtonPart:	amount = 1;					break;
94         case kControlPageUpPart:		amount = -linesInView;		break;
95         case kControlPageDownPart:	amount = linesInView;		break;
96     }
97     DoScrollBar (control, amount);
98 }
99 
100 //=============================================================================
101 // Rect SetTERect (void)
102 //=============================================================================
103 // set the dimensions of the text record in its window
104 //=============================================================================
105 
SetTERect(void)106 Rect SetTERect (void) {
107     Rect teRect = gCommandWin->portRect;
108     teRect.right -= SCROLLER_WIDTH;
109     InsetRect (&teRect, TEXT_MARGIN, TEXT_MARGIN);
110     linesInView = (teRect.bottom - teRect.top) / LINEHEIGHT;
111     teRect.bottom = teRect.top + linesInView * LINEHEIGHT;  /* round off */
112     return teRect;
113 }
114 
115 //=============================================================================
116 // static void AdjustCursor (EventRecord *theEvent)
117 //=============================================================================
118 // make the pointer an I-beam iff it's in the text window
119 //=============================================================================
120 
AdjustCursor(Point theLoc,RgnHandle theRgn)121 void AdjustCursor (Point theLoc, RgnHandle theRgn)
122 {
123     RgnHandle	arrowRgn, iBeamRgn, hiliteRgn, tempRgn;
124     Rect		theRect;
125     Point		thePoint;
126 
127     if (gInBackground)
128         return;
129 
130     arrowRgn = NewRgn();
131     SetRectRgn(arrowRgn, -32767, -32767, 32767, 32767);
132 
133 //	GlobalToLocal ((theLoc); ???
134 
135     if (gCommandWin == FrontWindow () ) {
136         SetPort(gCommandWin);
137         iBeamRgn = NewRgn();
138         hiliteRgn = NewRgn();
139 
140         theRect = TEXTREC->viewRect;
141         LocalToGlobal((Point *)&(theRect.top));
142         LocalToGlobal((Point *)&(theRect.bottom));
143         RectRgn(iBeamRgn, &theRect);
144 
145         TEGetHiliteRgn(hiliteRgn, hTERec);
146         thePoint.h = thePoint.v = 0;
147         LocalToGlobal(&thePoint);
148         OffsetRgn(hiliteRgn, thePoint.h, thePoint.v);
149 
150         DiffRgn(arrowRgn, hiliteRgn, arrowRgn);
151         DiffRgn(arrowRgn, iBeamRgn, arrowRgn);
152 
153         DiffRgn(iBeamRgn, hiliteRgn, iBeamRgn);
154 
155         if (PtInRgn(theLoc, iBeamRgn)) {
156             SetCursor(*GetCursor(iBeamCursor));
157             CopyRgn(iBeamRgn, theRgn);
158         } else if (PtInRgn(theLoc, hiliteRgn)) {
159             SetCursor(&qd.arrow);
160             CopyRgn(hiliteRgn, theRgn);
161         } else {
162             SetCursor(&qd.arrow);
163             CopyRgn(arrowRgn, theRgn);
164         }
165 
166         DisposeRgn(iBeamRgn);
167         DisposeRgn(hiliteRgn);
168 
169     } else  {
170         SetCursor(&qd.arrow);
171         CopyRgn(arrowRgn, theRgn);
172     }
173 
174     DisposeRgn(arrowRgn);
175 }
176 
177 
178 
179 //=============================================================================
180 // static void SetScrollRect (void)
181 //=============================================================================
182 // Set Scroll bar rec size
183 //=============================================================================
184 
SetScrollRect(void)185 void SetScrollRect (void) {
186     /* set the dimensions of the scroll bar in its window */
187 
188 // This change fixes the double flash on window resize -EAD
189 
190 //	MoveControl (vScroll, commandWin->portRect.right - SCROLLER_WIDTH, -1);
191 //	SizeControl (vScroll, SCROLLER_WIDTH + 1,
192 //			(commandWin->portRect.bottom - commandWin->portRect.top) - (SCROLLER_WIDTH - 2));
193     (*vScroll)->contrlRect.left = gCommandWin->portRect.right - SCROLLER_WIDTH;
194     (*vScroll)->contrlRect.top = -1;
195     (*vScroll)->contrlRect.right =  gCommandWin->portRect.right + 1;
196     (*vScroll)->contrlRect.bottom = gCommandWin->portRect.bottom - (SCROLLER_WIDTH - 1);
197 
198 }
199 
200 //=============================================================================
201 // static void AdjustScrollBar (void)
202 //=============================================================================
203 // Set the thumb on scrollbar
204 //=============================================================================
205 
AdjustScrollBar(void)206 static void AdjustScrollBar (void) {
207     /* adjust the scroll bar to match the position of the text view */
208     short oldval = GetControlValue (vScroll), oldmax = GetControlMaximum (vScroll);
209     short value, max;
210     short test;
211 
212     max = TEXTREC->nLines - linesInView;
213     if ((TEXTREC->teLength > 0) && (*(*TEXTREC->hText + TEXTREC->teLength - 1) == '\r')) max++;
214     if (max < 0) max = 0;
215     if (max != oldmax) SetControlMaximum (vScroll, max);
216     value = (short)((TEXTREC->viewRect.top - TEXTREC->destRect.top) / LINEHEIGHT);
217 //	value = roundup ((TEXTREC->viewRect.top - TEXTREC->destRect.top) / LINEHEIGHT);
218     if (value < 0) value = 0; else if (value > max) value = max;
219     if (value != oldval) SetControlValue (vScroll, value);
220 }
221 
roundup(float x)222 static short roundup (float x) {  /* a kludge to round up a float to an int */
223     if (((int) x) != ((int) (x += 0.5))) x += 0.5;
224     return (int) x;
225 }
226 
227 //=============================================================================
228 // void DoKeyPress (EventRecord *theEvent)
229 //=============================================================================
230 // Hanlde Keyboard Input
231 //=============================================================================
232 
DoKeyPress(EventRecord * theEvent)233 void DoKeyPress (EventRecord *theEvent) {
234     short whatKey = theEvent->message & charCodeMask;
235     if (theEvent->modifiers & cmdKey) {
236         long choice;
237         AdjustMenus ();
238         if (choice = MenuKey (theEvent->message)) DoMenu (choice);
239         else if (((whatKey == 'w') || (whatKey == 'W')) && (FrontWindow () == gGraphicsWin))
240             HideGrafWin ();
241         else if (whatKey == LEFTARROW)	GoStartOfLine ();
242         else if (whatKey == RIGHTARROW)	GoEndOfLine ();
243         else if (whatKey == UPARROW)	DoScrollBar (vScroll, - linesInView);
244         else if (whatKey == DOWNARROW)	DoScrollBar (vScroll, linesInView);
245     }
246     else if (theEvent->modifiers & optionKey) {
247         if (whatKey == LEFTARROW)		GoBackOneWord ();
248         else if (whatKey == RIGHTARROW)	GoForwardOneWord ();
249     }
250     else switch (whatKey) {
251         case PAGEUP:	DoScrollBar (vScroll, -linesInView);	break;
252         case PAGEDN:	DoScrollBar (vScroll, linesInView);		break;
253         case HOMEKEY:	DoScrollBar (vScroll, INT_MIN);			break;
254         case ENDKEY:	DoScrollBar (vScroll, INT_MAX);			break;
255         case FNKEY:												break;
256         case HELPKEY:											break;
257         default: recentChar = theEvent->message & charCodeMask;
258     }
259 }
260 
261 //=============================================================================
262 // static void DrawOnlyGrowIcon (WindowPtr window)
263 //=============================================================================
264 // draw growbox on command window with no scoll bars
265 //=============================================================================
266 
DrawOnlyGrowIcon(WindowPtr window)267 static void DrawOnlyGrowIcon (WindowPtr window)
268 {
269     RgnHandle saveRgn;
270     Rect growRect;
271 
272     growRect = window->portRect;
273     growRect.top = growRect.bottom - SCROLLER_WIDTH;
274     growRect.left = growRect.right - SCROLLER_WIDTH;
275     GetClip (saveRgn = NewRgn ());
276     ClipRect (&growRect);
277     DrawGrowIcon (window);
278     SetClip (saveRgn);
279     DisposeRgn (saveRgn);
280 }
281 
282 //=============================================================================
283 // void SetSelection (short start, short end)
284 //=============================================================================
285 // set text selection in the command window
286 //=============================================================================
287 
SetSelection(short start,short end)288 void SetSelection (short start, short end) {
289     TEXTREC->clikStuff = 255;  /* to make sure the caret appears at the start of a line when it should */
290     /* see tech note "TextEdit EOL Ambiguity" for more information */
291     TESetSelect (start, end, hTERec);
292 }
293 
294 //=============================================================================
295 // static void CancelFlash (void)
296 //=============================================================================
297 // cancel the matching-paren flashing
298 //=============================================================================
299 
CancelFlash(void)300 static void CancelFlash (void) {
301     if (flashTime) {
302         flashTime = 0;
303         SetSelection (cursorBeforeFlash, cursorBeforeFlash);
304     }
305 }
306 
307 //=============================================================================
308 // static void StopPasting (void)
309 //=============================================================================
310 // clean up after finishing a paste
311 //=============================================================================
312 
StopPasting(void)313 void StopPasting (void) {
314     pastedLength = 0;
315     if (pastedTextH) {
316         DisposeHandle (pastedTextH);
317         pastedTextH = NULL;
318     }
319 }
320 
321 //=============================================================================
322 // static void DoStyle (int whatStyle)
323 //=============================================================================
324 // set the text to a certain style
325 //=============================================================================
326 
DoStyle(int whatStyle)327 static void DoStyle (int whatStyle) {
328     TESetStyle (doFace, &(textStyle[whatStyle]), false, hTERec);
329 }
330 
331 //=============================================================================
332 // static void FlushOutput (void)
333 //=============================================================================
334 // clear out the output buffer, dumping its contents to the window
335 //=============================================================================
336 
FlushOutput(void)337 void FlushOutput (void) {
338     short totalLines, scrollAmount, max;
339 
340     if (outputBufferLength == 0) return;
341     CancelFlash ();
342     DoStyle (plainStyle);
343     HLock (hOutputBuffer);
344     TEInsert (*hOutputBuffer, outputBufferLength, hTERec);
345     HUnlock (hOutputBuffer);
346     outputBufferLength = 0;
347 
348     if (TEXTREC->teLength > SCROLLBACK_THRESHHOLD) {
349         /* make sure TE record isn't too long */
350 #ifdef ORIGINALCODE
351         /* I replaced this because Nyquist was crashing after the
352            buffer got filled. The replacement below is simpler and
353            eliminates the crashes, although it probably could cause
354            problems by clearing the selection.
355          */
356         int i = 1, newLength;
357         TEPtr textPtr;
358         while ((TEXTREC->teLength - TEXTREC->lineStarts[i]) >
359                (SCROLLBACK_THRESHHOLD - DELETE_BLOCK)) i++;
360         i = TEXTREC->lineStarts[i];
361         newLength = TEXTREC->teLength - i;
362         textPtr = (TEPtr)(*(TEXTREC->hText));
363         BlockMoveData ((Ptr)((long)textPtr + i), textPtr, newLength);
364         SetHandleSize (TEXTREC->hText, newLength);
365         TEXTREC->destRect.top += LINEHEIGHT;
366         TECalText (hTERec);
367         TEUpdate (&(TEXTREC->viewRect), hTERec);
368 #else
369         /* find the line start after DELETE_BLOCK */
370         int i = 1;
371         while (TEXTREC->lineStarts[i] < DELETE_BLOCK) i++;
372         TESetSelect(0, TEXTREC->lineStarts[i], hTERec);
373         TEDelete(hTERec);
374         /* after deletion, put cursor back at end of buffer */
375         TESetSelect(TEXTREC->teLength, TEXTREC->teLength, hTERec);
376 #endif
377     }
378     TESelView (hTERec);
379     AdjustScrollBar ();
380 }
381 
382 //=============================================================================
383 // void PrepareForInput (void)
384 //=============================================================================
385 // get ready to take input
386 //=============================================================================
387 
PrepareForInput(void)388 void PrepareForInput (void) {
389     FlushOutput ();
390     cmdStart = TEXTREC->selStart;
391 }
392 
393 //=============================================================================
394 // static void DeleteRange (void)
395 //=============================================================================
396 // delete the selected range of text, updating cmdStart as necessary
397 //=============================================================================
398 
DeleteRange(void)399 void DeleteRange (void) {
400     if (TEXTREC->selEnd <= cmdStart) return;
401     if (TEXTREC->selStart < cmdStart) SetSelection (cmdStart, TEXTREC->selEnd);
402     TEDelete (hTERec);
403 }
404 
405 //=============================================================================
406 // static void CopyThisLineToEnd (void)
407 //=============================================================================
408 // copy the line the caret is on to the end
409 //=============================================================================
410 
CopyThisLineToEnd(void)411 static void CopyThisLineToEnd (void) {
412     char *buffer;
413     short b, i, caretOffset;
414 
415     /* first find out exactly where it starts */
416     i = TEXTREC->nLines-1;  /* first find which line */
417     while (TEXTREC->selStart < TEXTREC->lineStarts[i]) i--;
418     while ((i > 0) && ((*(TEXTREC->hText))[TEXTREC->lineStarts[i]-1] != '\r'))
419         i--;  /* for wrapped lines */
420     i = TEXTREC->lineStarts[i];  /* now zero in on the exact character where it begins */
421     while ((TEXTCHAR(i) >= '0') && (TEXTCHAR(i) <= '9')) i++;  /* skip error level */
422     if ((TEXTCHAR(i) == '>') && (TEXTCHAR(i+1) == ' ')) i+=2;  /* get rid of leading prompt */
423 
424     caretOffset = TEXTREC->selStart - i;  /* how many characters in is the caret? */
425 
426     /* now put the line into the buffer */
427     b = 0;
428     while ((TEXTCHAR(i+b) != '\r') && (i+b < TEXTREC->teLength)) b++;  /* find the end of the line */
429     buffer = (char *) NewPtr (b);
430     BlockMoveData (*TEXTREC->hText + i, buffer, b);
431     buffer[b] = '\0';
432 
433     /* delete whatever's already on the last line */
434     SetSelection (cmdStart, TEXTREC->teLength);
435     TEDelete (hTERec);
436 
437     DoStyle (boldStyle);
438     TEInsert (buffer, b, hTERec);
439     DisposePtr (buffer);
440 
441     if (caretOffset < 0) caretOffset = b;
442     SetSelection (cmdStart + caretOffset, cmdStart + caretOffset);
443 }
444 
445 //=============================================================================
446 // Next four functions possition cursor in text
447 //=============================================================================
448 
GoStartOfLine(void)449 static void GoStartOfLine (void) {
450     short whichLine = TEXTREC->nLines - 1;  /* look for the caret; start at the end and go up */
451     while (TEXTREC->lineStarts[whichLine] > TEXTREC->selStart) whichLine--;
452     SetSelection (TEXTREC->lineStarts[whichLine], TEXTREC->lineStarts[whichLine]);
453     AdjustScrollBar ();
454 }
455 
GoEndOfLine(void)456 static void GoEndOfLine (void) {
457     short whichLine = TEXTREC->nLines - 1;  /* look for the caret; start at the end and go up */
458     while (TEXTREC->lineStarts[whichLine] > TEXTREC->selStart) whichLine--;
459     if (whichLine == TEXTREC->nLines - 1)
460         SetSelection (TEXTREC->teLength, TEXTREC->teLength);
461     else SetSelection (TEXTREC->lineStarts[whichLine+1] - 1, TEXTREC->lineStarts[whichLine+1] - 1);
462     AdjustScrollBar ();
463 }
464 
GoBackOneWord(void)465 static void GoBackOneWord (void) {
466     short i = TEXTREC->selStart;
467     while ((i > 0) && !isalnum (TEXTCHAR(i-1)))	i--;
468     while ((i > 0) && isalnum (TEXTCHAR(i-1)))	i--;
469     SetSelection (i, i);
470 }
471 
GoForwardOneWord(void)472 static void GoForwardOneWord (void) {
473     short i = TEXTREC->selStart;
474     while ((i < TEXTREC->teLength) && !isalnum (TEXTCHAR(i)))	i++;
475     while ((i < TEXTREC->teLength) && isalnum (TEXTCHAR(i)))	i++;
476     SetSelection (i, i);
477 }
478 
479 
480 //=============================================================================
481 // static void EditFreely (void)
482 //=============================================================================
483 // Enter text into the command windows
484 //=============================================================================
485 
EditFreely(void)486 static void EditFreely (void) {
487     Boolean done;
488     do {
489         done = false;
490         DoEvent ();
491         if (pastedLength > 0) {  /* if there is still text to paste, paste it */
492             int i = 0;
493             CancelFlash ();
494             if (TEXTREC->selStart < cmdStart) StopPasting ();
495             else {
496                 while ((i < pastedLength) && (((char *)(*pastedTextH))[i] != '\r')) i++;
497                 DoStyle (boldStyle);
498                 TEInsert (*pastedTextH, i, hTERec);
499                 AdjustScrollBar ();
500                 if (i < pastedLength) {  /* we were stopped by a carriage return, so eat it */
501                     i++;
502                     done = true;
503                 }
504                 pastedLength -= i;
505                 if (pastedLength > 0) {
506                     BlockMoveData ((Ptr)((long)(*pastedTextH) + i), *pastedTextH, pastedLength);
507                     SetHandleSize (pastedTextH, pastedLength);
508                 } else StopPasting ();
509             }
510         }
511         else if (recentChar) {  /* if the last event got us a character, process it */
512             int i;
513             Boolean wasOnLastLine;
514             CancelFlash ();
515 
516             if ((TEXTREC->selEnd <= cmdStart) && (TEXTREC->selStart != TEXTREC->selEnd)) continue;
517             if (TEXTREC->selStart < cmdStart) SetSelection (cmdStart, TEXTREC->selEnd);
518             wasOnLastLine = (TEXTREC->selStart >= cmdStart);
519 
520             if ((recentChar & 0xfc) == 0x1c) {  /* was this an arrow key? */
521                 TEXTREC->clikStuff = 255;  /* to make sure the caret appears where it should */
522                 TEKey (recentChar, hTERec);
523                 AdjustScrollBar ();
524                 continue;
525             }
526             if (!wasOnLastLine) CopyThisLineToEnd ();
527             switch (recentChar) {
528             case FWDDEL:
529                 if (TEXTREC->selStart != TEXTREC->selEnd) DeleteRange ();
530                 else if ((TEXTREC->selStart >= cmdStart) && (TEXTREC->selStart < TEXTREC->teLength)) {
531                     TEDeactivate (hTERec);
532                     SetSelection (TEXTREC->selStart, TEXTREC->selStart + 1);
533                     TEDelete (hTERec);
534                     if (FrontWindow () == gCommandWin) TEActivate (hTERec);
535                 }
536                 break;
537             case CLRKEY:
538                 if (TEXTREC->selStart != TEXTREC->selEnd) DeleteRange ();
539                 break;
540             case DELETE:
541                 if (TEXTREC->selStart != TEXTREC->selEnd) DeleteRange ();
542                 else if (TEXTREC->selStart > cmdStart) {
543                     TEXTREC->clikStuff = 255;  /* to make sure the caret appears where it should */
544                     TEKey (DELETE, hTERec);
545                 }
546                 break;
547             case RETURN:
548                 if (wasOnLastLine) done = true;
549                 break;
550             case ENTER:  /* ENTER ends command no matter what */
551                 done = true;
552                 break;
553             default:
554                 DoStyle (boldStyle);
555                 TEXTREC->clikStuff = 255;  /* to make sure the caret appears where it should */
556                 TEKey (recentChar, hTERec);
557                 if ((recentChar == ')') && (TEXTREC->selStart > cmdStart)) {
558                     short parenCount = -1;
559                     Boolean inQuotes = false;
560                     i = TEXTREC->selStart - 1;
561                     while ((--i >= cmdStart) && (parenCount != 0))
562                         switch ((*TEXTREC->hText)[i]) {
563                         case DBLQUOTE: inQuotes = !inQuotes; break;
564                         case '(': if (!inQuotes) parenCount++; break;
565                         case ')': if (!inQuotes) parenCount--; break;
566                         }
567                     if (parenCount == 0) {
568                         cursorBeforeFlash = TEXTREC->selStart;
569                         SetSelection (i+1, i+2);  /* flash the matching open-paren */
570                         flashTime = 10;
571                     }
572                 } else if ((recentChar == DBLQUOTE) && (TEXTREC->selStart > cmdStart)) {
573                     i = TEXTREC->selStart - 1;
574                     while ((--i >= cmdStart) && ((*TEXTREC->hText)[i] != DBLQUOTE)) ;
575                     if ((*TEXTREC->hText)[i] == DBLQUOTE) {
576                         cursorBeforeFlash = TEXTREC->selStart;
577                         SetSelection (i, i+1);  /* flash the matching double-quote */
578                         flashTime = 10;
579                     }
580                 }
581             }
582             AdjustScrollBar ();
583         }
584     } while (!done);
585 }
586 
macgets(void)587 char *macgets (void) {
588     /* retrieve a typed character */
589     /* Note that this uses some extensive (and clever, if I may say so myself) buffering. */
590     int i, b, bufSize;
591     char *ptr, *buffer;
592     Boolean done, onLastLine;
593 
594     PrepareForInput ();
595     do {  /* repeat until a full expression has been typed */
596         EditFreely ();  /* allow free editing for a while */
597 
598         /* Now, we have a complete command to parse, if and only if: */
599         /* - the cursor was on the last line when the user pressed Return or Enter, and */
600         /* - the user either pressed Enter, or else every '(' since the beginning */
601         /*     of the command is matched by a ')'. */
602         /* Quoting is watched for.  ( ") is not a complete expression. */
603 
604         done = true;
605         if (TEXTREC->selStart != TEXTREC->teLength)  /* if we're not at the end already */
606             SetSelection (TEXTREC->teLength, TEXTREC->teLength);  /* send cursor to end */
607         TEXTREC->clikStuff = 255;  /* to make sure the caret appears where it should */
608         TEKey ('\r', hTERec);
609 
610         /* check and see if we've completed the command yet */
611         if (recentChar != ENTER) {
612             Boolean inQuotes = false;
613             short parenCount = 0;
614             for (i = cmdStart; i < TEXTREC->teLength; i++)
615                 switch ((*TEXTREC->hText)[i]) {
616                 case DBLQUOTE: inQuotes = !inQuotes; break;
617                 case '(': if (!inQuotes) parenCount++; break;
618                 case ')': if (!inQuotes) parenCount--; break;
619                 }
620             if ((parenCount > 0) || inQuotes) done = false;
621         }
622 
623         AdjustScrollBar ();
624     } while (!done);
625 
626     /* put the entire command into the buffer, and return it */
627     bufSize = TEXTREC->teLength - cmdStart;
628     buffer = (char *) NewPtr (bufSize + 1);
629     BlockMoveData (*TEXTREC->hText + cmdStart, buffer, bufSize);
630     buffer[bufSize] = '\0';
631     return buffer;
632 }
633 
macputc(int ch)634 void macputc (int ch) {
635     /* put a char into the output buffer, and flush the buffer if necessary */
636     switch (ch) {
637         case '\t':
638             do { macputc (' '); } while (cursorPos & 7);
639             break;
640         case DELETE:
641             if (cursorPos) cursorPos--;  /* and fall through to default */
642         default:
643             if (outputBufferLength == MAX_BUF) FlushOutput ();
644             if (ch == '\n') {
645                 cursorPos = 0;
646                 (*hOutputBuffer)[outputBufferLength++] = '\r';
647             } else {
648                 cursorPos++;
649                 (*hOutputBuffer)[outputBufferLength++] = ch;
650             }
651     }
652 }
653 
macputs(char * s)654 void macputs (char *s) {
655     /* for completeness */
656     while (*s) macputc (*s++);
657 }
658 
scrflush(void)659 void scrflush (void) {
660     extern void osflush (void);
661     /* clear out everything */
662     FlushOutput ();
663     osflush ();
664 }
665 
scrclear(void)666 void scrclear (void) {
667     /* clear text window -- not implemented */
668 }
669 
670 //=============================================================================
671 // static void UpdateCmdWindow (void)
672 //=============================================================================
673 // main command window update procedure
674 //=============================================================================
675 
676 
UpdateCmdWindow(void)677 void UpdateCmdWindow (void) {
678     long textBottom;
679     Rect tempRect;
680 
681     InvalRect (&(gCommandWin->portRect));
682     BeginUpdate (gCommandWin);
683     BlockMoveData(&(gCommandWin->portRect), &tempRect, sizeof(Rect));
684     tempRect.right -= SCROLLER_WIDTH;
685     EraseRect (&tempRect);
686     if (gCommandWinResized) {
687         TEXTREC->viewRect = SetTERect ();
688         TEXTREC->destRect.right = TEXTREC->viewRect.right;
689         TECalText (hTERec);
690         SetScrollRect ();
691         gCommandWinResized = false;
692     }
693     DrawOnlyGrowIcon (gCommandWin);
694     FlushOutput ();
695 
696     TEXTREC->viewRect = SetTERect ();  /* adjust for possible change in height of status line */
697 
698     textBottom = TEXTREC->destRect.top + (TEXTREC->nLines * LINEHEIGHT);
699     if (TEXTREC->destRect.top > TEXTREC->viewRect.top)
700         TEScroll (0, (TEXTREC->viewRect.top - TEXTREC->destRect.top), hTERec);
701 
702     if (TEXTREC->destRect.top < TEXTREC->viewRect.top) {  /* make sure we don't get fractions of lineheights */
703         int amountOffTheTop = TEXTREC->viewRect.top - TEXTREC->destRect.top;
704         if (amountOffTheTop % LINEHEIGHT) TEScroll (0, amountOffTheTop % LINEHEIGHT, hTERec);
705     }
706     TEUpdate (&(TEXTREC->viewRect), hTERec);
707     AdjustScrollBar ();
708     UpdateControls (gCommandWin, gCommandWin->visRgn);
709     EndUpdate (gCommandWin);
710 }
711 
ActivateCmdWindow(void)712 void ActivateCmdWindow(void)
713 {
714     TEActivate (hTERec);
715     HiliteControl (vScroll, 0);
716     DrawOnlyGrowIcon (gCommandWin);
717 }
718 
DeactivateCmdWindow(void)719 void DeactivateCmdWindow(void)
720 {
721     TEDeactivate (hTERec);
722     HiliteControl (vScroll, 255);
723     DrawOnlyGrowIcon (gCommandWin);
724 }
725 
InitalizeCmdWindow(void)726 void InitalizeCmdWindow(void)
727 {
728 
729     /* setup the font, size and writing mode for the command window */
730     TextFont (kFontIDMonaco);
731     TextSize (9);
732     TextFace (0);
733     TextMode (srcCopy);
734     textStyle[plainStyle].tsFace = 0;
735     textStyle[boldStyle].tsFace = bold;
736 
737     currentStyle = plainStyle;
738 
739     {  /* set up scroll bar */
740         Rect scrollRect;
741         vScroll = NewControl (gCommandWin, &scrollRect, "\p", 0, 0, 0, 0, scrollBarProc, 0L);
742         SetScrollRect ();
743         ShowControl (vScroll);
744     }
745 
746     {  /* set up command text record */
747         Rect teRect = SetTERect ();
748         hTERec = (TEHandle)TEStyleNew (&teRect, &teRect);
749          TECalText (hTERec);
750         TEAutoView (true, hTERec);
751         TESetClickLoop (uppScrollClickLoop, hTERec);
752         TEActivate (hTERec);
753     }
754 
755     hOutputBuffer = NewHandle (MAX_BUF);  /* a handle to a buffer for text to be displayed */
756 }
757 
CleanupCmdWindow(void)758 void CleanupCmdWindow(void)
759 {
760     StopPasting ();
761     CloseWindow (gCommandWin);
762     TEDispose (hTERec);
763     DisposeHandle (hOutputBuffer);
764 }
765