home *** CD-ROM | disk | FTP | other *** search
/ Garbo / Garbo.cdr / pc / source / pct.arc / BROWSE.C next >
Text File  |  1986-04-01  |  15KB  |  597 lines

  1. /* b.c:    File Browse Facility */
  2.  
  3.  
  4. /* NOTE: The function "getcnb()" is a MWC-supplied function that
  5.          gets an unbuffered keypress from the standard input device.
  6.          Scan codes (keypad, etc.) are not interpreted.
  7. */
  8.  
  9. /* (c) Chuck Allison, 1986. */
  10.  
  11. #include <stdio.h>
  12. #include <ctype.h>
  13. #include <setjmp.h>
  14.  
  15. #define MAXLINE 1024
  16. #define MAXSIZE 5000
  17. /* SCRSIZ = number of screen rows - 2 */
  18. #define SCRSIZ 23
  19. #define OVRLP 3
  20. #define TABSPACE 8
  21. #define HORIZ_SCROLL 20
  22. #define TRIMLEN 30
  23.  
  24. int find(), prompt(), match(), browse(), n, screen_width=79,
  25.     cur_line, cur_col, tabstops[MAXLINE];
  26. char get_cmd(), *lines[MAXSIZE], fname[TRIMLEN];
  27. char *getstr();
  28. extern char *trim_fspec();
  29. jmp_buf env;
  30.  
  31. main(argc,argv)
  32. int argc;
  33. char *argv[];
  34. {
  35.     register i, j;
  36.  
  37.     clrscr();
  38.     settabs();
  39.  
  40.     if (argc == 1)
  41.     {
  42.         fputs("usage:  browse file1 [file2 ...]",stderr);
  43.         exit(1);
  44.     }
  45.  
  46.     /* ..Comment-out the following line if your compiler won't like it.. */
  47.     freopen("con","w",stdout);
  48.  
  49.     i = 1;
  50.     while (0 < i && i < argc)
  51.         if (freopen(argv[i],"r",stdin) != NULL)
  52.             i += browse(argv[i]);
  53.         else
  54.         {
  55.             /* ..file not found.. */
  56.             clrscr();
  57.             printf("%s not available.\n",argv[i]);
  58.             fputs("Hit any key...",stdout);
  59.             fflush(stdout);
  60.             getcnb();
  61.             /* ..remove filename from list.. */
  62.             for (j = i; j < argc-1; ++j)
  63.                 argv[j] = argv[j+1];
  64.             --argc;
  65.         }
  66.  
  67.     clrscr();
  68. }   
  69.             
  70. int browse(file)
  71. char *file;
  72. {
  73.     int factor, find_line, dir, column;
  74.     register i;
  75.     static char s[MAXLINE], t[MAXLINE];
  76.  
  77.     /* ..Read file.. */
  78.     clrscr();
  79.     setcur(SCRSIZ+1,1);
  80.     rvs(); bold();
  81.     printf("Reading %s ...",file); reset();
  82.     putchar(' '); column = 14+strlen(file);
  83.     for (n = 0; n < MAXSIZE-1 && fgets(s,MAXLINE-1,stdin) != NULL; ++n)
  84.     {
  85.         int sl;
  86.         sl = strlen(s);
  87.         if (s[sl-1] == '\n')
  88.             s[sl-1] = '\0';        /* zap newline */
  89.         detab(t,s);
  90.         trim(t);
  91.         lines[n] = (char *) malloc(strlen(t)+1);
  92.         if (lines[n] == NULL)
  93.         {
  94.             fputs("\nFile truncated.\n\nHit any key...",stderr);
  95.             getcnb();
  96.             break;
  97.         }
  98.         strcpy(lines[n],t);
  99.         setcur(SCRSIZ+1,column); printf("%4d",n);
  100.         fflush(stdout);
  101.     }
  102.  
  103.     if (n == 0)
  104.     {
  105.         fputs("\nFile is empty.\n\nHit any key... ",stdout);
  106.         fflush(stdout);
  107.         getcnb();
  108.         return 1;
  109.     }
  110.  
  111.     trim_fspec(fname,file,TRIMLEN-1);
  112.     strcpy(s,"");
  113.     cur_line = 0;
  114.     cur_col = 0;
  115.     setjmp(env);
  116.     paint();
  117.     
  118.     /* ..main loop: repeat forever.. */
  119.     for (;;)
  120.         switch(tolower(get_cmd(&factor)))
  121.         {
  122.             case 'u':
  123.                 /* ..window up.. */
  124.                 cur_line = max(0,cur_line-factor*SCRSIZ+OVRLP);
  125.                 if (cur_line > n-1)
  126.                    cur_line = 0;
  127.                 paint();
  128.                 break;
  129.             case 'd':
  130.                 /* ..window down.. */
  131.                 cur_line = min(n-1,cur_line+factor*SCRSIZ-OVRLP);
  132.                 if (cur_line < 0)
  133.                     cur_line = n-1;
  134.                 paint();
  135.                 break;
  136.             case '\015':
  137.             case '\004':
  138.                 /* ..window down one line.. */
  139.                 if (cur_line+SCRSIZ < n)
  140.                 {
  141.                     ++cur_line;
  142.                     setcur(SCRSIZ+2,1);
  143.                     if (cur_col < strlen(lines[cur_line+SCRSIZ-1]))
  144.                          printf("%-.*s\n",screen_width,
  145.                                  lines[cur_line+SCRSIZ-1]+cur_col);
  146.                     else
  147.                         putchar('\n');
  148.                     home();
  149.                     clear_line();
  150.                     rvs(); bold();
  151.                     printf("\"%s\" Lines: %d-%d  Cols: %d-%d",
  152.                       fname,cur_line+1,min(n,cur_line+SCRSIZ),cur_col+1,
  153.                       cur_col+screen_width);
  154.                     reset();
  155.                     setcur(SCRSIZ+2,1);
  156.                 }
  157.                 else
  158.                     beep();
  159.                 fflush(stdout);
  160.                 break; 
  161.             case '\033':
  162.             case '\025':
  163.                 /* ..window up one line.. */
  164.                 if (cur_line > 0)
  165.                 {
  166.                     --cur_line;
  167.                     paint();
  168.                 }
  169.                 else
  170.                     beep();
  171.                 fflush(stdout);
  172.                 break;
  173.             case 't':
  174.                 /* ..goto to top-of-file.. */
  175.                 cur_line = 0;
  176.                 paint();
  177.                 break;
  178.             case 'b':
  179.                 /* ..goto end-of-file.. */
  180.                 cur_line = max(0,n-SCRSIZ+1);              
  181.                 paint();
  182.                 break;
  183.             case 'r':
  184.                 /* ..scroll right.. */
  185.                 cur_col += factor*HORIZ_SCROLL;
  186.                 if (cur_col < 0)
  187.                     cur_col = MAXLINE-screen_width;    /* overflow check */
  188.                 cur_col = min(cur_col,MAXLINE-screen_width);
  189.                 paint();
  190.                 break;
  191.             case 'l':
  192.                 /* ..scroll left.. */
  193.                 cur_col -= factor*HORIZ_SCROLL;
  194.                 if (cur_col > MAXLINE-screen_width)
  195.                     cur_col = 0;        /* underflow check */
  196.                 cur_col = max(cur_col,0);
  197.                 paint();
  198.                 break;
  199.             case 'g':
  200.                 /* ..goto line number.. */
  201.                 if (factor >= 1 && factor <= n)
  202.                 {
  203.                     cur_line = factor-1;
  204.                     paint();
  205.                 }
  206.                 else
  207.                     beep();
  208.                 fflush(stdout);
  209.                 break;
  210.             case 'f':
  211.                 /* ..Find a string.. */
  212.                 dir = prompt(s);
  213.                 setcur(SCRSIZ+2,(screen_width-12)/2);
  214.                 bold(); blink();
  215.                 fputs("Searching...",stdout);
  216.                 reset();
  217.                 fflush(stdout);
  218.                 find_line = max(0,cur_line+dir);
  219.                 find_line = min(n-1,cur_line+dir);
  220.                 for (i = 1; i <= factor; ++i, find_line += dir)
  221.                     if (!find(s,&find_line,dir))
  222.                     {
  223.                         beep();
  224.                         fflush(stdout);
  225.                         goto nofind;
  226.                     }
  227.                 cur_line = max(0,find_line-dir);
  228.                 cur_line = min(n-1,find_line-dir);
  229. nofind:         paint();
  230.                 break;
  231.             case 's':
  232.             case '\006':
  233.                 /* ..Step-search.. */
  234.                 dir = prompt(s);
  235.                 do
  236.                 {
  237.                     setcur(SCRSIZ+2,(screen_width-12)/2);
  238.                     bold(); blink();
  239.                     fputs("Searching...",stdout);
  240.                     reset();
  241.                     fflush(stdout);
  242.                     find_line = max(0,cur_line+dir);
  243.                     find_line = min(n-1,cur_line+dir);
  244.                     if (!find(s,&find_line,dir))
  245.                     {
  246.                         beep();
  247.                         fflush(stdout);
  248.                         break;
  249.                     }
  250.                     cur_line = max(0,find_line);
  251.                     cur_line = min(n-1,find_line);
  252.                     paint();
  253.                     clear_line();
  254.                     rvs(); bold();
  255.                     fputs("Continue",stdout);
  256.                     reset();
  257.                     fputs(" (Y/N)? ",stdout);
  258.                     fflush(stdout);
  259.                 } while(tolower(getcnb()) == 'y');
  260.                 setcur(SCRSIZ+2,1);
  261.                 clear_line(); home(); clear_line(); rvs(); bold();
  262.                 printf("\"%s\" Lines: %d-%d  Cols: %d-%d",
  263.                   fname,cur_line+1,min(n,cur_line+SCRSIZ),cur_col+1,
  264.                   cur_col+screen_width);
  265.                 setcur(SCRSIZ+2,1); reset();
  266.                 fflush(stdout);
  267.                 break;
  268.             case 'h':
  269.                 help();
  270.                 paint();
  271.                 break;
  272.             case 'n':
  273.             case '\032':
  274.                 /* ..next file.. */
  275.                 clrscr();
  276.                 if (factor != 0)
  277.                 {
  278.                     release();
  279.                     return factor;
  280.                 }
  281.             case 'p':
  282.                 /* ..previous file.. */
  283.                 clrscr();
  284.                 if (factor != 0)
  285.                 {
  286.                     release();
  287.                     return -factor;
  288.                 }
  289.             case 'q':
  290.             case 'x':
  291.                 /* ..quit.. */
  292.                 clrscr();
  293.                 exit();
  294.             default:
  295.                 beep();
  296.                 fflush(stdout);
  297.         }
  298. }
  299.  
  300. char get_cmd(k)
  301. int *k;
  302. {
  303.     char c;
  304.     
  305.     /* ..get command with optional count prefix.. */
  306.     for (*k = 0; isdigit(c = getcnb()); *k = 10*(*k) + c-'0')
  307.         ;
  308.     if (*k == 0)
  309.         *k = 1;
  310.     return c;
  311. }
  312.  
  313. int prompt(s)
  314. char *s;
  315. {
  316.     char temp[MAXLINE], c;
  317.     
  318.     /* ..Get search-string.. */
  319.     home(); clear_line(); rvs(); bold();
  320.     printf("Find:");
  321.     reset();
  322.     printf(": ");
  323.     fflush(stdout);
  324.     if (getstr(temp,50) != NULL)
  325.         strcpy(s,temp);
  326.     else
  327.         fputs(s,stdout);
  328.     setcur(1,59); rvs(); bold(); 
  329.     fputs("F(orward)/B(ackward)",stdout);
  330.     reset(); 
  331.     fputs(": ",stdout);
  332.     fflush(stdout);
  333.     c = tolower(getcnb());
  334.     if (iscntrl(c))
  335.         longjmp(env,0);
  336.     return (c == 'b') ? -1 : 1;
  337. }
  338.  
  339. paint()
  340. {
  341.     register i;
  342.     
  343.     /* ..Print status line.. */
  344.     clrscr(); rvs(); bold();
  345.     printf("\"%s\"  Lines: %d-%d  Cols: %d-%d\n",fname,
  346.       cur_line+1,min(cur_line+SCRSIZ,n),cur_col+1,cur_col+screen_width);
  347.     reset();
  348.  
  349.     /* ..Paint screen with text lines.. */
  350.     for (i = cur_line; i < n && i < cur_line+SCRSIZ; ++i)
  351.         if (cur_col < strlen(lines[i]))
  352.             printf("%-.*s\n",min(strlen(lines[i]+cur_col),screen_width),
  353.               lines[i]+cur_col);
  354.         else
  355.             putchar('\n');
  356.  
  357.     if (i == n)
  358.     {
  359.         rvs();
  360.         fputs("*** End-of-File ***",stdout);
  361.         reset();
  362.     }
  363.     setcur(SCRSIZ+2,1);
  364.     fflush(stdout);
  365. }
  366.  
  367. int find(s,start,dir)
  368. char *s;
  369. int *start, dir;
  370. {
  371.     register i;
  372.     int found;
  373.     
  374.     /* ..find next occurrence of search-string.. */
  375.     found = 0;
  376.     for (i = *start; i < n && i >= 0; i += dir)
  377.         if ((found = match(lines[i],s)) == 1)
  378.             break;
  379.     *start = i;
  380.     return found;
  381. }
  382.  
  383.  
  384. int match(line,s)
  385. register char *line;
  386. char *s;
  387. {
  388.     register char *p;
  389.     
  390.     /* ..Check if search-string is in this line.. */
  391.     for (p = s; *line && *p; ++line)
  392.         if (tolower(*line) == tolower(*p))    /* ..Ignore case.. */
  393.             ++p;
  394.         else
  395.         {
  396.             line -= (p - s);
  397.             p = s;
  398.         }
  399.  
  400.     return (*p == '\0');
  401. }
  402.  
  403. detab(t,s)
  404. char *s, *t;
  405. {
  406.     register i, j;
  407.  
  408.     /* ..expand tabs; filter-out other control characters.. */
  409.     for (i = 0, j = 0; j < MAXLINE-1 && i < strlen(s); ++i)
  410.     if (s[i] == '\t')
  411.         do
  412.             t[j++] = ' ';
  413.         while (!tabstops[j]);
  414.     else if (!iscntrl(s[i]))
  415.         t[j++] = s[i];
  416.  
  417.     t[j] = '\0';
  418. }
  419.  
  420. settabs()
  421. {
  422.     register i;
  423.  
  424.     tabstops[0] = 0;
  425.     for (i = 1; i < MAXLINE; ++i)
  426.         tabstops[i] = (i%TABSPACE == 0);
  427. }
  428.  
  429. trim(s)
  430. char *s;
  431. {
  432.     register i;
  433.  
  434.     for (i = strlen(s)-1; i >= 0 && s[i] == ' '; --i)
  435.         ;
  436.     s[i+1] = '\0';
  437. }
  438.  
  439. help()
  440. {
  441.     /* ..Print help screen.. */
  442.     clrscr();
  443.     fputs("\n                             ",stdout);
  444.     bold(); rvs(); bold(); fputs("BROWSE UTILITY\n\n",stdout); reset();
  445.     bold(); fputs("\t   Screen Down",stdout);
  446.     reset(); fputs(" -        \t\t   D\n",stdout);
  447.     bold();  fputs("\tScreen Up",stdout);
  448.     reset(); fputs(" -          \t\t\U\n",stdout);
  449.     bold();  fputs("\tScreen Right",stdout);
  450.     reset(); fputs(" -       \t\tR\n",stdout);
  451.     bold();  fputs("\tScreen Left",stdout);
  452.     reset(); fputs(" -        \t\tL\n",stdout);
  453.     bold();  fputs("\tLine Down",stdout);
  454.     reset(); fputs(" -          \t\t^D, RETURN\n",stdout);
  455.     bold();  fputs("\tLine Up",stdout);
  456.     reset(); fputs(" -            \t\t^U, ESCAPE\n",stdout);
  457.     bold();  fputs("\tBottom-of-File",stdout);
  458.     reset(); fputs(" -     \t\tB\n",stdout);
  459.     bold();  fputs("\tTop-of-File",stdout);
  460.     reset(); fputs(" -        \t\tT\n",stdout);
  461.     bold();  fputs("\tGoto Line #",stdout);
  462.     reset(); fputs(" -        \t\t#G\n",stdout);
  463.     bold();  fputs("\tSearch (Find)",stdout);
  464.     reset(); fputs(" -      \t\tF\n",stdout);
  465.     bold();  fputs("\tStep-Search",stdout);
  466.     reset(); fputs(" -  \t\t\tS\n",stdout);
  467.     bold();  fputs("\tHelp",stdout);
  468.     reset(); fputs(" (this message) -\t\tH\n",stdout);
  469.     bold();  fputs("\tNext-file",stdout);
  470.     reset(); fputs(" -          \t\tN, ^Z\n",stdout);
  471.     bold();  fputs("\tPrevious-file",stdout);
  472.     reset(); fputs(" -      \t\tP\n",stdout);
  473.     bold();  fputs("\tChoose another file",stdout);
  474.     reset(); fputs(" -\t\t(Not available in this Version)\n",stdout);
  475.     bold();  fputs("\tQuit",stdout);
  476.     reset(); fputs(" -               \t\tQ, X\n",stdout);
  477.     fputs("\nThe commands U, D, F, N, P, R, and L may be preceded ",stdout);
  478.     fputs("by a repetition count.",stdout);
  479.     setcur(SCRSIZ+2,1);
  480.     bold(); fputs("...Hit any key to continue...",stdout); reset();
  481.     fflush(stdout);
  482.     getcnb();
  483. }
  484.  
  485. min(x,y) 
  486. int x, y;
  487. {
  488.     return (x <= y) ? x : y;
  489. }
  490.  
  491. max(x,y)
  492. int x, y;
  493. {
  494.     return (x >= y) ? x : y;
  495. }
  496.  
  497.  
  498. /* ..ANSI screen escape sequences.. */
  499.  
  500. setcur(row,col) 
  501. int row, col;
  502. {
  503.     printf("\033[%d;%dH",row,col);
  504. }
  505.  
  506. clrscr() 
  507. {
  508.     fputs("\033[2J",stdout);
  509. }
  510.  
  511. beep() 
  512. {
  513.     putchar('\007');
  514. }
  515.  
  516. home() 
  517. {
  518.     fputs("\033[H",stdout);
  519. }
  520.  
  521. clear_line() 
  522. {
  523.     fputs("\033[2K",stdout);
  524. }
  525.  
  526. clear_eol() 
  527. {
  528.     fputs("\033[K",stdout);
  529. }
  530.  
  531. reset() 
  532. {
  533.     fputs("\033[0m",stdout);
  534. }
  535.  
  536. bold() 
  537. {
  538.     fputs("\033[1m",stdout);
  539. }
  540.  
  541. underl() 
  542. {
  543.     fputs("\033[4m",stdout);
  544. }
  545.  
  546. blink() 
  547. {
  548.     fputs("\033[5m",stdout);
  549. }
  550.  
  551. rvs() 
  552. {
  553.     fputs("\033[7m",stdout);
  554. }
  555.  
  556.  
  557. release()
  558. {
  559.     register i;
  560.  
  561.     for (i = 0; i < n; ++i)
  562.         free(lines[i]);
  563. }
  564.  
  565. char *getstr(s,maxstr)
  566. char *s;
  567. int maxstr;
  568. {
  569.     char c, *p;
  570.  
  571.     p = s;
  572.     while (p-s < maxstr && (c = getcnb()) != '\r')
  573.         if (!iscntrl(c))
  574.         {
  575.             *p++ = c;
  576.             putchar(c);
  577.             fflush(stdout);
  578.         }
  579.         else if (c == '\b')
  580.             if (p > s)
  581.             {
  582.                 --p;
  583.                 fputs("\b \b",stdout);
  584.                 fflush(stdout);
  585.             }
  586.             else
  587.             {
  588.                 putchar('\007');
  589.                 fflush(stdout);
  590.             }
  591.         else
  592.             longjmp(env,0);
  593.  
  594.     *p = '\0';
  595.     return (p == s) ? NULL : s;
  596. }    
  597.