home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Crawly Crypt Collection 2
/
crawlyvol2.bin
/
apps
/
dtp
/
ghost
/
gs301src
/
atari
/
gp_atar3.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-09-17
|
62KB
|
2,716 lines
/* Copyright (C) 1989, 1992, 1993 Aladdin Enterprises. All rights reserved.
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. */
/* gp_atar3.c */
/*
* This file contains general utility routines for the Atari platform.
*/
#include "gp_atar3.h"
extern WINLIST *WList; /* gp_atar2.c */
extern WINDOW conswin; /* gp_atar2.c */
extern WINDOW imagwin, aboutwin, reswin; /* gp_atar2.c */
extern WINDOW devwin, sizwin, iconwin, printwin; /* gp_atar2.c */
extern OBJECT menuobj[], aboutobj[], resobj[], devobj[];
extern OBJECT sizobj[], iconobj[], printobj[], savemsg[];
extern GRAPHIC Graphic;
extern char saveline[MAXLEN]; /* gp_atar1.h */
extern char devices[DEVICES][DNAMELEN]; /* gp_atar1.h */
extern char sizes[DEVICES][DNAMELEN]; /* gp_atar1.h */
extern VWRK VWork; /* gp_atar1.h */
extern PSTATE State; /* gp_atar1.h */
WINDOW *WinFindH(), *WinAlloc();
WINLIST *WinListAdd(), *WinListDelete();
WINTEXT *WinTextAlloc();
char (*TextBuffRealloc())[COLUMNS+1];
GRAPHIC *GraphicAlloc();
void *ObjFindH();
void
GetPalette(int *Palette, VWRK *vw)
{
int ColorIndex;
int ColorEntry[3];
unsigned int DefinedColors = vw->PaletteSize/3;
for (ColorIndex = 0; ColorIndex < DefinedColors; ColorIndex++) {
vq_color(vw->VdiHandle, ColorIndex, DEFINED_INTENSITY, ColorEntry);
Palette[3*ColorIndex] = ColorEntry[0];
Palette[3*ColorIndex+1] = ColorEntry[1];
Palette[3*ColorIndex+2] = ColorEntry[2];
}
}
void
SetPalette(int *Palette, VWRK *vw)
{
int ColorIndex;
int ColorEntry[3];
unsigned int DefinedColors = vw->PaletteSize/3;
for (ColorIndex = 0; ColorIndex < DefinedColors; ColorIndex++) {
ColorEntry[0] = Palette[3*ColorIndex];
ColorEntry[1] = Palette[3*ColorIndex+1];
ColorEntry[2] = Palette[3*ColorIndex+2];
vs_color(vw->VdiHandle, ColorIndex, ColorEntry);
}
}
/* Set the position of an object window. */
int
SetWinPosition(WINDOW *win, VWRK *vw, PSTATE *st, float x, float y)
{
GRECT itemp;
OBJECT *object = win->obj;
itemp.g_x = nint(x * vw->full.g_w);
itemp.g_y = nint(y * vw->full.g_h);
EnforceLimits(&itemp, vw);
if (win->opened) {
st->Event->SendMsg[0] = WM_MOVED;
st->Event->SendMsg[3] = win->handle;
st->Event->SendMsg[4] = itemp.g_x;
st->Event->SendMsg[5] = itemp.g_y;
st->Event->SendMsg[6] = win->frame.g_w;
st->Event->SendMsg[7] = win->frame.g_h;
appl_write(st->ApId, 16, st->Event->SendMsg);
}
else {
int ChangeX = itemp.g_x - win->frame.g_x;
int ChangeY = itemp.g_y - win->frame.g_y;
win->frame.g_x = itemp.g_x;
win->frame.g_y = itemp.g_y;
win->canvas.g_x += ChangeX;
win->canvas.g_y += ChangeY;
object[0].ob_x += ChangeX;
object[0].ob_y += ChangeY;
}
}
/* Set the window frame size. */
int
SetWinFrame(WINDOW *win, VWRK *vw, PSTATE *st,
float x, float y, float w, float h)
{
GRECT itemp;
if (win->opened) {
itemp.g_x = nint(x * vw->full.g_w);
itemp.g_y = nint(y * vw->full.g_h);
itemp.g_w = nint(w * vw->full.g_w);
itemp.g_h = nint(h * vw->full.g_h);
EnforceLimits(&itemp, vw);
st->Event->SendMsg[0] = WM_SIZED;
st->Event->SendMsg[3] = win->handle;
st->Event->SendMsg[4] = itemp.g_x;
st->Event->SendMsg[5] = itemp.g_y;
st->Event->SendMsg[6] = itemp.g_w;
st->Event->SendMsg[7] = itemp.g_h;
appl_write(st->ApId, 16, st->Event->SendMsg);
}
else {
win->frame.g_x = nint(x * vw->full.g_w);
win->frame.g_y = nint(y * vw->full.g_h);
win->frame.g_w = nint(w * vw->full.g_w);
win->frame.g_h = nint(h * vw->full.g_h);
EnforceLimits(&win->frame, vw);
}
}
/* Load the configuration file. */
int
LoadConfig(VWRK *vw, PSTATE *st)
{
FILE *config;
char *PathFind(), *sptr;
char line[MAXLEN], envvar[MAXLEN], value[MAXLEN];
static short DevCount=1, SizCount=0;
int itemp, ret;
float tempx, tempy, tempw, temph;
/* Look for the configuration file in the current and HOME directories. */
if ((sptr = PathFind("HOME", CONFIGFILE, ",")) != NULL) {
strcpy(line, sptr);
}
else {
return -1;
}
if ((config = fopen(line, "r")) == NULL) {
sprintf(line, "[1][Could not open %s!][OK]", CONFIGFILE);
form_alert(1, line);
return -1;
}
/* Process the information in the config file. */
while (fgets(line, MAXLEN-1, config) != NULL) {
line[strlen(line)-1] = '\0';
if (!strncmp(line, "consolewin ", 11)) {
sscanf(line+11, "%f %f %f %f", &tempx, &tempy, &tempw, &temph);
SetWinFrame(&conswin, vw, st, tempx, tempy, tempw, temph);
}
else if (!strncmp(line, "imagewin ", 9)) {
sscanf(line+9, "%f %f %f %f", &tempx, &tempy, &tempw, &temph);
SetWinFrame(&imagwin, vw, st, tempx, tempy, tempw, temph);
}
else if (!strncmp(line, "aboutwin ", 9)) {
sscanf(line+9, "%f %f", &tempx, &tempy);
SetWinPosition(&aboutwin, vw, st, tempx, tempy);
}
else if (!strncmp(line, "reswin ", 7)) {
sscanf(line+7, "%f %f", &tempx, &tempy);
SetWinPosition(&reswin, vw, st, tempx, tempy);
}
else if (!strncmp(line, "devwin ", 7)) {
sscanf(line+7, "%f %f", &tempx, &tempy);
SetWinPosition(&devwin, vw, st, tempx, tempy);
}
else if (!strncmp(line, "sizwin ", 7)) {
sscanf(line+7, "%f %f", &tempx, &tempy);
SetWinPosition(&sizwin, vw, st, tempx, tempy);
}
else if (!strncmp(line, "iconwin ", 8)) {
sscanf(line+8, "%f %f", &tempx, &tempy);
SetWinPosition(&iconwin, vw, st, tempx, tempy);
}
else if (!strncmp(line, "printwin ", 9)) {
sscanf(line+9, "%f %f", &tempx, &tempy);
SetWinPosition(&printwin, vw, st, tempx, tempy);
}
else if (!strncmp(line, "device ", 7)) {
if (DevCount < DEVICES) {
sscanf(line+7, "%s", devices[DevCount]);
++DevCount;
}
}
else if (!strncmp(line, "pagesize ", 9)) {
if (SizCount < SIZES) {
sscanf(line+9, "%s", sizes[SizCount]);
++SizCount;
}
}
else if (!strncmp(line, "pshelp ", 7)) {
sscanf(line+7, "%d", &itemp);
st->PSHelp = itemp;
menu_icheck(menuobj, PSHELP, st->PSHelp);
}
else if (!strncmp(line, "setenv ", 7)) {
sscanf(line+7, "%s", envvar);
putenv(envvar);
}
}
fclose(config);
}
/* Save the configuration file. */
int
SaveConfig(VWRK *vw, PSTATE *st)
{
FILE *config, *backup;
char *PathFind(), *sptr;
char line[MAXLEN], configfile[MAXLEN], backupfile[MAXLEN];
short i, back=0;
int fx, fy, fw, fh;
float hnorm, vnorm;
if ((vw->full.g_w == 0) || (vw->full.g_h == 0)) {
form_alert(1, "[1][Could not save!|Internal Error.][OK]");
return -1;
}
/* Look for the configuration file in the current and HOME directories. */
if ((sptr = PathFind("HOME", CONFIGFILE, ",")) != NULL) {
strcpy(configfile, sptr);
strcpy(backupfile, sptr);
if ((sptr = strrchr(backupfile, '\\')) != NULL) {
strcpy(sptr+1, CONFIGBAK);
}
else {
strcpy(backupfile, CONFIGBAK);
}
back = 1;
}
if (!strlen(configfile)) {
if ((sptr = getenv("HOME")) != NULL) {
strcpy(configfile, sptr);
strcat(configfile, CONFIGFILE);
}
else {
strcat(configfile, CONFIGFILE);
}
}
sprintf(saveline, " Saving Configuration to %s ... ", configfile);
savemsg[0].ob_width = strlen(saveline) * vw->Wchar;
savemsg[1].ob_width = strlen(saveline) * vw->Wchar;
form_center(savemsg, &fx, &fy, &fw, &fh);
form_dial(FMD_START, 0, 0, vw->Wchar, vw->Hchar, fx, fy, fw, fh);
objc_draw(savemsg, 0, 2, fx, fy, fw, fh);
/* Back up the config file. */
if (back) {
if ((config = fopen(configfile, "r")) == NULL) {
sprintf(line, "[1][Could not open %s!][OK]", configfile);
form_dial(FMD_FINISH, 0, 0, vw->Wchar, vw->Hchar, fx, fy, fw, fh);
form_alert(1, line);
return -1;
}
if ((backup = fopen(backupfile, "w")) == NULL) {
sprintf(line, "[1][Could not open %s!][OK]", backupfile);
form_dial(FMD_FINISH, 0, 0, vw->Wchar, vw->Hchar, fx, fy, fw, fh);
form_alert(1, line);
return -1;
}
while (fgets(line, MAXLEN-1, config) != NULL) {
fputs(line, backup);
}
fclose(backup);
fclose(config);
}
if ((config = fopen(configfile, "w")) == NULL) {
sprintf(line, "[1][Could not open %s!][OK]", configfile);
form_dial(FMD_FINISH, 0, 0, vw->Wchar, vw->Hchar, fx, fy, fw, fh);
form_alert(1, line);
return -1;
}
hnorm = 1.0 / ((float)vw->full.g_w);
vnorm = 1.0 / ((float)vw->full.g_h);
/* Write information to the config file. */
fputs("# Configuration file for Atari ST Ghostscript.\n", config);
fputs("# Window x, y, w, and h are specified as fractions\n", config);
fputs("# of the screen size.\n\n", config);
fprintf(config, "consolewin %f %f %f %f\n",
conswin.frame.g_x * hnorm,
conswin.frame.g_y * vnorm,
conswin.frame.g_w * hnorm,
conswin.frame.g_h * vnorm);
fprintf(config, "imagewin %f %f %f %f\n",
imagwin.frame.g_x * hnorm,
imagwin.frame.g_y * vnorm,
imagwin.frame.g_w * hnorm,
imagwin.frame.g_h * vnorm);
fputs("\n# Only x and y for the following windows.\n\n", config);
fprintf(config, "aboutwin %f %f\n",
aboutwin.frame.g_x * hnorm,
aboutwin.frame.g_y * vnorm);
fprintf(config, "reswin %f %f\n",
reswin.frame.g_x * hnorm,
reswin.frame.g_y * vnorm);
fprintf(config, "devwin %f %f\n",
devwin.frame.g_x * hnorm,
devwin.frame.g_y * vnorm);
fprintf(config, "sizwin %f %f\n",
sizwin.frame.g_x * hnorm,
sizwin.frame.g_y * vnorm);
fprintf(config, "iconwin %f %f\n",
iconwin.frame.g_x * hnorm,
iconwin.frame.g_y * vnorm);
fprintf(config, "printwin %f %f\n",
printwin.frame.g_x * hnorm,
printwin.frame.g_y * vnorm);
fputs("\n# Devices available from the device dialog.\n\n", config);
for (i=1; i<DEVICES; ++i) {
fprintf(config, "device %s\n", devices[i]);
}
fputs("\n# Page sizes available from the size dialog.\n\n", config);
for (i=0; i<SIZES; ++i) {
fprintf(config, "pagesize %s\n", sizes[i]);
}
fputs("\n# Options: 1 = selected, 0 = unselected.\n\n", config);
fprintf(config, "pshelp %d\n", st->PSHelp);
/* Copy any environment variables from the backup file. */
#if 0
if (back) {
fputs("\n# Ghostscript Environment Variables.\n\n", config);
if ((backup = fopen(backupfile, "r")) == NULL) {
sprintf(line, "[1][Could not open %s!][OK]", backupfile);
form_dial(FMD_FINISH, 0, 0, vw->Wchar, vw->Hchar, fx, fy, fw, fh);
form_alert(1, line);
return -1;
}
while (fgets(line, MAXLEN-1, backup) != NULL) {
if (!strncmp(line, "setenv ", 7)) {
fputs(line, config);
}
}
fclose(backup);
}
#endif
fclose(config);
form_dial(FMD_FINISH, 0, 0, vw->Wchar, vw->Hchar, fx, fy, fw, fh);
}
int
DevObjUpdate(PSTATE *st)
{
int i;
/* Ensure that the button for the current device is selected. */
for (i=FIRSTDEV; !(devobj[i].ob_state & SELECTED) && (i<=LASTDEV); ++i);
if ((i <= LASTDEV) && (i != st->Device)) {
objc_change(devobj, i, 0,
devwin.canvas.g_x, devwin.canvas.g_y,
devwin.canvas.g_w, devwin.canvas.g_h,
(devobj[i].ob_state ^ SELECTED), devwin.opened);
objc_change(devobj, st->Device, 0,
devwin.canvas.g_x, devwin.canvas.g_y,
devwin.canvas.g_w, devwin.canvas.g_h,
(devobj[st->Device].ob_state ^ SELECTED), devwin.opened);
st->LastDevice = st->Device;
}
}
int
CopyImage(GRAPHIC *sgr, VWRK *vw, PSTATE *st)
{
WINDOW *bwin;
GRAPHIC *gr; /* new graphic structure */
WINLIST *wl = WList;
byte *buff;
ulong buff_size = sgr->image.fd_w * sgr->image.fd_h;
if ((bwin = WinAlloc()) == NULL) {
form_alert(1, "[1][Ghostscript Error!|No More Memory.][Continue]");
return (-1);
}
if ((gr = GraphicAlloc()) == NULL) {
form_alert(1, "[1][Ghostscript Error!|No More Memory.][Continue]");
WinFree(bwin);
return (-1);
}
if ((buff = (byte *)gs_malloc((uint)buff_size, 1, "bitbuffer")) == NULL) {
form_alert(1, "[1][Ghostscript Error!|No More Memory.][Continue]");
WinFree(bwin);
GraphicFree(gr);
return (-1);
}
BitWinInit(bwin, gr, C_GADGETS, C_TITL);
gr->image.fd_addr = (unsigned long) buff;
memcpy((void *)gr->image.fd_addr, (void *)sgr->image.fd_addr, buff_size);
WinListAdd(wl, bwin);
BitWinOpen(bwin, vw, st);
}
int
BitWinOpen(WINDOW *bwin, VWRK *vw, PSTATE *st)
{
GRAPHIC *gr = bwin->obj;
/* Open a window for a bitmap image. */
if (bwin->iconified) {
wind_open(bwin->handle,
bwin->frame.g_x, bwin->frame.g_y,
MIN(bwin->frame.g_w, bwin->mframe.g_w),
MIN(bwin->frame.g_h, bwin->mframe.g_h));
bwin->opened = 1;
bwin->iconified = 0;
}
else if (!bwin->opened) {
wind_calc(0, bwin->gadgets,
vw->full.g_x, vw->full.g_y,
gr->Width, gr->Height,
&bwin->mframe.g_x, &bwin->mframe.g_y,
&bwin->mframe.g_w, &bwin->mframe.g_h);
if ((bwin->frame.g_w + bwin->frame.g_h) == 0) {
bwin->frame.g_x = bwin->mframe.g_x;
bwin->frame.g_y = bwin->mframe.g_y;
bwin->frame.g_w = bwin->mframe.g_w;
bwin->frame.g_h = bwin->mframe.g_h;
}
bwin->handle = wind_create(
bwin->gadgets + (st->MultiTOS ? SMALLER : 0),
bwin->mframe.g_x, bwin->mframe.g_y,
bwin->mframe.g_w, bwin->mframe.g_h);
if (bwin->handle < 0) {
form_alert(1, "[1][Ghostscript Error!|No More Windows.][Continue]");
WinListDelete(WList, bwin);
return (-1);
}
wind_set(bwin->handle, WF_NAME, bwin->title, bwin->title, 0, 0);
wind_open(bwin->handle,
bwin->frame.g_x, bwin->frame.g_y,
MIN(bwin->frame.g_w, bwin->mframe.g_w),
MIN(bwin->frame.g_h, bwin->mframe.g_h));
wind_get(bwin->handle, WF_CURRXYWH,
&bwin->frame.g_x, &bwin->frame.g_y,
&bwin->frame.g_w, &bwin->frame.g_h);
wind_get(bwin->handle, WF_CURRXYWH,
&bwin->oframe.g_x, &bwin->oframe.g_y,
&bwin->oframe.g_w, &bwin->oframe.g_h);
wind_get(bwin->handle, WF_WORKXYWH,
&bwin->canvas.g_x, &bwin->canvas.g_y,
&bwin->canvas.g_w, &bwin->canvas.g_h);
gr->StepX = .9 * bwin->canvas.g_w;
gr->StepY = .9 * bwin->canvas.g_h;
bwin->opened = 1;
update_scroll(bwin->handle);
}
return 0;
}
int
HelpWinOpen(VWRK *vw, PSTATE *st, char *HelpFile)
{
FILE *helpf, *lib_fopen();
WINDOW *hwin;
WINTEXT *text;
WINLIST *wl=WList;
char line[MAXLEN], helpfile[MAXLEN];
int count, twincount=0, length, longest=0;
if ((hwin = WinAlloc()) == NULL) {
form_alert(1, "[1][Ghostscript Error!|No More Memory.][Continue]");
return (-1);
}
if ((text = WinTextAlloc(LINES)) == NULL) {
form_alert(1, "[1][Ghostscript Error!|No More Memory.][Continue]");
WinFree(hwin);
return (-1);
}
TextWinInit(hwin, text, H_GADGETS, H_TITL);
/* Read help file into the text buffer. */
strcpy(helpfile, HelpFile);
if ((helpf = lib_fopen(helpfile)) == NULL) {
sprintf(line, "[1][Could not open %s!][OK]", helpfile);
form_alert(1, line);
return -1;
}
for (count=0; (fgets(line, MAXLEN-1, helpf) != NULL); ++count) {
length = strlen(line);
line[length-2] = '\0';
if (length-2 > longest) longest = length-2;
if (count >= text->bsize - 1) {
int NewSize = text->bsize + LINES;
if (TextBuffRealloc(text, NewSize) == NULL) {
form_alert(1, "[1][There is only enough ram to|\
load a portion of this file.][Continue]");
break;
}
}
strcpy(text->buff[count], line);
}
fclose(helpf);
if (hwin->frame.g_w + hwin->frame.g_h == 0) {
wind_calc(0, hwin->gadgets, vw->full.g_x, vw->full.g_y,
(longest + 4)*vw->Wchar, (count + 1)*vw->Hchar,
&hwin->frame.g_x, &hwin->frame.g_y,
&hwin->frame.g_w, &hwin->frame.g_h);
/* Count the number of open text windows. */
do {
if (wl->Win->type == TEXT){
++twincount;
}
wl = wl->Next;
}
while (wl != WList);
/* Place the window according to how many text windows are open. */
hwin->frame.g_x = 2 * twincount * vw->Wchar;
hwin->frame.g_y = vw->full.g_y + twincount * vw->Hchar;
hwin->frame.g_w = MIN(hwin->frame.g_w, vw->full.g_w - hwin->frame.g_x);
hwin->frame.g_h = MIN(hwin->frame.g_h,
vw->full.g_h - twincount * vw->Hchar);
}
text->bw = longest;
text->bh = count;
WinListAdd(WList, hwin);
TextWinOpen(hwin, vw, st);
text->ln = count-1;
}
int
TextWinOpen(WINDOW *twin, VWRK *vw, PSTATE *st)
{
WINTEXT *text = twin->obj;
/* Create, open, and initialize a text window. */
if (twin->iconified) {
wind_open(twin->handle,
twin->frame.g_x, twin->frame.g_y,
MIN(twin->frame.g_w, twin->mframe.g_w),
MIN(twin->frame.g_h, twin->mframe.g_h));
twin->opened = 1;
twin->iconified = 0;
}
else if (!twin->opened) {
int dummy;
text->wc = vw->Wchar;
text->hc = vw->Hchar;
wind_calc(0, twin->gadgets, vw->full.g_x, vw->full.g_y,
(text->bw + 4)*text->wc, (text->bh + 1)*text->hc,
&twin->mframe.g_x, &twin->mframe.g_y,
&twin->mframe.g_w, &twin->mframe.g_h);
twin->mframe.g_x = MAX(twin->mframe.g_x, vw->full.g_x);
twin->mframe.g_y = MAX(twin->mframe.g_y, vw->full.g_y);
twin->mframe.g_w = MIN(twin->mframe.g_w, vw->full.g_w);
twin->mframe.g_h = MIN(twin->mframe.g_h, vw->full.g_h);
twin->handle = wind_create(
twin->gadgets + (st->MultiTOS ? SMALLER : 0),
twin->mframe.g_x, twin->mframe.g_y,
twin->mframe.g_w, twin->mframe.g_h);
if (twin->handle < 0) {
form_alert(1, "[1][Ghostscript Error!|No More Windows.][Continue]");
WinListDelete(WList, twin);
return (-1);
}
wind_set(twin->handle, WF_NAME,
twin->title, twin->title, 0, 0);
if ((twin->frame.g_w + twin->frame.g_h) == 0) {
wind_calc(0, twin->gadgets + (st->MultiTOS ? SMALLER : 0),
vw->full.g_x, vw->full.g_y,
(text->bw + 2)*text->wc, (text->bh + 1)*text->hc,
&twin->frame.g_x, &twin->frame.g_y,
&twin->frame.g_w, &twin->frame.g_h);
twin->frame.g_x = vw->full.g_x;
twin->frame.g_y = vw->full.g_y;
twin->frame.g_w = MIN(twin->frame.g_w, vw->full.g_w);
twin->frame.g_h = MIN(twin->frame.g_h, vw->full.g_h);
}
wind_open(twin->handle,
twin->frame.g_x, twin->frame.g_y,
twin->frame.g_w, twin->frame.g_h);
wind_get(twin->handle, WF_CURRXYWH,
&twin->oframe.g_x, &twin->oframe.g_y,
&twin->oframe.g_w, &twin->oframe.g_h);
wind_get(twin->handle, WF_WORKXYWH,
&twin->canvas.g_x, &twin->canvas.g_y,
&twin->canvas.g_w, &twin->canvas.g_h);
twin->opened = 1;
text->edge = twin->canvas.g_x;
text->top = twin->canvas.g_y;
text->xoff = text->wc/2;
text->yoff = text->hc/2;
text->lins = visible_lines(twin);
text->cols = visible_cols(twin);
text->ll = text->bh - 1;
text->ldl = text->fdl + text->lins - 1;
text->cx = align(text->edge + text->xoff);
text->cy = text->top + text->yoff;
vst_alignment(vw->VdiHandle, 0, 5, &dummy, &dummy);
clear_win(&twin->canvas);
update_scroll(twin->handle);
}
return 0;
}
int
ObjWinOpen(OBJECT obj[], WINDOW *owin, VWRK *vw, PSTATE *st)
{
/* Create and open a window for a GEM object. */
if (owin->iconified) {
obj[0].ob_flags ^= HIDETREE; /* Make the object tree visible. */
wind_open(owin->handle,
owin->frame.g_x, owin->frame.g_y,
owin->frame.g_w, owin->frame.g_h);
owin->opened = 1;
owin->iconified = 0;
}
else if (!owin->opened) {
owin->handle = wind_create(owin->gadgets,
vw->full.g_x, vw->full.g_y,
vw->full.g_w, vw->full.g_h);
if (owin->handle < 0) {
form_alert(1,
"[1][Ghostscript Error!|No More Windows.][Continue]");
WinListDelete(WList, owin);
return (-1);
}
wind_set(owin->handle, WF_NAME, owin->title, owin->title, 0, 0);
/* Make the object tree visible. */
obj[0].ob_flags ^= HIDETREE;
/* If the window has never been opened, width and height will
* be zero. In this case, center the object before opening
* the window.
*/
if ((owin->frame.g_w + owin->frame.g_h) == 0) {
int tempx, tempy;
form_center(obj,
&owin->canvas.g_x, &owin->canvas.g_y,
&owin->canvas.g_w, &owin->canvas.g_h);
wind_calc(0, owin->gadgets,
owin->canvas.g_x, owin->canvas.g_y,
owin->canvas.g_w, owin->canvas.g_h,
&tempx, &tempy,
&owin->frame.g_w, &owin->frame.g_h);
if (owin->frame.g_x + owin->frame.g_y) {
owin->canvas.g_x += owin->frame.g_x - tempx;
owin->canvas.g_y += owin->frame.g_y - tempy;
obj[0].ob_x += owin->frame.g_x - tempx;
obj[0].ob_y += owin->frame.g_y - tempy;
}
else {
owin->frame.g_x = tempx;
owin->frame.g_y = tempy;
}
}
/* The object is drawn by the redraw message which is
* automatically sent when the window is opened.
*/
wind_open(owin->handle,
owin->frame.g_x, owin->frame.g_y,
owin->frame.g_w, owin->frame.g_h);
owin->opened = 1;
}
else {
wind_set(owin->handle, WF_TOP, 0, 0, 0, 0);
}
return 0;
}
int
WinClose(WINDOW *win)
{
/* Close and delete the window; hide the object. */
if (win->iconified) {
wind_delete(win->handle);
win->handle = -1;
win->iconified = 0;
}
else if (win->opened) {
wind_get(win->handle, WF_CURRXYWH,
&win->frame.g_x, &win->frame.g_y,
&win->frame.g_w, &win->frame.g_h);
wind_get(win->handle, WF_CURRXYWH,
&win->oframe.g_x, &win->oframe.g_y,
&win->oframe.g_w, &win->oframe.g_h);
wind_close(win->handle);
wind_delete(win->handle);
if (win->type == OBJ) {
OBJECT *obj = win->obj;
obj[0].ob_flags ^= HIDETREE;
}
win->handle = -1;
win->opened = 0;
}
return 0;
}
int
bitw_arrow(PSTATE *st)
{
int ChangeX, ChangeY;
WINDOW *bwin = WinFindH(st->Event->Message[3]);
GRAPHIC *gr = bwin->obj;
VWRK *vw = &VWork;
switch (st->Event->Message[4]) {
case WA_UPLINE: /* up line or top of page */
if (st->Event->KeyState)
gr->PlotY = 0;
else
gr->PlotY = MAX(gr->PlotY - vw->Hchar, 0);
break;
case WA_DNLINE: /* down line or bottom of page */
if (st->Event->KeyState)
gr->PlotY = gr->Height - bwin->canvas.g_h;
else
gr->PlotY = MIN(gr->PlotY + vw->Hchar,
gr->Height - bwin->canvas.g_h);
break;
case WA_LFLINE: /* left line or left page edge */
if (st->Event->KeyState)
gr->PlotX = 0;
else
gr->PlotX = MAX(gr->PlotX - vw->Wchar, 0);
break;
case WA_RTLINE: /* right page edge */
if (st->Event->KeyState)
gr->PlotX = gr->Width - bwin->canvas.g_w;
else
gr->PlotX = MIN(gr->PlotX + vw->Wchar,
gr->Width - bwin->canvas.g_w);
break;
case WA_UPPAGE: /* up page */
gr->PlotY = MAX(gr->PlotY - gr->StepY, 0);
break;
case WA_DNPAGE: /* down page */
gr->PlotY = MIN(gr->PlotY + gr->StepY,
gr->Height - bwin->canvas.g_h);
break;
case WA_LFPAGE: /* left page */
gr->PlotX = MAX(gr->PlotX - gr->StepX, 0);
break;
case WA_RTPAGE: /* right page */
gr->PlotX = MIN(gr->PlotX + gr->StepX,
gr->Width - bwin->canvas.g_w);
break;
}
update_scroll(st->Event->Message[3]);
cursor(OFF);
HandleRedraw(FULL_WIN, &State);
cursor(ON);
}
int
txtw_hslide(PSTATE *st)
{
int ChangeX, ChangeY;
int handle = st->Event->Message[3];
WINDOW *twin = WinFindH(handle);
WINTEXT *text = twin->obj;
text->fdc = (text->bw + 2 - text->cols) * st->Event->Message[4]/1000;
text->ldc = text->fdc + text->cols - 1;
ChangeX = twin->canvas.g_x - text->fdc * text->wc - text->edge;
text->edge += ChangeX;
text->cx += ChangeX;
update_scroll(handle);
cursor(OFF);
HandleRedraw(FULL_WIN, st);
cursor(ON);
}
int
bitw_hslide(PSTATE *st)
{
WINDOW *bwin = WinFindH(st->Event->Message[3]);
GRAPHIC *gr = bwin->obj;
gr->PlotX = (gr->Width - bwin->canvas.g_w) * st->Event->Message[4]/1000;
update_scroll(st->Event->Message[3]);
HandleRedraw(FULL_WIN, st);
}
int
txtw_vslide(PSTATE *st)
{
int ChangeX, ChangeY;
WINTEXT *text = ObjFindH(st->Event->Message[3]);
int OldOffset = text->fdl - text->fl;
int NewOffset = (text->bh - text->lins) * st->Event->Message[4]/1000;
if (OldOffset < 0) OldOffset += text->bh;
text->fdl = text->fl + NewOffset;
if (text->fdl >= text->bh) text->fdl -= text->bh;
text->ldl = text->fdl + text->lins - 1;
if (text->ldl >= text->bh) text->ldl -= text->bh;
ChangeY = (OldOffset - NewOffset) * text->hc;
text->top += ChangeY;
text->cy += ChangeY;
}
int
bitw_vslide(PSTATE *st)
{
WINDOW *bwin = WinFindH(st->Event->Message[3]);
GRAPHIC *gr = bwin->obj;
gr->PlotY = (gr->Height - bwin->canvas.g_h) * st->Event->Message[4]/1000;
}
int
objw_move(PSTATE *st)
{
int ChangeX, ChangeY;
WINDOW *owin = WinFindH(st->Event->Message[3]);
OBJECT *obj = owin->obj;
wind_set(owin->handle, WF_CURRXYWH,
st->Event->Message[4], st->Event->Message[5],
st->Event->Message[6], st->Event->Message[7]);
ChangeX = st->Event->Message[4] - owin->frame.g_x;
ChangeY = st->Event->Message[5] - owin->frame.g_y;
obj[0].ob_x += ChangeX;
obj[0].ob_y += ChangeY;
wind_get(owin->handle, WF_CURRXYWH,
&owin->frame.g_x, &owin->frame.g_y,
&owin->frame.g_w, &owin->frame.g_h);
wind_get(owin->handle, WF_WORKXYWH,
&owin->canvas.g_x, &owin->canvas.g_y,
&owin->canvas.g_w, &owin->canvas.g_h);
}
int
bitw_move(PSTATE *st)
{
WINDOW *bwin = WinFindH(st->Event->Message[3]);
wind_set(bwin->handle, WF_CURRXYWH,
st->Event->Message[4], st->Event->Message[5],
MIN(bwin->mframe.g_w, st->Event->Message[6]),
MIN(bwin->mframe.g_h, st->Event->Message[7]));
wind_get(bwin->handle, WF_CURRXYWH,
&bwin->frame.g_x, &bwin->frame.g_y,
&bwin->frame.g_w, &bwin->frame.g_h);
wind_get(bwin->handle, WF_WORKXYWH,
&bwin->canvas.g_x, &bwin->canvas.g_y,
&bwin->canvas.g_w, &bwin->canvas.g_h);
}
int
txtw_move(PSTATE *st)
{
int ChangeX, ChangeY;
WINDOW *twin = WinFindH(st->Event->Message[3]);
WINTEXT *text = twin->obj;
int oldcanvas_x = twin->canvas.g_x;
int oldcanvas_y = twin->canvas.g_y;
wind_set(twin->handle, WF_CURRXYWH,
align(st->Event->Message[4]), st->Event->Message[5],
MIN(twin->mframe.g_w, st->Event->Message[6]),
MIN(twin->mframe.g_w, st->Event->Message[7]));
wind_get(twin->handle, WF_CURRXYWH,
&twin->frame.g_x, &twin->frame.g_y,
&twin->frame.g_w, &twin->frame.g_h);
wind_get(twin->handle, WF_WORKXYWH,
&twin->canvas.g_x, &twin->canvas.g_y,
&twin->canvas.g_w, &twin->canvas.g_h);
ChangeX = twin->canvas.g_x - oldcanvas_x;
ChangeY = twin->canvas.g_y - oldcanvas_y;
text->edge += ChangeX;
text->top += ChangeY;
text->cx += ChangeX;
text->cy += ChangeY;
}
int
txtw_arrow(PSTATE *st)
{
int ChangeX, ChangeY;
int handle = st->Event->Message[3];
WINDOW *twin = WinFindH(handle);
WINTEXT *text = twin->obj;
switch (st->Event->Message[4]) {
case WA_UPLINE: /* top line or up line */
if (st->Event->KeyState) {
ChangeY = twin->canvas.g_y - text->top;
text->top += ChangeY;
text->cy += ChangeY;
text->fdl = text->fl;
text->ldl = text->fl + text->lins - 1;
if (text->ldl >= text->bh) text->ldl -= text->bh;
}
else {
if (text->fdl != text->fl) {
text->top += text->hc;
text->cy += text->hc;
if (--text->fdl < 0) text->fdl += text->bh;
if (--text->ldl < 0) text->fdl += text->bh;
}
}
break;
case WA_DNLINE: /* bottom line or down line */
if (st->Event->KeyState) {
ChangeY = twin->canvas.g_y
- (text->bh - text->lins) * text->hc - text->top;
text->top += ChangeY;
text->cy += ChangeY;
text->fdl = text->ll - text->lins + 1;
text->ldl = text->ll;
if (text->fdl < 0) text->fdl += text->bh;
}
else {
if (text->ldl != text->ll) {
text->top -= text->hc;
text->cy -= text->hc;
if (++text->fdl >= text->bh) text->fdl = 0;
if (++text->ldl >= text->bh) text->ldl = 0;
}
}
break;
case WA_LFLINE: /* left line */
if (st->Event->KeyState) {
ChangeX = twin->canvas.g_x - text->edge;
text->edge += ChangeX;
text->cx += ChangeX;
text->fdc = 0;
text->ldc = text->cols - 1;
}
else {
if (text->fdc > 0) {
text->edge += text->wc;
text->cx += text->wc;
text->fdc--;
text->ldc--;
}
}
break;
case WA_RTLINE: /* right line */
if (st->Event->KeyState) {
ChangeX = twin->canvas.g_x
- (text->bw + 2 - text->cols) * text->wc - text->edge;
text->edge += ChangeX;
text->cx += ChangeX;
text->fdc = (text->bw + 2 - text->cols);
text->ldc = text->fdc + text->cols - 1;
}
else {
if ((text->fdc + text->cols) < (text->bw + 2)) {
text->edge -= text->wc;
text->cx -= text->wc;
text->fdc++;
text->ldc++;
}
}
break;
case WA_UPPAGE: /* up page */
{
int to_top = text->fdl - text->fl;
to_top = (to_top >= 0) ? to_top : to_top + text->bh;
if (to_top >= (text->lins - 1)) {
text->top += (text->lins - 1) * text->hc;
text->cy += (text->lins - 1) * text->hc;
text->fdl -= (text->lins - 1);
text->ldl -= (text->lins - 1);
if (text->fdl < 0) text->fdl += text->bh;
if (text->ldl < 0) text->ldl += text->bh;
}
else {
ChangeY = twin->canvas.g_y - text->top;
text->top += ChangeY;
text->cy += ChangeY;
text->fdl = text->fl;
text->ldl = text->fl + text->lins - 1;
if (text->ldl >= text->bh) text->ldl -= text->bh;
}
break;
}
case WA_DNPAGE: /* down page */
{
int to_bot = text->ll - text->ldl;
to_bot = (to_bot >= 0) ? to_bot : to_bot + text->bh;
if (to_bot >= (text->lins - 1)) {
text->top -= (text->lins - 1) * text->hc;
text->cy -= (text->lins - 1) * text->hc;
text->fdl += (text->lins - 1);
text->ldl += (text->lins - 1);
if (text->fdl >= text->bh) text->fdl -= text->bh;
if (text->ldl >= text->bh) text->ldl -= text->bh;
}
else {
ChangeY = twin->canvas.g_y
- (text->bh - text->lins) * text->hc - text->top;
text->top += ChangeY;
text->cy += ChangeY;
text->fdl = text->ll - text->lins + 1;
text->ldl = text->ll;
if (text->fdl < 0) text->fdl += text->bh;
}
break;
}
case WA_LFPAGE: /* left page */
if (text->fdc >= (text->cols - 1)) {
text->edge += (text->cols - 1) * text->wc;
text->cx += (text->cols - 1) * text->wc;
text->fdc -= (text->cols - 1);
text->ldc = text->fdc + text->cols - 1;
}
else {
ChangeX = twin->canvas.g_x - text->edge;
text->edge += ChangeX;
text->cx += ChangeX;
text->fdc = 0;
text->ldc = text->cols - 1;
}
break;
case WA_RTPAGE: /* right page */
if (text->fdc <= (text->bw - 2*text->cols + 3)) {
text->edge -= (text->cols - 1) * text->wc;
text->cx -= (text->cols - 1) * text->wc;
text->fdc += (text->cols - 1);
text->ldc += (text->cols - 1);
}
else {
ChangeX = twin->canvas.g_x
- (text->bw + 2 - text->cols) * text->wc - text->edge;
text->edge += ChangeX;
text->cx += ChangeX;
text->fdc = (text->bw + 2 - text->cols);
text->ldc = text->fdc + text->cols - 1;
}
break;
}
update_scroll(st->Event->Message[3]);
cursor(OFF);
HandleRedraw(FULL_WIN, &State);
cursor(ON);
}
int
txtw_size(PSTATE *st)
{
int handle = st->Event->Message[3];
WINDOW *twin = WinFindH(handle);
WINTEXT *text = twin->obj;
int offset, diff, ChangeX;
int old_x = twin->canvas.g_x;
int old_y = twin->canvas.g_y;
int old_w = twin->canvas.g_w;
int old_h = twin->canvas.g_h;
wind_set(twin->handle, WF_CURRXYWH,
st->Event->Message[4], st->Event->Message[5],
MIN(twin->mframe.g_w, st->Event->Message[6]),
MIN(twin->mframe.g_h, st->Event->Message[7]));
wind_get(twin->handle, WF_CURRXYWH,
&twin->frame.g_x, &twin->frame.g_y,
&twin->frame.g_w, &twin->frame.g_h);
wind_get(twin->handle, WF_WORKXYWH,
&twin->canvas.g_x, &twin->canvas.g_y,
&twin->canvas.g_w, &twin->canvas.g_h);
text->lins = visible_lines(twin);
text->cols = visible_cols(twin);
/* For the console window, put the current line at the bottom
* of the window and adjust the first and last lines accordingly.
* For other text windows, leave the first line unchanged if
* possible.
*/
if (twin->handle == conswin.handle) {
text->fdl = text->ln - text->lins + 1;
if (text->fdl > text->bh) {
text->fdl -= text->bh;
}
else if (text->fdl < 0 && !text->scrolled) {
text->fdl = 0;
}
else if (text->fdl < 0 && text->scrolled) {
text->fdl += text->bh;
}
}
text->ldl = text->fdl + text->lins - 1;
if (text->ldl >= text->bh) {
if (text->scrolled) {
text->ldl -= text->bh;
}
else { /* First displayed line must be changed. */
text->ldl = text->bh - 1;
text->fdl = text->ldl - text->lins + 1;
}
}
/* Keep the first column the same, if possible, and adjust the
* last column appropriately.
*/
text->ldc = text->fdc + text->cols - 1;
ChangeX = twin->canvas.g_x - old_x;
if ((diff = text->ldc - text->bw - 1) > 0) { /* Change first column. */
ChangeX += diff * text->wc;
text->ldc = text->bw + 1;
text->fdc = text->ldc - text->cols + 1;
}
/* Adjust the cursor position. */
text->cx += ChangeX;
offset = text->ln - text->fdl;
if (offset < 0) offset += text->bh;
if (offset >= text->bh) offset -= text->bh;
text->cy = twin->canvas.g_y + text->yoff + offset * text->hc;
/* Adjust the left edge and top of the page. */
text->edge += ChangeX;
offset = text->fdl - text->fl;
if (offset < 0) offset += text->bh;
if (offset >= text->bh) offset -= text->bh;
text->top = twin->canvas.g_y - offset * text->hc;
/* Redraw the window if the OS won't. */
if (old_x <= twin->canvas.g_x &&
old_y <= twin->canvas.g_y &&
old_w >= twin->canvas.g_w &&
old_h >= twin->canvas.g_h) {
cursor(OFF);
HandleRedraw(FULL_WIN, st);
cursor(ON);
}
update_scroll(handle);
}
int
bitw_size(PSTATE *st)
{
WINDOW *bwin = WinFindH(st->Event->Message[3]);
GRAPHIC *gr = bwin->obj;
wind_set(bwin->handle, WF_CURRXYWH,
st->Event->Message[4], st->Event->Message[5],
MIN(bwin->mframe.g_w, st->Event->Message[6]),
MIN(bwin->mframe.g_h, st->Event->Message[7]));
wind_get(bwin->handle, WF_CURRXYWH,
&bwin->frame.g_x, &bwin->frame.g_y,
&bwin->frame.g_w, &bwin->frame.g_h);
wind_get(bwin->handle, WF_WORKXYWH,
&bwin->canvas.g_x, &bwin->canvas.g_y,
&bwin->canvas.g_w, &bwin->canvas.g_h);
gr->StepX = .9 * bwin->canvas.g_w;
gr->StepY = .9 * bwin->canvas.g_h;
update_scroll(st->Event->Message[3]);
}
int
txtw_redraw(int full_win, PSTATE *st)
{
int handle = st->Event->Message[3];
WINDOW *twin = WinFindH(handle);
WINTEXT *text = twin->obj;
int i, cnt;
int x = align(twin->canvas.g_x + text->xoff);
int fcol = text->fdc;
int y, TopLineY, ln;
GRECT dirty, rect;
if (full_win) {
dirty.g_x = twin->canvas.g_x;
dirty.g_y = twin->canvas.g_y;
dirty.g_w = twin->canvas.g_w;
dirty.g_h = twin->canvas.g_h;
}
else {
dirty.g_x = st->Event->Message[4];
dirty.g_y = st->Event->Message[5];
dirty.g_w = st->Event->Message[6];
dirty.g_h = st->Event->Message[7];
}
TopLineY = twin->canvas.g_y + text->yoff;
cnt = text->ln - text->fdl + 1;
cnt = (cnt > 0) ? cnt : cnt + text->bh;
cnt = MIN(cnt, text->lins);
wind_get(twin->handle, WF_FIRSTXYWH,
&rect.g_x, &rect.g_y,
&rect.g_w, &rect.g_h);
graf_mouse(M_OFF, 0L);
while (rect.g_w && rect.g_h) {
if (rc_intersect(&dirty, &rect)) {
if (rc_intersect(&twin->canvas, &rect)) {
y = TopLineY;
grect_to_array(&rect, st->pxy);
vs_clip(VWork.VdiHandle, 1, st->pxy);
clear_win(&rect);
for (ln=text->fdl, i=cnt; i; i--, ln++, y+=text->hc) {
if (ln >= text->bh) ln -= text->bh;
if (strlen(text->buff[ln]) > fcol)
v_gtext(VWork.VdiHandle, x, y, text->buff[ln]+fcol);
}
vs_clip(VWork.VdiHandle, 0, st->pxy);
}
}
wind_get(twin->handle, WF_NEXTXYWH,
&rect.g_x, &rect.g_y,
&rect.g_w, &rect.g_h);
}
graf_mouse(M_ON, 0L);
}
int
objw_redraw(int full_win, PSTATE *st)
{
int handle = st->Event->Message[3];
WINDOW *owin = WinFindH(handle);
OBJECT *obj = owin->obj;
GRECT dirty, rect;
if (full_win) {
dirty.g_x = owin->canvas.g_x;
dirty.g_y = owin->canvas.g_y;
dirty.g_w = owin->canvas.g_w;
dirty.g_h = owin->canvas.g_h;
}
else {
dirty.g_x = st->Event->Message[4];
dirty.g_y = st->Event->Message[5];
dirty.g_w = st->Event->Message[6];
dirty.g_h = st->Event->Message[7];
}
wind_get(handle, WF_FIRSTXYWH,
&rect.g_x, &rect.g_y,
&rect.g_w, &rect.g_h);
graf_mouse(M_OFF, 0L);
while (rect.g_w && rect.g_h) {
if (rc_intersect(&dirty, &rect)) {
if (rc_intersect(&owin->canvas, &rect)) {
objc_draw(obj, 0, 3,
rect.g_x, rect.g_y,
rect.g_w, rect.g_h);
}
}
wind_get(handle, WF_NEXTXYWH,
&rect.g_x, &rect.g_y,
&rect.g_w, &rect.g_h);
}
graf_mouse(M_ON, 0L);
}
int
bitw_redraw(int full_win, PSTATE *st)
{
WINDOW *bwin = WinFindH(st->Event->Message[3]);
GRAPHIC *gr = bwin->obj;
GRECT dirty, rect;
if (full_win) {
dirty.g_x = bwin->canvas.g_x;
dirty.g_y = bwin->canvas.g_y;
dirty.g_w = bwin->canvas.g_w;
dirty.g_h = bwin->canvas.g_h;
}
else {
dirty.g_x = st->Event->Message[4];
dirty.g_y = st->Event->Message[5];
dirty.g_w = st->Event->Message[6];
dirty.g_h = st->Event->Message[7];
}
gr->PlotX = MIN(gr->PlotX, gr->Width - bwin->canvas.g_w);
gr->PlotY = MIN(gr->PlotY, gr->Height - bwin->canvas.g_h);
wind_get(bwin->handle, WF_FIRSTXYWH,
&rect.g_x, &rect.g_y,
&rect.g_w, &rect.g_h);
graf_mouse(M_OFF, 0L);
while (rect.g_w && rect.g_h) {
if (rc_intersect(&dirty, &rect)) {
if (rc_intersect(&bwin->canvas, &rect)) {
st->pxy[0] = gr->PlotX + (rect.g_x - bwin->canvas.g_x);
st->pxy[1] = gr->PlotY + (rect.g_y - bwin->canvas.g_y);
st->pxy[2] = st->pxy[0] + rect.g_w - 1;
st->pxy[3] = st->pxy[1] + rect.g_h - 1;
grect_to_array(&rect, &st->pxy[4]);
vs_clip(VWork.VdiHandle, 1, &st->pxy[4]);
vro_cpyfm(VWork.VdiHandle, 3, st->pxy,
&gr->image, &gr->screen);
vs_clip(VWork.VdiHandle, 0, &st->pxy[4]);
}
}
wind_get(bwin->handle, WF_NEXTXYWH,
&rect.g_x, &rect.g_y,
&rect.g_w, &rect.g_h);
}
graf_mouse(M_ON, 0L);
}
int
update_scroll(int handle)
{
int hslide_pos, hslide_siz, vslide_pos, vslide_siz;
WINDOW *win = WinFindH(handle);
switch (win->type) {
case BIT:
{
GRAPHIC *gr = win->obj;
if (gr->Width != win->canvas.g_w) {
hslide_pos = 1000 * gr->PlotX/(gr->Width - win->canvas.g_w);
}
else {
hslide_pos = 0;
}
if (gr->Height != win->canvas.g_h) {
vslide_pos = 1000 * gr->PlotY
/ (gr->Height - win->canvas.g_h);
}
else {
vslide_pos = 0;
}
hslide_siz = 1000 * win->canvas.g_w/gr->Width;
vslide_siz = 1000 * win->canvas.g_h/gr->Height;
}
break;
case TEXT:
{
WINTEXT *text = win->obj;
int offset = text->fdl - text->fl;
if (offset < 0) offset += text->bh;
if (text->cols != text->bw + 2) {
hslide_pos = 1000 * text->fdc/(text->bw + 2 - text->cols);
}
else {
hslide_pos = 0;
}
if (text->lins < text->bh) {
vslide_pos = 1000 * offset/(text->bh - text->lins);
}
else {
vslide_pos = 0;
}
hslide_siz = 1000 * text->cols/(text->bw + 2);
vslide_siz = 1000 * text->lins/text->bh;
}
break;
}
wind_set(handle, WF_HSLIDE, hslide_pos);
wind_set(handle, WF_VSLIDE, vslide_pos);
wind_set(handle, WF_HSLSIZE, hslide_siz);
wind_set(handle, WF_VSLSIZE, vslide_siz);
return 0;
}
int
TextWinInit(WINDOW *twin, WINTEXT *text, int gadgets, char *title)
{
twin->handle = -1;
twin->type = TEXT;
twin->obj = (void *)text;
twin->gadgets = gadgets;
twin->title = title;
twin->opened = 0;
twin->iconified = 0;
twin->canvas.g_x = 0; twin->canvas.g_y = 0;
twin->canvas.g_w = 0; twin->canvas.g_h = 0;
twin->frame.g_x = 0; twin->frame.g_y = 0;
twin->frame.g_w = 0; twin->frame.g_h = 0;
twin->oframe.g_x = 0; twin->oframe.g_y = 0;
twin->oframe.g_w = 0; twin->oframe.g_h = 0;
twin->mframe.g_x = 0; twin->mframe.g_y = 0;
twin->mframe.g_w = 0; twin->mframe.g_h = 0;
twin->redraw = txtw_redraw;
twin->move = txtw_move;
twin->size = txtw_size;
twin->arrow = txtw_arrow;
twin->hslide = txtw_hslide;
twin->vslide = txtw_vslide;
text->bw = COLUMNS;
text->bh = LINES;
text->top = text->edge = 0;
text->xoff = text->yoff = 0;
text->cx = text->cy = 0;
text->cstate = 0;
text->wc = text->hc = 0;
text->lins = text->cols = 0;
text->ln = text->cn = 0;
text->fl = 0;
text->ll = LINES-1;
text->fdl = 0;
text->ldl = LINES-1;
text->fdc = text->ldc = 0;
text->scrolled = 0;
}
int
BitWinInit(WINDOW *bwin, GRAPHIC *gr, int gadgets, char *title)
{
bwin->handle = -1;
bwin->type = BIT;
bwin->obj = (void *)gr;
bwin->gadgets = gadgets;
bwin->title = title;
bwin->opened = 0;
bwin->iconified = 0;
bwin->redraw = bitw_redraw;
bwin->move = bitw_move;
bwin->size = bitw_size;
bwin->arrow = bitw_arrow;
bwin->hslide = bitw_hslide;
bwin->vslide = bitw_vslide;
bwin->frame.g_x = imagwin.frame.g_x + 2 * VWork.Wchar;
bwin->frame.g_y = imagwin.frame.g_x + VWork.Hchar;
bwin->frame.g_w = imagwin.frame.g_w;
bwin->frame.g_h = imagwin.frame.g_h;
memcpy(gr, imagwin.obj, sizeof(GRAPHIC));
}
int
ObjWinInit(WINDOW *owin, OBJECT *object, int gadgets, char *title)
{
owin->handle = -1;
owin->type = OBJ;
owin->obj = (void *)object;
owin->gadgets = gadgets;
owin->title = title;
owin->opened = 0;
owin->iconified = 0;
owin->canvas.g_x = 0; owin->canvas.g_y = 0;
owin->canvas.g_w = 0; owin->canvas.g_h = 0;
owin->frame.g_x = 0; owin->frame.g_y = 0;
owin->frame.g_w = 0; owin->frame.g_h = 0;
owin->oframe.g_x = 0; owin->oframe.g_y = 0;
owin->oframe.g_w = 0; owin->oframe.g_h = 0;
owin->mframe.g_x = 0; owin->mframe.g_y = 0;
owin->mframe.g_w = 0; owin->mframe.g_h = 0;
owin->redraw = objw_redraw;
owin->move = objw_move;
owin->size = NULL;
owin->arrow = NULL;
owin->hslide = NULL;
owin->vslide = NULL;
}
/* WinAlloc allocates memory for a new window. */
WINDOW *
WinAlloc(void)
{
return (WINDOW *) gs_malloc((uint)sizeof(WINDOW), 1, "window");
}
/* Free the memory allocated for a window. */
int
WinFree(WINDOW *win)
{
gs_free((char *)win, 1, sizeof(WINDOW), "window");
}
/* WinTextAlloc allocates memory for a window text structure. */
WINTEXT *
WinTextAlloc(int Lines)
{
WINTEXT *text;
/* Allocate the WINTEXT structure. */
if ((text = (WINTEXT *) gs_malloc((uint)sizeof(WINTEXT), 1, "wintext")) == NULL) {
return text;
}
/* Allocate the character buffer. */
if ((text->buff = (char (*)[COLUMNS+1])gs_malloc((uint)(COLUMNS+1), Lines, "charbuff")) == NULL) {
gs_free((char *)text, 1, sizeof(WINTEXT), "wintext");
return (WINTEXT *)NULL;
}
text->bsize = Lines;
return text;
}
char
(*TextBuffRealloc(WINTEXT *text, int NewSize))[COLUMNS+1]
{
char (*temp)[COLUMNS+1];
/* Allocate another character buffer of the new size. */
if ((temp = (char (*)[COLUMNS+1])gs_malloc((uint)(COLUMNS+1), NewSize, "charbuff")) == NULL) {
return temp;
}
if (text->buff != 0) {
/* Copy the old buffer to the new one. */
memcpy(temp, text->buff, (MIN(text->bsize, NewSize))*(COLUMNS+1));
/* Free the old character buffer. */
gs_free((char *)text->buff, text->bsize, (COLUMNS+1), "charbuff");
}
text->bsize = NewSize;
text->buff = temp;
return temp;
}
/* Free the memory allocated for a window text structure. */
int
WinTextFree(WINTEXT *text)
{
gs_free((char *)text->buff, text->bsize, (COLUMNS+1), "charbuff");
gs_free((char *)text, 1, sizeof(WINTEXT), "wintext");
}
/* GraphicAlloc allocates memory for a graphic structure. */
GRAPHIC *
GraphicAlloc(void)
{
return (GRAPHIC *) gs_malloc((uint)sizeof(GRAPHIC), 1, "graphic");
}
/* Free the memory allocated for a graphic structure. */
int
GraphicFree(GRAPHIC *gr)
{
gs_free((char *)gr, 1, sizeof(GRAPHIC), "graphic");
}
/* Free the memory allocated for a bitmap buffer. */
int
BitBufferFree(GRAPHIC *gr)
{
char *buff = (char *)gr->image.fd_addr;
ulong buff_size = gr->image.fd_w * gr->image.fd_h;
gs_free((char *)buff, buff_size, 1, "bitbuffer");
}
/* ListAlloc allocates memory for a new element of the window list. */
WINLIST *
WinListAlloc(void)
{
return (WINLIST *) gs_malloc((uint)sizeof(WINLIST), 1, "winlist");
}
/* Free the memory for the winlist structure */
int
WinListFree(WINLIST *wl)
{
gs_free((char *)wl, 1, sizeof(WINLIST), "winlist");
}
/* WinListAdd adds a new window to the window list. */
WINLIST *
WinListAdd(WINLIST *wlist, WINDOW *win)
{
WINLIST *wl = WinListAlloc();
if (win->opened || win->iconified) return wlist;
if (wlist == NULL) { /* Begin a new list. */
wl->Prev = wl;
wl->Next = wl;
}
else { /* Add a new list element. */
wl->Prev = wlist->Prev;
wl->Next = wlist;
wlist->Prev->Next = wl;
wlist->Prev = wl;
}
wl->Win = win; /* Put the window in the list. */
return wl;
}
/* Delete a window from the window list and free its associated memory. */
WINLIST *
WinListDelete(WINLIST *wlist, WINDOW *win)
{
WINLIST *ret, *wl = wlist;
/*
* Return the new head of the window list. If the head was not
* deleted, it remains the head. If the head is deleted, make
* the next list element the head. If deleting the head leaves
* the list empty, then return NULL.
*/
ret = (win == wlist->Win) ?
((wlist->Next == wlist) ? NULL : wlist->Next) : wlist;
/* Delete the specified list element. */
do {
if (win == wl->Win) {
wl->Prev->Next = wl->Next;
wl->Next->Prev = wl->Prev;
break;
}
wl = wl->Next;
}
while (wl != wlist);
/* Free the memory for the window structure. */
if ((win->type == TEXT) && (win != &conswin)) {
WinTextFree(win->obj);
WinFree(win);
}
else if ((win->type == BIT) && (win != &imagwin)) {
GRAPHIC *gr = win->obj;
BitBufferFree(gr);
GraphicFree(gr);
WinFree(win);
}
/* Free the memory used for the window list. */
WinListFree(wl);
return ret;
}
/* Open all the windows in the window list, leaving the list intact. */
int
WinListOpen(WINLIST *wlist)
{
WINLIST *wl = wlist;
do {
if (wl->Win->iconified) {
wind_open(wl->Win->handle,
wl->Win->frame.g_x, wl->Win->frame.g_y,
wl->Win->frame.g_w, wl->Win->frame.g_h);
wl->Win->opened = 1;
wl->Win->iconified = 0;
if (wl->Win->type == OBJ) {
OBJECT *obj = wl->Win->obj;
obj[0].ob_flags ^= HIDETREE;
}
}
wl = wl->Next;
}
while (wl != wlist);
}
/* Close all the windows in the window list, leaving the list intact. */
int
WinListClose(WINLIST *wlist)
{
WINLIST *wl = wlist;
do {
if (wl->Win->opened) {
wind_get(wl->Win->handle, WF_CURRXYWH,
&wl->Win->oframe.g_x, &wl->Win->oframe.g_y,
&wl->Win->oframe.g_w, &wl->Win->oframe.g_h);
wind_get(wl->Win->handle, WF_CURRXYWH,
&wl->Win->frame.g_x, &wl->Win->frame.g_y,
&wl->Win->frame.g_w, &wl->Win->frame.g_h);
wind_close(wl->Win->handle);
wl->Win->opened = 0;
wl->Win->iconified = 1;
if (wl->Win->type == OBJ) {
OBJECT *obj = wl->Win->obj;
obj[0].ob_flags ^= HIDETREE;
}
}
wl = wl->Next;
}
while (wl != wlist);
}
/* Redraw all windows in the list. */
int
WinListRedraw(WINLIST *wlist, PSTATE *st)
{
WINLIST *wl = wlist;
do {
if (wl->Win->opened) {
st->Event->Message[3] = wl->Win->handle;
HandleRedraw(FULL_WIN, st);
}
wl = wl->Next;
}
while (wl != wlist);
}
/*
* Pathfind(path, file, sep) searches for 'file' in the path given
* by the envionment variable named in 'env'. Sep specifies the
* path separator. It returns a pointer to the filename if it is
* found, and a NULL if not.
*/
char *
PathFind(char *env, char *file, char *sep)
{
FILE *fp;
char path[2*MAXLEN];
static char name[MAXLEN];
char *ptr;
char *presub();
if ((fp = fopen(file, "r")) == NULL) {
if ((ptr = getenv(env)) != NULL) {
strcpy(path, ptr);
}
else {
return NULL;
}
if ((ptr = presub(path, sep)) == NULL) {
return NULL;
}
do {
strcpy(name, ptr);
if (name[strlen(name)-1] != '\\' ||
name[strlen(name)-1] != '/') strcat(name, "\\");
strcat(name, file);
if ((fp = fopen(name, "r")) != NULL) {
fclose(fp);
return name;
}
} while ((ptr = presub(NULL, sep)) != NULL);
}
else {
fclose(fp);
return file;
}
}
/* Presub(s, subs) searches the string s for the substring subs. Presub
* returns a pointer to the NULL terminated substring which immediately
* preceeds subs. If presub is called again with a NULL pointer for s,
* it returns a pointer to the substring between the previous subs and
* the current subs. If subs is a null character, presub returns a pointer
* to the portion of s between the previous subs and the end of s.
*/
char *presub(s, subs)
char *s, *subs;
{
int sublen;
char *mptr;
static int count;
static char match[MAXLEN], *ptr;
if (s != NULL) {
ptr = s;
count = 0;
}
mptr = match + count;
if ((sublen = strlen(subs)) == 0) {
strcpy(mptr, ptr);
return (mptr);
}
while (*ptr != '\0') {
if (strncmp(ptr, subs, sublen) == 0) {
match[count] = '\0';
ptr += sublen;
++count;
return (mptr);
}
match[count] = *ptr;
++ptr;
++count;
}
if ((match + count) > mptr) {
match[count] = *ptr;
++count;
return (mptr);
}
return (NULL);
}
/* Ensure that the size of a window is within the limits of
* the hardware.
*/
int EnforceLimits(GRECT *rect, VWRK *vw)
{
if ((rect->g_x < vw->full.g_x) || (rect->g_x >= vw->full.g_w)) {
rect->g_x = vw->full.g_x;
}
if ((rect->g_y < vw->full.g_y) || (rect->g_y >= vw->full.g_h)) {
rect->g_y = vw->full.g_y;
}
if (rect->g_w < 0) {
rect->g_w = vw->full.g_w - rect->g_x;
}
if (rect->g_h < 0) {
rect->g_h = vw->full.g_h - rect->g_y + vw->full.g_y;
}
}
/* Routine itoa(num, s) converts an integer, num, to an ascii string
* representation of the integer, pointed to by s. The integer 100 is
* converted to the string "100", etc.
*/
char *itoa(int number, char *s)
{
/* Local variables:
* i: loop counter,
* j: number of loops needed to transpose the string in s,
* body: integer part of num/10,
* remain: remainder of num/10,
* sign: sign of the integer,
* count: number of times num is divisible by 10,
* temp: temporary character storage.
*/
int i, j, num, body, remain, sign, count;
char temp;
count = 0;
num = number;
sign = 1;
if (num == 0) {
s[count] = '0';
++count;
} else {
if (num < 0) {
sign = -1;
num = -num;
}
while (num > 0) { /* Divide by 10, convert */
body = (num/10); /* remainder to ascii */
remain = num - body*10;
s[count] = remain + '0';
num = body;
++count;
}
if (sign < 0) {
s[count] = '-';
++count;
}
/* Ascii representation is transposed in s, so put it in
* the right order. */
j = count/2;
for (i = 0; i < j; ++i) {
temp = s[i];
s[i] = s[count-(i+1)];
s[count-(i+1)] = temp;
}
}
s[count] = '\0';
return(s);
}
/* Round to nearest integer. */
int
nint(double Num)
{
int Floor = floor(Num);
int Ceil = ceil(Num);
return (fabs(Num - Floor) > fabs(Num - Ceil)) ? Ceil : Floor;
}
int align(int x)
{
return ((x & 0xfffffff0) + ((x & 0xf) ? 0x10 : 0));
/* return ((x & 0xfffffff8) + ((x & 0x07) ? 0x08 : 0)); */
}
/*
* The remainder of this file contains printer output routines, most of
* which were contributed by Chris Strunk (some of them were written by me).
* I made some modifications to the following code (with permission), and
* may have introduced errors not in the original code.
* Tim Gallivan, 3/92.
*/
/*
* This file is Copyright (C) 1990 Christoph Strunk.
*
* You are not allowed to copy or modify it.
*/
#define ATARI_TOS (1)
#define MAKE_VOID (void *)
void con_flush();
int OutputIsAscii = 0, RTX_Found = 0;
long *old_ssp = NULL;
FILE *OutFile = NULL;
#if PC_DOS || ATARI_TOS
# define DIRECT 1 /* 1 = Direct Centronics port programming */
#endif
#if ATARI_TOS || ( PC_DOS && DIRECT )
static short prn_out ( int );
#endif
#if ATARI_TOS && LATTICE
#include <dos.h>
#endif
#ifdef __GNUC__
#include <osbind.h>
#endif
#if PC_DOS && DIRECT
#include <bios.h>
#endif
/* output one character */
static int fatal_output_error = 0;
void
lputc(c)
int c;
{
static short rc;
static unsigned char global_count = 0; /* other processes every 256 chars */
void l_stop(), fatal();
if ( fatal_output_error ) return;
global_count += 1;
c &= 255; /* New in 2.9.44: avoid signed char problems */
#if ATARI_TOS || PC_DOS
if ( ( c == '\n' ) && OutputIsAscii ) {
lputc ( '\r' ); /* recursion */
}
#endif
if ( OutFile ) {
rc = ( fputc ( c, OutFile ) == EOF );
} else {
#if ATARI_TOS || ( PC_DOS && DIRECT )
rc = prn_out ( c );
#else
rc = -1;
#endif
}
if ( rc ) {
if ( OutFile ) {
perror ( "\nlputc" );
fprintf ( stderr, "\nOutput error -- %s ?\n",
"Disk full or printer not ready" );
fclose ( OutFile );
OutFile = NULL;
} else {
fprintf ( stderr, "\nOutput error -- Printer not ready ?\n" );
}
l_stop();
fatal_output_error = 1;
fatal ( "Output error" );
}
#if ATARI_TOS
if ( RTX_Found && ! global_count ) call_yield(); /* allow other processes */
#endif
}
/* output a string */
void
lputs ( s )
char *s;
{
while ( *s ) lputc ( *s++ );
}
void
lflush()
{
if ( OutFile ) fflush ( OutFile );
}
/* start/stop lputc device */
void
l_start()
{
void l_stop(), fatal();
#if ATARI_TOS && DIRECT
volatile char *gpip = (char *) 0xFFFFFA01L;
int cnt;
if ( OutFile == NULL && old_ssp == NULL ) {
old_ssp = (void *) call_super ( NULL );
cnt = 0;
/* for ( cnt=0; ( *gpip & 1 ) && ( ++cnt <= 10 ); ) {
printf("cnt = %d\n", cnt); */
Ongibit(0x20); /* set strobe bit */
/* } */
if ( cnt > 10 ) {
l_stop();
dputs ( "\n" );
fatal_output_error = 1;
fatal ( "Printer not ready" );
}
}
#endif
#if ATARI_TOS && ! DIRECT
int cnt;
if ( OutFile == NULL && old_ssp == NULL ) {
old_ssp = (void *) call_super ( NULL );
for ( cnt=0; ( ! prt_ready(0) ) && ( ++cnt <= 10 ); ) {
Ongibit(0x20); /* set strobe bit */
}
if ( cnt > 10 ) {
l_stop();
dputs ( "\n" );
fatal_output_error = 1;
fatal ( "Printer not ready" );
}
}
#endif
#if PC_DOS && DIRECT
if ( OutFile == NULL && ( biosprint ( 2, 0, BiosChannel ) & 0x29 ) ) {
l_stop();
dputs ( "\n" );
fatal_output_error = 1;
fatal ( "Printer not ready" );
}
#endif
}
void l_stop()
{
lflush();
#if ATARI_TOS
if ( old_ssp != NULL ) {
MAKE_VOID call_super ( old_ssp );
old_ssp = NULL;
}
#endif
}
#if ATARI_TOS && DIRECT
extern void int_off __PROTO( ( void ) );
/* int_off: ori.w #$0700,sr
* ret
*/
extern void int_on __PROTO( ( void ) );
/* int_on: andi.w #$F8FF,sr
* ret
*/
static short prn_out ( c )
int c;
{
volatile unsigned long *hz_200;
register unsigned long end_time;
volatile char *gpip = (char *) 0xFFFFFA01L;
register char g;
#if OLD
unsigned char loop_count = 0;
#endif
if ( old_ssp == NULL ) l_start();
hz_200 = (unsigned long *) 0x04BAL;
#if OLD
end_time = *hz_200 + 200; /* check once per second */
#else
end_time = *hz_200 + 2; /* check 100 times per second */
#endif
while ( *gpip & 1 ) { /* wait */
#if OLD
/* Printer 1 sec. or more not ready ? */
if ( ( end_time < *hz_200 ) ||
( ( ( ++loop_count & 7 ) == 0 ) && ( BatchMode || RTX_Found ) ) ) {
con_flush(); /* allow Control_C, other Processes etc. */
end_time = *hz_200 + 2; /* check 100 times per second */
}
#else
if ( end_time <= *hz_200 ) {
con_flush(); /* allow Control_C, other Processes etc. */
end_time = *hz_200 + 1; /* check 200 times per second */
}
#endif
}
int_off(); /* disable interrupts */
gpip = (char *) 0xFFFF8800L; /* load sound chip adress now */
/* This next section of code was added by Tim Gallivan on 7/11/94
* to fix a problem of this routine not working on some hardware.
*/
*gpip = 7; /* select enable register */
g = *gpip; /* get old value */
g |= 0x80; /* set port B output bit */
gpip[2] = g;
/* End fix. */
*gpip = 15; /* select port B */
gpip[2] = (char) c; /* write out char */
*gpip = 14; /* select port A */
g = *gpip; /* get old value */
#if OLD
g &= 0xDF; /* clear strobe bit */
#else
g &= ~0x20; /* clear strobe bit */
#endif
gpip[2] = g;
g |= 0x20; /* set strobe bit */
g |= 0x20; /* short delay */
gpip[2] = g;
int_on(); /* enable interrupts */
return 0;
}
#endif
#if ATARI_TOS && ! DIRECT
static short prn_out ( c )
int c;
{
volatile unsigned long *hz_200 = (unsigned long *) 0x04BAL;
register unsigned long end_time;
if ( old_ssp == NULL ) l_start();
end_time = *hz_200 + 2; /* check 200 times per second */
while ( ! prt_ready(0) ) { /* wait */
if ( end_time <= *hz_200 ) {
con_flush(); /* allow Control_C, other Processes etc. */
end_time = *hz_200 + 1; /* check 200 times per second */
}
}
prt_out ( 0, c );
return 0;
}
#endif
#if PC_DOS && DIRECT
static short prn_out ( c )
int c;
{
while ( biosprint ( 0, c, BiosChannel ) & 0x29 ) {
/* wait until Ok or Control-C pressed */
con_flush();
}
return 0;
}
#endif
void
con_flush()
{
int chin;
void fatal();
chin = Crawio(0xFF);
if ((chin & 0xFF) == 3) fatal("Keyboard Interrupt");
}
void
fatal(char *message)
{
fprintf(stderr, "%s\n", message);
l_stop();
exit(-1);
}
/* Restore the usual desktop background. */
#undef puts
int RestoreBG(VWRK *vw)
{
puts("\033f");
v_hide_c(vw->VdiHandle);
form_dial(FMD_FINISH, 0, 0, 8, 16, 0, 0, vw->XRes, vw->YRes);
v_show_c(vw->VdiHandle, 0);
}
/*
#-----------------------------------------------------------------------------#
#: Simple support routines for LATTICE C 5.04.01 and other C compilers
#
#: Lattice C Assembler
#
#: The parameter comes on the stack for functions starting with '_'.
#
#: void *call_super ( void * ); supervisor mode on/off
#
#: Original code by Chris Strunk. Modified for use with gcc in
#: Ghostscript by Tim Gallivan, 3/92.
#-----------------------------------------------------------------------------#
*/
asm("\
.text 0
.globl _int_off
.globl _int_on
.globl _call_super
.globl _call_yield
.globl _call_nice
.globl _user_trace
.globl _prt_ready
.globl _prt_out
_get_la:
moveml d2/a2,sp@-
.byte 0xA0,0x00 | Adresse Line-A-Var nach A0 & D0
moveml sp@+,d2/a2
rts
_int_off:
oriw #0x0700,sr
rts
_int_on:
andiw #0xF8FF,sr
rts
_call_super:
movel a7@(4),a0
moveml d2/a2-a3,sp@-
movel a0,sp@-
movew #0x20,sp@-
movel a7,a3 | save current stack pointer
trap #1
movel a3,a7 | make bad stack pointer good again !!!!!!!
addql #6,sp
movel d0,a0 | return value in both: d0 and a0
moveml sp@+,d2/a2-a3
rts
_call_yield:
moveml d2/a2,sp@-
movew #0x00ff,sp@- | MiNT Syield() -- TOS illegal (rc -32)
trap #1
addql #2,sp
moveml sp@+,d2/a2
rts
_call_nice:
movel a7@(4),d0
moveml d2/a2,sp@-
movew d0,sp@-
movew #0x10A,sp@-
trap #1
addql #4,sp
moveml sp@+,d2/a2
rts
_user_trace:
moveml d1-d7/a0-a6,sp@-
moveql #0,d0
movel 0x3F0,a1 | TEMPLMON user trace vector
cmpal #0,a1 | not installed ?
beqs end_trace
jsr a1@ | execute it !
extl d0
end_trace:
moveml sp@+,d1-d7/a0-a6
rts
_prt_ready:
moveml d3/a3/a5,a7@-
subl a5,a5
movew d0,a7@-
movel 0x506,a0
jsr a0@
addql #2,a7
moveml a7@+,d3/a3/a5
rts
_prt_out:
moveml d3/a3/a5,a7@-
subl a5,a5
movew d1,a7@-
movew d0,a7@-
movel 0x50A,a0
jsr a0@
addql #4,a7
moveml a7@+,d3/a3/a5
rts
");