home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume27 / screen-3.5.1 / part02 / help.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-08-08  |  14.8 KB  |  626 lines

  1. /* Copyright (c) 1993
  2.  *      Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
  3.  *      Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
  4.  * Copyright (c) 1987 Oliver Laumann
  5.  *
  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 2, or (at your option)
  9.  * any later version.
  10.  *
  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.
  15.  *
  16.  * You should have received a copy of the GNU General Public License
  17.  * along with this program (see the file COPYING); if not, write to the
  18.  * Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19.  *
  20.  ****************************************************************
  21.  */
  22.  
  23. #include "rcs.h"
  24. RCS_ID("$Id: help.c,v 1.4 1993/08/05 14:23:47 mlschroe Exp $ FAU")
  25.  
  26. #include <stdio.h>
  27. #include <sys/types.h>
  28.  
  29. #include "config.h"
  30.  
  31. #include "screen.h"
  32. #include "extern.h"
  33.  
  34. char version[40];      /* initialised by main() */
  35.  
  36. extern struct display *display;
  37. extern char *noargs[];
  38.  
  39.  
  40. void
  41. exit_with_usage(myname)
  42. char *myname;
  43. {
  44.   printf("Use: %s [-opts] [cmd [args]]\n", myname);
  45.   printf(" or: %s -r [host.tty]\n\nOptions:\n", myname);
  46.   printf("-a           Force all capabilities into each window's termcap.\n");
  47.   printf("-A -[r|R]    Adapt all windows to the new display width & height.\n");
  48.   printf("-c file      Read configuration file instead of '.screenrc'.\n");
  49. #ifdef REMOTE_DETACH
  50.   printf("-d (-r)      Detach the elsewhere running screen (and reattach here).\n");
  51.   printf("-D (-r)      Detach and logout remote (and reattach here).\n");
  52. #endif
  53.   printf("-e xy        Change command characters.\n");
  54.   printf("-f           Flow control on, -fn = off, -fa = auto.\n");
  55.   printf("-h lines     Set the size of the scrollback history buffer.\n");
  56.   printf("-i           Interrupt output sooner when flow control is on.\n");
  57. #ifdef LOGOUTOK
  58.   printf("-l           Login mode on (update %s), -ln = off.\n", UTMPFILE);
  59. #endif
  60.   printf("-list        or -ls. Do nothing, just list our SockDir.\n");
  61.   printf("-L           Terminal's last character can be safely updated.\n");
  62.   printf("-m           ignore $STY variable, do create a new screen session.\n");
  63.   printf("-O           Choose optimal output rather than exact vt100 emulation.\n");
  64.   printf("-q           Quiet startup. Exits with non-zero return code if unsuccessful.\n");
  65.   printf("-r           Reattach to a detached screen process.\n");
  66.   printf("-R           Reattach if possible, otherwise start a new session.\n");
  67.   printf("-s shell     Shell to execute rather than $SHELL.\n");
  68.   printf("-S sockname  Name this session <pid>.sockname instead of <pid>.<tty>.<host>.\n");
  69.   printf("-t title     Set title. (window's name).\n");
  70.   printf("-T term      Use term as $TERM for windows, rather than \"screen\".\n");
  71.   printf("-v           Print \"Screen version %s\".\n", version);
  72.   printf("-wipe        Do nothing, just clean up SockDir.\n");
  73. #ifdef MULTI
  74.   printf("-x           Attach to a not detached screen. (Multi display mode).\n");
  75. #endif /* MULTI */
  76.   exit(1);
  77. }
  78.  
  79.  
  80. /*
  81. **   Here come the help page routines
  82. */
  83.  
  84. extern struct comm comms[];
  85. extern struct action ktab[];
  86.  
  87. static void HelpProcess __P((char **, int *));
  88. static void HelpAbort __P((void));
  89. static void HelpRedisplayLine __P((int, int, int, int));
  90. static void HelpSetCursor __P((void));
  91. static void add_key_to_buf __P((char *, int));
  92. static int  helppage __P((void));
  93.  
  94. struct helpdata
  95. {
  96.   int    maxrow, grow, numcols, numrows, num_names;
  97.   int    numskip, numpages;
  98.   int    command_search, command_bindings;
  99.   int   refgrow, refcommand_search;
  100.   int   inter, mcom, mkey;
  101.   int   nact[RC_LAST + 1];
  102. };
  103.  
  104. #define MAXKLEN 256
  105.  
  106. static struct LayFuncs HelpLf =
  107. {
  108.   HelpProcess,
  109.   HelpAbort,
  110.   HelpRedisplayLine,
  111.   DefClearLine,
  112.   DefRewrite,
  113.   HelpSetCursor,
  114.   DefResize,
  115.   DefRestore
  116. };
  117.  
  118.  
  119. void
  120. display_help()
  121. {
  122.   int i, n, key, mcom, mkey, l;
  123.   struct helpdata *helpdata;
  124.   int used[RC_LAST + 1];
  125.  
  126.   if (d_height < 6)
  127.     {
  128.       Msg(0, "Window height too small for help page");
  129.       return;
  130.     }
  131.   if (InitOverlayPage(sizeof(*helpdata), &HelpLf, 0))
  132.     return;
  133.  
  134.   helpdata = (struct helpdata *)d_lay->l_data;
  135.   helpdata->num_names = helpdata->command_bindings = 0;
  136.   helpdata->command_search = 0;
  137.   for (n = 0; n <= RC_LAST; n++)
  138.     used[n] = 0;
  139.   mcom = 0;
  140.   mkey = 0;
  141.   for (key = 0; key < 256; key++)
  142.     {
  143.       n = ktab[key].nr;
  144.       if (n == RC_ILLEGAL)
  145.     continue;
  146.       if (ktab[key].args == noargs)
  147.     {
  148.           used[n] += (key <= ' ' || key == 0x7f) ? 3 :
  149.                      (key > 0x7f) ? 5 : 2;
  150.     }
  151.       else
  152.     helpdata->command_bindings++;
  153.     }
  154.   for (n = i = 0; n <= RC_LAST; n++)
  155.     if (used[n])
  156.       {
  157.     l = strlen(comms[n].name);
  158.     if (l > mcom)
  159.       mcom = l;
  160.     if (used[n] > mkey)
  161.       mkey = used[n];
  162.         helpdata->nact[i++] = n;
  163.       }
  164.   debug1("help: %d commands bound to keys with no arguments\n", i);
  165.   debug2("mcom: %d  mkey: %d\n", mcom, mkey);
  166.   helpdata->num_names = i;
  167.  
  168.   if (mkey > MAXKLEN)
  169.     mkey = MAXKLEN;
  170.   helpdata->numcols = (d_width - !CLP)/(mcom + mkey + 1);
  171.   if (helpdata->numcols == 0)
  172.     {
  173.       HelpAbort();
  174.       Msg(0, "Width too small");
  175.       return;
  176.     }
  177.   helpdata->inter = (d_width - !CLP - (mcom + mkey) * helpdata->numcols) / (helpdata->numcols + 1);
  178.   if (helpdata->inter <= 0)
  179.     helpdata->inter = 1;
  180.   debug1("inter: %d\n", helpdata->inter);
  181.   helpdata->mcom = mcom;
  182.   helpdata->mkey = mkey;
  183.   helpdata->numrows = (helpdata->num_names + helpdata->numcols - 1) / helpdata->numcols;
  184.   debug1("Numrows: %d\n", helpdata->numrows);
  185.   helpdata->numskip = d_height-5 - (2 + helpdata->numrows);
  186.   while (helpdata->numskip < 0)
  187.     helpdata->numskip += d_height-5;
  188.   helpdata->numskip %= d_height-5;
  189.   debug1("Numskip: %d\n", helpdata->numskip);
  190.   if (helpdata->numskip > d_height/3 || helpdata->numskip > helpdata->command_bindings)
  191.     helpdata->numskip = 1;
  192.   helpdata->maxrow = 2 + helpdata->numrows + helpdata->numskip + helpdata->command_bindings;
  193.   helpdata->grow = 0;
  194.  
  195.   helpdata->numpages = (helpdata->maxrow + d_height-6) / (d_height-5);
  196.   helppage();
  197. }
  198.  
  199. static void
  200. HelpSetCursor()
  201. {
  202.   GotoPos(0, d_height - 1);
  203. }
  204.  
  205. static void
  206. HelpProcess(ppbuf, plen)
  207. char **ppbuf;
  208. int *plen;
  209. {
  210.   int done = 0;
  211.  
  212.   GotoPos(0, d_height-1);
  213.   while (!done && *plen > 0)
  214.     {
  215.       switch (**ppbuf)
  216.     {
  217.     case ' ':
  218.       if (helppage() == 0)
  219.             break;
  220.       /* FALLTHROUGH */
  221.     case '\r':
  222.     case '\n':
  223.       done = 1;
  224.       break;
  225.     default:
  226.       break;
  227.     }
  228.       ++*ppbuf;
  229.       --*plen;
  230.     }
  231.   if (done)
  232.     HelpAbort();
  233. }
  234.  
  235. static void
  236. HelpAbort()
  237. {
  238.   LAY_CALL_UP(Activate(0));
  239.   ExitOverlayPage();
  240. }
  241.  
  242.  
  243. static int
  244. helppage()
  245. {
  246.   struct helpdata *helpdata;
  247.   int col, crow, n, key;
  248.   char buf[MAXKLEN], Esc_buf[5], cbuf[256];
  249.  
  250.   helpdata = (struct helpdata *)d_lay->l_data;
  251.  
  252.   if (helpdata->grow >= helpdata->maxrow)
  253.     { 
  254.       return(-1);
  255.     }
  256.   helpdata->refgrow = helpdata->grow;
  257.   helpdata->refcommand_search = helpdata->command_search;
  258.  
  259.   /* Clear the help screen */
  260.   SetAttrFont(0, ASCII);
  261.   ClearDisplay();
  262.   
  263.   sprintf(cbuf,"Screen key bindings, page %d of %d.", helpdata->grow / (d_height-5) + 1, helpdata->numpages);
  264.   centerline(cbuf);
  265.   AddChar('\n');
  266.   crow = 2;
  267.  
  268.   *Esc_buf = '\0';
  269.   add_key_to_buf(Esc_buf, d_user->u_Esc);
  270.  
  271.   for (; crow < d_height - 3; crow++)
  272.     {
  273.       if (helpdata->grow < 1)
  274.         {
  275.          *buf = '\0';
  276.           add_key_to_buf(buf, d_user->u_MetaEsc);
  277.           sprintf(cbuf,"Command key:  %s   Literal %s:  %s", Esc_buf, Esc_buf, buf);
  278.           centerline(cbuf);
  279.       helpdata->grow++;
  280.         }
  281.       else if (helpdata->grow >= 2 && helpdata->grow-2 < helpdata->numrows)
  282.     {
  283.       for (col = 0; col < helpdata->numcols && (n = helpdata->numrows * col + (helpdata->grow-2)) < helpdata->num_names; col++)
  284.         {
  285.           AddStrn("", helpdata->inter - !col);
  286.           n = helpdata->nact[n];
  287.           debug1("help: searching key %d\n", n);
  288.           buf[0] = '\0';
  289.           for (key = 0; key < 256; key++)
  290.         if (ktab[key].nr == n && ktab[key].args == noargs)
  291.           {
  292.             strcat(buf, " ");
  293.             add_key_to_buf(buf, key);
  294.           }
  295.           AddStrn(comms[n].name, helpdata->mcom);
  296.           AddStrn(buf, helpdata->mkey);
  297.         }
  298.       AddStr("\r\n");
  299.           helpdata->grow++;
  300.         }
  301.       else if (helpdata->grow-2-helpdata->numrows >= helpdata->numskip 
  302.                && helpdata->grow-2-helpdata->numrows-helpdata->numskip < helpdata->command_bindings)
  303.         {
  304.           char **pp, *cp;
  305.  
  306.       while ((n = ktab[helpdata->command_search].nr) == RC_ILLEGAL
  307.          || ktab[helpdata->command_search].args == noargs)
  308.         {
  309.           if (++helpdata->command_search >= 256)
  310.         return -1;
  311.         }
  312.       buf[0] = '\0';
  313.       add_key_to_buf(buf, helpdata->command_search);
  314.       AddStrn(buf, 4);
  315.       col = 4;
  316.       AddStr(comms[n].name);
  317.       AddChar(' ');
  318.       col += strlen(comms[n].name) + 1;
  319.       pp = ktab[helpdata->command_search++].args;
  320.       while (pp && (cp = *pp) != NULL)
  321.         {
  322.           if (!*cp || (index(cp, ' ') != NULL))
  323.         {
  324.           if (index(cp, '\'') != NULL)
  325.             *buf = '"';
  326.           else
  327.             *buf = '\'';
  328.           sprintf(buf + 1, "%s%c", cp, *buf);
  329.           cp = buf;
  330.         }
  331.           if ((col += strlen(cp) + 1) >= d_width)
  332.         {
  333.           col = d_width - (col - (strlen(cp) + 1)) - 2;
  334.           if (col >= 0)
  335.             {
  336.               n = cp[col];
  337.               cp[col] = '\0';
  338.               AddStr(*pp);
  339.               AddChar('$');
  340.               cp[col] = (char) n;
  341.               }
  342.               break;
  343.             }
  344.           AddStr(cp);
  345.           AddChar((d_width - col != 1 || !pp[1]) ? ' ' : '$');
  346.           pp++;
  347.         }
  348.       AddStr("\r\n");
  349.       helpdata->grow++;
  350.     }
  351.       else
  352.     {
  353.           AddChar('\n');
  354.       helpdata->grow++;
  355.     }
  356.     }
  357.   AddChar('\n');
  358.   sprintf(cbuf,"[Press Space %s Return to end.]",
  359.      helpdata->grow < helpdata->maxrow ? "for next page;" : "or");
  360.   centerline(cbuf);
  361.   SetLastPos(0, d_height-1);
  362.   return(0);
  363. }
  364.  
  365. static void
  366. add_key_to_buf(buf, key)
  367. char *buf;
  368. int key;
  369. {
  370.   debug1("help: key found: %c\n", key);
  371.   buf += strlen(buf);
  372.   if (key == ' ')
  373.     sprintf(buf, "sp");
  374.   else if (key < ' ' || key == 0x7f)
  375.     sprintf(buf, "^%c", (key ^ 0x40));
  376.   else if (key >= 0x80)
  377.     sprintf(buf, "\\%03o", key);
  378.   else
  379.     sprintf(buf, "%c", key);
  380. }
  381.  
  382.  
  383. static void
  384. HelpRedisplayLine(y, xs, xe, isblank)
  385. int y, xs, xe, isblank;
  386. {
  387.   if (y < 0)
  388.     {
  389.       struct helpdata *helpdata;
  390.  
  391.       helpdata = (struct helpdata *)d_lay->l_data;
  392.       helpdata->grow = helpdata->refgrow;
  393.       helpdata->command_search = helpdata->refcommand_search;
  394.       helppage();
  395.       return;
  396.     }
  397.   if (y != 0 && y != d_height - 1)
  398.     return;
  399.   if (isblank)
  400.     return;
  401.   Clear(xs, y, xe, y);
  402. }
  403.  
  404.  
  405. /*
  406. **
  407. **    here is all the copyright stuff 
  408. **
  409. */
  410.  
  411. static void CopyrightProcess __P((char **, int *));
  412. static void CopyrightRedisplayLine __P((int, int, int, int));
  413. static void CopyrightAbort __P((void));
  414. static void CopyrightSetCursor __P((void));
  415. static void copypage __P((void));
  416.  
  417. struct copydata
  418. {
  419.   char    *cps, *savedcps;    /* position in the message */
  420.   char    *refcps, *refsavedcps;    /* backup for redisplaying */
  421. };
  422.  
  423. static struct LayFuncs CopyrightLf =
  424. {
  425.   CopyrightProcess,
  426.   CopyrightAbort,
  427.   CopyrightRedisplayLine,
  428.   DefClearLine,
  429.   DefRewrite,
  430.   CopyrightSetCursor,
  431.   DefResize,
  432.   DefRestore
  433. };
  434.  
  435. static const char cpmsg[] = "\
  436. \n\
  437. Screen version %v\n\
  438. \n\
  439. Copyright (c) 1993 Juergen Weigert, Michael Schroeder\n\
  440. Copyright (c) 1987 Oliver Laumann\n\
  441. \n\
  442. This program is free software; you can redistribute it and/or \
  443. modify it under the terms of the GNU General Public License as published \
  444. by the Free Software Foundation; either version 2, or (at your option) \
  445. any later version.\n\
  446. \n\
  447. This program is distributed in the hope that it will be useful, \
  448. but WITHOUT ANY WARRANTY; without even the implied warranty of \
  449. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the \
  450. GNU General Public License for more details.\n\
  451. \n\
  452. You should have received a copy of the GNU General Public License \
  453. along with this program (see the file COPYING); if not, write to the \
  454. Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.\n\
  455. \n\
  456. Send bugreports, fixes, enhancements, t-shirts, money, beer & pizza to \
  457. screen@uni-erlangen.de\n";
  458.  
  459.  
  460. static void
  461. CopyrightSetCursor()
  462. {
  463.   GotoPos(0, d_height - 1);
  464. }
  465.  
  466. static void
  467. CopyrightProcess(ppbuf, plen)
  468. char **ppbuf;
  469. int *plen;
  470. {
  471.   int done = 0;
  472.   struct copydata *copydata;
  473.  
  474.   copydata = (struct copydata *)d_lay->l_data;
  475.   GotoPos(0, d_height - 1);
  476.   while (!done && *plen > 0)
  477.     {
  478.       switch (**ppbuf)
  479.     {
  480.     case ' ':
  481.           if (*copydata->cps)
  482.         {
  483.           copypage();
  484.           break;
  485.         }
  486.       /* FALLTHROUGH */
  487.     case '\r':
  488.     case '\n':
  489.       CopyrightAbort();
  490.       done = 1;
  491.       break;
  492.     default:
  493.       break;
  494.     }
  495.       ++*ppbuf;
  496.       --*plen;
  497.     }
  498. }
  499.  
  500. static void
  501. CopyrightAbort()
  502. {
  503.   LAY_CALL_UP(Activate(0));
  504.   ExitOverlayPage();
  505. }
  506.  
  507. void
  508. display_copyright()
  509. {
  510.   struct copydata *copydata;
  511.  
  512.   if (d_width < 10 || d_height < 5)
  513.     {
  514.       Msg(0, "Window size too small for copyright page");
  515.       return;
  516.     }
  517.   if (InitOverlayPage(sizeof(*copydata), &CopyrightLf, 0))
  518.     return;
  519.   copydata = (struct copydata *)d_lay->l_data;
  520.   copydata->cps = (char *)cpmsg;
  521.   copydata->savedcps = 0;
  522.   copypage();
  523. }
  524.  
  525. static void
  526. copypage()
  527. {
  528.   register char *cps;
  529.   char *ws;
  530.   int x, y, l;
  531.   char cbuf[80];
  532.   struct copydata *copydata;
  533.  
  534.   copydata = (struct copydata *)d_lay->l_data;
  535.   SetAttrFont(0, ASCII);
  536.   ClearDisplay();
  537.   x = y = 0;
  538.   cps = copydata->cps;
  539.   copydata->refcps = cps;
  540.   copydata->refsavedcps = copydata->savedcps;
  541.   while (*cps && y < d_height - 3)
  542.     {
  543.       ws = cps;
  544.       while (*cps == ' ')
  545.     cps++;
  546.       if (strncmp(cps, "%v", 2) == 0)
  547.     {
  548.       copydata->savedcps = cps + 2;
  549.       cps = version;
  550.       continue;
  551.     }
  552.       while (*cps && *cps != ' ' && *cps != '\n')
  553.     cps++;
  554.       l = cps - ws;
  555.       cps = ws;
  556.       if (l > d_width - 1)
  557.     l = d_width - 1;
  558.       if (x && x + l >= d_width - 2)
  559.     {
  560.       AddStr("\r\n");
  561.       x = 0;
  562.       y++;
  563.       continue;
  564.     }
  565.       if (x)
  566.     {
  567.       AddChar(' ');
  568.       x++;
  569.     }
  570.       if (l)
  571.         AddStrn(ws, l);
  572.       x += l;
  573.       cps += l;
  574.       if (*cps == 0 && copydata->savedcps)
  575.     {
  576.       cps = copydata->savedcps;
  577.       copydata->savedcps = 0;
  578.     }
  579.       if (*cps == '\n')
  580.     {
  581.       AddStr("\r\n");
  582.       x = 0;
  583.       y++;
  584.     }
  585.       if (*cps == ' ' || *cps == '\n')
  586.     cps++;
  587.     }
  588.   while (*cps == '\n')
  589.     cps++;
  590.   while (y++ < d_height - 2)
  591.     AddStr("\r\n");
  592.   sprintf(cbuf,"[Press Space %s Return to end.]",
  593.      *cps ? "for next page;" : "or");
  594.   centerline(cbuf);
  595.   SetLastPos(0, d_height-1);
  596.   copydata->cps = cps;
  597. }
  598.  
  599. static void
  600. CopyrightRedisplayLine(y, xs, xe, isblank)
  601. int y, xs, xe, isblank;
  602. {
  603.   if (y < 0)
  604.     {
  605.       struct copydata *copydata;
  606.  
  607.       copydata = (struct copydata *)d_lay->l_data;
  608.       copydata->cps = copydata->refcps;
  609.       copydata->savedcps = copydata->refsavedcps;
  610.       copypage();
  611.       return;
  612.     }
  613.   if (y != 0 && y != d_height - 1)
  614.     return;
  615.   if (isblank)
  616.     return;
  617.   Clear(xs, y, xe, y);
  618. }
  619.  
  620. void 
  621. display_displays()
  622. {
  623.   /* To be filled in... */
  624. }
  625.  
  626.