home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 5 Edit / 05-Edit.zip / UE311C.ZIP / ST52.C < prev    next >
C/C++ Source or Header  |  1991-10-11  |  25KB  |  990 lines

  1. /*    ST52.C:    Atari ST1040/520 screen support functions
  2.         written by lots of people (see below)
  3.  
  4.         Daniel Lawrence
  5.         James Turner
  6.         Jeff Lomicka
  7.         J. C. Benoist
  8.  
  9.     Modification History:
  10.     31-dec-87    Jeff Lomicka
  11.     - massive changes/additions for accessories and mouse
  12.     20-jan-87    Daniel Lawrence
  13.     - changed code in domousekey() to pass five bytes, two zeros
  14.       (to tell input.c that this is a mouse event), x/ypos
  15.       and the mouse event type.
  16.     may 88        Jeff Lomicka and Dan Lawrence
  17.     - a lot of changes.  Through out aline.h, use the MWC and
  18.       ATARI names for things now.
  19.     - moving the mouse to the extreme upper left brings up
  20.       the desk accessory menu.  EMACS won't replot on the
  21.       way out yet.
  22.     - cleaned up behavior of the mouse and the cursor on exit
  23.     26-feb-89    Daniel Lawrence
  24.     - rewote input layer to conform to new specs in input.c
  25.     01-may-91    Daniel Lawrence/Suggested by Allan Pratt
  26.     - renamed atari source files to TOS.C and ST52.c
  27.     - changed symbols ATARI => ST52 and ST520 => TOS
  28. */
  29.  
  30. #define termdef 1        /* don't define "term" external */
  31.  
  32. #include    <stdio.h>
  33. #include    "estruct.h"
  34. #include    "eproto.h"
  35. #include    "edef.h"
  36. #include    "elang.h"
  37.  
  38. #if    ST52
  39.  
  40. /*
  41.     These routines provide support for the ATARI 1040ST and 520ST
  42. using the virtual VT52 Emulator
  43.  
  44. */
  45.  
  46. #include    <aesbind.h>
  47. #include    <gemdefs.h>
  48. #include    <obdefs.h>
  49. #include    <osbind.h>
  50. #include    <xbios.h>
  51. #include    <linea.h>
  52.  
  53. #define NROW    50    /* Screen size.         */
  54. #define NCOL    80    /* Edit if you want to.     */
  55. #define MARGIN    8    /* size of minimim margin and    */
  56. #define SCRSIZ    64    /* scroll size for extended lines */
  57. #define NPAUSE    300    /* # times thru update to pause */
  58. #define BIAS    0x20    /* Origin 0 coordinate bias.    */
  59. #define ESC    0x1B    /* ESC character.        */
  60. #define SCRFONT 2    /* index of 8x16 monochrome system default font */
  61. #define DENSIZE 50    /* # of lines in a dense screen */
  62.  
  63. /****    ST Internals definitions        *****/
  64.  
  65. /*    BIOS calls */
  66.  
  67. #define BCONSTAT    1    /* return input device status */
  68. #define CONIN        2    /* read character from device */
  69. #define BCONOUT     3    /* write character to device */
  70.  
  71. /*    XBIOS calls */
  72.  
  73. #define INITMOUS    0    /* initialize the mouse     */
  74. #define GETREZ        4    /* get current resolution    */
  75. #define SETSCREEN    5    /* set screen resolution    */
  76. #define SETPALETTE    6    /* set the color pallette    */
  77. #define SETCOLOR    7    /* set or read a color        */
  78. #define CURSCONF    21    /* set cursor configuration    */
  79. #define IKBDWS        25    /* intelligent keyboard send command */
  80. #define KBDVBASE    34    /* get keyboard table base    */
  81.  
  82. /*    GEMDOS calls */
  83.  
  84. #define EXEC        0x4b    /* Exec off a process */
  85. #define CON        2    /* CON: Keyboard and screen device */
  86.  
  87. /*    Palette color definitions    */
  88.  
  89. #define LOWPAL    "000700070770007707077777333733373773337737377777"
  90. #define MEDPAL    "000700007777"
  91. #define HIGHPAL "111000"
  92.  
  93. /*    ST Global definitions        */
  94.  
  95. int initrez;            /* initial screen resolution */
  96. int currez;            /* current screen resolution */
  97. int gemflag;            /* were we called from the desktop? */
  98. int mouseon;            /* True if mouse is on */
  99. char resname[][8] = {        /* screen resolution names */
  100.     "LOW", "MEDIUM", "HIGH", "DENSE"
  101. };
  102. short spalette[16];        /* original color palette settings */
  103. short palette[16];        /* current palette settings */
  104. static short scursor;        /* original text cursor mode */
  105.  
  106. struct la_data *aline;        /* Line A data structure */
  107.  
  108. struct la_ext *naline;        /* extended Line A data structure */
  109.  
  110. struct la_font **fonts;    /* Array of pointers to the three system
  111.               font headers returned by init (in register A1) */
  112.  
  113. struct la_font *system_font;    /* pointer to default system font */
  114. struct la_font *small_font;    /* pointer to small font */
  115.  
  116. /*
  117.     These are needed to make GEM happy
  118. */
  119. int contrl[ 11], intin[ 128], intout[ 128], ptsin[ 256], ptsout[ 12];
  120. static int worki[ 11] = {1,1,1,1,1,1,1,1,1,1,2}, worko[ 57];
  121.  
  122. /*
  123.     Some useful information about our environment
  124. */
  125. static int
  126.     g_wchar, g_hchar,    /* VDI's idea of current font size */
  127.     junk, gid, wkid;    /* Graphics ID, workstation ID */
  128.  
  129. static int oldbut = 0;        /* Previous state of mouse buttons */
  130. static int mctrl;        /* current BEG_MOUSE state */
  131. static struct { char *norm, *shift, *caps;} *kt;    /* Keyboard mapping */
  132.  
  133. /*
  134.     This object tree is for displaying the desk accessory menu.
  135.     Actual positions are written into this structure when the
  136.     screen size is known.
  137. */
  138. OBJECT menu[] =
  139.     {
  140.     -1, 1, 4,    G_IBOX,   NONE,  NORMAL, 0x0L,        0 , 0,   0,   0,/* Root */
  141.      4, 2, 2,     G_BOX,   NONE,  NORMAL, 0x10F0L,   0,    0,   1,   1,/* BAR */
  142.      1, 3, 3,    G_IBOX,   NONE,  NORMAL, 0x0L,        0,    0,   1,   1,/* Active */
  143.      2,-1,-1,  G_TITLE,   NONE,  NORMAL,  "",        0,    0,   1,   1,/* title */
  144.      0, 5, 5,    G_IBOX,   NONE,  NORMAL, 0x0L,        0,    0,   0,   0,/* screen */
  145.      4, 6,13,     G_BOX,   NONE,  NORMAL, 0xFF1100L, 0,    0,   0,   0,/* box */
  146.      7,-1,-1, G_STRING,   NONE,  NORMAL, TEXT179,0,0,168,    16,
  147. /*                                       "  About MicroEmacs" */
  148.      8,-1,-1, G_STRING,   NONE,DISABLED, "---------------------",
  149.                             0, 16, 168,  16,
  150.      9,-1,-1, G_STRING,   NONE,  NORMAL, "",        0, 32, 168,  16,
  151.     10,-1,-1, G_STRING,   NONE,  NORMAL, "",        0, 48, 168,  16,
  152.     11,-1,-1, G_STRING,   NONE,  NORMAL, "",        0, 64, 168,  16,
  153.     12,-1,-1, G_STRING,   NONE,  NORMAL, "",        0, 80, 168,  16,
  154.     13,-1,-1, G_STRING,   NONE,  NORMAL, "",        0, 96, 168,  16,
  155.      5,-1,-1, G_STRING, LASTOB,  NORMAL, "",        0,112, 168,  16
  156.     };
  157.  
  158. extern mymouse();        /* .s file for calling two mouse handlers */
  159. int (*first_mhandler)();    /* Address of first handler */
  160. int (*second_mhandler)();    /* Address of second handler */
  161. struct kbdvbase *kv;        /* Keyboard vector table */
  162. static int msevntsiz = 0;    /* Events in private mouse event queue */
  163. static unsigned short msevntq[16];/* State of mouse keys at event */
  164. static int msevntin = 0;    /* Queue input ptr */
  165. static int msevntout = 0;    /* Queue output ptr */
  166. static int mousekeys1 = 0;    /* Last mouse key event */
  167. static int mousecol = HUGE;    /* current mouse column */
  168. static int mouserow = HUGE;    /* current mouse row */
  169.  
  170. extern    int    ttopen();        /* Forward references.        */
  171. extern    int    ttgetc();
  172. extern    int    ttputc();
  173. extern    int    ttflush();
  174. extern    int    ttclose();
  175. extern    int    stmove();
  176. extern    int    steeol();
  177. extern    int    steeop();
  178. extern    int    stbeep();
  179. extern    int    stopen();
  180. extern    int    stclose();
  181. extern    int    stgetc();
  182. extern    int    stputc();
  183. extern    int    strev();
  184. extern    int    strez();
  185. extern    int    stkopen();
  186. extern    int    stkclose();
  187.  
  188. #if    COLOR
  189. extern    int    stfcol();
  190. extern    int    stbcol();
  191. #endif
  192.  
  193. /*
  194.  * Dispatch table. All the
  195.  * hard fields just point into the
  196.  * terminal I/O code.
  197.  */
  198. TERM    term    = {
  199.     NROW-1,
  200.     NROW-1,
  201.     NCOL,
  202.     NCOL,
  203.     MARGIN,
  204.     SCRSIZ,
  205.     NPAUSE,
  206.     &stopen,
  207.     &stclose,
  208.     &stkopen,
  209.     &stkclose,
  210.     &stgetc,
  211.     &stputc,
  212.     &ttflush,
  213.     &stmove,
  214.     &steeol,
  215.     &steeop,
  216.     &steeop,
  217.     &stbeep,
  218.     &strev,
  219.     &strez
  220. #if    COLOR
  221.     , &stfcol,
  222.     &stbcol
  223. #endif
  224. };
  225.  
  226. /*    input buffers and pointers    */
  227.  
  228. #define    IBUFSIZE    64    /* this must be a power of 2 */
  229.  
  230. unsigned char in_buf[IBUFSIZE];    /* input character buffer */
  231. int in_next = 0;        /* pos to retrieve next input character */
  232. int in_last = 0;        /* pos to place most recent input character */
  233.  
  234. in_init()    /* initialize the input buffer */
  235.  
  236. {
  237.     in_next = in_last = 0;
  238. }
  239.  
  240. in_check()    /* is the input buffer non-empty? */
  241.  
  242. {
  243.     if (in_next == in_last)
  244.         return(FALSE);
  245.     else
  246.         return(TRUE);
  247. }
  248.  
  249. in_put(event)
  250.  
  251. int event;    /* event to enter into the input buffer */
  252.  
  253. {
  254.     in_buf[in_last++] = event;
  255.     in_last &= (IBUFSIZE - 1);
  256. }
  257.  
  258. int in_get()    /* get an event from the input buffer */
  259.  
  260. {
  261.     register int event;    /* event to return */
  262.  
  263.     event = in_buf[in_next++];
  264.     in_next &= (IBUFSIZE - 1);
  265.     return(event);
  266. }
  267.  
  268. void init_aline()
  269.  
  270. {
  271.     int *ld_contrl;
  272.     int *ld_intin;
  273.  
  274.     linea0();
  275.  
  276.     /* save if the current mouse is hidden (ie we are not in GEM) */
  277.     gemflag = (mousehidden == 0);
  278.     while (mousehidden) {
  279.         showmouse();
  280.         }
  281.     aline = (struct la_data *)(la_init.li_a0);
  282.     fonts = (struct la_font **)(la_init.li_a1);
  283.     naline = ((struct la_ext *)aline) - 1;
  284.     scursor = naline->ld_status;        /* State of text cursor */
  285.     ld_contrl = aline->ld_contrl;        /* -> control junk    */
  286.     ld_intin  = aline->ld_intin;        /* -> intin junk    */
  287. }
  288.  
  289. init()
  290.  
  291. {
  292.     init_aline();
  293.     system_font = fonts[SCRFONT];        /* save it */
  294.     small_font = fonts[1];
  295. }
  296.  
  297.  
  298. switch_font(fp)
  299.  
  300. struct la_font *fp;
  301.  
  302. {
  303.        /* See linea.h for description of fields */
  304.  
  305.        V_CEL_HT = fp->font_height;
  306.        V_CEL_WR = aline->ld_vwrap * fp->font_height;
  307.        V_CEL_MY = (naline->ld_y_max / fp->font_height) - 1;
  308.        V_CEL_MX = (naline->ld_x_max / fp->font_fat_cell) - 1;
  309.        V_FNT_WR = fp->font_width;
  310.        V_FNT_ST = fp->font_low_ade;
  311.        V_FNT_ND = fp->font_hi_ade;
  312.        V_OFF_AD = (long) fp->font_char_off;
  313.        V_FNT_AD = (long) fp->font_data;
  314. }
  315.  
  316. stmove(row, col)
  317.  
  318. {
  319.     stputc(ESC);
  320.     stputc('Y');
  321.     stputc(row+BIAS);
  322.     stputc(col+BIAS);
  323. }
  324.  
  325. steeol()
  326.  
  327. {
  328.     stputc(ESC);
  329.     stputc('K');
  330. }
  331.  
  332. steeop()
  333.  
  334. {
  335. #if    COLOR
  336.     stfcol(gfcolor);
  337.     stbcol(gbcolor);
  338. #endif
  339.     stputc(ESC);
  340.     stputc('J');
  341. }
  342.  
  343. strev(status)    /* set the reverse video state */
  344.  
  345. int status;    /* TRUE = reverse video, FALSE = normal video */
  346.  
  347. {
  348.     if (currez > 1) {
  349.         stputc(ESC);
  350.         stputc(status ? 'p' : 'q');
  351.     }
  352. }
  353.  
  354. #if    COLOR
  355. mapcol(clr)    /* medium rez color translation */
  356.  
  357. int clr;    /* emacs color number to translate */
  358.  
  359. {
  360.     static int mctable[] = {0, 1, 2, 3, 2, 1, 2, 3};
  361.  
  362.     if (currez != 1)
  363.         return(clr);
  364.     else
  365.         return(mctable[clr]);
  366. }
  367.  
  368. stfcol(color)    /* set the forground color */
  369.  
  370. int color;    /* color to set forground to */
  371.  
  372. {
  373.     if (currez < 2) {
  374.         stputc(ESC);
  375.         stputc('b');
  376.         stputc(mapcol(color));
  377.     }
  378. }
  379.  
  380. stbcol(color)    /* set the background color */
  381.  
  382. int color;    /* color to set background to */
  383.  
  384. {
  385.     if (currez < 2) {
  386.         stputc(ESC);
  387.         stputc('c');
  388.         stputc(mapcol(color));
  389.     }
  390. }
  391. #endif
  392.  
  393. static char beep[] = {
  394.     0x00, 0x00,
  395.     0x01, 0x01,
  396.     0x02, 0x01,
  397.     0x03, 0x01,
  398.     0x04, 0x02,
  399.     0x05, 0x01,
  400.     0x07, 0x38,
  401.     0x08, 0x10,
  402.     0x09, 0x10,
  403.     0x0A, 0x10,
  404.     0x0B, 0x00,
  405.     0x0C, 0x30,
  406.     0x0D, 0x03,
  407.     0xFF, 100,
  408.     0x09, 0x00,
  409.     0x0A, 0x00,
  410.     0xFF, 0x00
  411. };
  412.  
  413. stbeep()
  414.  
  415. {
  416.     Dosound(beep);
  417. }
  418.  
  419. mouse_on()    /* turn the gem mouse ON */
  420.  
  421. {
  422.     if (!mouseon) {
  423.         graf_mouse( M_ON, 0L);
  424.         graf_mouse(ARROW, 0L);
  425.         mouseon = 1;
  426.     }
  427. }
  428.  
  429. mouse_off()    /* turn the gem mouse OFF */
  430.  
  431. {
  432.     if (mouseon) {
  433.         graf_mouse( M_OFF, 0L);
  434.         mouseon = 0;
  435.     }
  436.     if( !mousehidden) stbeep();
  437. }
  438.  
  439. /*
  440.     me_mh - MicroEmacs Mouse interrupt Handler.  This handler is called,
  441.     in addition to the regular mouse handler, in order for microemacs
  442.     to have access to some more information about the mouse events.
  443.  
  444.     What it does is:
  445.  
  446.     - Queue a copy of the mouse button state at the actual moment of
  447.     the event, rather than after GEM is finished playing with timers.
  448.  
  449.     - Convert all right-mouse-button events into left-mouse-button
  450.     events BEFORE GEM's mouse interrupt handler, so that GEM will generate
  451.     a left-mouse-button event.
  452. */
  453. me_mh(a)
  454.  
  455. char *a;
  456. {
  457.     register unsigned mousekeys;
  458.     
  459.     mousekeys = a[0] & 7;
  460.     if (mousekeys != 0)
  461.         a[0] = 0xFA;     /* Any key down means button 1 down */
  462.     else
  463.         a[0] = 0xf8;    /* Otherwise button 1 up */
  464.     if (msevntsiz < 16) {
  465.         /* Previous event was processed, look for next one */
  466.         if (mousekeys != mousekeys1) {
  467.             /* A button change is detected, insert it in queue */
  468.             msevntq[msevntin++] = mousekeys;
  469.             msevntin &= 15;
  470.             msevntsiz++;
  471.             mousekeys1 = mousekeys;
  472.         }
  473.     }
  474. }
  475.  
  476.  
  477. stkopen()    /* open the keyboard (and mouse) */
  478. {
  479. }
  480.  
  481. stopen()    /* open the screen */
  482.  
  483. {
  484.     register int i;
  485.  
  486.     init();
  487.  
  488. /*
  489.     Set up an interrupt handler for the mouse that performs both
  490.     me_mh() and the default mouse handling.  The .s file "stmouse.s"
  491.     contains some special code for this purpose.
  492. */
  493.     first_mhandler = me_mh;
  494.     kv = Kbdvbase();
  495.     second_mhandler = kv->kb_mousevec;
  496.     kv->kb_mousevec = mymouse;
  497. /*
  498.     In order to have both the mouse cursor and the text cursor on the
  499.     screen at the same time, we have to flash it ourselves, turning
  500.     the mouse cursor on and off for each flash.
  501.  
  502.     The cursors are both off whenever we are not in an input wait.
  503. */
  504.     Cursconf(3, 0);    /* Stop text cursor from flashing */   
  505.     Cursconf(0, 0);    /* Turn text cursor off */
  506. /*
  507.     Wake up GEM and the VDI
  508. */
  509.     appl_init();
  510.     gid = graf_handle(&g_wchar, &g_hchar, &junk, &junk);
  511. #if    0
  512.     /* We never use the VDI, but if you do, turn this back on */
  513.     v_opnvwk(worki, &wkid, worko);
  514. #endif
  515.     graf_mouse( M_OFF, 0L);
  516.     mouseon = 0;
  517. /*
  518.     Set up the menu bar's coordinates to match the font and screen size
  519.     for this screen resolution
  520. */
  521.     wind_get(0, WF_CURRXYWH,    /* Fetch actual screen size for menu */
  522.         &menu[0].ob_x, &menu[0].ob_y,
  523.         &menu[0].ob_width, &menu[0].ob_height);
  524.     menu[1].ob_x = menu[0].ob_width - 1;    /* Locate "desk" box */
  525.     menu[4].ob_width = menu[0].ob_width;
  526.     menu[4].ob_height = 8*g_hchar;
  527.     menu[5].ob_width = 21*g_wchar;
  528.     menu[5].ob_height = 8*g_hchar;
  529.     menu[5].ob_x = menu[0].ob_width - menu[5].ob_width;
  530.     for(i=6; i<14; i++) {
  531.         /* Desk accessory items */
  532.         menu[i].ob_y = (i-6)*g_hchar;
  533.         menu[i].ob_width = menu[5].ob_width;
  534.         menu[i].ob_height = g_hchar;
  535.     }
  536.     menu_bar(menu, 1);
  537. /*
  538.     Shut off GEM's user interface until we enter an input wait.
  539.     Note that unless we claim the mouse with BEG_MCTRL, we will not
  540.     get scheduled to run any time the left mouse button goes down while
  541.     the mouse is on the top 16 pixels of the screen.  We keep Emacs
  542.     "hung" whenever MCTRL is given to desk accessories or GEM, and keep
  543.     GEM hung whenever we have control.
  544. */
  545.     wind_update(BEG_UPDATE);    /* Shuts off GEM drawing */
  546.     wind_update(BEG_MCTRL);        /* Shuts off GEM use of mouse */
  547.  
  548.     mctrl = 0;            /* Flag that we have mouse control */
  549.     kt = Keytbl( -1L, -1L, -1L);
  550.  
  551.     ttopen();
  552.     eolexist = TRUE;
  553.  
  554.     /* save the current color palette */
  555.     for (i=0; i<16; i++)
  556.         spalette[i] = xbios(SETCOLOR, i, -1);
  557.  
  558.     /* and find the current resolution */
  559.     initrez = currez = xbios(GETREZ);
  560.     strcpy(sres, resname[currez]);
  561.  
  562.     /* set up the screen size and palette */
  563.     switch (currez) {
  564.         case 0: term.t_mrow = 25 - 1;
  565.             term.t_nrow = 25 - 1;
  566.             term.t_ncol = 40;
  567.             strcpy(palstr, LOWPAL);
  568.             break;
  569.  
  570.         case 1: term.t_mrow = 25 - 1;
  571.             term.t_nrow = 25 - 1;
  572.             strcpy(palstr, MEDPAL);
  573.             break;
  574.  
  575.         case 2: term.t_mrow = DENSIZE - 1;
  576.             term.t_nrow = 25 - 1;
  577.             strcpy(palstr, HIGHPAL);
  578.     }
  579.  
  580.     /* and set up the default palette */
  581.     spal(palstr);
  582.  
  583.     stputc(ESC);    /* automatic overflow off */
  584.     stputc('w');
  585.  
  586.     /* initialize the input buffer */
  587.     in_init();
  588. }
  589.  
  590. stkclose()    /* close the keyboard (and mouse) */
  591. {
  592. }
  593.  
  594. stclose()
  595.  
  596. {
  597.     stputc(ESC);    /* auto overflow on */
  598.     stputc('v');
  599.  
  600.     /* restore the original screen resolution */
  601.     if (currez == 3)
  602.         switch_font(system_font);
  603.     strez(resname[initrez]);
  604.  
  605.     /* restore the original palette settings */
  606.     xbios(SETPALETTE, spalette);
  607.  
  608.     ttclose();
  609.  
  610.     kv->kb_mousevec = second_mhandler;    /* Restore original handler */
  611.  
  612.     mouse_on();        /* turn the mouse on */
  613.     if (gemflag != 0) {
  614.         /* coming from gem..... we */
  615.         Cursconf(0, 0);        /* turn the cursor off */
  616.     } else {
  617.         /* coming from a shell, we */
  618.         Cursconf(1, 0);        /* turn the cursor on */
  619.         Cursconf(2, 0);        /* Turn text cursor blinking */
  620.         hidemouse();        /* Turn mouse off for shell */
  621.     }
  622.  
  623.     wind_update(END_MCTRL);        /* Return GEM's control of screen */
  624.     wind_update(END_UPDATE);
  625. #if    0
  626.     v_clsvwk(wkid);            /* Clean up GEM */
  627. #endif
  628.     appl_exit();
  629. }
  630.  
  631. /*    spal(pstr):    reset the current palette according to a
  632.             "palette string" of the form
  633.  
  634.     000111222333444555666777
  635.  
  636.     which contains the octal values for the palette registers
  637. */
  638.  
  639. spal(pstr)
  640.  
  641. char *pstr;    /* palette string */
  642.  
  643. {
  644.     int pal;    /* current palette position */
  645.     int clr;    /* current color value */
  646.     int i;
  647.  
  648.     for (pal = 0; pal < 16; pal++) {
  649.         if (*pstr== 0)
  650.             break;
  651.  
  652.         /* parse off a color */
  653.         clr = 0;
  654.         for (i = 0; i < 3; i++)
  655.             if (*pstr)
  656.                 clr = clr * 16 + (*pstr++ - '0');
  657.         palette[pal] = clr;
  658.     };
  659.  
  660.     /* and now set it */
  661.     xbios(SETPALETTE, palette);
  662. }
  663.  
  664. static domousekey(newbut, sk)
  665.  
  666. int sk;
  667.  
  668. {
  669.     register int k;
  670.  
  671.     for(k=1; k!=4; k = k<<1) {    /* J is butnum, k is bit num */ 
  672.         /* For each button on the mouse */
  673.         if ((oldbut&k) != (newbut&k)) {
  674.             /* This button changed, generate an event */
  675.             in_put(0);        /* escape indicator */
  676.             in_put(MOUS >> 8);    /* mouse event */
  677.             in_put(mousecol);    /* x-position */
  678.             in_put(mouserow);    /* y-position */
  679.             in_put(((newbut&k) ? 0 : 1)
  680.                 + (k==1 ? 4 : 0)
  681.                 + ((sk&3) ? 'A' : 'a'));
  682.         }
  683.     }
  684.     oldbut = newbut;
  685. }
  686.  
  687. stgetc()    /* get a char from the keyboard */
  688.  
  689. {
  690.     register int flashcounter;    /* Counter for flashing cursor */
  691.     register int ev_which;        /* Event returned */
  692.     register int sc;        /* Keyboard scan code */
  693.     static int bexpected = 1;    /* Expected next mouse state */
  694.     int mx, my, bstate, sk, key, mc;/* Event parameters */
  695.     int mes[8];
  696.  
  697.     /* Working out a multi-byte input sequence */
  698.     if (in_check())
  699.         return(in_get());
  700.  
  701.     Cursconf(1, 0);        /* Turn text cursor on */
  702.     mouse_on();        /* Let mouse work */
  703.     wind_update(END_UPDATE);
  704.     if (mctrl)
  705.         wind_update(END_MCTRL);
  706.     flashcounter = 0;
  707.     for(;;) {
  708.         if (!mctrl) {
  709.             /* We have control, so it is okay to flash cursor */
  710.             if (flashcounter == 6) {
  711.                 mouse_off();
  712.                 Cursconf(0, 0); /* After 60ms, turn it off */
  713.                 mouse_on();
  714.             } else if (flashcounter == 10) {
  715.                 /* Wrapped around one cycle of cursor flashing,
  716.                    turn it on */
  717.                 mouse_off();
  718.                 Cursconf(1, 0);
  719.                 mouse_on();
  720.                 flashcounter = 0;
  721.             }
  722.         }
  723.  
  724.         /* do the event-multi thing */
  725.         ev_which = evnt_multi(
  726.             MU_TIMER | MU_MESAG | MU_KEYBD | MU_BUTTON | MU_M1,
  727.             1,        /* Maximum clicks to wait for */
  728.             1,        /* Buttons that generate events */
  729.             bexpected,    /* Button states that generate events */
  730.             0, menu[1].ob_x, menu[1].ob_y,
  731.             menu[1].ob_width, menu[1].ob_height,
  732.             0, 0, 0, 0, 0,    /* enter/exit, x, y, w, h for rect 2 */
  733.             mes,        /* Buffer to receive mesasge */
  734.             /* Low and high order miliseconds of counter */
  735.             100, 0,
  736.             &mx, &my,    /* Mouse location */
  737.             &bstate,    /* State of the mouse buttons */
  738.             &sk,        /* State of the shift keys */
  739.             &key,        /* Key pressed */
  740.             &mc);        /* Actual number of clicks */
  741.  
  742.         if (ev_which & MU_KEYBD) {
  743.             /* Keyboard events cause keystrokes, add SPC prefix to fn keys */
  744.             if (mctrl)
  745.                 wind_update(BEG_MCTRL);
  746.             Giaccess(0, 9+128);
  747.             Giaccess(0, 10+128);
  748.  
  749.             /* Cancel any double-clicking */
  750.             nclicks = 0;
  751.             mctrl = 0;
  752.  
  753.                  sc = key>>8;
  754.                 key &= 0xff;
  755.             extcode( sk, sc, key);
  756.         } else if (ev_which & MU_BUTTON) {
  757.             /* Mouse event, look at our actual mouse event */
  758.             int top, junk;
  759.             wind_get(0, WF_TOP, &top, &junk, &junk, &junk);
  760.             if (top == 0) {
  761.                 /* Desktop is top window,
  762.                    allow Emacs to continue */
  763.                 bexpected = (~bstate)&1;
  764.                 mousecol = mx/g_wchar;
  765.                 mouserow = my/g_hchar;
  766.                 while(msevntsiz > 0) {
  767.                     /* Process each queued event */
  768.                     domousekey(msevntq[msevntout++], sk);
  769.                     msevntout &= 15;
  770.                     msevntsiz--;
  771.                     }
  772.                 if (mctrl) wind_update(BEG_MCTRL);
  773.                 mctrl = 0;
  774.             }
  775.         } else if (ev_which & MU_M1) {
  776.             /* Mouse entered desk menu, allow it to appear */
  777.             if (!mctrl) wind_update(END_MCTRL);
  778.             mctrl = 1;
  779.             sgarbf = TRUE;
  780.         } else if (ev_which & MU_TIMER) {
  781.             flashcounter++;
  782.         } else {
  783.             /* Most likely is the about message */
  784.         }
  785.  
  786.         /* is there now a pending event? */
  787.         if (in_check()) {
  788.             key = in_get();
  789.             break;
  790.         }
  791.     }
  792.  
  793.     if (mctrl)
  794.         wind_update(BEG_MCTRL);
  795.     wind_update(BEG_UPDATE);
  796.     mouse_off();
  797.     Cursconf(0, 0);            /* Turn text cursor off */
  798.     return(key & 0xFF);
  799. }
  800.  
  801. stputc(c)    /* output char c to the screen */
  802.  
  803. char c;     /* character to print out */
  804.  
  805. {
  806.     bios(BCONOUT, CON, c);
  807. }
  808.  
  809. strez(newrez)    /* change screen resolution */
  810.  
  811. char *newrez;    /* requested resolution */
  812.  
  813. {
  814.     int nrez;    /* requested new resolution */
  815.  
  816.     /* first, decode the resolution name */
  817.     for (nrez = 0; nrez < 4; nrez++)
  818.         if (strcmp(newrez, resname[nrez]) == 0)
  819.             break;
  820.     if (nrez == 4) {
  821.         mlwrite(TEXT180);
  822. /*                      "%%No such resolution" */
  823.         return(FALSE);
  824.     }
  825.  
  826.     /* next, make sure this resolution is legal for this monitor */
  827.     if ((currez < 2 && nrez > 1) || (currez > 1 && nrez < 2)) {
  828.         mlwrite(TEXT181);
  829. /*                      "%%Resolution illegal for this monitor" */
  830.         return(FALSE);
  831.     }
  832.  
  833.     /* eliminate non-changes */
  834.     if (currez == nrez)
  835.         return(TRUE);
  836.  
  837.     /* finally, make the change */
  838.     switch (nrez) {
  839.         case 0: /* low resolution - 16 colors */
  840.             newwidth(TRUE, 40);
  841.             strcpy(palstr, LOWPAL);
  842.             xbios(SETSCREEN, -1L, -1L, 0);
  843.             g_wchar = g_hchar = 8;
  844.             break;
  845.  
  846.         case 1: /* medium resolution - 4 colors */
  847.             newwidth(TRUE, 80);
  848.             strcpy(palstr, MEDPAL);
  849.             xbios(SETSCREEN, -1L, -1L, 1);
  850.             g_wchar = g_hchar = 8;
  851.             break;
  852.  
  853.         case 2: /* High resolution - 2 colors - 25 lines */
  854.             newsize(TRUE, 25);
  855.             strcpy(palstr, HIGHPAL);
  856.             switch_font(system_font);
  857.             g_wchar = g_hchar = 16;
  858.             break;
  859.  
  860.         case 3: /* Dense resolution - 2 colors - 40 lines */
  861.             newsize(TRUE, DENSIZE);
  862.             strcpy(palstr, HIGHPAL);
  863.             switch_font(small_font);
  864.             g_wchar = g_hchar = 8;
  865.             break;
  866.     }
  867.  
  868.     /* and set up the default palette */
  869.     spal(palstr);
  870.     currez = nrez;
  871.     strcpy(sres, resname[currez]);
  872.  
  873.     stputc(ESC);    /* automatic overflow off */
  874.     stputc('w');
  875.     return(TRUE);
  876. }
  877.  
  878. /*    extcode:    resolve Atari-ST extended character codes
  879.             encoding the proper sequences into emacs
  880.             printable character specifications
  881. */
  882.  
  883. int extcode( sk, sc, key)
  884. unsigned sk;    /* Shift keys from event */
  885. unsigned sc;    /* ST scancode */
  886. unsigned key;    /* GEMDOS translation of the key */
  887.     {
  888.     int shift;    /* CAPS LOCK flag doesn't come from EVENT_MULTI */
  889.     unsigned code;    /* Build up special function code */
  890. /*
  891.     Identify any shit-key codes associated with this keystorke
  892. */
  893.     code = 0;
  894. /*
  895.     I don't know why, but for some reason the codes for ALT of top row and
  896.     for CTRL of left, right and HOME come up wrong, and this fixes them.
  897. */
  898.     if( sc == 0x77) sc = 0x47;
  899.     else if( sc == 0x73) sc = 0x4b;
  900.     else if( sc == 0x74) sc = 0x4d;
  901.     else if( sc > 0x76) sc -= 0x76;
  902. /*
  903.     Bring the shifted function key scan codes back into regular range
  904. */
  905.     if( sc >= 0x54 && sc <= 0x5d) sc -= (0x54-0x3B);
  906.     if( sk & K_ALT)
  907.     { /* ALT shift requires special handling */
  908.     code |= ALTD;
  909. /*
  910.     ALT of ordinary keys always returns '0' for the key.  Look up
  911.     the actual key as if ALT weren't there.
  912. */
  913.     shift = Getshift(-1);    /* Get state of shift keys (CAPS lock) */
  914. /*
  915.     Map the key to a normal keystroke.  Keypad keys are treated special,
  916.     everyone else is mapped using the installed keytables.  This
  917.     means it will work right on German and other keyboards.
  918. */
  919.     if( sk & K_CTRL) { code |= CTRL; key = kt->caps[ sc];}
  920.     else if( sk & 3) key = kt->shift[ sc];    /* shift */
  921.     else if( shift & 16) key = kt->caps[ sc];    /* Caps lock */
  922.     else key = kt->norm[ sc];
  923.     }
  924. /*
  925.     Peel of the numeric keypad keys
  926. */
  927.     if( sc == 0x72) key = 'E';
  928.     if( sc >= 0x63 || sc == 0x4A || sc == 0x4E)
  929.     { /* Keypad keys are SPEC or CTRL of what's on the key */
  930.     code |= SPEC | CTRL;
  931.     }
  932. /*
  933.     translate function keys into digits
  934. */
  935.     if( sc >= 0x3b && sc <= 0x5d)
  936.     { /* This is a F1 thry F9 */
  937.     code |= SPEC;
  938.     key = sc - 0x3b + '1';
  939.     if( key == '9'+1) key = '0';
  940.     }
  941.     if( sc == 0x62) { code |= SPEC; key = 'H';}
  942.     if( sc == 0x61) { code |= SPEC; key = 'X';}
  943.     if( sc == 0x52) { code |= SPEC; key = 'C';}
  944.     if( sc == 0x47) { code |= SPEC; key = 'D';}
  945.     if( sc == 0x48) { code |= SPEC; key = 'P';}
  946.     if( sc == 0x4b) { code |= SPEC; key = 'B';}
  947.     if( sc == 0x50) { code |= SPEC; key = 'N';}
  948.     if( sc == 0x4d) { code |= SPEC; key = 'F';}
  949. /*
  950.     translate CTRL-shifted of keys that don't usually CTRL
  951. */
  952.     if((sk & K_CTRL) && (sc <= 0x0D || key == 0))
  953.     { /* Control of a non-usually-control key */
  954.     shift = Getshift(-1);    /* Get state of CAPS lock */
  955.     code |= CTRL;
  956.     if( sk & 3) key = kt->shift[ sc];        /* shift */
  957.     else if( shift & 16) key = kt->caps[ sc];    /* Caps lock */
  958.     else key = kt->norm[ sc];
  959.     }
  960.     if( key == 0) key = '@';                /* Catch junk */
  961.     if( code != 0)
  962.     { /* This is a special key */
  963.     if( code & SPEC)
  964.         { /* Get shift and ctrl of function keys */
  965.         if( sk & 3) code |= SHFT;
  966.         if( sk & K_CTRL) code |= CTRL;
  967.         }
  968.     in_put( 0);
  969.     in_put( code>>8);
  970.     in_put( key);
  971.     }
  972.     else in_put( key);
  973.     }
  974.  
  975. #if    FLABEL
  976. fnclabel(f, n)        /* label a function key */
  977.  
  978. int f,n;    /* default flag, numeric argument [unused] */
  979.  
  980. {
  981.     /* on machines with no function keys...don't bother */
  982.     return(TRUE);
  983. }
  984. #endif
  985. #else
  986. sthello()
  987. {
  988. }
  989. #endif
  990.