13e12c5d1SDavid du Colombier #include <u.h>
23e12c5d1SDavid du Colombier #include <libc.h>
37dd7cddfSDavid du Colombier #include <draw.h>
47dd7cddfSDavid du Colombier #include <thread.h>
57dd7cddfSDavid du Colombier #include <cursor.h>
67dd7cddfSDavid du Colombier #include <mouse.h>
77dd7cddfSDavid du Colombier #include <keyboard.h>
83e12c5d1SDavid du Colombier #include <frame.h>
93e12c5d1SDavid du Colombier #include "flayer.h"
103e12c5d1SDavid du Colombier #include "samterm.h"
113e12c5d1SDavid du Colombier
12a1216cc6SDavid du Colombier int mainstacksize = 16*1024;
13a1216cc6SDavid du Colombier
143e12c5d1SDavid du Colombier Text cmd;
153e12c5d1SDavid du Colombier Rune *scratch;
163e12c5d1SDavid du Colombier long nscralloc;
173e12c5d1SDavid du Colombier Cursor *cursor;
183e12c5d1SDavid du Colombier Flayer *which = 0;
193e12c5d1SDavid du Colombier Flayer *work = 0;
203e12c5d1SDavid du Colombier long snarflen;
213e12c5d1SDavid du Colombier long typestart = -1;
223e12c5d1SDavid du Colombier long typeend = -1;
233e12c5d1SDavid du Colombier long typeesc = -1;
243e12c5d1SDavid du Colombier long modified = 0; /* strange lookahead for menus */
257dd7cddfSDavid du Colombier char hostlock = 1;
263e12c5d1SDavid du Colombier char hasunlocked = 0;
277dd7cddfSDavid du Colombier int maxtab = 8;
28e7d29567SDavid du Colombier int autoindent;
293e12c5d1SDavid du Colombier
303e12c5d1SDavid du Colombier void
threadmain(int argc,char * argv[])317dd7cddfSDavid du Colombier threadmain(int argc, char *argv[])
323e12c5d1SDavid du Colombier {
33bd389b36SDavid du Colombier int i, got, scr;
343e12c5d1SDavid du Colombier Text *t;
353e12c5d1SDavid du Colombier Rectangle r;
363e12c5d1SDavid du Colombier Flayer *nwhich;
373e12c5d1SDavid du Colombier
383e12c5d1SDavid du Colombier getscreen(argc, argv);
393e12c5d1SDavid du Colombier iconinit();
403e12c5d1SDavid du Colombier initio();
413e12c5d1SDavid du Colombier scratch = alloc(100*RUNESIZE);
423e12c5d1SDavid du Colombier nscralloc = 100;
437dd7cddfSDavid du Colombier r = screen->r;
443e12c5d1SDavid du Colombier r.max.y = r.min.y+Dy(r)/5;
457dd7cddfSDavid du Colombier flstart(screen->clipr);
463e12c5d1SDavid du Colombier rinit(&cmd.rasp);
473e12c5d1SDavid du Colombier flnew(&cmd.l[0], gettext, 1, &cmd);
487dd7cddfSDavid du Colombier flinit(&cmd.l[0], r, font, cmdcols);
493e12c5d1SDavid du Colombier cmd.nwin = 1;
503e12c5d1SDavid du Colombier which = &cmd.l[0];
513e12c5d1SDavid du Colombier cmd.tag = Untagged;
523e12c5d1SDavid du Colombier outTs(Tversion, VERSION);
533e12c5d1SDavid du Colombier startnewfile(Tstartcmdfile, &cmd);
543e12c5d1SDavid du Colombier
553e12c5d1SDavid du Colombier got = 0;
563e12c5d1SDavid du Colombier for(;;got = waitforio()){
577dd7cddfSDavid du Colombier if(hasunlocked && RESIZED())
587dd7cddfSDavid du Colombier resize();
597dd7cddfSDavid du Colombier if(got&(1<<RHost))
603e12c5d1SDavid du Colombier rcv();
617dd7cddfSDavid du Colombier if(got&(1<<RPlumb)){
62bd389b36SDavid du Colombier for(i=0; cmd.l[i].textfn==0; i++)
63bd389b36SDavid du Colombier ;
64bd389b36SDavid du Colombier current(&cmd.l[i]);
65bd389b36SDavid du Colombier flsetselect(which, cmd.rasp.nrunes, cmd.rasp.nrunes);
667dd7cddfSDavid du Colombier type(which, RPlumb);
67bd389b36SDavid du Colombier }
687dd7cddfSDavid du Colombier if(got&(1<<RKeyboard))
693e12c5d1SDavid du Colombier if(which)
70bd389b36SDavid du Colombier type(which, RKeyboard);
713e12c5d1SDavid du Colombier else
723e12c5d1SDavid du Colombier kbdblock();
737dd7cddfSDavid du Colombier if(got&(1<<RMouse)){
747dd7cddfSDavid du Colombier if(hostlock==2 || !ptinrect(mousep->xy, screen->r)){
753e12c5d1SDavid du Colombier mouseunblock();
763e12c5d1SDavid du Colombier continue;
773e12c5d1SDavid du Colombier }
787dd7cddfSDavid du Colombier nwhich = flwhich(mousep->xy);
797dd7cddfSDavid du Colombier scr = which && ptinrect(mousep->xy, which->scroll);
807dd7cddfSDavid du Colombier if(mousep->buttons)
813e12c5d1SDavid du Colombier flushtyping(1);
827dd7cddfSDavid du Colombier if(mousep->buttons&1){
833e12c5d1SDavid du Colombier if(nwhich){
843e12c5d1SDavid du Colombier if(nwhich!=which)
853e12c5d1SDavid du Colombier current(nwhich);
863e12c5d1SDavid du Colombier else if(scr)
873e12c5d1SDavid du Colombier scroll(which, 1);
883e12c5d1SDavid du Colombier else{
893e12c5d1SDavid du Colombier t=(Text *)which->user1;
903e12c5d1SDavid du Colombier if(flselect(which)){
913e12c5d1SDavid du Colombier outTsl(Tdclick, t->tag, which->p0);
923e12c5d1SDavid du Colombier t->lock++;
933e12c5d1SDavid du Colombier }else if(t!=&cmd)
943e12c5d1SDavid du Colombier outcmd();
953e12c5d1SDavid du Colombier }
963e12c5d1SDavid du Colombier }
977dd7cddfSDavid du Colombier }else if((mousep->buttons&2) && which){
983e12c5d1SDavid du Colombier if(scr)
993e12c5d1SDavid du Colombier scroll(which, 2);
1003e12c5d1SDavid du Colombier else
1013e12c5d1SDavid du Colombier menu2hit();
1027dd7cddfSDavid du Colombier }else if((mousep->buttons&4)){
1033e12c5d1SDavid du Colombier if(scr)
1043e12c5d1SDavid du Colombier scroll(which, 3);
1053e12c5d1SDavid du Colombier else
1063e12c5d1SDavid du Colombier menu3hit();
107*a12e914dSDavid du Colombier }else if((mousep->buttons&8)){
108*a12e914dSDavid du Colombier scroll(which, 4);
109*a12e914dSDavid du Colombier }else if((mousep->buttons&16)){
110*a12e914dSDavid du Colombier scroll(which, 5);
1113e12c5d1SDavid du Colombier }
1123e12c5d1SDavid du Colombier mouseunblock();
1133e12c5d1SDavid du Colombier }
1143e12c5d1SDavid du Colombier }
1153e12c5d1SDavid du Colombier }
1163e12c5d1SDavid du Colombier
1173e12c5d1SDavid du Colombier
1183e12c5d1SDavid du Colombier void
resize(void)119e7d29567SDavid du Colombier resize(void)
120e7d29567SDavid du Colombier {
1213e12c5d1SDavid du Colombier int i;
1223e12c5d1SDavid du Colombier
1237dd7cddfSDavid du Colombier flresize(screen->clipr);
1243e12c5d1SDavid du Colombier for(i = 0; i<nname; i++)
1253e12c5d1SDavid du Colombier if(text[i])
1263e12c5d1SDavid du Colombier hcheck(text[i]->tag);
1273e12c5d1SDavid du Colombier }
1283e12c5d1SDavid du Colombier
1293e12c5d1SDavid du Colombier void
current(Flayer * nw)1303e12c5d1SDavid du Colombier current(Flayer *nw)
1313e12c5d1SDavid du Colombier {
1323e12c5d1SDavid du Colombier Text *t;
1333e12c5d1SDavid du Colombier
1343e12c5d1SDavid du Colombier if(which)
1353e12c5d1SDavid du Colombier flborder(which, 0);
1363e12c5d1SDavid du Colombier if(nw){
1373e12c5d1SDavid du Colombier flushtyping(1);
1383e12c5d1SDavid du Colombier flupfront(nw);
1393e12c5d1SDavid du Colombier flborder(nw, 1);
1403e12c5d1SDavid du Colombier buttons(Up);
1413e12c5d1SDavid du Colombier t = (Text *)nw->user1;
1423e12c5d1SDavid du Colombier t->front = nw-&t->l[0];
1433e12c5d1SDavid du Colombier if(t != &cmd)
1443e12c5d1SDavid du Colombier work = nw;
1453e12c5d1SDavid du Colombier }
1463e12c5d1SDavid du Colombier which = nw;
1473e12c5d1SDavid du Colombier }
1483e12c5d1SDavid du Colombier
1493e12c5d1SDavid du Colombier void
closeup(Flayer * l)1503e12c5d1SDavid du Colombier closeup(Flayer *l)
1513e12c5d1SDavid du Colombier {
1523e12c5d1SDavid du Colombier Text *t=(Text *)l->user1;
1533e12c5d1SDavid du Colombier int m;
1543e12c5d1SDavid du Colombier
1553e12c5d1SDavid du Colombier m = whichmenu(t->tag);
1563e12c5d1SDavid du Colombier if(m < 0)
1573e12c5d1SDavid du Colombier return;
1583e12c5d1SDavid du Colombier flclose(l);
1593e12c5d1SDavid du Colombier if(l == which){
1603e12c5d1SDavid du Colombier which = 0;
1613e12c5d1SDavid du Colombier current(flwhich(Pt(0, 0)));
1623e12c5d1SDavid du Colombier }
1633e12c5d1SDavid du Colombier if(l == work)
1643e12c5d1SDavid du Colombier work = 0;
1653e12c5d1SDavid du Colombier if(--t->nwin == 0){
1663e12c5d1SDavid du Colombier rclear(&t->rasp);
1673e12c5d1SDavid du Colombier free((uchar *)t);
1683e12c5d1SDavid du Colombier text[m] = 0;
1693e12c5d1SDavid du Colombier }else if(l == &t->l[t->front]){
1703e12c5d1SDavid du Colombier for(m=0; m<NL; m++) /* find one; any one will do */
1713e12c5d1SDavid du Colombier if(t->l[m].textfn){
1723e12c5d1SDavid du Colombier t->front = m;
1733e12c5d1SDavid du Colombier return;
1743e12c5d1SDavid du Colombier }
1753e12c5d1SDavid du Colombier panic("close");
1763e12c5d1SDavid du Colombier }
1773e12c5d1SDavid du Colombier }
1783e12c5d1SDavid du Colombier
1793e12c5d1SDavid du Colombier Flayer *
findl(Text * t)1803e12c5d1SDavid du Colombier findl(Text *t)
1813e12c5d1SDavid du Colombier {
1823e12c5d1SDavid du Colombier int i;
1833e12c5d1SDavid du Colombier for(i = 0; i<NL; i++)
1843e12c5d1SDavid du Colombier if(t->l[i].textfn==0)
1853e12c5d1SDavid du Colombier return &t->l[i];
1863e12c5d1SDavid du Colombier return 0;
1873e12c5d1SDavid du Colombier }
1883e12c5d1SDavid du Colombier
1893e12c5d1SDavid du Colombier void
duplicate(Flayer * l,Rectangle r,Font * f,int close)1903e12c5d1SDavid du Colombier duplicate(Flayer *l, Rectangle r, Font *f, int close)
1913e12c5d1SDavid du Colombier {
1923e12c5d1SDavid du Colombier Text *t=(Text *)l->user1;
1933e12c5d1SDavid du Colombier Flayer *nl = findl(t);
1943e12c5d1SDavid du Colombier Rune *rp;
1953e12c5d1SDavid du Colombier ulong n;
1963e12c5d1SDavid du Colombier
1973e12c5d1SDavid du Colombier if(nl){
1983e12c5d1SDavid du Colombier flnew(nl, gettext, l->user0, (char *)t);
1997dd7cddfSDavid du Colombier flinit(nl, r, f, l->f.cols);
2003e12c5d1SDavid du Colombier nl->origin = l->origin;
2013e12c5d1SDavid du Colombier rp = (*l->textfn)(l, l->f.nchars, &n);
2023e12c5d1SDavid du Colombier flinsert(nl, rp, rp+n, l->origin);
2033e12c5d1SDavid du Colombier flsetselect(nl, l->p0, l->p1);
2043e12c5d1SDavid du Colombier if(close){
2053e12c5d1SDavid du Colombier flclose(l);
2063e12c5d1SDavid du Colombier if(l==which)
2073e12c5d1SDavid du Colombier which = 0;
2083e12c5d1SDavid du Colombier }else
2093e12c5d1SDavid du Colombier t->nwin++;
2103e12c5d1SDavid du Colombier current(nl);
2113e12c5d1SDavid du Colombier hcheck(t->tag);
2123e12c5d1SDavid du Colombier }
2137dd7cddfSDavid du Colombier setcursor(mousectl, cursor);
2143e12c5d1SDavid du Colombier }
2153e12c5d1SDavid du Colombier
2163e12c5d1SDavid du Colombier void
buttons(int updown)2173e12c5d1SDavid du Colombier buttons(int updown)
2183e12c5d1SDavid du Colombier {
2197dd7cddfSDavid du Colombier while(((mousep->buttons&7)!=0) != updown)
2207dd7cddfSDavid du Colombier getmouse();
2213e12c5d1SDavid du Colombier }
2223e12c5d1SDavid du Colombier
2233e12c5d1SDavid du Colombier int
getr(Rectangle * rp)2243e12c5d1SDavid du Colombier getr(Rectangle *rp)
2253e12c5d1SDavid du Colombier {
2263e12c5d1SDavid du Colombier Point p;
2273e12c5d1SDavid du Colombier Rectangle r;
2283e12c5d1SDavid du Colombier
2297dd7cddfSDavid du Colombier *rp = getrect(3, mousectl);
2303e12c5d1SDavid du Colombier if(rp->max.x && rp->max.x-rp->min.x<=5 && rp->max.y-rp->min.y<=5){
2313e12c5d1SDavid du Colombier p = rp->min;
2323e12c5d1SDavid du Colombier r = cmd.l[cmd.front].entire;
2337dd7cddfSDavid du Colombier *rp = screen->r;
2343e12c5d1SDavid du Colombier if(cmd.nwin==1){
2353e12c5d1SDavid du Colombier if (p.y <= r.min.y)
2363e12c5d1SDavid du Colombier rp->max.y = r.min.y;
2373e12c5d1SDavid du Colombier else if (p.y >= r.max.y)
2383e12c5d1SDavid du Colombier rp->min.y = r.max.y;
2393e12c5d1SDavid du Colombier if (p.x <= r.min.x)
2403e12c5d1SDavid du Colombier rp->max.x = r.min.x;
2413e12c5d1SDavid du Colombier else if (p.x >= r.max.x)
2423e12c5d1SDavid du Colombier rp->min.x = r.max.x;
2433e12c5d1SDavid du Colombier }
2443e12c5d1SDavid du Colombier }
2457dd7cddfSDavid du Colombier return rectclip(rp, screen->r) &&
2463e12c5d1SDavid du Colombier rp->max.x-rp->min.x>100 && rp->max.y-rp->min.y>40;
2473e12c5d1SDavid du Colombier }
2483e12c5d1SDavid du Colombier
2493e12c5d1SDavid du Colombier void
snarf(Text * t,int w)2503e12c5d1SDavid du Colombier snarf(Text *t, int w)
2513e12c5d1SDavid du Colombier {
2523e12c5d1SDavid du Colombier Flayer *l = &t->l[w];
2533e12c5d1SDavid du Colombier
2543e12c5d1SDavid du Colombier if(l->p1>l->p0){
2553e12c5d1SDavid du Colombier snarflen = l->p1-l->p0;
2563e12c5d1SDavid du Colombier outTsll(Tsnarf, t->tag, l->p0, l->p1);
2573e12c5d1SDavid du Colombier }
2583e12c5d1SDavid du Colombier }
2593e12c5d1SDavid du Colombier
2603e12c5d1SDavid du Colombier void
cut(Text * t,int w,int save,int check)2613e12c5d1SDavid du Colombier cut(Text *t, int w, int save, int check)
2623e12c5d1SDavid du Colombier {
2633e12c5d1SDavid du Colombier long p0, p1;
264bd389b36SDavid du Colombier Flayer *l;
2653e12c5d1SDavid du Colombier
266bd389b36SDavid du Colombier l = &t->l[w];
267bd389b36SDavid du Colombier p0 = l->p0;
268bd389b36SDavid du Colombier p1 = l->p1;
269bd389b36SDavid du Colombier if(p0 == p1)
2703e12c5d1SDavid du Colombier return;
2713e12c5d1SDavid du Colombier if(p0 < 0)
2723e12c5d1SDavid du Colombier panic("cut");
2733e12c5d1SDavid du Colombier if(save)
2743e12c5d1SDavid du Colombier snarf(t, w);
2753e12c5d1SDavid du Colombier outTsll(Tcut, t->tag, p0, p1);
276bd389b36SDavid du Colombier flsetselect(l, p0, p0);
2773e12c5d1SDavid du Colombier t->lock++;
2783e12c5d1SDavid du Colombier hcut(t->tag, p0, p1-p0);
2793e12c5d1SDavid du Colombier if(check)
2803e12c5d1SDavid du Colombier hcheck(t->tag);
2813e12c5d1SDavid du Colombier }
2823e12c5d1SDavid du Colombier
2833e12c5d1SDavid du Colombier void
paste(Text * t,int w)2843e12c5d1SDavid du Colombier paste(Text *t, int w)
2853e12c5d1SDavid du Colombier {
2863e12c5d1SDavid du Colombier if(snarflen){
2873e12c5d1SDavid du Colombier cut(t, w, 0, 0);
2883e12c5d1SDavid du Colombier t->lock++;
2893e12c5d1SDavid du Colombier outTsl(Tpaste, t->tag, t->l[w].p0);
2903e12c5d1SDavid du Colombier }
2913e12c5d1SDavid du Colombier }
2923e12c5d1SDavid du Colombier
2933e12c5d1SDavid du Colombier void
scrorigin(Flayer * l,int but,long p0)2943e12c5d1SDavid du Colombier scrorigin(Flayer *l, int but, long p0)
2953e12c5d1SDavid du Colombier {
2963e12c5d1SDavid du Colombier Text *t=(Text *)l->user1;
2973e12c5d1SDavid du Colombier
2983e12c5d1SDavid du Colombier switch(but){
2993e12c5d1SDavid du Colombier case 1:
3003e12c5d1SDavid du Colombier outTsll(Torigin, t->tag, l->origin, p0);
3013e12c5d1SDavid du Colombier break;
3023e12c5d1SDavid du Colombier case 2:
3033e12c5d1SDavid du Colombier outTsll(Torigin, t->tag, p0, 1L);
3043e12c5d1SDavid du Colombier break;
3053e12c5d1SDavid du Colombier case 3:
3063e12c5d1SDavid du Colombier horigin(t->tag,p0);
3073e12c5d1SDavid du Colombier }
3083e12c5d1SDavid du Colombier }
3093e12c5d1SDavid du Colombier
3103e12c5d1SDavid du Colombier int
alnum(int c)3113e12c5d1SDavid du Colombier alnum(int c)
3123e12c5d1SDavid du Colombier {
3133e12c5d1SDavid du Colombier /*
3143e12c5d1SDavid du Colombier * Hard to get absolutely right. Use what we know about ASCII
3153e12c5d1SDavid du Colombier * and assume anything above the Latin control characters is
3163e12c5d1SDavid du Colombier * potentially an alphanumeric.
3173e12c5d1SDavid du Colombier */
3183e12c5d1SDavid du Colombier if(c<=' ')
3193e12c5d1SDavid du Colombier return 0;
3203e12c5d1SDavid du Colombier if(0x7F<=c && c<=0xA0)
3213e12c5d1SDavid du Colombier return 0;
3223e12c5d1SDavid du Colombier if(utfrune("!\"#$%&'()*+,-./:;<=>?@[\\]^`{|}~", c))
3233e12c5d1SDavid du Colombier return 0;
3243e12c5d1SDavid du Colombier return 1;
3253e12c5d1SDavid du Colombier }
3263e12c5d1SDavid du Colombier
3273e12c5d1SDavid du Colombier int
raspc(Rasp * r,long p)3283e12c5d1SDavid du Colombier raspc(Rasp *r, long p)
3293e12c5d1SDavid du Colombier {
3303e12c5d1SDavid du Colombier ulong n;
3313e12c5d1SDavid du Colombier rload(r, p, p+1, &n);
3323e12c5d1SDavid du Colombier if(n)
3333e12c5d1SDavid du Colombier return scratch[0];
3343e12c5d1SDavid du Colombier return 0;
3353e12c5d1SDavid du Colombier }
3363e12c5d1SDavid du Colombier
3373e12c5d1SDavid du Colombier long
ctlw(Rasp * r,long o,long p)3383e12c5d1SDavid du Colombier ctlw(Rasp *r, long o, long p)
3393e12c5d1SDavid du Colombier {
3403e12c5d1SDavid du Colombier int c;
3413e12c5d1SDavid du Colombier
3423e12c5d1SDavid du Colombier if(--p < o)
3433e12c5d1SDavid du Colombier return o;
3443e12c5d1SDavid du Colombier if(raspc(r, p)=='\n')
3453e12c5d1SDavid du Colombier return p;
3463e12c5d1SDavid du Colombier for(; p>=o && !alnum(c=raspc(r, p)); --p)
3473e12c5d1SDavid du Colombier if(c=='\n')
3483e12c5d1SDavid du Colombier return p+1;
3493e12c5d1SDavid du Colombier for(; p>o && alnum(raspc(r, p-1)); --p)
3503e12c5d1SDavid du Colombier ;
3513e12c5d1SDavid du Colombier return p>=o? p : o;
3523e12c5d1SDavid du Colombier }
3533e12c5d1SDavid du Colombier
3543e12c5d1SDavid du Colombier long
ctlu(Rasp * r,long o,long p)3553e12c5d1SDavid du Colombier ctlu(Rasp *r, long o, long p)
3563e12c5d1SDavid du Colombier {
357f43e6a25SDavid du Colombier if(--p < o)
358f43e6a25SDavid du Colombier return o;
359f43e6a25SDavid du Colombier if(raspc(r, p)=='\n')
360f43e6a25SDavid du Colombier return p;
3613e12c5d1SDavid du Colombier for(; p-1>=o && raspc(r, p-1)!='\n'; --p)
3623e12c5d1SDavid du Colombier ;
3633e12c5d1SDavid du Colombier return p>=o? p : o;
3643e12c5d1SDavid du Colombier }
3653e12c5d1SDavid du Colombier
3663e12c5d1SDavid du Colombier int
center(Flayer * l,long a)3673e12c5d1SDavid du Colombier center(Flayer *l, long a)
3683e12c5d1SDavid du Colombier {
3693e12c5d1SDavid du Colombier Text *t;
3703e12c5d1SDavid du Colombier
3713e12c5d1SDavid du Colombier t = l->user1;
3723e12c5d1SDavid du Colombier if(!t->lock && (a<l->origin || l->origin+l->f.nchars<a)){
3733e12c5d1SDavid du Colombier if(a > t->rasp.nrunes)
3743e12c5d1SDavid du Colombier a = t->rasp.nrunes;
3753e12c5d1SDavid du Colombier outTsll(Torigin, t->tag, a, 2L);
3763e12c5d1SDavid du Colombier return 1;
3773e12c5d1SDavid du Colombier }
3783e12c5d1SDavid du Colombier return 0;
3793e12c5d1SDavid du Colombier }
3803e12c5d1SDavid du Colombier
3813e12c5d1SDavid du Colombier int
onethird(Flayer * l,long a)3823e12c5d1SDavid du Colombier onethird(Flayer *l, long a)
3833e12c5d1SDavid du Colombier {
3843e12c5d1SDavid du Colombier Text *t;
3853e12c5d1SDavid du Colombier Rectangle s;
3863e12c5d1SDavid du Colombier long lines;
3873e12c5d1SDavid du Colombier
3883e12c5d1SDavid du Colombier t = l->user1;
3893e12c5d1SDavid du Colombier if(!t->lock && (a<l->origin || l->origin+l->f.nchars<a)){
3903e12c5d1SDavid du Colombier if(a > t->rasp.nrunes)
3913e12c5d1SDavid du Colombier a = t->rasp.nrunes;
3927dd7cddfSDavid du Colombier s = insetrect(l->scroll, 1);
3933e12c5d1SDavid du Colombier lines = ((s.max.y-s.min.y)/l->f.font->height+1)/3;
3943e12c5d1SDavid du Colombier if (lines < 2)
3953e12c5d1SDavid du Colombier lines = 2;
3963e12c5d1SDavid du Colombier outTsll(Torigin, t->tag, a, lines);
3973e12c5d1SDavid du Colombier return 1;
3983e12c5d1SDavid du Colombier }
3993e12c5d1SDavid du Colombier return 0;
4003e12c5d1SDavid du Colombier }
4013e12c5d1SDavid du Colombier
4023e12c5d1SDavid du Colombier void
flushtyping(int clearesc)4033e12c5d1SDavid du Colombier flushtyping(int clearesc)
4043e12c5d1SDavid du Colombier {
4053e12c5d1SDavid du Colombier Text *t;
4063e12c5d1SDavid du Colombier ulong n;
4073e12c5d1SDavid du Colombier
4083e12c5d1SDavid du Colombier if(clearesc)
4093e12c5d1SDavid du Colombier typeesc = -1;
4103e12c5d1SDavid du Colombier if(typestart == typeend) {
4113e12c5d1SDavid du Colombier modified = 0;
4123e12c5d1SDavid du Colombier return;
4133e12c5d1SDavid du Colombier }
4143e12c5d1SDavid du Colombier t = which->user1;
415219b2ee8SDavid du Colombier if(t != &cmd)
416219b2ee8SDavid du Colombier modified = 1;
4173e12c5d1SDavid du Colombier rload(&t->rasp, typestart, typeend, &n);
4183e12c5d1SDavid du Colombier scratch[n] = 0;
4193e12c5d1SDavid du Colombier if(t==&cmd && typeend==t->rasp.nrunes && scratch[typeend-typestart-1]=='\n'){
4203e12c5d1SDavid du Colombier setlock();
4213e12c5d1SDavid du Colombier outcmd();
4223e12c5d1SDavid du Colombier }
4233e12c5d1SDavid du Colombier outTslS(Ttype, t->tag, typestart, scratch);
4243e12c5d1SDavid du Colombier typestart = -1;
4253e12c5d1SDavid du Colombier typeend = -1;
4263e12c5d1SDavid du Colombier }
4273e12c5d1SDavid du Colombier
4287dd7cddfSDavid du Colombier #define BACKSCROLLKEY Kup
429e7d29567SDavid du Colombier #define ENDKEY Kend
4303e12c5d1SDavid du Colombier #define ESC 0x1B
431e7d29567SDavid du Colombier #define HOMEKEY Khome
432e7d29567SDavid du Colombier #define LEFTARROW Kleft
433e7d29567SDavid du Colombier #define LINEEND 0x05
434e7d29567SDavid du Colombier #define LINESTART 0x01
435e7d29567SDavid du Colombier #define PAGEDOWN Kpgdown
436e7d29567SDavid du Colombier #define PAGEUP Kpgup
437e7d29567SDavid du Colombier #define RIGHTARROW Kright
438e7d29567SDavid du Colombier #define SCROLLKEY Kdown
439*a12e914dSDavid du Colombier #define Kstx 0x02
440e7d29567SDavid du Colombier
441e7d29567SDavid du Colombier int
nontypingkey(int c)442e7d29567SDavid du Colombier nontypingkey(int c)
443e7d29567SDavid du Colombier {
444e7d29567SDavid du Colombier switch(c){
445e7d29567SDavid du Colombier case BACKSCROLLKEY:
446e7d29567SDavid du Colombier case ENDKEY:
447e7d29567SDavid du Colombier case HOMEKEY:
448e7d29567SDavid du Colombier case LEFTARROW:
449e7d29567SDavid du Colombier case LINEEND:
450e7d29567SDavid du Colombier case LINESTART:
451e7d29567SDavid du Colombier case PAGEDOWN:
452e7d29567SDavid du Colombier case PAGEUP:
453e7d29567SDavid du Colombier case RIGHTARROW:
454e7d29567SDavid du Colombier case SCROLLKEY:
455*a12e914dSDavid du Colombier case Kstx:
456e7d29567SDavid du Colombier return 1;
457e7d29567SDavid du Colombier }
458e7d29567SDavid du Colombier return 0;
459e7d29567SDavid du Colombier }
460e7d29567SDavid du Colombier
4613e12c5d1SDavid du Colombier
4623e12c5d1SDavid du Colombier void
type(Flayer * l,int res)463bd389b36SDavid du Colombier type(Flayer *l, int res) /* what a bloody mess this is */
4643e12c5d1SDavid du Colombier {
4653e12c5d1SDavid du Colombier Text *t = (Text *)l->user1;
4663e12c5d1SDavid du Colombier Rune buf[100];
4673e12c5d1SDavid du Colombier Rune *p = buf;
468bd389b36SDavid du Colombier int c, backspacing;
4697dd7cddfSDavid du Colombier long a, a0;
470bd389b36SDavid du Colombier int scrollkey;
471bd389b36SDavid du Colombier
472bd389b36SDavid du Colombier scrollkey = 0;
473bd389b36SDavid du Colombier if(res == RKeyboard)
474e7d29567SDavid du Colombier scrollkey = nontypingkey(qpeekc()); /* ICK */
4753e12c5d1SDavid du Colombier
4767dd7cddfSDavid du Colombier if(hostlock || t->lock){
4773e12c5d1SDavid du Colombier kbdblock();
4783e12c5d1SDavid du Colombier return;
4793e12c5d1SDavid du Colombier }
4803e12c5d1SDavid du Colombier a = l->p0;
4813e12c5d1SDavid du Colombier if(a!=l->p1 && !scrollkey){
4823e12c5d1SDavid du Colombier flushtyping(1);
4833e12c5d1SDavid du Colombier cut(t, t->front, 1, 1);
4843e12c5d1SDavid du Colombier return; /* it may now be locked */
4853e12c5d1SDavid du Colombier }
486bd389b36SDavid du Colombier backspacing = 0;
487bd389b36SDavid du Colombier while((c = kbdchar())>0){
488bd389b36SDavid du Colombier if(res == RKeyboard){
489e7d29567SDavid du Colombier if(nontypingkey(c) || c==ESC)
490bd389b36SDavid du Colombier break;
491bd389b36SDavid du Colombier /* backspace, ctrl-u, ctrl-w, del */
492bd389b36SDavid du Colombier if(c=='\b' || c==0x15 || c==0x17 || c==0x7F){
4933e12c5d1SDavid du Colombier backspacing = 1;
4943e12c5d1SDavid du Colombier break;
495bd389b36SDavid du Colombier }
496bd389b36SDavid du Colombier }
4973e12c5d1SDavid du Colombier *p++ = c;
498e7d29567SDavid du Colombier if(autoindent)
499e7d29567SDavid du Colombier if(c == '\n'){
500e7d29567SDavid du Colombier /* autoindent */
501e7d29567SDavid du Colombier int cursor, ch;
502e7d29567SDavid du Colombier cursor = ctlu(&t->rasp, 0, a+(p-buf)-1);
503e7d29567SDavid du Colombier while(p < buf+nelem(buf)){
504e7d29567SDavid du Colombier ch = raspc(&t->rasp, cursor++);
505e7d29567SDavid du Colombier if(ch == ' ' || ch == '\t')
506e7d29567SDavid du Colombier *p++ = ch;
507e7d29567SDavid du Colombier else
508e7d29567SDavid du Colombier break;
509e7d29567SDavid du Colombier }
510e7d29567SDavid du Colombier }
511bd389b36SDavid du Colombier if(c == '\n' || p >= buf+sizeof(buf)/sizeof(buf[0]))
5123e12c5d1SDavid du Colombier break;
5133e12c5d1SDavid du Colombier }
5143e12c5d1SDavid du Colombier if(p > buf){
5153e12c5d1SDavid du Colombier if(typestart < 0)
5163e12c5d1SDavid du Colombier typestart = a;
5173e12c5d1SDavid du Colombier if(typeesc < 0)
5183e12c5d1SDavid du Colombier typeesc = a;
5193e12c5d1SDavid du Colombier hgrow(t->tag, a, p-buf, 0);
5203e12c5d1SDavid du Colombier t->lock++; /* pretend we Trequest'ed for hdatarune*/
5213e12c5d1SDavid du Colombier hdatarune(t->tag, a, buf, p-buf);
5223e12c5d1SDavid du Colombier a += p-buf;
5233e12c5d1SDavid du Colombier l->p0 = a;
5243e12c5d1SDavid du Colombier l->p1 = a;
5253e12c5d1SDavid du Colombier typeend = a;
5263e12c5d1SDavid du Colombier if(c=='\n' || typeend-typestart>100)
5273e12c5d1SDavid du Colombier flushtyping(0);
5283e12c5d1SDavid du Colombier onethird(l, a);
5293e12c5d1SDavid du Colombier }
530e7d29567SDavid du Colombier if(c==SCROLLKEY || c==PAGEDOWN){
5313e12c5d1SDavid du Colombier flushtyping(0);
5323e12c5d1SDavid du Colombier center(l, l->origin+l->f.nchars+1);
5333e12c5d1SDavid du Colombier /* backspacing immediately after outcmd(): sorry */
534e7d29567SDavid du Colombier }else if(c==BACKSCROLLKEY || c==PAGEUP){
5357dd7cddfSDavid du Colombier flushtyping(0);
5367dd7cddfSDavid du Colombier a0 = l->origin-l->f.nchars;
5377dd7cddfSDavid du Colombier if(a0 < 0)
5387dd7cddfSDavid du Colombier a0 = 0;
5397dd7cddfSDavid du Colombier center(l, a0);
540e7d29567SDavid du Colombier }else if(c == RIGHTARROW){
541e7d29567SDavid du Colombier flushtyping(0);
542e7d29567SDavid du Colombier a0 = l->p0;
543e7d29567SDavid du Colombier if(a0 < t->rasp.nrunes)
544e7d29567SDavid du Colombier a0++;
545e7d29567SDavid du Colombier flsetselect(l, a0, a0);
546e7d29567SDavid du Colombier center(l, a0);
547e7d29567SDavid du Colombier }else if(c == LEFTARROW){
548e7d29567SDavid du Colombier flushtyping(0);
549e7d29567SDavid du Colombier a0 = l->p0;
550e7d29567SDavid du Colombier if(a0 > 0)
551e7d29567SDavid du Colombier a0--;
552e7d29567SDavid du Colombier flsetselect(l, a0, a0);
553e7d29567SDavid du Colombier center(l, a0);
554e7d29567SDavid du Colombier }else if(c == HOMEKEY){
555e7d29567SDavid du Colombier flushtyping(0);
556e7d29567SDavid du Colombier center(l, 0);
557e7d29567SDavid du Colombier }else if(c == ENDKEY){
558e7d29567SDavid du Colombier flushtyping(0);
559e7d29567SDavid du Colombier center(l, t->rasp.nrunes);
560e7d29567SDavid du Colombier }else if(c == LINESTART || c == LINEEND){
561e7d29567SDavid du Colombier flushtyping(1);
562e7d29567SDavid du Colombier if(c == LINESTART)
563e7d29567SDavid du Colombier while(a > 0 && raspc(&t->rasp, a-1)!='\n')
564e7d29567SDavid du Colombier a--;
565e7d29567SDavid du Colombier else
566e7d29567SDavid du Colombier while(a < t->rasp.nrunes && raspc(&t->rasp, a)!='\n')
567e7d29567SDavid du Colombier a++;
568e7d29567SDavid du Colombier l->p0 = l->p1 = a;
569e7d29567SDavid du Colombier for(l=t->l; l<&t->l[NL]; l++)
570e7d29567SDavid du Colombier if(l->textfn)
571e7d29567SDavid du Colombier flsetselect(l, l->p0, l->p1);
5727dd7cddfSDavid du Colombier }else if(backspacing && !hostlock){
573e7d29567SDavid du Colombier /* backspacing immediately after outcmd(): sorry */
5743e12c5d1SDavid du Colombier if(l->f.p0>0 && a>0){
5753e12c5d1SDavid du Colombier switch(c){
5763e12c5d1SDavid du Colombier case '\b':
5773e12c5d1SDavid du Colombier case 0x7F: /* del */
5783e12c5d1SDavid du Colombier l->p0 = a-1;
5793e12c5d1SDavid du Colombier break;
5803e12c5d1SDavid du Colombier case 0x15: /* ctrl-u */
5813e12c5d1SDavid du Colombier l->p0 = ctlu(&t->rasp, l->origin, a);
5823e12c5d1SDavid du Colombier break;
5833e12c5d1SDavid du Colombier case 0x17: /* ctrl-w */
5843e12c5d1SDavid du Colombier l->p0 = ctlw(&t->rasp, l->origin, a);
5853e12c5d1SDavid du Colombier break;
5863e12c5d1SDavid du Colombier }
5873e12c5d1SDavid du Colombier l->p1 = a;
5883e12c5d1SDavid du Colombier if(l->p1 != l->p0){
5893e12c5d1SDavid du Colombier /* cut locally if possible */
5903e12c5d1SDavid du Colombier if(typestart<=l->p0 && l->p1<=typeend){
5913e12c5d1SDavid du Colombier t->lock++; /* to call hcut */
5923e12c5d1SDavid du Colombier hcut(t->tag, l->p0, l->p1-l->p0);
5933e12c5d1SDavid du Colombier /* hcheck is local because we know rasp is contiguous */
5943e12c5d1SDavid du Colombier hcheck(t->tag);
5953e12c5d1SDavid du Colombier }else{
5963e12c5d1SDavid du Colombier flushtyping(0);
5973e12c5d1SDavid du Colombier cut(t, t->front, 0, 1);
5983e12c5d1SDavid du Colombier }
5993e12c5d1SDavid du Colombier }
6003e12c5d1SDavid du Colombier if(typeesc >= l->p0)
6013e12c5d1SDavid du Colombier typeesc = l->p0;
6023e12c5d1SDavid du Colombier if(typestart >= 0){
6033e12c5d1SDavid du Colombier if(typestart >= l->p0)
6043e12c5d1SDavid du Colombier typestart = l->p0;
6053e12c5d1SDavid du Colombier typeend = l->p0;
6063e12c5d1SDavid du Colombier if(typestart == typeend){
6073e12c5d1SDavid du Colombier typestart = -1;
6083e12c5d1SDavid du Colombier typeend = -1;
6093e12c5d1SDavid du Colombier modified = 0;
6103e12c5d1SDavid du Colombier }
6113e12c5d1SDavid du Colombier }
6123e12c5d1SDavid du Colombier }
613*a12e914dSDavid du Colombier }else if((mousep->buttons&8)){
614*a12e914dSDavid du Colombier scroll(which, 4);
615*a12e914dSDavid du Colombier }else if((mousep->buttons&16)){
616*a12e914dSDavid du Colombier scroll(which, 5);
617*a12e914dSDavid du Colombier }else if(c == Kstx){
618*a12e914dSDavid du Colombier t = &cmd;
619*a12e914dSDavid du Colombier for(l=t->l; l->textfn==0; l++)
620*a12e914dSDavid du Colombier ;
621*a12e914dSDavid du Colombier current(l);
622*a12e914dSDavid du Colombier flushtyping(0);
623*a12e914dSDavid du Colombier a = t->rasp.nrunes;
624*a12e914dSDavid du Colombier flsetselect(l, a, a);
625*a12e914dSDavid du Colombier center(l, a);
6263e12c5d1SDavid du Colombier }else{
6273e12c5d1SDavid du Colombier if(c==ESC && typeesc>=0){
6283e12c5d1SDavid du Colombier l->p0 = typeesc;
6293e12c5d1SDavid du Colombier l->p1 = a;
6303e12c5d1SDavid du Colombier flushtyping(1);
6313e12c5d1SDavid du Colombier }
6323e12c5d1SDavid du Colombier for(l=t->l; l<&t->l[NL]; l++)
6333e12c5d1SDavid du Colombier if(l->textfn)
6343e12c5d1SDavid du Colombier flsetselect(l, l->p0, l->p1);
6353e12c5d1SDavid du Colombier }
6363e12c5d1SDavid du Colombier }
6373e12c5d1SDavid du Colombier
6383e12c5d1SDavid du Colombier
6393e12c5d1SDavid du Colombier void
outcmd(void)6403e12c5d1SDavid du Colombier outcmd(void){
6413e12c5d1SDavid du Colombier if(work)
6423e12c5d1SDavid du Colombier outTsll(Tworkfile, ((Text *)work->user1)->tag, work->p0, work->p1);
6433e12c5d1SDavid du Colombier }
6443e12c5d1SDavid du Colombier
6453e12c5d1SDavid du Colombier void
panic(char * s)6463e12c5d1SDavid du Colombier panic(char *s)
6473e12c5d1SDavid du Colombier {
6487dd7cddfSDavid du Colombier panic1(display, s);
6497dd7cddfSDavid du Colombier }
6507dd7cddfSDavid du Colombier
6517dd7cddfSDavid du Colombier void
panic1(Display *,char * s)6527dd7cddfSDavid du Colombier panic1(Display*, char *s)
6537dd7cddfSDavid du Colombier {
6543e12c5d1SDavid du Colombier fprint(2, "samterm:panic: ");
6553e12c5d1SDavid du Colombier perror(s);
6563e12c5d1SDavid du Colombier abort();
6573e12c5d1SDavid du Colombier }
6583e12c5d1SDavid du Colombier
6593e12c5d1SDavid du Colombier Rune*
gettext(Flayer * l,long n,ulong * np)6603e12c5d1SDavid du Colombier gettext(Flayer *l, long n, ulong *np)
6613e12c5d1SDavid du Colombier {
6623e12c5d1SDavid du Colombier Text *t;
6633e12c5d1SDavid du Colombier
6643e12c5d1SDavid du Colombier t = l->user1;
6653e12c5d1SDavid du Colombier rload(&t->rasp, l->origin, l->origin+n, np);
6663e12c5d1SDavid du Colombier return scratch;
6673e12c5d1SDavid du Colombier }
6683e12c5d1SDavid du Colombier
6693e12c5d1SDavid du Colombier long
scrtotal(Flayer * l)6703e12c5d1SDavid du Colombier scrtotal(Flayer *l)
6713e12c5d1SDavid du Colombier {
6723e12c5d1SDavid du Colombier return ((Text *)l->user1)->rasp.nrunes;
6733e12c5d1SDavid du Colombier }
6743e12c5d1SDavid du Colombier
6753e12c5d1SDavid du Colombier void*
alloc(ulong n)6763e12c5d1SDavid du Colombier alloc(ulong n)
6773e12c5d1SDavid du Colombier {
6783e12c5d1SDavid du Colombier void *p;
6793e12c5d1SDavid du Colombier
6803e12c5d1SDavid du Colombier p = malloc(n);
6813e12c5d1SDavid du Colombier if(p == 0)
6823e12c5d1SDavid du Colombier panic("alloc");
6833e12c5d1SDavid du Colombier memset(p, 0, n);
6843e12c5d1SDavid du Colombier return p;
6853e12c5d1SDavid du Colombier }
686