home *** CD-ROM | disk | FTP | other *** search
/ Geek Gadgets 1 / ADE-1.bin / ade-dist / emacs-19.28-src.tgz / tar.out / fsf / emacs / src / amiga_screen.c < prev    next >
C/C++ Source or Header  |  1996-09-28  |  50KB  |  1,855 lines

  1. #include "config.h"
  2. #include "lisp.h"
  3. #include "termchar.h"
  4. #include "dispextern.h"
  5. #include "termhooks.h"
  6. #include "frame.h"
  7.  
  8. #include <stdio.h>
  9. #include <string.h>
  10. #include <stddef.h>
  11. #include <sys/time.h>
  12. #include <internal/devices.h>
  13. #include <internal/vars.h>
  14.  
  15. #define min(x,y) ((x) > (y) ? (y) : (x))
  16. #define max(x,y) ((x) < (y) ? (y) : (x))
  17.  
  18. #undef LONGBITS
  19.  
  20. #include <exec/types.h>
  21. #include <exec/interrupts.h>
  22. #include <devices/input.h>
  23. #include <devices/inputevent.h>
  24. #include <intuition/intuitionbase.h>
  25. #include <intuition/intuition.h>
  26. #include <devices/conunit.h>
  27. #include <devices/inputevent.h>
  28. #include <graphics/gfxbase.h>
  29. #include <graphics/gfxmacros.h>
  30. #include <utility/hooks.h>
  31. #include <workbench/startup.h>
  32. #include <workbench/workbench.h>
  33. #include <libraries/asl.h>
  34.  
  35. #include <proto/exec.h>
  36. #include <proto/dos.h>
  37. #include <proto/intuition.h>
  38. #include <proto/graphics.h>
  39. #include <proto/console.h>
  40. #include <proto/diskfont.h>
  41. #include <proto/wb.h>
  42. #include <proto/asl.h>
  43.  
  44. /* this is defined for those unlucky enough
  45.  * not to have the 3.0 headers  -ch3/16/93. */
  46. #ifndef WA_NewLookMenus
  47. #define WA_NewLookMenus (WA_Dummy + 0x30)
  48. #endif
  49.  
  50. #include "amiga.h"
  51.  
  52. #ifdef USE_PROTOS
  53. #include "protos.h"
  54. #endif
  55.  
  56. void screen_puts(FRAME_PTR f, char *str, unsigned int len);
  57.  
  58. /* CHFIXME: amiga.h */
  59. extern int map_menu_selection(int menu_num, int item_num, int subitem_num, Lisp_Object *subprefixes);
  60.  
  61. #define SHIFT_MASK (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT)
  62. #define CONTROL_MASK IEQUALIFIER_CONTROL
  63. /* CHFIXME: check other usages of META_MASK for need of NO_SNAP_MASK */
  64. #define META_MASK (IEQUALIFIER_LALT)
  65. /* CHFIXME: need input from others if using
  66.  * IEQUALIFIER_RELATIVEMOUSE make something fail
  67.  * IEQUALIFIER_RELATIVEMOUSE is set on normal typing but not
  68.  * when snapped characters are inserted (e.g. via snap or powersnap)
  69.  * these snappers use LALT as qualifier but don\'t want it to mean
  70.  * META
  71.  */
  72. #define NO_SNAP_MASK (IEQUALIFIER_RELATIVEMOUSE)
  73.  
  74. struct GfxBase *GfxBase;
  75. struct IntuitionBase *IntuitionBase;
  76. struct Library *DiskfontBase, *KeymapBase, *WorkbenchBase;
  77.  
  78. static char intkey_code, intkey_qualifier;
  79. static struct IOStdReq *input_req;
  80. static struct Interrupt int_handler_hook;
  81. static int hooked;
  82.  
  83. static struct MsgPort *wbport;
  84. static struct AppWindow *emacs_app_win;
  85. static struct AppIcon *emacs_icon;
  86.  
  87. struct Library *ConsoleDevice;
  88. static struct TextFont *font;
  89. static int font_opened;
  90. /* The reset string resets the console, turns off scrolling and sets up
  91.    the foreground & background colors. */
  92. #define CONSOLE_RESET "\x1b""c\x9b>1l\x9b""3%d;4%d;>%dm"
  93. static char reset_string[20]; /* Must be big enough for
  94.               printf(CONSOLE_RESET, foreground, background, background);
  95.               (0 <= foreground, background <= 7) */
  96.  
  97. /* These are the pen numbers for emacs window's base colors */
  98. int foreground = 1, background = 0;
  99.  
  100. /* Current window, and its main characteristics */
  101. #if 0
  102. struct Window *EMACS_WIN(f);
  103. #endif
  104. WORD emacs_x = 0, emacs_y = 0, emacs_w = 640, emacs_h = 200;
  105. char *emacs_screen_name;
  106. /* a storage area for the name of the screen last opened on */
  107. char emacs_screen_name_storage[MAXPUBSCREENNAME+1];
  108. int emacs_backdrop = 0;        /* Use backdrop window ? */
  109.  
  110. /* Current window size: */
  111. #define EMACS_X(f) (EMACS_WIN(f) ? EMACS_WIN(f)->LeftEdge : emacs_x)
  112. #define EMACS_Y(f) (EMACS_WIN(f) ? EMACS_WIN(f)->TopEdge : emacs_y)
  113. #define EMACS_W(f) (EMACS_WIN(f) ? EMACS_WIN(f)->Width : emacs_w)
  114. #define EMACS_H(f) (EMACS_WIN(f) ? EMACS_WIN(f)->Height : emacs_h)
  115.  
  116. /* used for setting the color of standout text  -ch3/16/93. */
  117. int inverse_fill_pen = 8, inverse_text_pen = 8;
  118.  
  119. /* IO request for all console io. */
  120. #ifndef MULTI_FRAME
  121. static struct IOStdReq *emacs_console;
  122. #else
  123. you lose
  124. #endif
  125.  
  126. #define emacs_icon_width 57
  127. #define emacs_icon_height 55
  128. #define emacs_icon_num_planes 1
  129. #define emacs_icon_words_per_plane 220
  130.  
  131. UWORD chip emacs_icon_data[1][55][4] = {
  132.   {
  133.     0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  134.     0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  135.     0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0fe0,0x6000,
  136.     0x0000,0x0000,0x0060,0x6000,0x0000,0x0000,0x0fff,0xe000,
  137.     0x0000,0x0000,0x1800,0x2000,0x0000,0x0000,0x13ff,0xa000,
  138.     0x0000,0x0000,0x1400,0xa000,0x0000,0x0000,0x3600,0xa000,
  139.     0x0000,0x0000,0x0000,0xa000,0x0000,0x0000,0x0c00,0xa000,
  140.     0x0000,0x0000,0x1e00,0xa000,0x0000,0x0000,0x0c00,0xa000,
  141.     0x0000,0x0000,0x0000,0xa000,0x0000,0x0000,0x2100,0xa000,
  142.     0x0000,0x0000,0x3300,0xa000,0x0000,0x0000,0x0c00,0xa000,
  143.     0x003f,0xffff,0xffff,0xb000,0x001f,0xffff,0xffff,0x8000,
  144.     0x004e,0x0000,0x0001,0xf000,0x00c6,0x00f0,0x0001,0x8000,
  145.     0x00c6,0x0100,0x0001,0x8000,0x0006,0x0103,0x9201,0x8000,
  146.     0x0006,0x013a,0x5201,0x8000,0x00c6,0x010a,0x5201,0x8000,
  147.     0x00c6,0x010a,0x5601,0x8000,0x0086,0x00f2,0x4a01,0x8000,
  148.     0x0006,0x0000,0x0001,0x8000,0x0046,0x0000,0x0001,0x8000,
  149.     0x00c6,0x7c00,0x0001,0x8000,0x00c6,0x4000,0x0001,0x8000,
  150.     0x0006,0x41d8,0xc319,0x8000,0x0006,0x7925,0x24a1,0x8000,
  151.     0x00c6,0x4125,0x2419,0x8000,0x01c6,0x4125,0x2485,0x8000,
  152.     0x0086,0x7d24,0xd319,0x8000,0x0007,0x0000,0x0003,0x8000,
  153.     0x0003,0xffe3,0xffff,0x0000,0x0081,0xfff7,0xfffe,0x0000,
  154.     0x01c0,0x0036,0x0000,0x0000,0x0180,0x0014,0x0f80,0x0000,
  155.     0x0000,0x0014,0x1040,0x0000,0x0000,0x0014,0x2720,0x0000,
  156.     0x0000,0x0012,0x28a0,0x0000,0x0080,0x000a,0x48a0,0x0000,
  157.     0x01c0,0x0009,0x90a0,0x0000,0x0180,0x0004,0x20a0,0x0000,
  158.     0x0000,0x0003,0xc0a0,0x0000,0x0000,0x0000,0x00a0,0x0000,
  159.     0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  160.     0x0000,0x0000,0x0000,0x0000
  161.   },
  162. };
  163.  
  164. struct Image far emacs_icon_image = {
  165.   0, 0,
  166.   emacs_icon_width, emacs_icon_height, emacs_icon_num_planes,
  167.   (UWORD *)emacs_icon_data,
  168.   3, 0,
  169.   0
  170. };
  171.  
  172. static struct DiskObject far emacs_icon_object = {
  173.   0, 0,
  174.   { 0, 0, 0, emacs_icon_width, emacs_icon_height, 0, 0, 0, (APTR)&emacs_icon_image },
  175.   0, 0, 0,
  176.   NO_ICON_POSITION, NO_ICON_POSITION
  177. };
  178.  
  179. static struct Hook background_hook;
  180.  
  181. #define TRY_NEW_MOUSE /* CHFIXME */
  182.  
  183. #define EVENTSIZE 32
  184.  
  185. static struct event {
  186.   ULONG class;
  187.   UWORD code, qual;
  188.   WORD x, y;
  189. } events[EVENTSIZE];
  190. static int event_num, event_in, event_out;
  191.  
  192. static struct wbevent {
  193.   struct wbevent *next;
  194.   char file[1];
  195. } *wbevents;
  196.  
  197. Lisp_Object Vamiga_mouse_pos;
  198. Lisp_Object Vamiga_mouse_item;
  199. extern Lisp_Object MouseMap;
  200. int amiga_remap_bsdel;
  201. int amiga_remap_numeric_keypad;
  202. int amiga_mouse_initialized;
  203. int amiga_wb_initialized;
  204. int emacs_iconified;
  205. static int mouse_event; /* set if mouse_event happened */
  206.  
  207. int
  208. mouse_event_pending()
  209. {
  210.     return mouse_event>0;
  211. }
  212. void
  213. reset_mouse_event_pending()
  214. {
  215.     mouse_event = 0;
  216. }
  217.  
  218. void
  219. set_mouse_event_pending()
  220. {
  221.     mouse_event = 1;
  222. }
  223.  
  224. static int amiga_pos_x(FRAME_PTR f, int x)
  225. {
  226.   return (x - EMACS_WIN(f)->BorderLeft) / EMACS_WIN(f)->RPort->Font->tf_XSize;
  227. }
  228.  
  229. static int amiga_pos_y(FRAME_PTR f, int y)
  230. {
  231.   return (y - EMACS_WIN(f)->BorderTop) / EMACS_WIN(f)->RPort->Font->tf_YSize;
  232. }
  233.  
  234. void
  235. glyph_to_pixel_coords(FRAME_PTR f, int col, int row, int *pixcol, int *pixrow)
  236. {
  237.     *pixcol = (col * EMACS_WIN(f)->RPort->Font->tf_XSize) + EMACS_WIN(f)->BorderLeft;
  238.     *pixrow = (row * EMACS_WIN(f)->RPort->Font->tf_YSize) + EMACS_WIN(f)->BorderTop;
  239. }
  240.  
  241. /* Given a pixel position (PIX_X, PIX_Y) on the frame F, return
  242.    glyph co-ordinates in (*X, *Y).  Set *BOUNDS to the rectangle
  243.    that the glyph at X, Y occupies, if BOUNDS != 0.
  244.    If NOCLIP is nonzero, do not force the value into range.  */
  245.  
  246. void
  247. pixel_to_glyph_coords(FRAME_PTR f, int pixcol, int pixrow, int *col, int *row,
  248.               void *bounds, int noclip)
  249. {
  250.     int acol, arow;
  251.  
  252.     /* Arrange for the division in amiga_pos_x etc. to round down
  253.        even for negative valuse. */
  254.     if(pixcol < 0)
  255.     pixcol -= EMACS_WIN(f)->RPort->Font->tf_XSize -1; /* CHFIXME: use FONT_WIDTH */
  256.     if(pixrow < 0)
  257.     pixrow -= EMACS_WIN(f)->RPort->Font->tf_YSize -1; /* CHFIXME: use FONT_HEIGH */
  258.     acol = amiga_pos_x(f, pixcol);
  259.     arow = amiga_pos_y(f, pixrow);
  260.     /* no bounds if not MULTI_FRAME */
  261.     if(!noclip)
  262.     {
  263.     if(acol < 0) acol = 0;
  264.     if(arow < 0) arow = 0;
  265.     if(acol > FRAME_WIDTH(f)) acol = FRAME_WIDTH(f);
  266.     if(arow > FRAME_HEIGHT(f)) arow = FRAME_HEIGHT(f);
  267.     }
  268.     *col = acol;
  269.     *row = arow;
  270. }
  271.  
  272. extern int waiting_for_input; /* CHFIXME */
  273. extern int frame_garbaged;
  274.  
  275. static void amiga_change_size(FRAME_PTR f)
  276. {
  277.   int new_height = amiga_pos_y(f, EMACS_WIN(f)->Height - EMACS_WIN(f)->BorderBottom);
  278.   int new_width = amiga_pos_x(f, EMACS_WIN(f)->Width - EMACS_WIN(f)->BorderRight);
  279.  
  280.   /* Is this true for Emacs 19.28?
  281.      I consider that refreshes are possible during a select, which is
  282.      true for the current state of emacs */
  283.   change_frame_size(selected_frame, new_height, new_width, 0,
  284.             !selecting && !waiting_for_input);
  285.  
  286.   /* Force redisplay */
  287.   SET_FRAME_GARBAGED(selected_frame);
  288. }
  289.  
  290. /* Get terminal size from system.
  291.    Store number of lines into *heightp and width into *widthp.
  292.    If zero is stored, the value is not valid.  */
  293.  
  294. void amiga_get_window_size (FRAME_PTR f, int *widthp, int *heightp)
  295. {
  296.   if (EMACS_WIN(f))
  297.     {
  298.       *heightp = amiga_pos_y(f, EMACS_WIN(f)->Height - EMACS_WIN(f)->BorderBottom);
  299.       *widthp = amiga_pos_x(f, EMACS_WIN(f)->Width - EMACS_WIN(f)->BorderRight);
  300.     }
  301.   else
  302.     {
  303.       *heightp = 0;
  304.       *widthp = 0;
  305.     }
  306. }
  307.  
  308. static int set_min_size(struct Window *win, struct TextFont *font,
  309.             WORD *minw, WORD *minh)
  310. {
  311.   *minw = 11 * font->tf_XSize + win->BorderLeft + win->BorderRight;
  312.   *minh = 4 * font->tf_YSize + win->BorderTop + win->BorderBottom;
  313.  
  314.   return (int)WindowLimits(win, *minw, *minh, 0, 0);
  315. }
  316.  
  317. struct fill
  318. {
  319.   struct Layer *layer;
  320.   struct Rectangle bounds;
  321.   WORD offsetx, offsety;
  322. };
  323.  
  324. /* __interrupt disables stack checking.   -ch3/19/93. */
  325. static ULONG __asm __saveds __interrupt
  326. fill_background(register __a2 struct RastPort *obj,
  327.         register __a1 struct fill *msg)
  328. {
  329.   struct Layer *l;
  330.  
  331.   SetAPen(obj, background);
  332.   SetDrMd(obj, JAM1);
  333.   SetAfPt(obj, 0, 0);
  334.   SetWrMsk(obj, 0xff);
  335.   /* Gross hack starts here */
  336.   l = obj->Layer;
  337.   obj->Layer = 0;
  338.   /* Stops */
  339.   RectFill(obj, msg->bounds.MinX, msg->bounds.MinY,
  340.        msg->bounds.MaxX, msg->bounds.MaxY);
  341.   /* Starts again */
  342.   obj->Layer = l;
  343.   /* And finally dies */
  344.  
  345.   return 0;
  346. }
  347.  
  348. static void clear_window(FRAME_PTR f)
  349. {
  350.   SetAPen(EMACS_WIN(f)->RPort, background);
  351.   RectFill(EMACS_WIN(f)->RPort, EMACS_WIN(f)->BorderLeft, EMACS_WIN(f)->BorderTop,
  352.        EMACS_WIN(f)->Width - EMACS_WIN(f)->BorderRight - 1,
  353.        EMACS_WIN(f)->Height - EMACS_WIN(f)->BorderBottom - 1);
  354. }
  355.  
  356. static int make_reset_string(void)
  357. {
  358.   sprintf(reset_string, CONSOLE_RESET, foreground, background, background);
  359. }
  360.  
  361. void reset_window(FRAME_PTR f)
  362. {
  363.   make_reset_string();
  364.   if (EMACS_WIN(f))
  365.     {
  366.       screen_puts (f, reset_string, strlen(reset_string));
  367.       clear_window(f);
  368.       amiga_change_size (f);
  369.     }
  370. }
  371.  
  372. static void close_app_win(void)
  373. {
  374.   if (emacs_app_win)
  375.     {
  376.       struct AppMessage *msg;
  377.  
  378.       RemoveAppWindow(emacs_app_win); /* What can I do if it fails ?! */
  379.       while (msg = (struct AppMessage *)GetMsg(wbport)) ReplyMsg(msg);
  380.     }
  381. }
  382.  
  383. #ifdef MULTI_FRAME
  384. you lose!
  385. #endif
  386.  
  387. static int close_emacs_window(FRAME_PTR f)
  388. {
  389.   close_app_win();
  390.   inputsig &= ~(1L << EMACS_WIN(f)->UserPort->mp_SigBit);
  391.   _device_close(emacs_console);
  392.   if(EMACS_WIN(f))
  393.     {
  394.       /* put title back the way it should be   -ch3/19/93. */
  395.       ShowTitle(EMACS_WIN(f)->WScreen, !emacs_backdrop);
  396.     }
  397.   CloseWindow(EMACS_WIN(f));
  398.   emacs_console = 0;
  399.   EMACS_WIN(f) = 0;
  400.   ConsoleDevice = 0;
  401. }
  402.  
  403. /* We need this function because we do not always have the string
  404.  * for the screen we opened on. for example LockPubScreen(NULL);
  405.  * This function will get the name by looping through all public
  406.  * screens looking for the one that matches ours. -ch3/20/93 */
  407.  
  408. char *get_screen_name(struct Screen *this, char *namebuf)
  409. {
  410.   struct PubScreenNode *pubscreens =
  411.     (struct PubScreenNode *)LockPubScreenList()->lh_Head;
  412.  
  413.   while (pubscreens->psn_Node.ln_Succ)
  414.     {
  415.       if (pubscreens->psn_Screen == this)
  416.     {
  417.       strcpy(namebuf, pubscreens->psn_Node.ln_Name);
  418.       UnlockPubScreenList();
  419.       return namebuf;
  420.     }
  421.       pubscreens = (struct PubScreenNode *)pubscreens->psn_Node.ln_Succ;
  422.     }
  423.   /* Failed to find screen */
  424.   namebuf[0] = '\0';
  425.   UnlockPubScreenList();
  426.  
  427.   return 0;
  428. }
  429.  
  430. enum open_emacs_win_ret { ok, no_screen, no_window };
  431.  
  432. /* added two parameters to eliminate the need for the global
  433.  * which was causing some unwanted effect (bugs). -ch3/19/93 */
  434.  
  435. static enum open_emacs_win_ret
  436. open_emacs_window(FRAME_PTR f, UWORD x, UWORD y, UWORD w, UWORD h, int backdrop,
  437.           char *pubscreen_name)
  438.      /* Open or reopen emacs window */
  439. {
  440.   WORD minw, minh;
  441.   struct Screen *new_screen;
  442.   struct Window *new_win;
  443.   struct IOStdReq *new_console;
  444.   int no_backdrop = !backdrop;
  445.  
  446.   new_screen = LockPubScreen(pubscreen_name);
  447.  
  448.   if (!new_screen)
  449.     return no_screen;
  450.  
  451.   /* removed newwindow structure, and added as tag
  452.    * items so that we can change them easier. -ch3/16/93. */
  453.  
  454.   new_win = OpenWindowTags(0, WA_Left, x, WA_Top, y,
  455.                   WA_Width, w, WA_Height, h,    /* Static items */
  456.                   WA_AutoAdjust, 1, WA_NewLookMenus, 1,
  457.                   WA_IDCMP, IDCMP_CLOSEWINDOW | IDCMP_RAWKEY |
  458.                             IDCMP_MOUSEBUTTONS| IDCMP_NEWSIZE |
  459.                             IDCMP_MENUPICK | IDCMP_MENUHELP,
  460.                   WA_PubScreen, new_screen,
  461. #if 0 /* CHFIXME: debugging aid */
  462.                   WA_BackFill, &background_hook,
  463. #endif
  464.                   WA_MenuHelp, 1, WA_Activate, 1,
  465.                   WA_SimpleRefresh, 1,
  466.                   WA_MaxWidth, -1, WA_MaxHeight, -1,
  467.                   WA_Backdrop, backdrop,    /* changing items */
  468.                   WA_Borderless, backdrop,
  469.                   WA_CloseGadget, no_backdrop,
  470.                   WA_SizeGadget, no_backdrop,
  471.                   WA_DragBar, no_backdrop,
  472.                   WA_DepthGadget, no_backdrop,
  473.                   WA_Title, no_backdrop ?
  474.                    "GNU Emacs 19.28, Amiga port "VERS : 0,
  475.                               TAG_END, 0);
  476.  
  477.   UnlockPubScreen(0L, new_screen);
  478.  
  479.   if (new_win)
  480.     {
  481.       /* if emacs_backdrop then the screen title will show BEHIND the window
  482.      -ch3/16/93. */
  483.       ShowTitle(new_screen, !emacs_backdrop);
  484.       SetFont(new_win->RPort, font);
  485.  
  486.       if (set_min_size(new_win, font, &minw, &minh) &&
  487.       (new_console = (struct IOStdReq *)
  488.        _device_open("console.device", CONU_CHARMAP, CONFLAG_NODRAW_ON_NEWSIZE,
  489.             (APTR)new_win, sizeof(*new_win),
  490.             sizeof(struct IOStdReq))))
  491.     {
  492.       inputsig |= 1L << new_win->UserPort->mp_SigBit;
  493.       ConsoleDevice = (struct Library *)new_console->io_Device;
  494. #if 0 /* CHFIXME */
  495.       emacs_app_win = AddAppWindowA(0, 0, new_win, wbport, 0);
  496. #endif
  497.       /* Copy the info into permanent storage */
  498.       EMACS_WIN(f) = new_win;
  499.       emacs_console = new_console;
  500.  
  501.       /* fetch the name of the current screen -ch3/19/93 */
  502.       emacs_screen_name = get_screen_name(EMACS_WIN(f)->WScreen,
  503.                           emacs_screen_name_storage);
  504.  
  505.       emacs_backdrop = backdrop;
  506.  
  507.       reset_window(f);
  508.  
  509.       return ok;
  510.     }
  511.       CloseWindow(new_win);
  512.     }
  513.   return no_window;
  514. }
  515.  
  516. void force_window(FRAME_PTR f)
  517. {
  518.   if (!EMACS_WIN(f) && !emacs_iconified)
  519.     {
  520.       if (open_emacs_window(f, emacs_x, emacs_y, emacs_w, emacs_h, emacs_backdrop,
  521.                 emacs_screen_name) != ok)
  522.     {
  523.       /* Try to return to defaults (Workbench, etc) */
  524.       if (open_emacs_window(f, 0, 0, 640, 200, 0, 0) != ok)
  525.           _fail("I've lost my window ! Exiting.");
  526.     }
  527.       resume_menus(f);
  528.     }
  529. }
  530.  
  531.  
  532. #define X_left  0xff51
  533. #define X_up    0xff52
  534. #define X_right 0xff53
  535. #define X_down  0xff54
  536. #define X_help  0xff6a    /* X11 code of the help key */
  537. #define X_f1    0xffbe     /* X11 code of f1 (f2, ..., f35 follow) */
  538.  
  539. /* returns:
  540.  *    -2 if msg is not class RAWKEY
  541.  *    same as RawKeyConvert otherwise:
  542.  *    buffer length if <= kbsize
  543.  *    -1 else
  544.  *
  545.  * fkeyflags[x] will be set to a function key if any
  546.  * the decoding is done ala x (see keyboard.c)
  547.  */
  548. static DeadKeyConvert(struct IntuiMessage *msg, UBYTE *kbuffer, USHORT *fkeyflags,
  549.               int kbsize,
  550.               struct KeyMap *kmap)
  551. {
  552.   static struct InputEvent ievent = {0, IECLASS_RAWKEY, 0, 0, 0};
  553.   int extra = 0, res;
  554.  
  555.   if (msg->Class != RAWKEY)
  556.   {
  557. #if 0
  558.       fprintf(stderr,"msg->Class = %d\n", (int) msg->Class);
  559. #endif
  560.       return (-2);
  561.   }
  562.  
  563.   /* Do some keymapping ourselves to make emacs users happy */
  564.  
  565.   switch(msg->Code)
  566.   {
  567.  case 0x40:
  568.       /* Ctrl-space becomes Ctrl-@ */
  569.       if (msg->Qualifier & CONTROL_MASK)
  570.       {
  571.       *kbuffer = 0;
  572.       *fkeyflags = 0;
  573.       return 1;
  574.       }
  575.       break;
  576.  case 0x41:
  577.       /* Backspace becomes DEL */
  578.       if (amiga_remap_bsdel)
  579.       {
  580.       *kbuffer = 0177;
  581.       *fkeyflags = 0;
  582.       return 1;
  583.       }
  584.       break;
  585.  case 0x46:
  586.       /* And DEL becomes CTRL-D */
  587.       if (amiga_remap_bsdel)
  588.       {
  589.       *kbuffer = 04;
  590.       *fkeyflags = 0;
  591.       return 1;
  592.       }
  593.       break;
  594.  case 0x4C: /* Up arrow */
  595.       *kbuffer = 0;
  596.       *fkeyflags = X_up;
  597.       return 1;
  598.  case 0x4D: /* Down arrow */
  599.       *kbuffer = 0;
  600.       *fkeyflags = X_down;
  601.       return 1;
  602.  case 0x4E: /* Forward arrow */
  603.       *kbuffer = 0;
  604.       *fkeyflags = X_right;
  605.       return 1;
  606.  case 0x4F: /* Backward arrow */
  607.       *kbuffer = 0;
  608.       *fkeyflags = X_left;
  609.       return 1;
  610.  case 0x50:
  611.  case 0x51:
  612.  case 0x52:
  613.  case 0x53:
  614.  case 0x54:
  615.  case 0x55:
  616.  case 0x56:
  617.  case 0x57:
  618.  case 0x58:
  619.  case 0x59:
  620.       /* Map function keys to X equivalent */
  621.       *kbuffer = 0;
  622.       *fkeyflags = msg->Code - 0x50 + X_f1;
  623.       return 1;
  624.  case 0x5F:
  625.       /* Map help key */
  626.       *kbuffer = 0;
  627.       *fkeyflags = X_help;
  628.       return 1;
  629. default:
  630.       break;
  631.   }
  632.   /* CHFIXME: may be replaced with kp-XXX symbols */
  633.   /* Stick numeric pad prefix in front of numeric keypad chars */
  634.   if (msg->Qualifier & IEQUALIFIER_NUMERICPAD && amiga_remap_numeric_keypad)
  635.     {
  636.       *kbuffer++ = 'x' & 037;
  637.       *fkeyflags++=0;
  638.       *kbuffer++ = '^' & 037;
  639.       *fkeyflags++=0;
  640.       *kbuffer++ = 'K';
  641.       *fkeyflags++=0;
  642.       kbsize -= 3;
  643.       extra = 3;
  644.     }
  645.  
  646.   /* pack input event */
  647.   ievent.ie_Code = msg->Code;
  648.  
  649.   /* Ignore meta in decoding keys when not snapping */
  650.   /* CHFIXME: if() needed below, too? */
  651.   if(msg->Qualifier & NO_SNAP_MASK)
  652.     ievent.ie_Qualifier = msg->Qualifier & ~META_MASK;
  653.   else
  654.     ievent.ie_Qualifier = msg->Qualifier;
  655.  
  656.   /* get previous codes from location pointed to by IAddress
  657.    *  this pointer is valid until IntuiMessage is replied.
  658.    */
  659.   ievent.ie_position.ie_addr = *((APTR *)msg->IAddress);
  660.   ievent.ie_position.ie_dead.ie_prev1DownQual &= ~META_MASK;
  661.   ievent.ie_position.ie_dead.ie_prev2DownQual &= ~META_MASK;
  662.  
  663.   res = RawKeyConvert(&ievent, kbuffer, kbsize, kmap);
  664.   if(res > 0)
  665.   {
  666.       int i;
  667.       
  668.       for(i = 0; i < res; i++)
  669.       *fkeyflags++ = 0;
  670.   }
  671.   return res ? res + extra : 0;
  672. }
  673.  
  674. void add_wbevent(struct WBArg *wbarg)
  675. {
  676.   char filename[256];
  677.  
  678.   if (wbarg->wa_Lock && NameFromLock(wbarg->wa_Lock, filename, 256))
  679.     {
  680.       struct wbevent *event;
  681.  
  682.       if (wbarg->wa_Name) AddPart(filename, wbarg->wa_Name, 256);
  683.       if (event = (struct wbevent *)malloc(offsetof(struct wbevent, file) +
  684.                        strlen(filename) + 1))
  685.     {
  686.       event->next = wbevents;
  687.       strcpy(event->file, filename);
  688.       wbevents = event;
  689.     }
  690.     }
  691. }
  692.  
  693. void get_mouse_char_pos(FRAME_PTR f, int *last_x, int *last_y)
  694. {
  695.     int x, y;
  696.     
  697.     if(EMACS_WIN(f))
  698.     {
  699.     x = EMACS_WIN(f) -> MouseX;
  700.     y = EMACS_WIN(f) -> MouseY;
  701.     if((x < 0) ||
  702.        (x > EMACS_WIN(f)->Width) ||
  703.        (y < 0) ||
  704.        (y > EMACS_WIN(f)->Height))
  705.     {
  706.         x = -1;
  707.         y = -1;
  708.     }
  709.     else
  710.     {
  711.         x = amiga_pos_x(f,x);
  712.         y = amiga_pos_y(f,y);
  713.     }
  714.     *last_x = x;
  715.     *last_y = y;
  716.     }
  717.     else
  718.     {
  719.     *last_x = -1;
  720.     *last_y = -1;
  721.     }
  722. }
  723.     
  724. void check_window(FRAME_PTR f, int force)
  725. {
  726. #ifdef TRY_NEW_MOUSE
  727.   struct input_event event;
  728.   struct timeval tv;
  729. #endif
  730.   ULONG class;
  731.   USHORT code, qualifier;
  732.   UWORD mx, my;
  733.   unsigned char buf[32];
  734.   /* fkey will be set to a value != 0 if a function key event should be created */ 
  735.   /* fkey needs to hold X key symbols 0xffXX */
  736.   USHORT fkey[32]; 
  737.   int buflen, deiconify, i;
  738.   struct IntuiMessage *msg;
  739.   int mouse_event = FALSE, wb_event = FALSE;
  740.   struct AppMessage *amsg;
  741.  
  742.   force_window(f);
  743.  
  744.   if (EMACS_WIN(f))
  745.     while (msg = (struct IntuiMessage *)GetMsg(EMACS_WIN(f)->UserPort))
  746.       {
  747.     class = msg->Class;
  748.     code = msg->Code;
  749.     qualifier = msg->Qualifier;
  750.     mx = msg->MouseX; my = msg->MouseY;
  751.     buflen = DeadKeyConvert(msg, buf, fkey, 32, 0);
  752.     ReplyMsg(msg);
  753. #if 0
  754.     fprintf(stderr,"class: 0x%08lx, code: 0x%08lx, qual: 0x%04x\n",
  755.         (int) class,
  756.         (int) code,
  757.         (int) qualifier);
  758. #endif
  759.     switch (class)
  760.       {
  761.       case IDCMP_CLOSEWINDOW: {
  762.         enque(030, FALSE, FALSE); enque(03, FALSE, FALSE); /* ^X^C */ /* CHFIXME: map to delete_window */
  763.         break;
  764.       }
  765.       case IDCMP_RAWKEY: {
  766.         if (buflen > 0)
  767.           {
  768.         unsigned char *sbuf = buf;
  769.         USHORT *sfkey = fkey;
  770.         int meta = (qualifier & META_MASK) && (qualifier & NO_SNAP_MASK);
  771.         int qual = (qualifier & SHIFT_MASK) ? shift_modifier : 0 +
  772.                    (qualifier & CONTROL_MASK) ? ctrl_modifier : 0 +
  773.                (meta) ? meta_modifier : 0;
  774.         
  775.         do
  776.             if(*sfkey)
  777.             {
  778.             /* provide full emacs qualifier mask for function keys */
  779.             enque(*sfkey++, qual, 1);
  780.             sbuf++;
  781.             }
  782.             else
  783.             {
  784.             /* Don't set META on CSI */
  785.             enque(*sbuf++, meta, 0);
  786.             sfkey++;
  787.             }
  788.         while (--buflen);
  789.           }
  790.         break;
  791.       }
  792.       case IDCMP_NEWSIZE:
  793.         amiga_change_size(f);
  794.         set_mouse_event_pending(); /* signal "input available" to get display redrawn */
  795.         break;
  796.       case IDCMP_MENUHELP:
  797.         break; /* CHFIXME */
  798.       case IDCMP_MENUPICK: 
  799.         if (code == MENUNULL) break;
  800.         {
  801.           int i;
  802.           Lisp_Object prefixes[3];
  803.           int menu_num = MENUNUM(code);
  804.           int item_num = ITEMNUM(code);
  805.           int subitem_num = SUBNUM(code);
  806.  
  807.           if((menu_num != NOMENU)
  808.          && (item_num != NOITEM)
  809.          && map_menu_selection(menu_num, item_num, subitem_num, prefixes))
  810.         {
  811.           
  812.           event.kind = menu_bar_event;
  813.           event.code = 0;
  814.           event.modifiers = 0;
  815.           event.x = 0;
  816.           event.y = 0;
  817.           event.frame_or_window = Qmenu_bar;
  818.           gettimeofday (&tv, NULL);
  819.           event.timestamp = tv.tv_usec;
  820.           kbd_buffer_store_event (&event);
  821.           for(i = 0; i < 3; i++)
  822.             {
  823.               if(NILP(prefixes[i]))
  824.             break;
  825.               /* CHFIXME: rethink validness of these values! */
  826.               event.frame_or_window = prefixes[i]; 
  827.               gettimeofday (&tv, NULL);
  828.               event.timestamp = tv.tv_usec;
  829.               kbd_buffer_store_event (&event);
  830.             }
  831.           set_mouse_event_pending(); /* get emacs to read the input queue */
  832.           }
  833.           
  834.         }
  835.         break; /* CHFIXME: add menu code */
  836.       case IDCMP_MOUSEBUTTONS: {
  837. #ifdef TRY_NEW_MOUSE
  838.           int but, down;
  839.           switch(code)
  840.           {
  841.       case SELECTDOWN: but = 0; down = 1; break;
  842.       case SELECTUP: but = 0; down = 0; break;
  843.       case MIDDLEDOWN: but = 1; down = 1; break;
  844.       case MIDDLEUP: but = 1; down = 0; break;
  845.       case MENUDOWN: but = 2; down = 1; break;
  846.       case MENUUP: but = 2; down = 0; break;
  847.       default: but = -1; break;
  848.           }
  849. #if 0
  850.           fprintf(stderr,"Mouse: button %d, down = %d\n", but, down);
  851. #endif
  852.           if(but >= 0)
  853.           {
  854.           event.kind = mouse_click;
  855.           event.code = but;
  856.           event.modifiers = ((qualifier & META_MASK) ? meta_modifier : 0)
  857.               + ((qualifier & SHIFT_MASK) ? shift_modifier : 0)
  858.               + ((qualifier & CONTROL_MASK) ? ctrl_modifier : 0)
  859.               + (down ? down_modifier : up_modifier);
  860. #if 1/* keyboard.c uses pixel_to_glyph, so we need original pos */
  861.           event.x = mx;
  862.           event.y = my;
  863. #else
  864.           event.x = amiga_pos_x(mx);
  865.           event.y = amiga_pos_y(my);
  866. #endif
  867.           event.frame_or_window = selected_frame;
  868.           gettimeofday (&tv, NULL);
  869.           event.timestamp = tv.tv_usec;
  870.           kbd_buffer_store_event (&event);
  871.           set_mouse_event_pending();
  872.           }
  873. #else
  874.         mouse_event = TRUE;
  875.         if (event_num == EVENTSIZE) break;
  876.  
  877.         events[event_in].class = class;
  878.         events[event_in].code = code;
  879.         events[event_in].qual = qualifier;
  880.         events[event_in].x = mx;
  881.         events[event_in].y = my;
  882.         event_num++;
  883.         event_in = (event_in + 1) % EVENTSIZE;
  884. #endif
  885.         break;
  886.       }
  887.       }
  888.       }
  889.   /* Handle App requests */
  890.   while (amsg = (struct AppMessage *)GetMsg(wbport))
  891.       switch (amsg->am_Type)
  892.     {
  893.     case AMTYPE_APPICON: case AMTYPE_APPWINDOW:
  894.       /* Add an event for all these files */
  895.       for (i = 0; i < amsg->am_NumArgs; i++) add_wbevent(amsg->am_ArgList + i);
  896.       wb_event = TRUE;
  897.       /* Reply to the message, and deiconify if was icon */
  898.       deiconify = amsg->am_Type == AMTYPE_APPICON;
  899.       ReplyMsg(amsg);
  900.       if (deiconify && emacs_icon)
  901.         /* Reopen window */
  902.         if (open_emacs_window(f, emacs_x, emacs_y, emacs_w, emacs_h, emacs_backdrop,
  903.                   emacs_screen_name) == ok)
  904.           {
  905.         resume_menus(f);
  906.         RemoveAppIcon(emacs_icon);
  907.         emacs_icon = 0;
  908.         emacs_iconified = 0;
  909.           }
  910.       break;
  911.     default: ReplyMsg(amsg); break;
  912.     }
  913.  
  914.   if (amiga_mouse_initialized && (force && event_num > 0 || mouse_event))
  915.     {
  916.       enque(AMIGASEQ, FALSE, FALSE); enque('M', FALSE, FALSE);
  917.     }
  918.   if (amiga_wb_initialized && (force && wbevents || wb_event))
  919.     {
  920.       enque(AMIGASEQ, FALSE, FALSE); enque('W', FALSE, FALSE);
  921.     }
  922. }
  923.  
  924. void setup_intchar(char intchar)
  925. {
  926.   char cqbuf[2];
  927.  
  928.   if (MapANSI(&intchar, 1, cqbuf, 1, 0) == 1)
  929.     {
  930.       intkey_code = cqbuf[0];
  931.       intkey_qualifier = cqbuf[1];
  932.     }
  933.   else
  934.     {
  935.       /* Default is CTRL-G in usa0 keymap */
  936.       intkey_code = 0x24;
  937.       intkey_qualifier = IEQUALIFIER_CONTROL;
  938.     }
  939. }
  940.  
  941. /* Hack to detect interrupt char as soon as it is pressed */
  942. /* __interrupt disables stack checking.  -ch3/19/93.*/
  943. static long __saveds __interrupt __asm
  944. int_handler(register __a0 struct InputEvent *ev)
  945. {
  946.   struct InputEvent *ep, *laste;
  947.   static struct InputEvent retkey;
  948.   ULONG lock = LockIBase(0);
  949. #ifndef MULTI_FRAME
  950.   FRAME_PTR f;
  951. #else
  952.   you lose, make loop of frames? 
  953. #endif
  954.   
  955.   if (EMACS_WIN(f) && IntuitionBase->ActiveWindow == EMACS_WIN(f))
  956.     {
  957.       laste = 0;
  958.  
  959.       /* run down the list of events to see if they pressed the magic key */
  960.       for (ep = ev; ep; laste = ep, ep = ep->ie_NextEvent)
  961.     if (ep->ie_Class == IECLASS_RAWKEY &&
  962.         (ep->ie_Qualifier & 0xff) == intkey_qualifier &&
  963.         ep->ie_Code == intkey_code)
  964.       {
  965.         /* Remove this key from input sequence */
  966.         if (laste) laste->ie_NextEvent = ep->ie_NextEvent;
  967.         else ev = ep->ie_NextEvent;
  968.  
  969.         Vquit_flag = Qt;
  970.         Signal(_us, SIGBREAKF_CTRL_C);
  971.       }
  972.     }
  973.   UnlockIBase(lock);
  974.  
  975.   /* pass on the pointer to the event */
  976.   return (long)ev;
  977. }
  978.  
  979. #if 0
  980. DEFUN ("amiga-mouse-events", Famiga_mouse_events, Samiga_mouse_events, 0, 0, 0,
  981.        "Return number of pending mouse events from Intuition.")
  982.      ()
  983. {
  984.   register Lisp_Object tem;
  985.  
  986.   check_intuition ();
  987.  
  988.   XSET (tem, Lisp_Int, event_num);
  989.  
  990.   return tem;
  991. }
  992.  
  993. DEFUN ("amiga-proc-mouse-event", Famiga_proc_mouse_event, Samiga_proc_mouse_event,
  994.        0, 0, 0,
  995.        "Pulls a mouse event out of the mouse event buffer and dispatches\n\
  996. the appropriate function to act upon this event.")
  997. ()
  998. {
  999.   register Lisp_Object mouse_cmd;
  1000.   register char com_letter;
  1001.   register char key_mask;
  1002.   register Lisp_Object tempx;
  1003.   register Lisp_Object tempy;
  1004.   extern Lisp_Object get_keyelt ();
  1005.   extern int meta_prefix_char;
  1006.   struct event *ev;
  1007.   int posx, posy;
  1008.  
  1009.   check_intuition ();
  1010.  
  1011.   if (event_num) {
  1012.     ev = &events[event_out];
  1013.     event_out = (event_out + 1) % EVENTSIZE;
  1014.     event_num--;
  1015.     if (ev->class == MOUSEBUTTONS)
  1016.       {
  1017.     switch (ev->code)
  1018.       {
  1019.       case SELECTDOWN: com_letter = 2; break;
  1020.       case SELECTUP: com_letter = 6; break;
  1021.       case MIDDLEDOWN: com_letter = 1; break;
  1022.       case MIDDLEUP: com_letter = 5; break;
  1023.       case MENUDOWN: com_letter = 0; break;
  1024.       case MENUUP: com_letter = 4; break;
  1025.       default: com_letter = 3; break;
  1026.       }
  1027.     posx = amiga_pos_x(f,ev->x);
  1028.     posy = amiga_pos_y(f,ev->y);
  1029.     XSET (tempx, Lisp_Int, min (FRAME_WIDTH (selected_frame)-1, max (0, posx)));
  1030.     XSET (tempy, Lisp_Int, min (FRAME_HEIGHT (selected_frame)-1, max (0, posy)));
  1031.       }
  1032.     else
  1033.       {
  1034.     /* Must be Menu Pick or Help */
  1035.     com_letter = ev->class == IDCMP_MENUPICK ? 3 : 7;
  1036.  
  1037.     /* The parameters passed describe the selected item */
  1038.     XSET (tempx, Lisp_Int, MENUNUM(ev->code));
  1039.     XSET (tempy, Lisp_Int, ITEMNUM(ev->code));
  1040.       }
  1041.     if (ev->qual & META_MASK) com_letter |= 0x20;
  1042.     if (ev->qual & SHIFT_MASK) com_letter |= 0x10;
  1043.     if (ev->qual & CONTROL_MASK) com_letter |= 0x40;
  1044.  
  1045.     Vamiga_mouse_pos = Fcons (tempx, Fcons (tempy, Qnil));
  1046.     Vamiga_mouse_item = make_number (com_letter);
  1047. #if 0 /* CHFIXME */
  1048.     mouse_cmd = get_keyelt (access_keymap (MouseMap, com_letter));
  1049.     if (NILP (mouse_cmd)) {
  1050.       bitch_at_user ();
  1051.       Vamiga_mouse_pos = Qnil;
  1052.     }
  1053.     else return call1 (mouse_cmd, Vamiga_mouse_pos);
  1054. #else
  1055.     return Qnil;
  1056. #endif
  1057.   }
  1058.   return Qnil;
  1059. }
  1060.  
  1061. DEFUN ("amiga-get-mouse-event", Famiga_get_mouse_event, Samiga_get_mouse_event,
  1062.        1, 1, 0,
  1063.        "Get next mouse event out of mouse event buffer (com-letter (x y)).\n\
  1064. ARG non-nil means return nil immediately if no pending event;\n\
  1065. otherwise, wait for an event.")
  1066. (arg)
  1067. Lisp_Object arg;
  1068. {
  1069.   register char com_letter;
  1070.   register char key_mask;
  1071.  
  1072.   register Lisp_Object tempx;
  1073.   register Lisp_Object tempy;
  1074.   struct event *ev;
  1075.   int posx, posy;
  1076.  
  1077.   check_intuition ();
  1078.  
  1079.   if (NILP (arg))
  1080.     {
  1081.       amiga_consume_input();
  1082.       while (!event_num)
  1083.     {
  1084.       int rfds = 1;
  1085.  
  1086.       select(1, &rfds, 0, 0, 0);
  1087.       amiga_consume_input();
  1088.     }
  1089.     }
  1090.   /*** ??? Surely you don't mean to busy wait??? */
  1091.  
  1092.   if (event_num) {
  1093.     ev = &events[event_out];
  1094.     event_out = (event_out + 1) % EVENTSIZE;
  1095.     event_num--;
  1096.     switch (ev->code)
  1097.       {
  1098.       case SELECTDOWN: com_letter = 2; break;
  1099.       case SELECTUP: com_letter = 6; break;
  1100.       case MIDDLEDOWN: com_letter = 1; break;
  1101.       case MIDDLEUP: com_letter = 5; break;
  1102.       case MENUDOWN: com_letter = 0; break;
  1103.       case MENUUP: com_letter = 4; break;
  1104.       default: com_letter = 3; break;
  1105.       }
  1106.     if (ev->qual & META_MASK) com_letter |= 0x20;
  1107.     if (ev->qual & SHIFT_MASK) com_letter |= 0x10;
  1108.     if (ev->qual & CONTROL_MASK) com_letter |= 0x40;
  1109.  
  1110.     posx = amiga_pos_x(f,ev->x);
  1111.     posy = amiga_pos_y(f,ev->y);
  1112.     XSET (tempx, Lisp_Int, min (FRAME_WIDTH (selected_frame)-1, max (0, posx)));
  1113.     XSET (tempy, Lisp_Int, min (FRAME_HEIGHT (selected_frame)-1, max (0, posy)));
  1114.  
  1115.     Vamiga_mouse_pos = Fcons (tempx, Fcons (tempy, Qnil));
  1116.     Vamiga_mouse_item = make_number (com_letter);
  1117.     return Fcons (com_letter, Fcons (Vamiga_mouse_pos, Qnil));
  1118.   }
  1119.   return Qnil;
  1120. }
  1121. #endif
  1122.  
  1123. DEFUN ("amiga-get-wb-event", Famiga_get_wb_event, Samiga_get_wb_event,
  1124.        1, 1, 0,
  1125.        "Get next Workbench event out of workbench event buffer (a file name).\n\
  1126. ARG non-nil means return nil immediately if no pending event;\n\
  1127. otherwise, wait for an event.")
  1128. (arg)
  1129. Lisp_Object arg;
  1130. {
  1131.   Lisp_Object file;
  1132.   struct wbevent *ev;
  1133.  
  1134.   check_intuition ();
  1135.  
  1136.   if (NILP (arg))
  1137.     {
  1138.       amiga_consume_input();
  1139.       while (!wbevents)
  1140.     {
  1141.       int rfds = 1;
  1142.  
  1143.       select(1, &rfds, 0, 0, 0);
  1144.       amiga_consume_input();
  1145.     }
  1146.     }
  1147.   /*** ??? Surely you don't mean to busy wait??? */
  1148.  
  1149.   if (wbevents) {
  1150.     file = build_string(wbevents->file);
  1151.     ev = wbevents;
  1152.     wbevents = wbevents->next;
  1153.     free(ev);
  1154.     return file;
  1155.   }
  1156.   return Qnil;
  1157. }
  1158.  
  1159. DEFUN("amiga-set-foreground-color", Famiga_set_foreground_color,
  1160.       Samiga_set_foreground_color, 1, 1, "nPen number: ",
  1161.       "Use PEN as foreground color")
  1162.      (pen)
  1163. {
  1164.   int fg;
  1165.  
  1166.   check_intuition();
  1167.   CHECK_NUMBER(pen, 0);
  1168.  
  1169.   fg = XUINT (pen);
  1170.   if (pen > 7) error("Pen colors must be between 0 & 7");
  1171.   foreground = fg;
  1172.   reset_window(selected_frame);
  1173.   return Qnil;
  1174. }
  1175.  
  1176. DEFUN("amiga-set-background-color", Famiga_set_background_color,
  1177.       Samiga_set_background_color, 1, 1, "nPen number: ",
  1178.       "Use PEN as background color")
  1179.      (pen)
  1180. {
  1181.   int bg;
  1182.  
  1183.   check_intuition();
  1184.   CHECK_NUMBER(pen, 0);
  1185.  
  1186.   bg = XUINT (pen);
  1187.   if (pen > 7) error("Pen colors must be between 0 & 7");
  1188.   background = bg;
  1189.   reset_window(selected_frame);
  1190.   return Qnil;
  1191. }
  1192.  
  1193. DEFUN("amiga-set-inverse-fill-pen", Famiga_set_inverse_fill_pen,
  1194.       Samiga_set_inverse_fill_pen, 1, 1, "nPen number: ",
  1195.       "Use PEN's color for inverse fills (0-7 or 8 for reverse)")
  1196.      (pen)
  1197. {
  1198.   int ifp = 8;
  1199.  
  1200.   check_intuition();
  1201.   CHECK_NUMBER(pen, 0);
  1202.  
  1203.   ifp = XUINT (pen);
  1204.   if (pen > 8)
  1205.     error("choices are from 0 to 8");
  1206.   inverse_fill_pen = ifp;
  1207.   reset_window(selected_frame);
  1208.   return Qnil;
  1209. }
  1210.  
  1211. DEFUN("amiga-set-inverse-text-pen", Famiga_set_inverse_text_pen,
  1212.       Samiga_set_inverse_text_pen, 1, 1, "nPen number: ",
  1213.       "Use PEN's color for inverse fills (0-7 or 8 for reverse)")
  1214.      (pen)
  1215. {
  1216.   int itp = 8;
  1217.  
  1218.   check_intuition();
  1219.   CHECK_NUMBER(pen, 0);
  1220.  
  1221.   itp = XUINT (pen);
  1222.   if (pen > 8)
  1223.     error("choices are from 0 to 8");
  1224.   inverse_text_pen = itp;
  1225.   reset_window(selected_frame);
  1226.   return Qnil;
  1227. }
  1228.  
  1229. DEFUN("amiga-set-font", Famiga_set_font, Samiga_set_font, 2, 2,
  1230.       "sFont: \n\
  1231. nSize: ",
  1232.       "Set font used for window to FONT with given HEIGHT.\n\
  1233. The font used must be non-proportional.")
  1234. (wfont, height)
  1235. {
  1236.   struct TextAttr attr;
  1237.   struct TextFont *newfont;
  1238.   char *fname;
  1239.   struct Lisp_String *fstr;
  1240.   WORD minw, minh, oldmw, oldmh;
  1241.   FRAME_PTR f = selected_frame; /* CHFIXME? */
  1242.   
  1243.   CHECK_STRING (wfont, 0);
  1244.   CHECK_NUMBER (height, 0);
  1245.  
  1246.   check_intuition();
  1247.  
  1248.   fstr = XSTRING (wfont);
  1249.   fname = (char *)alloca (fstr->size + 6);
  1250.   strcpy (fname, fstr->data);
  1251.   strcat (fname, ".font");
  1252.   attr.ta_Name = fname;
  1253.   attr.ta_YSize = XFASTINT (height);
  1254.   attr.ta_Style = 0;
  1255.   attr.ta_Flags = 0;
  1256.   newfont = OpenDiskFont (&attr);
  1257.  
  1258.   if (!newfont)
  1259.     error ("Font %s %d not found", fstr->data, XFASTINT (height));
  1260.   if (newfont->tf_Flags & FPF_PROPORTIONAL)
  1261.     {
  1262.       CloseFont(newfont);
  1263.       error ("Font %s %d is proportional", fstr->data, XFASTINT (height));
  1264.     }
  1265.  
  1266.   if (EMACS_WIN(f))
  1267.     {
  1268.       if (!set_min_size(EMACS_WIN(f), newfont, &minw, &minh))
  1269.     {
  1270.       CloseFont(newfont);
  1271.       if (!set_min_size(EMACS_WIN(f), font, &oldmw, &oldmh))
  1272.         _fail("Failed to restore old font, exiting.");
  1273.       error("Window is too small for this font, need at least %d(w) by %d(h)",
  1274.         minw, minh);
  1275.     }
  1276.       SetFont(EMACS_WIN(f)->RPort, newfont);
  1277.     }
  1278.   if (font_opened) CloseFont(font);
  1279.   font_opened = TRUE;
  1280.   font = newfont;
  1281.   reset_window(f);
  1282.   return Qnil;
  1283. }
  1284.  
  1285. DEFUN("amiga-set-geometry", Famiga_set_geometry, Samiga_set_geometry, 4, MANY, 0,
  1286.       "Set Emacs window geometry and screen.\n\
  1287. First 4 parameters are the (X,Y) position of the top-left corner of the window\n\
  1288. and its WIDTH and HEIGHT. These must be big enough for an 11x4 characters window.\n\
  1289. If nil is given for any of these, that means to keep the same value as before.\n\
  1290. The optional argument SCREEN specifies which screen to use, nil stands for the\n\
  1291. same screen as the window is on, t stands for the default public screen (normally\n\
  1292. the Workbench), a string specifies a given public screen.\n\
  1293. If optional argument BACKDROP is t, a backdrop window is used.")
  1294.   (nargs, args)
  1295.     int nargs;
  1296.     Lisp_Object *args;
  1297. {
  1298.   Lisp_Object x, y, w, h, scr = Qnil, backdrop = Qnil;
  1299.   int opened;
  1300.   WORD tempx, tempy, tempw, temph;
  1301.   char *screen_name;
  1302.   int use_backdrop;
  1303.   FRAME_PTR f = selected_frame; /* CHFIXME */
  1304.  
  1305.   if (nargs > 6) error("Too many arguments to amiga-set-geometry");
  1306.   x = args[0]; y = args[1]; w = args[2]; h = args[3];
  1307.   if (nargs > 4)
  1308.     {
  1309.       scr = args[4];
  1310.       if (nargs > 5) backdrop = args[5];
  1311.     }
  1312.  
  1313.   check_intuition();
  1314.  
  1315.   if (!NILP (x))
  1316.     {
  1317.       CHECK_NUMBER(x, 0);
  1318.       tempx = XUINT(x);
  1319.     }
  1320.   else tempx = EMACS_X();
  1321.   if (!NILP (y))
  1322.     {
  1323.       CHECK_NUMBER(y, 0);
  1324.       tempy = XUINT(y);
  1325.     }
  1326.   else tempy = EMACS_Y();
  1327.   if (!NILP (w))
  1328.     {
  1329.       CHECK_NUMBER(w, 0);
  1330.       tempw = XUINT(w);
  1331.     }
  1332.   else tempw = EMACS_W();
  1333.   if (!NILP (h))
  1334.     {
  1335.       CHECK_NUMBER(h, 0);
  1336.       temph = XUINT(h);
  1337.     }
  1338.   else temph = EMACS_H();
  1339.  
  1340.   use_backdrop = !NILP(backdrop);
  1341.  
  1342.   if (scr == Qt) screen_name = 0; /* set to zero for def. */
  1343.   else if (!NILP (scr))
  1344.     {
  1345.       CHECK_STRING (scr, 0);
  1346.       screen_name = XSTRING (scr)->data;
  1347.     }
  1348.   else screen_name = emacs_screen_name;
  1349.  
  1350.   if (EMACS_WIN(f))
  1351.     {
  1352.       struct Window *old_win = EMACS_WIN(f);
  1353.       struct IOStdReq *old_console = emacs_console;
  1354.  
  1355.       suspend_menus(f);
  1356.       opened = open_emacs_window(f, tempx, tempy, tempw, temph, use_backdrop,
  1357.                  screen_name);
  1358.       if (opened != ok)
  1359.     {
  1360.       resume_menus(f);
  1361.  
  1362.       if (opened == no_window) error("Failed to open desired window");
  1363.       else if (screen_name)
  1364.         error("Unknown public screen %s", screen_name);
  1365.       else error("The default screen wasn't found !?");
  1366.     }
  1367.  
  1368.       _device_close(old_console);
  1369.       CloseWindow(old_win);
  1370.       if (!resume_menus(f)) error("Failed to recover menus (No memory?)");
  1371.     }
  1372.   else /* No window, set defaults */
  1373.     {
  1374.       emacs_screen_name = screen_name;
  1375.       if (screen_name)
  1376.     {
  1377.       emacs_screen_name_storage[MAXPUBSCREENNAME] = '\0';
  1378.       strncpy(emacs_screen_name_storage, screen_name, MAXPUBSCREENNAME);
  1379.     }
  1380.       emacs_x = tempx;
  1381.       emacs_y = tempy;
  1382.       emacs_w = tempw;
  1383.       emacs_h = temph;
  1384.       emacs_backdrop = use_backdrop;
  1385.     }
  1386.   return Qnil;
  1387. }
  1388.  
  1389.  
  1390. /* The next 2 functions are very usefull for writing
  1391.  * arexx/lisp functions that interact with other programs
  1392.  * that will be sharing the same screen.  -ch3/19/93. */
  1393.  
  1394. DEFUN("amiga-get-window-geometry",
  1395.       Famiga_get_window_geometry, Samiga_get_window_geometry, 0, 0, 0,
  1396.       "Get Emacs window geometry.\n\
  1397. a list returned is of the form:  (iconified x y width height backdrop)\n\
  1398. where x, y, width, height are integers, backdrop is t or nil and iconified\n\
  1399. is t if the window is iconified and nil otherwise")
  1400. ()
  1401. {
  1402.   Lisp_Object x, y, w, h, b, i;
  1403.  
  1404.   XSET(x, Lisp_Int, EMACS_X());
  1405.   XSET(y, Lisp_Int, EMACS_Y());
  1406.   XSET(w, Lisp_Int, EMACS_W());
  1407.   XSET(h, Lisp_Int, EMACS_H());
  1408.   b = emacs_backdrop ? Qt : Qnil;
  1409.   i = emacs_iconified ? Qt : Qnil;
  1410.  
  1411.   return Fcons(i, Fcons(x, Fcons(y, Fcons(w, Fcons(h, Fcons(b, Qnil))))));
  1412. }
  1413.  
  1414. DEFUN("amiga-get-screen-geometry",
  1415.       Famiga_get_screen_geometry, Samiga_get_screen_geometry, 0, 0, 0,
  1416.       "Get geometry of the screen emacs window resides on.\n\
  1417. a list returned is of the form:  (name x y width height)\n\
  1418. where name is a string, x, y, width, height are integers.\n\
  1419. Only the public screen name is returned if the window is not currently open.\n\
  1420. In this last case, the name may be nil if the window will be opened on the\n\
  1421. default public screen.")
  1422. ()
  1423. {
  1424.   Lisp_Object name;
  1425.  
  1426.   if (emacs_screen_name) name = Qnil;
  1427.   else name = build_string(emacs_screen_name);
  1428.  
  1429.   if(EMACS_WIN(f))
  1430.     {
  1431.       struct Screen *s = EMACS_WIN(f)->WScreen;
  1432.       Lisp_Object x, y, w, h;
  1433.  
  1434.       XSET(x, Lisp_Int, s->LeftEdge);
  1435.       XSET(y, Lisp_Int, s->TopEdge);
  1436.       XSET(w, Lisp_Int, s->Width);
  1437.       XSET(h, Lisp_Int, s->Height);
  1438.  
  1439.       return Fcons(name, Fcons(x, Fcons(y, Fcons(w, Fcons(h, Qnil)))));
  1440.     }
  1441.   return Fcons(name, Qnil);
  1442. }
  1443.  
  1444. DEFUN("amiga-iconify", Famiga_iconify, Samiga_iconify, 0, 0, "",
  1445.       "Toggle the emacs iconification state.")
  1446. ()
  1447. {
  1448.     FRAME_PTR f = selected_frame; /* CHFIXME */
  1449.     
  1450.   check_intuition();
  1451.  
  1452.   if (emacs_iconified)
  1453.     {
  1454.       /* Deiconify */
  1455.  
  1456.       /* Reopen window */
  1457.       if (open_emacs_window(f, emacs_x, emacs_y, emacs_w, emacs_h, emacs_backdrop,
  1458.                 emacs_screen_name) != ok)
  1459.     error("Failed to deiconify (No memory?)");
  1460.       resume_menus(f);
  1461.  
  1462.       RemoveAppIcon(emacs_icon);
  1463.       emacs_icon = 0;
  1464.       emacs_iconified = 0;
  1465.     }
  1466.   else
  1467.     if (emacs_icon = AddAppIconA(0, 0, "Emacs", wbport, 0, &emacs_icon_object, 0))
  1468.       {
  1469.     if (EMACS_WIN(f))
  1470.       {
  1471.         /* Close window */
  1472.         emacs_x = EMACS_X(); emacs_y = EMACS_Y();
  1473.         emacs_w = EMACS_W(); emacs_h = EMACS_H();
  1474.         suspend_menus(f);
  1475.         close_emacs_window(f);
  1476.       }
  1477.     emacs_iconified = 1;
  1478.       }
  1479.     else error("Iconify attempt failed\n");
  1480.  
  1481.   return Qnil;
  1482. }
  1483.  
  1484. DEFUN("amiga-set-icon-pos", Famiga_set_icon_pos, Samiga_set_icon_pos, 2, 2,
  1485. "nX position: \n\
  1486. nY position: ",
  1487.       "Set the X Y position of the icon for emacs when iconified.")
  1488.   (Lisp_Object x, Lisp_Object y)
  1489. {
  1490.   long xpos, ypos;
  1491.  
  1492.   if (NILP (x)) emacs_icon_object.do_CurrentX = NO_ICON_POSITION;
  1493.   else
  1494.     {
  1495.       CHECK_NUMBER (x, 0);
  1496.       emacs_icon_object.do_CurrentX = XINT(x);
  1497.     }
  1498.   if (NILP (y)) emacs_icon_object.do_CurrentY = NO_ICON_POSITION;
  1499.   else
  1500.     {
  1501.       CHECK_NUMBER (y, 0);
  1502.       emacs_icon_object.do_CurrentY = XINT(y);
  1503.     }
  1504.  
  1505.   return Qnil;
  1506. }
  1507.  
  1508. struct EClockVal scount[16], ecount[16];
  1509. long total[16], counting[16], nb[16], susp[16];
  1510.  
  1511. void start_count(int n)
  1512. {
  1513.   nb[n]++;
  1514.   if (counting[n]) printf("Restarted %d\n", n);
  1515.   counting[n] = 1;
  1516.   /*ReadEClock(&scount[n]);*/
  1517. }
  1518.  
  1519. void stop_count(int n)
  1520. {
  1521.   if (counting[n])
  1522.     {
  1523.       /*ReadEClock(&ecount[n]);*/
  1524.       counting[n] = 0;
  1525.  
  1526.       total[n] += ecount[n].ev_lo - scount[n].ev_lo;
  1527.     }
  1528. }
  1529.  
  1530. void suspend_count(int n)
  1531. {
  1532.   if (counting[n] && susp[n]++ == 0)
  1533.     {
  1534.       /*ReadEClock(&ecount[n]);*/
  1535.       total[n] += ecount[n].ev_lo - scount[n].ev_lo;
  1536.     }
  1537. }
  1538.  
  1539. void resume_count(int n)
  1540. {
  1541.   if (counting[n] && --susp[n] == 0) /*ReadEClock(&scount[n])*/;
  1542. }
  1543.  
  1544. disp_counts(void)
  1545. {
  1546.   int i;
  1547.  
  1548.   for (i = 0; i < 16; i++)
  1549.     {
  1550.       printf("%d(%d) ", total[i], nb[i]);
  1551.       total[i] = nb[i] = 0;
  1552.     }
  1553.   printf("\n");
  1554. }
  1555.  
  1556. void screen_puts(FRAME_PTR f, char *str, unsigned int len)
  1557. {
  1558.   if (EMACS_WIN(f))
  1559.     {
  1560.       int i;
  1561.  
  1562.       emacs_console->io_Command = CMD_WRITE;
  1563.       emacs_console->io_Data    = (APTR)str;
  1564.       emacs_console->io_Length  = len;
  1565.  
  1566.       /*    start_count(0);
  1567.         for (i = 1; i <= 6; i++) suspend_count(i);*/
  1568.       DoIO(emacs_console); 
  1569.       /*    for (i = 1; i <= 6; i++) resume_count(i);
  1570.         stop_count(0);*/
  1571.     }
  1572. }
  1573.  
  1574. DEFUN ("amiga-activate-window", Famiga_activate_window, Samiga_activate_window, 0, 0, 0,
  1575.        "Makes emacs window the currently active one.")
  1576.      ()
  1577. {
  1578.   if(EMACS_WIN(f)) {
  1579.     ActivateWindow(EMACS_WIN(f));
  1580.     return Qnil;
  1581.   }
  1582.   error("No window to make active.");
  1583.   return Qnil;
  1584. }
  1585.  
  1586. void
  1587. Aframe_raise_lower(FRAME_PTR f, int raise)
  1588. {
  1589.     if(raise)
  1590.     {
  1591.     if(EMACS_WIN(f))
  1592.         WindowToFront(EMACS_WIN(f));
  1593.     }
  1594.     else
  1595.     {
  1596.     if(EMACS_WIN(f))
  1597.         WindowToBack(EMACS_WIN(f));
  1598.     }
  1599. }
  1600.  
  1601. DEFUN ("amiga-window-to-front", Famiga_window_to_front, Samiga_window_to_front, 0, 0, 0,
  1602.        "Pulls the emacs window to the front (including screen)")
  1603.      ()
  1604. {
  1605.   if(EMACS_WIN(f)) {
  1606.     WindowToFront(EMACS_WIN(f));
  1607.     ScreenToFront(EMACS_WIN(f)->WScreen);
  1608.     return Qnil;
  1609.   }
  1610.   error("No window to pull to the front.");
  1611.   return Qnil;
  1612. }
  1613.  
  1614. DEFUN ("amiga-window-to-back", Famiga_window_to_back, Samiga_window_to_back, 0, 0, 0,
  1615.        "Pushes the emacs window to the back (including screen)")
  1616.      ()
  1617. {
  1618.   if(EMACS_WIN(f)) {
  1619.     WindowToBack(EMACS_WIN(f));
  1620.     ScreenToBack(EMACS_WIN(f)->WScreen);
  1621.     return Qnil;
  1622.   }
  1623.   error("No window to push back.");
  1624.   return Qnil;
  1625. }
  1626.  
  1627. DEFUN ("amiga-popup-font-request", Famiga_popup_font_request, Samiga_popup_font_request, 0, 0, 0,
  1628.        "Open an ASL Font Requester and return the value as cons of font name and font size.")
  1629.      ()
  1630. {
  1631.     LONG Top = 0, Left = 0;
  1632.     Lisp_Object RetVal = Qnil;
  1633.     struct FontRequester *Req;
  1634.  
  1635.     if(EMACS_WIN(f))
  1636.     {
  1637.     Top = EMACS_WIN(f)->TopEdge + EMACS_WIN(f)->MouseY - 75;
  1638.     Left = EMACS_WIN(f)->LeftEdge + EMACS_WIN(f)->MouseX - 160;
  1639.     AslBase = OpenLibrary("asl.library", 0);
  1640.     if(AslBase)
  1641.     {
  1642.         Req = AllocAslRequestTags(ASL_FontRequest,
  1643.                       ASL_Hail, "Emacs Font Request",
  1644.                       ASL_FuncFlags, FONF_FIXEDWIDTH,
  1645.                       TAG_DONE);
  1646.         if(Req)
  1647.         {
  1648.         if(AslRequestTags(Req,
  1649.                   ASL_TopEdge, Top,
  1650.                   ASL_LeftEdge, Left,
  1651.                   ASL_Height, 250, TAG_DONE))
  1652.         {
  1653.             char *s;
  1654.  
  1655.             s = strstr(Req->fo_Attr.ta_Name, ".font");
  1656.             if(s)
  1657.             RetVal = Fcons(make_string(Req->fo_Attr.ta_Name,
  1658.                            s - Req->fo_Attr.ta_Name),
  1659.                        make_number(Req->fo_Attr.ta_YSize));
  1660.         }
  1661.         FreeAslRequest(Req);
  1662.         }
  1663.         CloseLibrary(AslBase);
  1664.     }
  1665.     }
  1666.     return RetVal;
  1667. }
  1668.  
  1669. #ifdef USE_SCROLL_BARS
  1670. /*
  1671.  * Lisp_ScrollBar is a Lisp_Vector
  1672.  */ 
  1673. struct Lisp_ScrollBar
  1674. {
  1675.     int size;
  1676.     struct Lisp_ScrollBar *next;
  1677.     Lisp_Object window;
  1678.     Lisp_Object 
  1679. };
  1680.  
  1681. /* Arrange for all scroll bars on FRAME to be removed at the next call
  1682.    to `*judge_scroll_bars_hook'.  A scroll bar may be spared if
  1683.    `*redeem_scroll_bar_hook' is applied to its window before the judgement. 
  1684.  
  1685.    This should be applied to each frame each time its window tree is
  1686.    redisplayed, even if it is not displaying scroll bars at the moment;
  1687.    if the HAS_SCROLL_BARS flag has just been turned off, only calling
  1688.    this and the judge_scroll_bars_hook will get rid of them.
  1689.  
  1690.    If non-zero, this hook should be safe to apply to any frame,
  1691.    whether or not it can support scroll bars, and whether or not it is
  1692.    currently displaying them.  */
  1693.  
  1694. void
  1695. Acondemn_scroll_bars(FRAME_PTR f)
  1696. {
  1697.     FRAME_CONDEMNED_SCROLL_BARS(f) = FRAME_SCROLL_BARS(f);
  1698.     FRAME_SCROLL_BARS(f) = Qnil;
  1699. }
  1700.  
  1701. /* Unmark WINDOW's scroll bar for deletion in this judgement cycle.
  1702.    Note that it's okay to redeem a scroll bar that is not condemned.  */
  1703.  
  1704. void
  1705. Aredeem_scroll_bar(struct window *w)
  1706. {
  1707.     FRAME_PTR f = WINDOW_FRAME(w);
  1708.  
  1709.     
  1710. }
  1711.  
  1712. /* Remove all scroll bars on FRAME that haven't been saved since the
  1713.    last call to `*condemn_scroll_bars_hook'.  
  1714.  
  1715.    This should be applied to each frame after each time its window
  1716.    tree is redisplayed, even if it is not displaying scroll bars at the
  1717.    moment; if the HAS_SCROLL_BARS flag has just been turned off, only
  1718.    calling this and condemn_scroll_bars_hook will get rid of them.
  1719.  
  1720.    If non-zero, this hook should be safe to apply to any frame,
  1721.    whether or not it can support scroll bars, and whether or not it is
  1722.    currently displaying them.  */
  1723. void Ajudge_scroll_bars(FRAME_PTR f)
  1724. {
  1725. }
  1726. #endif /* USE_SCROLL_BARS */
  1727.  
  1728. void syms_of_amiga_screen(void)
  1729. {
  1730.   DEFVAR_LISP ("amiga-mouse-item", &Vamiga_mouse_item,
  1731.            "Encoded representation of last mouse click, corresponding to\n\
  1732. numerical entries in amiga-mouse-map.");
  1733.   Vamiga_mouse_item = Qnil;
  1734.   DEFVAR_LISP ("amiga-mouse-pos", &Vamiga_mouse_pos,
  1735.            "Current x-y position of mouse by row, column as specified by font.");
  1736.   Vamiga_mouse_pos = Qnil;
  1737.  
  1738.   DEFVAR_BOOL ("amiga-remap-bsdel", &amiga_remap_bsdel,
  1739.            "*If true, map DEL to Ctrl-D and Backspace to DEL. \n\
  1740. This is the most convenient (and default) setting. If nil, don't remap.");
  1741.   amiga_remap_bsdel = 1;
  1742.  
  1743.   DEFVAR_BOOL ("amiga-remap-numeric-keypad", &amiga_remap_numeric_keypad,
  1744.            "*If true, numeric keypad keys are prefixed with C-x C-^ K.\n\
  1745. This enables you to remap them, but causes problems with functions like\n\
  1746. isearch-forward-regexp on some keyboards. Default to true.");
  1747.   amiga_remap_numeric_keypad = 1;
  1748.  
  1749.   DEFVAR_BOOL ("amiga-mouse-initialized", &amiga_mouse_initialized,
  1750.            "Set to true once lisp has been setup to process mouse commands.\n\
  1751. No mouse processing request (C-X C-^ M) will be queued while this is nil.");
  1752.   amiga_mouse_initialized = 0;
  1753.  
  1754.   DEFVAR_BOOL ("amiga-wb-initialized", &amiga_wb_initialized,
  1755.            "Set to true once lisp has been setup to process workbench commands.\n\
  1756. No workbench processing request (C-X C-^ W) will be queued while this is nil.");
  1757.   amiga_mouse_initialized = 0;
  1758.  
  1759. #if 0
  1760.   defsubr (&Samiga_mouse_events);
  1761.   defsubr (&Samiga_proc_mouse_event);
  1762.   defsubr (&Samiga_get_mouse_event);
  1763. #endif
  1764.   defsubr (&Samiga_get_wb_event);
  1765.   defsubr (&Samiga_set_font);
  1766.   defsubr (&Samiga_set_geometry);
  1767.   defsubr (&Samiga_set_background_color);
  1768.   defsubr (&Samiga_set_foreground_color);
  1769.   defsubr (&Samiga_iconify);
  1770.   defsubr (&Samiga_set_icon_pos);
  1771.  
  1772.   /* New functions  -ch3/19/93. */
  1773.   defsubr (&Samiga_set_inverse_text_pen);
  1774.   defsubr (&Samiga_set_inverse_fill_pen);
  1775.   defsubr (&Samiga_window_to_front);
  1776.   defsubr (&Samiga_window_to_back);
  1777.   defsubr (&Samiga_activate_window);
  1778.   defsubr (&Samiga_get_window_geometry);
  1779.   defsubr (&Samiga_get_screen_geometry);
  1780.  
  1781.   /* New functions -Alph08/24/94 */
  1782.   defsubr (&Samiga_popup_font_request);
  1783. }
  1784.  
  1785. void init_amiga_screen(void)
  1786. {
  1787.   event_num = event_in = event_out = 0;
  1788.  
  1789.   if (!((IntuitionBase = (struct IntuitionBase *)
  1790.      OpenLibrary("intuition.library", 37L)) &&
  1791.     (GfxBase = (struct GfxBase *)OpenLibrary("graphics.library", 0L)) &&
  1792.     (DiskfontBase = OpenLibrary("diskfont.library", 0L)) &&
  1793.     (WorkbenchBase = OpenLibrary("workbench.library", 37)) &&
  1794.     (KeymapBase = OpenLibrary("keymap.library", 36)) &&
  1795.     (input_req = (struct IOStdReq *)_device_open("input.device", 0, 0, 0, 0,
  1796.                              sizeof(struct IOStdReq)))))
  1797.     _fail("Need version 2.04 and diskfont.library!");
  1798.  
  1799.   if (!(wbport = CreateMsgPort())) no_memory();
  1800.  
  1801.   /* Add Ctrl-G detector */
  1802.   int_handler_hook.is_Data = 0;
  1803.   int_handler_hook.is_Code = (void *)int_handler;
  1804.   int_handler_hook.is_Node.ln_Pri = 100; /* 100 not 127 is the standard value
  1805.                       * for input stream handlers.  -ch3/19/93. */
  1806.   /* it is standard for interrupts to have names  -ch3/19/93.*/
  1807.   int_handler_hook.is_Node.ln_Name = "GNU Emacs CTRL-G handler";
  1808.   input_req->io_Command = IND_ADDHANDLER;
  1809.   input_req->io_Data = (APTR)&int_handler_hook;
  1810.  
  1811.   /* wasn't checking for error. -ch3/19/93. */
  1812. #if 1 /* CHFIXME make debugging life a bit more easy */
  1813.   hooked = FALSE;
  1814. #else
  1815.   if(0 == DoIO(input_req))
  1816.     hooked = TRUE;
  1817.   else
  1818.     {
  1819.       hooked = FALSE;
  1820.       _fail("couldn't get input handler hook for CTRL-G");
  1821.     }
  1822. #endif
  1823.   inputsig |= 1L << wbport->mp_SigBit;
  1824.  
  1825.   background_hook.h_Entry = (ULONG (*)()) fill_background; /* added cast. */
  1826.   font = GfxBase->DefaultFont;
  1827.  
  1828.   init_amiga_menu();
  1829. }
  1830.  
  1831. void cleanup_amiga_screen(void)
  1832. {
  1833.   if (hooked)
  1834.     {
  1835.       input_req->io_Command = IND_REMHANDLER;
  1836.       input_req->io_Data = (APTR)&int_handler_hook;
  1837.       DoIO(input_req);
  1838.     }
  1839.   close_app_win();
  1840.   if (wbport) DeleteMsgPort(wbport);
  1841.   cleanup_amiga_menu();
  1842.   _device_close(emacs_console);
  1843. #ifdef MULTI_FRAME
  1844.   you lose
  1845. #endif
  1846.   if (EMACS_WIN(f)) CloseWindow(EMACS_WIN(f));
  1847.   if (font_opened) CloseFont(font);
  1848.   if (IntuitionBase) CloseLibrary(IntuitionBase);
  1849.   if (GfxBase) CloseLibrary(GfxBase);
  1850.   if (DiskfontBase) CloseLibrary(DiskfontBase);
  1851.   if (WorkbenchBase) CloseLibrary(WorkbenchBase);
  1852.   if (KeymapBase) CloseLibrary(KeymapBase);
  1853.   _device_close(input_req);
  1854. }
  1855.