Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Path: utzoo!watmath!clyde!burl!ulysses!allegra!princeton!orsvax1!pyrnj!caip!lll-crg!mordor!ut-sally!ut-ngp!mic From: mic@ut-ngp.UUCP (Mic Kaczmarczik) Newsgroups: net.micro.amiga Subject: Amiga terminal driver for MicroEmacs (2 of 3) Message-ID: <3276@ut-ngp.UUCP> Date: Wed, 23-Apr-86 11:28:22 EST Article-I.D.: ut-ngp.3276 Posted: Wed Apr 23 11:28:22 1986 Date-Received: Sat, 26-Apr-86 05:16:48 EST Reply-To: mic@ut-ngp.UUCP (Mic Kaczmarczik) Organization: U. Texas Computation Ctr Lines: 645 This is the file 2 of 3 of the Amiga code for MicroEmacs. It contains the AmigaDOS terminal driver. Mic Kaczmarczik ...!ihnp4!seismo!ut-sally!ut-ngp!mic -------------------------------amigados.ar------------------------------------ -h- tty.c Wed Apr 23 08:53:26 1986 tty.c /* * Name: MicroEMACS * Amiga console device virtual terminal display * Version: 31 * Last Edit: 21-Apr-86 * Created: 19-Apr-86 ...!ihnp4!seismo!ut-sally!ut-ngp!mic * Modified: 21-Apr-86 ...!ihnp4!seismo!ut-sally!ut-ngp!mic * In ttresize() use ttmove(HUGE,HUGE) and cursor * position report to get the new window size */ #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; /* * Initialize the terminal when the editor * gets started up. This is a no-op on 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); 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; { register int q; q = n/10; if (q != 0) asciiparm(q); 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. */ ttinsl(row, bot, nchunk) { register int i; if (row == bot) { /* Funny case. */ if (nchunk != 1) abort(); 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. */ ttdell(row, bot, nchunk) { register int i; 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; /* Force ttmove() to do the move*/ ttcol = HUGE; ttmove(bot-nchunk,0); } /* * No-op. */ ttwindow(top,bot) { } /* * No-op. */ ttnowindow() { } /* * 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); ttputc('['); ttputc('m'); } else if (color == CMODE) { /* Reverse video. */ ttputc(ESC); ttputc('['); ttputc('7'); 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. */ #define CSI 0x9B ttresize() { register int newnrow, newncol; ttmove(HUGE,HUGE); /* Go to bottom right */ ttputc(CSI); /* See where cursor went to */ ttputc('6'); ttputc('n'); ttflush(); if (ttgetc() != CSI) /* parse the report */ returnf; if ((newnrow = readparm(';')) == -1) return; if ((newncol = readparm('R')) == -1) return; if (newnrow < 1) /* check limits. */ newnrow = 1; else if (newnrow > NROW) newnrow = NROW; if (newncol < 1) newncol = 1; else if (newncol > NCOL) newncol = NCOL; nrow = newnrow; ncol = newncol; } /* * Read an unsigned number from the terminal */ static readparm(delim) char delim; { register int parm; register int c; parm = 0; while ((c=ttgetc()) >= '0' && c <= '9') parm = 10 * parm + c - '0'; return (c == delim) ? parm : -1; } -h- ttydef.h Wed Apr 23 08:53:26 1986 ttydef.h /* * Name: MicroEMACS * Amiga console device virtual terminal header file * Version: 31 * Last edit: 20-Apr-86 * Created: 20-Apr-86 ...!ihnp4!seismo!ut-sally!ut-ngp!mic * */ #define GOSLING 1 /* Compile in fancy display. */ #define MEMMAP 0 /* Not memory mapped video. */ #define NROW 23 /* Rows. */ #define NCOL 77 /* Columns (AmigaDOS) */ /* * Special keys for the default Amiga console device keymap. * Function key codes are in the form 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. There is no shifted value for the * HELP key. */ #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 -h- ttyio.c Wed Apr 23 08:53:26 1986 ttyio.c /* * Name: MicroEMACS * AmigaDOS terminal I/O * Version: 31 * Compiler: Manx Aztec C * Last edit: 19-Apr-86 ...!ihnp4!seismo!ut-sally!ut-ngp!mic * Created: 19-Apr-86 ...!ihnp4!seismo!ut-sally!ut-ngp!mic */ #include "def.h" #include "sysdef.h" #include #include #define NIBUF 128 /* Probably excessive. */ #define NOBUF 512 /* Not too big for 750/730. */ struct FileHandle *tty; struct FileHandle *Open(); char obuf[NOBUF]; /* Output buffer */ int nobuf; /* # of bytes in above */ char ibuf[NIBUF]; /* Input buffer */ int nibuf; /* # of bytes in above */ int nrow; /* Terminal size, rows. */ int ncol; /* Terminal size, columns. */ #if MANX extern int Enable_Abort; #endif extern char *version[]; /* Defined in "version.c" */ /* * This routine gets called once, to set up the * terminal channel. */ ttopen() { char WindowName[80]; nrow = 23; ncol = 77; nobuf = nibuf = 0; #if MANX Enable_Abort = 0; /* Disable ^C during file I/O */ #endif strcpy(WindowName,"RAW:1/1/639/199/"); strcat(WindowName,version[0]); tty = Open(WindowName,MODE_NEWFILE); if (tty == (struct FileHandle *) 0) { printf("Can't open Emacs window!\n"); exit(200); } } /* * This function gets called just * before we go back home to the command interpreter. * On the Amiga it closes up the virtual terminal window. */ ttclose() { if (tty != (struct FileHandle *) 0L) { ttflush(); Close(tty); } tty = (struct FileHandle *) 0L; Enable_Abort = 1; } /* * Write a character to the display. * On the Amiga, terminal output is buffered, and * we just put the characters in the big array, * after cheching for overflow. */ ttputc(c) { if (nobuf >= NOBUF) ttflush(); obuf[nobuf++] = c; } /* * This function does the real work of * flushing out buffered I/O on the Amiga. All * we do is blast out the block with a write call. */ ttflush() { if (nobuf > 0) { Write(tty,obuf,(long) nobuf); nobuf = 0; } } /* * Read a character from the terminal, * performing no editing and doing no echo at all. */ ttgetc() { unsigned char c; /* must be unsigned! */ Read(tty,&c,1L); return ((int) c); } -h- ttykbd.c Wed Apr 23 08:53:26 1986 ttykbd.c /* * Name: MicroEMACS * Amiga virtual terminal keyboard, default console keymap. * Version: 31 * Last edit: 20-Apr-86 * Created: 19-Apr-86 ...!ihnp4!seismo!ut-sally!ut-ngp!mic * Supports all the default console device * (RAW:) input codes for the Amiga keyboard. * Modified: 20-Apr-86 ...!ihnp4!seismo!ut-sally!ut-ngp!mic * [UT-14A] Added processing for GR_to_META, so * characters in the alternate character set * can automatically map to META characters. * This is a rather nice thing to have... */ #include "def.h" #define ESC 0x1B /* Escape, arrows et al. */ #define CSI 0x9B /* Amiga CSI */ /* * The function keys on the Amiga send back * escape sequences of the form [code~, where code * is a one or two-character code for the key. To make * it easier to decode, we place the internal key values * for these codes in this table. */ short consolemap[] = { KF1, KF2, KF3, KF4, KF5, KF6, KF7, KF8, KF9, KF10, KSF1, KSF2, KSF3, KSF4, KSF5, KSF6, KSF7, KSF8, KSF9, KSF10 }; #define NFUNCKEYS ((sizeof consolemap)/(sizeof consolemap[0])) /* * Names for the keys with basic keycode * between KFIRST and KLAST (inclusive). This is used by * the key name routine in "kbd.c". KFIRST is KRANDOM, which * we don't bind anything useful to. */ char *keystrings[] = { NULL, "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10", "Shift-F1", "Shift-F2", "Shift-F3", "Shift-F4", "Shift-F5", "Shift-F6", "Shift-F7", "Shift-F8", "Shift-F9", "Shift-F10", "Up", "Shift-Up", "Down", "Shift-Down", "Left", "Shift-Left", "Right", "Shift-Right", "Help", NULL, NULL }; /* * Read in a key, doing the low level mapping * of ASCII code to 11 bit code. This level deals with * mapping the special keys into their spots in the C1 * control area. The C0 controls go right through, and * get remapped by "getkey". * * If GR_to_META is TRUE, characters in the Amiga alternate * character set get mapped to META characters. If FALSE, * they get sent straight through. */ extern int GR_to_META; /* defined in "kbd.c" */ getkbd() { register int c; register int n; loop: c = ttgetc(); if (c == CSI) { c = ttgetc(); /* Unshifted arrow keys */ if (c == 'A') return (KUP); if (c == 'B') return (KDOWN); if (c == 'C') return (KRIGHT); if (c == 'D') return (KLEFT); if (c == 'T') return (KSUP); if (c == 'S') return (KSDOWN); if (c == '?') { ttgetc(); /* discard '~' */ return (KHELP); } /* Shifted left, right */ if (c == ' ') { c = ttgetc(); if (c == 'A' || c == '@') return (c == 'A') ? (KSLEFT) : (KSRIGHT); goto loop; /* try again, sucker */ } /* Function keys */ if (c >= '0' && c <= '9') { n = 0; do { n = 10*n + c - '0'; c = ttgetc(); } while (c>='0' && c<='9'); if (c == '~' && n < NFUNCKEYS) { c = consolemap[n]; if (c != KRANDOM) return (c); goto loop; } else goto loop; /* Try again */ } goto loop; /* Try again */ } /* Meta keys -- also check for high bit set */ if ((c == ESC) || (GR_to_META && (c & 0x80))) { if (c == ESC) c = ttgetc(); c &= 0x7F; /* Strip high bit */ if (ISLOWER(c) != FALSE) /* Copy the standard */ c = TOUPPER(c); /* META code. */ if (c>=0x00 && c<=0x1F) c = KCTRL | (c+'@'); return (KMETA | c); } return (c); } /* * Terminal specific keymap initialization. * Attach the special keys to the appropriate built * in functions. Bind all of the assigned graphics in the * Amiga alternate character set to self-insert. * As is the case of all the keymap routines, errors * are very fatal. */ ttykeymapinit() { register SYMBOL *sp; register int i; keydup(KUP, "back-line"); keydup(KDOWN, "forw-line"); keydup(KRIGHT, "forw-char"); keydup(KLEFT, "back-char"); keydup(KHELP, "help"); keydup(KSUP, "goto-bob"); keydup(KSDOWN, "goto-eob"); keydup(KSRIGHT, "goto-eop"); keydup(KSLEFT, "goto-bop"); keydup(KF1, "down-window"); keydup(KF2, "forw-page"); keydup(KF3, "enlarge-window"); keydup(KF4, "forw-window"); keydup(KF5, "split-window"); keydup(KF6, "file-visit"); keydup(KF7, "file-save"); keydup(KF8, "start-macro"); keydup(KF9, "bind-to-key"); keydup(KF10, "display-version"); keydup(KSF1, "up-window"); keydup(KSF2, "back-page"); keydup(KSF3, "shrink-window"); keydup(KSF4, "back-window"); keydup(KSF5, "only-window"); keydup(KSF6, "file-read"); keydup(KSF7, "file-write"); keydup(KSF8, "end-macro"); keydup(KSF9, "display-bindings"); keydup(KSF10, "quit"); /* * Bind all positions that correspond * to characters in the Amiga alternate * character set to "ins-self". These characters may * be used just like any other character. */ if ((sp=symlookup("ins-self")) == NULL) abort(); for (i=0xA0; i<0xFF; ++i) { if (binding[i] != NULL) abort(); binding[i] = sp; ++sp->s_nkey; } }