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