view.c
上传用户:hepax88
上传日期:2007-01-03
资源大小:1101k
文件大小:7k
源码类别:

TCP/IP协议栈

开发平台:

Visual C++

  1. /* Random access file viewer. PC specific */
  2. #include <stdio.h>
  3. #include <conio.h>
  4. #include "global.h"
  5. #include "session.h"
  6. #include "tty.h"
  7. #include "commands.h"
  8. #include "socket.h"
  9. #include <dos.h>
  10. static long lineseek(FILE *fp,long offset,int nlines,int width);
  11. static int ctlproc(int c);
  12. int
  13. doview(argc,argv,p)
  14. int argc;
  15. char *argv[];
  16. void *p;
  17. {
  18. FILE *fp;
  19. if((fp = fopen(argv[1],READ_TEXT)) == NULL){
  20. printf("Can't read %sn",argv[1]);
  21. return 1;
  22. }
  23. newproc("view",512,view,0,(void *)fp,strdup(Cmdline),0);
  24. return 0;
  25. }
  26. /* Random-access file display program. Used both to read local
  27.  * files with the "view" command, and by the FTP client to view
  28.  * directory listings, temporary copies of read files, etc.
  29.  *
  30.  */
  31. void
  32. view(s,p1,p2)
  33. int s; /* If non-zero, poll interval for a changing file */
  34. void *p1; /* Open file pointer to read from */
  35. void *p2; /* If non-null, name to give to session. We free it */
  36. {
  37. struct session *sp;
  38. FILE *fp;
  39. char *name;
  40. int c;
  41. long offset = 0;
  42. int row,col;
  43. int cols;
  44. int rows;
  45. int32 polldelay = 0;
  46. struct text_info text_info;
  47. gettextinfo(&text_info);
  48. cols = text_info.screenwidth;
  49. rows = text_info.screenheight-1; /* Allow for status line */
  50. fp = (FILE *)p1;
  51. if(p2 != NULL)
  52. name = (char *)p2;
  53. else
  54. name = fpname(fp);
  55. if((sp = newsession(name,VIEW,1)) == NULL)
  56. return;
  57. if(p2 != NULL)
  58. free(name);
  59. if(s != 0)
  60. polldelay = s;
  61. sp->ctlproc = ctlproc;
  62. /* Put tty into raw mode so single-char responses will work */
  63. sp->ttystate.echo = sp->ttystate.edit = 0;
  64. for(;;){
  65. fseek(fp,offset,SEEK_SET);
  66. putchar(FF); /* Clear screen */
  67. /* Display a screen's worth of data, keeping track of
  68.  * cursor location so we know when the screen is full
  69.  */
  70. col = row = 0;
  71. while((c = getc(fp)),c != EOF){
  72. switch(c){
  73. case 'n':
  74. row++;
  75. col = 0;
  76. break;
  77. case 't':
  78. if(col < cols - 8)
  79. col = (col + 8) & ~7;
  80. break;
  81. default:
  82. col++;
  83. break;
  84. }
  85. if(col >= cols){
  86. /* Virtual newline caused by wraparound */
  87. col = 0;
  88. row++;
  89. }
  90. if(row >= rows)
  91. break; /* Screen now full */
  92. putchar(c);
  93. }
  94. #ifdef notdef
  95. if(feof(fp) && offset != 0){
  96. /* Hit end of file. Back up proper number of
  97.  * lines and try again.
  98.  */
  99. offset = lineseek(fp,offset,row-rows,cols);
  100. continue;
  101. }
  102. #endif
  103. fflush(stdout);
  104. /* If we hit the end of the file and the file may be
  105.  * growing, then set an alarm to time out the getchar()
  106.  */
  107. do {
  108. if(feof(fp) && polldelay != 0){
  109. kalarm(polldelay);
  110. }
  111. c = getchar(); /* Wait for user keystroke */
  112. kalarm(0L); /* Cancel alarm */
  113. if(c != -1 || errno != EALARM)
  114. break; /* User hit key */
  115. /* Alarm timeout; see if more data arrived by
  116.  * clearing the EOF flag, trying to read
  117.  * another byte, and then testing EOF again
  118.  */
  119. clearerr(fp);
  120. (void)getc(fp);
  121. c = ' '; /* Simulate a no-op keypress */
  122. } while(feof(fp));
  123. switch(c){
  124. case 'h': /* Home */
  125. case 'H':
  126. case '<': /* For emacs users */
  127. offset = 0;
  128. break;
  129. case 'e': /* End */
  130. case '>': /* For emacs users */
  131. fseek(fp,0L,SEEK_END);
  132. offset = lineseek(fp,ftell(fp),-rows,cols);
  133. break;
  134. case CTLD: /* Down one half screen (for VI users) */
  135. if(!feof(fp))
  136. offset = lineseek(fp,offset,rows/2,cols);
  137. break;
  138. case CTLU: /* Up one half screen (for VI users) */
  139. offset = lineseek(fp,offset,-rows/2,cols);
  140. break;
  141. case 'd': /* down line */
  142. case CTLN: /* For emacs users */
  143. case 'j': /* For vi users */
  144. if(!feof(fp))
  145. offset = lineseek(fp,offset,1,cols);
  146. break;
  147. case 'D': /* Down page */
  148. case CTLV: /* For emacs users */
  149. if(!feof(fp))
  150. offset = lineseek(fp,offset,rows,cols);
  151. break;
  152. case 'u': /* up line */
  153. case CTLP: /* for emacs users */
  154. case 'k': /* for vi users */
  155. offset = lineseek(fp,offset,-1,cols);
  156. break;
  157. case 'U': /* Up page */
  158. case 'v': /* for emacs users */
  159. offset = lineseek(fp,offset,-rows,cols);
  160. break;
  161. case CTLC:
  162. case 'q':
  163. case 'Q':
  164. case ESC:
  165. goto done;
  166. default:
  167. break; /* Redisplay screen */
  168. }
  169. }
  170. done: fclose(fp);
  171. freesession(sp);
  172. }
  173. /* Given a starting offset into an open file stream, scan forwards
  174.  * or backwards the specified number of lines and return a pointer to the
  175.  * new offset.
  176.  */
  177. static long
  178. lineseek(fp,start,nlines,width)
  179. FILE *fp; /* Open file stream */
  180. long start; /* Offset to start searching backwards from */
  181. int nlines; /* Number of lines to move forward (+) or back (-) */
  182. int width; /* Screen width (max line size) */
  183. {
  184. long offset;
  185. long *pointers;
  186. int col = 0;
  187. int c;
  188. int newlines = 0;
  189. if(nlines == 0)
  190. return start; /* Nothing to do */
  191. if(nlines > 0){ /* Look forward requested # of lines */
  192. fseek(fp,start,SEEK_SET);
  193. col = 0;
  194. while((c = getc(fp)),c != EOF){
  195. switch(c){
  196. case 'n':
  197. newlines++;
  198. col = 0;
  199. break;
  200. case 't':
  201. if(col < width - 8)
  202. col = (col + 8) & ~7;
  203. break;
  204. default:
  205. col++;
  206. break;
  207. }
  208. if(col >= width){
  209. /* Virtual newline caused by wraparound */
  210. col = 0;
  211. newlines++;
  212. }
  213. if(newlines >= nlines)
  214. break; /* Found requested count */
  215. }
  216. return ftell(fp); /* Could be EOF */
  217. }
  218. /* Backwards scan (the hardest)
  219.  * Start back up at most (width + 2) chars/line from the start.
  220.  * This handles full lines followed by expanded newline
  221.  * sequences
  222.  */
  223. nlines = -nlines;
  224. offset = (width + 2)*(nlines + 1);
  225. if(offset > start)
  226. offset = 0; /* Go to the start of the file */
  227. else
  228. offset = start - offset;
  229. fseek(fp,offset,SEEK_SET);
  230. /* Keep a circular list of the last 'nlines' worth of offsets to
  231.  * each line, starting with the first
  232.  */
  233. pointers = (int32 *)calloc(sizeof(long),nlines);
  234. pointers[newlines++ % nlines] = offset;
  235. /* Now count newlines up but not including the original
  236.  * starting point
  237.  */
  238. col = 0;
  239. for(;;){
  240. c = getc(fp);
  241. switch(c){
  242. case EOF:
  243. goto done;
  244. case 'n':
  245. col = 0;
  246. offset = ftell(fp);
  247. if(offset >= start)
  248. goto done;
  249. pointers[newlines++ % nlines] = offset;
  250. break;
  251. case 't':
  252. if(col < width - 8)
  253. col = (col + 8) & ~7;
  254. break;
  255. default:
  256. col++;
  257. break;
  258. }
  259. if(col >= width){
  260. /* Virtual newline caused by wraparound */
  261. col = 0;
  262. offset = ftell(fp);
  263. if(offset >= start)
  264. goto done;
  265. pointers[newlines++ % nlines] = offset;
  266. }
  267. }
  268. done:;
  269. if(newlines >= nlines){
  270. /* Select offset pointer nlines back */
  271. offset = pointers[newlines % nlines];
  272. } else {
  273. /* The specified number of newlines wasn't seen, so
  274.  * go to the start of the file
  275.  */
  276. offset = 0;
  277. }
  278. free(pointers);
  279. return offset;
  280. }
  281. /* Handle special keystrokes */
  282. static int
  283. ctlproc(c)
  284. int c;
  285. {
  286. switch(c){
  287. case 256 + 71: /* HOME */
  288. putc('h',Current->input);
  289. break;
  290. case 256 + 72: /* Cursor up */
  291. putc('u',Current->input);
  292. break;
  293. case 256 + 73: /* Page up */
  294. putc('U',Current->input);
  295. break;
  296. case 256 + 79: /* End */
  297. putc('e',Current->input);
  298. break;
  299. case 256 + 80: /* Cursor down */
  300. putc('d',Current->input);
  301. break;
  302. case 256 + 81: /* Page down */
  303. putc('D',Current->input);
  304. break;
  305. default:
  306. return c;
  307. }
  308. fflush(Current->input);
  309. return 0;
  310. }