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