Merge branch 'master' into lua-scripting
[screen-lua.git] / src / help.c
blob7bb7e6084f70d1c96f4261c81de3911ded18ebc8
1 /* Copyright (c) 2008, 2009
2 * Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
3 * Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
4 * Micah Cowan (micah@cowan.name)
5 * Sadrul Habib Chowdhury (sadrul@users.sourceforge.net)
6 * Copyright (c) 1993-2002, 2003, 2005, 2006, 2007
7 * Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
8 * Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
9 * Copyright (c) 1987 Oliver Laumann
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 3, or (at your option)
14 * any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program (see the file COPYING); if not, see
23 * http://www.gnu.org/licenses/, or contact Free Software Foundation, Inc.,
24 * 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
26 ****************************************************************
29 #include <sys/types.h>
31 #include "config.h"
33 #include "screen.h"
34 #include "extern.h"
36 char version[60]; /* initialised by main() */
38 extern struct layer *flayer;
39 extern struct display *display, *displays;
40 extern struct win *windows;
41 extern char *noargs[];
42 extern struct mchar mchar_blank, mchar_so;
43 extern int renditions[];
44 extern unsigned char *blank;
45 extern struct win *wtab[];
46 #ifdef MAPKEYS
47 extern struct term term[];
48 #endif
50 static void PadStr __P((char *, int, int, int));
52 extern char *wliststr;
53 extern char *wlisttit;
55 void
56 exit_with_usage(myname, message, arg)
57 char *myname, *message, *arg;
59 printf("Use: %s [-opts] [cmd [args]]\n", myname);
60 printf(" or: %s -r [host.tty]\n\nOptions:\n", myname);
61 printf("-a Force all capabilities into each window's termcap.\n");
62 printf("-A -[r|R] Adapt all windows to the new display width & height.\n");
63 printf("-c file Read configuration file instead of '.screenrc'.\n");
64 #ifdef REMOTE_DETACH
65 printf("-d (-r) Detach the elsewhere running screen (and reattach here).\n");
66 printf("-dmS name Start as daemon: Screen session in detached mode.\n");
67 printf("-D (-r) Detach and logout remote (and reattach here).\n");
68 printf("-D -RR Do whatever is needed to get a screen session.\n");
69 #endif
70 printf("-e xy Change command characters.\n");
71 printf("-f Flow control on, -fn = off, -fa = auto.\n");
72 printf("-h lines Set the size of the scrollback history buffer.\n");
73 printf("-i Interrupt output sooner when flow control is on.\n");
74 #if defined(LOGOUTOK) && defined(UTMPOK)
75 printf("-l Login mode on (update %s), -ln = off.\n", UTMPFILE);
76 #endif
77 printf("-list or -ls. Do nothing, just list our SockDir.\n");
78 printf("-L Turn on output logging.\n");
79 printf("-m ignore $STY variable, do create a new screen session.\n");
80 printf("-O Choose optimal output rather than exact vt100 emulation.\n");
81 printf("-p window Preselect the named window if it exists.\n");
82 printf("-q Quiet startup. Exits with non-zero return code if unsuccessful.\n");
83 printf("-r Reattach to a detached screen process.\n");
84 printf("-R Reattach if possible, otherwise start a new session.\n");
85 printf("-s shell Shell to execute rather than $SHELL.\n");
86 printf("-S sockname Name this session <pid>.sockname instead of <pid>.<tty>.<host>.\n");
87 printf("-t title Set title. (window's name).\n");
88 printf("-T term Use term as $TERM for windows, rather than \"screen\".\n");
89 #ifdef UTF8
90 printf("-U Tell screen to use UTF-8 encoding.\n");
91 #endif
92 printf("-v Print \"Screen version %s\".\n", version);
93 printf("-wipe Do nothing, just clean up SockDir.\n");
94 #ifdef MULTI
95 printf("-x Attach to a not detached screen. (Multi display mode).\n");
96 #endif /* MULTI */
97 printf("-X Execute <cmd> as a screen command in the specified session.\n");
98 if (message && *message)
100 printf("\nError: ");
101 printf(message, arg);
102 printf("\n");
104 exit(1);
108 ** Here come the help page routines
111 extern struct comm comms[];
112 extern struct action ktab[];
114 static void HelpProcess __P((char **, int *));
115 static void HelpAbort __P((void));
116 static void HelpRedisplayLine __P((int, int, int, int));
117 static void add_key_to_buf __P((char *, int));
118 static void AddAction __P((struct action *, int, int));
119 static int helppage __P((void));
121 struct helpdata
123 char *class;
124 struct action *ktabp;
125 int maxrow, grow, numcols, numrows, num_names;
126 int numskip, numpages;
127 int command_search, command_bindings;
128 int refgrow, refcommand_search;
129 int inter, mcom, mkey;
130 int nact[RC_LAST + 1];
133 #define MAXKLEN 256
135 static struct LayFuncs HelpLf =
137 HelpProcess,
138 HelpAbort,
139 HelpRedisplayLine,
140 DefClearLine,
141 DefRewrite,
142 DefResize,
143 DefRestore
147 void
148 display_help(class, ktabp)
149 char *class;
150 struct action *ktabp;
152 int i, n, key, mcom, mkey, l;
153 struct helpdata *helpdata;
154 int used[RC_LAST + 1];
156 if (flayer->l_height < 6)
158 LMsg(0, "Window height too small for help page");
159 return;
161 if (InitOverlayPage(sizeof(*helpdata), &HelpLf, 0))
162 return;
164 helpdata = (struct helpdata *)flayer->l_data;
165 helpdata->class = class;
166 helpdata->ktabp = ktabp;
167 helpdata->num_names = helpdata->command_bindings = 0;
168 helpdata->command_search = 0;
169 for (n = 0; n <= RC_LAST; n++)
170 used[n] = 0;
171 mcom = 0;
172 mkey = 0;
173 for (key = 0; key < 256 + KMAP_KEYS; key++)
175 n = ktabp[key].nr;
176 if (n == RC_ILLEGAL || n > RC_LAST)
177 continue;
178 if (ktabp[key].args == noargs)
180 used[n] += (key <= ' ' || key == 0x7f) ? 3 :
181 (key > 0x7f) ? 5 : 2;
183 else
184 helpdata->command_bindings++;
186 for (n = i = 0; n <= RC_LAST; n++)
187 if (used[n])
189 l = strlen(comms[n].name);
190 if (l > mcom)
191 mcom = l;
192 if (used[n] > mkey)
193 mkey = used[n];
194 helpdata->nact[i++] = n;
196 debug1("help: %d commands bound to keys with no arguments\n", i);
197 debug2("mcom: %d mkey: %d\n", mcom, mkey);
198 helpdata->num_names = i;
200 if (mkey > MAXKLEN)
201 mkey = MAXKLEN;
202 helpdata->numcols = flayer->l_width / (mcom + mkey + 1);
203 if (helpdata->numcols == 0)
205 HelpAbort();
206 LMsg(0, "Width too small");
207 return;
209 helpdata->inter = (flayer->l_width - (mcom + mkey) * helpdata->numcols) / (helpdata->numcols + 1);
210 if (helpdata->inter <= 0)
211 helpdata->inter = 1;
212 debug1("inter: %d\n", helpdata->inter);
213 helpdata->mcom = mcom;
214 helpdata->mkey = mkey;
215 helpdata->numrows = (helpdata->num_names + helpdata->numcols - 1) / helpdata->numcols;
216 debug1("Numrows: %d\n", helpdata->numrows);
217 helpdata->numskip = flayer->l_height-5 - (2 + helpdata->numrows);
218 while (helpdata->numskip < 0)
219 helpdata->numskip += flayer->l_height-5;
220 helpdata->numskip %= flayer->l_height-5;
221 debug1("Numskip: %d\n", helpdata->numskip);
222 if (helpdata->numskip > flayer->l_height/3 || helpdata->numskip > helpdata->command_bindings)
223 helpdata->numskip = 1;
224 helpdata->maxrow = 2 + helpdata->numrows + helpdata->numskip + helpdata->command_bindings;
225 helpdata->grow = 0;
227 helpdata->numpages = (helpdata->maxrow + flayer->l_height-6) / (flayer->l_height-5);
228 flayer->l_x = 0;
229 flayer->l_y = flayer->l_height - 1;
230 helppage();
233 static void
234 HelpProcess(ppbuf, plen)
235 char **ppbuf;
236 int *plen;
238 int done = 0;
240 while (!done && *plen > 0)
242 switch (**ppbuf)
244 case ' ':
245 if (helppage() == 0)
246 break;
247 /* FALLTHROUGH */
248 case '\r':
249 case '\n':
250 done = 1;
251 break;
252 default:
253 break;
255 ++*ppbuf;
256 --*plen;
258 if (done)
259 HelpAbort();
262 static void
263 HelpAbort()
265 LAY_CALL_UP(LRefreshAll(flayer, 0));
266 ExitOverlayPage();
270 static int
271 helppage()
273 struct helpdata *helpdata;
274 int col, crow, n, key, x;
275 char buf[MAXKLEN], Esc_buf[5], cbuf[256];
276 struct action *ktabp;
278 helpdata = (struct helpdata *)flayer->l_data;
280 ktabp = helpdata->ktabp;
281 if (helpdata->grow >= helpdata->maxrow)
282 return -1;
283 helpdata->refgrow = helpdata->grow;
284 helpdata->refcommand_search = helpdata->command_search;
286 /* Clear the help screen */
287 LClearAll(flayer, 0);
289 sprintf(cbuf,"Screen key bindings, page %d of %d.", helpdata->grow / (flayer->l_height-5) + 1, helpdata->numpages);
290 centerline(cbuf, 0);
291 crow = 2;
293 *Esc_buf = '\0';
294 *buf = '\0';
295 /* XXX fix escape character */
296 if (flayer->l_cvlist && flayer->l_cvlist->c_display)
298 add_key_to_buf(buf, flayer->l_cvlist->c_display->d_user->u_MetaEsc);
299 add_key_to_buf(Esc_buf, flayer->l_cvlist->c_display->d_user->u_Esc);
301 else
303 strcpy(Esc_buf, "??");
304 strcpy(buf, "??");
307 for (; crow < flayer->l_height - 3; crow++)
309 if (helpdata->grow < 1)
311 if (ktabp == ktab)
312 sprintf(cbuf,"Command key: %s Literal %s: %s", Esc_buf, Esc_buf, buf);
313 else
314 sprintf(cbuf,"Command class: '%.80s'", helpdata->class);
315 centerline(cbuf, crow);
316 helpdata->grow++;
318 else if (helpdata->grow >= 2 && helpdata->grow-2 < helpdata->numrows)
320 x = 0;
321 for (col = 0; col < helpdata->numcols && (n = helpdata->numrows * col + (helpdata->grow-2)) < helpdata->num_names; col++)
323 x += helpdata->inter - !col;
324 n = helpdata->nact[n];
325 buf[0] = '\0';
326 for (key = 0; key < 256 + KMAP_KEYS; key++)
327 if (ktabp[key].nr == n && ktabp[key].args == noargs && strlen(buf) < sizeof(buf) - 7)
329 strcat(buf, " ");
330 add_key_to_buf(buf, key);
332 PadStr(comms[n].name, helpdata->mcom, x, crow);
333 x += helpdata->mcom;
334 PadStr(buf, helpdata->mkey, x, crow);
335 x += helpdata->mkey;
337 helpdata->grow++;
339 else if (helpdata->grow-2-helpdata->numrows >= helpdata->numskip
340 && helpdata->grow-2-helpdata->numrows-helpdata->numskip < helpdata->command_bindings)
342 while ((n = ktabp[helpdata->command_search].nr) == RC_ILLEGAL
343 || ktabp[helpdata->command_search].args == noargs)
345 if (++helpdata->command_search >= 256 + KMAP_KEYS)
346 return -1;
348 buf[0] = '\0';
349 add_key_to_buf(buf, helpdata->command_search);
350 PadStr(buf, 5, 0, crow);
351 AddAction(&ktabp[helpdata->command_search++], 5, crow);
352 helpdata->grow++;
354 else
355 helpdata->grow++;
357 sprintf(cbuf,"[Press Space %s Return to end.]",
358 helpdata->grow < helpdata->maxrow ? "for next page;" : "or");
359 centerline(cbuf, flayer->l_height - 2);
360 LaySetCursor();
361 return 0;
364 static void
365 AddAction(act, x, y)
366 struct action *act;
367 int x, y;
369 char buf[256];
370 int del, l;
371 char *bp, *cp, **pp;
372 int *lp, ll;
373 int fr;
374 struct mchar mchar_dol;
376 mchar_dol = mchar_blank;
377 mchar_dol.image = '$';
379 fr = flayer->l_width - 1 - x;
380 if (fr <= 0)
381 return;
382 l = strlen(comms[act->nr].name);
384 if (l + 1 > fr)
385 l = fr - 1;
386 PadStr(comms[act->nr].name, l, x, y);
387 x += l;
388 fr -= l + 1;
389 LPutChar(flayer, fr ? &mchar_blank : &mchar_dol, x++, y);
391 pp = act->args;
392 lp = act->argl;
393 while (pp && (cp = *pp) != NULL)
395 del = 0;
396 bp = buf;
397 ll = *lp++;
398 if (!ll || (index(cp, ' ') != NULL))
400 if (index(cp, '\'') != NULL)
401 *bp++ = del = '"';
402 else
403 *bp++ = del = '\'';
405 while (ll-- && bp < buf + 250)
406 bp += AddXChar(bp, *(unsigned char *)cp++);
407 if (del)
408 *bp++ = del;
409 *bp = 0;
410 if ((fr -= (bp - buf) + 1) < 0)
412 fr += bp - buf;
413 if (fr > 0)
414 PadStr(buf, fr, x, y);
415 if (fr == 0)
416 LPutChar(flayer, &mchar_dol, x, y);
417 return;
419 PadStr(buf, strlen(buf), x, y);
420 x += strlen(buf);
421 pp++;
422 if (*pp)
423 LPutChar(flayer, fr ? &mchar_blank : &mchar_dol, x++, y);
427 static void
428 add_key_to_buf(buf, key)
429 char *buf;
430 int key;
432 buf += strlen(buf);
433 if (key < 0)
434 strcpy(buf, "unset");
435 else if (key == ' ')
436 strcpy(buf, "sp");
437 #ifdef MAPKEYS
438 else if (key >= 256)
440 key = key - 256 + T_CAPS;
441 buf[0] = ':';
442 buf[1] = term[key].tcname[0];
443 buf[2] = term[key].tcname[1];
444 buf[3] = ':';
445 buf[4] = 0;
447 #endif
448 else
449 buf[AddXChar(buf, key)] = 0;
453 static void
454 HelpRedisplayLine(y, xs, xe, isblank)
455 int y, xs, xe, isblank;
457 if (y < 0)
459 struct helpdata *helpdata;
461 helpdata = (struct helpdata *)flayer->l_data;
462 helpdata->grow = helpdata->refgrow;
463 helpdata->command_search = helpdata->refcommand_search;
464 helppage();
465 return;
467 if (y != 0 && y != flayer->l_height - 1)
468 return;
469 if (!isblank)
470 LClearArea(flayer, xs, y, xe, y, 0, 0);
476 ** here is all the copyright stuff
480 static void CopyrightProcess __P((char **, int *));
481 static void CopyrightRedisplayLine __P((int, int, int, int));
482 static void CopyrightAbort __P((void));
483 static void copypage __P((void));
485 struct copydata
487 char *cps, *savedcps; /* position in the message */
488 char *refcps, *refsavedcps; /* backup for redisplaying */
491 static struct LayFuncs CopyrightLf =
493 CopyrightProcess,
494 CopyrightAbort,
495 CopyrightRedisplayLine,
496 DefClearLine,
497 DefRewrite,
498 DefResize,
499 DefRestore
502 static const char cpmsg[] = "\
504 Screen version %v\n\
506 Copyright (c) 2008, 2009 Juergen Weigert, Michael Schroeder, Micah Cowan, Sadrul Habib Chowdhury\n\
507 Copyright (c) 1993-2002, 2003, 2005, 2006, 2007 Juergen Weigert, Michael Schroeder\n\
508 Copyright (c) 1987 Oliver Laumann\n\
510 This program is free software; you can redistribute it and/or \
511 modify it under the terms of the GNU General Public License as published \
512 by the Free Software Foundation; either version 3, or (at your option) \
513 any later version.\n\
515 This program is distributed in the hope that it will be useful, \
516 but WITHOUT ANY WARRANTY; without even the implied warranty of \
517 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the \
518 GNU General Public License for more details.\n\
520 You should have received a copy of the GNU General Public License \
521 along with this program (see the file COPYING); if not, see \
522 http://www.gnu.org/licenses/, or contact Free Software Foundation, Inc., \
523 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA.\n\
525 Send bugreports, fixes, enhancements, t-shirts, money, beer & pizza to \
526 screen@uni-erlangen.de\n";
529 static void
530 CopyrightProcess(ppbuf, plen)
531 char **ppbuf;
532 int *plen;
534 int done = 0;
535 struct copydata *copydata;
537 copydata = (struct copydata *)flayer->l_data;
538 while (!done && *plen > 0)
540 switch (**ppbuf)
542 case ' ':
543 if (*copydata->cps)
545 copypage();
546 break;
548 /* FALLTHROUGH */
549 case '\r':
550 case '\n':
551 CopyrightAbort();
552 done = 1;
553 break;
554 default:
555 break;
557 ++*ppbuf;
558 --*plen;
562 static void
563 CopyrightAbort()
565 LAY_CALL_UP(LRefreshAll(flayer, 0));
566 ExitOverlayPage();
569 void
570 display_copyright()
572 struct copydata *copydata;
574 if (flayer->l_width < 10 || flayer->l_height < 5)
576 LMsg(0, "Window size too small for copyright page");
577 return;
579 if (InitOverlayPage(sizeof(*copydata), &CopyrightLf, 0))
580 return;
581 copydata = (struct copydata *)flayer->l_data;
582 copydata->cps = (char *)cpmsg;
583 copydata->savedcps = 0;
584 flayer->l_x = 0;
585 flayer->l_y = flayer->l_height - 1;
586 copypage();
589 static void
590 copypage()
592 register char *cps;
593 char *ws;
594 int x, y, l;
595 char cbuf[80];
596 struct copydata *copydata;
598 ASSERT(flayer);
599 copydata = (struct copydata *)flayer->l_data;
601 LClearAll(flayer, 0);
602 x = y = 0;
603 cps = copydata->cps;
604 copydata->refcps = cps;
605 copydata->refsavedcps = copydata->savedcps;
606 while (*cps && y < flayer->l_height - 3)
608 ws = cps;
609 while (*cps == ' ')
610 cps++;
611 if (strncmp(cps, "%v", 2) == 0)
613 copydata->savedcps = cps + 2;
614 cps = version;
615 continue;
617 while (*cps && *cps != ' ' && *cps != '\n')
618 cps++;
619 l = cps - ws;
620 cps = ws;
621 if (l > flayer->l_width - 1)
622 l = flayer->l_width - 1;
623 if (x && x + l >= flayer->l_width - 2)
625 x = 0;
626 y++;
627 continue;
629 if (x)
631 LPutChar(flayer, &mchar_blank, x, y);
632 x++;
634 if (l)
635 LPutStr(flayer, ws, l, &mchar_blank, x, y);
636 x += l;
637 cps += l;
638 if (*cps == 0 && copydata->savedcps)
640 cps = copydata->savedcps;
641 copydata->savedcps = 0;
643 if (*cps == '\n')
645 x = 0;
646 y++;
648 if (*cps == ' ' || *cps == '\n')
649 cps++;
651 while (*cps == '\n')
652 cps++;
653 sprintf(cbuf,"[Press Space %s Return to end.]",
654 *cps ? "for next page;" : "or");
655 centerline(cbuf, flayer->l_height - 2);
656 copydata->cps = cps;
657 LaySetCursor();
660 static void
661 CopyrightRedisplayLine(y, xs, xe, isblank)
662 int y, xs, xe, isblank;
664 ASSERT(flayer);
665 if (y < 0)
667 struct copydata *copydata;
669 copydata = (struct copydata *)flayer->l_data;
670 copydata->cps = copydata->refcps;
671 copydata->savedcps = copydata->refsavedcps;
672 copypage();
673 return;
675 if (y != 0 && y != flayer->l_height - 1)
676 return;
677 if (isblank)
678 return;
679 LClearArea(flayer, xs, y, xe, y, 0, 0);
686 ** here is all the displays stuff
690 #ifdef MULTI
692 static void DisplaysProcess __P((char **, int *));
693 static void DisplaysRedisplayLine __P((int, int, int, int));
694 static void displayspage __P((void));
696 struct displaysdata
698 int dummy_element_for_solaris;
701 static struct LayFuncs DisplaysLf =
703 DisplaysProcess,
704 HelpAbort,
705 DisplaysRedisplayLine,
706 DefClearLine,
707 DefRewrite,
708 DefResize,
709 DefRestore
712 static void
713 DisplaysProcess(ppbuf, plen)
714 char **ppbuf;
715 int *plen;
717 int done = 0;
719 ASSERT(flayer);
720 while (!done && *plen > 0)
722 switch (**ppbuf)
724 case ' ':
725 displayspage();
726 break;
727 case '\r':
728 case '\n':
729 HelpAbort();
730 done = 1;
731 break;
732 default:
733 break;
735 ++*ppbuf;
736 --*plen;
741 void
742 display_displays()
744 if (flayer->l_width < 10 || flayer->l_height < 5)
746 LMsg(0, "Window size too small for displays page");
747 return;
749 if (InitOverlayPage(sizeof(struct displaysdata), &DisplaysLf, 0))
750 return;
751 flayer->l_x = 0;
752 flayer->l_y = flayer->l_height - 1;
753 displayspage();
757 * layout of the displays page is as follows:
759 xterm 80x42 jnweiger@/dev/ttyp4 0(m11) &rWx
760 facit 80x24 nb mlschroe@/dev/ttyhf 11(tcsh) rwx
761 xterm 80x42 jnhollma@/dev/ttyp5 0(m11) &R.x
763 | | | | | | | | ¦___ window permissions
764 | | | | | | | | (R. is locked r-only,
765 | | | | | | | | W has wlock)
766 | | | | | | | |___ Window is shared
767 | | | | | | |___ Name/Title of window
768 | | | | | |___ Number of window
769 | | | | |___ Name of the display (the attached device)
770 | | | |___ Username who is logged in at the display
771 | | |___ Display is in nonblocking mode. Shows 'NB' if obuf is full.
772 | |___ Displays geometry as width x height.
773 |___ the terminal type known by screen for this display.
777 static void
778 displayspage()
780 int y, l;
781 char tbuf[80];
782 struct display *d;
783 struct win *w;
784 static char *blockstates[5] = {"nb", "NB", "Z<", "Z>", "BL"};
786 LClearAll(flayer, 0);
788 leftline("term-type size user interface window", 0);
789 leftline("---------- ------- ---------- ----------------- ----------", 1);
790 y = 2;
792 for (d = displays; d; d = d->d_next)
794 w = d->d_fore;
796 if (y >= flayer->l_height - 3)
797 break;
798 sprintf(tbuf, "%-10.10s%4dx%-4d%10.10s@%-16.16s%s",
799 d->d_termname, d->d_width, d->d_height, d->d_user->u_name,
800 d->d_usertty,
801 (d->d_blocked || d->d_nonblock >= 0) && d->d_blocked <= 4 ? blockstates[d->d_blocked] : " ");
803 if (w)
805 l = 10 - strlen(w->w_title);
806 if (l < 0)
807 l = 0;
808 sprintf(tbuf + strlen(tbuf), "%3d(%.10s)%*s%c%c%c%c",
809 w->w_number, w->w_title, l, "",
810 /* w->w_dlist->next */ 0 ? '&' : ' ',
812 * The rwx triple:
813 * -,r,R no read, read, read only due to foreign wlock
814 * -,.,w,W no write, write suppressed by foreign wlock,
815 * write, own wlock
816 * -,x no execute, execute
818 #ifdef MULTIUSER
819 (AclCheckPermWin(d->d_user, ACL_READ, w) ? '-' :
820 ((w->w_wlock == WLOCK_OFF || d->d_user == w->w_wlockuser) ?
821 'r' : 'R')),
822 (AclCheckPermWin(d->d_user, ACL_READ, w) ? '-' :
823 ((w->w_wlock == WLOCK_OFF) ? 'w' :
824 ((d->d_user == w->w_wlockuser) ? 'W' : 'v'))),
825 (AclCheckPermWin(d->d_user, ACL_READ, w) ? '-' : 'x')
826 #else
827 'r', 'w', 'x'
828 #endif
831 leftline(tbuf, y);
832 y++;
834 sprintf(tbuf,"[Press Space %s Return to end.]",
835 1 ? "to refresh;" : "or");
836 centerline(tbuf, flayer->l_height - 2);
837 LaySetCursor();
840 static void
841 DisplaysRedisplayLine(y, xs, xe, isblank)
842 int y, xs, xe, isblank;
844 ASSERT(flayer);
845 if (y < 0)
847 displayspage();
848 return;
850 if (y != 0 && y != flayer->l_height - 1)
851 return;
852 if (isblank)
853 return;
854 LClearArea(flayer, xs, y, xe, y, 0, 0);
855 /* To be filled in... */
858 #endif /* MULTI */
863 ** here is the windowlist
867 struct wlistdata;
869 static void WListProcess __P((char **, int *));
870 static void WListRedisplayLine __P((int, int, int, int));
871 static void wlistpage __P((void));
872 static void WListLine __P((int, int, int, int));
873 static void WListLines __P((int, int));
874 static void WListMove __P((int, int));
875 static void WListUpdate __P((struct win *));
876 static int WListNormalize __P((void));
877 static int WListResize __P((int, int));
878 static int WListNext __P((struct wlistdata *, int, int));
880 struct wlistdata {
881 int pos;
882 int ypos;
883 int npos;
884 int numwin;
885 int first;
886 int last;
887 int start;
888 int order;
889 struct win *group;
890 int nested;
891 int list[MAXWIN];
894 static struct LayFuncs WListLf =
896 WListProcess,
897 HelpAbort,
898 WListRedisplayLine,
899 DefClearLine,
900 DefRewrite,
901 WListResize,
902 DefRestore
905 #define WTAB_GROUP_MATCHES(i) (group == wtab[i]->w_group)
907 static int
908 WListResize(wi, he)
909 int wi, he;
911 struct wlistdata *wlistdata;
912 if (wi < 10 || he < 5)
913 return -1;
914 wlistdata = (struct wlistdata *)flayer->l_data;
915 flayer->l_width = wi;
916 flayer->l_height = he;
917 wlistdata->numwin = he - 3;
918 if (wlistdata->ypos >= wlistdata->numwin)
919 wlistdata->ypos = wlistdata->numwin - 1;
920 flayer->l_y = he - 1;
921 return 0;
924 static void
925 WListProcess(ppbuf, plen)
926 char **ppbuf;
927 int *plen;
929 int done = 0;
930 struct wlistdata *wlistdata;
931 struct display *olddisplay = display;
932 int h;
933 struct win *group;
935 ASSERT(flayer);
936 wlistdata = (struct wlistdata *)flayer->l_data;
937 group = wlistdata->group;
938 h = wlistdata->numwin;
939 while (!done && *plen > 0)
941 if ((unsigned char)**ppbuf >= '0' && (unsigned char)**ppbuf <= '9')
943 int n = (unsigned char)**ppbuf - '0';
944 int d = 0;
945 if (n < MAXWIN && wtab[n] && WTAB_GROUP_MATCHES(n))
947 int i;
948 for (d = -wlistdata->npos, i = WListNext(wlistdata, -1, 0); i != n; i = WListNext(wlistdata, i, 1), d++)
951 if (d)
952 WListMove(d, -1);
954 switch ((unsigned char)**ppbuf)
956 case 0220: /* up */
957 case 16: /* ^P like emacs */
958 case 'k':
959 WListMove(-1, -1);
960 break;
961 case 0216: /* down */
962 case 14: /* ^N like emacs */
963 case 'j':
964 WListMove(1, -1);
965 break;
966 case '\025':
967 WListMove(-(h / 2), wlistdata->ypos);
968 break;
969 case '\004':
970 WListMove(h / 2, wlistdata->ypos);
971 break;
972 case 0002:
973 case 'b':
974 WListMove(-h, -1);
975 break;
976 case 0006:
977 case 'f':
978 WListMove(h, -1);
979 break;
980 case 0201: /* home */
981 WListMove(-wlistdata->pos, -1);
982 break;
983 case 0205: /* end */
984 WListMove(MAXWIN, -1);
985 break;
986 case 'a':
987 /* All-window view */
988 wlistdata->group = 0;
989 wlistdata->nested = WLIST_NESTED;
990 wlistpage();
991 break;
992 case 'g':
993 /* Toggle nested view */
994 wlistdata->nested ^= WLIST_NESTED;
995 wlistpage();
996 break;
997 case 'm':
998 /* Toggle MRU view */
999 wlistdata->order ^= 1;
1000 wlistpage();
1001 break;
1002 case '\r':
1003 case '\n':
1004 case ' ':
1005 h = wlistdata->pos;
1006 if (h == MAXWIN && Layer2Window(flayer) && Layer2Window(flayer)->w_type == W_TYPE_GROUP)
1007 break;
1008 if (display && h != MAXWIN && wtab[h] && (wtab[h]->w_type == W_TYPE_GROUP || wtab[h] == D_fore))
1010 wlistdata->group = wtab[h];
1011 wlistdata->pos = wtab[h]->w_number;
1012 wlistpage();
1013 break;
1015 done = 1;
1016 if (!display || h == MAXWIN || !wtab[h] || wtab[h] == D_fore || (flayer->l_cvlist && flayer->l_cvlist->c_lnext))
1017 HelpAbort();
1018 #ifdef MULTIUSER
1019 else if (AclCheckPermWin(D_user, ACL_READ, wtab[h]))
1020 HelpAbort();
1021 #endif
1022 else
1023 ExitOverlayPage(); /* no need to redisplay */
1024 /* restore display, don't switch wrong user */
1025 display = olddisplay;
1026 if (h != MAXWIN)
1027 SwitchWindow(h);
1028 break;
1029 case 0033:
1030 case 0007:
1031 h = wlistdata->start;
1032 if (h == -1 && Layer2Window(flayer) && Layer2Window(flayer)->w_type == W_TYPE_GROUP)
1034 struct win *p = Layer2Window(flayer);
1035 if (wlistdata->group != p)
1037 wlistdata->group = p;
1038 wlistpage();
1040 break;
1042 HelpAbort();
1043 display = olddisplay;
1044 if (h >= 0 && wtab[h])
1045 SwitchWindow(h);
1046 else if (h == -2)
1048 struct win *p = FindNiceWindow(display ? D_other : (struct win *)0, 0);
1049 if (p)
1050 SwitchWindow(p->w_number);
1052 done = 1;
1053 break;
1054 case '\010': /* ctrl-h */
1055 case 0177:
1056 if (!wlistdata->group)
1057 break;
1058 wlistdata->pos = wlistdata->group->w_number;
1059 wlistdata->group = wlistdata->group->w_group;
1060 if (wlistdata->group)
1061 wlistdata->pos = wlistdata->group->w_number;
1062 wlistpage();
1063 break;
1064 default:
1065 break;
1067 ++*ppbuf;
1068 --*plen;
1072 static void
1073 WListLine(y, i, pos, isblank)
1074 int y, i;
1075 int pos;
1076 int isblank;
1078 char *str;
1079 int n;
1080 int yoff, xoff = 0;
1081 struct wlistdata *wlistdata;
1082 struct win *group;
1083 struct mchar mchar_rend = mchar_blank;
1084 struct mchar *mchar = (struct mchar *)0;
1086 if (i == MAXWIN)
1087 return;
1088 wlistdata = (struct wlistdata *)flayer->l_data;
1089 if (wlistdata->nested && wtab[i])
1090 for (group = wtab[i]->w_group, xoff = 0; group != wlistdata->group;
1091 group = group->w_group, xoff += 2)
1093 yoff = wlistdata->group ? 3 : 2;
1094 display = Layer2Window(flayer) ? 0 : flayer->l_cvlist ? flayer->l_cvlist->c_display : 0;
1095 str = MakeWinMsgEv(wliststr, wtab[i], '%', flayer->l_width - xoff, (struct event *)0, 0);
1096 n = strlen(str);
1097 if (i != pos && isblank)
1098 while (n && str[n - 1] == ' ')
1099 n--;
1100 if (i == pos)
1101 mchar = &mchar_so;
1102 else if (wtab[i]->w_monitor == MON_DONE && renditions[REND_MONITOR] != -1)
1104 mchar = &mchar_rend;
1105 ApplyAttrColor(renditions[REND_MONITOR], mchar);
1107 else if ((wtab[i]->w_bell == BELL_DONE || wtab[i]->w_bell == BELL_FOUND) && renditions[REND_BELL] != -1)
1109 mchar = &mchar_rend;
1110 ApplyAttrColor(renditions[REND_BELL], mchar);
1112 else
1113 mchar = &mchar_blank;
1114 LPutWinMsg(flayer, str, (i == pos || !isblank) ? flayer->l_width : n, mchar, xoff, y + yoff);
1115 if (xoff)
1116 LPutWinMsg(flayer, "", xoff, mchar, 0, y + yoff);
1117 #if 0
1118 LPutStr(flayer, str, n, i == pos ? &mchar_so : &mchar_blank, 0, y + yoff);
1119 if (i == pos || !isblank)
1120 while(n < flayer->l_width)
1121 LPutChar(flayer, i == pos ? &mchar_so : &mchar_blank, n++, y + yoff);
1122 #endif
1123 return;
1127 static int
1128 WListNext(wlistdata, old, delta)
1129 struct wlistdata *wlistdata;
1130 int old, delta;
1132 int i;
1134 if (old == MAXWIN)
1135 return MAXWIN;
1136 if (old == -1)
1137 old = 0;
1138 else
1140 for (i = 0; i < MAXWIN && wlistdata->list[i] != -1; i++)
1141 if (wlistdata->list[i] == old)
1142 break;
1143 if (i < MAXWIN && wlistdata->list[i] != -1)
1144 old = i;
1147 old += delta;
1148 if (old < 0 || old >= MAXWIN || wlistdata->list[old] == -1)
1149 old -= delta;
1150 return wlistdata->list[old];
1153 static void
1154 WListLines(up, oldpos)
1155 int up, oldpos;
1157 struct wlistdata *wlistdata;
1158 int ypos, pos;
1159 int y, i, oldi;
1161 wlistdata = (struct wlistdata *)flayer->l_data;
1162 ypos = wlistdata->ypos;
1163 pos = wlistdata->pos;
1165 i = WListNext(wlistdata, pos, -ypos);
1166 for (y = 0; y < wlistdata->numwin; y++)
1168 if (i == MAXWIN || !wtab[i])
1169 return;
1170 if (y == 0)
1171 wlistdata->first = i;
1172 wlistdata->last = i;
1173 if (((i == oldpos || i == pos) && pos != oldpos) || (up > 0 && y >= wlistdata->numwin - up) || (up < 0 && y < -up))
1174 WListLine(y, i, pos, i != oldpos);
1175 if (i == pos)
1176 wlistdata->ypos = y;
1177 oldi = i;
1178 i = WListNext(wlistdata, i, 1);
1179 if (i == MAXWIN || i == oldi)
1180 break;
1184 static int
1185 WListNormalize()
1187 struct wlistdata *wlistdata;
1188 int i, oldi, n;
1189 int ypos, pos;
1191 wlistdata = (struct wlistdata *)flayer->l_data;
1192 ypos = wlistdata->ypos;
1193 pos = wlistdata->pos;
1194 if (ypos < 0)
1195 ypos = 0;
1196 if (ypos >= wlistdata->numwin)
1197 ypos = wlistdata->numwin - 1;
1198 for (n = 0, oldi = MAXWIN, i = pos; i != MAXWIN && i != oldi && n < wlistdata->numwin; oldi = i, i = WListNext(wlistdata, i, 1))
1199 n++;
1200 if (ypos < wlistdata->numwin - n)
1201 ypos = wlistdata->numwin - n;
1202 for (n = 0, oldi = MAXWIN, i = WListNext(wlistdata, -1, 0); i != MAXWIN && i != oldi && i != pos; oldi = i, i = WListNext(wlistdata, i, 1))
1203 n++;
1204 if (ypos > n)
1205 ypos = n;
1206 wlistdata->ypos = ypos;
1207 wlistdata->npos = n;
1208 return ypos;
1211 static void
1212 WListMove(num, ypos)
1213 int num;
1214 int ypos;
1216 struct wlistdata *wlistdata;
1217 int oldpos, oldypos, oldnpos;
1218 int pos, up;
1220 wlistdata = (struct wlistdata *)flayer->l_data;
1221 oldpos = wlistdata->pos;
1222 oldypos = wlistdata->ypos;
1223 oldnpos = wlistdata->npos;
1224 wlistdata->ypos = ypos == -1 ? oldypos + num : ypos;
1225 pos = WListNext(wlistdata, oldpos, num);
1226 wlistdata->pos = pos;
1227 ypos = WListNormalize();
1228 up = wlistdata->npos - ypos - (oldnpos - oldypos);
1229 if (up)
1231 LScrollV(flayer, up, 2, 2 + wlistdata->numwin - 1, 0);
1232 WListLines(up, oldpos);
1233 LaySetCursor();
1234 return;
1236 if (pos == oldpos)
1237 return;
1238 WListLine(oldypos, oldpos, pos, 0);
1239 WListLine(ypos, pos, pos, 1);
1240 LaySetCursor();
1243 static void
1244 WListRedisplayLine(y, xs, xe, isblank)
1245 int y, xs, xe, isblank;
1247 ASSERT(flayer);
1248 if (y < 0)
1250 wlistpage();
1251 return;
1253 if (y != 0 && y != flayer->l_height - 1)
1254 return;
1255 if (!isblank)
1256 LClearArea(flayer, xs, y, xe, y, 0, 0);
1259 static int
1260 WListOrder(wlistdata, ind, start, group)
1261 struct wlistdata *wlistdata;
1262 int ind, start;
1263 struct win *group;
1265 int i;
1267 if (ind >= MAXWIN)
1268 return ind;
1269 if (ind == 0)
1270 for (i = 0; i < MAXWIN; i++)
1271 wlistdata->list[i] = -1;
1273 if (wlistdata->order == WLIST_MRU)
1275 if (start == -1)
1276 start = windows->w_number;
1278 else
1280 if (start == -1)
1281 start = 0;
1282 while (start < MAXWIN && !wtab[start])
1283 start++;
1286 if (start >= MAXWIN || !wtab[start])
1287 return ind;
1289 if (!WTAB_GROUP_MATCHES(start))
1291 while (start < MAXWIN && (!wtab[start] || !WTAB_GROUP_MATCHES(start)))
1292 if (wlistdata->order != WLIST_MRU)
1293 start++;
1294 else if (wtab[start]->w_next)
1295 start = wtab[start]->w_next->w_number;
1296 else
1297 start = MAXWIN;
1298 if (start >= MAXWIN || !wtab[start])
1299 return ind;
1302 wlistdata->list[ind++] = start;
1303 if (wlistdata->nested && wtab[start]->w_type == W_TYPE_GROUP)
1304 ind = WListOrder(wlistdata, ind, -1, wtab[start]);
1306 if (wlistdata->order != WLIST_MRU)
1307 start++;
1308 else if (wtab[start]->w_next)
1309 start = wtab[start]->w_next->w_number;
1310 else
1311 return ind;
1312 return WListOrder(wlistdata, ind, start, group);
1315 void
1316 display_wlist(onblank, order, group)
1317 int onblank;
1318 int order;
1319 struct win *group;
1321 struct win *p;
1322 struct wlistdata *wlistdata;
1324 if (flayer->l_width < 10 || flayer->l_height < 6)
1326 LMsg(0, "Window size too small for window list page");
1327 return;
1329 if (onblank)
1331 debug3("flayer %x %d %x\n", flayer, flayer->l_width, flayer->l_height);
1332 if (!display)
1334 LMsg(0, "windowlist -b: display required");
1335 return;
1337 p = D_fore;
1338 if (p)
1340 SetForeWindow((struct win *)0);
1341 if (p->w_group)
1343 D_fore = p->w_group;
1344 flayer->l_data = (char *)p->w_group;
1346 Activate(0);
1348 if (flayer->l_width < 10 || flayer->l_height < 6)
1350 LMsg(0, "Window size too small for window list page");
1351 return;
1354 else
1355 p = Layer2Window(flayer);
1356 if (!group && p)
1357 group = p->w_group;
1358 if (InitOverlayPage(sizeof(*wlistdata), &WListLf, 0))
1359 return;
1360 wlistdata = (struct wlistdata *)flayer->l_data;
1361 flayer->l_x = 0;
1362 flayer->l_y = flayer->l_height - 1;
1363 wlistdata->start = onblank && p ? p->w_number : -1;
1364 wlistdata->order = (order & 0x1);
1365 wlistdata->group = group;
1366 wlistdata->pos = p ? p->w_number : WListNext(wlistdata, -1, 0);
1367 wlistdata->ypos = wlistdata->npos = 0;
1368 wlistdata->numwin = flayer->l_height - (group ? 4 : 3);
1369 wlistdata->nested = (order & WLIST_NESTED);
1370 wlistpage();
1373 static void
1374 wlistpage()
1376 struct wlistdata *wlistdata;
1377 char *str;
1378 int pos;
1379 struct win *group;
1381 wlistdata = (struct wlistdata *)flayer->l_data;
1382 group = wlistdata->group;
1384 LClearAll(flayer, 0);
1385 if (wlistdata->start >= 0 && wtab[wlistdata->start] == 0)
1386 wlistdata->start = -2;
1388 WListOrder(wlistdata, 0, -1, group);
1389 pos = wlistdata->pos;
1390 if (pos == MAXWIN || !wtab[pos] || !WTAB_GROUP_MATCHES(pos))
1392 if (wlistdata->order == WLIST_MRU)
1393 pos = WListNext(wlistdata, -1, wlistdata->npos);
1394 else
1396 /* find new position */
1397 if (pos < MAXWIN)
1398 while(++pos < MAXWIN)
1399 if (wtab[pos] && WTAB_GROUP_MATCHES(pos))
1400 break;
1401 if (pos == MAXWIN)
1402 while (--pos >= 0)
1403 if (wtab[pos] && WTAB_GROUP_MATCHES(pos))
1404 break;
1405 if (pos == -1)
1406 pos = MAXWIN;
1409 wlistdata->pos = pos;
1411 display = 0;
1412 str = MakeWinMsgEv(wlisttit, (struct win *)0, '%', flayer->l_width, (struct event *)0, 0);
1413 if (wlistdata->group)
1415 LPutWinMsg(flayer, "Group: ", 7, &mchar_blank, 0, 0);
1416 LPutWinMsg(flayer, wlistdata->group->w_title, strlen(wlistdata->group->w_title), &mchar_blank, 7, 0);
1417 LPutWinMsg(flayer, str, strlen(str), &mchar_blank, 0, 1);
1419 else
1421 LPutWinMsg(flayer, str, strlen(str), &mchar_blank, 0, 0);
1423 WListNormalize();
1424 WListLines(wlistdata->numwin, -1);
1425 LaySetCursor();
1428 static void
1429 WListUpdate(p)
1430 struct win *p;
1432 struct wlistdata *wlistdata;
1433 int i, n, y;
1435 if (p == 0)
1437 wlistpage();
1438 return;
1440 wlistdata = (struct wlistdata *)flayer->l_data;
1441 n = p->w_number;
1442 if (wlistdata->order == WLIST_NUM && (n < wlistdata->first || n > wlistdata->last))
1443 return;
1444 i = wlistdata->first;
1445 for (y = 0; y < wlistdata->numwin; y++)
1447 if (i == n)
1448 break;
1449 i = WListNext(wlistdata, i, 1);
1451 if (y == wlistdata->numwin)
1452 return;
1453 WListLine(y, i, wlistdata->pos, 0);
1454 LaySetCursor();
1457 void
1458 WListUpdatecv(cv, p)
1459 struct canvas *cv;
1460 struct win *p;
1462 if (cv->c_layer->l_layfn != &WListLf)
1463 return;
1464 CV_CALL(cv, WListUpdate(p));
1467 void
1468 WListLinkChanged()
1470 struct display *olddisplay = display;
1471 struct canvas *cv;
1472 struct wlistdata *wlistdata;
1474 for (display = displays; display; display = display->d_next)
1475 for (cv = D_cvlist; cv; cv = cv->c_next)
1477 if (!cv->c_layer || cv->c_layer->l_layfn != &WListLf)
1478 continue;
1479 wlistdata = (struct wlistdata *)cv->c_layer->l_data;
1480 if (wlistdata->order != WLIST_MRU)
1481 continue;
1482 CV_CALL(cv, WListUpdate(0));
1484 display = olddisplay;
1488 InWList()
1490 if (flayer && flayer->l_layfn == &WListLf)
1491 return 1;
1492 return 0;
1499 ** The bindkey help page
1503 #ifdef MAPKEYS
1504 extern struct kmap_ext *kmap_exts;
1505 extern int kmap_extn;
1506 extern struct action dmtab[];
1507 extern struct action mmtab[];
1510 static void BindkeyProcess __P((char **, int *));
1511 static void BindkeyAbort __P((void));
1512 static void BindkeyRedisplayLine __P((int, int, int, int));
1513 static void bindkeypage __P((void));
1515 struct bindkeydata
1517 char *title;
1518 struct action *tab;
1519 int pos;
1520 int last;
1521 int page;
1522 int pages;
1525 static struct LayFuncs BindkeyLf =
1527 BindkeyProcess,
1528 BindkeyAbort,
1529 BindkeyRedisplayLine,
1530 DefClearLine,
1531 DefRewrite,
1532 DefResize,
1533 DefRestore
1537 void
1538 display_bindkey(title, tab)
1539 char *title;
1540 struct action *tab;
1542 struct bindkeydata *bindkeydata;
1543 int i, n;
1545 if (flayer->l_height < 6)
1547 LMsg(0, "Window height too small for bindkey page");
1548 return;
1550 if (InitOverlayPage(sizeof(*bindkeydata), &BindkeyLf, 0))
1551 return;
1553 bindkeydata = (struct bindkeydata *)flayer->l_data;
1554 bindkeydata->title = title;
1555 bindkeydata->tab = tab;
1557 n = 0;
1558 for (i = 0; i < KMAP_KEYS+KMAP_AKEYS+kmap_extn; i++)
1560 if (tab[i].nr != RC_ILLEGAL)
1561 n++;
1563 bindkeydata->pos = 0;
1564 bindkeydata->page = 1;
1565 bindkeydata->pages = (n + flayer->l_height - 6) / (flayer->l_height - 5);
1566 if (bindkeydata->pages == 0)
1567 bindkeydata->pages = 1;
1568 flayer->l_x = 0;
1569 flayer->l_y = flayer->l_height - 1;
1570 bindkeypage();
1573 static void
1574 BindkeyAbort()
1576 LAY_CALL_UP(LRefreshAll(flayer, 0));
1577 ExitOverlayPage();
1580 static void
1581 bindkeypage()
1583 struct bindkeydata *bindkeydata;
1584 struct kmap_ext *kme;
1585 char tbuf[256];
1586 int del, i, y, sl;
1587 struct action *act;
1588 char *xch, *s, *p;
1590 bindkeydata = (struct bindkeydata *)flayer->l_data;
1592 LClearAll(flayer, 0);
1594 sprintf(tbuf, "%s key bindings, page %d of %d.", bindkeydata->title, bindkeydata->page, bindkeydata->pages);
1595 centerline(tbuf, 0);
1596 y = 2;
1597 for (i = bindkeydata->pos; i < KMAP_KEYS+KMAP_AKEYS+kmap_extn && y < flayer->l_height - 3; i++)
1599 p = tbuf;
1600 xch = " ";
1601 if (i < KMAP_KEYS)
1603 act = &bindkeydata->tab[i];
1604 if (act->nr == RC_ILLEGAL)
1605 continue;
1606 del = *p++ = ':';
1607 s = term[i + T_CAPS].tcname;
1608 sl = s ? strlen(s) : 0;
1610 else if (i < KMAP_KEYS+KMAP_AKEYS)
1612 act = &bindkeydata->tab[i];
1613 if (act->nr == RC_ILLEGAL)
1614 continue;
1615 del = *p++ = ':';
1616 s = term[i + (T_CAPS - T_OCAPS + T_CURSOR)].tcname;
1617 sl = s ? strlen(s) : 0;
1618 xch = "[A]";
1620 else
1622 kme = kmap_exts + (i - (KMAP_KEYS+KMAP_AKEYS));
1623 del = 0;
1624 s = kme->str;
1625 sl = kme->fl & ~KMAP_NOTIMEOUT;
1626 if ((kme->fl & KMAP_NOTIMEOUT) != 0)
1627 xch = "[T]";
1628 act = bindkeydata->tab == dmtab ? &kme->dm : bindkeydata->tab == mmtab ? &kme->mm : &kme->um;
1629 if (act->nr == RC_ILLEGAL)
1630 continue;
1632 while (sl-- > 0)
1633 p += AddXChar(p, *(unsigned char *)s++);
1634 if (del)
1635 *p++ = del;
1636 *p++ = ' ';
1637 while (p < tbuf + 15)
1638 *p++ = ' ';
1639 sprintf(p, "%s -> ", xch);
1640 p += 7;
1641 if (p - tbuf > flayer->l_width - 1)
1643 tbuf[flayer->l_width - 2] = '$';
1644 tbuf[flayer->l_width - 1] = 0;
1646 PadStr(tbuf, strlen(tbuf), 0, y);
1647 AddAction(act, strlen(tbuf), y);
1648 y++;
1650 y++;
1651 bindkeydata->last = i;
1652 sprintf(tbuf,"[Press Space %s Return to end.]", bindkeydata->page < bindkeydata->pages ? "for next page;" : "or");
1653 centerline(tbuf, flayer->l_height - 2);
1654 LaySetCursor();
1657 static void
1658 BindkeyProcess(ppbuf, plen)
1659 char **ppbuf;
1660 int *plen;
1662 int done = 0;
1663 struct bindkeydata *bindkeydata;
1665 bindkeydata = (struct bindkeydata *)flayer->l_data;
1666 while (!done && *plen > 0)
1668 switch (**ppbuf)
1670 case ' ':
1671 if (bindkeydata->page < bindkeydata->pages)
1673 bindkeydata->pos = bindkeydata->last;
1674 bindkeydata->page++;
1675 bindkeypage();
1676 break;
1678 /* FALLTHROUGH */
1679 case '\r':
1680 case '\n':
1681 done = 1;
1682 break;
1683 default:
1684 break;
1686 ++*ppbuf;
1687 --*plen;
1689 if (done)
1690 BindkeyAbort();
1693 static void
1694 BindkeyRedisplayLine(y, xs, xe, isblank)
1695 int y, xs, xe, isblank;
1697 if (y < 0)
1699 bindkeypage();
1700 return;
1702 if (y != 0 && y != flayer->l_height - 1)
1703 return;
1704 if (!isblank)
1705 LClearArea(flayer, xs, y, xe, y, 0, 0);
1708 #endif /* MAPKEYS */
1713 ** The zmodem active page
1717 #ifdef ZMODEM
1719 static void ZmodemRedisplayLine __P((int, int, int, int));
1720 static int ZmodemResize __P((int, int));
1722 static struct LayFuncs ZmodemLf =
1724 DefProcess,
1726 ZmodemRedisplayLine,
1727 DefClearLine,
1728 DefRewrite,
1729 ZmodemResize,
1730 DefRestore
1733 /*ARGSUSED*/
1734 static int
1735 ZmodemResize(wi, he)
1736 int wi, he;
1738 flayer->l_width = wi;
1739 flayer->l_height = he;
1740 flayer->l_x = flayer->l_width > 32 ? 32 : 0;
1741 return 0;
1744 static void
1745 ZmodemRedisplayLine(y, xs, xe, isblank)
1746 int y, xs, xe, isblank;
1748 DefRedisplayLine(y, xs, xe, isblank);
1749 if (y == 0 && xs == 0)
1750 LPutStr(flayer, "Zmodem active on another display", flayer->l_width > 32 ? 32 : flayer->l_width, &mchar_blank, 0, 0);
1753 void
1754 ZmodemPage()
1756 if (InitOverlayPage(1, &ZmodemLf, 1))
1757 return;
1758 LRefreshAll(flayer, 0);
1759 flayer->l_x = flayer->l_width > 32 ? 32 : 0;
1760 flayer->l_y = 0;
1763 #endif
1767 static void
1768 PadStr(str, n, x, y)
1769 char *str;
1770 int n, x, y;
1772 int l;
1774 l = strlen(str);
1775 if (l > n)
1776 l = n;
1777 LPutStr(flayer, str, l, &mchar_blank, x, y);
1778 if (l < n)
1779 LPutStr(flayer, (char *)blank, n - l, &mchar_blank, x + l, y);