v08i013: A Micro-Emacs variant that resembles GNU Emacs
sources-request at mirror.UUCP
sources-request at mirror.UUCP
Wed Jan 28 04:22:27 AEST 1987
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
More information about the Mod.sources
mailing list