home *** CD-ROM | disk | FTP | other *** search
- /* Copyright (C) 1991 David Elworthy. All rights reserved.
- Distributed by Free Software Foundation, Inc.
-
- This file is part of Ghostscript.
-
- Ghostscript is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY. No author or distributor accepts responsibility
- to anyone for the consequences of using it or for whether it serves any
- particular purpose or works at all, unless he says so in writing. Refer
- to the Ghostscript General Public License for full details.
-
- Everyone is granted permission to copy, modify and redistribute
- Ghostscript, but only under the conditions described in the Ghostscript
- General Public License. A copy of this license is supposed to have been
- given to you along with Ghostscript so you can know your rights and
- responsibilities. It should be in a file named COPYING. Among other
- things, the copyright notice and this notice must be preserved on all
- copies. */
-
- /* gdevarc1.c */
- /* Ghostscript driver for Acorn Archimedes (RISC OS) */
- /* The code here does output to a sprite, but none of the sprite display,
- or the general user interface stuff.
- */
-
- /*
- 1.0 -- April 1991 -- First working version
- 2.0 -- June 1991 -- Changed for GhostScript 2.2
- 2.1 -- Nov 1991 -- Some code moved to gp_arc
- Split into two parts
-
-
- If the symbol GS$Options is defined, up to four floats may be read from it, setting
- height and width in inches, and the x and y resolutions in dpi. The output is in the
- current mode. Finally, there may be an integer, which is non zero for save only mode.
- The defaults are A4, and 180 dpi. Specifying -1 for a variable gets you the default.
- From version 2.2, a menu for the read and print windows allows this to be altered.
-
- From version 2.0 onwards, the size of the window is changed to fit the sprite, and
- the sprite is redraw manually, rather than being attached to an icon.
-
- If the size is too large or the resolution too high, GS may fall over, probably not
- cleanly.
- */
-
- #include <stdlib.h>
- #include <string.h>
-
- #include "wimpc.h"
-
- #include "gx.h"
- #include "gsmatrix.h" /* for gxdevice.h */
- #include "gxbitmap.h"
- #include "gxdevice.h"
- /* Do all allocation directly */
- #include "malloc_.h"
-
- #include "h.os"
- #include "bbc.h"
- #include "wimp.h"
- #include "wimpt.h"
- #include "wimpio.h"
- #include "colourtran.h"
- #include "sprite.h"
- #include "menu.h"
- #include "werr.h"
- #include "saveas.h"
- #include "magnify.h"
- #include "dbox.h"
-
- #include "gdevarc.h"
- #include "gp_arc.h"
-
- /*-------------------------------------------------------------------------------*/
-
- BOOL arc_saver(char *filename, void *handle)
- {
- /* Save the whole sprite in one go */
- os_filestr f;
- adev_needed(handle);
-
- f.action = 10; /* Save with type info */
- f.name = filename;
- f.loadaddr = file_type;
- f.start = 4 + (int)(adev->sarea);
- f.end = adev->sarea->freeoff + (int)(adev->sarea);
-
- return (wimpt_complain(os_file(&f)) == NULL);
- }
-
- /*--- Low level window functions ---*/
-
- /* Pixel translation table - must be set up at start of redraw loop. */
- static char pixtrans[256];
-
- /* Set up the pixel translation table */
- void set_pixtrans(gx_device_arc *adev)
- {
- wimpt_noerr(
- colourtran_select_table(adev->mode,
- (wimp_paletteword *)(adev->paltab), -1, (wimp_paletteword *)-1,
- &pixtrans[0]));
- }
-
- /* Redraw the sprite: called on each iteration round the redraw loop */
- static void redraw_sprite(wimp_redrawstr *r, void *handle)
- {
- adev_needed(handle);
- wimp_winfo w_info;
-
- w_info.w = adev->page_window;
- wimpt_noerr(wimp_get_wind_info(&w_info));
-
- wimpt_noerr(
- sprite_put_scaled(adev->sarea, &(adev->sprite), 0,
- r->box.x0 - r->scx, r->box.y1 - r->scy + w_info.info.ex.y0,
- &(adev->f), (sprite_pixtrans *)&pixtrans[0]));
- }
-
- /* Set window title string */
- void arc_set_title(gx_device_arc *adev, char *title)
- {
- static char *window_title = "GhostScript Output";
-
- if (adev->f.xdiv == 1)
- {
- if (adev->f.xmag == 1)
- sprintf(title, "%s", window_title);
- else
- sprintf(title, "%s Zoom x %d", window_title, adev->f.xmag);
- }
- else if (adev->f.xdiv == 1)
- sprintf(title, "%s Zoom / %d", window_title, adev->f.xdiv);
- else
- sprintf(title, "%s Zoom x %d / %d", window_title, adev->f.xmag, adev->f.xdiv);
- }
-
- /* Set the extent of the window to the size of the output sprite */
- /* We get the extent from the current icon size and scale factors */
- void arc_set_window_extent(gx_device_arc *adev)
- {
- wimp_redrawstr wsize;
-
- wsize.w = adev->page_window;
- wsize.box.x0 = 0;
- wsize.box.y0 = -(adev->f.ymag * (adev->height << adev->yeig)) / adev->f.ydiv;
- wsize.box.x1 = (adev->f.xmag * (adev->width << adev->xeig)) / adev->f.xdiv;
- wsize.box.y1 = 0;
- wimpt_noerr(wimp_set_extent(&wsize));
- }
-
- /* Redraw on zoom change */
- static void do_zoom(void *handle)
- {
- gx_device_arc *adev = (gx_device_arc *)handle;
- wimp_redrawstr r;
- wimp_winfo w_info;
- wimp_wstate w_state;
-
- adev->f.ymag = adev->f.xmag;
- adev->f.ydiv = adev->f.xdiv;
- arc_set_window_extent(adev);
-
- /* Change the title string - assumes buffer is big enough! */
- w_info.w = adev->page_window;
- wimpt_noerr(wimp_get_wind_info(&w_info));
- arc_set_title(adev, w_info.info.title.indirecttext.buffer);
-
- /* Reopen the window to force the outline to be redrawn */
- /* This doesn't work unless you close it first! */
- wimpt_noerr(wimp_get_wind_state(adev->page_window, &w_state));
- wimpt_noerr(wimp_close_wind(adev->page_window));
- wimpt_noerr(wimp_open_wind(&w_state.o));
-
- r.w = adev->page_window;
- r.box.x0 = -1000000;
- r.box.y0 = -1000000;
- r.box.x1 = 1000000;
- r.box.y1 = 1000000;
- wimpt_noerr(wimp_force_redraw(&r));
- }
-
- /*--- Menus ---*/
-
- /* Page menu */
- static char *page_menu_text = ">Save,>Zoom,Zoom x 1";
- #define page_menu_Save (1)
- #define page_menu_Zoom (2)
- #define page_menu_ResetZoom (3)
-
- /* Page menu handler */
- void arc_process_page_menu(void *handle, char* hit)
- {
- adev_needed(handle);
-
- switch (hit[0])
- {
- case page_menu_Save:
- saveas(file_type, "GSOutput", adev->sarea_size, arc_saver, 0, 0, (void *)adev);
- break;
-
- case page_menu_Zoom:
- magnify_select(&(adev->f.xmag), &(adev->f.xdiv), Max_Zoom, Max_Zoom, do_zoom, adev);
- break;
-
- case page_menu_ResetZoom:
- adev->f.xmag = adev->f.xdiv = 1;
- do_zoom(adev);
- break;
- }
- }
-
- /* Create page menu */
- menu arc_create_page_menu(void *handle)
- {
- menu m = menu_new("GhostScript", page_menu_text);
- return m;
- }
-
- /*--- High level window functions ---*/
-
- /* Page window event handler - click on icon 1 is save */
- /* Do own redraw, so we can plot sprite zoomed */
- void arc_page_event_handler(wimp_eventstr *e, void *handle)
- {
- adev_needed(handle);
- if ((e->e == wimp_ESEND || e->e == wimp_ESENDWANTACK)
- && e->data.msg.hdr.action == wimp_PALETTECHANGE)
- {
- /* Force window redraw on palette change */
- wimp_redrawstr r;
- r.w = adev->page_window;
- r.box.x0 = r.box.y0 = -1000000;
- r.box.x1 = r.box.y1 = 1000000;
-
- wimp_force_redraw(&r);
- return;
- }
-
- if (e->e == wimp_EREDRAW) set_pixtrans(adev);
- w_event(e, redraw_sprite, &(adev->page_closed), handle);
- }
-
-
- /* Allocate space for a sprite of given size and mode, including palette */
- /* Also creates the palette table for colour translation */
- /* Deletes the sprite if it already exists */
- /* Returns true if there was enough memory - other errors via wimp (shouldn't happen) */
- /* There appears to be a bug in the standard GS allocators, such that if there is not enough
- memory, you get given a small black rather than a NULL return. Se we claim memory directly.
- */
- BOOL arc_create_op(gx_device_arc *dev)
- {
- int sbpp = 1 << bbc_modevar(dev->mode, bbc_Log2BPC);
- int nc = bbc_modevar(dev->mode, bbc_NColour)+1;
- int spritesize = dev->width * sbpp;
- sprite_header *header;
-
- spritesize = (spritesize/8 + 4) & ~3; /* word units */
- spritesize *= dev->height;
-
- spritesize += sizeof(sprite_header);
-
- /* Add space for palette */
- spritesize += 2*sizeof(int)*nc;
-
- /* Allow space for header */
- spritesize += sizeof(sprite_area);
-
- /* Allocate space for the sprite, and the sprite area header */
- if (spritesize > dev->sarea_size)
- {
- if (dev->sarea)
- { /* Free old memory - delete the sprite, too, to be safe */
- wimpt_noerr(sprite_delete(dev->sarea, &(dev->sprite)));
- free((char *)(dev->sarea));
- }
-
- dev->sarea_size = 0;
- dev->sarea = (sprite_area *)heap_alloc(spritesize);
-
- if (dev->sarea == NULL)
- return FALSE;
- dev->sarea_size = spritesize;
- dev->is_256 = (nc == 64);
- }
-
- /* Initialise the header */
- sprite_area_initialise(dev->sarea, dev->sarea_size);
-
- /* Initialise the sprite */
- dev->sprite.tag = sprite_id_addr;
- wimpt_noerr(
- sprite_create_rp(dev->sarea, sprite_name, sprite_haspalette, dev->width, dev->height, dev->mode,
- &(dev->sprite.s.addr)));
-
- /* The following is rather hacky, but seems to give a reasonable palette. */
- header = (sprite_header *)dev->sprite.s.addr;
-
- if (bbc_modevar(dev->mode, bbc_Log2BPP) != 3) /* Do nothing for 256 colour modes */
- {
- int *start = (&header->mode) + 1;
- int *end = (int *)((char *)header + header->image);
-
- /* Fix up the palette */
- while (start < end)
- {
- int t = *start & 0xF0F0F000;
- *start++ = t | ((t >> 4) & 0xF0F0F00);
- }
- }
-
- /* Create colour translation table */
- {
- int *from = (&header->mode) + 1;
- int *to = dev->paltab;
- int i;
-
- for (i = nc ; i > 0 ; i--) { *to++ = *from; from += 2; }
- }
- return TRUE;
- }
-
- /* Set the control block from the options. < 0 gets you the default. */
- void arc_set_options(gx_device_arc *adev, int mode, float width, float height, float xres, float yres)
- {
- float pwidth, pheight;
-
- adev->mode = mode;
- adev->xeig = bbc_modevar(adev->mode, bbc_XEigFactor);
- adev->yeig = bbc_modevar(adev->mode, bbc_YEigFactor);
-
- /* Default resolution is to assume 180 OS units per inch */
- if (xres <= 0) xres = 180;
- if (yres <= 0) yres = 180;
-
- /* Width and height default to A4 */
- pwidth = ((width <= 0) ? 8.27 : width) * xres;
- pheight = ((height <= 0) ? 11.70 : height) * yres;
-
- pwidth = pwidth / (1 << adev->xeig);
- pheight = pheight / (1 << adev->yeig);
- xres = xres / (1 << adev->xeig);
- yres = yres / (1 << adev->yeig);
-
- adev->width = (int)(pwidth + 0.5);
- adev->height = (int)(pheight + 0.5);
- adev->x_pixels_per_inch = xres;
- adev->y_pixels_per_inch = yres;
- }
-
- /* Dbox fields for options */
- #define opt_OK (0)
- /* #define opt_Cancel (1) No longer used */
- #define opt_Width (2)
- #define opt_Height (3)
- #define opt_XRes (4)
- #define opt_YRes (5)
- #define opt_SaveOnly (6)
-
- /* Floating point field access */
- static void set_field(dbox d, int field, float n)
- {
- char buffer[256];
- sprintf(buffer, "%g", n);
- dbox_setfield(d, field, buffer);
- }
-
- static void get_field(dbox d, int field, float *n)
- {
- char buffer[256];
- dbox_getfield(d, field, buffer, 256);
- sscanf(buffer, "%g", n);
- }
-
- /* Main menu handler: called on device options hit */
- BOOL arc_device_options(void *handle, char* hit)
- {
- adev_needed(handle);
-
- dbox d = dbox_new("GS_Options");
-
- if (d) /* If not, dbox_new failed */
- {
- int field;
- float xres, yres, width, height;
- float oxres, oyres, owidth, oheight;
- int mode, omode;
- BOOL saveonly, osaveonly;
- BOOL filling = TRUE;
-
- xres = adev->x_pixels_per_inch * (1 << adev->xeig);
- yres = adev->y_pixels_per_inch * (1 << adev->yeig);
- width = adev->width / adev->x_pixels_per_inch;
- height = adev->height / adev->y_pixels_per_inch;
- mode = adev->mode;
- saveonly = adev->save_only;
-
- /* Set current options in dbox */
- set_field(d, opt_Width, width);
- set_field(d, opt_Height, height);
- set_field(d, opt_XRes, xres);
- set_field(d, opt_YRes, yres);
- dbox_setnumeric(d, opt_SaveOnly, adev->save_only);
- dbox_show(d);
-
- while (filling)
- {
- field = dbox_fillin(d);
- if (field == opt_OK)
- {
- /* Set new options */
- owidth = width;
- oheight = height;
- oxres = xres;
- oyres = yres;
- omode = mode;
- osaveonly = saveonly;
-
- get_field(d, opt_Width, &width);
- get_field(d, opt_Height, &height);
- get_field(d, opt_XRes, &xres);
- get_field(d, opt_YRes, &yres);
- saveonly = (dbox_getnumeric(d, opt_SaveOnly) != 0);
- #ifdef AllowModeChange
- mode = wimpt_mode();
- #endif
- if (mode != omode || width != owidth || height != oheight ||
- xres != oxres || yres != oyres)
- {
- arc_set_options(adev, mode, width, height, xres, yres);
- if (!arc_create_op(adev))
- { /* Try to restore old options */
- arc_set_options(adev, omode, owidth, oheight, oxres, oyres);
- if (arc_create_op(adev))
- {
- werr(0,
- "Unable to create output (probably short of memory). Old options restored");
- }
- else
- {
- werr(0,
- "Unable to create output (probably short of memory), and old options could not be restored");
- return FALSE;
- gs_exit(1);
- }
- }
-
- arc_set_window_extent(adev);
- }
-
- adev->save_only = saveonly;
- filling = dbox_persist();
- }
- else if (/* field == opt_Cancel || */ field < 0)
- filling = FALSE;
- }
- dbox_dispose(&d);
- }
-
- return TRUE;
- }
-
-