123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664 |
- #include <u.h>
- #include <libc.h>
- #include <draw.h>
- #include <thread.h>
- #include <cursor.h>
- #include <mouse.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;
- int autoindent;
- 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)
- {
- 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 && (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 BACKSCROLLKEY Kup
- #define ENDKEY Kend
- #define ESC 0x1B
- #define HOMEKEY Khome
- #define LEFTARROW Kleft
- #define LINEEND 0x05
- #define LINESTART 0x01
- #define PAGEDOWN Kpgdown
- #define PAGEUP Kpgup
- #define RIGHTARROW Kright
- #define SCROLLKEY Kdown
- int
- nontypingkey(int c)
- {
- switch(c){
- case BACKSCROLLKEY:
- case ENDKEY:
- case HOMEKEY:
- case LEFTARROW:
- case LINEEND:
- case LINESTART:
- case PAGEDOWN:
- case PAGEUP:
- case RIGHTARROW:
- case SCROLLKEY:
- 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==ESC)
- break;
- /* backspace, ctrl-u, ctrl-w, del */
- if(c=='\b' || c==0x15 || c==0x17 || c==0x7F){
- backspacing = 1;
- break;
- }
- }
- *p++ = c;
- if(autoindent)
- if(c == '\n'){
- /* 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==SCROLLKEY || c==PAGEDOWN){
- flushtyping(0);
- center(l, l->origin+l->f.nchars+1);
- /* backspacing immediately after outcmd(): sorry */
- }else if(c==BACKSCROLLKEY || c==PAGEUP){
- flushtyping(0);
- a0 = l->origin-l->f.nchars;
- if(a0 < 0)
- a0 = 0;
- center(l, a0);
- }else if(c == RIGHTARROW){
- flushtyping(0);
- a0 = l->p0;
- if(a0 < t->rasp.nrunes)
- a0++;
- flsetselect(l, a0, a0);
- center(l, a0);
- }else if(c == LEFTARROW){
- flushtyping(0);
- a0 = l->p0;
- if(a0 > 0)
- a0--;
- flsetselect(l, a0, a0);
- center(l, a0);
- }else if(c == HOMEKEY){
- flushtyping(0);
- center(l, 0);
- }else if(c == ENDKEY){
- flushtyping(0);
- center(l, t->rasp.nrunes);
- }else if(c == LINESTART || c == LINEEND){
- flushtyping(1);
- if(c == LINESTART)
- 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 '\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*, 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;
- }
|