sources-request@mirror.UUCP (01/27/87)
Submitted by: Bob Larson <seismo!usc-oberon!blarson> Mod.sources: Volume 8, Issue 13 Archive-name: micrognu/Part06 #! /bin/sh # This is a shell archive, meaning: # 1. Remove everything above the #! /bin/sh line. # 2. Save the resulting text in a file. # 3. Execute the file with /bin/sh (not csh) to create the files: # tty/amiga/ttydef.h # tty/amiga/console.c # tty/amiga/menustack.c # tty/amiga/tty.c # tty/amiga/ttyio.c # tty/amiga/ttymenu.c # This archive created: Sat Nov 15 15:26:59 1986 export PATH; PATH=/bin:$PATH if test ! -d tty/amiga then mkdir tty/amiga fi if test ! -d sys/amiga then mkdir sys/amiga fi if test -f 'tty/amiga/ttydef.h' then echo shar: will not over-write existing file "'tty/amiga/ttydef.h'" else cat << \SHAR_EOF > 'tty/amiga/ttydef.h' /* * Name: MicroEMACS * Amiga console device virtual terminal header file * Version: Gnu v30 * Last edit: 26-Aug-86 * Created: 20-Apr-86 ...!ihnp4!seismo!ut-sally!ut-ngp!mic */ #define GOSLING /* Compile in fancy display. */ #define NROW 48 /* Max rows (only in interlace) */ #define NCOL 80 /* Columns (borderless window) */ /* * Special keys for the default Amiga console device keymap. * Function key codes are in the form <CSI>v~ * where v is a 1 or 2-digit code between 0 and 19, * so they comprise the first 20 entries in the key * table. The next 12 entries are for the help and * arrow keys. */ #define KF1 K01 #define KF2 K02 #define KF3 K03 #define KF4 K04 #define KF5 K05 #define KF6 K06 #define KF7 K07 #define KF8 K08 #define KF9 K09 #define KF10 K0A #define KSF1 K0B #define KSF2 K0C #define KSF3 K0D #define KSF4 K0E #define KSF5 K0F #define KSF6 K10 #define KSF7 K11 #define KSF8 K12 #define KSF9 K13 #define KSF10 K14 #define KUP K15 #define KSUP K16 #define KDOWN K17 #define KSDOWN K18 #define KLEFT K19 #define KSLEFT K1A #define KRIGHT K1B #define KSRIGHT K1C #define KHELP K1D /* The 'menu' key doesn't really appear on the * Amiga keyboard. When ttgetc() sees a menu * event, it saves the menu number and item, * then stuffs the sequence for KMENU into * the input buffer. */ #define KMENU K1E /* * Intuition menu interface. Each set of menu items * kept in a table of MenuBinding structures, which * is in turn kept in a table of MenuInfo structures. * * These tables are indexed via the menu and item * numbers to find the internal extended name of * the function associated with a certain item. */ struct MenuBinding { char *Command; char *Binding; }; struct MenuInfo { char *Name; /* name of menu */ short NumItems; /* # of items */ struct MenuBinding *Items; /* item name, internal binding */ }; #define NITEMS(arr) (sizeof(arr) / (sizeof(arr[0]))) /* * If either MENU, or BROWSER is defined, we need to define * DO_MENU to get the code for dealing with menu selections * compiled in. */ #ifdef MENU #define DO_MENU #else #ifdef BROWSER #define DO_MENU #endif BROWSER #endif MENU /* * MODE_RENDITION and TEXT_RENDITION * determine the way the mode line and * text area are rendered (using the SGR * sequence). TEXT_* and MODE_* set the * foreground (FG) and background (BG) * color to the specified number. If you * #define CHANGE_COLOR, you can redefine * these dynamically. */ #ifndef MODE_RENDITION #define MODE_RENDITION 7 #endif #ifndef TEXT_RENDITION #define TEXT_RENDITION 0 #endif #ifndef TEXT_FG #define TEXT_FG 1 #endif #ifndef TEXT_BG #define TEXT_BG 0 #endif #ifndef MODE_FG #define MODE_FG 1 #endif #ifndef MODE_BG #define MODE_BG 0 #endif /* * Return the width and height of * the default font for a window. */ #define FontWidth(w) (w)->RPort->TxWidth #define FontHeight(w) (w)->RPort->TxHeight SHAR_EOF fi # end of overwriting check if test -f 'tty/amiga/console.c' then echo shar: will not over-write existing file "'tty/amiga/console.c'" else cat << \SHAR_EOF > 'tty/amiga/console.c' /* * These functions are taken directly from the * console.device chapter in the Amiga V1.1 * ROM Kernel Manual. */ #include <exec/types.h> #include <exec/io.h> #include <devices/console.h> #include <libraries/dos.h> #include <intuition/intuition.h> extern LONG OpenDevice(); extern LONG DoIO(); extern LONG SendIO(); /* * Open a console device, given a read request * and a write request message. */ int OpenConsole(writerequest,readrequest,window) struct IOStdReq *writerequest; struct IOStdReq *readrequest; struct Window *window; { LONG error; writerequest->io_Data = (APTR) window; writerequest->io_Length = (ULONG) sizeof(*window); error = OpenDevice("console.device", 0L, writerequest, 0L); /* clone required parts of the request */ readrequest->io_Device = writerequest->io_Device; readrequest->io_Unit = writerequest->io_Unit; return((int) error); } /* * Output a single character * to a specified console */ int ConPutChar(request,character) struct IOStdReq *request; char character; { #ifdef V11 register int x; #endif request->io_Command = CMD_WRITE; request->io_Data = (APTR)&character; request->io_Length = (ULONG)1; DoIO(request); /* caution: read comments in manual! */ return(0); } /* * Output a NULL-terminated string of * characters to a console */ int ConPutStr(request,string) struct IOStdReq *request; char *string; { #ifdef V11 register int x; #endif request->io_Command = CMD_WRITE; request->io_Data = (APTR)string; request->io_Length = (LONG)-1; DoIO(request); return(0); } /* * Write out a string of predetermined * length to the console */ int ConWrite(request,string,len) struct IOStdReq *request; char *string; int len; { #ifdef V11 register int x; #endif request->io_Command = CMD_WRITE; request->io_Data = (APTR)string; request->io_Length = (LONG)len; DoIO(request); return(0); } /* * Queue up a read request * to a console */ int QueueRead(request,whereto) struct IOStdReq *request; char *whereto; { #ifdef V11 register int x; #endif request->io_Command = CMD_READ; request->io_Data = (APTR)whereto; request->io_Length = (LONG)1; SendIO(request); return(0); } SHAR_EOF fi # end of overwriting check if test -f 'tty/amiga/menustack.c' then echo shar: will not over-write existing file "'tty/amiga/menustack.c'" else cat << \SHAR_EOF > 'tty/amiga/menustack.c' /* * Simple menu package. Needs lotsa work to handle some cases. * * Copyright 1985 * Louis A. Mamakos * Software & Stuff * 14813 Ashford Place * Laurel, MD 20707 * * For non-commerical use only. This program, or any modifications, may not * be sold or incorporated into any product without prior permission from the * author. * * Modified by mwm to handle "stacking" menus. * NB - adding item to a menu that's been "popped" back to doesn't work, * and probably never will. */ #include <exec/types.h> #include <exec/nodes.h> #include <exec/lists.h> #include <exec/ports.h> #include <exec/devices.h> #include <exec/memory.h> #include <hardware/blit.h> #include <graphics/copper.h> #include <graphics/regions.h> #include <graphics/rastport.h> #include <graphics/gfxbase.h> #include <graphics/gels.h> #include <intuition/intuition.h> #define MNUM(menu,item,sub) (SHIFTMENU(menu)|SHIFTITEM(item)|SHIFTSUB(sub)) #define Menu_Clear DisposeMenus /* For ttyio.c */ extern char *AllocMem(); extern char *AllocRemember(); struct Mem_Node { struct Node mn_Node; struct Remember mn_Memory; struct Menu *mn_Menu; } *Top, *RemHead(); extern struct NewWindow MicroEMACS ; /* For Screen width & Height */ #define SCREENHEIGHT (MicroEMACS . MaxHeight) #define SCREENWIDTH (MicroEMACS . MaxWidth) static struct List Memory; static int Cur_Menu, Cur_MenuItem, Cur_SubItem; static struct Menu *LastMenu; static struct MenuItem *LastMenuItem, *LastSubItem; struct Menu *AutoMenu; /* menu struct being dynamically built */ char *strsave(); /* Save a string in the remember list */ Menu_Init() { Memory.lh_Head = (struct Node *) &(Memory.lh_Tail); Memory.lh_TailPred = (struct Node *) &(Memory.lh_Head); Memory.lh_Tail = NULL; Memory.lh_Type = NT_MEMORY; Top = NULL; Cur_Menu = Cur_MenuItem = Cur_SubItem = -1; AutoMenu = LastMenu = NULL; /* no menu chain yet */ LastMenuItem = LastSubItem = NULL; } Menu_Clear() { while ((Top = RemHead(&Memory)) != NULL) { FreeRemember(&(Top->mn_Memory), (LONG)TRUE); FreeMem(Top, (LONG)sizeof(struct Mem_Node)); } Menu_Init(); /* Just for safeties sake */ } Menu_Pop() { if ((Top = RemHead(&Memory)) == NULL) return NULL; FreeRemember(&(Top->mn_Memory), (LONG)TRUE); FreeMem(Top, (LONG)sizeof(struct Mem_Node)); /* Now, set Top back to the real list head */ Top = (struct Mem_Node *) Memory.lh_Head; LastMenu = Top->mn_Menu; LastMenuItem = NULL; /* Wrong, but you can't add items here anyway */ LastSubItem = NULL; /* ditto */ Cur_Menu--; } /* * Add a MENU item. Args are the text of the menu item, and an enable * flag. Returns an Intuition type menu number, with the MenuItem and * Menu SubItem being NOITEM and NOSUB. The MENUITEM part is valid. */ /* dummy Intuitext used to calculate length of menu names */ static struct IntuiText itd = { AUTOFRONTPEN, AUTOBACKPEN, JAM2, 1, 1, NULL, NULL, NULL }; Menu_Add(name, enabled) char *name; int enabled; { register struct Menu *m; if ((Top = (struct Mem_Node *) AllocMem( (LONG)sizeof(struct Mem_Node), MEMF_PUBLIC | MEMF_CLEAR)) == NULL) return NULL; Top->mn_Node.ln_Type = NT_MEMORY; if ((m = (struct Menu *)AllocRemember(&(Top->mn_Memory), (LONG)sizeof (struct Menu), MEMF_PUBLIC | MEMF_CLEAR)) == NULL) return NULL; Top->mn_Menu = m; if (LastMenu == NULL) AutoMenu = m; /* first menu on list */ else LastMenu->NextMenu = m; /* link it in */ LastMenuItem = NULL; /* end of previous MenuItem list */ LastSubItem = NULL; Cur_MenuItem = Cur_SubItem = -1; /* reset item numbers */ if (LastMenu == NULL) m->LeftEdge = 0; else m->LeftEdge = LastMenu->LeftEdge + LastMenu->Width; m->TopEdge = 0; itd.IText = (UBYTE *)name; m->Width = IntuiTextLength(&itd); Top->mn_Node.ln_Name = m->MenuName = strsave(name); m->Height = 0; m->Flags = enabled ? MENUENABLED : 0; m->FirstItem = NULL; LastMenu = m; AddHead(&Memory, Top); return MNUM(++Cur_Menu, NOITEM, NOSUB); } /* * Add a menu item to the current MENU. Note that Add_Menu *must* be * called before this function. */ Menu_Item_Add(name, flags, mux, ch) char *name; /* name of menu item */ USHORT flags; LONG mux; /* mutual exclusion mask */ BYTE ch; /* command sequence character, if COMMSEQ */ { register struct MenuItem *m, *n; register struct IntuiText *it; flags &= CHECKIT|CHECKED|COMMSEQ|MENUTOGGLE|ITEMENABLED|HIGHCOMP|HIGHBOX; if (LastMenu == NULL) return MNUM(NOMENU, NOITEM, NOSUB); if ((m = (struct MenuItem *) AllocRemember(&(Top->mn_Memory), (LONG)sizeof(struct MenuItem), MEMF_PUBLIC | MEMF_CLEAR)) == NULL) return MNUM(NOMENU, NOITEM, NOSUB); LastSubItem = NULL; /* terminate possible list of subitems */ Cur_SubItem = -1; if (LastMenuItem == NULL) LastMenu->FirstItem = m; else LastMenuItem->NextItem = m; m->Flags = flags | ITEMTEXT; /* * Check for highlight mode: if none selected, use HIGHCOMP */ if ((m->Flags & (HIGHCOMP | HIGHBOX)) == 0) m->Flags |= HIGHCOMP; m->Command = ch; m->MutualExclude = mux; m->SubItem = NULL; m->ItemFill = (APTR) AllocRemember(&(Top->mn_Memory), (LONG)sizeof(struct IntuiText), MEMF_PUBLIC | MEMF_CLEAR); it = (struct IntuiText *) m->ItemFill; it->FrontPen = AUTOFRONTPEN; it->BackPen = AUTOBACKPEN; it->DrawMode = JAM2; if (flags & CHECKIT) it->LeftEdge = CHECKWIDTH + 1; else it->LeftEdge = 1; it->TopEdge = 1; it->ITextFont = NULL; /* default font */ it->IText = (UBYTE *)strsave(name); it->NextText = NULL; if (LastMenuItem == NULL) { m->TopEdge = 2; m->LeftEdge = 0; } else if (LastMenuItem->TopEdge + 40 > SCREENHEIGHT) { m->TopEdge = 2; m->LeftEdge = LastMenuItem->LeftEdge + LastMenuItem->Width + 12; if (m->LeftEdge > SCREENWIDTH) { LastMenuItem->NextItem = NULL; LastMenuItem->Flags &= ~ITEMENABLED; return MNUM(NOMENU, NOITEM, NOSUB); } } else { m->TopEdge = LastMenuItem->TopEdge + 10; m->LeftEdge = LastMenuItem->LeftEdge; } m->Width = 0; if (flags & CHECKIT) m->Width += CHECKWIDTH; if (flags & COMMSEQ) m->Width += COMMWIDTH + 20; m->Width += IntuiTextLength(m->ItemFill); m->Height = 10; /* * Check last menu item's width to see if it is larger than this * item's. If new item is larger, then update width of all other * items. */ if (LastMenuItem) { if (LastMenuItem->Width > m->Width) m->Width = LastMenuItem->Width; else { register short delta = m->Width - LastMenuItem->Width; for (n = LastMenu->FirstItem; n != m; n = n->NextItem) { n->Width = m->Width; if (n->LeftEdge > 0) n->LeftEdge += delta; } if (m->LeftEdge > 0) m->LeftEdge += delta; } } LastMenuItem = m; return MNUM(Cur_Menu, ++Cur_MenuItem, NOSUB); } Menu_SubItem_Add(name, flags, mux, ch) char *name, ch; USHORT flags; LONG mux; { register struct MenuItem *m, *n; register struct IntuiText *it; flags &= CHECKIT|CHECKED|COMMSEQ|MENUTOGGLE|ITEMENABLED|HIGHCOMP|HIGHBOX; if (LastMenuItem == NULL) return MNUM(NOMENU, NOITEM, NOSUB); if ((m = (struct MenuItem *) AllocRemember(&(Top->mn_Memory), (LONG)sizeof(struct MenuItem), MEMF_PUBLIC | MEMF_CLEAR)) == NULL) return MNUM(NOMENU, NOITEM, NOSUB); if (LastSubItem == NULL) LastMenuItem->SubItem = m; else LastSubItem->NextItem = m; m->Flags = flags | ITEMTEXT; /* * check for highlight mode. If none selected, use HIGHCOMP */ if ((m->Flags & (HIGHCOMP|HIGHBOX)) == 0) m->Flags |= HIGHCOMP; m->Command = ch; m->MutualExclude = mux; m->SubItem = NULL; m->ItemFill = (APTR) AllocRemember(&(Top->mn_Memory), (LONG)sizeof(struct IntuiText), MEMF_PUBLIC | MEMF_CLEAR); it = (struct IntuiText *) m->ItemFill; it->FrontPen = AUTOFRONTPEN; it->BackPen = AUTOBACKPEN; it->DrawMode = JAM2; if (flags & CHECKIT) it->LeftEdge = CHECKWIDTH + 1; else it->LeftEdge = 1; it->TopEdge = 1; it->ITextFont = NULL; /* default font */ it->IText = (UBYTE *)strsave(name); it->NextText = NULL; m->LeftEdge = LastMenuItem->Width + 10; m->Width = 0; if (LastSubItem == NULL) m->TopEdge = 1; else m->TopEdge = LastSubItem->TopEdge + 10; if (flags & CHECKIT) m->Width += CHECKWIDTH; if (flags & COMMSEQ) m->Width += COMMWIDTH + 20; m->Width += IntuiTextLength(m->ItemFill); m->Height = 10; /* * Check last menu item's width to see if it is larger than this * item's. If new item is larger, then update width of all other * items. */ if (LastSubItem) { if (LastSubItem->Width > m->Width) m->Width = LastSubItem->Width; else for (n = LastMenuItem->SubItem; n != m; n = n->NextItem) n->Width = m->Width; } LastSubItem = m; return MNUM(Cur_Menu, Cur_MenuItem, ++Cur_SubItem); } char * strsave(string) char *string; { char *out ; out = (char *) AllocRemember(&(Top->mn_Memory), (LONG)(strlen(string) + 1), MEMF_PUBLIC) ; if (out == NULL) return NULL ; (void) strcpy(out, string) ; return out ; } SHAR_EOF fi # end of overwriting check if test -f 'tty/amiga/tty.c' then echo shar: will not over-write existing file "'tty/amiga/tty.c'" else cat << \SHAR_EOF > 'tty/amiga/tty.c' /* * Name: MicroEMACS * Amiga console device virtual terminal display * Version: GNU v30 * Last Edit: 23-Aug-86 ...!ihnp4!seismo!ut-sally!ut-ngp!mic * Created: 19-Apr-86 ...!ihnp4!seismo!ut-sally!ut-ngp!mic * * Drives the Amiga console device display. The code * is a combination of the Heath and ANSI terminal drivers, * plus some hacks to manage the console device colors. */ #include "def.h" #define BEL 0x07 /* BEL character. */ #define ESC 0x1B /* ESC character. */ extern int ttrow; extern int ttcol; extern int tttop; extern int ttbot; extern int tthue; int tceeol = 3; /* Costs, ANSI display. */ int tcinsl = 17; int tcdell = 16; #ifdef CHANGE_COLOR short mode_rendition = MODE_RENDITION, /* set standard colors */ text_rendition = TEXT_RENDITION, text_fg = TEXT_FG + 30, text_bg = TEXT_BG + 40, mode_fg = MODE_FG + 30, mode_bg = MODE_BG + 40; #else /* colors are hard-coded */ #define mode_rendition MODE_RENDITION #define text_rendition TEXT_RENDITION #define text_fg (TEXT_FG + 30) #define text_bg (TEXT_BG + 40) #define mode_fg (MODE_FG + 30) #define mode_bg (MODE_BG + 40) #endif /* * Initialize the terminal when the editor * gets started up. A no-op for the Amiga */ ttinit() { } /* * Clean up the terminal, in anticipation of * a return to the command interpreter. This * is a no-op on the Amiga. */ tttidy() { } /* * Move the cursor to the specified * origin 0 row and column position. Try to * optimize out extra moves; redisplay may * have left the cursor in the right * location last time! */ ttmove(row, col) { if (ttrow!=row || ttcol!=col) { ttputc(ESC); ttputc('['); asciiparm(row+1); ttputc(';'); asciiparm(col+1); ttputc('H'); ttrow = row; ttcol = col; } } /* * Erase to end of line. */ tteeol() { ttputc(ESC); ttputc('['); ttputc('K'); } /* * Erase to end of page. */ tteeop() { ttputc(ESC); /* reinforce current color values */ ttputc('['); asciiparm((tthue == CTEXT) ? text_rendition : mode_rendition); ttputc(';'); asciiparm(text_fg); ttputc(';'); asciiparm(text_bg); ttputc('m'); ttputc(ESC); /* clear to end of display */ ttputc('['); ttputc('J'); } /* * Make a noise. */ ttbeep() { ttputc(BEL); ttflush(); } /* * Convert a number to decimal * ascii, and write it out. Used to * deal with numeric arguments. */ asciiparm(n) register int n; { if (n > 9) asciiparm(n/10); ttputc((n%10) + '0'); } /* * Insert a block of blank lines onto the * screen, using a scrolling region that starts at row * "row" and extends down to row "bot". Deal with the one * line case, which is a little bit special, with special * case code. * * Since we don't really have a scrolling region, * delete the block of lines that would have been deleted if * we'd had one, then insert blank lines to move the rest * of the screen back to where it belongs. This idea from * the Heath driver. */ VOID ttinsl(row, bot, nchunk) { if (row == bot) { /* Funny case. */ if (nchunk != 1) panic("ttinsl: nchunk != 1"); ttmove(row, 0); tteeol(); return; } ttmove(1+bot-nchunk, 0); if (nchunk > 0) { /* Delete a chunk of lines */ ttputc(ESC); /* nchunk in size. Rest of */ ttputc('['); /* screen moves up. */ asciiparm(nchunk); ttputc('M'); } ttmove(row, 0); if (nchunk > 0) { /* Insert a chunk nchunk in size*/ ttputc(ESC); /* before current line, sliding */ ttputc('['); /* rest of screen down. */ asciiparm(nchunk); ttputc('L'); } ttrow = row; /* End up on current line */ ttcol = 0; } /* * Delete a block of lines, with the uppermost * line at row "row", in a screen slice that extends to * row "bot". The "nchunk" is the number of lines that have * to be deleted. This is done by deleting nchunk lines at the * appropriate spot, then inserting nchunk lines to make up for * the empty space at the bottom of the virtual scrolling region. */ VOID ttdell(row, bot, nchunk) { if (row == bot) { /* One line special case */ ttmove(row, 0); tteeol(); return; } if (nchunk > 0) { ttmove(row, 0); ttputc(ESC); ttputc('['); asciiparm(nchunk); ttputc('M'); } ttmove(1+bot-nchunk,0); if (nchunk > 0) { ttputc(ESC); /* For all lines in chunk */ ttputc('['); /* INS line before bottom */ asciiparm(nchunk); /* Bottom of window (and rest */ ttputc('L'); /* of screen) moves down */ } ttrow = HUGE; ttcol = HUGE; ttmove(bot-nchunk,0); } /* * No-op. */ ttwindow(top,bot) { } /* * No-op. */ ttnowindow() { } #ifdef CHANGE_COLOR /* * Set the rendition of the mode line by * selecting colors from the following: * 0 -- plain text * 1 -- bold-face * 3 -- italic * 4 -- underscore * 7 -- inverse video * Certain of these selections may be less than * appealing :-) */ ttmode(f, n, k) { register int s; char buf[2]; if (f == FALSE) { if ((s = ereply("Set mode line rendition (0-7): ", buf, sizeof(buf))) != TRUE) return (s); n = atoi(buf); } if (n < 0 || n > 7) return (FALSE); mode_rendition = n; /* store the color */ sgarbf = TRUE; return (TRUE); } /* * Set the rendition of the text area. * Most of these selections will be * less than appealing :-] */ tttext(f, n, k) { register int s; char buf[2]; if (f == FALSE) { if ((s = ereply("Set text rendition (0-7): ", buf, sizeof(buf))) != TRUE) return (s); n = atoi(buf); } if (n < 0 || n > 7) return (FALSE); text_rendition = n; /* store the color */ sgarbf = TRUE; return (TRUE); } /* * Set foreground color for entire window * to a value between 30 and 37, which * corresponds to the arguments 0-7. * This requires a total refresh, which * sets up the screen. */ textforeground(f, n, k) { register int s; char buf[2]; if (f == FALSE) { if ((s = ereply("Text foreground color (0-7): ", buf, sizeof(buf))) != TRUE) return (s); n = atoi(buf); } if (n < 0 || n > 7) return (FALSE); text_fg = n + 30; sgarbf = TRUE; return (TRUE); } /* * Set background color for entire window * to a value between 40 and 47 inclusive. */ textbackground(f, n, k) { register int s; char buf[2]; if (f == FALSE) { if ((s = ereply("Text background color (0-7): ", buf, sizeof(buf))) != TRUE) return (s); n = atoi(buf); } if (n < 0 || n > 7) return (FALSE); text_bg = n + 40; sgarbf = TRUE; return (TRUE); } /* * Set foreground color for entire the mode line */ modeforeground(f, n, k) { register int s; char buf[2]; if (f == FALSE) { if ((s = ereply("Mode line foreground color (0-7): ", buf, sizeof(buf))) != TRUE) return (s); n = atoi(buf); } if (n < 0 || n > 7) return (FALSE); mode_fg = n + 30; sgarbf = TRUE; return (TRUE); } /* * Set background color for the mode line */ modebackground(f, n, k) { register int s; char buf[2]; if (f == FALSE) { if ((s = ereply("Mode line background color (0-7): ", buf, sizeof(buf))) != TRUE) return (s); n = atoi(buf); } if (n < 0 || n > 7) return (FALSE); mode_bg = n + 40; sgarbf = TRUE; return (TRUE); } #endif /* * Set the current writing color to the * specified color. Watch for color changes that are * not going to do anything (the color is already right) * and don't send anything to the display. */ ttcolor(color) register int color; { if (color != tthue) { if (color == CTEXT) { /* Normal video. */ ttputc(ESC); /* Reset to 0 */ ttputc('['); ttputc('m'); ttputc(ESC); /* Set text style */ ttputc('['); asciiparm(text_rendition); ttputc(';'); asciiparm(text_fg); ttputc(';'); asciiparm(text_bg); ttputc('m'); } else if (color == CMODE) { /* Standout mode */ ttputc(ESC); /* Reset to 0 */ ttputc('['); ttputc('m'); ttputc(ESC); /* Set standout mode */ ttputc('['); asciiparm(mode_rendition); ttputc(';'); asciiparm(mode_fg); /* Use mode line colors */ ttputc(';'); asciiparm(mode_bg); ttputc('m'); } tthue = color; /* Save the color. */ } } /* * This routine is called by the * "refresh the screen" command to try and resize * the display. The new size, which must be deadstopped * to not exceed the NROW and NCOL limits, is stored * back into "nrow" and "ncol". Display can always deal * with a screen NROW by NCOL. Look in "window.c" to * see how the caller deals with a change. * On the Amiga, we make the Intuition terminal driver * do all the work. */ ttresize() { setttysize(); } SHAR_EOF fi # end of overwriting check if test -f 'tty/amiga/ttyio.c' then echo shar: will not over-write existing file "'tty/amiga/ttyio.c'" else cat << \SHAR_EOF > 'tty/amiga/ttyio.c' /* * Name: MicroEmacs * Amiga terminal-dependent I/O (Intuition) * Created: 21-Apr-86 ...!ihnp4!seismo!ut-sally!ut-ngp!mic */ /* * Lots of includes. */ #include <exec/types.h> #include <exec/nodes.h> #include <exec/lists.h> #include <exec/tasks.h> #include <exec/ports.h> #include <exec/io.h> #include <devices/console.h> #include <libraries/dos.h> #include <graphics/clip.h> #include <graphics/view.h> #include <graphics/rastport.h> #include <graphics/layers.h> #include <graphics/text.h> #include <graphics/gfxbase.h> #include <intuition/intuition.h> #ifdef CHANGE_FONT #include <libraries/diskfont.h> #endif #undef TRUE /* avoid redefinition messages */ #undef FALSE #include "def.h" /* includes sysdef.h and ttydef.h */ /* * External Amiga functions. Declared explicitly * to avoid problems with different compilers. */ extern LONG AbortIO(); extern LONG CloseDevice(); extern LONG CloseLibrary(); extern LONG CloseWindow(); extern struct MsgPort *CreatePort(); extern struct IOStdReq *CreateStdIO(); extern LONG DeletePort(); extern LONG DeleteStdIO(); extern struct IntuiMessage *GetMsg(); extern int OpenConsole(); extern char *OpenLibrary(); extern struct Window *OpenWindow(); #ifdef CHANGE_FONT extern struct TextFont *OpenDiskFont(); #endif extern LONG RectFill(); extern LONG ReplyMsg(); extern LONG SetAPen(); extern LONG SetDrMd(); extern LONG Wait(); #ifdef DO_MENU extern LONG ClearMenuStrip(); /* menu functions */ extern struct Menu *InitEmacsMenu(); extern struct MenuItem *ItemAddress(); extern LONG SetMenuStrip(); #endif extern int Enable_Abort; /* Do NOT allow abort! */ /* * External MicroEmacs functions and variables */ extern int quit(); /* Defined by "main.c" */ extern char *version; /* Version information */ /* * Library bases (used by glue libraries) */ struct IntuitionBase *IntuitionBase; struct GfxBase *GfxBase; #ifdef CHANGE_FONT ULONG DiskfontBase; #endif /* * Intuition window and menu variables */ #define WINDOWGADGETS (WINDOWDRAG | WINDOWDEPTH | WINDOWCLOSE) static short borderless = TRUE; /* Flag for borderless window */ static short leftedge = 0, /* Last top left position */ topedge = 0, width = 640, height = 200; struct NewWindow MicroEMACS = { 0, 0, /* start position */ 0, 0, /* width, height (set by ttopen)*/ 0, 1, /* detail pen, block pen */ #ifdef DO_MENU MENUPICK | /* If menu is used */ #endif #ifdef MOUSE MOUSEBUTTONS | /* If mouse is used */ #endif CLOSEWINDOW | NEWSIZE, /* IDCMP flags */ 0, /* window flags (set by ttopen) */ NULL, /* pointer to first user gadget */ NULL, /* pointer to user checkmark */ NULL, /* title (filled in later) */ NULL, /* pointer to screen (none) */ NULL, /* pointer to superbitmap */ 359,101, /* minimum size (with TOPAZ_80) */ 0, 0, /* maximum size (set by ttopen) */ WBENCHSCREEN /* screen in which to open */ }; struct Window *EmW; /* Our window */ static short toggling = FALSE; /* Prevent menu wiping */ #ifdef DO_MENU static struct Menu *EmacsMenu = NULL; /* Our menu */ #endif #ifdef CHANGE_FONT static struct TextFont *EmFont = NULL; #endif /* * The bridge between Intuition events and Emacs' single * input stream... */ static USHORT class, /* Intuition event */ code, /* information */ qualifier; static APTR address; static SHORT x, y; static LONG intuitionMsgBit; /* Signal bit */ #define INTUITION_MESSAGE ((LONG) (1L << intuitionMsgBit)) /* * To more thoroughly handle Intuition events, we buffer * them into a circular queue until other routines ask * for the information carried in them. */ #define NIBUF 256 /* Rather roomy... */ #define EVT_KBD 0 #define EVT_MOUSE 1 #define EVT_MENU 2 #define NULLEVT ((struct event *) 0) struct event { USHORT type; /* What is it? */ union { UBYTE ch; /* Keyboard event */ struct { /* Mouse click */ SHORT row, col; /* location in character raster */ USHORT qualifier; } mouse; USHORT code; /* Menu event */ } data; } ibuf[NIBUF]; /* Input buffer */ int ibufo, nibuf; /* head, # of bytes in ibuf */ /* * Console output */ #define CSI 0x9b /* Command Sequence Introducer */ #define ESC 0x1b /* Escape key */ #define NOBUF 512 /* About 1/4 screen */ static struct MsgPort *consoleWritePort; /* I/O ports */ static struct MsgPort *consoleReadPort; static struct IOStdReq *consoleWriteMsg; /* I/O messages */ static struct IOStdReq *consoleReadMsg; static LONG consoleMsgBit; /* signal bit */ #define CONSOLE_MESSAGE ((LONG) (1L << consoleMsgBit)) static unsigned char letter; /* Console input buffer */ static unsigned char obuf[NOBUF]; /* Terminal output buffer */ int nobuf; /* # of bytes in above */ int nrow; /* Terminal size, rows. */ int ncol; /* Terminal size, columns. */ extern int ttrow; /* Current cursor row */ /* * Open up the virtual terminal MicroEMACS communicates with. * Set up the window, console, and menu strip. */ ttopen() { register struct Screen *s; Enable_Abort = 0; /* Disable ^C */ GfxBase = (struct GfxBase *) OpenLibrary("graphics.library", (LONG) 0); if (GfxBase == NULL) /* Graphics lib */ cleanup(1); IntuitionBase = (struct IntuitionBase *) /* Intuition */ OpenLibrary("intuition.library", (LONG) 0); if (IntuitionBase == NULL) cleanup(2); #ifdef CHANGE_FONT DiskfontBase = (ULONG) OpenLibrary("diskfont.library", (LONG)0); if (DiskfontBase == NULL) cleanup(21); #endif /* * Create our window. Set window flags based on the current * value of the borderless flag, and the maximum size of the * window based on the size of the first screen in the screen * list with screen type WBENCHSCREEN (of which there had better * be *EXACTLY* one, right???...). To avoid possible crashes * if user is moving screens around, turn off multitasking * during the loop. */ Forbid(); /* user might be moving screen */ for (s = IntuitionBase->FirstScreen; s ; s = s->NextScreen) if ((s->Flags & SCREENTYPE) == WBENCHSCREEN) break; MicroEMACS.MaxWidth = s->Width; MicroEMACS.MaxHeight = s->Height; Permit(); /* Set the window size based on the last one that was open, * if it was borderless. Otherwise make it fill the screen. * Set max/min widths based on current screen size. * * Set flags and window title, then open window */ if (borderless) { MicroEMACS.Flags = WINDOWGADGETS | ACTIVATE | BORDERLESS; #ifdef TOGGLE_ZOOMS MicroEMACS.LeftEdge = 0; MicroEMACS.TopEdge = 0; MicroEMACS.Width = MicroEMACS.MaxWidth; MicroEMACS.Height = MicroEMACS.MaxHeight; #endif } else { MicroEMACS.Flags = WINDOWGADGETS | ACTIVATE | WINDOWSIZING; #ifndef TOGGLE_ZOOMS } #endif MicroEMACS.LeftEdge = leftedge; MicroEMACS.TopEdge = topedge; MicroEMACS.Width = width; MicroEMACS.Height = height; #ifdef TOGGLE_ZOOMS } #endif MicroEMACS.Title = (UBYTE *) version; /* name for window */ if ((EmW = OpenWindow(&MicroEMACS)) == NULL) cleanup(3); #ifdef CHANGE_FONT /* If the user requested a different font for the text, EmFont * will be non-null, so set the font for the RastPort. The * conole device will pick this up when we open it later on. */ if (EmFont) SetFont(EmW->RPort, EmFont); #endif /* Once the window is created, get the Intuition signal bit, * set up the menu, and tell the virtual terminal how big * it is. */ intuitionMsgBit = EmW->UserPort->mp_SigBit; #ifdef DO_MENU if (toggling == FALSE) EmacsMenu = InitEmacsMenu(EmW); SetMenuStrip(EmW, EmacsMenu); #endif setttysize(); /* Set up the console device. Create the necessary read/write * ports and messages, attach the console device thus created * to our window, initialize the console input buffer, and * queue the first read to the console. */ consoleWritePort = CreatePort("Emacs.con.write",(LONG) 0); if (consoleWritePort == NULL) cleanup(4); consoleWriteMsg = CreateStdIO(consoleWritePort); if (consoleWriteMsg == NULL) cleanup(5); consoleReadPort = CreatePort("Emacs.con.read",(LONG) 0); if (consoleReadPort == NULL) cleanup(6); consoleReadMsg = CreateStdIO(consoleReadPort); if (consoleReadMsg == NULL) cleanup(7); if (OpenConsole(consoleWriteMsg,consoleReadMsg,EmW) != 0) cleanup(8); consoleMsgBit = consoleReadPort->mp_SigBit; QueueRead(consoleReadMsg,&letter); nibuf = ibufo = 0; return (0); } /* * Close the virtual terminal, aborting any * I/O to the console device and de-allocating * everything we have allocated. */ ttclose() { ttflush(); AbortIO(consoleReadMsg); CloseDevice(consoleWriteMsg); cleanup(0); Enable_Abort = 1; } /* * Toggle between a borderless window * and a sizeable window. This lets you * use the whole screen if you want. * Bound to "toggle-window-hack" by * ttykbd.c */ togglewindow(f, n, k) { toggling = TRUE; /* Notify the system */ #ifdef TOGGLE_ZOOMS if (!borderless) { #endif leftedge = EmW->LeftEdge; /* save window state */ topedge = EmW->TopEdge; width = EmW->Width; height = EmW->Height; #ifdef TOGGLE_ZOOMS } #endif ttclose(); /* reset to zero */ borderless = !borderless; /* toggle window flag */ ttopen(); /* re-open tty window */ sgarbf = TRUE; /* screen was trashed */ nrow = ncol = -1; /* trash screen size */ refresh(); /* and redraw it */ toggling = FALSE; /* Ok, done */ return (TRUE); } #ifdef CHANGE_FONT /* * Select a different font for the Emacs window. * This obviously does not work very well * with proportional fonts, so we ask the * user to confirm before he uses one. * It's available if you want to be able * to use your own disk font (or Topaz 15 * under 1.2) to edit with. */ setfont(f, n, k) { register int s, size; register struct TextFont *newfont; char fontname[80], fontpath[84], fontsize[3]; struct TextAttr ta; /* Get font size */ if (f == TRUE) size = n; else { if ((s = ereply("Font size: ", fontsize, sizeof(fontsize))) != TRUE) return (s); size = atoi(fontsize); } if (size <= 0) { /* reset to default font */ if (EmFont) CloseFont(EmFont); EmFont = NULL; } else { /* user wants to set a new font name */ if ((s = ereply("Font name (e.g. topaz): ", fontname, sizeof(fontname))) != TRUE) return (s); strcpy(fontpath,fontname); strncat(fontpath,".font",sizeof(fontpath));/* make name */ /* set up text attributes */ ta.ta_Name = (UBYTE *)fontpath; ta.ta_YSize = size; ta.ta_Style = FS_NORMAL; ta.ta_Flags = 0; /* use either */ /* Look for the font */ ewprintf("Looking for %s %d...",fontname,size); if ((newfont = OpenDiskFont(&ta)) == NULL) { ewprintf("Can't find %s %d!",fontname,size); return (FALSE); } else { /* Found it! Check before using it. */ if ((newfont->tf_YSize != size) && ((s = eyesno( "Size unavailable - use closest"))!=TRUE)){ CloseFont(newfont); return (FALSE); } if ((newfont->tf_Flags & FPF_PROPORTIONAL) && (((s = eyesno("Use proportional font")))!=TRUE)){ CloseFont(newfont); return (FALSE); } /* Get rid of old font and cache the new one */ if (EmFont) CloseFont(EmFont); EmFont = newfont; } } /* Now that the font is selected, close the window. */ toggling = TRUE; /* Notify the system */ ttclose(); /* reset to zero */ ttopen(); /* re-open w/new font */ nrow = -1; /* trash size */ ncol = -1; /* so refresh() works */ refresh(); /* redo whole screen */ if (size > 0) ewprintf("Now using font %s %d",fontname,EmFont->tf_YSize); else ewprintf("Now using default font"); return (TRUE); } #endif /* * Write a single character to the screen. * Buffered for extra speed, so ttflush() * does all the work. */ ttputc(c) unsigned char c; { obuf[nobuf++] = c; if (nobuf >= NOBUF) ttflush(); } /* * Flush characters from the output buffer. * Just blast it out with a console write call. */ ttflush() { if (nobuf > 0) { ConWrite(consoleWriteMsg, obuf, nobuf); nobuf = 0; } } /* * Get a character for Emacs, without echo or * translation. Basically, handle Intuition * events until we get one that signifies * a character was typed in some way. */ ttgetc() { register struct IntuiMessage *message; /* IDCMP message */ register LONG wakeupmask; /* which signals? */ register int charfound; /* got a character yet? */ unsigned char nextchar(); /* return next char evt */ if (striptochar()) /* any chars in buffer? */ return (int) (nextchar() & 0xFF); charfound = FALSE; /* nope -- have to wait */ do { wakeupmask = Wait(INTUITION_MESSAGE|CONSOLE_MESSAGE); if (wakeupmask & CONSOLE_MESSAGE) { /* keyboard */ GetMsg(consoleReadPort); /* free message */ qchar(letter); /* do this FIRST */ QueueRead(consoleReadMsg, &letter); charfound = TRUE; } if (wakeupmask & INTUITION_MESSAGE) /* Intuition */ while(message = GetMsg(EmW->UserPort)) if (dispatch(message) == TRUE) charfound = TRUE; } while (charfound == FALSE); return (int) (nextchar() & 0xFF); /* found a character! */ } /* * Handle the events we handle... The result * returned indicates if we've put a character * in the input buffer. */ static dispatch(msg) register struct IntuiMessage *msg; { #ifdef DO_MENU register struct MenuItem *item; #endif register int txheight, txwidth; register struct RastPort *rp; int dx, dy, fgpen, drmode; class = msg->Class; /* grab the info before we */ code = msg->Code; /* reply to the message */ qualifier = msg->Qualifier; address = msg->IAddress; x = msg->MouseX; y = msg->MouseY; ReplyMsg(msg); /* return it to Intuition */ switch(class) { /* see what the fuss is about */ #ifdef DO_MENU case MENUPICK: if (code == MENUNULL) return (FALSE); while (code != MENUNULL) {/* handle multiple selection */ qmenu(code); item = ItemAddress(EmacsMenu,(LONG) code); code = item->NextSelect; } return (TRUE); /* puts <CSI>M~ in event queue */ break; #endif #ifdef MOUSE case MOUSEBUTTONS: /* fake the mouse key */ if (code != SELECTDOWN) /* ignore SELECTUP */ return (FALSE); qmouse(x, y, qualifier); return (TRUE); break; #endif case NEWSIZE: /* Sometimes when you resize the window to make it * smaller, garbage is left at the right and bottom * sides of the window. This code is devoted to * (somehow) getting rid of this garbage. Any * suggestions? */ rp = EmW->RPort; fgpen = rp->FgPen; /* save params */ drmode = rp->DrawMode; SetDrMd(rp, (LONG) JAM1); SetAPen(rp, (LONG) EmW->RPort->BgPen); /* Check the bottom of the window */ txheight = EmW->Height - EmW->BorderTop - EmW->BorderBottom; if (dy = (txheight % FontHeight(EmW))) RectFill(rp, (LONG) EmW->BorderLeft, (LONG) EmW->BorderTop + txheight - dy - 1, (LONG) (EmW->Width - 1) - EmW->BorderRight, (LONG) (EmW->Height - 1) - EmW->BorderBottom); /* Check the right side */ txwidth = EmW->Width - EmW->BorderLeft - EmW->BorderRight; if (dx = txwidth % FontWidth(EmW)) RectFill(rp, (LONG) EmW->BorderLeft + txwidth - dx - 1, (LONG) EmW->BorderTop, (LONG) (EmW->Width - 1) - EmW->BorderRight, (LONG) (EmW->Height - 1) - EmW->BorderBottom); SetDrMd(rp, (LONG) drmode); SetAPen(rp, (LONG) fgpen); /* restore colors */ /* Tell the console device to resize itself */ ttputc(CSI); ttputc('t'); ttputc(CSI); ttputc('u'); ttflush(); /* Signal the editor that a new size has occurred */ qchar(ESC); qchar('\f'); return (TRUE); /* we done (finally) */ break; case CLOSEWINDOW: /* Call quit() directly */ quit(FALSE, 1, KRANDOM); return (FALSE); break; default: panic("HandleMsg: unknown event!!!"); break; } return(FALSE); } #ifdef DO_MENU /* * Return the next menu selection number to * the caller. Used by "ttymenu.c". */ ttmenu(codep) USHORT *codep; { register struct event *e; struct event *nextevt(); e = nextevt(); if (e->type != EVT_MENU) return (FALSE); *codep = e->data.code; remevt(); /* remove event by hand */ return (TRUE); } #endif #ifdef MOUSE /* * Return the next mouse click values to * the caller. *Rowp and *colp will contain * the row and column where the mouse click occured. * This is so that only the terminal driver has * to know about the size of the window's font. * If the flag argument f is FALSE, the mouse event * is *not* removed from the queue, allowing routines * that need to (mainly getmouse()) to peek at it. */ ttmouse(f, rowp,colp,qualp) int f; USHORT *rowp, *colp, *qualp; { register struct event *e; struct event *nextevt(); e = nextevt(); if (e->type != EVT_MOUSE) return (FALSE); /* next isn't mouse evt */ *colp = e->data.mouse.col; *rowp = e->data.mouse.row; *qualp = e->data.mouse.qualifier; if (f) remevt(); /* remove the event */ return (TRUE); } #endif /* * Return the current size of the virtual * terminal in nrow and ncol, making sure * we don't go beyond the size of the internal * video array. * Assumes the current font is monospaced * (not always safe bet any more :-) :-). */ setttysize() { nrow = (EmW->Height - EmW->BorderTop - EmW->BorderBottom) / FontHeight(EmW); ncol = (EmW->Width - EmW->BorderLeft - EmW->BorderRight) / FontWidth(EmW); if (nrow < 1) nrow = 1; if (nrow > NROW) nrow = NROW; if (ncol < 1) ncol = 1; if (ncol > NCOL) ncol = NCOL; } /* * Exit as soon as possible, after displaying * the message. */ panic(s) char *s; { ewprintf(s); /* put message at bottom */ Delay((ULONG) 90); /* wait 1.5 seconds */ ttclose(); /* get rid of window &resources */ exit(10000); /* go 'way */ } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Event buffer management * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* * If the buffer's full, crap out, else * return a pointer to the (ibufo + nibuf)'th * event record (mod NIBUF). Postincrement * nibuf so it points at the next record and * also keeps track of how many events * are in the buffer. */ static struct event *newevt() { return ((nibuf < NIBUF) ? (ibuf + ((ibufo + nibuf++) % NIBUF)) : NULLEVT); } /* * Return pointer to next item in queue, * *without* removing it. */ static struct event *nextevt() { return (nibuf ? (ibuf + ibufo) : NULLEVT); } /* * Move buffer pointer to next item in queue. */ static remevt() { if (nibuf <= 0) nibuf = 0; else { nibuf--; ibufo++; ibufo %= NIBUF; /* wrap around in buffer */ } } /* * Return true if there are some characters available * in the buffer. Unlike striptochar, don't do anything * to the input buffer, just return a value. */ typeahead() { register int bufp; for (bufp = 0; bufp < nibuf; bufp++) if (ibuf[(ibufo + bufp) % NIBUF].type == EVT_KBD) return (TRUE); return (FALSE); } /* * See if there are any characters queued, * stripping any other events that may * be in the way. *Don't* remove the character * from the queue. */ static striptochar() { register struct event *e; while (e = nextevt()) if (e->type == EVT_KBD) return (TRUE); else remevt(); return (FALSE); } /* * Return next character in event buffer. */ static unsigned char nextchar() { register struct event *e; if (e = nextevt()) { remevt(); return (e->data.ch); } else return ((unsigned char) 0); /* shouldn't happen */ } /* * Add a keyboard event to the queue */ static qchar(c) unsigned char c; { register struct event *e; if (e = newevt()) { e->type = EVT_KBD; e->data.ch = c; } } #ifdef MOUSE /* * Add a mouse event to the queue, calculating * the row and column value from the current height * and width of the window's font. */ static qmouse(x, y, qual) SHORT x, y; USHORT qual; { register struct event *e; qchar(CSI); qchar('P'); qchar('~'); if (e = newevt()) { e->type = EVT_MOUSE; e->data.mouse.col = (x - EmW->BorderLeft) / FontWidth(EmW); e->data.mouse.row = (y - EmW->BorderTop) / FontHeight(EmW); e->data.mouse.qualifier = qual; } } #endif #ifdef DO_MENU /* * Add a menu key to queue */ static qmenu(code) USHORT code; { register struct event *e; qchar(CSI); /* menu key sequence */ qchar('M'); qchar('~'); if (e = newevt()) { e->type = EVT_MENU; e->data.code = code; } } #endif /* * Clean up. * * Fall through all the possible cases (0 means * get rid of everything and start with the case * that fits the error situation). */ static cleanup(prob) { switch (prob) { case 0: /* just clean everything up case 8: /* couldn't open console device */ DeleteStdIO(consoleReadMsg); case 7: /* couldn't get console read msg */ DeletePort(consoleReadPort); case 6: /* couldn't get console read port */ DeleteStdIO(consoleWriteMsg); case 5: /* couldn't get console write msg */ DeletePort(consoleWritePort); case 4: /* couldn't get console write port */ #ifdef CHANGE_FONT if ((toggling == FALSE) && EmFont) CloseFont(EmFont);/* access_count-- */ #endif #ifdef DO_MENU if (toggling == FALSE) { ClearMenuStrip(EmW); DisposeMenus(EmacsMenu); } #endif CloseWindow(EmW); case 3: /* couldn't open window */ #ifdef CHANGE_FONT CloseLibrary(DiskfontBase); #endif case 21: /* couldn't open DiskfontBase */ CloseLibrary(IntuitionBase); case 2: /* couldn't open IntuitionBase */ CloseLibrary(GfxBase); case 1: /* couldn't open GfxBase -- do nothing */ break; } return(0); } SHAR_EOF fi # end of overwriting check if test -f 'tty/amiga/ttymenu.c' then echo shar: will not over-write existing file "'tty/amiga/ttymenu.c'" else cat << \SHAR_EOF > 'tty/amiga/ttymenu.c' /* * ttymenu.c * * Incorporates the browser, for rummaging around on disks, * and the usual Emacs editing command menu * * Copyright (c) 1986, Mike Meyer * Manxification and Edit menu by Mic Kaczmarczik (no charge :-) * * Permission is hereby granted to distribute this program, so long as * this source file is distributed with it, and this copyright notice * is not removed from the file. * */ #include <exec/types.h> #include <libraries/dos.h> #include <libraries/dosextens.h> #include <intuition/intuition.h> #undef TRUE #undef FALSE #include "def.h" extern struct Menu *AutoMenu ; extern struct Window *EmW ; #define MNUM(menu,item,sub) (SHIFTMENU(menu)|SHIFTITEM(item)|SHIFTSUB(sub)) #ifdef BROWSER #define LONGEST_NAME 80 /* Longest file name we can deal with */ # ifndef MANX char *strchr(char *, int); # else char *index(); /* find first instance of c in s */ #define strchr(s, c) index(s, c) # endif # ifdef MENU #define FIRSTMENU 1 # else #define FIRSTMENU 0 # endif #endif BROWSER #ifdef MENU /* * When ttgetc() sees a menu selection event, it stuffs * the sequence <CSI>M~ into the input buffer, and * caches the menu number and item number for later. * This sequence is translated into the internal key code * KMENU, similar to KHELP and the other function keys. * * The menu item names are chosen to be relatively close * to the extended function names, so a user can usually * figure out the key binding of a menu item by searching * through the "display-bindings" buffer for something * that's close. */ /* * Commands for managing files and buffers */ static struct MenuBinding FileItems[] = { { "Find File C-x C-f", "find-file" }, { "Pop To File C-x 4 f", "find-file-other-window" }, { "Insert File C-x i", "insert-file" }, { "Save File C-x C-s", "save-buffer" }, { "Write File C-x C-w", "write-file" }, { "Switch To Buffer C-x b", "switch-to-buffer" }, { "Pop To Buffer C-x 4 b", "switch-to-buffer-other-window" }, { "Kill Buffer C-x k", "kill-buffer" }, { "List Buffers C-x C-b", "list-buffers" }, { "Save Buffers C-x s", "save-some-buffers" }, { "Save And Exit C-x C-c", "save-buffers-kill-emacs" } }; /* * Commands for various editing functions */ static struct MenuBinding EditItems[] = { { "Yank C-y", "yank" }, { "Blank Line C-o ", "open-line" }, { "Kill Line C-k", "kill-line" }, { "Delete Blank Lines C-x C-o","delete-blank-lines" }, { "Delete Blanks M-SPC", "just-one-space" }, { "Newline And Indent C-j", "newline-and-indent" }, { "Transpose Characters C-t", "transpose-chars" }, { "Quoted Insert C-q", "quoted-insert" } }; /* * Movement commands */ static struct MenuBinding MoveItems[] = { { "Scroll Up C-v", "scroll-up" }, { "Scroll Down M-v", "scroll-down" }, { "Start Of Line C-a", "beginning-of-line" }, { "Start Of Buffer M-<", "beginning-of-buffer" }, { "End Of Line C-e", "end-of-line" }, { "End Of Buffer M->", "end-of-buffer" }, { "Goto Line", "goto-line" }, { "Show Cursor C-x =", "what-cursor-position" } }; /* * Commands for searching and replacing */ static struct MenuBinding SearchItems[] = { { "I-Search Forward C-s", "isearch-forward" }, { "I-Search Backward C-r", "isearch-backward" }, { "Search Again", "search-again" }, { "Search Forward M-s", "search-forward" }, { "Search Backward M-r", "search-backward" }, { "Query Replace M-%", "query-replace" } }; /* * Commands that manipulate words */ static struct MenuBinding WordItems[] = { { "Forward Word M-f", "forward-word" }, { "Backward Word M-b", "backward-word" }, { "Kill Word M-d", "kill-word" }, { "Backward Kill Word M-DEL", "backward-kill-word" }, { "Capitalize Word M-c", "capitalize-word" }, { "Downcase Word M-l", "downcase-word" }, { "Upcase Word M-u", "upcase-word" } }; static struct MenuBinding ParaItems[] = { { "Forward Paragraph M-]", "forward-paragraph" }, { "Backward Paragraph M-[", "backward-paragraph" }, { "Fill Paragraph M-q", "fill-paragraph" }, { "Set Fill Column C-x f", "set-fill-column" }, { "Kill Paragraph", "kill-paragraph" }, { "Auto Fill Mode", "auto-fill-mode" } }; /* * Region stuff */ static struct MenuBinding RegionItems[] = { { "Set Mark C-@", "set-mark-command" }, { "Exch Point And Mark C-x C-x","exchange-point-and-mark" }, { "Kill Region C-w", "kill-region" }, { "Copy Region As Kill M-w", "copy-region-as-kill" }, { "Downcase Region C-x C-l","downcase-region" }, { "Upcase Region C-x C-u","upcase-region" } }; /* * Commands for manipulating windows */ static struct MenuBinding WindowItems[] = { { "Split Window C-x 2", "split-window-vertically" }, { "Delete Window C-x 0", "delete-window" }, { "Delete Other Windows C-x 1", "delete-other-windows" }, { "Down Window C-x o", "next-window" }, { "Up Window", "previous-window" }, { "Enlarge Window C-x ^", "enlarge-window" }, { "Shrink Window", "shrink-window" }, { "Redraw Display", "redraw-display" }, { "Recenter C-l", "recenter" }, { "Toggle Border", "toggle-window-hack" }, #ifdef CHANGE_FONT { "Set Font", "set-font" } #endif }; /* * Miscellaneous commands */ static struct MenuBinding MiscItems[] = { { "Start Kbd Macro C-x (", "start-kbd-macro" }, { "End Kbd Macro C-x )", "end-kbd-macro" }, { "Call Kbd Macro C-x e", "call-last-kbd-macro" }, { "Execute Command M-x", "execute-extended-command" }, { "Global Set Key", "global-set-key" }, { "Global Unset Key", "global-unset-key" }, { "Describe Key C-h c", "describe-key-briefly", }, { "Describe Bindings C-h b", "describe-bindings" }, { "Emacs Version", "emacs-version" }, { "New CLI C-z", "suspend-emacs" } }; /* * The following table contains the titles, number of * items, and pointers to, the individual menus. */ static struct MenuInfo EMInfo[] = { { "File ", NITEMS(FileItems), &FileItems[0] }, { "Edit ", NITEMS(EditItems), &EditItems[0] }, { "Move ", NITEMS(MoveItems), &MoveItems[0] }, { "Search ", NITEMS(SearchItems), &SearchItems[0] }, { "Word ", NITEMS(WordItems), &WordItems[0] }, { "Paragraph ", NITEMS(ParaItems), &ParaItems[0] }, { "Region ", NITEMS(RegionItems), &RegionItems[0] }, { "Window ", NITEMS(WindowItems), &WindowItems[0] }, { "Miscellaneous ", NITEMS(MiscItems), &MiscItems[0] } }; /* There are three cases to deal with; the menu alone, the Browser * alone, and both of them together. We #define some things to make * life a little easier to deal with */ # ifdef BROWSER # define Edit_Menu_Init() Menu_Add("Edit ", TRUE) # define Edit_Menu_Add(n) Menu_Item_Add(n,(USHORT)ITEMENABLED,0L,(BYTE)0) # define Edit_Item_Add(n) Menu_SubItem_Add(n,(USHORT)ITEMENABLED,0L,(BYTE)0) # else # define Edit_Menu_Init() cinf = NULL /* harmless */ # define Edit_Menu_Add(n) n[strlen(n)-1] = '\0'; Menu_Add(n, TRUE) # define Edit_Item_Add(n) Menu_Item_Add(n,(USHORT)ITEMENABLED,0L,(BYTE)0) # endif BROWSER #endif MENU /* * Heeere we go!!!! */ struct Menu * InitEmacsMenu(EmW) struct Window *EmW; { #ifdef MENU register struct MenuInfo *cinf, *lastinfo; register struct MenuBinding *cb, *lastbinding; #endif Menu_Init() ; /* init the menu */ #ifdef MENU Edit_Menu_Init() ; /* Set up for editing menu */ lastinfo = &EMInfo[NITEMS(EMInfo)]; /* loop sentinel */ for (cinf = EMInfo; cinf < lastinfo; cinf++) { Edit_Menu_Add(cinf->Name); lastbinding = &cinf->Items[cinf->NumItems]; for (cb = cinf->Items; cb < lastbinding; cb++) Edit_Item_Add(cb->Command); } #endif MENU #ifdef BROWSER Menu_Add("Disks ", TRUE) ; Menu_Item_Add("Df0:", (USHORT) ITEMENABLED, 0L, (BYTE) 0) ; Menu_Item_Add("Df1:", (USHORT) ITEMENABLED, 0L, (BYTE) 0) ; Menu_Item_Add("Ram:", (USHORT) ITEMENABLED, 0L, (BYTE) 0) ; #endif BROWSER return AutoMenu ; } /* * amigamenu() -- handles a menu pick. */ amigamenu(f, n, k) { unsigned short Menu_Number; char *name; int ttmenu(); /* in ttyio.c */ #ifdef BROWSER register unsigned short level, i, dirp; register char *cp; int stat; struct MenuItem *ItemAddress() ; /* State variables that describe the current directory */ static char Dir_Name[LONGEST_NAME] ; static unsigned short Menu_Level = 0 ; #endif #ifdef MENU SYMBOL *sp; #endif if (!ttmenu(&Menu_Number)) return FALSE; /* get menu number */ #ifndef BROWSER # ifdef MENU name = EMInfo[MENUNUM(Menu_Number)].Items[ITEMNUM(Menu_Number)].Binding; if ((sp=symlookup(name)) != NULL) return ((*sp->s_funcp)(f, n, KRANDOM)); panic("Unknown menu command!"); /* trouble! */ # endif #else /* we're using the Browser */ # ifdef MENU /* Handle commands from the Edit menu when using the Browser */ if (0 == MENUNUM(Menu_Number)) { name = EMInfo[ITEMNUM(Menu_Number)].Items[SUBNUM(Menu_Number)].Binding; if ((sp=symlookup(name)) != NULL) return ((*sp->s_funcp)(f, n, KRANDOM)); panic("Unknown menu command!"); /* trouble! */ } # endif /* Here when a selection was made in a Browser menu */ name = (char *)((struct IntuiText *) (ItemAddress(AutoMenu,(ULONG) Menu_Number) -> ItemFill)) -> IText ; level = MENUNUM(Menu_Number) - FIRSTMENU; /* Got what we want, so clear the menu to avoid confusing the user */ ClearMenuStrip(EmW) ; /* set dirp to FALSE if the name is not a directory or disk */ dirp = (strchr(name, '/') != NULL || strchr(name, ':') != NULL) ; /* First, set the directory name right */ if (level > Menu_Level) /* Not possible, die */ panic("impossible menu_level in amigamenu"); else if (level == 0) /* picked a new disk */ Dir_Name[0] = '\0' ; else if (level < Menu_Level) { /* Throw away some levels */ for (i = 1, cp = strchr(Dir_Name, ':'); i < level; i++) { if (cp == NULL) return FALSE; cp = strchr(cp, '/') ; } if (cp == NULL) panic("broken file name in amigamenu"); *++cp = '\0' ; } /* else Menu_Level == level, chose a file a current level */ /* Now, fix up the menu and it's state variable */ while (Menu_Level > level) { Menu_Level-- ; Menu_Pop() ; } /* If we added a directory, tack it onto the name */ if (dirp) { Menu_Level++ ; (void) strncat(Dir_Name, name, LONGEST_NAME - strlen(Dir_Name) - 1) ; } /* Now, tell the user all about it */ if (dirp) stat = Add_Dir(Dir_Name, name) ; else stat = Display_File(Dir_Name, name) ; SetMenuStrip(EmW, AutoMenu) ; return stat ; #endif BROWSER } #ifdef BROWSER /* * Display_File - Go fetch a the requested file into a window. */ Display_File(dir, file) char *dir, *file; { register BUFFER *bp, *findbuffer(); int s; char File_Name[LONGEST_NAME]; (void) strcpy(File_Name, dir); (void) strncat(File_Name, file, LONGEST_NAME - strlen(File_Name) - 1) ; if ((bp = findbuffer(File_Name, &s)) == NULL) return s; curbp = bp; if (showbuffer(bp, curwp, WFHARD) != TRUE) return FALSE; if (bp->b_fname[0] == 0) return (readin(File_Name)); /* Read it in. */ return TRUE; } /* * Add_Dir - given a dir and a name, add the menu name with the files in * dir as entries. Use AllocMem() in order to make * sure the file info block is on a longword boundary. */ static Add_Dir(dir, name) char *dir, *name; { register char *last_char ; register struct FileLock *my_lock, *Lock() ; unsigned short count ; int stat = FALSE; static char Name_Buf[LONGEST_NAME] ; char *AllocMem(); struct FileInfoBlock *File_Info; if ((File_Info = (struct FileInfoBlock *) AllocMem((LONG)sizeof(struct FileInfoBlock), 0L)) == NULL) return (FALSE); /* Fix up the trailing / if it needs it */ last_char = &dir[strlen(dir) - 1] ; if (*last_char == '/') *last_char = '\0' ; /* Now, start on the directory */ if ((my_lock = Lock(dir, ACCESS_READ)) == NULL) goto out; if (!Examine(my_lock, File_Info)) goto out; if (File_Info -> fib_DirEntryType < 0L) goto out; if (Menu_Add(name, TRUE) == 0) return NULL; for (count = 0; ExNext(my_lock, File_Info) || IoErr() != ERROR_NO_MORE_ENTRIES; count++) if (File_Info -> fib_DirEntryType < 0L) { if (Menu_Item_Add(File_Info -> fib_FileName, (USHORT)ITEMENABLED, 0L, (BYTE)0) == MNUM(NOMENU, NOITEM, NOSUB)) break ; } else { (void) strcpy(Name_Buf, File_Info -> fib_FileName) ; (void) strcat(Name_Buf, "/") ; if (Menu_Item_Add(Name_Buf, (USHORT) ITEMENABLED, 0L, (BYTE)0) == MNUM(NOMENU, NOITEM, NOSUB)) break ; } if (count == 0) Menu_Item_Add("EMPTY", (USHORT)0, 0L, (BYTE)0) ; /* Put everything back */ if (*last_char == '\0') *last_char = '/' ; stat = TRUE; out: UnLock(my_lock) ; FreeMem(File_Info, (LONG) sizeof(struct FileInfoBlock)); return stat; } #endif BROWSER SHAR_EOF fi # end of overwriting check # End of shell archive exit 0