home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / vol_200 / 283_01 / typeafil.c < prev    next >
C/C++ Source or Header  |  1988-05-13  |  10KB  |  328 lines

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