1 /* $MirOS: contrib/code/jupp/scrn.c,v 1.19 2017/01/10 23:59:33 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 unsigned char buf[16];
211 /* Deal with control characters */
218 } else if (unictrl(c)) {
223 if(*scrn==c && *attrf==a)
226 wid = joe_wcwidth(1,c);
232 if(t->x != xx || t->y != yy)
237 joe_snprintf_1((char *)buf,16,"<%X>",c);
250 /* UTF-8 char to non-UTF-8 terminal */
251 /* Don't convert control chars below 256 */
252 if ((c>=32 && c<=126) || c>=160) {
255 c = from_uni(locale_map,c);
260 /* Deal with control characters */
261 if (!joe_isprint(locale_map,c) && !(dspasis && c>=128)) {
266 if(*scrn==c && *attrf==a)
273 if(t->x != xx || t->y != yy)
281 if (!locale_map->type) {
282 /* Non UTF-8 char to non UTF-8 terminal */
283 /* Byte-byte Translate? */
285 /* Deal with control characters */
286 if (!joe_isprint(locale_map,c) && !(dspasis && c>=128)) {
291 if (*scrn==c && *attrf==a)
299 if(t->x != xx || t->y != yy)
306 /* Non UTF-8 char to UTF-8 terminal */
307 unsigned char buf[16];
310 /* Deal with control characters */
311 if (!(dspasis && c>=128) && !joe_isprint(map,c)) {
317 if (c < 32 || (c >= 0x7F && c < 0xA0)) {
319 a = (a | UNDERLINE) ^ INVERSE;
323 if (*scrn == c && *attrf == a)
326 wid = joe_wcwidth(0,c);
331 if(t->x != xx || t->y != yy)
345 /* Set scrolling region */
347 static void setregn(SCRN *t, int top, int bot)
354 if (t->top != top || t->bot != bot) {
357 texec(t->cap, t->cs, 1, top, bot - 1, 0, 0);
363 /* Enter insert mode */
365 static void setins(SCRN *t, int x)
367 if (t->ins != 1 && t->im) {
369 texec(t->cap, t->im, 1, x, 0, 0, 0);
373 /* Exit insert mode */
378 texec(t->cap, t->ei, 1, 0, 0, 0, 0);
384 /* Erase from given screen coordinate to end of line */
386 int eraeol(SCRN *t, int x, int y)
388 int *s, *ss, *a, *aa;
389 int w = t->co - x - 1; /* Don't worry about last column */
393 s = t->scrn + y * t->co + x;
394 a = t->attr + y * t->co + x;
401 } else if (*--aa != 0) {
407 if ((ss - s > 3 || s[w] != ' ' || a[w] != 0) && t->ce) {
410 texec(t->cap, t->ce, 1, 0, 0, 0, 0);
413 } else if (s != ss) {
416 if (t->x != x || t->y != y)
432 static void out(unsigned char *t, unsigned char c)
437 SCRN *nopen(CAP *cap)
439 SCRN *t = calloc(1, sizeof(SCRN));
445 setcap(cap, baud, out, NULL);
447 t->li = getnum(t->cap,US "li");
450 t->co = getnum(t->cap,US "co");
455 if (x > 7 && y > 3) {
460 t->haz = getflag(t->cap,US "hz");
461 t->os = getflag(t->cap,US "os");
462 t->eo = getflag(t->cap,US "eo");
463 if (getflag(t->cap,US "hc"))
465 if (t->os || getflag(t->cap,US "ul"))
468 t->xn = getflag(t->cap,US "xn");
469 t->am = getflag(t->cap,US "am");
471 t->cl = jgetstr(t->cap,US "cl");
472 t->cd = jgetstr(t->cap,US "cd");
475 t->ti = jgetstr(t->cap,US "ti");
476 t->te = jgetstr(t->cap,US "te");
478 if (pastetite && t->cap->paste_on && t->cap->paste_off) {
480 t->ti = (void *)strdup(t->cap->paste_on);
481 t->te = (void *)strdup(t->cap->paste_off);
486 n1 = t->ti ? strlen(t->ti) : 0;
487 n2 = strlen(t->cap->paste_on);
488 cp = joe_malloc(n1 + n2 + 1);
490 memcpy(cp, t->ti, n1);
491 memcpy(cp + n1, t->cap->paste_on, n2 + 1);
494 n1 = t->te ? strlen(t->te) : 0;
495 n2 = strlen(t->cap->paste_off);
496 cp = joe_malloc(n1 + n2 + 1);
497 memcpy(cp, t->cap->paste_off, n2 + 1);
499 memcpy(cp + n2, t->te, n1 + 1);
504 t->ut = getflag(t->cap,US "ut");
505 t->Sb = jgetstr(t->cap,US "AB");
506 if (!t->Sb) t->Sb = jgetstr(t->cap,US "Sb");
507 t->Sf = jgetstr(t->cap,US "AF");
508 if (!t->Sf) t->Sf = jgetstr(t->cap,US "Sf");
510 if (!(t->me = jgetstr(t->cap,US "me")))
512 if ((t->mb = jgetstr(t->cap,US "mb")))
514 if ((t->md = jgetstr(t->cap,US "md")))
516 if ((t->mh = jgetstr(t->cap,US "mh")))
518 if ((t->mr = jgetstr(t->cap,US "mr")))
519 t->avattr |= INVERSE;
524 /* Install color support if it looks like an ansi terminal (it has bold which begins with ESC [) */
526 if (!t->Sf && t->md && t->md[0]=='\\' && t->md[1]=='E' && t->md[2]=='[') {
528 t->Sf =US "\\E[3%dm";
529 t->Sb =US "\\E[4%dm";
532 if (!t->Sf && t->md && t->md[0]=='\033' && t->md[1]=='[') {
534 t->Sf =US "\033[3%p1%dm";
535 t->Sb =US "\033[4%p1%dm";
540 if (getnum(t->cap,US "sg") <= 0 && !t->mr && jgetstr(t->cap,US "se")) {
541 if ((t->so = jgetstr(t->cap,US "so")) != NULL)
542 t->avattr |= INVERSE;
543 t->se = jgetstr(t->cap,US "se");
545 if (getflag(t->cap,US "xs") || getflag(t->cap,US "xt"))
548 if (getnum(t->cap,US "ug") <= 0 && jgetstr(t->cap,US "ue")) {
549 if ((t->us = jgetstr(t->cap,US "us")) != NULL)
550 t->avattr |= UNDERLINE;
551 t->ue = jgetstr(t->cap,US "ue");
554 if (!(t->uc = jgetstr(t->cap,US "uc")))
558 t->avattr |= UNDERLINE;
560 t->ms = getflag(t->cap,US "ms");
562 t->da = getflag(t->cap,US "da");
563 t->db = getflag(t->cap,US "db");
564 t->cs = jgetstr(t->cap,US "cs");
565 t->rr = getflag(t->cap,US "rr");
566 t->sf = jgetstr(t->cap,US "sf");
567 t->sr = jgetstr(t->cap,US "sr");
568 t->SF = jgetstr(t->cap,US "SF");
569 t->SR = jgetstr(t->cap,US "SR");
570 t->al = jgetstr(t->cap,US "al");
571 t->dl = jgetstr(t->cap,US "dl");
572 t->AL = jgetstr(t->cap,US "AL");
573 t->DL = jgetstr(t->cap,US "DL");
574 if (!getflag(t->cap,US "ns") && !t->sf)
577 if (!getflag(t->cap,US "in") && baud < 38400) {
578 t->dc = jgetstr(t->cap,US "dc");
579 t->DC = jgetstr(t->cap,US "DC");
580 t->dm = jgetstr(t->cap,US "dm");
581 t->ed = jgetstr(t->cap,US "ed");
583 t->im = jgetstr(t->cap,US "im");
584 t->ei = jgetstr(t->cap,US "ei");
585 t->ic = jgetstr(t->cap,US "ic");
586 t->IC = jgetstr(t->cap,US "IC");
587 t->ip = jgetstr(t->cap,US "ip");
588 t->mi = getflag(t->cap,US "mi");
591 if (jgetstr(t->cap,US "bc"))
592 t->bs = jgetstr(t->cap,US "bc");
593 else if (jgetstr(t->cap,US "le"))
594 t->bs = jgetstr(t->cap,US "le");
595 if (getflag(t->cap,US "bs"))
598 t->cbs = tcost(t->cap, t->bs, 1, 2, 2, 0, 0);
601 if (jgetstr(t->cap,US "do"))
602 t->lf = jgetstr(t->cap,US "do");
603 t->clf = tcost(t->cap, t->lf, 1, 2, 2, 0, 0);
605 t->up = jgetstr(t->cap,US "up");
606 t->cup = tcost(t->cap, t->up, 1, 2, 2, 0, 0);
608 t->nd = jgetstr(t->cap,US "nd");
611 if (getnum(t->cap,US "it") > 0)
612 t->tw = getnum(t->cap,US "it");
613 else if (getnum(t->cap,US "tw") > 0)
614 t->tw = getnum(t->cap,US "tw");
616 if (!(t->ta = jgetstr(t->cap,US "ta")))
617 if (getflag(t->cap,US "pt"))
619 t->bt = jgetstr(t->cap,US "bt");
620 if (getflag(t->cap,US "xt") || !usetabs) {
625 t->cta = tcost(t->cap, t->ta, 1, 2, 2, 0, 0);
626 t->cbt = tcost(t->cap, t->bt, 1, 2, 2, 0, 0);
628 t->ho = jgetstr(t->cap,US "ho");
629 t->cho = tcost(t->cap, t->ho, 1, 2, 2, 0, 0);
630 t->ll = jgetstr(t->cap,US "ll");
631 t->cll = tcost(t->cap, t->ll, 1, 2, 2, 0, 0);
634 if (jgetstr(t->cap,US "cr"))
635 t->cr = jgetstr(t->cap,US "cr");
636 if (getflag(t->cap,US "nc") || getflag(t->cap,US "xr"))
638 t->ccr = tcost(t->cap, t->cr, 1, 2, 2, 0, 0);
640 t->cRI = tcost(t->cap, t->RI = jgetstr(t->cap,US "RI"), 1, 2, 2, 0, 0);
641 t->cLE = tcost(t->cap, t->LE = jgetstr(t->cap,US "LE"), 1, 2, 2, 0, 0);
642 t->cUP = tcost(t->cap, t->UP = jgetstr(t->cap,US "UP"), 1, 2, 2, 0, 0);
643 t->cDO = tcost(t->cap, t->DO = jgetstr(t->cap,US "DO"), 1, 2, 2, 0, 0);
644 t->cch = tcost(t->cap, t->ch = jgetstr(t->cap,US "ch"), 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->ccV = tcost(t->cap, t->cV = jgetstr(t->cap,US "cV"), 1, 2, 2, 0, 0);
647 t->ccm = tcost(t->cap, t->cm = jgetstr(t->cap,US "cm"), 1, 2, 2, 0, 0);
649 t->cce = tcost(t->cap, t->ce = jgetstr(t->cap,US "ce"), 1, 2, 2, 0, 0);
651 /* Make sure terminal can do absolute positioning */
656 if (t->ho && (t->lf || t->DO || t->cv))
658 if (t->ll && (t->up || t->UP || t->cv))
666 /* these are strings, but I do not know if %s is appropriate -mirabilos */
667 fprintf(stderr,"cm=%d ch=%d cv=%d ho=%d lf=%d DO=%d ll=%d up=%d UP=%d cr=%d\n",
668 t->cm, t->ch, t->cv, t->ho, t->lf, t->DO, t->ll, t->up, t->UP, t->cr);
670 fprintf(stderr,"Sorry, your terminal can't do absolute cursor positioning.\nIt's broken\n");
674 /* Determine if we can scroll */
675 if (((t->sr || t->SR) && (t->sf || t->SF) && t->cs) || ((t->al || t->AL) && (t->dl || t->DL)))
677 else if (baud < 38400)
680 /* Determine if we can ins/del within lines */
681 if ((t->im || t->ic || t->IC) && (t->dc || t->DC))
684 /* Adjust for high baud rates */
690 /* Send out terminal initialization string */
692 texec(t->cap, t->ti, 1, 0, 0, 0, 0);
693 if (!skiptop && t->cl)
694 texec(t->cap, t->cl, 1, 0, 0, 0, 0);
696 /* Initialize variable screen size dependant vars */
697 t->htab = calloc(256, sizeof(struct hentry));
699 nresize(t, t->co, t->li);
704 /* Change size of screen */
706 void nresize(SCRN *t, int w, int h)
725 joe_free(t->compose);
730 t->scrn = calloc(t->li * t->co, sizeof(int));
731 t->attr = calloc(t->li * t->co, sizeof(int));
732 t->sary = calloc(t->li, sizeof(int));
733 t->updtab = calloc(t->li, sizeof(int));
734 t->syntab = calloc(t->li, sizeof(int));
735 t->compose = calloc(t->co, sizeof(int));
736 t->ofst = calloc(t->co, sizeof(int));
737 t->ary = calloc(t->co, sizeof(struct hentry));
742 /* Calculate cost of positioning the cursor using only relative cursor
743 * positioning functions: t->(lf, DO, up, UP, bs, LE, RI, ta, bt) and rewriting
744 * characters (to move right)
746 * This doesn't use the am and bw capabilities although it probably could.
749 static int relcost(register SCRN *t, register int x, register int y, register int ox, register int oy)
753 /* If we don't know the cursor position, force use of absolute positioning */
754 if (oy == -1 || ox == -1)
757 /* First adjust row */
761 /* Have to go down */
763 int mult = dist * t->clf;
765 if (dist < 10 && t->cDO < mult)
767 else if (dist >= 10 && t->cDO + 1 < mult)
783 int mult = dist * t->cup;
785 if (dist < 10 && t->cUP < mult)
787 else if (dist >= 10 && t->cUP < mult)
800 /* Now adjust column */
803 if (x > ox && t->ta) {
805 int ntabs = (dist + ox % t->tw) / t->tw;
806 int cstunder = x % t->tw + t->cta * ntabs;
809 if (x + t->tw < t->co && t->bs)
810 cstover = t->cbs * (t->tw - x % t->tw) + t->cta * (ntabs + 1);
813 if (dist < 10 && cstunder < t->cRI && cstunder < x - ox && cstover > cstunder)
814 return cost + cstunder;
815 else if (cstunder < t->cRI + 1 && cstunder < x - ox && cstover > cstunder)
816 return cost + cstunder;
817 else if (dist < 10 && cstover < t->cRI && cstover < x - ox)
818 return cost + cstover;
819 else if (cstover < t->cRI + 1 && cstover < x - ox)
820 return cost + cstover;
821 } else if (x < ox && t->bt) {
823 int ntabs = (dist + t->tw - ox % t->tw) / t->tw;
824 int cstunder, cstover;
827 cstunder = t->cbt * ntabs + t->cbs * (t->tw - x % t->tw);
831 cstover = t->cbt * (ntabs + 1) + x % t->tw;
834 if (dist < 10 && cstunder < t->cLE && (t->bs ? cstunder < (ox - x) * t->cbs : 1)
835 && cstover > cstunder)
836 return cost + cstunder;
837 if (cstunder < t->cLE + 1 && (t->bs ? cstunder < (ox - x) * t->cbs : 1)
838 && cstover > cstunder)
839 return cost + cstunder;
840 else if (dist < 10 && cstover < t->cRI && (t->bs ? cstover < (ox - x) * t->cbs : 1))
841 return cost + cstover;
842 else if (cstover < t->cRI + 1 && (t->bs ? cstover < (ox - x) * t->cbs : 1))
843 return cost + cstover;
846 /* Use simple motions */
850 /* Have to go left */
852 int mult = dist * t->cbs;
854 if (t->cLE < mult && dist < 10)
856 else if (t->cLE + 1 < mult)
867 /* Have to go right */
868 /* Hmm.. this should take into account possible attribute changes */
869 if (t->cRI < dist && dist < 10)
871 else if (t->cRI + 1 < dist)
880 /* Find optimal set of cursor positioning commands to move from the current
881 * cursor row and column (either or both of which might be unknown) to the
882 * given new row and column and execute them.
885 static void cposs(register SCRN *t, register int x, register int y)
887 register int bestcost, cost;
892 /* Home y position is usually 0, but it is 'top' if we have scrolling region
893 * relative addressing
903 /* Assume best way is with only using relative cursor positioning */
905 bestcost = relcost(t, x, y, t->x, t->y);
908 /* Now check if combinations of absolute cursor positioning functions are
909 * better (or necessary in case one or both cursor positions are unknown)
912 if (t->ccm < bestcost) {
913 cost = tcost(t->cap, t->cm, 1, y, x, 0, 0);
914 if (cost < bestcost) {
919 if (t->ccr < bestcost) {
920 cost = relcost(t, x, y, 0, t->y) + t->ccr;
921 if (cost < bestcost) {
926 if (t->cho < bestcost) {
927 cost = relcost(t, x, y, 0, hy) + t->cho;
928 if (cost < bestcost) {
933 if (t->cll < bestcost) {
934 cost = relcost(t, x, y, 0, hl) + t->cll;
935 if (cost < bestcost) {
940 if (t->cch < bestcost && x != t->x) {
941 cost = relcost(t, x, y, x, t->y) + tcost(t->cap, t->ch, 1, x, 0, 0, 0);
942 if (cost < bestcost) {
947 if (t->ccv < bestcost && y != t->y) {
948 cost = relcost(t, x, y, t->x, y) + tcost(t->cap, t->cv, 1, y, 0, 0, 0);
949 if (cost < bestcost) {
954 if (t->ccV < bestcost) {
955 cost = relcost(t, x, y, 0, y) + tcost(t->cap, t->cV, 1, y, 0, 0, 0);
956 if (cost < bestcost) {
961 if (t->cch + t->ccv < bestcost && x != t->x && y != t->y) {
962 cost = tcost(t->cap, t->cv, 1, y - hy, 0, 0, 0) + tcost(t->cap, t->ch, 1, x, 0, 0, 0);
963 if (cost < bestcost) {
968 if (t->ccv + t->ccr < bestcost && y != t->y) {
969 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);
970 if (cost < bestcost) {
975 if (t->cll + t->cch < bestcost) {
976 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);
977 if (cost < bestcost) {
982 if (t->cll + t->ccv < bestcost) {
983 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);
984 if (cost < bestcost) {
989 if (t->cho + t->cch < bestcost) {
990 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);
991 if (cost < bestcost) {
996 if (t->cho + t->ccv < bestcost) {
997 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);
998 if (cost < bestcost) {
999 /* dead store: bestcost = cost; */
1004 /* Do absolute cursor positioning if we don't know the cursor position or
1005 * if it is faster than doing only relative cursor positioning
1010 texec(t->cap, t->cr, 1, 0, 0, 0, 0);
1014 texec(t->cap, t->ho, 1, 0, 0, 0, 0);
1019 texec(t->cap, t->ll, 1, 0, 0, 0, 0);
1024 texec(t->cap, t->ll, 1, 0, 0, 0, 0);
1029 texec(t->cap, t->ho, 1, 0, 0, 0, 0);
1035 texec(t->cap, t->ch, 1, x, 0, 0, 0);
1039 texec(t->cap, t->ll, 1, 0, 0, 0, 0);
1044 texec(t->cap, t->ho, 1, 0, 0, 0, 0);
1049 texec(t->cap, t->cr, 1, 0, 0, 0, 0);
1054 texec(t->cap, t->cv, 1, y, 0, 0, 0);
1058 texec(t->cap, t->cm, 1, y, x, 0, 0);
1063 texec(t->cap, t->cv, 1, y, 0, 0, 0);
1065 texec(t->cap, t->ch, 1, x, 0, 0, 0);
1069 texec(t->cap, t->cV, 1, y, 0, 0, 0);
1075 /* Use relative cursor position functions if we're not there yet */
1077 /* First adjust row */
1079 /* Have to go down */
1080 if (!t->lf || t->cDO < (y - t->y) * t->clf) {
1081 texec(t->cap, t->DO, 1, y - t->y, 0, 0, 0);
1085 texec(t->cap, t->lf, 1, 0, 0, 0, 0);
1088 } else if (y < t->y) {
1090 if (!t->up || t->cUP < (t->y - y) * t->cup) {
1091 texec(t->cap, t->UP, 1, t->y - y, 0, 0, 0);
1095 texec(t->cap, t->up, 1, 0, 0, 0, 0);
1101 if (x > t->x && t->ta) {
1102 int ntabs = (x - t->x + t->x % t->tw) / t->tw;
1103 int cstunder = x % t->tw + t->cta * ntabs;
1106 if (x + t->tw < t->co && t->bs)
1107 cstover = t->cbs * (t->tw - x % t->tw) + t->cta * (ntabs + 1);
1110 if (cstunder < t->cRI && cstunder < x - t->x && cstover > cstunder) {
1112 t->x = x - x % t->tw;
1114 texec(t->cap, t->ta, 1, 0, 0, 0, 0);
1117 } else if (cstover < t->cRI && cstover < x - t->x) {
1118 t->x = t->tw + x - x % t->tw;
1121 texec(t->cap, t->ta, 1, 0, 0, 0, 0);
1124 } else if (x < t->x && t->bt) {
1125 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;
1126 int cstunder, cstover;
1129 cstunder = t->cbt * ntabs + t->cbs * (t->tw - x % t->tw);
1133 cstover = t->cbt * (ntabs + 1) + x % t->tw;
1136 if (cstunder < t->cLE && (t->bs ? cstunder < (t->x - x) * t->cbs : 1)
1137 && cstover > cstunder) {
1140 texec(t->cap, t->bt, 1, 0, 0, 0, 0);
1142 t->x = x + t->tw - x % t->tw;
1144 } else if (cstover < t->cRI && (t->bs ? cstover < (t->x - x) * t->cbs : 1)) {
1145 t->x = x - x % t->tw;
1148 texec(t->cap, t->bt, 1, 0, 0, 0, 0);
1153 /* Now adjust column */
1155 /* Have to go left */
1156 if (!t->bs || t->cLE < (t->x - x) * t->cbs) {
1157 texec(t->cap, t->LE, 1, t->x - x, 0, 0, 0);
1161 texec(t->cap, t->bs, 1, 0, 0, 0, 0);
1164 } else if (x > t->x) {
1165 /* Have to go right */
1166 /* Hmm.. this should take into account possible attribute changes */
1167 if (x-t->x>1 && t->RI) {
1168 texec(t->cap, t->RI, 1, x - t->x, 0, 0, 0);
1172 texec(t->cap, t->nd, 1, 0, 0, 0, 0);
1177 /* if (t->cRI < x - t->x) { */
1179 int *s = t->scrn + t->x + t->y * t->co;
1180 int *a = t->attr + t->x + t->y * t->co;
1186 if(*s==-1) c=' ', atr=0;
1187 else c= *s, atr= *a;
1189 if (atr != t->attrib)
1201 int cpos(register SCRN *t, register int x, register int y)
1203 /* Move cursor quickly if we can */
1205 if (x > t->x && x - t->x < 4 && !t->ins) {
1206 int *cs = t->scrn + t->x + t->co * t->y;
1207 int *as = t->attr + t->x + t->co * t->y;
1209 /* We used to space over unknown chars, but they now could be
1210 the right half of a UTF-8 two column character, so we can't.
1211 Also do not try to emit utf-8 sequences here. */
1212 if(*cs<32 || *cs>=127)
1215 if (*as != t->attrib)
1224 } while (x != t->x);
1229 if ((!t->ms && t->attrib & (INVERSE | UNDERLINE | BG_NOT_DEFAULT)) ||
1230 (t->ut && (t->attrib & BG_NOT_DEFAULT)))
1231 set_attr(t, t->attrib & ~(INVERSE | UNDERLINE | BG_MASK));
1233 /* Should be in cposs */
1234 if (y < t->top || y >= t->bot)
1235 setregn(t, 0, t->li);
1241 static void doinschr(SCRN *t, int x, int y, int *s, int *as, int n)
1250 if (x >= t->co - 1 || n <= 0)
1252 if (t->im || t->ic || t->IC) {
1254 if ((n == 1 && t->ic) || !t->IC) {
1257 for (a = 0; a != n; ++a) {
1258 texec(t->cap, t->ic, 1, x, 0, 0, 0);
1259 texec(t->cap, t->ip, 1, x, 0, 0, 0);
1264 texec(t->cap, t->IC, 1, n, 0, 0, 0);
1267 mmove(t->scrn + x + t->co * y + n, t->scrn + x + t->co * y, (t->co - (x + n)) * sizeof(int));
1268 mmove(t->attr + x + t->co * y + n, t->attr + x + t->co * y, (t->co - (x + n)) * sizeof(int));
1269 mmove(t->scrn + x + t->co * y, s, n * sizeof(int));
1270 mmove(t->attr + x + t->co * y, s, n * sizeof(int));
1273 static void dodelchr(SCRN *t, int x, int y, int n)
1279 if (!n || x >= t->co - 1)
1281 if (t->dc || t->DC) {
1283 texec(t->cap, t->dm, 1, x, 0, 0, 0); /* Enter delete mode */
1284 if ((n == 1 && t->dc) || !t->DC)
1286 texec(t->cap, t->dc, 1, x, 0, 0, 0);
1288 texec(t->cap, t->DC, 1, n, 0, 0, 0);
1289 texec(t->cap, t->ed, 1, x, 0, 0, 0); /* Exit delete mode */
1291 mmove(t->scrn + t->co * y + x, t->scrn + t->co * y + x + n, (t->co - (x + n)) * sizeof(int));
1292 mmove(t->attr + t->co * y + x, t->attr + t->co * y + x + n, (t->co - (x + n)) * sizeof(int));
1293 msetI(t->scrn + t->co * y + t->co - n, ' ', n);
1294 msetI(t->attr + t->co * y + t->co - n, 0, n);
1297 /* Insert/Delete within line */
1298 /* FIXME: doesn't know about attr */
1300 void magic(SCRN *t, int y, int *cs, int *ca,int *s, int *a, int placex)
1302 struct hentry *htab = t->htab;
1303 int *ofst = t->ofst;
1307 if (!(t->im || t->ic || t->IC) || !(t->dc || t->DC))
1309 mset(htab, 0, 256 * sizeof(struct hentry));
1311 msetI(ofst, 0, t->co);
1313 /* Build hash table */
1314 for (x = 0; x != t->co - 1; ++x) {
1315 t->ary[aryx].next = htab[cs[x] & 255].next;
1316 t->ary[aryx].loc = x;
1317 ++htab[cs[x] & 255].loc;
1318 htab[cs[x] & 255].next = aryx++;
1321 /* Build offset table */
1322 for (x = 0; x < t->co - 1;)
1323 if (htab[s[x] & 255].loc >= 15)
1324 ofst[x++] = t->co - 1;
1333 for (aryy = htab[s[x] & 255].next; aryy; aryy = t->ary[aryy].next) {
1335 int tsfo = t->ary[aryy].loc - x;
1336 int cst = -abs(tsfo);
1339 for (amnt = 0; x + amnt < t->co - 1 && x + tsfo + amnt < t->co - 1; ++amnt) {
1340 if (cs[x + tsfo + amnt] != s[x + amnt])
1342 else if ((s[x + amnt] & 255) != 32 || pre != 32)
1344 pre = s[x + amnt] & 255;
1347 for (back = 0; back + x > 0 && back + tsfo + x > 0; --back) {
1348 if (cs[x + tsfo + back - 1] != s[x + back - 1])
1350 else if ((s[x + back - 1] & 255) != 32 || pre != 32)
1352 pre = s[x + back - 1] & 255;
1362 ofst[x] = t->co - 1;
1364 } else if (best < 2)
1365 for (z = 0; z != maxlen; ++z)
1366 ofst[x + z] = t->co - 1;
1368 for (z = 0; z != maxlen - bestback; ++z)
1369 ofst[x + z + bestback] = t->ary[maxaryy].loc - x;
1373 /* Apply scrolling commands */
1375 for (x = 0; x != t->co - 1; ++x) {
1378 if (q && q != t->co - 1) {
1382 for (z = x; z != t->co - 1 && ofst[z] == q; ++z) ;
1383 while (s[x] == cs[x] && x < placex)
1385 dodelchr(t, x, y, q);
1386 for (fu = x; fu != t->co - 1; ++fu)
1387 if (ofst[fu] != t->co - 1)
1393 for (z = x; z != t->co - 1 && ofst[z] == q; ++z) ;
1394 while (s[x + q] == cs[x + q] && x - q < placex)
1396 doinschr(t, x + q, y, s + x + q, a + x + q, -q);
1397 for (fu = x; fu != t->co - 1; ++fu)
1398 if (ofst[fu] != t->co - 1)
1406 static void doupscrl(SCRN *t, int top, int bot, int amnt)
1413 if (top == 0 && bot == t->li && (t->sf || t->SF)) {
1414 setregn(t, 0, t->li);
1415 cpos(t, 0, t->li - 1);
1416 if ((amnt == 1 && t->sf) || !t->SF)
1418 texec(t->cap, t->sf, 1, t->li - 1, 0, 0, 0);
1420 texec(t->cap, t->SF, a, a, 0, 0, 0);
1423 if (bot == t->li && (t->dl || t->DL)) {
1424 setregn(t, 0, t->li);
1426 if ((amnt == 1 && t->dl) || !t->DL)
1428 texec(t->cap, t->dl, 1, top, 0, 0, 0);
1430 texec(t->cap, t->DL, a, a, 0, 0, 0);
1433 if (t->cs && (t->sf || t->SF)) {
1434 setregn(t, top, bot);
1435 cpos(t, 0, bot - 1);
1436 if ((amnt == 1 && t->sf) || !t->SF)
1438 texec(t->cap, t->sf, 1, bot - 1, 0, 0, 0);
1440 texec(t->cap, t->SF, a, a, 0, 0, 0);
1443 if ((t->dl || t->DL) && (t->al || t->AL)) {
1445 if ((amnt == 1 && t->dl) || !t->DL)
1447 texec(t->cap, t->dl, 1, top, 0, 0, 0);
1449 texec(t->cap, t->DL, a, a, 0, 0, 0);
1451 cpos(t, 0, bot - amnt);
1452 if ((amnt == 1 && t->al) || !t->AL)
1454 texec(t->cap, t->al, 1, bot - amnt, 0, 0, 0);
1456 texec(t->cap, t->AL, a, a, 0, 0, 0);
1459 msetI(t->updtab + top, 1, bot - top);
1460 msetI(t->syntab + top, -1, bot - top);
1464 mmove(t->scrn + top * t->co, t->scrn + (top + amnt) * t->co, (bot - top - amnt) * t->co * sizeof(int));
1465 mmove(t->attr + top * t->co, t->attr + (top + amnt) * t->co, (bot - top - amnt) * t->co * sizeof(int));
1467 if (bot == t->li && t->db) {
1468 msetI(t->scrn + (t->li - amnt) * t->co, -1, amnt * t->co);
1469 msetI(t->attr + (t->li - amnt) * t->co, 0, amnt * t->co);
1470 msetI(t->updtab + t->li - amnt, 1, amnt);
1471 msetI(t->syntab + t->li - amnt, -1, amnt);
1473 msetI(t->scrn + (bot - amnt) * t->co, ' ', amnt * t->co);
1474 msetI(t->attr + (bot - amnt) * t->co, 0, amnt * t->co);
1478 static void dodnscrl(SCRN *t, int top, int bot, int amnt)
1485 if (top == 0 && bot == t->li && (t->sr || t->SR)) {
1486 setregn(t, 0, t->li);
1488 if ((amnt == 1 && t->sr) || !t->SR)
1490 texec(t->cap, t->sr, 1, 0, 0, 0, 0);
1492 texec(t->cap, t->SR, a, a, 0, 0, 0);
1495 if (bot == t->li && (t->al || t->AL)) {
1496 setregn(t, 0, t->li);
1498 if ((amnt == 1 && t->al) || !t->AL)
1500 texec(t->cap, t->al, 1, top, 0, 0, 0);
1502 texec(t->cap, t->AL, a, a, 0, 0, 0);
1505 if (t->cs && (t->sr || t->SR)) {
1506 setregn(t, top, bot);
1508 if ((amnt == 1 && t->sr) || !t->SR)
1510 texec(t->cap, t->sr, 1, top, 0, 0, 0);
1512 texec(t->cap, t->SR, a, a, 0, 0, 0);
1515 if ((t->dl || t->DL) && (t->al || t->AL)) {
1516 cpos(t, 0, bot - amnt);
1517 if ((amnt == 1 && t->dl) || !t->DL)
1519 texec(t->cap, t->dl, 1, bot - amnt, 0, 0, 0);
1521 texec(t->cap, t->DL, a, a, 0, 0, 0);
1524 if ((amnt == 1 && t->al) || !t->AL)
1526 texec(t->cap, t->al, 1, top, 0, 0, 0);
1528 texec(t->cap, t->AL, a, a, 0, 0, 0);
1531 msetI(t->updtab + top, 1, bot - top);
1532 msetI(t->syntab + top, -1, bot - top);
1535 mmove(t->scrn + (top + amnt) * t->co, t->scrn + top * t->co, (bot - top - amnt) * t->co * sizeof(int));
1536 mmove(t->attr + (top + amnt) * t->co, t->attr + top * t->co, (bot - top - amnt) * t->co * sizeof(int));
1538 if (!top && t->da) {
1539 msetI(t->scrn, -1, amnt * t->co);
1540 msetI(t->attr, 0, amnt * t->co);
1541 msetI(t->updtab, 1, amnt);
1542 msetI(t->syntab, -1, amnt);
1544 msetI(t->scrn + t->co * top, ' ', amnt * t->co);
1545 msetI(t->attr + t->co * top, 0, amnt * t->co);
1549 void nscroll(SCRN *t)
1553 for (y = 0; y != t->li; ++y) {
1557 if (q && q != t->li) {
1559 for (z = y; z != t->li && t->sary[z] == q; ++z)
1561 doupscrl(t, y, z + q, q);
1564 for (r = y; r != t->li && (t->sary[r] < 0 || t->sary[r] == t->li); ++r) ;
1568 if (q && q != t->li) {
1569 for (z = p; t->sary[z] = 0, (z && t->sary[z - 1] == q); --z) ;
1570 dodnscrl(t, z + q, p + 1, -q);
1578 msetI(t->sary, 0, t->li);
1581 void npartial(SCRN *t)
1585 setregn(t, 0, t->li);
1588 void nescape(SCRN *t)
1591 cpos(t, 0, t->li - 1);
1592 eraeol(t, 0, t->li - 1);
1594 texec(t->cap, t->te, 1, 0, 0, 0, 0);
1597 void nreturn(SCRN *t)
1600 texec(t->cap, t->ti, 1, 0, 0, 0, 0);
1601 if (!skiptop && t->cl)
1602 texec(t->cap, t->cl, 1, 0, 0, 0, 0);
1606 void nclose(SCRN *t)
1611 setregn(t, 0, t->li);
1612 cpos(t, 0, t->li - 1);
1614 texec(t->cap, t->te, 1, 0, 0, 0, 0);
1626 void nscrldn(SCRN *t, int top, int bot, int amnt)
1630 if (!amnt || top >= bot || bot > t->li)
1632 if ((amnt < bot - top && bot - top - amnt < amnt / 2) || !t->scroll)
1634 if (amnt < bot - top) {
1635 for (x = bot; x != top + amnt; --x) {
1636 t->sary[x - 1] = (t->sary[x - amnt - 1] == t->li ? t->li : t->sary[x - amnt - 1] - amnt);
1637 t->updtab[x - 1] = t->updtab[x - amnt - 1];
1638 t->syntab[x - 1] = t->syntab[x - amnt - 1];
1640 for (x = top; x != top + amnt; ++x) {
1645 if (amnt > bot - top)
1647 msetI(t->sary + top, t->li, amnt);
1648 if (amnt == bot - top) {
1649 msetI(t->updtab + top, 1, amnt);
1650 msetI(t->syntab + top, -1, amnt);
1654 void nscrlup(SCRN *t, int top, int bot, int amnt)
1658 if (!amnt || top >= bot || bot > t->li)
1660 if ((amnt < bot - top && bot - top - amnt < amnt / 2) || !t->scroll)
1662 if (amnt < bot - top) {
1663 for (x = top + amnt; x != bot; ++x) {
1664 t->sary[x - amnt] = (t->sary[x] == t->li ? t->li : t->sary[x] + amnt);
1665 t->updtab[x - amnt] = t->updtab[x];
1666 t->syntab[x - amnt] = t->syntab[x];
1668 for (x = bot - amnt; x != bot; ++x) {
1673 if (amnt > bot - top)
1675 msetI(t->sary + bot - amnt, t->li, amnt);
1676 if (amnt == bot - top) {
1677 msetI(t->updtab + bot - amnt, 1, amnt);
1678 msetI(t->syntab + bot - amnt, -1, amnt);
1682 extern volatile int dostaupd;
1684 void nredraw(SCRN *t)
1687 msetI(t->scrn, ' ', t->co * skiptop);
1688 msetI(t->attr, 0, t->co * skiptop);
1689 msetI(t->scrn + skiptop * t->co, -1, (t->li - skiptop) * t->co);
1690 msetI(t->attr + skiptop * t->co, 0, (t->li - skiptop) * t->co);
1691 msetI(t->sary, 0, t->li);
1692 msetI(t->updtab + skiptop, -1, t->li - skiptop);
1693 msetI(t->syntab + skiptop, -1, t->li - skiptop);
1702 setregn(t, 0, t->li);
1706 texec(t->cap, t->cl, 1, 0, 0, 0, 0);
1709 msetI(t->scrn, ' ', t->li * t->co);
1710 msetI(t->attr, 0, t->li * t->co);
1713 texec(t->cap, t->cd, 1, 0, 0, 0, 0);
1714 msetI(t->scrn, ' ', t->li * t->co);
1715 msetI(t->attr, 0, t->li * t->co);
1720 /* Convert color/attribute name into internal code */
1722 int meta_color(unsigned char *s)
1724 if(!strcmp((char *)s,"inverse"))
1726 else if(!strcmp((char *)s,"underline"))
1728 else if(!strcmp((char *)s,"bold"))
1730 else if(!strcmp((char *)s,"blink"))
1732 else if(!strcmp((char *)s,"dim"))
1734 else if(!strcmp((char *)s,"white"))
1736 else if(!strcmp((char *)s,"cyan"))
1738 else if(!strcmp((char *)s,"magenta"))
1740 else if(!strcmp((char *)s,"blue"))
1742 else if(!strcmp((char *)s,"yellow"))
1744 else if(!strcmp((char *)s,"green"))
1746 else if(!strcmp((char *)s,"red"))
1748 else if(!strcmp((char *)s,"black"))
1750 else if(!strcmp((char *)s,"bg_white"))
1752 else if(!strcmp((char *)s,"bg_cyan"))
1754 else if(!strcmp((char *)s,"bg_magenta"))
1756 else if(!strcmp((char *)s,"bg_blue"))
1758 else if(!strcmp((char *)s,"bg_yellow"))
1760 else if(!strcmp((char *)s,"bg_green"))
1762 else if(!strcmp((char *)s,"bg_red"))
1764 else if(!strcmp((char *)s,"bg_black"))
1772 * 't' is SCRN to write to.
1773 * 'scrn' is address of field in character buffer
1774 * 'attr' is address of field in attribute buffer
1775 * 'x', 'y' are starting column and line numbers of field
1776 * 'ofst' is first column within string to display
1777 * 's', 'len' is string to generate in field
1778 * 'atr' is screeen attributes (and color) which should be used
1779 * 'width' is column width of field
1780 * 'flg' if set, erases to end of line
1783 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)
1787 int last_col = x + width;
1791 for (col = 0;len != 0 && x < last_col; len--) {
1795 if (fmt) my_atr |= *fmt++;
1796 if (locale_map->type) {
1797 /* UTF-8 mode: decode character and determine its width */
1798 c = utf8_decode(&sm,c);
1800 wid = joe_wcwidth(1,c);
1802 /* Byte mode: character is one column wide */
1807 if (x + wid > last_col) {
1808 /* Character crosses end of field, so fill balance of field with '>' characters instead */
1809 while (x < last_col) {
1810 outatr(utf8_map, t, scrn, attr, x, y, '>', my_atr);
1816 /* Emit character */
1817 outatr(locale_map, t, scrn, attr, x, y, c, my_atr);
1822 } else if ((col + wid) > ofst) {
1823 /* Wide character crosses left side of field */
1827 outatr(utf8_map, t, scrn, attr, x, y, '<', my_atr);
1838 /* Fill balance of field with spaces */
1839 while (x < last_col) {
1840 outatr(utf8_map, t, scrn, attr, x, y, ' ', 0);
1845 /* Erase to end of line */
1850 /* Width function for above */
1852 int txtwidth(unsigned char *s,int len)
1854 if (locale_map->type) {
1860 int d = utf8_decode(&sm,*s++);
1862 col += joe_wcwidth(1,d);
1870 /* Generate text with formatting escape sequences */
1872 void genfmt(SCRN *t, int x, int y, int ofst, const unsigned char *s, int flg)
1874 int *scrn = t->scrn + y * t->co + x;
1875 int *attr = t->attr + y * t->co + x;
1883 while ((c = *s++) != '\0')
1910 if (col++ >= ofst) {
1911 outatr(locale_map, t, scrn, attr, x, y, (c&0x7F), atr);
1921 if (locale_map->type) {
1922 /* UTF-8 mode: decode character and determine its width */
1923 c = utf8_decode(&sm,c);
1925 wid = joe_wcwidth(1,c);
1928 /* Byte mode: character is one column wide */
1934 outatr(locale_map, t, scrn, attr, x, y, c, atr);
1939 } else if (col+wid>ofst) {
1945 outatr(utf8_map, t, scrn, attr, x, y, '<', atr);
1960 /* Determine column width of string with format codes */
1962 int fmtlen(const unsigned char *s)
1970 while ((c = (*s++))) {
1992 if(locale_map->type) {
1993 c = utf8_decode(&sm,c);
1995 wid = joe_wcwidth(1,c);
2005 /* Return offset within format string which corresponds to a particular
2008 /* FIXME: this is not valid if we land in the middle of a double-wide character */
2010 int fmtpos(unsigned char *s, int goal)
2012 unsigned char *org = s;
2019 while ((c= *s) && col<goal) {
2043 if(locale_map->type) {
2044 c = utf8_decode(&sm,c);
2046 wid = joe_wcwidth(1,c);
2054 return s - org + goal - col;