13e12c5d1SDavid du Colombier #include <u.h> 23e12c5d1SDavid du Colombier #include <libc.h> 33e12c5d1SDavid du Colombier #include <bio.h> 43e12c5d1SDavid du Colombier #include <ctype.h> 53e12c5d1SDavid du Colombier 63e12c5d1SDavid du Colombier /* 73e12c5d1SDavid du Colombier * block up paragraphs, possibly with indentation 83e12c5d1SDavid du Colombier */ 93e12c5d1SDavid du Colombier 103e12c5d1SDavid du Colombier void fmt(Biobuf*); 113e12c5d1SDavid du Colombier void outchar(Rune); 123e12c5d1SDavid du Colombier void addrune(Rune); 133e12c5d1SDavid du Colombier void outword(void); 143e12c5d1SDavid du Colombier void puncttest(void); 153e12c5d1SDavid du Colombier void flush(void); 163e12c5d1SDavid du Colombier 173e12c5d1SDavid du Colombier int join=1; /* can input lines be joined? */ 183e12c5d1SDavid du Colombier int indent=0; /* how many spaces to indent */ 193e12c5d1SDavid du Colombier int length=70; /* how many columns per output line */ 203e12c5d1SDavid du Colombier Biobuf bin; 213e12c5d1SDavid du Colombier Biobuf bout; 223e12c5d1SDavid du Colombier 233e12c5d1SDavid du Colombier void 243e12c5d1SDavid du Colombier main(int argc, char **argv) 253e12c5d1SDavid du Colombier { 263e12c5d1SDavid du Colombier int i, f; 273e12c5d1SDavid du Colombier ARGBEGIN{ 283e12c5d1SDavid du Colombier case 'i': 293e12c5d1SDavid du Colombier indent = atoi(ARGF()); 303e12c5d1SDavid du Colombier break; 313e12c5d1SDavid du Colombier case 'j': 323e12c5d1SDavid du Colombier join = 0; 333e12c5d1SDavid du Colombier break; 343e12c5d1SDavid du Colombier case 'w': 353e12c5d1SDavid du Colombier case 'l': 363e12c5d1SDavid du Colombier length = atoi(ARGF()); 373e12c5d1SDavid du Colombier break; 383e12c5d1SDavid du Colombier default: 393e12c5d1SDavid du Colombier fprint(2, "Usage: %s [-j] [-i indent] [-l length] [file ...]\n", 403e12c5d1SDavid du Colombier argv0); 413e12c5d1SDavid du Colombier exits("usage"); 423e12c5d1SDavid du Colombier }ARGEND 433e12c5d1SDavid du Colombier if(length<=indent){ 443e12c5d1SDavid du Colombier fprint(2, "%s: line length<=indentation\n", argv0); 453e12c5d1SDavid du Colombier exits("length"); 463e12c5d1SDavid du Colombier } 473e12c5d1SDavid du Colombier Binit(&bout, 1, OWRITE); 483e12c5d1SDavid du Colombier if(argc<=0){ 493e12c5d1SDavid du Colombier Binit(&bin, 0, OREAD); 503e12c5d1SDavid du Colombier fmt(&bin); 513e12c5d1SDavid du Colombier }else{ 523e12c5d1SDavid du Colombier for(i=0; i<argc; i++){ 533e12c5d1SDavid du Colombier f=open(argv[i], OREAD); 543e12c5d1SDavid du Colombier if(f<0) 553e12c5d1SDavid du Colombier perror(argv[i]); 563e12c5d1SDavid du Colombier else{ 573e12c5d1SDavid du Colombier Binit(&bin, f, OREAD); 583e12c5d1SDavid du Colombier fmt(&bin); 59*219b2ee8SDavid du Colombier Bterm(&bin); 603e12c5d1SDavid du Colombier if(i!=argc-1) 613e12c5d1SDavid du Colombier Bputc(&bout, '\n'); 623e12c5d1SDavid du Colombier } 633e12c5d1SDavid du Colombier } 643e12c5d1SDavid du Colombier } 653e12c5d1SDavid du Colombier exits(0); 663e12c5d1SDavid du Colombier } 673e12c5d1SDavid du Colombier void 683e12c5d1SDavid du Colombier fmt(Biobuf *f) 693e12c5d1SDavid du Colombier { 703e12c5d1SDavid du Colombier long c; 713e12c5d1SDavid du Colombier 723e12c5d1SDavid du Colombier while((c = Bgetrune(f)) >= 0) 733e12c5d1SDavid du Colombier outchar((Rune) c); 743e12c5d1SDavid du Colombier flush(); 753e12c5d1SDavid du Colombier } 763e12c5d1SDavid du Colombier 773e12c5d1SDavid du Colombier #define TAB 8 783e12c5d1SDavid du Colombier #define NWORD (TAB*32) 793e12c5d1SDavid du Colombier 803e12c5d1SDavid du Colombier Rune word[NWORD+1]; 813e12c5d1SDavid du Colombier Rune *wp=word; 823e12c5d1SDavid du Colombier int col=0; /* output column number */ 833e12c5d1SDavid du Colombier int bol=1; /* at beginning of output line? */ 843e12c5d1SDavid du Colombier int punct=0; /* last character out was punctuation? */ 853e12c5d1SDavid du Colombier int newline=1; /* last char read was newline(1) or init space(2) */ 863e12c5d1SDavid du Colombier 873e12c5d1SDavid du Colombier void 883e12c5d1SDavid du Colombier outchar(Rune c){ 893e12c5d1SDavid du Colombier switch(c){ 903e12c5d1SDavid du Colombier case '\0': 913e12c5d1SDavid du Colombier break; 923e12c5d1SDavid du Colombier case '\n': 933e12c5d1SDavid du Colombier switch(newline){ 943e12c5d1SDavid du Colombier case 0: 953e12c5d1SDavid du Colombier if(join) 963e12c5d1SDavid du Colombier outword(); 973e12c5d1SDavid du Colombier else 983e12c5d1SDavid du Colombier flush(); 993e12c5d1SDavid du Colombier break; 1003e12c5d1SDavid du Colombier case 1: 1013e12c5d1SDavid du Colombier flush(); 1023e12c5d1SDavid du Colombier case 2: 1033e12c5d1SDavid du Colombier Bputc(&bout, '\n'); 1043e12c5d1SDavid du Colombier wp=word; 1053e12c5d1SDavid du Colombier } 1063e12c5d1SDavid du Colombier newline=1; 1073e12c5d1SDavid du Colombier break; 1083e12c5d1SDavid du Colombier case ' ': 1093e12c5d1SDavid du Colombier case '\t': 1103e12c5d1SDavid du Colombier switch(newline) { 1113e12c5d1SDavid du Colombier case 0: 1123e12c5d1SDavid du Colombier outword(); 1133e12c5d1SDavid du Colombier break; 1143e12c5d1SDavid du Colombier case 1: 1153e12c5d1SDavid du Colombier flush(); 1163e12c5d1SDavid du Colombier newline=2; 1173e12c5d1SDavid du Colombier case 2: 1183e12c5d1SDavid du Colombier do { 1193e12c5d1SDavid du Colombier addrune(L' '); 1203e12c5d1SDavid du Colombier } while(c=='\t' && (wp-word)%TAB); 1213e12c5d1SDavid du Colombier } 1223e12c5d1SDavid du Colombier break; 1233e12c5d1SDavid du Colombier default: 1243e12c5d1SDavid du Colombier addrune(c); 1253e12c5d1SDavid du Colombier newline=0; 1263e12c5d1SDavid du Colombier } 1273e12c5d1SDavid du Colombier } 1283e12c5d1SDavid du Colombier 1293e12c5d1SDavid du Colombier void 1303e12c5d1SDavid du Colombier addrune(Rune c) 1313e12c5d1SDavid du Colombier { 1323e12c5d1SDavid du Colombier if(wp==&word[NWORD]) { 1333e12c5d1SDavid du Colombier if(utfrune(" \t",wp[-1])) 1343e12c5d1SDavid du Colombier wp=word; 1353e12c5d1SDavid du Colombier outword(); 1363e12c5d1SDavid du Colombier } 1373e12c5d1SDavid du Colombier *wp++=c; 1383e12c5d1SDavid du Colombier } 1393e12c5d1SDavid du Colombier 1403e12c5d1SDavid du Colombier void 1413e12c5d1SDavid du Colombier outword(void) 1423e12c5d1SDavid du Colombier { 1433e12c5d1SDavid du Colombier int i; 1443e12c5d1SDavid du Colombier 1453e12c5d1SDavid du Colombier if(wp==word) 1463e12c5d1SDavid du Colombier return; 1473e12c5d1SDavid du Colombier if(wp-word+col+(bol?0:punct?2:1)>length){ 1483e12c5d1SDavid du Colombier Bputc(&bout, '\n'); 1493e12c5d1SDavid du Colombier col=0; 1503e12c5d1SDavid du Colombier bol=1; 1513e12c5d1SDavid du Colombier } 1523e12c5d1SDavid du Colombier if(col==0){ 1533e12c5d1SDavid du Colombier for(i=0;i+8<=indent;i+=8) 1543e12c5d1SDavid du Colombier Bputc(&bout, '\t'); 1553e12c5d1SDavid du Colombier while(i++<indent) 1563e12c5d1SDavid du Colombier Bputc(&bout, ' '); 1573e12c5d1SDavid du Colombier col=indent; 1583e12c5d1SDavid du Colombier } 1593e12c5d1SDavid du Colombier if(bol) 1603e12c5d1SDavid du Colombier bol=0; 1613e12c5d1SDavid du Colombier else{ 1623e12c5d1SDavid du Colombier if(punct){ 1633e12c5d1SDavid du Colombier Bputc(&bout, ' '); 1643e12c5d1SDavid du Colombier col++; 1653e12c5d1SDavid du Colombier } 1663e12c5d1SDavid du Colombier Bputc(&bout, ' '); 1673e12c5d1SDavid du Colombier col++; 1683e12c5d1SDavid du Colombier } 1693e12c5d1SDavid du Colombier puncttest(); 1703e12c5d1SDavid du Colombier for (i = 0; word+i < wp; i++) 1713e12c5d1SDavid du Colombier Bputrune(&bout, word[i]); 1723e12c5d1SDavid du Colombier col+=i; 1733e12c5d1SDavid du Colombier wp=word; 1743e12c5d1SDavid du Colombier } 1753e12c5d1SDavid du Colombier /* is the word followed by major punctuation, .?:! */ 1763e12c5d1SDavid du Colombier /* disregard short things followed by periods; they are probably 1773e12c5d1SDavid du Colombier initials or titles like Mrs. and Dr. */ 1783e12c5d1SDavid du Colombier void 1793e12c5d1SDavid du Colombier puncttest(void) 1803e12c5d1SDavid du Colombier { 1813e12c5d1SDavid du Colombier Rune *rp; 1823e12c5d1SDavid du Colombier 1833e12c5d1SDavid du Colombier punct = 0; 1843e12c5d1SDavid du Colombier for(rp=wp; --rp>=word; ) { 1853e12c5d1SDavid du Colombier switch(*rp) { 1863e12c5d1SDavid du Colombier case ')': case '\'': case '"': 1873e12c5d1SDavid du Colombier continue; 1883e12c5d1SDavid du Colombier case '.': 1893e12c5d1SDavid du Colombier if(isupper(*word)&&rp-word<=3) 1903e12c5d1SDavid du Colombier return; 191*219b2ee8SDavid du Colombier case '?': case '!': /*case ':':*/ 1923e12c5d1SDavid du Colombier punct = 1; 1933e12c5d1SDavid du Colombier default: 1943e12c5d1SDavid du Colombier return; 1953e12c5d1SDavid du Colombier } 1963e12c5d1SDavid du Colombier } 1973e12c5d1SDavid du Colombier } 1983e12c5d1SDavid du Colombier void 1993e12c5d1SDavid du Colombier flush(void){ 2003e12c5d1SDavid du Colombier outword(); 2013e12c5d1SDavid du Colombier if(col!=0){ 2023e12c5d1SDavid du Colombier Bputc(&bout, '\n'); 2033e12c5d1SDavid du Colombier col=0; 2043e12c5d1SDavid du Colombier bol=1; 2053e12c5d1SDavid du Colombier } 2063e12c5d1SDavid du Colombier } 207