home *** CD-ROM | disk | FTP | other *** search
/ The Datafile PD-CD 3 / PDCD_3.iso / languages / scheme / xscheme028 / c / awimpstuf next >
Encoding:
Text File  |  1992-04-27  |  32.4 KB  |  1,326 lines

  1. /* Arcstuff.c
  2.  * Archimedes RISC OS specific frontend routines for Xscheme.
  3.  */
  4.  
  5. #include <stdio.h>
  6. #include <stdlib.h>
  7. #include <math.h>
  8. #include <string.h>
  9. #include <ctype.h>
  10. #include <signal.h>
  11. #include <time.h>
  12. #include "kernel.h"
  13. #include "os.h"
  14. #include "bbc.h"
  15.  
  16. #include "xscheme.h"
  17.  
  18. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  19. +*++++++++++++++++++++++ WIMP interfacing code ++++++++++++++++++++++++++++
  20. +*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
  21.  
  22. #include "wimp.h"
  23. #include "wimpt.h"
  24. #include "win.h"
  25. #include "event.h"
  26. #include "res.h"
  27. #include "werr.h"
  28. #include "template.h"
  29. #include "dbox.h"
  30.  
  31.  
  32. /* structure to hold screen size and log.-to-phys.-coord. translation info */
  33. typedef struct _svar {
  34.         int xeigh;      /* translation factors */
  35.         int yeigh;
  36.         int xphys;      /* physical resolution */
  37.         int yphys;
  38.         int xppc;       /* pixels per char */
  39.         int yppc;
  40.         } screenvar;
  41.  
  42. /* structure for times emulation */
  43. struct tms {
  44.         time_t tms_utime;
  45.         time_t tms_stime;
  46.         time_t tms_cutime;
  47.         time_t tms_cstime;
  48.         };
  49.  
  50. /* menu entries */
  51. #define XF_INFO 1
  52. #define XF_QUIT 2
  53.  
  54. /* icons in dialog box for the info fields */
  55. #define XF_XL_INFO      5
  56. #define XF_XF_INFO      6
  57.  
  58. /* misc defines */
  59. #define ReadModeVar     53
  60. #define ReadVDUvar      49
  61. #define XEIGH           4
  62. #define YEIGH           5
  63. #define XSIZE           11
  64. #define YSIZE           12
  65. #define CARET           40              /* 40 OS_units heigth */
  66. #define HZ              100
  67. #define PATHBUF         256
  68. #define WSTDMASK        wimp_EMPTRENTER | wimp_EMPTRLEAVE
  69. #define WKEYMASK        WSTDMASK | wimp_EMNULL
  70.  
  71. #define max(a,b) (a>b?a:b)
  72. #define min(a,b) (a<b?a:b)
  73.  
  74. /*** global variables: ***/
  75.  
  76. static wimp_t   task_handle;
  77. static wimp_w   xf_main_wind;
  78. static menu     xf_menu;
  79. static int      colors;
  80. static BOOL     initing;
  81. static struct tms systime;
  82. static time_t   sys_timeslp;
  83.  
  84. /* filepaths */
  85. char *loadpath = NULL;
  86. char *curdir = NULL;
  87.  
  88. /* redraw info */
  89. static int      xf_needs_redraw = FALSE;
  90. static int      r_xmin = 32768;
  91. static int      r_xmax = 0;
  92. static int      r_ymin = 32768;
  93. static int      r_ymax = 0;
  94.  
  95. /* phys. mode info */
  96. static int      max_x_size;
  97. static int      max_y_size;
  98. static char*    screen;
  99. static int      xf_cursor_x;
  100. static int      xf_cursor_y;
  101. static int      char_x_size;
  102. static int      char_y_size;
  103.  
  104. /* ringbuffer for keyboard input */
  105. static struct keybuf {
  106.         int first;
  107.         int last;
  108.         int count;
  109.         int chars[BUFSIZ];
  110.         } keybuffer;
  111.  
  112. /* Wimp version number we know about *100 */
  113. static int wimp_version = 200;
  114.  
  115. /* pump up the initial stack */
  116. int __root_stack_size = 32 * 1024;
  117.  
  118. /* the info fields */
  119. static char *xl_version = "XScheme  0.28 (23 Jul 1991)";
  120. static char *xf_version = "Frontend 0.11 (27 Apr 1992)";
  121.  
  122. /* and some forward declarations */
  123. int xf_w_open_window (wimp_openstr *);
  124. void xf_clear_screen(void);
  125.  
  126. /*** general routines ***/
  127.  
  128. /* convert a string to lower case */
  129. char *stolower(char *bla)
  130. {
  131.         char *bli, *blu;
  132.         int i;
  133.  
  134.         if (strlen(bla) == 0)
  135.                 return bla;
  136.  
  137.         bli = malloc(strlen(bla));
  138.         blu = bli;
  139.  
  140.         for(i = 0; i <= strlen(bla); i++)
  141.                 bli[i] = tolower(bla[i]);
  142.  
  143.         return blu;
  144. }
  145.  
  146. /* duplicate a string */
  147. char *strdup(char *from)
  148. {
  149.         char *to;
  150.  
  151.         to = malloc(strlen(from));
  152.         return(strcpy(to, from));
  153. }
  154.  
  155. /* get time from 100Hz clock */
  156. long get_time(void)
  157. {
  158.         char timbuf[5];
  159.  
  160.         _kernel_osword(1, (int *)&timbuf);
  161.  
  162.         /* return only low 4 bytes of time. */
  163.         return (long) (timbuf[0] + (timbuf[1]<<8) + (timbuf[2]<<16) + (timbuf[3]<<24));
  164. }
  165.  
  166. /* init keybuffer */
  167. void init_keybuffer(void)
  168. {
  169.         keybuffer.first = 0;
  170.         keybuffer.last = 0;
  171.         keybuffer.count = 0;
  172. }
  173.  
  174. /* push one keypress onto buffer, do nothing if buffer overflow */
  175. void pushkey(int key)
  176. {
  177.         if (keybuffer.count < BUFSIZ)
  178.         {
  179.                 keybuffer.chars[keybuffer.last] = key;
  180.                 keybuffer.last = (keybuffer.last + 1) % BUFSIZ;
  181.                 keybuffer.count++;
  182.         }
  183. }
  184.  
  185. /* pop a keypress from buffer, return -1 if empty */
  186. int popkey(void)
  187. {
  188.         int tmpkey;
  189.  
  190.         if (keybuffer.count > 0)
  191.         {
  192.                 tmpkey = keybuffer.chars[keybuffer.first];
  193.                 keybuffer.first = (keybuffer.first + 1) % BUFSIZ;
  194.                 keybuffer.count--;
  195.         }
  196.         else
  197.                 tmpkey = -1;
  198.         return tmpkey;
  199. }
  200.  
  201. /* handle a keypress, translate keycodes, handle escape key */
  202. void xf_handle_key(int chcode)
  203. {
  204.         switch (chcode)
  205.         {
  206.         case 27:
  207.                 raise(SIGINT);
  208.                 break;
  209.         default:
  210.                 pushkey(chcode);
  211.         }
  212. }
  213.  
  214. /* get physical screen size */
  215. screenvar *xf_get_screen_size(void)
  216. {
  217.         int *ssize;
  218.         int xp[3];
  219.  
  220.         ssize = (int *)malloc(sizeof(struct _svar));
  221.  
  222.         /* get translation info */
  223.         ssize[0] = bbc_modevar(-1, XEIGH);
  224.         ssize[1] = bbc_modevar(-1, YEIGH);
  225.         /* get max. x- and y-coordinates from OS */
  226.         ssize[2] = bbc_modevar(-1, XSIZE);
  227.         ssize[3] = bbc_modevar(-1, YSIZE);
  228.  
  229.         /* get x/y pix. per char */
  230.         xp[0] = 162;    /* x size of char */
  231.         xp[1] = 163;    /* y */
  232.         xp[2] = -1;     /* end of table */
  233.         bbc_vduvars (xp, xp);
  234.         ssize[4] = xp[0];
  235.         ssize[5] = xp[1];
  236.  
  237.         /* while we're at it: set char sizes */
  238.         char_x_size = ssize[4] << ssize[0];
  239.         char_y_size = ssize[5] << ssize[1];
  240.         return (screenvar *)ssize;
  241. }
  242.  
  243. /* adjust scrollbar positions if caret outside of vis. window area */
  244. void xf_adjust_posn(wimp_caretstr *pos)
  245. {
  246.         wimp_wstate wstate;
  247.         int vis_x_min, vis_x_max;
  248.         int vis_y_min, vis_y_max;
  249.         int xsize, ysize;
  250.         int dx, dy;
  251.         wimp_box wbox;
  252.  
  253.         dx = dy = -32768;
  254.  
  255.         wimp_get_wind_state(pos->w, &wstate);
  256.  
  257.         /* get visible Part of work area */
  258.         xsize = wstate.o.box.x1 - wstate.o.box.x0;
  259.         ysize = wstate.o.box.y1 - wstate.o.box.y0;
  260.         vis_x_min = wstate.o.x;
  261.         vis_y_max = wstate.o.y;
  262.         vis_x_max = wstate.o.x + xsize;
  263.         vis_y_min = wstate.o.y - ysize;
  264.  
  265.         /* get direction to scroll */
  266.         if (pos->x < vis_x_min)
  267.                 dx = max(0, pos->x - xsize / 2);
  268.         if (pos->x > vis_x_max - char_x_size)
  269.                 dx = min(max_x_size * char_x_size - xsize, pos->x - xsize / 2);
  270.         if (pos->y >= vis_y_max - CARET - 4)
  271.                 dy = min(0, pos->y + CARET);
  272.         if (pos->y < vis_y_min)
  273.                 dy = pos->y + ysize;
  274.  
  275.         /* scroll window thru vis. part in necessary */
  276.         if (dx > -32768 || dy > -32768)
  277.         {
  278.                 wbox.x0 = 0;
  279.                 wbox.y1 = 0;
  280.                 wbox.x1 = max_x_size * char_x_size;
  281.                 wbox.y0 = -max_y_size * char_y_size;
  282.  
  283.                 /* default values for unset d*'s */
  284.                 if (dx == -32768)
  285.                         dx = wstate.o.x;
  286.                 if (dy == -32768)
  287.                         dy = wstate.o.y;
  288.  
  289.                 wimp_blockcopy(wstate.o.w, &wbox, dx - wstate.o.x, - dy - wstate.o.y);
  290.  
  291.                 wstate.o.x = dx;
  292.                 wstate.o.y = dy;
  293.  
  294.                 wimp_open_wind(&wstate.o);
  295.         }
  296. }
  297.  
  298. /* set caret, low level */
  299. void xf_w_set_caret(BOOL force_vis)
  300. {
  301.         wimp_caretstr posn;
  302.  
  303.         if (wimp_get_caret_pos(&posn) == NULL)
  304.                 if (posn.w == xf_main_wind || initing)
  305.                 {
  306.                         posn.x = xf_cursor_x * char_x_size;
  307.                         posn.y = - xf_cursor_y * char_y_size - (CARET & 0xffff);
  308.                         posn.w = xf_main_wind;
  309.                         posn.i = -1;
  310.                         posn.height = CARET;
  311.  
  312.                         /* watch out for caret inside visible part of window */
  313.                         if (force_vis)
  314.                                 xf_adjust_posn(&posn);
  315.  
  316.                         wimp_set_caret_pos(&posn);
  317.                 }
  318. }
  319.  
  320. /* set caret, don't force visibility */
  321. void xf_set_caret(void)
  322. {
  323.         xf_w_set_caret(FALSE);
  324. }
  325.  
  326. /* set caret, make visible */
  327. void xf_find_caret(void)
  328. {
  329.         xf_w_set_caret(TRUE);
  330. }
  331.  
  332. /* task closedown */
  333. void xf_closedown(void)
  334. {
  335.         wimp_close_wind(xf_main_wind);
  336.         win_activedec();
  337.         wimp_taskclose(task_handle);
  338. }
  339.  
  340. /* program info */
  341. void xf_prog_info(void)
  342. {
  343.         dbox window;
  344.  
  345.         if ((window = dbox_new("ProgInfo")) != 0)
  346.         {
  347.                 /* insert version strings */
  348.                 dbox_setfield (window, XF_XL_INFO, xl_version);
  349.                 dbox_setfield (window, XF_XF_INFO, xf_version);
  350.  
  351.                 dbox_show(window);
  352.                 /* keep on screen as long as needed */
  353.                 dbox_fillin(window);
  354.                 /* then get rid of it */
  355.                 dbox_dispose(&window);
  356.         }
  357. }
  358.  
  359. /* event_process()-routine with caring for the actual runtime */
  360. void xf_event_process(void)
  361. {
  362.         systime.tms_utime += get_time() - sys_timeslp;
  363.         event_process();
  364.         sys_timeslp = get_time();
  365. }
  366. /*** virtual screen routines ***/
  367.  
  368. /* invalidate protions of the logical screen */
  369. void xf_invalidate_screen(int x0, int y0, int x1, int y1)
  370. {
  371.         /* adjust rectangle to be redrawn */
  372.         if (x0 < r_xmin)
  373.                 r_xmin = x0;
  374.         if (y0 < r_ymin)
  375.                 r_ymin = y0;
  376.         if (x1 > r_xmax)
  377.                 r_xmax = x1;
  378.         if (y1 > r_ymax)
  379.                 r_ymax = y1;
  380.  
  381.         xf_needs_redraw = TRUE;
  382. }
  383.  
  384. /* force redraw of altered portions (= window update) */
  385. void xf_force_redraw(void)
  386. {
  387.         wimp_redrawstr winr;
  388.         wimp_winfo winfo;
  389.  
  390.         if (xf_needs_redraw)
  391.         {
  392.                 wimp_get_wind_info(&winfo);
  393.  
  394.                 /* build rectangle to redraw */
  395.                 winr.w = xf_main_wind;
  396.                 winr.box.x0 = r_xmin * char_x_size;
  397.                 winr.box.x1 = (r_xmax + 1) * char_x_size;
  398.                 winr.box.y0 = - (r_ymax + 1) * char_y_size;
  399.                 winr.box.y1 = - r_ymin * char_y_size;
  400.  
  401.                 wimp_force_redraw(&winr);
  402.  
  403.                 /* reset redraw info */
  404.                 r_xmin = 32768;
  405.                 r_xmax = 0;
  406.                 r_ymax = 0;
  407.                 r_ymin = 32768;
  408.                 xf_needs_redraw = FALSE;
  409.         }
  410. }
  411.  
  412. /* posn. cursor, ignore invalid positions */
  413. void xf_gotoxy(int x, int y)
  414. {
  415.         if (x >= 0 && x < max_x_size && y >= 0 && y < max_y_size)
  416.         {
  417.                 xf_cursor_x = x;
  418.                 xf_cursor_y = y;
  419.         }
  420. }
  421.  
  422. /* scroll window */
  423. void xf_scroll(void)
  424. {
  425.         char *i, *j;
  426.         wimp_box wbox;
  427.  
  428.         /* scroll array up */
  429.         for (i = screen, j = screen + max_x_size; j < (screen + \
  430.                   max_x_size * max_y_size); *i = *j, i++, j++);
  431.  
  432.         /* clear last line */
  433.         for (; i < j; i++)
  434.                 *i = 0;
  435.  
  436.         /* scroll window contents */
  437.         wbox.x0 = 0;
  438.         wbox.x1 = max_x_size * char_x_size;
  439.         wbox.y1 = - char_y_size;
  440.         wbox.y0 = - max_y_size * char_y_size;
  441.  
  442.         wimp_blockcopy(xf_main_wind, &wbox, 0,-(max_y_size - 1) * char_y_size);
  443.         xf_invalidate_screen(0, max_y_size - 2, max_x_size, max_y_size - 1);
  444.         xf_force_redraw();
  445. }
  446.  
  447. /* cursor to next line */
  448. void xf_next_line(void)
  449. {
  450.         xf_cursor_y++;
  451.         if (xf_cursor_y == max_y_size)
  452.         {
  453.                 xf_cursor_y--;
  454.                 xf_scroll();
  455.         }
  456.  
  457.         /* this is necessary for I/O intensive tasks */
  458. }
  459.  
  460. /* cursor to previous line */
  461. void xf_previous_line(void)
  462. {
  463.         if (xf_cursor_y > 0)
  464.                 xf_cursor_y--;
  465. }
  466.  
  467. /* create a new line */
  468. void xf_new_line(void)
  469. {
  470.         xf_next_line();
  471.         xf_gotoxy(0, xf_cursor_y);
  472.         xf_find_caret();
  473.  
  474.         /* for I/O intensive tasks... */
  475.         xf_event_process();
  476. }
  477.  
  478.  
  479. /* advance cursor by 1 pos. */
  480. void xf_next_char(void)
  481. {
  482.         xf_cursor_x++;
  483.         if (xf_cursor_x == max_x_size)
  484.         {
  485.                 xf_cursor_x = 0;
  486.                 xf_next_line();
  487.         }
  488. }
  489.  
  490. /* back cursor 1 char */
  491. void xf_previous_char(void)
  492. {
  493.         xf_cursor_x--;
  494.         if (xf_cursor_x < 0)
  495.         {
  496.                 xf_cursor_x = max_x_size - 1;
  497.                 xf_previous_line();
  498.         }
  499. }
  500.  
  501. /* delete character before cursor */
  502. void xf_back_del()
  503. {
  504.         int i;
  505.         int adr;
  506.  
  507.         if (xf_cursor_x > 0)
  508.         {
  509.                 xf_cursor_x--;
  510.                 adr = xf_cursor_y * max_x_size;
  511.  
  512.                 /* shift line to the right */
  513.                 for (i = xf_cursor_x; i < max_x_size - 1; i++)
  514.                         screen[adr + i] = screen[adr + i + 1];
  515.  
  516.                 screen[adr + max_x_size - 1] = 0;
  517.  
  518.                 xf_invalidate_screen(xf_cursor_x, xf_cursor_y, max_x_size, xf_cursor_y);
  519.         }
  520.         xf_set_caret();
  521. }
  522.  
  523. /* print a character to cursor pos., no redrawing forced. */
  524. /* check for control chars */
  525. void xf__putc(int c)
  526. {
  527.         static BOOL in_gotoxy = FALSE;
  528.         static int numpars = 0;
  529.         static int params[2];
  530.  
  531.         /* collect coords if in a gotoxy-sequence */
  532.         if (in_gotoxy)
  533.         {
  534.                 params[numpars++] = c;
  535.                 if (numpars == 2)
  536.                 {
  537.                         xf_gotoxy(params[0], params[1]);
  538.                         in_gotoxy = 0;
  539.                 }
  540.         }
  541.         else
  542.         {
  543.                 /* otherwise process character: */
  544.                 switch (c)
  545.                 {
  546.                 /* cursor down (newline) */
  547.                 case 10:
  548.                         xf_new_line();
  549.                         break;
  550.                 /* carriage return */
  551.                 case 13:
  552.                         xf_gotoxy(0, xf_cursor_y);
  553.                         break;
  554.                 /* cursor up */
  555.                 case 11:
  556.                         xf_previous_line();
  557.                         break;
  558.                 /* cursor back 1 char */
  559.                 case 8:
  560.                         xf_previous_char();
  561.                         break;
  562.                 /* cursor advance 1 char */
  563.                 case 9:
  564.                         xf_next_char();
  565.                         break;
  566.                 /* clear screen */
  567.                 case 12:
  568.                         xf_clear_screen();
  569.                         break;
  570.                 /* home cursor */
  571.                 case 30:
  572.                         xf_gotoxy(0,0);
  573.                         break;
  574.                 /* position cursor */
  575.                 case 31:
  576.                         in_gotoxy = TRUE;
  577.                         numpars = 0;
  578.                         break;
  579.                 /* delete char to left of cursor */
  580.                 case 127:
  581.                         xf_back_del();
  582.                         break;
  583.                 /* or just print the char */
  584.                 default:
  585.                         if (c > 31)
  586.                         {
  587.                                 screen[xf_cursor_x + xf_cursor_y * max_x_size] = (char) c;
  588.                                 xf_invalidate_screen(xf_cursor_x, xf_cursor_y, xf_cursor_x, \
  589.                                                                                 xf_cursor_y);
  590.                                 xf_next_char();
  591.                         }
  592.                 }
  593.         }
  594. }
  595.  
  596. /* print a char to cursor os. redrawing forced */
  597. void xf_putchar(int c)
  598. {
  599.         xf__putc(c);
  600.         xf_force_redraw();
  601. }
  602.  
  603. /* print a string to cursor pos. */
  604. void xf_puts(char *string)
  605. {
  606.         int i;
  607.  
  608.         for (i = 0; i < strlen(string); i++)
  609.                 xf__putc(string[i]);
  610.  
  611.         xf_force_redraw();
  612. }
  613.  
  614. /* return a character from the board */
  615. int xf_getchar(void)
  616. {
  617.         int tmpchar;
  618.         BOOL valid = FALSE;
  619.  
  620.         xf_find_caret();
  621.  
  622.         /* don't process null-events while in here */
  623.         event_setmask(WKEYMASK);
  624.  
  625.         /* continue until we can process the key */
  626.         while (!valid)
  627.         {
  628.                 /* wait for a keypress from user */
  629.                 while ((tmpchar = popkey()) == -1)
  630.                 {
  631.                         xf_event_process();
  632.                 }
  633.  
  634.                 if (tmpchar > 0x100)
  635.                         wimp_processkey(tmpchar);
  636.                 else
  637.                         valid = TRUE;
  638.         }
  639.  
  640.         event_setmask(WSTDMASK);
  641.  
  642.         return tmpchar;
  643. }
  644.  
  645. /* clear virtual screen */
  646. void xf_clear_screen(void)
  647. {
  648.         int i;
  649.         /* clear screen */
  650.         for (i=0; i < max_x_size * max_y_size; i++)
  651.                 screen[i] = 0;
  652.  
  653.         /* invalidate total screen */
  654.         xf_invalidate_screen(0, 0, max_x_size, max_y_size);
  655.         xf_force_redraw();
  656.  
  657.         /* reset cursor positions */
  658.         xf_gotoxy(0, 0);
  659. }
  660.  
  661. /* initialize virtual screen */
  662. int xf_init_screen(wimp_w window, screenvar *svar)
  663. {
  664.         wimp_winfo winfo;
  665.         int win_x_size;
  666.         int win_y_size;
  667.  
  668.         winfo.w = window;
  669.         wimp_get_wind_info(&winfo);
  670.  
  671.         /* get maximum wrk area extent */
  672.         win_x_size = winfo.info.ex.x1 - winfo.info.ex.x0;
  673.         win_y_size = winfo.info.ex.y1 - winfo.info.ex.y0;
  674.  
  675.         /* set global variables */
  676.         max_x_size = win_x_size / (svar->xppc << svar->xeigh);
  677.         max_y_size = win_y_size / (svar->yppc << svar->yeigh);
  678.  
  679.         /* allocate screen memory */
  680.         screen = malloc(max_x_size*max_y_size);
  681.         if (screen == NULL)
  682.                 return FALSE;
  683.  
  684.         xf_clear_screen();
  685.  
  686.         return TRUE;
  687. }
  688.  
  689. /*** window routines ***/
  690.  
  691. /* create window, don't open */
  692. int xf_create_window(char *name, wimp_w *handle)
  693. {
  694.         wimp_wind *window;
  695.  
  696.         window = template_syshandle(name);
  697.  
  698.         colors = (3 << 4) | window->colours[wimp_WCWKAREAFORE] ^
  699.                             window->colours[wimp_WCWKAREABACK] ;
  700.  
  701.         if (window == 0)
  702.                 return FALSE;
  703.  
  704.         return (wimpt_complain(wimp_create_wind(window, handle)) == 0);
  705. }
  706.  
  707. /* open window, low level */
  708. int xf_w_open_window(wimp_openstr *ostr)
  709. {
  710.         return (wimpt_complain(wimp_open_wind(ostr)) == 0);
  711. }
  712.  
  713. /* open window, high level */
  714. int xf_open_window(wimp_w wind)
  715. {
  716.         wimp_wstate  win;
  717.         wimp_openstr ostr;
  718.         screenvar *ssize;
  719.         int wxsize, wysize;
  720.         int xpos, ypos;
  721.         int result;
  722.  
  723.         /* tell event system about it */
  724.         win_activeinc();
  725.  
  726.         /* get screensize */
  727.         ssize = xf_get_screen_size();
  728.  
  729.         /* build wimp_openstr */
  730.         wimp_get_wind_state(wind, &win);
  731.         ostr = win.o;
  732.         ostr.behind = -1;
  733.         ostr.x = 0;
  734.         ostr.y = 0;
  735.  
  736.         /* get size of visible work area */
  737.         wxsize = ostr.box.x1 - ostr.box.x0;
  738.         wysize = ostr.box.y1 - ostr.box.y0;
  739.  
  740.         /* pos. of window on screen */
  741.         xpos = ((ssize->xphys << ssize->xeigh) - wxsize)/2;
  742.         ypos = ((ssize->yphys << ssize->yeigh) - wysize)/2;
  743.  
  744.         /* center window on screen */
  745.         ostr.box.x0 = xpos;
  746.         ostr.box.x1 = xpos + wxsize;
  747.         ostr.box.y0 = ypos;
  748.         ostr.box.y1 = ypos + wysize;
  749.  
  750.         /* open window on screen */
  751.         result = xf_w_open_window(&ostr);
  752.  
  753.         /* init underlying screen */
  754.         xf_init_screen(wind, ssize);
  755.  
  756.         return (result != 0);
  757. }
  758.  
  759.  
  760. /*** special window routines ***/
  761.  
  762. static void xf_redraw_main_window(wimp_w window)
  763. {
  764.         BOOL            more;
  765.         wimp_redrawstr  rwind;
  766.         int             ox,oy;
  767.         int             top, left, right, bottom;
  768.         int             i,j;
  769.         int             curchar;
  770.  
  771.         /* get screen coordinates of visible area */
  772.         rwind.w = window;
  773.         wimpt_noerr(wimp_redraw_wind(&rwind, &more));
  774.  
  775.         ox = rwind.box.x0 - rwind.scx;
  776.         oy = rwind.box.y1 - rwind.scy;
  777.  
  778.         /* while there's still something to redraw */
  779.         while (more)
  780.         {
  781.                 /* compute rectangle to redraw */
  782.                 top =           rwind.g.y1 + 1 - oy;
  783.                 left =          rwind.g.x0 - ox;
  784.                 right =         rwind.g.x1 - ox;
  785.                 bottom =        rwind.g.y0 + 1 - oy;
  786.  
  787.                 /* compute textgrid coordinates */
  788.                 top = (-top) / char_y_size;
  789.                 left = left /char_x_size;
  790.                 right = right / char_x_size;
  791.                 bottom = (-bottom) / char_y_size;
  792.  
  793.                 wimp_setcolour(colors);
  794.  
  795.                 /* redraw rectangle */
  796.                 for(j = top; j <= bottom; j++)
  797.                 {
  798.                         for(i = left; i <= right; i++)
  799.                         { 
  800.                                 if ((curchar = screen[j * max_x_size + i]) > 0)
  801.                                 {
  802.                                         bbc_move(ox + (i * char_x_size), oy-1-(j * char_y_size));
  803.                                         bbc_vdu(curchar);
  804.                                 }
  805.                         }
  806.                 }
  807.                 /* get next next rectangle */
  808.                 wimp_get_rectangle(&rwind, &more);
  809.         }
  810.         xf_set_caret();
  811. }
  812.  
  813. /*** event routines ***/
  814.  
  815. /* event handler for main window */
  816. void xf_main_event_handler(wimp_eventstr *event, void *handle)
  817. {
  818.         handle = handle;        /* we get it, but there's no need for it */
  819.  
  820.         /* handle the event */
  821.         switch (event->e)
  822.         {
  823.                 case wimp_EREDRAW:
  824.                         xf_redraw_main_window(event->data.o.w);
  825.                         break;
  826.                 case wimp_EOPEN:
  827.                         xf_w_open_window(&event->data.o);
  828.                         break;
  829.                 case wimp_ECLOSE:
  830.                         xf_closedown();
  831.                         break;
  832.                 case wimp_EKEY:
  833.                         xf_handle_key(event->data.key.chcode);
  834.                         break;
  835.                 case wimp_EBUT:
  836.                         if (event->data.but.m.bbits & (wimp_BLEFT | wimp_BRIGHT))
  837.                                 xf_set_caret();
  838.                         break;
  839.                 default:;
  840.                         /* ignore */
  841.         }
  842. }
  843.  
  844. /* event handler for the menu */
  845. void xf_menu_handler(void *handle, char *sel)
  846. {
  847.         handle = handle;
  848.  
  849.         switch (sel[0])
  850.         {
  851.                 case XF_INFO:
  852.                         xf_prog_info();
  853.                         break;
  854.                 case XF_QUIT:
  855.                         xf_closedown();
  856.                         break;
  857.         }
  858. }
  859.  
  860. /*** Wimp frontend initialisation routine ***/
  861. int xf_init(void)
  862. {
  863.         initing = TRUE;
  864.  
  865.         /* init event system */
  866.         event_setmask(WSTDMASK);
  867.         win_init();
  868.         /* start task */
  869.         wimp_taskinit("Xscheme interpreter", &wimp_version, &task_handle);
  870.  
  871.         /* setup system runtime */
  872.         systime.tms_utime = 0;
  873.         systime.tms_stime = 0;
  874.         systime.tms_cutime = 0;
  875.         systime.tms_cstime = 0;
  876.  
  877.         sys_timeslp = get_time();
  878.  
  879.         /* secure floating point op's */
  880.         wimp_save_fp_state_on_poll();
  881.  
  882.         /* initialize resources */
  883.         res_init("XScheme");
  884.         template_init();
  885.         dbox_init();
  886.  
  887.         loadpath = malloc(BUFSIZ);
  888.         _kernel_getenv("Xscheme$resDir", loadpath, BUFSIZ);
  889.  
  890.         /* the main window */
  891.         if (!xf_create_window("MainWindow", &xf_main_wind))
  892.                 return FALSE;
  893.         /* setup event handler for window, set 'handle' to 0... */
  894.         win_register_event_handler(xf_main_wind, xf_main_event_handler, 0);
  895.  
  896.         /* the menu tree */
  897.         if ((xf_menu = menu_new("Xscheme",">Info,Quit")) == NULL)
  898.                 return FALSE;
  899.  
  900.         /* attach menu to window */
  901.         if (!event_attachmenu(xf_main_wind, xf_menu, xf_menu_handler, 0))
  902.                 return FALSE;
  903.  
  904.         xf_open_window(xf_main_wind);
  905.  
  906.         xf_set_caret();
  907.  
  908.         /* init the keyboard buffer */
  909.         init_keybuffer();
  910.  
  911.         initing = FALSE;
  912.  
  913.         return TRUE;
  914. }
  915.  
  916. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  917. +*+++++++++++++++++++ WIMP interfacing code end +++++++++++++++++++++++++++
  918. +*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
  919.  
  920.  
  921. /* -- external variables */
  922. extern  FILE * tfp;
  923. extern LVAL xlenv, xlfenv, xldenv;
  924.  
  925. /* -- local variables */
  926. static  char    lbuf[BUFSIZ];
  927. static  int     lpos[BUFSIZ];
  928. int     lposition;  /* export this */
  929. static  int     lindex;
  930. static  int     lcount;
  931.  
  932. char *xfgets(char*, int, FILE *);
  933. char read_keybd(void);
  934. void osx_check(int);
  935. void init_tty(void);
  936. VOID xinfo(void);
  937. void onsusp(void);
  938.  
  939. /* xsystem - run a process, sending output (if any) to stdout/stderr */
  940. LVAL
  941. xsystem()
  942. {
  943.         extern LVAL     true;
  944.         char            *comstr;
  945.         LVAL            command;
  946.         int             result;
  947.         time_t          stime;
  948.  
  949.         /* get shell command */
  950.         command = xlgastring();
  951.         xllastarg();
  952.  
  953.         comstr = (char *) getstring(command);
  954.  
  955.         /* start external process, measure runtime internally */
  956.         stime = get_time();
  957.         result = system(comstr);
  958.         systime.tms_stime += get_time() - stime;
  959.  
  960.         return (result ? cvfixnum(result) : true);
  961. }
  962.  
  963.  
  964.  
  965. /* osinit - initialize OS for Xscheme */
  966. VOID osinit (char *banner)
  967. {
  968.         if (xf_init() != TRUE)
  969.                 exit (-1);
  970.         xf_puts(banner);
  971.         xf_putchar('\n');
  972.  
  973.         init_tty();
  974.         lindex  = 0;
  975.         lcount  = 0;
  976. }
  977.  
  978.  
  979. /* -- osfinish - clean up before returning to the operating system */
  980. VOID osfinish()
  981. {
  982.         xf_closedown();
  983. }
  984.  
  985.  
  986. /* -- xoserror - print an error message */
  987. VOID xoserror(msg)
  988. char         *msg;
  989. {
  990.         werr(0, "error: %s\n", msg );
  991. }
  992.  
  993.  
  994. /* osrand - return next random number in sequence */
  995. int osrand(rseed)
  996.   int rseed;
  997. {
  998.     long k1;
  999.  
  1000.     /* make sure we don't get stuck at zero */
  1001.     if (rseed == 0L) rseed = 1L;
  1002.  
  1003.     /* algorithm taken from Dr. Dobbs Journal, November 1985, page 91 */
  1004.     k1 = rseed / 127773L;
  1005.     if ((rseed = 16807L * (rseed - k1 * 127773L) - k1 * 2836L) < 0L)
  1006.         rseed += 2147483647L;
  1007.  
  1008.     /* return a random number between 0 and MAXFIX */
  1009.     return rseed;
  1010. }
  1011.  
  1012. /* fix names in the form "[path.]bla.lsp" to become "[path.]lsp.bla" */
  1013. char *fixname(const char *name)
  1014. {
  1015.         char *hname, *hhn;
  1016.         char *retval;
  1017.         int i;
  1018.         char c[10];
  1019.         char fix[5];
  1020.  
  1021.         retval = malloc(strlen(name));
  1022.         strcpy(retval, name);
  1023.  
  1024.         hname = retval + (strlen(retval)-3);
  1025.  
  1026.         i = strlen(retval);
  1027.  
  1028.         if (i < 3)
  1029.                 return (char *)retval;
  1030.  
  1031.         strcpy(fix, stolower(hname));
  1032.  
  1033.         /* lsp postfix? */
  1034.         if (strcmp(fix, "wks") == 0 || strcmp(fix, "scm") == 0)
  1035.         {
  1036.                 hhn = hname - 1;
  1037.                 hname -= 2;
  1038.                 while(*hname != '.' && hname > retval)
  1039.                         --hname;
  1040.                 if (*hname == '.')
  1041.                         hname++;
  1042.  
  1043.                 /* then turn it into a prefix for the filename */
  1044.                 strncpy(c, hname, (int) (hhn - hname));
  1045.                 strcpy (hname, strcat(fix,"."));
  1046.                 hname+=4;
  1047.                 strcpy (hname, c);
  1048.                 retval[i] = '\0';
  1049.         }
  1050.  
  1051.         return retval;
  1052. }
  1053.  
  1054. /* open a file trying given and fixed name */
  1055. FILE *osopen (char *name, char *mode)
  1056. {
  1057.         int j;
  1058.         FILE *retval = NULL;
  1059.         char curdir[BUFSIZ];
  1060.         char tmppath[PATHBUF];
  1061.         char *nname = NULL;
  1062.  
  1063.         /* eval curdir every single time, it may change! */
  1064.         _kernel_getenv("Xscheme$WorkDir", curdir, BUFSIZ);
  1065.  
  1066.         nname = (char *)name;
  1067.         j = 0;
  1068.         while (retval == NULL && j<2)
  1069.         {
  1070.                 /* first pass: try normal filename */
  1071.                 /* on the second pass fix the postfix-problem */
  1072.                 if (j==1)
  1073.                         nname = fixname(name);
  1074.                 ++j;
  1075.  
  1076.                 tmppath[0] = 0;
  1077.  
  1078.                 if (curdir != NULL)
  1079.                 {
  1080.                         strcpy(tmppath, curdir);
  1081.                         tmppath[strlen(curdir)] = 0;
  1082.                 }
  1083.                 retval = fopen(strcat(tmppath, nname), mode);
  1084.  
  1085.                 if (retval == NULL)
  1086.                 {
  1087.                         if (loadpath != NULL)
  1088.                         {
  1089.                                 strcpy(tmppath, loadpath);
  1090.                                 tmppath[strlen(loadpath)] = 0;
  1091.                         }
  1092.                         retval = fopen(strcat(tmppath, nname), mode);
  1093.                 }
  1094.  
  1095.                 if (retval == NULL)
  1096.                         retval = fopen(nname, mode);
  1097.  
  1098.         }
  1099.  
  1100.         if (nname != name)
  1101.                 free(nname);
  1102.  
  1103.         return retval;
  1104. }
  1105.  
  1106. /* rename argument file as backup, return success name */
  1107. /* For new systems -- if cannot do it, just return TRUE! */
  1108.  
  1109. int renamebackup(filename)
  1110.   char *filename;
  1111. {
  1112.     return TRUE;
  1113. }
  1114.  
  1115. /* -- ostgetc - get a character from the terminal */
  1116. int ostgetc(void)
  1117. {
  1118.         while(--lcount < 0 )
  1119.         {
  1120.                 if ( xfgets(lbuf,BUFSIZ,stdin) == NULL )
  1121.                         return( EOF );
  1122.  
  1123.                 lcount = strlen( lbuf );
  1124.                 if (tfp!=NULL) fwrite(lbuf,1,lcount,tfp);
  1125.  
  1126.                 lindex = 0;
  1127.                 lposition = 0;
  1128.         }
  1129.  
  1130.         return( lbuf[lindex++] );
  1131. }
  1132.  
  1133.  
  1134. /* -- ostputc - put a character to the terminal */
  1135. VOID ostputc(ch)
  1136. int     ch;
  1137. {
  1138.         /* -- output the character */
  1139.         xf_putchar(ch);
  1140.  
  1141.         /* -- output the char to the transcript file */
  1142.         if ( tfp != NULL )
  1143.                 fputc( ch, tfp );
  1144. }
  1145.  
  1146.  
  1147.  
  1148.  
  1149. /* -- osflush - flush the terminal input buffer */
  1150. VOID osflush()
  1151. {
  1152.         init_keybuffer();
  1153.         lindex = lcount = lposition = 0;
  1154. }
  1155.  
  1156. void oscheck()
  1157. {
  1158.         xf_event_process();
  1159. }
  1160.  
  1161. void osx_check(int ch)
  1162. {
  1163.      switch (ch) {
  1164.         case '\003':
  1165.           xltoplevel(); /* control-c */
  1166.         case '\007':
  1167.           xlcleanup();  /* control-g */
  1168.         case '\020':
  1169.           xlcontinue(); /* control-p */
  1170.         case '\024':    /* control-t */
  1171.           xinfo();
  1172.           xf_puts("\n> ");
  1173.      }
  1174. }
  1175.  
  1176.  
  1177. /* -- ossymbols - enter os-specific symbols */
  1178. VOID ossymbols()
  1179. {
  1180. }
  1181.  
  1182.  
  1183. /* xinfo - show information on control-t */
  1184. VOID xinfo()
  1185. {
  1186.   extern int nfree, gccalls;
  1187.   extern long total;
  1188.   char tymebuf[100];
  1189.   time_t tyme;
  1190.   char buf[500];
  1191.  
  1192.   time(&tyme);
  1193.   strcpy(tymebuf, ctime(&tyme));
  1194.   tymebuf[19] = '\0';
  1195.   sprintf(buf,"\n[ %s Free: %d, GC calls: %d, Total: %ld ]",
  1196.     tymebuf, nfree,gccalls,total);
  1197.   errputstr(buf);
  1198. }
  1199.  
  1200. /* xflush - flush the input line buffer and start a new line */
  1201. VOID xflush()
  1202. {
  1203.   osflush();
  1204.   ostputc('\n');
  1205. }
  1206.  
  1207.  
  1208. char read_keybd()
  1209. {  
  1210.         return(xf_getchar());
  1211. }
  1212.  
  1213. /* xgetkey - get a key from the keyboard */
  1214. LVAL xgetkey()
  1215. {
  1216.     xllastarg();
  1217.     return (cvfixnum((FIXTYPE)read_keybd()));
  1218. }
  1219.  
  1220. VOID xlresetint(dummy)
  1221. int dummy;
  1222. {
  1223.     signal(SIGINT, xlresetint);
  1224.     xltoplevel();
  1225. }
  1226.  
  1227. void init_tty(void)
  1228. {
  1229.  
  1230.         signal(SIGINT, xlresetint);
  1231.  
  1232. #ifdef SIGTSTP
  1233.         if (signal(SIGTSTP, onsusp) == SIG_DFL)
  1234.         {
  1235.                 signal(SIGTSTP, onsusp);
  1236.         }
  1237. #endif
  1238. }
  1239.  
  1240. void onsusp(void)
  1241. {
  1242. #ifdef SIGSTP
  1243.     /* ignore SIGTTOU so we dont get stopped if csh grabs the tty */
  1244.     signal(SIGTTOU, SIG_IGN);
  1245.     stty(0, &savetty);
  1246.     xflush();
  1247.     signal(SIGTTOU,SIG_DFL);
  1248.  
  1249.     /* send the TSTP signal to suspend our process group */
  1250.     signal(SIGTSTP, SIG_DFL);
  1251.     sigsetmask(0);
  1252.     kill(0, SIGTSTP);
  1253.     /* pause for station break */
  1254.  
  1255.     /* we re back */
  1256.     signal(SIGTSTP, onsusp);
  1257.     stty(0, &newtty);
  1258. #endif
  1259. }
  1260.  
  1261.  
  1262.  
  1263. char *xfgets(s, n, iop)
  1264. char *s;
  1265. int n;
  1266. FILE *iop;
  1267. {
  1268.         register c;
  1269.         register char *cs;
  1270.  
  1271.         cs = s;
  1272.         while (--n>0 && (c = read_keybd()) != EOF) {
  1273.              switch(c) {
  1274.                   case '\003' :                 /* CTRL-c */
  1275.                   case '\007' :                 /* CTRL-g */
  1276.                   case '\020' :                 /* CTRL-p */
  1277.                   case '\024' : osx_check(c);   /* CTRL-t */
  1278.                                 n++;
  1279.                                 break;
  1280.  
  1281.                   case 8      :
  1282.                   case 127    : if (cs==s) break;   /* not before beginning */
  1283.                                 stdputstr("\x08 \x08");
  1284.                                 
  1285.                                 n+=2;           
  1286.                                 cs--;
  1287.                                 break;
  1288.  
  1289.                   case '\r'   : c = '\n';
  1290.                                 *cs++ = c;
  1291.                   default     : if (c >= ' ')
  1292.                                         *cs++ = c;      /* character */
  1293.                                 ostputc(c);
  1294.                 }
  1295.                 if (c=='\n') break;
  1296.         }
  1297.         if (c == EOF && cs==s) return(NULL);
  1298.         *cs = '\0';
  1299.         return(s);
  1300. }
  1301.  
  1302. /* xtime - get the current time */
  1303. LVAL xtime()
  1304. {
  1305.     xllastarg();
  1306.     return (cvfixnum((FIXTYPE)time((time_t)0)));
  1307. }
  1308.  
  1309. /* xdifftime - get the difference between two time values */
  1310. LVAL xdifftime()
  1311. {
  1312.     time_t t1,t2;
  1313.     LVAL val;
  1314.     val = xlgafixnum(); t1 = (time_t)getfixnum(val);
  1315.     val = xlgafixnum(); t2 = (time_t)getfixnum(val);
  1316.     xllastarg();
  1317.     return (cvflonum((FLOTYPE)difftime(t1,t2)));
  1318. }
  1319.  
  1320. /* main - the main routine */
  1321. int main(argc,argv)
  1322.   int argc; char *argv[];
  1323. {
  1324.     xlmain(argc,argv);
  1325. }
  1326.