home *** CD-ROM | disk | FTP | other *** search
/ Fish 'n' More 2 / fishmore-publicdomainlibraryvol.ii1991xetec.iso / dirs / stv_427.lzh / STV / source / file.c < prev    next >
C/C++ Source or Header  |  1991-01-09  |  8KB  |  302 lines

  1. /*********************************
  2. *  FILE  01/02/91
  3. *  Source file for STV
  4. *  © Copyright 1990 Timm Martin
  5. *  All Rights Reserved Worldwide
  6. **********************************/
  7.  
  8. #include <exec/types.h>
  9. #include <functions.h>
  10. #include <intuition/intuition.h>
  11. #include <libraries/dos.h>
  12. #include <stdio.h>
  13. #include <workbench/startup.h>
  14. #include "func.h"
  15. #include "main.h"
  16.  
  17. /*************************
  18. *  FILE BUFFER STRUCTURE
  19. **************************/
  20.  
  21. struct FileBuffer current_file =  /* GLOBAL */
  22. {
  23.   /* char *  Name       */ NULL,
  24.   /* char *  Partial    */ NULL,
  25.   /* char *  Buffer     */ NULL,
  26.   /* char ** Table      */ NULL,
  27.   /* long    BufferSize */ 0,
  28.   /* long    FileSize   */ 0,
  29.   /* long    TableSize  */ 0,
  30.   /* long    Lines      */ 0,
  31. };
  32.  
  33. /*
  34. need 1 extra byte for a newline to terminate the final line if it doesn't
  35. already have one
  36. */
  37. #define EXTRA 1
  38.  
  39. /*************
  40. *  FILE FREE
  41. **************/
  42.  
  43. /* 
  44. This procedure frees the memory used by the file buffer and line table and
  45. sets the corresponding pointers to NULL.
  46. */
  47.  
  48. void file_free( void )
  49. {
  50.   if (current_file.Buffer)
  51.   {
  52.     FreeMem( current_file.Buffer, current_file.BufferSize );
  53.     current_file.Buffer = NULL;
  54.   }
  55.   if (current_file.Table)
  56.   {
  57.     FreeMem( current_file.Table, current_file.TableSize );
  58.     current_file.Table = NULL;
  59.   }
  60.   /* so prop gadget won't be misadjusted */
  61.   current_file.Lines = 0;
  62. }
  63.  
  64. /*************
  65. *  FILE LOAD
  66. **************/
  67.  
  68. /* 
  69. This procedure attempts to load the specified file, returning YES or NO
  70. whether it was successful.
  71. */
  72.  
  73. BOOL file_load( void )
  74. {
  75.   REG char *c;            /* position in file */
  76.   char *end;              /* end of the buffer */
  77.   struct FileHandle *fp;  /* pointer to text file */
  78.   REG long lines;         /* number of lines in file (or current line) */
  79.   REG char *s;            /* start of current line */
  80.   long size;              /* size of the file in bytes */
  81.  
  82.   /* add extra byte needed */
  83.   current_file.BufferSize = current_file.FileSize + EXTRA;
  84.  
  85.   /* allocate memory to hold the file */
  86.   if (current_file.Buffer = AllocMem( current_file.BufferSize, NULL ))
  87.   {
  88.     /* try to open the file */
  89.     if (fp = Open( current_file.Name, MODE_OLDFILE ))
  90.     {
  91.       /* try to read entire file into buffer */
  92.       size = current_file.FileSize =
  93.              Read( fp, current_file.Buffer, current_file.FileSize );
  94.       
  95.       /* find the end of the file */
  96.       end = current_file.Buffer + size;
  97.       
  98.       /* need to count how many lines there are */
  99.       for (lines = 0, c = current_file.Buffer; c < end; c++)
  100.         if (*c == '\n')
  101.           lines++;
  102.       
  103.       /* if the very last character is not a newline, the last line won't
  104.        * be counted as a line, so need to count it and terminate it with
  105.        * a newline so that its length will be calculated.  If the file is
  106.        * empty, one blank line will be created.
  107.        */
  108.       if (!lines || *(c-1) != '\n')
  109.       {
  110.         *(c-1) = '\n';  /* add a newline */
  111.         end++;          /* increment end of the file */
  112.         lines++;        /* there's another line */
  113.       }
  114.  
  115.       /* record number of lines */
  116.       current_file.Lines     = lines;
  117.       /* add 1 extra line--the last line recorded is false */
  118.       current_file.TableSize = (lines + 1) * sizeof(char *);
  119.       
  120.       /* try to allocate memory to hold table--will always have at least one
  121.        * line
  122.        */
  123.       if (current_file.Table = AllocMem( current_file.TableSize, NULL ))
  124.       {
  125.         current_file.Table[0] = current_file.Buffer;
  126.         /* need to get pointer to beginning of each line */
  127.         for (lines = 1, c = current_file.Buffer; c < end; c++)
  128.         {
  129.           /* if reached end of this line */
  130.           if (*c == '\n')
  131.           {
  132.             /* get pointer to beginning of next line */
  133.             current_file.Table[lines++] = c + 1;
  134.             /* change newline to null */
  135.             *c = '\0';
  136.           }
  137.         }
  138.       } /* if allocated table memory */
  139.       
  140.       Close( fp );
  141.     } /* if opened file */
  142.   }   /* if allocated file memory */
  143.   
  144.   /* if didn't make it this far, something went wrong */
  145.   return (current_file.Table != NULL);
  146. }
  147.  
  148. /*************
  149. *  FILE NAME
  150. **************/
  151.  
  152. /* 
  153. This procedure saves the full path name, then tries to determine just the
  154. name of the file itself.
  155. */
  156.  
  157. void file_name( char *name )
  158. {
  159.   REG char *c;
  160.   int i;
  161.   
  162.   current_file.Name = name;
  163.   
  164.   /* find the end of the string */
  165.   for (c = name, i = 0; *c; c++, i++);
  166.   /* go backwards until reach beginning of string or a colon or slash */
  167.   while (i >= 0 && *c != '/' && *c != ':') { c--; i--; };
  168.   /* file name itself begins just after the slash or colon */
  169.   current_file.Partial = c + 1;
  170. }
  171.  
  172. /*************
  173. *  FILE READ
  174. **************/
  175.  
  176. /* 
  177. This function tries to read the specified file, displaying it in the window,
  178. and letting the user view it.  It returns when the user has presses ESCape or
  179. clicked on the close window gadget.  Either SELECT_STOP, SELECT_PREV, or
  180. SELECT_NEXT is returned (as returned by window_input()).
  181. */
  182.  
  183. #define IGNORE (void *)-1L
  184.  
  185. SELECT file_read( char *name, SELECT prev, SELECT next )
  186. {
  187.   char buffer[80];  /* to hold title */
  188.   SELECT file;      /* which file does user want next? */
  189.  
  190.   /* let user know loading file */
  191.   file_name( name );
  192.   sprintf( buffer, "Loading %s...", current_file.Partial );
  193.   SetWindowTitles( win, buffer, IGNORE );
  194.  
  195.   /* adjust the prev and next menu items */
  196.   menu_prevnext( prev, next );
  197.  
  198.   /* clear existing display, if any */
  199.   SetAPen( rp, BLUE );
  200.   RectFill( rp, (long)stats.LeftEdge, (long)stats.TopEdge,
  201.                 (long)stats.RightEdge, (long)stats.BottomEdge );
  202.  
  203.   /* get file size and try to load it */
  204.   if (file_size() && file_load())
  205.     sprintf( buffer, "%s (%ld lines, %ld bytes)", 
  206.              current_file.Partial, current_file.Lines, current_file.FileSize );
  207.   else
  208.   {
  209.     sprintf( buffer, "Could not read %s!", current_file.Partial );
  210.     /* do this now so won't read partial file and mess things up */
  211.     file_free();
  212.   }
  213.   /* let the user know what happened */
  214.   SetWindowTitles( win, buffer, IGNORE );
  215.  
  216.   /* set prop gadgets */
  217.   initialize();
  218.   /* display text */
  219.   text_display();
  220.   /* get window input */
  221.   file = input_window( prev, next );
  222.   /* get rid of file */
  223.   file_free();
  224.   
  225.   return (file);
  226. }
  227.  
  228. /***************
  229. *  FILE SELECT
  230. ****************/
  231.  
  232. /* 
  233. This procedure handles the selection of the current file.
  234. */
  235.  
  236. void file_select( void )
  237. {
  238.   SELECT current = 0;         /* current file--start with first one */
  239.   SELECT file = SELECT_SOME;  /* whether to stop or keep going */
  240.   char *name;                 /* name of the file to be loaded */
  241.   SELECT next;                /* is there a next file? */
  242.   SELECT prev;                /* is there a previous file? */
  243.   
  244.   /* while want to keep going */
  245.   while (file != SELECT_STOP)
  246.   {
  247.     /* if not working on file 0, there must be a previous file */
  248.     prev = current > 0 ? SELECT_SOME : SELECT_NONE;
  249.     /* if not working on last file, there must be a next file */
  250.     next = current < arguments.Files - 1 ? SELECT_SOME : SELECT_NONE;
  251.  
  252.     /* if from workbench */
  253.     if (arguments.ArgList)
  254.     {
  255.       /* need to change directory to that of file */
  256.       CurrentDir( (struct FileLock *)arguments.ArgList[current].wa_Lock );
  257.       name = arguments.ArgList[current].wa_Name;
  258.     }
  259.     else
  260.       /* else from CLI--just grab file name */
  261.       name = arguments.Names[current];
  262.  
  263.     /* read this file and find out what user wants to do next */
  264.     file = file_read( name, prev, next );
  265.     /* will add or subtract 1 based on whether NEXT or PREV */
  266.     current += file;
  267.   }
  268. }
  269.  
  270. /*************
  271. *  FILE SIZE
  272. **************/
  273.  
  274. /* 
  275. This function returns YES or NO whether the file size could be calculated. 
  276. The file size is placed in current_file.FileSize.
  277. */
  278.  
  279. #define INFO_SIZE (long)sizeof(struct FileInfoBlock)
  280. #define FAILED -1
  281.  
  282. BOOL file_size( void )
  283. {
  284.   struct FileInfoBlock *info;  /* to hold file information */
  285.   struct FileLock *lock;       /* need to lock file to get info */
  286.  
  287.   /* assume that this won't work */
  288.   current_file.FileSize = FAILED;
  289.   
  290.   if (lock = Lock( current_file.Name, ACCESS_READ ))
  291.   {
  292.     if (info = AllocMem( INFO_SIZE, NULL ))
  293.     {
  294.       if (Examine( lock, info ))
  295.         current_file.FileSize = info->fib_Size;
  296.       FreeMem( info, INFO_SIZE );
  297.     }
  298.     UnLock( lock );
  299.   }
  300.   return (current_file.FileSize != FAILED);
  301. }
  302.