home *** CD-ROM | disk | FTP | other *** search
/ ftp.whtech.com / ftp.whtech.com.7z / ftp.whtech.com / emulators / v9t9 / linux / sources / V9t9 / source / help.c < prev    next >
Encoding:
C/C++ Source or Header  |  2006-10-19  |  6.8 KB  |  332 lines

  1.  
  2. /*    Print help for commands / options  */
  3.  
  4. #include <stdarg.h>
  5. #include <stdlib.h>
  6. #include "v9t9_common.h"
  7. #include "command.h"
  8. #include "command_lexer.h"
  9. #include "command_parser.h"
  10. #include "system.h"
  11.  
  12. /*************************************************/
  13.  
  14. /*    Codes used in help text:
  15.  
  16.     \t      -- indent block
  17.     \b        -- end block
  18.     \n        -- paragraph break
  19. */
  20.  
  21. static OSHandle helptext;
  22.  
  23. #define    MAXLINEWIDTH    256        // maximum line width
  24. #define COLS            80        // # cols to use
  25.  
  26. /*    This struct holds information about a side of the screen.  */
  27.  
  28. #define SBUF 1024                // power of two, please!
  29. #define SBUFMASK 1023
  30. typedef struct {
  31.     short       offset;            // start column (absolute)
  32.     short       width;            // # cols of data (no blank space)
  33.     char        buffer[SBUF];    // (circular) info waiting to be expelled
  34.     short       bptr;            // ptr to start of buffer 
  35.     short       blen;            // ptr to # chars waiting in buffer
  36.  
  37.     short       indent;            // # cols indented (absolute per line)
  38.     short       vrow;            // virtual row of screen (for sync)
  39.     short       vcol;            // virtual column (0--width-1)
  40.  
  41.     bool        atEOL;            // is the line ready to be flushed?
  42.     bool        impInd;            // are we implicitly indenting?
  43. } HelpBuf;
  44.  
  45. HelpBuf     helpbuf;
  46.  
  47. /*    Initialize a buffer */
  48. static void
  49. h_init(HelpBuf * s, short offset, short width)
  50. {
  51.     memset((void *) s, 0, sizeof(*s));
  52.  
  53.     s->offset = offset;
  54.     s->width = width;
  55. }
  56.  
  57. static void h_output(HelpBuf * helpbuf);
  58.  
  59. static void
  60. hprintf(HelpBuf * s, char *format, ...)
  61. {
  62.     va_list     ap;
  63.     char        buffer[256], *bptr;
  64.     char       *text;
  65.  
  66.     va_start(ap, format);
  67.     bptr = mvprintf(buffer, sizeof(buffer), format, ap);
  68.     va_end(ap);
  69.  
  70.     text = bptr;
  71.     while (*text) {
  72.         if (s->blen >= SBUF)
  73.             h_output(&helpbuf);
  74.  
  75.         if (s->blen < SBUF) {
  76.             s->buffer[(s->bptr + s->blen) & SBUFMASK] = *text++;
  77.             s->blen++;
  78.         }
  79.     }
  80.  
  81.     if (bptr != buffer)
  82.         free(bptr);
  83. }
  84.  
  85.  
  86.  
  87. /*
  88.  *    Indent more 
  89.  */
  90. static void
  91. h_indent(HelpBuf * s, short how)
  92. {
  93.     if (s->width - s->indent - how > (COLS / 8))    // minimum viewable
  94.         s->indent += how;
  95.     else if (s->width - s->indent - 1 > (COLS / 10))
  96.         s->indent++;            // mini-indent
  97. }
  98.  
  99. /*
  100.  *    Indent less 
  101.  */
  102. static void
  103. h_outdent(HelpBuf * s, short how)
  104. {
  105.     if (s->width - s->indent < (COLS / 8))
  106.         s->indent++;            // we mini-indented
  107.     else if (s->indent >= how)
  108.         s->indent -= how;
  109. }
  110.  
  111.  
  112. //  This is the only buffer printed to the screen (via HelpBufs)
  113. //
  114. static char outLine[MAXLINEWIDTH];    // always enough (s->width)
  115.  
  116. static      bool
  117. isBreaker(char c)
  118. {
  119.     return c == '\n' || c == '\r' || c == ' ' || c == '\t' || c == '\b'
  120.         || c == '|';
  121. }
  122.  
  123. /*    
  124.  *    Dump one line from a buffer, without breaking words
  125.  *    
  126.  *    Allow dumping an empty buffer.
  127.  */
  128. static void
  129. h_dumpline(HelpBuf * s)
  130. {
  131.     short       col;
  132.     short       len;            // # chars in line[]
  133.     short       afterspace, eol = 0, ind = 0;
  134.  
  135.  
  136.     col = s->offset + s->indent;    // where to store
  137.     s->vcol = s->indent;
  138.     len = 0;
  139.     afterspace = s->width - s->indent;    // maximum # chars if no other breakers
  140.  
  141. //  memset(outLine+s->offset, ' ', s->width);               // TEST init
  142.  
  143.     while ((s->blen > 0) && (s->vcol < s->width) && !(eol || ind)) {
  144.         char        c = s->buffer[s->bptr];
  145.  
  146.         outLine[col + len++] = c;
  147.         s->vcol++;
  148.  
  149.         if (isBreaker(c))        // breakers
  150.         {
  151.             afterspace = len;
  152.             eol = (c == '\n' || c == '\r');    // end of line/section
  153.             eol += (c == '\r');    // 1=section break, 2=line break
  154.             ind = (c == '\t' || c == '\b');    // indent section
  155.             ind += (c == '\b');    // 1==in, 2==out
  156.         }
  157.  
  158.         s->bptr = (s->bptr + 1) & SBUFMASK;
  159.         s->blen--;
  160.     }
  161.  
  162.     if (s->blen != 0 || (eol || ind)) {
  163.         //  put back what we ignored    
  164.         s->blen += (len - afterspace);
  165.         s->bptr = (s->bptr - (len - afterspace)) & SBUFMASK;
  166.  
  167.         if (eol || ind) {
  168.             len++;                // eat up control char
  169.             afterspace--;
  170.         }
  171.  
  172.         while (afterspace < len)
  173.             outLine[col + (--len)] = ' ';    // erase wrapped partofword
  174.     }
  175.  
  176.     s->vcol = 0;
  177.     s->vrow++;
  178.     s->atEOL = (eol == 1) || (ind) || (s->blen == 0);
  179.  
  180.     if (s->atEOL || ind)
  181.         if (s->impInd) {
  182.             h_outdent(s, (COLS / 40));
  183.             s->impInd = false;
  184.         }
  185.  
  186.     if (ind) {
  187.         if (ind == 1)
  188.             h_indent(s, (COLS / 25));
  189.         else
  190.             h_outdent(s, (COLS / 25));
  191.     }
  192. }
  193.  
  194. static void
  195. h_line(HelpBuf * helpbuf, char ch)
  196. {
  197.     char        line[256];
  198.  
  199.     memset(line, ch, 255);
  200.     line[255] = 0;
  201.  
  202.     hprintf(helpbuf, "%.*s\r", helpbuf->width - helpbuf->indent - 2, line);
  203. }
  204.  
  205. static void
  206. h_printline(void)
  207. {
  208.     char *ptr = outLine + COLS - 1;
  209.     while (ptr > outLine && isspace(*(ptr-1)))
  210.         *--ptr = 0;
  211.     *ptr++ = '\n'; *ptr= 0;
  212.     OS_AppendHandle(&helptext, outLine, ptr - outLine);
  213. }
  214.  
  215. static void
  216. h_output(HelpBuf * helpbuf)
  217. {
  218.     while (helpbuf->blen)        // while there's stuff to dump...
  219.     {
  220.         memset(outLine, ' ', COLS);
  221.         outLine[COLS] = '\n';
  222.  
  223.         if (helpbuf->atEOL)
  224.             helpbuf->atEOL = false;
  225.  
  226.         if (!helpbuf->atEOL)
  227.             h_dumpline(helpbuf);
  228.  
  229.         // output generated line
  230.         h_printline();
  231.     }
  232. }
  233.  
  234. /*************************************/
  235.  
  236. static void
  237. command_arg_help(command_arg * arg)
  238. {
  239.     while (arg) {
  240.         hprintf(&helpbuf, "%s (%s): %s\r",
  241.                 arg->name, ca_types[arg->type], arg->help);
  242.         h_output(&helpbuf);
  243.         arg = arg->next;
  244.     }
  245. }
  246.  
  247. static void
  248. command_symbol_help(command_symbol * sym)
  249. {
  250.     while (sym) {
  251.         char       *ptr = sym->name;
  252.  
  253.         if (sym->help) {
  254.             while (*ptr && *ptr != '|')
  255.                 ptr++;
  256.             hprintf(&helpbuf, "%.*s: %s\n\t",
  257.                     ptr - sym->name, sym->name, sym->help);
  258.             if (sym->flags == c_DONT_SAVE) {
  259.                 hprintf(&helpbuf, "Not saved to configuration file\r");
  260.             } else if (sym->flags & c_SESSION_ONLY) {
  261.                 hprintf(&helpbuf, "Only saved to session files\r");
  262.             } else if (sym->flags & c_CONFIG_ONLY) {
  263.                 hprintf(&helpbuf, "Only saved to config files\r");
  264.             }
  265.             if (sym->args) {
  266.                 hprintf(&helpbuf, "Arguments:\t");
  267.                 command_arg_help(sym->args);
  268.                 hprintf(&helpbuf, "\b");
  269.             }
  270.             if (sym->args && sym->ret == sym->args) {
  271.                 hprintf(&helpbuf, "Returns first argument\r");
  272.             } else if (sym->ret != NULL) {
  273.                 hprintf(&helpbuf, "Returns:\r");
  274.                 command_arg_help(sym->ret);
  275.             }
  276.             hprintf(&helpbuf, "\b");
  277.             h_output(&helpbuf);
  278.         }
  279.         sym = sym->next;
  280.     }
  281. }
  282.  
  283. static void
  284. command_symbol_table_help(command_symbol_table * table)
  285. {
  286.     while (table) {
  287.         if (table->name) {
  288.             h_line(&helpbuf, '=');
  289.             hprintf(&helpbuf, "%s\r", table->name);
  290.         }
  291.         if (table->help) {
  292.             h_line(&helpbuf, '=');
  293.             hprintf(&helpbuf, "%s\r", table->help);
  294.         }
  295.  
  296.         h_line(&helpbuf, '-');
  297.  
  298.         if (table->list)
  299.             command_symbol_help(table->list);
  300.  
  301.         if (table->sub) {
  302.             hprintf(&helpbuf, "\t");
  303.             h_output(&helpbuf);
  304.             command_symbol_table_help(table->sub);
  305.             hprintf(&helpbuf, "\b");
  306.         }
  307.  
  308.         h_output(&helpbuf);
  309.         table = table->next;
  310.     }
  311. }
  312.  
  313. void
  314. command_help(void)
  315. {
  316.     void       *ptr;
  317.  
  318.     OS_NewHandle(0, &helptext);
  319.     h_init(&helpbuf, 0, COLS);
  320.  
  321.     if (universe)
  322.         command_symbol_table_help(universe);
  323.     else
  324.         hprintf(&helpbuf, "No commands defined\n");
  325.  
  326.     h_output(&helpbuf);
  327.     ptr = OS_LockHandle(&helptext);
  328.     system_log(LOG_USER, ptr);
  329.     OS_UnlockHandle(&helptext);
  330.     OS_FreeHandle(&helptext);
  331. }
  332.