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)
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>
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
[];
47 extern struct term term
[];
50 static void PadStr
__P((char *, int, int, int));
52 extern char *wliststr
;
53 extern char *wlisttit
;
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");
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");
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
);
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");
90 printf("-U Tell screen to use UTF-8 encoding.\n");
92 printf("-v Print \"Screen version %s\".\n", version
);
93 printf("-wipe Do nothing, just clean up SockDir.\n");
95 printf("-x Attach to a not detached screen. (Multi display mode).\n");
97 printf("-X Execute <cmd> as a screen command in the specified session.\n");
98 if (message
&& *message
)
101 printf(message
, arg
);
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));
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];
135 static struct LayFuncs HelpLf
=
148 display_help(class, ktabp
)
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");
161 if (InitOverlayPage(sizeof(*helpdata
), &HelpLf
, 0))
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
++)
173 for (key
= 0; key
< 256 + KMAP_KEYS
; key
++)
178 if (ktabp
[key
].args
== noargs
)
180 used
[n
] += (key
<= ' ' || key
== 0x7f) ? 3 :
181 (key
> 0x7f) ? 5 : 2;
184 helpdata
->command_bindings
++;
186 for (n
= i
= 0; n
<= RC_LAST
; n
++)
189 l
= strlen(comms
[n
].name
);
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
;
202 helpdata
->numcols
= flayer
->l_width
/ (mcom
+ mkey
+ 1);
203 if (helpdata
->numcols
== 0)
206 LMsg(0, "Width too small");
209 helpdata
->inter
= (flayer
->l_width
- (mcom
+ mkey
) * helpdata
->numcols
) / (helpdata
->numcols
+ 1);
210 if (helpdata
->inter
<= 0)
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
;
227 helpdata
->numpages
= (helpdata
->maxrow
+ flayer
->l_height
-6) / (flayer
->l_height
-5);
229 flayer
->l_y
= flayer
->l_height
- 1;
234 HelpProcess(ppbuf
, plen
)
240 while (!done
&& *plen
> 0)
265 LAY_CALL_UP(LRefreshAll(flayer
, 0));
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
)
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
);
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
);
303 strcpy(Esc_buf
, "??");
307 for (; crow
< flayer
->l_height
- 3; crow
++)
309 if (helpdata
->grow
< 1)
312 sprintf(cbuf
,"Command key: %s Literal %s: %s", Esc_buf
, Esc_buf
, buf
);
314 sprintf(cbuf
,"Command class: '%.80s'", helpdata
->class);
315 centerline(cbuf
, crow
);
318 else if (helpdata
->grow
>= 2 && helpdata
->grow
-2 < helpdata
->numrows
)
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
];
326 for (key
= 0; key
< 256 + KMAP_KEYS
; key
++)
327 if (ktabp
[key
].nr
== n
&& ktabp
[key
].args
== noargs
&& strlen(buf
) < sizeof(buf
) - 7)
330 add_key_to_buf(buf
, key
);
332 PadStr(comms
[n
].name
, helpdata
->mcom
, x
, crow
);
334 PadStr(buf
, helpdata
->mkey
, x
, crow
);
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
)
349 add_key_to_buf(buf
, helpdata
->command_search
);
350 PadStr(buf
, 5, 0, crow
);
351 AddAction(&ktabp
[helpdata
->command_search
++], 5, crow
);
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);
374 struct mchar mchar_dol
;
376 mchar_dol
= mchar_blank
;
377 mchar_dol
.image
= '$';
379 fr
= flayer
->l_width
- 1 - x
;
382 l
= strlen(comms
[act
->nr
].name
);
386 PadStr(comms
[act
->nr
].name
, l
, x
, y
);
389 LPutChar(flayer
, fr
? &mchar_blank
: &mchar_dol
, x
++, y
);
393 while (pp
&& (cp
= *pp
) != NULL
)
398 if (!ll
|| (index(cp
, ' ') != NULL
))
400 if (index(cp
, '\'') != NULL
)
405 while (ll
-- && bp
< buf
+ 250)
406 bp
+= AddXChar(bp
, *(unsigned char *)cp
++);
410 if ((fr
-= (bp
- buf
) + 1) < 0)
414 PadStr(buf
, fr
, x
, y
);
416 LPutChar(flayer
, &mchar_dol
, x
, y
);
419 PadStr(buf
, strlen(buf
), x
, y
);
423 LPutChar(flayer
, fr
? &mchar_blank
: &mchar_dol
, x
++, y
);
428 add_key_to_buf(buf
, key
)
434 strcpy(buf
, "unset");
440 key
= key
- 256 + T_CAPS
;
442 buf
[1] = term
[key
].tcname
[0];
443 buf
[2] = term
[key
].tcname
[1];
449 buf
[AddXChar(buf
, key
)] = 0;
454 HelpRedisplayLine(y
, xs
, xe
, isblank
)
455 int y
, xs
, xe
, isblank
;
459 struct helpdata
*helpdata
;
461 helpdata
= (struct helpdata
*)flayer
->l_data
;
462 helpdata
->grow
= helpdata
->refgrow
;
463 helpdata
->command_search
= helpdata
->refcommand_search
;
467 if (y
!= 0 && y
!= flayer
->l_height
- 1)
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));
487 char *cps
, *savedcps
; /* position in the message */
488 char *refcps
, *refsavedcps
; /* backup for redisplaying */
491 static struct LayFuncs CopyrightLf
=
495 CopyrightRedisplayLine
,
502 static const char cpmsg
[] = "\
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";
530 CopyrightProcess(ppbuf
, plen
)
535 struct copydata
*copydata
;
537 copydata
= (struct copydata
*)flayer
->l_data
;
538 while (!done
&& *plen
> 0)
565 LAY_CALL_UP(LRefreshAll(flayer
, 0));
572 struct copydata
*copydata
;
574 if (flayer
->l_width
< 10 || flayer
->l_height
< 5)
576 LMsg(0, "Window size too small for copyright page");
579 if (InitOverlayPage(sizeof(*copydata
), &CopyrightLf
, 0))
581 copydata
= (struct copydata
*)flayer
->l_data
;
582 copydata
->cps
= (char *)cpmsg
;
583 copydata
->savedcps
= 0;
585 flayer
->l_y
= flayer
->l_height
- 1;
596 struct copydata
*copydata
;
599 copydata
= (struct copydata
*)flayer
->l_data
;
601 LClearAll(flayer
, 0);
604 copydata
->refcps
= cps
;
605 copydata
->refsavedcps
= copydata
->savedcps
;
606 while (*cps
&& y
< flayer
->l_height
- 3)
611 if (strncmp(cps
, "%v", 2) == 0)
613 copydata
->savedcps
= cps
+ 2;
617 while (*cps
&& *cps
!= ' ' && *cps
!= '\n')
621 if (l
> flayer
->l_width
- 1)
622 l
= flayer
->l_width
- 1;
623 if (x
&& x
+ l
>= flayer
->l_width
- 2)
631 LPutChar(flayer
, &mchar_blank
, x
, y
);
635 LPutStr(flayer
, ws
, l
, &mchar_blank
, x
, y
);
638 if (*cps
== 0 && copydata
->savedcps
)
640 cps
= copydata
->savedcps
;
641 copydata
->savedcps
= 0;
648 if (*cps
== ' ' || *cps
== '\n')
653 sprintf(cbuf
,"[Press Space %s Return to end.]",
654 *cps
? "for next page;" : "or");
655 centerline(cbuf
, flayer
->l_height
- 2);
661 CopyrightRedisplayLine(y
, xs
, xe
, isblank
)
662 int y
, xs
, xe
, isblank
;
667 struct copydata
*copydata
;
669 copydata
= (struct copydata
*)flayer
->l_data
;
670 copydata
->cps
= copydata
->refcps
;
671 copydata
->savedcps
= copydata
->refsavedcps
;
675 if (y
!= 0 && y
!= flayer
->l_height
- 1)
679 LClearArea(flayer
, xs
, y
, xe
, y
, 0, 0);
686 ** here is all the displays stuff
692 static void DisplaysProcess
__P((char **, int *));
693 static void DisplaysRedisplayLine
__P((int, int, int, int));
694 static void displayspage
__P((void));
698 int dummy_element_for_solaris
;
701 static struct LayFuncs DisplaysLf
=
705 DisplaysRedisplayLine
,
713 DisplaysProcess(ppbuf
, plen
)
720 while (!done
&& *plen
> 0)
744 if (flayer
->l_width
< 10 || flayer
->l_height
< 5)
746 LMsg(0, "Window size too small for displays page");
749 if (InitOverlayPage(sizeof(struct displaysdata
), &DisplaysLf
, 0))
752 flayer
->l_y
= flayer
->l_height
- 1;
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.
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);
792 for (d
= displays
; d
; d
= d
->d_next
)
796 if (y
>= flayer
->l_height
- 3)
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
,
801 (d
->d_blocked
|| d
->d_nonblock
>= 0) && d
->d_blocked
<= 4 ? blockstates
[d
->d_blocked
] : " ");
805 l
= 10 - strlen(w
->w_title
);
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 ? '&' : ' ',
813 * -,r,R no read, read, read only due to foreign wlock
814 * -,.,w,W no write, write suppressed by foreign wlock,
816 * -,x no execute, execute
819 (AclCheckPermWin(d
->d_user
, ACL_READ
, w
) ? '-' :
820 ((w
->w_wlock
== WLOCK_OFF
|| d
->d_user
== w
->w_wlockuser
) ?
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')
834 sprintf(tbuf
,"[Press Space %s Return to end.]",
835 1 ? "to refresh;" : "or");
836 centerline(tbuf
, flayer
->l_height
- 2);
841 DisplaysRedisplayLine(y
, xs
, xe
, isblank
)
842 int y
, xs
, xe
, isblank
;
850 if (y
!= 0 && y
!= flayer
->l_height
- 1)
854 LClearArea(flayer
, xs
, y
, xe
, y
, 0, 0);
855 /* To be filled in... */
863 ** here is the windowlist
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));
894 static struct LayFuncs WListLf
=
905 #define WTAB_GROUP_MATCHES(i) (group == wtab[i]->w_group)
911 struct wlistdata
*wlistdata
;
912 if (wi
< 10 || he
< 5)
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;
925 WListProcess(ppbuf
, plen
)
930 struct wlistdata
*wlistdata
;
931 struct display
*olddisplay
= display
;
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';
945 if (n
< MAXWIN
&& wtab
[n
] && WTAB_GROUP_MATCHES(n
))
948 for (d
= -wlistdata
->npos
, i
= WListNext(wlistdata
, -1, 0); i
!= n
; i
= WListNext(wlistdata
, i
, 1), d
++)
954 switch ((unsigned char)**ppbuf
)
957 case 16: /* ^P like emacs */
961 case 0216: /* down */
962 case 14: /* ^N like emacs */
967 WListMove(-(h
/ 2), wlistdata
->ypos
);
970 WListMove(h
/ 2, wlistdata
->ypos
);
980 case 0201: /* home */
981 WListMove(-wlistdata
->pos
, -1);
984 WListMove(MAXWIN
, -1);
987 /* All-window view */
988 wlistdata
->group
= 0;
989 wlistdata
->nested
= WLIST_NESTED
;
993 /* Toggle nested view */
994 wlistdata
->nested
^= WLIST_NESTED
;
998 /* Toggle MRU view */
999 wlistdata
->order
^= 1;
1006 if (h
== MAXWIN
&& Layer2Window(flayer
) && Layer2Window(flayer
)->w_type
== W_TYPE_GROUP
)
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
;
1016 if (!display
|| h
== MAXWIN
|| !wtab
[h
] || wtab
[h
] == D_fore
|| (flayer
->l_cvlist
&& flayer
->l_cvlist
->c_lnext
))
1019 else if (AclCheckPermWin(D_user
, ACL_READ
, wtab
[h
]))
1023 ExitOverlayPage(); /* no need to redisplay */
1024 /* restore display, don't switch wrong user */
1025 display
= olddisplay
;
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
;
1043 display
= olddisplay
;
1044 if (h
>= 0 && wtab
[h
])
1048 struct win
*p
= FindNiceWindow(display
? D_other
: (struct win
*)0, 0);
1050 SwitchWindow(p
->w_number
);
1054 case '\010': /* ctrl-h */
1056 if (!wlistdata
->group
)
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
;
1073 WListLine(y
, i
, pos
, isblank
)
1081 struct wlistdata
*wlistdata
;
1083 struct mchar mchar_rend
= mchar_blank
;
1084 struct mchar
*mchar
= (struct mchar
*)0;
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);
1097 if (i
!= pos
&& isblank
)
1098 while (n
&& str
[n
- 1] == ' ')
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
);
1113 mchar
= &mchar_blank
;
1114 LPutWinMsg(flayer
, str
, (i
== pos
|| !isblank
) ? flayer
->l_width
: n
, mchar
, xoff
, y
+ yoff
);
1116 LPutWinMsg(flayer
, "", xoff
, mchar
, 0, y
+ yoff
);
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
);
1128 WListNext(wlistdata
, old
, delta
)
1129 struct wlistdata
*wlistdata
;
1140 for (i
= 0; i
< MAXWIN
&& wlistdata
->list
[i
] != -1; i
++)
1141 if (wlistdata
->list
[i
] == old
)
1143 if (i
< MAXWIN
&& wlistdata
->list
[i
] != -1)
1148 if (old
< 0 || old
>= MAXWIN
|| wlistdata
->list
[old
] == -1)
1150 return wlistdata
->list
[old
];
1154 WListLines(up
, oldpos
)
1157 struct wlistdata
*wlistdata
;
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
])
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
);
1176 wlistdata
->ypos
= y
;
1178 i
= WListNext(wlistdata
, i
, 1);
1179 if (i
== MAXWIN
|| i
== oldi
)
1187 struct wlistdata
*wlistdata
;
1191 wlistdata
= (struct wlistdata
*)flayer
->l_data
;
1192 ypos
= wlistdata
->ypos
;
1193 pos
= wlistdata
->pos
;
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))
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))
1206 wlistdata
->ypos
= ypos
;
1207 wlistdata
->npos
= n
;
1212 WListMove(num
, ypos
)
1216 struct wlistdata
*wlistdata
;
1217 int oldpos
, oldypos
, oldnpos
;
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
);
1231 LScrollV(flayer
, up
, 2, 2 + wlistdata
->numwin
- 1, 0);
1232 WListLines(up
, oldpos
);
1238 WListLine(oldypos
, oldpos
, pos
, 0);
1239 WListLine(ypos
, pos
, pos
, 1);
1244 WListRedisplayLine(y
, xs
, xe
, isblank
)
1245 int y
, xs
, xe
, isblank
;
1253 if (y
!= 0 && y
!= flayer
->l_height
- 1)
1256 LClearArea(flayer
, xs
, y
, xe
, y
, 0, 0);
1260 WListOrder(wlistdata
, ind
, start
, group
)
1261 struct wlistdata
*wlistdata
;
1270 for (i
= 0; i
< MAXWIN
; i
++)
1271 wlistdata
->list
[i
] = -1;
1273 if (wlistdata
->order
== WLIST_MRU
)
1276 start
= windows
->w_number
;
1282 while (start
< MAXWIN
&& !wtab
[start
])
1286 if (start
>= MAXWIN
|| !wtab
[start
])
1289 if (!WTAB_GROUP_MATCHES(start
))
1291 while (start
< MAXWIN
&& (!wtab
[start
] || !WTAB_GROUP_MATCHES(start
)))
1292 if (wlistdata
->order
!= WLIST_MRU
)
1294 else if (wtab
[start
]->w_next
)
1295 start
= wtab
[start
]->w_next
->w_number
;
1298 if (start
>= MAXWIN
|| !wtab
[start
])
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
)
1308 else if (wtab
[start
]->w_next
)
1309 start
= wtab
[start
]->w_next
->w_number
;
1312 return WListOrder(wlistdata
, ind
, start
, group
);
1316 display_wlist(onblank
, order
, group
)
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");
1331 debug3("flayer %x %d %x\n", flayer
, flayer
->l_width
, flayer
->l_height
);
1334 LMsg(0, "windowlist -b: display required");
1340 SetForeWindow((struct win
*)0);
1343 D_fore
= p
->w_group
;
1344 flayer
->l_data
= (char *)p
->w_group
;
1348 if (flayer
->l_width
< 10 || flayer
->l_height
< 6)
1350 LMsg(0, "Window size too small for window list page");
1355 p
= Layer2Window(flayer
);
1358 if (InitOverlayPage(sizeof(*wlistdata
), &WListLf
, 0))
1360 wlistdata
= (struct wlistdata
*)flayer
->l_data
;
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
);
1376 struct wlistdata
*wlistdata
;
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
);
1396 /* find new position */
1398 while(++pos
< MAXWIN
)
1399 if (wtab
[pos
] && WTAB_GROUP_MATCHES(pos
))
1403 if (wtab
[pos
] && WTAB_GROUP_MATCHES(pos
))
1409 wlistdata
->pos
= pos
;
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);
1421 LPutWinMsg(flayer
, str
, strlen(str
), &mchar_blank
, 0, 0);
1424 WListLines(wlistdata
->numwin
, -1);
1432 struct wlistdata
*wlistdata
;
1440 wlistdata
= (struct wlistdata
*)flayer
->l_data
;
1442 if (wlistdata
->order
== WLIST_NUM
&& (n
< wlistdata
->first
|| n
> wlistdata
->last
))
1444 i
= wlistdata
->first
;
1445 for (y
= 0; y
< wlistdata
->numwin
; y
++)
1449 i
= WListNext(wlistdata
, i
, 1);
1451 if (y
== wlistdata
->numwin
)
1453 WListLine(y
, i
, wlistdata
->pos
, 0);
1458 WListUpdatecv(cv
, p
)
1462 if (cv
->c_layer
->l_layfn
!= &WListLf
)
1464 CV_CALL(cv
, WListUpdate(p
));
1470 struct display
*olddisplay
= display
;
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
)
1479 wlistdata
= (struct wlistdata
*)cv
->c_layer
->l_data
;
1480 if (wlistdata
->order
!= WLIST_MRU
)
1482 CV_CALL(cv
, WListUpdate(0));
1484 display
= olddisplay
;
1490 if (flayer
&& flayer
->l_layfn
== &WListLf
)
1499 ** The bindkey help page
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));
1525 static struct LayFuncs BindkeyLf
=
1529 BindkeyRedisplayLine
,
1538 display_bindkey(title
, tab
)
1542 struct bindkeydata
*bindkeydata
;
1545 if (flayer
->l_height
< 6)
1547 LMsg(0, "Window height too small for bindkey page");
1550 if (InitOverlayPage(sizeof(*bindkeydata
), &BindkeyLf
, 0))
1553 bindkeydata
= (struct bindkeydata
*)flayer
->l_data
;
1554 bindkeydata
->title
= title
;
1555 bindkeydata
->tab
= tab
;
1558 for (i
= 0; i
< KMAP_KEYS
+KMAP_AKEYS
+kmap_extn
; i
++)
1560 if (tab
[i
].nr
!= RC_ILLEGAL
)
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;
1569 flayer
->l_y
= flayer
->l_height
- 1;
1576 LAY_CALL_UP(LRefreshAll(flayer
, 0));
1583 struct bindkeydata
*bindkeydata
;
1584 struct kmap_ext
*kme
;
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);
1597 for (i
= bindkeydata
->pos
; i
< KMAP_KEYS
+KMAP_AKEYS
+kmap_extn
&& y
< flayer
->l_height
- 3; i
++)
1603 act
= &bindkeydata
->tab
[i
];
1604 if (act
->nr
== RC_ILLEGAL
)
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
)
1616 s
= term
[i
+ (T_CAPS
- T_OCAPS
+ T_CURSOR
)].tcname
;
1617 sl
= s
? strlen(s
) : 0;
1622 kme
= kmap_exts
+ (i
- (KMAP_KEYS
+KMAP_AKEYS
));
1625 sl
= kme
->fl
& ~KMAP_NOTIMEOUT
;
1626 if ((kme
->fl
& KMAP_NOTIMEOUT
) != 0)
1628 act
= bindkeydata
->tab
== dmtab
? &kme
->dm
: bindkeydata
->tab
== mmtab
? &kme
->mm
: &kme
->um
;
1629 if (act
->nr
== RC_ILLEGAL
)
1633 p
+= AddXChar(p
, *(unsigned char *)s
++);
1637 while (p
< tbuf
+ 15)
1639 sprintf(p
, "%s -> ", xch
);
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
);
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);
1658 BindkeyProcess(ppbuf
, plen
)
1663 struct bindkeydata
*bindkeydata
;
1665 bindkeydata
= (struct bindkeydata
*)flayer
->l_data
;
1666 while (!done
&& *plen
> 0)
1671 if (bindkeydata
->page
< bindkeydata
->pages
)
1673 bindkeydata
->pos
= bindkeydata
->last
;
1674 bindkeydata
->page
++;
1694 BindkeyRedisplayLine(y
, xs
, xe
, isblank
)
1695 int y
, xs
, xe
, isblank
;
1702 if (y
!= 0 && y
!= flayer
->l_height
- 1)
1705 LClearArea(flayer
, xs
, y
, xe
, y
, 0, 0);
1708 #endif /* MAPKEYS */
1713 ** The zmodem active page
1719 static void ZmodemRedisplayLine
__P((int, int, int, int));
1720 static int ZmodemResize
__P((int, int));
1722 static struct LayFuncs ZmodemLf
=
1726 ZmodemRedisplayLine
,
1735 ZmodemResize(wi
, he
)
1738 flayer
->l_width
= wi
;
1739 flayer
->l_height
= he
;
1740 flayer
->l_x
= flayer
->l_width
> 32 ? 32 : 0;
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);
1756 if (InitOverlayPage(1, &ZmodemLf
, 1))
1758 LRefreshAll(flayer
, 0);
1759 flayer
->l_x
= flayer
->l_width
> 32 ? 32 : 0;
1768 PadStr(str
, n
, x
, y
)
1777 LPutStr(flayer
, str
, l
, &mchar_blank
, x
, y
);
1779 LPutStr(flayer
, (char *)blank
, n
- l
, &mchar_blank
, x
+ l
, y
);