\File{hes.c},{05:16},{May 19 1991}
\L{\LB{\K{\#include} \<stdio.h\>}}
\L{\LB{\K{\#include} \S{}\"hes.h\"\SE{}}}
\L{\LB{}}
\L{\LB{\C{}\/* debugging flags:}}
\L{\LB{}}
\L{\LB{DEBUG\_PARSER    \-\-\-\- aids in debugging the parser in load\_windows() }}
\L{\LB{}}
\L{\LB{}}
\L{\LB{}}
\L{\LB{*\/\CE{}}}
\L{\LB{}}
\L{\LB{\C{}\/* help window editing system  \-\-\-\- HES}}
\L{\LB{}}
\L{\LB{   written \&\& designed by UChin Kim  }}
\L{\LB{}}
\L{\LB{   prototype of things to come.  }}
\L{\LB{}}
\L{\LB{   the basic idea behind this is to allow help documentation to be}}
\L{\LB{   incrementally modified on\-line as needed.  if a user finds the current}}
\L{\LB{   help documentation to be inadequate, he can always add his own }}
\L{\LB{   (provided that he knows how to use the system).  the core of this}}
\L{\LB{   idea is that of extensibility.  use the tools to make more tools.  }}
\L{\LB{   granted, in this case, it is limited to making more documentation.}}
\L{\LB{   }}
\L{\LB{   another idea related to this is that of deferment.  one of the }}
\L{\LB{   great ideas in computer science.  defer arbitrary decisions as much}}
\L{\LB{   as possible and\/or allow the user to choose if possible.  (emacs is}}
\L{\LB{   a great example of this concept \-\-\- emacs is very customizable)  }}
\L{\LB{   the only thing this particular system allows deferment of is of}}
\L{\LB{   the contents of the help windows themselves.  }}
\L{\LB{}}
\L{\LB{   Possible future refinements include:  allow a tree\-like hierarchy }}
\L{\LB{   of help windows \-\- so that the user can browse through at his }}
\L{\LB{   leisure.  not sure how to incorporate this so that it is easy to}}
\L{\LB{   use and intuitive and elegant.  one possibility would be to }}
\L{\LB{   display the tree structure and allow the user to click on whatever}}
\L{\LB{   topics he wants to see.  good thing about this is that user can}}
\L{\LB{   click on any sublevel of help immediately without having to go }}
\L{\LB{   through intermediate help levels.  (maybe it\'s not a tree structure}}
\L{\LB{   but a web\-structure ?)  we could have something like a rogue}}
\L{\LB{   maze \-\-\- no, not a rogue maze, but a special type of web.  }}
\L{\LB{}}
\L{\LB{   a special type of web that is limited to four (or eight?) connections.}}
\L{\LB{   think this out later.  it might be possible to set up a type of}}
\L{\LB{   browser \-\-\- a revolutionary type of browser  }}
\L{\LB{}}
\L{\LB{   anyways, this is HES.  currently, it will allow a user to do the }}
\L{\LB{   following: }}
\L{\LB{   1. display a list of current help windows.  }}
\L{\LB{   2. edit a help window.}}
\L{\LB{   3. save a help window.  (or save all help windows?)}}
\L{\LB{   4. display a help window.}}
\L{\LB{}}
\L{\LB{}}
\L{\LB{   format of help window file:}}
\L{\LB{   }}
\L{\LB{   help windows can either be edited online or through the use }}
\L{\LB{   of an editor.  }}
\L{\LB{}}
\L{\LB{   EBNF Syntax:}}
\L{\LB{   \{\} encloses 0 or more}}
\L{\LB{   [] encloses 0 or 1.}}
\L{\LB{}}
\L{\LB{   help\-file: \{help\-window\}}}
\L{\LB{              EOF\-delimiter}}
\L{\LB{}}
\L{\LB{   help\-window: \'\|\' help\-name \'\|\'}}
\L{\LB{                help\-text}}
\L{\LB{}}
\L{\LB{   EOF\-delimiter:  \'\|EOF\|\'}}
\L{\LB{}}
\L{\LB{}}
\L{\LB{}}
\L{\LB{   example:}}
\L{\LB{}}
\L{\LB{\|Filtering\|}}
\L{\LB{}}
\L{\LB{       filtering is ....}}
\L{\LB{       ...}}
\L{\LB{       ...}}
\L{\LB{       ...}}
\L{\LB{}}
\L{\LB{}}
\L{\LB{\|Tracing\|}}
\L{\LB{}}
\L{\LB{       tracing involves the assigning of ...}}
\L{\LB{       ...}}
\L{\LB{       ...}}
\L{\LB{       ...}}
\L{\LB{}}
\L{\LB{}}
\L{\LB{\|EOF\|}}
\L{\LB{}}
\L{\LB{}}
\L{\LB{}}
\L{\LB{   functions\/operations:}}
\L{\LB{}}
\L{\LB{   \- edit a window.}}
\L{\LB{   \- display a window.}}
\L{\LB{   \- display a windows list}}
\L{\LB{   \- save the windows.}}
\L{\LB{   \- load windows.}}
\L{\LB{}}
\L{\LB{*\/\CE{}}}
\L{\LB{}}
\L{\LB{\C{}\/*}}
\L{\LB{\{}}
\L{\LB{  char name[HELPNAMSIZE];}}
\L{\LB{  char buffer[HELPBUFSIZE];}}
\L{\LB{\}; *\/\CE{}}}
\L{\LB{}}
\L{\LB{\K{struct} \{}}
\L{\LB{  \K{char} name[HELPNAMSIZE];}}
\L{\LB{  \K{char} buffer[HELPBUFSIZE];}}
\L{\LB{  \} hw[MAXWIND]; \C{}\/* hw[MAXWIND]; *\/\CE{} \C{}\/* allow up to MAXWIND help screens *\/\CE{}}}
\L{\LB{}}
\L{\LB{\K{int} num\_windows = 0;  \C{}\/* initially, no windows are loaded *\/\CE{}}}
\L{\LB{}}
\L{\LB{}}
\L{\LB{\K{void} init\_hw()}}
\L{\LB{}}
\L{\LB{\C{}\/* initialize the contents of the hw[] array. }}
\L{\LB{   specifically, for each element of the array, set }}
\L{\LB{   its name to the empty string, and set its buffer }}
\L{\LB{   to the empty string *\/\CE{}}}
\L{\LB{\{}}
\L{\LB{  \K{int} i;}}
\L{\LB{   }}
\L{\LB{  \K{for} (i = 0; i \< MAXWIND; i++) \{}}
\L{\LB{    hw[i].name[0] = NULL; }}
\L{\LB{    hw[i].buffer[0] = NULL;}}
\L{\LB{  \}}}
\L{\LB{\}}}
\L{\LB{}}
\L{\LB{}}
\L{\LB{\K{char} *get\_keyword(line)}}
\L{\LB{\K{char} *line;}}
\L{\LB{}}
\L{\LB{\C{}\/* get\_keyword parses a line of the following format:}}
\L{\LB{   \'\|\' keyword \'\|\'}}
\L{\LB{   example:  \|hello\|    }}
\L{\LB{   \|goodbye\|  and so on.  the keyword must be }}
\L{\LB{   separated by \'\|\' (or whatever DELIMITER is set to).  }}
\L{\LB{   get\_keyword will read up to the next \'\|\' character.}}
\L{\LB{   no spaces should be between the delimiters.  *\/\CE{}}}
\L{\LB{\C{}\/* seems to work *\/\CE{}}}
\L{\LB{}}
\L{\LB{}}
\L{\LB{\{}}
\L{\LB{  \K{static} \K{char} key[HELPNAMSIZE];}}
\L{\LB{  \K{int} index = 0;}}
\L{\LB{  \K{int} exit\_flag = FALSE;}}
\L{\LB{}}
\L{\LB{  key[0] = NULL; \C{}\/* initialize char array *\/\CE{}}}
\L{\LB{  \K{if} (*line == NULL) \{}}
\L{\LB{\K{\#ifdef} DEBUG\_PARSER}}
\L{\LB{    fprintf(stderr, \S{}\"get\_keyword(): being passed a null string.\!n\"\SE{});}}
\L{\LB{\K{\#endif}  }}
\L{\LB{    }}
\L{\LB{    }}
\L{\LB{    \K{return}(key);}}
\L{\LB{  \}}}
\L{\LB{}}
\L{\LB{  line++; \C{}\/* have line point past the first delimiter *\/\CE{}}}
\L{\LB{  \K{while} ( (*line != NULL) \&\& (*line != DELIMITER) \&\& (exit\_flag == FALSE) ) \{}}
\L{\LB{    key[index] = *line;}}
\L{\LB{    line++;}}
\L{\LB{    index++;}}
\L{\LB{    \K{if} (index \>= (HELPNAMSIZE \- 1)) exit\_flag = TRUE; \C{}\/* no more space *\/\CE{}}}
\L{\LB{  \}}}
\L{\LB{}}
\L{\LB{  key[index] = NULL; \C{}\/* make the string a proper C string *\/\CE{}}}
\L{\LB{  \K{return}(key);}}
\L{\LB{\}}}
\L{\LB{    }}
\L{\LB{\K{int} int\_scanf()}}
\L{\LB{}}
\L{\LB{\{}}
\L{\LB{\C{}\/* int\_scanf is an improvement on the regular scanf.  for }}
\L{\LB{   some reason that i cannot fathom, scanf bombs if you tell}}
\L{\LB{   it to expect an integer input and the user types in a letter}}
\L{\LB{   as a reply.  int\_scanf works only for integer input }}
\L{\LB{}}
\L{\LB{   int\_scanf reads the input in as a string.  then tries to }}
\L{\LB{   convert it to an integer.  if this is not possible, it returns}}
\L{\LB{   a default value of 0.  *\/\CE{}}}
\L{\LB{}}
\L{\LB{  \K{char} str[40];}}
\L{\LB{  \K{int} num;}}
\L{\LB{  \K{int}  scan\_flag;}}
\L{\LB{}}
\L{\LB{  scan\_flag = scanf(\S{}\"\%s\"\SE{}, str);}}
\L{\LB{  \K{if} ( (scan\_flag == 0) \|\| (scan\_flag == EOF) ) \{}}
\L{\LB{    \K{return}(0);}}
\L{\LB{  \}}}
\L{\LB{}}
\L{\LB{  scan\_flag = sscanf(str, \S{}\"\%d\"\SE{}, \&num);}}
\L{\LB{  \K{if} (scan\_flag == 1) \{}}
\L{\LB{    \K{return}(num);}}
\L{\LB{  \}}}
\L{\LB{  \K{else} \{}}
\L{\LB{    \K{return}(0);}}
\L{\LB{  \}}}
\L{\LB{\}}}
\L{\LB{}}
\L{\LB{  }}
\L{\LB{}}
\L{\LB{  }}
\L{\LB{}}
\L{\LB{}}
\L{\LB{\K{void} load\_windows(filename)}}
\L{\LB{\K{char} *filename;}}
\L{\LB{}}
\L{\LB{\C{}\/* debugged *\/\CE{}}}
\L{\LB{}}
\L{\LB{\C{}\/* load\_windows loads a set of windows from a file }}
\L{\LB{   format is as follows:}}
\L{\LB{}}
\L{\LB{   (there should be no leading spaces before the keywords)}}
\L{\LB{}}
\L{\LB{\|Filtering\|}}
\L{\LB{}}
\L{\LB{   Text follows}}
\L{\LB{   .}}
\L{\LB{   .}}
\L{\LB{   .}}
\L{\LB{}}
\L{\LB{\|Tracing\|}}
\L{\LB{   }}
\L{\LB{   Text follows}}
\L{\LB{   .}}
\L{\LB{   .}}
\L{\LB{   .}}
\L{\LB{   }}
\L{\LB{}}
\L{\LB{\|EOF\|      }}
\L{\LB{}}
\L{\LB{}}
\L{\LB{}}
\L{\LB{   basic strategy is as follows:}}
\L{\LB{}}
\L{\LB{   load\_windows keeps reading lines until it finds a line}}
\L{\LB{   starting with \'\|\'.  It assumes a keyword is enclosed with }}
\L{\LB{   \'\|\' on either side (no spaces allowed).  Lines following}}
\L{\LB{   the keyword are assumed to be the help text associated with}}
\L{\LB{   the keyword.  The appearance of the next keyword delimits}}
\L{\LB{   the text of the previous keyword help text.  And so on }}
\L{\LB{   until the end, when the reserved keyword \'\|EOF\|\' tells }}
\L{\LB{   load\_windows to stop reading any more lines.  }}
\L{\LB{}}
\L{\LB{*\/\CE{}}}
\L{\LB{}}
\L{\LB{}}
\L{\LB{}}
\L{\LB{\{}}
\L{\LB{}}
\L{\LB{  FILE *fp;}}
\L{\LB{}}
\L{\LB{  \K{char} *lineptr, line[LINESIZE]; }}
\L{\LB{}}
\L{\LB{  \K{char} current\_help[HELPNAMSIZE]; \C{}\/* name of current help text *\/\CE{}}}
\L{\LB{  \K{int} current\_len = 0; \C{}\/* length of current help buffer *\/\CE{}}}
\L{\LB{  }}
\L{\LB{}}
\L{\LB{\C{}\/* possible states for the parser to be in *\/\CE{}}}
\L{\LB{}}
\L{\LB{\C{}\/* \#define IN\_LIMBO  1}}
\L{\LB{   \#define IN\_TEXT   2}}
\L{\LB{*\/\CE{}}}
\L{\LB{}}
\L{\LB{\C{}\/* algorithm: starts out IN\_LIMBO.  reads in a line at a}}
\L{\LB{   time until it finds a DELIMITER.  if DELIMITER is EOF}}
\L{\LB{   then closes file and returns.  otherwise we are IN\_TEXT}}
\L{\LB{   and we set current\_help to the name of the keyword, and then}}
\L{\LB{   enter IN\_TEXT.  if, while in IN\_TEXT, we run out of buffer}}
\L{\LB{   space for the particular keyword, we enter IN\_LIMBO again.  }}
\L{\LB{   if we encounter a DELIMITER, but we have no more room for}}
\L{\LB{   keywords, we enter IN\_LIMBO (or close up?)  *\/\CE{}}}
\L{\LB{}}
\L{\LB{  \K{int} state = IN\_LIMBO;}}
\L{\LB{  \K{int} exit\_flag = FALSE;}}
\L{\LB{  \K{int} defer\_read = FALSE; }}
\L{\LB{  \K{int} help\_no = \-1; \C{}\/* keeps track of which help message to}}
\L{\LB{}\Tab{16}{      read in *\/\CE{}}}
\L{\LB{}}
\L{\LB{  init\_hw();  \C{}\/* need to reset hw[] *\/\CE{}}}
\L{\LB{}}
\L{\LB{}}
\L{\LB{  fp = fopen(filename, \S{}\"r\"\SE{});}}
\L{\LB{  \K{if} (fp == NULL) \{}}
\L{\LB{    perror(\S{}\"load\_windows(): Can\'t open the file.\"\SE{});}}
\L{\LB{    \K{return};}}
\L{\LB{  \}}}
\L{\LB{}}
\L{\LB{  \C{}\/* process a line at a time }}
\L{\LB{     using fgets().  }}
\L{\LB{}}
\L{\LB{     *\/\CE{}}}
\L{\LB{}}
\L{\LB{  lineptr = fgets(line, LINESIZE, fp); }}
\L{\LB{}}
\L{\LB{  \K{while} ( (lineptr != NULL)  \&\& (exit\_flag == FALSE) ) \{  \C{}\/* lev 1 *\/\CE{}}}
\L{\LB{    \K{if} (state == IN\_LIMBO) \{  \C{}\/* lev 2 *\/\CE{}}}
\L{\LB{      \K{if} (line[0] == DELIMITER) \{   \C{}\/* lev 3 *\/\CE{}}}
\L{\LB{}\Tab{8}{strcpy(current\_help,get\_keyword(line));}}
\L{\LB{\K{\#ifdef} DEBUG\_PARSER}}
\L{\LB{}\Tab{8}{fprintf(stderr, \S{}\"parser: added delimiter \%s \!n\"\SE{}, current\_help);}}
\L{\LB{\K{\#endif}}}
\L{\LB{}\Tab{8}{\K{if} (strncmp(line, EOF\_END, strlen(EOF\_END)) == 0) }}
\L{\LB{}\Tab{8}{  exit\_flag = TRUE; }}
\L{\LB{}\Tab{8}{\K{else} \{  \C{}\/* lev 4 *\/\CE{}}}
\L{\LB{}\Tab{8}{  state = IN\_TEXT;}}
\L{\LB{}\Tab{8}{  current\_len = 0; \C{}\/* reset the current length of the help buffer *\/\CE{}}}
\L{\LB{}\Tab{8}{  help\_no = help\_no + 1;  \C{}\/* point to next help buffer *\/\CE{}}}
\L{\LB{\K{\#ifdef} DEBUG\_PARSER}}
\L{\LB{}\Tab{8}{  fprintf(stderr, \S{}\"new help buffer \# is \%d \!n\"\SE{}, help\_no);}}
\L{\LB{\K{\#endif}}}
\L{\LB{}\Tab{8}{  \K{if} (help\_no \> MAXWIND) \{}}
\L{\LB{}\Tab{8}{    exit\_flag = TRUE;}}
\L{\LB{}\Tab{8}{    help\_no = help\_no \- 1;}}
\L{\LB{}\Tab{8}{  \}}}
\L{\LB{}\Tab{8}{  \K{else} \{  \C{}\/* lev 5 *\/\CE{}}}
\L{\LB{}\Tab{8}{    strcpy(hw[help\_no].name, current\_help);}}
\L{\LB{\K{\#ifdef} DEBUG\_PARSER}}
\L{\LB{}\Tab{8}{    fprintf(stderr, \S{}\"assigned delimiter to buffer \%d \!n\"\SE{}, help\_no);}}
\L{\LB{\K{\#endif}}}
\L{\LB{}\Tab{8}{  \}  \C{}\/* end lev 5 *\/\CE{}}}
\L{\LB{}\Tab{8}{\}  \C{}\/* end lev 4 *\/\CE{}}}
\L{\LB{}}
\L{\LB{      \}  \C{}\/* end lev 3 *\/\CE{}}}
\L{\LB{      \C{}\/* otherwise do nothing *\/\CE{}}}
\L{\LB{    \}   \C{}\/* end lev 2 *\/\CE{}}}
\L{\LB{}}
\L{\LB{    \K{else} \K{if} (state == IN\_TEXT) \{    \C{}\/* lev 2 *\/\CE{}}}
\L{\LB{      \C{}\/* checks that the total length of the help text }}
\L{\LB{}\Tab{8}{ will not be more than the buffer size for it.}}
\L{\LB{}\Tab{8}{ if total length is less, then add it, otherwise}}
\L{\LB{}\Tab{8}{ enter IN\_LIMBO *\/\CE{}}}
\L{\LB{      \K{if} (line[0] == DELIMITER) \{   \C{}\/* lev 3 *\/\CE{}}}
\L{\LB{}\Tab{8}{defer\_read = TRUE; \C{}\/* reprocess this line *\/\CE{}}}
\L{\LB{}\Tab{8}{state = IN\_LIMBO;}}
\L{\LB{      \}  \C{}\/* end lev 3 *\/\CE{}}}
\L{\LB{}}
\L{\LB{      \K{else} \{    \C{}\/* lev 3 *\/\CE{}}}
\L{\LB{}\Tab{8}{current\_len = current\_len + strlen(line);}}
\L{\LB{\K{\#ifdef} DEBUG\_PARSER}}
\L{\LB{}\Tab{8}{fprintf(stderr, \S{}\"new text length is \%d \!n\"\SE{}, current\_len);}}
\L{\LB{\K{\#endif}}}
\L{\LB{}\Tab{8}{\K{if} (current\_len \< HELPBUFSIZE) \{  \C{}\/* lev 4 *\/\CE{}}}
\L{\LB{}\Tab{8}{  strcat(hw[help\_no].buffer, line);}}
\L{\LB{}\Tab{8}{\} \C{}\/* end else *\/\CE{}  \C{}\/* end lev 4 *\/\CE{}}}
\L{\LB{}\Tab{8}{\K{else} \{  \C{}\/* we\'ve run out of space for that particular buffer (lev 4)*\/\CE{}}}
\L{\LB{}\Tab{8}{  defer\_read = TRUE; \C{}\/* reprocess this line, for no good reason *\/\CE{}}}
\L{\LB{}\Tab{8}{  state = IN\_LIMBO; }}
\L{\LB{\K{\#ifdef} DEBUG\_PARSER}}
\L{\LB{}\Tab{8}{  fprintf(stderr, \S{}\"just entered limbo.\!n\"\SE{});}}
\L{\LB{\K{\#endif}}}
\L{\LB{}\Tab{8}{\} \C{}\/* end lev 4 *\/\CE{}}}
\L{\LB{      \} \C{}\/* end lev 3 *\/\CE{}}}
\L{\LB{    \} \C{}\/* end lev 2 *\/\CE{}}}
\L{\LB{}}
\L{\LB{      }}
\L{\LB{    \C{}\/* now get the next line *\/\CE{}}}
\L{\LB{    \K{if} (defer\_read == TRUE)}}
\L{\LB{      defer\_read = FALSE;}}
\L{\LB{    \K{else} \{}}
\L{\LB{      lineptr = fgets(line, LINESIZE, fp);}}
\L{\LB{    \}}}
\L{\LB{}}
\L{\LB{  \} \C{}\/* end while loop *\/\CE{}  \C{}\/* end lev 1 *\/\CE{}}}
\L{\LB{}}
\L{\LB{\C{}\/* by now, we\'ve finished reading in everything we needed to }}
\L{\LB{   read in.  close the file, set some global variables and}}
\L{\LB{   return *\/\CE{}}}
\L{\LB{}}
\L{\LB{  fclose(fp);}}
\L{\LB{}}
\L{\LB{  num\_windows = help\_no + 1;}}
\L{\LB{}}
\L{\LB{\}}}
\L{\LB{}}
\L{\LB{\K{int} index\_window(name)}}
\L{\LB{\K{char} *name;}}
\L{\LB{}}
\L{\LB{\C{}\/* index\_window finds name in the hw array, and returns the}}
\L{\LB{   indice corresponding to that name. uses a linear search.}}
\L{\LB{   better search is not needed because there are usually }}
\L{\LB{   less than 20 items to search anyways.  returns \-1 if }}
\L{\LB{   not found *\/\CE{}}}
\L{\LB{\{}}
\L{\LB{  \K{int} i = 0;}}
\L{\LB{  \K{int} found = FALSE;}}
\L{\LB{  \K{int} index;}}
\L{\LB{  }}
\L{\LB{  \K{while} ( (i \< num\_windows) \&\& (found == FALSE) ) \{}}
\L{\LB{\K{\#ifdef} DEBUG\_PARSER}}
\L{\LB{    fprintf(stderr, \S{}\"index(): comparing \<\%s\> with \<\%s\> \!n\"\SE{}, name, hw[i].name);}}
\L{\LB{\K{\#endif}}}
\L{\LB{    \K{if} (strcmp(name, hw[i].name) == 0) \{}}
\L{\LB{      index = i;}}
\L{\LB{      found = TRUE;}}
\L{\LB{\K{\#ifdef} DEBUG\_PARSER      }}
\L{\LB{      fputs(\S{}\"index(): comparison was true.\"\SE{});}}
\L{\LB{\K{\#endif}      }}
\L{\LB{    \}}}
\L{\LB{    i++;  \C{}\/* point to next item *\/\CE{}}}
\L{\LB{  \}}}
\L{\LB{}}
\L{\LB{  \K{if} (found == TRUE) }}
\L{\LB{    \K{return}(index);}}
\L{\LB{  \K{else} \K{return}(\-1);}}
\L{\LB{\}}}
\L{\LB{}}
\L{\LB{  }}
\L{\LB{}}
\L{\LB{\K{void} display\_window(name)}}
\L{\LB{\K{char} *name;}}
\L{\LB{}}
\L{\LB{\C{}\/* displays the windows in hw[], }}
\L{\LB{   displays the windows up to num\_windows.  *\/\CE{}}}
\L{\LB{     }}
\L{\LB{\{}}
\L{\LB{}}
\L{\LB{  \K{int} i;}}
\L{\LB{  }}
\L{\LB{  i = index\_window(name);}}
\L{\LB{\K{\#ifdef} DEBUG\_PARSER}}
\L{\LB{  fprintf(stderr,\S{}\"display\_window(): index of window is \%d \!n\"\SE{}, i);}}
\L{\LB{\K{\#endif}  }}
\L{\LB{  }}
\L{\LB{  }}
\L{\LB{  \K{if} (i == \-1) \{}}
\L{\LB{\K{\#ifdef} DEBUG\_PARSER}}
\L{\LB{    fprintf(stderr, \S{}\"display\_window(): couldn\'t find your window.\!n\"\SE{});}}
\L{\LB{\K{\#endif}  }}
\L{\LB{    }}
\L{\LB{  \}}}
\L{\LB{\K{\#ifdef} DEBUG\_PARSER}}
\L{\LB{}}
\L{\LB{  }}
\L{\LB{  fprintf(stderr, \S{}\"Window : \%s \!n\"\SE{}, hw[i].name);}}
\L{\LB{  fprintf(stderr, \S{}\"Text: \%s\"\SE{}, hw[i].buffer);}}
\L{\LB{\K{\#endif}  }}
\L{\LB{\}}}
\L{\LB{}}
\L{\LB{}}
\L{\LB{\K{void} list\_window\_names()}}
\L{\LB{\C{}\/* list\_window\_names lists the names of all the windows it knows *\/\CE{}}}
\L{\LB{}}
\L{\LB{\{}}
\L{\LB{  \K{int} i;}}
\L{\LB{\K{\#ifdef} DEBUG\_PARSER}}
\L{\LB{}}
\L{\LB{  }}
\L{\LB{  fprintf(stderr, \S{}\"\!n\!n\"\SE{});}}
\L{\LB{  fprintf(stderr, \S{}\"\-\-\- List of Windows \-\-\-\!n\"\SE{});}}
\L{\LB{  \K{for} (i = 0; i \< num\_windows; i++) \{}}
\L{\LB{    fprintf(stderr, \S{}\"\%s\!n\"\SE{}, hw[i].name);}}
\L{\LB{  \}}}
\L{\LB{  fprintf(stderr, \S{}\"\!n\!n\"\SE{});}}
\L{\LB{\K{\#endif}    }}
\L{\LB{\}}}
\L{\LB{}}
\L{\LB{}}
\L{\LB{\K{void} simple\_menu()}}
\L{\LB{\C{}\/* simple\_menu displays a list of choices, lets the user}}
\L{\LB{select from them. and executes the appropriate routines *\/\CE{}}}
\L{\LB{}}
\L{\LB{\{}}
\L{\LB{}}
\L{\LB{  \K{int} choice;}}
\L{\LB{  \K{int} exit\_flag = FALSE;}}
\L{\LB{  \K{int} scan\_flag;}}
\L{\LB{}}
\L{\LB{  \K{void} handle\_list(), handle\_edit(), handle\_load();}}
\L{\LB{  \K{void} handle\_display();}}
\L{\LB{}}
\L{\LB{  \K{do} \{}}
\L{\LB{\K{\#ifdef} DEBUG\_PARSER}}
\L{\LB{    printf(\S{}\"\!n\!n\!n\"\SE{});}}
\L{\LB{    printf(\S{}\"\-\-\- Le Menu Simplistique \-\-\-\!n\"\SE{});}}
\L{\LB{    printf(\S{}\"1. list window names. \!n\"\SE{});}}
\L{\LB{    printf(\S{}\"2. edit a window. \!n\"\SE{});}}
\L{\LB{    printf(\S{}\"3. load a windows file. \!n\"\SE{});}}
\L{\LB{    printf(\S{}\"4. display a window screen. \!n\"\SE{});}}
\L{\LB{    printf(\S{}\"5. exit this menu.\!n\"\SE{});}}
\L{\LB{    printf(\S{}\"\!n\!nEnter the number corresponding to your choice.\!n\"\SE{});}}
\L{\LB{\K{\#endif}}}
\L{\LB{    choice = int\_scanf(); }}
\L{\LB{}}
\L{\LB{    \K{if} ( (choice \> 0) \&\& (choice \< 6) ) \{}}
\L{\LB{      \K{switch}(choice) \{}}
\L{\LB{      \K{case} 1: handle\_list(); \K{break};}}
\L{\LB{      \K{case} 2: handle\_edit(); \K{break};}}
\L{\LB{      \K{case} 3: handle\_load(); \K{break};}}
\L{\LB{      \K{case} 4: handle\_display(); \K{break};}}
\L{\LB{      \K{case} 5: exit\_flag = TRUE; \K{break};}}
\L{\LB{      \}}}
\L{\LB{    \}}}
\L{\LB{}}
\L{\LB{  \} \K{while} (exit\_flag == FALSE);}}
\L{\LB{\}}}
\L{\LB{}}
\L{\LB{}}
\L{\LB{\K{void} handle\_list()}}
\L{\LB{\{}}
\L{\LB{  list\_window\_names();}}
\L{\LB{\}}}
\L{\LB{}}
\L{\LB{\K{void} handle\_edit()}}
\L{\LB{\{}}
\L{\LB{  printf(\S{}\"editor: Not implemented yet. Tough luck.\!n\"\SE{});}}
\L{\LB{\}}}
\L{\LB{}}
\L{\LB{\K{void} handle\_load()}}
\L{\LB{\{}}
\L{\LB{  \K{char} filename[40];}}
\L{\LB{  \K{int} scan\_flag;}}
\L{\LB{}}
\L{\LB{  printf(\S{}\"Enter file name to load: \"\SE{});}}
\L{\LB{  scan\_flag = scanf(\S{}\"\%s\"\SE{}, filename);}}
\L{\LB{  \K{if} (scan\_flag != 1) \{}}
\L{\LB{    filename[0] = \S{}\'\!0\'\SE{}; }}
\L{\LB{  \}}}
\L{\LB{}}
\L{\LB{  load\_windows(filename);}}
\L{\LB{  list\_window\_names();}}
\L{\LB{\}}}
\L{\LB{}}
\L{\LB{\K{void} handle\_display()}}
\L{\LB{\{}}
\L{\LB{}}
\L{\LB{  \K{char} name[HELPNAMSIZE];}}
\L{\LB{  \K{int} scan\_flag;}}
\L{\LB{}}
\L{\LB{  printf(\S{}\"Enter name of window to display: \"\SE{});}}
\L{\LB{  }}
\L{\LB{  scan\_flag = scanf(\S{}\"\%s\"\SE{}, name);}}
\L{\LB{  \K{if} (scan\_flag != 1) \{}}
\L{\LB{    name[0] = \S{}\'\!0\'\SE{};}}
\L{\LB{  \}}}
\L{\LB{}}
\L{\LB{  display\_window(name);}}
\L{\LB{}}
\L{\LB{\}}}
