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