1 /* $MirOS: contrib/code/jupp/scrn.c,v 1.26 2017/08/08 16:09:43 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);
222 if(*scrn==c && *attrf==a)
229 if(t->x != xx || t->y != yy)
236 unsigned char buf[7];
240 if (wid == 0 && xx > 0)
241 attrf[-1] |= HAS_COMBINING;
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[7];
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);
1036 texec(t->cap, t->ch, 1, x, 0, 0, 0);
1040 texec(t->cap, t->ll, 1, 0, 0, 0, 0);
1045 texec(t->cap, t->ho, 1, 0, 0, 0, 0);
1050 texec(t->cap, t->cr, 1, 0, 0, 0, 0);
1056 texec(t->cap, t->cv, 1, y, 0, 0, 0);
1060 texec(t->cap, t->cm, 1, y, x, 0, 0);
1065 texec(t->cap, t->cv, 1, y, 0, 0, 0);
1067 texec(t->cap, t->ch, 1, x, 0, 0, 0);
1071 texec(t->cap, t->cV, 1, y, 0, 0, 0);
1077 /* Use relative cursor position functions if we're not there yet */
1079 /* First adjust row */
1081 /* Have to go down */
1082 if (!t->lf || t->cDO < (y - t->y) * t->clf) {
1083 texec(t->cap, t->DO, 1, y - t->y, 0, 0, 0);
1087 texec(t->cap, t->lf, 1, 0, 0, 0, 0);
1090 } else if (y < t->y) {
1092 if (!t->up || t->cUP < (t->y - y) * t->cup) {
1093 texec(t->cap, t->UP, 1, t->y - y, 0, 0, 0);
1097 texec(t->cap, t->up, 1, 0, 0, 0, 0);
1103 if (x > t->x && t->ta) {
1104 int ntabs = (x - t->x + t->x % t->tw) / t->tw;
1105 int cstunder = x % t->tw + t->cta * ntabs;
1108 if (x + t->tw < t->co && t->bs)
1109 cstover = t->cbs * (t->tw - x % t->tw) + t->cta * (ntabs + 1);
1112 if (cstunder < t->cRI && cstunder < x - t->x && cstover > cstunder) {
1114 t->x = x - x % t->tw;
1116 texec(t->cap, t->ta, 1, 0, 0, 0, 0);
1119 } else if (cstover < t->cRI && cstover < x - t->x) {
1120 t->x = t->tw + x - x % t->tw;
1123 texec(t->cap, t->ta, 1, 0, 0, 0, 0);
1126 } else if (x < t->x && t->bt) {
1127 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;
1128 int cstunder, cstover;
1131 cstunder = t->cbt * ntabs + t->cbs * (t->tw - x % t->tw);
1135 cstover = t->cbt * (ntabs + 1) + x % t->tw;
1138 if (cstunder < t->cLE && (t->bs ? cstunder < (t->x - x) * t->cbs : 1)
1139 && cstover > cstunder) {
1142 texec(t->cap, t->bt, 1, 0, 0, 0, 0);
1144 t->x = x + t->tw - x % t->tw;
1146 } else if (cstover < t->cRI && (t->bs ? cstover < (t->x - x) * t->cbs : 1)) {
1147 t->x = x - x % t->tw;
1150 texec(t->cap, t->bt, 1, 0, 0, 0, 0);
1155 /* Now adjust column */
1157 /* Have to go left */
1158 if (!t->bs || t->cLE < (t->x - x) * t->cbs) {
1159 texec(t->cap, t->LE, 1, t->x - x, 0, 0, 0);
1163 texec(t->cap, t->bs, 1, 0, 0, 0, 0);
1166 } else if (x > t->x) {
1167 /* Have to go right */
1168 /* Hmm.. this should take into account possible attribute changes */
1169 if (x-t->x>1 && t->RI) {
1170 texec(t->cap, t->RI, 1, x - t->x, 0, 0, 0);
1174 texec(t->cap, t->nd, 1, 0, 0, 0, 0);
1179 /* if (t->cRI < x - t->x) { */
1181 int *s = t->scrn + t->x + t->y * t->co;
1182 int *a = t->attr + t->x + t->y * t->co;
1188 if(*s==-1) c=' ', atr=0;
1189 else c= *s, atr= *a;
1191 if (atr != t->attrib)
1203 int cpos(register SCRN *t, register int x, register int y)
1205 /* Move cursor quickly if we can */
1207 if (x > t->x && x - t->x < 4 && !t->ins) {
1208 int *cs = t->scrn + t->x + t->co * t->y;
1209 int *as = t->attr + t->x + t->co * t->y;
1211 /* We used to space over unknown chars, but they now could be
1212 the right half of a UTF-8 two column character, so we can't.
1213 Also do not try to emit utf-8 sequences here. */
1214 if(*cs<32 || *cs>=127)
1217 /* has a combining character attached? */
1218 if (*as & HAS_COMBINING)
1221 if (*as != t->attrib)
1230 } while (x != t->x);
1235 if ((!t->ms && t->attrib & (INVERSE | UNDERLINE | BG_NOT_DEFAULT)) ||
1236 (t->ut && (t->attrib & BG_NOT_DEFAULT)))
1237 set_attr(t, t->attrib & ~(INVERSE | UNDERLINE | BG_MASK));
1239 /* Should be in cposs */
1240 if (y < t->top || y >= t->bot)
1241 setregn(t, 0, t->li);
1247 static void doinschr(SCRN *t, int x, int y, int *s, int *as, int n)
1256 if (x >= t->co - 1 || n <= 0)
1258 if (t->im || t->ic || t->IC) {
1260 if ((n == 1 && t->ic) || !t->IC) {
1263 for (a = 0; a != n; ++a) {
1264 texec(t->cap, t->ic, 1, x, 0, 0, 0);
1265 texec(t->cap, t->ip, 1, x, 0, 0, 0);
1270 texec(t->cap, t->IC, 1, n, 0, 0, 0);
1273 mmove(t->scrn + x + t->co * y + n, t->scrn + x + t->co * y, (t->co - (x + n)) * sizeof(int));
1274 mmove(t->attr + x + t->co * y + n, t->attr + x + t->co * y, (t->co - (x + n)) * sizeof(int));
1275 mmove(t->scrn + x + t->co * y, s, n * sizeof(int));
1276 mmove(t->attr + x + t->co * y, s, n * sizeof(int));
1279 static void dodelchr(SCRN *t, int x, int y, int n)
1285 if (!n || x >= t->co - 1)
1287 if (t->dc || t->DC) {
1289 texec(t->cap, t->dm, 1, x, 0, 0, 0); /* Enter delete mode */
1290 if ((n == 1 && t->dc) || !t->DC)
1292 texec(t->cap, t->dc, 1, x, 0, 0, 0);
1294 texec(t->cap, t->DC, 1, n, 0, 0, 0);
1295 texec(t->cap, t->ed, 1, x, 0, 0, 0); /* Exit delete mode */
1297 mmove(t->scrn + t->co * y + x, t->scrn + t->co * y + x + n, (t->co - (x + n)) * sizeof(int));
1298 mmove(t->attr + t->co * y + x, t->attr + t->co * y + x + n, (t->co - (x + n)) * sizeof(int));
1299 msetI(t->scrn + t->co * y + t->co - n, ' ', n);
1300 msetI(t->attr + t->co * y + t->co - n, 0, n);
1303 /* Insert/Delete within line */
1304 /* FIXME: doesn't know about attr */
1306 void magic(SCRN *t, int y, int *cs, int *ca,int *s, int *a, int placex)
1308 struct hentry *htab = t->htab;
1309 int *ofst = t->ofst;
1313 if (!(t->im || t->ic || t->IC) || !(t->dc || t->DC))
1315 mset(htab, 0, 256 * sizeof(struct hentry));
1317 msetI(ofst, 0, t->co);
1319 /* Build hash table */
1320 for (x = 0; x != t->co - 1; ++x) {
1321 t->ary[aryx].next = htab[cs[x] & 255].next;
1322 t->ary[aryx].loc = x;
1323 ++htab[cs[x] & 255].loc;
1324 htab[cs[x] & 255].next = aryx++;
1327 /* Build offset table */
1328 for (x = 0; x < t->co - 1;)
1329 if (htab[s[x] & 255].loc >= 15)
1330 ofst[x++] = t->co - 1;
1339 for (aryy = htab[s[x] & 255].next; aryy; aryy = t->ary[aryy].next) {
1341 int tsfo = t->ary[aryy].loc - x;
1342 int cst = -abs(tsfo);
1345 for (amnt = 0; x + amnt < t->co - 1 && x + tsfo + amnt < t->co - 1; ++amnt) {
1346 if (cs[x + tsfo + amnt] != s[x + amnt])
1348 else if ((s[x + amnt] & 255) != 32 || pre != 32)
1350 pre = s[x + amnt] & 255;
1353 for (back = 0; back + x > 0 && back + tsfo + x > 0; --back) {
1354 if (cs[x + tsfo + back - 1] != s[x + back - 1])
1356 else if ((s[x + back - 1] & 255) != 32 || pre != 32)
1358 pre = s[x + back - 1] & 255;
1368 ofst[x] = t->co - 1;
1370 } else if (best < 2)
1371 for (z = 0; z != maxlen; ++z)
1372 ofst[x + z] = t->co - 1;
1374 for (z = 0; z != maxlen - bestback; ++z)
1375 ofst[x + z + bestback] = t->ary[maxaryy].loc - x;
1379 /* Apply scrolling commands */
1381 for (x = 0; x != t->co - 1; ++x) {
1384 if (q && q != t->co - 1) {
1388 for (z = x; z != t->co - 1 && ofst[z] == q; ++z)
1390 while (s[x] == cs[x] && x < placex)
1392 dodelchr(t, x, y, q);
1393 for (fu = x; fu != t->co - 1; ++fu)
1394 if (ofst[fu] != t->co - 1)
1400 for (z = x; z != t->co - 1 && ofst[z] == q; ++z)
1402 while (s[x + q] == cs[x + q] && x - q < placex)
1404 doinschr(t, x + q, y, s + x + q, a + x + q, -q);
1405 for (fu = x; fu != t->co - 1; ++fu)
1406 if (ofst[fu] != t->co - 1)
1414 static void doupscrl(SCRN *t, int top, int bot, int amnt)
1421 if (top == 0 && bot == t->li && (t->sf || t->SF)) {
1422 setregn(t, 0, t->li);
1423 cpos(t, 0, t->li - 1);
1424 if ((amnt == 1 && t->sf) || !t->SF)
1426 texec(t->cap, t->sf, 1, t->li - 1, 0, 0, 0);
1428 texec(t->cap, t->SF, a, a, 0, 0, 0);
1431 if (bot == t->li && (t->dl || t->DL)) {
1432 setregn(t, 0, t->li);
1434 if ((amnt == 1 && t->dl) || !t->DL)
1436 texec(t->cap, t->dl, 1, top, 0, 0, 0);
1438 texec(t->cap, t->DL, a, a, 0, 0, 0);
1441 if (t->cs && (t->sf || t->SF)) {
1442 setregn(t, top, bot);
1443 cpos(t, 0, bot - 1);
1444 if ((amnt == 1 && t->sf) || !t->SF)
1446 texec(t->cap, t->sf, 1, bot - 1, 0, 0, 0);
1448 texec(t->cap, t->SF, a, a, 0, 0, 0);
1451 if ((t->dl || t->DL) && (t->al || t->AL)) {
1453 if ((amnt == 1 && t->dl) || !t->DL)
1455 texec(t->cap, t->dl, 1, top, 0, 0, 0);
1457 texec(t->cap, t->DL, a, a, 0, 0, 0);
1459 cpos(t, 0, bot - amnt);
1460 if ((amnt == 1 && t->al) || !t->AL)
1462 texec(t->cap, t->al, 1, bot - amnt, 0, 0, 0);
1464 texec(t->cap, t->AL, a, a, 0, 0, 0);
1467 msetI(t->updtab + top, 1, bot - top);
1468 msetI(t->syntab + top, -1, bot - top);
1472 mmove(t->scrn + top * t->co, t->scrn + (top + amnt) * t->co, (bot - top - amnt) * t->co * sizeof(int));
1473 mmove(t->attr + top * t->co, t->attr + (top + amnt) * t->co, (bot - top - amnt) * t->co * sizeof(int));
1475 if (bot == t->li && t->db) {
1476 msetI(t->scrn + (t->li - amnt) * t->co, -1, amnt * t->co);
1477 msetI(t->attr + (t->li - amnt) * t->co, 0, amnt * t->co);
1478 msetI(t->updtab + t->li - amnt, 1, amnt);
1479 msetI(t->syntab + t->li - amnt, -1, amnt);
1481 msetI(t->scrn + (bot - amnt) * t->co, ' ', amnt * t->co);
1482 msetI(t->attr + (bot - amnt) * t->co, 0, amnt * t->co);
1486 static void dodnscrl(SCRN *t, int top, int bot, int amnt)
1493 if (top == 0 && bot == t->li && (t->sr || t->SR)) {
1494 setregn(t, 0, t->li);
1496 if ((amnt == 1 && t->sr) || !t->SR)
1498 texec(t->cap, t->sr, 1, 0, 0, 0, 0);
1500 texec(t->cap, t->SR, a, a, 0, 0, 0);
1503 if (bot == t->li && (t->al || t->AL)) {
1504 setregn(t, 0, t->li);
1506 if ((amnt == 1 && t->al) || !t->AL)
1508 texec(t->cap, t->al, 1, top, 0, 0, 0);
1510 texec(t->cap, t->AL, a, a, 0, 0, 0);
1513 if (t->cs && (t->sr || t->SR)) {
1514 setregn(t, top, bot);
1516 if ((amnt == 1 && t->sr) || !t->SR)
1518 texec(t->cap, t->sr, 1, top, 0, 0, 0);
1520 texec(t->cap, t->SR, a, a, 0, 0, 0);
1523 if ((t->dl || t->DL) && (t->al || t->AL)) {
1524 cpos(t, 0, bot - amnt);
1525 if ((amnt == 1 && t->dl) || !t->DL)
1527 texec(t->cap, t->dl, 1, bot - amnt, 0, 0, 0);
1529 texec(t->cap, t->DL, a, a, 0, 0, 0);
1532 if ((amnt == 1 && t->al) || !t->AL)
1534 texec(t->cap, t->al, 1, top, 0, 0, 0);
1536 texec(t->cap, t->AL, a, a, 0, 0, 0);
1539 msetI(t->updtab + top, 1, bot - top);
1540 msetI(t->syntab + top, -1, bot - top);
1543 mmove(t->scrn + (top + amnt) * t->co, t->scrn + top * t->co, (bot - top - amnt) * t->co * sizeof(int));
1544 mmove(t->attr + (top + amnt) * t->co, t->attr + top * t->co, (bot - top - amnt) * t->co * sizeof(int));
1546 if (!top && t->da) {
1547 msetI(t->scrn, -1, amnt * t->co);
1548 msetI(t->attr, 0, amnt * t->co);
1549 msetI(t->updtab, 1, amnt);
1550 msetI(t->syntab, -1, amnt);
1552 msetI(t->scrn + t->co * top, ' ', amnt * t->co);
1553 msetI(t->attr + t->co * top, 0, amnt * t->co);
1557 void nscroll(SCRN *t)
1561 for (y = 0; y != t->li; ++y) {
1565 if (q && q != t->li) {
1567 for (z = y; z != t->li && t->sary[z] == q; ++z)
1569 doupscrl(t, y, z + q, q);
1572 for (r = y; r != t->li && (t->sary[r] < 0 || t->sary[r] == t->li); ++r)
1577 if (q && q != t->li) {
1578 for (z = p; t->sary[z] = 0, (z && t->sary[z - 1] == q); --z)
1580 dodnscrl(t, z + q, p + 1, -q);
1588 msetI(t->sary, 0, t->li);
1591 void npartial(SCRN *t)
1595 setregn(t, 0, t->li);
1598 void nescape(SCRN *t)
1601 cpos(t, 0, t->li - 1);
1602 eraeol(t, 0, t->li - 1);
1604 texec(t->cap, t->te, 1, 0, 0, 0, 0);
1607 void nreturn(SCRN *t)
1610 texec(t->cap, t->ti, 1, 0, 0, 0, 0);
1611 if (!skiptop && t->cl)
1612 texec(t->cap, t->cl, 1, 0, 0, 0, 0);
1616 void nclose(SCRN *t)
1621 setregn(t, 0, t->li);
1622 cpos(t, 0, t->li - 1);
1624 texec(t->cap, t->te, 1, 0, 0, 0, 0);
1636 void nscrldn(SCRN *t, int top, int bot, int amnt)
1640 if (!amnt || top >= bot || bot > t->li)
1642 if ((amnt < bot - top && bot - top - amnt < amnt / 2) || !t->scroll)
1644 if (amnt < bot - top) {
1645 for (x = bot; x != top + amnt; --x) {
1646 t->sary[x - 1] = (t->sary[x - amnt - 1] == t->li ? t->li : t->sary[x - amnt - 1] - amnt);
1647 t->updtab[x - 1] = t->updtab[x - amnt - 1];
1648 t->syntab[x - 1] = t->syntab[x - amnt - 1];
1650 for (x = top; x != top + amnt; ++x) {
1655 if (amnt > bot - top)
1657 msetI(t->sary + top, t->li, amnt);
1658 if (amnt == bot - top) {
1659 msetI(t->updtab + top, 1, amnt);
1660 msetI(t->syntab + top, -1, amnt);
1664 void nscrlup(SCRN *t, int top, int bot, int amnt)
1668 if (!amnt || top >= bot || bot > t->li)
1670 if ((amnt < bot - top && bot - top - amnt < amnt / 2) || !t->scroll)
1672 if (amnt < bot - top) {
1673 for (x = top + amnt; x != bot; ++x) {
1674 t->sary[x - amnt] = (t->sary[x] == t->li ? t->li : t->sary[x] + amnt);
1675 t->updtab[x - amnt] = t->updtab[x];
1676 t->syntab[x - amnt] = t->syntab[x];
1678 for (x = bot - amnt; x != bot; ++x) {
1683 if (amnt > bot - top)
1685 msetI(t->sary + bot - amnt, t->li, amnt);
1686 if (amnt == bot - top) {
1687 msetI(t->updtab + bot - amnt, 1, amnt);
1688 msetI(t->syntab + bot - amnt, -1, amnt);
1692 extern volatile int dostaupd;
1694 void nredraw(SCRN *t)
1697 msetI(t->scrn, ' ', t->co * skiptop);
1698 msetI(t->attr, 0, t->co * skiptop);
1699 msetI(t->scrn + skiptop * t->co, -1, (t->li - skiptop) * t->co);
1700 msetI(t->attr + skiptop * t->co, 0, (t->li - skiptop) * t->co);
1701 msetI(t->sary, 0, t->li);
1702 msetI(t->updtab + skiptop, -1, t->li - skiptop);
1703 msetI(t->syntab + skiptop, -1, t->li - skiptop);
1712 setregn(t, 0, t->li);
1716 texec(t->cap, t->cl, 1, 0, 0, 0, 0);
1719 msetI(t->scrn, ' ', t->li * t->co);
1720 msetI(t->attr, 0, t->li * t->co);
1723 texec(t->cap, t->cd, 1, 0, 0, 0, 0);
1724 msetI(t->scrn, ' ', t->li * t->co);
1725 msetI(t->attr, 0, t->li * t->co);
1730 /* Convert color/attribute name into internal code */
1732 int meta_color(unsigned char *s)
1734 if(!strcmp((char *)s,"inverse"))
1736 else if(!strcmp((char *)s,"underline"))
1738 else if(!strcmp((char *)s,"bold"))
1740 else if(!strcmp((char *)s,"blink"))
1742 else if(!strcmp((char *)s,"dim"))
1744 else if(!strcmp((char *)s,"white"))
1746 else if(!strcmp((char *)s,"cyan"))
1748 else if(!strcmp((char *)s,"magenta"))
1750 else if(!strcmp((char *)s,"blue"))
1752 else if(!strcmp((char *)s,"yellow"))
1754 else if(!strcmp((char *)s,"green"))
1756 else if(!strcmp((char *)s,"red"))
1758 else if(!strcmp((char *)s,"black"))
1760 else if(!strcmp((char *)s,"bg_white"))
1762 else if(!strcmp((char *)s,"bg_cyan"))
1764 else if(!strcmp((char *)s,"bg_magenta"))
1766 else if(!strcmp((char *)s,"bg_blue"))
1768 else if(!strcmp((char *)s,"bg_yellow"))
1770 else if(!strcmp((char *)s,"bg_green"))
1772 else if(!strcmp((char *)s,"bg_red"))
1774 else if(!strcmp((char *)s,"bg_black"))
1782 * 't' is SCRN to write to.
1783 * 'scrn' is address of field in character buffer
1784 * 'attr' is address of field in attribute buffer
1785 * 'x', 'y' are starting column and line numbers of field
1786 * 'ofst' is first column within string to display
1787 * 's', 'len' is string to generate in field
1788 * 'atr' is screeen attributes (and color) which should be used
1789 * 'width' is column width of field
1790 * 'flg' if set, erases to end of line
1793 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)
1797 int last_col = x + width;
1801 for (col = 0;len != 0 && x < last_col; len--) {
1805 if (fmt) my_atr |= *fmt++;
1806 if (locale_map->type) {
1807 /* UTF-8 mode: decode character and determine its width */
1808 c = utf8_decode(&sm,c);
1810 wid = joe_wcwidth(1,c);
1812 /* Byte mode: character is one column wide */
1817 if (x + wid > last_col) {
1818 /* Character crosses end of field, so fill balance of field with '>' characters instead */
1819 while (x < last_col) {
1820 outatr(utf8_map, t, scrn, attr, x, y, '>', my_atr);
1825 } else /* if (wid >(=) 0) */ {
1826 /* Emit character */
1827 outatr(locale_map, t, scrn, attr, x, y, c, my_atr);
1832 } else if ((col + wid) > ofst) {
1833 /* Wide character crosses left side of field */
1837 outatr(utf8_map, t, scrn, attr, x, y, '<', my_atr);
1848 /* Fill balance of field with spaces */
1849 while (x < last_col) {
1850 outatr(utf8_map, t, scrn, attr, x, y, ' ', 0);
1855 /* Erase to end of line */
1860 /* Width function for above */
1862 int txtwidth(unsigned char *s,int len)
1864 if (locale_map->type) {
1870 int d = utf8_decode(&sm,*s++);
1872 col += joe_wcwidth(1,d);
1880 /* Generate text with formatting escape sequences */
1882 void genfmt(SCRN *t, int x, int y, int ofst, const unsigned char *s, int flg)
1884 int *scrn = t->scrn + y * t->co + x;
1885 int *attr = t->attr + y * t->co + x;
1893 while ((c = *s++) != '\0')
1920 if (col++ >= ofst) {
1921 outatr(locale_map, t, scrn, attr, x, y, (c&0x7F), atr);
1931 if (locale_map->type) {
1932 /* UTF-8 mode: decode character and determine its width */
1933 c = utf8_decode(&sm,c);
1935 wid = joe_wcwidth(1, c);
1938 /* Byte mode: character is one column wide */
1944 outatr(locale_map, t, scrn, attr, x, y, c, atr);
1949 } else if (col+wid>ofst) {
1955 outatr(utf8_map, t, scrn, attr, x, y, '<', atr);
1970 /* Determine column width of string with format codes */
1972 int fmtlen(const unsigned char *s)
1980 while ((c = (*s++))) {
2002 if(locale_map->type) {
2003 c = utf8_decode(&sm,c);
2005 wid = joe_wcwidth(1,c);
2015 /* Return offset within format string which corresponds to a particular
2018 /* FIXME: this is not valid if we land in the middle of a double-wide character */
2020 int fmtpos(unsigned char *s, int goal)
2022 unsigned char *org = s;
2029 while ((c= *s) && col<goal) {
2053 if(locale_map->type) {
2054 c = utf8_decode(&sm,c);
2056 wid = joe_wcwidth(1,c);
2064 return s - org + goal - col;