home *** CD-ROM | disk | FTP | other *** search
/ Frozen Fish 1: Amiga / FrozenFish-Apr94.iso / bbs / alib / d1xx / d107 / svtools.lha / SVTools / Vnews / vnews.c < prev    next >
C/C++ Source or Header  |  1987-10-31  |  21KB  |  824 lines

  1. /************************************************************
  2.   Vnews
  3.  
  4.   Started by: Stephen Vermeulen 1987.
  5.  
  6.   26-Aug-1987  This version has been Manxified.
  7.                Also some workbench support has been implemented.
  8.  
  9.   This program is designed to be a simple news file reader.
  10.   The user invokes it with the name of the directory containing
  11.   the news files he wants to read.  The program then allows
  12.   him to read these files easily.
  13.  
  14.   Syntax from CLI:
  15.  
  16.          vnews [dir_name [first_file]]
  17.  
  18.          vnews dir_name
  19.  
  20.            will display the contents of all the files in
  21.            the directory named dir_name.
  22.  
  23.          vnews
  24.  
  25.            will display the contents of all the files in
  26.            the current directory.
  27.  
  28.          vnews dir_name first_file
  29.  
  30.            will allow you to read all the files within the
  31.            directory "dir_name" and will start you at
  32.            file "first_file"
  33.  
  34.   Syntax from Workbench:
  35.  
  36.         Just point and click.  To specify the directory to read the
  37.         news files from enter the following line into the TOOL TYPES
  38.         field:
  39.  
  40.            DIR=MyDirectoryName
  41.  
  42.         The default width that tabs are to be expanded to is specified
  43.         by the following line:
  44.  
  45.            TAB=n
  46.  
  47.         where n is a small positive number.
  48.  
  49.         The reading can start with any particular file, just include
  50.         a line like:
  51.  
  52.            FIRST=first_file_name
  53.  
  54. NOTE:  some aspects of the code are clearly examples of how
  55.        not to code in C!  Ie: I have made extensive and
  56.        unforgivable use of the GOTO statement...
  57. ************************************************************/
  58.  
  59. #include <intuition/intuition.h>
  60. #include <graphics/gfxmacros.h>
  61. #include <workbench/startup.h>
  62. #include <workbench/workbench.h>
  63. #include <stdio.h>
  64. #include <functions.h>
  65.  
  66. #define PGUP 1
  67. #define PGDN 2
  68. #define NEXT 3
  69. #define PREV 4
  70. #define HELP 5
  71. #define FILE_GAD 6
  72.  
  73. struct IntuitionBase *IntuitionBase;  /* to use intuition functions */
  74. struct GfxBase *GfxBase;              /* to use graphics functions  */
  75. extern long IconBase;
  76. extern struct WBStartup *WBenchMsg;
  77.  
  78. #define MAX_FILES 1000
  79.  
  80. /**************************************
  81.   Yuck, static list size in the Amiga?
  82.   Poor programming, bad boy, naughty...
  83.   Seriously though, since good old
  84.   Ami needs at least 2 blocks per file
  85.   and there are only 1800 blocks on a
  86.   floppy this should suffice for all
  87.   but nutty hard disk owners...
  88. ***************************************/
  89.  
  90. char *file_list[MAX_FILES];
  91.  
  92. /************************************************************
  93.   The following stuff sets up the window to be used to display
  94.   the text along with its gadgets that advance you through
  95.   the text of a single message, of from message to message.
  96.  
  97.   The following gadgets are provided:
  98.  
  99.     PgUp  - display next page of the current message
  100.     PgDn  - displays the previous page of the current message
  101.     Next  - displays the next message
  102.     Prev  - displays the previous message
  103.  
  104.   These all live in the title bar, along with the name of
  105.   the file that is being displayed.
  106. ************************************************************/
  107.  
  108. #define LEFT_OFFSET 300
  109.  
  110. struct IntuiText pgup_text =
  111. {
  112.   1, 0, JAM2, 0, 0, NULL, (UBYTE *) "Prev", NULL
  113. };
  114.  
  115. struct IntuiText pgdn_text =
  116. {
  117.   1, 0, JAM2, 0, 0, NULL, (UBYTE *) "back", NULL
  118. };
  119.  
  120. struct IntuiText next_text =
  121. {
  122.   1, 0, JAM2, 0, 0, NULL, (UBYTE *) "fore", NULL
  123. };
  124.  
  125. struct IntuiText prev_text =
  126. {
  127.   1, 0, JAM2, 0, 0, NULL, (UBYTE *) "Next", NULL
  128. };
  129.  
  130. struct IntuiText help_text =
  131. {
  132.   1, 0, JAM2, 0, 0, NULL, (UBYTE *) "?", NULL
  133. };
  134.  
  135. struct Gadget pgup_gad =
  136. {
  137.   NULL,
  138.   LEFT_OFFSET, 0, 32, 10,
  139.   GADGHCOMP, RELVERIFY | TOPBORDER,  BOOLGADGET,
  140.   NULL, NULL,
  141.   &pgup_text,
  142.   NULL,  NULL,  PREV,  NULL
  143. };
  144.  
  145. struct Gadget pgdn_gad =
  146. {
  147.   &pgup_gad,
  148.   LEFT_OFFSET+48, 0, 32, 10,
  149.   GADGHCOMP, RELVERIFY | TOPBORDER,  BOOLGADGET,
  150.   NULL, NULL,
  151.   &pgdn_text,
  152.   NULL,  NULL,  PGDN,  NULL
  153. };
  154.  
  155. struct Gadget next_gad =
  156. {
  157.   &pgdn_gad,
  158.   LEFT_OFFSET+96, 0, 32, 10,
  159.   GADGHCOMP, RELVERIFY | TOPBORDER,  BOOLGADGET,
  160.   NULL, NULL,
  161.   &next_text,
  162.   NULL,  NULL,  PGUP,  NULL
  163. };
  164.  
  165. struct Gadget prev_gad =
  166. {
  167.   &next_gad,
  168.   LEFT_OFFSET+144, 0, 32, 10,
  169.   GADGHCOMP, RELVERIFY | TOPBORDER,  BOOLGADGET,
  170.   NULL, NULL,
  171.   &prev_text,
  172.   NULL,  NULL,  NEXT,  NULL
  173. };
  174.  
  175. struct Gadget help_gad =
  176. {
  177.   &prev_gad,
  178.   LEFT_OFFSET+192, 0, 8, 10,
  179.   GADGHCOMP, RELVERIFY | TOPBORDER,  BOOLGADGET,
  180.   NULL, NULL,
  181.   &help_text,
  182.   NULL,  NULL,  HELP,  NULL
  183. };
  184.  
  185. char file_string[32] = "";
  186.  
  187. struct StringInfo file_info =
  188. {
  189.   (UBYTE *) &file_string,
  190.   NULL,
  191.   0, 30,
  192.   0, 0, 0, 0,
  193.   0, 0,
  194.   NULL, 0, NULL
  195. };
  196.  
  197. struct Gadget file_gad =
  198. {
  199.   &help_gad,
  200.   LEFT_OFFSET+208, 0, 78, 10,
  201.   GADGHCOMP, RELVERIFY | TOPBORDER,  STRGADGET,
  202.   NULL, NULL,
  203.   NULL,
  204.   NULL,
  205.   (APTR) &file_info,  FILE_GAD,  NULL
  206. };
  207.  
  208. struct NewWindow nw =
  209. {
  210.   0, 3, 640, 200-3,  /* we should go for the max in case morerows was used */
  211.   -1, -1,
  212.   GADGETUP | CLOSEWINDOW,
  213.   WINDOWDEPTH | WINDOWCLOSE | SMART_REFRESH | BORDERLESS | ACTIVATE,
  214.   &file_gad,
  215.   NULL,
  216.   NULL,
  217.   NULL, /* default screen */
  218.   NULL, /* no special bm */
  219.   0, 0, -1, -1,
  220.   WBENCHSCREEN
  221. };
  222.  
  223. struct NewWindow new_help =
  224. {
  225.   168, 47, 304, 110,
  226.   -1, -1,
  227.   CLOSEWINDOW,
  228.   WINDOWDEPTH | WINDOWCLOSE | SMART_REFRESH,
  229.   NULL,
  230.   NULL,
  231.   (UBYTE *) "Vnews Help",
  232.   NULL, /* default screen */
  233.   NULL, /* no special bm */
  234.   0, 0, -1, -1,
  235.   WBENCHSCREEN
  236. };
  237.  
  238. /************************************************************
  239.   This array is used to hold offsets from the start of the
  240.   file to the nth page in it, so the PgDn function works, as
  241.   the file is paged through by hitting PgUp the position of
  242.   each page start is entered into the array, then when PgDn
  243.   is hit you can easily backup.
  244. ************************************************************/
  245.  
  246. unsigned long int page_top[MAX_FILES];
  247. short current_page;  /* index for the page_top array */
  248. short current_file;  /* index for the file name array */
  249. struct Window *w;
  250. FILE *in;
  251.  
  252. /************************************************************
  253.   The display_page() function displays a page of text from
  254.   the file on the screen.  It first clears the window, then
  255.   it does a line by line display of the file, it reads from
  256.   the line one line of text at a time, printing each line of
  257.   text to the window and then advancing to the next line on
  258.   the window, when it has printed 23 lines of text the process
  259.   stops.
  260. ************************************************************/
  261.  
  262. char temp_buf[200];
  263.  
  264. /************************************************************
  265.   The clean_string function removes CR's from the text string
  266.   and expands tabs out to tabwidth spaces each.
  267.  
  268.   Note the value for tabwidth can only be specified if the
  269.   program is started from the workbench.
  270. ************************************************************/
  271.  
  272. short tabwidth;
  273.  
  274. void clean_string(s)
  275. register char *s;
  276. {
  277.   register int n;
  278.   register int i, j, k;
  279.  
  280.   n = strlen(s);
  281.   if (n)
  282.   {
  283.     if (index(s, 10) || index(s, 13) || index(s, 9))
  284.     {
  285.       for (i = 0; i < n; ++i)
  286.       {
  287.         switch(s[i])
  288.         {
  289.           case 10:  /* line feed -- replace with space */
  290.           case 13:  /* carriage return -- replace with space */
  291.             s[i] = ' ';
  292.             break;
  293.           case 9:   /* tab -- expand to tabwidth spaces */
  294.             s[i] = ' ';
  295.             if (tabwidth > 1)
  296.             {
  297.               /*****************************
  298.                 First figure out how far to
  299.                 the next tab stop.
  300.               ******************************/
  301.  
  302.               k = tabwidth - (i % tabwidth);
  303.  
  304.               if (k > 1)
  305.               {
  306.                 movmem(s + i + 1, s + i + k, n - i);
  307.                 for (j = 1; j < k; ++j)
  308.                   s[i+j] = ' ';
  309.                 n += k;
  310.               }
  311.             }
  312.             break;
  313.         }
  314.       }
  315.     }
  316.   }
  317. }
  318.  
  319. void display_page()
  320. {
  321.   int dy;
  322.  
  323.   SetAPen(w->RPort, 0L);
  324.   RectFill(w->RPort, 0L, (long) w->BorderTop + 1,
  325.                      (long) w->Width - 1, (long) w->Height - w->BorderBottom);
  326.   SetAPen(w->RPort, 1L);
  327.   dy = w->RPort->TxHeight;
  328.   Move(w->RPort, 0L, (long) w->BorderTop + dy);
  329.   while((w->RPort->cp_y + dy) < w->Height) /* enough room */
  330.   {
  331.     if (fgets(temp_buf, 80, in))
  332.     {
  333.       temp_buf[80] = 0;      /* always force an end of string here
  334.                                 as fgets does not put one in if 80
  335.                                 characters were read before any
  336.                                 end of line type character was hit
  337.                               */
  338.       clean_string(temp_buf);
  339.  
  340.       /*********************************************
  341.         This is not the best way of doing it, because
  342.         lines that are longer than about 80 characters
  343.         get truncated.  One should really break long
  344.         lines appropriately so that all the text does
  345.         get displayed.
  346.  
  347.         This problem has been partially eliminated
  348.         by reading in only 80 character chunks from
  349.         the file by the fgets() function.  This is
  350.         not the true solution because it depends on the
  351.         font that is being used.
  352.       *********************************************/
  353.  
  354.       Text(w->RPort, temp_buf, (long) strlen(temp_buf));
  355.       w->RPort->cp_x = 0;
  356.       w->RPort->cp_y += dy;
  357.     }
  358.     else  /* we have reached EOF */
  359.     {
  360.       clean_string(temp_buf);
  361.       Text(w->RPort, temp_buf, (long) strlen(temp_buf));
  362.       goto eof_stop;
  363.     }
  364.   }
  365. eof_stop:
  366.   return;
  367. }
  368.  
  369. /************************************************************
  370.   The next_page() function has three modes depending on the
  371.   value of n:
  372.  
  373.     -1  - Move to the previous page and display one page of the
  374.           file.
  375.  
  376.      0  - Display the file from the very first line.
  377.  
  378.     +1  - Move the file to the next page and display it.
  379. ************************************************************/
  380.  
  381. void next_page(n)
  382. short n;
  383. {
  384.   unsigned long int pos;
  385.  
  386.   if (!in) return;
  387.   switch(n)
  388.   {
  389.     case -1:
  390.       if (current_page) --current_page;
  391.       fseek(in, page_top[current_page], 0);
  392.       display_page();
  393.       break;
  394.     case 0:
  395.       current_page = 0;
  396.       page_top[0] = 0;
  397.       display_page();
  398.       break;
  399.     case 1:
  400.       pos = ftell(in);
  401.       if (pos != EOF)
  402.       {
  403.         if (current_page < MAX_FILES) ++current_page;
  404.         page_top[current_page] = pos;
  405.         display_page();
  406.       }
  407.       break;
  408.   }
  409. }
  410.  
  411. /************************************************************
  412.   The next file function has three modes depending on the
  413.   value of n:
  414.  
  415.   -1 - Move to the previous file in the file list.
  416.    0 - Open the very first file in the file list.
  417.   +1 - Move to the next file in the file list.
  418. *************************************************************/
  419.  
  420. void next_file(n)
  421. short n;
  422. {
  423.   switch(n)
  424.   {
  425.     case -1:
  426.       if (current_file) --current_file;
  427.       if (in) fclose(in);
  428.       in = fopen(file_list[current_file], "r");
  429.       break;
  430.     case 0:
  431.       current_file = 0;
  432.       in = fopen(file_list[current_file], "r");
  433.       break;
  434.     case 1:
  435.       if (current_file < MAX_FILES) ++current_file;
  436.       if (in) fclose(in);
  437.       in = fopen(file_list[current_file], "r");
  438.       break;
  439.   }
  440.   if (in)
  441.   {
  442.     SetWindowTitles(w, file_list[current_file], -1L);
  443.   }
  444.   else
  445.   {
  446.     SetWindowTitles(w, "No more news!", -1L);
  447.   }
  448. }
  449.  
  450. extern char *scdir();
  451. extern char *malloc();
  452.  
  453. /******************************
  454.   Function to compare strings
  455. ******************************/
  456.  
  457. compare(a, b)
  458. char **a, **b;
  459. {
  460.   return(strcmp(*a, *b));
  461. }
  462.  
  463. /***************************************
  464.   this function scans the current
  465.   directory, using the "pattern" string,
  466.   placing pointers to the file names in
  467.   the file_names array, it allocates the
  468.   nessecary string space, up to a maximum
  469.   of nmax strings.
  470.  
  471.   Oh yes, it sorts the strings with the
  472.   function comp too.
  473. *****************************************/
  474.  
  475. get_dir(pattern, file_names, nmax, comp)
  476. char *pattern, *file_names[];
  477. short nmax;
  478. short (*comp)();
  479. {
  480.   char *s;
  481.   int i, j;
  482.  
  483.   /*********************************
  484.     Paranoia time, zero all pointers
  485.     manually...
  486.   **********************************/
  487.  
  488.   for (i = 0; i < nmax; ++i)
  489.     file_names[i] = 0;
  490.  
  491.   i = 0;
  492.  
  493.   while((s = scdir(pattern)) && (i < nmax))
  494.   {
  495.     if (file_names[i] = malloc(strlen(s) + 1))
  496.     {
  497.       strcpy(file_names[i], s);
  498.       ++i;
  499.     }
  500.   }
  501.  
  502.   /******************************************
  503.     Now sort the file lists that have been
  504.     built up.
  505.   ******************************************/
  506.  
  507.   qsort(file_names, i, 4, comp);
  508. }
  509.  
  510. /**********************************************
  511.   this function frees up the space taken by the
  512.   copys of the strings.
  513. ***********************************************/
  514.  
  515. free_strings(file_names, nmax)
  516. char *file_names[];
  517. short nmax;
  518. {
  519.   short j;
  520.  
  521.   j = 0;
  522.   while (file_names[j])
  523.   {
  524.     free(file_names[j]);
  525.     ++j;
  526.   }
  527. }
  528.  
  529. /************************************************
  530.   This is a function that gets a value from a
  531.   tool type field.  You give it a toolarry pointer
  532.   a tooltype string and a conversion string and
  533.   a pointer of where to put the result.
  534. *************************************************/
  535.  
  536. getToolValue(ta, tt, cs, x)
  537. char **ta;
  538. char *tt, *cs, *x;
  539. {
  540.   char *s;
  541.  
  542.   if (s = FindToolType(ta, tt))
  543.     sscanf(s, cs, x);
  544. }
  545.  
  546. /************************************************
  547.   The following is a function that returns TRUE
  548.   is a certain tool type mode is set.
  549. *************************************************/
  550.  
  551. isToolModeSet(ta, tt, tm)
  552. char **ta, *tt, *tm;
  553. {
  554.   char *s;
  555.  
  556.   if (s = FindToolType(ta, tt))
  557.     return((short) MatchToolValue(s, tm));
  558.   return(0);
  559. }
  560.  
  561. char start_name[90], directory[90], temp[90], dir_path[90];
  562.  
  563. void main(argc, argv)
  564. int argc;
  565. char *argv[];
  566. {
  567.   int flag;
  568.   int func, class, i;
  569.   struct IntuiMessage *mess;
  570.   struct Screen wb_screen;
  571.   struct Window *hw;
  572.   char **toolarray;
  573.   struct WBArg *arg;
  574.   struct DiskObject *diskobj;
  575.  
  576.   IntuitionBase = (struct IntuitionBase *)
  577.                   OpenLibrary("intuition.library", 0L);
  578.   if (!IntuitionBase) goto no_intuition;
  579.   GfxBase = (struct GfxBase *) OpenLibrary("graphics.library", 0L);
  580.   if (!GfxBase) goto no_graphics;
  581.   IconBase = (long) OpenLibrary("icon.library", 0L);
  582.   if (!IconBase) goto no_icons;
  583.  
  584.   tabwidth = 2;
  585.   start_name[0] = 0;
  586.   dir_path[0] = 0;
  587.  
  588.   /**************************
  589.     Are we running from CLI
  590.     or the Workbench?
  591.   **************************/
  592.  
  593.   if (argc)
  594.   {
  595.     /************************
  596.       Running from the CLI
  597.     ************************/
  598.  
  599.     if (argc > 1)
  600.     {
  601.       strcpy(start_name, argv[1]);
  602.       strcpy(dir_path, argv[1]);
  603.       if (start_name[strlen(start_name) - 1] == ':')
  604.         strcat(start_name, "*");
  605.       else
  606.       {
  607.         strcat(start_name, "/*");
  608.         strcat(dir_path, "/");
  609.       }
  610.     }
  611.     else
  612.       strcpy(start_name, "*");
  613.     get_dir(start_name, file_list, MAX_FILES, compare);
  614.     if (argc > 2)
  615.     {
  616.       strcpy(start_name, argv[1]);
  617.       if (start_name[strlen(start_name) - 1] == ':')
  618.         strcat(start_name, argv[2]);
  619.       else
  620.       {
  621.         strcat(start_name, "/");
  622.         strcat(start_name, argv[2]);
  623.       }
  624.     }
  625.     else
  626.       start_name[0] = 0;
  627.   }
  628.   else
  629.   {
  630.     /****************************
  631.       Running from the Workbench
  632.  
  633.       Arg will always point to the
  634.       tool's icon.  So what we must
  635.       do is scan this tool type
  636.       array to read in the name of
  637.       the directory to use and the
  638.       name of the first file to
  639.       start with and the tab size.
  640.     *****************************/
  641.  
  642.     arg = WBenchMsg->sm_ArgList;
  643.  
  644.     /**************************************
  645.       First we change our current directory
  646.       to the location of the program.  This
  647.       is needed in case the user just specifies
  648.       a relative directory path name.
  649.     ***************************************/
  650.  
  651.     (void) CurrentDir(arg->wa_Lock);
  652.     diskobj = GetDiskObject(arg->wa_Name);
  653.  
  654.     /*********************************
  655.       now parse the tooltypes array
  656.     **********************************/
  657.  
  658.     directory[0] = 0;
  659.     temp[0] = 0;
  660.     if (diskobj)
  661.     {
  662.       toolarray = diskobj->do_ToolTypes;
  663.       getToolValue(toolarray, "TAB", "%d", &tabwidth);
  664.       getToolValue(toolarray, "DIR", "%s", directory);
  665.       getToolValue(toolarray, "FIRST", "%s", temp);
  666.       FreeDiskObject(diskobj);
  667.     }
  668.     if (temp[0])
  669.     {
  670.       strcpy(start_name, directory);
  671.       strcpy(dir_path, directory);
  672.       if (start_name[strlen(start_name) - 1] == ':')
  673.         strcat(start_name, temp);
  674.       else
  675.       {
  676.         strcat(start_name, "/");
  677.         strcat(dir_path, "/");
  678.         strcat(start_name, temp);
  679.       }
  680.     }
  681.     if (directory[strlen(directory) - 1] == ':')
  682.       strcat(directory, "*");
  683.     else
  684.       strcat(directory, "/*");
  685.     get_dir(directory, file_list, MAX_FILES, compare);
  686.   }
  687.  
  688.   /****************************************
  689.     The directory has now been read and sorted
  690.     it is time to walk through the files.
  691.  
  692.     Lets open the window so that it makes full
  693.     use of the workbench screen.
  694.   ****************************************/
  695.  
  696.   GetScreenData(&wb_screen, (long) sizeof(struct Screen), WBENCHSCREEN, NULL);
  697.   nw.Width = wb_screen.Width;
  698.   nw.Height = wb_screen.Height - 3;
  699.   w = (struct Window *) OpenWindow(&nw);
  700.   if (!w) goto no_window; /* can't open window error */
  701.   if (start_name[0]) /* start at this file */
  702.   {
  703.     current_file = 0;
  704.     while (strcmp(start_name, file_list[current_file]) &&
  705.            file_list[current_file]) ++current_file;
  706.     --current_file;
  707.     next_file(1);
  708.     next_page(0);
  709.   }
  710.   else
  711.   {
  712.     next_file(0);      /* open a new file (the first) for display */
  713.     next_page(0);     /* display the next page in this file */
  714.   }
  715.   flag = TRUE;
  716.   while(flag)
  717.   {
  718.     Wait(1L << w->UserPort->mp_SigBit);
  719.     while(mess = (struct IntuiMessage *) GetMsg(w->UserPort))
  720.     {
  721.       func = ((struct Gadget *) mess->IAddress)->GadgetID;
  722.       class = mess->Class;
  723.       ReplyMsg(mess);
  724.       if (class == CLOSEWINDOW) flag = FALSE;
  725.       switch(func)
  726.       {
  727.         case PGUP:
  728.           if (feof(in))
  729.           {
  730.             next_file(1);
  731.             next_page(0);
  732.           }
  733.           else
  734.             next_page(1);
  735.           break;
  736.         case PGDN:
  737.           if (current_page == 0)
  738.           {
  739.             next_file(-1);
  740.             next_page(0);
  741.           }
  742.           else
  743.             next_page(-1);
  744.           break;
  745.         case NEXT:
  746.           next_file(1);
  747.           next_page(0);
  748.           break;
  749.         case PREV:
  750.           next_file(-1);
  751.           next_page(0);
  752.           break;
  753.         case HELP:
  754.           if (hw = OpenWindow(&new_help))
  755.           {
  756.             Move(hw->RPort, 4L, 18L);
  757.             Text(hw->RPort, "------------  Vnews 1.1  -----------", 36L);
  758.             Move(hw->RPort, 4L, 26L);
  759.             Text(hw->RPort, "By: Stephen Vermeulen (403) 282-7990", 36L);
  760.             Move(hw->RPort, 4L, 34L);
  761.             Text(hw->RPort, "            Copyright 1987          ", 36L);
  762.             Move(hw->RPort, 4L, 42L);
  763.             Text(hw->RPort, "This program is in the public domain", 36L);
  764.             Move(hw->RPort, 4L, 50L);
  765.             Text(hw->RPort, "except it may not be sold or packaged", 37L);
  766.             Move(hw->RPort, 4L, 58L);
  767.             Text(hw->RPort, "with a commercial product.          ", 36L);
  768.             Move(hw->RPort, 4L, 66L);
  769.             Text(hw->RPort, "To use just click on the title bar  ", 36L);
  770.             Move(hw->RPort, 4L, 74L);
  771.             Text(hw->RPort, "icons:", 6L);
  772.             Move(hw->RPort, 4L, 82L);
  773.             Text(hw->RPort, "Prev  gets you to the previous file ", 36L);
  774.             Move(hw->RPort, 4L, 90L);
  775.             Text(hw->RPort, "Back  moves backwards one page      ", 36L);
  776.             Move(hw->RPort, 4L, 98L);
  777.             Text(hw->RPort, "Fore  moves foward one page         ", 36L);
  778.             Move(hw->RPort, 4L, 106L);
  779.             Text(hw->RPort, "Next  gets you to the next file     ", 36L);
  780.             Wait(1L << hw->UserPort->mp_SigBit);
  781.             while(mess = (struct IntuiMessage *) GetMsg(hw->UserPort))
  782.               ReplyMsg(mess);
  783.             CloseWindow(hw);
  784.           }
  785.           break;
  786.         case FILE_GAD:
  787.  
  788.           /**************************************
  789.             Get a filename to go to from the user
  790.             The user has already typed it in, so
  791.             process it.  Note we will have to
  792.             preference it with the directory path!
  793.           ***************************************/
  794.  
  795.           strcpy(start_name, dir_path);
  796.           strcat(start_name, file_string);
  797.           if (start_name[0]) /* start at this file */
  798.           {
  799.             current_file = 0;
  800.             while (strcmp(start_name, file_list[current_file]) &&
  801.                    file_list[current_file]) ++current_file;
  802.             --current_file;
  803.             next_file(1);
  804.             next_page(0);
  805.           }
  806.           break;
  807.       }
  808.     } /* end of while more messages */
  809.   }  /* end of while(flag) */
  810.   CloseWindow(w);
  811.  
  812. no_window:
  813. dir_error:
  814.   free_strings(file_list, MAX_FILES);
  815. no_files:
  816.   CloseLibrary(IconBase);
  817. no_icons:
  818.   CloseLibrary(GfxBase);
  819. no_graphics:
  820.   CloseLibrary(IntuitionBase);
  821. no_intuition:
  822.   return;
  823. }
  824.