forsyth20121205-174063a80cc13 years agoHistory
1404 lines · 28.3 KB · Brainfuck
RawDownload
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.