home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / listings / v_11_11 / splash / justify.cpp < prev    next >
Text File  |  1993-01-15  |  4KB  |  152 lines

  1. /*
  2.  * Simple program to read STDIN and justify the text to the
  3.  * specified number of columns and output to STDOUT.
  4.  * The padding is alternated from line to line so as to look even.
  5.  * Blank lines in the input stream are preserved.
  6.  * This was designed to be used as a filter.
  7.  * As with fmt(1) indents are preserved, this can be disabled
  8.  * with an option.
  9.  * Also a change in indent level will be treated as the end of a 
  10.  * stream, so no words on the following line will be wrapped up to
  11.  * the current line.
  12.  */
  13.  
  14. #include    <iostream.h>
  15. #include    <stdlib.h>
  16. #include    <ctype.h>
  17.  
  18. #include    "splash.h"
  19. #include    "tracer.h"
  20.  
  21. // Some useful synonyms
  22. typedef SPString Str;
  23. typedef SPStringList StrList;
  24.  
  25. int tog= 0;
  26.  
  27. static int nextnonspace(const Str& s, int n)
  28. {
  29.     while(n < s.length() && s[n] == ' ') n++;    
  30.     return n;
  31. }
  32.  
  33. static int prevnonspace(const Str& s, int n)
  34. {
  35.     while(n >= 0 && s[n] == ' ') n--;    
  36.     return n;
  37. }
  38.  
  39. void justify(Str& ln, int width)
  40. {
  41. TRACER("justify(Str ln, int width)")
  42.     LTRACE(2, ln)
  43.     int p, o= tog?0:ln.length();
  44.     while(ln.length() < width){
  45.     if(tog){ // left to right pad
  46.         p= ln.index(" ", o); // find a space
  47.         if(p > 0){
  48.         ln.substr(p, 0)= " "; // insert a space
  49.         o= nextnonspace(ln, p); // start from next non-space
  50.         }else if(o) o= 0; // reset
  51.         else ln += " "; // put at end of line
  52.     }else{ // right to left pad
  53.         p= ln.rindex(" ", o); // find a space
  54.         if(p > 0){
  55.         ln.substr(p, 0)= " "; // insert a space
  56.         o= prevnonspace(ln, p); // start from previous non-space
  57.         }else if(o != ln.length()) o= ln.length(); // reset
  58.         else ln += " "; // put at end of line
  59.     }    
  60.     }
  61.     tog ^= 1;
  62. }
  63.  
  64. void Usage()
  65. {
  66.     cout << "Usage: justify [-i] [width]" << endl;
  67.     cout << "\t-i ignores leading whitespace" << endl;
  68.     cout << "\twidth is the line width, default is 79" << endl;
  69.     exit(1);
  70. }
  71.  
  72. int main(int argc,  char **argv)
  73. {
  74. FTRACER("main()", 0, cout)
  75. Str inl, curln, curword;
  76. StrList words;
  77. int width= 79, wwidth, ignorews= 0, lastindent= 0;
  78. Str lws;    // leading whitespace
  79. StrList ARGS;
  80.  
  81.     for(int i=1;i<argc;i++){ // load args
  82.     ARGS.push(argv[i]);
  83.     }
  84.     
  85.     while(ARGS){ // process them
  86.     Str arg= ARGS.shift();
  87.     if(arg == "-i") ignorews= 1;
  88.     else if(arg == "-x") TRACE_ON
  89.     else if(isdigit(arg[0])) width= atoi(arg);
  90.     else Usage();
  91.     }
  92.     
  93.     while(cin >> inl){
  94.     LTRACE(2, inl)
  95.  
  96.     if(inl.length() == 0){ // honour existing blank lines
  97.         if(curln.length()){
  98.         if(lws.length()) cout << lws; // leading space
  99.         cout << curln << endl; // flush previous line
  100.         }
  101.         cout << endl; // output blank line
  102.         curln= "";
  103.         continue;
  104.     }
  105.  
  106.     if(!ignorews){ // don't ignore leading whitespace
  107.         StrList t= m("^([ \t]+)", inl); // get leading whitespace
  108.         LTRACE(4, "Length = " << t[0].length());
  109.             if(t){
  110.         int l= 0;
  111.         for(int i=0;i<t[0].length();i++){ // expand tabs
  112.             if(t[0][i] == '\t') l= l + (8 - l%8);
  113.             else l++;
  114.         }
  115.         wwidth= width - l;
  116.         }else wwidth= width;
  117.         if(wwidth != lastindent && curln.length()){ // indent changed, flush line
  118.         if(lws.length()) cout << lws; // leading space
  119.         cout << curln << endl; // flush previous line
  120.         curln= "";
  121.         }
  122.         lastindent= wwidth;
  123.         lws= t[0];
  124.     }else wwidth= width;
  125.     
  126.         words.push(inl.split("' '")); // put at end of word FIFO
  127.     LTRACE(2, words)
  128.     while(words){
  129.         if(curln.length() == 0){
  130.         curln= words.shift(); // get first word
  131.         }
  132.         while(curln.length() < wwidth){
  133.         if(!words) break; // need to refill FIFO
  134.         curword= words.shift(); // next word
  135.         if(curln.length() + curword.length() + 1 > wwidth){
  136.             words.unshift(curword); // put it back
  137.             justify(curln, wwidth); // pads with spaces to width
  138.         }else curln += (" " + curword); // add word to line
  139.         }
  140.         if(curln.length() >= wwidth){ // done with this line
  141.         if(lws.length()) cout << lws; // leading space
  142.         cout << curln << endl;
  143.         curln= "";
  144.         }
  145.     }
  146.     }
  147.     if(curln.length()){
  148.     if(lws.length()) cout << lws; // leading space
  149.     cout << curln << endl;
  150.     }
  151. }
  152.