/* * 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); }