/* * This file is part of the UCB release of Plan 9. It is subject to the license * terms in the LICENSE file found in the top-level directory of this * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No * part of the UCB release of Plan 9, including this file, may be copied, * modified, propagated, or distributed except according to the terms contained * in the LICENSE file. */ #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" 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; voidthreadmain(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(); } }} voidresize(void){ int i; flresize(screen->clipr); for(i = 0; i<nname; i++) if(text[i]) hcheck(text[i]->tag);} voidcurrent(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;} voidcloseup(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;} voidduplicate(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);} voidbuttons(int updown){ while(((mousep->buttons&7)!=0) != updown) getmouse();} intgetr(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;} voidsnarf(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); }} voidcut(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);} voidpaste(Text *t, int w){ if(snarflen){ cut(t, w, 0, 0); t->lock++; outTsl(Tpaste, t->tag, t->l[w].p0); }} voidscrorigin(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); }} intalnum(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;} intraspc(Rasp *r, long p){ ulong n; rload(r, p, p+1, &n); if(n) return scratch[0]; return 0;} longctlw(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;} longctlu(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;} intcenter(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;} intonethird(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;} voidflushtyping(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 intnontypingkey(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;} voidtype(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;Lines 1–500 of 675. Load more
/* * This file is part of the UCB release of Plan 9. It is subject to the license * terms in the LICENSE file found in the top-level directory of this * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No * part of the UCB release of Plan 9, including this file, may be copied, * modified, propagated, or distributed except according to the terms contained * in the LICENSE file. */ #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" 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; 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;