Merge branch 'master' into cmd-alias
[screen-lua.git] / src / help.c
blobaa570fecaa02d22bec7a1dfbd413c83683e6925c
1 /* Copyright (c) 2008
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 unsigned char *blank;
44 extern struct win *wtab[];
45 #ifdef MAPKEYS
46 extern struct term term[];
47 #endif
49 static void PadStr __P((char *, int, int, int));
51 extern char *wliststr;
52 extern char *wlisttit;
54 void
55 exit_with_usage(myname, message, arg)
56 char *myname, *message, *arg;
58 printf("Use: %s [-opts] [cmd [args]]\n", myname);
59 printf(" or: %s -r [host.tty]\n\nOptions:\n", myname);
60 printf("-a Force all capabilities into each window's termcap.\n");
61 printf("-A -[r|R] Adapt all windows to the new display width & height.\n");
62 printf("-c file Read configuration file instead of '.screenrc'.\n");
63 #ifdef REMOTE_DETACH
64 printf("-d (-r) Detach the elsewhere running screen (and reattach here).\n");
65 printf("-dmS name Start as daemon: Screen session in detached mode.\n");
66 printf("-D (-r) Detach and logout remote (and reattach here).\n");
67 printf("-D -RR Do whatever is needed to get a screen session.\n");
68 #endif
69 printf("-e xy Change command characters.\n");
70 printf("-f Flow control on, -fn = off, -fa = auto.\n");
71 printf("-h lines Set the size of the scrollback history buffer.\n");
72 printf("-i Interrupt output sooner when flow control is on.\n");
73 #if defined(LOGOUTOK) && defined(UTMPOK)
74 printf("-l Login mode on (update %s), -ln = off.\n", UTMPFILE);
75 #endif
76 printf("-list or -ls. Do nothing, just list our SockDir.\n");
77 printf("-L Turn on output logging.\n");
78 printf("-m ignore $STY variable, do create a new screen session.\n");
79 printf("-O Choose optimal output rather than exact vt100 emulation.\n");
80 printf("-p window Preselect the named window if it exists.\n");
81 printf("-q Quiet startup. Exits with non-zero return code if unsuccessful.\n");
82 printf("-r Reattach to a detached screen process.\n");
83 printf("-R Reattach if possible, otherwise start a new session.\n");
84 printf("-s shell Shell to execute rather than $SHELL.\n");
85 printf("-S sockname Name this session <pid>.sockname instead of <pid>.<tty>.<host>.\n");
86 printf("-t title Set title. (window's name).\n");
87 printf("-T term Use term as $TERM for windows, rather than \"screen\".\n");
88 #ifdef UTF8
89 printf("-U Tell screen to use UTF-8 encoding.\n");
90 #endif
91 printf("-v Print \"Screen version %s\".\n", version);
92 printf("-wipe Do nothing, just clean up SockDir.\n");
93 #ifdef MULTI
94 printf("-x Attach to a not detached screen. (Multi display mode).\n");
95 #endif /* MULTI */
96 printf("-X Execute <cmd> as a screen command in the specified session.\n");
97 if (message && *message)
99 printf("\nError: ");
100 printf(message, arg);
101 printf("\n");
103 exit(1);
107 ** Here come the help page routines
110 extern struct comm comms[];
111 extern struct action ktab[];
113 static void HelpProcess __P((char **, int *));
114 static void HelpAbort __P((void));
115 static void HelpRedisplayLine __P((int, int, int, int));
116 static void add_key_to_buf __P((char *, int));
117 static void AddAction __P((struct action *, int, int));
118 static int helppage __P((void));
120 struct helpdata
122 char *class;
123 struct action *ktabp;
124 int maxrow, grow, numcols, numrows, num_names;
125 int numskip, numpages;
126 int command_search, command_bindings;
127 int refgrow, refcommand_search;
128 int inter, mcom, mkey;
129 int nact[RC_LAST + 1];
132 #define MAXKLEN 256
134 static struct LayFuncs HelpLf =
136 HelpProcess,
137 HelpAbort,
138 HelpRedisplayLine,
139 DefClearLine,
140 DefRewrite,
141 DefResize,
142 DefRestore
146 void
147 display_help(class, ktabp)
148 char *class;
149 struct action *ktabp;
151 int i, n, key, mcom, mkey, l;
152 struct helpdata *helpdata;
153 int used[RC_LAST + 1];
155 if (flayer->l_height < 6)
157 LMsg(0, "Window height too small for help page");
158 return;
160 if (InitOverlayPage(sizeof(*helpdata), &HelpLf, 0))
161 return;
163 helpdata = (struct helpdata *)flayer->l_data;
164 helpdata->class = class;
165 helpdata->ktabp = ktabp;
166 helpdata->num_names = helpdata->command_bindings = 0;
167 helpdata->command_search = 0;
168 for (n = 0; n <= RC_LAST; n++)
169 used[n] = 0;
170 mcom = 0;
171 mkey = 0;
172 for (key = 0; key < 256 + KMAP_KEYS; key++)
174 n = ktabp[key].nr;
175 if (n == RC_ILLEGAL || n > RC_LAST)
176 continue;
177 if (ktabp[key].args == noargs)
179 used[n] += (key <= ' ' || key == 0x7f) ? 3 :
180 (key > 0x7f) ? 5 : 2;
182 else
183 helpdata->command_bindings++;
185 for (n = i = 0; n <= RC_LAST; n++)
186 if (used[n])
188 l = strlen(comms[n].name);
189 if (l > mcom)
190 mcom = l;
191 if (used[n] > mkey)
192 mkey = used[n];
193 helpdata->nact[i++] = n;
195 debug1("help: %d commands bound to keys with no arguments\n", i);
196 debug2("mcom: %d mkey: %d\n", mcom, mkey);
197 helpdata->num_names = i;
199 if (mkey > MAXKLEN)
200 mkey = MAXKLEN;
201 helpdata->numcols = flayer->l_width / (mcom + mkey + 1);
202 if (helpdata->numcols == 0)
204 HelpAbort();
205 LMsg(0, "Width too small");
206 return;
208 helpdata->inter = (flayer->l_width - (mcom + mkey) * helpdata->numcols) / (helpdata->numcols + 1);
209 if (helpdata->inter <= 0)
210 helpdata->inter = 1;
211 debug1("inter: %d\n", helpdata->inter);
212 helpdata->mcom = mcom;
213 helpdata->mkey = mkey;
214 helpdata->numrows = (helpdata->num_names + helpdata->numcols - 1) / helpdata->numcols;
215 debug1("Numrows: %d\n", helpdata->numrows);
216 helpdata->numskip = flayer->l_height-5 - (2 + helpdata->numrows);
217 while (helpdata->numskip < 0)
218 helpdata->numskip += flayer->l_height-5;
219 helpdata->numskip %= flayer->l_height-5;
220 debug1("Numskip: %d\n", helpdata->numskip);
221 if (helpdata->numskip > flayer->l_height/3 || helpdata->numskip > helpdata->command_bindings)
222 helpdata->numskip = 1;
223 helpdata->maxrow = 2 + helpdata->numrows + helpdata->numskip + helpdata->command_bindings;
224 helpdata->grow = 0;
226 helpdata->numpages = (helpdata->maxrow + flayer->l_height-6) / (flayer->l_height-5);
227 flayer->l_x = 0;
228 flayer->l_y = flayer->l_height - 1;
229 helppage();
232 static void
233 HelpProcess(ppbuf, plen)
234 char **ppbuf;
235 int *plen;
237 int done = 0;
239 while (!done && *plen > 0)
241 switch (**ppbuf)
243 case ' ':
244 if (helppage() == 0)
245 break;
246 /* FALLTHROUGH */
247 case '\r':
248 case '\n':
249 done = 1;
250 break;
251 default:
252 break;
254 ++*ppbuf;
255 --*plen;
257 if (done)
258 HelpAbort();
261 static void
262 HelpAbort()
264 LAY_CALL_UP(LRefreshAll(flayer, 0));
265 ExitOverlayPage();
269 static int
270 helppage()
272 struct helpdata *helpdata;
273 int col, crow, n, key, x;
274 char buf[MAXKLEN], Esc_buf[5], cbuf[256];
275 struct action *ktabp;
277 helpdata = (struct helpdata *)flayer->l_data;
279 ktabp = helpdata->ktabp;
280 if (helpdata->grow >= helpdata->maxrow)
281 return -1;
282 helpdata->refgrow = helpdata->grow;
283 helpdata->refcommand_search = helpdata->command_search;
285 /* Clear the help screen */
286 LClearAll(flayer, 0);
288 sprintf(cbuf,"Screen key bindings, page %d of %d.", helpdata->grow / (flayer->l_height-5) + 1, helpdata->numpages);
289 centerline(cbuf, 0);
290 crow = 2;
292 *Esc_buf = '\0';
293 *buf = '\0';
294 /* XXX fix escape character */
295 if (flayer->l_cvlist && flayer->l_cvlist->c_display)
297 add_key_to_buf(buf, flayer->l_cvlist->c_display->d_user->u_MetaEsc);
298 add_key_to_buf(Esc_buf, flayer->l_cvlist->c_display->d_user->u_Esc);
300 else
302 strcpy(Esc_buf, "??");
303 strcpy(buf, "??");
306 for (; crow < flayer->l_height - 3; crow++)
308 if (helpdata->grow < 1)
310 if (ktabp == ktab)
311 sprintf(cbuf,"Command key: %s Literal %s: %s", Esc_buf, Esc_buf, buf);
312 else
313 sprintf(cbuf,"Command class: '%.80s'", helpdata->class);
314 centerline(cbuf, crow);
315 helpdata->grow++;
317 else if (helpdata->grow >= 2 && helpdata->grow-2 < helpdata->numrows)
319 x = 0;
320 for (col = 0; col < helpdata->numcols && (n = helpdata->numrows * col + (helpdata->grow-2)) < helpdata->num_names; col++)
322 x += helpdata->inter - !col;
323 n = helpdata->nact[n];
324 buf[0] = '\0';
325 for (key = 0; key < 256 + KMAP_KEYS; key++)
326 if (ktabp[key].nr == n && ktabp[key].args == noargs && strlen(buf) < sizeof(buf) - 7)
328 strcat(buf, " ");
329 add_key_to_buf(buf, key);
331 PadStr(comms[n].name, helpdata->mcom, x, crow);
332 x += helpdata->mcom;
333 PadStr(buf, helpdata->mkey, x, crow);
334 x += helpdata->mkey;
336 helpdata->grow++;
338 else if (helpdata->grow-2-helpdata->numrows >= helpdata->numskip
339 && helpdata->grow-2-helpdata->numrows-helpdata->numskip < helpdata->command_bindings)
341 while ((n = ktabp[helpdata->command_search].nr) == RC_ILLEGAL
342 || ktabp[helpdata->command_search].args == noargs)
344 if (++helpdata->command_search >= 256 + KMAP_KEYS)
345 return -1;
347 buf[0] = '\0';
348 add_key_to_buf(buf, helpdata->command_search);
349 PadStr(buf, 5, 0, crow);
350 AddAction(&ktabp[helpdata->command_search++], 5, crow);
351 helpdata->grow++;
353 else
354 helpdata->grow++;
356 sprintf(cbuf,"[Press Space %s Return to end.]",
357 helpdata->grow < helpdata->maxrow ? "for next page;" : "or");
358 centerline(cbuf, flayer->l_height - 2);
359 LaySetCursor();
360 return 0;
363 static void
364 AddAction(act, x, y)
365 struct action *act;
366 int x, y;
368 char buf[256];
369 int del, l;
370 char *bp, *cp, **pp;
371 int *lp, ll;
372 int fr;
373 struct mchar mchar_dol;
375 mchar_dol = mchar_blank;
376 mchar_dol.image = '$';
378 fr = flayer->l_width - 1 - x;
379 if (fr <= 0)
380 return;
381 l = strlen(comms[act->nr].name);
383 if (l + 1 > fr)
384 l = fr - 1;
385 PadStr(comms[act->nr].name, l, x, y);
386 x += l;
387 fr -= l + 1;
388 LPutChar(flayer, fr ? &mchar_blank : &mchar_dol, x++, y);
390 pp = act->args;
391 lp = act->argl;
392 while (pp && (cp = *pp) != NULL)
394 del = 0;
395 bp = buf;
396 ll = *lp++;
397 if (!ll || (index(cp, ' ') != NULL))
399 if (index(cp, '\'') != NULL)
400 *bp++ = del = '"';
401 else
402 *bp++ = del = '\'';
404 while (ll-- && bp < buf + 250)
405 bp += AddXChar(bp, *(unsigned char *)cp++);
406 if (del)
407 *bp++ = del;
408 *bp = 0;
409 if ((fr -= (bp - buf) + 1) < 0)
411 fr += bp - buf;
412 if (fr > 0)
413 PadStr(buf, fr, x, y);
414 if (fr == 0)
415 LPutChar(flayer, &mchar_dol, x, y);
416 return;
418 PadStr(buf, strlen(buf), x, y);
419 x += strlen(buf);
420 pp++;
421 if (*pp)
422 LPutChar(flayer, fr ? &mchar_blank : &mchar_dol, x++, y);
426 static void
427 add_key_to_buf(buf, key)
428 char *buf;
429 int key;
431 buf += strlen(buf);
432 if (key < 0)
433 strcpy(buf, "unset");
434 else if (key == ' ')
435 strcpy(buf, "sp");
436 #ifdef MAPKEYS
437 else if (key >= 256)
439 key = key - 256 + T_CAPS;
440 buf[0] = ':';
441 buf[1] = term[key].tcname[0];
442 buf[2] = term[key].tcname[1];
443 buf[3] = ':';
444 buf[4] = 0;
446 #endif
447 else
448 buf[AddXChar(buf, key)] = 0;
452 static void
453 HelpRedisplayLine(y, xs, xe, isblank)
454 int y, xs, xe, isblank;
456 if (y < 0)
458 struct helpdata *helpdata;
460 helpdata = (struct helpdata *)flayer->l_data;
461 helpdata->grow = helpdata->refgrow;
462 helpdata->command_search = helpdata->refcommand_search;
463 helppage();
464 return;
466 if (y != 0 && y != flayer->l_height - 1)
467 return;
468 if (!isblank)
469 LClearArea(flayer, xs, y, xe, y, 0, 0);
475 ** here is all the copyright stuff
479 static void CopyrightProcess __P((char **, int *));
480 static void CopyrightRedisplayLine __P((int, int, int, int));
481 static void CopyrightAbort __P((void));
482 static void copypage __P((void));
484 struct copydata
486 char *cps, *savedcps; /* position in the message */
487 char *refcps, *refsavedcps; /* backup for redisplaying */
490 static struct LayFuncs CopyrightLf =
492 CopyrightProcess,
493 CopyrightAbort,
494 CopyrightRedisplayLine,
495 DefClearLine,
496 DefRewrite,
497 DefResize,
498 DefRestore
501 static const char cpmsg[] = "\
503 Screen version %v\n\
505 Copyright (c) 2008 Juergen Weigert, Michael Schroeder, Micah Cowan, Sadrul Habib Chowdhury\n\
506 Copyright (c) 1993-2002, 2003, 2005, 2006, 2007 Juergen Weigert, Michael Schroeder\n\
507 Copyright (c) 1987 Oliver Laumann\n\
509 This program is free software; you can redistribute it and/or \
510 modify it under the terms of the GNU General Public License as published \
511 by the Free Software Foundation; either version 3, or (at your option) \
512 any later version.\n\
514 This program is distributed in the hope that it will be useful, \
515 but WITHOUT ANY WARRANTY; without even the implied warranty of \
516 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the \
517 GNU General Public License for more details.\n\
519 You should have received a copy of the GNU General Public License \
520 along with this program (see the file COPYING); if not, see \
521 http://www.gnu.org/licenses/, or contact Free Software Foundation, Inc., \
522 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA.\n\
524 Send bugreports, fixes, enhancements, t-shirts, money, beer & pizza to \
525 screen@uni-erlangen.de\n";
528 static void
529 CopyrightProcess(ppbuf, plen)
530 char **ppbuf;
531 int *plen;
533 int done = 0;
534 struct copydata *copydata;
536 copydata = (struct copydata *)flayer->l_data;
537 while (!done && *plen > 0)
539 switch (**ppbuf)
541 case ' ':
542 if (*copydata->cps)
544 copypage();
545 break;
547 /* FALLTHROUGH */
548 case '\r':
549 case '\n':
550 CopyrightAbort();
551 done = 1;
552 break;
553 default:
554 break;
556 ++*ppbuf;
557 --*plen;
561 static void
562 CopyrightAbort()
564 LAY_CALL_UP(LRefreshAll(flayer, 0));
565 ExitOverlayPage();
568 void
569 display_copyright()
571 struct copydata *copydata;
573 if (flayer->l_width < 10 || flayer->l_height < 5)
575 LMsg(0, "Window size too small for copyright page");
576 return;
578 if (InitOverlayPage(sizeof(*copydata), &CopyrightLf, 0))
579 return;
580 copydata = (struct copydata *)flayer->l_data;
581 copydata->cps = (char *)cpmsg;
582 copydata->savedcps = 0;
583 flayer->l_x = 0;
584 flayer->l_y = flayer->l_height - 1;
585 copypage();
588 static void
589 copypage()
591 register char *cps;
592 char *ws;
593 int x, y, l;
594 char cbuf[80];
595 struct copydata *copydata;
597 ASSERT(flayer);
598 copydata = (struct copydata *)flayer->l_data;
600 LClearAll(flayer, 0);
601 x = y = 0;
602 cps = copydata->cps;
603 copydata->refcps = cps;
604 copydata->refsavedcps = copydata->savedcps;
605 while (*cps && y < flayer->l_height - 3)
607 ws = cps;
608 while (*cps == ' ')
609 cps++;
610 if (strncmp(cps, "%v", 2) == 0)
612 copydata->savedcps = cps + 2;
613 cps = version;
614 continue;
616 while (*cps && *cps != ' ' && *cps != '\n')
617 cps++;
618 l = cps - ws;
619 cps = ws;
620 if (l > flayer->l_width - 1)
621 l = flayer->l_width - 1;
622 if (x && x + l >= flayer->l_width - 2)
624 x = 0;
625 y++;
626 continue;
628 if (x)
630 LPutChar(flayer, &mchar_blank, x, y);
631 x++;
633 if (l)
634 LPutStr(flayer, ws, l, &mchar_blank, x, y);
635 x += l;
636 cps += l;
637 if (*cps == 0 && copydata->savedcps)
639 cps = copydata->savedcps;
640 copydata->savedcps = 0;
642 if (*cps == '\n')
644 x = 0;
645 y++;
647 if (*cps == ' ' || *cps == '\n')
648 cps++;
650 while (*cps == '\n')
651 cps++;
652 sprintf(cbuf,"[Press Space %s Return to end.]",
653 *cps ? "for next page;" : "or");
654 centerline(cbuf, flayer->l_height - 2);
655 copydata->cps = cps;
656 LaySetCursor();
659 static void
660 CopyrightRedisplayLine(y, xs, xe, isblank)
661 int y, xs, xe, isblank;
663 ASSERT(flayer);
664 if (y < 0)
666 struct copydata *copydata;
668 copydata = (struct copydata *)flayer->l_data;
669 copydata->cps = copydata->refcps;
670 copydata->savedcps = copydata->refsavedcps;
671 copypage();
672 return;
674 if (y != 0 && y != flayer->l_height - 1)
675 return;
676 if (isblank)
677 return;
678 LClearArea(flayer, xs, y, xe, y, 0, 0);
685 ** here is all the displays stuff
689 #ifdef MULTI
691 static void DisplaysProcess __P((char **, int *));
692 static void DisplaysRedisplayLine __P((int, int, int, int));
693 static void displayspage __P((void));
695 struct displaysdata
697 int dummy_element_for_solaris;
700 static struct LayFuncs DisplaysLf =
702 DisplaysProcess,
703 HelpAbort,
704 DisplaysRedisplayLine,
705 DefClearLine,
706 DefRewrite,
707 DefResize,
708 DefRestore
711 static void
712 DisplaysProcess(ppbuf, plen)
713 char **ppbuf;
714 int *plen;
716 int done = 0;
718 ASSERT(flayer);
719 while (!done && *plen > 0)
721 switch (**ppbuf)
723 case ' ':
724 displayspage();
725 break;
726 case '\r':
727 case '\n':
728 HelpAbort();
729 done = 1;
730 break;
731 default:
732 break;
734 ++*ppbuf;
735 --*plen;
740 void
741 display_displays()
743 if (flayer->l_width < 10 || flayer->l_height < 5)
745 LMsg(0, "Window size too small for displays page");
746 return;
748 if (InitOverlayPage(sizeof(struct displaysdata), &DisplaysLf, 0))
749 return;
750 flayer->l_x = 0;
751 flayer->l_y = flayer->l_height - 1;
752 displayspage();
756 * layout of the displays page is as follows:
758 xterm 80x42 jnweiger@/dev/ttyp4 0(m11) &rWx
759 facit 80x24 nb mlschroe@/dev/ttyhf 11(tcsh) rwx
760 xterm 80x42 jnhollma@/dev/ttyp5 0(m11) &R.x
762 | | | | | | | | ¦___ window permissions
763 | | | | | | | | (R. is locked r-only,
764 | | | | | | | | W has wlock)
765 | | | | | | | |___ Window is shared
766 | | | | | | |___ Name/Title of window
767 | | | | | |___ Number of window
768 | | | | |___ Name of the display (the attached device)
769 | | | |___ Username who is logged in at the display
770 | | |___ Display is in nonblocking mode. Shows 'NB' if obuf is full.
771 | |___ Displays geometry as width x height.
772 |___ the terminal type known by screen for this display.
776 static void
777 displayspage()
779 int y, l;
780 char tbuf[80];
781 struct display *d;
782 struct win *w;
783 static char *blockstates[5] = {"nb", "NB", "Z<", "Z>", "BL"};
785 LClearAll(flayer, 0);
787 leftline("term-type size user interface window", 0);
788 leftline("---------- ------- ---------- ----------------- ----------", 1);
789 y = 2;
791 for (d = displays; d; d = d->d_next)
793 w = d->d_fore;
795 if (y >= flayer->l_height - 3)
796 break;
797 sprintf(tbuf, "%-10.10s%4dx%-4d%10.10s@%-16.16s%s",
798 d->d_termname, d->d_width, d->d_height, d->d_user->u_name,
799 d->d_usertty,
800 (d->d_blocked || d->d_nonblock >= 0) && d->d_blocked <= 4 ? blockstates[d->d_blocked] : " ");
802 if (w)
804 l = 10 - strlen(w->w_title);
805 if (l < 0)
806 l = 0;
807 sprintf(tbuf + strlen(tbuf), "%3d(%.10s)%*s%c%c%c%c",
808 w->w_number, w->w_title, l, "",
809 /* w->w_dlist->next */ 0 ? '&' : ' ',
811 * The rwx triple:
812 * -,r,R no read, read, read only due to foreign wlock
813 * -,.,w,W no write, write suppressed by foreign wlock,
814 * write, own wlock
815 * -,x no execute, execute
817 #ifdef MULTIUSER
818 (AclCheckPermWin(d->d_user, ACL_READ, w) ? '-' :
819 ((w->w_wlock == WLOCK_OFF || d->d_user == w->w_wlockuser) ?
820 'r' : 'R')),
821 (AclCheckPermWin(d->d_user, ACL_READ, w) ? '-' :
822 ((w->w_wlock == WLOCK_OFF) ? 'w' :
823 ((d->d_user == w->w_wlockuser) ? 'W' : 'v'))),
824 (AclCheckPermWin(d->d_user, ACL_READ, w) ? '-' : 'x')
825 #else
826 'r', 'w', 'x'
827 #endif
830 leftline(tbuf, y);
831 y++;
833 sprintf(tbuf,"[Press Space %s Return to end.]",
834 1 ? "to refresh;" : "or");
835 centerline(tbuf, flayer->l_height - 2);
836 LaySetCursor();
839 static void
840 DisplaysRedisplayLine(y, xs, xe, isblank)
841 int y, xs, xe, isblank;
843 ASSERT(flayer);
844 if (y < 0)
846 displayspage();
847 return;
849 if (y != 0 && y != flayer->l_height - 1)
850 return;
851 if (isblank)
852 return;
853 LClearArea(flayer, xs, y, xe, y, 0, 0);
854 /* To be filled in... */
857 #endif /* MULTI */
862 ** here is the windowlist
866 struct wlistdata;
868 static void WListProcess __P((char **, int *));
869 static void WListRedisplayLine __P((int, int, int, int));
870 static void wlistpage __P((void));
871 static void WListLine __P((int, int, int, int));
872 static void WListLines __P((int, int));
873 static void WListMove __P((int, int));
874 static void WListUpdate __P((struct win *));
875 static int WListNormalize __P((void));
876 static int WListResize __P((int, int));
877 static int WListNext __P((struct wlistdata *, int, int));
879 struct wlistdata {
880 int pos;
881 int ypos;
882 int npos;
883 int numwin;
884 int first;
885 int last;
886 int start;
887 int order;
888 struct win *group;
889 int nested;
890 int list[MAXWIN];
893 static struct LayFuncs WListLf =
895 WListProcess,
896 HelpAbort,
897 WListRedisplayLine,
898 DefClearLine,
899 DefRewrite,
900 WListResize,
901 DefRestore
904 #define WTAB_GROUP_MATCHES(i) (group == wtab[i]->w_group)
906 static int
907 WListResize(wi, he)
908 int wi, he;
910 struct wlistdata *wlistdata;
911 if (wi < 10 || he < 5)
912 return -1;
913 wlistdata = (struct wlistdata *)flayer->l_data;
914 flayer->l_width = wi;
915 flayer->l_height = he;
916 wlistdata->numwin = he - 3;
917 if (wlistdata->ypos >= wlistdata->numwin)
918 wlistdata->ypos = wlistdata->numwin - 1;
919 flayer->l_y = he - 1;
920 return 0;
923 static void
924 WListProcess(ppbuf, plen)
925 char **ppbuf;
926 int *plen;
928 int done = 0;
929 struct wlistdata *wlistdata;
930 struct display *olddisplay = display;
931 int h;
932 struct win *group;
934 ASSERT(flayer);
935 wlistdata = (struct wlistdata *)flayer->l_data;
936 group = wlistdata->group;
937 h = wlistdata->numwin;
938 while (!done && *plen > 0)
940 if ((unsigned char)**ppbuf >= '0' && (unsigned char)**ppbuf <= '9')
942 int n = (unsigned char)**ppbuf - '0';
943 int d = 0;
944 if (n < MAXWIN && wtab[n] && WTAB_GROUP_MATCHES(n))
946 int i;
947 for (d = -wlistdata->npos, i = WListNext(wlistdata, -1, 0); i != n; i = WListNext(wlistdata, i, 1), d++)
950 if (d)
951 WListMove(d, -1);
953 switch ((unsigned char)**ppbuf)
955 case 0220: /* up */
956 case 16: /* ^P like emacs */
957 case 'k':
958 WListMove(-1, -1);
959 break;
960 case 0216: /* down */
961 case 14: /* ^N like emacs */
962 case 'j':
963 WListMove(1, -1);
964 break;
965 case '\025':
966 WListMove(-(h / 2), wlistdata->ypos);
967 break;
968 case '\004':
969 WListMove(h / 2, wlistdata->ypos);
970 break;
971 case 0002:
972 case 'b':
973 WListMove(-h, -1);
974 break;
975 case 0006:
976 case 'f':
977 WListMove(h, -1);
978 break;
979 case 0201: /* home */
980 WListMove(-wlistdata->pos, -1);
981 break;
982 case 0205: /* end */
983 WListMove(MAXWIN, -1);
984 break;
985 case 'a':
986 /* All-window view */
987 wlistdata->group = 0;
988 wlistdata->nested = WLIST_NESTED;
989 wlistpage();
990 break;
991 case 'g':
992 /* Toggle nested view */
993 wlistdata->nested ^= WLIST_NESTED;
994 wlistpage();
995 break;
996 case 'm':
997 /* Toggle MRU view */
998 wlistdata->order ^= 1;
999 wlistpage();
1000 break;
1001 case '\r':
1002 case '\n':
1003 case ' ':
1004 h = wlistdata->pos;
1005 if (h == MAXWIN && Layer2Window(flayer) && Layer2Window(flayer)->w_type == W_TYPE_GROUP)
1006 break;
1007 if (display && h != MAXWIN && wtab[h] && (wtab[h]->w_type == W_TYPE_GROUP || wtab[h] == D_fore))
1009 wlistdata->group = wtab[h];
1010 wlistdata->pos = wtab[h]->w_number;
1011 wlistpage();
1012 break;
1014 done = 1;
1015 if (!display || h == MAXWIN || !wtab[h] || wtab[h] == D_fore || (flayer->l_cvlist && flayer->l_cvlist->c_lnext))
1016 HelpAbort();
1017 #ifdef MULTIUSER
1018 else if (AclCheckPermWin(D_user, ACL_READ, wtab[h]))
1019 HelpAbort();
1020 #endif
1021 else
1022 ExitOverlayPage(); /* no need to redisplay */
1023 /* restore display, don't switch wrong user */
1024 display = olddisplay;
1025 if (h != MAXWIN)
1026 SwitchWindow(h);
1027 break;
1028 case 0033:
1029 case 0007:
1030 h = wlistdata->start;
1031 if (h == -1 && Layer2Window(flayer) && Layer2Window(flayer)->w_type == W_TYPE_GROUP)
1033 struct win *p = Layer2Window(flayer);
1034 if (wlistdata->group != p)
1036 wlistdata->group = p;
1037 wlistpage();
1039 break;
1041 HelpAbort();
1042 display = olddisplay;
1043 if (h >= 0 && wtab[h])
1044 SwitchWindow(h);
1045 else if (h == -2)
1047 struct win *p = FindNiceWindow(display ? D_other : (struct win *)0, 0);
1048 if (p)
1049 SwitchWindow(p->w_number);
1051 done = 1;
1052 break;
1053 case '\010': /* ctrl-h */
1054 case 0177:
1055 if (!wlistdata->group)
1056 break;
1057 wlistdata->pos = wlistdata->group->w_number;
1058 wlistdata->group = wlistdata->group->w_group;
1059 if (wlistdata->group)
1060 wlistdata->pos = wlistdata->group->w_number;
1061 wlistpage();
1062 break;
1063 default:
1064 break;
1066 ++*ppbuf;
1067 --*plen;
1071 static void
1072 WListLine(y, i, pos, isblank)
1073 int y, i;
1074 int pos;
1075 int isblank;
1077 char *str;
1078 int n;
1079 int yoff, xoff = 0;
1080 struct wlistdata *wlistdata;
1081 struct win *group;
1083 if (i == MAXWIN)
1084 return;
1085 wlistdata = (struct wlistdata *)flayer->l_data;
1086 if (wlistdata->nested && wtab[i])
1087 for (group = wtab[i]->w_group, xoff = 0; group != wlistdata->group;
1088 group = group->w_group, xoff += 2)
1090 yoff = wlistdata->group ? 3 : 2;
1091 display = Layer2Window(flayer) ? 0 : flayer->l_cvlist ? flayer->l_cvlist->c_display : 0;
1092 str = MakeWinMsgEv(wliststr, wtab[i], '%', flayer->l_width - xoff, (struct event *)0, 0);
1093 n = strlen(str);
1094 if (i != pos && isblank)
1095 while (n && str[n - 1] == ' ')
1096 n--;
1097 LPutWinMsg(flayer, str, (i == pos || !isblank) ? flayer->l_width : n, i == pos ? &mchar_so : &mchar_blank, xoff, y + yoff);
1098 if (xoff)
1099 LPutWinMsg(flayer, "", xoff, i == pos ? &mchar_so : &mchar_blank, 0, y + yoff);
1100 #if 0
1101 LPutStr(flayer, str, n, i == pos ? &mchar_so : &mchar_blank, 0, y + yoff);
1102 if (i == pos || !isblank)
1103 while(n < flayer->l_width)
1104 LPutChar(flayer, i == pos ? &mchar_so : &mchar_blank, n++, y + yoff);
1105 #endif
1106 return;
1110 static int
1111 WListNext(wlistdata, old, delta)
1112 struct wlistdata *wlistdata;
1113 int old, delta;
1115 int i;
1117 if (old == MAXWIN)
1118 return MAXWIN;
1119 if (old == -1)
1120 old = 0;
1121 else
1123 for (i = 0; i < MAXWIN && wlistdata->list[i] != -1; i++)
1124 if (wlistdata->list[i] == old)
1125 break;
1126 if (i < MAXWIN && wlistdata->list[i] != -1)
1127 old = i;
1130 old += delta;
1131 if (old < 0 || old >= MAXWIN || wlistdata->list[old] == -1)
1132 old -= delta;
1133 return wlistdata->list[old];
1136 static void
1137 WListLines(up, oldpos)
1138 int up, oldpos;
1140 struct wlistdata *wlistdata;
1141 int ypos, pos;
1142 int y, i, oldi;
1144 wlistdata = (struct wlistdata *)flayer->l_data;
1145 ypos = wlistdata->ypos;
1146 pos = wlistdata->pos;
1148 i = WListNext(wlistdata, pos, -ypos);
1149 for (y = 0; y < wlistdata->numwin; y++)
1151 if (i == MAXWIN || !wtab[i])
1152 return;
1153 if (y == 0)
1154 wlistdata->first = i;
1155 wlistdata->last = i;
1156 if (((i == oldpos || i == pos) && pos != oldpos) || (up > 0 && y >= wlistdata->numwin - up) || (up < 0 && y < -up))
1157 WListLine(y, i, pos, i != oldpos);
1158 if (i == pos)
1159 wlistdata->ypos = y;
1160 oldi = i;
1161 i = WListNext(wlistdata, i, 1);
1162 if (i == MAXWIN || i == oldi)
1163 break;
1167 static int
1168 WListNormalize()
1170 struct wlistdata *wlistdata;
1171 int i, oldi, n;
1172 int ypos, pos;
1174 wlistdata = (struct wlistdata *)flayer->l_data;
1175 ypos = wlistdata->ypos;
1176 pos = wlistdata->pos;
1177 if (ypos < 0)
1178 ypos = 0;
1179 if (ypos >= wlistdata->numwin)
1180 ypos = wlistdata->numwin - 1;
1181 for (n = 0, oldi = MAXWIN, i = pos; i != MAXWIN && i != oldi && n < wlistdata->numwin; oldi = i, i = WListNext(wlistdata, i, 1))
1182 n++;
1183 if (ypos < wlistdata->numwin - n)
1184 ypos = wlistdata->numwin - n;
1185 for (n = 0, oldi = MAXWIN, i = WListNext(wlistdata, -1, 0); i != MAXWIN && i != oldi && i != pos; oldi = i, i = WListNext(wlistdata, i, 1))
1186 n++;
1187 if (ypos > n)
1188 ypos = n;
1189 wlistdata->ypos = ypos;
1190 wlistdata->npos = n;
1191 return ypos;
1194 static void
1195 WListMove(num, ypos)
1196 int num;
1197 int ypos;
1199 struct wlistdata *wlistdata;
1200 int oldpos, oldypos, oldnpos;
1201 int pos, up;
1203 wlistdata = (struct wlistdata *)flayer->l_data;
1204 oldpos = wlistdata->pos;
1205 oldypos = wlistdata->ypos;
1206 oldnpos = wlistdata->npos;
1207 wlistdata->ypos = ypos == -1 ? oldypos + num : ypos;
1208 pos = WListNext(wlistdata, oldpos, num);
1209 wlistdata->pos = pos;
1210 ypos = WListNormalize();
1211 up = wlistdata->npos - ypos - (oldnpos - oldypos);
1212 if (up)
1214 LScrollV(flayer, up, 2, 2 + wlistdata->numwin - 1, 0);
1215 WListLines(up, oldpos);
1216 LaySetCursor();
1217 return;
1219 if (pos == oldpos)
1220 return;
1221 WListLine(oldypos, oldpos, pos, 0);
1222 WListLine(ypos, pos, pos, 1);
1223 LaySetCursor();
1226 static void
1227 WListRedisplayLine(y, xs, xe, isblank)
1228 int y, xs, xe, isblank;
1230 ASSERT(flayer);
1231 if (y < 0)
1233 wlistpage();
1234 return;
1236 if (y != 0 && y != flayer->l_height - 1)
1237 return;
1238 if (!isblank)
1239 LClearArea(flayer, xs, y, xe, y, 0, 0);
1242 static int
1243 WListOrder(wlistdata, ind, start, group)
1244 struct wlistdata *wlistdata;
1245 int ind, start;
1246 struct win *group;
1248 int i;
1250 if (ind >= MAXWIN)
1251 return ind;
1252 if (ind == 0)
1253 for (i = 0; i < MAXWIN; i++)
1254 wlistdata->list[i] = -1;
1256 if (wlistdata->order == WLIST_MRU)
1258 if (start == -1)
1259 start = windows->w_number;
1261 else
1263 if (start == -1)
1264 start = 0;
1265 while (start < MAXWIN && !wtab[start])
1266 start++;
1269 if (start >= MAXWIN || !wtab[start])
1270 return ind;
1272 if (!WTAB_GROUP_MATCHES(start))
1274 while (start < MAXWIN && (!wtab[start] || !WTAB_GROUP_MATCHES(start)))
1275 if (wlistdata->order != WLIST_MRU)
1276 start++;
1277 else if (wtab[start]->w_next)
1278 start = wtab[start]->w_next->w_number;
1279 else
1280 start = MAXWIN;
1281 if (start >= MAXWIN || !wtab[start])
1282 return ind;
1285 wlistdata->list[ind++] = start;
1286 if (wlistdata->nested && wtab[start]->w_type == W_TYPE_GROUP)
1287 ind = WListOrder(wlistdata, ind, -1, wtab[start]);
1289 if (wlistdata->order != WLIST_MRU)
1290 start++;
1291 else if (wtab[start]->w_next)
1292 start = wtab[start]->w_next->w_number;
1293 else
1294 return ind;
1295 return WListOrder(wlistdata, ind, start, group);
1298 void
1299 display_wlist(onblank, order, group)
1300 int onblank;
1301 int order;
1302 struct win *group;
1304 struct win *p;
1305 struct wlistdata *wlistdata;
1307 if (flayer->l_width < 10 || flayer->l_height < 6)
1309 LMsg(0, "Window size too small for window list page");
1310 return;
1312 if (onblank)
1314 debug3("flayer %x %d %x\n", flayer, flayer->l_width, flayer->l_height);
1315 if (!display)
1317 LMsg(0, "windowlist -b: display required");
1318 return;
1320 p = D_fore;
1321 if (p)
1323 SetForeWindow((struct win *)0);
1324 if (p->w_group)
1326 D_fore = p->w_group;
1327 flayer->l_data = (char *)p->w_group;
1329 Activate(0);
1331 if (flayer->l_width < 10 || flayer->l_height < 6)
1333 LMsg(0, "Window size too small for window list page");
1334 return;
1337 else
1338 p = Layer2Window(flayer);
1339 if (!group && p)
1340 group = p->w_group;
1341 if (InitOverlayPage(sizeof(*wlistdata), &WListLf, 0))
1342 return;
1343 wlistdata = (struct wlistdata *)flayer->l_data;
1344 flayer->l_x = 0;
1345 flayer->l_y = flayer->l_height - 1;
1346 wlistdata->start = onblank && p ? p->w_number : -1;
1347 wlistdata->order = (order & 0x1);
1348 wlistdata->group = group;
1349 wlistdata->pos = p ? p->w_number : WListNext(wlistdata, -1, 0);
1350 wlistdata->ypos = wlistdata->npos = 0;
1351 wlistdata->numwin = flayer->l_height - (group ? 4 : 3);
1352 wlistdata->nested = (order & WLIST_NESTED);
1353 wlistpage();
1356 static void
1357 wlistpage()
1359 struct wlistdata *wlistdata;
1360 char *str;
1361 int pos;
1362 struct win *group;
1364 wlistdata = (struct wlistdata *)flayer->l_data;
1365 group = wlistdata->group;
1367 LClearAll(flayer, 0);
1368 if (wlistdata->start >= 0 && wtab[wlistdata->start] == 0)
1369 wlistdata->start = -2;
1371 WListOrder(wlistdata, 0, -1, group);
1372 pos = wlistdata->pos;
1373 if (pos == MAXWIN || !wtab[pos] || !WTAB_GROUP_MATCHES(pos))
1375 if (wlistdata->order == WLIST_MRU)
1376 pos = WListNext(wlistdata, -1, wlistdata->npos);
1377 else
1379 /* find new position */
1380 if (pos < MAXWIN)
1381 while(++pos < MAXWIN)
1382 if (wtab[pos] && WTAB_GROUP_MATCHES(pos))
1383 break;
1384 if (pos == MAXWIN)
1385 while (--pos >= 0)
1386 if (wtab[pos] && WTAB_GROUP_MATCHES(pos))
1387 break;
1388 if (pos == -1)
1389 pos = MAXWIN;
1392 wlistdata->pos = pos;
1394 display = 0;
1395 str = MakeWinMsgEv(wlisttit, (struct win *)0, '%', flayer->l_width, (struct event *)0, 0);
1396 if (wlistdata->group)
1398 LPutWinMsg(flayer, "Group: ", 7, &mchar_blank, 0, 0);
1399 LPutWinMsg(flayer, wlistdata->group->w_title, strlen(wlistdata->group->w_title), &mchar_blank, 7, 0);
1400 LPutWinMsg(flayer, str, strlen(str), &mchar_blank, 0, 1);
1402 else
1404 LPutWinMsg(flayer, str, strlen(str), &mchar_blank, 0, 0);
1406 WListNormalize();
1407 WListLines(wlistdata->numwin, -1);
1408 LaySetCursor();
1411 static void
1412 WListUpdate(p)
1413 struct win *p;
1415 struct wlistdata *wlistdata;
1416 int i, n, y;
1418 if (p == 0)
1420 wlistpage();
1421 return;
1423 wlistdata = (struct wlistdata *)flayer->l_data;
1424 n = p->w_number;
1425 if (wlistdata->order == WLIST_NUM && (n < wlistdata->first || n > wlistdata->last))
1426 return;
1427 i = wlistdata->first;
1428 for (y = 0; y < wlistdata->numwin; y++)
1430 if (i == n)
1431 break;
1432 i = WListNext(wlistdata, i, 1);
1434 if (y == wlistdata->numwin)
1435 return;
1436 WListLine(y, i, wlistdata->pos, 0);
1437 LaySetCursor();
1440 void
1441 WListUpdatecv(cv, p)
1442 struct canvas *cv;
1443 struct win *p;
1445 if (cv->c_layer->l_layfn != &WListLf)
1446 return;
1447 CV_CALL(cv, WListUpdate(p));
1450 void
1451 WListLinkChanged()
1453 struct display *olddisplay = display;
1454 struct canvas *cv;
1455 struct wlistdata *wlistdata;
1457 for (display = displays; display; display = display->d_next)
1458 for (cv = D_cvlist; cv; cv = cv->c_next)
1460 if (!cv->c_layer || cv->c_layer->l_layfn != &WListLf)
1461 continue;
1462 wlistdata = (struct wlistdata *)cv->c_layer->l_data;
1463 if (wlistdata->order != WLIST_MRU)
1464 continue;
1465 CV_CALL(cv, WListUpdate(0));
1467 display = olddisplay;
1471 InWList()
1473 if (flayer && flayer->l_layfn == &WListLf)
1474 return 1;
1475 return 0;
1482 ** The bindkey help page
1486 #ifdef MAPKEYS
1487 extern struct kmap_ext *kmap_exts;
1488 extern int kmap_extn;
1489 extern struct action dmtab[];
1490 extern struct action mmtab[];
1493 static void BindkeyProcess __P((char **, int *));
1494 static void BindkeyAbort __P((void));
1495 static void BindkeyRedisplayLine __P((int, int, int, int));
1496 static void bindkeypage __P((void));
1498 struct bindkeydata
1500 char *title;
1501 struct action *tab;
1502 int pos;
1503 int last;
1504 int page;
1505 int pages;
1508 static struct LayFuncs BindkeyLf =
1510 BindkeyProcess,
1511 BindkeyAbort,
1512 BindkeyRedisplayLine,
1513 DefClearLine,
1514 DefRewrite,
1515 DefResize,
1516 DefRestore
1520 void
1521 display_bindkey(title, tab)
1522 char *title;
1523 struct action *tab;
1525 struct bindkeydata *bindkeydata;
1526 int i, n;
1528 if (flayer->l_height < 6)
1530 LMsg(0, "Window height too small for bindkey page");
1531 return;
1533 if (InitOverlayPage(sizeof(*bindkeydata), &BindkeyLf, 0))
1534 return;
1536 bindkeydata = (struct bindkeydata *)flayer->l_data;
1537 bindkeydata->title = title;
1538 bindkeydata->tab = tab;
1540 n = 0;
1541 for (i = 0; i < KMAP_KEYS+KMAP_AKEYS+kmap_extn; i++)
1543 if (tab[i].nr != RC_ILLEGAL)
1544 n++;
1546 bindkeydata->pos = 0;
1547 bindkeydata->page = 1;
1548 bindkeydata->pages = (n + flayer->l_height - 6) / (flayer->l_height - 5);
1549 if (bindkeydata->pages == 0)
1550 bindkeydata->pages = 1;
1551 flayer->l_x = 0;
1552 flayer->l_y = flayer->l_height - 1;
1553 bindkeypage();
1556 static void
1557 BindkeyAbort()
1559 LAY_CALL_UP(LRefreshAll(flayer, 0));
1560 ExitOverlayPage();
1563 static void
1564 bindkeypage()
1566 struct bindkeydata *bindkeydata;
1567 struct kmap_ext *kme;
1568 char tbuf[256];
1569 int del, i, y, sl;
1570 struct action *act;
1571 char *xch, *s, *p;
1573 bindkeydata = (struct bindkeydata *)flayer->l_data;
1575 LClearAll(flayer, 0);
1577 sprintf(tbuf, "%s key bindings, page %d of %d.", bindkeydata->title, bindkeydata->page, bindkeydata->pages);
1578 centerline(tbuf, 0);
1579 y = 2;
1580 for (i = bindkeydata->pos; i < KMAP_KEYS+KMAP_AKEYS+kmap_extn && y < flayer->l_height - 3; i++)
1582 p = tbuf;
1583 xch = " ";
1584 if (i < KMAP_KEYS)
1586 act = &bindkeydata->tab[i];
1587 if (act->nr == RC_ILLEGAL)
1588 continue;
1589 del = *p++ = ':';
1590 s = term[i + T_CAPS].tcname;
1591 sl = s ? strlen(s) : 0;
1593 else if (i < KMAP_KEYS+KMAP_AKEYS)
1595 act = &bindkeydata->tab[i];
1596 if (act->nr == RC_ILLEGAL)
1597 continue;
1598 del = *p++ = ':';
1599 s = term[i + (T_CAPS - T_OCAPS + T_CURSOR)].tcname;
1600 sl = s ? strlen(s) : 0;
1601 xch = "[A]";
1603 else
1605 kme = kmap_exts + (i - (KMAP_KEYS+KMAP_AKEYS));
1606 del = 0;
1607 s = kme->str;
1608 sl = kme->fl & ~KMAP_NOTIMEOUT;
1609 if ((kme->fl & KMAP_NOTIMEOUT) != 0)
1610 xch = "[T]";
1611 act = bindkeydata->tab == dmtab ? &kme->dm : bindkeydata->tab == mmtab ? &kme->mm : &kme->um;
1612 if (act->nr == RC_ILLEGAL)
1613 continue;
1615 while (sl-- > 0)
1616 p += AddXChar(p, *(unsigned char *)s++);
1617 if (del)
1618 *p++ = del;
1619 *p++ = ' ';
1620 while (p < tbuf + 15)
1621 *p++ = ' ';
1622 sprintf(p, "%s -> ", xch);
1623 p += 7;
1624 if (p - tbuf > flayer->l_width - 1)
1626 tbuf[flayer->l_width - 2] = '$';
1627 tbuf[flayer->l_width - 1] = 0;
1629 PadStr(tbuf, strlen(tbuf), 0, y);
1630 AddAction(act, strlen(tbuf), y);
1631 y++;
1633 y++;
1634 bindkeydata->last = i;
1635 sprintf(tbuf,"[Press Space %s Return to end.]", bindkeydata->page < bindkeydata->pages ? "for next page;" : "or");
1636 centerline(tbuf, flayer->l_height - 2);
1637 LaySetCursor();
1640 static void
1641 BindkeyProcess(ppbuf, plen)
1642 char **ppbuf;
1643 int *plen;
1645 int done = 0;
1646 struct bindkeydata *bindkeydata;
1648 bindkeydata = (struct bindkeydata *)flayer->l_data;
1649 while (!done && *plen > 0)
1651 switch (**ppbuf)
1653 case ' ':
1654 if (bindkeydata->page < bindkeydata->pages)
1656 bindkeydata->pos = bindkeydata->last;
1657 bindkeydata->page++;
1658 bindkeypage();
1659 break;
1661 /* FALLTHROUGH */
1662 case '\r':
1663 case '\n':
1664 done = 1;
1665 break;
1666 default:
1667 break;
1669 ++*ppbuf;
1670 --*plen;
1672 if (done)
1673 BindkeyAbort();
1676 static void
1677 BindkeyRedisplayLine(y, xs, xe, isblank)
1678 int y, xs, xe, isblank;
1680 if (y < 0)
1682 bindkeypage();
1683 return;
1685 if (y != 0 && y != flayer->l_height - 1)
1686 return;
1687 if (!isblank)
1688 LClearArea(flayer, xs, y, xe, y, 0, 0);
1691 #endif /* MAPKEYS */
1696 ** The zmodem active page
1700 #ifdef ZMODEM
1702 static void ZmodemRedisplayLine __P((int, int, int, int));
1703 static int ZmodemResize __P((int, int));
1705 static struct LayFuncs ZmodemLf =
1707 DefProcess,
1709 ZmodemRedisplayLine,
1710 DefClearLine,
1711 DefRewrite,
1712 ZmodemResize,
1713 DefRestore
1716 /*ARGSUSED*/
1717 static int
1718 ZmodemResize(wi, he)
1719 int wi, he;
1721 flayer->l_width = wi;
1722 flayer->l_height = he;
1723 flayer->l_x = flayer->l_width > 32 ? 32 : 0;
1724 return 0;
1727 static void
1728 ZmodemRedisplayLine(y, xs, xe, isblank)
1729 int y, xs, xe, isblank;
1731 DefRedisplayLine(y, xs, xe, isblank);
1732 if (y == 0 && xs == 0)
1733 LPutStr(flayer, "Zmodem active on another display", flayer->l_width > 32 ? 32 : flayer->l_width, &mchar_blank, 0, 0);
1736 void
1737 ZmodemPage()
1739 if (InitOverlayPage(1, &ZmodemLf, 1))
1740 return;
1741 LRefreshAll(flayer, 0);
1742 flayer->l_x = flayer->l_width > 32 ? 32 : 0;
1743 flayer->l_y = 0;
1746 #endif
1750 static void
1751 PadStr(str, n, x, y)
1752 char *str;
1753 int n, x, y;
1755 int l;
1757 l = strlen(str);
1758 if (l > n)
1759 l = n;
1760 LPutStr(flayer, str, l, &mchar_blank, x, y);
1761 if (l < n)
1762 LPutStr(flayer, (char *)blank, n - l, &mchar_blank, x + l, y);