diff --git a/sys/src/cmd/samterm.mono/flayer.c b/sys/src/cmd/samterm.mono/flayer.c new file mode 100644 index 000000000..2dd023e3c --- /dev/null +++ b/sys/src/cmd/samterm.mono/flayer.c @@ -0,0 +1,492 @@ +#include +#include +#include +#include +#include +#include +#include +#include "flayer.h" +#include "samterm.h" + +#define DELTA 10 + +static Flayer **llist; /* front to back */ +static int nllist; +static int nlalloc; +static Rectangle lDrect; + +Vis visibility(Flayer *); +void newvisibilities(int); +void llinsert(Flayer*); +void lldelete(Flayer*); + +Image *maincols[NCOL]; +Image *cmdcols[NCOL]; + +void +flstart(Rectangle r) +{ + lDrect = r; + + /* Main text is yellowish */ + maincols[BACK] = display->black; + maincols[HIGH] = allocimage(display, Rect(0,0,1,1), screen->chan, 1, 0x555555FF); + maincols[BORD] = allocimage(display, Rect(0,0,2,2), screen->chan, 1, 0x222222FF); + maincols[TEXT] = display->white; + maincols[HTEXT] = display->black; + + /* Command text is blueish */ + cmdcols[BACK] = display->black; + cmdcols[HIGH] = allocimage(display, Rect(0,0,1,1), screen->chan, 1, 0x555555FF); + cmdcols[BORD] = allocimage(display, Rect(0,0,2,2), screen->chan, 1, 0x222222FF); + cmdcols[TEXT] = display->white; + cmdcols[HTEXT] = display->black; +} + +void +flnew(Flayer *l, Rune *(*fn)(Flayer*, long, ulong*), int u0, void *u1) +{ + if(nllist == nlalloc){ + nlalloc += DELTA; + llist = realloc(llist, nlalloc*sizeof(Flayer**)); + if(llist == 0) + panic("flnew"); + } + l->textfn = fn; + l->user0 = u0; + l->user1 = u1; + l->lastsr = ZR; + llinsert(l); +} + +Rectangle +flrect(Flayer *l, Rectangle r) +{ + rectclip(&r, lDrect); + l->entire = r; + l->scroll = insetrect(r, FLMARGIN); + r.min.x = + l->scroll.max.x = r.min.x+FLMARGIN+FLSCROLLWID+(FLGAP-FLMARGIN); + return r; +} + +void +flinit(Flayer *l, Rectangle r, Font *ft, Image **cols) +{ + lldelete(l); + llinsert(l); + l->visible = All; + l->origin = l->p0 = l->p1 = 0; + frinit(&l->f, insetrect(flrect(l, r), FLMARGIN), ft, screen, cols); + l->f.maxtab = maxtab*stringwidth(ft, "0"); + newvisibilities(1); + draw(screen, l->entire, l->f.cols[BACK], nil, ZP); + scrdraw(l, 0L); + flborder(l, 0); + flrefresh(l, l->entire, 0); +} + +void +flclose(Flayer *l) +{ + if(l->visible == All) + draw(screen, l->entire, display->black, nil, ZP); + else if(l->visible == Some){ + if(l->f.b == 0) + l->f.b = allocimage(display, l->entire, screen->chan, 0, DNofill); + if(l->f.b){ + draw(l->f.b, l->entire, display->black, nil, ZP); + flrefresh(l, l->entire, 0); + } + } + frclear(&l->f, 1); + lldelete(l); + if(l->f.b && l->visible!=All) + freeimage(l->f.b); + l->textfn = 0; + newvisibilities(1); +} + +void +flborder(Flayer *l, int wide) +{ + if(flprepare(l)){ + border(l->f.b, l->entire, FLMARGIN, l->f.cols[BACK], ZP); + border(l->f.b, l->entire, wide? FLMARGIN : 1, l->f.cols[BORD], ZP); + if(l->visible==Some) + flrefresh(l, l->entire, 0); + } +} + +Flayer * +flwhich(Point p) +{ + int i; + + if(p.x==0 && p.y==0) + return nllist? llist[0] : 0; + for(i=0; ientire)) + return llist[i]; + return 0; +} + +void +flupfront(Flayer *l) +{ + int v = l->visible; + + lldelete(l); + llinsert(l); + if(v!=All) + newvisibilities(0); +} + +void +newvisibilities(int redraw) + /* if redraw false, we know it's a flupfront, and needn't + * redraw anyone becoming partially covered */ +{ + int i; + Vis ov; + Flayer *l; + + for(i = 0; ilastsr = ZR; /* make sure scroll bar gets redrawn */ + ov = l->visible; + l->visible = visibility(l); +#define V(a, b) (((a)<<2)|((b))) + switch(V(ov, l->visible)){ + case V(Some, None): + if(l->f.b) + freeimage(l->f.b); + case V(All, None): + case V(All, Some): + l->f.b = 0; + frclear(&l->f, 0); + break; + + case V(Some, Some): + if(l->f.b==0 && redraw) + case V(None, Some): + flprepare(l); + if(l->f.b && redraw){ + flrefresh(l, l->entire, 0); + freeimage(l->f.b); + l->f.b = 0; + frclear(&l->f, 0); + } + case V(None, None): + case V(All, All): + break; + + case V(Some, All): + if(l->f.b){ + draw(screen, l->entire, l->f.b, nil, l->entire.min); + freeimage(l->f.b); + l->f.b = screen; + break; + } + case V(None, All): + flprepare(l); + break; + } + if(ov==None && l->visible!=None) + flnewlyvisible(l); + } +} + +void +llinsert(Flayer *l) +{ + int i; + for(i=nllist; i>0; --i) + llist[i]=llist[i-1]; + llist[0]=l; + nllist++; +} + +void +lldelete(Flayer *l) +{ + int i; + + for(i=0; if, sp, ep, p0-l->origin); + scrdraw(l, scrtotal(l)); + if(l->visible==Some) + flrefresh(l, l->entire, 0); + } +} + +void +fldelete(Flayer *l, long p0, long p1) +{ + if(flprepare(l)){ + p0 -= l->origin; + if(p0 < 0) + p0 = 0; + p1 -= l->origin; + if(p1<0) + p1 = 0; + frdelete(&l->f, p0, p1); + scrdraw(l, scrtotal(l)); + if(l->visible==Some) + flrefresh(l, l->entire, 0); + } +} + +int +flselect(Flayer *l, ulong *p) +{ + static int clickcount; + static Point clickpt = {-10, -10}; + int dt, dx, dy; + + if(l->visible!=All) + flupfront(l); + dt = mousep->msec - l->click; + dx = abs(mousep->xy.x - clickpt.x); + dy = abs(mousep->xy.y - clickpt.y); + *p = frcharofpt(&l->f, mousep->xy) + l->origin; + + l->click = mousep->msec; + clickpt = mousep->xy; + + if(dx < 3 && dy < 3 && dt < Clicktime && clickcount < 3) + return ++clickcount; + clickcount = 0; + + frselect(&l->f, mousectl); + l->p0 = l->f.p0+l->origin; + l->p1 = l->f.p1+l->origin; + return 0; +} + +void +flsetselect(Flayer *l, long p0, long p1) +{ + ulong fp0, fp1; + + if(l->visible==None || !flprepare(l)){ + l->p0 = p0, l->p1 = p1; + return; + } + l->p0 = p0, l->p1 = p1; + flfp0p1(l, &fp0, &fp1); + if(fp0==l->f.p0 && fp1==l->f.p1) + return; + + if(fp1<=l->f.p0 || fp0>=l->f.p1 || l->f.p0==l->f.p1 || fp0==fp1){ + /* no overlap or trivial repainting */ + frdrawsel(&l->f, frptofchar(&l->f, l->f.p0), l->f.p0, l->f.p1, 0); + frdrawsel(&l->f, frptofchar(&l->f, fp0), fp0, fp1, 1); + goto Refresh; + } + /* the current selection and the desired selection overlap and are both non-empty */ + if(fp0 < l->f.p0){ + /* extend selection backwards */ + frdrawsel(&l->f, frptofchar(&l->f, fp0), fp0, l->f.p0, 1); + }else if(fp0 > l->f.p0){ + /* trim first part of selection */ + frdrawsel(&l->f, frptofchar(&l->f, l->f.p0), l->f.p0, fp0, 0); + } + if(fp1 > l->f.p1){ + /* extend selection forwards */ + frdrawsel(&l->f, frptofchar(&l->f, l->f.p1), l->f.p1, fp1, 1); + }else if(fp1 < l->f.p1){ + /* trim last part of selection */ + frdrawsel(&l->f, frptofchar(&l->f, fp1), fp1, l->f.p1, 0); + } + + Refresh: + l->f.p0 = fp0; + l->f.p1 = fp1; + if(l->visible==Some) + flrefresh(l, l->entire, 0); +} + +void +flfp0p1(Flayer *l, ulong *pp0, ulong *pp1) +{ + long p0 = l->p0-l->origin, p1 = l->p1-l->origin; + + if(p0 < 0) + p0 = 0; + if(p1 < 0) + p1 = 0; + if(p0 > l->f.nchars) + p0 = l->f.nchars; + if(p1 > l->f.nchars) + p1 = l->f.nchars; + *pp0 = p0; + *pp1 = p1; +} + +Rectangle +rscale(Rectangle r, Point old, Point new) +{ + r.min.x = r.min.x*new.x/old.x; + r.min.y = r.min.y*new.y/old.y; + r.max.x = r.max.x*new.x/old.x; + r.max.y = r.max.y*new.y/old.y; + return r; +} + +void +flresize(Rectangle dr) +{ + int i; + Flayer *l; + Frame *f; + Rectangle r, olDrect; + int move; + + olDrect = lDrect; + lDrect = dr; + move = 0; + /* no moving on rio; must repaint */ + if(0 && Dx(dr)==Dx(olDrect) && Dy(dr)==Dy(olDrect)) + move = 1; + else + draw(screen, lDrect, display->black, nil, ZP); + for(i=0; ilastsr = ZR; + f = &l->f; + if(move) + r = rectaddpt(rectsubpt(l->entire, olDrect.min), dr.min); + else{ + r = rectaddpt(rscale(rectsubpt(l->entire, olDrect.min), + subpt(olDrect.max, olDrect.min), + subpt(dr.max, dr.min)), dr.min); + if(l->visible==Some && f->b){ + freeimage(f->b); + frclear(f, 0); + } + f->b = 0; + if(l->visible!=None) + frclear(f, 0); + } + if(!rectclip(&r, dr)) + panic("flresize"); + if(r.max.x-r.min.x<100) + r.min.x = dr.min.x; + if(r.max.x-r.min.x<100) + r.max.x = dr.max.x; + if(r.max.y-r.min.y<2*FLMARGIN+f->font->height) + r.min.y = dr.min.y; + if(r.max.y-r.min.y<2*FLMARGIN+f->font->height) + r.max.y = dr.max.y; + if(!move) + l->visible = None; + frsetrects(f, insetrect(flrect(l, r), FLMARGIN), f->b); + if(!move && f->b) + scrdraw(l, scrtotal(l)); + } + newvisibilities(1); +} + +int +flprepare(Flayer *l) +{ + Frame *f; + ulong n; + Rune *r; + + if(l->visible == None) + return 0; + f = &l->f; + if(f->b == 0){ + if(l->visible == All) + f->b = screen; + else if((f->b = allocimage(display, l->entire, screen->chan, 0, 0))==0) + return 0; + draw(f->b, l->entire, f->cols[BACK], nil, ZP); + border(f->b, l->entire, l==llist[0]? FLMARGIN : 1, f->cols[BORD], ZP); + n = f->nchars; + frinit(f, f->entire, f->font, f->b, 0); + f->maxtab = maxtab*stringwidth(f->font, "0"); + r = (*l->textfn)(l, n, &n); + frinsert(f, r, r+n, (ulong)0); + frdrawsel(f, frptofchar(f, f->p0), f->p0, f->p1, 0); + flfp0p1(l, &f->p0, &f->p1); + frdrawsel(f, frptofchar(f, f->p0), f->p0, f->p1, 1); + l->lastsr = ZR; + scrdraw(l, scrtotal(l)); + } + return 1; +} + +static int somevis, someinvis, justvis; + +Vis +visibility(Flayer *l) +{ + somevis = someinvis = 0; + justvis = 1; + flrefresh(l, l->entire, 0); + justvis = 0; + if(somevis==0) + return None; + if(someinvis==0) + return All; + return Some; +} + +void +flrefresh(Flayer *l, Rectangle r, int i) +{ + Flayer *t; + Rectangle s; + + Top: + if((t=llist[i++]) == l){ + if(!justvis) + draw(screen, r, l->f.b, nil, r.min); + somevis = 1; + }else{ + if(!rectXrect(t->entire, r)) + goto Top; /* avoid stacking unnecessarily */ + if(t->entire.min.x>r.min.x){ + s = r; + s.max.x = t->entire.min.x; + flrefresh(l, s, i); + r.min.x = t->entire.min.x; + } + if(t->entire.min.y>r.min.y){ + s = r; + s.max.y = t->entire.min.y; + flrefresh(l, s, i); + r.min.y = t->entire.min.y; + } + if(t->entire.max.xentire.max.x; + flrefresh(l, s, i); + r.max.x = t->entire.max.x; + } + if(t->entire.max.yentire.max.y; + flrefresh(l, s, i); + r.max.y = t->entire.max.y; + } + /* remaining piece of r is blocked by t; forget about it */ + someinvis = 1; + } +} diff --git a/sys/src/cmd/samterm.mono/flayer.h b/sys/src/cmd/samterm.mono/flayer.h new file mode 100644 index 000000000..24aafc55a --- /dev/null +++ b/sys/src/cmd/samterm.mono/flayer.h @@ -0,0 +1,50 @@ +typedef enum Vis{ + None=0, + Some, + All, +}Vis; + +enum{ + Clicktime=500, /* milliseconds */ +}; + +typedef struct Flayer Flayer; + +struct Flayer +{ + Frame f; + long origin; /* offset of first char in flayer */ + long p0, p1; + long click; /* time at which selection click occurred, in HZ */ + Rune *(*textfn)(Flayer*, long, ulong*); + int user0; + void *user1; + Rectangle entire; + Rectangle scroll; + Rectangle lastsr; /* geometry of scrollbar when last drawn */ + Vis visible; +}; + +void flborder(Flayer*, int); +void flclose(Flayer*); +void fldelete(Flayer*, long, long); +void flfp0p1(Flayer*, ulong*, ulong*); +void flinit(Flayer*, Rectangle, Font*, Image**); +void flinsert(Flayer*, Rune*, Rune*, long); +void flnew(Flayer*, Rune *(*fn)(Flayer*, long, ulong*), int, void*); +int flprepare(Flayer*); +Rectangle flrect(Flayer*, Rectangle); +void flrefresh(Flayer*, Rectangle, int); +void flresize(Rectangle); +int flselect(Flayer*, ulong*); +void flsetselect(Flayer*, long, long); +void flstart(Rectangle); +void flupfront(Flayer*); +Flayer *flwhich(Point); + +#define FLMARGIN 4 +#define FLSCROLLWID 12 +#define FLGAP 4 + +extern Image *maincols[NCOL]; +extern Image *cmdcols[NCOL]; diff --git a/sys/src/cmd/samterm.mono/icons.c b/sys/src/cmd/samterm.mono/icons.c new file mode 100644 index 000000000..fcbd5e805 --- /dev/null +++ b/sys/src/cmd/samterm.mono/icons.c @@ -0,0 +1,52 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include "flayer.h" +#include "samterm.h" + +Cursor bullseye={ + {-7, -7}, + {0x1F, 0xF8, 0x3F, 0xFC, 0x7F, 0xFE, 0xFB, 0xDF, + 0xF3, 0xCF, 0xE3, 0xC7, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xE3, 0xC7, 0xF3, 0xCF, + 0x7B, 0xDF, 0x7F, 0xFE, 0x3F, 0xFC, 0x1F, 0xF8,}, + {0x00, 0x00, 0x0F, 0xF0, 0x31, 0x8C, 0x21, 0x84, + 0x41, 0x82, 0x41, 0x82, 0x41, 0x82, 0x7F, 0xFE, + 0x7F, 0xFE, 0x41, 0x82, 0x41, 0x82, 0x41, 0x82, + 0x21, 0x84, 0x31, 0x8C, 0x0F, 0xF0, 0x00, 0x00,} +}; +Cursor deadmouse={ + {-7, -7}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x0C, 0x00, 0x8E, 0x1D, 0xC7, + 0xFF, 0xE3, 0xFF, 0xF3, 0xFF, 0xFF, 0x7F, 0xFE, + 0x3F, 0xF8, 0x17, 0xF0, 0x03, 0xE0, 0x00, 0x00,}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00, 0x82, + 0x04, 0x41, 0xFF, 0xE1, 0x5F, 0xF1, 0x3F, 0xFE, + 0x17, 0xF0, 0x03, 0xE0, 0x00, 0x00, 0x00, 0x00,} +}; +Cursor lockarrow={ + {-7, -7}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0F, 0xC0, 0x0F, 0xC0, + 0x03, 0xC0, 0x07, 0xC0, 0x0E, 0xC0, 0x1C, 0xC0, + 0x38, 0x00, 0x70, 0x00, 0xE0, 0xDB, 0xC0, 0xDB,} +}; + +Image *darkgrey; + +void +iconinit(void) +{ + darkgrey = allocimage(display, Rect(0, 0, 1, 1), screen->chan, 1, 0x444444FF); +} diff --git a/sys/src/cmd/samterm.mono/io.c b/sys/src/cmd/samterm.mono/io.c new file mode 100644 index 000000000..bd9b3a3b6 --- /dev/null +++ b/sys/src/cmd/samterm.mono/io.c @@ -0,0 +1,286 @@ +#include +#include +#include +#include +#include +#include +#include +#include "flayer.h" +#include "samterm.h" + +int cursorfd; +int plumbfd = -1; +int input; +int got; +int block; +int kbdc; +int resized; +uchar *hostp; +uchar *hoststop; +uchar *plumbbase; +uchar *plumbp; +uchar *plumbstop; +Channel *plumbc; +Channel *hostc; +Mousectl *mousectl; +Mouse *mousep; +Keyboardctl *keyboardctl; +void panic(char*); + +void +initio(void) +{ + threadsetname("main"); + mousectl = initmouse(nil, display->image); + if(mousectl == nil){ + fprint(2, "samterm: mouse init failed: %r\n"); + threadexitsall("mouse"); + } + mousep = mousectl; + keyboardctl = initkeyboard(nil); + if(keyboardctl == nil){ + fprint(2, "samterm: keyboard init failed: %r\n"); + threadexitsall("kbd"); + } + hoststart(); + plumbstart(); +} + +void +getmouse(void) +{ + if(readmouse(mousectl) < 0) + panic("mouse"); +} + +void +mouseunblock(void) +{ + got &= ~(1<buttons&(1<<(but-1)); +} + +void +externload(int i) +{ + plumbbase = malloc(plumbbuf[i].n); + if(plumbbase == 0) + return; + memmove(plumbbase, plumbbuf[i].data, plumbbuf[i].n); + plumbp = plumbbase; + plumbstop = plumbbase + plumbbuf[i].n; + got |= 1<c; + alts[RKeyboard].v = &r; + alts[RKeyboard].op = CHANRCV; + if(block & (1<c; + alts[RMouse].v = &mousectl->Mouse; + alts[RMouse].op = CHANRCV; + if(block & (1<resizec; + alts[RResize].v = nil; + alts[RResize].op = CHANRCV; + if(block & (1<bufp > display->buf) + flushimage(display, 1); + type = alt(alts); + switch(type){ + case RHost: + hostp = hostbuf[i].data; + hoststop = hostbuf[i].data + hostbuf[i].n; + block = 0; + break; + case RPlumb: + externload(i); + break; + case RKeyboard: + kbdc = r; + break; + case RMouse: + break; + case RResize: + resized = 1; + /* do the resize in line if we've finished initializing and we're not in a blocking state */ + if(hasunlocked && block==0 && RESIZED()) + resize(); + goto again; + } + got |= 1<= plumbstop){ + got &= ~(1<= 0) + return 1; + if(nbrecv(keyboardctl->c, &r) > 0){ + kpeekc = r; + return 1; + } + return 0; +} + +int +ekbd(void) +{ + int c; + Rune r; + + if(kpeekc >= 0){ + c = kpeekc; + kpeekc = -1; + return c; + } + if(recv(keyboardctl->c, &r) < 0){ + fprint(2, "samterm: keybard recv error: %r\n"); + panic("kbd"); + } + return r; +} + +int +kbdchar(void) +{ + int c, i; + + c = externchar(); + if(c > 0) + return c; + if(got & (1<0){ + externload(i); + c = externchar(); + if(c > 0) + return c; + } + if(!ecankbd()) + return -1; + return ekbd(); +} + +int +qpeekc(void) +{ + return kbdc; +} + +int +RESIZED(void) +{ + if(resized){ + if(getwindow(display, Refnone) < 0) + panic("can't reattach to window"); + resized = 0; + return 1; + } + return 0; +} diff --git a/sys/src/cmd/samterm.mono/main.c b/sys/src/cmd/samterm.mono/main.c new file mode 100644 index 000000000..33d98dfea --- /dev/null +++ b/sys/src/cmd/samterm.mono/main.c @@ -0,0 +1,731 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include "flayer.h" +#include "samterm.h" + +int mainstacksize = 16*1024; + +Text cmd; +Rune *scratch; +long nscralloc; +Cursor *cursor; +Flayer *which = 0; +Flayer *work = 0; +long snarflen; +long typestart = -1; +long typeend = -1; +long typeesc = -1; +long modified = 0; /* strange lookahead for menus */ +char hostlock = 1; +char hasunlocked = 0; +int maxtab = 8; +int autoindent; +int spacesindent; + +void +threadmain(int argc, char *argv[]) +{ + int i, got, nclick, scr, chord; + Text *t; + Rectangle r; + Flayer *nwhich; + ulong p; + + getscreen(argc, argv); + iconinit(); + initio(); + scratch = alloc(100*RUNESIZE); + nscralloc = 100; + r = screen->r; + r.max.y = r.min.y+Dy(r)/5; + flstart(screen->clipr); + rinit(&cmd.rasp); + flnew(&cmd.l[0], gettext, 1, &cmd); + flinit(&cmd.l[0], r, font, cmdcols); + cmd.nwin = 1; + which = &cmd.l[0]; + cmd.tag = Untagged; + outTs(Tversion, VERSION); + startnewfile(Tstartcmdfile, &cmd); + + got = 0; + chord = 0; + for(;;got = waitforio()){ + if(hasunlocked && RESIZED()) + resize(); + if(got&(1<xy, screen->r)){ + mouseunblock(); + continue; + } + nwhich = flwhich(mousep->xy); + scr = which && (ptinrect(mousep->xy, which->scroll) || + mousep->buttons&(8|16)); + if(mousep->buttons) + flushtyping(1); + if((mousep->buttons&1)==0) + chord = 0; + if(chord && which && which==nwhich){ + chord |= mousep->buttons; + t = (Text *)which->user1; + if(!t->lock){ + int w = which-t->l; + if(chord&2){ + cut(t, w, 1, 1); + chord &= ~2; + } + if(chord&4){ + paste(t, w); + chord &= ~4; + } + } + }else if(mousep->buttons&(1|8)){ + if(scr) + scroll(which, (mousep->buttons&8) ? 4 : 1); + else if(nwhich && nwhich!=which) + current(nwhich); + else{ + t=(Text *)which->user1; + nclick = flselect(which, &p); + if(nclick > 0){ + if(nclick > 1) + outTsl(Ttclick, t->tag, p); + else + outTsl(Tdclick, t->tag, p); + t->lock++; + }else if(t!=&cmd) + outcmd(); + if(mousep->buttons&1) + chord = mousep->buttons; + } + }else if((mousep->buttons&2) && which){ + if(scr) + scroll(which, 2); + else + menu2hit(); + }else if(mousep->buttons&(4|16)){ + if(scr) + scroll(which, (mousep->buttons&16) ? 5 : 3); + else + menu3hit(); + } + mouseunblock(); + } + } +} + + +void +resize(void) +{ + int i; + + flresize(screen->clipr); + for(i = 0; itag); +} + +void +current(Flayer *nw) +{ + Text *t; + + if(which) + flborder(which, 0); + if(nw){ + flushtyping(1); + flupfront(nw); + flborder(nw, 1); + buttons(Up); + t = (Text *)nw->user1; + t->front = nw-&t->l[0]; + if(t != &cmd) + work = nw; + } + which = nw; +} + +void +closeup(Flayer *l) +{ + Text *t=(Text *)l->user1; + int m; + + m = whichmenu(t->tag); + if(m < 0) + return; + flclose(l); + if(l == which){ + which = 0; + current(flwhich(Pt(0, 0))); + } + if(l == work) + work = 0; + if(--t->nwin == 0){ + rclear(&t->rasp); + free((uchar *)t); + text[m] = 0; + }else if(l == &t->l[t->front]){ + for(m=0; ml[m].textfn){ + t->front = m; + return; + } + panic("close"); + } +} + +Flayer * +findl(Text *t) +{ + int i; + for(i = 0; il[i].textfn==0) + return &t->l[i]; + return 0; +} + +void +duplicate(Flayer *l, Rectangle r, Font *f, int close) +{ + Text *t=(Text *)l->user1; + Flayer *nl = findl(t); + Rune *rp; + ulong n; + + if(nl){ + flnew(nl, gettext, l->user0, (char *)t); + flinit(nl, r, f, l->f.cols); + nl->origin = l->origin; + rp = (*l->textfn)(l, l->f.nchars, &n); + flinsert(nl, rp, rp+n, l->origin); + flsetselect(nl, l->p0, l->p1); + if(close){ + flclose(l); + if(l==which) + which = 0; + }else + t->nwin++; + current(nl); + hcheck(t->tag); + } + setcursor(mousectl, cursor); +} + +void +buttons(int updown) +{ + while(((mousep->buttons&7)!=0) != updown) + getmouse(); +} + +int +getr(Rectangle *rp) +{ + Point p; + Rectangle r; + + *rp = screen->r; + p = rp->min; + r = cmd.l[cmd.front].entire; + if(cmd.nwin==1) + rp->min.y = r.max.y; + + return rectclip(rp, screen->r) && + rp->max.x-rp->min.x>100 && rp->max.y-rp->min.y>40; +} + +void +snarf(Text *t, int w) +{ + Flayer *l = &t->l[w]; + + if(l->p1>l->p0){ + snarflen = l->p1-l->p0; + outTsll(Tsnarf, t->tag, l->p0, l->p1); + } +} + +void +cut(Text *t, int w, int save, int check) +{ + long p0, p1; + Flayer *l; + + l = &t->l[w]; + p0 = l->p0; + p1 = l->p1; + if(p0 == p1) + return; + if(p0 < 0) + panic("cut"); + if(save) + snarf(t, w); + outTsll(Tcut, t->tag, p0, p1); + flsetselect(l, p0, p0); + t->lock++; + hcut(t->tag, p0, p1-p0); + if(check) + hcheck(t->tag); +} + +void +paste(Text *t, int w) +{ + if(snarflen){ + cut(t, w, 0, 0); + t->lock++; + outTsl(Tpaste, t->tag, t->l[w].p0); + } +} + +void +scrorigin(Flayer *l, int but, long p0) +{ + Text *t=(Text *)l->user1; + + if(t->tag == Untagged) + return; + + switch(but){ + case 1: + outTsll(Torigin, t->tag, l->origin, p0); + break; + case 2: + outTsll(Torigin, t->tag, p0, 1L); + break; + case 3: + horigin(t->tag,p0); + } +} + +int +alnum(int c) +{ + /* + * Hard to get absolutely right. Use what we know about ASCII + * and assume anything above the Latin control characters is + * potentially an alphanumeric. + */ + if(c<=' ') + return 0; + if(0x7F<=c && c<=0xA0) + return 0; + if(utfrune("!\"#$%&'()*+,-./:;<=>?@[\\]^`{|}~", c)) + return 0; + return 1; +} + +int +raspc(Rasp *r, long p) +{ + ulong n; + rload(r, p, p+1, &n); + if(n) + return scratch[0]; + return 0; +} + +int +getcol(Rasp *r, long p) +{ + int col; + + for(col = 0; p > 0 && raspc(r, p-1)!='\n'; p--, col++) + ; + return col; +} + +long +del(Rasp *r, long o, long p) +{ + int i, col, n; + + if(--p < o) + return o; + if(!spacesindent || raspc(r, p)!=' ') + return p; + col = getcol(r, p) + 1; + if((n = col % maxtab) == 0) + n = maxtab; + for(i = 0; p-1>=o && raspc(r, p-1)==' ' && i=o? p : o; +} + +long +ctlw(Rasp *r, long o, long p) +{ + int c; + + if(--p < o) + return o; + if(raspc(r, p)=='\n') + return p; + for(; p>=o && !alnum(c=raspc(r, p)); --p) + if(c=='\n') + return p+1; + for(; p>o && alnum(raspc(r, p-1)); --p) + ; + return p>=o? p : o; +} + +long +ctlu(Rasp *r, long o, long p) +{ + if(--p < o) + return o; + if(raspc(r, p)=='\n') + return p; + for(; p-1>=o && raspc(r, p-1)!='\n'; --p) + ; + return p>=o? p : o; +} + +int +center(Flayer *l, long a) +{ + Text *t; + + t = l->user1; + if(!t->lock && (aorigin || l->origin+l->f.nchars t->rasp.nrunes) + a = t->rasp.nrunes; + outTsll(Torigin, t->tag, a, 2L); + return 1; + } + return 0; +} + +int +onethird(Flayer *l, long a) +{ + Text *t; + Rectangle s; + long lines; + + t = l->user1; + if(!t->lock && (aorigin || l->origin+l->f.nchars t->rasp.nrunes) + a = t->rasp.nrunes; + s = insetrect(l->scroll, 1); + lines = ((s.max.y-s.min.y)/l->f.font->height+1)/3; + if (lines < 2) + lines = 2; + outTsll(Torigin, t->tag, a, lines); + return 1; + } + return 0; +} + +void +flushtyping(int clearesc) +{ + Text *t; + ulong n; + + if(clearesc) + typeesc = -1; + if(typestart == typeend) { + modified = 0; + return; + } + t = which->user1; + if(t != &cmd) + modified = 1; + rload(&t->rasp, typestart, typeend, &n); + scratch[n] = 0; + if(t==&cmd && typeend==t->rasp.nrunes && scratch[typeend-typestart-1]=='\n'){ + setlock(); + outcmd(); + } + outTslS(Ttype, t->tag, typestart, scratch); + typestart = -1; + typeend = -1; +} + +int +nontypingkey(int c) +{ + switch(c){ + case Kup: + case Kdown: + case Khome: + case Kend: + case Kpgdown: + case Kpgup: + case Kleft: + case Kright: + case Ksoh: + case Kenq: + case Kstx: + case Kbel: + return 1; + } + return 0; +} + + +void +type(Flayer *l, int res) /* what a bloody mess this is */ +{ + Text *t = (Text *)l->user1; + Rune buf[100]; + Rune *p = buf; + int c, backspacing; + long a, a0; + int scrollkey; + + scrollkey = 0; + if(res == RKeyboard) + scrollkey = nontypingkey(qpeekc()); /* ICK */ + + if(hostlock || t->lock){ + kbdblock(); + return; + } + a = l->p0; + if(a!=l->p1 && !scrollkey){ + flushtyping(1); + cut(t, t->front, 1, 1); + return; /* it may now be locked */ + } + backspacing = 0; + while((c = kbdchar())>0){ + if(res == RKeyboard){ + if(nontypingkey(c) || c==Kesc) + break; + /* backspace, ctrl-u, ctrl-w, del */ + if(c==Kbs || c==Knack || c==Ketb || c==Kdel){ + backspacing = 1; + break; + } + } + if(spacesindent && c == '\t'){ + int i, col, n; + col = getcol(&t->rasp, a); + n = maxtab - col % maxtab; + for(i = 0; i < n && p < buf+nelem(buf); i++) + *p++ = ' '; + } else + *p++ = c; + if(c == '\n' && autoindent && t != &cmd){ + /* autoindent */ + int cursor, ch; + cursor = ctlu(&t->rasp, 0, a+(p-buf)-1); + while(p < buf+nelem(buf)){ + ch = raspc(&t->rasp, cursor++); + if(ch == ' ' || ch == '\t') + *p++ = ch; + else + break; + } + } + if(c == '\n' || p >= buf+sizeof(buf)/sizeof(buf[0])) + break; + } + if(p > buf){ + if(typestart < 0) + typestart = a; + if(typeesc < 0) + typeesc = a; + hgrow(t->tag, a, p-buf, 0); + t->lock++; /* pretend we Trequest'ed for hdatarune*/ + hdatarune(t->tag, a, buf, p-buf); + a += p-buf; + l->p0 = a; + l->p1 = a; + typeend = a; + if(c=='\n' || typeend-typestart>100) + flushtyping(0); + onethird(l, a); + } + if(c==Kdown || c==Kpgdown){ + flushtyping(0); + center(l, l->origin+l->f.nchars+1); + /* backspacing immediately after outcmd(): sorry */ + }else if(c==Kup || c==Kpgup){ + flushtyping(0); + a0 = l->origin-l->f.nchars; + if(a0 < 0) + a0 = 0; + center(l, a0); + }else if(c == Kright){ + flushtyping(0); + a0 = l->p0; + if(a0 < t->rasp.nrunes) + a0++; + flsetselect(l, a0, a0); + center(l, a0); + }else if(c == Kleft){ + flushtyping(0); + a0 = l->p0; + if(a0 > 0) + a0--; + flsetselect(l, a0, a0); + center(l, a0); + }else if(c == Khome){ + flushtyping(0); + center(l, 0); + }else if(c == Kend){ + flushtyping(0); + center(l, t->rasp.nrunes); + }else if(c == Ksoh || c == Kenq){ + flushtyping(1); + if(c == Ksoh) + while(a > 0 && raspc(&t->rasp, a-1)!='\n') + a--; + else + while(a < t->rasp.nrunes && raspc(&t->rasp, a)!='\n') + a++; + l->p0 = l->p1 = a; + for(l=t->l; l<&t->l[NL]; l++) + if(l->textfn) + flsetselect(l, l->p0, l->p1); + }else if(backspacing && !hostlock){ + /* backspacing immediately after outcmd(): sorry */ + if(l->f.p0>0 && a>0){ + switch(c){ + case Kbs: + case Kdel: /* del */ + l->p0 = del(&t->rasp, l->origin, a); + break; + case Knack: /* ctrl-u */ + l->p0 = ctlu(&t->rasp, l->origin, a); + break; + case Ketb: /* ctrl-w */ + l->p0 = ctlw(&t->rasp, l->origin, a); + break; + } + l->p1 = a; + if(l->p1 != l->p0){ + /* cut locally if possible */ + if(typestart<=l->p0 && l->p1<=typeend){ + t->lock++; /* to call hcut */ + hcut(t->tag, l->p0, l->p1-l->p0); + /* hcheck is local because we know rasp is contiguous */ + hcheck(t->tag); + }else{ + flushtyping(0); + cut(t, t->front, 0, 1); + } + } + if(typeesc >= l->p0) + typeesc = l->p0; + if(typestart >= 0){ + if(typestart >= l->p0) + typestart = l->p0; + typeend = l->p0; + if(typestart == typeend){ + typestart = -1; + typeend = -1; + modified = 0; + } + } + } + }else if(c == Kstx){ + t = &cmd; + for(l=t->l; l->textfn==0; l++) + ; + current(l); + flushtyping(0); + a = t->rasp.nrunes; + flsetselect(l, a, a); + center(l, a); + }else if(c == Kbel){ + int i; + if(work == nil) + return; + if(which != work){ + current(work); + return; + } + t = (Text*)work->user1; + l = &t->l[t->front]; + for(i=t->front; t->nwin>1 && (i = (i+1)%NL) != t->front; ) + if(t->l[i].textfn != 0){ + l = &t->l[i]; + break; + } + current(l); + }else{ + if(c==Kesc && typeesc>=0){ + l->p0 = typeesc; + l->p1 = a; + flushtyping(1); + } + for(l=t->l; l<&t->l[NL]; l++) + if(l->textfn) + flsetselect(l, l->p0, l->p1); + } +} + + +void +outcmd(void){ + if(work) + outTsll(Tworkfile, ((Text *)work->user1)->tag, work->p0, work->p1); +} + +void +panic(char *s) +{ + panic1(display, s); +} + +void +panic1(Display*, char *s) +{ + fprint(2, "samterm:panic: "); + perror(s); + abort(); +} + +Rune* +gettext(Flayer *l, long n, ulong *np) +{ + Text *t; + + t = l->user1; + rload(&t->rasp, l->origin, l->origin+n, np); + return scratch; +} + +long +scrtotal(Flayer *l) +{ + return ((Text *)l->user1)->rasp.nrunes; +} + +void* +alloc(ulong n) +{ + void *p; + + p = malloc(n); + if(p == 0) + panic("alloc"); + memset(p, 0, n); + return p; +} diff --git a/sys/src/cmd/samterm.mono/menu.c b/sys/src/cmd/samterm.mono/menu.c new file mode 100644 index 000000000..4b409a70b --- /dev/null +++ b/sys/src/cmd/samterm.mono/menu.c @@ -0,0 +1,402 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include "flayer.h" +#include "samterm.h" + +uchar **name; /* first byte is ' ' or '\'': modified state */ +Text **text; /* pointer to Text associated with file */ +ushort *tag; /* text[i].tag, even if text[i] not defined */ +int nname; +int mname; +int mw; + +char *genmenu3(int); +char *genmenu2(int); +char *genmenu2c(int); + +enum Menu2 +{ + Cut, + Paste, + Snarf, + Plumb, + Look, + Exch, + Search, + NMENU2 = Search, + Send = Search, + NMENU2C +}; + +enum Menu3 +{ + New, + Zerox, + Resize, + Close, + Write, + NMENU3 +}; + +char *menu2str[] = { + "cut", + "paste", + "snarf", + "plumb", + "look", + "", + 0, /* storage for last pattern */ +}; + +char *menu3str[] = { + "new", + "zerox", + "resize", + "close", + "write", +}; + +Menu menu2 = {0, genmenu2}; +Menu menu2c ={0, genmenu2c}; +Menu menu3 = {0, genmenu3}; + +void +menu2hit(void) +{ + Text *t=(Text *)which->user1; + int w = which-t->l; + int m; + + if(hversion==0 || plumbfd<0) + menu2str[Plumb] = "(plumb)"; + m = menuhit(2, mousectl, t==&cmd? &menu2c : &menu2, nil); + if(hostlock || t->lock) + return; + + switch(m){ + case Cut: + cut(t, w, 1, 1); + break; + + case Paste: + paste(t, w); + break; + + case Snarf: + snarf(t, w); + break; + + case Plumb: + if(hversion > 0) + outTsll(Tplumb, t->tag, which->p0, which->p1); + break; + + case Exch: + snarf(t, w); + outT0(Tstartsnarf); + setlock(); + break; + + case Look: + outTsll(Tlook, t->tag, which->p0, which->p1); + setlock(); + break; + + case Search: + outcmd(); + if(t==&cmd) + outTsll(Tsend, 0 /*ignored*/, which->p0, which->p1); + else + outT0(Tsearch); + setlock(); + break; + } +} + +void +menu3hit(void) +{ + Rectangle r; + Flayer *l; + int m, i; + Text *t; + + mw = -1; + switch(m = menuhit(3, mousectl, &menu3, nil)){ + case -1: + break; + + case New: + if(!hostlock) + sweeptext(1, 0); + break; + + case Zerox: + case Resize: + if(!hostlock){ + setcursor(mousectl, &bullseye); + buttons(Down); + if((mousep->buttons&4) && (l = flwhich(mousep->xy)) && getr(&r)) + duplicate(l, r, l->f.font, m==Resize); + else + setcursor(mousectl, cursor); + buttons(Up); + } + break; + + case Close: + if(!hostlock){ + setcursor(mousectl, &bullseye); + buttons(Down); + if((mousep->buttons&4) && (l = flwhich(mousep->xy)) && !hostlock){ + t=(Text *)l->user1; + if (t->nwin>1) + closeup(l); + else if(t!=&cmd) { + outTs(Tclose, t->tag); + setlock(); + } + } + setcursor(mousectl, cursor); + buttons(Up); + } + break; + + case Write: + if(!hostlock){ + setcursor(mousectl, &bullseye); + buttons(Down); + if((mousep->buttons&4) && (l = flwhich(mousep->xy))){ + outTs(Twrite, ((Text *)l->user1)->tag); + setlock(); + }else + setcursor(mousectl, cursor); + buttons(Up); + } + break; + + default: + if(t = text[m-NMENU3]){ + i = t->front; + if(t->nwin==0 || t->l[i].textfn==0) + return; /* not ready yet; try again later */ + if(t->nwin>1 && which==&t->l[i]) + do + if(++i==NL) + i = 0; + while(i!=t->front && t->l[i].textfn==0); + current(&t->l[i]); + }else if(!hostlock) + sweeptext(0, tag[m-NMENU3]); + break; + } +} + + +Text * +sweeptext(int new, int tag) +{ + Rectangle r; + Text *t; + + if(getr(&r) && (t = malloc(sizeof(Text)))){ + memset((void*)t, 0, sizeof(Text)); + //current((Flayer *)0); + flnew(&t->l[0], gettext, 0, (char *)t); + flinit(&t->l[0], r, font, maincols); /*bnl*/ + t->nwin = 1; + rinit(&t->rasp); + if(new) + startnewfile(Tstartnewfile, t); + else{ + rinit(&t->rasp); + t->tag = tag; + startfile(t); + } + return t; + } + return 0; +} + +int +whichmenu(int tg) +{ + int i; + + for(i=0; in; --i) + name[i]=name[i-1], text[i]=text[i-1], tag[i]=tag[i-1]; + text[n] = t; + tag[n] = tg; + name[n] = alloc(strlen((char*)s)+2); + name[n][0] = m; + strcpy((char*)name[n]+1, (char*)s); + nname++; + menu3.lasthit = n+NMENU3; +} + +void +menudel(int n) +{ + int i; + + if(nname==0 || n>=nname || text[n]) + panic("menudel"); + free(name[n]); + --nname; + for(i = n; iuser1; + char *p; + if(n>=NMENU2+(menu2str[Search]!=0)) + return 0; + p = menu2str[n]; + if(!hostlock && !t->lock || n==Search || n==Look) + return p; + return paren(p); +} +char* +genmenu2c(int n) +{ + Text *t=(Text *)which->user1; + char *p; + if(n >= NMENU2C) + return 0; + if(n == Send) + p="send"; + else + p = menu2str[n]; + if(!hostlock && !t->lock) + return p; + return paren(p); +} +char * +genmenu3(int n) +{ + Text *t; + int c, i, k, l, w; + Rune r; + char *p; + + if(n >= NMENU3+nname) + return 0; + if(n < NMENU3){ + p = menu3str[n]; + if(hostlock) + p = paren(p); + return p; + } + n -= NMENU3; + if(n == 0) /* unless we've been fooled, this is cmd */ + return (char *)&name[n][1]; + if(mw == -1){ + mw = 7; /* strlen("~~sam~~"); */ + for(i=1; i mw) + mw = w; + } + } + if(mw > NBUF) + mw = NBUF; + t = text[n]; + buf[0] = name[n][0]; + buf[1] = '-'; + buf[2] = ' '; + buf[3] = ' '; + if(t){ + if(t->nwin == 1) + buf[1] = '+'; + else if(t->nwin > 1) + buf[1] = '*'; + if(work && t==(Text *)work->user1) { + buf[2]= '.'; + if(modified) + buf[0] = '\''; + } + } + l = utflen((char*)name[n]+1); + if(l > NBUF-4-2){ + i = 4; + k = 1; + while(i < NBUF/2){ + k += chartorune(&r, (char*)name[n]+k); + i++; + } + c = name[n][k]; + name[n][k] = 0; + strcpy((char*)buf+4, (char*)name[n]+1); + name[n][k] = c; + strcat((char*)buf, "..."); + while((l-i) >= NBUF/2-4){ + k += chartorune(&r, (char*)name[n]+k); + i++; + } + strcat((char*)buf, (char*)name[n]+k); + }else + strcpy((char*)buf+4, (char*)name[n]+1); + i = utflen((char*)buf); + k = strlen((char*)buf); + while(i +#include +#include +#include +#include +#include +#include +#include +#include +#include "flayer.h" +#include "samterm.h" + +#define HSIZE 3 /* Type + short count */ +Header h; +uchar indata[DATASIZE+1]; /* room for NUL */ +uchar outdata[DATASIZE]; +short outcount; +int hversion; +int exiting; + +void inmesg(Hmesg, int); +int inshort(int); +long inlong(int); +vlong invlong(int); +void hsetdot(int, long, long); +void hmoveto(int, long); +void hsetsnarf(int); +void hplumb(int); +void clrlock(void); +int snarfswap(char*, int, char**); + +void +rcv(void) +{ + int c; + static state = 0; + static count = 0; + static i = 0; + static int errs = 0; + + while((c=rcvchar()) != -1) + switch(state){ + case 0: + h.type = c; + state++; + break; + + case 1: + h.count0 = c; + state++; + break; + + case 2: + h.count1 = c; + count = h.count0|(h.count1<<8); + i = 0; + if(count > DATASIZE){ + if(++errs < 5){ + dumperrmsg(count, h.type, h.count0, c); + state = 0; + continue; + } + fprint(2, "type %d count %d\n", h.type, count); + panic("count>DATASIZE"); + } + if(count == 0) + goto zerocount; + state++; + break; + + case 3: + indata[i++] = c; + if(i == count){ + zerocount: + indata[i] = 0; + inmesg(h.type, count); + state = count = 0; + continue; + } + break; + } +} + +Text * +whichtext(int tg) +{ + int i; + + for(i=0; inwin>0) + closeup(&((Text *)l)->l[((Text *)l)->front]); + text[i] = t; + text[i]->tag = m; + break; + + case Hcurrent: + if(whichmenu(m)<0) + break; + t = whichtext(m); + i = which && ((Text *)which->user1)==&cmd && m!=cmd.tag; + if(t==0 && (t = sweeptext(0, m))==0) + break; + if(t->l[t->front].textfn==0) + panic("Hcurrent"); + lp = &t->l[t->front]; + if(i){ + flupfront(lp); + flborder(lp, 0); + work = lp; + }else + current(lp); + break; + + case Hmovname: + if((m=whichmenu(m)) < 0) + break; + t = text[m]; + l = tag[m]; + i = name[m][0]; + text[m] = 0; /* suppress panic in menudel */ + menudel(m); + if(t == &cmd) + m = 0; + else{ + if (nname>0 && text[0]==&cmd) + m = 1; + else m = 0; + for(; m= 0) + hgrow(m, l, inlong(6), 1); + break; + + case Hnewname: + menuins(0, (uchar *)"", (Text *)0, ' ', m); + break; + + case Hcheck0: + i = whichmenu(m); + if(i>=0) { + t = text[i]; + if(t) + t->lock++; + outTs(Tcheck, m); + } + break; + + case Hcheck: + i = whichmenu(m); + if(i>=0) { + t = text[i]; + if(t && t->lock) + t->lock--; + hcheck(m); + } + break; + + case Hunlock: + clrlock(); + break; + + case Hdata: + if(whichmenu(m) >= 0) + l += hdata(m, l, indata+6, count-6); + Checkscroll: + if(m == cmd.tag){ + for(i=0; itextfn) + center(lp, l>=0? l : lp->p1); + } + } + break; + + case Horigin: + if(whichmenu(m) >= 0) + horigin(m, l); + break; + + case Hunlockfile: + if(whichmenu(m)>=0 && (t = whichtext(m))->lock){ + --t->lock; + l = -1; + goto Checkscroll; + } + break; + + case Hsetdot: + if(whichmenu(m) >= 0) + hsetdot(m, l, inlong(6)); + break; + + case Hgrowdata: + if(whichmenu(m)<0) + break; + hgrow(m, l, inlong(6), 0); + whichtext(m)->lock++; /* fake the request */ + l += hdata(m, l, indata+10, count-10); + goto Checkscroll; + + case Hmoveto: + if(whichmenu(m)>=0) + hmoveto(m, l); + break; + + case Hclean: + if((m = whichmenu(m)) >= 0) + name[m][0] = ' '; + break; + + case Hdirty: + if((m = whichmenu(m))>=0) + name[m][0] = '\''; + break; + + case Hdelname: + if((m=whichmenu(m)) >= 0) + menudel(m); + break; + + case Hcut: + if(whichmenu(m) >= 0) + hcut(m, l, inlong(6)); + break; + + case Hclose: + if(whichmenu(m)<0 || (t = whichtext(m))==0) + break; + l = t->nwin; + for(i = 0,lp = t->l; l>0 && itextfn){ + closeup(lp); + --l; + } + break; + + case Hsetpat: + setpat((char *)indata); + break; + + case Hsetsnarf: + hsetsnarf(m); + break; + + case Hsnarflen: + snarflen = inlong(0); + break; + + case Hack: + outT0(Tack); + break; + + case Hexit: + exiting = 1; + outT0(Texit); + threadexitsall(nil); + break; + + case Hplumb: + hplumb(m); + break; + } +} + +void +setlock(void) +{ + hostlock++; + setcursor(mousectl, cursor = &lockarrow); +} + +void +clrlock(void) +{ + hasunlocked = 1; + if(hostlock > 0) + hostlock--; + if(hostlock == 0) + setcursor(mousectl, cursor=(Cursor *)0); +} + +void +startfile(Text *t) +{ + outTsv(Tstartfile, t->tag, (vlong)t); /* for 64-bit pointers */ + setlock(); +} + +void +startnewfile(int type, Text *t) +{ + t->tag = Untagged; + outTv(type, (vlong)t); /* for 64-bit pointers */ +} + +int +inshort(int n) +{ + return indata[n]|(indata[n+1]<<8); +} + +long +inlong(int n) +{ + return indata[n]|(indata[n+1]<<8)| + ((long)indata[n+2]<<16)|((long)indata[n+3]<<24); +} + +vlong +invlong(int n) +{ + vlong v; + + v = (indata[n+7]<<24) | (indata[n+6]<<16) | (indata[n+5]<<8) | indata[n+4]; + v = (v<<16) | (indata[n+3]<<8) | indata[n+2]; + v = (v<<16) | (indata[n+1]<<8) | indata[n]; + return v; +} + +void +outT0(Tmesg type) +{ + outstart(type); + outsend(); +} + +void +outTl(Tmesg type, long l) +{ + outstart(type); + outlong(l); + outsend(); +} + +void +outTs(Tmesg type, int s) +{ + outstart(type); + outshort(s); + outsend(); +} + +void +outTss(Tmesg type, int s1, int s2) +{ + outstart(type); + outshort(s1); + outshort(s2); + outsend(); +} + +void +outTsll(Tmesg type, int s1, long l1, long l2) +{ + outstart(type); + outshort(s1); + outlong(l1); + outlong(l2); + outsend(); +} + +void +outTsl(Tmesg type, int s1, long l1) +{ + outstart(type); + outshort(s1); + outlong(l1); + outsend(); +} + +void +outTsv(Tmesg type, int s1, vlong v1) +{ + outstart(type); + outshort(s1); + outvlong(v1); + outsend(); +} + +void +outTv(Tmesg type, vlong v1) +{ + outstart(type); + outvlong(v1); + outsend(); +} + +void +outTslS(Tmesg type, int s1, long l1, Rune *s) +{ + char buf[DATASIZE*UTFmax+1]; + char *c; + + outstart(type); + outshort(s1); + outlong(l1); + c = buf; + while(*s) + c += runetochar(c, s++); + *c++ = 0; + outcopy(c-buf, (uchar *)buf); + outsend(); +} + +void +outTsls(Tmesg type, int s1, long l1, int s2) +{ + outstart(type); + outshort(s1); + outlong(l1); + outshort(s2); + outsend(); +} + +void +outstart(Tmesg type) +{ + outdata[0] = type; + outcount = 0; +} + +void +outcopy(int count, uchar *data) +{ + while(count--) + outdata[HSIZE+outcount++] = *data++; +} + +void +outshort(int s) +{ + uchar buf[2]; + + buf[0]=s; + buf[1]=s>>8; + outcopy(2, buf); +} + +void +outlong(long l) +{ + uchar buf[4]; + + buf[0]=l; + buf[1]=l>>8; + buf[2]=l>>16; + buf[3]=l>>24; + outcopy(4, buf); +} + +void +outvlong(vlong v) +{ + int i; + uchar buf[8]; + + for(i = 0; i < sizeof(buf); i++){ + buf[i] = v; + v >>= 8; + } + + outcopy(8, buf); +} + +void +outsend(void) +{ + if(outcount>DATASIZE-HSIZE) + panic("outcount>sizeof outdata"); + outdata[1]=outcount; + outdata[2]=outcount>>8; + if(write(1, (char *)outdata, outcount+HSIZE)!=outcount+HSIZE) + panic("write error"); +} + + +void +hsetdot(int m, long p0, long p1) +{ + Text *t = whichtext(m); + Flayer *l = &t->l[t->front]; + + flushtyping(1); + flsetselect(l, p0, p1); +} + +void +horigin(int m, long p0) +{ + Text *t = whichtext(m); + Flayer *l = &t->l[t->front]; + long a; + ulong n; + Rune *r; + + if(!flprepare(l)){ + l->origin = p0; + return; + } + a = p0-l->origin; + if(a>=0 && af.nchars) + frdelete(&l->f, 0, a); + else if(a<0 && -af.nchars){ + r = rload(&t->rasp, p0, l->origin, &n); + frinsert(&l->f, r, r+n, 0); + }else + frdelete(&l->f, 0, l->f.nchars); + l->origin = p0; + scrdraw(l, t->rasp.nrunes); + if(l->visible==Some) + flrefresh(l, l->entire, 0); + hcheck(m); +} + +void +hmoveto(int m, long p0) +{ + Text *t = whichtext(m); + Flayer *l = &t->l[t->front]; + + if(p0origin || p0-l->origin>l->f.nchars*9/10) + outTsll(Torigin, m, p0, 2L); +} + +void +hcheck(int m) +{ + Flayer *l; + Text *t; + int reqd = 0, i; + long n, nl, a; + Rune *r; + + if(m == Untagged) + return; + t = whichtext(m); + if(t == 0) /* possible in a half-built window */ + return; + for(l = &t->l[0], i = 0; itextfn==0 || !flprepare(l)) /* BUG: don't + need this if BUG below + is fixed */ + continue; + a = t->l[i].origin; + n = rcontig(&t->rasp, a, a+l->f.nchars, 1); + if(nf.nchars) /* text missing in middle of screen */ + a+=n; + else{ /* text missing at end of screen? */ + Again: + if(l->f.lastlinefull) + goto Checksel; /* all's well */ + a = t->l[i].origin+l->f.nchars; + n = t->rasp.nrunes-a; + if(n==0) + goto Checksel; + if(n>TBLOCKSIZE) + n = TBLOCKSIZE; + n = rcontig(&t->rasp, a, a+n, 1); + if(n>0){ + rload(&t->rasp, a, a+n, 0); + nl = l->f.nchars; + r = scratch; + flinsert(l, r, r+n, l->origin+nl); + if(nl == l->f.nchars) /* made no progress */ + goto Checksel; + goto Again; + } + } + if(!reqd){ + n = rcontig(&t->rasp, a, a+TBLOCKSIZE, 0); + if(n <= 0) + panic("hcheck request==0"); + outTsls(Trequest, m, a, (int)n); + outTs(Tcheck, m); + t->lock++; /* for the Trequest */ + t->lock++; /* for the Tcheck */ + reqd++; + } + Checksel: + flsetselect(l, l->p0, l->p1); + } +} + +void +flnewlyvisible(Flayer *l) +{ + hcheck(((Text *)l->user1)->tag); +} + +void +hsetsnarf(int nc) +{ + char *s2; + char *s1; + int i; + int n; + + setcursor(mousectl, &deadmouse); + s2 = alloc(nc+1); + for(i=0; i= 0){ + if(!s1) + n = 0; + s1 = realloc(s1, n+1); + if (!s1) + panic("realloc"); + s1[n] = 0; + snarflen = n; + outTs(Tsetsnarf, n); + if(n>0 && write(1, s1, n)!=n) + panic("snarf write error"); + free(s1); + }else + outTs(Tsetsnarf, 0); + free(s2); + setcursor(mousectl, cursor); +} + +void +hplumb(int nc) +{ + int i; + char *s; + Plumbmsg *m; + + s = alloc(nc); + for(i=0; i= 0){ + m = plumbunpack(s, nc); + if(m != 0) + plumbsend(plumbfd, m); + plumbfree(m); + } + free(s); +} + +void +hgrow(int m, long a, long new, int req) +{ + int i; + Flayer *l; + Text *t = whichtext(m); + long o, b; + + if(new <= 0) + panic("hgrow"); + rresize(&t->rasp, a, 0L, new); + for(l = &t->l[0], i = 0; itextfn == 0) + continue; + o = l->origin; + b = a-o-rmissing(&t->rasp, o, a); + if(a < o) + l->origin+=new; + if(a < l->p0) + l->p0+=new; + if(a < l->p1) + l->p1+=new; + /* must prevent b temporarily becoming unsigned */ + if(!req || a0 && b>l->f.nchars) || + (l->f.nchars==0 && a-o>0)) + continue; + if(new>TBLOCKSIZE) + new = TBLOCKSIZE; + outTsls(Trequest, m, a, (int)new); + t->lock++; + req = 0; + } +} + +int +hdata1(Text *t, long a, Rune *r, int len) +{ + int i; + Flayer *l; + long o, b; + + for(l = &t->l[0], i=0; itextfn==0) + continue; + o = l->origin; + b = a-o-rmissing(&t->rasp, o, a); + /* must prevent b temporarily becoming unsigned */ + if(a0 && b>l->f.nchars)) + continue; + flinsert(l, r, r+len, o+b); + } + rdata(&t->rasp, a, a+len, r); + rclean(&t->rasp); + return len; +} + +int +hdata(int m, long a, uchar *s, int len) +{ + int i, w; + Text *t = whichtext(m); + Rune buf[DATASIZE], *r; + + if(t->lock) + --t->lock; + if(len == 0) + return 0; + r = buf; + for(i=0; ilock) + --t->lock; + if(len == 0) + return 0; + return hdata1(t, a, r, len); +} + +void +hcut(int m, long a, long old) +{ + Flayer *l; + Text *t = whichtext(m); + int i; + long o, b; + + if(t->lock) + --t->lock; + for(l = &t->l[0], i = 0; itextfn == 0) + continue; + o = l->origin; + b = a-o-rmissing(&t->rasp, o, a); + /* must prevent b temporarily becoming unsigned */ + if((b<0 || bf.nchars) && a+old>=o){ + fldelete(l, b<0? o : o+b, + a+old-rmissing(&t->rasp, o, a+old)); + } + if(a+oldorigin-=old; + else if(a<=o) + l->origin = a; + if(a+oldp0) + l->p0-=old; + else if(a<=l->p0) + l->p0 = a; + if(a+oldp1) + l->p1-=old; + else if(a<=l->p1) + l->p1 = a; + } + rresize(&t->rasp, a, old, 0L); + rclean(&t->rasp); +} diff --git a/sys/src/cmd/samterm.mono/mkfile b/sys/src/cmd/samterm.mono/mkfile new file mode 100644 index 000000000..0f360e674 --- /dev/null +++ b/sys/src/cmd/samterm.mono/mkfile @@ -0,0 +1,36 @@ + syms + for(i in *.c) $CC -aa $CFLAGS $i >> syms diff --git a/sys/src/cmd/samterm.mono/plan9.c b/sys/src/cmd/samterm.mono/plan9.c new file mode 100644 index 000000000..1fa199fb7 --- /dev/null +++ b/sys/src/cmd/samterm.mono/plan9.c @@ -0,0 +1,274 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include "flayer.h" +#include "samterm.h" + +enum { + STACK = 4096, +}; + +static char exname[64]; + +void +usage(void) +{ + fprint(2, "usage: samterm [-ai]\n"); + threadexitsall("usage"); +} + +void +getscreen(int argc, char **argv) +{ + char *t; + + ARGBEGIN{ + case 'a': + autoindent = 1; + break; + case 'i': + spacesindent = 1; + break; + default: + usage(); + }ARGEND + + if(initdraw(panic1, nil, "sam") < 0){ + fprint(2, "samterm: initdraw: %r\n"); + threadexitsall("init"); + } + t = getenv("tabstop"); + if(t != nil) + maxtab = strtoul(t, nil, 0); + free(t); + draw(screen, screen->clipr, display->black, nil, ZP); +} + +int +screensize(int *w, int *h) +{ + int fd, n; + char buf[5*12+1]; + + fd = open("/dev/screen", OREAD); + if(fd < 0) + return 0; + n = read(fd, buf, sizeof(buf)-1); + close(fd); + if (n != sizeof(buf)-1) + return 0; + buf[n] = 0; + if (h) { + *h = atoi(buf+4*12)-atoi(buf+2*12); + if (*h < 0) + return 0; + } + if (w) { + *w = atoi(buf+3*12)-atoi(buf+1*12); + if (*w < 0) + return 0; + } + return 1; +} + +int +snarfswap(char *fromsam, int nc, char **tosam) +{ + char *s1; + int f, n, ss; + + f = open("/dev/snarf", 0); + if(f < 0) + return -1; + ss = SNARFSIZE; + if(hversion < 2) + ss = 4096; + *tosam = s1 = alloc(ss); + n = read(f, s1, ss-1); + close(f); + if(n < 0) + n = 0; + if (n == 0) { + *tosam = 0; + free(s1); + } else + s1[n] = 0; + f = create("/dev/snarf", 1, 0666); + if(f >= 0){ + write(f, fromsam, nc); + close(f); + } + return n; +} + +void +dumperrmsg(int count, int type, int count0, int c) +{ + fprint(2, "samterm: host mesg: count %d %ux %ux %ux %s...ignored\n", + count, type, count0, c, rcvstring()); +} + +void +removeextern(void) +{ + remove(exname); +} + +Readbuf hostbuf[2]; +Readbuf plumbbuf[2]; + +void +extproc(void *argv) +{ + Channel *c; + int i, n, which, *fdp; + void **arg; + + arg = argv; + c = arg[0]; + fdp = arg[1]; + + i = 0; + for(;;){ + i = 1-i; /* toggle */ + n = read(*fdp, plumbbuf[i].data, sizeof plumbbuf[i].data); + if(n <= 0){ + fprint(2, "samterm: extern read error: %r\n"); + threadexits("extern"); /* not a fatal error */ + } + plumbbuf[i].n = n; + which = i; + send(c, &which); + } +} + +int +plumbformat(int i) +{ + Plumbmsg *m; + char *addr, *data, *act; + int n; + + data = (char*)plumbbuf[i].data; + m = plumbunpack(data, plumbbuf[i].n); + if(m == nil) + return 0; + n = m->ndata; + if(n == 0){ + plumbfree(m); + return 0; + } + act = plumblookup(m->attr, "action"); + if(act!=nil && strcmp(act, "showfile")!=0){ + /* can't handle other cases yet */ + plumbfree(m); + return 0; + } + addr = plumblookup(m->attr, "addr"); + if(addr){ + if(addr[0] == '\0') + addr = nil; + else + addr = strdup(addr); /* copy to safe storage; we'll overwrite data */ + } + memmove(data, "B ", 2); /* we know there's enough room for this */ + memmove(data+2, m->data, n); + n += 2; + if(data[n-1] != '\n') + data[n++] = '\n'; + if(addr != nil){ + if(n+strlen(addr)+1+1 <= READBUFSIZE) + n += sprint(data+n, "%s\n", addr); + free(addr); + } + plumbbuf[i].n = n; + plumbfree(m); + return 1; +} + +void +plumbproc(void *argv) +{ + Channel *c; + int i, n, which, *fdp; + void **arg; + + arg = argv; + c = arg[0]; + fdp = arg[1]; + + i = 0; + for(;;){ + i = 1-i; /* toggle */ + n = read(*fdp, plumbbuf[i].data, READBUFSIZE); + if(n <= 0){ + fprint(2, "samterm: plumb read error: %r\n"); + threadexits("plumb"); /* not a fatal error */ + } + plumbbuf[i].n = n; + if(plumbformat(i)){ + which = i; + send(c, &which); + } + } +} + +int +plumbstart(void) +{ + static int fd; + static void *arg[2]; + + plumbfd = plumbopen("send", OWRITE|OCEXEC); /* not open is ok */ + fd = plumbopen("edit", OREAD|OCEXEC); + if(fd < 0) + return -1; + plumbc = chancreate(sizeof(int), 0); + if(plumbc == nil){ + close(fd); + return -1; + } + arg[0] =plumbc; + arg[1] = &fd; + proccreate(plumbproc, arg, STACK); + return 1; +} + +void +hostproc(void *arg) +{ + Channel *c; + int i, n, which; + + c = arg; + + i = 0; + for(;;){ + i = 1-i; /* toggle */ + n = read(0, hostbuf[i].data, sizeof hostbuf[i].data); + if(n <= 0){ + if(n==0){ + if(exiting) + threadexits(nil); + werrstr("unexpected eof"); + } + fprint(2, "samterm: host read error: %r\n"); + threadexitsall("host"); + } + hostbuf[i].n = n; + which = i; + send(c, &which); + } +} + +void +hoststart(void) +{ + hostc = chancreate(sizeof(int), 0); + proccreate(hostproc, hostc, STACK); +} diff --git a/sys/src/cmd/samterm.mono/rasp.c b/sys/src/cmd/samterm.mono/rasp.c new file mode 100644 index 000000000..52f03edb1 --- /dev/null +++ b/sys/src/cmd/samterm.mono/rasp.c @@ -0,0 +1,265 @@ +#include +#include +#include +#include +#include +#include +#include +#include "flayer.h" +#include "samterm.h" + +void +rinit(Rasp *r) +{ + r->nrunes=0; + r->sect=0; +} + +void +rclear(Rasp *r) +{ + Section *s, *ns; + + for(s=r->sect; s; s=ns){ + ns = s->next; + free(s->text); + free(s); + } + r->sect = 0; +} + +Section* +rsinsert(Rasp *r, Section *s) /* insert before s */ +{ + Section *t; + Section *u; + + t = alloc(sizeof(Section)); + if(r->sect == s){ /* includes empty list case: r->sect==s==0 */ + r->sect = t; + t->next = s; + }else{ + u = r->sect; + if(u == 0) + panic("rsinsert 1"); + do{ + if(u->next == s){ + t->next = s; + u->next = t; + goto Return; + } + u=u->next; + }while(u); + panic("rsinsert 2"); + } + Return: + return t; +} + +void +rsdelete(Rasp *r, Section *s) +{ + Section *t; + + if(s == 0) + panic("rsdelete"); + if(r->sect == s){ + r->sect = s->next; + goto Free; + } + for(t=r->sect; t; t=t->next) + if(t->next == s){ + t->next = s->next; + Free: + if(s->text) + free(s->text); + free(s); + return; + } + panic("rsdelete 2"); +} + +void +splitsect(Rasp *r, Section *s, long n0) +{ + if(s == 0) + panic("splitsect"); + rsinsert(r, s->next); + if(s->text == 0) + s->next->text = 0; + else{ + s->next->text = alloc(RUNESIZE*(TBLOCKSIZE+1)); + Strcpy(s->next->text, s->text+n0); + s->text[n0] = 0; + } + s->next->nrunes = s->nrunes-n0; + s->nrunes = n0; +} + +Section * +findsect(Rasp *r, Section *s, long p, long q) /* find sect containing q and put q on a sect boundary */ +{ + if(s==0 && p!=q) + panic("findsect"); + for(; s && p+s->nrunes<=q; s=s->next) + p += s->nrunes; + if(p != q){ + splitsect(r, s, q-p); + s = s->next; + } + return s; +} + +void +rresize(Rasp *r, long a, long old, long new) +{ + Section *s, *t, *ns; + + s = findsect(r, r->sect, 0L, a); + t = findsect(r, s, a, a+old); + for(; s!=t; s=ns){ + ns=s->next; + rsdelete(r, s); + } + /* now insert the new piece before t */ + if(new > 0){ + ns=rsinsert(r, t); + ns->nrunes=new; + ns->text=0; + } + r->nrunes += new-old; +} + +void +rdata(Rasp *r, long p0, long p1, Rune *cp) +{ + Section *s, *t, *ns; + + s = findsect(r, r->sect, 0L, p0); + t = findsect(r, s, p0, p1); + for(; s!=t; s=ns){ + ns=s->next; + if(s->text) + panic("rdata"); + rsdelete(r, s); + } + p1 -= p0; + s = rsinsert(r, t); + s->text = alloc(RUNESIZE*(TBLOCKSIZE+1)); + memmove(s->text, cp, RUNESIZE*p1); + s->text[p1] = 0; + s->nrunes = p1; +} + +void +rclean(Rasp *r) +{ + Section *s; + + for(s=r->sect; s; s=s->next) + while(s->next && (s->text!=0)==(s->next->text!=0)){ + if(s->text){ + if(s->nrunes+s->next->nrunes>TBLOCKSIZE) + break; + Strcpy(s->text+s->nrunes, s->next->text); + } + s->nrunes += s->next->nrunes; + rsdelete(r, s->next); + } +} + +void +Strcpy(Rune *to, Rune *from) +{ + do; while(*to++ = *from++); +} + +Rune* +rload(Rasp *r, ulong p0, ulong p1, ulong *nrp) +{ + Section *s; + long p; + int n, nb; + + nb = 0; + Strgrow(&scratch, &nscralloc, p1-p0+1); + scratch[0] = 0; + for(p=0,s=r->sect; s && p+s->nrunes<=p0; s=s->next) + p += s->nrunes; + while(ptext){ + n = s->nrunes-(p0-p); + if(n>p1-p0) /* all in this section */ + n = p1-p0; + memmove(scratch+nb, s->text+(p0-p), n*RUNESIZE); + nb += n; + scratch[nb] = 0; + } + p += s->nrunes; + p0 = p; + s = s->next; + } + if(nrp) + *nrp = nb; + return scratch; +} + +int +rmissing(Rasp *r, ulong p0, ulong p1) +{ + Section *s; + long p; + int n, nm=0; + + for(p=0,s=r->sect; s && p+s->nrunes<=p0; s=s->next) + p += s->nrunes; + while(ptext == 0){ + n = s->nrunes-(p0-p); + if(n > p1-p0) /* all in this section */ + n = p1-p0; + nm += n; + } + p += s->nrunes; + p0 = p; + s = s->next; + } + return nm; +} + +int +rcontig(Rasp *r, ulong p0, ulong p1, int text) +{ + Section *s; + long p, n; + int np=0; + + for(p=0,s=r->sect; s && p+s->nrunes<=p0; s=s->next) + p += s->nrunes; + while(ptext!=0) : (s->text==0))){ + n = s->nrunes-(p0-p); + if(n > p1-p0) /* all in this section */ + n = p1-p0; + np += n; + p += s->nrunes; + p0 = p; + s = s->next; + } + return np; +} + +void +Strgrow(Rune **s, long *n, int want) /* can always toss the old data when called */ +{ + if(*n >= want) + return; + free(*s); + *s = alloc(RUNESIZE*want); + *n = want; +} diff --git a/sys/src/cmd/samterm.mono/samterm.h b/sys/src/cmd/samterm.mono/samterm.h new file mode 100644 index 000000000..264d148e2 --- /dev/null +++ b/sys/src/cmd/samterm.mono/samterm.h @@ -0,0 +1,181 @@ +#define SAMTERM + +#define RUNESIZE sizeof(Rune) +#define MAXFILES 256 +#define READBUFSIZE 8192 +#define NL 5 + +enum{ + Up, + Down, + + Kbel=0x7, +}; + +typedef struct Text Text; +typedef struct Section Section; +typedef struct Rasp Rasp; +typedef struct Readbuf Readbuf; + +struct Section +{ + long nrunes; + Rune *text; /* if null, we haven't got it */ + Section *next; +}; + +struct Rasp +{ + long nrunes; + Section *sect; +}; + +#define Untagged ((ushort)65535) + +struct Text +{ + Rasp rasp; + short nwin; + short front; /* input window */ + ushort tag; + char lock; + Flayer l[NL]; /* screen storage */ +}; + +struct Readbuf +{ + short n; /* # bytes in buf */ + uchar data[READBUFSIZE]; /* data bytes */ +}; + +enum Resource +{ + RHost, + RKeyboard, + RMouse, + RPlumb, + RResize, + NRes, +}; + +extern Text **text; +extern uchar **name; +extern ushort *tag; +extern int nname; +extern int mname; +extern Cursor bullseye; +extern Cursor deadmouse; +extern Cursor lockarrow; +extern Cursor *cursor; +extern Flayer *which; +extern Flayer *work; +extern Text cmd; +extern Rune *scratch; +extern long nscralloc; +extern char hostlock; +extern char hasunlocked; +extern long snarflen; +extern Mousectl* mousectl; +extern Keyboardctl* keyboardctl; +extern Mouse* mousep; +extern long modified; +extern int maxtab; +extern Readbuf hostbuf[2]; /* double buffer; it's synchronous communication */ +extern Readbuf plumbbuf[2]; /* double buffer; it's synchronous communication */ +extern Channel *plumbc; +extern Channel *hostc; +extern int hversion; +extern int plumbfd; +extern int exiting; +extern int autoindent; +extern int spacesindent; + +Rune *gettext(Flayer*, long, ulong*); +void *alloc(ulong n); + +void iconinit(void); +void getscreen(int, char**); +void initio(void); +void setlock(void); +void outcmd(void); +void rinit(Rasp*); +void startnewfile(int, Text*); +void getmouse(void); +void mouseunblock(void); +void kbdblock(void); +void hoststart(void); +int plumbstart(void); +int button(int but); +int load(char*, int); +int waitforio(void); +int rcvchar(void); +int getch(void); +int kbdchar(void); +int qpeekc(void); +void cut(Text*, int, int, int); +void paste(Text*, int); +void snarf(Text*, int); +int center(Flayer*, long); +int xmenuhit(int, Menu*); +void buttons(int); +int getr(Rectangle*); +void current(Flayer*); +void duplicate(Flayer*, Rectangle, Font*, int); +void startfile(Text*); +void panic(char*); +void panic1(Display*, char*); +void closeup(Flayer*); +void Strgrow(Rune**, long*, int); +int RESIZED(void); +void resize(void); +void rcv(void); +void type(Flayer*, int); +void menu2hit(void); +void menu3hit(void); +void scroll(Flayer*, int); +void hcheck(int); +void rclear(Rasp*); +int whichmenu(int); +void hcut(int, long, long); +void horigin(int, long); +void hgrow(int, long, long, int); +int hdata(int, long, uchar*, int); +int hdatarune(int, long, Rune*, int); +Rune *rload(Rasp*, ulong, ulong, ulong*); +void menuins(int, uchar*, Text*, int, int); +void menudel(int); +Text *sweeptext(int, int); +void setpat(char*); +void scrdraw(Flayer*, long tot); +int rcontig(Rasp*, ulong, ulong, int); +int rmissing(Rasp*, ulong, ulong); +void rresize(Rasp *, long, long, long); +void rdata(Rasp*, long, long, Rune*); +void rclean(Rasp*); +void scrorigin(Flayer*, int, long); +long scrtotal(Flayer*); +void flnewlyvisible(Flayer*); +char *rcvstring(void); +void Strcpy(Rune*, Rune*); +void Strncpy(Rune*, Rune*, long); +void flushtyping(int); +void dumperrmsg(int, int, int, int); +int screensize(int*,int*); +void getmouse(void); + +#include "mesg.h" + +void outTs(Tmesg, int); +void outT0(Tmesg); +void outTl(Tmesg, long); +void outTslS(Tmesg, int, long, Rune*); +void outTsll(Tmesg, int, long, long); +void outTsl(Tmesg, int, long); +void outTsv(Tmesg, int, vlong); +void outTv(Tmesg, vlong); +void outstart(Tmesg); +void outcopy(int, uchar*); +void outshort(int); +void outlong(long); +void outvlong(vlong); +void outsend(void); diff --git a/sys/src/cmd/samterm.mono/scroll.c b/sys/src/cmd/samterm.mono/scroll.c new file mode 100644 index 000000000..e710cc910 --- /dev/null +++ b/sys/src/cmd/samterm.mono/scroll.c @@ -0,0 +1,177 @@ +#include +#include +#include +#include +#include +#include +#include +#include "flayer.h" +#include "samterm.h" + +static Image *scrtmp; +static Image *scrback; + +void +scrtemps(void) +{ + int h; + + if(scrtmp) + return; + if(screensize(0, &h) == 0) + h = 2048; + scrtmp = allocimage(display, Rect(0, 0, 32, h), screen->chan, 0, 0); + scrback = allocimage(display, Rect(0, 0, 32, h), screen->chan, 0, 0); + if(scrtmp==0 || scrback==0) + panic("scrtemps"); +} + +Rectangle +scrpos(Rectangle r, long p0, long p1, long tot) +{ + Rectangle q; + int h; + + q = r; + h = q.max.y-q.min.y; + if(tot == 0) + return q; + if(tot > 1024L*1024L) + tot>>=10, p0>>=10, p1>>=10; + if(p0 > 0) + q.min.y += h*p0/tot; + if(p1 < tot) + q.max.y -= h*(tot-p1)/tot; + if(q.max.y < q.min.y+2){ + if(q.min.y+2 <= r.max.y) + q.max.y = q.min.y+2; + else + q.min.y = q.max.y-2; + } + return q; +} + +void +scrmark(Flayer *l, Rectangle r) +{ + r.max.x--; + if(rectclip(&r, l->scroll)) { + if (l->f.b == nil) + panic("scrmark: nil l->f.b"); + draw(l->f.b, r, l->f.cols[HIGH], nil, ZP); + } +} + +void +scrunmark(Flayer *l, Rectangle r) +{ + if(rectclip(&r, l->scroll)) { + if (l->f.b == nil) + panic("scrunmark: nil l->f.b"); + draw(l->f.b, r, scrback, nil, Pt(0, r.min.y-l->scroll.min.y)); + } +} + +void +scrdraw(Flayer *l, long tot) +{ + Rectangle r, r1, r2; + Image *b; + + scrtemps(); + if(l->f.b == 0) + panic("scrdraw"); + r = l->scroll; + r1 = r; + if(l->visible == All){ + b = scrtmp; + r1.min.x = 0; + r1.max.x = Dx(r); + }else + b = l->f.b; + r2 = scrpos(r1, l->origin, l->origin+l->f.nchars, tot); + if(!eqrect(r2, l->lastsr)){ + l->lastsr = r2; + draw(b, r1, l->f.cols[BORD], nil, ZP); + draw(b, r2, l->f.cols[BACK], nil, r2.min); + r2 = r1; + r2.min.x = r2.max.x-1; + draw(b, r2, l->f.cols[BORD], nil, ZP); + if(b!=l->f.b) + draw(l->f.b, r, b, nil, r1.min); + } +} + +void +scroll(Flayer *l, int but) +{ + int in = 0, oin; + long tot = scrtotal(l); + Rectangle scr, r, s, rt; + int x, y, my, oy, h; + long p0; + + if(l->visible==None) + return; + + s = l->scroll; + x = s.min.x+FLSCROLLWID/2; + scr = scrpos(l->scroll, l->origin, l->origin+l->f.nchars, tot); + r = scr; + y = scr.min.y; + my = mousep->xy.y; + draw(scrback, Rect(0,0,Dx(l->scroll), Dy(l->scroll)), l->f.b, nil, l->scroll.min); + do{ + oin = in; + in = (but > 3) || (but == 2) || abs(x-mousep->xy.x)<=FLSCROLLWID/2; + if(oin && !in) + scrunmark(l, r); + if(in){ + scrmark(l, r); + oy = y; + my = mousep->xy.y; + if(my < s.min.y) + my = s.min.y; + if(my >= s.max.y) + my = s.max.y; + if(but == 1 || but == 4){ + p0 = l->origin-frcharofpt(&l->f, Pt(s.max.x, my)); + rt = scrpos(l->scroll, p0, p0+l->f.nchars, tot); + y = rt.min.y; + }else if(but == 2){ + y = my; + if(y > s.max.y-2) + y = s.max.y-2; + }else if(but == 3 || but == 5){ + p0 = l->origin+frcharofpt(&l->f, Pt(s.max.x, my)); + rt = scrpos(l->scroll, p0, p0+l->f.nchars, tot); + y = rt.min.y; + } + if(y != oy){ + scrunmark(l, r); + r = rectaddpt(scr, Pt(0, y-scr.min.y)); + scrmark(l, r); + } + } + }while(but <= 3 && button(but)); + if(in){ + h = s.max.y-s.min.y; + scrunmark(l, r); + p0 = 0; + if(but == 1 || but == 4){ + but = 1; + p0 = (long)(my-s.min.y)/l->f.font->height+1; + }else if(but == 2){ + if(tot > 1024L*1024L) + p0 = ((tot>>10)*(y-s.min.y)/h)<<10; + else + p0 = tot*(y-s.min.y)/h; + }else if(but == 3 || but == 5){ + but = 3; + p0 = l->origin+frcharofpt(&l->f, Pt(s.max.x, my)); + if(p0 > tot) + p0 = tot; + } + scrorigin(l, but, p0); + } +} diff --git a/sys/src/cmd/samterm.mono/syms b/sys/src/cmd/samterm.mono/syms new file mode 100644 index 000000000..895afc676 --- /dev/null +++ b/sys/src/cmd/samterm.mono/syms @@ -0,0 +1,1055 @@ +sizeof_1_ = 8; +aggr _1_ +{ + 'D' 0 hlength; + 'D' 4 llength; +}; + +defn +_1_(addr) { + complex _1_ addr; + print(" hlength ", addr.hlength, "\n"); + print(" llength ", addr.llength, "\n"); +}; + +sizeof_2_ = 8; +aggr _2_ +{ + 'V' 0 length; + { + 'D' 0 hlength; + 'D' 4 llength; + }; +}; + +defn +_2_(addr) { + complex _2_ addr; + print(" length ", addr.length, "\n"); + print("_1_ {\n"); + _1_(addr+0); + print("}\n"); +}; + +UTFmax = 3; +Runesync = 128; +Runeself = 128; +Runeerror = 128; +sizeofFconv = 24; +aggr Fconv +{ + 'X' 0 out; + 'X' 4 eout; + 'D' 8 f1; + 'D' 12 f2; + 'D' 16 f3; + 'D' 20 chr; +}; + +defn +Fconv(addr) { + complex Fconv addr; + print(" out ", addr.out\X, "\n"); + print(" eout ", addr.eout\X, "\n"); + print(" f1 ", addr.f1, "\n"); + print(" f2 ", addr.f2, "\n"); + print(" f3 ", addr.f3, "\n"); + print(" chr ", addr.chr, "\n"); +}; + +sizeofTm = 40; +aggr Tm +{ + 'D' 0 sec; + 'D' 4 min; + 'D' 8 hour; + 'D' 12 mday; + 'D' 16 mon; + 'D' 20 year; + 'D' 24 wday; + 'D' 28 yday; + 'a' 32 zone; + 'D' 36 tzoff; +}; + +defn +Tm(addr) { + complex Tm addr; + print(" sec ", addr.sec, "\n"); + print(" min ", addr.min, "\n"); + print(" hour ", addr.hour, "\n"); + print(" mday ", addr.mday, "\n"); + print(" mon ", addr.mon, "\n"); + print(" year ", addr.year, "\n"); + print(" wday ", addr.wday, "\n"); + print(" yday ", addr.yday, "\n"); + print(" zone ", addr.zone, "\n"); + print(" tzoff ", addr.tzoff, "\n"); +}; + +PNPROC = 1; +PNGROUP = 2; +sizeofLock = 4; +aggr Lock +{ + 'D' 0 val; +}; + +defn +Lock(addr) { + complex Lock addr; + print(" val ", addr.val, "\n"); +}; + +sizeofQLp = 12; +aggr QLp +{ + 'D' 0 inuse; + 'A' QLp 4 next; + 'C' 8 state; +}; + +defn +QLp(addr) { + complex QLp addr; + print(" inuse ", addr.inuse, "\n"); + print(" next ", addr.next\X, "\n"); + print(" state ", addr.state, "\n"); +}; + +sizeofQLock = 16; +aggr QLock +{ + Lock 0 lock; + 'D' 4 locked; + 'A' QLp 8 $head; + 'A' QLp 12 $tail; +}; + +defn +QLock(addr) { + complex QLock addr; + print("Lock lock {\n"); + Lock(addr.lock); + print("}\n"); + print(" locked ", addr.locked, "\n"); + print(" $head ", addr.$head\X, "\n"); + print(" $tail ", addr.$tail\X, "\n"); +}; + +sizeofRWLock = 20; +aggr RWLock +{ + Lock 0 lock; + 'D' 4 readers; + 'D' 8 writer; + 'A' QLp 12 $head; + 'A' QLp 16 $tail; +}; + +defn +RWLock(addr) { + complex RWLock addr; + print("Lock lock {\n"); + Lock(addr.lock); + print("}\n"); + print(" readers ", addr.readers, "\n"); + print(" writer ", addr.writer, "\n"); + print(" $head ", addr.$head\X, "\n"); + print(" $tail ", addr.$tail\X, "\n"); +}; + +RFNAMEG = 1; +RFENVG = 2; +RFFDG = 4; +RFNOTEG = 8; +RFPROC = 16; +RFMEM = 32; +RFNOWAIT = 64; +RFCNAMEG = 1024; +RFCENVG = 2048; +RFCFDG = 4096; +RFREND = 8192; +sizeofQid = 8; +aggr Qid +{ + 'U' 0 path; + 'U' 4 vers; +}; + +defn +Qid(addr) { + complex Qid addr; + print(" path ", addr.path, "\n"); + print(" vers ", addr.vers, "\n"); +}; + +sizeofDir = 116; +aggr Dir +{ + 'a' 0 name; + 'a' 28 uid; + 'a' 56 gid; + Qid 84 qid; + 'U' 92 mode; + 'D' 96 atime; + 'D' 100 mtime; + { + 'V' 104 length; + { + 'D' 104 hlength; + 'D' 108 llength; + }; + }; + 'u' 112 type; + 'u' 114 dev; +}; + +defn +Dir(addr) { + complex Dir addr; + print(" name ", addr.name, "\n"); + print(" uid ", addr.uid, "\n"); + print(" gid ", addr.gid, "\n"); + print("Qid qid {\n"); + Qid(addr.qid); + print("}\n"); + print(" mode ", addr.mode, "\n"); + print(" atime ", addr.atime, "\n"); + print(" mtime ", addr.mtime, "\n"); + print("_2_ {\n"); + _2_(addr+104); + print("}\n"); + print(" type ", addr.type, "\n"); + print(" dev ", addr.dev, "\n"); +}; + +sizeofWaitmsg = 112; +aggr Waitmsg +{ + 'a' 0 pid; + 'a' 12 time; + 'a' 48 msg; +}; + +defn +Waitmsg(addr) { + complex Waitmsg addr; + print(" pid ", addr.pid, "\n"); + print(" time ", addr.time, "\n"); + print(" msg ", addr.msg, "\n"); +}; + +DBlack = 255; +DBlue = 201; +DRed = 15; +DYellow = 3; +DGreen = 192; +DWhite = 0; +Displaybufsize = 8000; +ICOSSCALE = 1024; +Borderwidth = 4; +Refbackup = 0; +Refnone = 1; +Refmesg = 2; +Endsquare = 0; +Enddisc = 1; +Endarrow = 2; +Endmask = 31; +sizeofPoint = 8; +aggr Point +{ + 'D' 0 x; + 'D' 4 y; +}; + +defn +Point(addr) { + complex Point addr; + print(" x ", addr.x, "\n"); + print(" y ", addr.y, "\n"); +}; + +sizeofRectangle = 16; +aggr Rectangle +{ + Point 0 min; + Point 8 max; +}; + +defn +Rectangle(addr) { + complex Rectangle addr; + print("Point min {\n"); + Point(addr.min); + print("}\n"); + print("Point max {\n"); + Point(addr.max); + print("}\n"); +}; + +sizeofScreen = 16; +aggr Screen +{ + 'X' 0 display; + 'D' 4 id; + 'X' 8 image; + 'X' 12 fill; +}; + +defn +Screen(addr) { + complex Screen addr; + print(" display ", addr.display\X, "\n"); + print(" id ", addr.id, "\n"); + print(" image ", addr.image\X, "\n"); + print(" fill ", addr.fill\X, "\n"); +}; + +sizeofDisplay = 8156; +aggr Display +{ + QLock 0 qlock; + 'D' 16 dirno; + 'D' 20 fd; + 'D' 24 reffd; + 'D' 28 ctlfd; + 'D' 32 imageid; + 'D' 36 $local; + 'D' 40 ldepth; + 'X' 44 error; + 'X' 48 devdir; + 'X' 52 windir; + 'a' 56 oldlabel; + 'U' 120 dataqid; + 'X' 124 ones; + 'X' 128 zeros; + 'X' 132 image; + 'a' 136 buf; + 'X' 8140 bufp; + 'X' 8144 defaultfont; + 'X' 8148 defaultsubfont; + 'X' 8152 windows; +}; + +defn +Display(addr) { + complex Display addr; + print("QLock qlock {\n"); + QLock(addr.qlock); + print("}\n"); + print(" dirno ", addr.dirno, "\n"); + print(" fd ", addr.fd, "\n"); + print(" reffd ", addr.reffd, "\n"); + print(" ctlfd ", addr.ctlfd, "\n"); + print(" imageid ", addr.imageid, "\n"); + print(" $local ", addr.$local, "\n"); + print(" ldepth ", addr.ldepth, "\n"); + print(" error ", addr.error\X, "\n"); + print(" devdir ", addr.devdir\X, "\n"); + print(" windir ", addr.windir\X, "\n"); + print(" oldlabel ", addr.oldlabel, "\n"); + print(" dataqid ", addr.dataqid, "\n"); + print(" ones ", addr.ones\X, "\n"); + print(" zeros ", addr.zeros\X, "\n"); + print(" image ", addr.image\X, "\n"); + print(" buf ", addr.buf, "\n"); + print(" bufp ", addr.bufp\X, "\n"); + print(" defaultfont ", addr.defaultfont\X, "\n"); + print(" defaultsubfont ", addr.defaultsubfont\X, "\n"); + print(" windows ", addr.windows\X, "\n"); +}; + +sizeofImage = 56; +aggr Image +{ + 'A' Display 0 display; + 'D' 4 id; + Rectangle 8 r; + Rectangle 24 clipr; + 'D' 40 ldepth; + 'D' 44 repl; + 'A' Screen 48 screen; + 'A' Image 52 next; +}; + +defn +Image(addr) { + complex Image addr; + print(" display ", addr.display\X, "\n"); + print(" id ", addr.id, "\n"); + print("Rectangle r {\n"); + Rectangle(addr.r); + print("}\n"); + print("Rectangle clipr {\n"); + Rectangle(addr.clipr); + print("}\n"); + print(" ldepth ", addr.ldepth, "\n"); + print(" repl ", addr.repl, "\n"); + print(" screen ", addr.screen\X, "\n"); + print(" next ", addr.next\X, "\n"); +}; + +sizeofRGB = 12; +aggr RGB +{ + 'U' 0 red; + 'U' 4 green; + 'U' 8 blue; +}; + +defn +RGB(addr) { + complex RGB addr; + print(" red ", addr.red, "\n"); + print(" green ", addr.green, "\n"); + print(" blue ", addr.blue, "\n"); +}; + +sizeofFontchar = 8; +aggr Fontchar +{ + 'D' 0 x; + 'b' 4 top; + 'b' 5 bottom; + 'C' 6 left; + 'b' 7 width; +}; + +defn +Fontchar(addr) { + complex Fontchar addr; + print(" x ", addr.x, "\n"); + print(" top ", addr.top, "\n"); + print(" bottom ", addr.bottom, "\n"); + print(" left ", addr.left, "\n"); + print(" width ", addr.width, "\n"); +}; + +sizeofSubfont = 16; +aggr Subfont +{ + 'X' 0 name; + 'd' 4 n; + 'b' 6 height; + 'C' 7 ascent; + 'A' Fontchar 8 info; + 'A' Image 12 bits; +}; + +defn +Subfont(addr) { + complex Subfont addr; + print(" name ", addr.name\X, "\n"); + print(" n ", addr.n, "\n"); + print(" height ", addr.height, "\n"); + print(" ascent ", addr.ascent, "\n"); + print(" info ", addr.info\X, "\n"); + print(" bits ", addr.bits\X, "\n"); +}; + +LOG2NFCACHE = 6; +NFCACHE = 64; +NFLOOK = 5; +NFSUBF = 2; +MAXFCACHE = 1029; +MAXSUBF = 50; +DSUBF = 4; +SUBFAGE = 10000; +CACHEAGE = 10000; +sizeofCachefont = 16; +aggr Cachefont +{ + 'u' 0 min; + 'u' 2 max; + 'D' 4 offset; + 'X' 8 name; + 'X' 12 subfontname; +}; + +defn +Cachefont(addr) { + complex Cachefont addr; + print(" min ", addr.min, "\n"); + print(" max ", addr.max, "\n"); + print(" offset ", addr.offset, "\n"); + print(" name ", addr.name\X, "\n"); + print(" subfontname ", addr.subfontname\X, "\n"); +}; + +sizeofCacheinfo = 8; +aggr Cacheinfo +{ + 'u' 0 x; + 'b' 2 width; + 'C' 3 left; + 'u' 4 value; + 'u' 6 age; +}; + +defn +Cacheinfo(addr) { + complex Cacheinfo addr; + print(" x ", addr.x, "\n"); + print(" width ", addr.width, "\n"); + print(" left ", addr.left, "\n"); + print(" value ", addr.value, "\n"); + print(" age ", addr.age, "\n"); +}; + +sizeofCachesubf = 12; +aggr Cachesubf +{ + 'U' 0 age; + 'A' Cachefont 4 cf; + 'A' Subfont 8 f; +}; + +defn +Cachesubf(addr) { + complex Cachesubf addr; + print(" age ", addr.age, "\n"); + print(" cf ", addr.cf\X, "\n"); + print(" f ", addr.f\X, "\n"); +}; + +sizeofFont = 52; +aggr Font +{ + 'X' 0 name; + 'A' Display 4 display; + 'd' 8 height; + 'd' 10 ascent; + 'D' 12 maxldepth; + 'd' 16 width; + 'd' 18 ldepth; + 'd' 20 nsub; + 'U' 24 age; + 'D' 28 ncache; + 'D' 32 nsubf; + 'A' Cacheinfo 36 cache; + 'A' Cachesubf 40 subf; + 'A' Cachefont 44 sub; + 'A' Image 48 cacheimage; +}; + +defn +Font(addr) { + complex Font addr; + print(" name ", addr.name\X, "\n"); + print(" display ", addr.display\X, "\n"); + print(" height ", addr.height, "\n"); + print(" ascent ", addr.ascent, "\n"); + print(" maxldepth ", addr.maxldepth, "\n"); + print(" width ", addr.width, "\n"); + print(" ldepth ", addr.ldepth, "\n"); + print(" nsub ", addr.nsub, "\n"); + print(" age ", addr.age, "\n"); + print(" ncache ", addr.ncache, "\n"); + print(" nsubf ", addr.nsubf, "\n"); + print(" cache ", addr.cache\X, "\n"); + print(" subf ", addr.subf\X, "\n"); + print(" sub ", addr.sub\X, "\n"); + print(" cacheimage ", addr.cacheimage\X, "\n"); +}; + +complex Point ZP; +complex Rectangle ZR; +complex Display display; +complex Font font; +complex Image screen; +sizeofAlt = 20; +aggr Alt +{ + 'X' 0 c; + 'X' 4 v; + 'D' 8 op; + 'X' 12 tag; + 'U' 16 q; +}; + +defn +Alt(addr) { + complex Alt addr; + print(" c ", addr.c\X, "\n"); + print(" v ", addr.v\X, "\n"); + print(" op ", addr.op, "\n"); + print(" tag ", addr.tag\X, "\n"); + print(" q ", addr.q, "\n"); +}; + +sizeofRef = 4; +aggr Ref +{ + 'D' 0 ref; +}; + +defn +Ref(addr) { + complex Ref addr; + print(" ref ", addr.ref, "\n"); +}; + +sizeofCursor = 72; +aggr Cursor +{ + Point 0 offset; + 'a' 8 clr; + 'a' 40 set; +}; + +defn +Cursor(addr) { + complex Cursor addr; + print("Point offset {\n"); + Point(addr.offset); + print("}\n"); + print(" clr ", addr.clr, "\n"); + print(" set ", addr.set, "\n"); +}; + +sizeofMouse = 16; +aggr Mouse +{ + 'D' 0 buttons; + Point 4 xy; + 'U' 12 msec; +}; + +defn +Mouse(addr) { + complex Mouse addr; + print(" buttons ", addr.buttons, "\n"); + print("Point xy {\n"); + Point(addr.xy); + print("}\n"); + print(" msec ", addr.msec, "\n"); +}; + +sizeofMousectl = 44; +aggr Mousectl +{ + { + 'D' 0 buttons; + Point 4 xy; + 'U' 12 msec; + }; + 'X' 16 c; + 'X' 20 reshapec; + 'X' 24 file; + 'D' 28 mfd; + 'D' 32 cfd; + 'D' 36 pid; + 'A' Image 40 image; +}; + +defn +Mousectl(addr) { + complex Mousectl addr; + print("Mouse {\n"); + Mouse(addr+0); + print("}\n"); + print(" c ", addr.c\X, "\n"); + print(" reshapec ", addr.reshapec\X, "\n"); + print(" file ", addr.file\X, "\n"); + print(" mfd ", addr.mfd, "\n"); + print(" cfd ", addr.cfd, "\n"); + print(" pid ", addr.pid, "\n"); + print(" image ", addr.image\X, "\n"); +}; + +sizeofMenu = 12; +aggr Menu +{ + 'X' 0 item; + 'X' 4 gen; + 'D' 8 lasthit; +}; + +defn +Menu(addr) { + complex Menu addr; + print(" item ", addr.item\X, "\n"); + print(" gen ", addr.gen\X, "\n"); + print(" lasthit ", addr.lasthit, "\n"); +}; + +sizeofKeyboardctl = 20; +aggr Keyboardctl +{ + 'X' 0 c; + 'X' 4 file; + 'D' 8 consfd; + 'D' 12 ctlfd; + 'D' 16 pid; +}; + +defn +Keyboardctl(addr) { + complex Keyboardctl addr; + print(" c ", addr.c\X, "\n"); + print(" file ", addr.file\X, "\n"); + print(" consfd ", addr.consfd, "\n"); + print(" ctlfd ", addr.ctlfd, "\n"); + print(" pid ", addr.pid, "\n"); +}; + +BACK = 0; +HIGH = 1; +BORD = 2; +TEXT = 3; +HTEXT = 4; +NCOL = 5; +sizeof_3_ = 4; +aggr _3_ +{ + 'd' 0 bc; + 'd' 2 minwid; +}; + +defn +_3_(addr) { + complex _3_ addr; + print(" bc ", addr.bc, "\n"); + print(" minwid ", addr.minwid, "\n"); +}; + +sizeof_4_ = 4; +aggr _4_ +{ + 'X' 0 ptr; + { + 'd' 0 bc; + 'd' 2 minwid; + }; +}; + +defn +_4_(addr) { + complex _4_ addr; + print(" ptr ", addr.ptr\X, "\n"); + print("_3_ {\n"); + _3_(addr+0); + print("}\n"); +}; + +sizeofFrbox = 12; +aggr Frbox +{ + 'D' 0 wid; + 'D' 4 nrune; + { + 'X' 8 ptr; + { + 'd' 8 bc; + 'd' 10 minwid; + }; + }; +}; + +defn +Frbox(addr) { + complex Frbox addr; + print(" wid ", addr.wid, "\n"); + print(" nrune ", addr.nrune, "\n"); + print("_4_ {\n"); + _4_(addr+8); + print("}\n"); +}; + +complex Font font; +complex Display display; +sizeofFrame = 108; +aggr Frame +{ + 'A' Font 0 font; + 'A' Display 4 display; + 'A' Image 8 b; + 'a' 12 cols; + Rectangle 32 r; + Rectangle 48 entire; + 'X' 64 scroll; + 'A' Frbox 68 box; + 'U' 72 p0; + 'U' 76 p1; + 'u' 80 nbox; + 'u' 82 nalloc; + 'u' 84 maxtab; + 'u' 86 nchars; + 'u' 88 nlines; + 'u' 90 maxlines; + 'u' 92 lastlinefull; + 'u' 94 modified; + 'A' Image 96 tick; + 'A' Image 100 tickback; + 'D' 104 ticked; +}; + +defn +Frame(addr) { + complex Frame addr; + print(" font ", addr.font\X, "\n"); + print(" display ", addr.display\X, "\n"); + print(" b ", addr.b\X, "\n"); + print(" cols ", addr.cols, "\n"); + print("Rectangle r {\n"); + Rectangle(addr.r); + print("}\n"); + print("Rectangle entire {\n"); + Rectangle(addr.entire); + print("}\n"); + print(" scroll ", addr.scroll\X, "\n"); + print(" box ", addr.box\X, "\n"); + print(" p0 ", addr.p0, "\n"); + print(" p1 ", addr.p1, "\n"); + print(" nbox ", addr.nbox, "\n"); + print(" nalloc ", addr.nalloc, "\n"); + print(" maxtab ", addr.maxtab, "\n"); + print(" nchars ", addr.nchars, "\n"); + print(" nlines ", addr.nlines, "\n"); + print(" maxlines ", addr.maxlines, "\n"); + print(" lastlinefull ", addr.lastlinefull, "\n"); + print(" modified ", addr.modified, "\n"); + print(" tick ", addr.tick\X, "\n"); + print(" tickback ", addr.tickback\X, "\n"); + print(" ticked ", addr.ticked, "\n"); +}; + +None = 0; +Some = 1; +All = 2; +Clicktime = 1000; +sizeofFlayer = 172; +aggr Flayer +{ + Frame 0 f; + 'D' 108 origin; + 'D' 112 p0; + 'D' 116 p1; + 'D' 120 click; + 'X' 124 textfn; + 'D' 128 user0; + 'X' 132 user1; + Rectangle 136 entire; + Rectangle 152 scroll; + 'D' 168 visible; +}; + +defn +Flayer(addr) { + complex Flayer addr; + print("Frame f {\n"); + Frame(addr.f); + print("}\n"); + print(" origin ", addr.origin, "\n"); + print(" p0 ", addr.p0, "\n"); + print(" p1 ", addr.p1, "\n"); + print(" click ", addr.click, "\n"); + print(" textfn ", addr.textfn\X, "\n"); + print(" user0 ", addr.user0, "\n"); + print(" user1 ", addr.user1\X, "\n"); + print("Rectangle entire {\n"); + Rectangle(addr.entire); + print("}\n"); + print("Rectangle scroll {\n"); + Rectangle(addr.scroll); + print("}\n"); + print(" visible ", addr.visible, "\n"); +}; + +Up = 0; +Down = 1; +sizeofSection = 12; +aggr Section +{ + 'D' 0 nrunes; + 'X' 4 text; + 'A' Section 8 next; +}; + +defn +Section(addr) { + complex Section addr; + print(" nrunes ", addr.nrunes, "\n"); + print(" text ", addr.text\X, "\n"); + print(" next ", addr.next\X, "\n"); +}; + +sizeofRasp = 8; +aggr Rasp +{ + 'D' 0 nrunes; + 'A' Section 4 sect; +}; + +defn +Rasp(addr) { + complex Rasp addr; + print(" nrunes ", addr.nrunes, "\n"); + print(" sect ", addr.sect\X, "\n"); +}; + +sizeofText = 876; +aggr Text +{ + Rasp 0 rasp; + 'd' 8 nwin; + 'd' 10 front; + 'u' 12 tag; + 'C' 14 lock; + 'a' 16 l; +}; + +defn +Text(addr) { + complex Text addr; + print("Rasp rasp {\n"); + Rasp(addr.rasp); + print("}\n"); + print(" nwin ", addr.nwin, "\n"); + print(" front ", addr.front, "\n"); + print(" tag ", addr.tag, "\n"); + print(" lock ", addr.lock, "\n"); + print(" l ", addr.l, "\n"); +}; + +sizeofReadbuf = 8196; +aggr Readbuf +{ + 'd' 0 n; + 'a' 2 data; +}; + +defn +Readbuf(addr) { + complex Readbuf addr; + print(" n ", addr.n, "\n"); + print(" data ", addr.data, "\n"); +}; + +RHost = 0; +RKeyboard = 1; +RMouse = 2; +RPlumb = 3; +RReshape = 4; +NRes = 5; +complex Cursor bullseye; +complex Cursor deadmouse; +complex Cursor lockarrow; +complex Cursor cursor; +complex Flayer which; +complex Flayer work; +complex Text cmd; +complex Mousectl mousectl; +complex Keyboardctl keyboardctl; +complex Mouse mousep; +Tversion = 0; +Tstartcmdfile = 1; +Tcheck = 2; +Trequest = 3; +Torigin = 4; +Tstartfile = 5; +Tworkfile = 6; +Ttype = 7; +Tcut = 8; +Tpaste = 9; +Tsnarf = 10; +Tstartnewfile = 11; +Twrite = 12; +Tclose = 13; +Tlook = 14; +Tsearch = 15; +Tsend = 16; +Tdclick = 17; +Tstartsnarf = 18; +Tsetsnarf = 19; +Tack = 20; +Texit = 21; +Tplumb = 22; +TMAX = 23; +Hversion = 0; +Hbindname = 1; +Hcurrent = 2; +Hnewname = 3; +Hmovname = 4; +Hgrow = 5; +Hcheck0 = 6; +Hcheck = 7; +Hunlock = 8; +Hdata = 9; +Horigin = 10; +Hunlockfile = 11; +Hsetdot = 12; +Hgrowdata = 13; +Hmoveto = 14; +Hclean = 15; +Hdirty = 16; +Hcut = 17; +Hsetpat = 18; +Hdelname = 19; +Hclose = 20; +Hsetsnarf = 21; +Hsnarflen = 22; +Hack = 23; +Hexit = 24; +Hplumb = 25; +HMAX = 26; +sizeofHeader = 4; +aggr Header +{ + 'b' 0 type; + 'b' 1 count0; + 'b' 2 count1; + 'a' 3 data; +}; + +defn +Header(addr) { + complex Header addr; + print(" type ", addr.type, "\n"); + print(" count0 ", addr.count0, "\n"); + print(" count1 ", addr.count1, "\n"); + print(" data ", addr.data, "\n"); +}; + +complex Text cmd; +complex Cursor cursor; +complex Flayer which; +complex Flayer work; +complex Text threadmain:t; +complex Rectangle threadmain:r; +complex Flayer threadmain:nwhich; +complex Flayer current:nw; +complex Text current:t; +complex Flayer closeup:l; +complex Text closeup:t; +complex Text findl:t; +complex Flayer duplicate:l; +complex Rectangle duplicate:r; +complex Font duplicate:f; +complex Text duplicate:t; +complex Flayer duplicate:nl; +complex Rectangle getr:rp; +complex Point getr:p; +complex Rectangle getr:r; +complex Text snarf:t; +complex Flayer snarf:l; +complex Text cut:t; +complex Flayer cut:l; +complex Text paste:t; +complex Flayer scrorigin:l; +complex Text scrorigin:t; +complex Rasp raspc:r; +complex Rasp ctlw:r; +complex Rasp ctlu:r; +complex Flayer center:l; +complex Text center:t; +complex Flayer onethird:l; +complex Text onethird:t; +complex Rectangle onethird:s; +complex Text flushtyping:t; +complex Flayer type:l; +complex Text type:t; +complex Flayer gettext:l; +complex Text gettext:t; +complex Flayer scrtotal:l; diff --git a/sys/src/cmd/samterm/flayer.c b/sys/src/cmd/samterm/flayer.c index 2dd023e3c..7dd6897d5 100644 --- a/sys/src/cmd/samterm/flayer.c +++ b/sys/src/cmd/samterm/flayer.c @@ -29,17 +29,17 @@ flstart(Rectangle r) lDrect = r; /* Main text is yellowish */ - maincols[BACK] = display->black; - maincols[HIGH] = allocimage(display, Rect(0,0,1,1), screen->chan, 1, 0x555555FF); - maincols[BORD] = allocimage(display, Rect(0,0,2,2), screen->chan, 1, 0x222222FF); - maincols[TEXT] = display->white; + maincols[BACK] = allocimagemix(display, DPaleyellow, DWhite); + maincols[HIGH] = allocimage(display, Rect(0,0,1,1), screen->chan, 1, DDarkyellow); + maincols[BORD] = allocimage(display, Rect(0,0,2,2), screen->chan, 1, DYellowgreen); + maincols[TEXT] = display->black; maincols[HTEXT] = display->black; /* Command text is blueish */ - cmdcols[BACK] = display->black; - cmdcols[HIGH] = allocimage(display, Rect(0,0,1,1), screen->chan, 1, 0x555555FF); - cmdcols[BORD] = allocimage(display, Rect(0,0,2,2), screen->chan, 1, 0x222222FF); - cmdcols[TEXT] = display->white; + cmdcols[BACK] = allocimagemix(display, DPalebluegreen, DWhite); + cmdcols[HIGH] = allocimage(display, Rect(0,0,1,1), screen->chan, 1, DPalegreygreen); + cmdcols[BORD] = allocimage(display, Rect(0,0,2,2), screen->chan, 1, DPurpleblue); + cmdcols[TEXT] = display->black; cmdcols[HTEXT] = display->black; } @@ -90,12 +90,12 @@ void flclose(Flayer *l) { if(l->visible == All) - draw(screen, l->entire, display->black, nil, ZP); + draw(screen, l->entire, display->white, nil, ZP); else if(l->visible == Some){ if(l->f.b == 0) l->f.b = allocimage(display, l->entire, screen->chan, 0, DNofill); if(l->f.b){ - draw(l->f.b, l->entire, display->black, nil, ZP); + draw(l->f.b, l->entire, display->white, nil, ZP); flrefresh(l, l->entire, 0); } } @@ -363,7 +363,7 @@ flresize(Rectangle dr) if(0 && Dx(dr)==Dx(olDrect) && Dy(dr)==Dy(olDrect)) move = 1; else - draw(screen, lDrect, display->black, nil, ZP); + draw(screen, lDrect, display->white, nil, ZP); for(i=0; ilastsr = ZR; diff --git a/sys/src/cmd/samterm/main.c b/sys/src/cmd/samterm/main.c index bd46bc677..33d98dfea 100644 --- a/sys/src/cmd/samterm/main.c +++ b/sys/src/cmd/samterm/main.c @@ -253,7 +253,7 @@ getr(Rectangle *rp) rp->min.y = r.max.y; return rectclip(rp, screen->r) && - rp->max.x-rp->min.x>100 && rp->max.y-rp->min.y>40; + rp->max.x-rp->min.x>100 && rp->max.y-rp->min.y>40; } void diff --git a/sys/src/cmd/samterm/plan9.c b/sys/src/cmd/samterm/plan9.c index 1fa199fb7..3d2065d82 100644 --- a/sys/src/cmd/samterm/plan9.c +++ b/sys/src/cmd/samterm/plan9.c @@ -46,7 +46,7 @@ getscreen(int argc, char **argv) if(t != nil) maxtab = strtoul(t, nil, 0); free(t); - draw(screen, screen->clipr, display->black, nil, ZP); + draw(screen, screen->clipr, display->white, nil, ZP); } int