home *** CD-ROM | disk | FTP | other *** search
/ Garbo / Garbo.cdr / pc / memacs / ue311c.arc / ST520.C < prev    next >
C/C++ Source or Header  |  1990-08-16  |  25KB  |  986 lines

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