home *** CD-ROM | disk | FTP | other *** search
/ Crawly Crypt Collection 2 / crawlyvol2.bin / apps / dtp / ghost / gs301src / atari / gp_atar3.bak < prev    next >
Text File  |  1994-09-17  |  62KB  |  2,762 lines

  1. /* Copyright (C) 1989, 1992, 1993 Aladdin Enterprises.  All rights reserved.
  2.  
  3. This file is part of Ghostscript.
  4.  
  5. Ghostscript is distributed in the hope that it will be useful, but
  6. WITHOUT ANY WARRANTY.  No author or distributor accepts responsibility
  7. to anyone for the consequences of using it or for whether it serves any
  8. particular purpose or works at all, unless he says so in writing.  Refer
  9. to the Ghostscript General Public License for full details.
  10.  
  11. Everyone is granted permission to copy, modify and redistribute
  12. Ghostscript, but only under the conditions described in the Ghostscript
  13. General Public License.  A copy of this license is supposed to have been
  14. given to you along with Ghostscript so you can know your rights and
  15. responsibilities.  It should be in a file named COPYING.  Among other
  16. things, the copyright notice and this notice must be preserved on all
  17. copies.  */
  18.  
  19. /* gp_atar3.c */
  20.  
  21. /*
  22.  * This file contains general utility routines for the Atari platform.
  23.  */
  24.  
  25. #include "gp_atar3.h"
  26.  
  27. extern WINLIST *WList;                    /* gp_atar2.c */
  28. extern WINDOW conswin;                    /* gp_atar2.c */
  29. extern WINDOW imagwin, aboutwin, reswin;        /* gp_atar2.c */
  30. extern WINDOW devwin, sizwin, iconwin, outwin;        /* gp_atar2.c */
  31.  
  32. extern OBJECT aboutobj[], resobj[], devobj[];
  33. extern OBJECT sizobj[], iconobj[], outobj[], savemsg[];
  34.  
  35. extern GRAPHIC Graphic;
  36.  
  37. extern char saveline[MAXLEN];                /* gp_atar1.h */
  38. extern char devices[DEVICES][DNAMELEN];            /* gp_atar1.h */
  39. extern char sizes[DEVICES][DNAMELEN];            /* gp_atar1.h */
  40.  
  41. extern VWRK VWork;                    /* gp_atar1.h */
  42. extern PSTATE State;                    /* gp_atar1.h */
  43.  
  44. WINDOW  *WinFindH(), *WinAlloc();
  45. WINLIST *WinListAdd(), *WinListDelete();
  46. WINTEXT *WinTextAlloc();
  47. char    (*TextBuffRealloc())[COLUMNS+1];
  48. GRAPHIC *GraphicAlloc();
  49.  
  50. void *ObjFindH();
  51.  
  52. void
  53. GetPalette(int *Palette, VWRK *vw)
  54. {
  55.     int ColorIndex;
  56.     int ColorEntry[3];
  57.     unsigned int DefinedColors = vw->PaletteSize/3;
  58.  
  59.     for (ColorIndex = 0; ColorIndex < DefinedColors; ColorIndex++) {
  60.  
  61.     vq_color(vw->VdiHandle, ColorIndex, DEFINED_INTENSITY, ColorEntry);
  62.  
  63.     Palette[3*ColorIndex]   = ColorEntry[0];
  64.     Palette[3*ColorIndex+1] = ColorEntry[1];
  65.     Palette[3*ColorIndex+2] = ColorEntry[2];
  66.       
  67.     }
  68. }
  69.  
  70. void
  71. SetPalette(int *Palette, VWRK *vw)
  72.   
  73.     int ColorIndex;
  74.     int ColorEntry[3];
  75.     unsigned int DefinedColors = vw->PaletteSize/3;
  76.  
  77.     for (ColorIndex = 0; ColorIndex < DefinedColors; ColorIndex++) {
  78.  
  79.     ColorEntry[0] = Palette[3*ColorIndex];
  80.     ColorEntry[1] = Palette[3*ColorIndex+1];
  81.     ColorEntry[2] = Palette[3*ColorIndex+2];
  82.   
  83.     vs_color(vw->VdiHandle, ColorIndex, ColorEntry);
  84.     }
  85. }
  86.  
  87. /* Load the configuration file. */
  88.  
  89. int
  90. LoadConfig(VWRK *vw, PSTATE *st)
  91. {
  92.  
  93.     FILE *config;
  94.     char *PathFind(), *sptr;
  95.     char line[MAXLEN];
  96.  
  97.     static short DevCount=1, SizCount=0;
  98.     float tempx, tempy, tempw, temph;
  99.     GRECT itemp;
  100.  
  101.     /* Look for the configuration file in the current and HOME directories. */
  102.  
  103.     if ((sptr = PathFind("HOME", CONFIGFILE, ",")) != NULL) {
  104.     strcpy(line, sptr);
  105.     }
  106.     else {    
  107.     return -1;
  108.     }
  109.  
  110.     if ((config = fopen(line, "r")) == NULL) {
  111.     sprintf(line, "[1][Could not open %s!][OK]", CONFIGFILE);
  112.     form_alert(1, line);
  113.     return -1;
  114.     }
  115.  
  116.     /* Process the information in the config file. */
  117.  
  118.     while (fgets(line, MAXLEN-1, config) != NULL) {
  119.  
  120.     line[strlen(line)-1] = '\0';
  121.  
  122.     if (!strncmp(line, "consolewin ", 11)) {
  123.  
  124.         sscanf(line+11, "%f %f %f %f",
  125.         &tempx, &tempy, &tempw, &temph);
  126.  
  127.         if (conswin.opened) {
  128.  
  129.         itemp.g_x = nint(tempx * vw->full.g_w);
  130.         itemp.g_y = nint(tempy * vw->full.g_h);
  131.         itemp.g_w = nint(tempw * vw->full.g_w);
  132.         itemp.g_h = nint(temph * vw->full.g_h);
  133.  
  134.         EnforceLimits(&itemp, vw);
  135.  
  136.         st->Event->SendMsg[0] = WM_SIZED;
  137.         st->Event->SendMsg[3] = conswin.handle;
  138.         st->Event->SendMsg[4] = itemp.g_x;
  139.         st->Event->SendMsg[5] = itemp.g_y;
  140.         st->Event->SendMsg[6] = itemp.g_w;
  141.         st->Event->SendMsg[7] = itemp.g_h;
  142.         appl_write(st->ApId, 16, st->Event->SendMsg);
  143.  
  144.         }
  145.         else {
  146.  
  147.         conswin.frame.g_x = nint(tempx * vw->full.g_w);
  148.         conswin.frame.g_y = nint(tempy * vw->full.g_h);
  149.         conswin.frame.g_w = nint(tempw * vw->full.g_w);
  150.         conswin.frame.g_h = nint(temph * vw->full.g_h);
  151.  
  152.         EnforceLimits(&conswin.frame, vw);
  153.  
  154.         }
  155.  
  156.     }
  157.  
  158.     if (!strncmp(line, "imagewin ", 9)) {
  159.  
  160.         sscanf(line+9, "%f %f %f %f",
  161.         &tempx, &tempy, &tempw, &temph);
  162.  
  163.         if (imagwin.opened) {
  164.  
  165.         itemp.g_x = nint(tempx * vw->full.g_w);
  166.         itemp.g_y = nint(tempy * vw->full.g_h);
  167.         itemp.g_w = nint(tempw * vw->full.g_w);
  168.         itemp.g_h = nint(temph * vw->full.g_h);
  169.  
  170.         EnforceLimits(&itemp, vw);
  171.  
  172.         st->Event->SendMsg[0] = WM_SIZED;
  173.         st->Event->SendMsg[3] = imagwin.handle;
  174.         st->Event->SendMsg[4] = itemp.g_x;
  175.         st->Event->SendMsg[5] = itemp.g_y;
  176.         st->Event->SendMsg[6] = itemp.g_w;
  177.         st->Event->SendMsg[7] = itemp.g_h;
  178.         appl_write(st->ApId, 16, st->Event->SendMsg);
  179.  
  180.         }
  181.         else {
  182.  
  183.         imagwin.frame.g_x = nint(tempx * vw->full.g_w);
  184.         imagwin.frame.g_y = nint(tempy * vw->full.g_h);
  185.         imagwin.frame.g_w = nint(tempw * vw->full.g_w);
  186.         imagwin.frame.g_h = nint(temph * vw->full.g_h);
  187.  
  188.         EnforceLimits(&imagwin.frame, vw);
  189.  
  190.         }
  191.  
  192.     }
  193.  
  194.     if (!strncmp(line, "aboutwin ", 9)) {
  195.  
  196.         sscanf(line+9, "%f %f", &tempx, &tempy);
  197.  
  198.         itemp.g_x = nint(tempx * vw->full.g_w);
  199.         itemp.g_y = nint(tempy * vw->full.g_h);
  200.  
  201.         EnforceLimits(&itemp, vw);
  202.  
  203.         if (aboutwin.opened) {
  204.  
  205.         st->Event->SendMsg[0] = WM_MOVED;
  206.         st->Event->SendMsg[3] = aboutwin.handle;
  207.         st->Event->SendMsg[4] = itemp.g_x;
  208.         st->Event->SendMsg[5] = itemp.g_y;
  209.         st->Event->SendMsg[6] = aboutwin.frame.g_w;
  210.         st->Event->SendMsg[7] = aboutwin.frame.g_h;
  211.         appl_write(st->ApId, 16, st->Event->SendMsg);
  212.  
  213.         }
  214.         else {
  215.  
  216.         int ChangeX = itemp.g_x - aboutwin.frame.g_x;
  217.         int ChangeY = itemp.g_y - aboutwin.frame.g_y;
  218.  
  219.         aboutwin.frame.g_x = itemp.g_x;
  220.         aboutwin.frame.g_y = itemp.g_y;
  221.  
  222.         aboutwin.canvas.g_x += ChangeX;
  223.         aboutwin.canvas.g_y += ChangeY;
  224.  
  225.         aboutobj[0].ob_x += ChangeX;
  226.         aboutobj[0].ob_y += ChangeY;
  227.  
  228.         }
  229.     }
  230.  
  231.     if (!strncmp(line, "reswin ", 7)) {
  232.  
  233.         sscanf(line+7, "%f %f", &tempx, &tempy);
  234.  
  235.         itemp.g_x = nint(tempx * vw->full.g_w);
  236.         itemp.g_y = nint(tempy * vw->full.g_h);
  237.  
  238.         EnforceLimits(&itemp, vw);
  239.  
  240.         if (reswin.opened) {
  241.  
  242.         st->Event->SendMsg[0] = WM_MOVED;
  243.         st->Event->SendMsg[3] = reswin.handle;
  244.         st->Event->SendMsg[4] = itemp.g_x;
  245.         st->Event->SendMsg[5] = itemp.g_y;
  246.         st->Event->SendMsg[6] = reswin.frame.g_w;
  247.         st->Event->SendMsg[7] = reswin.frame.g_h;
  248.         appl_write(st->ApId, 16, st->Event->SendMsg);
  249.  
  250.         }
  251.         else {
  252.  
  253.         int ChangeX = itemp.g_x - reswin.frame.g_x;
  254.         int ChangeY = itemp.g_y - reswin.frame.g_y;
  255.  
  256.         reswin.frame.g_x = itemp.g_x;
  257.         reswin.frame.g_y = itemp.g_y;
  258.  
  259.         reswin.canvas.g_x += ChangeX;
  260.         reswin.canvas.g_y += ChangeY;
  261.  
  262.         resobj[0].ob_x += ChangeX;
  263.         resobj[0].ob_y += ChangeY;
  264.  
  265.         }
  266.  
  267.     }
  268.  
  269.     if (!strncmp(line, "devwin ", 7)) {
  270.  
  271.         sscanf(line+7, "%f %f", &tempx, &tempy);
  272.  
  273.         itemp.g_x = nint(tempx * vw->full.g_w);
  274.         itemp.g_y = nint(tempy * vw->full.g_h);
  275.  
  276.         EnforceLimits(&itemp, vw);
  277.  
  278.         if (devwin.opened) {
  279.  
  280.         st->Event->SendMsg[0] = WM_MOVED;
  281.         st->Event->SendMsg[3] = devwin.handle;
  282.         st->Event->SendMsg[4] = itemp.g_x;
  283.         st->Event->SendMsg[5] = itemp.g_y;
  284.         st->Event->SendMsg[6] = devwin.frame.g_w;
  285.         st->Event->SendMsg[7] = devwin.frame.g_h;
  286.         appl_write(st->ApId, 16, st->Event->SendMsg);
  287.  
  288.         }
  289.         else {
  290.  
  291.         int ChangeX = itemp.g_x - devwin.frame.g_x;
  292.         int ChangeY = itemp.g_y - devwin.frame.g_y;
  293.  
  294.         devwin.frame.g_x = itemp.g_x;
  295.         devwin.frame.g_y = itemp.g_y;
  296.  
  297.         devwin.canvas.g_x += ChangeX;
  298.         devwin.canvas.g_y += ChangeY;
  299.  
  300.         devobj[0].ob_x += ChangeX;
  301.         devobj[0].ob_y += ChangeY;
  302.  
  303.         }
  304.  
  305.     }
  306.  
  307.     if (!strncmp(line, "sizwin ", 7)) {
  308.  
  309.         sscanf(line+7, "%f %f", &tempx, &tempy);
  310.  
  311.         itemp.g_x = nint(tempx * vw->full.g_w);
  312.         itemp.g_y = nint(tempy * vw->full.g_h);
  313.  
  314.         EnforceLimits(&itemp, vw);
  315.  
  316.         if (sizwin.opened) {
  317.  
  318.         st->Event->SendMsg[0] = WM_MOVED;
  319.         st->Event->SendMsg[3] = sizwin.handle;
  320.         st->Event->SendMsg[4] = itemp.g_x;
  321.         st->Event->SendMsg[5] = itemp.g_y;
  322.         st->Event->SendMsg[6] = sizwin.frame.g_w;
  323.         st->Event->SendMsg[7] = sizwin.frame.g_h;
  324.         appl_write(st->ApId, 16, st->Event->SendMsg);
  325.  
  326.         }
  327.         else {
  328.  
  329.         int ChangeX = itemp.g_x - sizwin.frame.g_x;
  330.         int ChangeY = itemp.g_y - sizwin.frame.g_y;
  331.  
  332.         sizwin.frame.g_x = itemp.g_x;
  333.         sizwin.frame.g_y = itemp.g_y;
  334.  
  335.         sizwin.canvas.g_x += ChangeX;
  336.         sizwin.canvas.g_y += ChangeY;
  337.  
  338.         sizobj[0].ob_x += ChangeX;
  339.         sizobj[0].ob_y += ChangeY;
  340.  
  341.         }
  342.  
  343.     }
  344.  
  345.     if (!strncmp(line, "iconwin ", 8)) {
  346.  
  347.         sscanf(line+8, "%f %f", &tempx, &tempy);
  348.  
  349.         itemp.g_x = nint(tempx * vw->full.g_w);
  350.         itemp.g_y = nint(tempy * vw->full.g_h);
  351.  
  352.         EnforceLimits(&itemp, vw);
  353.  
  354.         if (iconwin.opened) {
  355.  
  356.         st->Event->SendMsg[0] = WM_MOVED;
  357.         st->Event->SendMsg[3] = iconwin.handle;
  358.         st->Event->SendMsg[4] = itemp.g_x;
  359.         st->Event->SendMsg[5] = itemp.g_y;
  360.         st->Event->SendMsg[6] = iconwin.frame.g_w;
  361.         st->Event->SendMsg[7] = iconwin.frame.g_h;
  362.         appl_write(st->ApId, 16, st->Event->SendMsg);
  363.  
  364.         }
  365.         else {
  366.  
  367.         int ChangeX = itemp.g_x - iconwin.frame.g_x;
  368.         int ChangeY = itemp.g_y - iconwin.frame.g_y;
  369.  
  370.         iconwin.frame.g_x = itemp.g_x;
  371.         iconwin.frame.g_y = itemp.g_y;
  372.  
  373.         iconwin.canvas.g_x += ChangeX;
  374.         iconwin.canvas.g_y += ChangeY;
  375.  
  376.         iconobj[0].ob_x += ChangeX;
  377.         iconobj[0].ob_y += ChangeY;
  378.  
  379.         }
  380.  
  381.     }
  382.  
  383.     if (!strncmp(line, "device ", 7)) {
  384.         if (DevCount < DEVICES) {
  385.         sscanf(line+7, "%s", devices[DevCount]);
  386.         ++DevCount;
  387.         }
  388.     }
  389.  
  390.     if (!strncmp(line, "pagesize ", 9)) {
  391.         if (SizCount < SIZES) {
  392.         sscanf(line+9, "%s", sizes[SizCount]);
  393.         ++SizCount;
  394.         }
  395.     }
  396.  
  397.     }
  398.  
  399.     fclose(config);
  400. }
  401.  
  402. /* Save the configuration file. */
  403.  
  404. int
  405. SaveConfig(VWRK *vw)
  406. {
  407.  
  408.     FILE *config;
  409.  
  410.     char *PathFind(), *sptr;
  411.     char line[MAXLEN], configfile[MAXLEN];
  412.  
  413.     short i;
  414.     int fx, fy, fw, fh;
  415.  
  416.     float hnorm, vnorm;
  417.  
  418.     if ((vw->full.g_w == 0) || (vw->full.g_h == 0)) {
  419.     form_alert(1, "[1][Could not save!|Internal Error.][OK]");
  420.     return -1;
  421.     }
  422.  
  423.     /* Look for the configuration file in the current and HOME directories. */
  424.  
  425.     if ((sptr = PathFind("HOME", CONFIGFILE, ",")) != NULL) {
  426.     strcpy(configfile, sptr);
  427. /*    rename(configfile, "stgs.bak"); */
  428.     }
  429.  
  430.     if (!strlen(configfile)) {
  431.     if ((sptr = getenv("HOME")) != NULL) {
  432.         strcpy(configfile, sptr);
  433.         strcat(configfile, CONFIGFILE);
  434.     }
  435.     else {
  436.         strcat(configfile, CONFIGFILE);
  437.     }
  438.     }
  439.  
  440.     if ((config = fopen(configfile, "w")) == NULL) {
  441.     sprintf(line, "[1][Could not open %s!][OK]", configfile);
  442.     form_alert(1, line);
  443.     return -1;
  444.     }
  445.  
  446.     sprintf(saveline, " Saving Configuration to %s ... ", configfile);
  447.     savemsg[0].ob_width = strlen(saveline) * vw->Wchar;
  448.     savemsg[1].ob_width = strlen(saveline) * vw->Wchar;
  449.  
  450.     form_center(savemsg, &fx, &fy, &fw, &fh);
  451.     form_dial(FMD_START, 0, 0, vw->Wchar, vw->Hchar, fx, fy, fw, fh);
  452.     objc_draw(savemsg, 0, 2, fx, fy, fw, fh);
  453.  
  454.     hnorm = 1.0 / ((float)vw->full.g_w);
  455.     vnorm = 1.0 / ((float)vw->full.g_h);
  456.  
  457.     /* Write information to the config file. */
  458.  
  459.     fputs("# Configuration file for Atari ST Ghostscript.\n", config);
  460.     fputs("# Window x, y, w, and h are specified as fractions\n", config);
  461.     fputs("# of the screen size.\n\n", config);
  462.  
  463.     fprintf(config, "consolewin %f %f %f %f\n",
  464.     conswin.frame.g_x * hnorm,
  465.     conswin.frame.g_y * vnorm,
  466.     conswin.frame.g_w * hnorm,
  467.     conswin.frame.g_h * vnorm);
  468.  
  469.     fprintf(config, "imagewin %f %f %f %f\n",
  470.     imagwin.frame.g_x * hnorm,
  471.     imagwin.frame.g_y * vnorm,
  472.     imagwin.frame.g_w * hnorm,
  473.     imagwin.frame.g_h * vnorm);
  474.  
  475.     fputs("\n# Only x and y for the following windows.\n\n", config);
  476.  
  477.     fprintf(config, "aboutwin %f %f\n",
  478.     aboutwin.frame.g_x * hnorm,
  479.     aboutwin.frame.g_y * vnorm);
  480.  
  481.     fprintf(config, "reswin %f %f\n",
  482.     reswin.frame.g_x * hnorm,
  483.     reswin.frame.g_y * vnorm);
  484.  
  485.     fprintf(config, "devwin %f %f\n",
  486.     devwin.frame.g_x * hnorm,
  487.     devwin.frame.g_y * vnorm);
  488.  
  489.     fprintf(config, "sizwin %f %f\n",
  490.     sizwin.frame.g_x * hnorm,
  491.     sizwin.frame.g_y * vnorm);
  492.  
  493.     fprintf(config, "iconwin %f %f\n",
  494.     iconwin.frame.g_x * hnorm,
  495.     iconwin.frame.g_y * vnorm);
  496.  
  497.     fputs("\n# Devices available from the device dialog.\n\n", config);
  498.  
  499.     for (i=1; i<DEVICES; ++i) {
  500.     fprintf(config, "device %s\n", devices[i]);
  501.     }
  502.  
  503.     fputs("\n# Page sizes available from the size dialog.\n\n", config);
  504.  
  505.     for (i=0; i<SIZES; ++i) {
  506.     fprintf(config, "pagesize %s\n", sizes[i]);
  507.     }
  508.  
  509.     fclose(config);
  510.  
  511.     form_dial(FMD_FINISH, 0, 0, vw->Wchar, vw->Hchar, fx, fy, fw, fh);
  512.  
  513. }
  514.  
  515. int
  516. CopyImage(GRAPHIC *sgr, VWRK *vw, PSTATE *st)
  517. {
  518.     WINDOW *bwin;
  519.     GRAPHIC *gr;        /* new graphic structure */
  520.  
  521.     WINLIST *wl = WList;
  522.  
  523.     byte *buff;
  524.  
  525.     ulong buff_size = sgr->image.fd_w * sgr->image.fd_h;
  526.  
  527.     if ((bwin = WinAlloc()) == NULL) {
  528.     form_alert(1, "[1][Ghostscript Error!|No More Memory.][Continue]");
  529.     return (-1);
  530.     }
  531.  
  532.     if ((gr = GraphicAlloc()) == NULL) {
  533.     form_alert(1, "[1][Ghostscript Error!|No More Memory.][Continue]");
  534.     WinFree(bwin);
  535.     return (-1);
  536.     }
  537.  
  538.     if ((buff = (byte *)gs_malloc((uint)buff_size, 1, "bitbuffer")) == NULL) {
  539.     form_alert(1, "[1][Ghostscript Error!|No More Memory.][Continue]");
  540.     WinFree(bwin);
  541.     GraphicFree(gr);
  542.     return (-1);
  543.     }
  544.  
  545.     BitWinInit(bwin, gr, C_GADGETS, C_TITL);
  546.  
  547.     gr->image.fd_addr = (unsigned long) buff;
  548.  
  549.     memcpy((void *)gr->image.fd_addr, (void *)sgr->image.fd_addr, buff_size);
  550.  
  551.     WinListAdd(wl, bwin);
  552.     BitWinOpen(bwin, vw, st);
  553.  
  554. }
  555.  
  556. int
  557. BitWinOpen(WINDOW *bwin, VWRK *vw, PSTATE *st)
  558. {
  559.     GRAPHIC *gr = bwin->obj;
  560.  
  561.     /* Open a window for a bitmap image. */
  562.  
  563.     if (bwin->iconified) {
  564.     wind_open(bwin->handle,
  565.         bwin->frame.g_x, bwin->frame.g_y,
  566.         MIN(bwin->frame.g_w, bwin->mframe.g_w),
  567.         MIN(bwin->frame.g_h, bwin->mframe.g_h));
  568.  
  569.     bwin->opened = 1;
  570.     bwin->iconified = 0;
  571.     }
  572.     else if (!bwin->opened) {
  573.  
  574.     wind_calc(0, bwin->gadgets,
  575.         vw->full.g_x, vw->full.g_y,
  576.         gr->Width, gr->Height,
  577.         &bwin->mframe.g_x, &bwin->mframe.g_y,
  578.         &bwin->mframe.g_w, &bwin->mframe.g_h);
  579.  
  580.     if ((bwin->frame.g_w + bwin->frame.g_h) == 0) {
  581.         bwin->frame.g_x = bwin->mframe.g_x;
  582.         bwin->frame.g_y = bwin->mframe.g_y;
  583.         bwin->frame.g_w = bwin->mframe.g_w;
  584.         bwin->frame.g_h = bwin->mframe.g_h;
  585.     }
  586.  
  587.     bwin->handle = wind_create(
  588.         bwin->gadgets + (st->MultiTOS ? SMALLER : 0),
  589.         bwin->mframe.g_x, bwin->mframe.g_y,
  590.         bwin->mframe.g_w, bwin->mframe.g_h);
  591.  
  592.     if (bwin->handle < 0) {
  593.         form_alert(1, "[1][Ghostscript Error!|No More Windows.][Continue]");
  594.         WinListDelete(WList, bwin);
  595.         return (-1);
  596.     }
  597.  
  598.     wind_set(bwin->handle, WF_NAME, bwin->title, bwin->title, 0, 0);
  599.  
  600.     wind_open(bwin->handle,
  601.         bwin->frame.g_x, bwin->frame.g_y,
  602.         MIN(bwin->frame.g_w, bwin->mframe.g_w),
  603.         MIN(bwin->frame.g_h, bwin->mframe.g_h));
  604.  
  605.     wind_get(bwin->handle, WF_CURRXYWH,
  606.         &bwin->frame.g_x, &bwin->frame.g_y,
  607.         &bwin->frame.g_w, &bwin->frame.g_h);
  608.  
  609.     wind_get(bwin->handle, WF_CURRXYWH,
  610.         &bwin->oframe.g_x, &bwin->oframe.g_y,
  611.         &bwin->oframe.g_w, &bwin->oframe.g_h);
  612.  
  613.     wind_get(bwin->handle, WF_WORKXYWH,
  614.         &bwin->canvas.g_x, &bwin->canvas.g_y,
  615.         &bwin->canvas.g_w, &bwin->canvas.g_h);
  616.  
  617.     gr->StepX = .9 * bwin->canvas.g_w;
  618.     gr->StepY = .9 * bwin->canvas.g_h;
  619.  
  620.     bwin->opened = 1;
  621.     update_scroll(bwin->handle);
  622.     }
  623.  
  624.     return 0;
  625. }
  626.  
  627. int
  628. HelpWinOpen(VWRK *vw, PSTATE *st, char *HelpFile)
  629. {
  630.     FILE *helpf, *lib_fopen();
  631.     WINDOW *hwin;
  632.     WINTEXT *text;
  633.     WINLIST *wl=WList;
  634.  
  635.     char line[MAXLEN], helpfile[MAXLEN];
  636.     int count, twincount=0, length, longest=0;
  637.  
  638.     if ((hwin = WinAlloc()) == NULL) {
  639.     form_alert(1, "[1][Ghostscript Error!|No More Memory.][Continue]");
  640.     return (-1);
  641.     }
  642.  
  643.     if ((text = WinTextAlloc(LINES)) == NULL) {
  644.     form_alert(1, "[1][Ghostscript Error!|No More Memory.][Continue]");
  645.     WinFree(hwin);
  646.     return (-1);
  647.     }
  648.  
  649.     TextWinInit(hwin, text, H_GADGETS, H_TITL);
  650.  
  651.     /* Read help file into the text buffer. */
  652.  
  653.     strcpy(helpfile, HelpFile);
  654.  
  655.     if ((helpf = lib_fopen(helpfile)) == NULL) {
  656.     sprintf(line, "[1][Could not open %s!][OK]", helpfile);
  657.     form_alert(1, line);
  658.     return -1;
  659.     }
  660.  
  661.     for (count=0; (fgets(line, MAXLEN-1, helpf) != NULL); ++count) {
  662.  
  663.     length = strlen(line);
  664.     line[length-2] = '\0';
  665.  
  666.     if (length-2 > longest) longest = length-2;
  667.  
  668.     if (count >= text->bsize - 1) {
  669.         int NewSize = text->bsize + LINES;
  670.         if (TextBuffRealloc(text, NewSize) == NULL) {
  671.         form_alert(1, "[1][There is only enough ram to|\
  672.             load a portion of this file.][Continue]");
  673.         break;
  674.         }
  675.     }
  676.  
  677.     strcpy(text->buff[count], line);
  678.  
  679.     }
  680.  
  681.     fclose(helpf);
  682.  
  683.     if (hwin->frame.g_w + hwin->frame.g_h == 0) {
  684.     wind_calc(0, hwin->gadgets, vw->full.g_x, vw->full.g_y,
  685.         (longest + 4)*vw->Wchar, (count + 1)*vw->Hchar,
  686.         &hwin->frame.g_x, &hwin->frame.g_y,
  687.         &hwin->frame.g_w, &hwin->frame.g_h);
  688.  
  689.     /* Count the number of open text windows. */
  690.  
  691.     do {
  692.         if (wl->Win->type == TEXT){
  693.         ++twincount;
  694.         }
  695.         wl = wl->Next;
  696.     }
  697.     while (wl != WList);
  698.  
  699.     /* Place the window according to how many text windows are open. */
  700.  
  701.     hwin->frame.g_x = 2 * twincount * vw->Wchar;
  702.     hwin->frame.g_y = vw->full.g_y + twincount * vw->Hchar;
  703.     hwin->frame.g_w = MIN(hwin->frame.g_w, vw->full.g_w - hwin->frame.g_x);
  704.     hwin->frame.g_h = MIN(hwin->frame.g_h,
  705.         vw->full.g_h - twincount * vw->Hchar);
  706.     }
  707.  
  708.     text->bw = longest;
  709.     text->bh = count;
  710.  
  711.     WinListAdd(WList, hwin);
  712.     TextWinOpen(hwin, vw, st);
  713.  
  714.     text->ln = count-1;
  715. }
  716.  
  717. int
  718. TextWinOpen(WINDOW *twin, VWRK *vw, PSTATE *st)
  719. {
  720.  
  721.     WINTEXT *text = twin->obj;
  722.  
  723.     /* Create, open, and initialize a text window. */
  724.  
  725.     if (twin->iconified) {
  726.     wind_open(twin->handle,
  727.         twin->frame.g_x, twin->frame.g_y,
  728.         MIN(twin->frame.g_w, twin->mframe.g_w),
  729.         MIN(twin->frame.g_h, twin->mframe.g_h));
  730.  
  731.     twin->opened = 1;
  732.     twin->iconified = 0;
  733.     }
  734.     else if (!twin->opened) {
  735.  
  736.     int dummy;
  737.  
  738.     text->wc = vw->Wchar;
  739.     text->hc = vw->Hchar;
  740.  
  741.     wind_calc(0, twin->gadgets, vw->full.g_x, vw->full.g_y,
  742.         (text->bw + 4)*text->wc, (text->bh + 1)*text->hc,
  743.         &twin->mframe.g_x, &twin->mframe.g_y,
  744.         &twin->mframe.g_w, &twin->mframe.g_h);
  745.  
  746.     twin->mframe.g_x = MAX(twin->mframe.g_x, vw->full.g_x);
  747.     twin->mframe.g_y = MAX(twin->mframe.g_y, vw->full.g_y);
  748.     twin->mframe.g_w = MIN(twin->mframe.g_w, vw->full.g_w);
  749.     twin->mframe.g_h = MIN(twin->mframe.g_h, vw->full.g_h);
  750.  
  751.     twin->handle = wind_create(
  752.         twin->gadgets + (st->MultiTOS ? SMALLER : 0),
  753.         twin->mframe.g_x, twin->mframe.g_y,
  754.         twin->mframe.g_w, twin->mframe.g_h);
  755.  
  756.     if (twin->handle < 0) {
  757.         form_alert(1, "[1][Ghostscript Error!|No More Windows.][Continue]");
  758.         WinListDelete(WList, twin);
  759.         return (-1);
  760.     }
  761.  
  762.     wind_set(twin->handle, WF_NAME,
  763.         twin->title, twin->title, 0, 0);
  764.  
  765.     if ((twin->frame.g_w + twin->frame.g_h) == 0) {
  766.  
  767.         wind_calc(0, twin->gadgets + (st->MultiTOS ? SMALLER : 0),
  768.         vw->full.g_x, vw->full.g_y,
  769.         (text->bw + 2)*text->wc, (text->bh + 1)*text->hc,
  770.         &twin->frame.g_x, &twin->frame.g_y,
  771.         &twin->frame.g_w, &twin->frame.g_h);
  772.  
  773.         twin->frame.g_x = vw->full.g_x;
  774.         twin->frame.g_y = vw->full.g_y;
  775.         twin->frame.g_w = MIN(twin->frame.g_w, vw->full.g_w);
  776.         twin->frame.g_h = MIN(twin->frame.g_h, vw->full.g_h);
  777.  
  778.     }
  779.  
  780.     wind_open(twin->handle,
  781.         twin->frame.g_x, twin->frame.g_y,
  782.         twin->frame.g_w, twin->frame.g_h);
  783.  
  784.     wind_get(twin->handle, WF_CURRXYWH,
  785.         &twin->oframe.g_x, &twin->oframe.g_y,
  786.         &twin->oframe.g_w, &twin->oframe.g_h);
  787.  
  788.     wind_get(twin->handle, WF_WORKXYWH,
  789.         &twin->canvas.g_x, &twin->canvas.g_y,
  790.         &twin->canvas.g_w, &twin->canvas.g_h);
  791.  
  792.     twin->opened = 1;
  793.  
  794.     text->edge = twin->canvas.g_x;
  795.     text->top = twin->canvas.g_y;
  796.  
  797.     text->xoff = text->wc/2;
  798.     text->yoff = text->hc/2;
  799.  
  800.     text->lins = visible_lines(twin);
  801.     text->cols = visible_cols(twin);
  802.     text->ll   = text->bh - 1;
  803.     text->ldl  = text->fdl + text->lins - 1;
  804.  
  805.     text->cx = align(text->edge + text->xoff);
  806.     text->cy = text->top + text->yoff;
  807.  
  808.     vst_alignment(vw->VdiHandle, 0, 5, &dummy, &dummy);
  809.  
  810.     clear_win(&twin->canvas);
  811.     update_scroll(twin->handle);
  812.  
  813.     }
  814.  
  815.     return 0;
  816. }
  817.  
  818. int
  819. ObjWinOpen(OBJECT obj[], WINDOW *owin, VWRK *vw, PSTATE *st)
  820. {
  821.  
  822.     /* Create and open a window for a GEM object. */
  823.  
  824.     if (owin->iconified) {
  825.  
  826.     obj[0].ob_flags ^= HIDETREE;     /* Make the object tree visible. */
  827.  
  828.     wind_open(owin->handle,
  829.         owin->frame.g_x, owin->frame.g_y,
  830.         owin->frame.g_w, owin->frame.g_h);
  831.  
  832.     owin->opened = 1;
  833.     owin->iconified = 0;
  834.  
  835.     }
  836.     else if (!owin->opened) {
  837.  
  838.     owin->handle = wind_create(owin->gadgets,
  839.         vw->full.g_x, vw->full.g_y,
  840.         vw->full.g_w, vw->full.g_h);
  841.  
  842.     if (owin->handle < 0) {
  843.         form_alert(1,
  844.         "[1][Ghostscript Error!|No More Windows.][Continue]");
  845.         WinListDelete(WList, owin);
  846.         return (-1);
  847.         }
  848.  
  849.     wind_set(owin->handle, WF_NAME, owin->title, owin->title, 0, 0);
  850.  
  851.     /* Make the object tree visible. */
  852.  
  853.     obj[0].ob_flags ^= HIDETREE;
  854.  
  855.     /* If the window has never been opened, width and height will
  856.      * be zero. In this case, center the object before opening
  857.      * the window.
  858.      */
  859.  
  860.     if ((owin->frame.g_w + owin->frame.g_h) == 0) {
  861.         int tempx, tempy;
  862.  
  863.         form_center(obj,
  864.         &owin->canvas.g_x, &owin->canvas.g_y,
  865.         &owin->canvas.g_w, &owin->canvas.g_h);
  866.  
  867.         wind_calc(0, owin->gadgets,
  868.         owin->canvas.g_x, owin->canvas.g_y,
  869.         owin->canvas.g_w, owin->canvas.g_h,
  870.         &tempx, &tempy,
  871.         &owin->frame.g_w, &owin->frame.g_h);
  872.  
  873.         if (owin->frame.g_x + owin->frame.g_y) {
  874.         owin->canvas.g_x += owin->frame.g_x - tempx;
  875.         owin->canvas.g_y += owin->frame.g_y - tempy;
  876.         obj[0].ob_x += owin->frame.g_x - tempx;
  877.         obj[0].ob_y += owin->frame.g_y - tempy;
  878.         }
  879.         else {
  880.         owin->frame.g_x = tempx;
  881.         owin->frame.g_y = tempy;
  882.         }
  883.  
  884.     }
  885.  
  886.     /* The object is drawn by the redraw message which is
  887.      * automatically sent when the window is opened.
  888.      */
  889.  
  890.     wind_open(owin->handle,
  891.         owin->frame.g_x, owin->frame.g_y,
  892.         owin->frame.g_w, owin->frame.g_h);
  893.  
  894.     owin->opened = 1;
  895.  
  896.     }
  897.     else {
  898.     wind_set(owin->handle, WF_TOP, 0, 0, 0, 0);
  899.     }
  900.  
  901.     return 0;
  902.  
  903. }
  904.  
  905. int
  906. WinClose(WINDOW *win)
  907. {
  908.  
  909.     /* Close and delete the window; hide the object. */
  910.     
  911.     if (win->iconified) {
  912.  
  913.     wind_delete(win->handle);
  914.  
  915.     win->handle = -1;
  916.     win->iconified = 0;
  917.  
  918.     }
  919.     else if (win->opened) {
  920.  
  921.     wind_get(win->handle, WF_CURRXYWH,
  922.         &win->frame.g_x, &win->frame.g_y,
  923.         &win->frame.g_w, &win->frame.g_h);
  924.  
  925.     wind_get(win->handle, WF_CURRXYWH,
  926.         &win->oframe.g_x, &win->oframe.g_y,
  927.         &win->oframe.g_w, &win->oframe.g_h);
  928.  
  929.     wind_close(win->handle);
  930.     wind_delete(win->handle);
  931.  
  932.     if (win->type == OBJ) {
  933.         OBJECT *obj = win->obj;
  934.         obj[0].ob_flags ^= HIDETREE;
  935.     }
  936.  
  937.     win->handle = -1;
  938.     win->opened = 0;
  939.     }
  940.  
  941.     return 0;
  942. }
  943.  
  944. int
  945. bitw_arrow(PSTATE *st)
  946. {
  947.     int ChangeX, ChangeY;
  948.  
  949.     WINDOW *bwin = WinFindH(st->Event->Message[3]);
  950.     GRAPHIC *gr = bwin->obj;
  951.     VWRK *vw = &VWork;
  952.  
  953.     switch (st->Event->Message[4]) {
  954.  
  955.     case WA_UPLINE:    /* up line or top of page */
  956.     if (st->Event->KeyState)
  957.         gr->PlotY = 0;
  958.     else
  959.         gr->PlotY = MAX(gr->PlotY - vw->Hchar, 0);
  960.     break;
  961.  
  962.     case WA_DNLINE:    /* down line or bottom of page */
  963.     if (st->Event->KeyState)
  964.         gr->PlotY = gr->Height - bwin->canvas.g_h;
  965.     else
  966.         gr->PlotY = MIN(gr->PlotY + vw->Hchar,
  967.         gr->Height - bwin->canvas.g_h);
  968.     break;
  969.  
  970.     case WA_LFLINE:    /* left line or left page edge */
  971.     if (st->Event->KeyState)
  972.         gr->PlotX = 0;
  973.     else
  974.         gr->PlotX = MAX(gr->PlotX - vw->Wchar, 0);
  975.     break;
  976.  
  977.     case WA_RTLINE:    /* right page edge */
  978.     if (st->Event->KeyState)
  979.         gr->PlotX = gr->Width - bwin->canvas.g_w;
  980.     else
  981.         gr->PlotX = MIN(gr->PlotX + vw->Wchar, 
  982.         gr->Width - bwin->canvas.g_w);
  983.     break;
  984.  
  985.     case WA_UPPAGE:    /* up page */
  986.     gr->PlotY = MAX(gr->PlotY - gr->StepY, 0);
  987.     break;
  988.  
  989.     case WA_DNPAGE:    /* down page */
  990.     gr->PlotY = MIN(gr->PlotY + gr->StepY,
  991.         gr->Height - bwin->canvas.g_h);
  992.     break;
  993.  
  994.     case WA_LFPAGE:    /* left page */
  995.     gr->PlotX = MAX(gr->PlotX - gr->StepX, 0);
  996.     break;
  997.  
  998.     case WA_RTPAGE:    /* right page */
  999.     gr->PlotX = MIN(gr->PlotX + gr->StepX,
  1000.         gr->Width - bwin->canvas.g_w);
  1001.     break;
  1002.  
  1003.     }
  1004.  
  1005.     update_scroll(st->Event->Message[3]);
  1006.     cursor(OFF);
  1007.     HandleRedraw(FULL_WIN, &State);
  1008.     cursor(ON);
  1009.  
  1010. }
  1011.  
  1012. int
  1013. txtw_hslide(PSTATE *st)
  1014. {
  1015.     int ChangeX, ChangeY;
  1016.     int handle = st->Event->Message[3];
  1017.  
  1018.     WINDOW  *twin = WinFindH(handle);
  1019.     WINTEXT *text = twin->obj;
  1020.  
  1021.     text->fdc = (text->bw + 2 - text->cols) * st->Event->Message[4]/1000;
  1022.     text->ldc = text->fdc + text->cols - 1;
  1023.  
  1024.     ChangeX = twin->canvas.g_x - text->fdc * text->wc - text->edge;
  1025.  
  1026.     text->edge += ChangeX;
  1027.     text->cx   += ChangeX;
  1028.  
  1029.     update_scroll(handle);
  1030.     cursor(OFF);
  1031.     HandleRedraw(FULL_WIN, st);
  1032.     cursor(ON);
  1033. }
  1034.  
  1035. int
  1036. bitw_hslide(PSTATE *st)
  1037. {
  1038.     WINDOW *bwin = WinFindH(st->Event->Message[3]); 
  1039.     GRAPHIC *gr = bwin->obj;
  1040.  
  1041.     gr->PlotX = (gr->Width - bwin->canvas.g_w) * st->Event->Message[4]/1000;
  1042.  
  1043.     update_scroll(st->Event->Message[3]);
  1044.     HandleRedraw(FULL_WIN, st);
  1045. }
  1046.  
  1047. int
  1048. txtw_vslide(PSTATE *st)
  1049. {
  1050.     int ChangeX, ChangeY;
  1051.     WINTEXT *text = ObjFindH(st->Event->Message[3]);
  1052.  
  1053.     int OldOffset = text->fdl - text->fl;
  1054.     int NewOffset = (text->bh - text->lins) * st->Event->Message[4]/1000;
  1055.  
  1056.     if (OldOffset < 0) OldOffset += text->bh;
  1057.  
  1058.     text->fdl = text->fl + NewOffset;
  1059.     if (text->fdl >= text->bh) text->fdl -= text->bh;
  1060.  
  1061.     text->ldl = text->fdl + text->lins - 1;
  1062.     if (text->ldl >= text->bh) text->ldl -= text->bh;
  1063.  
  1064.     ChangeY = (OldOffset - NewOffset) * text->hc;
  1065.     text->top += ChangeY;
  1066.     text->cy  += ChangeY;
  1067. }
  1068.  
  1069. int
  1070. bitw_vslide(PSTATE *st)
  1071. {
  1072.     WINDOW *bwin = WinFindH(st->Event->Message[3]);
  1073.     GRAPHIC *gr = bwin->obj;
  1074.  
  1075.     gr->PlotY = (gr->Height - bwin->canvas.g_h) * st->Event->Message[4]/1000;
  1076. }
  1077.  
  1078. int
  1079. objw_move(PSTATE *st)
  1080. {
  1081.     int ChangeX, ChangeY;
  1082.  
  1083.     WINDOW *owin = WinFindH(st->Event->Message[3]);
  1084.     OBJECT *obj = owin->obj;
  1085.  
  1086.     wind_set(owin->handle, WF_CURRXYWH,
  1087.     st->Event->Message[4], st->Event->Message[5],
  1088.     st->Event->Message[6], st->Event->Message[7]);
  1089.  
  1090.     ChangeX = st->Event->Message[4] - owin->frame.g_x;
  1091.     ChangeY = st->Event->Message[5] - owin->frame.g_y;
  1092.  
  1093.     obj[0].ob_x += ChangeX;
  1094.     obj[0].ob_y += ChangeY;
  1095.  
  1096.     wind_get(owin->handle, WF_CURRXYWH,
  1097.     &owin->frame.g_x, &owin->frame.g_y,
  1098.     &owin->frame.g_w, &owin->frame.g_h);
  1099.  
  1100.     wind_get(owin->handle, WF_WORKXYWH,
  1101.     &owin->canvas.g_x, &owin->canvas.g_y,
  1102.     &owin->canvas.g_w, &owin->canvas.g_h);
  1103.  
  1104. }
  1105.  
  1106. int
  1107. bitw_move(PSTATE *st)
  1108. {
  1109.  
  1110.     WINDOW *bwin = WinFindH(st->Event->Message[3]);
  1111.  
  1112.     wind_set(bwin->handle, WF_CURRXYWH,
  1113.     st->Event->Message[4], st->Event->Message[5],
  1114.     MIN(bwin->mframe.g_w, st->Event->Message[6]),
  1115.     MIN(bwin->mframe.g_h, st->Event->Message[7]));
  1116.  
  1117.     wind_get(bwin->handle, WF_CURRXYWH,
  1118.     &bwin->frame.g_x, &bwin->frame.g_y,
  1119.     &bwin->frame.g_w, &bwin->frame.g_h);
  1120.  
  1121.     wind_get(bwin->handle, WF_WORKXYWH,
  1122.     &bwin->canvas.g_x, &bwin->canvas.g_y,
  1123.     &bwin->canvas.g_w, &bwin->canvas.g_h);
  1124. }
  1125.  
  1126. int
  1127. txtw_move(PSTATE *st)
  1128. {
  1129.     int ChangeX, ChangeY;
  1130.  
  1131.     WINDOW *twin = WinFindH(st->Event->Message[3]);
  1132.     WINTEXT *text = twin->obj;
  1133.  
  1134.     int oldcanvas_x = twin->canvas.g_x;
  1135.     int oldcanvas_y = twin->canvas.g_y;
  1136.  
  1137.     wind_set(twin->handle, WF_CURRXYWH,
  1138.     align(st->Event->Message[4]), st->Event->Message[5],
  1139.     MIN(twin->mframe.g_w, st->Event->Message[6]),
  1140.     MIN(twin->mframe.g_w, st->Event->Message[7]));
  1141.  
  1142.     wind_get(twin->handle, WF_CURRXYWH,
  1143.     &twin->frame.g_x, &twin->frame.g_y,
  1144.     &twin->frame.g_w, &twin->frame.g_h);
  1145.  
  1146.     wind_get(twin->handle, WF_WORKXYWH,
  1147.     &twin->canvas.g_x, &twin->canvas.g_y,
  1148.     &twin->canvas.g_w, &twin->canvas.g_h);
  1149.  
  1150.     ChangeX = twin->canvas.g_x - oldcanvas_x;
  1151.     ChangeY = twin->canvas.g_y - oldcanvas_y;
  1152.  
  1153.     text->edge += ChangeX;
  1154.     text->top  += ChangeY;
  1155.  
  1156.     text->cx += ChangeX;
  1157.     text->cy += ChangeY;
  1158. }
  1159.  
  1160. int
  1161. txtw_arrow(PSTATE *st)
  1162. {
  1163.     int ChangeX, ChangeY;
  1164.     int handle = st->Event->Message[3];
  1165.  
  1166.     WINDOW *twin  = WinFindH(handle);
  1167.     WINTEXT *text = twin->obj;
  1168.  
  1169.     switch (st->Event->Message[4]) {
  1170.  
  1171.     case WA_UPLINE:    /* top line or up line */
  1172.     if (st->Event->KeyState) {
  1173.         ChangeY = twin->canvas.g_y - text->top;
  1174.         text->top += ChangeY;
  1175.         text->cy  += ChangeY;
  1176.         text->fdl = text->fl;
  1177.         text->ldl = text->fl + text->lins - 1;
  1178.         if (text->ldl >= text->bh) text->ldl -= text->bh;
  1179.     }
  1180.     else {
  1181.         if (text->fdl != text->fl) {
  1182.         text->top += text->hc;
  1183.         text->cy += text->hc;
  1184.         if (--text->fdl < 0) text->fdl += text->bh;
  1185.         if (--text->ldl < 0) text->fdl += text->bh;
  1186.         }
  1187.     }
  1188.     break;
  1189.  
  1190.     case WA_DNLINE:    /* bottom line or down line */
  1191.     if (st->Event->KeyState) {
  1192.         ChangeY = twin->canvas.g_y
  1193.             - (text->bh - text->lins) * text->hc - text->top;
  1194.         text->top += ChangeY;
  1195.         text->cy  += ChangeY;
  1196.         text->fdl = text->ll - text->lins + 1;
  1197.         text->ldl = text->ll;
  1198.         if (text->fdl < 0) text->fdl += text->bh;
  1199.     }
  1200.     else {
  1201.         if (text->ldl != text->ll) {
  1202.         text->top -= text->hc;
  1203.         text->cy  -= text->hc;
  1204.         if (++text->fdl >= text->bh) text->fdl = 0;
  1205.         if (++text->ldl >= text->bh) text->ldl = 0;
  1206.         }
  1207.     }
  1208.     break;
  1209.  
  1210.     case WA_LFLINE:    /* left line */
  1211.     if (st->Event->KeyState) {
  1212.         ChangeX = twin->canvas.g_x - text->edge;
  1213.         text->edge += ChangeX;
  1214.         text->cx   += ChangeX;
  1215.         text->fdc = 0;
  1216.         text->ldc = text->cols - 1;
  1217.     }
  1218.     else {
  1219.         if (text->fdc > 0) {
  1220.         text->edge += text->wc;
  1221.         text->cx  += text->wc;
  1222.         text->fdc--;
  1223.         text->ldc--;
  1224.         }
  1225.     }
  1226.     break;
  1227.  
  1228.     case WA_RTLINE:    /* right line */
  1229.     if (st->Event->KeyState) {
  1230.         ChangeX = twin->canvas.g_x
  1231.             - (text->bw + 2 - text->cols) * text->wc - text->edge;
  1232.         text->edge += ChangeX;
  1233.         text->cx   += ChangeX;
  1234.         text->fdc = (text->bw + 2 - text->cols);
  1235.         text->ldc = text->fdc + text->cols - 1;
  1236.     }
  1237.     else {
  1238.         if ((text->fdc + text->cols) < (text->bw + 2)) {
  1239.         text->edge -= text->wc;
  1240.         text->cx  -= text->wc;
  1241.         text->fdc++;
  1242.         text->ldc++;
  1243.         }
  1244.     }
  1245.     break;
  1246.  
  1247.     case WA_UPPAGE:    /* up page */
  1248.       {
  1249.     int to_top = text->fdl - text->fl;
  1250.     to_top = (to_top >= 0) ? to_top : to_top + text->bh;
  1251.  
  1252.     if (to_top >= (text->lins - 1)) {
  1253.         text->top += (text->lins - 1) * text->hc;
  1254.         text->cy  += (text->lins - 1) * text->hc;
  1255.         text->fdl -= (text->lins - 1);
  1256.         text->ldl  -= (text->lins - 1);
  1257.         if (text->fdl < 0) text->fdl += text->bh;
  1258.         if (text->ldl < 0) text->ldl += text->bh;
  1259.     }
  1260.     else {
  1261.         ChangeY = twin->canvas.g_y - text->top;
  1262.         text->top += ChangeY;
  1263.         text->cy  += ChangeY;
  1264.         text->fdl = text->fl;
  1265.         text->ldl = text->fl + text->lins - 1;
  1266.         if (text->ldl >= text->bh) text->ldl -= text->bh;
  1267.     }
  1268.     break;
  1269.       }
  1270.  
  1271.     case WA_DNPAGE:    /* down page */
  1272.       {
  1273.     int to_bot = text->ll - text->ldl;
  1274.     to_bot = (to_bot >= 0) ? to_bot : to_bot + text->bh;
  1275.  
  1276.     if (to_bot >= (text->lins - 1)) {
  1277.         text->top -= (text->lins - 1) * text->hc;
  1278.         text->cy  -= (text->lins - 1) * text->hc;
  1279.         text->fdl += (text->lins - 1);
  1280.         text->ldl += (text->lins - 1);
  1281.         if (text->fdl >= text->bh) text->fdl -= text->bh;
  1282.         if (text->ldl >= text->bh) text->ldl -= text->bh;
  1283.     }
  1284.     else {
  1285.         ChangeY = twin->canvas.g_y
  1286.             - (text->bh - text->lins) * text->hc - text->top;
  1287.         text->top += ChangeY;
  1288.         text->cy  += ChangeY;
  1289.         text->fdl = text->ll - text->lins + 1;
  1290.         text->ldl = text->ll;
  1291.         if (text->fdl < 0) text->fdl += text->bh;
  1292.     }
  1293.     break;
  1294.       }
  1295.  
  1296.     case WA_LFPAGE:    /* left page */
  1297.     if (text->fdc  >= (text->cols - 1)) {
  1298.         text->edge += (text->cols - 1) * text->wc;
  1299.         text->cx   += (text->cols - 1) * text->wc;
  1300.         text->fdc  -= (text->cols - 1);
  1301.         text->ldc = text->fdc + text->cols - 1;
  1302.     }
  1303.     else {
  1304.         ChangeX = twin->canvas.g_x - text->edge;
  1305.         text->edge += ChangeX;
  1306.         text->cx   += ChangeX;
  1307.         text->fdc = 0;
  1308.         text->ldc = text->cols - 1;
  1309.     }
  1310.     break;
  1311.  
  1312.     case WA_RTPAGE:    /* right page */
  1313.     if (text->fdc <= (text->bw - 2*text->cols + 3)) {
  1314.         text->edge -= (text->cols - 1) * text->wc;
  1315.         text->cx  -= (text->cols - 1) * text->wc;
  1316.         text->fdc += (text->cols - 1);
  1317.         text->ldc += (text->cols - 1);
  1318.     }
  1319.     else {
  1320.         ChangeX = twin->canvas.g_x
  1321.             - (text->bw + 2 - text->cols) * text->wc - text->edge;
  1322.         text->edge += ChangeX;
  1323.         text->cx   += ChangeX;
  1324.         text->fdc = (text->bw + 2 - text->cols);
  1325.         text->ldc = text->fdc + text->cols - 1;
  1326.     }
  1327.     break;
  1328.  
  1329.     }
  1330.  
  1331.     update_scroll(st->Event->Message[3]);
  1332.     cursor(OFF);
  1333.     HandleRedraw(FULL_WIN, &State);
  1334.     cursor(ON);
  1335.  
  1336. }
  1337.  
  1338. int
  1339. txtw_size(PSTATE *st)
  1340. {
  1341.  
  1342.     int handle = st->Event->Message[3];
  1343.  
  1344.     WINDOW *twin = WinFindH(handle);
  1345.     WINTEXT *text = twin->obj;
  1346.  
  1347.     int offset, diff, ChangeX;
  1348.  
  1349.     int old_x = twin->canvas.g_x;
  1350.     int old_y = twin->canvas.g_y;
  1351.     int old_w = twin->canvas.g_w;
  1352.     int old_h = twin->canvas.g_h;
  1353.  
  1354.     wind_set(twin->handle, WF_CURRXYWH,
  1355.     st->Event->Message[4], st->Event->Message[5],
  1356.     MIN(twin->mframe.g_w, st->Event->Message[6]),
  1357.     MIN(twin->mframe.g_h, st->Event->Message[7]));
  1358.  
  1359.     wind_get(twin->handle, WF_CURRXYWH,
  1360.     &twin->frame.g_x, &twin->frame.g_y,
  1361.     &twin->frame.g_w, &twin->frame.g_h);
  1362.  
  1363.     wind_get(twin->handle, WF_WORKXYWH,
  1364.     &twin->canvas.g_x, &twin->canvas.g_y,
  1365.     &twin->canvas.g_w, &twin->canvas.g_h);
  1366.  
  1367.     text->lins = visible_lines(twin);
  1368.     text->cols = visible_cols(twin);
  1369.  
  1370.     /* For the console window, put the current line at the bottom
  1371.      * of the window and adjust the first and last lines accordingly.
  1372.      * For other text windows, leave the first line unchanged if
  1373.      * possible.
  1374.      */
  1375.  
  1376.     if (twin->handle == conswin.handle) {
  1377.     text->fdl = text->ln - text->lins + 1;
  1378.  
  1379.     if (text->fdl > text->bh) {
  1380.         text->fdl -= text->bh;
  1381.     }
  1382.     else if (text->fdl < 0 && !text->scrolled) {
  1383.         text->fdl = 0;
  1384.     }
  1385.     else if (text->fdl < 0 && text->scrolled) {
  1386.         text->fdl += text->bh;
  1387.     }
  1388.     }
  1389.  
  1390.     text->ldl = text->fdl + text->lins - 1;
  1391.  
  1392.     if (text->ldl >= text->bh) {
  1393.     if (text->scrolled) {
  1394.         text->ldl -= text->bh;
  1395.     }
  1396.     else {        /* First displayed line must be changed. */
  1397.         text->ldl = text->bh - 1;
  1398.         text->fdl = text->ldl - text->lins + 1;
  1399.     }
  1400.     }
  1401.  
  1402.     /* Keep the first column the same, if possible, and adjust the
  1403.      * last column appropriately.
  1404.      */
  1405.  
  1406.     text->ldc = text->fdc + text->cols - 1;
  1407.     ChangeX = twin->canvas.g_x - old_x;
  1408.  
  1409.     if ((diff = text->ldc - text->bw - 1) > 0) {  /* Change first column. */
  1410.     ChangeX += diff * text->wc;
  1411.     text->ldc = text->bw + 1;
  1412.     text->fdc = text->ldc - text->cols + 1;
  1413.     }
  1414.  
  1415.     /* Adjust the cursor position. */
  1416.  
  1417.     text->cx += ChangeX;
  1418.  
  1419.     offset = text->ln - text->fdl;
  1420.     if (offset < 0) offset += text->bh;
  1421.     if (offset >= text->bh) offset -= text->bh;
  1422.     text->cy = twin->canvas.g_y + text->yoff + offset * text->hc;
  1423.  
  1424.     /* Adjust the left edge and top of the page. */
  1425.  
  1426.     text->edge += ChangeX;
  1427.  
  1428.     offset = text->fdl - text->fl;
  1429.     if (offset < 0) offset += text->bh;
  1430.     if (offset >= text->bh) offset -= text->bh;
  1431.     text->top = twin->canvas.g_y - offset * text->hc;
  1432.  
  1433.     /* Redraw the window if the OS won't. */
  1434.  
  1435.     if (old_x <= twin->canvas.g_x &&
  1436.     old_y <= twin->canvas.g_y &&
  1437.     old_w >= twin->canvas.g_w &&
  1438.     old_h >= twin->canvas.g_h) {
  1439.  
  1440.     cursor(OFF);
  1441.     HandleRedraw(FULL_WIN, st);
  1442.     cursor(ON);
  1443.     }
  1444.  
  1445.     update_scroll(handle);
  1446. }
  1447.  
  1448. int
  1449. bitw_size(PSTATE *st)
  1450. {
  1451.  
  1452.     WINDOW *bwin = WinFindH(st->Event->Message[3]);
  1453.     GRAPHIC *gr = bwin->obj;
  1454.  
  1455.     wind_set(bwin->handle, WF_CURRXYWH,
  1456.     st->Event->Message[4], st->Event->Message[5],
  1457.     MIN(bwin->mframe.g_w, st->Event->Message[6]),
  1458.     MIN(bwin->mframe.g_h, st->Event->Message[7]));
  1459.  
  1460.     wind_get(bwin->handle, WF_CURRXYWH,
  1461.     &bwin->frame.g_x, &bwin->frame.g_y,
  1462.     &bwin->frame.g_w, &bwin->frame.g_h);
  1463.  
  1464.     wind_get(bwin->handle, WF_WORKXYWH,
  1465.     &bwin->canvas.g_x, &bwin->canvas.g_y,
  1466.     &bwin->canvas.g_w, &bwin->canvas.g_h);
  1467.  
  1468.     gr->StepX = .9 * bwin->canvas.g_w;
  1469.     gr->StepY = .9 * bwin->canvas.g_h;
  1470.  
  1471.     update_scroll(st->Event->Message[3]);
  1472. }
  1473.  
  1474.  
  1475. int
  1476. txtw_redraw(int full_win, PSTATE *st)
  1477. {
  1478.     int handle = st->Event->Message[3];
  1479.  
  1480.     WINDOW *twin = WinFindH(handle);
  1481.     WINTEXT *text = twin->obj;
  1482.  
  1483.     int i, cnt;
  1484.     int x = align(twin->canvas.g_x + text->xoff);
  1485.     int fcol = text->fdc;
  1486.     int y, TopLineY, ln;
  1487.  
  1488.     GRECT dirty, rect;
  1489.  
  1490.     if (full_win) {
  1491.     dirty.g_x = twin->canvas.g_x;
  1492.     dirty.g_y = twin->canvas.g_y;
  1493.     dirty.g_w = twin->canvas.g_w;
  1494.     dirty.g_h = twin->canvas.g_h;
  1495.     }
  1496.     else {
  1497.     dirty.g_x = st->Event->Message[4];
  1498.     dirty.g_y = st->Event->Message[5];
  1499.     dirty.g_w = st->Event->Message[6];
  1500.     dirty.g_h = st->Event->Message[7];
  1501.     }
  1502.  
  1503.     TopLineY = twin->canvas.g_y + text->yoff;
  1504.  
  1505.     cnt = text->ln - text->fdl + 1;
  1506.     cnt = (cnt > 0) ? cnt : cnt + text->bh;
  1507.     cnt = MIN(cnt, text->lins);
  1508.  
  1509.     wind_get(twin->handle, WF_FIRSTXYWH,
  1510.     &rect.g_x, &rect.g_y,
  1511.     &rect.g_w, &rect.g_h);
  1512.  
  1513.     graf_mouse(M_OFF, 0L);
  1514.  
  1515.     while (rect.g_w && rect.g_h) {
  1516.  
  1517.     if (rc_intersect(&dirty, &rect)) {
  1518.         if (rc_intersect(&twin->canvas, &rect)) {
  1519.         
  1520.         y = TopLineY;
  1521.  
  1522.         grect_to_array(&rect, st->pxy);
  1523.         vs_clip(VWork.VdiHandle, 1, st->pxy);
  1524.         
  1525.         clear_win(&rect);
  1526.  
  1527.         for (ln=text->fdl, i=cnt; i; i--, ln++, y+=text->hc) {
  1528.             if (ln >= text->bh) ln -= text->bh;
  1529.             if (strlen(text->buff[ln]) > fcol)
  1530.             v_gtext(VWork.VdiHandle, x, y, text->buff[ln]+fcol);
  1531.         }
  1532.  
  1533.         vs_clip(VWork.VdiHandle, 0, st->pxy);
  1534.         }
  1535.     }
  1536.  
  1537.     wind_get(twin->handle, WF_NEXTXYWH,
  1538.         &rect.g_x, &rect.g_y,
  1539.         &rect.g_w, &rect.g_h);
  1540.     }
  1541.  
  1542.     graf_mouse(M_ON, 0L);
  1543.  
  1544. }
  1545.  
  1546. int
  1547. objw_redraw(int full_win, PSTATE *st)
  1548. {
  1549.  
  1550.     int handle = st->Event->Message[3];
  1551.  
  1552.     WINDOW *owin = WinFindH(handle);
  1553.     OBJECT *obj = owin->obj;
  1554.  
  1555.     GRECT dirty, rect;
  1556.  
  1557.     if (full_win) {
  1558.     dirty.g_x = owin->canvas.g_x;
  1559.     dirty.g_y = owin->canvas.g_y;
  1560.     dirty.g_w = owin->canvas.g_w;
  1561.     dirty.g_h = owin->canvas.g_h;
  1562.     }
  1563.     else {
  1564.     dirty.g_x = st->Event->Message[4];
  1565.     dirty.g_y = st->Event->Message[5];
  1566.     dirty.g_w = st->Event->Message[6];
  1567.     dirty.g_h = st->Event->Message[7];
  1568.     }
  1569.  
  1570.     wind_get(handle, WF_FIRSTXYWH,
  1571.     &rect.g_x, &rect.g_y,
  1572.     &rect.g_w, &rect.g_h);
  1573.  
  1574.     graf_mouse(M_OFF, 0L);
  1575.  
  1576.     while (rect.g_w && rect.g_h) {
  1577.  
  1578.     if (rc_intersect(&dirty, &rect)) {
  1579.         if (rc_intersect(&owin->canvas, &rect)) {
  1580.         objc_draw(obj, 0, 3,
  1581.             rect.g_x, rect.g_y,
  1582.             rect.g_w, rect.g_h);
  1583.         }
  1584.     }
  1585.  
  1586.     wind_get(handle, WF_NEXTXYWH,
  1587.         &rect.g_x, &rect.g_y,
  1588.         &rect.g_w, &rect.g_h);
  1589.  
  1590.     }
  1591.  
  1592.     graf_mouse(M_ON, 0L);
  1593.  
  1594. }
  1595.  
  1596. int
  1597. bitw_redraw(int full_win, PSTATE *st)
  1598. {
  1599.  
  1600.     WINDOW *bwin = WinFindH(st->Event->Message[3]);
  1601.     GRAPHIC *gr  = bwin->obj;
  1602.  
  1603.     GRECT dirty, rect;
  1604.  
  1605.     if (full_win) {
  1606.     dirty.g_x = bwin->canvas.g_x;
  1607.     dirty.g_y = bwin->canvas.g_y;
  1608.     dirty.g_w = bwin->canvas.g_w;
  1609.     dirty.g_h = bwin->canvas.g_h;
  1610.     }
  1611.     else {
  1612.     dirty.g_x = st->Event->Message[4];
  1613.     dirty.g_y = st->Event->Message[5];
  1614.     dirty.g_w = st->Event->Message[6];
  1615.     dirty.g_h = st->Event->Message[7];
  1616.     }
  1617.  
  1618.     gr->PlotX = MIN(gr->PlotX, gr->Width - bwin->canvas.g_w);
  1619.     gr->PlotY = MIN(gr->PlotY, gr->Height - bwin->canvas.g_h);
  1620.  
  1621.     wind_get(bwin->handle, WF_FIRSTXYWH,
  1622.     &rect.g_x, &rect.g_y,
  1623.     &rect.g_w, &rect.g_h);
  1624.  
  1625.     graf_mouse(M_OFF, 0L);
  1626.  
  1627.     while (rect.g_w && rect.g_h) {
  1628.     if (rc_intersect(&dirty, &rect)) {
  1629.         if (rc_intersect(&bwin->canvas, &rect)) {
  1630.         
  1631.         st->pxy[0] = gr->PlotX + (rect.g_x - bwin->canvas.g_x);
  1632.         st->pxy[1] = gr->PlotY + (rect.g_y - bwin->canvas.g_y);
  1633.         st->pxy[2] = st->pxy[0] + rect.g_w - 1;
  1634.         st->pxy[3] = st->pxy[1] + rect.g_h - 1;
  1635.  
  1636.         grect_to_array(&rect, &st->pxy[4]);
  1637.  
  1638.         vs_clip(VWork.VdiHandle, 1, &st->pxy[4]);
  1639.         vro_cpyfm(VWork.VdiHandle, 3, st->pxy,
  1640.             &gr->image, &gr->screen);
  1641.         vs_clip(VWork.VdiHandle, 0, &st->pxy[4]);
  1642.  
  1643.         }
  1644.     }
  1645.  
  1646.     wind_get(bwin->handle, WF_NEXTXYWH,
  1647.         &rect.g_x, &rect.g_y,
  1648.         &rect.g_w, &rect.g_h);
  1649.     }
  1650.  
  1651.     graf_mouse(M_ON, 0L);
  1652.  
  1653. }
  1654.  
  1655. int
  1656. update_scroll(int handle)
  1657. {
  1658.     int hslide_pos, hslide_siz, vslide_pos, vslide_siz;
  1659.  
  1660.     WINDOW *win = WinFindH(handle);
  1661.  
  1662.     switch (win->type) {
  1663.  
  1664.     case BIT:
  1665.       {
  1666.     GRAPHIC *gr = win->obj;
  1667.  
  1668.     if (gr->Width != win->canvas.g_w) {
  1669.         hslide_pos = 1000 * gr->PlotX/(gr->Width - win->canvas.g_w);
  1670.     }
  1671.     else {
  1672.         hslide_pos = 0;
  1673.     }
  1674.  
  1675.     if (gr->Height != win->canvas.g_h) {
  1676.         vslide_pos = 1000 * gr->PlotY
  1677.                / (gr->Height - win->canvas.g_h);
  1678.     }
  1679.     else {
  1680.         vslide_pos = 0;
  1681.     }
  1682.  
  1683.     hslide_siz = 1000 * win->canvas.g_w/gr->Width;
  1684.     vslide_siz = 1000 * win->canvas.g_h/gr->Height;
  1685.  
  1686.       }
  1687.     break;
  1688.  
  1689.     case TEXT:
  1690.       {
  1691.     WINTEXT *text = win->obj;
  1692.  
  1693.     int offset = text->fdl - text->fl;
  1694.  
  1695.     if (offset < 0) offset += text->bh;
  1696.  
  1697.     if (text->cols != text->bw + 2) {
  1698.         hslide_pos = 1000 * text->fdc/(text->bw + 2 - text->cols);
  1699.     }
  1700.     else {
  1701.         hslide_pos = 0;
  1702.     }
  1703.  
  1704.     if (text->lins < text->bh) {
  1705.         vslide_pos = 1000 * offset/(text->bh - text->lins);
  1706.     }
  1707.     else {
  1708.         vslide_pos = 0;
  1709.     }
  1710.  
  1711.     hslide_siz = 1000 * text->cols/(text->bw + 2);
  1712.     vslide_siz = 1000 * text->lins/text->bh;
  1713.  
  1714.       }
  1715.     break;
  1716.  
  1717.     }
  1718.  
  1719.     wind_set(handle, WF_HSLIDE,  hslide_pos);
  1720.     wind_set(handle, WF_VSLIDE,  vslide_pos);
  1721.     wind_set(handle, WF_HSLSIZE, hslide_siz);
  1722.     wind_set(handle, WF_VSLSIZE, vslide_siz);
  1723.  
  1724.     return 0;
  1725. }
  1726.  
  1727. int
  1728. TextWinInit(WINDOW *twin, WINTEXT *text, int gadgets, char *title)
  1729. {
  1730.     twin->handle = -1;
  1731.     twin->type = TEXT;
  1732.     twin->obj = (void *)text;
  1733.     twin->gadgets = gadgets;
  1734.     twin->title = title;
  1735.     twin->opened = 0;
  1736.     twin->iconified = 0;
  1737.  
  1738.     twin->canvas.g_x = 0; twin->canvas.g_y = 0;
  1739.     twin->canvas.g_w = 0; twin->canvas.g_h = 0;
  1740.  
  1741.     twin->frame.g_x = 0; twin->frame.g_y = 0;
  1742.     twin->frame.g_w = 0; twin->frame.g_h = 0;
  1743.  
  1744.     twin->oframe.g_x = 0; twin->oframe.g_y = 0;
  1745.     twin->oframe.g_w = 0; twin->oframe.g_h = 0;
  1746.  
  1747.     twin->mframe.g_x = 0; twin->mframe.g_y = 0;
  1748.     twin->mframe.g_w = 0; twin->mframe.g_h = 0;
  1749.  
  1750.     twin->redraw = txtw_redraw;
  1751.     twin->move   = txtw_move;
  1752.     twin->size   = txtw_size;
  1753.     twin->arrow  = txtw_arrow;
  1754.     twin->hslide = txtw_hslide;
  1755.     twin->vslide = txtw_vslide;
  1756.  
  1757.     text->bw   = COLUMNS;
  1758.     text->bh   = LINES;
  1759.     text->top  = text->edge = 0;
  1760.     text->xoff = text->yoff = 0;
  1761.     text->cx   = text->cy   = 0;
  1762.     text->cstate = 0;
  1763.     text->wc   = text->hc   = 0;
  1764.     text->lins = text->cols = 0;
  1765.     text->ln   = text->cn   = 0;
  1766.     text->fl   = 0;
  1767.     text->ll   = LINES-1;
  1768.     text->fdl  = 0;
  1769.     text->ldl  = LINES-1;
  1770.     text->fdc  = text->ldc  = 0;
  1771.     text->scrolled = 0;
  1772. }
  1773.  
  1774. int
  1775. BitWinInit(WINDOW *bwin, GRAPHIC *gr, int gadgets, char *title)
  1776. {
  1777.     bwin->handle = -1;
  1778.     bwin->type = BIT;
  1779.     bwin->obj = (void *)gr;
  1780.     bwin->gadgets = gadgets;
  1781.     bwin->title = title;
  1782.     bwin->opened = 0;
  1783.     bwin->iconified = 0;
  1784.  
  1785.     bwin->redraw = bitw_redraw;
  1786.     bwin->move   = bitw_move;
  1787.     bwin->size   = bitw_size;
  1788.     bwin->arrow  = bitw_arrow;
  1789.     bwin->hslide = bitw_hslide;
  1790.     bwin->vslide = bitw_vslide;
  1791.  
  1792.     bwin->frame.g_x = imagwin.frame.g_x + 2 * VWork.Wchar;
  1793.     bwin->frame.g_y = imagwin.frame.g_x + VWork.Hchar;
  1794.     bwin->frame.g_w = imagwin.frame.g_w;
  1795.     bwin->frame.g_h = imagwin.frame.g_h;
  1796.  
  1797.     memcpy(gr, imagwin.obj, sizeof(GRAPHIC));
  1798.  
  1799. }
  1800.  
  1801. int
  1802. ObjWinInit(WINDOW *owin, OBJECT *object, int gadgets, char *title)
  1803. {
  1804.     owin->handle = -1;
  1805.     owin->type = OBJ;
  1806.     owin->obj = (void *)object;
  1807.     owin->gadgets = gadgets;
  1808.     owin->title = title;
  1809.     owin->opened = 0;
  1810.     owin->iconified = 0;
  1811.  
  1812.     owin->canvas.g_x = 0; owin->canvas.g_y = 0;
  1813.     owin->canvas.g_w = 0; owin->canvas.g_h = 0;
  1814.  
  1815.     owin->frame.g_x = 0; owin->frame.g_y = 0;
  1816.     owin->frame.g_w = 0; owin->frame.g_h = 0;
  1817.  
  1818.     owin->oframe.g_x = 0; owin->oframe.g_y = 0;
  1819.     owin->oframe.g_w = 0; owin->oframe.g_h = 0;
  1820.  
  1821.     owin->mframe.g_x = 0; owin->mframe.g_y = 0;
  1822.     owin->mframe.g_w = 0; owin->mframe.g_h = 0;
  1823.  
  1824.     owin->redraw = objw_redraw;
  1825.     owin->move   = objw_move;
  1826.     owin->size   = NULL;
  1827.     owin->arrow  = NULL;
  1828.     owin->hslide = NULL;
  1829.     owin->vslide = NULL;
  1830. }
  1831.  
  1832. /* WinAlloc allocates memory for a new window. */
  1833.  
  1834. WINDOW *
  1835. WinAlloc(void)
  1836. {
  1837.     return (WINDOW *) gs_malloc((uint)sizeof(WINDOW), 1, "window");
  1838. }
  1839.  
  1840. /* Free the memory allocated for a window. */
  1841.  
  1842. int
  1843. WinFree(WINDOW *win)
  1844. {
  1845.     gs_free((char *)win, 1, sizeof(WINDOW), "window");
  1846. }
  1847.  
  1848. /* WinTextAlloc allocates memory for a window text structure. */
  1849.  
  1850. WINTEXT *
  1851. WinTextAlloc(int Lines)
  1852. {
  1853.     WINTEXT *text;
  1854.  
  1855.     /* Allocate the WINTEXT structure. */
  1856.  
  1857.     if ((text = (WINTEXT *) gs_malloc((uint)sizeof(WINTEXT), 1, "wintext")) == NULL) {
  1858.     return text;
  1859.     }
  1860.  
  1861.     /* Allocate the character buffer. */
  1862.  
  1863.     if ((text->buff = (char (*)[COLUMNS+1])gs_malloc((uint)(COLUMNS+1), Lines, "charbuff")) == NULL) {
  1864.     gs_free((char *)text, 1, sizeof(WINTEXT), "wintext");
  1865.     return (WINTEXT *)NULL;
  1866.     }
  1867.  
  1868.     text->bsize = Lines;
  1869.  
  1870.     return text;
  1871. }
  1872.  
  1873. char
  1874. (*TextBuffRealloc(WINTEXT *text, int NewSize))[COLUMNS+1]
  1875. {
  1876.     char (*temp)[COLUMNS+1];
  1877.  
  1878.     /* Allocate another character buffer of the new size. */
  1879.  
  1880.     if ((temp = (char (*)[COLUMNS+1])gs_malloc((uint)(COLUMNS+1), NewSize, "charbuff")) == NULL) {
  1881.     return temp;
  1882.     }
  1883.  
  1884.     if (text->buff != 0) {
  1885.  
  1886.     /* Copy the old buffer to the new one. */
  1887.     memcpy(temp, text->buff, (MIN(text->bsize, NewSize))*(COLUMNS+1));
  1888.  
  1889.     /* Free the old character buffer. */
  1890.     gs_free((char *)text->buff, text->bsize, (COLUMNS+1), "charbuff");
  1891.  
  1892.     }
  1893.  
  1894.     text->bsize = NewSize;
  1895.     text->buff = temp;
  1896.     return temp;
  1897. }
  1898.  
  1899. /* Free the memory allocated for a window text structure. */
  1900.  
  1901. int
  1902. WinTextFree(WINTEXT *text)
  1903. {
  1904.     gs_free((char *)text->buff, text->bsize, (COLUMNS+1), "charbuff");
  1905.     gs_free((char *)text, 1, sizeof(WINTEXT), "wintext");
  1906. }
  1907.  
  1908. /* GraphicAlloc allocates memory for a graphic structure. */
  1909.  
  1910. GRAPHIC *
  1911. GraphicAlloc(void)
  1912. {
  1913.     return (GRAPHIC *) gs_malloc((uint)sizeof(GRAPHIC), 1, "graphic");
  1914. }
  1915.  
  1916. /* Free the memory allocated for a graphic structure. */
  1917.  
  1918. int
  1919. GraphicFree(GRAPHIC *gr)
  1920. {
  1921.     gs_free((char *)gr, 1, sizeof(GRAPHIC), "graphic");
  1922. }
  1923.  
  1924. /* Free the memory allocated for a bitmap buffer. */
  1925.  
  1926. int
  1927. BitBufferFree(GRAPHIC *gr)
  1928. {
  1929.     char *buff = (char *)gr->image.fd_addr;
  1930.     ulong buff_size = gr->image.fd_w * gr->image.fd_h;
  1931.  
  1932.     gs_free((char *)buff, buff_size, 1, "bitbuffer");
  1933. }
  1934.  
  1935. /* ListAlloc allocates memory for a new element of the window list. */
  1936.  
  1937. WINLIST *
  1938. WinListAlloc(void)
  1939. {
  1940.     return (WINLIST *) gs_malloc((uint)sizeof(WINLIST), 1, "winlist");
  1941. }
  1942.  
  1943. /* Free the memory for the winlist structure */
  1944.  
  1945. int
  1946. WinListFree(WINLIST *wl)
  1947. {
  1948.     gs_free((char *)wl, 1, sizeof(WINLIST), "winlist");
  1949. }
  1950.  
  1951. /* WinListAdd adds a new window to the window list. */
  1952.  
  1953. WINLIST *
  1954. WinListAdd(WINLIST *wlist, WINDOW *win)
  1955. {
  1956.     WINLIST *wl = WinListAlloc();
  1957.  
  1958.     if (win->opened || win->iconified) return wlist;
  1959.  
  1960.     if (wlist == NULL) {    /* Begin a new list. */
  1961.  
  1962.     wl->Prev = wl;
  1963.     wl->Next = wl;
  1964.  
  1965.     }
  1966.     else {            /* Add a new list element. */
  1967.  
  1968.     wl->Prev = wlist->Prev;
  1969.     wl->Next = wlist;
  1970.  
  1971.     wlist->Prev->Next = wl;
  1972.     wlist->Prev = wl;
  1973.  
  1974.     }
  1975.  
  1976.     wl->Win = win;        /* Put the window in the list. */
  1977.     return wl;
  1978. }
  1979.  
  1980.  
  1981. /* Delete a window from the window list and free its associated memory. */
  1982.  
  1983. WINLIST *
  1984. WinListDelete(WINLIST *wlist, WINDOW *win)
  1985. {
  1986.     WINLIST *ret, *wl = wlist;
  1987.  
  1988.     /*
  1989.      * Return the new head of the window list. If the head was not
  1990.      * deleted, it remains the head. If the head is deleted, make
  1991.      * the next list element the head. If deleting the head leaves
  1992.      * the list empty, then return NULL.
  1993.      */
  1994.  
  1995.     ret = (win == wlist->Win) ?
  1996.     ((wlist->Next == wlist) ? NULL : wlist->Next) : wlist;
  1997.  
  1998.     /* Delete the specified list element. */
  1999.  
  2000.     do {
  2001.     if (win == wl->Win) {
  2002.         wl->Prev->Next = wl->Next;
  2003.         wl->Next->Prev = wl->Prev;
  2004.         break;
  2005.     }
  2006.     wl = wl->Next;
  2007.     }
  2008.     while (wl != wlist);
  2009.  
  2010.     /* Free the memory for the window structure. */
  2011.     if ((win->type == TEXT) && (win != &conswin)) {
  2012.     WinTextFree(win->obj);
  2013.     WinFree(win);
  2014.     }
  2015.     else if ((win->type == BIT) && (win != &imagwin)) {
  2016.     GRAPHIC *gr = win->obj;
  2017.         BitBufferFree(gr);
  2018.     GraphicFree(gr);
  2019.     WinFree(win);
  2020.     }
  2021.  
  2022.     /* Free the memory used for the window list. */
  2023.     WinListFree(wl);
  2024.  
  2025.     return ret;
  2026. }
  2027.  
  2028. /* Open all the windows in the window list, leaving the list intact. */
  2029.  
  2030. int
  2031. WinListOpen(WINLIST *wlist)
  2032. {
  2033.     WINLIST *wl = wlist;
  2034.  
  2035.     do {
  2036.     if (wl->Win->iconified) {
  2037.         wind_open(wl->Win->handle,
  2038.         wl->Win->frame.g_x, wl->Win->frame.g_y,
  2039.         wl->Win->frame.g_w, wl->Win->frame.g_h);
  2040.  
  2041.         wl->Win->opened = 1;
  2042.         wl->Win->iconified = 0;
  2043.  
  2044.         if (wl->Win->type == OBJ) {
  2045.         OBJECT *obj = wl->Win->obj;
  2046.         obj[0].ob_flags ^= HIDETREE;
  2047.         }
  2048.     }
  2049.  
  2050.     wl = wl->Next;
  2051.     }
  2052.     while (wl != wlist);
  2053. }
  2054.  
  2055. /* Close all the windows in the window list, leaving the list intact. */
  2056.  
  2057. int
  2058. WinListClose(WINLIST *wlist)
  2059. {
  2060.     WINLIST *wl = wlist;
  2061.  
  2062.     do {
  2063.     if (wl->Win->opened) {
  2064.  
  2065.         wind_get(wl->Win->handle, WF_CURRXYWH,
  2066.         &wl->Win->oframe.g_x, &wl->Win->oframe.g_y,
  2067.         &wl->Win->oframe.g_w, &wl->Win->oframe.g_h);
  2068.  
  2069.         wind_get(wl->Win->handle, WF_CURRXYWH,
  2070.         &wl->Win->frame.g_x, &wl->Win->frame.g_y,
  2071.         &wl->Win->frame.g_w, &wl->Win->frame.g_h);
  2072.  
  2073.         wind_close(wl->Win->handle);
  2074.         wl->Win->opened = 0;
  2075.         wl->Win->iconified = 1;
  2076.  
  2077.         if (wl->Win->type == OBJ) {
  2078.         OBJECT *obj = wl->Win->obj;
  2079.         obj[0].ob_flags ^= HIDETREE;
  2080.         }
  2081.  
  2082.     }
  2083.  
  2084.     wl = wl->Next;
  2085.     }
  2086.     while (wl != wlist);
  2087. }
  2088.  
  2089. /* Redraw all windows in the list. */
  2090.  
  2091. int
  2092. WinListRedraw(WINLIST *wlist, PSTATE *st)
  2093. {
  2094.     WINLIST *wl = wlist;
  2095.  
  2096.     do {
  2097.     if (wl->Win->opened) {
  2098.         st->Event->Message[3] = wl->Win->handle;
  2099.         HandleRedraw(FULL_WIN, st);
  2100.     }
  2101.  
  2102.     wl = wl->Next;
  2103.     }
  2104.     while (wl != wlist);
  2105. }
  2106.  
  2107. /*
  2108.  * Pathfind(path, file, sep) searches for 'file' in the path given
  2109.  * by the envionment variable named in 'env'. Sep specifies the
  2110.  * path separator. It returns a pointer to the filename if it is
  2111.  * found, and a NULL if not.
  2112.  */
  2113.  
  2114. char *
  2115. PathFind(char *env, char *file, char *sep)
  2116. {
  2117.     FILE *fp;
  2118.  
  2119.     char path[2*MAXLEN];
  2120.     static char name[MAXLEN];
  2121.  
  2122.     char *ptr;
  2123.     char *presub();
  2124.  
  2125.     if ((fp = fopen(file, "r")) == NULL) {
  2126.  
  2127.     if ((ptr = getenv(env)) != NULL) {
  2128.         strcpy(path, ptr);
  2129.     }
  2130.     else {
  2131.         return NULL;
  2132.     }
  2133.  
  2134.     if ((ptr = presub(path, sep)) == NULL) {
  2135.         return NULL;
  2136.     }
  2137.  
  2138.     do {
  2139.         strcpy(name, ptr);
  2140.  
  2141.         if (name[strlen(name)-1] != '\\' ||
  2142.         name[strlen(name)-1] != '/') strcat(name, "\\");
  2143.  
  2144.         strcat(name, file);
  2145.  
  2146.         if ((fp = fopen(name, "r")) != NULL) {
  2147.         fclose(fp);
  2148.         return name;
  2149.         }
  2150.  
  2151.     } while ((ptr = presub(NULL, sep)) != NULL);
  2152.  
  2153.     }
  2154.     else {
  2155.     fclose(fp);
  2156.     return file;
  2157.     }
  2158. }
  2159.  
  2160. /* Presub(s, subs) searches the string s for the substring subs. Presub
  2161.  * returns a pointer to the NULL terminated substring which immediately
  2162.  * preceeds subs. If presub is called again with a NULL pointer for s, 
  2163.  * it returns a pointer to the substring between the previous subs and
  2164.  * the current subs. If subs is a null character, presub returns a pointer
  2165.  * to the portion of s between the previous subs and the end of s.
  2166.  */
  2167.  
  2168. char *presub(s, subs)
  2169. char *s, *subs;
  2170. {
  2171.     int sublen;
  2172.     char *mptr;
  2173.     static int count;
  2174.     static char match[MAXLEN], *ptr;
  2175.  
  2176.     if (s != NULL) {
  2177.         ptr = s;
  2178.         count = 0;
  2179.     }
  2180.  
  2181.     mptr = match + count;
  2182.     if ((sublen = strlen(subs)) == 0) {
  2183.         strcpy(mptr, ptr);
  2184.         return (mptr);
  2185.     }
  2186.  
  2187.     while (*ptr != '\0') {
  2188.         if (strncmp(ptr, subs, sublen) == 0) {
  2189.             match[count] = '\0';
  2190.             ptr += sublen;
  2191.             ++count;
  2192.             return (mptr);
  2193.         }
  2194.         match[count] = *ptr;
  2195.         ++ptr;
  2196.         ++count;
  2197.         
  2198.     }
  2199.  
  2200.     if ((match + count) > mptr) {
  2201.         match[count] = *ptr;
  2202.         ++count;
  2203.         return (mptr);
  2204.  
  2205.     }
  2206.  
  2207.     return (NULL);
  2208.  
  2209. }
  2210.  
  2211. /* Ensure that the size of a window is within the limits of
  2212.  * the hardware.
  2213.  */
  2214.  
  2215. int EnforceLimits(GRECT *rect, VWRK *vw)
  2216. {
  2217.  
  2218.     if ((rect->g_x < vw->full.g_x) || (rect->g_x >= vw->full.g_w)) {
  2219.     rect->g_x = vw->full.g_x;
  2220.     }
  2221.  
  2222.     if ((rect->g_y < vw->full.g_y) || (rect->g_y >= vw->full.g_h)) {
  2223.     rect->g_y = vw->full.g_y;
  2224.     }
  2225.  
  2226.     if (rect->g_w < 0) {
  2227.     rect->g_w = vw->full.g_w - rect->g_x;
  2228.     }
  2229.  
  2230.     if (rect->g_h < 0) {
  2231.     rect->g_h = vw->full.g_h - rect->g_y + vw->full.g_y;
  2232.     }
  2233. }
  2234.  
  2235.  
  2236.  
  2237. /* Routine itoa(num, s) converts an integer, num, to an ascii string 
  2238.  * representation of the integer, pointed to by s. The integer 100 is 
  2239.  *  converted to the string "100", etc.
  2240.  */
  2241.  
  2242. char *itoa(int number, char *s)
  2243. {
  2244.  
  2245. /* Local variables:
  2246.  *    i:        loop counter,
  2247.  *    j:        number of loops needed to transpose the string in s,
  2248.  *    body:        integer part of num/10,
  2249.  *    remain:        remainder of num/10,
  2250.  *    sign:        sign of the integer,
  2251.  *    count:        number of times num is divisible by 10,
  2252.  *    temp:        temporary character storage.
  2253.  */
  2254.  
  2255.     int i, j, num, body, remain, sign, count;
  2256.     char temp;
  2257.  
  2258.     count = 0;
  2259.     num = number;
  2260.     sign = 1;
  2261.  
  2262.     if (num == 0) {
  2263.         s[count] = '0';
  2264.         ++count;
  2265.     } else {
  2266.  
  2267.         if (num < 0) {
  2268.             sign = -1;
  2269.             num = -num;
  2270.         }
  2271.  
  2272.         while (num > 0) {        /* Divide by 10, convert */
  2273.             body = (num/10);    /* remainder to ascii    */
  2274.             remain = num - body*10;
  2275.             s[count] = remain + '0';
  2276.             num = body;
  2277.             ++count;
  2278.         }
  2279.  
  2280.         if (sign < 0) {
  2281.             s[count] = '-';
  2282.             ++count;
  2283.         }
  2284.  
  2285.         /* Ascii representation is transposed in s, so put it in 
  2286.          * the right order. */
  2287.  
  2288.         j = count/2;    
  2289.  
  2290.         for (i = 0; i < j; ++i) {
  2291.             temp = s[i];
  2292.             s[i] = s[count-(i+1)];
  2293.             s[count-(i+1)] = temp;
  2294.         }
  2295.  
  2296.     }
  2297.  
  2298.     s[count] = '\0';
  2299.     return(s);
  2300.  
  2301. }
  2302.  
  2303. /* Round to nearest integer. */
  2304.  
  2305. int
  2306. nint(double Num)
  2307. {
  2308.  
  2309.     int Floor = floor(Num);
  2310.     int Ceil  = ceil(Num);
  2311.  
  2312.     return (fabs(Num - Floor) > fabs(Num - Ceil)) ? Ceil : Floor;
  2313.  
  2314. }
  2315.  
  2316. int align(int x)
  2317. {
  2318.     return ((x & 0xfffffff0) + ((x & 0xf) ? 0x10 : 0));
  2319. /*    return ((x & 0xfffffff8) + ((x & 0x07) ? 0x08 : 0)); */
  2320. }
  2321.  
  2322.  
  2323. /*
  2324.  * The remainder of this file contains printer output routines, most of
  2325.  * which were contributed by Chris Strunk (some of them were written by me).
  2326.  * I made some modifications to the following code (with permission), and
  2327.  * may have introduced errors not in the original code.
  2328.  * Tim Gallivan, 3/92.
  2329.  */
  2330.  
  2331. /*
  2332.  * This file is Copyright (C) 1990 Christoph Strunk.
  2333.  *
  2334.  * You are not allowed to copy or modify it.
  2335.  */
  2336.  
  2337. #define ATARI_TOS    (1)
  2338. #define MAKE_VOID    (void *)
  2339.  
  2340. void con_flush();
  2341. int OutputIsAscii = 0, RTX_Found = 0;
  2342. long *old_ssp = NULL;
  2343. FILE *OutFile = NULL;
  2344.  
  2345. #if PC_DOS || ATARI_TOS
  2346. #  define DIRECT    1    /* 1 = Direct Centronics port programming */
  2347. #endif
  2348.  
  2349. #if ATARI_TOS || ( PC_DOS && DIRECT )
  2350. static short prn_out ( int );
  2351. #endif
  2352.  
  2353. #if ATARI_TOS && LATTICE
  2354. #include <dos.h>
  2355. #endif
  2356.  
  2357. #ifdef __GNUC__
  2358. #include <osbind.h>
  2359. #endif
  2360.  
  2361. #if PC_DOS && DIRECT
  2362. #include <bios.h>
  2363. #endif
  2364.  
  2365. /* output one character */
  2366.  
  2367. static int fatal_output_error = 0;
  2368.  
  2369. void
  2370. lputc(c)
  2371. int c;
  2372. {
  2373.     static short rc;
  2374.     static unsigned char global_count = 0; /* other processes every 256 chars */
  2375.     void l_stop(), fatal();
  2376.  
  2377.     if ( fatal_output_error ) return;
  2378.  
  2379.     global_count += 1;
  2380.  
  2381.     c &= 255;            /* New in 2.9.44: avoid signed char problems */
  2382.  
  2383. #if ATARI_TOS || PC_DOS
  2384.     if ( ( c == '\n' ) && OutputIsAscii ) {
  2385.       lputc ( '\r' );    /* recursion */
  2386.     }
  2387. #endif
  2388.  
  2389.     if ( OutFile ) {
  2390.        rc = ( fputc ( c, OutFile ) == EOF );
  2391.     } else {
  2392. #if ATARI_TOS || ( PC_DOS && DIRECT )
  2393.                    rc = prn_out ( c );
  2394. #else
  2395.                    rc = -1;
  2396. #endif
  2397.     }
  2398.  
  2399.     if ( rc ) {
  2400.         if ( OutFile ) {
  2401.             perror ( "\nlputc" );
  2402.             fprintf ( stderr, "\nOutput error -- %s ?\n",
  2403.                       "Disk full or printer not ready" );
  2404.             fclose ( OutFile );
  2405.             OutFile = NULL;
  2406.         } else {
  2407.             fprintf ( stderr, "\nOutput error -- Printer not ready ?\n" );
  2408.         }
  2409.         l_stop();
  2410.         fatal_output_error = 1;
  2411.         fatal ( "Output error" );
  2412.     }
  2413.  
  2414. #if ATARI_TOS
  2415.     if ( RTX_Found && ! global_count ) call_yield(); /* allow other processes */
  2416. #endif
  2417. }
  2418.  
  2419. /* output a string */
  2420.  
  2421. void
  2422. lputs ( s )
  2423. char *s;
  2424. {
  2425.     while ( *s ) lputc ( *s++ );
  2426. }
  2427.  
  2428. void
  2429. lflush()
  2430. {
  2431.    if ( OutFile ) fflush ( OutFile );
  2432. }
  2433.  
  2434. /* start/stop lputc device */
  2435.  
  2436. void
  2437. l_start()
  2438. {
  2439.   void l_stop(), fatal();
  2440.  
  2441. #if ATARI_TOS && DIRECT
  2442.   volatile char *gpip = (char *) 0xFFFFFA01L;
  2443.   int cnt;
  2444.  
  2445.   if ( OutFile == NULL && old_ssp == NULL ) {
  2446.     old_ssp = (void *) call_super ( NULL );
  2447.     cnt = 0;
  2448. /*    for ( cnt=0; ( *gpip & 1 ) && ( ++cnt <= 10 ); ) {
  2449.      printf("cnt = %d\n", cnt); */
  2450.      Ongibit(0x20);                                        /* set strobe bit */
  2451. /*    } */
  2452.     if ( cnt > 10 ) {
  2453.       l_stop();
  2454.       puts ( "\n" );
  2455.       fatal_output_error = 1;
  2456.       fatal ( "Printer not ready" );
  2457.     }
  2458.   }
  2459. #endif
  2460. #if ATARI_TOS && ! DIRECT
  2461.   int cnt;
  2462.  
  2463.   if ( OutFile == NULL && old_ssp == NULL ) {
  2464.     old_ssp = (void *) call_super ( NULL );
  2465.  
  2466.     for ( cnt=0; ( ! prt_ready(0) ) && ( ++cnt <= 10 ); ) {
  2467.      Ongibit(0x20);                                        /* set strobe bit */
  2468.     }
  2469.     if ( cnt > 10 ) {
  2470.       l_stop();
  2471.       puts ( "\n" );
  2472.       fatal_output_error = 1;
  2473.       fatal ( "Printer not ready" );
  2474.     }
  2475.   }
  2476. #endif
  2477. #if PC_DOS && DIRECT
  2478.   if ( OutFile == NULL && ( biosprint ( 2, 0, BiosChannel ) & 0x29 ) ) {
  2479.     l_stop();
  2480.     puts ( "\n" );
  2481.     fatal_output_error = 1;
  2482.     fatal ( "Printer not ready" );
  2483.   }
  2484. #endif
  2485. }
  2486.  
  2487. void l_stop()
  2488. {
  2489.     lflush();
  2490. #if ATARI_TOS
  2491.     if ( old_ssp != NULL ) {
  2492.         MAKE_VOID call_super ( old_ssp );
  2493.         old_ssp = NULL;
  2494.     }
  2495. #endif
  2496. }
  2497.  
  2498. #if ATARI_TOS && DIRECT
  2499.  
  2500. extern void int_off __PROTO( ( void ) );
  2501.  
  2502. /* int_off:  ori.w  #$0700,sr
  2503.  *           ret
  2504.  */
  2505.  
  2506. extern void int_on __PROTO( ( void ) );
  2507.  
  2508. /* int_on:   andi.w #$F8FF,sr
  2509.  *           ret
  2510.  */
  2511.  
  2512. static short prn_out ( c )
  2513. int c;
  2514. {
  2515.   volatile unsigned long *hz_200;
  2516.   register unsigned long end_time;
  2517.   volatile char *gpip = (char *) 0xFFFFFA01L;
  2518.   register char g;
  2519.  
  2520. #if OLD
  2521.   unsigned char loop_count = 0;
  2522. #endif
  2523.  
  2524.   if ( old_ssp == NULL ) l_start();
  2525.  
  2526.   hz_200 = (unsigned long *) 0x04BAL;
  2527. #if OLD
  2528.   end_time = *hz_200 + 200;        /* check once per second */
  2529. #else
  2530.   end_time = *hz_200 + 2;          /* check 100 times per second */
  2531. #endif
  2532.  
  2533.   while ( *gpip & 1 ) {  /* wait */
  2534. #if OLD
  2535.     /* Printer 1 sec. or more not ready ? */
  2536.     if ( ( end_time < *hz_200 ) ||
  2537.          ( ( ( ++loop_count & 7 ) == 0 ) && ( BatchMode || RTX_Found ) ) ) {
  2538.         con_flush();         /* allow Control_C, other Processes etc. */
  2539.         end_time = *hz_200 + 2;          /* check 100 times per second */
  2540.     }
  2541. #else
  2542.     if ( end_time <= *hz_200 ) {
  2543.         con_flush();               /* allow Control_C, other Processes etc. */
  2544.         end_time = *hz_200 + 1;              /* check 200 times per second */
  2545.     }
  2546. #endif
  2547.   }
  2548.  
  2549.   int_off();                   /* disable interrupts */
  2550.  
  2551.   gpip = (char *) 0xFFFF8800L; /* load sound chip adress now */
  2552.  
  2553.   /* This next section of code was added by Tim Gallivan on 7/11/94
  2554.    * to fix a problem of this routine not working on some hardware.
  2555.    */
  2556.  
  2557.   *gpip = 7;               /* select enable register */
  2558.   g = *gpip;                   /* get old value */
  2559.   g |= 0x80;                   /* set port B output bit */
  2560.   gpip[2] = g;
  2561.  
  2562.   /* End fix. */
  2563.  
  2564.   *gpip = 15;                  /* select port B */
  2565.   gpip[2] = (char) c;          /* write out char */
  2566.   *gpip = 14;                  /* select port A */
  2567.   g = *gpip;                   /* get old value */
  2568. #if OLD
  2569.   g &= 0xDF;                   /* clear strobe bit */
  2570. #else
  2571.   g &= ~0x20;                  /* clear strobe bit */
  2572. #endif
  2573.   gpip[2] = g;
  2574.   g |= 0x20;                   /* set strobe bit */
  2575.   g |= 0x20;                   /* short delay */
  2576.   gpip[2] = g;
  2577.  
  2578.   int_on();                    /* enable interrupts */
  2579.  
  2580.   return 0;
  2581. }
  2582. #endif
  2583.  
  2584. #if ATARI_TOS && ! DIRECT
  2585. static short prn_out ( c )
  2586. int c;
  2587. {
  2588.   volatile unsigned long *hz_200 = (unsigned long *) 0x04BAL;
  2589.   register unsigned long end_time;
  2590.  
  2591.   if ( old_ssp == NULL ) l_start();
  2592.  
  2593.   end_time = *hz_200 + 2;          /* check 200 times per second */
  2594.  
  2595.   while ( ! prt_ready(0) ) {  /* wait */
  2596.     if ( end_time <= *hz_200 ) {
  2597.         con_flush();               /* allow Control_C, other Processes etc. */
  2598.         end_time = *hz_200 + 1;              /* check 200 times per second */
  2599.     }
  2600.   }
  2601.  
  2602.   prt_out ( 0, c );
  2603.  
  2604.   return 0;
  2605. }
  2606. #endif
  2607.  
  2608. #if PC_DOS && DIRECT
  2609.  
  2610. static short prn_out ( c )
  2611. int c;
  2612. {
  2613.   while ( biosprint ( 0, c, BiosChannel ) & 0x29 ) {
  2614.     /* wait until Ok or Control-C pressed */
  2615.     con_flush();
  2616.   }
  2617.  
  2618.   return 0;
  2619. }
  2620.  
  2621. #endif
  2622.  
  2623. void
  2624. con_flush()
  2625. {
  2626.     int chin;
  2627.     void fatal();
  2628.  
  2629.     chin = Crawio(0xFF);
  2630.     if ((chin & 0xFF) == 3) fatal("Keyboard Interrupt");
  2631. }
  2632.  
  2633. void
  2634. fatal(char *message)
  2635. {
  2636.     fprintf(stderr, "%s\n", message);
  2637.     l_stop();
  2638.     exit(-1);
  2639. }
  2640.  
  2641. /* Restore the usual desktop background. */
  2642.  
  2643. #undef puts
  2644.  
  2645. int RestoreBG(VWRK *vw)
  2646. {
  2647.     puts("\033f");
  2648.     v_hide_c(vw->VdiHandle);
  2649.     form_dial(FMD_FINISH, 0, 0, 8, 16, 0, 0, vw->XRes, vw->YRes);
  2650.     v_show_c(vw->VdiHandle, 0);
  2651. }
  2652.  
  2653. /*
  2654. #-----------------------------------------------------------------------------#
  2655. #:    Simple support routines for LATTICE C 5.04.01 and other C compilers
  2656. #
  2657. #:    Lattice C Assembler
  2658. #
  2659. #:    The parameter comes on the stack for functions starting with '_'.
  2660. #
  2661. #:    void *call_super ( void * );  supervisor mode on/off
  2662. #
  2663. #:    Original code by Chris Strunk. Modified for use with gcc in
  2664. #:    Ghostscript by Tim Gallivan, 3/92.
  2665. #-----------------------------------------------------------------------------#
  2666. */
  2667.     asm("\
  2668.  
  2669.     .text 0
  2670.  
  2671.     .globl _int_off
  2672.     .globl _int_on
  2673.     .globl _call_super
  2674.     .globl _call_yield
  2675.     .globl _call_nice
  2676.     .globl _user_trace
  2677.     .globl _prt_ready
  2678.     .globl _prt_out
  2679.  
  2680. _get_la:
  2681.     moveml   d2/a2,sp@- 
  2682.     .byte    0xA0,0x00            | Adresse Line-A-Var nach A0 & D0
  2683.     moveml   sp@+,d2/a2
  2684.     rts
  2685.  
  2686. _int_off:
  2687.     oriw     #0x0700,sr
  2688.     rts
  2689.  
  2690. _int_on:
  2691.     andiw    #0xF8FF,sr
  2692.     rts
  2693.  
  2694. _call_super:
  2695.     movel    a7@(4),a0
  2696.     moveml   d2/a2-a3,sp@-
  2697.     movel    a0,sp@-
  2698.     movew    #0x20,sp@-
  2699.     movel    a7,a3     | save current stack pointer
  2700.     trap      #1
  2701.     movel    a3,a7     | make bad stack pointer good again !!!!!!!
  2702.     addql    #6,sp
  2703.     movel    d0,a0     | return value in both: d0 and a0
  2704.     moveml   sp@+,d2/a2-a3
  2705.     rts
  2706.  
  2707. _call_yield:
  2708.     moveml   d2/a2,sp@-
  2709.     movew    #0x00ff,sp@-   | MiNT Syield()  --  TOS illegal (rc -32)
  2710.     trap      #1
  2711.     addql    #2,sp
  2712.     moveml   sp@+,d2/a2
  2713.     rts
  2714.  
  2715. _call_nice:
  2716.     movel    a7@(4),d0
  2717.     moveml   d2/a2,sp@-
  2718.     movew    d0,sp@-
  2719.     movew    #0x10A,sp@-
  2720.     trap      #1
  2721.     addql    #4,sp
  2722.     moveml   sp@+,d2/a2
  2723.     rts
  2724.  
  2725. _user_trace:
  2726.     moveml   d1-d7/a0-a6,sp@-
  2727.     moveql   #0,d0
  2728.     movel    0x3F0,a1     | TEMPLMON user trace vector
  2729.     cmpal    #0,a1       | not installed ?
  2730.     beqs     end_trace
  2731.     jsr      a1@        | execute it !
  2732.     extl     d0
  2733.  
  2734. end_trace:
  2735.     moveml   sp@+,d1-d7/a0-a6
  2736.     rts
  2737.  
  2738. _prt_ready:
  2739.     moveml    d3/a3/a5,a7@-
  2740.     subl    a5,a5
  2741.     movew    d0,a7@-
  2742.     movel    0x506,a0
  2743.     jsr    a0@
  2744.     addql    #2,a7
  2745.     moveml    a7@+,d3/a3/a5
  2746.     rts
  2747.  
  2748. _prt_out:
  2749.     moveml    d3/a3/a5,a7@-
  2750.     subl    a5,a5
  2751.     movew    d1,a7@-
  2752.     movew    d0,a7@-
  2753.     movel    0x50A,a0
  2754.     jsr    a0@
  2755.     addql    #4,a7
  2756.     moveml    a7@+,d3/a3/a5
  2757.     rts
  2758.  
  2759.     ");
  2760.  
  2761.