22 long modified = 0; /* strange lookahead for menus */
29 #define chording 0 /* code here for reference but it causes deadlocks */
32 notifyf(void *a, char *msg)
34 if(strcmp(msg, "interrupt") == 0)
40 threadmain(int argc, char *argv[])
48 * sam is talking to us on fd 0 and 1.
49 * move these elsewhere so that if we accidentally
50 * use 0 and 1 in other code, nothing bad happens.
58 open("/dev/null", OREAD);
59 if(open("/dev/tty", OWRITE) < 0)
60 open("/dev/null", OWRITE);
64 if(protodebug) print("getscreen\n");
65 getscreen(argc, argv);
66 if(protodebug) print("iconinit\n");
68 if(protodebug) print("initio\n");
70 if(protodebug) print("scratch\n");
71 scratch = alloc(100*RUNESIZE);
74 r.max.y = r.min.y+Dy(r)/5;
75 if(protodebug) print("flstart\n");
76 flstart(screen->clipr);
78 flnew(&cmd.l[0], gettext, 1, &cmd);
79 flinit(&cmd.l[0], r, font, cmdcols);
83 outTs(Tversion, VERSION);
84 startnewfile(Tstartcmdfile, &cmd);
87 if(protodebug) print("loop\n");
88 for(;;got = waitforio()){
89 if(hasunlocked && RESIZED())
94 for(i=0; cmd.l[i].textfn==0; i++)
97 flsetselect(which, cmd.rasp.nrunes, cmd.rasp.nrunes);
100 if(got&(1<<RKeyboard))
102 type(which, RKeyboard);
106 if(hostlock==2 || !ptinrect(mousep->xy, screen->r)){
110 nwhich = flwhich(mousep->xy);
111 scr = which && ptinrect(mousep->xy, which->scroll);
114 if(chording && chord==1 && !mousep->buttons)
116 if(chording && chord)
117 chord |= mousep->buttons;
118 else if(mousep->buttons&1){
125 t=(Text *)which->user1;
127 outTsl(Tdclick, t->tag, which->p0);
131 if(mousep->buttons&1)
132 chord = mousep->buttons;
135 }else if((mousep->buttons&2) && which){
140 }else if((mousep->buttons&4)){
148 if(chording && chord){
149 t = (Text*)which->user1;
150 if(!t->lock && !hostlock){
169 flresize(screen->clipr);
170 for(i = 0; i<nname; i++)
172 hcheck(text[i]->tag);
187 t = (Text *)nw->user1;
188 t->front = nw-&t->l[0];
198 Text *t=(Text *)l->user1;
201 m = whichmenu(t->tag);
207 current(flwhich(Pt(0, 0)));
215 }else if(l == &t->l[t->front]){
216 for(m=0; m<NL; m++) /* find one; any one will do */
229 for(i = 0; i<NL; i++)
230 if(t->l[i].textfn==0)
236 duplicate(Flayer *l, Rectangle r, Font *f, int close)
238 Text *t=(Text *)l->user1;
239 Flayer *nl = findl(t);
244 flnew(nl, gettext, l->user0, (char *)t);
245 flinit(nl, r, f, l->f.cols);
246 nl->origin = l->origin;
247 rp = (*l->textfn)(l, l->f.nchars, &n);
248 flinsert(nl, rp, rp+n, l->origin);
249 flsetselect(nl, l->p0, l->p1);
259 setcursor(mousectl, cursor);
265 while(((mousep->buttons&7)!=0) != updown)
275 *rp = getrect(3, mousectl);
276 if(rp->max.x && rp->max.x-rp->min.x<=5 && rp->max.y-rp->min.y<=5){
278 r = cmd.l[cmd.front].entire;
283 else if (p.y >= r.max.y)
287 else if (p.x >= r.max.x)
291 return rectclip(rp, screen->r) &&
292 rp->max.x-rp->min.x>100 && rp->max.y-rp->min.y>40;
296 snarf(Text *t, int w)
298 Flayer *l = &t->l[w];
301 snarflen = l->p1-l->p0;
302 outTsll(Tsnarf, t->tag, l->p0, l->p1);
307 cut(Text *t, int w, int save, int check)
321 outTsll(Tcut, t->tag, p0, p1);
322 flsetselect(l, p0, p0);
324 hcut(t->tag, p0, p1-p0);
330 paste(Text *t, int w)
335 outTsl(Tpaste, t->tag, t->l[w].p0);
340 scrorigin(Flayer *l, int but, long p0)
342 Text *t=(Text *)l->user1;
346 outTsll(Torigin, t->tag, l->origin, p0);
349 outTsll(Torigin, t->tag, p0, 1L);
360 * Hard to get absolutely right. Use what we know about ASCII
361 * and assume anything above the Latin control characters is
362 * potentially an alphanumeric.
366 if(0x7F<=c && c<=0xA0)
368 if(utfrune("!\"#$%&'()*+,-./:;<=>?@[\\]^`{|}~", c))
374 raspc(Rasp *r, long p)
377 rload(r, p, p+1, &n);
384 ctlw(Rasp *r, long o, long p)
390 if(raspc(r, p)=='\n')
392 for(; p>=o && !alnum(c=raspc(r, p)); --p)
395 for(; p>o && alnum(raspc(r, p-1)); --p)
401 ctlu(Rasp *r, long o, long p)
405 if(raspc(r, p)=='\n')
407 for(; p-1>=o && raspc(r, p-1)!='\n'; --p)
413 center(Flayer *l, long a)
418 if(!t->lock && (a<l->origin || l->origin+l->f.nchars<a)){
419 if(a > t->rasp.nrunes)
421 outTsll(Torigin, t->tag, a, 2L);
428 thirds(Flayer *l, long a, int n)
435 if(!t->lock && (a<l->origin || l->origin+l->f.nchars<a)){
436 if(a > t->rasp.nrunes)
438 s = insetrect(l->scroll, 1);
439 lines = (n*(s.max.y-s.min.y)/l->f.font->height+1)/3;
442 outTsll(Torigin, t->tag, a, lines);
449 onethird(Flayer *l, long a)
451 return thirds(l, a, 1);
455 twothirds(Flayer *l, long a)
457 return thirds(l, a, 2);
461 flushtyping(int clearesc)
468 if(typestart == typeend) {
475 rload(&t->rasp, typestart, typeend, &n);
477 if(t==&cmd && typeend==t->rasp.nrunes && scratch[typeend-typestart-1]=='\n'){
481 outTslS(Ttype, t->tag, typestart, scratch);
486 #define BACKSCROLLKEY Kup
489 #define HOMEKEY Khome
490 #define LEFTARROW Kleft
492 #define LINESTART 0x01
493 #define PAGEDOWN Kpgdown
495 #define RIGHTARROW Kright
496 #define SCROLLKEY Kdown
497 #define CUT (Kcmd+'x')
498 #define COPY (Kcmd+'c')
499 #define PASTE (Kcmd+'v')
523 type(Flayer *l, int res) /* what a bloody mess this is */
525 Text *t = (Text *)l->user1;
534 scrollkey = nontypingkey(qpeekc()); /* ICK */
536 if(hostlock || t->lock){
541 if(a!=l->p1 && !scrollkey){
543 cut(t, t->front, 1, 1);
544 return; /* it may now be locked */
547 while((c = kbdchar())>0){
548 if(res == RKeyboard){
549 if(nontypingkey(c) || c==ESC)
551 /* backspace, ctrl-u, ctrl-w, del */
552 if(c=='\b' || c==0x15 || c==0x17 || c==0x7F){
562 cursor = ctlu(&t->rasp, 0, a+(p-buf)-1);
563 while(p < buf+nelem(buf)){
564 ch = raspc(&t->rasp, cursor++);
565 if(ch == ' ' || ch == '\t')
571 if(c == '\n' || p >= buf+nelem(buf))
579 hgrow(t->tag, a, p-buf, 0);
580 t->lock++; /* pretend we Trequest'ed for hdatarune*/
581 hdatarune(t->tag, a, buf, p-buf);
586 if(c=='\n' || typeend-typestart>100)
590 if(c==SCROLLKEY || c==PAGEDOWN){
592 center(l, l->origin+l->f.nchars+1);
593 }else if(c==BACKSCROLLKEY || c==PAGEUP){
595 a0 = l->origin-l->f.nchars;
599 }else if(c == RIGHTARROW){
602 if(a0 < t->rasp.nrunes)
604 flsetselect(l, a0, a0);
606 }else if(c == LEFTARROW){
611 flsetselect(l, a0, a0);
613 }else if(c == HOMEKEY){
616 }else if(c == ENDKEY){
618 center(l, t->rasp.nrunes);
619 }else if(c == LINESTART || c == LINEEND){
622 while(a > 0 && raspc(&t->rasp, a-1)!='\n')
625 while(a < t->rasp.nrunes && raspc(&t->rasp, a)!='\n')
628 for(l=t->l; l<&t->l[NL]; l++)
630 flsetselect(l, l->p0, l->p1);
631 }else if(backspacing && !hostlock){
632 /* backspacing immediately after outcmd(): sorry */
633 if(l->f.p0>0 && a>0){
639 case 0x15: /* ctrl-u */
640 l->p0 = ctlu(&t->rasp, l->origin, a);
642 case 0x17: /* ctrl-w */
643 l->p0 = ctlw(&t->rasp, l->origin, a);
648 /* cut locally if possible */
649 if(typestart<=l->p0 && l->p1<=typeend){
650 t->lock++; /* to call hcut */
651 hcut(t->tag, l->p0, l->p1-l->p0);
652 /* hcheck is local because we know rasp is contiguous */
656 cut(t, t->front, 0, 1);
662 if(typestart >= l->p0)
665 if(typestart == typeend){
673 if(c==ESC && typeesc>=0){
678 for(l=t->l; l<&t->l[NL]; l++)
680 flsetselect(l, l->p0, l->p1);
684 cut(t, t->front, 1, 1);
702 outTsll(Tworkfile, ((Text *)work->user1)->tag, work->p0, work->p1);
712 panic1(Display *d, char *s)
714 fprint(2, "samterm:panic: ");
720 gettext(Flayer *l, long n, ulong *np)
725 rload(&t->rasp, l->origin, l->origin+n, np);
732 return ((Text *)l->user1)->rasp.nrunes;