1 /* $MirOS: contrib/code/jupp/scrn.c,v 1.25 2017/07/09 01:19:54 tg Exp $ */
3 * Device independant TTY interface for JOE
5 * (C) 1992 Joseph H. Allen
7 * This file is part of JOE (Joe's Own Editor)
34 /* How to display characters (especially the control ones) */
35 /* here are characters ... */
36 static const unsigned char xlatc[256] = {
37 64, 65, 66, 67, 68, 69, 70, 71, /* 8 */
38 72, 73, 74, 75, 76, 77, 78, 79, /* 16 */
39 80, 81, 82, 83, 84, 85, 86, 87, /* 24 */
40 88, 89, 90, 91, 92, 93, 94, 95, /* 32 */
41 32, 33, 34, 35, 36, 37, 38, 39, /* 40 */
42 40, 41, 42, 43, 44, 45, 46, 47, /* 48 */
43 48, 49, 50, 51, 52, 53, 54, 55, /* 56 */
44 56, 57, 58, 59, 60, 61, 62, 63, /* 64 */
46 64, 65, 66, 67, 68, 69, 70, 71, /* 72 */
47 72, 73, 74, 75, 76, 77, 78, 79, /* 80 */
48 80, 81, 82, 83, 84, 85, 86, 87, /* 88 */
49 88, 89, 90, 91, 92, 93, 94, 95, /* 96 */
50 96, 97, 98, 99, 100, 101, 102, 103, /* 104 */
51 104, 105, 106, 107, 108, 109, 110, 111, /* 112 */
52 112, 113, 114, 115, 116, 117, 118, 119, /* 120 */
53 120, 121, 122, 123, 124, 125, 126, 63, /* 128 */
55 64, 65, 66, 67, 68, 69, 70, 71, /* 136 */
56 72, 73, 74, 75, 76, 77, 78, 79, /* 144 */
57 80, 81, 82, 83, 84, 85, 86, 87, /* 152 */
58 88, 89, 90, 91, 92, 93, 94, 95, /* 160 */
59 32, 33, 34, 35, 36, 37, 38, 39, /* 168 */
60 40, 41, 42, 43, 44, 45, 46, 47, /* 176 */
61 48, 49, 50, 51, 52, 53, 54, 55, /* 184 */
62 56, 57, 58, 59, 60, 61, 62, 63, /* 192 */
64 64, 65, 66, 67, 68, 69, 70, 71, /* 200 */
65 72, 73, 74, 75, 76, 77, 78, 79, /* 208 */
66 80, 81, 82, 83, 84, 85, 86, 87, /* 216 */
67 88, 89, 90, 91, 92, 93, 94, 95, /* 224 */
68 96, 97, 98, 99, 100, 101, 102, 103, /* 232 */
69 104, 105, 106, 107, 108, 109, 110, 111, /* 240 */
70 112, 113, 114, 115, 116, 117, 118, 119, /* 248 */
71 120, 121, 122, 123, 124, 125, 126, 63 /* 256 */
73 /* ... and here their attributes */
74 static const unsigned short xlata[256] = {
75 UNDERLINE, UNDERLINE, UNDERLINE, UNDERLINE, /* 4 */
76 UNDERLINE, UNDERLINE, UNDERLINE, UNDERLINE, /* 8 */
77 UNDERLINE, UNDERLINE, UNDERLINE, UNDERLINE, /* 12 */
78 UNDERLINE, UNDERLINE, UNDERLINE, UNDERLINE, /* 16 */
79 UNDERLINE, UNDERLINE, UNDERLINE, UNDERLINE, /* 20 */
80 UNDERLINE, UNDERLINE, UNDERLINE, UNDERLINE, /* 24 */
81 UNDERLINE, UNDERLINE, UNDERLINE, UNDERLINE, /* 28 */
82 UNDERLINE, UNDERLINE, UNDERLINE, UNDERLINE, /* 32 */
83 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 48 */
84 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 64 */
85 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 80 */
86 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 96 */
87 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 112 */
88 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, UNDERLINE, /* 128 */
90 INVERSE + UNDERLINE, INVERSE + UNDERLINE, /* 130 */
91 INVERSE + UNDERLINE, INVERSE + UNDERLINE, /* 132 */
92 INVERSE + UNDERLINE, INVERSE + UNDERLINE, /* 134 */
93 INVERSE + UNDERLINE, INVERSE + UNDERLINE, /* 136 */
94 INVERSE + UNDERLINE, INVERSE + UNDERLINE, /* 138 */
95 INVERSE + UNDERLINE, INVERSE + UNDERLINE, /* 140 */
96 INVERSE + UNDERLINE, INVERSE + UNDERLINE, /* 142 */
97 INVERSE + UNDERLINE, INVERSE + UNDERLINE, /* 144 */
98 INVERSE + UNDERLINE, INVERSE + UNDERLINE, /* 146 */
99 INVERSE + UNDERLINE, INVERSE + UNDERLINE, /* 148 */
100 INVERSE + UNDERLINE, INVERSE + UNDERLINE, /* 150 */
101 INVERSE + UNDERLINE, INVERSE + UNDERLINE, /* 152 */
102 INVERSE + UNDERLINE, INVERSE + UNDERLINE, /* 154 */
103 INVERSE + UNDERLINE, INVERSE + UNDERLINE, /* 156 */
104 INVERSE + UNDERLINE, INVERSE + UNDERLINE, /* 158 */
105 INVERSE + UNDERLINE, INVERSE + UNDERLINE, /* 160 */
107 INVERSE, INVERSE, INVERSE, INVERSE, /* 164 */
108 INVERSE, INVERSE, INVERSE, INVERSE, /* 168 */
109 INVERSE, INVERSE, INVERSE, INVERSE, /* 172 */
110 INVERSE, INVERSE, INVERSE, INVERSE, /* 176 */
111 INVERSE, INVERSE, INVERSE, INVERSE, /* 180 */
112 INVERSE, INVERSE, INVERSE, INVERSE, /* 184 */
113 INVERSE, INVERSE, INVERSE, INVERSE, /* 188 */
114 INVERSE, INVERSE, INVERSE, INVERSE, /* 192 */
115 INVERSE, INVERSE, INVERSE, INVERSE, /* 196 */
116 INVERSE, INVERSE, INVERSE, INVERSE, /* 200 */
117 INVERSE, INVERSE, INVERSE, INVERSE, /* 204 */
118 INVERSE, INVERSE, INVERSE, INVERSE, /* 208 */
119 INVERSE, INVERSE, INVERSE, INVERSE, /* 212 */
120 INVERSE, INVERSE, INVERSE, INVERSE, /* 216 */
121 INVERSE, INVERSE, INVERSE, INVERSE, /* 220 */
122 INVERSE, INVERSE, INVERSE, INVERSE, /* 224 */
123 INVERSE, INVERSE, INVERSE, INVERSE, /* 228 */
124 INVERSE, INVERSE, INVERSE, INVERSE, /* 232 */
125 INVERSE, INVERSE, INVERSE, INVERSE, /* 236 */
126 INVERSE, INVERSE, INVERSE, INVERSE, /* 240 */
127 INVERSE, INVERSE, INVERSE, INVERSE, /* 244 */
128 INVERSE, INVERSE, INVERSE, INVERSE, /* 248 */
129 INVERSE, INVERSE, INVERSE, INVERSE, /* 252 */
130 INVERSE, INVERSE, INVERSE, INVERSE + UNDERLINE /* 256 */
135 int set_attr(SCRN *t, int c)
141 /* Attributes which have gone off */
142 e = ((AT_MASK|FG_NOT_DEFAULT|BG_NOT_DEFAULT)&t->attrib & ~c);
144 if (e) { /* If any attribute go off, switch them all off: fixes bug on PCs */
146 texec(t->cap, t->me, 1, 0, 0, 0, 0);
149 texec(t->cap, t->ue, 1, 0, 0, 0, 0);
151 texec(t->cap, t->se, 1, 0, 0, 0, 0);
156 /* Attributes which have turned on */
157 e = (c & ~t->attrib);
161 texec(t->cap, t->mr, 1, 0, 0, 0, 0);
163 texec(t->cap, t->so, 1, 0, 0, 0, 0);
168 texec(t->cap, t->us, 1, 0, 0, 0, 0);
171 texec(t->cap, t->mb, 1, 0, 0, 0, 0);
174 texec(t->cap, t->md, 1, 0, 0, 0, 0);
177 texec(t->cap, t->mh, 1, 0, 0, 0, 0);
179 if ((t->attrib&FG_MASK)!=(c&FG_MASK))
180 if (t->Sf) texec(t->cap,t->Sf,1,7-(((c&FG_VALUE)>>FG_SHIFT)),0,0,0);
182 if ((t->attrib&BG_MASK)!=(c&BG_MASK))
183 if (t->Sb) texec(t->cap,t->Sb,1,((c&BG_VALUE)>>BG_SHIFT),0,0,0);
190 /* Output character with attributes */
192 void outatr_help(SCRN *t,int *scrn,int *attrf,int xx,int yy,int c,int a)
194 /* kludge for help_display() only */
195 if (locale_map->type && !joe_isprint(locale_map,c)) {
199 outatr(locale_map, t, scrn, attrf, xx, yy, c, a);
202 void outatr(struct charmap *map,SCRN *t,int *scrn,int *attrf,int xx,int yy,int c,int a)
205 if(locale_map->type) {
206 /* UTF-8 char to UTF-8 terminal */
209 switch ((wid = unictrl(c))) {
211 /* not a control character */
212 wid = joe_wcwidth(1, c);
221 if(*scrn==c && *attrf==a)
228 if(t->x != xx || t->y != yy)
235 unsigned char buf[7];
239 if (wid == 0 && xx > 0)
240 attrf[-1] |= HAS_COMBINING;
249 /* UTF-8 char to non-UTF-8 terminal */
250 /* Don't convert control chars below 256 */
251 if ((c>=32 && c<=126) || c>=160) {
254 c = from_uni(locale_map,c);
259 /* Deal with control characters */
260 if (!joe_isprint(locale_map,c) && !(dspasis && c>=128)) {
265 if(*scrn==c && *attrf==a)
272 if(t->x != xx || t->y != yy)
280 if (!locale_map->type) {
281 /* Non UTF-8 char to non UTF-8 terminal */
282 /* Byte-byte Translate? */
284 /* Deal with control characters */
285 if (!joe_isprint(locale_map,c) && !(dspasis && c>=128)) {
290 if (*scrn==c && *attrf==a)
298 if(t->x != xx || t->y != yy)
305 /* Non UTF-8 char to UTF-8 terminal */
306 unsigned char buf[7];
309 /* Deal with control characters */
310 if (!(dspasis && c>=128) && !joe_isprint(map,c)) {
316 if (c < 32 || (c >= 0x7F && c < 0xA0)) {
318 a = (a | UNDERLINE) ^ INVERSE;
322 if (*scrn == c && *attrf == a)
325 wid = joe_wcwidth(0,c);
330 if(t->x != xx || t->y != yy)
344 /* Set scrolling region */
346 static void setregn(SCRN *t, int top, int bot)
353 if (t->top != top || t->bot != bot) {
356 texec(t->cap, t->cs, 1, top, bot - 1, 0, 0);
362 /* Enter insert mode */
364 static void setins(SCRN *t, int x)
366 if (t->ins != 1 && t->im) {
368 texec(t->cap, t->im, 1, x, 0, 0, 0);
372 /* Exit insert mode */
377 texec(t->cap, t->ei, 1, 0, 0, 0, 0);
383 /* Erase from given screen coordinate to end of line */
385 int eraeol(SCRN *t, int x, int y)
387 int *s, *ss, *a, *aa;
388 int w = t->co - x - 1; /* Don't worry about last column */
392 s = t->scrn + y * t->co + x;
393 a = t->attr + y * t->co + x;
400 } else if (*--aa != 0) {
406 if ((ss - s > 3 || s[w] != ' ' || a[w] != 0) && t->ce) {
409 texec(t->cap, t->ce, 1, 0, 0, 0, 0);
412 } else if (s != ss) {
415 if (t->x != x || t->y != y)
431 static void out(unsigned char *t, unsigned char c)
436 SCRN *nopen(CAP *cap)
438 SCRN *t = calloc(1, sizeof(SCRN));
444 setcap(cap, baud, out, NULL);
446 t->li = getnum(t->cap,US "li");
449 t->co = getnum(t->cap,US "co");
454 if (x > 7 && y > 3) {
459 t->haz = getflag(t->cap,US "hz");
460 t->os = getflag(t->cap,US "os");
461 t->eo = getflag(t->cap,US "eo");
462 if (getflag(t->cap,US "hc"))
464 if (t->os || getflag(t->cap,US "ul"))
467 t->xn = getflag(t->cap,US "xn");
468 t->am = getflag(t->cap,US "am");
470 t->cl = jgetstr(t->cap,US "cl");
471 t->cd = jgetstr(t->cap,US "cd");
474 t->ti = jgetstr(t->cap,US "ti");
475 t->te = jgetstr(t->cap,US "te");
477 if (pastetite && t->cap->paste_on && t->cap->paste_off) {
479 t->ti = (void *)strdup(t->cap->paste_on);
480 t->te = (void *)strdup(t->cap->paste_off);
485 n1 = t->ti ? strlen(t->ti) : 0;
486 n2 = strlen(t->cap->paste_on);
487 cp = joe_malloc(n1 + n2 + 1);
489 memcpy(cp, t->ti, n1);
490 memcpy(cp + n1, t->cap->paste_on, n2 + 1);
493 n1 = t->te ? strlen(t->te) : 0;
494 n2 = strlen(t->cap->paste_off);
495 cp = joe_malloc(n1 + n2 + 1);
496 memcpy(cp, t->cap->paste_off, n2 + 1);
498 memcpy(cp + n2, t->te, n1 + 1);
503 t->ut = getflag(t->cap,US "ut");
504 t->Sb = jgetstr(t->cap,US "AB");
505 if (!t->Sb) t->Sb = jgetstr(t->cap,US "Sb");
506 t->Sf = jgetstr(t->cap,US "AF");
507 if (!t->Sf) t->Sf = jgetstr(t->cap,US "Sf");
509 if (!(t->me = jgetstr(t->cap,US "me")))
511 if ((t->mb = jgetstr(t->cap,US "mb")))
513 if ((t->md = jgetstr(t->cap,US "md")))
515 if ((t->mh = jgetstr(t->cap,US "mh")))
517 if ((t->mr = jgetstr(t->cap,US "mr")))
518 t->avattr |= INVERSE;
523 /* Install color support if it looks like an ansi terminal (it has bold which begins with ESC [) */
525 if (!t->Sf && t->md && t->md[0]=='\\' && t->md[1]=='E' && t->md[2]=='[') {
527 t->Sf =US "\\E[3%dm";
528 t->Sb =US "\\E[4%dm";
531 if (!t->Sf && t->md && t->md[0]=='\033' && t->md[1]=='[') {
533 t->Sf =US "\033[3%p1%dm";
534 t->Sb =US "\033[4%p1%dm";
539 if (getnum(t->cap,US "sg") <= 0 && !t->mr && jgetstr(t->cap,US "se")) {
540 if ((t->so = jgetstr(t->cap,US "so")) != NULL)
541 t->avattr |= INVERSE;
542 t->se = jgetstr(t->cap,US "se");
544 if (getflag(t->cap,US "xs") || getflag(t->cap,US "xt"))
547 if (getnum(t->cap,US "ug") <= 0 && jgetstr(t->cap,US "ue")) {
548 if ((t->us = jgetstr(t->cap,US "us")) != NULL)
549 t->avattr |= UNDERLINE;
550 t->ue = jgetstr(t->cap,US "ue");
553 if (!(t->uc = jgetstr(t->cap,US "uc")))
557 t->avattr |= UNDERLINE;
559 t->ms = getflag(t->cap,US "ms");
561 t->da = getflag(t->cap,US "da");
562 t->db = getflag(t->cap,US "db");
563 t->cs = jgetstr(t->cap,US "cs");
564 t->rr = getflag(t->cap,US "rr");
565 t->sf = jgetstr(t->cap,US "sf");
566 t->sr = jgetstr(t->cap,US "sr");
567 t->SF = jgetstr(t->cap,US "SF");
568 t->SR = jgetstr(t->cap,US "SR");
569 t->al = jgetstr(t->cap,US "al");
570 t->dl = jgetstr(t->cap,US "dl");
571 t->AL = jgetstr(t->cap,US "AL");
572 t->DL = jgetstr(t->cap,US "DL");
573 if (!getflag(t->cap,US "ns") && !t->sf)
576 if (!getflag(t->cap,US "in") && baud < 38400) {
577 t->dc = jgetstr(t->cap,US "dc");
578 t->DC = jgetstr(t->cap,US "DC");
579 t->dm = jgetstr(t->cap,US "dm");
580 t->ed = jgetstr(t->cap,US "ed");
582 t->im = jgetstr(t->cap,US "im");
583 t->ei = jgetstr(t->cap,US "ei");
584 t->ic = jgetstr(t->cap,US "ic");
585 t->IC = jgetstr(t->cap,US "IC");
586 t->ip = jgetstr(t->cap,US "ip");
587 t->mi = getflag(t->cap,US "mi");
590 if (jgetstr(t->cap,US "bc"))
591 t->bs = jgetstr(t->cap,US "bc");
592 else if (jgetstr(t->cap,US "le"))
593 t->bs = jgetstr(t->cap,US "le");
594 if (getflag(t->cap,US "bs"))
597 t->cbs = tcost(t->cap, t->bs, 1, 2, 2, 0, 0);
600 if (jgetstr(t->cap,US "do"))
601 t->lf = jgetstr(t->cap,US "do");
602 t->clf = tcost(t->cap, t->lf, 1, 2, 2, 0, 0);
604 t->up = jgetstr(t->cap,US "up");
605 t->cup = tcost(t->cap, t->up, 1, 2, 2, 0, 0);
607 t->nd = jgetstr(t->cap,US "nd");
610 if (getnum(t->cap,US "it") > 0)
611 t->tw = getnum(t->cap,US "it");
612 else if (getnum(t->cap,US "tw") > 0)
613 t->tw = getnum(t->cap,US "tw");
615 if (!(t->ta = jgetstr(t->cap,US "ta")))
616 if (getflag(t->cap,US "pt"))
618 t->bt = jgetstr(t->cap,US "bt");
619 if (getflag(t->cap,US "xt") || !usetabs) {
624 t->cta = tcost(t->cap, t->ta, 1, 2, 2, 0, 0);
625 t->cbt = tcost(t->cap, t->bt, 1, 2, 2, 0, 0);
627 t->ho = jgetstr(t->cap,US "ho");
628 t->cho = tcost(t->cap, t->ho, 1, 2, 2, 0, 0);
629 t->ll = jgetstr(t->cap,US "ll");
630 t->cll = tcost(t->cap, t->ll, 1, 2, 2, 0, 0);
633 if (jgetstr(t->cap,US "cr"))
634 t->cr = jgetstr(t->cap,US "cr");
635 if (getflag(t->cap,US "nc") || getflag(t->cap,US "xr"))
637 t->ccr = tcost(t->cap, t->cr, 1, 2, 2, 0, 0);
639 t->cRI = tcost(t->cap, t->RI = jgetstr(t->cap,US "RI"), 1, 2, 2, 0, 0);
640 t->cLE = tcost(t->cap, t->LE = jgetstr(t->cap,US "LE"), 1, 2, 2, 0, 0);
641 t->cUP = tcost(t->cap, t->UP = jgetstr(t->cap,US "UP"), 1, 2, 2, 0, 0);
642 t->cDO = tcost(t->cap, t->DO = jgetstr(t->cap,US "DO"), 1, 2, 2, 0, 0);
643 t->cch = tcost(t->cap, t->ch = jgetstr(t->cap,US "ch"), 1, 2, 2, 0, 0);
644 t->ccv = tcost(t->cap, t->cv = jgetstr(t->cap,US "cv"), 1, 2, 2, 0, 0);
645 t->ccV = tcost(t->cap, t->cV = jgetstr(t->cap,US "cV"), 1, 2, 2, 0, 0);
646 t->ccm = tcost(t->cap, t->cm = jgetstr(t->cap,US "cm"), 1, 2, 2, 0, 0);
648 t->cce = tcost(t->cap, t->ce = jgetstr(t->cap,US "ce"), 1, 2, 2, 0, 0);
650 /* Make sure terminal can do absolute positioning */
655 if (t->ho && (t->lf || t->DO || t->cv))
657 if (t->ll && (t->up || t->UP || t->cv))
665 /* these are strings, but I do not know if %s is appropriate -mirabilos */
666 fprintf(stderr,"cm=%d ch=%d cv=%d ho=%d lf=%d DO=%d ll=%d up=%d UP=%d cr=%d\n",
667 t->cm, t->ch, t->cv, t->ho, t->lf, t->DO, t->ll, t->up, t->UP, t->cr);
669 fprintf(stderr,"Sorry, your terminal can't do absolute cursor positioning.\nIt's broken\n");
673 /* Determine if we can scroll */
674 if (((t->sr || t->SR) && (t->sf || t->SF) && t->cs) || ((t->al || t->AL) && (t->dl || t->DL)))
676 else if (baud < 38400)
679 /* Determine if we can ins/del within lines */
680 if ((t->im || t->ic || t->IC) && (t->dc || t->DC))
683 /* Adjust for high baud rates */
689 /* Send out terminal initialization string */
691 texec(t->cap, t->ti, 1, 0, 0, 0, 0);
692 if (!skiptop && t->cl)
693 texec(t->cap, t->cl, 1, 0, 0, 0, 0);
695 /* Initialize variable screen size dependant vars */
696 t->htab = calloc(256, sizeof(struct hentry));
698 nresize(t, t->co, t->li);
703 /* Change size of screen */
705 void nresize(SCRN *t, int w, int h)
724 joe_free(t->compose);
729 t->scrn = calloc(t->li * t->co, sizeof(int));
730 t->attr = calloc(t->li * t->co, sizeof(int));
731 t->sary = calloc(t->li, sizeof(int));
732 t->updtab = calloc(t->li, sizeof(int));
733 t->syntab = calloc(t->li, sizeof(int));
734 t->compose = calloc(t->co, sizeof(int));
735 t->ofst = calloc(t->co, sizeof(int));
736 t->ary = calloc(t->co, sizeof(struct hentry));
741 /* Calculate cost of positioning the cursor using only relative cursor
742 * positioning functions: t->(lf, DO, up, UP, bs, LE, RI, ta, bt) and rewriting
743 * characters (to move right)
745 * This doesn't use the am and bw capabilities although it probably could.
748 static int relcost(register SCRN *t, register int x, register int y, register int ox, register int oy)
752 /* If we don't know the cursor position, force use of absolute positioning */
753 if (oy == -1 || ox == -1)
756 /* First adjust row */
760 /* Have to go down */
762 int mult = dist * t->clf;
764 if (dist < 10 && t->cDO < mult)
766 else if (dist >= 10 && t->cDO + 1 < mult)
782 int mult = dist * t->cup;
784 if (dist < 10 && t->cUP < mult)
786 else if (dist >= 10 && t->cUP < mult)
799 /* Now adjust column */
802 if (x > ox && t->ta) {
804 int ntabs = (dist + ox % t->tw) / t->tw;
805 int cstunder = x % t->tw + t->cta * ntabs;
808 if (x + t->tw < t->co && t->bs)
809 cstover = t->cbs * (t->tw - x % t->tw) + t->cta * (ntabs + 1);
812 if (dist < 10 && cstunder < t->cRI && cstunder < x - ox && cstover > cstunder)
813 return cost + cstunder;
814 else if (cstunder < t->cRI + 1 && cstunder < x - ox && cstover > cstunder)
815 return cost + cstunder;
816 else if (dist < 10 && cstover < t->cRI && cstover < x - ox)
817 return cost + cstover;
818 else if (cstover < t->cRI + 1 && cstover < x - ox)
819 return cost + cstover;
820 } else if (x < ox && t->bt) {
822 int ntabs = (dist + t->tw - ox % t->tw) / t->tw;
823 int cstunder, cstover;
826 cstunder = t->cbt * ntabs + t->cbs * (t->tw - x % t->tw);
830 cstover = t->cbt * (ntabs + 1) + x % t->tw;
833 if (dist < 10 && cstunder < t->cLE && (t->bs ? cstunder < (ox - x) * t->cbs : 1)
834 && cstover > cstunder)
835 return cost + cstunder;
836 if (cstunder < t->cLE + 1 && (t->bs ? cstunder < (ox - x) * t->cbs : 1)
837 && cstover > cstunder)
838 return cost + cstunder;
839 else if (dist < 10 && cstover < t->cRI && (t->bs ? cstover < (ox - x) * t->cbs : 1))
840 return cost + cstover;
841 else if (cstover < t->cRI + 1 && (t->bs ? cstover < (ox - x) * t->cbs : 1))
842 return cost + cstover;
845 /* Use simple motions */
849 /* Have to go left */
851 int mult = dist * t->cbs;
853 if (t->cLE < mult && dist < 10)
855 else if (t->cLE + 1 < mult)
866 /* Have to go right */
867 /* Hmm.. this should take into account possible attribute changes */
868 if (t->cRI < dist && dist < 10)
870 else if (t->cRI + 1 < dist)
879 /* Find optimal set of cursor positioning commands to move from the current
880 * cursor row and column (either or both of which might be unknown) to the
881 * given new row and column and execute them.
884 static void cposs(register SCRN *t, register int x, register int y)
886 register int bestcost, cost;
891 /* Home y position is usually 0, but it is 'top' if we have scrolling region
892 * relative addressing
902 /* Assume best way is with only using relative cursor positioning */
904 bestcost = relcost(t, x, y, t->x, t->y);
907 /* Now check if combinations of absolute cursor positioning functions are
908 * better (or necessary in case one or both cursor positions are unknown)
911 if (t->ccm < bestcost) {
912 cost = tcost(t->cap, t->cm, 1, y, x, 0, 0);
913 if (cost < bestcost) {
918 if (t->ccr < bestcost) {
919 cost = relcost(t, x, y, 0, t->y) + t->ccr;
920 if (cost < bestcost) {
925 if (t->cho < bestcost) {
926 cost = relcost(t, x, y, 0, hy) + t->cho;
927 if (cost < bestcost) {
932 if (t->cll < bestcost) {
933 cost = relcost(t, x, y, 0, hl) + t->cll;
934 if (cost < bestcost) {
939 if (t->cch < bestcost && x != t->x) {
940 cost = relcost(t, x, y, x, t->y) + tcost(t->cap, t->ch, 1, x, 0, 0, 0);
941 if (cost < bestcost) {
946 if (t->ccv < bestcost && y != t->y) {
947 cost = relcost(t, x, y, t->x, y) + tcost(t->cap, t->cv, 1, y, 0, 0, 0);
948 if (cost < bestcost) {
953 if (t->ccV < bestcost) {
954 cost = relcost(t, x, y, 0, y) + tcost(t->cap, t->cV, 1, y, 0, 0, 0);
955 if (cost < bestcost) {
960 if (t->cch + t->ccv < bestcost && x != t->x && y != t->y) {
961 cost = tcost(t->cap, t->cv, 1, y - hy, 0, 0, 0) + tcost(t->cap, t->ch, 1, x, 0, 0, 0);
962 if (cost < bestcost) {
967 if (t->ccv + t->ccr < bestcost && y != t->y) {
968 cost = tcost(t->cap, t->cv, 1, y, 0, 0, 0) + tcost(t->cap, t->cr, 1, 0, 0, 0, 0) + relcost(t, x, y, 0, y);
969 if (cost < bestcost) {
974 if (t->cll + t->cch < bestcost) {
975 cost = tcost(t->cap, t->ll, 1, 0, 0, 0, 0) + tcost(t->cap, t->ch, 1, x, 0, 0, 0) + relcost(t, x, y, x, hl);
976 if (cost < bestcost) {
981 if (t->cll + t->ccv < bestcost) {
982 cost = tcost(t->cap, t->ll, 1, 0, 0, 0, 0) + tcost(t->cap, t->cv, 1, y, 0, 0, 0) + relcost(t, x, y, 0, y);
983 if (cost < bestcost) {
988 if (t->cho + t->cch < bestcost) {
989 cost = tcost(t->cap, t->ho, 1, 0, 0, 0, 0) + tcost(t->cap, t->ch, 1, x, 0, 0, 0) + relcost(t, x, y, x, hy);
990 if (cost < bestcost) {
995 if (t->cho + t->ccv < bestcost) {
996 cost = tcost(t->cap, t->ho, 1, 0, 0, 0, 0) + tcost(t->cap, t->cv, 1, y, 0, 0, 0) + relcost(t, x, y, 0, y);
997 if (cost < bestcost) {
998 /* dead store: bestcost = cost; */
1003 /* Do absolute cursor positioning if we don't know the cursor position or
1004 * if it is faster than doing only relative cursor positioning
1009 texec(t->cap, t->cr, 1, 0, 0, 0, 0);
1013 texec(t->cap, t->ho, 1, 0, 0, 0, 0);
1018 texec(t->cap, t->ll, 1, 0, 0, 0, 0);
1023 texec(t->cap, t->ll, 1, 0, 0, 0, 0);
1028 texec(t->cap, t->ho, 1, 0, 0, 0, 0);
1034 texec(t->cap, t->ch, 1, x, 0, 0, 0);
1038 texec(t->cap, t->ll, 1, 0, 0, 0, 0);
1043 texec(t->cap, t->ho, 1, 0, 0, 0, 0);
1048 texec(t->cap, t->cr, 1, 0, 0, 0, 0);
1053 texec(t->cap, t->cv, 1, y, 0, 0, 0);
1057 texec(t->cap, t->cm, 1, y, x, 0, 0);
1062 texec(t->cap, t->cv, 1, y, 0, 0, 0);
1064 texec(t->cap, t->ch, 1, x, 0, 0, 0);
1068 texec(t->cap, t->cV, 1, y, 0, 0, 0);
1074 /* Use relative cursor position functions if we're not there yet */
1076 /* First adjust row */
1078 /* Have to go down */
1079 if (!t->lf || t->cDO < (y - t->y) * t->clf) {
1080 texec(t->cap, t->DO, 1, y - t->y, 0, 0, 0);
1084 texec(t->cap, t->lf, 1, 0, 0, 0, 0);
1087 } else if (y < t->y) {
1089 if (!t->up || t->cUP < (t->y - y) * t->cup) {
1090 texec(t->cap, t->UP, 1, t->y - y, 0, 0, 0);
1094 texec(t->cap, t->up, 1, 0, 0, 0, 0);
1100 if (x > t->x && t->ta) {
1101 int ntabs = (x - t->x + t->x % t->tw) / t->tw;
1102 int cstunder = x % t->tw + t->cta * ntabs;
1105 if (x + t->tw < t->co && t->bs)
1106 cstover = t->cbs * (t->tw - x % t->tw) + t->cta * (ntabs + 1);
1109 if (cstunder < t->cRI && cstunder < x - t->x && cstover > cstunder) {
1111 t->x = x - x % t->tw;
1113 texec(t->cap, t->ta, 1, 0, 0, 0, 0);
1116 } else if (cstover < t->cRI && cstover < x - t->x) {
1117 t->x = t->tw + x - x % t->tw;
1120 texec(t->cap, t->ta, 1, 0, 0, 0, 0);
1123 } else if (x < t->x && t->bt) {
1124 int ntabs = ((t->x + t->tw - 1) - (t->x + t->tw - 1) % t->tw - ((x + t->tw - 1) - (x + t->tw - 1) % t->tw)) / t->tw;
1125 int cstunder, cstover;
1128 cstunder = t->cbt * ntabs + t->cbs * (t->tw - x % t->tw);
1132 cstover = t->cbt * (ntabs + 1) + x % t->tw;
1135 if (cstunder < t->cLE && (t->bs ? cstunder < (t->x - x) * t->cbs : 1)
1136 && cstover > cstunder) {
1139 texec(t->cap, t->bt, 1, 0, 0, 0, 0);
1141 t->x = x + t->tw - x % t->tw;
1143 } else if (cstover < t->cRI && (t->bs ? cstover < (t->x - x) * t->cbs : 1)) {
1144 t->x = x - x % t->tw;
1147 texec(t->cap, t->bt, 1, 0, 0, 0, 0);
1152 /* Now adjust column */
1154 /* Have to go left */
1155 if (!t->bs || t->cLE < (t->x - x) * t->cbs) {
1156 texec(t->cap, t->LE, 1, t->x - x, 0, 0, 0);
1160 texec(t->cap, t->bs, 1, 0, 0, 0, 0);
1163 } else if (x > t->x) {
1164 /* Have to go right */
1165 /* Hmm.. this should take into account possible attribute changes */
1166 if (x-t->x>1 && t->RI) {
1167 texec(t->cap, t->RI, 1, x - t->x, 0, 0, 0);
1171 texec(t->cap, t->nd, 1, 0, 0, 0, 0);
1176 /* if (t->cRI < x - t->x) { */
1178 int *s = t->scrn + t->x + t->y * t->co;
1179 int *a = t->attr + t->x + t->y * t->co;
1185 if(*s==-1) c=' ', atr=0;
1186 else c= *s, atr= *a;
1188 if (atr != t->attrib)
1200 int cpos(register SCRN *t, register int x, register int y)
1202 /* Move cursor quickly if we can */
1204 if (x > t->x && x - t->x < 4 && !t->ins) {
1205 int *cs = t->scrn + t->x + t->co * t->y;
1206 int *as = t->attr + t->x + t->co * t->y;
1208 /* We used to space over unknown chars, but they now could be
1209 the right half of a UTF-8 two column character, so we can't.
1210 Also do not try to emit utf-8 sequences here. */
1211 if(*cs<32 || *cs>=127)
1214 /* has a combining character attached? */
1215 if (*as & HAS_COMBINING)
1218 if (*as != t->attrib)
1227 } while (x != t->x);
1232 if ((!t->ms && t->attrib & (INVERSE | UNDERLINE | BG_NOT_DEFAULT)) ||
1233 (t->ut && (t->attrib & BG_NOT_DEFAULT)))
1234 set_attr(t, t->attrib & ~(INVERSE | UNDERLINE | BG_MASK));
1236 /* Should be in cposs */
1237 if (y < t->top || y >= t->bot)
1238 setregn(t, 0, t->li);
1244 static void doinschr(SCRN *t, int x, int y, int *s, int *as, int n)
1253 if (x >= t->co - 1 || n <= 0)
1255 if (t->im || t->ic || t->IC) {
1257 if ((n == 1 && t->ic) || !t->IC) {
1260 for (a = 0; a != n; ++a) {
1261 texec(t->cap, t->ic, 1, x, 0, 0, 0);
1262 texec(t->cap, t->ip, 1, x, 0, 0, 0);
1267 texec(t->cap, t->IC, 1, n, 0, 0, 0);
1270 mmove(t->scrn + x + t->co * y + n, t->scrn + x + t->co * y, (t->co - (x + n)) * sizeof(int));
1271 mmove(t->attr + x + t->co * y + n, t->attr + x + t->co * y, (t->co - (x + n)) * sizeof(int));
1272 mmove(t->scrn + x + t->co * y, s, n * sizeof(int));
1273 mmove(t->attr + x + t->co * y, s, n * sizeof(int));
1276 static void dodelchr(SCRN *t, int x, int y, int n)
1282 if (!n || x >= t->co - 1)
1284 if (t->dc || t->DC) {
1286 texec(t->cap, t->dm, 1, x, 0, 0, 0); /* Enter delete mode */
1287 if ((n == 1 && t->dc) || !t->DC)
1289 texec(t->cap, t->dc, 1, x, 0, 0, 0);
1291 texec(t->cap, t->DC, 1, n, 0, 0, 0);
1292 texec(t->cap, t->ed, 1, x, 0, 0, 0); /* Exit delete mode */
1294 mmove(t->scrn + t->co * y + x, t->scrn + t->co * y + x + n, (t->co - (x + n)) * sizeof(int));
1295 mmove(t->attr + t->co * y + x, t->attr + t->co * y + x + n, (t->co - (x + n)) * sizeof(int));
1296 msetI(t->scrn + t->co * y + t->co - n, ' ', n);
1297 msetI(t->attr + t->co * y + t->co - n, 0, n);
1300 /* Insert/Delete within line */
1301 /* FIXME: doesn't know about attr */
1303 void magic(SCRN *t, int y, int *cs, int *ca,int *s, int *a, int placex)
1305 struct hentry *htab = t->htab;
1306 int *ofst = t->ofst;
1310 if (!(t->im || t->ic || t->IC) || !(t->dc || t->DC))
1312 mset(htab, 0, 256 * sizeof(struct hentry));
1314 msetI(ofst, 0, t->co);
1316 /* Build hash table */
1317 for (x = 0; x != t->co - 1; ++x) {
1318 t->ary[aryx].next = htab[cs[x] & 255].next;
1319 t->ary[aryx].loc = x;
1320 ++htab[cs[x] & 255].loc;
1321 htab[cs[x] & 255].next = aryx++;
1324 /* Build offset table */
1325 for (x = 0; x < t->co - 1;)
1326 if (htab[s[x] & 255].loc >= 15)
1327 ofst[x++] = t->co - 1;
1336 for (aryy = htab[s[x] & 255].next; aryy; aryy = t->ary[aryy].next) {
1338 int tsfo = t->ary[aryy].loc - x;
1339 int cst = -abs(tsfo);
1342 for (amnt = 0; x + amnt < t->co - 1 && x + tsfo + amnt < t->co - 1; ++amnt) {
1343 if (cs[x + tsfo + amnt] != s[x + amnt])
1345 else if ((s[x + amnt] & 255) != 32 || pre != 32)
1347 pre = s[x + amnt] & 255;
1350 for (back = 0; back + x > 0 && back + tsfo + x > 0; --back) {
1351 if (cs[x + tsfo + back - 1] != s[x + back - 1])
1353 else if ((s[x + back - 1] & 255) != 32 || pre != 32)
1355 pre = s[x + back - 1] & 255;
1365 ofst[x] = t->co - 1;
1367 } else if (best < 2)
1368 for (z = 0; z != maxlen; ++z)
1369 ofst[x + z] = t->co - 1;
1371 for (z = 0; z != maxlen - bestback; ++z)
1372 ofst[x + z + bestback] = t->ary[maxaryy].loc - x;
1376 /* Apply scrolling commands */
1378 for (x = 0; x != t->co - 1; ++x) {
1381 if (q && q != t->co - 1) {
1385 for (z = x; z != t->co - 1 && ofst[z] == q; ++z)
1387 while (s[x] == cs[x] && x < placex)
1389 dodelchr(t, x, y, q);
1390 for (fu = x; fu != t->co - 1; ++fu)
1391 if (ofst[fu] != t->co - 1)
1397 for (z = x; z != t->co - 1 && ofst[z] == q; ++z)
1399 while (s[x + q] == cs[x + q] && x - q < placex)
1401 doinschr(t, x + q, y, s + x + q, a + x + q, -q);
1402 for (fu = x; fu != t->co - 1; ++fu)
1403 if (ofst[fu] != t->co - 1)
1411 static void doupscrl(SCRN *t, int top, int bot, int amnt)
1418 if (top == 0 && bot == t->li && (t->sf || t->SF)) {
1419 setregn(t, 0, t->li);
1420 cpos(t, 0, t->li - 1);
1421 if ((amnt == 1 && t->sf) || !t->SF)
1423 texec(t->cap, t->sf, 1, t->li - 1, 0, 0, 0);
1425 texec(t->cap, t->SF, a, a, 0, 0, 0);
1428 if (bot == t->li && (t->dl || t->DL)) {
1429 setregn(t, 0, t->li);
1431 if ((amnt == 1 && t->dl) || !t->DL)
1433 texec(t->cap, t->dl, 1, top, 0, 0, 0);
1435 texec(t->cap, t->DL, a, a, 0, 0, 0);
1438 if (t->cs && (t->sf || t->SF)) {
1439 setregn(t, top, bot);
1440 cpos(t, 0, bot - 1);
1441 if ((amnt == 1 && t->sf) || !t->SF)
1443 texec(t->cap, t->sf, 1, bot - 1, 0, 0, 0);
1445 texec(t->cap, t->SF, a, a, 0, 0, 0);
1448 if ((t->dl || t->DL) && (t->al || t->AL)) {
1450 if ((amnt == 1 && t->dl) || !t->DL)
1452 texec(t->cap, t->dl, 1, top, 0, 0, 0);
1454 texec(t->cap, t->DL, a, a, 0, 0, 0);
1456 cpos(t, 0, bot - amnt);
1457 if ((amnt == 1 && t->al) || !t->AL)
1459 texec(t->cap, t->al, 1, bot - amnt, 0, 0, 0);
1461 texec(t->cap, t->AL, a, a, 0, 0, 0);
1464 msetI(t->updtab + top, 1, bot - top);
1465 msetI(t->syntab + top, -1, bot - top);
1469 mmove(t->scrn + top * t->co, t->scrn + (top + amnt) * t->co, (bot - top - amnt) * t->co * sizeof(int));
1470 mmove(t->attr + top * t->co, t->attr + (top + amnt) * t->co, (bot - top - amnt) * t->co * sizeof(int));
1472 if (bot == t->li && t->db) {
1473 msetI(t->scrn + (t->li - amnt) * t->co, -1, amnt * t->co);
1474 msetI(t->attr + (t->li - amnt) * t->co, 0, amnt * t->co);
1475 msetI(t->updtab + t->li - amnt, 1, amnt);
1476 msetI(t->syntab + t->li - amnt, -1, amnt);
1478 msetI(t->scrn + (bot - amnt) * t->co, ' ', amnt * t->co);
1479 msetI(t->attr + (bot - amnt) * t->co, 0, amnt * t->co);
1483 static void dodnscrl(SCRN *t, int top, int bot, int amnt)
1490 if (top == 0 && bot == t->li && (t->sr || t->SR)) {
1491 setregn(t, 0, t->li);
1493 if ((amnt == 1 && t->sr) || !t->SR)
1495 texec(t->cap, t->sr, 1, 0, 0, 0, 0);
1497 texec(t->cap, t->SR, a, a, 0, 0, 0);
1500 if (bot == t->li && (t->al || t->AL)) {
1501 setregn(t, 0, t->li);
1503 if ((amnt == 1 && t->al) || !t->AL)
1505 texec(t->cap, t->al, 1, top, 0, 0, 0);
1507 texec(t->cap, t->AL, a, a, 0, 0, 0);
1510 if (t->cs && (t->sr || t->SR)) {
1511 setregn(t, top, bot);
1513 if ((amnt == 1 && t->sr) || !t->SR)
1515 texec(t->cap, t->sr, 1, top, 0, 0, 0);
1517 texec(t->cap, t->SR, a, a, 0, 0, 0);
1520 if ((t->dl || t->DL) && (t->al || t->AL)) {
1521 cpos(t, 0, bot - amnt);
1522 if ((amnt == 1 && t->dl) || !t->DL)
1524 texec(t->cap, t->dl, 1, bot - amnt, 0, 0, 0);
1526 texec(t->cap, t->DL, a, a, 0, 0, 0);
1529 if ((amnt == 1 && t->al) || !t->AL)
1531 texec(t->cap, t->al, 1, top, 0, 0, 0);
1533 texec(t->cap, t->AL, a, a, 0, 0, 0);
1536 msetI(t->updtab + top, 1, bot - top);
1537 msetI(t->syntab + top, -1, bot - top);
1540 mmove(t->scrn + (top + amnt) * t->co, t->scrn + top * t->co, (bot - top - amnt) * t->co * sizeof(int));
1541 mmove(t->attr + (top + amnt) * t->co, t->attr + top * t->co, (bot - top - amnt) * t->co * sizeof(int));
1543 if (!top && t->da) {
1544 msetI(t->scrn, -1, amnt * t->co);
1545 msetI(t->attr, 0, amnt * t->co);
1546 msetI(t->updtab, 1, amnt);
1547 msetI(t->syntab, -1, amnt);
1549 msetI(t->scrn + t->co * top, ' ', amnt * t->co);
1550 msetI(t->attr + t->co * top, 0, amnt * t->co);
1554 void nscroll(SCRN *t)
1558 for (y = 0; y != t->li; ++y) {
1562 if (q && q != t->li) {
1564 for (z = y; z != t->li && t->sary[z] == q; ++z)
1566 doupscrl(t, y, z + q, q);
1569 for (r = y; r != t->li && (t->sary[r] < 0 || t->sary[r] == t->li); ++r)
1574 if (q && q != t->li) {
1575 for (z = p; t->sary[z] = 0, (z && t->sary[z - 1] == q); --z)
1577 dodnscrl(t, z + q, p + 1, -q);
1585 msetI(t->sary, 0, t->li);
1588 void npartial(SCRN *t)
1592 setregn(t, 0, t->li);
1595 void nescape(SCRN *t)
1598 cpos(t, 0, t->li - 1);
1599 eraeol(t, 0, t->li - 1);
1601 texec(t->cap, t->te, 1, 0, 0, 0, 0);
1604 void nreturn(SCRN *t)
1607 texec(t->cap, t->ti, 1, 0, 0, 0, 0);
1608 if (!skiptop && t->cl)
1609 texec(t->cap, t->cl, 1, 0, 0, 0, 0);
1613 void nclose(SCRN *t)
1618 setregn(t, 0, t->li);
1619 cpos(t, 0, t->li - 1);
1621 texec(t->cap, t->te, 1, 0, 0, 0, 0);
1633 void nscrldn(SCRN *t, int top, int bot, int amnt)
1637 if (!amnt || top >= bot || bot > t->li)
1639 if ((amnt < bot - top && bot - top - amnt < amnt / 2) || !t->scroll)
1641 if (amnt < bot - top) {
1642 for (x = bot; x != top + amnt; --x) {
1643 t->sary[x - 1] = (t->sary[x - amnt - 1] == t->li ? t->li : t->sary[x - amnt - 1] - amnt);
1644 t->updtab[x - 1] = t->updtab[x - amnt - 1];
1645 t->syntab[x - 1] = t->syntab[x - amnt - 1];
1647 for (x = top; x != top + amnt; ++x) {
1652 if (amnt > bot - top)
1654 msetI(t->sary + top, t->li, amnt);
1655 if (amnt == bot - top) {
1656 msetI(t->updtab + top, 1, amnt);
1657 msetI(t->syntab + top, -1, amnt);
1661 void nscrlup(SCRN *t, int top, int bot, int amnt)
1665 if (!amnt || top >= bot || bot > t->li)
1667 if ((amnt < bot - top && bot - top - amnt < amnt / 2) || !t->scroll)
1669 if (amnt < bot - top) {
1670 for (x = top + amnt; x != bot; ++x) {
1671 t->sary[x - amnt] = (t->sary[x] == t->li ? t->li : t->sary[x] + amnt);
1672 t->updtab[x - amnt] = t->updtab[x];
1673 t->syntab[x - amnt] = t->syntab[x];
1675 for (x = bot - amnt; x != bot; ++x) {
1680 if (amnt > bot - top)
1682 msetI(t->sary + bot - amnt, t->li, amnt);
1683 if (amnt == bot - top) {
1684 msetI(t->updtab + bot - amnt, 1, amnt);
1685 msetI(t->syntab + bot - amnt, -1, amnt);
1689 extern volatile int dostaupd;
1691 void nredraw(SCRN *t)
1694 msetI(t->scrn, ' ', t->co * skiptop);
1695 msetI(t->attr, 0, t->co * skiptop);
1696 msetI(t->scrn + skiptop * t->co, -1, (t->li - skiptop) * t->co);
1697 msetI(t->attr + skiptop * t->co, 0, (t->li - skiptop) * t->co);
1698 msetI(t->sary, 0, t->li);
1699 msetI(t->updtab + skiptop, -1, t->li - skiptop);
1700 msetI(t->syntab + skiptop, -1, t->li - skiptop);
1709 setregn(t, 0, t->li);
1713 texec(t->cap, t->cl, 1, 0, 0, 0, 0);
1716 msetI(t->scrn, ' ', t->li * t->co);
1717 msetI(t->attr, 0, t->li * t->co);
1720 texec(t->cap, t->cd, 1, 0, 0, 0, 0);
1721 msetI(t->scrn, ' ', t->li * t->co);
1722 msetI(t->attr, 0, t->li * t->co);
1727 /* Convert color/attribute name into internal code */
1729 int meta_color(unsigned char *s)
1731 if(!strcmp((char *)s,"inverse"))
1733 else if(!strcmp((char *)s,"underline"))
1735 else if(!strcmp((char *)s,"bold"))
1737 else if(!strcmp((char *)s,"blink"))
1739 else if(!strcmp((char *)s,"dim"))
1741 else if(!strcmp((char *)s,"white"))
1743 else if(!strcmp((char *)s,"cyan"))
1745 else if(!strcmp((char *)s,"magenta"))
1747 else if(!strcmp((char *)s,"blue"))
1749 else if(!strcmp((char *)s,"yellow"))
1751 else if(!strcmp((char *)s,"green"))
1753 else if(!strcmp((char *)s,"red"))
1755 else if(!strcmp((char *)s,"black"))
1757 else if(!strcmp((char *)s,"bg_white"))
1759 else if(!strcmp((char *)s,"bg_cyan"))
1761 else if(!strcmp((char *)s,"bg_magenta"))
1763 else if(!strcmp((char *)s,"bg_blue"))
1765 else if(!strcmp((char *)s,"bg_yellow"))
1767 else if(!strcmp((char *)s,"bg_green"))
1769 else if(!strcmp((char *)s,"bg_red"))
1771 else if(!strcmp((char *)s,"bg_black"))
1779 * 't' is SCRN to write to.
1780 * 'scrn' is address of field in character buffer
1781 * 'attr' is address of field in attribute buffer
1782 * 'x', 'y' are starting column and line numbers of field
1783 * 'ofst' is first column within string to display
1784 * 's', 'len' is string to generate in field
1785 * 'atr' is screeen attributes (and color) which should be used
1786 * 'width' is column width of field
1787 * 'flg' if set, erases to end of line
1790 void genfield(SCRN *t,int *scrn,int *attr,int x,int y,int ofst,unsigned char *s,int len,int atr,int width,int flg,int *fmt)
1794 int last_col = x + width;
1798 for (col = 0;len != 0 && x < last_col; len--) {
1802 if (fmt) my_atr |= *fmt++;
1803 if (locale_map->type) {
1804 /* UTF-8 mode: decode character and determine its width */
1805 c = utf8_decode(&sm,c);
1807 wid = joe_wcwidth(1,c);
1809 /* Byte mode: character is one column wide */
1814 if (x + wid > last_col) {
1815 /* Character crosses end of field, so fill balance of field with '>' characters instead */
1816 while (x < last_col) {
1817 outatr(utf8_map, t, scrn, attr, x, y, '>', my_atr);
1822 } else /* if (wid >(=) 0) */ {
1823 /* Emit character */
1824 outatr(locale_map, t, scrn, attr, x, y, c, my_atr);
1829 } else if ((col + wid) > ofst) {
1830 /* Wide character crosses left side of field */
1834 outatr(utf8_map, t, scrn, attr, x, y, '<', my_atr);
1845 /* Fill balance of field with spaces */
1846 while (x < last_col) {
1847 outatr(utf8_map, t, scrn, attr, x, y, ' ', 0);
1852 /* Erase to end of line */
1857 /* Width function for above */
1859 int txtwidth(unsigned char *s,int len)
1861 if (locale_map->type) {
1867 int d = utf8_decode(&sm,*s++);
1869 col += joe_wcwidth(1,d);
1877 /* Generate text with formatting escape sequences */
1879 void genfmt(SCRN *t, int x, int y, int ofst, const unsigned char *s, int flg)
1881 int *scrn = t->scrn + y * t->co + x;
1882 int *attr = t->attr + y * t->co + x;
1890 while ((c = *s++) != '\0')
1917 if (col++ >= ofst) {
1918 outatr(locale_map, t, scrn, attr, x, y, (c&0x7F), atr);
1928 if (locale_map->type) {
1929 /* UTF-8 mode: decode character and determine its width */
1930 c = utf8_decode(&sm,c);
1932 wid = joe_wcwidth(1, c);
1935 /* Byte mode: character is one column wide */
1941 outatr(locale_map, t, scrn, attr, x, y, c, atr);
1946 } else if (col+wid>ofst) {
1952 outatr(utf8_map, t, scrn, attr, x, y, '<', atr);
1967 /* Determine column width of string with format codes */
1969 int fmtlen(const unsigned char *s)
1977 while ((c = (*s++))) {
1999 if(locale_map->type) {
2000 c = utf8_decode(&sm,c);
2002 wid = joe_wcwidth(1,c);
2012 /* Return offset within format string which corresponds to a particular
2015 /* FIXME: this is not valid if we land in the middle of a double-wide character */
2017 int fmtpos(unsigned char *s, int goal)
2019 unsigned char *org = s;
2026 while ((c= *s) && col<goal) {
2050 if(locale_map->type) {
2051 c = utf8_decode(&sm,c);
2053 wid = joe_wcwidth(1,c);
2061 return s - org + goal - col;