1 /******************************************************************************
2 *
3 *  NSSDC/CDF                 Toolbox of routines for CDF Toolkit (Macintosh).
4 *
5 *  Version 1.2a, 15-Nov-97, Hughes STX.
6 *
7 *  Modification history:
8 *
9 *   V1.0  26-Oct-94, J Love	Original version.
10 *   V1.1  19-Sep-95, J Love	Macintosh event handling.
11 *   V1.1a 29-Sep-95, J Love	Macintosh dialog filtering.  Outline default
12 *				button.  The CDF cursor.
13 *   V1.2  15-Aug-95, J Love	CDF V2.6.
14 *   V1.2a 15-Nov-97, J Love	Windows NT (renamed functions).
15 *
16 ******************************************************************************/
17 
18 #define TOOLBOX2
19 #include "windoz.h"
20 
21 #if defined(mac)
22 #include "cdfdist.rh"
23 #include "so.rh"
24 #endif
25 
26 /******************************************************************************
27 * Macros.
28 ******************************************************************************/
29 
30 #define ToBottom(textH,atPoint) \
31 (((*textH)->nLines * (*textH)->lineHeight) - atPoint.v)
32 
33 #define MAX_TE_TEXT_LEN         30000   /* 32767 doesn't seem to work. */
34 #define MAX_TE_TEXT_LEN_wNL     (MAX_TE_TEXT_LEN - NUMsoCOLS)
35 
36 /******************************************************************************
37 * Local function prototypes.
38 ******************************************************************************/
39 
40 static void FlashButton PROTOARGs((DialogPtr dialog, int itemN));
41 static void delay PROTOARGs((double seconds));
42 static void UpdateCursorSO PROTOARGs((EventRecord *event));
43 static void SaveStatusLine PROTOARGs((char *text));
44 
45 /******************************************************************************
46 * MacExecuteSO.
47 ******************************************************************************/
48 
49 void MacExecuteSO (exeFnc, qopFnc)
50 Logical (*exeFnc) PROTOARGs((int argC, char *argV[]));
51 Logical (*qopFnc) PROTOARGs((int *argC, char **argV[]));
52 {
53   int argC; char **argV; EventRecord event; WindowPtr whichWindow;
54   InitMacUI ();
55   InitMacMenusSO ();
56   if (!(*qopFnc)(&argC,&argV)) return;
57   InitMacSO ();
58   MacExecuteTimer (exeFnc, argC, argV);
59   UpdateSOscrollBars ();
60   FreeMacQOPs (argC, argV);
61   for (;;) {
62      SystemTask ();
63      TEIdle (soTextH);
64      GetNextEvent (everyEvent, &event);
65        switch (event.what) {
66          /*********************************************************************
67          * Check if a null event;
68          *********************************************************************/
69          case nullEvent:
70            UpdateCursorSO (&event);
71            break;
72          /*********************************************************************
73          * Check if a mouse down event.
74          *********************************************************************/
75          case mouseDown: {
76 	   switch (FindWindow(event.where,&whichWindow)) {
77              /*****************************************************************
78              * Check if mouse down in menu bar.
79              *****************************************************************/
80              case inMenuBar: {
81                long tempL = MenuSelect (event.where);
82                short menuId = HighSHORTinLONG (tempL);
83                short itemN = LowSHORTinLONG (tempL);
84                switch (menuId) {
85 	         case APPLEmi:
86 	           switch (itemN) {
87 	             case ABOUTin:
88 	               DisplayAbout ();
89 	               break;
90 	             default: {
91 	               Str255 name;
92 	               GetItem (appleMenuHso, itemN, name);
93 	               OpenDeskAcc (name);
94 	               SetPort (soWindowP);
95 	               break;
96 	             }
97 	           }
98 	           break;
99                  case FILEmi:
100                    switch (itemN) {
101                      case EXECUTEin:
102 		       if ((*qopFnc)(&argC,&argV)) {
103 		         MacExecuteTimer (exeFnc, argC, argV);
104 		         UpdateSOscrollBars ();
105 		         FreeMacQOPs (argC, argV);
106 		       }
107                        break;
108                      case SAVEinFILE:
109                        SaveSO (FALSE);
110                        break;
111                      case SAVEASinFILE:
112                        SaveSO (TRUE);
113                        break;
114                      case CLEARinFILE:
115                        ResetSO (TRUE);
116                        break;
117                      case QUITin:
118                        return;
119                    }
120                    break;
121                }
122                HiliteMenu (0);
123                break;
124              }
125              /*****************************************************************
126              * Check for mouse down in drag region of a window.
127              *****************************************************************/
128              case inDrag: {
129                RectPtr screen = &qd.screenBits.bounds;
130                Rect dragRect;
131                dragRect.top = screen->top + 40;
132                dragRect.left = screen->left + 40;
133                dragRect.bottom = screen->bottom - 40;
134                dragRect.right = screen->right - 40;
135                DragWindow (whichWindow, event.where, &dragRect);
136                break;
137              }
138              /*****************************************************************
139              * Check for mouse down in system window.
140              *****************************************************************/
141              case inSysWindow:
142                SystemClick (&event, whichWindow);
143                break;
144              /*****************************************************************
145              * Check for mouse down in body of a window.
146              *****************************************************************/
147              case inContent: {
148                Point tPoint = event.where; ControlHandle controlHandle;
149                short partCode;
150                GlobalToLocal (&tPoint);
151                partCode = FindControl (tPoint, whichWindow, &controlHandle);
152                if (partCode != 0) {
153                  float pct;
154                  short delta, toBottom, value, newAtPointV;
155                  long ref = GetCRefCon (controlHandle);
156                  switch (ref) {
157                    case VSCROLLsoREFCON:
158 		     switch (partCode) {
159 		       case inUpButton:
160 			 if (soAtPoint.v > 0) {
161 			   delta = MINIMUM (soLineHeight, soAtPoint.v);
162                            TEScroll ((short) 0, delta, soTextH);
163 			   soAtPoint.v -= delta;
164 			 }
165 			 break;
166 		       case inDownButton:
167 		         toBottom = ToBottom (soTextH, soAtPoint);
168 			 if (toBottom > 0) {
169 			   delta = MINIMUM (soLineHeight, toBottom);
170                            TEScroll ((short) 0, -delta, soTextH);
171 			   soAtPoint.v += delta;
172 			 }
173 			 break;
174 		       case inPageUp:
175 		         if (soAtPoint.v > 0) {
176 			   delta = MINIMUM (soViewHeight, soAtPoint.v);
177 		           TEScroll ((short) 0, delta, soTextH);
178 			   soAtPoint.v -= delta;
179 			 }
180 			 break;
181 		       case inPageDown:
182 		         toBottom = ToBottom (soTextH, soAtPoint);
183 			 if (toBottom > 0) {
184 		           delta = MINIMUM (soViewHeight, toBottom);
185 			   TEScroll ((short) 0, -delta, soTextH);
186 			   soAtPoint.v += delta;
187 			 }
188 			 break;
189 		       case inThumb:
190 			 if (TrackControl(controlHandle,tPoint,NULL) != 0) {
191                            if (soDestHeight > soViewHeight) {
192 			     value = GetCtlValue (controlHandle);
193 			     pct = ((float) value) /
194 				   ((float) (SCROLLsoMAX - SCROLLsoMIN));
195 			     newAtPointV = soDestHeight * pct;
196 			     newAtPointV -= (newAtPointV % soLineHeight);
197 			     delta = newAtPointV - soAtPoint.v;
198 			     TEScroll ((short) 0, -delta, soTextH);
199 			     soAtPoint.v = newAtPointV;
200 			   }
201 			 }
202 		         break;
203 		     }
204 		     UpdateSOscrollBars ();
205                      break;
206                  }
207                }
208                break;
209              }
210            }
211            break;
212 	 }
213          /*********************************************************************
214          * Check if a key down event.
215          *********************************************************************/
216          case keyDown:
217          case autoKey: {
218            char keyCode = (char) ((event.message & keyCodeMask) >> 8);
219            short delta, toBottom;
220            switch (keyCode) {
221              case PAGEup_KEYCODE:
222 	       if (soAtPoint.v > 0) {
223 		 delta = MINIMUM (soViewHeight, soAtPoint.v);
224 		 TEScroll ((short) 0, delta, soTextH);
225 	         soAtPoint.v -= delta;
226 	       }
227                break;
228              case PAGEdown_KEYCODE:
229 	       toBottom = ToBottom (soTextH, soAtPoint);
230 	       if (toBottom > 0) {
231 		 delta = MINIMUM (soViewHeight, toBottom);
232 		 TEScroll ((short) 0, -delta, soTextH);
233 		 soAtPoint.v += delta;
234 	       }
235                break;
236              case R_KEYCODE:
237                if ((event.modifiers & cmdKey) != 0) {
238 	         if ((*qopFnc)(&argC,&argV)) {
239 	           MacExecuteTimer (exeFnc, argC, argV);
240 	           UpdateSOscrollBars ();
241 	           FreeMacQOPs (argC, argV);
242 	         }
243                }
244                break;
245              case S_KEYCODE:
246                if ((*soTextH)->teLength > 0) SaveSO (FALSE);
247                break;
248              case Q_KEYCODE:
249                if ((event.modifiers & cmdKey) != 0) return;
250                break;
251              default:
252                break;
253            }
254            UpdateSOscrollBars ();
255            break;
256          }
257          /*********************************************************************
258          * Check for an activation event (activate or deactivate).
259          *********************************************************************/
260          case activateEvt:
261            if ((event.modifiers & activeFlag) != 0) {
262              TEActivate (soTextH);
263              ShowControl (soVscrollH);
264              SetCursor (CDF_CURSOR);
265            }
266            else {
267              TEDeactivate (soTextH);
268              HideControl (soVscrollH);
269            }
270            break;
271          /*********************************************************************
272          * Check for an update event for a window.
273          *********************************************************************/
274          case updateEvt: {
275            BeginUpdate ((WindowPtr) event.message);
276            EraseRect (&soTextRect);
277            TEUpdate (&soTextRect, soTextH);
278            DrawControls (soWindowP);
279            DrawStatusLine (NULL);
280            EndUpdate ((WindowPtr) event.message);
281            break;
282          }
283        }
284   }
285 
286 }
287 
288 /******************************************************************************
289 * MacExecuteTimer.
290 ******************************************************************************/
291 
292 void MacExecuteTimer (exeFnc, argC, argV)
293 Logical (*exeFnc) PROTOARGs((int argC, char *argV[]));
294 int argC;
295 char *argV[];
296 {
297   char text[SO_STATUS_LINE_LEN+1]; clock_t endClock, totalClock;
298   int hour, minute, second, hundredths, i;
299   ResetSO (FALSE);
300   if ((*soTextH)->teLength > 0) {
301     TEScroll ((short) 0, -soLineHeight, soTextH);
302     soAtPoint.v += soLineHeight;
303     for (i = 0; i < NUMsoCOLS - 1; i++) WriteOut (stdout, "-");
304     WriteOut (stdout, "\n");
305   }
306   strcpyX (text, "Executing...", 0);
307   CatNcharacters (text, 46, (int) ' ');
308   strcatX (text, "Elapsed time: 00:00:00.00", 0);
309   DrawStatusLine (text);
310   startClock = clock ();
311   lastSecond = 0;
312   (*exeFnc) (argC, argV);
313   endClock = clock ();
314   totalClock = endClock - startClock;
315   hour = (int) ((totalClock / CLOCKS_PER_SEC) / 3600);
316   minute = (int) ((totalClock / CLOCKS_PER_SEC) / 60);
317   second = (int) ((totalClock / CLOCKS_PER_SEC) % 60);
318   hundredths = (int) (((totalClock % CLOCKS_PER_SEC) * 100) / CLOCKS_PER_SEC);
319   strcpyX (text, "Executing...complete.", 0);
320   CatNcharacters (text, 37, (int) ' ');
321   sprintf (EofS(text), "Elapsed time: %02d:%02d:%02d.%02d",
322 	   hour, minute, second, hundredths);
323   DrawStatusLine (text);
324   return;
325 }
326 
327 /******************************************************************************
328 * InitMacUI.
329 *   Initialize the Macintosh User Interface.
330 ******************************************************************************/
331 
InitMacUI()332 void InitMacUI () {
333   InitGraf (&qd.thePort);
334   InitFonts ();
335   FlushEvents ((short) everyEvent, (short) 0);
336   InitWindows ();
337   TEInit ();
338   InitDialogs (NULL);
339   InitCursor ();
340   return;
341 }
342 
343 /******************************************************************************
344 * InitMacSO.
345 *   Initialize the Macintosh standard output window.
346 ******************************************************************************/
347 
InitMacSO()348 void InitMacSO () {
349   static WindowRecord wRecord;
350   WindowPtr behindWindow = (WindowPtr) -1;   /* On top of all other windows. */
351   soWindowP = GetNewWindow (SOri, &wRecord, behindWindow);
352   ShowWindow (soWindowP);
353   SetPort (soWindowP);
354   TextFont (monaco);
355   soTextRect.top = MARGINsoSIZE;
356   soTextRect.left = MARGINsoSIZE;
357   soTextRect.bottom = MARGINsoSIZE + (NUMsoROWS * FONTsoHEIGHT);
358   soTextRect.right = MARGINsoSIZE + (NUMsoCOLS * FONTsoWIDTH);
359   soTextH = TENew (&soTextRect, &soTextRect);
360   soViewHeight = soTextRect.bottom - soTextRect.top;
361   soLineHeight = (*soTextH)->lineHeight;
362   soNviewLines = soViewHeight / soLineHeight;
363   soDestHeight = 0;
364   soAtPoint.v = 0;
365   soVscrollH = GetNewControl (SOSCROLLri, soWindowP);
366   soStatusRect.top = WINDOWsoHEIGHT - STATUSareaHEIGHT;
367   soStatusRect.left = 0;
368   soStatusRect.bottom = WINDOWsoHEIGHT;
369   soStatusRect.right = WINDOWsoWIDTH;
370   DrawStatusLine (NULL);
371   return;
372 }
373 
374 /******************************************************************************
375 * InitMacMenusSO.
376 *   Initialize the Macintosh menus for the standard output window.
377 ******************************************************************************/
378 
InitMacMenusSO()379 void InitMacMenusSO () {
380   appleMenuHso = GetMenu (APPLEri);
381   AddResMenu (appleMenuHso, *((long *) "DRVR"));
382   InsertMenu (appleMenuHso, 0);
383   fileMenuHso = GetMenu (FILEri);
384   InsertMenu (fileMenuHso, 0);
385   DrawMenuBar ();
386   DisableItem (fileMenuHso, SAVEinFILE);
387   DisableItem (fileMenuHso, SAVEASinFILE);
388   DisableItem (fileMenuHso, CLEARinFILE);
389   return;
390 }
391 
392 /******************************************************************************
393 * UpdateCursorSO.
394 ******************************************************************************/
395 
UpdateCursorSO(event)396 static void UpdateCursorSO (event)
397 EventRecord *event;
398 {
399   WindowPtr whichWindow;
400   switch (FindWindow(event->where,&whichWindow)) {
401     case inContent: {
402       Point tPoint = event->where; ControlHandle controlHandle;
403       GlobalToLocal (&tPoint);
404       if (FindControl(tPoint,whichWindow,&controlHandle) == 0)
405         SetCursor (CDF_CURSOR);
406       else
407         SetCursor (ARROW_CURSOR);
408       break;
409     }
410     default:
411       SetCursor (ARROW_CURSOR);
412       break;
413   }
414   return;
415 }
416 
417 /******************************************************************************
418 * MacMessageDialog.
419 ******************************************************************************/
420 
MacMessageDialog(severityText,messageText)421 void MacMessageDialog (severityText, messageText)
422 char *severityText;
423 char *messageText;
424 {
425   DialogRecord dRecord; DialogPtr dialogP; static Rect rect0s = { 0,0,0,0 };
426   WindowPtr behind = (WindowPtr) -1;
427 #ifndef __MWERKS__
428   short itemN;
429 #else
430   SInt16 itemN;
431   UserItemUPP OutlineDefaultButtonUPP;
432   OutlineDefaultButtonUPP = NewUserItemProc (OutlineDefaultButton);
433 #endif
434   ParamText (CtoPstr(severityText), CtoPstr(messageText),
435 	     CtoPstr(""), CtoPstr(""));
436   PtoCstr ((uChar *) severityText);
437   PtoCstr ((uChar *) messageText);
438   dialogP = GetNewDialog (MESSAGEri, &dRecord, behind);
439 #ifndef __MWERKS__
440   SetDItem (dialogP, (short) ODBinMD, (short) userItem,
441 	    	(Handle) OutlineDefaultButton, &rect0s);
442 #else
443   SetDItem (dialogP, (short) ODBinMD, (short) userItem,
444 	    	(Handle) OutlineDefaultButtonUPP, &rect0s);
445 #endif
446   if (soWindowP != NULL) {				/* Only if SO. */
447     HideControl (soVscrollH);
448     TEDeactivate (soTextH);
449   }
450   ShowWindow ((WindowPtr) dialogP);
451   ModalDialog (NULL, &itemN);
452   CloseDialog (dialogP);
453   if (soWindowP != NULL) {				/* Only if SO. */
454     ShowControl (soVscrollH);
455     TEActivate (soTextH);
456   }
457   return;
458 }
459 
460 /******************************************************************************
461 * DrawStatusLine.
462 * Note that `soStatusLine' is blank padded just in case it got shorter.
463 ******************************************************************************/
464 
DrawStatusLine(text)465 void DrawStatusLine (text)
466 char *text;
467 {
468   int i;
469   MoveTo ((short) soStatusRect.left, (short) soStatusRect.top);
470   LineTo ((short) soStatusRect.right, (short) soStatusRect.top);
471   MoveTo ((short) (soStatusRect.left + 2), (short) (soStatusRect.bottom - 4));
472   TextFont (monaco);
473   TextMode (srcCopy);
474   if (text != NULL) strcpyX (soStatusLine, text, SO_STATUS_LINE_LEN);
475   for (i = strlen(soStatusLine); i < SO_STATUS_LINE_LEN; i++) {
476      soStatusLine[i] = ' ';
477   }
478   CtoPstr (soStatusLine);
479   DrawString ((uChar *) soStatusLine);
480   PtoCstr ((uChar *) soStatusLine);
481   return;
482 }
483 
484 /******************************************************************************
485 * SaveStatusLine.
486 ******************************************************************************/
487 
SaveStatusLine(text)488 static void SaveStatusLine (text)
489 char *text;
490 {
491   strcpyX (text, soStatusLine, SO_STATUS_LINE_LEN);
492   return;
493 }
494 
495 /******************************************************************************
496 * FreeMacQOPs.
497 ******************************************************************************/
498 
FreeMacQOPs(argC,argV)499 void FreeMacQOPs (argC, argV)
500 int argC;
501 char *argV[];
502 {
503   int argN;
504   for (argN = 0; argN < argC; argN++) cdf_FreeMemory (argV[argN], FatalError);
505   cdf_FreeMemory (argV, FatalError);
506   return;
507 }
508 
509 /******************************************************************************
510 * CalcBounds.
511 ******************************************************************************/
512 
CalcBounds(rect,width,height,topPct,leftPct)513 void CalcBounds (rect, width, height, topPct, leftPct)
514 Rect *rect;
515 int width;
516 int height;
517 double topPct;
518 double leftPct;
519 {
520   Rect screenRect = qd.screenBits.bounds;
521   short screenWidth = screenRect.right - screenRect.left;
522   short screenHeight = screenRect.bottom - screenRect.top;
523   rect->left = (screenWidth - width) * leftPct;
524   rect->right = rect->left + width;
525   rect->top = ((screenHeight -
526   		MENUbarHEIGHT -
527   	        TITLEbarHEIGHT -
528   	        height) * topPct) + MENUbarHEIGHT + TITLEbarHEIGHT;
529   rect->bottom = rect->top + height;
530   return;
531 }
532 
533 /******************************************************************************
534 * ResetSO.
535 ******************************************************************************/
536 
ResetSO(clear)537 void ResetSO (clear)
538 Logical clear;
539 {
540   if (clear) {
541     TEScroll ((short) 0, soAtPoint.v, soTextH);
542     soAtPoint.v = 0;
543     TESetSelect (0L, (long) (*soTextH)->teLength, soTextH);
544     TEDelete (soTextH);
545     TESetSelect (0L, 0L, soTextH);
546     soDestHeight = 0;
547     DisableItem (fileMenuHso, SAVEinFILE);
548     DisableItem (fileMenuHso, SAVEASinFILE);
549     DisableItem (fileMenuHso, CLEARinFILE);
550   }
551   else {
552     short toBottom = ToBottom (soTextH, soAtPoint);
553     if (toBottom > 0) {
554       TEScroll ((short) 0, -toBottom, soTextH);
555       soAtPoint.v += toBottom;
556     }
557   }
558   UpdateSOscrollBars ();
559   soLineCount = 0;
560   return;
561 }
562 
563 /******************************************************************************
564 * UpdateSOscrollBars.
565 * Currently only a vertical scroll bar is used.
566 ******************************************************************************/
567 
UpdateSOscrollBars(void)568 void UpdateSOscrollBars (void) {
569   float pct = BOO(soDestHeight == 0,0.0,
570 		  ((float) soAtPoint.v) / ((float) soDestHeight));
571   short value = SCROLLsoMIN + (pct * (SCROLLsoMAX - SCROLLsoMIN));
572   SetCtlValue (soVscrollH, value);
573   return;
574 }
575 
576 /******************************************************************************
577 * SaveSO.
578 * Returns TRUE if the standard output was successfully saved.
579 ******************************************************************************/
580 
SaveSO(as)581 Logical SaveSO (as)
582 Logical as;		/* If TRUE, prompt for file in which to save output. */
583 {
584   Logical overWrite = FALSE;
585   char errorMsg[] = "Unable to save output.";
586   char fileName[DU_MAX_PATH_LEN+1], a_mode[1+1];
587   FILE *fp;
588   /****************************************************************************
589   * If necessary, prompt for file.
590   ****************************************************************************/
591   if (as) {
592     StandardFileReply reply;
593     char prompt[] = "Enter output file:";
594     char defaultName[] = "";
595     StandardPutFile (CtoPstr(prompt), CtoPstr(defaultName), &reply);
596     if (reply.sfGood) {
597       BuildMacPath (&reply.sfFile, fileName, FALSE);
598       if (reply.sfReplacing) overWrite = TRUE;
599     }
600     else
601       return FALSE;
602   }
603   else {
604     strcpyX (fileName, pgmName, DU_MAX_NAME_LEN);
605     strcatX (fileName, ".so", DU_MAX_NAME_LEN);
606     MakeLowerString (fileName);
607   }
608   /****************************************************************************
609   * If the file exists, prompt for what to do.
610   ****************************************************************************/
611   if (IsReg(fileName)) {
612     if (!overWrite) {
613       DialogPtr dialog; DialogRecord dRecord;
614       static Rect rect0s = { 0,0,0,0 }; WindowPtr behind = (WindowPtr) -1;
615 #ifndef __MWERKS__
616 	  short itemN;
617 #else
618 	  SInt16 itemN;
619 	  UserItemUPP OutlineDefaultButtonUPP;
620 	  OutlineDefaultButtonUPP = NewUserItemProc (OutlineDefaultButton);
621 #endif
622       ParamText (CtoPstr(fileName),CtoPstr(""),CtoPstr(""),CtoPstr(""));
623       PtoCstr ((uChar *) fileName);
624       dialog = GetNewDialog (OFEXISTSri, &dRecord, behind);
625 #ifndef __MWERKS__
626       SetDItem (dialog, (short) ODBinEXISTS, (short) userItem,
627 		        (Handle) OutlineDefaultButton, &rect0s);
628 #else
629       SetDItem (dialog, (short) ODBinEXISTS, (short) userItem,
630 				(Handle) OutlineDefaultButtonUPP, &rect0s);
631 #endif
632       HideControl (soVscrollH);
633       TEDeactivate (soTextH);
634       ShowWindow ((WindowPtr) dialog);
635       SetCursor (ARROW_CURSOR);
636       ModalDialog (NULL, &itemN);
637       CloseDialog (dialog);
638       TEActivate (soTextH);
639       ShowControl (soVscrollH);
640       switch (itemN) {
641         case OVERinEXISTS:
642           strcpyX (a_mode, "w", 0);
643           break;
644         case APPENDinEXISTS:
645           strcpyX (a_mode, "a", 0);
646           break;
647         case CANCELinEXISTS:
648           return FALSE;
649       }
650     }
651     else
652       strcpyX (a_mode, "w", 0);
653   }
654   else
655     strcpyX (a_mode, "w", 0);
656   /****************************************************************************
657   * Open file.
658   ****************************************************************************/
659   fp = fopen (fileName, a_mode);
660   if (fp == NULL) {
661     DisplayError (errorMsg);
662     return FALSE;
663   }
664   /****************************************************************************
665   * Write to the file.
666   ****************************************************************************/
667   if ((*soTextH)->teLength > 0) {
668     if (fwrite (*((*soTextH)->hText),(*soTextH)->teLength,1,fp) != 1) {
669       DisplayError (errorMsg);
670       fclose (fp);
671       return FALSE;
672     }
673   }
674   /****************************************************************************
675   * Close file.
676   ****************************************************************************/
677   if (fclose(fp) == EOF) {
678     DisplayError (errorMsg);
679     return FALSE;
680   }
681   return TRUE;
682 }
683 
684 /******************************************************************************
685 * BuildMacPath.
686 ******************************************************************************/
687 
688 #define ROOT_dirID	2
689 
BuildMacPath(spec,path,stripExt)690 Logical BuildMacPath (spec, path, stripExt)
691 FSSpec *spec;			/* In: File specification from File Manager. */
692 char path[DU_MAX_PATH_LEN+1];	/* Out: Full/relative path. */
693 Logical stripExt;		/* In: If TRUE, strip off file extension. */
694 {
695   long parID = spec->parID,	/* Parent directory identifier. */
696        curID;			/* Current directory identifier. */
697   CInfoPBRec pb;
698   char dir[DU_MAX_DIR_LEN+1];
699   HGetVol (NULL, NULL, &curID);
700   PstrcpyX (path, (char *) spec->name, DU_MAX_PATH_LEN);
701   if (stripExt) {
702     char *dot = strchr (path, '.');
703     if (dot != NULL) *dot = NUL;
704   }
705   if (parID == curID) return TRUE;
706   pb.dirInfo.ioCompletion = NULL;
707   pb.dirInfo.ioNamePtr = (StringPtr) dir;
708   pb.dirInfo.ioVRefNum = spec->vRefNum;
709   pb.dirInfo.ioFDirIndex = -1;
710   while (parID != ROOT_dirID) {
711     pb.dirInfo.ioDrDirID = parID;
712     if (PBGetCatInfo(&pb,FALSE) != noErr) return FALSE;
713     prependX (path, ":", DU_MAX_PATH_LEN);
714     PprependX (path, (char *) pb.dirInfo.ioNamePtr, DU_MAX_PATH_LEN);
715     parID = pb.dirInfo.ioDrParID;
716     if (parID == curID) {
717       prependX (path, ":", DU_MAX_PATH_LEN);
718       return TRUE;
719     }
720   }
721   pb.dirInfo.ioDrDirID = parID;
722   if (PBGetCatInfo(&pb,FALSE) != noErr) return FALSE;
723   prependX (path, ":", DU_MAX_PATH_LEN);
724   PprependX (path, (char *) pb.dirInfo.ioNamePtr, DU_MAX_PATH_LEN);
725   return TRUE;
726 }
727 
728 /******************************************************************************
729 * DisplayAbout.
730 ******************************************************************************/
731 
DisplayAbout()732 void DisplayAbout () {
733   DialogRecord dRecord;
734   DialogPtr dialogP;
735   WindowPtr behind = (WindowPtr) -1;
736   char tempS[15+1], subIncrement;
737   long version, release, increment;
738 #ifndef __MWERKS__
739   short itemN;
740 #else
741   SInt16 itemN;
742 #endif
743   CDFlib (GET_, LIB_VERSION_, &version,
744 	        LIB_RELEASE_, &release,
745 	        LIB_INCREMENT_, &increment,
746 	        LIB_subINCREMENT_, &subIncrement,
747 	  NULL_);
748   sprintf (tempS, "V%ld.%ld.%ld%c", version, release, increment, subIncrement);
749   ParamText (CtoPstr(tempS), CtoPstr(""), CtoPstr(""), CtoPstr(""));
750   dialogP = GetNewDialog (ABOUTri, &dRecord, behind);
751   ShowWindow ((WindowPtr) dialogP);
752   ModalDialog (NULL, &itemN);
753   CloseDialog (dialogP);
754   return;
755 }
756 
757 /******************************************************************************
758 * WriteOutMacSO.
759 ******************************************************************************/
760 
WriteOutMacSO(text)761 void WriteOutMacSO (text)
762 char *text;
763 {
764   char *ptr = text, *ptrNL; size_t len;
765   /**************************************************************************
766   * If paging is on, first prompt for `more...' if the end of the standard
767   * output screen has been reached.
768   **************************************************************************/
769   for (;;) {
770      /***********************************************************************
771      * If the maximum number of lines have been written that will fit on
772      * the screen, then if paging prompt for RETURN before resetting the SO
773      * window, otherwise automatically reset the SO window.
774      ***********************************************************************/
775      if (soLineCount == MAX_LINES_WHEN_PAGING) {
776        if (pagingOn) {
777 	 	char key = NUL; char savedStatusLine[SO_STATUS_LINE_LEN+1];
778 	 	SaveStatusLine (savedStatusLine);
779 	 	DrawStatusLine ("Enter RETURN for more...");
780 	 	MacReadKeySO (&key);
781 	 	if (key != '\r' && key != '\n') pagingOn = FALSE;
782 	 	ResetSO (FALSE);
783 	 	DrawStatusLine (savedStatusLine);
784 	 	soLineCount = 0;
785        }
786        else
787 	 	ResetSO (FALSE);
788      }
789      /***********************************************************************
790      * Write the string up to the next newline character.  If there aren't
791      * any(more) newline characters, write the rest of the string.
792      ***********************************************************************/
793      ptrNL = strchr (ptr, Nl);
794      if (ptrNL == NULL) {
795        len = strlen (ptr);
796        if (len + (*soTextH)->teLength > MAX_TE_TEXT_LEN) MacSOoverFlow ();
797        WriteStringSO (ptr, len);
798        break;
799      }
800      else {
801        len = (int) (ptrNL - ptr + 1);
802        if (len + (*soTextH)->teLength > MAX_TE_TEXT_LEN) MacSOoverFlow ();
803        WriteStringSO (ptr, len);
804        if ((*soTextH)->teLength > MAX_TE_TEXT_LEN_wNL)
805 	 	 MacSOoverFlow ();
806        else
807 	 	 soLineCount++;
808        ptr = ptrNL + 1;
809        if (*ptr == NUL) break;
810      }
811   }
812   return;
813 }
814 
815 /******************************************************************************
816 * WriteStringSO.
817 * `TEKey' is used if the string contains one or more backspace characters
818 * because `TEInsert' doesn't handle them properly.  Also, all newline
819 * characters must first be converted to carriage return characters (for
820 * TextEdit).  Note that because MPW C has reversed the values normally
821 * associated with '\r' and '\n', the actual numeric values must be used
822 * ('\015' and '\012', respectively).
823 ******************************************************************************/
824 
WriteStringSO(string,length)825 void WriteStringSO (string, length)
826 char *string;
827 size_t length;
828 {
829   int i; char *ptr;
830   if (length > 0 && (*soTextH)->teLength == 0) {
831     EnableItem (fileMenuHso, SAVEinFILE);
832     EnableItem (fileMenuHso, SAVEASinFILE);
833     EnableItem (fileMenuHso, CLEARinFILE);
834   }
835   ptr = (char *) cdf_AllocateMemory (length + 1, FatalError);
836   strcpyX (ptr, string, length);
837   for (i = 0; ptr[i] != NUL; i++) if (ptr[i] == '\012') ptr[i] = '\015';
838   if (strchr(ptr,Bs) != NULL) {
839     for (i = 0; ptr[i] != NUL; i++) TEKey (ptr[i], soTextH);
840   }
841   else
842     TEInsert (ptr, (long) length, soTextH);
843   cdf_FreeMemory (ptr, FatalError);
844   soDestHeight = (*soTextH)->nLines * soLineHeight;
845   return;
846 }
847 
848 /******************************************************************************
849 * MacSOoverFlow.
850 ******************************************************************************/
851 
MacSOoverFlow()852 void MacSOoverFlow () {
853   DialogPtr dialog; DialogRecord dRecord;
854   WindowPtr behind = (WindowPtr) -1; static Rect rect0s = { 0,0,0,0 };
855   char savedStatusLine[SO_STATUS_LINE_LEN+1];
856 #ifndef __MWERKS__
857   short itemN;
858 #else
859   SInt16 itemN;
860   UserItemUPP OutlineDefaultButtonUPP;
861   OutlineDefaultButtonUPP = NewUserItemProc (OutlineDefaultButton);
862 #endif
863   SaveStatusLine (savedStatusLine);
864   DrawStatusLine ("");
865   dialog = GetNewDialog (SOOFLOWri, &dRecord, behind);
866 #ifndef __MWERKS__
867   SetDItem (dialog, (short) ODBinOFLOW, (short) userItem,
868 		    (Handle) OutlineDefaultButton, &rect0s);
869 #else
870   SetDItem (dialog, (short) ODBinOFLOW, (short) userItem,
871 		    (Handle) OutlineDefaultButtonUPP, &rect0s);
872 #endif
873   HideControl (soVscrollH);
874   TEDeactivate (soTextH);
875   ShowWindow ((WindowPtr) dialog);
876   SetCursor (ARROW_CURSOR);
877   ModalDialog (NULL, &itemN);
878   CloseDialog (dialog);
879   TEActivate (soTextH);
880   ShowControl (soVscrollH);
881   switch (itemN) {
882     case SAVEinOFLOW:
883       SaveSO (FALSE);
884       break;
885     case SAVEASinOFLOW:
886       SaveSO (TRUE);
887       break;
888     case CLEARinOFLOW:
889       break;
890     case ABORTinOFLOW:
891       Exit;
892   }
893   ResetSO (TRUE);
894   DrawStatusLine (savedStatusLine);
895 }
896 
897 /******************************************************************************
898 * MacReadKeySO.
899 *   Read a character from the keyboard.  This routine should only be used in
900 * `standard output' programs.
901 ******************************************************************************/
902 
MacReadKeySO(key)903 void MacReadKeySO (key)
904 char *key;
905 {
906   EventRecord event;
907   for (;;) {
908      SystemTask ();
909      TEIdle (soTextH);
910      GetNextEvent(everyEvent,&event);
911      switch (event.what) {
912        /*********************************************************************
913        * Null event.
914        *********************************************************************/
915        case nullEvent:
916          UpdateCursorSO (&event);
917 		 break;
918        /*********************************************************************
919        * Key down event.
920        *********************************************************************/
921        case keyDown: {
922 		 if (ABORTkeyMAC(event)) {
923 	   		cdf_FreeMemory (NULL, FatalError);
924 	   		Exit;
925 	 	 }
926          *key = (char) (event.message & charCodeMask);
927 	 	 return;
928        }
929        /*********************************************************************
930        * Check for an activation event (activate or deactivate).
931        *********************************************************************/
932        case activateEvt:
933 		 if ((event.modifiers & activeFlag) != 0) {
934 		   TEActivate (soTextH);
935 		   ShowControl (soVscrollH);
936 	 	   SetCursor (CDF_CURSOR);
937 		 }
938 	 	 else {
939 	 	   TEDeactivate (soTextH);
940 	 	   HideControl (soVscrollH);
941 		 }
942 	 	 break;
943        /*********************************************************************
944        * Check for an update event for a window.
945        *********************************************************************/
946        case updateEvt: {
947 		 BeginUpdate ((WindowPtr) event.message);
948 		 EraseRect (&soTextRect);
949 		 TEUpdate (&soTextRect, soTextH);
950 		 DrawControls (soWindowP);
951 	  	 DrawStatusLine (NULL);
952 	 	 EndUpdate ((WindowPtr) event.message);
953 	 	 break;
954        }
955      }
956   }
957 }
958 
959 /******************************************************************************
960 * CheckForAbortSOmac.
961 ******************************************************************************/
962 
CheckForAbortSOmac()963 void CheckForAbortSOmac () {
964   EventRecord event; clock_t currentClock, totalClock;
965   int hour, minute, second; char text[SO_STATUS_LINE_LEN+1];
966   SystemTask ();
967   TEIdle (soTextH);
968   GetNextEvent (everyEvent, &event);
969   switch (event.what) {
970     case nullEvent:
971       break;
972     case mouseDown: {
973       WindowPtr whichWindow;
974       switch (FindWindow(event.where,&whichWindow)) {
975         case inMenuBar:
976 	  break;
977         case inDrag: {
978           RectPtr screen = &qd.screenBits.bounds; Rect dragRect;
979           dragRect.top = screen->top + 40;
980           dragRect.left = screen->left + 40;
981           dragRect.bottom = screen->bottom - 40;
982           dragRect.right = screen->right - 40;
983           DragWindow (whichWindow, event.where, &dragRect);
984           break;
985 		}
986         case inSysWindow:
987           SystemClick (&event, whichWindow);
988           break;
989         case inContent:
990 	  break;
991       }
992     }
993     case keyDown:
994       if (ABORTkeyMAC(event)) {
995 		cdf_FreeMemory (NULL, FatalError);
996 		Exit;
997       }
998       break;
999     case activateEvt:
1000       if ((event.modifiers & activeFlag) != 0) {
1001         TEActivate (soTextH);
1002         ShowControl (soVscrollH);
1003 		SetCursor (CDF_CURSOR);
1004       }
1005       else {
1006         TEDeactivate (soTextH);
1007         HideControl (soVscrollH);
1008       }
1009       break;
1010     case updateEvt:
1011       BeginUpdate ((WindowPtr) event.message);
1012       EraseRect (&soTextRect);
1013       TEUpdate (&soTextRect, soTextH);
1014       DrawControls (soWindowP);
1015       DrawStatusLine (NULL);
1016       EndUpdate ((WindowPtr) event.message);
1017       break;
1018   }
1019   currentClock = clock ();
1020   totalClock = currentClock - startClock;
1021   second = (totalClock / CLOCKS_PER_SEC) % 60;
1022   if (second != lastSecond) {
1023     hour = (totalClock / CLOCKS_PER_SEC) / 3600;
1024     minute = (totalClock / CLOCKS_PER_SEC) / 60;
1025     strcpyX (text, "Executing...", 0);
1026     CatNcharacters (text, 46, (int) ' ');
1027     sprintf (EofS(text), "Elapsed time: %02d:%02d:%02d.00",
1028 	     hour, minute, second);
1029     DrawStatusLine (text);
1030     lastSecond = second;
1031     UpdateCursorSO (&event);
1032   }
1033   return;
1034 }
1035 
1036 /******************************************************************************
1037 * OutlineDefaultButton.
1038 ******************************************************************************/
1039 #ifndef __MWERKS__
OutlineDefaultButton(window,itemN)1040 pascal void OutlineDefaultButton (window, itemN)
1041 DialogPtr window;
1042 short itemN;
1043 #else
1044 pascal void OutlineDefaultButton (DialogPtr window, SInt16 itemN)
1045 #endif
1046 {
1047   short itemType; Handle handle; Rect rect;
1048   itemN = 1;	/* Set to default button's item number. */
1049   GetDItem ((DialogPtr) window, itemN, &itemType, &handle, &rect);
1050   PenSize ((short) 3, (short) 3);
1051   InsetRect (&rect, (short) -4, (short) -4);
1052   FrameRoundRect (&rect, (short) 22, (short) 22);
1053   PenNormal ();
1054   return;
1055 }
1056 
1057 /******************************************************************************
1058 * FilterForSKTs.
1059 ******************************************************************************/
1060 
FilterForSKTs(pb)1061 pascal Boolean FilterForSKTs (pb)
1062 ParmBlkPtr pb;
1063 {
1064   char *name = PtoCstr (pb->fileParam.ioNamePtr);
1065   Boolean filterOut = (!Trailer(name,".skt") && !Trailer(name,".SKT") &&
1066 		       !Trailer(name,".skt;1") && !Trailer(name,".SKT;1"));
1067   CtoPstr (name);
1068   return filterOut;
1069 }
1070 
1071 /******************************************************************************
1072 * FilterForCDFs.
1073 ******************************************************************************/
1074 
FilterForCDFs(pb)1075 pascal Boolean FilterForCDFs (pb)
1076 ParmBlkPtr pb;
1077 {
1078   char *name = PtoCstr (pb->fileParam.ioNamePtr);
1079   Boolean filterOut = (!Trailer(name,".cdf") && !Trailer(name,".CDF") &&
1080 		       !Trailer(name,".cdf;1") && !Trailer(name,".CDF;1"));
1081   CtoPstr (name);
1082   return filterOut;
1083 }
1084 
1085 /******************************************************************************
1086 * FilterDialogQOPfsi.
1087 ******************************************************************************/
FilterDialogQOPfsi(dialog,event,itemN)1088 pascal Boolean FilterDialogQOPfsi (dialog, event, itemN)
1089 DialogPtr dialog;
1090 EventRecord *event;
1091 #ifndef __MWERKS__
1092 short *itemN;
1093 #else
1094 SInt16 *itemN;
1095 #endif
1096 {
1097   switch (event->what) {
1098     case keyDown: {
1099       char chr = (char) (event->message & charCodeMask);
1100       if ((event->modifiers & cmdKey) != 0) {
1101         if ('a' <= chr && chr <= 'z') chr ^= 0x60;
1102       }
1103       if (chr == (char) KB_RETURN) {
1104         FlashButton (dialog, OKin);
1105         *itemN = OKin;
1106         return TRUE;
1107       }
1108       if (chr == (char) EXITkey_FSI) {
1109         FlashButton (dialog, CANCELin);
1110 	 	*itemN = CANCELin;
1111 		return TRUE;
1112       }
1113       break;
1114     }
1115   }
1116    return FALSE;
1117 }
1118 
1119 /******************************************************************************
1120 * FilterDialogQOPso.
1121 ******************************************************************************/
1122 
FilterDialogQOPso(dialog,event,itemN)1123 pascal Boolean FilterDialogQOPso (dialog, event, itemN)
1124 DialogPtr dialog;
1125 EventRecord *event;
1126 #ifndef __MWERKS__
1127 short *itemN;
1128 #else
1129 SInt16 *itemN;
1130 #endif
1131 {
1132   switch (event->what) {
1133     case keyDown: {
1134       char key = (char) ((event->message & keyCodeMask) >> 8);
1135       if (key == RETURN_KEYCODE) {
1136         FlashButton (dialog, OKin);
1137         *itemN = OKin;
1138         return TRUE;
1139       }
1140       if ((event->modifiers & cmdKey) != 0 && key == Q_KEYCODE) {
1141         FlashButton (dialog, CANCELin);
1142 		*itemN = CANCELin;
1143 		return TRUE;
1144       }
1145       break;
1146     }
1147   }
1148   return FALSE;
1149 }
1150 
1151 /******************************************************************************
1152 * FlashButton.
1153 ******************************************************************************/
1154 
FlashButton(dialog,itemN)1155 static void FlashButton (dialog, itemN)
1156 DialogPtr dialog;
1157 int itemN;
1158 {
1159   short itemType, ovalWH = 15; Handle handle; Rect rect; GrafPtr currentPort;
1160   GetDItem (dialog, (short) itemN, &itemType, &handle, &rect);
1161   GetPort (&currentPort);
1162   SetPort ((GrafPtr) dialog);
1163   InvertRoundRect (&rect, ovalWH, ovalWH);
1164   FrameRoundRect (&rect, ovalWH, ovalWH);
1165   delay (0.1);
1166   InvertRoundRect (&rect, ovalWH, ovalWH);
1167   FrameRoundRect (&rect, ovalWH, ovalWH);
1168   delay (0.1);
1169   SetPort (currentPort);
1170   return;
1171 }
1172 
1173 /******************************************************************************
1174 * delay.
1175 ******************************************************************************/
1176 
delay(seconds)1177 static void delay (seconds)
1178 double seconds;
1179 {
1180   EventRecord event; long untilTick; short nullEventMask = 0;
1181   EventAvail (nullEventMask, &event);
1182   untilTick = event.when + (long) (seconds * 60);
1183   for (;;) {
1184      EventAvail (nullEventMask, &event);
1185      if (event.when > untilTick) break;
1186   }
1187   return;
1188 }
1189