Start converting to GPL v3+ (ref: ticket #23900)
[screen-lua.git] / src / help.c
blob3b71b251b837f24dc6ce47317fedb5f278560d3a
1 /* Copyright (c) 1993-2002
2 * Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
3 * Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
4 * Copyright (c) 1987 Oliver Laumann
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 3, or (at your option)
9 * any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program (see the file COPYING); if not, see
18 * http://www.gnu.org/licenses/, or contact Free Software Foundation, Inc.,
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
21 ****************************************************************
24 #include <sys/types.h>
26 #include "config.h"
28 #include "screen.h"
29 #include "extern.h"
31 char version[40]; /* initialised by main() */
33 extern struct layer *flayer;
34 extern struct display *display, *displays;
35 extern struct win *windows;
36 extern char *noargs[];
37 extern struct mchar mchar_blank, mchar_so;
38 extern unsigned char *blank;
39 extern struct win *wtab[];
40 #ifdef MAPKEYS
41 extern struct term term[];
42 #endif
44 static void PadStr __P((char *, int, int, int));
46 extern char *wliststr;
47 extern char *wlisttit;
49 void
50 exit_with_usage(myname, message, arg)
51 char *myname, *message, *arg;
53 printf("Use: %s [-opts] [cmd [args]]\n", myname);
54 printf(" or: %s -r [host.tty]\n\nOptions:\n", myname);
55 printf("-a Force all capabilities into each window's termcap.\n");
56 printf("-A -[r|R] Adapt all windows to the new display width & height.\n");
57 printf("-c file Read configuration file instead of '.screenrc'.\n");
58 #ifdef REMOTE_DETACH
59 printf("-d (-r) Detach the elsewhere running screen (and reattach here).\n");
60 printf("-dmS name Start as daemon: Screen session in detached mode.\n");
61 printf("-D (-r) Detach and logout remote (and reattach here).\n");
62 printf("-D -RR Do whatever is needed to get a screen session.\n");
63 #endif
64 printf("-e xy Change command characters.\n");
65 printf("-f Flow control on, -fn = off, -fa = auto.\n");
66 printf("-h lines Set the size of the scrollback history buffer.\n");
67 printf("-i Interrupt output sooner when flow control is on.\n");
68 #if defined(LOGOUTOK) && defined(UTMPOK)
69 printf("-l Login mode on (update %s), -ln = off.\n", UTMPFILE);
70 #endif
71 printf("-list or -ls. Do nothing, just list our SockDir.\n");
72 printf("-L Turn on output logging.\n");
73 printf("-m ignore $STY variable, do create a new screen session.\n");
74 printf("-O Choose optimal output rather than exact vt100 emulation.\n");
75 printf("-p window Preselect the named window if it exists.\n");
76 printf("-q Quiet startup. Exits with non-zero return code if unsuccessful.\n");
77 printf("-r Reattach to a detached screen process.\n");
78 printf("-R Reattach if possible, otherwise start a new session.\n");
79 printf("-s shell Shell to execute rather than $SHELL.\n");
80 printf("-S sockname Name this session <pid>.sockname instead of <pid>.<tty>.<host>.\n");
81 printf("-t title Set title. (window's name).\n");
82 printf("-T term Use term as $TERM for windows, rather than \"screen\".\n");
83 #ifdef UTF8
84 printf("-U Tell screen to use UTF-8 encoding.\n");
85 #endif
86 printf("-v Print \"Screen version %s\".\n", version);
87 printf("-wipe Do nothing, just clean up SockDir.\n");
88 #ifdef MULTI
89 printf("-x Attach to a not detached screen. (Multi display mode).\n");
90 #endif /* MULTI */
91 printf("-X Execute <cmd> as a screen command in the specified session.\n");
92 if (message && *message)
94 printf("\nError: ");
95 printf(message, arg);
96 printf("\n");
98 exit(1);
102 ** Here come the help page routines
105 extern struct comm comms[];
106 extern struct action ktab[];
108 static void HelpProcess __P((char **, int *));
109 static void HelpAbort __P((void));
110 static void HelpRedisplayLine __P((int, int, int, int));
111 static void add_key_to_buf __P((char *, int));
112 static void AddAction __P((struct action *, int, int));
113 static int helppage __P((void));
115 struct helpdata
117 char *class;
118 struct action *ktabp;
119 int maxrow, grow, numcols, numrows, num_names;
120 int numskip, numpages;
121 int command_search, command_bindings;
122 int refgrow, refcommand_search;
123 int inter, mcom, mkey;
124 int nact[RC_LAST + 1];
127 #define MAXKLEN 256
129 static struct LayFuncs HelpLf =
131 HelpProcess,
132 HelpAbort,
133 HelpRedisplayLine,
134 DefClearLine,
135 DefRewrite,
136 DefResize,
137 DefRestore
141 void
142 display_help(class, ktabp)
143 char *class;
144 struct action *ktabp;
146 int i, n, key, mcom, mkey, l;
147 struct helpdata *helpdata;
148 int used[RC_LAST + 1];
150 if (flayer->l_height < 6)
152 LMsg(0, "Window height too small for help page");
153 return;
155 if (InitOverlayPage(sizeof(*helpdata), &HelpLf, 0))
156 return;
158 helpdata = (struct helpdata *)flayer->l_data;
159 helpdata->class = class;
160 helpdata->ktabp = ktabp;
161 helpdata->num_names = helpdata->command_bindings = 0;
162 helpdata->command_search = 0;
163 for (n = 0; n <= RC_LAST; n++)
164 used[n] = 0;
165 mcom = 0;
166 mkey = 0;
167 for (key = 0; key < 256 + KMAP_KEYS; key++)
169 n = ktabp[key].nr;
170 if (n == RC_ILLEGAL)
171 continue;
172 if (ktabp[key].args == noargs)
174 used[n] += (key <= ' ' || key == 0x7f) ? 3 :
175 (key > 0x7f) ? 5 : 2;
177 else
178 helpdata->command_bindings++;
180 for (n = i = 0; n <= RC_LAST; n++)
181 if (used[n])
183 l = strlen(comms[n].name);
184 if (l > mcom)
185 mcom = l;
186 if (used[n] > mkey)
187 mkey = used[n];
188 helpdata->nact[i++] = n;
190 debug1("help: %d commands bound to keys with no arguments\n", i);
191 debug2("mcom: %d mkey: %d\n", mcom, mkey);
192 helpdata->num_names = i;
194 if (mkey > MAXKLEN)
195 mkey = MAXKLEN;
196 helpdata->numcols = flayer->l_width / (mcom + mkey + 1);
197 if (helpdata->numcols == 0)
199 HelpAbort();
200 LMsg(0, "Width too small");
201 return;
203 helpdata->inter = (flayer->l_width - (mcom + mkey) * helpdata->numcols) / (helpdata->numcols + 1);
204 if (helpdata->inter <= 0)
205 helpdata->inter = 1;
206 debug1("inter: %d\n", helpdata->inter);
207 helpdata->mcom = mcom;
208 helpdata->mkey = mkey;
209 helpdata->numrows = (helpdata->num_names + helpdata->numcols - 1) / helpdata->numcols;
210 debug1("Numrows: %d\n", helpdata->numrows);
211 helpdata->numskip = flayer->l_height-5 - (2 + helpdata->numrows);
212 while (helpdata->numskip < 0)
213 helpdata->numskip += flayer->l_height-5;
214 helpdata->numskip %= flayer->l_height-5;
215 debug1("Numskip: %d\n", helpdata->numskip);
216 if (helpdata->numskip > flayer->l_height/3 || helpdata->numskip > helpdata->command_bindings)
217 helpdata->numskip = 1;
218 helpdata->maxrow = 2 + helpdata->numrows + helpdata->numskip + helpdata->command_bindings;
219 helpdata->grow = 0;
221 helpdata->numpages = (helpdata->maxrow + flayer->l_height-6) / (flayer->l_height-5);
222 flayer->l_x = 0;
223 flayer->l_y = flayer->l_height - 1;
224 helppage();
227 static void
228 HelpProcess(ppbuf, plen)
229 char **ppbuf;
230 int *plen;
232 int done = 0;
234 while (!done && *plen > 0)
236 switch (**ppbuf)
238 case ' ':
239 if (helppage() == 0)
240 break;
241 /* FALLTHROUGH */
242 case '\r':
243 case '\n':
244 done = 1;
245 break;
246 default:
247 break;
249 ++*ppbuf;
250 --*plen;
252 if (done)
253 HelpAbort();
256 static void
257 HelpAbort()
259 LAY_CALL_UP(LRefreshAll(flayer, 0));
260 ExitOverlayPage();
264 static int
265 helppage()
267 struct helpdata *helpdata;
268 int col, crow, n, key, x;
269 char buf[MAXKLEN], Esc_buf[5], cbuf[256];
270 struct action *ktabp;
272 helpdata = (struct helpdata *)flayer->l_data;
274 ktabp = helpdata->ktabp;
275 if (helpdata->grow >= helpdata->maxrow)
276 return -1;
277 helpdata->refgrow = helpdata->grow;
278 helpdata->refcommand_search = helpdata->command_search;
280 /* Clear the help screen */
281 LClearAll(flayer, 0);
283 sprintf(cbuf,"Screen key bindings, page %d of %d.", helpdata->grow / (flayer->l_height-5) + 1, helpdata->numpages);
284 centerline(cbuf, 0);
285 crow = 2;
287 *Esc_buf = '\0';
288 *buf = '\0';
289 /* XXX fix escape character */
290 if (flayer->l_cvlist && flayer->l_cvlist->c_display)
292 add_key_to_buf(buf, flayer->l_cvlist->c_display->d_user->u_MetaEsc);
293 add_key_to_buf(Esc_buf, flayer->l_cvlist->c_display->d_user->u_Esc);
295 else
297 strcpy(Esc_buf, "??");
298 strcpy(buf, "??");
301 for (; crow < flayer->l_height - 3; crow++)
303 if (helpdata->grow < 1)
305 if (ktabp == ktab)
306 sprintf(cbuf,"Command key: %s Literal %s: %s", Esc_buf, Esc_buf, buf);
307 else
308 sprintf(cbuf,"Command class: '%.80s'", helpdata->class);
309 centerline(cbuf, crow);
310 helpdata->grow++;
312 else if (helpdata->grow >= 2 && helpdata->grow-2 < helpdata->numrows)
314 x = 0;
315 for (col = 0; col < helpdata->numcols && (n = helpdata->numrows * col + (helpdata->grow-2)) < helpdata->num_names; col++)
317 x += helpdata->inter - !col;
318 n = helpdata->nact[n];
319 buf[0] = '\0';
320 for (key = 0; key < 256 + KMAP_KEYS; key++)
321 if (ktabp[key].nr == n && ktabp[key].args == noargs && strlen(buf) < sizeof(buf) - 7)
323 strcat(buf, " ");
324 add_key_to_buf(buf, key);
326 PadStr(comms[n].name, helpdata->mcom, x, crow);
327 x += helpdata->mcom;
328 PadStr(buf, helpdata->mkey, x, crow);
329 x += helpdata->mkey;
331 helpdata->grow++;
333 else if (helpdata->grow-2-helpdata->numrows >= helpdata->numskip
334 && helpdata->grow-2-helpdata->numrows-helpdata->numskip < helpdata->command_bindings)
336 while ((n = ktabp[helpdata->command_search].nr) == RC_ILLEGAL
337 || ktabp[helpdata->command_search].args == noargs)
339 if (++helpdata->command_search >= 256 + KMAP_KEYS)
340 return -1;
342 buf[0] = '\0';
343 add_key_to_buf(buf, helpdata->command_search);
344 PadStr(buf, 5, 0, crow);
345 AddAction(&ktabp[helpdata->command_search++], 5, crow);
346 helpdata->grow++;
348 else
349 helpdata->grow++;
351 sprintf(cbuf,"[Press Space %s Return to end.]",
352 helpdata->grow < helpdata->maxrow ? "for next page;" : "or");
353 centerline(cbuf, flayer->l_height - 2);
354 LaySetCursor();
355 return 0;
358 static void
359 AddAction(act, x, y)
360 struct action *act;
361 int x, y;
363 char buf[256];
364 int del, l;
365 char *bp, *cp, **pp;
366 int *lp, ll;
367 int fr;
368 struct mchar mchar_dol;
370 mchar_dol = mchar_blank;
371 mchar_dol.image = '$';
373 fr = flayer->l_width - 1 - x;
374 if (fr <= 0)
375 return;
376 l = strlen(comms[act->nr].name);
378 if (l + 1 > fr)
379 l = fr - 1;
380 PadStr(comms[act->nr].name, l, x, y);
381 x += l;
382 fr -= l + 1;
383 LPutChar(flayer, fr ? &mchar_blank : &mchar_dol, x++, y);
385 pp = act->args;
386 lp = act->argl;
387 while (pp && (cp = *pp) != NULL)
389 del = 0;
390 bp = buf;
391 ll = *lp++;
392 if (!ll || (index(cp, ' ') != NULL))
394 if (index(cp, '\'') != NULL)
395 *bp++ = del = '"';
396 else
397 *bp++ = del = '\'';
399 while (ll-- && bp < buf + 250)
400 bp += AddXChar(bp, *(unsigned char *)cp++);
401 if (del)
402 *bp++ = del;
403 *bp = 0;
404 if ((fr -= (bp - buf) + 1) < 0)
406 fr += bp - buf;
407 if (fr > 0)
408 PadStr(buf, fr, x, y);
409 if (fr == 0)
410 LPutChar(flayer, &mchar_dol, x, y);
411 return;
413 PadStr(buf, strlen(buf), x, y);
414 x += strlen(buf);
415 pp++;
416 if (*pp)
417 LPutChar(flayer, fr ? &mchar_blank : &mchar_dol, x++, y);
421 static void
422 add_key_to_buf(buf, key)
423 char *buf;
424 int key;
426 buf += strlen(buf);
427 if (key < 0)
428 strcpy(buf, "unset");
429 else if (key == ' ')
430 strcpy(buf, "sp");
431 #ifdef MAPKEYS
432 else if (key >= 256)
434 key = key - 256 + T_CAPS;
435 buf[0] = ':';
436 buf[1] = term[key].tcname[0];
437 buf[2] = term[key].tcname[1];
438 buf[3] = ':';
439 buf[4] = 0;
441 #endif
442 else
443 buf[AddXChar(buf, key)] = 0;
447 static void
448 HelpRedisplayLine(y, xs, xe, isblank)
449 int y, xs, xe, isblank;
451 if (y < 0)
453 struct helpdata *helpdata;
455 helpdata = (struct helpdata *)flayer->l_data;
456 helpdata->grow = helpdata->refgrow;
457 helpdata->command_search = helpdata->refcommand_search;
458 helppage();
459 return;
461 if (y != 0 && y != flayer->l_height - 1)
462 return;
463 if (!isblank)
464 LClearArea(flayer, xs, y, xe, y, 0, 0);
470 ** here is all the copyright stuff
474 static void CopyrightProcess __P((char **, int *));
475 static void CopyrightRedisplayLine __P((int, int, int, int));
476 static void CopyrightAbort __P((void));
477 static void copypage __P((void));
479 struct copydata
481 char *cps, *savedcps; /* position in the message */
482 char *refcps, *refsavedcps; /* backup for redisplaying */
485 static struct LayFuncs CopyrightLf =
487 CopyrightProcess,
488 CopyrightAbort,
489 CopyrightRedisplayLine,
490 DefClearLine,
491 DefRewrite,
492 DefResize,
493 DefRestore
496 static const char cpmsg[] = "\
498 Screen version %v\n\
500 Copyright (c) 1993-2002 Juergen Weigert, Michael Schroeder\n\
501 Copyright (c) 1987 Oliver Laumann\n\
503 This program is free software; you can redistribute it and/or \
504 modify it under the terms of the GNU General Public License as published \
505 by the Free Software Foundation; either version 3, or (at your option) \
506 any later version.\n\
508 This program is distributed in the hope that it will be useful, \
509 but WITHOUT ANY WARRANTY; without even the implied warranty of \
510 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the \
511 GNU General Public License for more details.\n\
513 You should have received a copy of the GNU General Public License \
514 along with this program (see the file COPYING); if not, see \
515 http://www.gnu.org/licenses/, or contact Free Software Foundation, Inc., \
516 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA.\n\
518 Send bugreports, fixes, enhancements, t-shirts, money, beer & pizza to \
519 screen@uni-erlangen.de\n";
522 static void
523 CopyrightProcess(ppbuf, plen)
524 char **ppbuf;
525 int *plen;
527 int done = 0;
528 struct copydata *copydata;
530 copydata = (struct copydata *)flayer->l_data;
531 while (!done && *plen > 0)
533 switch (**ppbuf)
535 case ' ':
536 if (*copydata->cps)
538 copypage();
539 break;
541 /* FALLTHROUGH */
542 case '\r':
543 case '\n':
544 CopyrightAbort();
545 done = 1;
546 break;
547 default:
548 break;
550 ++*ppbuf;
551 --*plen;
555 static void
556 CopyrightAbort()
558 LAY_CALL_UP(LRefreshAll(flayer, 0));
559 ExitOverlayPage();
562 void
563 display_copyright()
565 struct copydata *copydata;
567 if (flayer->l_width < 10 || flayer->l_height < 5)
569 LMsg(0, "Window size too small for copyright page");
570 return;
572 if (InitOverlayPage(sizeof(*copydata), &CopyrightLf, 0))
573 return;
574 copydata = (struct copydata *)flayer->l_data;
575 copydata->cps = (char *)cpmsg;
576 copydata->savedcps = 0;
577 flayer->l_x = 0;
578 flayer->l_y = flayer->l_height - 1;
579 copypage();
582 static void
583 copypage()
585 register char *cps;
586 char *ws;
587 int x, y, l;
588 char cbuf[80];
589 struct copydata *copydata;
591 ASSERT(flayer);
592 copydata = (struct copydata *)flayer->l_data;
594 LClearAll(flayer, 0);
595 x = y = 0;
596 cps = copydata->cps;
597 copydata->refcps = cps;
598 copydata->refsavedcps = copydata->savedcps;
599 while (*cps && y < flayer->l_height - 3)
601 ws = cps;
602 while (*cps == ' ')
603 cps++;
604 if (strncmp(cps, "%v", 2) == 0)
606 copydata->savedcps = cps + 2;
607 cps = version;
608 continue;
610 while (*cps && *cps != ' ' && *cps != '\n')
611 cps++;
612 l = cps - ws;
613 cps = ws;
614 if (l > flayer->l_width - 1)
615 l = flayer->l_width - 1;
616 if (x && x + l >= flayer->l_width - 2)
618 x = 0;
619 y++;
620 continue;
622 if (x)
624 LPutChar(flayer, &mchar_blank, x, y);
625 x++;
627 if (l)
628 LPutStr(flayer, ws, l, &mchar_blank, x, y);
629 x += l;
630 cps += l;
631 if (*cps == 0 && copydata->savedcps)
633 cps = copydata->savedcps;
634 copydata->savedcps = 0;
636 if (*cps == '\n')
638 x = 0;
639 y++;
641 if (*cps == ' ' || *cps == '\n')
642 cps++;
644 while (*cps == '\n')
645 cps++;
646 sprintf(cbuf,"[Press Space %s Return to end.]",
647 *cps ? "for next page;" : "or");
648 centerline(cbuf, flayer->l_height - 2);
649 copydata->cps = cps;
650 LaySetCursor();
653 static void
654 CopyrightRedisplayLine(y, xs, xe, isblank)
655 int y, xs, xe, isblank;
657 ASSERT(flayer);
658 if (y < 0)
660 struct copydata *copydata;
662 copydata = (struct copydata *)flayer->l_data;
663 copydata->cps = copydata->refcps;
664 copydata->savedcps = copydata->refsavedcps;
665 copypage();
666 return;
668 if (y != 0 && y != flayer->l_height - 1)
669 return;
670 if (isblank)
671 return;
672 LClearArea(flayer, xs, y, xe, y, 0, 0);
679 ** here is all the displays stuff
683 #ifdef MULTI
685 static void DisplaysProcess __P((char **, int *));
686 static void DisplaysRedisplayLine __P((int, int, int, int));
687 static void displayspage __P((void));
689 struct displaysdata
691 int dummy_element_for_solaris;
694 static struct LayFuncs DisplaysLf =
696 DisplaysProcess,
697 HelpAbort,
698 DisplaysRedisplayLine,
699 DefClearLine,
700 DefRewrite,
701 DefResize,
702 DefRestore
705 static void
706 DisplaysProcess(ppbuf, plen)
707 char **ppbuf;
708 int *plen;
710 int done = 0;
712 ASSERT(flayer);
713 while (!done && *plen > 0)
715 switch (**ppbuf)
717 case ' ':
718 displayspage();
719 break;
720 case '\r':
721 case '\n':
722 HelpAbort();
723 done = 1;
724 break;
725 default:
726 break;
728 ++*ppbuf;
729 --*plen;
734 void
735 display_displays()
737 if (flayer->l_width < 10 || flayer->l_height < 5)
739 LMsg(0, "Window size too small for displays page");
740 return;
742 if (InitOverlayPage(sizeof(struct displaysdata), &DisplaysLf, 0))
743 return;
744 flayer->l_x = 0;
745 flayer->l_y = flayer->l_height - 1;
746 displayspage();
750 * layout of the displays page is as follows:
752 xterm 80x42 jnweiger@/dev/ttyp4 0(m11) &rWx
753 facit 80x24 nb mlschroe@/dev/ttyhf 11(tcsh) rwx
754 xterm 80x42 jnhollma@/dev/ttyp5 0(m11) &R.x
756 | | | | | | | | ¦___ window permissions
757 | | | | | | | | (R. is locked r-only,
758 | | | | | | | | W has wlock)
759 | | | | | | | |___ Window is shared
760 | | | | | | |___ Name/Title of window
761 | | | | | |___ Number of window
762 | | | | |___ Name of the display (the attached device)
763 | | | |___ Username who is logged in at the display
764 | | |___ Display is in nonblocking mode. Shows 'NB' if obuf is full.
765 | |___ Displays geometry as width x height.
766 |___ the terminal type known by screen for this display.
770 static void
771 displayspage()
773 int y, l;
774 char tbuf[80];
775 struct display *d;
776 struct win *w;
777 static char *blockstates[5] = {"nb", "NB", "Z<", "Z>", "BL"};
779 LClearAll(flayer, 0);
781 leftline("term-type size user interface window", 0);
782 leftline("---------- ------- ---------- ----------------- ----------", 1);
783 y = 2;
785 for (d = displays; d; d = d->d_next)
787 w = d->d_fore;
789 if (y >= flayer->l_height - 3)
790 break;
791 sprintf(tbuf, "%-10.10s%4dx%-4d%10.10s@%-16.16s%s",
792 d->d_termname, d->d_width, d->d_height, d->d_user->u_name,
793 d->d_usertty,
794 (d->d_blocked || d->d_nonblock >= 0) && d->d_blocked <= 4 ? blockstates[d->d_blocked] : " ");
796 if (w)
798 l = 10 - strlen(w->w_title);
799 if (l < 0)
800 l = 0;
801 sprintf(tbuf + strlen(tbuf), "%3d(%.10s)%*s%c%c%c%c",
802 w->w_number, w->w_title, l, "",
803 /* w->w_dlist->next */ 0 ? '&' : ' ',
805 * The rwx triple:
806 * -,r,R no read, read, read only due to foreign wlock
807 * -,.,w,W no write, write suppressed by foreign wlock,
808 * write, own wlock
809 * -,x no execute, execute
811 #ifdef MULTIUSER
812 (AclCheckPermWin(d->d_user, ACL_READ, w) ? '-' :
813 ((w->w_wlock == WLOCK_OFF || d->d_user == w->w_wlockuser) ?
814 'r' : 'R')),
815 (AclCheckPermWin(d->d_user, ACL_READ, w) ? '-' :
816 ((w->w_wlock == WLOCK_OFF) ? 'w' :
817 ((d->d_user == w->w_wlockuser) ? 'W' : 'v'))),
818 (AclCheckPermWin(d->d_user, ACL_READ, w) ? '-' : 'x')
819 #else
820 'r', 'w', 'x'
821 #endif
824 leftline(tbuf, y);
825 y++;
827 sprintf(tbuf,"[Press Space %s Return to end.]",
828 1 ? "to refresh;" : "or");
829 centerline(tbuf, flayer->l_height - 2);
830 LaySetCursor();
833 static void
834 DisplaysRedisplayLine(y, xs, xe, isblank)
835 int y, xs, xe, isblank;
837 ASSERT(flayer);
838 if (y < 0)
840 displayspage();
841 return;
843 if (y != 0 && y != flayer->l_height - 1)
844 return;
845 if (isblank)
846 return;
847 LClearArea(flayer, xs, y, xe, y, 0, 0);
848 /* To be filled in... */
851 #endif /* MULTI */
856 ** here is the windowlist
860 struct wlistdata;
862 static void WListProcess __P((char **, int *));
863 static void WListRedisplayLine __P((int, int, int, int));
864 static void wlistpage __P((void));
865 static void WListLine __P((int, int, int, int));
866 static void WListLines __P((int, int));
867 static void WListMove __P((int, int));
868 static void WListUpdate __P((struct win *));
869 static int WListNormalize __P((void));
870 static int WListResize __P((int, int));
871 static int WListNext __P((struct wlistdata *, int, int));
873 struct wlistdata {
874 int pos;
875 int ypos;
876 int npos;
877 int numwin;
878 int first;
879 int last;
880 int start;
881 int order;
882 struct win *group;
883 int nested;
884 int list[MAXWIN];
887 static struct LayFuncs WListLf =
889 WListProcess,
890 HelpAbort,
891 WListRedisplayLine,
892 DefClearLine,
893 DefRewrite,
894 WListResize,
895 DefRestore
898 #define WTAB_GROUP_MATCHES(i) (group == wtab[i]->w_group)
900 static int
901 WListResize(wi, he)
902 int wi, he;
904 struct wlistdata *wlistdata;
905 if (wi < 10 || he < 5)
906 return -1;
907 wlistdata = (struct wlistdata *)flayer->l_data;
908 flayer->l_width = wi;
909 flayer->l_height = he;
910 wlistdata->numwin = he - 3;
911 if (wlistdata->ypos >= wlistdata->numwin)
912 wlistdata->ypos = wlistdata->numwin - 1;
913 flayer->l_y = he - 1;
914 return 0;
917 static void
918 WListProcess(ppbuf, plen)
919 char **ppbuf;
920 int *plen;
922 int done = 0;
923 struct wlistdata *wlistdata;
924 struct display *olddisplay = display;
925 int h;
926 struct win *group;
928 ASSERT(flayer);
929 wlistdata = (struct wlistdata *)flayer->l_data;
930 group = wlistdata->group;
931 h = wlistdata->numwin;
932 while (!done && *plen > 0)
934 if ((unsigned char)**ppbuf >= '0' && (unsigned char)**ppbuf <= '9')
936 int n = (unsigned char)**ppbuf - '0';
937 int d = 0;
938 if (n < MAXWIN && wtab[n] && WTAB_GROUP_MATCHES(n))
940 int i;
941 for (d = -wlistdata->npos, i = WListNext(wlistdata, -1, 0); i != n; i = WListNext(wlistdata, i, 1), d++)
944 if (d)
945 WListMove(d, -1);
947 switch ((unsigned char)**ppbuf)
949 case 0220: /* up */
950 case 16: /* ^P like emacs */
951 case 'k':
952 WListMove(-1, -1);
953 break;
954 case 0216: /* down */
955 case 14: /* ^N like emacs */
956 case 'j':
957 WListMove(1, -1);
958 break;
959 case '\025':
960 WListMove(-(h / 2), wlistdata->ypos);
961 break;
962 case '\004':
963 WListMove(h / 2, wlistdata->ypos);
964 break;
965 case 0002:
966 case 'b':
967 WListMove(-h, -1);
968 break;
969 case 0006:
970 case 'f':
971 WListMove(h, -1);
972 break;
973 case 0201: /* home */
974 WListMove(-wlistdata->pos, -1);
975 break;
976 case 0205: /* end */
977 WListMove(MAXWIN, -1);
978 break;
979 case 'a':
980 /* All-window view */
981 wlistdata->group = 0;
982 wlistdata->nested = WLIST_NESTED;
983 wlistpage();
984 break;
985 case 'g':
986 /* Toggle nested view */
987 wlistdata->nested ^= WLIST_NESTED;
988 wlistpage();
989 break;
990 case 'm':
991 /* Toggle MRU view */
992 wlistdata->order ^= 1;
993 wlistpage();
994 break;
995 case '\r':
996 case '\n':
997 case ' ':
998 h = wlistdata->pos;
999 if (h == MAXWIN && Layer2Window(flayer) && Layer2Window(flayer)->w_type == W_TYPE_GROUP)
1000 break;
1001 if (display && h != MAXWIN && wtab[h] && (wtab[h]->w_type == W_TYPE_GROUP || wtab[h] == D_fore))
1003 wlistdata->group = wtab[h];
1004 wlistdata->pos = wtab[h]->w_number;
1005 wlistpage();
1006 break;
1008 done = 1;
1009 if (!display || h == MAXWIN || !wtab[h] || wtab[h] == D_fore || (flayer->l_cvlist && flayer->l_cvlist->c_lnext))
1010 HelpAbort();
1011 #ifdef MULTIUSER
1012 else if (AclCheckPermWin(D_user, ACL_READ, wtab[h]))
1013 HelpAbort();
1014 #endif
1015 else
1016 ExitOverlayPage(); /* no need to redisplay */
1017 /* restore display, don't switch wrong user */
1018 display = olddisplay;
1019 if (h != MAXWIN)
1020 SwitchWindow(h);
1021 break;
1022 case 0033:
1023 case 0007:
1024 h = wlistdata->start;
1025 if (h == -1 && Layer2Window(flayer) && Layer2Window(flayer)->w_type == W_TYPE_GROUP)
1027 struct win *p = Layer2Window(flayer);
1028 if (wlistdata->group != p)
1030 wlistdata->group = p;
1031 wlistpage();
1033 break;
1035 HelpAbort();
1036 display = olddisplay;
1037 if (h >= 0 && wtab[h])
1038 SwitchWindow(h);
1039 else if (h == -2)
1041 struct win *p = FindNiceWindow(display ? D_other : (struct win *)0, 0);
1042 if (p)
1043 SwitchWindow(p->w_number);
1045 done = 1;
1046 break;
1047 case '\010': /* ctrl-h */
1048 case 0177:
1049 if (!wlistdata->group)
1050 break;
1051 wlistdata->pos = wlistdata->group->w_number;
1052 wlistdata->group = wlistdata->group->w_group;
1053 if (wlistdata->group)
1054 wlistdata->pos = wlistdata->group->w_number;
1055 wlistpage();
1056 break;
1057 default:
1058 break;
1060 ++*ppbuf;
1061 --*plen;
1065 static void
1066 WListLine(y, i, pos, isblank)
1067 int y, i;
1068 int pos;
1069 int isblank;
1071 char *str;
1072 int n;
1073 int yoff, xoff = 0;
1074 struct wlistdata *wlistdata;
1075 struct win *group;
1077 if (i == MAXWIN)
1078 return;
1079 wlistdata = (struct wlistdata *)flayer->l_data;
1080 if (wlistdata->nested && wtab[i])
1081 for (group = wtab[i]->w_group, xoff = 0; group != wlistdata->group;
1082 group = group->w_group, xoff += 2)
1084 yoff = wlistdata->group ? 3 : 2;
1085 display = Layer2Window(flayer) ? 0 : flayer->l_cvlist ? flayer->l_cvlist->c_display : 0;
1086 str = MakeWinMsgEv(wliststr, wtab[i], '%', flayer->l_width - xoff, (struct event *)0, 0);
1087 n = strlen(str);
1088 if (i != pos && isblank)
1089 while (n && str[n - 1] == ' ')
1090 n--;
1091 LPutWinMsg(flayer, str, (i == pos || !isblank) ? flayer->l_width : n, i == pos ? &mchar_so : &mchar_blank, xoff, y + yoff);
1092 if (xoff)
1093 LPutWinMsg(flayer, "", xoff, i == pos ? &mchar_so : &mchar_blank, 0, y + yoff);
1094 #if 0
1095 LPutStr(flayer, str, n, i == pos ? &mchar_so : &mchar_blank, 0, y + yoff);
1096 if (i == pos || !isblank)
1097 while(n < flayer->l_width)
1098 LPutChar(flayer, i == pos ? &mchar_so : &mchar_blank, n++, y + yoff);
1099 #endif
1100 return;
1104 static int
1105 WListNext(wlistdata, old, delta)
1106 struct wlistdata *wlistdata;
1107 int old, delta;
1109 int i;
1111 if (old == MAXWIN)
1112 return MAXWIN;
1113 if (old == -1)
1114 old = 0;
1115 else
1117 for (i = 0; i < MAXWIN && wlistdata->list[i] != -1; i++)
1118 if (wlistdata->list[i] == old)
1119 break;
1120 if (i < MAXWIN && wlistdata->list[i] != -1)
1121 old = i;
1124 old += delta;
1125 if (old < 0 || old >= MAXWIN || wlistdata->list[old] == -1)
1126 old -= delta;
1127 return wlistdata->list[old];
1130 static void
1131 WListLines(up, oldpos)
1132 int up, oldpos;
1134 struct wlistdata *wlistdata;
1135 int ypos, pos;
1136 int y, i, oldi;
1138 wlistdata = (struct wlistdata *)flayer->l_data;
1139 ypos = wlistdata->ypos;
1140 pos = wlistdata->pos;
1142 i = WListNext(wlistdata, pos, -ypos);
1143 for (y = 0; y < wlistdata->numwin; y++)
1145 if (i == MAXWIN || !wtab[i])
1146 return;
1147 if (y == 0)
1148 wlistdata->first = i;
1149 wlistdata->last = i;
1150 if (((i == oldpos || i == pos) && pos != oldpos) || (up > 0 && y >= wlistdata->numwin - up) || (up < 0 && y < -up))
1151 WListLine(y, i, pos, i != oldpos);
1152 if (i == pos)
1153 wlistdata->ypos = y;
1154 oldi = i;
1155 i = WListNext(wlistdata, i, 1);
1156 if (i == MAXWIN || i == oldi)
1157 break;
1161 static int
1162 WListNormalize()
1164 struct wlistdata *wlistdata;
1165 int i, oldi, n;
1166 int ypos, pos;
1168 wlistdata = (struct wlistdata *)flayer->l_data;
1169 ypos = wlistdata->ypos;
1170 pos = wlistdata->pos;
1171 if (ypos < 0)
1172 ypos = 0;
1173 if (ypos >= wlistdata->numwin)
1174 ypos = wlistdata->numwin - 1;
1175 for (n = 0, oldi = MAXWIN, i = pos; i != MAXWIN && i != oldi && n < wlistdata->numwin; oldi = i, i = WListNext(wlistdata, i, 1))
1176 n++;
1177 if (ypos < wlistdata->numwin - n)
1178 ypos = wlistdata->numwin - n;
1179 for (n = 0, oldi = MAXWIN, i = WListNext(wlistdata, -1, 0); i != MAXWIN && i != oldi && i != pos; oldi = i, i = WListNext(wlistdata, i, 1))
1180 n++;
1181 if (ypos > n)
1182 ypos = n;
1183 wlistdata->ypos = ypos;
1184 wlistdata->npos = n;
1185 return ypos;
1188 static void
1189 WListMove(num, ypos)
1190 int num;
1191 int ypos;
1193 struct wlistdata *wlistdata;
1194 int oldpos, oldypos, oldnpos;
1195 int pos, up;
1197 wlistdata = (struct wlistdata *)flayer->l_data;
1198 oldpos = wlistdata->pos;
1199 oldypos = wlistdata->ypos;
1200 oldnpos = wlistdata->npos;
1201 wlistdata->ypos = ypos == -1 ? oldypos + num : ypos;
1202 pos = WListNext(wlistdata, oldpos, num);
1203 wlistdata->pos = pos;
1204 ypos = WListNormalize();
1205 up = wlistdata->npos - ypos - (oldnpos - oldypos);
1206 if (up)
1208 LScrollV(flayer, up, 2, 2 + wlistdata->numwin - 1, 0);
1209 WListLines(up, oldpos);
1210 LaySetCursor();
1211 return;
1213 if (pos == oldpos)
1214 return;
1215 WListLine(oldypos, oldpos, pos, 0);
1216 WListLine(ypos, pos, pos, 1);
1217 LaySetCursor();
1220 static void
1221 WListRedisplayLine(y, xs, xe, isblank)
1222 int y, xs, xe, isblank;
1224 ASSERT(flayer);
1225 if (y < 0)
1227 wlistpage();
1228 return;
1230 if (y != 0 && y != flayer->l_height - 1)
1231 return;
1232 if (!isblank)
1233 LClearArea(flayer, xs, y, xe, y, 0, 0);
1236 static int
1237 WListOrder(wlistdata, ind, start, group)
1238 struct wlistdata *wlistdata;
1239 int ind, start;
1240 struct win *group;
1242 int i;
1244 if (ind >= MAXWIN)
1245 return ind;
1246 if (ind == 0)
1247 for (i = 0; i < MAXWIN; i++)
1248 wlistdata->list[i] = -1;
1250 if (wlistdata->order == WLIST_MRU)
1252 if (start == -1)
1253 start = windows->w_number;
1255 else
1257 if (start == -1)
1258 start = 0;
1259 while (start < MAXWIN && !wtab[start])
1260 start++;
1263 if (start >= MAXWIN || !wtab[start])
1264 return ind;
1266 if (!WTAB_GROUP_MATCHES(start))
1268 while (start < MAXWIN && (!wtab[start] || !WTAB_GROUP_MATCHES(start)))
1269 if (wlistdata->order != WLIST_MRU)
1270 start++;
1271 else if (wtab[start]->w_next)
1272 start = wtab[start]->w_next->w_number;
1273 else
1274 start = MAXWIN;
1275 if (start >= MAXWIN || !wtab[start])
1276 return ind;
1279 wlistdata->list[ind++] = start;
1280 if (wlistdata->nested && wtab[start]->w_type == W_TYPE_GROUP)
1281 ind = WListOrder(wlistdata, ind, -1, wtab[start]);
1283 if (wlistdata->order != WLIST_MRU)
1284 start++;
1285 else if (wtab[start]->w_next)
1286 start = wtab[start]->w_next->w_number;
1287 else
1288 return ind;
1289 return WListOrder(wlistdata, ind, start, group);
1292 void
1293 display_wlist(onblank, order, group)
1294 int onblank;
1295 int order;
1296 struct win *group;
1298 struct win *p;
1299 struct wlistdata *wlistdata;
1301 if (flayer->l_width < 10 || flayer->l_height < 6)
1303 LMsg(0, "Window size too small for window list page");
1304 return;
1306 if (onblank)
1308 debug3("flayer %x %d %x\n", flayer, flayer->l_width, flayer->l_height);
1309 if (!display)
1311 LMsg(0, "windowlist -b: display required");
1312 return;
1314 p = D_fore;
1315 if (p)
1317 SetForeWindow((struct win *)0);
1318 if (p->w_group)
1320 D_fore = p->w_group;
1321 flayer->l_data = (char *)p->w_group;
1323 Activate(0);
1325 if (flayer->l_width < 10 || flayer->l_height < 6)
1327 LMsg(0, "Window size too small for window list page");
1328 return;
1331 else
1332 p = Layer2Window(flayer);
1333 if (!group && p)
1334 group = p->w_group;
1335 if (InitOverlayPage(sizeof(*wlistdata), &WListLf, 0))
1336 return;
1337 wlistdata = (struct wlistdata *)flayer->l_data;
1338 flayer->l_x = 0;
1339 flayer->l_y = flayer->l_height - 1;
1340 wlistdata->start = onblank && p ? p->w_number : -1;
1341 wlistdata->order = (order & 0x1);
1342 wlistdata->group = group;
1343 wlistdata->pos = p ? p->w_number : WListNext(wlistdata, -1, 0);
1344 wlistdata->ypos = wlistdata->npos = 0;
1345 wlistdata->numwin = flayer->l_height - (group ? 4 : 3);
1346 wlistdata->nested = (order & WLIST_NESTED);
1347 wlistpage();
1350 static void
1351 wlistpage()
1353 struct wlistdata *wlistdata;
1354 char *str;
1355 int pos;
1356 struct win *group;
1358 wlistdata = (struct wlistdata *)flayer->l_data;
1359 group = wlistdata->group;
1361 LClearAll(flayer, 0);
1362 if (wlistdata->start >= 0 && wtab[wlistdata->start] == 0)
1363 wlistdata->start = -2;
1365 WListOrder(wlistdata, 0, -1, group);
1366 pos = wlistdata->pos;
1367 if (pos == MAXWIN || !wtab[pos] || !WTAB_GROUP_MATCHES(pos))
1369 if (wlistdata->order == WLIST_MRU)
1370 pos = WListNext(wlistdata, -1, wlistdata->npos);
1371 else
1373 /* find new position */
1374 if (pos < MAXWIN)
1375 while(++pos < MAXWIN)
1376 if (wtab[pos] && WTAB_GROUP_MATCHES(pos))
1377 break;
1378 if (pos == MAXWIN)
1379 while (--pos >= 0)
1380 if (wtab[pos] && WTAB_GROUP_MATCHES(pos))
1381 break;
1382 if (pos == -1)
1383 pos = MAXWIN;
1386 wlistdata->pos = pos;
1388 display = 0;
1389 str = MakeWinMsgEv(wlisttit, (struct win *)0, '%', flayer->l_width, (struct event *)0, 0);
1390 if (wlistdata->group)
1392 LPutWinMsg(flayer, "Group: ", 7, &mchar_blank, 0, 0);
1393 LPutWinMsg(flayer, wlistdata->group->w_title, strlen(wlistdata->group->w_title), &mchar_blank, 7, 0);
1394 LPutWinMsg(flayer, str, strlen(str), &mchar_blank, 0, 1);
1396 else
1398 LPutWinMsg(flayer, str, strlen(str), &mchar_blank, 0, 0);
1400 WListNormalize();
1401 WListLines(wlistdata->numwin, -1);
1402 LaySetCursor();
1405 static void
1406 WListUpdate(p)
1407 struct win *p;
1409 struct wlistdata *wlistdata;
1410 int i, n, y;
1412 if (p == 0)
1414 wlistpage();
1415 return;
1417 wlistdata = (struct wlistdata *)flayer->l_data;
1418 n = p->w_number;
1419 if (wlistdata->order == WLIST_NUM && (n < wlistdata->first || n > wlistdata->last))
1420 return;
1421 i = wlistdata->first;
1422 for (y = 0; y < wlistdata->numwin; y++)
1424 if (i == n)
1425 break;
1426 i = WListNext(wlistdata, i, 1);
1428 if (y == wlistdata->numwin)
1429 return;
1430 WListLine(y, i, wlistdata->pos, 0);
1431 LaySetCursor();
1434 void
1435 WListUpdatecv(cv, p)
1436 struct canvas *cv;
1437 struct win *p;
1439 if (cv->c_layer->l_layfn != &WListLf)
1440 return;
1441 CV_CALL(cv, WListUpdate(p));
1444 void
1445 WListLinkChanged()
1447 struct display *olddisplay = display;
1448 struct canvas *cv;
1449 struct wlistdata *wlistdata;
1451 for (display = displays; display; display = display->d_next)
1452 for (cv = D_cvlist; cv; cv = cv->c_next)
1454 if (!cv->c_layer || cv->c_layer->l_layfn != &WListLf)
1455 continue;
1456 wlistdata = (struct wlistdata *)cv->c_layer->l_data;
1457 if (wlistdata->order != WLIST_MRU)
1458 continue;
1459 CV_CALL(cv, WListUpdate(0));
1461 display = olddisplay;
1465 InWList()
1467 if (flayer && flayer->l_layfn == &WListLf)
1468 return 1;
1469 return 0;
1476 ** The bindkey help page
1480 #ifdef MAPKEYS
1481 extern struct kmap_ext *kmap_exts;
1482 extern int kmap_extn;
1483 extern struct action dmtab[];
1484 extern struct action mmtab[];
1487 static void BindkeyProcess __P((char **, int *));
1488 static void BindkeyAbort __P((void));
1489 static void BindkeyRedisplayLine __P((int, int, int, int));
1490 static void bindkeypage __P((void));
1492 struct bindkeydata
1494 char *title;
1495 struct action *tab;
1496 int pos;
1497 int last;
1498 int page;
1499 int pages;
1502 static struct LayFuncs BindkeyLf =
1504 BindkeyProcess,
1505 BindkeyAbort,
1506 BindkeyRedisplayLine,
1507 DefClearLine,
1508 DefRewrite,
1509 DefResize,
1510 DefRestore
1514 void
1515 display_bindkey(title, tab)
1516 char *title;
1517 struct action *tab;
1519 struct bindkeydata *bindkeydata;
1520 int i, n;
1522 if (flayer->l_height < 6)
1524 LMsg(0, "Window height too small for bindkey page");
1525 return;
1527 if (InitOverlayPage(sizeof(*bindkeydata), &BindkeyLf, 0))
1528 return;
1530 bindkeydata = (struct bindkeydata *)flayer->l_data;
1531 bindkeydata->title = title;
1532 bindkeydata->tab = tab;
1534 n = 0;
1535 for (i = 0; i < KMAP_KEYS+KMAP_AKEYS+kmap_extn; i++)
1537 if (tab[i].nr != RC_ILLEGAL)
1538 n++;
1540 bindkeydata->pos = 0;
1541 bindkeydata->page = 1;
1542 bindkeydata->pages = (n + flayer->l_height - 6) / (flayer->l_height - 5);
1543 if (bindkeydata->pages == 0)
1544 bindkeydata->pages = 1;
1545 flayer->l_x = 0;
1546 flayer->l_y = flayer->l_height - 1;
1547 bindkeypage();
1550 static void
1551 BindkeyAbort()
1553 LAY_CALL_UP(LRefreshAll(flayer, 0));
1554 ExitOverlayPage();
1557 static void
1558 bindkeypage()
1560 struct bindkeydata *bindkeydata;
1561 struct kmap_ext *kme;
1562 char tbuf[256];
1563 int del, i, y, sl;
1564 struct action *act;
1565 char *xch, *s, *p;
1567 bindkeydata = (struct bindkeydata *)flayer->l_data;
1569 LClearAll(flayer, 0);
1571 sprintf(tbuf, "%s key bindings, page %d of %d.", bindkeydata->title, bindkeydata->page, bindkeydata->pages);
1572 centerline(tbuf, 0);
1573 y = 2;
1574 for (i = bindkeydata->pos; i < KMAP_KEYS+KMAP_AKEYS+kmap_extn && y < flayer->l_height - 3; i++)
1576 p = tbuf;
1577 xch = " ";
1578 if (i < KMAP_KEYS)
1580 act = &bindkeydata->tab[i];
1581 if (act->nr == RC_ILLEGAL)
1582 continue;
1583 del = *p++ = ':';
1584 s = term[i + T_CAPS].tcname;
1585 sl = s ? strlen(s) : 0;
1587 else if (i < KMAP_KEYS+KMAP_AKEYS)
1589 act = &bindkeydata->tab[i];
1590 if (act->nr == RC_ILLEGAL)
1591 continue;
1592 del = *p++ = ':';
1593 s = term[i + (T_CAPS - T_OCAPS + T_CURSOR)].tcname;
1594 sl = s ? strlen(s) : 0;
1595 xch = "[A]";
1597 else
1599 kme = kmap_exts + (i - (KMAP_KEYS+KMAP_AKEYS));
1600 del = 0;
1601 s = kme->str;
1602 sl = kme->fl & ~KMAP_NOTIMEOUT;
1603 if ((kme->fl & KMAP_NOTIMEOUT) != 0)
1604 xch = "[T]";
1605 act = bindkeydata->tab == dmtab ? &kme->dm : bindkeydata->tab == mmtab ? &kme->mm : &kme->um;
1606 if (act->nr == RC_ILLEGAL)
1607 continue;
1609 while (sl-- > 0)
1610 p += AddXChar(p, *(unsigned char *)s++);
1611 if (del)
1612 *p++ = del;
1613 *p++ = ' ';
1614 while (p < tbuf + 15)
1615 *p++ = ' ';
1616 sprintf(p, "%s -> ", xch);
1617 p += 7;
1618 if (p - tbuf > flayer->l_width - 1)
1620 tbuf[flayer->l_width - 2] = '$';
1621 tbuf[flayer->l_width - 1] = 0;
1623 PadStr(tbuf, strlen(tbuf), 0, y);
1624 AddAction(act, strlen(tbuf), y);
1625 y++;
1627 y++;
1628 bindkeydata->last = i;
1629 sprintf(tbuf,"[Press Space %s Return to end.]", bindkeydata->page < bindkeydata->pages ? "for next page;" : "or");
1630 centerline(tbuf, flayer->l_height - 2);
1631 LaySetCursor();
1634 static void
1635 BindkeyProcess(ppbuf, plen)
1636 char **ppbuf;
1637 int *plen;
1639 int done = 0;
1640 struct bindkeydata *bindkeydata;
1642 bindkeydata = (struct bindkeydata *)flayer->l_data;
1643 while (!done && *plen > 0)
1645 switch (**ppbuf)
1647 case ' ':
1648 if (bindkeydata->page < bindkeydata->pages)
1650 bindkeydata->pos = bindkeydata->last;
1651 bindkeydata->page++;
1652 bindkeypage();
1653 break;
1655 /* FALLTHROUGH */
1656 case '\r':
1657 case '\n':
1658 done = 1;
1659 break;
1660 default:
1661 break;
1663 ++*ppbuf;
1664 --*plen;
1666 if (done)
1667 BindkeyAbort();
1670 static void
1671 BindkeyRedisplayLine(y, xs, xe, isblank)
1672 int y, xs, xe, isblank;
1674 if (y < 0)
1676 bindkeypage();
1677 return;
1679 if (y != 0 && y != flayer->l_height - 1)
1680 return;
1681 if (!isblank)
1682 LClearArea(flayer, xs, y, xe, y, 0, 0);
1685 #endif /* MAPKEYS */
1690 ** The zmodem active page
1694 #ifdef ZMODEM
1696 static void ZmodemRedisplayLine __P((int, int, int, int));
1697 static int ZmodemResize __P((int, int));
1699 static struct LayFuncs ZmodemLf =
1701 DefProcess,
1703 ZmodemRedisplayLine,
1704 DefClearLine,
1705 DefRewrite,
1706 ZmodemResize,
1707 DefRestore
1710 /*ARGSUSED*/
1711 static int
1712 ZmodemResize(wi, he)
1713 int wi, he;
1715 flayer->l_width = wi;
1716 flayer->l_height = he;
1717 flayer->l_x = flayer->l_width > 32 ? 32 : 0;
1718 return 0;
1721 static void
1722 ZmodemRedisplayLine(y, xs, xe, isblank)
1723 int y, xs, xe, isblank;
1725 DefRedisplayLine(y, xs, xe, isblank);
1726 if (y == 0 && xs == 0)
1727 LPutStr(flayer, "Zmodem active on another display", flayer->l_width > 32 ? 32 : flayer->l_width, &mchar_blank, 0, 0);
1730 void
1731 ZmodemPage()
1733 if (InitOverlayPage(1, &ZmodemLf, 1))
1734 return;
1735 LRefreshAll(flayer, 0);
1736 flayer->l_x = flayer->l_width > 32 ? 32 : 0;
1737 flayer->l_y = 0;
1740 #endif
1744 static void
1745 PadStr(str, n, x, y)
1746 char *str;
1747 int n, x, y;
1749 int l;
1751 l = strlen(str);
1752 if (l > n)
1753 l = n;
1754 LPutStr(flayer, str, l, &mchar_blank, x, y);
1755 if (l < n)
1756 LPutStr(flayer, (char *)blank, n - l, &mchar_blank, x + l, y);