home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume8 / micrognu / part06 < prev    next >
Text File  |  1987-01-26  |  59KB  |  2,393 lines

  1. Subject:  v08i013:  A Micro-Emacs variant that resembles GNU Emacs
  2. Newsgroups: mod.sources
  3. Approved: mirror!rs
  4.  
  5. Submitted by: Bob Larson <seismo!usc-oberon!blarson>
  6. Mod.sources: Volume 8, Issue 13
  7. Archive-name: micrognu/Part06
  8.  
  9.  
  10. #! /bin/sh
  11. # This is a shell archive, meaning:
  12. # 1. Remove everything above the #! /bin/sh line.
  13. # 2. Save the resulting text in a file.
  14. # 3. Execute the file with /bin/sh (not csh) to create the files:
  15. #    tty/amiga/ttydef.h
  16. #    tty/amiga/console.c
  17. #    tty/amiga/menustack.c
  18. #    tty/amiga/tty.c
  19. #    tty/amiga/ttyio.c
  20. #    tty/amiga/ttymenu.c
  21. # This archive created: Sat Nov 15 15:26:59 1986
  22. export PATH; PATH=/bin:$PATH
  23. if test ! -d tty/amiga
  24. then
  25. mkdir tty/amiga
  26. fi
  27. if test ! -d sys/amiga
  28. then
  29. mkdir sys/amiga
  30. fi
  31. if test -f 'tty/amiga/ttydef.h'
  32. then
  33.     echo shar: will not over-write existing file "'tty/amiga/ttydef.h'"
  34. else
  35. cat << \SHAR_EOF > 'tty/amiga/ttydef.h'
  36. /*
  37.  * Name:    MicroEMACS
  38.  *        Amiga console device virtual terminal header file
  39.  * Version:    Gnu v30
  40.  * Last edit:    26-Aug-86
  41.  * Created:    20-Apr-86 ...!ihnp4!seismo!ut-sally!ut-ngp!mic
  42.  */
  43. #define    GOSLING                /* Compile in fancy display.    */
  44.  
  45. #define    NROW    48            /* Max rows (only in interlace)    */
  46. #define    NCOL    80            /* Columns (borderless window)    */
  47.  
  48. /*
  49.  * Special keys for the default Amiga console device keymap.
  50.  * Function key codes are in the form <CSI>v~
  51.  * where v is a 1 or 2-digit code between 0 and 19,
  52.  * so they comprise the first 20 entries in the key
  53.  * table.  The next 12 entries are for the help and
  54.  * arrow keys.
  55.  */
  56. #define    KF1    K01
  57. #define    KF2    K02
  58. #define    KF3    K03
  59. #define    KF4    K04
  60. #define    KF5    K05
  61. #define    KF6    K06
  62. #define    KF7    K07
  63. #define    KF8    K08
  64. #define    KF9    K09
  65. #define    KF10    K0A
  66. #define    KSF1    K0B
  67. #define    KSF2    K0C
  68. #define    KSF3    K0D
  69. #define    KSF4    K0E
  70. #define    KSF5    K0F
  71. #define    KSF6    K10
  72. #define    KSF7    K11
  73. #define    KSF8    K12
  74. #define    KSF9    K13
  75. #define    KSF10    K14
  76. #define    KUP    K15
  77. #define    KSUP    K16
  78. #define    KDOWN    K17
  79. #define    KSDOWN    K18
  80. #define    KLEFT    K19
  81. #define    KSLEFT    K1A
  82. #define    KRIGHT    K1B
  83. #define    KSRIGHT    K1C
  84. #define    KHELP    K1D
  85.  
  86. /* The 'menu' key doesn't really appear on the
  87.  * Amiga keyboard.  When ttgetc() sees a menu
  88.  * event, it saves the menu number and item,
  89.  * then stuffs the sequence for KMENU into
  90.  * the input buffer.
  91.  */
  92. #define    KMENU    K1E
  93.  
  94. /*
  95.  * Intuition menu interface.  Each set of menu items
  96.  * kept in a table of MenuBinding structures, which
  97.  * is in turn kept in a table of MenuInfo structures.
  98.  *
  99.  * These tables are indexed via the menu and item
  100.  * numbers to find the internal extended name of
  101.  * the function associated with a certain item.
  102.  */
  103. struct MenuBinding {
  104.     char *Command;
  105.     char *Binding;
  106. };
  107.  
  108. struct MenuInfo {
  109.     char *Name;            /* name of menu            */
  110.     short NumItems;            /* # of items            */
  111.     struct MenuBinding *Items;    /* item name, internal binding    */
  112. };
  113.  
  114. #define NITEMS(arr) (sizeof(arr) / (sizeof(arr[0])))
  115.  
  116. /*
  117.  * If either MENU, or BROWSER is defined, we need to define
  118.  * DO_MENU to get the code for dealing with menu selections
  119.  * compiled in.
  120.  */
  121.  
  122. #ifdef    MENU
  123. #define    DO_MENU
  124. #else
  125. #ifdef    BROWSER
  126. #define    DO_MENU
  127. #endif    BROWSER
  128. #endif    MENU
  129.  
  130. /*
  131.  * MODE_RENDITION and TEXT_RENDITION
  132.  * determine the way the mode line and
  133.  * text area are rendered (using the SGR
  134.  * sequence).  TEXT_* and MODE_* set the
  135.  * foreground (FG) and background (BG)
  136.  * color to the specified number.  If you
  137.  * #define CHANGE_COLOR, you can redefine
  138.  * these dynamically.
  139.  */
  140.  
  141. #ifndef MODE_RENDITION
  142. #define    MODE_RENDITION 7
  143. #endif
  144.  
  145. #ifndef TEXT_RENDITION
  146. #define    TEXT_RENDITION 0
  147. #endif
  148.  
  149. #ifndef    TEXT_FG
  150. #define TEXT_FG 1
  151. #endif
  152.  
  153. #ifndef TEXT_BG
  154. #define TEXT_BG 0
  155. #endif
  156.  
  157. #ifndef    MODE_FG
  158. #define MODE_FG 1
  159. #endif
  160.  
  161. #ifndef    MODE_BG
  162. #define MODE_BG 0
  163. #endif
  164.  
  165. /*
  166.  * Return the width and height of
  167.  * the default font for a window.
  168.  */
  169.  
  170. #define    FontWidth(w) (w)->RPort->TxWidth
  171. #define    FontHeight(w) (w)->RPort->TxHeight
  172. SHAR_EOF
  173. fi # end of overwriting check
  174. if test -f 'tty/amiga/console.c'
  175. then
  176.     echo shar: will not over-write existing file "'tty/amiga/console.c'"
  177. else
  178. cat << \SHAR_EOF > 'tty/amiga/console.c'
  179. /*
  180.  * These functions are taken directly from the
  181.  * console.device chapter in the Amiga V1.1
  182.  * ROM Kernel Manual.
  183.  */
  184. #include <exec/types.h>
  185. #include <exec/io.h>
  186. #include <devices/console.h>
  187. #include <libraries/dos.h>
  188. #include <intuition/intuition.h>
  189.  
  190. extern    LONG    OpenDevice();
  191. extern    LONG    DoIO();
  192. extern    LONG    SendIO();
  193.  
  194. /*
  195.  * Open a console device, given a read request
  196.  * and a write request message.
  197.  */
  198.  
  199. int OpenConsole(writerequest,readrequest,window)
  200. struct IOStdReq *writerequest;
  201. struct IOStdReq *readrequest;
  202. struct Window *window;
  203. {
  204.     LONG error; 
  205.     writerequest->io_Data = (APTR) window;
  206.     writerequest->io_Length = (ULONG) sizeof(*window);
  207.     error = OpenDevice("console.device", 0L, writerequest, 0L);
  208.  
  209.     /* clone required parts of the request */
  210.     readrequest->io_Device = writerequest->io_Device;
  211.     readrequest->io_Unit   = writerequest->io_Unit;
  212.     return((int) error);
  213. }
  214.  
  215. /*
  216.  * Output a single character    
  217.  * to a specified console
  218.  */ 
  219.  
  220. int ConPutChar(request,character)
  221. struct IOStdReq *request;
  222. char character;
  223. {
  224. #ifdef    V11
  225.     register int x;
  226. #endif
  227.     request->io_Command = CMD_WRITE;
  228.     request->io_Data = (APTR)&character;
  229.     request->io_Length = (ULONG)1;
  230.     DoIO(request);
  231.     /* caution: read comments in manual! */
  232.     return(0);
  233. }
  234.  
  235. /*
  236.  * Output a NULL-terminated string of
  237.  * characters to a console
  238.  */ 
  239.  
  240. int ConPutStr(request,string)
  241. struct IOStdReq *request;
  242. char *string;
  243. {
  244. #ifdef    V11
  245.     register int x;
  246. #endif
  247.     request->io_Command = CMD_WRITE;
  248.     request->io_Data = (APTR)string;
  249.     request->io_Length = (LONG)-1;
  250.     DoIO(request);
  251.     return(0);
  252. }
  253.  
  254. /*
  255.  * Write out a string of predetermined
  256.  * length to the console
  257.  */
  258.  
  259. int ConWrite(request,string,len)
  260. struct IOStdReq *request;
  261. char *string;
  262. int len;
  263. {
  264. #ifdef    V11
  265.     register int x;
  266. #endif
  267.     request->io_Command = CMD_WRITE;
  268.     request->io_Data = (APTR)string;
  269.     request->io_Length = (LONG)len;
  270.     DoIO(request);
  271.     return(0);
  272. }
  273.  
  274. /*
  275.  * Queue up a read request 
  276.  * to a console
  277.  */
  278.  
  279. int QueueRead(request,whereto)
  280. struct IOStdReq *request;
  281. char *whereto;
  282. {
  283. #ifdef    V11
  284.     register int x;
  285. #endif
  286.     request->io_Command = CMD_READ;
  287.     request->io_Data = (APTR)whereto;
  288.     request->io_Length = (LONG)1;
  289.     SendIO(request);
  290.     return(0);
  291. }
  292.  
  293. SHAR_EOF
  294. fi # end of overwriting check
  295. if test -f 'tty/amiga/menustack.c'
  296. then
  297.     echo shar: will not over-write existing file "'tty/amiga/menustack.c'"
  298. else
  299. cat << \SHAR_EOF > 'tty/amiga/menustack.c'
  300. /*
  301.  *  Simple menu package.  Needs lotsa work to handle some cases.
  302.  *
  303.  *  Copyright 1985
  304.  *  Louis A. Mamakos
  305.  *  Software & Stuff
  306.  *  14813 Ashford Place
  307.  *  Laurel, MD  20707
  308.  *
  309.  *  For non-commerical use only.  This program, or any modifications, may not
  310.  *  be sold or incorporated into any product without prior permission from the
  311.  *  author.
  312.  *
  313.  *  Modified by mwm to handle "stacking" menus.
  314.  *    NB - adding item to a menu that's been "popped" back to doesn't work,
  315.  *    and probably never will.
  316.  */
  317.  
  318. #include <exec/types.h>
  319. #include <exec/nodes.h>
  320. #include <exec/lists.h>
  321. #include <exec/ports.h>
  322. #include <exec/devices.h>
  323. #include <exec/memory.h>
  324. #include <hardware/blit.h>
  325. #include <graphics/copper.h>
  326. #include <graphics/regions.h>
  327. #include <graphics/rastport.h>
  328. #include <graphics/gfxbase.h>
  329. #include <graphics/gels.h>
  330. #include <intuition/intuition.h>
  331.  
  332. #define MNUM(menu,item,sub) (SHIFTMENU(menu)|SHIFTITEM(item)|SHIFTSUB(sub))
  333. #define    Menu_Clear    DisposeMenus    /* For ttyio.c    */
  334.  
  335. extern    char    *AllocMem();
  336. extern    char    *AllocRemember();
  337.  
  338. struct    Mem_Node {
  339.    struct Node mn_Node;
  340.    struct Remember mn_Memory;
  341.    struct Menu *mn_Menu;
  342.    } *Top, *RemHead();
  343.  
  344. extern struct NewWindow MicroEMACS ;    /* For Screen width & Height    */
  345. #define SCREENHEIGHT    (MicroEMACS . MaxHeight)
  346. #define SCREENWIDTH    (MicroEMACS . MaxWidth)
  347.  
  348. static struct List Memory;
  349. static int Cur_Menu, Cur_MenuItem, Cur_SubItem;
  350. static struct Menu *LastMenu;
  351. static struct MenuItem *LastMenuItem, *LastSubItem;
  352.  
  353. struct Menu *AutoMenu;      /* menu struct being dynamically built */
  354.  
  355. char *strsave();        /* Save a string in the remember list */
  356.  
  357. Menu_Init()
  358. {
  359.    Memory.lh_Head = (struct Node *) &(Memory.lh_Tail);
  360.    Memory.lh_TailPred = (struct Node *) &(Memory.lh_Head);
  361.    Memory.lh_Tail = NULL;
  362.    Memory.lh_Type = NT_MEMORY;
  363.    Top = NULL;
  364.    Cur_Menu = Cur_MenuItem = Cur_SubItem = -1;
  365.    AutoMenu = LastMenu = NULL;     /* no menu chain yet */
  366.    LastMenuItem = LastSubItem = NULL;
  367. }
  368.  
  369. Menu_Clear()
  370. {
  371.  
  372.    while ((Top = RemHead(&Memory)) != NULL) {
  373.       FreeRemember(&(Top->mn_Memory), (LONG)TRUE);
  374.       FreeMem(Top, (LONG)sizeof(struct Mem_Node));
  375.   }
  376.   Menu_Init();            /* Just for safeties sake */
  377. }
  378.  
  379. Menu_Pop()
  380. {
  381.  
  382.    if ((Top = RemHead(&Memory)) == NULL) return NULL;
  383.    FreeRemember(&(Top->mn_Memory), (LONG)TRUE);
  384.    FreeMem(Top, (LONG)sizeof(struct Mem_Node));
  385.    /* Now, set Top back to the real list head */
  386.    Top = (struct Mem_Node *) Memory.lh_Head;
  387.    LastMenu = Top->mn_Menu;
  388.    LastMenuItem = NULL;        /* Wrong, but you can't add items here anyway */
  389.    LastSubItem = NULL;        /*    ditto                      */
  390.    Cur_Menu--;
  391. }
  392. /*
  393.  *  Add a MENU item.  Args are the text of the menu item, and an enable
  394.  *  flag.  Returns an Intuition type menu number, with the MenuItem and
  395.  *  Menu SubItem being NOITEM and NOSUB.  The MENUITEM part is valid.
  396.  */
  397. /* dummy Intuitext used to calculate length of menu names */
  398. static struct IntuiText itd = {
  399.    AUTOFRONTPEN, AUTOBACKPEN, JAM2, 1, 1, NULL, NULL, NULL
  400. };
  401.  
  402. Menu_Add(name, enabled)
  403.    char *name;
  404.    int enabled;
  405. {
  406.    register struct Menu *m;
  407.  
  408.    if ((Top = (struct Mem_Node *) AllocMem(
  409.          (LONG)sizeof(struct Mem_Node), MEMF_PUBLIC | MEMF_CLEAR)) == NULL)
  410.       return NULL;
  411.    Top->mn_Node.ln_Type = NT_MEMORY;
  412.  
  413.    if ((m = (struct Menu *)AllocRemember(&(Top->mn_Memory),
  414.                  (LONG)sizeof (struct Menu), MEMF_PUBLIC | MEMF_CLEAR)) == NULL)
  415.       return NULL;
  416.    Top->mn_Menu = m;
  417.  
  418.    if (LastMenu == NULL)
  419.       AutoMenu = m;     /* first menu on list */
  420.    else
  421.       LastMenu->NextMenu = m;      /* link it in */
  422.  
  423.    LastMenuItem = NULL;            /* end of previous MenuItem list */
  424.    LastSubItem = NULL;
  425.    Cur_MenuItem = Cur_SubItem = -1; /* reset item numbers */
  426.    if (LastMenu == NULL)
  427.       m->LeftEdge = 0;
  428.    else
  429.       m->LeftEdge = LastMenu->LeftEdge + LastMenu->Width;
  430.    m->TopEdge = 0;
  431.    itd.IText = (UBYTE *)name;
  432.    m->Width = IntuiTextLength(&itd);
  433.    Top->mn_Node.ln_Name = m->MenuName = strsave(name);
  434.    m->Height = 0;
  435.    m->Flags = enabled ? MENUENABLED : 0;
  436.    m->FirstItem = NULL;
  437.    LastMenu = m;
  438.  
  439.    AddHead(&Memory, Top);
  440.    return MNUM(++Cur_Menu, NOITEM, NOSUB);
  441. }
  442.  
  443. /*
  444.  *  Add a menu item to the current MENU.  Note that Add_Menu *must* be
  445.  *  called before this function.
  446.  */
  447. Menu_Item_Add(name, flags, mux, ch)
  448.    char *name;       /* name of menu item */
  449.    USHORT flags;
  450.    LONG mux;         /* mutual exclusion mask */
  451.    BYTE ch;        /* command sequence character, if COMMSEQ */
  452. {
  453.    register struct MenuItem *m, *n;
  454.    register struct IntuiText *it;
  455.  
  456.    flags &= CHECKIT|CHECKED|COMMSEQ|MENUTOGGLE|ITEMENABLED|HIGHCOMP|HIGHBOX;
  457.    if (LastMenu == NULL)
  458.       return MNUM(NOMENU, NOITEM, NOSUB);
  459.  
  460.    if ((m = (struct MenuItem *) AllocRemember(&(Top->mn_Memory),
  461.            (LONG)sizeof(struct MenuItem), MEMF_PUBLIC | MEMF_CLEAR)) == NULL)
  462.       return MNUM(NOMENU, NOITEM, NOSUB);
  463.  
  464.    LastSubItem = NULL;        /* terminate possible list of subitems */
  465.    Cur_SubItem = -1;
  466.    if (LastMenuItem == NULL)
  467.       LastMenu->FirstItem  = m;
  468.    else
  469.       LastMenuItem->NextItem = m;
  470.    m->Flags = flags | ITEMTEXT;
  471.    /*
  472.     *  Check for highlight mode:  if none selected, use HIGHCOMP
  473.     */
  474.    if ((m->Flags & (HIGHCOMP | HIGHBOX)) == 0)
  475.       m->Flags |= HIGHCOMP;
  476.    m->Command = ch;
  477.    m->MutualExclude = mux;
  478.    m->SubItem = NULL;
  479.    m->ItemFill = (APTR) AllocRemember(&(Top->mn_Memory),
  480.                  (LONG)sizeof(struct IntuiText), MEMF_PUBLIC | MEMF_CLEAR);
  481.    it = (struct IntuiText *) m->ItemFill;
  482.    it->FrontPen = AUTOFRONTPEN;
  483.    it->BackPen = AUTOBACKPEN;
  484.    it->DrawMode = JAM2;
  485.    if (flags & CHECKIT)
  486.       it->LeftEdge = CHECKWIDTH + 1;
  487.    else
  488.       it->LeftEdge = 1;
  489.    it->TopEdge = 1;
  490.    it->ITextFont = NULL;      /* default font */
  491.    it->IText = (UBYTE *)strsave(name);
  492.    it->NextText = NULL;
  493.    if (LastMenuItem == NULL) {
  494.       m->TopEdge = 2;
  495.       m->LeftEdge = 0;
  496.    } else if (LastMenuItem->TopEdge + 40 > SCREENHEIGHT) {
  497.       m->TopEdge = 2;
  498.       m->LeftEdge = LastMenuItem->LeftEdge + LastMenuItem->Width + 12;
  499.       if (m->LeftEdge > SCREENWIDTH) {
  500.       LastMenuItem->NextItem = NULL;
  501.       LastMenuItem->Flags &= ~ITEMENABLED;
  502.             return MNUM(NOMENU, NOITEM, NOSUB);
  503.       }
  504.    } else {
  505.       m->TopEdge = LastMenuItem->TopEdge + 10;
  506.       m->LeftEdge = LastMenuItem->LeftEdge;
  507.    }
  508.    m->Width = 0;
  509.    if (flags & CHECKIT)
  510.       m->Width += CHECKWIDTH;
  511.    if (flags & COMMSEQ)
  512.       m->Width += COMMWIDTH + 20;
  513.    m->Width += IntuiTextLength(m->ItemFill);
  514.    m->Height = 10;
  515.    /*
  516.     *  Check last menu item's width to see if it is larger than this
  517.     *  item's.  If new item is larger, then update width of all other
  518.     *  items.
  519.     */
  520.    if (LastMenuItem) {
  521.       if (LastMenuItem->Width > m->Width)
  522.         m->Width = LastMenuItem->Width;
  523.       else {
  524.          register short delta = m->Width - LastMenuItem->Width;
  525.  
  526.      for (n = LastMenu->FirstItem; n != m; n = n->NextItem) {
  527.         n->Width = m->Width;
  528.         if (n->LeftEdge > 0) n->LeftEdge += delta;
  529.      }
  530.      if (m->LeftEdge > 0) m->LeftEdge += delta;
  531.       }
  532.    }
  533.    LastMenuItem = m;
  534.    return MNUM(Cur_Menu, ++Cur_MenuItem, NOSUB);
  535. }
  536.  
  537.  
  538.  
  539. Menu_SubItem_Add(name, flags, mux, ch)
  540.    char *name, ch;
  541.    USHORT flags;
  542.    LONG mux;
  543. {
  544.    register struct MenuItem *m, *n;
  545.    register struct IntuiText *it;
  546.  
  547.    flags &= CHECKIT|CHECKED|COMMSEQ|MENUTOGGLE|ITEMENABLED|HIGHCOMP|HIGHBOX;
  548.    if (LastMenuItem == NULL)
  549.       return MNUM(NOMENU, NOITEM, NOSUB);
  550.  
  551.    if ((m = (struct MenuItem *) AllocRemember(&(Top->mn_Memory),
  552.            (LONG)sizeof(struct MenuItem), MEMF_PUBLIC | MEMF_CLEAR)) == NULL)
  553.       return MNUM(NOMENU, NOITEM, NOSUB);
  554.  
  555.    if (LastSubItem == NULL)
  556.       LastMenuItem->SubItem = m;
  557.    else
  558.       LastSubItem->NextItem = m;
  559.    m->Flags = flags | ITEMTEXT;
  560.    /*
  561.     * check for highlight mode.  If none selected, use HIGHCOMP
  562.     */
  563.    if ((m->Flags & (HIGHCOMP|HIGHBOX)) == 0)
  564.       m->Flags |= HIGHCOMP;
  565.    m->Command = ch;
  566.    m->MutualExclude = mux;
  567.    m->SubItem = NULL;
  568.    m->ItemFill = (APTR) AllocRemember(&(Top->mn_Memory),
  569.                      (LONG)sizeof(struct IntuiText), MEMF_PUBLIC | MEMF_CLEAR);
  570.    it = (struct IntuiText *) m->ItemFill;
  571.    it->FrontPen = AUTOFRONTPEN;
  572.    it->BackPen = AUTOBACKPEN;
  573.    it->DrawMode = JAM2;
  574.    if (flags & CHECKIT)
  575.       it->LeftEdge = CHECKWIDTH + 1;
  576.    else
  577.       it->LeftEdge = 1;
  578.    it->TopEdge = 1;
  579.    it->ITextFont = NULL;      /* default font */
  580.    it->IText = (UBYTE *)strsave(name);
  581.    it->NextText = NULL;
  582.    m->LeftEdge = LastMenuItem->Width + 10;
  583.    m->Width = 0;
  584.    if (LastSubItem == NULL)
  585.       m->TopEdge = 1;
  586.    else
  587.       m->TopEdge = LastSubItem->TopEdge + 10;
  588.    if (flags & CHECKIT)
  589.       m->Width += CHECKWIDTH;
  590.    if (flags & COMMSEQ)
  591.       m->Width += COMMWIDTH + 20;
  592.    m->Width += IntuiTextLength(m->ItemFill);
  593.    m->Height = 10;
  594.    /*
  595.     *  Check last menu item's width to see if it is larger than this
  596.     *  item's.  If new item is larger, then update width of all other
  597.     *  items.
  598.     */
  599.    if (LastSubItem) {
  600.     if (LastSubItem->Width > m->Width)
  601.         m->Width = LastSubItem->Width;
  602.     else
  603.         for (n = LastMenuItem->SubItem; n != m; n = n->NextItem)
  604.         n->Width = m->Width;
  605.    }
  606.    LastSubItem = m;
  607.    return MNUM(Cur_Menu, Cur_MenuItem, ++Cur_SubItem);
  608. }
  609.  
  610. char *
  611. strsave(string) char *string; {
  612.    char *out ;
  613.  
  614.    out = (char *) AllocRemember(&(Top->mn_Memory), (LONG)(strlen(string) + 1),
  615.     MEMF_PUBLIC) ;
  616.    if (out == NULL) return NULL ;
  617.  
  618.    (void) strcpy(out, string) ;
  619.    return out ;
  620. }
  621. SHAR_EOF
  622. fi # end of overwriting check
  623. if test -f 'tty/amiga/tty.c'
  624. then
  625.     echo shar: will not over-write existing file "'tty/amiga/tty.c'"
  626. else
  627. cat << \SHAR_EOF > 'tty/amiga/tty.c'
  628. /*
  629.  * Name:    MicroEMACS
  630.  *        Amiga console device virtual terminal display
  631.  * Version:    GNU v30
  632.  * Last Edit:    23-Aug-86 ...!ihnp4!seismo!ut-sally!ut-ngp!mic
  633.  * Created:    19-Apr-86 ...!ihnp4!seismo!ut-sally!ut-ngp!mic
  634.  *
  635.  * Drives the Amiga console device display.  The code
  636.  * is a combination of the Heath and ANSI terminal drivers,
  637.  * plus some hacks to manage the console device colors.
  638.  */
  639.  
  640. #include    "def.h"
  641.  
  642. #define    BEL    0x07            /* BEL character.        */
  643. #define    ESC    0x1B            /* ESC character.        */
  644.  
  645. extern    int    ttrow;
  646. extern    int    ttcol;
  647. extern    int    tttop;
  648. extern    int    ttbot;
  649. extern    int    tthue;
  650.  
  651. int    tceeol    =    3;        /* Costs, ANSI display.        */
  652. int    tcinsl    =     17;
  653. int    tcdell    =    16;
  654.  
  655.  
  656. #ifdef    CHANGE_COLOR
  657. short    mode_rendition = MODE_RENDITION,    /* set standard colors */
  658.     text_rendition = TEXT_RENDITION,
  659.     text_fg = TEXT_FG + 30,
  660.     text_bg = TEXT_BG + 40,
  661.     mode_fg = MODE_FG + 30,
  662.     mode_bg = MODE_BG + 40;
  663. #else                /* colors are hard-coded        */
  664. #define mode_rendition MODE_RENDITION
  665. #define    text_rendition TEXT_RENDITION
  666. #define text_fg (TEXT_FG + 30)
  667. #define text_bg (TEXT_BG + 40)
  668. #define mode_fg (MODE_FG + 30)
  669. #define mode_bg (MODE_BG + 40)
  670. #endif
  671.  
  672. /*
  673.  * Initialize the terminal when the editor
  674.  * gets started up.  A no-op for the Amiga
  675.  */
  676. ttinit()
  677. {
  678. }
  679.  
  680. /*
  681.  * Clean up the terminal, in anticipation of
  682.  * a return to the command interpreter. This
  683.  * is a no-op on the Amiga.
  684.  */
  685. tttidy()
  686. {
  687. }
  688.  
  689. /*
  690.  * Move the cursor to the specified
  691.  * origin 0 row and column position. Try to
  692.  * optimize out extra moves; redisplay may
  693.  * have left the cursor in the right
  694.  * location last time!
  695.  */
  696. ttmove(row, col)
  697. {
  698.     if (ttrow!=row || ttcol!=col) {
  699.         ttputc(ESC);
  700.         ttputc('[');
  701.         asciiparm(row+1);
  702.         ttputc(';');
  703.         asciiparm(col+1);
  704.         ttputc('H');
  705.         ttrow = row;
  706.         ttcol = col;
  707.     }
  708. }
  709.  
  710. /*
  711.  * Erase to end of line.
  712.  */
  713. tteeol()
  714. {
  715.     ttputc(ESC);
  716.     ttputc('[');
  717.     ttputc('K');
  718. }
  719.  
  720. /*
  721.  * Erase to end of page.
  722.  */
  723. tteeop()
  724. {
  725.     ttputc(ESC);    /* reinforce current color values */
  726.     ttputc('[');
  727.     asciiparm((tthue == CTEXT) ? text_rendition : mode_rendition);
  728.     ttputc(';');
  729.     asciiparm(text_fg);
  730.     ttputc(';');
  731.     asciiparm(text_bg);
  732.     ttputc('m');
  733.  
  734.     ttputc(ESC);    /* clear to end of display */
  735.     ttputc('[');
  736.     ttputc('J');
  737. }
  738.  
  739. /*
  740.  * Make a noise.
  741.  */
  742. ttbeep()
  743. {
  744.     ttputc(BEL);
  745.     ttflush();
  746. }
  747.  
  748. /*
  749.  * Convert a number to decimal
  750.  * ascii, and write it out. Used to
  751.  * deal with numeric arguments.
  752.  */
  753. asciiparm(n)
  754. register int    n;
  755. {
  756.     if (n > 9)
  757.         asciiparm(n/10);
  758.     ttputc((n%10) + '0');
  759. }
  760.  
  761. /*
  762.  * Insert a block of blank lines onto the
  763.  * screen, using a scrolling region that starts at row
  764.  * "row" and extends down to row "bot".  Deal with the one
  765.  * line case, which is a little bit special, with special
  766.  * case code.
  767.  *
  768.  * Since we don't really have a scrolling region,
  769.  * delete the block of lines that would have been deleted if
  770.  * we'd had one, then insert blank lines to move the rest
  771.  * of the screen back to where it belongs.  This idea from
  772.  * the Heath driver.
  773.  */
  774. VOID ttinsl(row, bot, nchunk)
  775. {
  776.     if (row == bot) {            /* Funny case.        */
  777.         if (nchunk != 1)
  778.             panic("ttinsl: nchunk != 1");
  779.         ttmove(row, 0);
  780.         tteeol();
  781.         return;
  782.     } 
  783.     ttmove(1+bot-nchunk, 0);
  784.     if (nchunk > 0) {        /* Delete a chunk of lines    */
  785.         ttputc(ESC);        /* nchunk in size.  Rest of    */
  786.         ttputc('[');        /* screen moves up.        */
  787.         asciiparm(nchunk);
  788.         ttputc('M');
  789.     }
  790.     ttmove(row, 0);
  791.     if (nchunk > 0) {        /* Insert a chunk nchunk in size*/
  792.         ttputc(ESC);        /* before current line,    sliding    */
  793.         ttputc('[');        /* rest of screen down.        */
  794.         asciiparm(nchunk);
  795.         ttputc('L');
  796.     }
  797.     ttrow = row;            /* End up on current line    */
  798.     ttcol = 0;
  799. }
  800.  
  801. /*
  802.  * Delete a block of lines, with the uppermost
  803.  * line at row "row", in a screen slice that extends to
  804.  * row "bot". The "nchunk" is the number of lines that have
  805.  * to be deleted.  This is done by deleting nchunk lines at the
  806.  * appropriate spot, then inserting nchunk lines to make up for
  807.  * the empty space at the bottom of the virtual scrolling region.
  808.  */
  809. VOID ttdell(row, bot, nchunk)
  810. {
  811.     if (row == bot) {        /* One line special case    */
  812.         ttmove(row, 0);
  813.         tteeol();
  814.         return;
  815.     }
  816.     if (nchunk > 0) {
  817.         ttmove(row, 0);
  818.         ttputc(ESC);
  819.         ttputc('[');
  820.         asciiparm(nchunk);
  821.         ttputc('M');
  822.     }
  823.     ttmove(1+bot-nchunk,0);
  824.     if (nchunk > 0) {
  825.         ttputc(ESC);        /* For all lines in chunk    */
  826.         ttputc('[');        /* INS line before bottom    */
  827.         asciiparm(nchunk);    /* Bottom of window (and rest     */
  828.         ttputc('L');        /* of screen) moves down */
  829.     }
  830.     ttrow = HUGE;
  831.     ttcol = HUGE;
  832.     ttmove(bot-nchunk,0);
  833. }
  834.  
  835. /*
  836.  * No-op.
  837.  */
  838. ttwindow(top,bot)
  839. {
  840. }
  841.  
  842. /*
  843.  * No-op.
  844.  */
  845. ttnowindow()
  846. {
  847. }
  848.  
  849. #ifdef    CHANGE_COLOR
  850. /*
  851.  * Set the rendition of the mode line by
  852.  * selecting colors from the following:
  853.  *    0 -- plain text
  854.  *    1 -- bold-face
  855.  *    3 -- italic
  856.  *    4 -- underscore
  857.  *    7 -- inverse video
  858.  * Certain of these selections may be less than
  859.  * appealing :-)
  860.  */
  861.  
  862. ttmode(f, n, k)
  863. {
  864.     register int    s;
  865.     char        buf[2];
  866.  
  867.     if (f == FALSE) {
  868.         if ((s = ereply("Set mode line rendition (0-7): ",
  869.                 buf, sizeof(buf))) != TRUE)
  870.             return (s);
  871.         n = atoi(buf);
  872.     }
  873.     if (n < 0 || n > 7)
  874.         return (FALSE);
  875.  
  876.     mode_rendition = n;        /* store the color    */
  877.     sgarbf = TRUE;
  878.     return (TRUE);
  879. }
  880.  
  881. /*
  882.  * Set the rendition of the text area.
  883.  * Most of these selections will be
  884.  * less than appealing :-]
  885.  */
  886.  
  887. tttext(f, n, k)
  888. {
  889.     register int    s;
  890.     char        buf[2];
  891.  
  892.     if (f == FALSE) {
  893.         if ((s = ereply("Set text rendition (0-7): ",
  894.                 buf, sizeof(buf))) != TRUE)
  895.             return (s);
  896.         n = atoi(buf);
  897.     }
  898.     if (n < 0 || n > 7)
  899.         return (FALSE);
  900.  
  901.     text_rendition = n;        /* store the color    */
  902.     sgarbf = TRUE;
  903.     return (TRUE);
  904. }
  905.  
  906. /*
  907.  * Set foreground color for entire window
  908.  * to a value between 30 and 37, which
  909.  * corresponds to the arguments 0-7.
  910.  * This requires a total refresh, which
  911.  * sets up the screen.
  912.  */
  913.  
  914. textforeground(f, n, k)
  915. {
  916.     register int    s;
  917.     char        buf[2];
  918.  
  919.     if (f == FALSE) {
  920.         if ((s = ereply("Text foreground color (0-7): ",
  921.                 buf, sizeof(buf))) != TRUE)
  922.             return (s);
  923.         n = atoi(buf);
  924.     }
  925.     if (n < 0 || n > 7)
  926.         return (FALSE);
  927.  
  928.     text_fg = n + 30;
  929.     sgarbf = TRUE;
  930.     return (TRUE);
  931. }
  932.  
  933. /*
  934.  * Set background color for entire window
  935.  * to a value between 40 and 47 inclusive.
  936.  */
  937.  
  938. textbackground(f, n, k)
  939. {
  940.     register int    s;
  941.     char        buf[2];
  942.  
  943.     if (f == FALSE) {
  944.         if ((s = ereply("Text background color (0-7): ",
  945.                 buf, sizeof(buf))) != TRUE)
  946.             return (s);
  947.         n = atoi(buf);
  948.     }
  949.     if (n < 0 || n > 7)
  950.         return (FALSE);
  951.  
  952.     text_bg = n + 40;
  953.     sgarbf = TRUE;
  954.     return (TRUE);
  955. }
  956.  
  957. /*
  958.  * Set foreground color for entire the mode line
  959.  */
  960.  
  961. modeforeground(f, n, k)
  962. {
  963.     register int    s;
  964.     char        buf[2];
  965.  
  966.     if (f == FALSE) {
  967.         if ((s = ereply("Mode line foreground color (0-7): ",
  968.                 buf, sizeof(buf))) != TRUE)
  969.             return (s);
  970.         n = atoi(buf);
  971.     }
  972.     if (n < 0 || n > 7)
  973.         return (FALSE);
  974.  
  975.     mode_fg = n + 30;
  976.     sgarbf = TRUE;
  977.     return (TRUE);
  978. }
  979.  
  980. /*
  981.  * Set background color for the mode line
  982.  */
  983.  
  984. modebackground(f, n, k)
  985. {
  986.     register int    s;
  987.     char        buf[2];
  988.  
  989.     if (f == FALSE) {
  990.         if ((s = ereply("Mode line background color (0-7): ",
  991.                 buf, sizeof(buf))) != TRUE)
  992.             return (s);
  993.         n = atoi(buf);
  994.     }
  995.     if (n < 0 || n > 7)
  996.         return (FALSE);
  997.  
  998.     mode_bg = n + 40;
  999.     sgarbf = TRUE;
  1000.     return (TRUE);
  1001. }
  1002. #endif
  1003.  
  1004. /*
  1005.  * Set the current writing color to the
  1006.  * specified color. Watch for color changes that are
  1007.  * not going to do anything (the color is already right)
  1008.  * and don't send anything to the display.
  1009.  */
  1010.  
  1011. ttcolor(color)
  1012. register int    color;
  1013. {
  1014.     if (color != tthue) {
  1015.         if (color == CTEXT) {        /* Normal video.    */
  1016.             ttputc(ESC);        /* Reset to 0        */
  1017.             ttputc('[');
  1018.             ttputc('m');
  1019.             ttputc(ESC);        /* Set text style    */
  1020.             ttputc('[');
  1021.             asciiparm(text_rendition);
  1022.             ttputc(';');
  1023.             asciiparm(text_fg);
  1024.             ttputc(';');
  1025.             asciiparm(text_bg);
  1026.             ttputc('m');
  1027.         } else if (color == CMODE) {    /* Standout mode    */
  1028.             ttputc(ESC);        /* Reset to 0        */
  1029.             ttputc('[');
  1030.             ttputc('m');
  1031.             ttputc(ESC);        /* Set standout mode    */
  1032.             ttputc('[');
  1033.             asciiparm(mode_rendition);
  1034.             ttputc(';');
  1035.             asciiparm(mode_fg);    /* Use mode line colors    */
  1036.             ttputc(';');
  1037.             asciiparm(mode_bg);
  1038.             ttputc('m');
  1039.         }
  1040.         tthue = color;            /* Save the color.    */
  1041.     }
  1042. }
  1043.  
  1044. /*
  1045.  * This routine is called by the
  1046.  * "refresh the screen" command to try and resize
  1047.  * the display. The new size, which must be deadstopped
  1048.  * to not exceed the NROW and NCOL limits, is stored
  1049.  * back into "nrow" and "ncol". Display can always deal
  1050.  * with a screen NROW by NCOL. Look in "window.c" to
  1051.  * see how the caller deals with a change.
  1052.  * On the Amiga, we make the Intuition terminal driver
  1053.  * do all the work.
  1054.  */
  1055.  
  1056. ttresize()
  1057. {
  1058.      setttysize();
  1059. }
  1060. SHAR_EOF
  1061. fi # end of overwriting check
  1062. if test -f 'tty/amiga/ttyio.c'
  1063. then
  1064.     echo shar: will not over-write existing file "'tty/amiga/ttyio.c'"
  1065. else
  1066. cat << \SHAR_EOF > 'tty/amiga/ttyio.c'
  1067. /*
  1068.  * Name:    MicroEmacs
  1069.  *        Amiga terminal-dependent I/O (Intuition)
  1070.  * Created:    21-Apr-86 ...!ihnp4!seismo!ut-sally!ut-ngp!mic
  1071.  */
  1072.  
  1073. /*
  1074.  * Lots of includes.
  1075.  */
  1076.  
  1077. #include <exec/types.h>
  1078. #include <exec/nodes.h>
  1079. #include <exec/lists.h>
  1080. #include <exec/tasks.h>
  1081. #include <exec/ports.h>
  1082. #include <exec/io.h>
  1083. #include <devices/console.h>
  1084. #include <libraries/dos.h>
  1085. #include <graphics/clip.h>
  1086. #include <graphics/view.h>
  1087. #include <graphics/rastport.h>
  1088. #include <graphics/layers.h>
  1089. #include <graphics/text.h>
  1090. #include <graphics/gfxbase.h>
  1091. #include <intuition/intuition.h>
  1092. #ifdef    CHANGE_FONT
  1093. #include <libraries/diskfont.h>
  1094. #endif
  1095.  
  1096. #undef    TRUE            /* avoid redefinition messages         */
  1097. #undef    FALSE
  1098. #include "def.h"        /* includes sysdef.h and ttydef.h    */
  1099.  
  1100. /*
  1101.  * External Amiga functions.  Declared explicitly
  1102.  * to avoid problems with different compilers.
  1103.  */
  1104. extern    LONG             AbortIO();
  1105. extern    LONG             CloseDevice();
  1106. extern    LONG             CloseLibrary();
  1107. extern    LONG             CloseWindow();
  1108. extern    struct    MsgPort        *CreatePort();
  1109. extern    struct    IOStdReq    *CreateStdIO();
  1110. extern    LONG             DeletePort();
  1111. extern    LONG             DeleteStdIO();
  1112. extern    struct    IntuiMessage    *GetMsg();
  1113. extern    int             OpenConsole();
  1114. extern    char            *OpenLibrary();
  1115. extern    struct    Window        *OpenWindow();
  1116. #ifdef    CHANGE_FONT
  1117. extern    struct TextFont        *OpenDiskFont();
  1118. #endif
  1119. extern    LONG             RectFill();
  1120. extern    LONG             ReplyMsg();
  1121. extern    LONG             SetAPen();
  1122. extern    LONG             SetDrMd();
  1123. extern    LONG             Wait();
  1124.  
  1125. #ifdef    DO_MENU
  1126. extern    LONG             ClearMenuStrip();    /* menu functions */
  1127. extern    struct    Menu        *InitEmacsMenu();
  1128. extern    struct    MenuItem    *ItemAddress();
  1129. extern    LONG             SetMenuStrip();
  1130. #endif
  1131.  
  1132. extern    int    Enable_Abort;        /* Do NOT allow abort!        */
  1133.  
  1134. /*
  1135.  * External MicroEmacs functions and variables
  1136.  */
  1137. extern    int    quit();            /* Defined by "main.c"    */
  1138. extern    char    *version;        /* Version information        */
  1139.  
  1140. /*
  1141.  * Library bases (used by glue libraries)
  1142.  */
  1143. struct    IntuitionBase    *IntuitionBase;
  1144. struct    GfxBase        *GfxBase;
  1145. #ifdef    CHANGE_FONT
  1146. ULONG            DiskfontBase;
  1147. #endif
  1148.  
  1149. /*
  1150.  * Intuition window and menu variables
  1151.  */
  1152. #define WINDOWGADGETS (WINDOWDRAG | WINDOWDEPTH | WINDOWCLOSE)
  1153.  
  1154. static short    borderless = TRUE;    /* Flag for borderless window    */
  1155. static short    leftedge = 0,        /* Last top left position    */
  1156.         topedge = 0,
  1157.         width = 640,
  1158.         height = 200;
  1159.  
  1160. struct NewWindow MicroEMACS = {
  1161.     0,    0,            /* start position           */
  1162.     0,    0,            /* width, height (set by ttopen)*/
  1163.     0,    1,                 /* detail pen, block pen    */
  1164. #ifdef    DO_MENU
  1165.     MENUPICK |            /* If menu is used        */
  1166. #endif
  1167. #ifdef    MOUSE
  1168.     MOUSEBUTTONS |             /* If mouse is used        */
  1169. #endif
  1170.     CLOSEWINDOW | NEWSIZE,        /* IDCMP flags            */
  1171.     0,                /* window flags    (set by ttopen)    */
  1172.     NULL,                /* pointer to first user gadget */
  1173.     NULL,                /* pointer to user checkmark    */ 
  1174.     NULL,                /* title (filled in later)    */
  1175.     NULL,                /* pointer to screen (none)    */
  1176.     NULL,                /* pointer to superbitmap    */
  1177.     359,101,            /* minimum size (with TOPAZ_80)    */
  1178.     0, 0,                /* maximum size (set by ttopen)    */
  1179.     WBENCHSCREEN            /* screen in which to open    */ 
  1180. };
  1181.  
  1182. struct Window    *EmW;                /* Our window        */
  1183. static short        toggling = FALSE;    /* Prevent menu wiping    */
  1184.  
  1185. #ifdef    DO_MENU
  1186. static struct Menu    *EmacsMenu = NULL;    /* Our menu        */
  1187. #endif
  1188. #ifdef    CHANGE_FONT
  1189. static    struct TextFont *EmFont = NULL;
  1190. #endif
  1191.  
  1192. /*
  1193.  * The bridge between Intuition events and Emacs' single
  1194.  * input stream...
  1195.  */
  1196. static USHORT        class,            /* Intuition event    */
  1197.             code,            /*   information    */
  1198.             qualifier;
  1199. static APTR        address;
  1200. static SHORT        x, y;
  1201. static LONG        intuitionMsgBit;    /* Signal bit        */
  1202. #define INTUITION_MESSAGE ((LONG) (1L << intuitionMsgBit))
  1203.  
  1204. /*
  1205.  * To more thoroughly handle Intuition events, we buffer
  1206.  * them into a circular queue until other routines ask
  1207.  * for the information carried in them.
  1208.  */
  1209. #define    NIBUF    256            /* Rather roomy...        */
  1210. #define    EVT_KBD        0
  1211. #define    EVT_MOUSE    1
  1212. #define EVT_MENU    2
  1213. #define NULLEVT    ((struct event *) 0)
  1214.  
  1215. struct    event {
  1216.     USHORT type;            /* What is it?            */
  1217.     union    {
  1218.         UBYTE    ch;        /* Keyboard event        */
  1219.         struct {        /* Mouse click            */
  1220.             SHORT row, col;    /* location in character raster    */
  1221.             USHORT qualifier;
  1222.         } mouse;
  1223.         USHORT    code;        /* Menu event            */
  1224.     } data;
  1225. }        ibuf[NIBUF];        /* Input buffer            */
  1226. int        ibufo, nibuf;        /* head, # of bytes in ibuf    */
  1227.  
  1228. /*
  1229.  * Console output
  1230.  */
  1231. #define    CSI    0x9b            /* Command Sequence Introducer    */
  1232. #define    ESC    0x1b            /* Escape key            */
  1233. #define    NOBUF    512            /* About 1/4 screen        */
  1234.  
  1235. static struct MsgPort    *consoleWritePort;    /* I/O ports         */
  1236. static struct MsgPort    *consoleReadPort;    
  1237. static struct IOStdReq    *consoleWriteMsg;    /* I/O messages        */
  1238. static struct IOStdReq    *consoleReadMsg;
  1239. static LONG        consoleMsgBit;        /* signal bit        */
  1240. #define CONSOLE_MESSAGE ((LONG) (1L << consoleMsgBit))
  1241. static unsigned char    letter;            /* Console input buffer    */
  1242.  
  1243. static unsigned char    obuf[NOBUF];    /* Terminal output buffer    */
  1244. int            nobuf;        /* # of bytes in above        */
  1245. int            nrow;        /* Terminal size, rows.        */
  1246. int            ncol;        /* Terminal size, columns.    */
  1247. extern int        ttrow;        /* Current cursor row        */
  1248.  
  1249. /*
  1250.  * Open up the virtual terminal MicroEMACS communicates with.
  1251.  * Set up the window, console, and menu strip.
  1252.  */
  1253.  
  1254. ttopen()
  1255. {
  1256.     register struct Screen *s;
  1257.  
  1258.     Enable_Abort = 0;                /* Disable ^C    */
  1259.  
  1260.     GfxBase = (struct GfxBase *)
  1261.         OpenLibrary("graphics.library", (LONG) 0);
  1262.     if (GfxBase  == NULL)                /* Graphics lib    */
  1263.         cleanup(1);
  1264.  
  1265.     IntuitionBase = (struct IntuitionBase *)    /* Intuition    */
  1266.         OpenLibrary("intuition.library", (LONG) 0);
  1267.     if (IntuitionBase == NULL)
  1268.         cleanup(2);
  1269.  
  1270. #ifdef    CHANGE_FONT
  1271.     DiskfontBase = (ULONG) OpenLibrary("diskfont.library", (LONG)0);
  1272.     if (DiskfontBase == NULL)
  1273.         cleanup(21);
  1274. #endif
  1275.     /*
  1276.      * Create our window. Set window flags based on the current
  1277.      * value of the borderless flag, and the maximum size of the
  1278.      * window based on the size of the first screen in the screen
  1279.      * list with screen type WBENCHSCREEN (of which there had better
  1280.      * be *EXACTLY* one, right???...).  To avoid possible crashes
  1281.      * if user is moving screens around, turn off multitasking
  1282.      * during the loop.
  1283.      */
  1284.     Forbid();    /* user might be moving screen */
  1285.     for (s = IntuitionBase->FirstScreen; s ; s = s->NextScreen)
  1286.         if ((s->Flags & SCREENTYPE) == WBENCHSCREEN)
  1287.             break;
  1288.     MicroEMACS.MaxWidth = s->Width;
  1289.     MicroEMACS.MaxHeight = s->Height;
  1290.     Permit();
  1291.  
  1292.     /* Set the window size based on the last one that was open,
  1293.      * if it was borderless. Otherwise make it fill the screen.
  1294.      * Set max/min widths based on current screen size.
  1295.      *
  1296.      * Set flags and window title, then open window
  1297.      */
  1298.     if (borderless) {
  1299.         MicroEMACS.Flags = WINDOWGADGETS | ACTIVATE | BORDERLESS;
  1300. #ifdef    TOGGLE_ZOOMS
  1301.         MicroEMACS.LeftEdge = 0;
  1302.         MicroEMACS.TopEdge = 0;
  1303.         MicroEMACS.Width = MicroEMACS.MaxWidth;
  1304.         MicroEMACS.Height = MicroEMACS.MaxHeight;
  1305. #endif
  1306.     } else {
  1307.         MicroEMACS.Flags = WINDOWGADGETS | ACTIVATE | WINDOWSIZING;
  1308. #ifndef    TOGGLE_ZOOMS
  1309.     }
  1310. #endif
  1311.         MicroEMACS.LeftEdge = leftedge;
  1312.         MicroEMACS.TopEdge = topedge;
  1313.         MicroEMACS.Width = width;
  1314.         MicroEMACS.Height = height;
  1315. #ifdef    TOGGLE_ZOOMS
  1316.     }
  1317. #endif
  1318.     MicroEMACS.Title = (UBYTE *) version;    /* name for window */
  1319.     if ((EmW = OpenWindow(&MicroEMACS)) == NULL)
  1320.         cleanup(3);
  1321.  
  1322. #ifdef    CHANGE_FONT
  1323.     /* If the user requested a different font for the text, EmFont
  1324.      * will be non-null, so set the font for the RastPort.  The
  1325.      * conole device will pick this up when we open it later on.
  1326.      */
  1327.     if (EmFont)
  1328.         SetFont(EmW->RPort, EmFont);
  1329. #endif
  1330.  
  1331.     /* Once the window is created, get the Intuition signal bit,
  1332.      * set up the menu, and tell the virtual terminal how big
  1333.      * it is.
  1334.       */
  1335.     intuitionMsgBit = EmW->UserPort->mp_SigBit;
  1336. #ifdef    DO_MENU
  1337.     if (toggling == FALSE)
  1338.         EmacsMenu = InitEmacsMenu(EmW);
  1339.     SetMenuStrip(EmW, EmacsMenu);
  1340. #endif
  1341.     setttysize();
  1342.  
  1343.     /* Set up the console device.  Create the necessary read/write
  1344.      * ports and messages, attach the console device thus created
  1345.      * to our window, initialize the console input buffer, and
  1346.      * queue the first read to the console.
  1347.      */
  1348.  
  1349.     consoleWritePort = CreatePort("Emacs.con.write",(LONG) 0);
  1350.     if (consoleWritePort == NULL)
  1351.         cleanup(4);
  1352.     consoleWriteMsg = CreateStdIO(consoleWritePort);
  1353.     if (consoleWriteMsg == NULL)
  1354.         cleanup(5);
  1355.  
  1356.     consoleReadPort = CreatePort("Emacs.con.read",(LONG) 0);
  1357.     if (consoleReadPort == NULL)
  1358.         cleanup(6);
  1359.     consoleReadMsg = CreateStdIO(consoleReadPort);
  1360.     if (consoleReadMsg == NULL)
  1361.         cleanup(7);
  1362.  
  1363.     if (OpenConsole(consoleWriteMsg,consoleReadMsg,EmW) != 0)
  1364.         cleanup(8);
  1365.     consoleMsgBit = consoleReadPort->mp_SigBit;
  1366.  
  1367.     QueueRead(consoleReadMsg,&letter);
  1368.     nibuf = ibufo = 0;
  1369.  
  1370.     return (0);
  1371. }
  1372.  
  1373. /*
  1374.  * Close the virtual terminal, aborting any
  1375.  * I/O to the console device and de-allocating
  1376.  * everything we have allocated.
  1377.  */
  1378. ttclose()
  1379. {
  1380.     ttflush();
  1381.     AbortIO(consoleReadMsg);
  1382.     CloseDevice(consoleWriteMsg);
  1383.     cleanup(0);
  1384.     Enable_Abort = 1;
  1385. }
  1386.  
  1387. /*
  1388.  * Toggle between a borderless window
  1389.  * and a sizeable window. This lets you
  1390.  * use the whole screen if you want.
  1391.  * Bound to "toggle-window-hack" by
  1392.  * ttykbd.c
  1393.  */
  1394.  
  1395. togglewindow(f, n, k)
  1396. {
  1397.     toggling = TRUE;            /* Notify the system    */
  1398. #ifdef    TOGGLE_ZOOMS
  1399.     if (!borderless) {
  1400. #endif
  1401.         leftedge = EmW->LeftEdge;    /* save window state    */
  1402.         topedge = EmW->TopEdge;
  1403.         width = EmW->Width;
  1404.         height = EmW->Height;
  1405. #ifdef    TOGGLE_ZOOMS
  1406.     }
  1407. #endif
  1408.     ttclose();                /* reset to zero    */
  1409.  
  1410.     borderless = !borderless;        /* toggle window flag    */
  1411.     ttopen();                /* re-open tty window    */
  1412.     sgarbf = TRUE;                /* screen was trashed    */
  1413.     nrow = ncol = -1;            /* trash screen size    */
  1414.     refresh();                /* and redraw it    */
  1415.     toggling = FALSE;            /* Ok, done        */
  1416.     return (TRUE);
  1417. }
  1418.  
  1419. #ifdef    CHANGE_FONT
  1420. /*
  1421.  * Select a different font for the Emacs window.
  1422.  * This obviously does not work very well
  1423.  * with proportional fonts, so we ask the
  1424.  * user to confirm before he uses one.
  1425.  * It's available if you want to be able
  1426.  * to use your own disk font (or Topaz 15
  1427.  * under 1.2) to edit with.
  1428.  */
  1429.  
  1430. setfont(f, n, k)
  1431. {
  1432.     register int    s, size;
  1433.     register struct TextFont *newfont;
  1434.     char        fontname[80], fontpath[84], fontsize[3];
  1435.     struct TextAttr    ta;
  1436.  
  1437.     /* Get font size */
  1438.     if (f == TRUE)
  1439.         size = n;
  1440.     else {
  1441.         if ((s = ereply("Font size: ",
  1442.                 fontsize, sizeof(fontsize))) != TRUE)
  1443.             return (s);
  1444.         size = atoi(fontsize);
  1445.     }
  1446.  
  1447.     if (size <= 0) {    /* reset to default font    */
  1448.         if (EmFont)
  1449.             CloseFont(EmFont);
  1450.         EmFont = NULL;
  1451.     } else {        /* user wants to set a new font name */
  1452.         if ((s = ereply("Font name (e.g. topaz): ",
  1453.                 fontname, sizeof(fontname))) != TRUE)
  1454.             return (s);
  1455.         strcpy(fontpath,fontname);
  1456.         strncat(fontpath,".font",sizeof(fontpath));/* make name */
  1457.  
  1458.         /* set up text attributes */
  1459.         ta.ta_Name = (UBYTE *)fontpath;
  1460.         ta.ta_YSize = size;
  1461.         ta.ta_Style = FS_NORMAL;
  1462.         ta.ta_Flags = 0; /* use either */
  1463.  
  1464.         /* Look for the font */
  1465.         ewprintf("Looking for %s %d...",fontname,size);
  1466.         if ((newfont = OpenDiskFont(&ta)) == NULL) {
  1467.             ewprintf("Can't find %s %d!",fontname,size);
  1468.             return (FALSE);
  1469.         } else { /* Found it! Check before using it. */
  1470.             if ((newfont->tf_YSize != size) && ((s = eyesno(
  1471.                "Size unavailable - use closest"))!=TRUE)){
  1472.                 CloseFont(newfont);
  1473.                 return (FALSE);
  1474.             }
  1475.             if ((newfont->tf_Flags & FPF_PROPORTIONAL) &&
  1476.                 (((s = eyesno("Use proportional font")))!=TRUE)){
  1477.                 CloseFont(newfont);
  1478.                 return (FALSE);
  1479.             }
  1480.             /* Get rid of old font and cache the new one */
  1481.             if (EmFont)
  1482.                 CloseFont(EmFont);
  1483.             EmFont = newfont;
  1484.         }
  1485.     }
  1486.  
  1487.     /* Now that the font is selected, close the window. */
  1488.     toggling = TRUE;            /* Notify the system    */
  1489.     ttclose();                /* reset to zero    */
  1490.     ttopen();                /* re-open w/new font    */
  1491.     nrow = -1;                /* trash size        */
  1492.     ncol = -1;                /* so refresh() works    */
  1493.     refresh();                /* redo whole screen    */
  1494.     if (size > 0)
  1495.         ewprintf("Now using font %s %d",fontname,EmFont->tf_YSize);
  1496.     else
  1497.         ewprintf("Now using default font");
  1498.     return (TRUE);
  1499. }
  1500. #endif
  1501.  
  1502. /*
  1503.  * Write a single character to the screen.
  1504.  * Buffered for extra speed, so ttflush()
  1505.  * does all the work.
  1506.  */
  1507. ttputc(c)
  1508. unsigned char c;
  1509. {
  1510.     obuf[nobuf++] = c;
  1511.     if (nobuf >= NOBUF)
  1512.         ttflush();
  1513. }
  1514.  
  1515. /*
  1516.  * Flush characters from the output buffer.
  1517.  * Just blast it out with a console write call.
  1518.  */
  1519. ttflush()
  1520. {
  1521.     if (nobuf > 0) {
  1522.         ConWrite(consoleWriteMsg, obuf, nobuf);
  1523.         nobuf = 0;
  1524.     }
  1525. }
  1526.  
  1527. /*
  1528.  * Get a character for Emacs, without echo or
  1529.  * translation.  Basically, handle Intuition
  1530.  * events until we get one that signifies
  1531.  * a character was typed in some way.
  1532.  */
  1533. ttgetc()
  1534. {
  1535.     register struct    IntuiMessage *message;    /* IDCMP message     */
  1536.     register LONG        wakeupmask;    /* which signals?    */
  1537.     register int    charfound;        /* got a character yet?    */
  1538.     unsigned char    nextchar();        /* return next char evt    */
  1539.  
  1540.     if (striptochar())            /* any chars in buffer?    */
  1541.         return (int) (nextchar() & 0xFF);
  1542.  
  1543.     charfound = FALSE;            /* nope -- have to wait    */
  1544.     do {
  1545.         wakeupmask = Wait(INTUITION_MESSAGE|CONSOLE_MESSAGE);
  1546.  
  1547.         if (wakeupmask & CONSOLE_MESSAGE) {    /* keyboard     */
  1548.             GetMsg(consoleReadPort);    /* free message     */
  1549.             qchar(letter);            /* do this FIRST */
  1550.             QueueRead(consoleReadMsg, &letter);
  1551.             charfound = TRUE;
  1552.         }
  1553.  
  1554.         if (wakeupmask & INTUITION_MESSAGE)    /* Intuition    */
  1555.             while(message =    GetMsg(EmW->UserPort))
  1556.                 if (dispatch(message) == TRUE)
  1557.                     charfound = TRUE;
  1558.     } while (charfound == FALSE);
  1559.  
  1560.     return (int) (nextchar() & 0xFF);        /* found a character!    */
  1561. }
  1562.  
  1563. /*
  1564.  * Handle the events we handle...  The result
  1565.  * returned indicates if we've put a character
  1566.  * in the input buffer.
  1567.  */
  1568. static dispatch(msg)
  1569. register struct IntuiMessage *msg;
  1570. {
  1571. #ifdef    DO_MENU
  1572.     register struct    MenuItem    *item;
  1573. #endif
  1574.     register int            txheight, txwidth;
  1575.     register struct RastPort    *rp;
  1576.     int                dx, dy, fgpen, drmode;
  1577.             
  1578.     class =    msg->Class;        /* grab the info before we     */
  1579.     code = msg->Code;        /* reply to the message        */
  1580.     qualifier = msg->Qualifier;
  1581.     address = msg->IAddress;
  1582.     x = msg->MouseX;
  1583.     y = msg->MouseY;
  1584.     ReplyMsg(msg);            /* return it to Intuition    */
  1585.  
  1586.     switch(class) {            /* see what the fuss is about    */
  1587. #ifdef    DO_MENU
  1588.     case MENUPICK:
  1589.         if (code == MENUNULL)
  1590.             return (FALSE);
  1591.         while (code != MENUNULL) {/* handle multiple selection    */
  1592.             qmenu(code);
  1593.             item = ItemAddress(EmacsMenu,(LONG) code);
  1594.             code = item->NextSelect;
  1595.         }
  1596.         return (TRUE);        /* puts <CSI>M~ in event queue    */
  1597.         break;
  1598. #endif
  1599.  
  1600. #ifdef    MOUSE
  1601.     case MOUSEBUTTONS:            /* fake the mouse key    */
  1602.         if (code != SELECTDOWN)        /* ignore SELECTUP    */
  1603.             return (FALSE);
  1604.         qmouse(x, y, qualifier);
  1605.         return (TRUE);
  1606.         break;
  1607. #endif
  1608.     case NEWSIZE:
  1609.         /* Sometimes when you resize the window to make it
  1610.          * smaller, garbage is left at the right and bottom
  1611.          * sides of the window. This code is devoted to
  1612.          * (somehow) getting rid of this garbage.  Any
  1613.          * suggestions?
  1614.          */
  1615.  
  1616.         rp = EmW->RPort;
  1617.         fgpen = rp->FgPen;        /* save params        */
  1618.         drmode = rp->DrawMode;
  1619.         SetDrMd(rp, (LONG) JAM1);
  1620.         SetAPen(rp, (LONG) EmW->RPort->BgPen);
  1621.  
  1622.         /* Check the bottom of the window
  1623.          */
  1624.         txheight = EmW->Height - EmW->BorderTop - EmW->BorderBottom;
  1625.         if (dy = (txheight % FontHeight(EmW)))
  1626.             RectFill(rp,
  1627.                 (LONG) EmW->BorderLeft,
  1628.                 (LONG) EmW->BorderTop + txheight - dy - 1,
  1629.                 (LONG) (EmW->Width - 1) - EmW->BorderRight,
  1630.                 (LONG) (EmW->Height - 1) - EmW->BorderBottom);
  1631.  
  1632.         /* Check the right side
  1633.          */
  1634.         txwidth = EmW->Width - EmW->BorderLeft - EmW->BorderRight;
  1635.         if (dx = txwidth % FontWidth(EmW))
  1636.             RectFill(rp,
  1637.                 (LONG) EmW->BorderLeft + txwidth - dx - 1,
  1638.                 (LONG) EmW->BorderTop,
  1639.                 (LONG) (EmW->Width - 1) - EmW->BorderRight,
  1640.                 (LONG) (EmW->Height - 1) - EmW->BorderBottom);
  1641.  
  1642.         SetDrMd(rp, (LONG) drmode);
  1643.         SetAPen(rp, (LONG) fgpen);    /* restore colors */
  1644.  
  1645.         /* Tell the console device to resize itself */
  1646.         ttputc(CSI);
  1647.         ttputc('t');
  1648.         ttputc(CSI);
  1649.         ttputc('u');
  1650.         ttflush();
  1651.  
  1652.         /* Signal the editor that a new size has occurred */
  1653.         qchar(ESC);
  1654.         qchar('\f');
  1655.  
  1656.         return (TRUE);            /* we done (finally)    */
  1657.         break;
  1658.  
  1659.         case CLOSEWINDOW:            /* Call quit() directly    */
  1660.         quit(FALSE, 1, KRANDOM);
  1661.         return (FALSE);
  1662.                 break;
  1663.     default:
  1664.         panic("HandleMsg: unknown event!!!");
  1665.         break;
  1666.     }
  1667.     return(FALSE);
  1668. }
  1669.  
  1670. #ifdef    DO_MENU
  1671. /*
  1672.  * Return the next menu selection number to
  1673.  * the caller.  Used by "ttymenu.c".
  1674.  */
  1675. ttmenu(codep)
  1676. USHORT *codep;
  1677. {
  1678.     register struct event *e;
  1679.     struct event *nextevt();
  1680.  
  1681.     e = nextevt();
  1682.     if (e->type != EVT_MENU)
  1683.         return (FALSE);
  1684.  
  1685.     *codep = e->data.code;
  1686.     remevt();            /* remove event by hand    */
  1687.     return (TRUE);
  1688. }
  1689. #endif
  1690.  
  1691. #ifdef    MOUSE
  1692. /*
  1693.  * Return the next mouse click values to
  1694.  * the caller.   *Rowp and *colp will contain
  1695.  * the row and column where the mouse click occured.
  1696.  * This is so that only the terminal driver has
  1697.  * to know about the size of the window's font.
  1698.  * If the flag argument f is FALSE, the mouse event
  1699.  * is *not* removed from the queue, allowing routines
  1700.  * that need to (mainly getmouse()) to peek at it.
  1701.  */
  1702. ttmouse(f, rowp,colp,qualp)
  1703. int f;
  1704. USHORT *rowp, *colp, *qualp;
  1705. {
  1706.     register struct event *e;
  1707.     struct event *nextevt();
  1708.  
  1709.     e = nextevt();
  1710.     if (e->type != EVT_MOUSE)
  1711.         return (FALSE);        /* next isn't mouse evt */
  1712.  
  1713.     *colp = e->data.mouse.col;
  1714.     *rowp = e->data.mouse.row;
  1715.     *qualp = e->data.mouse.qualifier;
  1716.     if (f)
  1717.         remevt();            /* remove the event    */
  1718.     return (TRUE);
  1719. }
  1720. #endif
  1721.  
  1722. /*
  1723.  * Return the current size of the virtual
  1724.  * terminal in nrow and ncol, making sure
  1725.  * we don't go beyond the size of the internal
  1726.  * video array.
  1727.  * Assumes the current font is monospaced
  1728.  * (not always safe bet any more :-) :-).
  1729.  */
  1730. setttysize()
  1731. {
  1732.     nrow = (EmW->Height - EmW->BorderTop
  1733.             - EmW->BorderBottom) / FontHeight(EmW);
  1734.     ncol = (EmW->Width - EmW->BorderLeft
  1735.             - EmW->BorderRight) / FontWidth(EmW);
  1736.     if (nrow < 1)
  1737.         nrow = 1;
  1738.     if (nrow > NROW)
  1739.         nrow = NROW;
  1740.     if (ncol < 1)
  1741.         ncol = 1;
  1742.     if (ncol > NCOL)
  1743.         ncol = NCOL;
  1744. }
  1745.  
  1746. /*
  1747.  * Exit as soon as possible, after displaying
  1748.  * the message.
  1749.  */
  1750. panic(s)
  1751. char *s;
  1752. {
  1753.     ewprintf(s);        /* put message at bottom    */
  1754.     Delay((ULONG) 90);    /* wait 1.5 seconds        */
  1755.     ttclose();        /* get rid of window &resources    */
  1756.     exit(10000);        /* go 'way            */
  1757. }
  1758.  
  1759. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  1760.  *             Event buffer management         *
  1761.  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  1762.  
  1763. /*
  1764.  * If the buffer's full, crap out, else
  1765.  * return a pointer to the (ibufo + nibuf)'th
  1766.  * event record (mod NIBUF).  Postincrement
  1767.  * nibuf so it points at the next record and
  1768.  * also keeps track of how many events
  1769.  * are in the buffer.
  1770.  */
  1771. static struct event *newevt()
  1772. {
  1773.     return ((nibuf < NIBUF) ? 
  1774.         (ibuf + ((ibufo + nibuf++) % NIBUF)) : NULLEVT);
  1775. }
  1776.  
  1777. /*
  1778.  * Return pointer to next item in queue,
  1779.  * *without* removing it.
  1780.  */
  1781. static struct event *nextevt()
  1782. {
  1783.     return (nibuf ? (ibuf + ibufo) : NULLEVT);
  1784. }
  1785.  
  1786. /*
  1787.  * Move buffer pointer to next item in queue.
  1788.  */
  1789. static remevt()
  1790. {
  1791.     if (nibuf <= 0)
  1792.         nibuf = 0;
  1793.     else {
  1794.         nibuf--;
  1795.         ibufo++;
  1796.         ibufo %= NIBUF;        /* wrap around in buffer    */
  1797.     }
  1798. }
  1799.  
  1800. /*
  1801.  * Return true if there are some characters available
  1802.  * in the buffer.  Unlike striptochar, don't do anything
  1803.  * to the input buffer, just return a value.
  1804.  */
  1805. typeahead()
  1806. {
  1807.     register int bufp;
  1808.  
  1809.     for (bufp = 0; bufp < nibuf; bufp++)
  1810.         if (ibuf[(ibufo + bufp) % NIBUF].type == EVT_KBD)
  1811.             return (TRUE);
  1812.     return (FALSE);
  1813. }
  1814.  
  1815. /*
  1816.  * See if there are any characters queued,
  1817.  * stripping any other events that may
  1818.  * be in the way.  *Don't* remove the character
  1819.  * from the  queue.
  1820.  */
  1821. static striptochar()
  1822. {
  1823.     register struct event *e;
  1824.  
  1825.     while (e = nextevt())
  1826.         if (e->type == EVT_KBD)
  1827.             return (TRUE);
  1828.         else
  1829.             remevt();
  1830.     return (FALSE);
  1831. }
  1832.  
  1833. /*
  1834.  * Return next character in event buffer.
  1835.  */
  1836. static unsigned char nextchar()
  1837. {
  1838.     register struct event *e;
  1839.  
  1840.     if (e = nextevt()) {
  1841.         remevt();
  1842.         return (e->data.ch);
  1843.     }
  1844.     else
  1845.         return ((unsigned char) 0);    /* shouldn't happen    */
  1846. }
  1847.  
  1848. /*
  1849.  * Add a keyboard event to the queue
  1850.  */
  1851. static qchar(c)
  1852. unsigned char c;
  1853. {
  1854.     register struct event *e;
  1855.  
  1856.     if (e = newevt()) {
  1857.         e->type = EVT_KBD;
  1858.         e->data.ch = c;
  1859.     }
  1860. }
  1861.  
  1862. #ifdef    MOUSE
  1863. /*
  1864.  * Add a mouse event to the queue, calculating
  1865.  * the row and column value from the current height
  1866.  * and width of the window's font.
  1867.  */
  1868. static qmouse(x, y, qual)
  1869. SHORT x, y;
  1870. USHORT qual;
  1871. {
  1872.     register struct event *e;
  1873.  
  1874.     qchar(CSI);
  1875.     qchar('P');
  1876.     qchar('~');
  1877.     if (e = newevt()) {
  1878.         e->type = EVT_MOUSE;
  1879.         e->data.mouse.col = (x - EmW->BorderLeft) / FontWidth(EmW);
  1880.         e->data.mouse.row = (y - EmW->BorderTop) / FontHeight(EmW);
  1881.         e->data.mouse.qualifier = qual;
  1882.     }
  1883. }
  1884. #endif
  1885.  
  1886. #ifdef    DO_MENU
  1887. /*
  1888.  * Add a menu key to queue
  1889.  */
  1890. static qmenu(code)
  1891. USHORT code;
  1892. {
  1893.     register struct event *e;
  1894.  
  1895.     qchar(CSI);        /* menu key sequence    */
  1896.     qchar('M');
  1897.     qchar('~');
  1898.     if (e = newevt()) {
  1899.         e->type = EVT_MENU;
  1900.         e->data.code = code;
  1901.     }
  1902. }
  1903. #endif
  1904.  
  1905. /*
  1906.  * Clean up.
  1907.  *
  1908.  * Fall through all the possible cases (0 means
  1909.  * get rid of everything and start with the case
  1910.  * that fits the error situation).
  1911.  */
  1912.  
  1913. static cleanup(prob)
  1914. {
  1915.     switch (prob) {
  1916.     case 0:            /* just clean everything up
  1917.  
  1918.     case 8:            /* couldn't open console device        */
  1919.         DeleteStdIO(consoleReadMsg);
  1920.     case 7:            /* couldn't get console read msg    */
  1921.         DeletePort(consoleReadPort);
  1922.     case 6:            /* couldn't get console read port    */
  1923.         DeleteStdIO(consoleWriteMsg);
  1924.     case 5:            /* couldn't get console write msg    */
  1925.         DeletePort(consoleWritePort);
  1926.     case 4:            /* couldn't get console write port    */
  1927. #ifdef    CHANGE_FONT
  1928.         if ((toggling == FALSE) && EmFont)
  1929.             CloseFont(EmFont);/* access_count-- */
  1930. #endif
  1931. #ifdef    DO_MENU
  1932.         if (toggling == FALSE) {
  1933.             ClearMenuStrip(EmW);
  1934.             DisposeMenus(EmacsMenu);
  1935.         }
  1936. #endif
  1937.         CloseWindow(EmW);
  1938.     case 3:            /* couldn't open window            */
  1939. #ifdef    CHANGE_FONT
  1940.         CloseLibrary(DiskfontBase);
  1941. #endif
  1942.     case 21:        /* couldn't open DiskfontBase        */
  1943.         CloseLibrary(IntuitionBase);
  1944.     case 2:            /* couldn't open IntuitionBase        */
  1945.         CloseLibrary(GfxBase);
  1946.     case 1:            /* couldn't open GfxBase -- do nothing    */
  1947.         break;
  1948.     }
  1949.         return(0);
  1950. }
  1951.  
  1952. SHAR_EOF
  1953. fi # end of overwriting check
  1954. if test -f 'tty/amiga/ttymenu.c'
  1955. then
  1956.     echo shar: will not over-write existing file "'tty/amiga/ttymenu.c'"
  1957. else
  1958. cat << \SHAR_EOF > 'tty/amiga/ttymenu.c'
  1959. /*
  1960.  * ttymenu.c
  1961.  *
  1962.  * Incorporates the browser, for rummaging around on disks,
  1963.  * and the usual Emacs editing command menu
  1964.  *
  1965.  *    Copyright (c) 1986, Mike Meyer
  1966.  *    Manxification and Edit menu by Mic Kaczmarczik (no charge :-)
  1967.  *
  1968.  * Permission is hereby granted to distribute this program, so long as
  1969.  * this source file is distributed with it, and this copyright notice
  1970.  * is not removed from the file.
  1971.  *
  1972.  */
  1973.  
  1974. #include <exec/types.h>
  1975. #include <libraries/dos.h>
  1976. #include <libraries/dosextens.h>
  1977. #include <intuition/intuition.h>
  1978. #undef    TRUE
  1979. #undef    FALSE
  1980. #include "def.h"
  1981.  
  1982. extern struct Menu        *AutoMenu ;
  1983. extern struct Window        *EmW ;
  1984.  
  1985. #define MNUM(menu,item,sub) (SHIFTMENU(menu)|SHIFTITEM(item)|SHIFTSUB(sub))
  1986.  
  1987. #ifdef    BROWSER
  1988. #define LONGEST_NAME    80    /* Longest file name we can deal with    */
  1989.  
  1990. # ifndef    MANX
  1991. char *strchr(char *, int);
  1992. # else
  1993. char *index();            /* find first instance of c in s    */
  1994. #define    strchr(s, c) index(s, c)
  1995. # endif
  1996.  
  1997. # ifdef    MENU
  1998. #define    FIRSTMENU    1
  1999. # else
  2000. #define    FIRSTMENU    0
  2001. # endif
  2002.  
  2003. #endif    BROWSER
  2004.  
  2005. #ifdef    MENU
  2006. /*
  2007.  * When ttgetc() sees a menu selection event, it stuffs
  2008.  * the sequence <CSI>M~ into the input buffer, and
  2009.  * caches the menu number and item number for later.
  2010.  * This sequence is translated into the internal key code
  2011.  * KMENU, similar to KHELP and the other function keys.
  2012.  *
  2013.  * The menu item names are chosen to be relatively close
  2014.  * to the extended function names, so a user can usually
  2015.  * figure out the key binding of a menu item by searching
  2016.  * through the "display-bindings" buffer for something
  2017.  * that's close.
  2018.  */
  2019.  
  2020. /*
  2021.  * Commands for managing files and buffers
  2022.  */
  2023.  
  2024. static struct MenuBinding FileItems[] = {
  2025.     { "Find File         C-x C-f",    "find-file"            },
  2026.     { "Pop To File       C-x 4 f",    "find-file-other-window"    },
  2027.     { "Insert File       C-x i",    "insert-file"            },
  2028.     { "Save File         C-x C-s",    "save-buffer"            },
  2029.     { "Write File        C-x C-w",    "write-file"            },
  2030.     { "Switch To Buffer  C-x b",    "switch-to-buffer"        },
  2031.     { "Pop To Buffer     C-x 4 b",    "switch-to-buffer-other-window"    },
  2032.     { "Kill Buffer       C-x k",    "kill-buffer"            },
  2033.     { "List Buffers      C-x C-b",    "list-buffers"            },
  2034.     { "Save Buffers      C-x s",    "save-some-buffers"        },
  2035.     { "Save And Exit     C-x C-c",    "save-buffers-kill-emacs"    }
  2036. };
  2037.  
  2038. /*
  2039.  * Commands for various editing functions
  2040.  */
  2041.  
  2042. static struct MenuBinding EditItems[] = {
  2043.     { "Yank                 C-y",    "yank"                },
  2044.     { "Blank Line           C-o ",    "open-line"            },
  2045.     { "Kill Line            C-k",    "kill-line"            },
  2046.     { "Delete Blank Lines   C-x C-o","delete-blank-lines"        },
  2047.     { "Delete Blanks        M-SPC",    "just-one-space"        },
  2048.     { "Newline And Indent   C-j",    "newline-and-indent"        },
  2049.     { "Transpose Characters C-t",    "transpose-chars"        },
  2050.     { "Quoted Insert        C-q",    "quoted-insert"            }
  2051. };
  2052.  
  2053. /*
  2054.  * Movement commands
  2055.  */
  2056.  
  2057. static struct MenuBinding MoveItems[] = {
  2058.     { "Scroll Up       C-v",    "scroll-up"            },
  2059.     { "Scroll Down     M-v",    "scroll-down"            },
  2060.     { "Start Of Line   C-a",    "beginning-of-line"        },
  2061.     { "Start Of Buffer M-<",    "beginning-of-buffer"        },
  2062.     { "End Of Line     C-e",    "end-of-line"            },
  2063.     { "End Of Buffer   M->",    "end-of-buffer"            },
  2064.     { "Goto Line",            "goto-line"            },
  2065.     { "Show Cursor     C-x =",    "what-cursor-position"        }
  2066. };
  2067.  
  2068. /*
  2069.  * Commands for searching and replacing
  2070.  */
  2071.  
  2072. static struct MenuBinding SearchItems[] = {
  2073.     { "I-Search Forward  C-s",    "isearch-forward"    },
  2074.     { "I-Search Backward C-r",    "isearch-backward"    },
  2075.     { "Search Again",        "search-again"        },
  2076.     { "Search Forward    M-s",    "search-forward"    },
  2077.     { "Search Backward   M-r",    "search-backward"    },
  2078.     { "Query Replace     M-%",    "query-replace"        }
  2079. };
  2080.  
  2081. /*
  2082.  * Commands that manipulate words
  2083.  */
  2084. static struct MenuBinding WordItems[] = {
  2085.     { "Forward Word       M-f",    "forward-word"            },
  2086.     { "Backward Word      M-b",    "backward-word"            },
  2087.     { "Kill Word          M-d",    "kill-word"             },
  2088.     { "Backward Kill Word M-DEL",    "backward-kill-word"         },
  2089.     { "Capitalize Word    M-c",    "capitalize-word"        },
  2090.     { "Downcase Word      M-l",    "downcase-word"            },
  2091.     { "Upcase Word        M-u",    "upcase-word"            }
  2092. };
  2093.  
  2094. static struct MenuBinding ParaItems[] = {
  2095.     { "Forward Paragraph  M-]",    "forward-paragraph"        },
  2096.     { "Backward Paragraph M-[",    "backward-paragraph"        },
  2097.     { "Fill Paragraph     M-q",    "fill-paragraph"        },
  2098.     { "Set Fill Column    C-x f",    "set-fill-column"        },
  2099.     { "Kill Paragraph",        "kill-paragraph"        },
  2100.     { "Auto Fill Mode",        "auto-fill-mode"        }
  2101. };
  2102.  
  2103. /*
  2104.  * Region stuff
  2105.  */
  2106.  
  2107. static struct MenuBinding RegionItems[] = {
  2108.     { "Set Mark            C-@",    "set-mark-command"        },
  2109.     { "Exch Point And Mark C-x C-x","exchange-point-and-mark"    },
  2110.     { "Kill Region         C-w",    "kill-region"            },
  2111.     { "Copy Region As Kill M-w",    "copy-region-as-kill"        },
  2112.     { "Downcase Region     C-x C-l","downcase-region"        },
  2113.     { "Upcase Region       C-x C-u","upcase-region"            }
  2114. };
  2115.  
  2116. /*
  2117.  * Commands for manipulating windows
  2118.  */
  2119.  
  2120. static struct MenuBinding WindowItems[] = {
  2121.     { "Split Window         C-x 2", "split-window-vertically"    },
  2122.     { "Delete Window        C-x 0",    "delete-window"            },
  2123.     { "Delete Other Windows C-x 1",    "delete-other-windows"        },
  2124.     { "Down Window          C-x o",    "next-window"            },
  2125.     { "Up Window",            "previous-window"        },
  2126.     { "Enlarge Window       C-x ^",    "enlarge-window"        },
  2127.     { "Shrink Window",        "shrink-window"            },
  2128.     { "Redraw Display",        "redraw-display"        },
  2129.     { "Recenter             C-l",    "recenter"            },
  2130.     { "Toggle Border",        "toggle-window-hack"        },
  2131. #ifdef    CHANGE_FONT
  2132.     { "Set Font",            "set-font"            }
  2133. #endif
  2134. };
  2135.  
  2136. /*
  2137.  * Miscellaneous commands
  2138.  */
  2139.  
  2140. static struct MenuBinding MiscItems[] = {
  2141.     { "Start Kbd Macro   C-x (",    "start-kbd-macro"        },
  2142.     { "End Kbd Macro     C-x )",    "end-kbd-macro"            },
  2143.     { "Call Kbd Macro    C-x e",    "call-last-kbd-macro"        },
  2144.     { "Execute Command   M-x",    "execute-extended-command"    },
  2145.     { "Global Set Key",        "global-set-key"        },
  2146.     { "Global Unset Key",        "global-unset-key"        },
  2147.     { "Describe Key      C-h c",    "describe-key-briefly",        },
  2148.     { "Describe Bindings C-h b",    "describe-bindings"        },
  2149.     { "Emacs Version",        "emacs-version"            },
  2150.     { "New CLI           C-z",    "suspend-emacs"            }
  2151. };
  2152.  
  2153. /*
  2154.  * The following table contains the titles, number of
  2155.  * items, and pointers to, the individual menus.
  2156.  */
  2157.  
  2158. static struct MenuInfo EMInfo[] = {
  2159.     { "File  ",        NITEMS(FileItems),    &FileItems[0]    },
  2160.     { "Edit  ",        NITEMS(EditItems),    &EditItems[0]    },
  2161.     { "Move  ",         NITEMS(MoveItems),    &MoveItems[0]    },
  2162.     { "Search  ",        NITEMS(SearchItems),    &SearchItems[0] },
  2163.     { "Word  ",        NITEMS(WordItems),    &WordItems[0]    },
  2164.     { "Paragraph  ",    NITEMS(ParaItems),    &ParaItems[0]    },
  2165.     { "Region  ",        NITEMS(RegionItems),    &RegionItems[0]    },
  2166.     { "Window  ",        NITEMS(WindowItems),    &WindowItems[0] },
  2167.     { "Miscellaneous  ",    NITEMS(MiscItems),    &MiscItems[0]    }
  2168. };
  2169.  
  2170. /* There are three cases to deal with; the menu alone, the Browser
  2171.  * alone, and both of them together.  We #define some things to make
  2172.  * life a little easier to deal with
  2173.  */
  2174. # ifdef    BROWSER
  2175. #  define Edit_Menu_Init() Menu_Add("Edit ", TRUE) 
  2176. #  define Edit_Menu_Add(n) Menu_Item_Add(n,(USHORT)ITEMENABLED,0L,(BYTE)0)
  2177. #  define Edit_Item_Add(n) Menu_SubItem_Add(n,(USHORT)ITEMENABLED,0L,(BYTE)0)
  2178. # else
  2179. #  define Edit_Menu_Init() cinf = NULL    /* harmless */
  2180. #  define Edit_Menu_Add(n) n[strlen(n)-1] = '\0'; Menu_Add(n, TRUE)
  2181. #  define Edit_Item_Add(n) Menu_Item_Add(n,(USHORT)ITEMENABLED,0L,(BYTE)0)
  2182. # endif    BROWSER
  2183.  
  2184. #endif    MENU
  2185.  
  2186. /*
  2187.  * Heeere we go!!!!
  2188.  */
  2189.  
  2190. struct Menu * InitEmacsMenu(EmW)
  2191. struct Window *EmW;
  2192. {
  2193. #ifdef    MENU
  2194.     register struct MenuInfo *cinf, *lastinfo;
  2195.     register struct MenuBinding *cb, *lastbinding;
  2196. #endif
  2197.  
  2198.     Menu_Init() ;            /* init the menu        */
  2199.  
  2200. #ifdef    MENU
  2201.  
  2202.     Edit_Menu_Init() ;        /* Set up for editing menu    */
  2203.     lastinfo = &EMInfo[NITEMS(EMInfo)];    /* loop sentinel    */    
  2204.     for (cinf = EMInfo; cinf < lastinfo; cinf++) {
  2205.         Edit_Menu_Add(cinf->Name);
  2206.         lastbinding = &cinf->Items[cinf->NumItems];
  2207.         for (cb = cinf->Items; cb < lastbinding; cb++)
  2208.             Edit_Item_Add(cb->Command);
  2209.     }
  2210. #endif    MENU
  2211.  
  2212. #ifdef    BROWSER
  2213.     Menu_Add("Disks ", TRUE) ;
  2214.     Menu_Item_Add("Df0:", (USHORT) ITEMENABLED, 0L, (BYTE) 0) ;
  2215.     Menu_Item_Add("Df1:", (USHORT) ITEMENABLED, 0L, (BYTE) 0) ;
  2216.     Menu_Item_Add("Ram:", (USHORT) ITEMENABLED, 0L, (BYTE) 0) ;
  2217. #endif    BROWSER
  2218.  
  2219.     return     AutoMenu ;
  2220. }
  2221.  
  2222. /*
  2223.  * amigamenu() -- handles a menu pick.
  2224.  */
  2225.  
  2226. amigamenu(f, n, k) {
  2227.     unsigned short        Menu_Number;
  2228.     char            *name;
  2229.     int            ttmenu(); /* in ttyio.c */
  2230.  
  2231. #ifdef    BROWSER
  2232.     register unsigned short    level, i, dirp;
  2233.     register char        *cp;
  2234.     int            stat;
  2235.     struct MenuItem        *ItemAddress() ;
  2236.  
  2237.     /* State variables that describe the current directory */
  2238.     static char        Dir_Name[LONGEST_NAME] ;
  2239.     static unsigned short    Menu_Level = 0 ;
  2240. #endif
  2241. #ifdef    MENU
  2242.     SYMBOL    *sp;
  2243. #endif
  2244.  
  2245.     if (!ttmenu(&Menu_Number)) return FALSE;    /* get menu number */
  2246.  
  2247. #ifndef    BROWSER
  2248. # ifdef    MENU
  2249.     name = EMInfo[MENUNUM(Menu_Number)].Items[ITEMNUM(Menu_Number)].Binding;
  2250.     if ((sp=symlookup(name)) != NULL)
  2251.         return ((*sp->s_funcp)(f, n, KRANDOM));
  2252.     panic("Unknown menu command!");    /* trouble!    */
  2253. # endif
  2254. #else    /* we're using the Browser */
  2255. # ifdef    MENU
  2256.     /* Handle commands from the Edit menu when using the Browser */
  2257.     if (0 == MENUNUM(Menu_Number)) {
  2258.         name = EMInfo[ITEMNUM(Menu_Number)].Items[SUBNUM(Menu_Number)].Binding;
  2259.         if ((sp=symlookup(name)) != NULL)
  2260.             return ((*sp->s_funcp)(f, n, KRANDOM));
  2261.         panic("Unknown menu command!");    /* trouble!    */
  2262.     }
  2263. # endif
  2264.     /* Here when a selection was made in a Browser menu */
  2265.     name = (char *)((struct IntuiText *)
  2266.         (ItemAddress(AutoMenu,(ULONG) Menu_Number) -> ItemFill))
  2267.         -> IText ;
  2268.     level = MENUNUM(Menu_Number) - FIRSTMENU;
  2269.  
  2270.     /* Got what we want, so clear the menu to avoid confusing the user */
  2271.     ClearMenuStrip(EmW) ;
  2272.  
  2273.     /* set dirp to FALSE if the name is not a directory or disk */
  2274.     dirp = (strchr(name, '/') != NULL || strchr(name, ':') != NULL) ;
  2275.  
  2276.     /* First, set the directory name right */
  2277.     if (level > Menu_Level)            /* Not possible, die */
  2278.         panic("impossible menu_level in amigamenu");
  2279.     else if (level == 0)            /* picked a new disk */
  2280.         Dir_Name[0] = '\0' ;
  2281.     else if (level < Menu_Level) {        /* Throw away some levels */
  2282.         for (i = 1, cp = strchr(Dir_Name, ':'); i < level; i++) {
  2283.             if (cp == NULL) return FALSE;
  2284.             cp = strchr(cp, '/') ;
  2285.             }
  2286.         if (cp == NULL) panic("broken file name in amigamenu");
  2287.         *++cp = '\0' ;
  2288.         }
  2289.     /* else Menu_Level == level, chose a file a current level */
  2290.  
  2291.     /* Now, fix up the menu and it's state variable */
  2292.     while (Menu_Level > level) {
  2293.         Menu_Level-- ;
  2294.         Menu_Pop() ;
  2295.         }
  2296.  
  2297.     /* If we added a directory, tack it onto the name */
  2298.     if (dirp) {
  2299.         Menu_Level++ ;
  2300.         (void) strncat(Dir_Name, name,
  2301.             LONGEST_NAME - strlen(Dir_Name) - 1) ;
  2302.         }
  2303.  
  2304.     /* Now, tell the user all about it */
  2305.     if (dirp) stat = Add_Dir(Dir_Name, name) ;
  2306.     else stat = Display_File(Dir_Name, name) ;
  2307.     SetMenuStrip(EmW, AutoMenu) ;
  2308.     return stat ;
  2309. #endif    BROWSER
  2310. }
  2311.  
  2312. #ifdef    BROWSER
  2313. /*
  2314.  * Display_File - Go fetch a the requested file into a window.
  2315.  */
  2316. Display_File(dir, file) char *dir, *file; {
  2317.     register BUFFER    *bp, *findbuffer();
  2318.     int        s;
  2319.     char        File_Name[LONGEST_NAME];
  2320.  
  2321.     (void) strcpy(File_Name, dir);
  2322.     (void) strncat(File_Name, file, LONGEST_NAME - strlen(File_Name) - 1) ;
  2323.     if ((bp = findbuffer(File_Name, &s)) == NULL) return s;
  2324.     curbp = bp;
  2325.     if (showbuffer(bp, curwp, WFHARD) != TRUE) return FALSE;
  2326.     if (bp->b_fname[0] == 0)
  2327.         return (readin(File_Name));        /* Read it in.    */
  2328.     return TRUE;
  2329.     }
  2330. /*
  2331.  * Add_Dir - given a dir and a name, add the menu name with the files in
  2332.  *    dir as entries.  Use AllocMem() in order to make
  2333.  *      sure the file info block is on a longword boundary.
  2334.  */
  2335. static
  2336. Add_Dir(dir, name) char *dir, *name; {
  2337.     register char            *last_char ;
  2338.     register struct FileLock    *my_lock, *Lock() ;
  2339.     unsigned short            count ;
  2340.     int                stat = FALSE;
  2341.     static char            Name_Buf[LONGEST_NAME] ;
  2342.     char                *AllocMem();
  2343.     struct    FileInfoBlock        *File_Info;
  2344.  
  2345.     if ((File_Info = (struct FileInfoBlock *)
  2346.         AllocMem((LONG)sizeof(struct FileInfoBlock), 0L)) == NULL)
  2347.         return (FALSE);
  2348.  
  2349.     /* Fix up the trailing / if it needs it */
  2350.     last_char = &dir[strlen(dir) - 1] ;
  2351.     if (*last_char == '/') *last_char = '\0' ;
  2352.  
  2353.     /* Now, start on the directory */
  2354.     if ((my_lock = Lock(dir, ACCESS_READ)) == NULL) goto out;
  2355.  
  2356.     if (!Examine(my_lock, File_Info)) goto out;
  2357.     if (File_Info -> fib_DirEntryType < 0L)
  2358.         goto out;
  2359.  
  2360.     if (Menu_Add(name, TRUE) == 0) return NULL;
  2361.     for (count = 0; ExNext(my_lock, File_Info) 
  2362.             || IoErr() != ERROR_NO_MORE_ENTRIES; count++)
  2363.         if (File_Info -> fib_DirEntryType < 0L) {
  2364.             if (Menu_Item_Add(File_Info -> fib_FileName,
  2365.                 (USHORT)ITEMENABLED, 0L, (BYTE)0)
  2366.                     == MNUM(NOMENU, NOITEM, NOSUB))
  2367.                     break ;
  2368.             }
  2369.         else {
  2370.             (void) strcpy(Name_Buf, File_Info -> fib_FileName) ;
  2371.             (void) strcat(Name_Buf, "/") ;
  2372.             if (Menu_Item_Add(Name_Buf,
  2373.                 (USHORT) ITEMENABLED, 0L, (BYTE)0)
  2374.                      == MNUM(NOMENU, NOITEM, NOSUB))
  2375.                 break ;
  2376.             }
  2377.     if (count == 0) Menu_Item_Add("EMPTY", (USHORT)0, 0L, (BYTE)0) ;
  2378.  
  2379.     /* Put everything back */
  2380.     if (*last_char == '\0') *last_char = '/' ;
  2381.     stat = TRUE;
  2382. out:
  2383.     UnLock(my_lock) ;
  2384.     FreeMem(File_Info, (LONG) sizeof(struct FileInfoBlock));
  2385.     return stat;
  2386.     }
  2387. #endif    BROWSER
  2388. SHAR_EOF
  2389. fi # end of overwriting check
  2390. #    End of shell archive
  2391. exit 0
  2392.  
  2393.