FILEVIEW.C 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352
  1. /* fileview.c - File viewing door that demonstrates the use of the */
  2. /* PagedViewer() function. This door can be setup to */
  3. /* to display a single text file, or any file from an */
  4. /* entire directory of text files. The program accepts */
  5. /* a single command-line argument, which if present, */
  6. /* specifies the filename or wildcard of the files to */
  7. /* display. If this argument is not present, all files */
  8. /* in the current directory will be available for */
  9. /* viewing. If there is more than one possible file to */
  10. /* be displayed, this program will display a list of */
  11. /* files that the user can choose from to display. If */
  12. /* there is only one possible file, that file is */
  13. /* is displayed. This program uses PagedViewer() for two */
  14. /* seperate uses - the list of available files, and for */
  15. /* viewing the file itself. */
  16. #include <stdlib.h>
  17. #include <string.h>
  18. #include <stdio.h>
  19. #include "bpfind.h"
  20. #include "opendoor.h"
  21. #include "pageview.h"
  22. /* Configurable constants. */
  23. #define FILENAME_SIZE 75
  24. #define PATH_CHARS (FILENAME_SIZE - 13)
  25. #define LINE_SIZE 80
  26. #define ARRAY_GROW_SIZE 20
  27. /* Global variables. */
  28. int nTotalFiles = 0;
  29. int nFileArraySize = 0;
  30. char *paszFileArray = NULL;
  31. FILE *pfCurrentFile;
  32. int nTotalLines = 0;
  33. int nLineArraySize = 0;
  34. long *palLineOffset = NULL;
  35. /* Function prototypes. */
  36. void AddFilesMatching(char *pszFileSpec);
  37. char *GetFilename(int nIndex);
  38. int AddFilename(char *pszFilename);
  39. void GetDirOnly(char *pszOutDirName, const char *pszInPathName);
  40. int DirExists(const char *pszDirName);
  41. void BuildPath(char *pszOut, char *pszPath, char *pszFilename);
  42. void FreeFileList(void);
  43. void DisplayFileName(int nLine, void *pCallbackData);
  44. void DisplayFile(char *pszFilename);
  45. void DisplayFileLine(int nLine, void *pCallbackData);
  46. int AddOffsetToArray(long lOffset);
  47. void FreeLineArray(void);
  48. /* Program execution begins here. */
  49. int main(int nArgCount, char *papszArgument[])
  50. {
  51. int nArg;
  52. int nChoice;
  53. od_init();
  54. /* Get file specifiction from command-line, if any. */
  55. if(nArgCount >= 2)
  56. {
  57. for(nArg = 1; nArg < nArgCount; ++nArg)
  58. {
  59. AddFilesMatching(papszArgument[nArg]);
  60. }
  61. }
  62. /* If there are no command-line parameters, use *.* */
  63. else
  64. {
  65. AddFilesMatching("*.*");
  66. }
  67. /* If there are no matching files, display error. */
  68. if(nTotalFiles == 0)
  69. {
  70. od_printf("No files were found.\n\r\n\r");
  71. od_printf("Press [Enter] to continue.\n\r");
  72. od_get_answer("\n\r");
  73. return(0);
  74. }
  75. /* If only one file was found, then display it. */
  76. else if(nTotalFiles == 1)
  77. {
  78. DisplayFile(GetFilename(0));
  79. }
  80. /* If more than one file was found, allow user to choose file */
  81. /* to display. */
  82. else
  83. {
  84. /* Loop until user chooses to quit. */
  85. nChoice = 0;
  86. for(;;)
  87. {
  88. /* Get user's selection. */
  89. nChoice = PagedViewer(nChoice, nTotalFiles, DisplayFileName,
  90. NULL, TRUE, "Choose A File To Display", 19);
  91. /* If user chose to quit, then exit door. */
  92. if(nChoice == NO_LINE) break;
  93. /* Otherwise, display the file that the user chose. */
  94. DisplayFile(GetFilename(nChoice));
  95. }
  96. }
  97. FreeFileList();
  98. return(0);
  99. }
  100. void AddFilesMatching(char *pszFileSpec)
  101. {
  102. struct ffblk DirEntry;
  103. int bNoMoreFiles;
  104. char szDirName[PATH_CHARS + 1];
  105. char szFileName[FILENAME_SIZE];
  106. /* Check that file specification is not too long. */
  107. if(strlen(pszFileSpec) > PATH_CHARS)
  108. {
  109. return;
  110. }
  111. /* Get directory name from path. */
  112. GetDirOnly(szDirName, pszFileSpec);
  113. bNoMoreFiles = findfirst(pszFileSpec, &DirEntry, FA_RDONLY);
  114. while(!bNoMoreFiles)
  115. {
  116. BuildPath(szFileName, szDirName, DirEntry.ff_name);
  117. AddFilename(szFileName);
  118. bNoMoreFiles = findnext(&DirEntry);
  119. }
  120. }
  121. void GetDirOnly(char *pszOutDirName, const char *pszInPathName)
  122. {
  123. char *pchBackslashChar;
  124. /* Default dir name is entire path. */
  125. strcpy(pszOutDirName, pszInPathName);
  126. /* If there is a backslash in the string. */
  127. pchBackslashChar = strrchr(pszOutDirName, '\\');
  128. if(pchBackslashChar != NULL)
  129. {
  130. /* Remove all character beginning at last backslash from path. */
  131. *pchBackslashChar = '\0';
  132. }
  133. else
  134. {
  135. /* If there is no backslash in the filename, then the dir name */
  136. /* is empty. */
  137. pszOutDirName[0] = '\0';
  138. }
  139. }
  140. void BuildPath(char *pszOut, char *pszPath, char *pszFilename)
  141. {
  142. /* Copy path to output filename. */
  143. strcpy(pszOut, pszPath);
  144. /* Ensure there is a trailing backslash. */
  145. if(strlen(pszOut) > 0 && pszOut[strlen(pszOut) - 1] != '\\')
  146. {
  147. strcat(pszOut, "\\");
  148. }
  149. /* Append base filename. */
  150. strcat(pszOut, pszFilename);
  151. }
  152. char *GetFilename(int nIndex)
  153. {
  154. return(paszFileArray + (nIndex * FILENAME_SIZE));
  155. }
  156. int AddFilename(char *pszFilename)
  157. {
  158. int nNewArraySize;
  159. char *paszNewArray;
  160. char *pszNewString;
  161. /* If array is full, then try to grow it. */
  162. if(nTotalFiles == nFileArraySize)
  163. {
  164. nNewArraySize = nFileArraySize + ARRAY_GROW_SIZE;
  165. if((paszNewArray =
  166. realloc(paszFileArray, nNewArraySize * FILENAME_SIZE)) == NULL)
  167. {
  168. return(FALSE);
  169. }
  170. nFileArraySize = nNewArraySize;
  171. paszFileArray = paszNewArray;
  172. }
  173. /* Get address to place new string at, while incrementing total number */
  174. /* of filenames. */
  175. pszNewString = GetFilename(nTotalFiles++);
  176. /* Copy up to the maximum number of filename characters to the string. */
  177. strncpy(pszNewString, pszFilename, FILENAME_SIZE - 1);
  178. pszNewString[FILENAME_SIZE - 1] = '\0';
  179. return(TRUE);
  180. }
  181. void FreeFileList(void)
  182. {
  183. if(nFileArraySize > 0)
  184. {
  185. free(paszFileArray);
  186. nFileArraySize = 0;
  187. nTotalFiles = 0;
  188. paszFileArray = NULL;
  189. }
  190. }
  191. void DisplayFileName(int nLine, void *pCallbackData)
  192. {
  193. (void)pCallbackData;
  194. od_printf(GetFilename(nLine));
  195. }
  196. void DisplayFile(char *pszFilename)
  197. {
  198. char szLine[LINE_SIZE];
  199. long lnOffset;
  200. /* Clear the screen. */
  201. od_clr_scr();
  202. /* Attempt to open the file. */
  203. pfCurrentFile = fopen(pszFilename, "r");
  204. if(pfCurrentFile == NULL)
  205. {
  206. od_printf("Unable to open file.\n\r\n\r");
  207. od_printf("Press [Enter] to continue.\n\r");
  208. od_get_answer("\n\r");
  209. return;
  210. }
  211. /* Get file offsets of each line and total line count from file. */
  212. for(;;)
  213. {
  214. lnOffset = fTell(pfCurrentFile);
  215. if(fgets(szLine, LINE_SIZE, pfCurrentFile) == NULL) break;
  216. AddOffsetToArray(lnOffset);
  217. }
  218. /* Use PagedViewer() to view the file. */
  219. PagedViewer(0, nTotalLines, DisplayFileLine, NULL, FALSE, NULL, 21);
  220. /* Deallocate array of line offsets. */
  221. FreeLineArray();
  222. /* Close the file. */
  223. fclose(pfCurrentFile);
  224. }
  225. void DisplayFileLine(int nLine, void *pCallbackData)
  226. {
  227. char szLine[LINE_SIZE];
  228. long lnTargetOffset = palLineOffset[nLine];
  229. int nLineLen;
  230. (void)pCallbackData;
  231. /* Move to proper offset in file. */
  232. if(lnTargetOffset != ftell(pfCurrentFile))
  233. {
  234. fseek(pfCurrentFile, lnTargetOffset, SEEK_SET);
  235. }
  236. /* Get line from line. */
  237. if(fgets(szLine, LINE_SIZE, pfCurrentFile) != NULL)
  238. {
  239. /* Remote any trailing CR/LF sequence from line. */
  240. nLineLen = strlen(szLine);
  241. while(nLineLen > 0
  242. && (szLine[nLineLen - 1] == '\r' || szLine[nLineLen - 1] == '\n'))
  243. {
  244. szLine[--nLineLen] = '\0';
  245. }
  246. /* Display the line on the screen. */
  247. od_disp_str(szLine);
  248. }
  249. }
  250. int AddOffsetToArray(long lOffset)
  251. {
  252. long *palNewArray;
  253. int nNewArraySize;
  254. /* If array is full, then grow it. */
  255. if(nTotalLines == nLineArraySize)
  256. {
  257. nNewArraySize = nLineArraySize + ARRAY_GROW_SIZE;
  258. if((palNewArray =
  259. realloc(palLineOffset, nNewArraySize * sizeof(long))) == NULL)
  260. {
  261. return(FALSE);
  262. }
  263. nLineArraySize = nNewArraySize;
  264. palLineOffset = palNewArray;
  265. }
  266. palLineOffset[nTotalLines++] = lOffset;
  267. return(TRUE);
  268. }
  269. void FreeLineArray(void)
  270. {
  271. if(nLineArraySize > 0)
  272. {
  273. nTotalLines = 0;
  274. nLineArraySize = 0;
  275. free(palLineOffset);
  276. palLineOffset = NULL;
  277. }
  278. }