home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume3 / mg2a / part14 < prev    next >
Encoding:
Text File  |  1989-02-03  |  58.7 KB  |  2,426 lines

  1. Path: xanth!mcnc!ece-csc!ncsuvx!lll-winken!lll-tis!helios.ee.lbl.gov!pasteur!ames!necntc!ncoast!allbery
  2. From: BLARSON@ECLA.USC.EDU (Bob Larson)
  3. Newsgroups: comp.sources.misc
  4. Subject: v03i038: mg 2a part 14 of 15
  5. Message-ID: <12401301436.47.BLARSON@ECLA.USC.EDU>
  6. Date: 26 May 88 05:03:23 GMT
  7. Sender: allbery@ncoast.UUCP
  8. Reply-To: BLARSON@ECLA.USC.EDU (Bob Larson)
  9. Lines: 2413
  10. Approved: allbery@ncoast.UUCP
  11.  
  12. comp.sources.misc: Volume 3, Issue 38
  13. Submitted-By: "Bob Larson" <BLARSON@ECLA.USC.EDU>
  14. Archive-Name: mg2a/Part14
  15.  
  16. #    This is a shell archive.
  17. #    Remove everything above and including the cut line.
  18. #    Then run the rest of the file through sh.
  19. #----cut here-----cut here-----cut here-----cut here----#
  20. #!/bin/sh
  21. # shar:    Shell Archiver
  22. #    Run the following text with /bin/sh to create:
  23. #    sys/amiga/alloca.asm
  24. #    sys/amiga/menustack.c
  25. #    sys/amiga/offset.c
  26. #    sys/amiga/sleep.c
  27. #    sys/amiga/spawn.c
  28. #    sys/amiga/sysdef.h
  29. #    sys/amiga/sysinit.c
  30. #    sys/amiga/tty.c
  31. #    sys/amiga/ttydef.h
  32. #    sys/amiga/ttyicon.c
  33. #    sys/amiga/ttyio.c
  34. # This archive created: Mon May 23 18:10:12 1988
  35. # By:    blarson
  36. if test -d sys
  37. then true
  38. else mkdir sys
  39. fi
  40. if test -d sys/amiga
  41. then true
  42. else mkdir sys/amiga
  43. fi
  44. cat << \SHAR_EOF > sys/amiga/alloca.asm
  45. *
  46. * alloca()
  47. *
  48. * This routine was written by Stephen Walton, swalton@solar.stanford.edu,
  49. * a rank asm amateur, to attempt to provide the alloca() function for Manx
  50. * Aztec C on the Amiga.  It probably does horrible illegal things to the
  51. * stack but seems to mostly work.
  52. *
  53. * This subroutine expects a single int as argument, and returns a pointer
  54. * to a block of memory of that size allocated off the local stack.  Thus,
  55. * this memory is automatically freed when the current subroutine exits.
  56. *
  57. * This version for the default Manx settings (int = 16 bits).  To use
  58. * with int=32 bits, simply change both the ".w" to ".l"
  59. *
  60.     xdef    _alloca
  61. _alloca
  62.     move.l    a7,a1        ; Save current value of stack pointer
  63.     move.w    4(a7),d0    ; Number of bytes needed
  64.     suba.w    d0,a7        ; Move stack up that many places
  65.     move.l    (a1),(a7)    ; Place return address in proper place
  66.     move.l    a7,d0        ; Return value into d0
  67.     add.l    #6,d0        ;  plus amount by which stack is popped
  68.     rts            ; And back we go
  69. SHAR_EOF
  70. cat << \SHAR_EOF > sys/amiga/menustack.c
  71. /*
  72.  *  Simple menu package.  Needs lotsa work to handle some cases.
  73.  *
  74.  *  Copyright 1985
  75.  *  Louis A. Mamakos
  76.  *  Software & Stuff
  77.  *  14813 Ashford Place
  78.  *  Laurel, MD  20707
  79.  *
  80.  *  For non-commerical use only.  This program, or any modifications, may not
  81.  *  be sold or incorporated into any product without prior permission from the
  82.  *  author.
  83.  *
  84.  *  Modified by mwm to handle "stacking" menus.
  85.  *    NB - adding item to a menu that's been "popped" back to doesn't work,
  86.  *    and probably never will.
  87.  *  Modified again by MPK to allow subitems again (non-stacking), and
  88.  *  fix bug when visiting files not in last menu.
  89.  *
  90.  *  Modified once again by MPK to avoid calling strsave() if desired.  This
  91.  *    is controlled by the newly-added last parameter to *_Add(), which
  92.  *    indicates whether the menu name should be saved off by strsave().
  93.  *      I suppose *not* saving strings might break on a system where
  94.  *    MEMF_PUBLIC meant something, but I think that's far in the future...
  95.  */
  96.  
  97. #include <exec/types.h>
  98. #include <exec/nodes.h>
  99. #include <exec/lists.h>
  100. #include <exec/ports.h>
  101. #include <exec/devices.h>
  102. #include <exec/memory.h>
  103. #include <hardware/blit.h>
  104. #include <graphics/copper.h>
  105. #include <graphics/regions.h>
  106. #include <graphics/rastport.h>
  107. #include <graphics/gfxbase.h>
  108. #include <graphics/gels.h>
  109. #include <intuition/intuition.h>
  110.  
  111. #define MNUM(menu,item,sub) (SHIFTMENU(menu)|SHIFTITEM(item)|SHIFTSUB(sub))
  112. #define    Menu_Clear    DisposeMenus    /* For ttyio.c    */
  113.  
  114. extern    char    *AllocMem();
  115. extern    char    *AllocRemember();
  116.  
  117. struct    Mem_Node {
  118.    struct Node mn_Node;
  119.    struct Remember mn_Memory;
  120.    struct Menu *mn_Menu;
  121.    } *Top, *RemHead();
  122.  
  123. extern struct Screen WBInfo;    /* For Screen width & Height    */
  124. #define SCREENHEIGHT    (WBInfo . Height)
  125. #define SCREENWIDTH    (WBInfo . Width)
  126.  
  127. static struct List Memory;
  128. static int Cur_Menu, Cur_MenuItem, Cur_SubItem;
  129. static struct Menu *LastMenu;
  130. static struct MenuItem *LastMenuItem, *LastSubItem;
  131.  
  132. struct Menu *AutoMenu;      /* menu struct being dynamically built */
  133.  
  134. char *strsave();        /* Save a string in the remember list */
  135.  
  136. #ifdef LATTICE
  137. void
  138. #endif
  139. Menu_Init()
  140. {
  141.    Memory.lh_Head = (struct Node *) &(Memory.lh_Tail);
  142.    Memory.lh_TailPred = (struct Node *) &(Memory.lh_Head);
  143.    Memory.lh_Tail = NULL;
  144.    Memory.lh_Type = NT_MEMORY;
  145.    Top = NULL;
  146.    Cur_Menu = Cur_MenuItem = Cur_SubItem = -1;
  147.    AutoMenu = LastMenu = NULL;     /* no menu chain yet */
  148.    LastMenuItem = LastSubItem = NULL;
  149. }
  150.  
  151. #ifdef LATTICE
  152. void
  153. #endif
  154. Menu_Clear()
  155. {
  156.  
  157.    while ((Top = RemHead(&Memory)) != NULL) {
  158.       FreeRemember(&(Top->mn_Memory), (LONG)TRUE);
  159.       FreeMem(Top, (LONG)sizeof(struct Mem_Node));
  160.   }
  161.   Menu_Init();            /* Just for safeties sake */
  162. }
  163.  
  164. #ifdef LATTICE
  165. void
  166. #endif
  167. Menu_Pop()
  168. {
  169.  
  170.    if ((Top = RemHead(&Memory)) == NULL) return;
  171.    FreeRemember(&(Top->mn_Memory), (LONG)TRUE);
  172.    FreeMem(Top, (LONG)sizeof(struct Mem_Node));
  173.    /* Now, set Top back to the real list head */
  174.    Top = (struct Mem_Node *) Memory.lh_Head;
  175.    LastMenu = Top->mn_Menu;
  176.    LastMenu->NextMenu = NULL;    /* Tie off the menu list */
  177.    LastMenuItem = NULL;        /* Wrong, but you can't add items here anyway */
  178.    LastSubItem = NULL;        /*    ditto                      */
  179.    Cur_Menu--;
  180. }
  181.  
  182. /*
  183.  *  Add a MENU item.  Args are the text of the menu item, and an enable
  184.  *  flag.  Returns an Intuition type menu number, with the MenuItem and
  185.  *  Menu SubItem being NOITEM and NOSUB.  The MENUITEM part is valid.
  186.  */
  187. /* dummy Intuitext used to calculate length of menu names */
  188. static struct IntuiText itd = {
  189.    AUTOFRONTPEN, AUTOBACKPEN, JAM2, 1, 1, NULL, NULL, NULL
  190. };
  191.  
  192. Menu_Add(name, enabled, saveit)
  193.    char *name;
  194.    int enabled;
  195.    int saveit;
  196. {
  197.    register struct Menu *m;
  198.  
  199.    if ((Top = (struct Mem_Node *) AllocMem(
  200.          (LONG)sizeof(struct Mem_Node), MEMF_PUBLIC | MEMF_CLEAR)) == NULL)
  201.       return NULL;
  202.    Top->mn_Node.ln_Type = NT_MEMORY;
  203.  
  204.    if ((m = (struct Menu *)AllocRemember(&(Top->mn_Memory),
  205.                  (LONG)sizeof (struct Menu), MEMF_PUBLIC | MEMF_CLEAR)) == NULL)
  206.       return NULL;
  207.    Top->mn_Menu = m;
  208.  
  209.    if (LastMenu == NULL)
  210.       AutoMenu = m;     /* first menu on list */
  211.    else
  212.       LastMenu->NextMenu = m;      /* link it in */
  213.  
  214.    LastMenuItem = NULL;            /* end of previous MenuItem list */
  215.    LastSubItem = NULL;
  216.    Cur_MenuItem = Cur_SubItem = -1; /* reset item numbers */
  217.    if (LastMenu == NULL)
  218.       m->LeftEdge = 0;
  219.    else
  220.       m->LeftEdge = LastMenu->LeftEdge + LastMenu->Width;
  221.    m->TopEdge = 0;
  222.    itd.IText = (UBYTE *)name;
  223.    m->Width = IntuiTextLength(&itd);
  224.    Top->mn_Node.ln_Name = m->MenuName = saveit ? strsave(name) : name;
  225.    m->Height = 0;
  226.    m->Flags = enabled ? MENUENABLED : 0;
  227.    m->FirstItem = NULL;
  228.    LastMenu = m;
  229.  
  230.    AddHead(&Memory, Top);
  231.    return MNUM(++Cur_Menu, NOITEM, NOSUB);
  232. }
  233.  
  234. /*
  235.  *  Add a menu item to the current MENU.  Note that Add_Menu *must* be
  236.  *  called before this function.
  237.  */
  238. Menu_Item_Add(name, flags, mux, ch, saveit)
  239.    char *name;        /* name of menu item */
  240.    USHORT flags;
  241.    LONG mux;        /* mutual exclusion mask */
  242.    BYTE ch;        /* command sequence character, if COMMSEQ */
  243.    int saveit;        /* save name using strsave? */
  244. {
  245.    register struct MenuItem *m, *n;
  246.    register struct IntuiText *it;
  247.  
  248.    flags &= CHECKIT|CHECKED|COMMSEQ|MENUTOGGLE|ITEMENABLED|HIGHCOMP|HIGHBOX;
  249.    if (LastMenu == NULL)
  250.       return MNUM(NOMENU, NOITEM, NOSUB);
  251.  
  252.    if ((m = (struct MenuItem *) AllocRemember(&(Top->mn_Memory),
  253.            (LONG)sizeof(struct MenuItem), MEMF_PUBLIC | MEMF_CLEAR)) == NULL)
  254.       return MNUM(NOMENU, NOITEM, NOSUB);
  255.  
  256.    LastSubItem = NULL;        /* terminate possible list of subitems */
  257.    Cur_SubItem = -1;
  258.    if (LastMenuItem == NULL)
  259.       LastMenu->FirstItem  = m;
  260.    else
  261.       LastMenuItem->NextItem = m;
  262.    m->Flags = flags | ITEMTEXT;
  263.    /*
  264.     *  Check for highlight mode:  if none selected, use HIGHCOMP
  265.     */
  266.    if ((m->Flags & (HIGHCOMP | HIGHBOX)) == 0)
  267.       m->Flags |= HIGHCOMP;
  268.    m->Command = ch;
  269.    m->MutualExclude = mux;
  270.    m->SubItem = NULL;
  271.    m->ItemFill = (APTR) AllocRemember(&(Top->mn_Memory),
  272.                  (LONG)sizeof(struct IntuiText), MEMF_PUBLIC | MEMF_CLEAR);
  273.    it = (struct IntuiText *) m->ItemFill;
  274.    it->FrontPen = AUTOFRONTPEN;
  275.    it->BackPen = AUTOBACKPEN;
  276.    it->DrawMode = JAM2;
  277.    if (flags & CHECKIT)
  278.       it->LeftEdge = CHECKWIDTH + 1;
  279.    else
  280.       it->LeftEdge = 1;
  281.    it->TopEdge = 1;
  282.    it->ITextFont = NULL;      /* default font */
  283.    it->IText = (UBYTE *)(saveit ? strsave(name) : name);
  284.    it->NextText = NULL;
  285.    if (LastMenuItem == NULL) {
  286.       m->TopEdge = 2;
  287.       m->LeftEdge = 0;
  288.    } else if (LastMenuItem->TopEdge + 40 > SCREENHEIGHT) {
  289.       m->TopEdge = 2;
  290.       m->LeftEdge = LastMenuItem->LeftEdge + LastMenuItem->Width + 12;
  291.       if (m->LeftEdge > SCREENWIDTH) {
  292.       LastMenuItem->NextItem = NULL;
  293.       LastMenuItem->Flags &= ~ITEMENABLED;
  294.             return MNUM(NOMENU, NOITEM, NOSUB);
  295.       }
  296.    } else {
  297.       m->TopEdge = LastMenuItem->TopEdge + 10;
  298.       m->LeftEdge = LastMenuItem->LeftEdge;
  299.    }
  300.    m->Width = 0;
  301.    if (flags & CHECKIT)
  302.       m->Width += CHECKWIDTH;
  303.    if (flags & COMMSEQ)
  304.       m->Width += COMMWIDTH + 20;
  305.    m->Width += IntuiTextLength(m->ItemFill);
  306.    m->Height = 10;
  307.    /*
  308.     *  Check last menu item's width to see if it is larger than this
  309.     *  item's.  If new item is larger, then update width of all other
  310.     *  items.
  311.     */
  312.    if (LastMenuItem) {
  313.       if (LastMenuItem->Width > m->Width)
  314.         m->Width = LastMenuItem->Width;
  315.       else {
  316.          register short delta = m->Width - LastMenuItem->Width;
  317.  
  318.      for (n = LastMenu->FirstItem; n != m; n = n->NextItem) {
  319.         n->Width = m->Width;
  320.         if (n->LeftEdge > 0) n->LeftEdge += delta;
  321.      }
  322.      if (m->LeftEdge > 0) m->LeftEdge += delta;
  323.       }
  324.    }
  325.    LastMenuItem = m;
  326.    return MNUM(Cur_Menu, ++Cur_MenuItem, NOSUB);
  327. }
  328.  
  329.  
  330.  
  331. Menu_SubItem_Add(name, flags, mux, ch, saveit)
  332.    char *name, ch;
  333.    USHORT flags;
  334.    LONG mux;
  335.    int saveit;
  336. {
  337.    register struct MenuItem *m, *n;
  338.    register struct IntuiText *it;
  339.  
  340.    flags &= CHECKIT|CHECKED|COMMSEQ|MENUTOGGLE|ITEMENABLED|HIGHCOMP|HIGHBOX;
  341.    if (LastMenuItem == NULL)
  342.       return MNUM(NOMENU, NOITEM, NOSUB);
  343.  
  344.    if ((m = (struct MenuItem *) AllocRemember(&(Top->mn_Memory),
  345.            (LONG)sizeof(struct MenuItem), MEMF_PUBLIC | MEMF_CLEAR)) == NULL)
  346.       return MNUM(NOMENU, NOITEM, NOSUB);
  347.  
  348.    if (LastSubItem == NULL)
  349.       LastMenuItem->SubItem = m;
  350.    else
  351.       LastSubItem->NextItem = m;
  352.    m->Flags = flags | ITEMTEXT;
  353.    /*
  354.     * check for highlight mode.  If none selected, use HIGHCOMP
  355.     */
  356.    if ((m->Flags & (HIGHCOMP|HIGHBOX)) == 0)
  357.       m->Flags |= HIGHCOMP;
  358.    m->Command = ch;
  359.    m->MutualExclude = mux;
  360.    m->SubItem = NULL;
  361.    m->ItemFill = (APTR) AllocRemember(&(Top->mn_Memory),
  362.                      (LONG)sizeof(struct IntuiText), MEMF_PUBLIC | MEMF_CLEAR);
  363.    it = (struct IntuiText *) m->ItemFill;
  364.    it->FrontPen = AUTOFRONTPEN;
  365.    it->BackPen = AUTOBACKPEN;
  366.    it->DrawMode = JAM2;
  367.    if (flags & CHECKIT)
  368.       it->LeftEdge = CHECKWIDTH + 1;
  369.    else
  370.       it->LeftEdge = 1;
  371.    it->TopEdge = 1;
  372.    it->ITextFont = NULL;      /* default font */
  373.    it->IText = (UBYTE *)(saveit ? strsave(name) : name);
  374.    it->NextText = NULL;
  375.    m->LeftEdge = LastMenuItem->Width + 10;
  376.    m->Width = 0;
  377.    if (LastSubItem == NULL)
  378.       m->TopEdge = 1;
  379.    else
  380.       m->TopEdge = LastSubItem->TopEdge + 10;
  381.    if (flags & CHECKIT)
  382.       m->Width += CHECKWIDTH;
  383.    if (flags & COMMSEQ)
  384.       m->Width += COMMWIDTH + 20;
  385.    m->Width += IntuiTextLength(m->ItemFill);
  386.    m->Height = 10;
  387.    /*
  388.     *  Check last menu item's width to see if it is larger than this
  389.     *  item's.  If new item is larger, then update width of all other
  390.     *  items.
  391.     */
  392.    if (LastSubItem) {
  393.     if (LastSubItem->Width > m->Width)
  394.         m->Width = LastSubItem->Width;
  395.     else
  396.         for (n = LastMenuItem->SubItem; n != m; n = n->NextItem)
  397.         n->Width = m->Width;
  398.    }
  399.    LastSubItem = m;
  400.    return MNUM(Cur_Menu, Cur_MenuItem, ++Cur_SubItem);
  401. }
  402.  
  403. char *
  404. strsave(string) char *string; {
  405.    char *out ;
  406.  
  407.    out = (char *) AllocRemember(&(Top->mn_Memory), (LONG)(strlen(string) + 1),
  408.     MEMF_PUBLIC) ;
  409.    if (out == NULL) return NULL ;
  410.  
  411.    (void) strcpy(out, string) ;
  412.    return out ;
  413. }
  414. SHAR_EOF
  415. cat << \SHAR_EOF > sys/amiga/offset.c
  416. /*
  417.  * Used to return number of bytes member is from start of structure type.
  418.  * This is used because Manx 3.20a can't handle Bob's OFFSET macro 
  419.  */
  420.  
  421. char *offset_dummy = 0;
  422. SHAR_EOF
  423. cat << \SHAR_EOF > sys/amiga/sleep.c
  424. /*
  425.  * Name:    MicroEmacs
  426.  *        AmigaDOS sleep function
  427.  * Version:    31
  428.  * Last Edit:    18-Apr-86
  429.  * Created:    18-Apr-86 ...!ihnp4!seismo!ut-sally!ut-ngp!mic
  430.  */
  431.  
  432. /* There are really 60 ticks/second, but I don't want to wait that     */
  433. /* long when matching parentheses... */
  434. #define    TICKS    45
  435. extern    long Delay();
  436.  
  437. #ifdef    LATTICE
  438. void
  439. #endif
  440. sleep(n)
  441. int n;
  442. {
  443.     if (n > 0)
  444.         Delay((long) n * TICKS);
  445. }
  446. SHAR_EOF
  447. cat << \SHAR_EOF > sys/amiga/spawn.c
  448. /*
  449.  * Name:    MG
  450.  * Version:    2x
  451.  *        Spawn an AmigaDOS subprocess
  452.  * Last edit:    05-Sep-1987
  453.  * By:        ...!ihnp4!seismo!ut-sally!ut-ngp!mic
  454.  */
  455.  
  456. #include <libraries/dos.h>
  457. #include <libraries/dosextens.h>
  458. #undef TRUE
  459. #undef FALSE
  460. #include "def.h"        /* AFTER system files to avoid redef's */
  461.  
  462. /*
  463.  * Create a subjob with a copy of the command intrepreter in it.
  464.  * This is really a way to get a new copy of the CLI, because
  465.  * we don't wait around for the new process to quit.  Note the use
  466.  * of a file handle to nil: to avoid the "endcli" message going out
  467.  * to Emacs's standard output.
  468.  */
  469.  
  470. spawncli(f, n)
  471. {
  472.     struct FileHandle *nil, *Open();
  473.     
  474.     ewprintf("[Starting new CLI]");
  475.     nil = Open("NIL:", MODE_NEWFILE);
  476.     if (nil == (struct FileHandle *) 0) { /* highly unlikely */
  477.         ewprintf("Can't create nil file handle");
  478.         return (FALSE);
  479.     }
  480.     Execute("NEWCLI \"CON:0/0/640/200/MicroEmacs Subprocess\"",nil,nil);
  481.     Close(nil);
  482.     return (TRUE);
  483. }
  484.  
  485.  
  486. SHAR_EOF
  487. cat << \SHAR_EOF > sys/amiga/sysdef.h
  488. /*
  489.  * Name:    MicroEMACS
  490.  * Version:    MG 2a
  491.  *        Commodore Amiga system header file.
  492.  */
  493.  
  494. /* Neither can lattice 4 */
  495. extern char *offset_dummy;        /* Manx 3.2 can't handle 0->    */
  496. #define OFFSET(type,member) \
  497.  ((char *)&(((type *)offset_dummy)->member)-(char *)((type *)offset_dummy))
  498.  
  499. #ifdef    MANX
  500. #define    PCC    0            /* "[]" works.            */
  501. #else
  502. #define    PCC    1            /* "[]" does not work.        */
  503. #endif
  504.  
  505. #define    VARARGS
  506. #define    DPROMPT                /* we always want delayed prompts */
  507. #define    KBLOCK    4096            /* Kill grow.            */
  508. #define    GOOD    0            /* Good exit status.        */
  509. #define    SYSINIT    sysinit()        /* System-specific initialization */
  510. #define SYSCLEANUP syscleanup()        /* System-specific cleanup    */
  511. #define MALLOCROUND(m)    (m+=7,m&=~7)    /* Round up to 8 byte boundary    */
  512. #define NULL    ((char *) 0)        /* These are crass, but        */ 
  513. #define    EOF    -1            /* will work`            */
  514.  
  515. /*
  516.  * Macros used by the buffer name making code.
  517.  * Start at the end of the file name, scan to the left
  518.  * until BDC1 (or BDC2, if defined) is reached. The buffer
  519.  * name starts just to the right of that location, and
  520.  * stops at end of string (or at the next BDC3 character,
  521.  * if defined). BDC2 and BDC3 are mainly for VMS.
  522.  */
  523. #define    BDC1    ':'            /* Buffer names.        */
  524. #define    BDC2    '/'
  525.  
  526.  
  527. /*
  528.  * Typedefs for internal key type and how big a region can be.
  529.  */
  530.  
  531. typedef short    KCHAR;    /* type used to represent Emacs characters */
  532. typedef    long    RSIZE;    /* size of a region    */
  533.  
  534. #define    MAXPATH    128    /* longest expected directory path    */
  535.  
  536. #define    bcopy(src,dest,len) movmem(src,dest,len)
  537.  
  538. #define fncmp Strcmp
  539.  
  540. #ifndef NO_DIRED
  541. #define rename(s1,s2) (Rename(s1,s2) == -1 ? 0 : -1)
  542. #define unlinkdir(s1) (DeleteFile(s1) == -1 ? 0 : -1)
  543. #endif
  544. SHAR_EOF
  545. cat << \SHAR_EOF > sys/amiga/sysinit.c
  546. /*
  547.  * Name:    MG 2a
  548.  *
  549.  *         Very early-on system-specific initialization for whatever's
  550.  *        necessary.
  551.  * Last edit:    05-May-88, Stephen Walton, swalton@solar.stanford.edu
  552.  * Created:    Stephen Walton, 3-Dec-87.
  553.  *    
  554.  */
  555. #include <libraries/dosextens.h>
  556. #include "sysdef.h"
  557.  
  558. #undef    FALSE
  559. #undef    TRUE
  560. #define    TRUE    1
  561. #define    FALSE    0
  562.  
  563. #ifdef USE_ARP
  564. struct Library    *ArpBase;
  565. extern struct    Library *OpenLibrary();
  566. #endif
  567.  
  568. #ifndef    NO_DIR
  569. extern struct    Task *FindTask();
  570. static BPTR    StartLock;
  571. char        MyDirName[MAXPATH];
  572. extern BPTR    DupLock(), CurrentDir();
  573. #endif NO_DIR
  574.  
  575. sysinit()
  576. {
  577.     long len;
  578.     BPTR MyDirLock;
  579.  
  580. #ifdef USE_ARP
  581.     if (!(ArpBase = OpenLibrary("arp.library", 0L)))
  582.         panic("Compiled with USE_ARP, but arp.library not found");
  583. #endif
  584. #ifndef NO_DIR
  585.     /*
  586.      * The following attempt to be clever assigns the external StartLock
  587.      * to the lock on the current directory, then switches our CurrentDir
  588.      * to a duplicate of that lock so we can restore the original lock
  589.      * on exit.
  590.      */
  591.  
  592.     StartLock = ((struct Process *)FindTask(0L))->pr_CurrentDir;
  593.     (void) CurrentDir(MyDirLock = DupLock(StartLock));
  594.     len = PathName(MyDirLock, MyDirName, MAXPATH/31L);
  595. #endif NO_DIR
  596. }
  597.  
  598. /*
  599.  * System dependent cleanup for the Amiga.
  600.  */
  601. syscleanup()
  602. {
  603.     UnLock(CurrentDir(StartLock));    /* restore startup directory    */
  604. #ifdef USE_ARP
  605.     if (ArpBase)
  606.         CloseLibrary(ArpBase);
  607. #endif
  608. }
  609. SHAR_EOF
  610. cat << \SHAR_EOF > sys/amiga/tty.c
  611. /*
  612.  * Name:    MG 2a
  613.  *        Amiga console device virtual terminal display
  614.  * Last Edit:    29-Nov-87 mic@emx.cc.utexas.edu
  615.  * Created:    19-Apr-86 mic@emx.cc.utexas.edu
  616.  *
  617.  * Drives the Amiga console device display.  The code is basically
  618.  * like the termcap driver in that it uses the console device
  619.  * scrolling region.  It also has some hacks to manage the console
  620.  * device colors.  The latest hack is to inform the terminal I/O
  621.  * driver when we intend to do an escape sequence; this allows the
  622.  * terminal I/O driver to turn off the cursor without breaking up
  623.  * the sequences, leading to a garbled screen.
  624.  */
  625.  
  626. #include <exec/types.h>
  627. #include <exec/nodes.h>
  628. #include <exec/lists.h>
  629. #include <exec/tasks.h>
  630. #include <exec/ports.h>
  631. #include <exec/io.h>
  632. #include <devices/console.h>
  633. #include <libraries/dos.h>
  634. #include <graphics/clip.h>
  635. #include <graphics/view.h>
  636. #include <graphics/rastport.h>
  637. #include <graphics/layers.h>
  638. #include <graphics/text.h>
  639. #include <graphics/gfxbase.h>
  640. #ifndef    MANX
  641. #include <intuition/intuitionbase.h>
  642. #endif
  643. #include <intuition/intuition.h>
  644.  
  645. #undef    TRUE
  646. #undef    FALSE
  647. #include    "def.h"
  648.  
  649. #define    BEL    0x07            /* BEL character.        */
  650. #define    ESC    0x1B            /* ESC character.        */
  651. #define    LF    0x0A            /* Linefeed character        */
  652. #define    CSI    0x9B            /* Command Sequence Introducer    */
  653.  
  654. extern    int    ttrow;
  655. extern    int    ttcol;
  656. extern    int    tttop;
  657. extern    int    ttbot;
  658. extern    int    tthue;
  659.  
  660. int    tceeol    =    3;        /* Costs, ANSI display.        */
  661. int    tcinsl    =     17;
  662. int    tcdell    =    16;
  663.  
  664.  
  665. #ifdef    CHANGE_COLOR
  666. short    mode_rendition = MODE_RENDITION,    /* set standard colors */
  667.     text_rendition = TEXT_RENDITION,
  668.     text_fg = TEXT_FG + 30,
  669.     text_bg = TEXT_BG + 40,
  670.     mode_fg = MODE_FG + 30,
  671.     mode_bg = MODE_BG + 40;
  672. #else                /* colors are hard-coded        */
  673. #define mode_rendition MODE_RENDITION
  674. #define    text_rendition TEXT_RENDITION
  675. #define text_fg (TEXT_FG + 30)
  676. #define text_bg (TEXT_BG + 40)
  677. #define mode_fg (MODE_FG + 30)
  678. #define mode_bg (MODE_BG + 40)
  679. #endif
  680.  
  681. #ifdef    LATTICE
  682. VOID    asciiparm(int) ;
  683. #else
  684. VOID    asciiparm() ;
  685. #endif
  686. VOID    ttnowindow() ;
  687. VOID    ttwindow() ;
  688.  
  689. /*
  690.  * Initialize the terminal when the editor
  691.  * Initialize the virtual terminal.
  692.  * Set the console device's top edge below
  693.  * the front-to-back gadgets, to avoid
  694.  * garbage when scrolling.
  695.  */
  696. VOID
  697. ttinit()
  698. {
  699.     ttputc(CSI);
  700.     asciiparm(TOP_OFFSET);
  701.     ttputc('y');
  702. }
  703.  
  704. /*
  705.  * Clean up the terminal, in anticipation of
  706.  * a return to the command interpreter. This
  707.  * is a no-op on the Amiga, since the window
  708.  * is deleted anyway.
  709.  */
  710. VOID
  711. tttidy()
  712. {
  713. }
  714.  
  715. /*
  716.  * Move the cursor to the specified origin 0 row and column position. Try to
  717.  * optimize out extra moves; redisplay may have left the cursor in the right
  718.  * location last time!
  719.  */
  720. VOID
  721. ttmove(row, col)
  722. {
  723.     if (ttrow!=row || ttcol!=col) {
  724.         ttnflush(8);        /* flush if buffer too full     */
  725.         ttputc(CSI);
  726.         asciiparm(row+1);
  727.         ttputc(';');
  728.         asciiparm(col+1);
  729.         ttputc('H');
  730.         ttrow = row;
  731.         ttcol = col;
  732.     }
  733. }
  734.  
  735. /*
  736.  * Erase to end of line.
  737.  */
  738. VOID
  739. tteeol()
  740. {
  741.     ttnflush(2);        /* flush if not enough room to fit in buffer */
  742.     ttputc(CSI);
  743.     ttputc('K');
  744. }
  745.  
  746. /*
  747.  * Erase to end of page.
  748.  */
  749. VOID
  750. tteeop()
  751. {
  752.     ttnflush(12);        /* flush (but only if not enough room for seq */
  753.     ttputc(CSI);
  754.     asciiparm((tthue == CTEXT) ? text_rendition : mode_rendition);
  755.     ttputc(';');
  756.     asciiparm(text_fg);
  757.     ttputc(';');
  758.     asciiparm(text_bg);
  759.     ttputc('m');
  760.     ttputc(CSI);    /* clear to end of display */
  761.     ttputc('J');
  762. }
  763.  
  764. /*
  765.  * Make a noise.
  766.  */
  767. VOID
  768. ttbeep()
  769. {
  770.     ttputc(BEL);
  771.     ttflush();
  772. }
  773.  
  774. /*
  775.  * Convert a number to decimal
  776.  * ascii, and write it out. Used to
  777.  * deal with numeric arguments.
  778.  */
  779. VOID
  780. asciiparm(n)
  781. register int    n;
  782. {
  783.     if (n > 9)
  784.         asciiparm(n/10);
  785.     ttputc((n%10) + '0');
  786. }
  787.  
  788. /*
  789.  * Insert a block of blank lines onto the
  790.  * screen, using a scrolling region that starts at row
  791.  * "row" and extends down to row "bot".  Deal with the one
  792.  * line case, which is a little bit special, with special
  793.  * case code.
  794.  */
  795. VOID
  796. ttinsl(row, bot, nchunk)
  797. {
  798.     if (row == bot) {            /* Funny case.        */
  799.         if (nchunk != 1)
  800.             panic("ttinsl: nchunk != 1");
  801.         ttmove(row, 0);
  802.         tteeol();
  803.         return;
  804.     } 
  805.     ttmove(1+bot-nchunk, 0);
  806.     if (nchunk > 0) {
  807.         ttwindow(row, bot);
  808.         ttnflush(4);        /* don't break the sequence  */
  809.         ttputc(CSI);
  810.           asciiparm(nchunk);
  811.         ttputc('T');        /* Scroll scrolling region down    */
  812.         ttnowindow();
  813.     }
  814. }
  815.  
  816. /*
  817.  * Delete a block of lines, with the uppermost
  818.  * line at row "row", in a screen slice that extends to
  819.  * row "bot". The "nchunk" is the number of lines that have
  820.  * to be deleted.  It's really easy with the console
  821.  * device scrolling region.
  822.  */
  823. VOID
  824. ttdell(row, bot, nchunk)
  825. {
  826.     if (row == bot) {        /* One line special case    */
  827.         ttmove(row, 0);
  828.         tteeol();
  829.         return;
  830.     }
  831.     if (nchunk > 0) {
  832.         ttwindow(row, bot);
  833.         ttnflush(4);        /* don't break esc. sequence    */
  834.         ttputc(CSI);
  835.           asciiparm(nchunk);
  836.         ttputc('S');        /* Scroll scrolling region up    */
  837.         ttnowindow();
  838.     }
  839.     ttrow = HUGE;
  840.     ttcol = HUGE;
  841.     ttmove(bot-nchunk,0);
  842. }
  843.  
  844. /*
  845.  * This routine sets the scrolling window on the display to go from line
  846.  * "top" to line "bot" (origin 0, inclusive). The caller checks for the
  847.  * pathalogical 1 line scroll window that doesn't work right on all
  848.  * systems, and avoids it. The "ttrow" and "ttcol" variables are set
  849.  * to a crazy value to ensure that ttmove() actually does something.
  850.  */
  851.  
  852. extern    struct Window    *EmW;            /* The window MG uses */
  853.  
  854. VOID
  855. ttwindow(top,bot)
  856. {
  857.     if (tttop != top || ttbot != bot) {
  858.         ttnflush(10);            /* Flush if necessary    */
  859.         ttputc(CSI);            /* Home cursor        */
  860.         ttputc('H');
  861.  
  862.         ttputc(CSI);            /* Set top offset    */
  863.         asciiparm(TOP_OFFSET + top * FontHeight(EmW));
  864.         ttputc('y');
  865.  
  866.         ttputc(CSI);
  867.         asciiparm(bot - top + 1);    /* Set page length    */
  868.         ttputc('t');
  869.  
  870.         ttrow = HUGE;            /* Force cursor reset    */
  871.         ttcol = HUGE;
  872.         tttop = top;            /* Save region state    */
  873.         ttbot = bot;
  874.     }
  875. }
  876.  
  877. /*
  878.  * Switch to full screen scrolling
  879.  */
  880. VOID
  881. ttnowindow()
  882. {
  883.     ttnflush(10);            /* Flush if necessary        */
  884.     ttputc(CSI);            /* Home cursor            */
  885.     ttputc('H');
  886.  
  887.     ttputc(CSI);            /* Set top offset to normal    */
  888.     asciiparm(TOP_OFFSET);
  889.     ttputc('y');
  890.  
  891.     ttputc(CSI);            /* Set page length to nrow    */
  892.     asciiparm(nrow);
  893.     ttputc('t');
  894.  
  895.     ttrow = HUGE;            /* Make cursor unknown.        */
  896.     ttcol = HUGE;
  897.     tttop = HUGE;
  898.     ttbot = HUGE;
  899. }
  900.  
  901. #ifdef    CHANGE_COLOR
  902. /*
  903.  * Set the rendition of the mode line by
  904.  * selecting colors from the following:
  905.  *    0 -- plain text
  906.  *    1 -- bold-face
  907.  *    3 -- italic
  908.  *    4 -- underscore
  909.  *    7 -- inverse video
  910.  * Certain of these selections may be less than
  911.  * appealing :-)
  912.  */
  913.  
  914. ttmode(f, n)
  915. {
  916.     register int    s;
  917.     char        buf[2];
  918.  
  919.     if (!(f & FFARG)) {
  920.         if ((s = ereply("Set mode line rendition (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.     mode_rendition = n;        /* store the color    */
  929.     sgarbf = TRUE;
  930.     return (TRUE);
  931. }
  932.  
  933. /*
  934.  * Set the rendition of the text area.
  935.  * Most of these selections will be
  936.  * less than appealing :-]
  937.  */
  938.  
  939. tttext(f, n)
  940. {
  941.     register int    s;
  942.     char        buf[2];
  943.  
  944.     if (!(f & FFARG)) {
  945.         if ((s = ereply("Set text rendition (0-7): ",
  946.                 buf, sizeof(buf))) != TRUE)
  947.             return (s);
  948.         n = atoi(buf);
  949.     }
  950.     if (n < 0 || n > 7)
  951.         return (FALSE);
  952.  
  953.     text_rendition = n;        /* store the color    */
  954.     sgarbf = TRUE;
  955.     return (TRUE);
  956. }
  957.  
  958. /*
  959.  * Set foreground color for entire window
  960.  * to a value between 30 and 37, which
  961.  * corresponds to the arguments 0-7.
  962.  * This requires a total refresh, which
  963.  * sets up the screen.
  964.  */
  965.  
  966. textforeground(f, n)
  967. {
  968.     register int    s;
  969.     char        buf[2];
  970.  
  971.     if (!(f & FFARG)) {
  972.         if ((s = ereply("Text foreground color (0-7): ",
  973.                 buf, sizeof(buf))) != TRUE)
  974.             return (s);
  975.         n = atoi(buf);
  976.     }
  977.     if (n < 0 || n > 7)
  978.         return (FALSE);
  979.  
  980.     text_fg = n + 30;
  981.     sgarbf = TRUE;
  982.     return (TRUE);
  983. }
  984.  
  985. /*
  986.  * Set background color for entire window
  987.  * to a value between 40 and 47 inclusive.
  988.  */
  989.  
  990. textbackground(f, n)
  991. {
  992.     register int    s;
  993.     char        buf[2];
  994.  
  995.     if (!(f & FFARG)) {
  996.         if ((s = ereply("Text background color (0-7): ",
  997.                 buf, sizeof(buf))) != TRUE)
  998.             return (s);
  999.         n = atoi(buf);
  1000.     }
  1001.     if (n < 0 || n > 7)
  1002.         return (FALSE);
  1003.  
  1004.     text_bg = n + 40;
  1005.     sgarbf = TRUE;
  1006.     return (TRUE);
  1007. }
  1008.  
  1009. /*
  1010.  * Set foreground color for entire the mode line
  1011.  */
  1012.  
  1013. modeforeground(f, n)
  1014. {
  1015.     register int    s;
  1016.     char        buf[2];
  1017.  
  1018.     if (!(f & FFARG)) {
  1019.         if ((s = ereply("Mode line foreground color (0-7): ",
  1020.                 buf, sizeof(buf))) != TRUE)
  1021.             return (s);
  1022.         n = atoi(buf);
  1023.     }
  1024.     if (n < 0 || n > 7)
  1025.         return (FALSE);
  1026.  
  1027.     mode_fg = n + 30;
  1028.     sgarbf = TRUE;
  1029.     return (TRUE);
  1030. }
  1031.  
  1032. /*
  1033.  * Set background color for the mode line
  1034.  */
  1035.  
  1036. modebackground(f, n)
  1037. {
  1038.     register int    s;
  1039.     char        buf[2];
  1040.  
  1041.     if (!(f & FFARG)) {
  1042.         if ((s = ereply("Mode line background color (0-7): ",
  1043.                 buf, sizeof(buf))) != TRUE)
  1044.             return (s);
  1045.         n = atoi(buf);
  1046.     }
  1047.     if (n < 0 || n > 7)
  1048.         return (FALSE);
  1049.  
  1050.     mode_bg = n + 40;
  1051.     sgarbf = TRUE;
  1052.     return (TRUE);
  1053. }
  1054. #endif
  1055.  
  1056. /*
  1057.  * Set the current writing color to the
  1058.  * specified color. Watch for color changes that are
  1059.  * not going to do anything (the color is already right)
  1060.  * and don't send anything to the display.
  1061.  */
  1062.  
  1063. VOID
  1064. ttcolor(color)
  1065. register int    color;
  1066. {
  1067.     if (color != tthue) {
  1068.         ttnflush(12);            /* Flush if necessary    */
  1069.         if (color == CTEXT) {        /* Normal video.    */
  1070.             ttputc(CSI);        /* Reset to 0        */
  1071.             ttputc('m');
  1072.             ttputc(CSI);        /* Set text style    */
  1073.             asciiparm(text_rendition);
  1074.             ttputc(';');
  1075.             asciiparm(text_fg);
  1076.             ttputc(';');
  1077.             asciiparm(text_bg);
  1078.             ttputc('m');
  1079.         } else if (color == CMODE) {    /* Standout mode    */
  1080.             ttputc(CSI);        /* Reset to 0        */
  1081.             ttputc('m');
  1082.             ttputc(CSI);        /* Set standout mode    */
  1083.             asciiparm(mode_rendition);
  1084.             ttputc(';');
  1085.             asciiparm(mode_fg);    /* Use mode line colors    */
  1086.             ttputc(';');
  1087.             asciiparm(mode_bg);
  1088.             ttputc('m');
  1089.         }
  1090.         tthue = color;            /* Save the color.    */
  1091.     }
  1092. }
  1093.  
  1094. /*
  1095.  * This routine is called by the "refresh the screen" command to try and resize
  1096.  * the display. The new size, which must be deadstopped to not exceed the NROW
  1097.  * and NCOL limits, is stored back into "nrow" and "ncol". Display can always
  1098.  * deal with a screen NROW by NCOL. Look in "window.c" to see how the caller
  1099.  * deals with a change. On the Amiga, we make the Intuition terminal driver
  1100.  * do all the work.
  1101.  */
  1102.  
  1103. VOID
  1104. ttresize()
  1105. {
  1106.      setttysize();
  1107. }
  1108. SHAR_EOF
  1109. cat << \SHAR_EOF > sys/amiga/ttydef.h
  1110. /*
  1111.  * Name:    MicroEMACS
  1112.  *        Amiga console device virtual terminal header file
  1113.  * Version:    MG 2a
  1114.  * Last edit:    28-Nov-87 ...!seismo!ut-sally!ut-ngp!mic (mic@emx.cc.utexas.edu)
  1115.  * Created:    20-Apr-86 ...!seismo!ut-sally!ut-ngp!mic
  1116.  */
  1117.  
  1118. #define    GOSLING                /* Compile in fancy display. */
  1119. #define    TOP_OFFSET    11        /* # raster lines from top of window */
  1120.  
  1121. #ifndef    NROW
  1122. #define    NROW        51        /* Max rows (interlaced screen)      */
  1123. #endif
  1124.  
  1125. #ifndef    NCOL
  1126. #define    NCOL        85        /* Max cols (MoreRows, borderless) */
  1127. #endif
  1128.  
  1129. #ifndef LR_BORDER
  1130. #define    LR_BORDER (3 + 20)        /* Vertical border size (pixels)  */
  1131. #endif
  1132.  
  1133. #ifndef TB_BORDER
  1134. #define    TB_BORDER (TOP_OFFSET + 2)    /* Horizontal border size (pixels)*/
  1135. #endif
  1136.  
  1137. #ifndef    INIT_ROWS
  1138. #define    INIT_ROWS 24            /* Desired initial window height  */
  1139. #endif
  1140.  
  1141. #ifndef    INIT_COLS
  1142. #define    INIT_COLS 80            /* Desired initial window width      */
  1143. #endif
  1144.  
  1145. /*
  1146.  * Function key codes (using 16-bit KEY values)
  1147.  */
  1148. #define    KFIRST    0x100
  1149.  
  1150. #define    KUP    0x100
  1151. #define    KDOWN    0x101
  1152. #define KLEFT    0x102
  1153. #define    KRIGHT    0x103
  1154.  
  1155. #define    KSUP    0x104
  1156. #define    KSDOWN    0x105
  1157. #define    KSLEFT    0x106
  1158. #define    KSRIGHT    0x107
  1159.  
  1160. #define    KHELP    0x108
  1161. #define    KMENU    0x109
  1162. #define    KRESIZE    0x10A
  1163.  
  1164. #define    KF1    0x10C
  1165. #define    KF2    0x10D
  1166. #define KF3    0x10E
  1167. #define    KF4    0x10F
  1168. #define KF5    0x110
  1169. #define KF6    0x111
  1170. #define KF7    0x112
  1171. #define KF8    0x113
  1172. #define KF9    0x114
  1173. #define KF10    0x115
  1174.  
  1175. #define    KSF1    0x116
  1176. #define    KSF2    0x117
  1177. #define KSF3    0x118
  1178. #define    KSF4    0x119
  1179. #define KSF5    0x11A
  1180. #define KSF6    0x11B
  1181. #define KSF7    0x11C
  1182. #define KSF8    0x11D
  1183. #define KSF9    0x11E
  1184. #define KSF10    0x11F
  1185.  
  1186. #define    KW___MOUSE    0x120
  1187. #define    KW__CMOUSE    0x121
  1188. #define    KW_S_MOUSE    0x122
  1189. #define    KW_SCMOUSE    0x123
  1190. #define    KWA__MOUSE    0x124
  1191. #define    KWA_CMOUSE    0x125
  1192. #define    KWAS_MOUSE    0x126
  1193. #define    KWASCMOUSE    0x127
  1194. #define    KM___MOUSE    0x128
  1195. #define    KM__CMOUSE    0x129
  1196. #define    KM_S_MOUSE    0x12A
  1197. #define    KM_SCMOUSE    0x12B
  1198. #define    KMA__MOUSE    0x12C
  1199. #define    KMA_CMOUSE    0x12D
  1200. #define    KMAS_MOUSE    0x12E
  1201. #define    KMASCMOUSE    0x12F
  1202. #define    KE___MOUSE    0x130
  1203. #define    KE__CMOUSE    0x131
  1204. #define    KE_S_MOUSE    0x132
  1205. #define    KE_SCMOUSE    0x133
  1206. #define    KEA__MOUSE    0x134
  1207. #define    KEA_CMOUSE    0x135
  1208. #define    KEAS_MOUSE    0x136
  1209. #define    KEASCMOUSE    0x137
  1210.  
  1211. #define    KLAST    KEASCMOUSE
  1212.  
  1213. /*
  1214.  * Mouse key encoding stuff...  The bit fields are:
  1215.  *
  1216.  *           4 3       2       1     0
  1217.  *        | where    | ALT | SHIFT | CTRL
  1218.  *
  1219.  * Where ALT, SHIFT, and CTRL indicate qualifiers, and the 2-bit
  1220.  * where field indicates whether the click was (initially) in a window,
  1221.  * a mode line, or the echo line.  The mouse functions are smart enough
  1222.  * to remap themselves if necessary; we implement these as keys so
  1223.  * users can rebind things to their taste.
  1224.  */
  1225. #define    M_X_ZERO    ' '
  1226. #define    M_Y_ZERO    ' '
  1227. #define    MQ_OFFSET    0x40
  1228. #define    MQ_NOQUAL    0x00
  1229. #define    MQ_CTRL        0x01
  1230. #define    MQ_SHIFT    0x02
  1231. #define    MQ_ALT        0x04
  1232. #define    MQ_WINDOW    0x00
  1233. #define    MQ_MODE        0x08
  1234. #define    MQ_ECHO        0x10
  1235. #define    MQ_WHERE(m)    (m & 0x18)    /* get where field */
  1236. #define    MQ_QUALS(m)    (m & 0x07)    /* get qualifier field */
  1237.  
  1238. /*
  1239.  * Intuition menu interface.  Each set of menu items kept in a table of
  1240.  * MenuBinding structures, which is in turn kept in a table of MenuInfo
  1241.  * structures. These tables are indexed via the menu and item numbers to
  1242.  * find the internal extended name of the function associated with a
  1243.  * certain item.
  1244.  */
  1245. #define    MN_OFFSET    ' '        /* menu char - ' ' = real code */
  1246. struct MenuBinding {
  1247.     char    *Command;
  1248.     int    (*Function)();
  1249. };
  1250.  
  1251. struct MenuInfo {
  1252.     char *Name;            /* name of menu            */
  1253.     short NumItems;            /* # of items            */
  1254.     struct MenuBinding *Items;    /* item name, internal binding    */
  1255. };
  1256.  
  1257. #define NITEMS(arr) (sizeof(arr) / (sizeof(arr[0])))
  1258.  
  1259. /*
  1260.  * If either MENU, or BROWSER is defined, we need to define
  1261.  * DO_MENU to get the code for dealing with menu selections
  1262.  * compiled in.
  1263.  */
  1264.  
  1265. #ifdef    MENU
  1266. #define    DO_MENU
  1267. #else
  1268. #ifdef    BROWSER
  1269. #define    DO_MENU
  1270. #endif    BROWSER
  1271. #endif    MENU
  1272.  
  1273. /*
  1274.  * MODE_RENDITION and TEXT_RENDITION determine the way the mode line and
  1275.  * text area are rendered (using the SGR sequence).  TEXT_* and MODE_* set
  1276.  * the foreground (FG) and background (BG) color to the specified number.
  1277.  * If you* #define CHANGE_COLOR, you can redefine these dynamically.
  1278.  */
  1279.  
  1280. #ifndef MODE_RENDITION
  1281. #define    MODE_RENDITION 7
  1282. #endif
  1283.  
  1284. #ifndef TEXT_RENDITION
  1285. #define    TEXT_RENDITION 0
  1286. #endif
  1287.  
  1288. #ifndef    TEXT_FG
  1289. #define TEXT_FG 1
  1290. #endif
  1291.  
  1292. #ifndef TEXT_BG
  1293. #define TEXT_BG 0
  1294. #endif
  1295.  
  1296. #ifndef    MODE_FG
  1297. #define MODE_FG 1
  1298. #endif
  1299.  
  1300. #ifndef    MODE_BG
  1301. #define MODE_BG 0
  1302. #endif
  1303.  
  1304. /*
  1305.  * Return the width and height of
  1306.  * the default font for a window.
  1307.  */
  1308.  
  1309. #define    FontWidth(w) (w)->RPort->TxWidth
  1310. #define    FontHeight(w) (w)->RPort->TxHeight
  1311. SHAR_EOF
  1312. cat << \SHAR_EOF > sys/amiga/ttyicon.c
  1313. /*
  1314.  * Name:    MG 2a
  1315.  *        Iconify the MG window using Leo Schwab's iconify() routine.
  1316.  * Last Edit:    07-Jan-88    mic@emx.utexas.edu
  1317.  * Created:    04-Jan-88    mic@emx.utexas.edu
  1318.  */
  1319.  
  1320. #ifdef    DO_ICONIFY
  1321.  
  1322. #include <exec/types.h>
  1323. #include <exec/memory.h>
  1324. #include <intuition/intuition.h>
  1325. #include "iconify.h"
  1326. #undef    TRUE
  1327. #undef    FALSE
  1328. #include "def.h"
  1329.  
  1330. /*
  1331.  * Simple Mg 2a icon image.  We need a more imaginative one.
  1332.  */
  1333.  
  1334. UWORD mg2a[160] = {
  1335. /* Bit Plane #0 */
  1336.  
  1337.    0x0000,0x0000,0x0000,0x0000,
  1338.    0x3fff,0xffff,0xffff,0xf000,
  1339.    0x3fff,0xffff,0xffff,0xf000,
  1340.    0x3c00,0x0000,0x0000,0xf000,
  1341.    0x3cc1,0x8f80,0x0000,0xf000,
  1342.    0x3ce3,0x9ce0,0x0000,0xf000,
  1343.    0x3cf7,0xb800,0x0000,0xf000,
  1344.    0x3cff,0xb9e0,0x0000,0xf000,
  1345.    0x3cfb,0xb8e0,0x0000,0xf000,
  1346.    0x3ce3,0x9ce3,0xf000,0xf000,
  1347.    0x3ce3,0x8fe7,0x3800,0xf000,
  1348.    0x3c00,0x0000,0x39f8,0xf000,
  1349.    0x3c00,0x0000,0xf01c,0xf000,
  1350.    0x3c00,0x0003,0x80fc,0xf000,
  1351.    0x3c00,0x0007,0x3b1c,0xf000,
  1352.    0x3c00,0x0007,0xf9ee,0xf000,
  1353.    0x3c00,0x0000,0x0000,0xf000,
  1354.    0x3fff,0xffff,0xffff,0xf000,
  1355.    0x3fff,0xffff,0xffff,0xf000,
  1356.    0x0000,0x0000,0x0000,0x0000,
  1357.  
  1358. /* Bit Plane #1 */
  1359.  
  1360.    0xffff,0xffff,0xffff,0xfc00,
  1361.    0xffff,0xffff,0xffff,0xfc00,
  1362.    0xf000,0x0000,0x0000,0x3c00,
  1363.    0xf000,0x0000,0x0000,0x3c00,
  1364.    0xf040,0x8000,0x0000,0x3c00,
  1365.    0xf020,0x8420,0x0000,0x3c00,
  1366.    0xf010,0x8800,0x0000,0x3c00,
  1367.    0xf000,0x8820,0x0000,0x3c00,
  1368.    0xf020,0x8820,0x0000,0x3c00,
  1369.    0xf020,0x8420,0x1000,0x3c00,
  1370.    0xf020,0x8021,0x0800,0x3c00,
  1371.    0xf000,0x0000,0x0808,0x3c00,
  1372.    0xf000,0x0000,0x1004,0x3c00,
  1373.    0xf000,0x0000,0x8004,0x3c00,
  1374.    0xf000,0x0001,0x0804,0x3c00,
  1375.    0xf000,0x0000,0x0802,0x3c00,
  1376.    0xf000,0x0000,0x0000,0x3c00,
  1377.    0xf000,0x0000,0x0000,0x3c00,
  1378.    0xffff,0xffff,0xffff,0xfc00,
  1379.    0xffff,0xffff,0xffff,0xfc00
  1380. };
  1381.  
  1382. static struct Image iconimg = {        /*  Icon Image  */
  1383.      0, 0,
  1384.     54, 20, 2,
  1385.     NULL,    /* filled in later */
  1386.     0x3, 0,
  1387.     NULL
  1388. };
  1389.  
  1390. /*
  1391.  * Iconify MG's window using tthide(), iconify(), and ttshow().
  1392.  */
  1393.  
  1394. int tticon(f, n)
  1395. {
  1396.     static UWORD    iconX = 0, iconY = 0;
  1397.     UWORD        *chipbitmap;
  1398.     struct Image    *chipimg;
  1399.     extern short    toggling;
  1400.     extern APTR    AllocMem();
  1401.  
  1402.     /* copy the bitmap into chip memory */
  1403.     if (NULL == (chipbitmap = (UWORD * )
  1404.         AllocMem((ULONG) sizeof(mg2a), MEMF_CHIP | MEMF_PUBLIC))) {
  1405.         ewprintf("Can't allocate image bitmap");
  1406.         return FALSE;
  1407.     }
  1408.     bcopy((char *)mg2a, (char *)chipbitmap, (int) sizeof(mg2a));
  1409.  
  1410.     /* copy the image structure too */
  1411.     if (NULL == (chipimg = (struct Image *)
  1412.         AllocMem((ULONG) sizeof(iconimg), MEMF_CHIP | MEMF_PUBLIC))) {
  1413.         FreeMem(chipbitmap, (ULONG) sizeof(iconimg));
  1414.         ewprintf("Can't allocate image structure");
  1415.         return FALSE;
  1416.     }
  1417.     bcopy((char *)&iconimg, (char *)chipimg, (int) sizeof(iconimg));
  1418.     chipimg->ImageData = chipbitmap;
  1419.  
  1420.     /* hide the window, display the icon, then redisplay the window */
  1421.     tthide(FALSE);    /* not resizing */
  1422.  
  1423.     iconify(&iconX, &iconY, chipimg->Width, chipimg->Height, NULL,
  1424.         (APTR) chipimg, (int) ICON_IMAGE); /* iconify    */
  1425.     FreeMem(chipimg, (ULONG) sizeof(iconimg));
  1426.     FreeMem(chipbitmap, (ULONG) sizeof(mg2a));
  1427.  
  1428.     ttshow(FALSE);    /* no resize */
  1429.     return TRUE;
  1430. }
  1431. #endif DO_ICONIFY
  1432. SHAR_EOF
  1433. cat << \SHAR_EOF > sys/amiga/ttyio.c
  1434. /*
  1435.  * Name:    MG 2a
  1436.  *        Amiga terminal window I/O, with all kinds o' trimmings.
  1437.  *        This module is 'way too big.
  1438.  * Last Edit:    01-Dec-87 mic@emx.cc.utexas.edu
  1439.  * Created:    21-Apr-86 mic@emx.cc.utexas.edu
  1440.  */
  1441.  
  1442. /*
  1443.  * Lots of includes.
  1444.  */
  1445.  
  1446. #include <exec/types.h>
  1447. #include <exec/nodes.h>
  1448. #include <exec/lists.h>
  1449. #include <exec/tasks.h>
  1450. #include <exec/ports.h>
  1451. #include <exec/io.h>
  1452. #include <devices/console.h>
  1453. #include <devices/inputevent.h>
  1454. #include <libraries/dos.h>
  1455. #include <graphics/clip.h>
  1456. #include <graphics/view.h>
  1457. #include <graphics/rastport.h>
  1458. #include <graphics/layers.h>
  1459. #include <graphics/text.h>
  1460. #include <graphics/gfxbase.h>
  1461. #include <intuition/intuition.h>
  1462. #include <intuition/intuitionbase.h>
  1463. #include <libraries/diskfont.h>
  1464.  
  1465. #undef    TRUE            /* avoid redefinition messages         */
  1466. #undef    FALSE
  1467. #include "def.h"        /* includes sysdef.h and ttydef.h    */
  1468.  
  1469. /*
  1470.  * External Amiga functions.
  1471.  */
  1472. extern    LONG             AbortIO();
  1473. extern    LONG             CloseDevice();
  1474. extern    LONG             CloseLibrary();
  1475. extern    LONG             CloseWindow();
  1476. extern    struct    MsgPort        *CreatePort();
  1477. extern    struct    IOStdReq    *CreateStdIO();
  1478. extern    LONG             DeletePort();
  1479. extern    LONG             DeleteStdIO();
  1480. extern    struct    IntuiMessage    *GetMsg();
  1481. #ifndef    V11
  1482. extern    LONG            GetScreenData();
  1483. #endif
  1484. extern    int             OpenConsole();
  1485. extern    char            *OpenLibrary();
  1486. extern    struct    Window        *OpenWindow();
  1487. extern    struct TextFont        *OpenDiskFont();
  1488. extern    LONG             RectFill();
  1489. extern    LONG             ReplyMsg();
  1490. extern    LONG             RawKeyConvert();
  1491. extern    LONG             SetAPen();
  1492. extern    LONG             SetDrMd();
  1493. extern    LONG             Wait();
  1494.  
  1495. #ifdef    DO_MENU
  1496. extern    LONG             ClearMenuStrip();    /* menu functions */
  1497. extern    struct    Menu        *InitEmacsMenu();
  1498. extern    struct    MenuItem    *ItemAddress();
  1499. extern    LONG             SetMenuStrip();
  1500. #endif
  1501.  
  1502. #ifdef    MANX
  1503. extern    int    Enable_Abort;        /* Do NOT allow abort!        */
  1504. #endif
  1505.  
  1506. /*
  1507.  * External MG functions and variables
  1508.  */
  1509. extern    int    quit();            /* Defined by "main.c"        */
  1510. extern    char    version[];        /* Version information        */
  1511. extern    int    ttrow;            /* Current cursor row        */
  1512. extern    int    use_metakey;        /* Do meta characters?        */
  1513.  
  1514. /*
  1515.  * Non-int internal functions.  P?() is used to conditionally indicate
  1516.  * ANSI-style prototype arguments for compilers (i.e. Lattice) that
  1517.  * support them.
  1518.  */
  1519. #ifdef    LATTICE
  1520. #define    P1(a)    a,
  1521. #define    P2(a,b)    a,b
  1522. #define    P3(a,b,c) a,b,c
  1523. #else
  1524. #define    P1(a)
  1525. #define    P2(a,b)
  1526. #define P3(a,b,c)
  1527. #endif
  1528.  
  1529. VOID        panic(P1(char *));
  1530. VOID        setttysize();
  1531. VOID        ttclose();
  1532. VOID        ttflush();
  1533. VOID        ttnflush(P1(int));
  1534. VOID        ttputc(P1(unsigned char));
  1535.  
  1536. static VOID    cleanup();
  1537. static VOID    firstwin();
  1538. static VOID    qkey(P1(KCHAR));
  1539. #ifdef    DO_MENU
  1540. static VOID    qmenu(P1(USHORT));
  1541. #endif
  1542. #ifdef    MOUSE
  1543. static VOID    qmouse(P3(SHORT, SHORT, USHORT));
  1544. #endif
  1545. static VOID    ttreopen(P1(int)) ;
  1546. static VOID    setmaxima() ;
  1547. static struct Screen    *wbscreen();
  1548.  
  1549. /*
  1550.  * Library bases (used by glue libraries)
  1551.  */
  1552.  
  1553. struct    IntuitionBase    *IntuitionBase;
  1554. struct    GfxBase        *GfxBase;
  1555. ULONG            DiskfontBase;
  1556.  
  1557. /*
  1558.  * Intuition window and menu variables.  MG gets used a lot, because it
  1559.  * gets reconfigured on the fly for the amiga-set-font and toggle-border
  1560.  * operations.
  1561.  */
  1562.  
  1563. #define WINDOWGADGETS (WINDOWDRAG | WINDOWDEPTH | WINDOWCLOSE)
  1564. #define WINDOWFLAGS    (WINDOWGADGETS | ACTIVATE)
  1565.  
  1566. struct NewWindow MG = {
  1567.     0,    0,            /* start position           */
  1568.     0,    0,            /* width, height (set by ttopen)*/
  1569.     0,    1,                 /* detail pen, block pen    */
  1570. #ifdef    DO_MENU
  1571.     MENUPICK |            /* If menu is used        */
  1572. #endif
  1573. #ifdef    MOUSE
  1574.     MOUSEBUTTONS |             /* If mouse is used        */
  1575. #endif
  1576.     INTUITICKS | RAWKEY |
  1577.     CLOSEWINDOW | NEWSIZE,        /* IDCMP flags            */
  1578.     0,                /* window flags    (set by ttopen)    */
  1579.     NULL,                /* pointer to first user gadget */
  1580.     NULL,                /* pointer to user checkmark    */ 
  1581.     NULL,                /* title (filled in later)    */
  1582.     NULL,                /* pointer to screen (none)    */
  1583.     NULL,                /* pointer to superbitmap    */
  1584.     220,40,                /* minimum size    (small!)    */
  1585.     0, 0,                /* maximum size (set by ttopen)    */
  1586.     WBENCHSCREEN            /* screen in which to open    */ 
  1587. };
  1588.  
  1589. static short    borderless = TRUE;    /* Flag for borderless window    */
  1590. static short    toggle_zooms = TRUE;    /* Does toggling border zoom?    */
  1591. static int    last_top, last_left, last_height, last_width;
  1592.  
  1593. struct Window    *EmW = NULL;        /* Our window            */
  1594. struct Screen    *EmS = NULL;        /* Our screen (usually WB)    */
  1595. short        toggling = FALSE;    /* Prevent menu wiping        */
  1596. #ifndef    V11
  1597. struct Screen    WBInfo;            /* Info about the WB screen    */
  1598. #endif
  1599. struct TextFont *EmFont = NULL;        /* Our font (usually TOPAZ_xx)    */
  1600.  
  1601. #ifdef    DO_MENU
  1602. static struct Menu    *EmacsMenu = NULL;    /* Our menu        */
  1603. #endif
  1604.  
  1605. static ULONG        class;            /* Intuition event    */
  1606. static USHORT        code,            /*   information    */
  1607.             qualifier;
  1608. static APTR        address;
  1609. static SHORT        x, y;
  1610. static LONG        intuitionMsgBit;    /* Signal bit        */
  1611. #define INTUITION_MESSAGE ((LONG) (1L << intuitionMsgBit))
  1612.  
  1613. /* * * * * * * * * * * * * console I/O * * * * * * * * * * * * * * * * */
  1614.  
  1615. #define    CSI    0x9b            /* Command Sequence Introducer    */
  1616. #define    NOBUF    512            /* About 1/4 screen        */
  1617. #define    NIBUF    256            /* Input buffer            */
  1618.  
  1619. static KCHAR        ibuf[NIBUF];    /* keyboard input buffer    */
  1620. static int        ibufo, nibuf;    /* head, # of bytes in ibuf    */
  1621.  
  1622. #ifndef    PROMPTWAIT
  1623. #define    PROMPTWAIT 20            /* ticks to wait before timeout    */
  1624. #endif
  1625. static    LONG        tickcount;    /* # intuiticks    since last char    */
  1626.  
  1627. static struct MsgPort    *conWritePort = NULL;    /* I/O ports         */
  1628. static struct IOStdReq    *conWriteMsg = NULL;    /* I/O messages        */
  1629. struct Device        *ConsoleDevice;            /* used by RawKeyConvert*/
  1630. static unsigned char    outbuf[NOBUF+7];    /* output buffer    */
  1631. static unsigned char    *obuf;            /* first output char    */
  1632. int            nobuf;            /* # of bytes in above    */
  1633. int            nrow;            /* Terminal size, rows.    */
  1634. int            ncol;            /* Terminal size, cols.    */
  1635.  
  1636. /* * * * * * * * * functions to open/reopen the window * * * * * * * * * */
  1637.  
  1638. /*
  1639.  * Open up the virtual terminal MG communicates with. Set up the window,
  1640.  * console, and menu strip.
  1641.  */
  1642.  
  1643. ttopen()
  1644. {
  1645.  
  1646. #ifdef    MANX
  1647.     Enable_Abort = 0;                /* Disable ^C    */
  1648. #endif
  1649.  
  1650.     /* firstwin() is only called the very first time we open the window */
  1651.     if (toggling == FALSE)
  1652.         firstwin();
  1653.  
  1654.     /* Set the window size, set the flags and title, and open it */
  1655.  
  1656.     setmaxima();
  1657.     MG.Flags = WINDOWFLAGS;
  1658.     MG.Flags |= borderless ? BORDERLESS : WINDOWSIZING;
  1659.     MG.Title = (UBYTE *) &version[0];
  1660.  
  1661.     if ((EmW = OpenWindow(&MG)) == NULL)
  1662.         cleanup();
  1663.     SetFont(EmW->RPort, EmFont);
  1664.  
  1665.     /* Once the window is created, get the Intuition signal bit, set up
  1666.      * the menu, and tell the virtual terminal how big it is.
  1667.       */
  1668.     setttysize();
  1669.     intuitionMsgBit = EmW->UserPort->mp_SigBit;
  1670. #ifdef    DO_MENU
  1671.     if (toggling == FALSE)
  1672.         EmacsMenu = InitEmacsMenu(EmW);
  1673.     if (EmacsMenu == NULL)
  1674.         cleanup();
  1675.     SetMenuStrip(EmW, EmacsMenu);
  1676. #endif
  1677.  
  1678.     /* Attach a console device (purely for output now) to our window
  1679.      */
  1680.  
  1681.     if ((conWritePort = CreatePort("Emacs.con.write", 0L)) == NULL)
  1682.         cleanup();
  1683.     if ((conWriteMsg = CreateStdIO(conWritePort)) == NULL)
  1684.         cleanup();
  1685.  
  1686.     if (OpenConsole(conWriteMsg,NULL,EmW) != 0)
  1687.         cleanup();
  1688.  
  1689.     ConsoleDevice = conWriteMsg->io_Device;
  1690.     nibuf = ibufo = 0;
  1691.  
  1692.     return (0);
  1693. }
  1694.  
  1695. /*
  1696.  * Set up the initial state of the window.  Opens up libraries, decides how
  1697.  * big the initial window should be, and whether it should be borderless.
  1698.  */
  1699.  
  1700. static VOID firstwin()
  1701. {
  1702.     GfxBase = (struct GfxBase *) OpenLibrary("graphics.library", 0L);
  1703.     if (GfxBase == NULL)                /* Graphics lib    */
  1704.         cleanup();
  1705.  
  1706.     IntuitionBase = (struct IntuitionBase *)     /* Intuition    */
  1707.         OpenLibrary("intuition.library", 0L);
  1708.     if (IntuitionBase == NULL)
  1709.         cleanup();
  1710.  
  1711.     DiskfontBase = (ULONG) OpenLibrary("diskfont.library", 0L);
  1712.     if (DiskfontBase == NULL)
  1713.         cleanup();
  1714.  
  1715.     /* Get our screen and font, then figure out if we can go borderless
  1716.     */
  1717.     if ((EmS = wbscreen()) == NULL)
  1718.         cleanup();
  1719.     EmFont = OpenDiskFont(EmS->Font);
  1720.     if ((EmS->Width >= ((INIT_COLS * EmFont->tf_XSize) + LR_BORDER)) &&
  1721.         (EmS->Height >= ((INIT_ROWS * EmFont->tf_YSize) + TB_BORDER)))
  1722.         borderless = FALSE;
  1723.  
  1724.     /* Set the size of the initial window and fake the last one
  1725.      */
  1726.     last_width = MG.Width = EmS->Width;
  1727.     last_height = MG.Height = EmS->Height;
  1728.     last_left = MG.LeftEdge = 0;
  1729.     last_top = MG.TopEdge = 0;
  1730.  
  1731.     bcopy(outbuf,"\x9b0 p", 4);    /* preload cursor off sequence */
  1732.     obuf = outbuf + 4;
  1733. }
  1734.  
  1735. /*
  1736.  * Make sure the window isn't bigger than NROW * NCOL, while accounting
  1737.  * for borders & such.  Since the window might not be at its largest right
  1738.  * now, deadstop both the current width and the maxwidth.
  1739.  */
  1740.  
  1741. static VOID setmaxima()
  1742. {
  1743.     register int maxw, maxh;
  1744.  
  1745.     MG.MaxWidth = EmS->Width;
  1746.     MG.MaxHeight = EmS->Height;
  1747.     maxw = NCOL * EmFont->tf_XSize + (borderless ? 0 : LR_BORDER);
  1748.     maxh = NROW * EmFont->tf_YSize + (borderless ? TOP_OFFSET : TB_BORDER);
  1749.  
  1750.     if (MG.MaxWidth > maxw)        MG.MaxWidth = maxw;
  1751.     if (MG.Width > maxw)        MG.Width = maxw;
  1752.  
  1753.     if (MG.MaxHeight > maxh)    MG.MaxHeight = maxh;
  1754.     if (MG.Height > maxh)        MG.Height = maxh;
  1755. }
  1756.  
  1757.  
  1758. /* Return a pointer the workbench screen, using GetScreenData() to do
  1759.  * things like a good citizen.  Left the V11 code in as a reminder
  1760.  * that what works is not always the _best_ way to do things.
  1761.  * Thanks to Tom Rokicki for reminding me (mpk) this had to be done.
  1762.  */
  1763.  
  1764. static struct Screen
  1765. *wbscreen()
  1766. {
  1767. #ifndef    V11
  1768.     return GetScreenData(&WBInfo, (ULONG) sizeof(WBInfo),
  1769.         WBENCHSCREEN, NULL) ? &WBInfo : ((struct Screen *)NULL);
  1770. #else
  1771.     register struct Screen    *s;
  1772.     Forbid();
  1773.     for (s = IntuitionBase->FirstScreen; s ; s = s->NextScreen)
  1774.         if ((s->Flags & SCREENTYPE) == WBENCHSCREEN)
  1775.             break;
  1776.     Permit();
  1777.     return (s);
  1778. #endif
  1779. }
  1780.  
  1781. /*
  1782.  * Hide the window and open it up again.  If resize is TRUE, they're
  1783.  * being called as part of a resize operation, so assume that the
  1784.  * NewWindow structure is set correctly.  Otherwise, store the current
  1785.  * window size and position in the NewWindow structure.
  1786.  *
  1787.  * These two functions are split so we can do things like ttreopen() and
  1788.  * tticon() cleanly.
  1789.  */
  1790.  
  1791. VOID
  1792. tthide(resize)
  1793. int resize;
  1794. {
  1795.     toggling = TRUE;
  1796.     if (resize == FALSE) {             /* if we're resizing,    */
  1797.         MG.LeftEdge = EmW->LeftEdge; /* use current window size    */
  1798.         MG.TopEdge = EmW->TopEdge;
  1799.         MG.Width = EmW->Width;
  1800.         MG.Height = EmW->Height;
  1801.     }
  1802.     ttclose();                /* reset to zero    */
  1803. }
  1804.  
  1805. VOID
  1806. ttshow(resize)
  1807. int resize;
  1808. {
  1809.     ttopen();                /* re-open tty window    */
  1810.     ttinit();                /* re-initalize tty    */
  1811.     sgarbf = TRUE;                /* screen was trashed    */
  1812.     if (resize == TRUE)
  1813.         nrow = ncol = -1;        /* trash screen size    */
  1814.     refresh();                /* and redraw it    */
  1815.     toggling = FALSE;            /* Ok, done        */
  1816. }
  1817.  
  1818. /*
  1819.  * ttreopen() was split into the two functions above when tticon()
  1820.  * was introduced.
  1821.  */
  1822.  
  1823. static VOID
  1824. ttreopen(resize)
  1825. int resize;
  1826. {
  1827.     tthide(resize);
  1828.     ttshow(resize);
  1829. }
  1830.  
  1831. /* * * * * * * * * * * * functions to close the window * * * * * * * * */
  1832.  
  1833. /*
  1834.  * Close the virtual terminal.  If toggling, don't release all
  1835.  * the other resources we've allocated.
  1836.  */
  1837. VOID
  1838. ttclose()
  1839. {
  1840.     ttflush();
  1841.     CloseDevice(conWriteMsg);
  1842.     DeleteStdIO(conWriteMsg);    conWriteMsg = NULL;
  1843.     DeletePort(conWritePort);    conWritePort = NULL;
  1844. #ifdef    DO_MENU
  1845.     ClearMenuStrip(EmW);
  1846. #endif
  1847.     CloseWindow(EmW);
  1848.     if (toggling == FALSE)
  1849.         cleanup();        /* clean up everything    */
  1850. #ifdef    MANX
  1851.     Enable_Abort = 1;
  1852. #endif
  1853. }
  1854.  
  1855.  
  1856. /*
  1857.  * Clean up.  Done only when we're really closing up shop
  1858.  */
  1859.  
  1860. static VOID
  1861. cleanup()
  1862. {
  1863.     if (conWriteMsg)    DeleteStdIO(conWriteMsg);
  1864.     if (conWritePort)    DeletePort(conWritePort);
  1865. #ifdef    DO_MENU
  1866.     if (EmacsMenu)        DisposeMenus(EmacsMenu);
  1867. #endif
  1868.     if (EmFont)        CloseFont(EmFont);
  1869.     if (DiskfontBase)    CloseLibrary(DiskfontBase);
  1870.     if (IntuitionBase)    CloseLibrary(IntuitionBase);
  1871.     if (GfxBase)        CloseLibrary(GfxBase);
  1872. }
  1873.  
  1874. /* * * * * * * * functions that diddle the window and reopen it * * * * * */
  1875.  
  1876. /*
  1877.  * Toggle between a borderless window and a sizeable window. This lets you
  1878.  * use the whole screen if you want. Bound to "amiga-toggle-border".
  1879.  */
  1880.  
  1881. togglewindow(f, n)
  1882. {
  1883.  
  1884.     if ((borderless = !borderless) == TRUE) {/* *always* save last     */
  1885.         last_top = EmW->TopEdge;    /* bordered window size     */
  1886.         last_left = EmW->LeftEdge;
  1887.         last_width = EmW->Width;
  1888.         last_height = EmW->Height;
  1889.     }
  1890.  
  1891.     if (toggle_zooms == FALSE) {        /* just use current size */
  1892.         ttreopen(FALSE);    
  1893.         return (TRUE);
  1894.     }
  1895.  
  1896.     /* zooming -- if borderless, go as big as possible.  If
  1897.      * bordered, set to last saved value of bordered window
  1898.      */
  1899.     if (borderless) {
  1900.         MG.LeftEdge = 0;
  1901.         MG.TopEdge = 0;
  1902.         MG.Width = MG.MaxWidth;
  1903.         MG.Height = MG.MaxHeight;
  1904.     } else {
  1905.         MG.LeftEdge = last_left;
  1906.         MG.TopEdge = last_top;
  1907.         MG.Width = last_width;
  1908.         MG.Height = last_height;
  1909.     }
  1910.     ttreopen(TRUE);            /* open with new size    */
  1911.     return (TRUE);
  1912. }
  1913.  
  1914. /*
  1915.  * Modify the action of "amiga-toggle-border", reporting outcome to user.
  1916.  * Bound to "amiga-zoom-mode".
  1917.  */
  1918. togglezooms(f, n)
  1919. {
  1920.     toggle_zooms = !toggle_zooms;
  1921.     ewprintf("Toggling border %s",
  1922.         toggle_zooms ?  "expands window to screen size" :
  1923.                 "retains current window size");
  1924.     return (TRUE);
  1925. }
  1926.  
  1927. #ifdef    CHANGE_FONT
  1928. /*
  1929.  * Select a different font for the MG window. This does not work very well with
  1930.  * proportional fonts, so we ask the user to confirm before he uses one. It's
  1931.  * available if you want to be able to use your own disk font (or Topaz 11
  1932.  * under 1.2) to edit with.
  1933.  */
  1934.  
  1935. setfont(f, n)
  1936. {
  1937.     register int    s, size;
  1938.     register struct TextFont *newfont;
  1939.     char        fontname[80], fontpath[84], fontsize[3];
  1940.     struct TextAttr    ta;
  1941.  
  1942.     /* If negative size, reset to default font
  1943.      */
  1944.     if ((f & FFARG) && (n <= 0)) {
  1945.         CloseFont(EmFont);            /* return old font  */
  1946.         EmFont = OpenDiskFont(EmS->Font);    /* screen's default */
  1947.         ttreopen(FALSE);            /* no resize        */
  1948.         ewprintf("Now using default font");
  1949.         return (TRUE);
  1950.     }
  1951.  
  1952.     if ((s = ereply("Font name: ",fontname, sizeof(fontname))) != TRUE)
  1953.         return (s);
  1954.     strcpy(fontpath,fontname);
  1955.     strncat(fontpath,".font",sizeof(fontpath));/* make name */
  1956.  
  1957.     /* Get font size */
  1958.     if (f & FFARG)
  1959.         size = n;
  1960.     else {
  1961.         if ((s = ereply("Font size: ",
  1962.                 fontsize, sizeof(fontsize))) != TRUE)
  1963.             return (s);
  1964.         size = atoi(fontsize);
  1965.     }
  1966.  
  1967.     /* Set up text attributes */
  1968.     ta.ta_Name = (UBYTE *)fontpath;
  1969.     ta.ta_YSize = size;
  1970.     ta.ta_Style = FS_NORMAL;
  1971.     ta.ta_Flags = 0;
  1972.  
  1973.     /* Look for the font */
  1974.     ewprintf("Looking for %s %d...",fontname,size);
  1975.     if ((newfont = OpenDiskFont(&ta)) == NULL) {
  1976.         ewprintf("Can't find %s %d!",fontname,size);
  1977.         return (FALSE);
  1978.     } 
  1979.  
  1980.     /* Found it! Check before using it */
  1981.     if ((newfont->tf_YSize != size) &&
  1982.         ((s = eyesno("Size unavailable - use closest")) != TRUE)) {
  1983.         CloseFont(newfont);
  1984.         return (FALSE);
  1985.     }
  1986.     if ((newfont->tf_Flags & FPF_PROPORTIONAL) &&
  1987.         (((s = eyesno("Use proportional font")))!= TRUE)) {
  1988.             CloseFont(newfont);
  1989.             return (FALSE);
  1990.     }
  1991.  
  1992.     /* Get rid of old font and reopen with the new one */
  1993.     CloseFont(EmFont);
  1994.     EmFont = newfont;
  1995.     ttreopen(FALSE);
  1996.     ewprintf("Now using font %s %d",fontname,EmFont->tf_YSize);
  1997.     return (TRUE);
  1998. }
  1999. #endif
  2000.  
  2001. /* * * * * * * * * * * * * console output functions  * * * * * * * * * * * * */
  2002.  
  2003. /*
  2004.  * Write a single character to the screen. Buffered for speed, so ttflush()
  2005.  * does all the work.
  2006.  */
  2007. VOID
  2008. ttputc(c)
  2009. unsigned char c;
  2010. {
  2011.     obuf[nobuf++] = c;
  2012.     if (nobuf >= NOBUF)
  2013.         ttflush();
  2014. }
  2015.  
  2016. /*
  2017.  * Flush characters from the output buffer.  If the # of characters is
  2018.  * greater than a certain ad-hoc value, turn the cursor off while doing
  2019.  * the write. To avoid extra writes, the output buffer has been preloaded
  2020.  * with the cursor-off sequence.  Outbuf is large enough to hold the extra
  2021.  * 7 characters.
  2022.  */
  2023. #define    MIN_OFF    8
  2024. VOID
  2025. ttflush()
  2026. {
  2027.     if (nobuf > 0) {
  2028.         if (nobuf <= MIN_OFF)    /* don't turn off for short writes */
  2029.             ConWrite(conWriteMsg, obuf, nobuf);
  2030.         else {
  2031.             obuf[nobuf++] = '\x9b';
  2032.             obuf[nobuf++] = ' ';
  2033.             obuf[nobuf++] = 'p';
  2034.             ConWrite(conWriteMsg, outbuf, nobuf + 4);
  2035.         }
  2036.         nobuf = 0;
  2037.     }
  2038. }
  2039.  
  2040. /*
  2041.  * The caller intends to output an escape sequence, but only flush
  2042.  * the buffer if there's not enough room to hold the complete sequence.
  2043.  * This avoids breaking up escape sequences when we turn the cursor
  2044.  * off in ttflush(), at the expense of some extra function calls.
  2045.  */
  2046. VOID ttnflush(n)
  2047. int n;
  2048. {
  2049.     if ((nobuf + n) > NOBUF)
  2050.         ttflush();
  2051. }
  2052.  
  2053. /* * * * * * * * * * * * * console input functions  * * * * * * * * * * * * */
  2054.  
  2055. /*
  2056.  * Read a character (really a KCHAR, > 8 bits), blocking till a character
  2057.  * is put in the input buffer and can be returned.
  2058.  */
  2059. ttgetc()
  2060. {
  2061.     return handle_kbd(FALSE);
  2062. }
  2063.  
  2064. /*
  2065.  * Return TRUE if we've waited for 2 seconds and nothing has happened,
  2066.  * else return false.
  2067.  */
  2068.  
  2069. ttwait()
  2070. {
  2071.     return handle_kbd(TRUE);    /* time out after 2 sec */
  2072. }
  2073.  
  2074. /*
  2075.  * Common routine for handling character input, with and without timeout.
  2076.  * Handle events until:
  2077.  *
  2078.  *    1) a character is put in the input buffer
  2079.  *    2) if timeout == TRUE, PROMPTWAIT IntuiTicks have gone by
  2080.  *
  2081.  * If timeout == FALSE, the input character is returned and removed from
  2082.  *    the input buffer.
  2083.  *
  2084.  * If timeout == TRUE, returns TRUE if the read timed out, else FALSE.
  2085.  *    Leaves any character typed in the input buffer.
  2086.  */
  2087.  
  2088. static handle_kbd(timeout)
  2089. register int timeout;
  2090. {
  2091.     register struct    IntuiMessage *message;    /* IDCMP message     */
  2092.     register LONG    wakeupmask;        /* which signals?    */
  2093.     register int    charfound;        /* got a character yet?    */
  2094.     KCHAR        k;
  2095.  
  2096.     tickcount = 0;                /* *always* zero the count */
  2097.     if (nibuf)                /* any chars? return if so */
  2098.         return timeout ? FALSE : nextkey();
  2099.  
  2100.     charfound = FALSE;            /* nope -- have to wait    */
  2101.     do {
  2102.         wakeupmask = Wait(INTUITION_MESSAGE);
  2103.  
  2104.         /*  Handle Intuiticks specially for speed */
  2105.         while(message =    GetMsg(EmW->UserPort))
  2106.             if (message->Class == INTUITICKS) {
  2107.                 tickcount++;
  2108.                 ReplyMsg(message);
  2109.             } else if (dispatch(message) == TRUE)
  2110.                 charfound = TRUE;
  2111.  
  2112.         /* time out if enough ticks have gone by without
  2113.          * any keyboard input.  We do this *after* all the
  2114.          * events in the current list have been dispatched.
  2115.          */
  2116.         if (timeout && (tickcount > PROMPTWAIT))
  2117.             break;
  2118.     } while (charfound == FALSE);
  2119.  
  2120.  
  2121.     /* If called by ttwait(), return FALSE if a character was found.
  2122.      * Else return the next character in the input buffer
  2123.     */
  2124.     return timeout ? (!charfound) : nextkey();
  2125. }
  2126.  
  2127. /*
  2128.  * Handle the events we handle...  The result returned indicates if we've put
  2129.  * a character in the input buffer.
  2130.  */
  2131. #ifdef    DO_METAKEY
  2132. #define    IEQUALIFIER_ALT        (IEQUALIFIER_RALT | IEQUALIFIER_LALT)
  2133. #endif
  2134.  
  2135. static dispatch(msg)
  2136. register struct IntuiMessage *msg;
  2137. {
  2138. #ifdef    DO_MENU
  2139.     register struct    MenuItem    *item;
  2140. #endif
  2141.  
  2142.     register int            txheight, txwidth;
  2143.     register struct RastPort    *rp;
  2144.     int                dx, dy, fgpen, drmode;
  2145.  
  2146.     static struct InputEvent FakedEvent = { NULL, IECLASS_RAWKEY, 0, 0, 0 };
  2147.     unsigned char            keybuf[64], altbuf[64];
  2148.     int                keylen, altlen, i;
  2149. #ifndef    V11
  2150.     APTR                deadcodes;
  2151. #endif
  2152.  
  2153.     class =    msg->Class;        /* grab the info before we     */
  2154.     code = msg->Code;        /* reply to the message        */
  2155.     qualifier = msg->Qualifier;
  2156.     address = msg->IAddress;
  2157.     x = msg->MouseX;
  2158.     y = msg->MouseY;
  2159. #ifndef    V11
  2160.     if (class == RAWKEY)        /* get dead key info        */
  2161.         deadcodes = (APTR) *address;
  2162. #endif
  2163.     ReplyMsg(msg);            /* return it to Intuition    */
  2164.  
  2165.     switch(class) {            /* see what the fuss is about    */
  2166.     case RAWKEY:
  2167.         FakedEvent.ie_Code = code;
  2168.         FakedEvent.ie_Qualifier = qualifier;
  2169. #ifndef    V11
  2170.         FakedEvent.ie_EventAddress = deadcodes;
  2171. #endif
  2172.         keylen = (int) RawKeyConvert(&FakedEvent,
  2173.             keybuf,    (LONG)sizeof(keybuf), NULL);
  2174.  
  2175. #ifdef    DO_METAKEY
  2176.         /* Special mapping for ALT-ed keys.  The intent is to get
  2177.          * around keymaps where the ALT'ed characters map to
  2178.          * things other than (0x80 | (c)).  This may not work
  2179.          * for all possible keymaps, but it seems to be ok
  2180.          * for the keymaps distributed with 1.2.
  2181.          */
  2182.         if ((qualifier & IEQUALIFIER_ALT) && use_metakey) {
  2183.             FakedEvent.ie_Qualifier &= ~IEQUALIFIER_ALT;
  2184.             altlen = (int) RawKeyConvert(&FakedEvent, altbuf,
  2185.                 (LONG)sizeof(altbuf), NULL);
  2186.             if (altlen == 1)
  2187.                 altbuf[0] |= 0x80;
  2188.             for (i = 0; i < altlen ; i++)
  2189.                 qkey((KCHAR) altbuf[i]);
  2190.             return (altlen > 0) ? TRUE : FALSE;
  2191.         }
  2192. #endif
  2193.         /* non-ALTed key */
  2194.         for (i = 0; i < keylen; i++)
  2195.             qkey((KCHAR) keybuf[i]);
  2196.         return (keylen > 0) ? TRUE : FALSE;
  2197.         break;
  2198.  
  2199. #ifdef    DO_MENU
  2200.     case MENUPICK:
  2201.         if (code == MENUNULL)
  2202.             return (FALSE);
  2203.         while (code != MENUNULL) {/* handle multiple selection    */
  2204.             qmenu(code);
  2205.             item = ItemAddress(EmacsMenu,(LONG) code);
  2206.             code = item->NextSelect;
  2207.         }
  2208.         return (TRUE);        /* puts KMENU in event queue    */
  2209.         break;
  2210. #endif
  2211.  
  2212. #ifdef    MOUSE
  2213.     case MOUSEBUTTONS:            /* fake the mouse key    */
  2214.         if (code != SELECTDOWN)        /* ignore SELECTUP    */
  2215.             return (FALSE);
  2216.         qmouse(x, y, qualifier);
  2217.         return (TRUE);
  2218.         break;
  2219. #endif
  2220.  
  2221.     case NEWSIZE:
  2222.         /* Sometimes when you resize the window to make it smaller,
  2223.          * garbage is left at the right and bottom sides of the
  2224.          * window. This code is devoted to (somehow) getting rid
  2225.          * of this garbage.  Any suggestions?
  2226.          */
  2227.  
  2228.         rp = EmW->RPort;
  2229.         fgpen = rp->FgPen;        /* save params        */
  2230.         drmode = rp->DrawMode;
  2231.         SetDrMd(rp, (LONG) JAM1);
  2232.         SetAPen(rp, (LONG) EmW->RPort->BgPen);
  2233.  
  2234.         /* Check the bottom of the window
  2235.          */
  2236.         txheight = EmW->Height - EmW->BorderTop - EmW->BorderBottom;
  2237.         if (dy = (txheight % FontHeight(EmW)))
  2238.             RectFill(rp,
  2239.                 (LONG) EmW->BorderLeft,
  2240.                 (LONG) EmW->BorderTop + txheight - dy - 1,
  2241.                 (LONG) (EmW->Width - 1) - EmW->BorderRight,
  2242.                 (LONG) (EmW->Height - 1) - EmW->BorderBottom);
  2243.  
  2244.         /* Check the right side
  2245.          */
  2246.         txwidth = EmW->Width - EmW->BorderLeft - EmW->BorderRight;
  2247.         if (dx = txwidth % FontWidth(EmW))
  2248.             RectFill(rp,
  2249.                 (LONG) EmW->BorderLeft + txwidth - dx - 1,
  2250.                 (LONG) EmW->BorderTop,
  2251.                 (LONG) (EmW->Width - 1) - EmW->BorderRight,
  2252.                 (LONG) (EmW->Height - 1) - EmW->BorderBottom);
  2253.  
  2254.         SetDrMd(rp, (LONG) drmode);
  2255.         SetAPen(rp, (LONG) fgpen);    /* restore colors */
  2256.  
  2257.         /* Tell the console device to resize itself */
  2258.         ttputc(CSI);
  2259.         ttputc('t');
  2260.         ttputc(CSI);
  2261.         ttputc('u');
  2262.         ttflush();
  2263.  
  2264.         /* Signal the editor that a new size has occurred.
  2265.          * I may break down and do this asynchronously...
  2266.          */
  2267.         qkey(KRESIZE);
  2268.         return (TRUE);            /* we done (finally)    */
  2269.         break;
  2270.  
  2271.         case CLOSEWINDOW:
  2272.         /* Calling quit() directly is not a guaranteed win. */
  2273.         quit(FFRAND, 1);
  2274.         return (FALSE);
  2275.                 break;
  2276.  
  2277.     default:
  2278.         panic("HandleMsg: unknown event!!!");
  2279.         break;
  2280.     }
  2281.     return(FALSE);
  2282. }
  2283.  
  2284. /*
  2285.  * Return the current size of the virtual terminal in nrow and ncol,
  2286.  * making sure we don't go beyond the size of the internal video array.
  2287.  * Assumes the current font is monospaced.
  2288.  */
  2289. VOID
  2290. setttysize()
  2291. {
  2292.     nrow = (EmW->Height - TOP_OFFSET
  2293.             - EmW->BorderBottom) / FontHeight(EmW);
  2294.     ncol = (EmW->Width - EmW->BorderLeft
  2295.             - EmW->BorderRight) / FontWidth(EmW);
  2296.     if (nrow < 1)        nrow = 1;
  2297.     if (nrow > NROW)    nrow = NROW;
  2298.     if (ncol < 1)        ncol = 1;
  2299.     if (ncol > NCOL)    ncol = NCOL;
  2300. }
  2301.  
  2302. /*
  2303.  * Exit as soon as possible, after displaying the message.
  2304.  */
  2305. VOID
  2306. panic(s)
  2307. char *s;
  2308. {
  2309.     ewprintf(s);        /* put message at bottom    */
  2310.     Delay((ULONG) 90);    /* wait 1.5 seconds        */
  2311.     ttclose();        /* get rid of window &resources    */
  2312.     exit(10000);        /* go 'way            */
  2313. }
  2314.  
  2315. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  2316.  *             Event buffer management         *
  2317.  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  2318.  
  2319. /*
  2320.  * Return next key in the input buffer, if any available.  Returns -1 if not.
  2321.  */
  2322. static int
  2323. nextkey()
  2324. {
  2325.     register KCHAR k;
  2326.  
  2327.     if (nibuf <= 0) {        /* shouldn't happen, but could... */
  2328.         nibuf = 0;
  2329.         return -1;
  2330.     } else {
  2331.         k = ibuf[ibufo++];
  2332.         nibuf--;
  2333.         ibufo %= NIBUF;
  2334.         return (int) k;
  2335.     }
  2336. }            
  2337.  
  2338. /*
  2339.  * Return true if there are some characters available in the input buffer.
  2340.  */
  2341. typeahead()
  2342. {
  2343.     return (nibuf > 0);
  2344. }
  2345.  
  2346. /*
  2347.  * Add a key to the input queue
  2348.  */
  2349. static VOID
  2350. qkey(k)
  2351. KCHAR k;
  2352. {
  2353.     if (nibuf < NIBUF)
  2354.         ibuf[(ibufo + nibuf++) % NIBUF] = k;
  2355. }
  2356.  
  2357. #ifdef    MOUSE
  2358. /*
  2359.  * Add a mouse event to the input queue, calculating the row and column
  2360.  * value from the current height and width of the window's font.
  2361.  */
  2362.  
  2363. static VOID
  2364. qmouse(x, y, qual)
  2365. SHORT x, y;
  2366. USHORT qual;
  2367. {
  2368.     register int    myqual = MQ_NOQUAL;
  2369.     register int    row, col;
  2370.     register WINDOW    *wp;    
  2371.  
  2372.     /* get row, column    */
  2373.     col = (x - EmW->BorderLeft) / FontWidth(EmW);
  2374.     row = (y - TOP_OFFSET) / FontHeight(EmW);
  2375.  
  2376.     /* find out which kind of window was clicked in */
  2377.     for (wp = wheadp; wp != NULL; wp = wp->w_wndp)
  2378.         if ((row >= wp->w_toprow) && 
  2379.             (row <= (wp->w_toprow + wp->w_ntrows)))
  2380.             break;
  2381.     if (wp == NULL)
  2382.         myqual |= MQ_ECHO;
  2383.     else if (row == (wp->w_toprow + wp->w_ntrows))
  2384.         myqual |= MQ_MODE;
  2385.     else
  2386.         myqual |= MQ_WINDOW;
  2387.  
  2388.     /* figure out qualifiers    */
  2389.     if (qual & IEQUALIFIER_CONTROL)
  2390.         myqual |= MQ_CTRL;
  2391.     if (qual & (IEQUALIFIER_LSHIFT | IEQUALIFIER_LSHIFT))
  2392.         myqual |= MQ_SHIFT;
  2393.     if (qual & (IEQUALIFIER_LALT | IEQUALIFIER_RALT))
  2394.         myqual |= MQ_ALT;
  2395.  
  2396.     /*
  2397.       * Queue up the whole mess.  If user didn't click in the echo
  2398.      * line, transmit the x, y values to the mouse function
  2399.      */
  2400.     qkey(KW___MOUSE + myqual);
  2401.     if (MQ_WHERE(myqual) != MQ_ECHO) {
  2402.         qkey(M_X_ZERO + col);
  2403.         qkey(M_Y_ZERO + row);
  2404.     }
  2405. }
  2406. #endif
  2407.  
  2408. #ifdef    DO_MENU
  2409. /*
  2410.  * Add a menu event to the queue.
  2411.  */
  2412. static VOID
  2413. qmenu(code)
  2414. USHORT code;
  2415. {
  2416.     qkey(KMENU);        /* menu key sequence    */
  2417.     qkey(((KCHAR) MENUNUM(code)) + MN_OFFSET);
  2418.     qkey(((KCHAR) ITEMNUM(code)) + MN_OFFSET);
  2419.     qkey(((KCHAR) SUBNUM(code)) + MN_OFFSET);
  2420. }
  2421. #endif
  2422. SHAR_EOF
  2423. #    End of shell archive
  2424. exit 0
  2425. -------
  2426.