~ubuntu-branches/ubuntu/jaunty/ghostscript/jaunty-updates

« back to all changes in this revision

Viewing changes to base/dmmain.c

  • Committer: Bazaar Package Importer
  • Author(s): Till Kamppeter
  • Date: 2009-01-20 16:40:45 UTC
  • mfrom: (1.1.10 upstream)
  • Revision ID: james.westby@ubuntu.com-20090120164045-lnfhi0n30o5lwhwa
Tags: 8.64.dfsg.1~svn9377-0ubuntu1
* New upstream release (SVN rev 9377)
   o Fixes many bugs concerning PDF rendering, to make the PDF printing
     workflow correctly working.
   o Fixes long-standing bugs in many drivers, like input paper tray and
     duplex options not working for the built-in PCL 4, 5, 5c, 5e, and
     6/XL drivers, PDF input not working for bjc600, bjc800, and cups
     output devices, several options not working and uninitialized
     memory with cups output device.
   o Merged nearly all patches of the Ubuntu and Debian packages upstream.
   o Fixes LP: #317810, LP: #314439, LP: #314018.
* debian/patches/03_libpaper_support.dpatch,
  debian/patches/11_gs-cjk_font_glyph_handling_fix.dpatch,
  debian/patches/12_gs-cjk_vertical_writing_metrics_fix.dpatch,
  debian/patches/13_gs-cjk_cjkps_examples.dpatch,
  debian/patches/20_bbox_segv_fix.dpatch,
  debian/patches/21_brother_7x0_gdi_fix.dpatch,
  debian/patches/22_epsn_margin_workaround.dpatch,
  debian/patches/24_gs_man_fix.dpatch,
  debian/patches/25_toolbin_insecure_tmp_usage_fix.dpatch,
  debian/patches/26_assorted_script_fixes.dpatch,
  debian/patches/29_gs_css_fix.dpatch,
  debian/patches/30_ps2pdf_man_improvement.dpatch,
  debian/patches/31_fix-gc-sigbus.dpatch,
  debian/patches/34_ftbfs-on-hurd-fix.dpatch,
  debian/patches/35_disable_libcairo.dpatch,
  debian/patches/38_pxl-duplex.dpatch,
  debian/patches/39_pxl-resolution.dpatch,
  debian/patches/42_gs-init-ps-delaybind-fix.dpatch,
  debian/patches/45_bjc600-bjc800-pdf-input.dpatch,
  debian/patches/48_cups-output-device-pdf-duplex-uninitialized-memory-fix.dpatch,
  debian/patches/50_lips4-floating-point-exception.dpatch,
  debian/patches/52_cups-device-logging.dpatch,
  debian/patches/55_pcl-input-slot-fix.dpatch,
  debian/patches/57_pxl-input-slot-fix.dpatch,
  debian/patches/60_pxl-cups-driver-pdf.dpatch,
  debian/patches/62_onebitcmyk-pdf.dpatch,
  debian/patches/65_too-big-temp-files-1.dpatch,
  debian/patches/67_too-big-temp-files-2.dpatch,
  debian/patches/70_take-into-account-data-in-stream-buffer-before-refill.dpatch:
  Removed, applied upstream.
* debian/patches/01_docdir_fix_for_debian.dpatch,
  debian/patches/02_gs_man_fix_debian.dpatch,
  debian/patches/01_docdir-fix-for-debian.dpatch,
  debian/patches/02_docdir-fix-for-debian.dpatch: Renamed patches to
  make merging with Debian easier.
* debian/patches/32_improve-handling-of-media-size-changes-from-gv.dpatch, 
  debian/patches/33_bad-params-to-xinitimage-on-large-bitmaps.dpatch:
  regenerated for new source directory structure.
* debian/rules: Corrected paths to remove cidfmap (it is in Resource/Init/
  in GS 8.64) and to install headers (source paths are psi/ and base/ now).
* debian/rules: Remove all fontmaps, as DeFoMa replaces them.
* debian/local/pdftoraster/pdftoraster.c,
  debian/local/pdftoraster/pdftoraster.convs, debian/rules: Removed
  added pdftoraster filter and use the one which comes with Ghostscript.
* debian/ghostscript.links: s/8.63/8.64/

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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 8022 2007-06-05 22:23:38Z 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
 
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
 
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
 
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 */
 
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. */
 
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. */
 
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. */
 
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. */
 
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 */
 
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 */
 
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 */
 
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 */
 
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
 
 
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
*/
 
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
 
 
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
 
 
523
static void window_invalidate(WindowRef windowRef)
 
524
{
 
525
    Rect portRect;
 
526
 
 
527
    GetWindowPortBounds(windowRef, &portRect);
 
528
    InvalWindowRect(windowRef, &portRect);
 
529
}
 
530
 
 
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
/*********************************************************************/
 
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
 
 
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
 
 
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
 
 
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
 
 
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
 
 
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
 
 
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
 
 
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
 
 
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