/* 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; iPSHelp); /* 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 #endif #ifdef __GNUC__ #include #endif #if PC_DOS && DIRECT #include #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 ");