[PATCH] Screen buffers ESC keypresses indefinitely since sgr support
[screen.git] / src / winmsg.c
blob53f3261f6f6b1b665a5ca8c9f33507fc133ba265
1 /* Copyright (c) 2013
2 * Mike Gerwitz (mtg@gnu.org)
3 * Copyright (c) 2010
4 * Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
5 * Sadrul Habib Chowdhury (sadrul@users.sourceforge.net)
6 * Copyright (c) 2008, 2009
7 * Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
8 * Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
9 * Micah Cowan (micah@cowan.name)
10 * Sadrul Habib Chowdhury (sadrul@users.sourceforge.net)
11 * Copyright (c) 1993-2002, 2003, 2005, 2006, 2007
12 * Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
13 * Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
14 * Copyright (c) 1987 Oliver Laumann
16 * This program is free software; you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License as published by
18 * the Free Software Foundation; either version 3, or (at your option)
19 * any later version.
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
26 * You should have received a copy of the GNU General Public License
27 * along with this program (see the file COPYING); if not, see
28 * https://www.gnu.org/licenses/, or contact Free Software Foundation, Inc.,
29 * 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
31 ****************************************************************
34 #include "config.h"
36 #include "winmsg.h"
38 #include "screen.h"
40 #include "fileio.h"
41 #include "help.h"
42 #include "logfile.h"
43 #include "mark.h"
44 #include "process.h"
45 #include "sched.h"
47 /* TODO: rid global variable (has been renamed to point this out; see commit
48 * history) */
49 WinMsgBuf *g_winmsg;
51 #define CHRPAD 127
53 /* maximum limit on MakeWinMsgEv recursion */
54 #define WINMSG_RECLIMIT 10
56 /* escape char for backtick output */
57 #define WINMSG_BT_ESC '\005'
59 /* redundant definition abstraction for escape character handlers; note that
60 * a variable varadic macro name is a gcc extension and is not portable, so
61 * we instead use two separate macros */
62 #define WINMSG_ESC_PARAMS \
63 __attribute__((unused)) WinMsgEsc *esc, \
64 __attribute__((unused)) char **src, \
65 __attribute__((unused)) WinMsgBufContext *wmbc, \
66 __attribute__((unused)) WinMsgCond *cond
67 #define winmsg_esc__name(name) __WinMsgEsc##name
68 #define winmsg_esc__def(name) static void winmsg_esc__name(name)
69 #define winmsg_esc(name) winmsg_esc__def(name)(WINMSG_ESC_PARAMS)
70 #define winmsg_esc_ex(name, ...) winmsg_esc__def(name)(WINMSG_ESC_PARAMS, __VA_ARGS__)
71 #define WINMSG_ESC_ARGS &esc, &s, wmbc, cond
72 #define WinMsgDoEsc(name) winmsg_esc__name(name)(WINMSG_ESC_ARGS)
73 #define WinMsgDoEscEx(name, ...) winmsg_esc__name(name)(WINMSG_ESC_ARGS, __VA_ARGS__)
75 static void _MakeWinMsgEvRec(WinMsgBufContext *, WinMsgCond *, char *, Window *, int *, int);
78 /* TODO: remove the redundant arguments */
79 static char *pad_expand(WinMsgBuf *winmsg, char *buf, char *p, int numpad, int padlen)
81 char *pn, *pn2;
82 int i, r;
84 padlen = padlen - (p - buf); /* space for rent */
85 if (padlen < 0)
86 padlen = 0;
87 pn2 = pn = p + padlen;
88 r = winmsg->numrend;
89 while (p >= buf) {
90 if (r && *p != CHRPAD && p - buf == winmsg->rendpos[r - 1]) {
91 winmsg->rendpos[--r] = pn - buf;
92 continue;
94 *pn-- = *p;
95 if (*p-- == CHRPAD) {
96 pn[1] = ' ';
97 i = numpad > 0 ? (padlen + numpad - 1) / numpad : 0;
98 padlen -= i;
99 while (i-- > 0)
100 *pn-- = ' ';
101 numpad--;
102 if (r && p - buf == winmsg->rendpos[r - 1])
103 winmsg->rendpos[--r] = pn - buf;
106 return pn2;
109 int AddWinMsgRend(WinMsgBuf *winmsg, const char *str, uint64_t r)
111 if (winmsg->numrend >= MAX_WINMSG_REND || str < winmsg->buf || str >= winmsg->buf + MAXSTR)
112 return -1;
114 wmb_rendadd(winmsg, r, str - winmsg->buf);
115 return 0;
119 winmsg_esc_ex(Wflags, Window *win)
121 *wmbc->p = '\0';
123 if (win)
124 AddWindowFlags(wmbc->p, wmbc_bytesleft(wmbc), win);
126 if (*wmbc->p)
127 wmc_set(cond);
129 wmbc_fastfw0(wmbc);
132 winmsg_esc(Pid)
134 wmbc_printf(wmbc, "%d", (esc->flags.plus && display) ? D_userpid : getpid());
137 winmsg_esc_ex(Backtick, int id, Window *win, int *tick, struct timeval *now, int rec)
139 Backtick *bt;
140 char *btresult;
142 if (!(bt = bt_find_id(id)))
143 return;
145 /* TODO: not re-entrant; static buffer returned */
146 btresult = runbacktick(bt, tick, now->tv_sec);
147 _MakeWinMsgEvRec(wmbc, cond, btresult, win, tick, rec);
150 winmsg_esc_ex(CopyMode, Event *ev)
152 if (display && ev && ev != &D_hstatusev) { /* Hack */
153 /* Is the layer in the current canvas in copy mode? */
154 Canvas *cv = (Canvas *)ev->data;
155 if (ev == &cv->c_captev && cv->c_layer->l_layfn == &MarkLf)
156 wmc_set(cond);
160 winmsg_esc(EscSeen)
162 if (display && D_ESCseen) {
163 wmc_set(cond);
167 winmsg_esc_ex(Focus, Window *win, Event *ev)
169 /* small hack (TODO: explain.) */
170 if (display && ((ev && ev == &D_forecv->c_captev) || (!ev && win && win == D_fore)))
171 esc->flags.minus ^= 1;
173 if (esc->flags.minus)
174 wmc_set(cond);
177 winmsg_esc(HostName)
179 if (*wmbc_strcpy(wmbc, HostName))
180 wmc_set(cond);
183 winmsg_esc_ex(Hstatus, Window *win, int *tick, int rec)
185 if (!win || win->w_hstatus == NULL || *win->w_hstatus == '\0')
186 return;
188 _MakeWinMsgEvRec(wmbc, cond, win->w_hstatus, win, tick, rec);
191 winmsg_esc_ex(PadOrTrunc, int *numpad, int *lastpad, int padlen)
193 /* TODO: encapsulate */
194 WinMsgBuf *winmsg = wmbc->buf;
195 uint64_t r;
197 wmbc_putchar(wmbc, ' ');
198 wmbc->p--; /* TODO: temporary to work with old code */
200 if (esc->num || esc->flags.zero || esc->flags.plus || esc->flags.lng || (**src != WINESC_PAD)) {
201 /* expand all pads */
202 if (esc->flags.minus) {
203 esc->num = (esc->flags.plus ? *lastpad : padlen) - esc->num;
205 if (!esc->flags.plus && padlen == 0)
206 esc->num = wmbc->p - winmsg->buf;
208 esc->flags.plus = 0;
209 } else if (!esc->flags.zero) {
210 if (**src != WINESC_PAD && esc->num == 0 && !esc->flags.plus)
211 esc->num = 100;
213 if (esc->num > 100)
214 esc->num = 100;
216 if (padlen == 0)
217 esc->num = wmbc->p - winmsg->buf;
218 else
219 esc->num = (padlen - (esc->flags.plus ? *lastpad : 0)) * esc->num / 100;
222 if (esc->num < 0)
223 esc->num = 0;
225 if (esc->flags.plus)
226 esc->num += *lastpad;
228 if (esc->num > MAXSTR - 1)
229 esc->num = MAXSTR - 1;
231 if (*numpad)
232 wmbc->p = pad_expand(winmsg, winmsg->buf, wmbc->p, *numpad, esc->num);
234 *numpad = 0;
235 if (wmbc->p - winmsg->buf > esc->num && !esc->flags.lng) {
236 int left, trunc;
238 if (wmbc->trunc.pos == -1) {
239 wmbc->trunc.pos = *lastpad;
240 wmbc->trunc.perc = 0;
243 trunc = *lastpad + wmbc->trunc.perc * (esc->num - *lastpad) / 100;
244 if (trunc > esc->num)
245 trunc = esc->num;
246 if (trunc < *lastpad)
247 trunc = *lastpad;
249 left = wmbc->trunc.pos - trunc;
250 if (left > wmbc->p - winmsg->buf - esc->num)
251 left = wmbc->p - winmsg->buf - esc->num;
253 if (left > 0) {
254 if (left + *lastpad > wmbc->p - winmsg->buf)
255 left = wmbc->p - winmsg->buf - *lastpad;
257 if (wmbc->p - winmsg->buf - *lastpad - left > 0)
258 memmove(winmsg->buf + *lastpad, winmsg->buf + *lastpad + left,
259 wmbc->p - winmsg->buf - *lastpad - left);
261 wmbc->p -= left;
262 r = winmsg->numrend;
263 while (r && winmsg->rendpos[r - 1] > *lastpad) {
264 r--;
265 winmsg->rendpos[r] -= left;
266 if (winmsg->rendpos[r] < *lastpad)
267 winmsg->rendpos[r] = *lastpad;
270 if (wmbc->trunc.ellip) {
271 if (wmbc->p - winmsg->buf > *lastpad)
272 winmsg->buf[*lastpad] = '.';
273 if (wmbc->p - winmsg->buf > *lastpad + 1)
274 winmsg->buf[*lastpad + 1] = '.';
275 if (wmbc->p - winmsg->buf > *lastpad + 2)
276 winmsg->buf[*lastpad + 2] = '.';
280 if (wmbc->p - winmsg->buf > esc->num) {
281 wmbc->p = winmsg->buf + esc->num;
282 if (wmbc->trunc.ellip) {
283 if (esc->num - 1 >= *lastpad)
284 wmbc->p[-1] = '.';
285 if (esc->num - 2 >= *lastpad)
286 wmbc->p[-2] = '.';
287 if (esc->num - 3 >= *lastpad)
288 wmbc->p[-3] = '.';
291 r = winmsg->numrend;
292 while (r && winmsg->rendpos[r - 1] > esc->num)
293 winmsg->rendpos[--r] = esc->num;
296 wmbc->trunc.pos = -1;
297 wmbc->trunc.ellip = false;
299 if (*lastpad > wmbc->p - winmsg->buf)
300 *lastpad = wmbc->p - winmsg->buf;
303 if (**src == WINESC_PAD) {
304 while (wmbc->p - winmsg->buf < esc->num)
305 wmbc_putchar(wmbc, ' ');
307 *lastpad = wmbc->p - winmsg->buf;
308 wmbc->trunc.pos = -1;
309 wmbc->trunc.ellip = false;
311 } else if (padlen) {
312 *wmbc->p = CHRPAD; /* internal pad representation */
313 (*numpad)++;
316 wmbc->p++; /* TODO: temporary; see above */
320 * Processes rendition
322 * The first character of SRC is assumed to be (unverified) the opening brace
323 * of the sequence.
325 winmsg_esc(Rend)
327 char rbuf[RENDBUF_SIZE];
328 uint8_t i;
329 uint64_t r;
331 (*src)++;
332 for (i = 0; i < (RENDBUF_SIZE-1); i++) {
333 char c = (*src)[i];
334 if (c && c != WINESC_REND_END)
335 rbuf[i] = c;
336 else
337 break;
340 if (((*src)[i] == WINESC_REND_END) && (wmbc->buf->numrend < MAX_WINMSG_REND)) {
341 r = 0;
342 rbuf[i] = '\0';
343 if (i != 1 || rbuf[0] != WINESC_REND_POP)
344 r = ParseAttrColor(rbuf, 0);
345 AddWinMsgRend(wmbc->buf, wmbc->p, r);
347 *src += i;
350 winmsg_esc(SessName)
352 char *session_name = strchr(SocketName, '.') + 1;
354 if (*wmbc_strcpy(wmbc, session_name))
355 wmc_set(cond);
358 winmsg_esc_ex(TruncPos, uint8_t perc, bool ellip)
360 /* TODO: encapsulate */
361 wmbc->trunc.pos = wmbc_offset(wmbc);
362 wmbc->trunc.perc = perc;
363 wmbc->trunc.ellip = ellip;
366 winmsg_esc_ex(WinNames, const bool hide_cur, Window *win)
368 Window *oldfore = NULL;
369 size_t max = wmbc_bytesleft(wmbc);
371 if (display) {
372 oldfore = D_fore;
373 D_fore = win;
376 /* TODO: no need to enforce a limit here */
377 AddWindows(wmbc, max - 1,
378 hide_cur
379 | (esc->flags.lng ? 0 : 2)
380 | (esc->flags.plus ? 4 : 0)
381 | (esc->flags.minus ? 8 : 0),
382 win ? win->w_number : -1);
384 if (display)
385 D_fore = oldfore;
387 if (*wmbc->p)
388 wmc_set(cond);
390 wmbc_fastfw0(wmbc);
393 winmsg_esc_ex(WinArgv, Window *win)
395 if (!win || !win->w_cmdargs[0])
396 return;
398 wmbc_printf(wmbc, "%s", win->w_cmdargs[0]);
399 wmbc_fastfw0(wmbc);
401 if (**src == WINESC_CMD_ARGS) {
402 for (int i = 1; win->w_cmdargs[i]; i++) {
403 wmbc_printf(wmbc, " %s", win->w_cmdargs[i]);
404 wmbc_fastfw0(wmbc);
409 winmsg_esc_ex(WinNum, Window *win)
411 if (esc->num == 0)
412 esc->num = 1;
414 if (!win) {
415 wmbc_printf(wmbc, "%*s", esc->num, esc->num > 1 ? "--" : "-");
416 } else {
417 wmbc_printf(wmbc, "%*d", esc->num, win->w_number);
420 wmc_set(cond);
423 winmsg_esc_ex(WinCount, Window *win)
425 if (esc->num == 0)
426 esc->num = 1;
428 if (!win) {
429 wmbc_printf(wmbc, "%*s", esc->num, esc->num > 1 ? "--" : "-");
430 } else {
431 int count = 0;
433 for (Window *w = win; w; w = w->w_prev_mru) {
434 if (esc->flags.minus) {
435 if (w->w_group == win->w_group && w->w_type != W_TYPE_GROUP) {
436 count++;
438 } else {
439 count++;
443 wmbc_printf(wmbc, "%*d", esc->num, count);
446 wmc_set(cond);
449 winmsg_esc_ex(WinLogName, Window *win)
451 if (win && win->w_log && win->w_log->fp)
452 wmbc_printf(wmbc, "%s", win->w_log->name);
456 winmsg_esc_ex(WinTty, Window *win)
458 if (win && win->w_tty[0])
459 wmbc_printf(wmbc, "%s", win->w_tty);
463 winmsg_esc_ex(WinSize, Window *win)
465 if (!win)
466 wmbc_printf(wmbc, "--x--");
467 else
468 wmbc_printf(wmbc, "%dx%d", win->w_width, win->w_height);
471 winmsg_esc_ex(WinTitle, Window *win)
473 if (!win)
474 return;
476 if (*wmbc_strcpy(wmbc, win->w_title))
477 wmc_set(cond);
480 winmsg_esc_ex(WinGroup, Window *win)
482 if (!win || !win->w_group)
483 return;
485 if (*wmbc_strcpy(wmbc, win->w_group->w_title))
486 wmc_set(cond);
490 winmsg_esc_ex(Cond, int *condrend)
492 if (wmc_is_active(cond)) {
493 bool chg;
494 wmbc->p = wmbc->buf->buf + wmc_end(cond, wmbc_offset(wmbc), &chg);
496 if (chg)
497 wmbc->buf->numrend = *condrend;
499 wmc_deinit(cond);
500 return;
503 wmc_init(cond, wmbc_offset(wmbc));
504 *condrend = wmbc->buf->numrend;
507 winmsg_esc_ex(CondElse, int *condrend)
509 if (wmc_is_active(cond)) {
510 bool chg;
511 wmbc->p = wmbc->buf->buf + wmc_else(cond, wmbc_offset(wmbc), &chg);
513 /* if the true branch was discarded, restore to previous rendition
514 * state; otherwise, we're keeping it, so update the rendition state */
515 if (chg)
516 wmbc->buf->numrend = *condrend;
517 else
518 *condrend = wmbc->buf->numrend;
523 /* TODO: this is temporary until refactoring is complete and this code need not
524 * be abstracted */
525 static void _MakeWinMsgEvRec(WinMsgBufContext *wmbc, WinMsgCond *cond, char *str,
526 Window *win, int *tick, int rec)
528 int oldtick = *tick;
529 WinMsgBuf *tmp = wmb_create();
531 if (tmp == NULL)
532 Panic(0, "%s", strnomem);
534 /* create message in a new buffer and merge into our own */
535 MakeWinMsgEv(tmp, str, win, WINMSG_BT_ESC, 0, NULL, rec + 1);
536 if (*wmbc_mergewmb(wmbc, tmp))
537 wmc_set(cond);
539 /* TODO: handle some other way; not re-entrant */
540 if (!*tick || oldtick < *tick)
541 *tick = oldtick;
543 wmb_free(tmp);
546 /* TODO: const char *str for safety and reassurance */
547 char *MakeWinMsgEv(WinMsgBuf *winmsg, char *str, Window *win,
548 int chesc, int padlen, Event *ev, int rec)
550 static int tick;
551 struct timeval now;
552 int qmnumrend = 0;
553 int numpad = 0;
554 int lastpad = 0;
555 WinMsgBufContext *wmbc;
556 WinMsgEsc esc;
557 WinMsgCond *cond;
559 /* TODO: temporary to work into existing code */
560 if (winmsg == NULL) {
561 if (g_winmsg == NULL) {
562 if ((g_winmsg = wmb_create()) == NULL)
563 Panic(0, "%s", strnomem);
565 winmsg = g_winmsg;
568 if (rec > WINMSG_RECLIMIT)
569 return winmsg->buf;
571 cond = calloc(1, sizeof(WinMsgCond));
572 if (cond == NULL)
573 Panic(0, "%s", strnomem);
575 /* set to sane state (clear garbage) */
576 wmc_deinit(cond);
578 /* TODO: we can get rid of this once winmsg is properly handled by caller */
579 if (winmsg->numrend > 0)
580 winmsg->numrend = 0;
582 wmb_reset(winmsg);
583 wmbc = wmbc_create(winmsg);
585 if (wmbc == NULL)
586 Panic(0, "%s", strnomem);
588 tick = 0;
589 gettimeofday(&now, NULL);
590 for (char *s = str; *s; s++) {
591 if (*s != chesc) {
592 if ((chesc == '%') && (*s == '^')) {
593 s++;
594 if (*s != '^' && *s >= 64)
595 wmbc_putchar(wmbc, *s & 0x1f);
596 continue;
598 wmbc_putchar(wmbc, *s);
599 continue;
602 if (*++s == chesc) /* double escape ? */
603 continue;
605 /* initialize escape */
606 if ((esc.flags.plus = (*s == '+')) != 0)
607 s++;
608 if ((esc.flags.minus = (*s == '-')) != 0)
609 s++;
610 if ((esc.flags.zero = (*s == '0')) != 0)
611 s++;
612 esc.num = 0;
613 while (*s >= '0' && *s <= '9')
614 esc.num = esc.num * 10 + (*s++ - '0');
615 if ((esc.flags.lng = (*s == 'L')) != 0)
616 s++;
618 switch (*s) {
619 case WINESC_COND:
620 WinMsgDoEscEx(Cond, &qmnumrend);
621 break;
622 case WINESC_COND_ELSE:
623 WinMsgDoEscEx(CondElse, &qmnumrend);
624 break;
625 case WINESC_HSTATUS:
626 WinMsgDoEscEx(Hstatus, win, &tick, rec);
627 break;
628 case WINESC_BACKTICK:
629 WinMsgDoEscEx(Backtick, esc.num, win, &tick, &now, rec);
630 break;
631 case WINESC_CMD:
632 case WINESC_CMD_ARGS:
633 WinMsgDoEscEx(WinArgv, win);
634 break;
635 case WINESC_WIN_NAMES:
636 case WINESC_WIN_NAMES_NOCUR:
637 WinMsgDoEscEx(WinNames, (*s == WINESC_WIN_NAMES_NOCUR), win);
638 break;
639 case WINESC_WFLAGS:
640 WinMsgDoEscEx(Wflags, win);
641 break;
642 case WINESC_WIN_TITLE:
643 WinMsgDoEscEx(WinTitle, win);
644 break;
645 case WINESC_WIN_GROUP:
646 WinMsgDoEscEx(WinGroup, win);
647 break;
648 case WINESC_REND_START:
649 WinMsgDoEsc(Rend);
650 break;
651 case WINESC_HOST:
652 WinMsgDoEsc(HostName);
653 break;
654 case WINESC_SESS_NAME:
655 WinMsgDoEsc(SessName);
656 break;
657 case WINESC_PID:
658 WinMsgDoEsc(Pid);
659 break;
660 case WINESC_FOCUS:
661 WinMsgDoEscEx(Focus, win, ev);
662 break;
663 case WINESC_COPY_MODE:
664 WinMsgDoEscEx(CopyMode, ev);
665 break;
666 case WINESC_ESC_SEEN:
667 WinMsgDoEsc(EscSeen);
668 break;
669 case WINESC_TRUNC_POS:
670 WinMsgDoEscEx(TruncPos,
671 ((esc.num > 100) ? 100 : esc.num),
672 esc.flags.lng);
673 break;
674 case WINESC_PAD:
675 case WINESC_TRUNC:
676 WinMsgDoEscEx(PadOrTrunc, &numpad, &lastpad, padlen);
677 break;
678 case WINESC_WIN_SIZE:
679 WinMsgDoEscEx(WinSize, win);
680 break;
681 case WINESC_WIN_NUM:
682 WinMsgDoEscEx(WinNum, win);
683 break;
684 case WINESC_WIN_COUNT:
685 WinMsgDoEscEx(WinCount, win);
686 break;
687 case WINESC_WIN_LOGNAME:
688 WinMsgDoEscEx(WinLogName, win);
689 break;
690 case WINESC_WIN_TTY:
691 WinMsgDoEscEx(WinTty, win);
692 break;
695 if (wmc_is_active(cond) && !wmc_is_set(cond))
696 wmbc->p = wmbc->buf->buf + wmc_end(cond, wmbc_offset(wmbc), NULL) + 1;
697 wmbc_putchar(wmbc, '\0' );
698 wmbc->p--; /* TODO: temporary to work with old code */
699 if (numpad) {
700 if (padlen > MAXSTR - 1)
701 padlen = MAXSTR - 1;
702 pad_expand(winmsg, winmsg->buf, wmbc->p, numpad, padlen);
704 if (ev) {
705 evdeq(ev); /* just in case */
706 ev->timeout = 0;
708 if (ev && tick) {
709 now.tv_usec = 100000;
710 if (tick == 1)
711 now.tv_sec++;
712 else
713 now.tv_sec += tick - (now.tv_sec % tick);
714 ev->timeout = (now.tv_sec * 1000 + now.tv_usec / 1000);
717 free(cond);
718 wmbc_free(wmbc);
719 return winmsg->buf;
722 char *MakeWinMsg(char *s, Window *win, int esc)
724 return MakeWinMsgEv(NULL, s, win, esc, 0, NULL, 0);
727 static int WindowChangedCheck(char *s, WinMsgEscapeChar what, int *hp)
729 int h = 0;
730 int l;
731 while (*s) {
732 if (*s++ != (hp ? '%' : '\005'))
733 continue;
734 l = 0;
735 s += (*s == '+');
736 s += (*s == '-');
737 while (*s >= '0' && *s <= '9')
738 s++;
739 if (*s == 'L') {
740 s++;
741 l = 0x100;
743 if (*s == WINESC_HSTATUS)
744 h = 1;
745 if (*s == (char)what || ((*s | l) == (int)what))
746 break;
747 if (*s)
748 s++;
750 if (hp)
751 *hp = h;
752 return *s ? 1 : 0;
755 void WindowChanged(Window *win, WinMsgEscapeChar what)
757 int inwstr, inhstr, inlstr;
758 int inwstrh = 0, inhstrh = 0, inlstrh = 0;
759 int got, ox, oy;
760 Display *olddisplay = display;
761 Canvas *cv;
763 if (what == WINESC_WFLAGS) {
764 WindowChanged(NULL, WINESC_WIN_NAMES | 0x100);
765 WindowChanged(NULL, WINESC_WIN_NAMES_NOCUR | 0x100);
768 if (what) {
769 inwstr = WindowChangedCheck(captionstring, what, &inwstrh);
770 inhstr = WindowChangedCheck(hstatusstring, what, &inhstrh);
771 inlstr = WindowChangedCheck(wliststr, what, &inlstrh);
772 } else {
773 inwstr = inhstr = 0;
774 inlstr = 1;
777 if (win == NULL) {
778 for (display = displays; display; display = display->d_next) {
779 ox = D_x;
780 oy = D_y;
781 for (cv = D_cvlist; cv; cv = cv->c_next) {
782 if (inlstr
783 || (inlstrh && win && win->w_hstatus && *win->w_hstatus
784 && WindowChangedCheck(win->w_hstatus, what, NULL)))
785 WListUpdatecv(cv, NULL);
786 win = Layer2Window(cv->c_layer);
787 if (inwstr
788 || (inwstrh && win && win->w_hstatus && *win->w_hstatus
789 && WindowChangedCheck(win->w_hstatus, what, NULL))) {
790 if (captiontop) {
791 if (cv->c_ys - 1 >= 0)
792 RefreshLine(cv->c_ys - 1, 0, D_width -1 , 0);
793 } else {
794 if (cv->c_ye + 1 < D_height)
795 RefreshLine(cv->c_ye + 1, 0, D_width - 1, 0);
799 win = D_fore;
800 if (inhstr
801 || (inhstrh && win && win->w_hstatus && *win->w_hstatus
802 && WindowChangedCheck(win->w_hstatus, what, NULL)))
803 RefreshHStatus();
804 if (ox != -1 && oy != -1)
805 GotoPos(ox, oy);
807 display = olddisplay;
808 return;
811 if (win->w_hstatus && *win->w_hstatus && (inwstrh || inhstrh || inlstrh)
812 && WindowChangedCheck(win->w_hstatus, what, NULL)) {
813 inwstr |= inwstrh;
814 inhstr |= inhstrh;
815 inlstr |= inlstrh;
817 if (!inwstr && !inhstr && !inlstr)
818 return;
819 for (display = displays; display; display = display->d_next) {
820 got = 0;
821 ox = D_x;
822 oy = D_y;
823 for (cv = D_cvlist; cv; cv = cv->c_next) {
824 if (inlstr)
825 WListUpdatecv(cv, win);
826 if (Layer2Window(cv->c_layer) != win)
827 continue;
828 got = 1;
829 if (inwstr) {
830 if (captiontop) {
831 if (cv->c_ys -1 >= 0)
832 RefreshLine(cv->c_ys - 1, 0, D_width - 1, 0);
833 } else {
834 if (cv->c_ye + 1 < D_height)
835 RefreshLine(cv->c_ye + 1, 0, D_width - 1, 0);
839 if (got && inhstr && win == D_fore)
840 RefreshHStatus();
841 if (ox != -1 && oy != -1)
842 GotoPos(ox, oy);
844 display = olddisplay;