home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / vol_200 / 240_01 / typeafil.c < prev    next >
Text File  |  1987-07-30  |  10KB  |  339 lines

  1. /*
  2. **  typeafil.c
  3. **  26 oct 86, dco
  4. */
  5.  
  6.  
  7. #include <stdlib.h>
  8. #include <string.h>
  9. #include <setjmp.h>
  10. #include <alloc.h>
  11. #include "ciao.h"
  12.  
  13.  
  14. /* 
  15. ** typeafile() -- type a file with optional word wrap in a window box
  16. */
  17.  
  18. #define MSG_SOURCE "ciao: typeafile"  /* version info could go here */
  19. #define PGUP 0xC9
  20. #define LINESIZE 128
  21. #define ESCMSG  "--PgUp reviews, any key continues, Esc quits--"
  22.  
  23. int Control_C_Flag = 0;  /* global informs caller that exit was by Control-C */
  24.  
  25. static FILE *f;
  26. static char *s, *word, *msg;
  27. static jmp_buf mk;
  28. static int lines, wide, deep, longline, wordwrap;
  29.  
  30. static int review = 0;
  31. static int contin = -1;
  32.  
  33.  
  34.  
  35.  
  36.  
  37. static void yo_heave_ho()     /* control-C, escape, ferror() grease trap */
  38. {
  39.      longjmp( mk, -1 );
  40. }
  41.  
  42.  
  43. static void cctrap()
  44. {
  45.       Control_C_Flag = 1;     /* inform caller of system level interrupt */
  46.       yo_heave_ho();
  47. }
  48. static int garm()
  49. {
  50.        return (0);
  51. }
  52.  
  53.  
  54. static void reframe()
  55. {
  56.       review = lines = 0;
  57.       rewind(f);
  58.       strcpy(s,"");
  59.       strcpy(word,"");
  60.       clrwindow();
  61. }
  62.  
  63.  
  64.  
  65. static void muf( p ) char *p;
  66. {
  67.      register int i;
  68.      register char *q;
  69.  
  70.      ++lines;
  71.  
  72.      /* allow typeafile() to read its own documentation; 
  73.      ** i.e., suppress ^ escape char commands by using
  74.      ** wink() instead of wputs()
  75.      */
  76.  
  77.      q = p;
  78.      while ( *q ) wink( *q++ );
  79.      wink('\n');
  80.  
  81.      if (lines >= deep)
  82.      {
  83.         wprintf("^1%s^", msg ); 
  84.         while( kbhit() ) getch();
  85.  
  86.         if ((i = keyin( noop )) == 27) yo_heave_ho();  /* FLOW STATEMENT #1 */
  87.         review = ((i == PGUP) || (i == '9'));          /* FLOW STATEMENT #2 */
  88.  
  89.         for ( i = strlen( msg ); i; i-- ) wink('\b');
  90.         clreol(); 
  91.         lines = 0;
  92.      }
  93. }
  94.  
  95.  
  96.  
  97.  
  98. static void showscreen()
  99. {
  100.     register char *q, *r;
  101.  
  102.     do
  103.     {
  104.          /* BLOCK:  get input, from file if necessary */
  105.  
  106.               if (strlen(word) >= wide)
  107.               {
  108.                   strcpy( s, word );
  109.                   strcpy( word, "" );
  110.               }
  111.               else
  112.               {
  113.                   if (feof(f))  /* this fixes the duplicate line bug at eof */
  114.                   {
  115.                        contin = 0;
  116.                        continue;
  117.                   }
  118.                   else
  119.                   {
  120.                        fgets( s, LINESIZE, f );      /* get next line from file */
  121.                   }
  122.                   if (ferror(f))
  123.                   {
  124.                        yo_heave_ho();
  125.                   }
  126.                   r = strchr( s, '\n' );  /* newline in string? */ 
  127.                   longline = 0;
  128.                   if ( r != NULL )
  129.                   {
  130.                       *r = '\0';          /* make line null terminated */
  131.                   }
  132.                   else longline = 1;      /* fixes extra space in longlines */
  133.               }
  134.  
  135.  
  136.          /* BLOCK:  handle word wrap */
  137.  
  138.               if (wordwrap && strlen(word) > 0) 
  139.               {
  140.                   if (strlen( s ) == 0)     /* we're at end of a paragraph! */
  141.                   {
  142.                       muf(word);            /* finish up last line */
  143.                       if (review) continue;
  144.                       muf(s);               /* put space between paragraphs */
  145.                       strcpy(word,"");
  146.                       continue;
  147.                   }
  148.                   else  /* insert old word(s) in front of new */
  149.                   {
  150.                       r = strrchr(word,'\0');
  151.                       r--;
  152.                       if (!longline)
  153.                       {
  154.                            if (*r != ' ')
  155.                                strcat( word, " ");
  156.                            if (strpbrk(r,".!?") != NULL)
  157.                                strcat( word, " ");
  158.                       }
  159.                       strcat( word, s );
  160.                       strcpy( s, word );
  161.                       strcpy( word,"" );
  162.                   }
  163.               }
  164.  
  165.  
  166.          /* BLOCK:  split s into s and word, if necessary */
  167.  
  168.               q = s + wide;                  /* find right margin */
  169.               r = strrchr(s, '\0');          /* find tail end */
  170.               if ( r > q )              /* tail is beyond margin */
  171.               {
  172.                  /* does q break in a blank field or a text field? */
  173.  
  174.                  if (*q == ' ')  /* q is in a blanks field, easy case! */
  175.                  {
  176.                       *q = '\0'; 
  177.                       while (*++q == ' ')    /* skip right to text (if any) */
  178.                           ;
  179.                       strcpy( word, q );           /* save (null?) remainder */
  180.                  }
  181.                  else  /* q is in a text field */
  182.                  {
  183.                       r = q;                      /* in case there's no help */
  184.                       while ((q > s) && (*q != ' '))  /* find blanks to left */
  185.                           q--;
  186.                       if ( q == s )  /* gosh, no blanks! */
  187.                       {
  188.                           strcpy( word, r );
  189.                           *r = '\0'; 
  190.                       }
  191.                       else /* if ( q > s ) */
  192.                       {
  193.                           q++;                       /* advance to word nose */
  194.                           strcpy( word, q );               /* save remainder */
  195.                           *q = '\0';             /* truncate s after a blank */
  196.                       }
  197.                  }
  198.               }
  199.  
  200.          /* BLOCK:  output the line */
  201.  
  202.               muf( s );
  203.               strcpy(s,"");
  204.               if (!wordwrap && strlen(word) > 0)
  205.               {
  206.                 /* wordwrap suppressed, behave like ordinary type command */
  207.                    muf( word );
  208.                    strcpy(word,"");
  209.               }
  210.  
  211.     } while (lines > 0 && contin && !review);
  212.  
  213.     if (!contin)  /* end of file condition */
  214.     {
  215.         wputs("^2 eof ^1 --PgUp reviews, any key quits--^");
  216.         while (kbhit()) getch();
  217.         review = (lines = keyin(noop)) == PGUP;
  218.     }
  219.  
  220.     contin |= (strlen(word) > 0 || review);
  221. }
  222.  
  223.  
  224.  
  225.  
  226. static void show()        /* recursive, puts page addresses on the stack */
  227. {
  228.     auto long filepos;    /* where each screen page starts in the file */
  229.  
  230.     while (contin)        /* and the garden path begins here...! */
  231.     {
  232.          if (review)      /* show returned!  back up exactly one screen page */
  233.          {
  234.               reframe();
  235.               fseek(f,filepos,SEEK_SET);
  236.          }
  237.          else 
  238.               filepos = ftell(f);  /* mark place for THIS screen! */
  239.  
  240.          showscreen();    /* show THIS screen; sets contin, review flags */
  241.  
  242.          if (review) 
  243.               return;     /* (gasp! twisty! devious!) show LAST screen! */
  244.          else 
  245.               show();     /* show NEXT screen! stack gets deeper */
  246.     }
  247. }
  248.  
  249.  
  250.  
  251. void typeafile( p, wrap, tx, ty, bx, by ) char *p; int wrap, tx, ty, bx, by;
  252. {
  253.      char far *b;
  254.      union REGS cursor;
  255.  
  256.      Control_C_Flag = 0;
  257.      ctrlbrk ( cctrap );
  258.      b = savescreen( &cursor );
  259.      hidecursor();
  260.  
  261.      if (((s = malloc( LINESIZE * 2 )) == NULL) || ((word = malloc( LINESIZE * 2 )) == NULL))
  262.      {
  263.           thurb();
  264.           defcursor();
  265.           wprintf("%s ERROR: not enough k",MSG_SOURCE);
  266.           exit(1);
  267.      }
  268.  
  269.      windowbox( tx, ty, bx, by );     /* set up display area */
  270.      getwindow( &tx, &ty, &bx, &by ); /* was the window squashed? */
  271.  
  272.      fullscreen();
  273.      gotoxy( tx + 1, ty - 1 );
  274.      wprintf("╡^2 %s ^╞", p );
  275.      setwindow( ++tx, ty, bx, by );   /* get a little bit of right margin */
  276.      gotoxy(0,0);
  277.  
  278.      wide = bx - tx;
  279.      deep = by - ty;
  280.  
  281.      msg = ESCMSG;
  282.      if ((wide < strlen(msg)) || (deep < 2))
  283.      {
  284.           thurb();
  285.           fullscreen();
  286.           defcursor();
  287.           wprintf("\n%s ERROR: bad window size: %dx%d?",MSG_SOURCE,wide,deep);
  288.           exit(1);
  289.      }
  290.  
  291.      if ( (f = fopen( p, "r" )) != NULL )
  292.      {
  293.         if (setjmp(mk) != 0)
  294.         {
  295.              if ferror(f) /* while attempting to read open file */
  296.              {
  297.                   fclose(f);  
  298.                   goto zoo;
  299.              }
  300.              /* otherwise, Control-C or ESC gave us a nice exit */
  301.         }
  302.         else
  303.         {
  304.              wordwrap = wrap;    /* makes the feature optional */
  305.              contin = -1;
  306.              while (contin)      /* usually, just passing through! */
  307.              {
  308.                   reframe();
  309.                   show();        /* normally, contin = 0 when show returns */
  310.  
  311.                /* But if contin is still non-zero at this point, we've 
  312.                ** got a nonsensical request to review page minus one.
  313.                ** Go to BOF and start over.  Rewind clears feof flag,
  314.                ** if set, while fseek(f,0L,SEEK_SET) does not.
  315.                */
  316.              }
  317.         }
  318.         fclose(f);  /* WOI-FM is playing midnight space music. */
  319.      }
  320.      else 
  321.      {
  322. zoo:    thurb();
  323.         wprintf("\n^1%s ERROR: couldn't read %s^\n",MSG_SOURCE,p);
  324.         setsynch(1); 
  325.         perror( "Might have been"); 
  326.         setsynch(0); 
  327.         wprintf("\n^1--any key continues--^"); 
  328.         while (kbhit()) getch(); getch(); 
  329.      }
  330.  
  331.      free( s );
  332.      free( word );
  333.      restorescreen( b, &cursor );
  334.      ctrlbrk( garm );
  335. }
  336.  
  337. /* eof: typeafil.c */
  338.  
  339.