diff options
author | rsc <devnull@localhost> | 2003-09-30 17:47:44 +0000 |
---|---|---|
committer | rsc <devnull@localhost> | 2003-09-30 17:47:44 +0000 |
commit | 84b1cb73b3f0837f5b959579818158fbb2b1b206 (patch) | |
tree | 7e27c119d2c2fe00a70a39985c3715b3d8ca363b /src/cmd/samterm/main.c | |
parent | a59ea66fa99f7b6f03eac71dc0713c33f912b6ab (diff) | |
download | plan9port-84b1cb73b3f0837f5b959579818158fbb2b1b206.tar.gz plan9port-84b1cb73b3f0837f5b959579818158fbb2b1b206.tar.bz2 plan9port-84b1cb73b3f0837f5b959579818158fbb2b1b206.zip |
Initial revision
Diffstat (limited to 'src/cmd/samterm/main.c')
-rw-r--r-- | src/cmd/samterm/main.c | 585 |
1 files changed, 585 insertions, 0 deletions
diff --git a/src/cmd/samterm/main.c b/src/cmd/samterm/main.c new file mode 100644 index 00000000..ef958d78 --- /dev/null +++ b/src/cmd/samterm/main.c @@ -0,0 +1,585 @@ +#include <u.h> +#include <libc.h> +#include <draw.h> +#include <thread.h> +#include <mouse.h> +#include <cursor.h> +#include <keyboard.h> +#include <frame.h> +#include "flayer.h" +#include "samterm.h" + +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; + +void +threadmain(int argc, char *argv[]) +{ + int i, got, scr; + Text *t; + Rectangle r; + Flayer *nwhich; + + 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; + for(;;got = waitforio()){ + if(hasunlocked && RESIZED()) + resize(); + if(got&(1<<RHost)) + rcv(); + if(got&(1<<RPlumb)){ + for(i=0; cmd.l[i].textfn==0; i++) + ; + current(&cmd.l[i]); + flsetselect(which, cmd.rasp.nrunes, cmd.rasp.nrunes); + type(which, RPlumb); + } + if(got&(1<<RKeyboard)) + if(which) + type(which, RKeyboard); + else + kbdblock(); + if(got&(1<<RMouse)){ + if(hostlock==2 || !ptinrect(mousep->xy, screen->r)){ + mouseunblock(); + continue; + } + nwhich = flwhich(mousep->xy); + scr = which && ptinrect(mousep->xy, which->scroll); + if(mousep->buttons) + flushtyping(1); + if(mousep->buttons&1){ + if(nwhich){ + if(nwhich!=which) + current(nwhich); + else if(scr) + scroll(which, 1); + else{ + t=(Text *)which->user1; + if(flselect(which)){ + outTsl(Tdclick, t->tag, which->p0); + t->lock++; + }else if(t!=&cmd) + outcmd(); + } + } + }else if((mousep->buttons&2) && which){ + if(scr) + scroll(which, 2); + else + menu2hit(); + }else if((mousep->buttons&4)){ + if(scr) + scroll(which, 3); + else + menu3hit(); + } + mouseunblock(); + } + } +} + + +void +resize(void) +{ + int i; + + flresize(screen->clipr); + for(i = 0; i<nname; i++) + if(text[i]) + hcheck(text[i]->tag); +} + +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; m<NL; m++) /* find one; any one will do */ + if(t->l[m].textfn){ + t->front = m; + return; + } + panic("close"); + } +} + +Flayer * +findl(Text *t) +{ + int i; + for(i = 0; i<NL; i++) + if(t->l[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 = getrect(3, mousectl); + if(rp->max.x && rp->max.x-rp->min.x<=5 && rp->max.y-rp->min.y<=5){ + p = rp->min; + r = cmd.l[cmd.front].entire; + *rp = screen->r; + if(cmd.nwin==1){ + if (p.y <= r.min.y) + rp->max.y = r.min.y; + else if (p.y >= r.max.y) + rp->min.y = r.max.y; + if (p.x <= r.min.x) + rp->max.x = r.min.x; + else if (p.x >= r.max.x) + rp->min.x = r.max.x; + } + } + 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; + + 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; +} + +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) +{ + 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 && (a<l->origin || l->origin+l->f.nchars<a)){ + if(a > 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 && (a<l->origin || l->origin+l->f.nchars<a)){ + if(a > 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; +} + +#define SCROLLKEY Kdown +#define BACKSCROLLKEY Kup +#define ESC 0x1B + +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 = (qpeekc()==SCROLLKEY || qpeekc()==BACKSCROLLKEY); /* 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(c==SCROLLKEY || c==BACKSCROLLKEY || c==ESC) + break; + /* backspace, ctrl-u, ctrl-w, del */ + if(c=='\b' || c==0x15 || c==0x17 || c==0x7F){ + backspacing = 1; + break; + } + } + *p++ = c; + 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 == SCROLLKEY){ + flushtyping(0); + center(l, l->origin+l->f.nchars+1); + /* backspacing immediately after outcmd(): sorry */ + }else if(c == BACKSCROLLKEY){ + flushtyping(0); + a0 = l->origin-l->f.nchars; + if(a0 < 0) + a0 = 0; + center(l, a0); + }else if(backspacing && !hostlock){ + if(l->f.p0>0 && a>0){ + switch(c){ + case '\b': + case 0x7F: /* del */ + l->p0 = a-1; + break; + case 0x15: /* ctrl-u */ + l->p0 = ctlu(&t->rasp, l->origin, a); + break; + case 0x17: /* 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==ESC && 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 *d, 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; +} |