implement Textm; include "common.m";include "keyboard.m"; sys : Sys;utils : Utils;framem : Framem;drawm : Draw;acme : Acme;graph : Graph;gui : Gui;dat : Dat;scrl : Scroll;bufferm : Bufferm;filem : Filem;columnm : Columnm;windowm : Windowm;exec : Exec; Dir, sprint : import sys;frgetmouse : import acme;min, warning, error, stralloc, strfree, isalnum : import utils;Frame, frinsert, frdelete, frptofchar, frcharofpt, frselect, frdrawsel, frdrawsel0, frtick : import framem;BUFSIZE, Astring, SZINT, TRUE, FALSE, XXX, Reffont, Dirlist,Scrollwid, Scrollgap, seq, mouse : import dat;EM_NORMAL, EM_RAW, EM_MASK : import dat;ALPHA_LATIN, ALPHA_GREEK, ALPHA_CYRILLIC: import Dat;BACK, TEXT, HIGH, HTEXT : import Framem;Flushon, Flushoff : import Draw;Point, Display, Rect, Image : import drawm;charwidth, bflush, draw : import graph;black, white, mainwin, display : import gui;Buffer : import bufferm;File : import filem;Column : import columnm;Window : import windowm;scrdraw : import scrl; cvlist: adt { ld: int; nm: string; si: string; so: string;}; # "@@", "'EKSTYZekstyz ", "ьЕКСТЫЗекстызъЁё", latintab := array[] of { cvlist( ALPHA_LATIN, "latin", nil, nil ), cvlist( ALPHA_GREEK, "greek", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", "ΑΒΞΔΕΦΓΘΙΪΚΛΜΝΟΠΨΡΣΤΥΫΩΧΗΖαβξδεφγθιϊκλμνοπψρστυϋωχηζ" ), cvlist( ALPHA_CYRILLIC, "cyrillic", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", "АБЧДЭФГШИЙХЛМНОПЕРЩЦУВЮХЯЖабчдэфгшийхлмноперщцувюхяж" ), cvlist(-1, nil, nil, nil)}; alphabet := ALPHA_LATIN; # per window perhaps setalphabet(s: string){ for(a := 0; latintab[a].ld != -1; a++){ k := latintab[a].ld; for(i := 0; latintab[i].ld != -1; i++){ if(s == transs(latintab[i].nm, k)){ alphabet = latintab[i].ld; return; } } }} transc(c: int, k: int): int{ for(i := 0; latintab[i].ld != -1; i++){ if(k == latintab[i].ld){ si := latintab[i].si; so := latintab[i].so; ln := len si; for(j := 0; j < ln; j++) if(c == si[j]) return so[j]; } } return c;} transs(s: string, k: int): string{ ln := len s; for(i := 0; i < ln; i++) s[i] = transc(s[i], k); return s;} init(mods : ref Dat->Mods){ sys = mods.sys; framem = mods.framem; dat = mods.dat; utils = mods.utils; drawm = mods.draw; acme = mods.acme; graph = mods.graph; gui = mods.gui; scrl = mods.scroll; bufferm = mods.bufferm; filem = mods.filem; columnm = mods.columnm; windowm = mods.windowm; exec = mods.exec;} TABDIR : con 3; # width of tabs in directory windows # remove eventuallyKF : con 16rF000;Kup : con KF | 16r0E;Kleft : con KF | 16r11;Kright : con KF | 16r12;Kdown : con 16r80; nulltext : Text; newtext() : ref Text{ t := ref nulltext; t.frame = framem->newframe(); return t;} Text.init(t : self ref Text, f : ref File, r : Rect, rf : ref Dat->Reffont, cols : array of ref Image){ t.file = f; t.all = r; t.scrollr = r; t.scrollr.max.x = r.min.x+Scrollwid; t.lastsr = dat->nullrect; r.min.x += Scrollwid+Scrollgap; t.eq0 = ~0; t.ncache = 0; t.reffont = rf; t.tabstop = dat->maxtab; for(i:=0; i<Framem->NCOL; i++) t.frame.cols[i] = cols[i]; t.redraw(r, rf.f, mainwin, -1);} Text.redraw(t : self ref Text, r : Rect, f : ref Draw->Font, b : ref Image, odx : int){ framem->frinit(t.frame, r, f, b, t.frame.cols); rr := t.frame.r; rr.min.x -= Scrollwid; # back fill to scroll bar draw(t.frame.b, rr, t.frame.cols[Framem->BACK], nil, (0, 0)); # use no wider than 3-space tabs in a directory maxt := dat->maxtab; if(t.what == Body){ if(t.w != nil && t.w.isdir) maxt = min(TABDIR, dat->maxtab); else maxt = t.tabstop; } t.frame.maxtab = maxt*charwidth(f, '0'); # c = '0'; # if(t.what==Body && t.w!=nil && t.w.isdir) # c = ' '; # t.frame.maxtab = Dat->Maxtab*charwidth(f, c); if(t.what==Body && t.w.isdir && odx!=t.all.dx()){ if(t.frame.maxlines > 0){ t.reset(); t.columnate(t.w.dlp, t.w.ndl); t.show(0, 0); } }else{ t.fill(); t.setselect(t.q0, t.q1); }} Text.reshape(t : self ref Text, r : Rect) : int{ odx : int; if(r.dy() > 0) r.max.y -= r.dy()%t.frame.font.height; else r.max.y = r.min.y; odx = t.all.dx(); t.all = r; t.scrollr = r; t.scrollr.max.x = r.min.x+Scrollwid; t.lastsr = dat->nullrect; r.min.x += Scrollwid+Scrollgap; framem->frclear(t.frame, 0); # t.redraw(r, t.frame.font, t.frame.b, odx); t.redraw(r, t.frame.font, mainwin, odx); return r.max.y;} Text.close(t : self ref Text){ t.cache = nil; framem->frclear(t.frame, 1); t.file.deltext(t); t.file = nil; t.reffont.close(); if(dat->argtext == t) dat->argtext = nil; if(dat->typetext == t) dat->typetext = nil; if(dat->seltext == t) dat->seltext = nil; if(dat->mousetext == t) dat->mousetext = nil; if(dat->barttext == t) dat->barttext = nil;} dircmp(da : ref Dirlist, db : ref Dirlist) : int{ if (da.r < db.r) return -1; if (da.r > db.r) return 1; return 0;} qsort(a : array of ref Dirlist, n : int){ i, j : int; t : ref Dirlist; while(n > 1) { i = n>>1; t = a[0]; a[0] = a[i]; a[i] = t; i = 0; j = n; for(;;) { do i++; while(i < n && dircmp(a[i], a[0]) < 0); do j--; while(j > 0 && dircmp(a[j], a[0]) > 0); if(j < i) break; t = a[i]; a[i] = a[j]; a[j] = t; } t = a[0]; a[0] = a[j]; a[j] = t; n = n-j-1; if(j >= n) { qsort(a, j); a = a[j+1:]; } else { qsort(a[j+1:], n); n = j; } }} Text.columnate(t : self ref Text, dlp : array of ref Dirlist, ndl : int){ i, j, w, colw, mint, maxt, ncol, nrow : int; dl : ref Dirlist; q1 : int; if(t.file.ntext > 1) return; mint = charwidth(t.frame.font, '0'); # go for narrower tabs if set more than 3 wide t.frame.maxtab = min(dat->maxtab, TABDIR)*mint; maxt = t.frame.maxtab; colw = 0; for(i=0; i<ndl; i++){ dl = dlp[i]; w = dl.wid; if(maxt-w%maxt < mint) w += mint; if(w % maxt) w += maxt-(w%maxt); if(w > colw) colw = w; } if(colw == 0) ncol = 1; else ncol = utils->max(1, t.frame.r.dx()/colw); nrow = (ndl+ncol-1)/ncol; q1 = 0; for(i=0; i<nrow; i++){ for(j=i; j<ndl; j+=nrow){ dl = dlp[j]; t.file.insert(q1, dl.r, len dl.r); q1 += len dl.r; if(j+nrow >= ndl) break; w = dl.wid; if(maxt-w%maxt < mint){ t.file.insert(q1, "\t", 1); q1++; w += mint; } do{ t.file.insert(q1, "\t", 1); q1++; w += maxt-(w%maxt); }while(w < colw); } t.file.insert(q1, "\n", 1); q1++; }} Text.loadx(t : self ref Text, q0 : int, file : string, setqid : int) : int{ rp : ref Astring; dl : ref Dirlist; dlp : array of ref Dirlist; i, n, ndl : int; fd : ref Sys->FD; q, q1 : int; d : Dir; u : ref Text; ok : int; if(t.ncache!=0 || t.file.buf.nc || t.w==nil || t!=t.w.body || (t.w.isdir && t.file.name==nil)) error("text.load"); { fd = sys->open(file, Sys->OREAD); if(fd == nil){ warning(nil, sprint("can't open %s: %r\n", file)); raise "e"; } (ok, d) = sys->fstat(fd); if(ok){ warning(nil, sprint("can't fstat %s: %r\n", file)); raise "e"; } if(d.qid.qtype & Sys->QTDIR){ # this is checked in get() but it's possible the file changed underfoot if(t.file.ntext > 1){ warning(nil, sprint("%s is a directory; can't read with multiple windows on it\n", file)); raise "e"; } t.w.isdir = TRUE; t.w.filemenu = FALSE; if(t.file.name[len t.file.name-1] != '/') t.w.setname(t.file.name + "/", len t.file.name+1); dlp = nil; ndl = 0; for(;;){ (nd, dbuf) := sys->dirread(fd); if(nd <= 0) break; for(i=0; i<nd; i++){ dl = ref Dirlist; dl.r = dbuf[i].name; if(dbuf[i].mode & Sys->DMDIR) dl.r = dl.r + "/"; dl.wid = graph->strwidth(t.frame.font, dl.r); ndl++; odlp := dlp; dlp = array[ndl] of ref Dirlist; dlp[0:] = odlp[0:ndl-1]; odlp = nil; dlp[ndl-1] = dl; } } qsort(dlp, ndl); t.w.dlp = dlp; t.w.ndl = ndl; t.columnate(dlp, ndl); q1 = t.file.buf.nc; }else{ tmp : int; t.w.isdir = FALSE; t.w.filemenu = TRUE; tmp = t.file.loadx(q0, fd); q1 = q0 + tmp; } fd = nil; if(setqid){ t.file.dev = d.dev; t.file.mtime = d.mtime; t.file.qidpath = d.qid.path; } rp = stralloc(BUFSIZE); for(q=q0; q<q1; q+=n){ n = q1-q; if(n > Dat->BUFSIZE) n = Dat->BUFSIZE; t.file.buf.read(q, rp, 0, n); if(q < t.org) t.org += n; else if(q <= t.org+t.frame.nchars) frinsert(t.frame, rp.s, n, q-t.org); if(t.frame.lastlinefull) break; } strfree(rp); rp = nil; for(i=0; i<t.file.ntext; i++){ u = t.file.text[i]; if(u != t){ if(u.org > u.file.buf.nc) # will be 0 because of reset(), but safety first u.org = 0; u.reshape(u.all); u.backnl(u.org, 0); # go to beginning of line } u.setselect(q0, q0); } return q1-q0; } exception{ * => fd = nil; return 0; } return 0;} Text.bsinsert(t : self ref Text, q0 : int, r : string, n : int, tofile : int) : (int, int){ tp : ref Astring; bp, up : int; i, initial : int; { if(t.what == Tag) # can't happen but safety first: mustn't backspace over file name raise "e"; bp = 0; for(i=0; i<n; i++) if(r[bp++] == '\b'){ --bp; initial = 0; tp = utils->stralloc(n); for (k := 0; k < i; k++) tp.s[k] = r[k]; up = i; for(; i<n; i++){ tp.s[up] = r[bp++]; if(tp.s[up] == '\b') if(up == 0) initial++; else --up; else up++; } if(initial){ if(initial > q0) initial = q0; q0 -= initial; t.delete(q0, q0+initial, tofile); } n = up; t.insert(q0, tp.s, n, tofile, 0); strfree(tp); tp = nil; return (q0, n); } raise "e"; return(0, 0); } exception{ * => t.insert(q0, r, n, tofile, 0); return (q0, n); } return (0, 0);} Text.insert(t : self ref Text, q0 : int, r : string, n : int, tofile : int, echomode : int){ c, i : int; u : ref Text; if(tofile && t.ncache != 0) error("text.insert"); if(n == 0) return; if(tofile){ t.file.insert(q0, r, n); if(t.what == Body){ t.w.dirty = TRUE;Lines 1–500 of 1404. Load more
implement Textm; include "common.m"; include "keyboard.m"; sys : Sys; utils : Utils; framem : Framem; drawm : Draw; acme : Acme; graph : Graph; gui : Gui; dat : Dat; scrl : Scroll; bufferm : Bufferm; filem : Filem; columnm : Columnm; windowm : Windowm; exec : Exec; Dir, sprint : import sys; frgetmouse : import acme; min, warning, error, stralloc, strfree, isalnum : import utils; Frame, frinsert, frdelete, frptofchar, frcharofpt, frselect, frdrawsel, frdrawsel0, frtick : import framem; BUFSIZE, Astring, SZINT, TRUE, FALSE, XXX, Reffont, Dirlist,Scrollwid, Scrollgap, seq, mouse : import dat; EM_NORMAL, EM_RAW, EM_MASK : import dat; ALPHA_LATIN, ALPHA_GREEK, ALPHA_CYRILLIC: import Dat; BACK, TEXT, HIGH, HTEXT : import Framem; Flushon, Flushoff : import Draw; Point, Display, Rect, Image : import drawm; charwidth, bflush, draw : import graph; black, white, mainwin, display : import gui; Buffer : import bufferm; File : import filem; Column : import columnm; Window : import windowm; scrdraw : import scrl; cvlist: adt { ld: int; nm: string; si: string; so: string; }; # "@@", "'EKSTYZekstyz ", "ьЕКСТЫЗекстызъЁё", latintab := array[] of { cvlist( ALPHA_LATIN, "latin", nil, nil ), cvlist( ALPHA_GREEK, "greek", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", "ΑΒΞΔΕΦΓΘΙΪΚΛΜΝΟΠΨΡΣΤΥΫΩΧΗΖαβξδεφγθιϊκλμνοπψρστυϋωχηζ" ), cvlist( ALPHA_CYRILLIC, "cyrillic", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", "АБЧДЭФГШИЙХЛМНОПЕРЩЦУВЮХЯЖабчдэфгшийхлмноперщцувюхяж" ), cvlist(-1, nil, nil, nil) }; alphabet := ALPHA_LATIN; # per window perhaps setalphabet(s: string) { for(a := 0; latintab[a].ld != -1; a++){ k := latintab[a].ld; for(i := 0; latintab[i].ld != -1; i++){ if(s == transs(latintab[i].nm, k)){ alphabet = latintab[i].ld; return; } } } } transc(c: int, k: int): int { for(i := 0; latintab[i].ld != -1; i++){ if(k == latintab[i].ld){ si := latintab[i].si; so := latintab[i].so; ln := len si; for(j := 0; j < ln; j++) if(c == si[j]) return so[j]; } } return c; } transs(s: string, k: int): string { ln := len s; for(i := 0; i < ln; i++) s[i] = transc(s[i], k); return s; } init(mods : ref Dat->Mods) { sys = mods.sys; framem = mods.framem; dat = mods.dat; utils = mods.utils; drawm = mods.draw; acme = mods.acme; graph = mods.graph; gui = mods.gui; scrl = mods.scroll; bufferm = mods.bufferm; filem = mods.filem; columnm = mods.columnm; windowm = mods.windowm; exec = mods.exec; } TABDIR : con 3; # width of tabs in directory windows # remove eventually KF : con 16rF000; Kup : con KF | 16r0E; Kleft : con KF | 16r11; Kright : con KF | 16r12; Kdown : con 16r80; nulltext : Text; newtext() : ref Text { t := ref nulltext; t.frame = framem->newframe(); return t; } Text.init(t : self ref Text, f : ref File, r : Rect, rf : ref Dat->Reffont, cols : array of ref Image) { t.file = f; t.all = r; t.scrollr = r; t.scrollr.max.x = r.min.x+Scrollwid; t.lastsr = dat->nullrect; r.min.x += Scrollwid+Scrollgap; t.eq0 = ~0; t.ncache = 0; t.reffont = rf; t.tabstop = dat->maxtab; for(i:=0; i<Framem->NCOL; i++) t.frame.cols[i] = cols[i]; t.redraw(r, rf.f, mainwin, -1); } Text.redraw(t : self ref Text, r : Rect, f : ref Draw->Font, b : ref Image, odx : int) { framem->frinit(t.frame, r, f, b, t.frame.cols); rr := t.frame.r; rr.min.x -= Scrollwid; # back fill to scroll bar draw(t.frame.b, rr, t.frame.cols[Framem->BACK], nil, (0, 0)); # use no wider than 3-space tabs in a directory maxt := dat->maxtab; if(t.what == Body){ if(t.w != nil && t.w.isdir) maxt = min(TABDIR, dat->maxtab); else maxt = t.tabstop; } t.frame.maxtab = maxt*charwidth(f, '0'); # c = '0'; # if(t.what==Body && t.w!=nil && t.w.isdir) # c = ' '; # t.frame.maxtab = Dat->Maxtab*charwidth(f, c); if(t.what==Body && t.w.isdir && odx!=t.all.dx()){ if(t.frame.maxlines > 0){ t.reset(); t.columnate(t.w.dlp, t.w.ndl); t.show(0, 0); } }else{ t.fill(); t.setselect(t.q0, t.q1); } } Text.reshape(t : self ref Text, r : Rect) : int { odx : int; if(r.dy() > 0) r.max.y -= r.dy()%t.frame.font.height; else r.max.y = r.min.y; odx = t.all.dx(); t.all = r; t.scrollr = r; t.scrollr.max.x = r.min.x+Scrollwid; t.lastsr = dat->nullrect; r.min.x += Scrollwid+Scrollgap; framem->frclear(t.frame, 0); # t.redraw(r, t.frame.font, t.frame.b, odx); t.redraw(r, t.frame.font, mainwin, odx); return r.max.y; } Text.close(t : self ref Text) { t.cache = nil; framem->frclear(t.frame, 1); t.file.deltext(t); t.file = nil; t.reffont.close(); if(dat->argtext == t) dat->argtext = nil; if(dat->typetext == t) dat->typetext = nil; if(dat->seltext == t) dat->seltext = nil; if(dat->mousetext == t) dat->mousetext = nil; if(dat->barttext == t) dat->barttext = nil; } dircmp(da : ref Dirlist, db : ref Dirlist) : int { if (da.r < db.r) return -1; if (da.r > db.r) return 1; return 0; } qsort(a : array of ref Dirlist, n : int) { i, j : int; t : ref Dirlist; while(n > 1) { i = n>>1; t = a[0]; a[0] = a[i]; a[i] = t; i = 0; j = n; for(;;) { do i++; while(i < n && dircmp(a[i], a[0]) < 0); do j--; while(j > 0 && dircmp(a[j], a[0]) > 0); if(j < i) break; t = a[i]; a[i] = a[j]; a[j] = t; } t = a[0]; a[0] = a[j]; a[j] = t; n = n-j-1; if(j >= n) { qsort(a, j); a = a[j+1:]; } else { qsort(a[j+1:], n); n = j; } } } Text.columnate(t : self ref Text, dlp : array of ref Dirlist, ndl : int) { i, j, w, colw, mint, maxt, ncol, nrow : int; dl : ref Dirlist; q1 : int; if(t.file.ntext > 1) return; mint = charwidth(t.frame.font, '0'); # go for narrower tabs if set more than 3 wide t.frame.maxtab = min(dat->maxtab, TABDIR)*mint; maxt = t.frame.maxtab; colw = 0; for(i=0; i<ndl; i++){ dl = dlp[i]; w = dl.wid; if(maxt-w%maxt < mint) w += mint; if(w % maxt) w += maxt-(w%maxt); if(w > colw) colw = w; } if(colw == 0) ncol = 1; else ncol = utils->max(1, t.frame.r.dx()/colw); nrow = (ndl+ncol-1)/ncol; q1 = 0; for(i=0; i<nrow; i++){ for(j=i; j<ndl; j+=nrow){ dl = dlp[j]; t.file.insert(q1, dl.r, len dl.r); q1 += len dl.r; if(j+nrow >= ndl) break; w = dl.wid; if(maxt-w%maxt < mint){ t.file.insert(q1, "\t", 1); q1++; w += mint; } do{ t.file.insert(q1, "\t", 1); q1++; w += maxt-(w%maxt); }while(w < colw); } t.file.insert(q1, "\n", 1); q1++; } } Text.loadx(t : self ref Text, q0 : int, file : string, setqid : int) : int { rp : ref Astring; dl : ref Dirlist; dlp : array of ref Dirlist; i, n, ndl : int; fd : ref Sys->FD; q, q1 : int; d : Dir; u : ref Text; ok : int; if(t.ncache!=0 || t.file.buf.nc || t.w==nil || t!=t.w.body || (t.w.isdir && t.file.name==nil)) error("text.load"); { fd = sys->open(file, Sys->OREAD); if(fd == nil){ warning(nil, sprint("can't open %s: %r\n", file)); raise "e"; } (ok, d) = sys->fstat(fd); if(ok){ warning(nil, sprint("can't fstat %s: %r\n", file)); raise "e"; } if(d.qid.qtype & Sys->QTDIR){ # this is checked in get() but it's possible the file changed underfoot if(t.file.ntext > 1){ warning(nil, sprint("%s is a directory; can't read with multiple windows on it\n", file)); raise "e"; } t.w.isdir = TRUE; t.w.filemenu = FALSE; if(t.file.name[len t.file.name-1] != '/') t.w.setname(t.file.name + "/", len t.file.name+1); dlp = nil; ndl = 0; for(;;){ (nd, dbuf) := sys->dirread(fd); if(nd <= 0) break; for(i=0; i<nd; i++){ dl = ref Dirlist; dl.r = dbuf[i].name; if(dbuf[i].mode & Sys->DMDIR) dl.r = dl.r + "/"; dl.wid = graph->strwidth(t.frame.font, dl.r); ndl++; odlp := dlp; dlp = array[ndl] of ref Dirlist; dlp[0:] = odlp[0:ndl-1]; odlp = nil; dlp[ndl-1] = dl; } } qsort(dlp, ndl); t.w.dlp = dlp; t.w.ndl = ndl; t.columnate(dlp, ndl); q1 = t.file.buf.nc; }else{ tmp : int; t.w.isdir = FALSE; t.w.filemenu = TRUE; tmp = t.file.loadx(q0, fd); q1 = q0 + tmp; } fd = nil; if(setqid){ t.file.dev = d.dev; t.file.mtime = d.mtime; t.file.qidpath = d.qid.path; } rp = stralloc(BUFSIZE); for(q=q0; q<q1; q+=n){ n = q1-q; if(n > Dat->BUFSIZE) n = Dat->BUFSIZE; t.file.buf.read(q, rp, 0, n); if(q < t.org) t.org += n; else if(q <= t.org+t.frame.nchars) frinsert(t.frame, rp.s, n, q-t.org); if(t.frame.lastlinefull) break; } strfree(rp); rp = nil; for(i=0; i<t.file.ntext; i++){ u = t.file.text[i]; if(u != t){ if(u.org > u.file.buf.nc) # will be 0 because of reset(), but safety first u.org = 0; u.reshape(u.all); u.backnl(u.org, 0); # go to beginning of line } u.setselect(q0, q0); } return q1-q0; } exception{ * => fd = nil; return 0; } return 0; } Text.bsinsert(t : self ref Text, q0 : int, r : string, n : int, tofile : int) : (int, int) { tp : ref Astring; bp, up : int; i, initial : int; { if(t.what == Tag) # can't happen but safety first: mustn't backspace over file name raise "e"; bp = 0; for(i=0; i<n; i++) if(r[bp++] == '\b'){ --bp; initial = 0; tp = utils->stralloc(n); for (k := 0; k < i; k++) tp.s[k] = r[k]; up = i; for(; i<n; i++){ tp.s[up] = r[bp++]; if(tp.s[up] == '\b') if(up == 0) initial++; else --up; else up++; } if(initial){ if(initial > q0) initial = q0; q0 -= initial; t.delete(q0, q0+initial, tofile); } n = up; t.insert(q0, tp.s, n, tofile, 0); strfree(tp); tp = nil; return (q0, n); } raise "e"; return(0, 0); } exception{ * => t.insert(q0, r, n, tofile, 0); return (q0, n); } return (0, 0); } Text.insert(t : self ref Text, q0 : int, r : string, n : int, tofile : int, echomode : int) { c, i : int; u : ref Text; if(tofile && t.ncache != 0) error("text.insert"); if(n == 0) return; if(tofile){ t.file.insert(q0, r, n); if(t.what == Body){ t.w.dirty = TRUE;