1 /* Copyright (C) 2001-2006 Artifex Software, Inc.
2    All Rights Reserved.
3 
4    This software is provided AS-IS with no warranty, either express or
5    implied.
6 
7    This software is distributed under license and may not be copied, modified
8    or distributed except as expressly authorized under the terms of that
9    license.  Refer to licensing information at http://www.artifex.com/
10    or contact Artifex Software, Inc.,  7 Mt. Lassen Drive - Suite A-134,
11    San Rafael, CA  94903, U.S.A., +1(415)492-9861, for further information.
12 */
13 /* $Id: dmmain.c 9750 2009-05-21 19:13:36Z giles $ */
14 
15 /* Ghostscript shlib example wrapper for Macintosh (Classic/Carbon) contributed
16    by Nigel Hathaway. Uses the Metrowerks CodeWarrior SIOUX command-line library.
17  */
18 
19 #if __ide_target("Ghostscript PPC (Debug)") || __ide_target("Ghostscript PPC (Release)")
20 #define TARGET_API_MAC_CARBON 0
21 #define TARGET_API_MAC_OS8 1
22 #define ACCESSOR_CALLS_ARE_FUNCTIONS 1
23 #endif
24 
25 #include <Carbon.h>
26 
27 #include <stdlib.h>
28 #include <string.h>
29 #include <stdio.h>
30 #include <console.h>
31 #include <SIOUX.h>
32 #include <SIOUXGlobals.h>
33 #include <SIOUXMenus.h>
34 
35 #include "gscdefs.h"
36 #define GSREVISION gs_revision
37 #include "ierrors.h"
38 #include "iapi.h"
39 
40 #if DEBUG
41 #include "vdtrace.h"
42 #endif
43 
44 #include "gdevdsp.h"
45 
46 #define kScrollBarWidth   15
47 #define MAX_ARGS 25
48 
49 Boolean   gRunningOnX = false;
50 Boolean   gDone;
51 ControlActionUPP gActionFunctionScrollUPP;
52 
53 const char start_string[] = "systemdict /start get exec\n";
54 void *instance;
55 
56 const unsigned int display_format = DISPLAY_COLORS_RGB | DISPLAY_UNUSED_FIRST |
57                                     DISPLAY_DEPTH_8 | DISPLAY_BIGENDIAN |
58                                     DISPLAY_TOPFIRST;
59 typedef struct IMAGE_S IMAGE;
60 struct IMAGE_S {
61     void *handle;
62     void *device;
63     WindowRef  windowRef;
64     ControlRef scrollbarVertRef;
65     ControlRef scrollbarHorizRef;
66     PixMapHandle pixmapHdl;
67     UInt64 update_time;
68     int update_interval;
69     IMAGE *next;
70 };
71 
72 IMAGE *first_image;
73 
74 static IMAGE *image_find(void *handle, void *device);
75 
76 static int GSDLLCALL gsdll_stdin(void *instance, char *buf, int len);
77 static int GSDLLCALL gsdll_stdout(void *instance, const char *str, int len);
78 static int GSDLLCALL gsdll_stderr(void *instance, const char *str, int len);
79 static int GSDLLCALL gsdll_poll(void *handle);
80 
81 static int display_open(void *handle, void *device);
82 static int display_preclose(void *handle, void *device);
83 static int display_close(void *handle, void *device);
84 static int display_presize(void *handle, void *device, int width, int height,
85     int raster, unsigned int format);
86 static int display_size(void *handle, void *device, int width, int height,
87     int raster, unsigned int format, unsigned char *pimage);
88 static int display_sync(void *handle, void *device);
89 static int display_page(void *handle, void *device, int copies, int flush);
90 static int display_update(void *handle, void *device,
91     int x, int y, int w, int h);
92 
93 static size_t get_input(void *ptr, size_t size);
94 
95 static void window_create (IMAGE *img);
96 static void window_invalidate (WindowRef windowRef);
97 static void window_adjust_scrollbars (WindowRef windowRef);
98 
99 void    main                      (void);
100 OSErr   quitAppEventHandler       (AppleEvent *,AppleEvent *,SInt32);
101 void    doEvents                  (EventRecord *);
102 void    doMouseDown               (EventRecord *);
103 void    doUpdate                  (EventRecord *);
104 void    doUpdateWindow            (EventRecord *);
105 void    doOSEvent                 (EventRecord *);
106 void    doInContent               (EventRecord *,WindowRef);
107 pascal void    actionFunctionScroll      (ControlRef,ControlPartCode);
108 
109 /*********************************************************************/
110 /* stdio functions */
111 static int GSDLLCALL
gsdll_stdin(void * instance,char * buf,int len)112 gsdll_stdin(void *instance, char *buf, int len)
113 {
114     if (isatty(fileno(stdin)))
115        return get_input(buf, len);
116     else
117        return fread(buf, 1, len, stdin);
118 }
119 
120 static int GSDLLCALL
gsdll_stdout(void * instance,const char * str,int len)121 gsdll_stdout(void *instance, const char *str, int len)
122 {
123     int n = fwrite(str, 1, len, stdout);
124     fflush(stdout);
125     return n;
126 }
127 
128 static int GSDLLCALL
gsdll_stderr(void * instance,const char * str,int len)129 gsdll_stderr(void *instance, const char *str, int len)
130 {
131     return gsdll_stdout(instance, str, len);
132 }
133 
134 /* Poll the caller for cooperative multitasking. */
135 /* If this function is NULL, polling is not needed */
gsdll_poll(void * handle)136 static int GSDLLCALL gsdll_poll(void *handle)
137 {
138     EventRecord eventStructure;
139 
140     while (WaitNextEvent(everyEvent, &eventStructure, 0, NULL))
141         doEvents(&eventStructure);
142 
143     return (gDone ? e_Fatal : 0);
144 }
145 /*********************************************************************/
146 
147 /* new dll display device */
148 
149 /* New device has been opened */
150 /* This is the first event from this device. */
display_open(void * handle,void * device)151 static int display_open(void *handle, void *device)
152 {
153     IMAGE *img = (IMAGE *)malloc(sizeof(IMAGE));
154     if (img == NULL)
155        return -1;
156     memset(img, 0, sizeof(IMAGE));
157 
158     /* add to list */
159     if (first_image)
160        img->next = first_image;
161     first_image = img;
162 
163     /* remember device and handle */
164     img->handle = handle;
165     img->device = device;
166 
167     /* create window */
168     window_create(img);
169 
170     gsdll_poll(handle);
171     return 0;
172 }
173 
174 /* Device is about to be closed. */
175 /* Device will not be closed until this function returns. */
display_preclose(void * handle,void * device)176 static int display_preclose(void *handle, void *device)
177 {
178     /* do nothing - no thread synchonisation needed */
179     return 0;
180 }
181 
182 /* Device has been closed. */
183 /* This is the last event from this device. */
display_close(void * handle,void * device)184 static int display_close(void *handle, void *device)
185 {
186     IMAGE *img = image_find(handle, device);
187     if (img == NULL)
188        return -1;
189 
190     gsdll_poll(handle);
191 
192     /* remove from list */
193     if (img == first_image)
194         first_image = img->next;
195     else
196     {
197         IMAGE *tmp;
198         for (tmp = first_image; tmp!=0; tmp=tmp->next)
199         {
200             if (img == tmp->next)
201             tmp->next = img->next;
202         }
203     }
204 
205     DisposePixMap(img->pixmapHdl);   // need to go in doCloseWindow()
206     DisposeWindow(img->windowRef);
207 
208     free(img);
209 
210     return 0;
211 }
212 
213 /* Device is about to be resized. */
214 /* Resize will only occur if this function returns 0. */
display_presize(void * handle,void * device,int width,int height,int raster,unsigned int format)215 static int display_presize(void *handle, void *device, int width, int height,
216     int raster, unsigned int format)
217 {
218     /* Check for correct format (32-bit RGB), fatal error if not */
219     if (format != display_format)
220     {
221         printf("DisplayFormat has been set to an incompatible value.\n");
222         fflush(stdout);
223         return e_rangecheck;
224     }
225 
226     return 0;
227 }
228 
229 /* Device has been resized. */
230 /* New pointer to raster returned in pimage */
display_size(void * handle,void * device,int width,int height,int raster,unsigned int format,unsigned char * pimage)231 static int display_size(void *handle, void *device, int width, int height,
232     int raster, unsigned int format, unsigned char *pimage)
233 {
234     PixMapPtr pixmap;
235     IMAGE *img = image_find(handle, device);
236     if (img == NULL)
237        return -1;
238 
239     /* Check that image is within allowable bounds */
240     if (raster > 0x3fff)
241     {
242        printf("QuickDraw can't cope with an image this big.\n");
243        fflush(stdout);
244        if (img->pixmapHdl)
245        {
246            DisposePixMap(img->pixmapHdl);
247            img->pixmapHdl = NULL;
248        }
249        return e_rangecheck;
250     }
251 
252     /* Create the PixMap */
253     if (!img->pixmapHdl)
254         img->pixmapHdl = NewPixMap();
255 
256     pixmap = *(img->pixmapHdl);
257     pixmap->baseAddr = (char*)pimage;
258     pixmap->rowBytes = (((SInt16)raster) & 0x3fff) | 0x8000;
259     pixmap->bounds.right = width;
260     pixmap->bounds.bottom = height;
261     pixmap->packType = 0;
262     pixmap->packSize = 0;
263     pixmap->pixelType = RGBDirect;
264     pixmap->pixelSize = 32;
265     pixmap->cmpCount = 3;
266     pixmap->cmpSize = 8;
267 
268     /* Update the display window */
269     window_adjust_scrollbars(img->windowRef);
270     window_invalidate(img->windowRef);
271     return gsdll_poll(handle);
272 }
273 
274 /* flushpage */
display_sync(void * handle,void * device)275 static int display_sync(void *handle, void *device)
276 {
277     IMAGE *img = image_find(handle, device);
278     if (img == NULL)
279        return -1;
280 
281     window_invalidate(img->windowRef);
282     gsdll_poll(handle);
283 
284     return 0;
285 }
286 
287 /* showpage */
288 /* If you want to pause on showpage, then don't return immediately */
display_page(void * handle,void * device,int copies,int flush)289 static int display_page(void *handle, void *device, int copies, int flush)
290 {
291     return display_sync(handle, device);
292 }
293 
294 /* Poll the caller for cooperative multitasking. */
295 /* If this function is NULL, polling is not needed */
display_update(void * handle,void * device,int x,int y,int w,int h)296 static int display_update(void *handle, void *device,
297     int x, int y, int w, int h)
298 {
299     UInt64 t1;
300     UInt64 t2;
301     int delta;
302     IMAGE *img = image_find(handle, device);
303     if (img == NULL)
304        return -1;
305 
306     Microseconds((UnsignedWide*)&t1);
307     delta = (t1 - img->update_time) / 1000000L;
308     if (img->update_interval < 1)
309     img->update_interval = 1;    /* seconds */
310     if (delta < 0)
311         img->update_time = t1;
312     else if (delta > img->update_interval)
313     {
314         /* redraw window */
315         window_invalidate(img->windowRef);
316 
317         /* Make sure the update interval is at least 10 times
318          * what it takes to paint the window
319          */
320         Microseconds((UnsignedWide*)&t2);
321         delta = (t2 - t1) / 1000;
322         if (delta < 0)
323             delta += 60000;    /* delta = time to redraw */
324         if (delta > img->update_interval * 100)
325             img->update_interval = delta/100;
326         img->update_time = t2;
327     }
328 
329     return gsdll_poll(handle);
330 }
331 
332 display_callback display = {
333     sizeof(display_callback),
334     DISPLAY_VERSION_MAJOR,
335     DISPLAY_VERSION_MINOR,
336     display_open,
337     display_preclose,
338     display_close,
339     display_presize,
340     display_size,
341     display_sync,
342     display_page,
343     display_update,
344     NULL,    /* memalloc */
345     NULL,    /* memfree */
346     NULL	 /* display_separation */
347 };
348 
image_find(void * handle,void * device)349 static IMAGE * image_find(void *handle, void *device)
350 {
351     IMAGE *img;
352     for (img = first_image; img!=0; img=img->next) {
353     if ((img->handle == handle) && (img->device == device))
354         return img;
355     }
356     return NULL;
357 }
358 
359 /*********************************************************************/
360 
361 static char *stdin_buf = NULL;
362 static size_t stdin_bufpos = 0;
363 static size_t stdin_bufsize = 0;
364 
365 /* This function is a fudge which allows the SIOUX window to be waiting for
366    input and not be modal at the same time. (Why didn't MetroWerks think of that?)
367    It is based on the SIOUX function ReadCharsFromConsole(), and contains an
368    event loop which allows other windows to be active.
369    It collects characters up to when the user presses ENTER, stores the complete
370    buffer and gives as much to the calling function as it wants until it runs
371    out, at which point it gets another line (or set of lines if pasting from the
372    clipboard) from the user.
373 */
get_input(void * ptr,size_t size)374 static size_t get_input(void *ptr, size_t size)
375 {
376     EventRecord eventStructure;
377     long charswaiting, old_charswaiting = 0;
378     char *text;
379 
380 #if SIOUX_USE_WASTE
381     Handle textHandle;
382 #endif
383 
384     /* If needing more input, set edit start position */
385     if (!stdin_buf)
386 #if SIOUX_USE_WASTE
387         SIOUXselstart = WEGetTextLength(SIOUXTextWindow->edit);
388 #else
389         SIOUXselstart = (*SIOUXTextWindow->edit)->teLength;
390 #endif
391 
392     /* Wait until user presses exit (or quits) */
393     while(!gDone && !stdin_buf)
394     {
395 #if SIOUX_USE_WASTE
396         charswaiting = WEGetTextLength(SIOUXTextWindow->edit) - SIOUXselstart;
397 #else
398         if ((*SIOUXTextWindow->edit)->teLength > 0)
399             charswaiting = (*SIOUXTextWindow->edit)->teLength - SIOUXselstart;
400         else
401             charswaiting = ((unsigned short) (*SIOUXTextWindow->edit)->teLength) - SIOUXselstart;
402 #endif
403 
404         /* If something has happened, see if we need to do anything */
405         if (charswaiting != old_charswaiting)
406         {
407 #if SIOUX_USE_WASTE
408             textHandle = WEGetText(SIOUXTextWindow->edit);
409             HLock(textHandle);
410             text = *textHandle + SIOUXselstart;
411 #else
412             text = (*(*SIOUXTextWindow->edit)->hText) + SIOUXselstart;
413 #endif
414             /* If user has pressed enter, gather up the buffer ready for returning */
415             if (text[charswaiting-1] == '\r')
416             {
417                 stdin_buf = malloc(charswaiting);
418                 if (!stdin_buf)
419                     return -1;
420                 stdin_bufsize = charswaiting;
421                 memcpy(stdin_buf, text, stdin_bufsize);
422                 SIOUXselstart += charswaiting;
423 
424                 text = stdin_buf;
425                 while (text = memchr(text, '\r', charswaiting - (text - stdin_buf)))
426                     *text = '\n';
427             }
428 #if SIOUX_USE_WASTE
429             HUnlock(textHandle);
430 #endif
431             old_charswaiting = charswaiting;
432 
433             if (stdin_buf)
434                 break;
435         }
436 
437         /* Wait for next event and process it */
438         SIOUXState = SCANFING;
439 
440         if(WaitNextEvent(everyEvent, &eventStructure, SIOUXSettings.sleep ,NULL))
441             doEvents(&eventStructure);
442         else
443             SIOUXHandleOneEvent(&eventStructure);
444 
445         SIOUXState = IDLE;
446     }
447 
448     /* If data has been entered, return as much as has been requested */
449     if (stdin_buf && !gDone)
450     {
451         if (size >= stdin_bufsize - stdin_bufpos)
452         {
453             size = stdin_bufsize - stdin_bufpos;
454             memcpy (ptr, stdin_buf + stdin_bufpos, size);
455             free(stdin_buf);
456             stdin_buf = NULL;
457             stdin_bufpos = 0;
458             stdin_bufsize = 0;
459         }
460         else
461         {
462             memcpy (ptr, stdin_buf + stdin_bufpos, size);
463             stdin_bufpos += size;
464         }
465         return size;
466     }
467     else if (stdin_buf)
468     {
469         free(stdin_buf);
470         stdin_buf = NULL;
471         stdin_bufpos = 0;
472         stdin_bufsize = 0;
473     }
474 
475     return 0;
476 }
477 
478 /*********************************************************************/
479 
window_create(IMAGE * img)480 static void window_create(IMAGE *img)
481 {
482     WindowRef windowRef;
483     Str255    windowTitle = "\pGhostscript Image";
484     Rect      windowRect = {20,4,580,420};//, portRect;
485     Rect      scrollbarRect = {0,0,0,0};
486 
487 #if TARGET_API_MAC_CARBON
488     GetAvailableWindowPositioningBounds(GetMainDevice(),&windowRect);
489 #endif
490 
491     /* Create a new suitablty positioned window */
492     windowRect.top = windowRect.top * 2 + 2;
493     windowRect.bottom -= 10;
494     windowRect.left += 4;
495     windowRect.right = ((windowRect.bottom - windowRect.top) * 3) / 4 + windowRect.left;
496 
497     if(!(windowRef = NewCWindow(NULL, &windowRect, windowTitle, true,
498                                 zoomDocProc, (WindowRef) -1, false, 0)))
499         ExitToShell();
500 
501     img->windowRef = windowRef;
502 
503     SetWRefCon(img->windowRef, (SInt32)img);
504 
505     /* Create the window's scrollbars */
506 #if TARGET_API_MAC_CARBON
507     if(gRunningOnX)
508         ChangeWindowAttributes(windowRef,kWindowLiveResizeAttribute,0);
509 
510     CreateScrollBarControl(windowRef, &scrollbarRect, 0, 0, 0, 0,
511                            true, gActionFunctionScrollUPP, &(img->scrollbarVertRef));
512 
513     CreateScrollBarControl(windowRef, &scrollbarRect, 0, 0, 0, 0,
514                            true, gActionFunctionScrollUPP, &(img->scrollbarHorizRef));
515 #else
516     img->scrollbarVertRef = NewControl(windowRef,&scrollbarRect,"\p",false,0,0,0,scrollBarProc,0);
517     img->scrollbarHorizRef = NewControl(windowRef,&scrollbarRect,"\p",false,0,0,0,scrollBarProc,0);
518 #endif
519 
520     window_adjust_scrollbars(windowRef);
521 }
522 
window_invalidate(WindowRef windowRef)523 static void window_invalidate(WindowRef windowRef)
524 {
525     Rect portRect;
526 
527     GetWindowPortBounds(windowRef, &portRect);
528     InvalWindowRect(windowRef, &portRect);
529 }
530 
window_adjust_scrollbars(WindowRef windowRef)531 static void window_adjust_scrollbars(WindowRef windowRef)
532 {
533     IMAGE *img;
534     Rect   portRect;
535 
536     img = (IMAGE*)GetWRefCon(windowRef);
537     GetWindowPortBounds(windowRef,&portRect);
538 
539     /* Move the crollbars to the edges of the window */
540     HideControl(img->scrollbarVertRef);
541     HideControl(img->scrollbarHorizRef);
542 
543     MoveControl(img->scrollbarVertRef,portRect.right - kScrollBarWidth,
544                 portRect.top - 1);
545     MoveControl(img->scrollbarHorizRef,portRect.left - 1,
546                 portRect.bottom - kScrollBarWidth);
547 
548     SizeControl(img->scrollbarVertRef,kScrollBarWidth + 1,
549                 portRect.bottom - portRect.top - kScrollBarWidth + 1);
550     SizeControl(img->scrollbarHorizRef, portRect.right - portRect.left - kScrollBarWidth + 1,
551                 kScrollBarWidth + 1);
552 
553     /* Adjust the scroll position showing */
554     if (img->pixmapHdl)
555     {
556         PixMap *pixmap = *(img->pixmapHdl);
557         int visibleHeight = portRect.bottom - portRect.top - kScrollBarWidth;
558         int visibleWidth = portRect.right - portRect.left - kScrollBarWidth;
559 
560         if (pixmap->bounds.bottom > visibleHeight)
561         {
562             SetControl32BitMaximum(img->scrollbarVertRef,
563                                    pixmap->bounds.bottom - visibleHeight);
564             SetControlViewSize(img->scrollbarVertRef,visibleHeight);
565         }
566         else
567             SetControlMaximum(img->scrollbarVertRef, 0);
568 
569         if (pixmap->bounds.right > visibleWidth)
570         {
571             SetControl32BitMaximum(img->scrollbarHorizRef,
572                                    pixmap->bounds.right - visibleWidth);
573             SetControlViewSize(img->scrollbarHorizRef, visibleWidth);
574         }
575         else
576             SetControlMaximum(img->scrollbarHorizRef, 0);
577     }
578 
579     ShowControl(img->scrollbarVertRef);
580     ShowControl(img->scrollbarHorizRef);
581 }
582 
583 /*********************************************************************/
main(void)584 void main(void)
585 {
586     int code;
587     int exit_code;
588     int argc;
589     char **argv;
590     char dformat[64], ddevice[32];
591     SInt32        response;
592 
593     /* Initialize operating environment */
594 #if TARGET_API_MAC_CARBON
595     MoreMasterPointers(224);
596 #else
597     MoreMasters();
598 #endif
599     InitCursor();
600     FlushEvents(everyEvent,0);
601 
602     if (AEInstallEventHandler(kCoreEventClass,kAEQuitApplication,
603                               NewAEEventHandlerUPP((AEEventHandlerProcPtr) quitAppEventHandler),
604                               0L,false) != noErr)
605         ExitToShell();
606 
607 	gActionFunctionScrollUPP = NewControlActionUPP(&actionFunctionScroll);
608 
609     Gestalt(gestaltMenuMgrAttr,&response);
610     if(response & gestaltMenuMgrAquaLayoutMask)
611                 gRunningOnX = true;
612 
613     /* Initialize SIOUX */
614     SIOUXSettings.initializeTB = false;
615     SIOUXSettings.standalone = false;
616     SIOUXSettings.asktosaveonclose = false;
617     SIOUXSettings.sleep = GetCaretTime();
618     SIOUXSettings.userwindowtitle = "\pGhostscript";
619 
620     /* Get arguments from user */
621     argc = ccommand(&argv);
622 
623     /* Show command line window */
624     if (InstallConsole(0))
625         ExitToShell();
626 
627     /* Part of fudge to make SIOUX accept characters without becoming modal */
628     SelectWindow(SIOUXTextWindow->window);
629     PostEvent(keyDown, 0x4c00);  // Enter
630     ReadCharsFromConsole(dformat, 0x7FFF);
631     clrscr();
632 
633     /* Add in the display format as the first command line argument */
634     if (argc >= MAX_ARGS - 1)
635     {
636        printf("Too many command line arguments\n");
637        return;
638     }
639 
640     memmove(&argv[3], &argv[1], (argc-1) * sizeof(char**));
641     argc += 2;
642     argv[1] = ddevice;
643     argv[2] = dformat;
644 
645 	sprintf(ddevice, "-sDEVICE=display");
646     sprintf(dformat, "-dDisplayFormat=%d", display_format);
647 
648     /* Run Ghostscript */
649     if (gsapi_new_instance(&instance, NULL) < 0)
650     {
651        printf("Can't create Ghostscript instance\n");
652        return;
653     }
654 
655 #ifdef DEBUG
656     visual_tracer_init();
657     set_visual_tracer(&visual_tracer);
658 #endif
659 
660     gsapi_set_stdio(instance, gsdll_stdin, gsdll_stdout, gsdll_stderr);
661     gsapi_set_poll(instance, gsdll_poll);
662     gsapi_set_display_callback(instance, &display);
663 
664     code = gsapi_init_with_args(instance, argc, argv);
665     if (code == 0)
666        code = gsapi_run_string(instance, start_string, 0, &exit_code);
667     else
668     {
669        printf("Failed to initialize. Error %d.\n", code);
670        fflush(stdout);
671     }
672     code = gsapi_exit(instance);
673     if (code != 0)
674     {
675        printf("Failed to terminate. Error %d.\n", code);
676        fflush(stdout);
677     }
678 
679     gsapi_delete_instance(instance);
680 
681 #ifdef DEBUG
682     visual_tracer_close();
683 #endif
684 
685     /* Ghostscript has finished - let user see output before quitting */
686     WriteCharsToConsole("\r[Finished - hit any key to quit]", 33);
687     fflush(stdout);
688 
689     /* Process events until a key is hit or user quits from menu */
690     while(!gDone)
691     {
692         EventRecord eventStructure;
693 
694         if(WaitNextEvent(everyEvent,&eventStructure,SIOUXSettings.sleep,NULL))
695         {
696             if (eventStructure.what == keyDown)
697             gDone = true;
698 
699             doEvents(&eventStructure);
700         }
701         else
702             SIOUXHandleOneEvent(&eventStructure);
703     }
704 }
705 
706 /*********************************************************************/
707 
doEvents(EventRecord * eventStrucPtr)708 void doEvents(EventRecord *eventStrucPtr)
709 {
710     WindowRef      windowRef;
711 
712     if (eventStrucPtr->what == mouseDown &&
713         FindWindow(eventStrucPtr->where,&windowRef) == inMenuBar)
714         SelectWindow(SIOUXTextWindow->window);
715 
716     SIOUXSettings.standalone = true;
717     if (SIOUXHandleOneEvent(eventStrucPtr))
718     {
719         if (SIOUXQuitting)
720             gDone = true;
721         SIOUXSettings.standalone = false;
722         return;
723     }
724     SIOUXSettings.standalone = false;
725 
726     switch(eventStrucPtr->what)
727     {
728     case kHighLevelEvent:
729         AEProcessAppleEvent(eventStrucPtr);
730         break;
731 
732     case mouseDown:
733         doMouseDown(eventStrucPtr);
734         break;
735 
736     case keyDown:
737     case autoKey:
738         break;
739 
740     case updateEvt:
741         doUpdate(eventStrucPtr);
742         break;
743 
744     case activateEvt:
745         DrawGrowIcon(windowRef);
746         break;
747 
748     case osEvt:
749         doOSEvent(eventStrucPtr);
750         break;
751     }
752 }
753 
doMouseDown(EventRecord * eventStrucPtr)754 void doMouseDown(EventRecord *eventStrucPtr)
755 {
756     WindowRef      windowRef;
757     WindowPartCode partCode, zoomPart;
758     BitMap         screenBits;
759     Rect           constraintRect, mainScreenRect;
760     Point          standardStateHeightAndWidth;
761     long           newSize;
762 
763     partCode = FindWindow(eventStrucPtr->where,&windowRef);
764 
765     switch(partCode)
766     {
767     case inMenuBar:
768         break;
769 
770     case inContent:
771         if(windowRef != FrontWindow())
772             SelectWindow(windowRef);
773         else
774             doInContent(eventStrucPtr,windowRef);
775         break;
776 
777     case inDrag:
778         DragWindow(windowRef,eventStrucPtr->where,NULL);
779         break;
780 
781     case inGoAway:
782         break;
783 
784     case inGrow:
785         constraintRect.top   = 75;
786         constraintRect.left = 250;
787         constraintRect.bottom = constraintRect.right = 32767;
788         newSize = GrowWindow(windowRef,eventStrucPtr->where,&constraintRect);
789         if (newSize != 0)
790             SizeWindow(windowRef,LoWord(newSize),HiWord(newSize),true);
791         window_adjust_scrollbars(windowRef);
792         window_invalidate(windowRef);
793         break;
794 
795     case inZoomIn:
796     case inZoomOut:
797         mainScreenRect = GetQDGlobalsScreenBits(&screenBits)->bounds;
798         standardStateHeightAndWidth.v = mainScreenRect.bottom;
799         standardStateHeightAndWidth.h = mainScreenRect.right;
800 
801         if(IsWindowInStandardState(windowRef,&standardStateHeightAndWidth,NULL))
802             zoomPart = inZoomIn;
803         else
804             zoomPart = inZoomOut;
805 
806         if(TrackBox(windowRef,eventStrucPtr->where,partCode))
807         {
808             ZoomWindowIdeal(windowRef,zoomPart,&standardStateHeightAndWidth);
809             window_adjust_scrollbars(windowRef);
810         }
811         break;
812     }
813 }
814 
doUpdate(EventRecord * eventStrucPtr)815 void doUpdate(EventRecord *eventStrucPtr)
816 {
817     WindowRef windowRef;
818 
819     windowRef = (WindowRef) eventStrucPtr->message;
820 
821     window_adjust_scrollbars(windowRef);
822 
823     BeginUpdate(windowRef);
824 
825     SetPortWindowPort(windowRef);
826     doUpdateWindow(eventStrucPtr);
827 
828     EndUpdate(windowRef);
829 }
830 
doUpdateWindow(EventRecord * eventStrucPtr)831 void doUpdateWindow(EventRecord *eventStrucPtr)
832 {
833     IMAGE *img;
834     WindowRef    windowRef;
835     Rect         srcRect, destRect, fillRect;
836     PixMapHandle srcPixmapHdl, destPixmapHdl;
837     RGBColor     grayColour = { 0xC000,0xC000,0xC000 };
838     SInt32  hScroll, vScroll;
839 
840     windowRef = (WindowRef) eventStrucPtr->message;
841     img = (IMAGE*)GetWRefCon(windowRef);
842     srcPixmapHdl = img->pixmapHdl;
843     destPixmapHdl = GetPortPixMap(GetWindowPort(windowRef));
844     hScroll = GetControl32BitValue(img->scrollbarHorizRef);
845     vScroll = GetControl32BitValue(img->scrollbarVertRef);
846 
847     if (srcPixmapHdl)
848     {
849         PixMap *pixmap = *srcPixmapHdl;
850         PixPatHandle hdlPixPat = NewPixPat();
851         MakeRGBPat(hdlPixPat, &grayColour);
852 
853         GetWindowPortBounds(windowRef,&destRect);
854         destRect.right  -= kScrollBarWidth;
855         destRect.bottom -= kScrollBarWidth;
856 
857         if (destRect.right > pixmap->bounds.right)
858         {
859             fillRect.top = destRect.top;
860             fillRect.bottom = destRect.bottom;
861             fillRect.left = pixmap->bounds.right;
862             fillRect.right = destRect.right;
863             FillCRect(&fillRect, hdlPixPat);
864             destRect.right = pixmap->bounds.right;
865         }
866         if (destRect.bottom > pixmap->bounds.bottom)
867         {
868             fillRect.top = pixmap->bounds.bottom;
869             fillRect.bottom = destRect.bottom;
870             fillRect.left = destRect.left;
871             fillRect.right = destRect.right;
872             FillCRect(&fillRect, hdlPixPat);
873             destRect.bottom = pixmap->bounds.bottom;
874         }
875         DisposePixPat(hdlPixPat);
876 
877         srcRect = destRect;
878         srcRect.left += hScroll;
879         srcRect.right += hScroll;
880         srcRect.top += vScroll;
881         srcRect.bottom += vScroll;
882 
883         CopyBits((BitMap*)*srcPixmapHdl, (BitMap*)*destPixmapHdl,
884                  &srcRect, &destRect, srcCopy, NULL);
885     }
886 
887     DrawGrowIcon(windowRef);
888 }
889 
doOSEvent(EventRecord * eventStrucPtr)890 void doOSEvent(EventRecord *eventStrucPtr)
891 {
892     switch((eventStrucPtr->message >> 24) & 0x000000FF)
893     {
894     case suspendResumeMessage:
895         if((eventStrucPtr->message & resumeFlag) == 1)
896           SetThemeCursor(kThemeArrowCursor);
897         break;
898     }
899 }
900 
doInContent(EventRecord * eventStrucPtr,WindowRef windowRef)901 void doInContent(EventRecord *eventStrucPtr,WindowRef windowRef)
902 {
903     ControlPartCode controlPartCode;
904     ControlRef      controlRef;
905 
906     SetPortWindowPort(windowRef);
907     GlobalToLocal(&eventStrucPtr->where);
908 
909     if(controlRef = FindControlUnderMouse(eventStrucPtr->where,windowRef,&controlPartCode))
910     {
911 #if TARGET_API_MAC_CARBON
912         TrackControl(controlRef,eventStrucPtr->where,(ControlActionUPP) -1);
913 #else
914         if (controlPartCode == kControlIndicatorPart)
915             TrackControl(controlRef,eventStrucPtr->where,NULL);
916         else
917             TrackControl(controlRef,eventStrucPtr->where,gActionFunctionScrollUPP);
918 #endif
919 
920         window_invalidate(windowRef);
921     }
922 }
923 
actionFunctionScroll(ControlRef controlRef,ControlPartCode controlPartCode)924 pascal void actionFunctionScroll(ControlRef controlRef,ControlPartCode controlPartCode)
925 {
926     SInt32 scrollDistance, controlValue, oldControlValue, controlMax;
927 
928     if(controlPartCode != kControlNoPart)
929     {
930         if(controlPartCode != kControlIndicatorPart)
931         {
932             switch(controlPartCode)
933             {
934             case kControlUpButtonPart:
935             case kControlDownButtonPart:
936                 scrollDistance = 10;
937                 break;
938 
939             case kControlPageUpPart:
940             case kControlPageDownPart:
941                 scrollDistance = 100;
942                 break;
943 
944             default:
945                 scrollDistance = 0;
946                 break;
947             }
948 
949             if (scrollDistance)
950             {
951                 if((controlPartCode == kControlDownButtonPart) ||
952                    (controlPartCode == kControlPageDownPart))
953                     scrollDistance = -scrollDistance;
954 
955                 controlValue = GetControl32BitValue(controlRef);
956 
957                 if(((controlValue == GetControl32BitMaximum(controlRef)) && scrollDistance < 0) ||
958                    ((controlValue == GetControl32BitMinimum(controlRef)) && scrollDistance > 0))
959                     return;
960 
961                 oldControlValue = controlValue;
962                 controlMax = GetControl32BitMaximum(controlRef);
963                 controlValue = oldControlValue - scrollDistance;
964 
965                 if(controlValue < 0)
966                     controlValue = 0;
967                 else if(controlValue > controlMax)
968                     controlValue = controlMax;
969 
970                 SetControl32BitValue(controlRef,controlValue);
971             }
972         }
973     }
974 }
975 
quitAppEventHandler(AppleEvent * appEvent,AppleEvent * reply,SInt32 handlerRefcon)976 OSErr quitAppEventHandler(AppleEvent *appEvent,AppleEvent *reply,SInt32 handlerRefcon)
977 {
978     OSErr    osError;
979     DescType returnedType;
980     Size     actualSize;
981 
982     osError = AEGetAttributePtr(appEvent,keyMissedKeywordAttr,typeWildCard,&returnedType,NULL,0,
983                                 &actualSize);
984 
985     if(osError == errAEDescNotFound)
986     {
987         gDone = true;
988         osError = noErr;
989     }
990     else if(osError == noErr)
991         osError = errAEParamMissed;
992 
993     return osError;
994 }
995 
996 /*********************************************************************/
997 
998