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