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