Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP
Path: utzoo!mnetor!seismo!rutgers!ucla-cs!zen!ucbvax!s.cc.purdue.edu!dillon%cory.berkeley.edu
From: dillon%cory.berkeley.edu@berkeley.edu (Matt Dillon)
Newsgroups: comp.sources.amiga
Subject: DME V1.27 (sources part 2 of 2)
Message-ID: <384@s.cc.purdue.edu>
Date: Wed, 1-Jul-87 08:34:46 EDT
Article-I.D.: s.384
Posted: Wed Jul  1 08:34:46 1987
Date-Received: Sat, 11-Jul-87 01:33:29 EDT
Sender: doc@s.cc.purdue.edu
Reply-To: doc@s.cc.purdue.edu (Craig Norborg)
Distribution: world
Organization: Purdue University Computing Center
Lines: 1822
Approved: doc@s.cc.purdue.edu


	This is part 2 of 2 of the sources to dme.

#	This is a shell archive.
#	Remove everything above and including the cut line.
#	Then run the rest of the file through sh.
#----cut here-----cut here-----cut here-----cut here----#
#!/bin/sh
# Xshar: Extended Shell Archiver.
# This is part  2 out of  2.
# This archive created: Wed Jul  1 07:25:23 1987
# By: Craig Norborg (Purdue University Computing Center)
#	Run the following text with /bin/sh to create:
#	defs.h
#	keyboard.c
#	subs.c
#	text2.c
cat << \SHAR_EOF > defs.h

/*
 * DEFS.H
 *
 *	(C)Copyright 1987 by Matthew Dillon, All Rights Reserved
 *
 */

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include "xmisc.h"

#define MAXTOGGLE   256
#define QMOVE	    0x6B

#define COLT(n)  (XTbase + (n) * Xsize)
#define ROWT(n)  (YTbase + (n) * Ysize)
#define COL(n)	 (Xbase  + (n) * Xsize)
#define ROW(n)	 (Ybase  + (n) * Ysize)

typedef unsigned char u_char;
typedef struct WBStartup  WBS;
typedef struct DiskObject DISKOBJ;

extern WBS	*Wbs;
extern DISKOBJ	*Do;

extern short Xsize, Ysize;
extern short XTbase, YTbase;
extern short Rows, Columns;
extern short Xbase, Ybase;
extern short Xpixs, Ypixs;
extern u_char *av[];
extern char Wdisable;


typedef struct _ED {
    struct _ED *next, **prev;
    WIN *Win;
    long Topline, Topcolumn;
    long Line, Column;
    long Lines, Maxlines;
    u_char **List;
    u_char Name[64];
    u_char Wtitle[130];
    char Modified;
    u_char Tabstop;
    u_char Margin;
    char Insertmode;
    char Wordwrap;
    char iconmode;	    /* window in icon mode		    */
    short Winx, Winy, Winwidth, Winheight;
    short IWinx, IWiny;
    long BSline, BEline;    /* block start and end lines	    */
    short BSchar, BEchar;   /* char start on BSline, end on BEline  */
    long dirlock;	    /* directory lock			    */
} ED;


#ifndef NULL
#define NULL 0
#endif
#ifdef E
#undef E
#endif

extern ED E, *Ep, *Base;
extern char Savetabs, titleupdate;
extern char memoryfail, Nsu;
extern u_char Current[256];
extern short Clen;
extern char  Abortcommand, MShowTitle;
extern short ComLineMode;
extern RP *Rp;
extern WIN *Win;

extern u_char *MAllocate();
extern u_char *AllocMem(), *strcpy(), *malloc();
extern char *keyspectomacro();

extern void search_operation();



SHAR_EOF
cat << \SHAR_EOF > keyboard.c

/*
 *  KEYBOARD.C
 *
 *	(C)Copyright 1987 by Matthew Dillon
 *
 *  Handle keyboard related stuff such as keyboard mappings.  Every time
 *  a key is pressed, KEYCTL() is called with the code.  KEYCTL() remembers
 *  which qualifier keys are currently held down, and when a non-qualifier
 *  key is pressed finds the hash entry for the key.  If no hash entry
 *  exists (e.g. you type a normal 'a') the default keymap is used.
 */

#include "defs.h"

typedef struct IOStdReq CIO;

#define QUAL_SHIFT   0x01
#define QUAL_CTRL    0x02
#define QUAL_AMIGA   0x04
#define QUAL_ALT     0x08
#define QUAL_LMB     0x10
#define QUAL_MMB     0x20
#define QUAL_RMB     0x40

#define XBITSET(array,bit)   (array[(bit)>>3] |= 1<<((bit)&7))
#define XBITTEST(array,bit)  (array[(bit)>>3] & 1<<((bit)&7))


#define HASHSIZE  64

typedef struct _HASH {
    struct _HASH *next;     /* next hash   */
    u_char code;	    /* keycode	   */
    u_char mask;	    /* qual. mask  */
    u_char qual;	    /* qual. comp  */
    u_char stat;	    /* string static? */
    char *str;		    /* command string */
} HASH;

HASH *Hash[HASHSIZE];

static u_char isascii[0x80/8];	/* is printable ascii	*/
static u_char isalpha[0x80/8];	/* is alpha a-z/A-Z	*/
static u_char ctoa[0x80];	/* cvt to character	    */
static u_char cstoa[0x80];	/* cvt to shifted chacter   */

dealloc_hash()
{
    register HASH *hash, *hnext = NULL;
    register short i;

    for (i = 0; i < HASHSIZE; ++i) {
	for (hash = Hash[i]; hash; hash = hnext) {
	    hnext = hash->next;
	    if (!hash->stat)
		FreeMem(hash->str, strlen(hash->str)+1);
	    FreeMem(hash, sizeof(HASH));
	}
	Hash[i] = NULL;
    }
}

resethash()
{
    register short i;

    static struct {
	char *from, *to;
    } defmap[] = {
	"esc",      "esc",
	"return",   "return insline up firstnb down",
	"enter",    "return",
	"up",       "up",
	"down",     "down",
	"right",    "right",
	"left",     "left",
	"bs",       "bs",
	"del",      "del",
	"help",     "newwindow newfile s:DME.DOC escimm `find '",
	"tab",      "tab",
	"s-up",     "top",
	"s-down",   "bottom",
	"s-right",  "last",
	"s-left",   "first",
	"s-tab",    "backtab",
	"s-del",    "deline",
	"s- ",      "` '",              /* shift space to space */
	"c-l",      "wleft",
	"c-r",      "wright",
	"c-i",      "insertmode on",
	"c-o",      "insertmode off",
	"c-j",      "join",
	"c-s",      "split first down",
	"c-del",    "remeol",
	"c-n",      "next",
	"c-p",      "prev",
	"c-/",      "escimm `find '",
	"c-g",      "escimm `goto '",
	"c-up",     "pageup",
	"c-down",   "pagedown",
	"c-q",      "quit",
	"c-f",      "reformat",
	"c-w",      "wordwrap toggle",
	"f1",       "escimm `insfile '",
	"f2",       "escimm `newfile '",
	"f3",       "escimm `newwindow newfile '",
	"f7",       "escimm `bsave '",
	"f8",       "saveold escimm `newfile '",
	"f9",       "saveold",
	"f10",      "saveold quit",
	"c-b",      "block",
	"c-u",      "unblock",
	"a-d",      "bdelete",
	"a-c",      "bcopy",
	"a-m",      "bmove",
	"a-s",      "bsource",
	"a-S",      "unblock block block bsource",
	"L-lmb",    "tomouse",      /*  left button                 */
	"L-mmo",    "tomouse",      /*  mouse move w/left held down */
	"R-rmb",    "iconify",      /*  right button                */
	NULL, NULL
    };

    dealloc_hash();
    loaddefaultkeymap();
    for (i = 0; defmap[i].from; ++i) {
	u_char code, qual;
	if (get_codequal(defmap[i].from, &code, &qual))
	    addhash(code, 1, 0xFF, qual, defmap[i].to);
    }
}

/*
 *  Go through keycodes $00 to $4F and load the ctoa[], cstoa[], and
 *  isalpha[] char tables from the default console keymap.
 */

loaddefaultkeymap()
{
    CIO cio;
    struct KeyMap km;

    /*
     * Note: -1 specification for unit # means that we are not openning
     * a real console.	We can only execute a CD_ASKDEFAULTKEYMAP through
     * it.
     */

    if (!OpenDevice("console.device", -1, &cio, 0)) {
	cio.io_Command = CD_ASKDEFAULTKEYMAP;
	cio.io_Data = (APTR)&km;
	cio.io_Length = sizeof(km);
	DoIO(&cio);
	loadhilo(km.km_LoKeyMapTypes, km.km_LoKeyMap, km.km_LoCapsable, 0, 0x40, 0x00);
	loadhilo(km.km_HiKeyMapTypes, km.km_HiKeyMap, km.km_HiCapsable, 0, 0x10, 0x40);
	CloseDevice(&cio);
    } else {
	if (Output())
	    puts ("Unable to get console keymap");
    }
}


/*
 *  Decode plain and shifted keys only.  Ignore strings larger than
 *  a single character (thus things like the cursor keys do not get
 *  mapped)
 */

loadhilo(types, map, caps, is, ie, ia)
u_char *types;
u_char *caps;
long *map;
{
    register long n;
    register int idx;
    register u_char *ptr;
    u_char c;

    for (; is < ie; ++is) {
	n = map[is];
	if (n && (types[is] & 0x60)) {	    /*	STRING 0x40 or BUG 0x20 */
	    ptr = (u_char *)n;
	    n = 0;
	    if (ptr[0] == 0)
		n = ptr[1];
	    if (ptr[0] == 1)
		n = ptr[ptr[1]];
	    if (types[is] & KCF_SHIFT) {
		if (ptr[2] == 0)
		    n |= ptr[3] << 8;
		if (ptr[2] == 1)
		    n |= ptr[ptr[3]] << 8;
	    }
	}
	idx = is + ia;
	c = n;
	ctoa[idx] = c;
	cstoa[idx] = (n>>8) & 0xFF;
	if (caps[is>>3] & (1 << (is&7)))
	    XBITSET(isalpha,idx);
	if (c >= 32 && c != 0x7F && ctoa[idx])
	    XBITSET(isascii,idx);
    }
}


returnoveride(n)
{
    HASH *hash;
    static u_char *str;
    static int stat;

    for (hash = Hash[0x44 % HASHSIZE]; hash; hash = hash->next) {
	if (hash->code == 0x44 && hash->qual == 0) {
	    if (n) {
		str = (u_char *)hash->str;
		stat= hash->stat;
		hash->str = "return";
		hash->stat = 1;
	    } else {
		if (str == NULL) {
		    remhash(0x44, -1, 0);
		} else {
		    hash->str = (char *)str;
		    hash->stat= stat;
		}
	    }
	    return(0);
	}
    }
    if (n) {
	addhash(0x44, 1, 0xFF, 0, "return");
	str = NULL;
    }
}



addhash(code, stat, mask, qual, str)
u_char code, stat, mask, qual;
u_char *str;
{
    register HASH **p, *hash;

    hash = *(p = &Hash[code % HASHSIZE]);
    while (hash) {
	if (hash->code == code && hash->qual == qual && hash->mask == mask) {
	    if (!hash->stat)
		FreeMem(hash->str, strlen(hash->str)+1);
	    goto newstr;
	}
	hash = *(p = &hash->next);
    }
    *p = hash = (HASH *)AllocMem(sizeof(HASH), 0);
    hash->next = NULL;
newstr:
    hash->code = code;
    hash->stat = stat;
    hash->mask = mask;
    hash->qual = qual;
    hash->str = (char *)str;
    if (!stat)			/* if not static */
	hash->str = (char *)strcpy(AllocMem(strlen(str)+1, 0), str);
}


remhash(code, mask, qual)
u_char code, mask, qual;
{
    register HASH *hash, **p;

    hash = *(p = &Hash[code % HASHSIZE]);
    while (hash) {
	if (hash->code == code && hash->qual == qual && hash->mask == mask) {
	    if (!hash->stat)
		FreeMem(hash->str, strlen(hash->str)+1);
	    *p = hash->next;
	    FreeMem(hash, sizeof(HASH));
	    return(1);
	}
	hash = *(p = &hash->next);
    }
    return(0);
}


keyctl(code, qual)
register USHORT qual;
{
    register u_char c, c2;
    register HASH *hash;

    code &= 0xFF;

    if ((code & 0x78) == 0x60)	    /*	forget qualifier keys	*/
	return(0);
    if (code & 0x80)		    /*	forget upstrokes	*/
	return(0);

    c2 = 0;
    if (qual & (IEQUALIFIER_LSHIFT|IEQUALIFIER_RSHIFT))
	c2 |= QUAL_SHIFT;
    if (qual & (IEQUALIFIER_CONTROL))
	c2 |= QUAL_CTRL;
    if (qual & (IEQUALIFIER_LCOMMAND|IEQUALIFIER_RCOMMAND))
	c2 |= QUAL_AMIGA;
    if (qual & (IEQUALIFIER_LALT|IEQUALIFIER_RALT))
	c2 |= QUAL_ALT;
    if ((qual & IEQUALIFIER_CAPSLOCK) && (code <= 0x37) && XBITTEST(isalpha,code))
	c2 |= QUAL_SHIFT;
    if (qual & IEQUALIFIER_LEFTBUTTON)
	c2 |= QUAL_LMB;
    if (qual & IEQUALIFIER_MIDBUTTON)
	c2 |= QUAL_MMB;
    if (qual & (IEQUALIFIER_RBUTTON))
	c2 |= QUAL_RMB;
    for (hash = Hash[code % HASHSIZE]; hash; hash = hash->next) {
	if (hash->code == code) {
	    if ((c2 & hash->mask) == hash->qual)
		break;
	}
    }

    /*
     *	Use hash entry only if not in command line mode, or if the
     *	entry does not correspond to an alpha key.
     */

    if (hash) {
	char buf[256];
	/*printf ("c2 %lx BIT: %lx\n", c2, XBITTEST(isascii,code));*/
	if (c2 || !ComLineMode || !XBITTEST(isascii,code)) {
	    strcpy(buf, hash->str);
	    do_command(buf);
	    return(0);
	}
    }

    if (code < 0x50) {
	c = (c2 & QUAL_SHIFT) ? cstoa[code] : ctoa[code];
	if (c2 & QUAL_CTRL)
	    c &= 0x1F;
	if (c && (c2 & QUAL_ALT))
	    c |= 0x80;
	if (c && (c2 & QUAL_AMIGA))
	    c |= 0xC0;
	if (c) {
	    u_char buf[3];
	    buf[0] = '\'';
	    buf[1] = c;
	    buf[2] = 0;
	    do_command(buf);
	}
    }
}

#define LN(a,b,c,d)  ((a<<24)|(b<<16)|(c<<8)|d)

long lname[] = {
    LN('e','s','c',0x45), LN('f','1', 0 ,0x50), LN('f','2', 0 ,0x51),
    LN('f','3', 0 ,0x52), LN('f','4', 0 ,0x53), LN('f','5', 0 ,0x54),
    LN('f','6', 0 ,0x55), LN('f','7', 0 ,0x56), LN('f','8', 0 ,0x57),
    LN('f','9', 0 ,0x58), LN('f','1','0',0x59), LN('d','e','l',0x46),
    LN('b','a','c',0x41), LN('b','s', 0 ,0x41), LN('t','a','b',0x42),
    LN('h','e','l',0x5F), LN('r','e','t',0x44), LN('u','p', 0 ,0x4C),
    LN('d','o','w',0x4D), LN('r','i','g',0x4E), LN('l','e','f',0x4F),
    LN('e','n','t',0x43), LN('n','k','-',0x4A), LN('n','k','.',0x3C),
    LN('n','k','0',0x0F),
    LN('n','k','1',0x1D), LN('n','k','2',0x1E), LN('n','k','3',0x1F),
    LN('n','k','4',0x2D), LN('n','k','5',0x2E), LN('n','k','6',0x2F),
    LN('n','k','7',0x3D), LN('n','k','8',0x3E), LN('n','k','9',0x3F),
    LN('l','m','b',0x68), LN('m','m','b',0x6A), LN('r','m','b',0x69),
    LN('m','m','o',QMOVE),
    0
};


char *
keyspectomacro(str)
char *str;
{
    HASH *hash;
    u_char code, qual;

    if (get_codequal(str, &code, &qual)) {
	for (hash = Hash[code % HASHSIZE]; hash; hash = hash->next) {
	    if (hash->code == code) {
		if (hash->qual == (qual & hash->mask))
		    return(hash->str);
	    }
	}
    }
    title ("Bad command or unmapped key");
    return(NULL);
}


get_codequal(str, pcode, pqual)
u_char *pcode, *pqual;
u_char *str;
{
    u_char qual;
    register short i;

    qual = 0;
    if (strlen(str) > 1) {
	for (; *str && *str != '-'; ++str) {
	    if (*str == 's')
		qual |= QUAL_SHIFT;
	    if (*str == 'c')
		qual |= QUAL_CTRL;
	    if (*str == 'a')
		qual |= QUAL_ALT;
	    if (*str == 'A')
		qual |= QUAL_AMIGA;
	    if (*str == 'L')
		qual |= QUAL_LMB;
	    if (*str == 'M')
		qual |= QUAL_MMB;
	    if (*str == 'R')
		qual |= QUAL_RMB;
	    if (!qual)
		goto notqual;
	}
	if (*str)
	    ++str;
    }
notqual:
    *pqual = qual;
    if (strlen(str) != 1) {	      /* long name   */
	register short shift = 24;
	register long mult = 0;

	while (*str && shift >= 8) {
	    if (*str >= 'A' && *str <= 'Z')
		*str = *str - 'A' + 'a';
	    mult |= *str << shift;
	    shift -= 8;
	    ++str;
	}
	for (i = 0; lname[i]; ++i) {
	    if (mult == (lname[i] & 0xFFFFFF00)) {
		*pcode = lname[i] & 0x7F;
		return(1);
	    }
	}
    } else {			     /* short name  */
	for (i = 0; i < sizeof(ctoa); ++i) {
	    if (*str == ctoa[i]) {
		*pcode = i;
		return(1);
	    }
	}
	for (i = 0; i < sizeof(cstoa); ++i) {
	    if (*str == cstoa[i]) {
		*pcode = i;
		*pqual |= QUAL_SHIFT;
		return(1);
	    }
	}
    }
    return(0);
}

u_char *
cqtoa(code, qual)
{
    static u_char buf[32];
    register u_char *ptr = buf;
    register int i;

    if (qual & QUAL_SHIFT)
	*ptr++ = 's';
    if (qual & QUAL_CTRL)
	*ptr++ = 'c';
    if (qual & QUAL_ALT)
	*ptr++ = 'a';
    if (qual & QUAL_AMIGA)
	*ptr++ = 'A';
    if (qual & QUAL_LMB)
	*ptr++ = 'L';
    if (qual & QUAL_MMB)
	*ptr++ = 'M';
    if (qual & QUAL_RMB)
	*ptr++ = 'R';
    if (qual)
	*ptr++ = '-';
    for (i = 0; i < sizeof(lname)/sizeof(lname[0]); ++i) {
	if ((lname[i]&0xFF) == code) {
	    *ptr++ = (lname[i]>>24);
	    *ptr++ = (lname[i]>>16);
	    *ptr++ = (lname[i]>>8);
	    break;
	}
    }
    if (i == sizeof(lname)/sizeof(lname[0]))
	*ptr++ = ctoa[code];
    *ptr++ = 0;
    return(buf);
}


do_map()
{
    u_char code, qual;

    if (get_codequal(av[1], &code, &qual)) {
	addhash(code, 0, 0xFF, qual, av[2]);
    } else {
	title("Unknown Key");
    }
}

do_unmap()	  /* key   */
{
    u_char code, qual;

    if (get_codequal(av[1], &code, &qual)) {
	remhash(code, -1, qual);
    } else {
	title("Unknown Command");
    }
}

do_clearmap()
{
    resethash();
}

/*
 * SAVEMAP  file
 * SAVESMAP file
 */

do_savemap()
{
    char sysalso;
    char err = 0;
    u_char buf[256];
    long fi;
    register int i;
    register HASH *hash;

    fi = xopen(av[1], "w", 512);
    if (fi) {
	sysalso = av[0][4] == 's';
	for (i = 0; i < HASHSIZE; ++i) {
	    for (hash = Hash[i]; hash; hash = hash->next) {
		if (hash->stat == 0 || sysalso) {
		    sprintf(buf, "map `%s' `%s'", cqtoa(hash->code, hash->qual), hash->str);
		    xputs(fi, buf);
		}
	    }
	}
	xclose(fi);
	if (err)
	    title ("Unable to Write");
	else
	    title ("OK");
    } else {
	title("Unable to open file");
    }
}


SHAR_EOF
cat << \SHAR_EOF > subs.c

/*
 *  SUBS.C
 *
 *	(C)Copyright 1987 by Matthew Dillon, All Rights Reserved
 *
 *
 *  Subroutines.  Mainly workbench support stuff
 */


#include "defs.h"

makemygadget(gad)
register struct Gadget *gad;
{
    static unsigned long ga[] = {
	0x00000000,	/* 32 pixels across */
	0x00FDCBFD,
	0xFFFDDFFD,
	0x00000000,
	0x00DFDDDF,
	0x00000000,
	0xBC0EF00B,
	0x00000000,
	0xBFC00CDC,
	0x00000000,
	0xA00DF00F,
	0x00000000,
	0x00000000,

	0x00000000,
	0x00FDCBFD,
	0xFFFDDFFD,
	0x00000000,
	0x00DFDDDF,
	0x00000000,
	0xBC0EF00B,
	0x00000000,
	0xBFC00CDC,
	0x00000000,
	0xA00DF00F,
	0x00000000,
	0x00000000
    };
    static struct Image image = {
	0, 0, 20, sizeof(ga)/4/2, 2, (APTR)ga, 3, 0, NULL
    };
    bzero(gad, sizeof(struct Gadget));
    gad->Width = 20;
    gad->Height = sizeof(ga)/4/2 + 1;
    gad->Flags	= GADGIMAGE|GADGHCOMP;
    gad->GadgetType   = BOOLGADGET;
    gad->Activation = RELVERIFY|GADGIMMEDIATE;
    gad->GadgetRender = (APTR)ℑ
}

/*
 * return index of first non space.  Returns 255 if no spaces found.
 */

firstns(str)
register char *str;
{
    register short i;

    for (i = 0; str[i] && str[i] == ' '; ++i);
    if (str[i] == 0)
	i = 0;
    return(i);
}

lastns(str)
register char *str;
{
    register short i;

    for (i = strlen(str) - 1; i > 0 && str[i] == ' '; --i);
    if (i < 0)
	i = 0;
    return(i);
}

wordlen(str)
register char *str;
{
    register short i;

    for (i = 0; *str && *str != ' '; ++i, ++str);
    return(i);
}

/*
 *  Find the path from some root device to a specific filename (src), and
 *  stick the result in (dest).  If unable to backtrace along directories,
 *  simply copy (src) into (dest)
 *
 *  Returns (1) if able to backtrace, (0) if not.
 */

getpath(src, dest)
char *src, *dest;
{
    register long flock, pflock;
    register short len, total;
    register FIB *fib = (FIB *)malloc(sizeof(FIB));
    char c;

    dest[0] = 0;
    total = 1;
    flock = Lock(src, ACCESS_READ);
    if (flock == NULL) {			   /* missing file?    */
	for (len = strlen(src); len >= 0; --len) {
	    if (src[len] == '/') {
		--len;
		break;
	    }
	    if (src[len] == ':')
		break;
	}
	if (c = src[len + 1]) {
	    strcpy(dest, src+len+2);
	    total = strlen(dest)+1;
	}
	src[len + 1] = 0;
	flock = Lock(src, ACCESS_READ);
	src[len + 1] = c;
    }
    if (flock) {
	do {
	    pflock = ParentDir(flock);
	    if (Examine(flock, fib) == 0) {
		puts ("Examine failed");
		fib->fib_FileName[0] = 0;
	    }
	    if (fib->fib_FileName[0] == 0)
		strcpy(fib->fib_FileName, "ram");
	    len = strlen(fib->fib_FileName);
	    bmov(dest, dest + len + 1, total);
	    dest[len] = (pflock) ? '/' : ':';
	    bmov(fib->fib_FileName, dest, len);
	    total += len + 1;
	    UnLock(flock);
	    flock = pflock;
	} while(pflock);
	len = strlen(dest) - 1;
	if (dest[len] == '/')
	    dest[len] = 0;
	return(1);
    }
    strcpy(dest, src);
    return(0);
}



SHAR_EOF
cat << \SHAR_EOF > text2.c

/*
 * TEXT2.C
 *
 *	(C)Copyright 1987 by Matthew Dillon, All Rights Reserved
 */

#include "defs.h"

#define TU	    titleupdate = 1
#define nomemory()  {memoryfail = 1; TU;}

do_remeol()
{
    Current[Clen = E.Column] = 0;
    text_sync();
    text_redisplaycurrline();
}

do_wleft()
{
    register u_char *ptr;
    register int i;

    for (;;) {
	i = E.Column;
	if (i == 0)
	    goto prevline;
	--i;
	while (i && Current[i] == ' ')
	    --i;
	if (i == 0 && Current[0] == ' ') {
prevline:
	    if (ComLineMode || E.Line == 0) {
		i = E.Column;
		break;
	    }
	    text_sync();
	    --E.Line;
	    text_load();
	    E.Column = Clen;
	    continue;
	}
	while (i && Current[i] != ' ')
	    --i;
	if (Current[i] == ' ')
	    ++i;
	break;
    }
    E.Column = i;
    text_sync();
}


do_wright()
{
    register u_char *ptr;
    register int i;

    for (;;) {
	i = E.Column;
	if (i == Clen)
	    goto nextline;
	while (i != Clen && Current[i] != ' ')  /* skip past current word */
	    ++i;
	while (i != Clen && Current[i] == ' ')  /* to beg. of next word   */
	    ++i;
	if (i == Clen) {
nextline:
	    if (ComLineMode || E.Line == E.Lines - 1) {
		i = E.Column;
		break;
	    }
	    text_sync();
	    ++E.Line;
	    text_load();
	    E.Column = i = 0;
	    if (Current[0] != ' ')
		break;
	    continue;
	}
	break;
    }
    E.Column = i;
    text_sync();
}


do_split()		/* split line in two at cursor pos */
{
    u_char buf[256];

    strcpy(buf, Current+E.Column);
    Current[Clen = E.Column] = '\0';
    text_sync();
    SetAPen(Rp, 0);
    if (Nsu == 0)
	RectFill(Rp, COL(0), ROW(E.Line-E.Topline), Xbase+Xpixs, ROW(E.Line-E.Topline+1)-1);
    SetAPen(Rp, 1);
    text_displayseg(E.Line - E.Topline, 1);
    do_downadd();
    do_insline();
    strcpy(Current, buf);
    Clen = strlen(Current);
    text_sync();
    text_displayseg(E.Line - E.Topline, 1);
    do_up();
}

do_join()
{
    register int i = Clen, j;

    if (E.Line + 1 < E.Lines && strlen(E.List[E.Line+1])+i <= 253) {
	if (i && Current[i-1] != ' ')
	    Current[i++] = ' ';
	strcpy(Current+i, E.List[E.Line+1]);
	for (j = i; Current[j] == ' '; ++j);
	for (; i >= 0 && Current[i] == ' '; --i);
	if (j > i+2)
	    bmov(Current+j, Current+i+2, strlen(Current+j)+1);
	Clen = strlen(Current);
	text_sync();
	text_displayseg(E.Line - E.Topline, 1);
	do_down();
	do_deline();
	do_up();
	return(1);
    }
    return(0);
}

do_margin()
{
    E.Margin = atoi(av[1]);
}

do_wordwrap()
{
    if (av[1][1] == 'n')
	E.Wordwrap = 1;
    if (av[1][1] == 'f')
	E.Wordwrap = 0;
    if (av[1][0] == 't')
	E.Wordwrap = 1 - E.Wordwrap;
    if (E.Wordwrap)
	title("Wordwrap ON");
    else
	title("Wordwrap OFF");
}

/*
 * n == -1  :	force reformat entire paragraph
 * n ==  0  :	only until line equalizes (from text_write())
 *
 * What is a paragraph?   A paragraph ends whenever the left justification
 * gets larger, or on a blank line.
 */

do_reformat(n)
{
    register char *str;
    int nlok, lnsc, fnst, fnsc;
    int column = E.Column;
    int srow   = E.Line;
    int crow   = srow;
    int erow   = srow;
    short dins = 0;	    /* relative insert lines/delete lines   */
    char moded = 0;	    /* any modifications done at all?	    */
    char checked = 0;	    /* for cursor positioning.		    */

    if (E.Margin == 0)
	E.Margin = 75;

    ++Nsu;
    for (;;) {
	str = (char *)E.List[E.Line+1];
	fnst = 0;
	fnsc = firstns(Current);
	nlok = (E.Line + 1 < E.Lines && fnsc >= (fnst=firstns(str)));
	if (nlok && str[0] == 0)
	    nlok = 0;
	lnsc = lastns(Current);
	if (lnsc < E.Margin) {	  /* space at end of line for marg-lnsc-2 letter word	*/
	    if (nlok == 0)	  /* but no more data to joinup   */
		break;		  /* done */
	    if (E.Margin - lnsc - 2 >= wordlen(str+fnst)) {
		E.Column = 0;
		Clen = lastns(Current);
		if (Current[Clen])
		    ++Clen;
		moded = 1;
		--dins;
		if (do_join())
		    continue;
		++dins;
		title("Error, Margin > 124");
		break;
	    }
	    if (n == 0)        /* if couldn't mod line, and text_write, don't update any more */
		break;
	    do_down();
	    erow = E.Line;
	    continue;
	}
				/* no space, need to split	*/
				/* find start of prev word	*/
	for (;;) {
	    register int i = lnsc;
	    while (i && Current[i] != ' ')
		--i;
	    lnsc = i;
	    if (i >= E.Margin) {
		while (i && Current[i] == ' ')
		    --i;
		if (i < E.Margin)
		    break;
		lnsc = i;
		continue;
	    }
	    break;
	}
	if (lnsc) {		/* ok to split at word		*/
	    ++lnsc;
	    ++dins;
	    E.Column = lnsc;
	    do_split(); /* Split at point LNSC		*/
	    do_down();		/* must insert proper amount?	*/
	    {
		int indent = (nlok == 0) ? fnsc : fnst;
		if (!checked) {
		    checked = 1;
		    if (lnsc <= column) {   /* if split before cursor	*/
			column = column - E.Column + indent;
			++crow;
		    }
		}
		if (Clen + indent < 253) {
		    bmov(Current, Current + indent, strlen(Current)+1);
		    bset(Current, indent, ' ');
		    Clen += indent;
		}
	    }
	    erow = E.Line;
	    continue;
	}
	if (n == 0)
	    break;
	do_down();
    }
    if (column < 0 || column > 200) {
	printf ("Col failure: %ld\n", column);
	column = 0;
    }
    if (srow >= E.Lines) {
	srow = E.Lines - 1;
	goto ra;
    }
    if (dins || srow < E.Topline || srow >= E.Topline + Rows) {
ra:
	text_sync();
	--Nsu;
	E.Line = crow;
	E.Column = column;
	text_load();
	if (!text_sync())
	    text_redisplay();
    } else {
	text_sync();
	--Nsu;
	E.Line = crow;
	E.Column = column;
	text_load();
	if (erow != srow) {
	    if (!text_sync()) {
		++erow;
		if (erow - E.Topline > Rows)
		    erow = E.Topline + Rows;
		SetAPen(Rp, 0);
		RectFill(Rp, COL(0), ROW(srow - E.Topline), Xbase+Xpixs, ROW(erow - E.Topline)-1);
		SetAPen(Rp, 1);
		text_displayseg(srow - E.Topline, erow - srow);
	    }
	} else {
	    text_sync();
	    if (moded)
		text_redisplaycurrline();
	}
    }
    if (column > Clen) {
	bset(Current+Clen, column - Clen, ' ');
	Current[column] = 0;
    }
    E.Column = column;
}


do_tabstop()
{
    E.Tabstop = atoi(av[1]);
}


do_insertmode()
{
    if (av[1][0]) {
	switch(av[1][1] & 0x1F) {
	case 'n'&0x1F:
	    E.Insertmode = 1;
	    break;
	case 'f'&0x1F:
	    E.Insertmode = 0;
	    break;
	case 'o'&0x1F:
	    E.Insertmode = 1 - E.Insertmode;
	    break;
	}
	if (E.Insertmode)
	    title("Insert mode on");
	else
	    title("Insert mode off");
    }
}

do_insline()
{
    register u_char *ptr;

    TU;
    E.Modified = 1;
    text_sync();
    if (makeroom(32) && (ptr = MAllocate(1))) {
	bmov(E.List+E.Line, E.List+E.Line+1, sizeof(char *) * (E.Lines-E.Line));
	E.List[E.Line] = ptr;
	*ptr = 0;
	++E.Lines;
	if (E.Line < E.BSline)
	    ++E.BSline;
	if (E.Line <= E.BEline)
	    ++E.BEline;
    } else {
	nomemory();
    }
    text_load();
    if (Nsu == 0)
	ScrollRaster(Rp,0,-Ysize, COL(0), ROW(E.Line-E.Topline), COL(Columns)-1, ROW(Rows)-1);
    text_displayseg(E.Line - E.Topline, 1);
}

do_deline()
{
    int delline;

    if (E.Lines > 1) {
	TU;
	E.Modified = 1;
	text_sync();
	FreeMem(E.List[E.Line], strlen(E.List[E.Line])+1);
	bmov(E.List+E.Line+1, E.List+E.Line, sizeof(char *) * (E.Lines-E.Line-1));
	if (E.Line < E.BSline)
	    --E.BSline;
	if (E.Line <= E.BEline)
	    --E.BEline;
	delline = E.Line;
	if (E.Line >= --E.Lines) {
	    --E.Line;
	    text_load();
	    if (E.Line < E.Topline) {
		if (Nsu == 0) {
		    E.Topline = E.Line - (Rows>>1);
		    if (E.Topline < 0)
			E.Topline = 0;
		    text_redisplay();
		}
		return(0);
	    }
	}
	text_load();
	if (Nsu == 0)
	    ScrollRaster(Rp,0,Ysize, COL(0), ROW(delline-E.Topline), COL(Columns)-1, ROW(Rows)-1);
	text_displayseg(Rows-1, 1);
    } else {
	do_firstcolumn();
	do_remeol();
	E.Modified = 0;
    }
}

do_edit()
{
    long fi;
    long oldlock;
    long lines;
    u_char buf[256];
    u_char ebuf[256];
    u_char *ptr;
    char failed = 1;
    short iwiny;

    TU;
    text_sync();
    if (*av[0] == 'n') {        /* newfile or insfile   */
	if (E.Modified && getyn("Delete modified Image?") == 0)
	    return(0);
	iwiny = E.IWiny;
	text_uninit();
	text_init();
	E.IWiny = iwiny;
	E.Modified = 0;
	E.Line = E.Topline = 0;
	strncpy(E.Name, av[1], 63);
    } else {
	E.Modified = 1;
    }
    lines = E.Lines;
    if (Wbs && Wdisable == 0)
	oldlock = CurrentDir(E.dirlock);
    if (fi = xopen(av[1], "r", 4096)) {
	register int i, j;
	char oktitle = 1;

	title("Loading...");
	while (xgets(fi, buf, 255)) {
	    failed = 0;
	    for(i = j = 0; buf[i] && j < 254; ++i) {
		if (buf[i] == 9) {		    /* expand tabs (always 8)	*/
		    do {
			ebuf[j++] = ' ';
		    } while ((j % 8) && j < 254);
		} else {
		    ebuf[j++] = buf[i];
		}
	    }
	    while (j && ebuf[j-1] == ' ')
		--j;
	    ebuf[j] = 0;
	    if (makeroom(256) && (ptr = MAllocate(j+1))) {
		E.List[E.Lines++] = ptr;
		bmov(ebuf, ptr, j+1);
	    } else {
		nomemory();
		oktitle = 0;
		break;
	    }
	}
	if (oktitle)
	    title("OK");
    } else {
	title("File Not Found");
    }
    xclose(fi);
    if (Wbs && Wdisable == 0)
	CurrentDir(oldlock);
    if (E.Lines != 1 && lines == 1 && E.List[0][0] == 0) {
	E.Modified = 0;
	E.Line = 0;
	FreeMem(E.List[0], strlen(E.List[0])+1);
	bmov(E.List+1, E.List, sizeof(char *) * (--E.Lines));
    } else {
	if (!failed && lines <= E.Lines - 1) {
	    E.BSline = lines;
	    E.BEline = E.Lines-1;
	    do_bmove();
	}
    }
    text_load();
    text_redisplay();
}

static char blockmode;

do_bsave()
{
    blockmode = 1;
    do_saveas();
}

do_save()
{
    av[1] = E.Name;
    do_saveas();
}

do_savetabs()
{
    Savetabs = (av[1][0] && av[1][1] == 'n') ? 1 : 0;
}

do_saveas()
{
    long fi;
    long oldlock;
    register long i;
    register short j, k;
    register u_char *ptr, *bp;
    long xs, xe;
    u_char buf[256];
    char bm;

    bm = blockmode;
    if (blockmode && blockok()) {
	xs = E.BSline;
	xe = E.BEline + 1;
    } else {
	xs = 0;
	xe = E.Lines;
    }
    blockmode = 0;
    text_sync();
    if (Wbs && Wdisable == 0) {     /* Write out .info file */
	DISKOBJ sdo, *d;
	bzero(&sdo, sizeof(sdo));
	oldlock = CurrentDir(E.dirlock);
	if ((d = GetDiskObject(av[1])) == NULL) {
	    if (getpath(Wbs->sm_ArgList[0].wa_Name, buf)) {
		sdo.do_Magic = WB_DISKMAGIC;
		sdo.do_Version = WB_DISKVERSION;
		makemygadget(&sdo.do_Gadget);
		sdo.do_Type = WBPROJECT;
		sdo.do_DefaultTool = buf;
		sdo.do_ToolTypes = NULL;
		sdo.do_CurrentX = NO_ICON_POSITION;
		sdo.do_CurrentY = NO_ICON_POSITION;
		sdo.do_DrawerData = NULL;
		sdo.do_ToolWindow = NULL;
		sdo.do_StackSize = 8192;
		PutDiskObject(av[1], &sdo);
	    }
	} else {
	    FreeDiskObject(d);
	}
    }
    if (fi = xopen(av[1], "w", 4096)) {
	xasync(fi, 1);
	title("Saving...");
	for (i = xs; i < xe; ++i) {
	    ptr = E.List[i];
	    if (Savetabs) {
		for (bp = buf, j = 0; *ptr; ++ptr, ++bp, j = (j+1)&7) {
		    *bp = *ptr;
		    if (j == 7 && *bp == ' ' && *(bp-1) == ' ') {
			k = j;
			while (k-- >= 0 && *bp == ' ')
			    --bp;
			*++bp = 9;
		    } else {
			if (*bp == '\"' || *bp == '\'' || *bp == '\`')
			    break;
		    }
		}
		strcpy(bp, ptr);
		ptr = buf;
	    }
	    if (xwrite(fi, ptr, strlen(ptr)) == 0 || xwrite(fi, "\n", 1) == 0) {
		xclose(fi);
		goto err;
	    }
	}
	if (xclose(fi) == 0) {
err:	    Abortcommand = 1;
	    title("WRITE FAILED!");
	} else {
	    E.Modified &= bm;
	    title("OK");
	}
	if (Wbs && Wdisable == 0)
	    CurrentDir(oldlock);
    } else {
	title("Unable to open write file");
	Abortcommand = 1;
    }
}


do_block()	    /* block, unblock	*/
{
    switch(av[0][0]) {
    case 'b':
	if (E.BSline < 0) {
	    E.BSline = E.Line;
	    title("Block Begin");
	} else {
	    if (E.BEline >= 0) {
		title("Block Already Marked");
		break;
	    }
	    title("Block End");
	    E.BEline = E.Line;
	    if (E.BSline > E.BEline) {
		E.BEline = E.BSline;
		E.BSline = E.Line;
	    }
	}
	break;
    case 'u':
	E.BSline = E.BEline = -1;
	title ("Block Unmarked");
	break;
    }
}

static
blockok()
{
    if (E.BSline >= 0 && E.BEline >= 0 && E.BSline <= E.BEline && E.BEline < E.Lines)
	return(1);
    E.BSline = E.BEline = -1;
    title("Block Not Specified");
    return(0);
}


do_bdelete()
{
    register long i, n;

    if (blockok()) {
	text_sync();
	n = E.BEline - E.BSline + 1;
	if (E.Line >= E.BSline && E.Line <= E.BEline)
	    E.Line = E.BSline;
	if (E.Line > E.BEline)
	    E.Line -= n;
	for (i = E.BSline; i < E.BEline; ++i)
	    FreeMem(E.List[i], strlen(E.List[i])+1);
	bmov(E.List+E.BEline+1,E.List+E.BSline,(E.Lines-E.BEline-1)*sizeof(E.List[0]));
	E.Lines -= n;
	E.Modified = 1;
	if (E.Line >= E.Lines)
	    E.Line = E.Lines - 1;
	if (E.Line < 0)
	    E.Line = 0;
	if (E.Lines == 0) {
	    text_uninit();
	    text_init();
	}
	TU;
	text_load();
	E.BSline = E.BEline = -1;
	if (!text_sync())
	    text_redisplay();
    }
}


do_bcopy()
{
    register u_char **list;
    register long lines, i;
    register ED *e;

    if (blockok()) {
	text_sync();
	lines = E.BEline - E.BSline + 1;
	list = (u_char **)MAllocate(sizeof(char *) * (E.Lines+lines));
	if (list) {
	    for (i = 0; i < lines; ++i) {
		list[E.Line + i] = MAllocate(strlen(E.List[E.BSline+i])+1);
		strcpy(list[E.Line + i], E.List[E.BSline+i]);
	    }
	    bmov(E.List+0, list, E.Line * sizeof(char *));
	    bmov(E.List+E.Line, list + E.Line + lines, (E.Lines-E.Line)*sizeof(char *));
	}
	FreeMem(E.List, E.Maxlines * 4);
	E.List = list;
	E.Lines += lines;
	E.Maxlines = E.Lines;
	text_load();
	E.BSline = E.BEline = -1;
	if (!text_sync())
	    text_redisplay();
    }
}


do_bmove()
{
    register long lines;
    register u_char **temp;

    if (blockok()) {
	if (E.Line >= E.BSline && E.Line <= E.BEline) {
	    title("Cannot Move into self");
	    return(0);
	}
	text_sync();
	lines = E.BEline - E.BSline + 1;
	temp = (u_char **)MAllocate(lines * sizeof(char *));
	bmov(E.List + E.BSline, temp, lines * sizeof(char *));
	if (E.Line > E.BSline) {
	    bmov(E.List+E.BEline+1, E.List+E.BSline, (E.Line-E.BEline-1)*4);
	    bmov(temp, E.List + E.Line - lines, lines * 4);
	} else {
	    bmov(E.List+E.Line, E.List+E.Line+lines, (E.BSline-E.Line)*4);
	    bmov(temp, E.List + E.Line, lines * 4);
	}
	FreeMem(temp, lines * sizeof(char *));
	E.BSline = E.BEline = -1;
	text_load();
	if (!text_sync())
	    text_redisplay();
    }
}


/*
 * IF condition trueaction, IFELSE condition trueaction falseaction
 *
 *  condition:	!condition NOT the specified condition.
 *		#	   toggle number is SET
 *		top	   top of file (on first line)
 *		bot	   end of file (on last line)
 *		left	   start of line (leftmost column)
 *		right	   end of line (nothing but spaces under and to the right)
 *		modified   text has been modified
 *		insert	   currently in insert mode
 *		y[<=>]#    cursor is (any OR combo of <,>,=) row #  (line numbers start at 1)
 *		x[<=>]#    cursor is (<,>,<=,>=,<>) column #	    (columns start at 1)
 *			    <> means 'not equal'
 *
 *		cl	   char under cursor is lower case
 *		cu	   char under cursor is upper case
 *		ca	   char under cursor is alpha
 *		cn	   char under cursor is numeric
 *		cb	   char within selected block
 *		c[<=>]#    char under cursor is (combo of <,>,and =) #
 */

do_if()
{
    char haselse = (av[0][2] == 'e');
    char iswhile = (av[0][0] == 'w');
    char istrue, notop = 0;
    char c, cx, cc;
    u_char *buf1, *buf2;
    register u_char *ptr;
    int i, cxn, cn;

    buf1 = (u_char *)malloc(256);
    buf2 = (u_char *)malloc(256);
    if (buf1 == NULL || buf2 == NULL) {
	if (buf1) free(buf1);
	if (buf2) free(buf2);
	title("No Memory!");
	return(0);
    }
    breakreset();
    ptr = av[1];
    if (*ptr == '!') {
	notop = 1;
	++ptr;
    }
    c = ptr[0];
    cn= atoi(ptr);
    cx= ptr[1];
    cxn=atoi(ptr+1);
    strcpy(buf1, av[2]);

loop:
    istrue = 0;
    i = 0;
    switch(c) {
    case 'x':
	i = E.Column + 1;
    case 'y':
	if (!i)
	    i = E.Line + 1;
conditional:
	{
	    register int j, n;
	    char any = 0;

	    for (j = 1; ptr[j] && (ptr[j]<'0'||ptr[j]>'9'); ++j);
	    n = atoi(ptr+j);
	    for (j = 1; ptr[j]; ++j) {
		switch(ptr[j]) {
		case '<':
		    any = 1;
		    if (i < n)
			istrue = 1;
		    break;
		case '=':
		    any = 1;
		    if (i == n)
			istrue = 1;
		    break;
		case '>':
		    any = 1;
		    if (i > n)
			istrue = 1;
		    break;
		}
	    }
	    if (!any && i == n)  /* default is equivalence   */
		istrue = 1;
	}
	break;
    case 't':
	istrue = E.Line == 0;
	break;
    case 'b':
	istrue = E.Line == E.Lines-1;
	break;
    case 'l':
	istrue = E.Column == 0;
	break;
    case 'r':
	istrue = E.Column == Clen;
	break;
    case 'm':
	text_sync();
	istrue = E.Modified != 0;
	break;
    case 'i':
	istrue = E.Insertmode != 0;
	break;
    case 'c':
	cc = Current[E.Column];
	switch(cx) {
	case 'b':
	    istrue = E.Line >= E.BSline && E.Line <= E.BEline;
	    break;
	case 'l':
	    istrue = cc >= 'a' && cc <= 'z';
	    break;
	case 'u':
	    istrue = cc >= 'A' && cc <= 'Z';
	    break;
	case 'a':
	    istrue = (cc>='a'&&cc<='z')||(cc>='A'&&cc<='Z')||(cc>='0'&&cc<='9');
	    break;
	case 'n':
	    istrue = (cc >= '0' && cc <= '9');
	    break;
	default:		/* c[<=>]#  */
	    i = Current[E.Column];
	    goto conditional;
	    break;
	}
	break;
    default:
	if (c >= '0' && c <= '9')
	    istrue = do_toggle(cn) != 0;
	else
	    title("bad conditional");
	break;
    }
    istrue ^= notop;
    if (istrue) {
	strcpy(buf2, buf1);	/* could be executed multiple times */
	if (do_command(buf2) == 0)
	    goto done;
	if (iswhile) {
	    if (breakcheck())
		Abortcommand = 1;
	    else
		goto loop;
	}
    } else {
	if (haselse) {		/* only executed once */
	    strcpy(buf2, av[3]);
	    do_command(buf2);
	}
    }
done:
    free(buf1);
    free(buf2);
}


/*
 * TOGGLE #, SETTOGGLE #, RESETTOGGLE #
 */

do_toggle(n)
{
    static char tg[MAXTOGGLE];
    int i;

    if (n >= 0) {
	if (n >= MAXTOGGLE)
	    return(0);
	return(tg[n]);
    }
    i = atoi(av[1]);
    if (i >= 0 && i < MAXTOGGLE) {
	switch(av[0][0]) {
	case 't':
	    tg[i] = !tg[i];
	    break;
	case 's':
	    tg[i] = 1;
	    break;
	case 'r':
	    tg[i] = 0;
	    break;
	}
    }
}


do_tlate()
{
    register u_char *ptr = av[1];
    register int n;
    char c = Current[E.Column];

    if (ptr[0] == '+')
	c += atoi(ptr+1);
    else
    if (ptr[0] == '-')
	c -= atoi(ptr+1);
    else
	c = atoi(ptr);
    if (c) {
	if (Current[E.Column] == 0)
	    Current[E.Column+1] = 0;
	Current[E.Column] = c;
	if (Nsu == 0) {
	    movetocursor();
	    Text(Rp, Current+E.Column, 1);
	}
    }
}

/*
 *  BSOURCE
 *
 *  note that since the start and end lines are loaded immediately and the
 *  block unblock'd before execution starts, you can theoretically have
 *  another BSOURCE as part of this BSOURCE (but be carefull!).
 */

do_bsource()
{
    u_char buf[256];
    register int i, sl, se;

    if (blockok()) {
	sl = E.BSline;
	se = E.BEline + 1;
	E.BSline = E.BEline = -1;

	for (i = sl; i < se && i < E.Lines; ++i) {
	    text_sync();	/* make sure we are using latest text */
	    strcpy(buf, E.List[i]);
	    if (do_command(buf) == 0)
		break;
	}
    }
}

movetocursor()
{
    Move(Rp, XTbase+(E.Column-E.Topcolumn)*Xsize, YTbase+(E.Line-E.Topline)*Ysize);
}

u_char *
MAllocate(bytes)
{
    return(AllocMem(bytes, MEMF_CLEAR|MEMF_PUBLIC));
}


makeroom(n)
{
    register u_char **Newlist;

    if (E.Lines >= E.Maxlines) {
	Newlist = (u_char **)MAllocate(sizeof(char *) * (E.Maxlines + n));
	if (Newlist) {
	    bmov(E.List, Newlist, sizeof(char *) * E.Maxlines);
	    FreeMem(E.List, sizeof(char *) * E.Maxlines);
	    E.List = Newlist;
	    E.Maxlines += n;
	    return(1);
	} else {
	    nomemory();
	}
	return(0);
    }
    return(1);
}


SHAR_EOF