home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume15 / mfold-1.04-ps / part01 next >
Text File  |  1990-10-14  |  25KB  |  902 lines

  1. Newsgroups: comp.sources.misc
  2. X-UNIX-From: smidt@fy.chalmers.se
  3. Subject: v15i082: mfold - Maaniker's fold and column making (version 1.04)
  4. from: Peter Smidt <smidt@fy.chalmers.se>
  5. Sender: allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc)
  6.  
  7. Posting-number: Volume 15, Issue 82
  8. Submitted-by: Peter Smidt <smidt@fy.chalmers.se>
  9. Archive-name: mfold-1.04-ps/part01
  10.  
  11. [It's unclear whether this is official or not.  ++bsa]
  12.  
  13. There have been no big changes. The doc and man pages have
  14. got improved english thanks to some helpsome people. Mfold
  15. now reads input from the command line (one doesn't need to
  16. write 'mfold < my_file'). A bug (or two?) are removed.
  17.  
  18. mfold (version 1.04)
  19.  
  20. ---- Cut Here and feed the following to sh ----
  21. #!/bin/sh
  22. # This is mfold, a shell archive (produced by shar 3.49)
  23. # To extract the files from this archive, save it to a file, remove
  24. # everything above the "!/bin/sh" line above, and type "sh file_name".
  25. #
  26. # made 10/11/1990 06:25 UTC by smidt@tapioca
  27. # Source directory /nfs/alcazar/u/smidt/src/mfold/exp
  28. #
  29. # existing files will NOT be overwritten unless -c is specified
  30. #
  31. # This shar contains:
  32. # length  mode       name
  33. # ------ ---------- ------------------------------------------
  34. #    597 -rw-r--r-- README
  35. #     87 -rw-r--r-- makefile
  36. #   3817 -rw-r--r-- mfold.1
  37. #  14166 -rw-r--r-- mfold.c
  38. #   2727 -rw-r--r-- mfold_doc
  39. #
  40. # ============= README ==============
  41. if test -f 'README' -a X"$1" != X"-c"; then
  42.     echo 'x - skipping README (File already exists)'
  43. else
  44. echo 'x - extracting README (Text)'
  45. sed 's/^X//' << 'SHAR_EOF' > 'README' &&
  46. Version 1.04, last change 30 september 1990.
  47. X
  48. The program mfold is a simple folding and column making program.
  49. unpack the files from the shar file put them in a empty
  50. directory, type 'make' and you'll get the executable. A manual
  51. is included in the shar file.
  52. X
  53. A bug have been removed and some optimization have been done since the first
  54. posting to alt.sources.
  55. X
  56. Thanks to all the people who have sent typo fixes.
  57. X
  58. A more exact documentation is in mfold_doc.
  59. X
  60. X
  61. Bug reports, ideas, or patches could be sent to;
  62. Peter Smidt   smidt@cd.chalmers.se    or
  63. Peter Smidt   smidt@fy.chalmers.se
  64. X
  65. /Maaniker
  66. SHAR_EOF
  67. chmod 0644 README ||
  68. echo 'restore of README failed'
  69. Wc_c="`wc -c < 'README'`"
  70. test 597 -eq "$Wc_c" ||
  71.     echo 'README: original size 597, current size' "$Wc_c"
  72. fi
  73. # ============= makefile ==============
  74. if test -f 'makefile' -a X"$1" != X"-c"; then
  75.     echo 'x - skipping makefile (File already exists)'
  76. else
  77. echo 'x - extracting makefile (Text)'
  78. sed 's/^X//' << 'SHAR_EOF' > 'makefile' &&
  79. mfold: mfold.o
  80. X    cc mfold.o -o mfold
  81. X    rm -f mfold.o
  82. X
  83. mfold.o: mfold.c
  84. X    cc -c mfold.c -O
  85. SHAR_EOF
  86. chmod 0644 makefile ||
  87. echo 'restore of makefile failed'
  88. Wc_c="`wc -c < 'makefile'`"
  89. test 87 -eq "$Wc_c" ||
  90.     echo 'makefile: original size 87, current size' "$Wc_c"
  91. fi
  92. # ============= mfold.1 ==============
  93. if test -f 'mfold.1' -a X"$1" != X"-c"; then
  94.     echo 'x - skipping mfold.1 (File already exists)'
  95. else
  96. echo 'x - extracting mfold.1 (Text)'
  97. sed 's/^X//' << 'SHAR_EOF' > 'mfold.1' &&
  98. .\" Public Domain 1990 of Chalmers Computer Society.
  99. .\"
  100. .\"    @(#)mfold.1    (G|teborg) 1990-09-11
  101. .\"
  102. .TH MFOLD 1 "September 11, 1990"
  103. .UC
  104. .SH NAME
  105. mfold \- Maaniker's fold and column making
  106. .SH SYNOPSIS
  107. .B mfold
  108. [
  109. .B \-sn -ln -en -wn -f -d
  110. .B -rn
  111. .B -tn -cn -pn -n -L -Bn
  112. .B -D '<text>' -i '<text>'
  113. .B file
  114. ]
  115. .SH DESCRIPTION
  116. .I Mfold
  117. reads text files from standard input and writes to standard
  118. output. A filename 'file' could be used instead of standard input.
  119. .I Mfold
  120. concatenates and folds the text in one or more columns
  121. without breaking in the middle of a word. Tabs and newlines are
  122. converted to blank space. Multiple blank space is substituted with
  123. one single blank space. Some flags don't do anything if they aren't
  124. used together with either '-c' or '-d'.
  125. .PP
  126. There is a limited amount of options:
  127. .TP
  128. .B \-sn
  129. Start line for
  130. .I mfold,
  131. where n is the line number. The preceding text
  132. is passed through
  133. .I mfold
  134. without being changed. If an end-of-file character is encountered
  135. before line n,
  136. .I mfold
  137. will end the execution.
  138. .TP
  139. .B \-i
  140. Insert text at the beginning of every line, or with '\-c', at every
  141. column. This option as the last flag doesn't need any argument if
  142. a null argument is wanted. A space is required between the flag
  143. and the argument. Tabs may be present in the insert text. Default
  144. insert text is a null string.
  145. .TP
  146. .B \-ln
  147. Length for output lines, excluding any insert text and excluding
  148. any delimiter text. Where n is the number of characters. Default
  149. length is 80.
  150. .TP
  151. .B \-en
  152. .I Mfold
  153. will end the folding at input line n. Text coming after this
  154. line is not being changed by
  155. .I mfold.
  156. .TP
  157. .B \-wn
  158. Specify the width n, of the not folded lines to avoid overrunning the
  159. internal reverse buffer when using the '-d' flag. '-w' is not always
  160. provided. Run
  161. .I mfold,
  162. look at the result and decide if you want to specify the full
  163. width. Default is 80 characters.
  164. .TP
  165. .B \-f
  166. Fill each line with blank space to its full line length.
  167. .TP
  168. .B \-rn
  169. Fill the space between the words in the lines with
  170. .br
  171. (n \- 1) extra blank spaces, until the lines get an even right
  172. margin. The words will get a little random placement on the
  173. lines. If the lines become very ugly, specify a smaller n.
  174. .TP
  175. .B \-d
  176. Reverse the text for dyslexics.
  177. .TP
  178. .B \-tn
  179. Expand the tabs to spaces, where n is the number of
  180. spaces. Default is four spaces. Use only with '-d'.
  181. .TP
  182. .B \-cn
  183. Specify columns where n is the number of columns. Text is inserted at
  184. every column.
  185. .TP
  186. .B \-pn
  187. Specify page length n. Meaningful when used with the '-c'
  188. flag. Default is 40 lines per page.
  189. .TP
  190. .B \-n
  191. Many newlines in a row is not substituted with one single 
  192. blank space, which is otherwise the default. Instead they are
  193. left without change, but may be put in a separate column.
  194. .TP
  195. .B \-L
  196. Write a ^L (newpage) at the end of each page. Use with '-c'.
  197. .TP
  198. .B \-Bn
  199. Write n newlines at the bottom of each page. Default is
  200. one newline. Use when the number of columns is greater then one.
  201. .TP
  202. .B \-D
  203. Specify column delimiter. Default is three blank spaces. Tabs may be
  204. present in the delimiter. This option as the last flag doesn't need
  205. any argument if a null argument is wanted.
  206. .SH ERRORS
  207. You will notice them, when you give bad flags.
  208. .SH AUTHOR
  209. Peter Smidt, Chalmers Computer Society.
  210. .SH SEE ALSO
  211. awk(1), sed(1), lex(1), nroff(1), fmt(1), fold(1), rev(1)
  212. .SH BUGS
  213. If underlining is present it will get messed up with the
  214. text. The '-c' flag
  215. .I may
  216. produce some extra unnecessary blank space at the end of the
  217. lines. When a word is longer than the line length, the word may be
  218. cut at an inappropriate place. Everything except blank space,
  219. newline and tab counts as parts of words.
  220. .I Mfold
  221. doesn't want the input file to begin with the '-' character.
  222. .SH BUG REPORTS TO
  223. Peter Smidt  smidt@cd.chalmers.se    or
  224. .br
  225. Peter Smidt  smidt@fy.chalmers.se
  226. SHAR_EOF
  227. chmod 0644 mfold.1 ||
  228. echo 'restore of mfold.1 failed'
  229. Wc_c="`wc -c < 'mfold.1'`"
  230. test 3817 -eq "$Wc_c" ||
  231.     echo 'mfold.1: original size 3817, current size' "$Wc_c"
  232. fi
  233. # ============= mfold.c ==============
  234. if test -f 'mfold.c' -a X"$1" != X"-c"; then
  235.     echo 'x - skipping mfold.c (File already exists)'
  236. else
  237. echo 'x - extracting mfold.c (Text)'
  238. sed 's/^X//' << 'SHAR_EOF' > 'mfold.c' &&
  239. #include <stdio.h>
  240. #include <curses.h>
  241. X
  242. #define DEF_LINE_LEN    80
  243. #define DEF_WORD_LEN    40
  244. #define DEF_TAB_LEN        4
  245. #define FULL_WIDTH        80
  246. #define PAGE_LEN        40
  247. #define POS1            1
  248. #define DO_ALL1 \
  249. X    col_pos = POS1;\
  250. X    for ( doo = 0; doo < ins_len; doo++ ) {\
  251. X        putcolu(insert[doo]);\
  252. X    }
  253. #define BOT_LINES        1
  254. #define STR                15
  255. #define TEST_STR        25
  256. #define GET_NUM_STR        25
  257. X
  258. int colu_chars, colu_lines;
  259. int page_len = PAGE_LEN, columns = 1, lin = 0, bot_lines = BOT_LINES;
  260. int got_newpage = FALSE, got_dyslexi = FALSE, full_line = FULL_WIDTH;
  261. int tab_len = DEF_TAB_LEN, ins_tabs = 0, del_len, got_fill = FALSE;
  262. int got_mrandom = FALSE, got_bot = FALSE, ins_len, mrandom = 1;
  263. char **cur_page, *malloc(), *delim = "   ", **glob_argv;
  264. X
  265. main(argc, argv)
  266. char *argv[];
  267. int argc;
  268. {
  269. X    int col_pos = 1, j = 0, k, in, doo, line_len = DEF_LINE_LEN, row_count = 1;
  270. X    int cnt_nwl = 0, new_wo_le, dummy = TRUE, end = 2;
  271. X    int width = FULL_WIDTH, in_2 = 0, in_3 = 0, tmp_chars = 0;
  272. X    char *cur_word, *insert = "", *s = "Bad option '  '";
  273. X    int index, start = 1, word_len = DEF_WORD_LEN;
  274. X    int got_start = FALSE, got_line_len = FALSE, got_insert = FALSE;
  275. X    int got_tab_len = FALSE, got_end = FALSE, got_width = FALSE;
  276. X    int got_columns = FALSE, got_page_len = FALSE;
  277. X    int got_newlines = FALSE, got_delim = FALSE, got_file = FALSE;
  278. X    int index_start = 0, index_insert = 0, index_line_len = 0;
  279. X    int index_tab_len = 0, index_end = 0, index_width = 0;
  280. X    int index_columns = 0, index_page_len = 0, index_delim = 0;
  281. X    int index_bot = 0, index_mrandom = 0, index_file = 0;
  282. X    FILE *fil = stdin;
  283. X    glob_argv = argv;
  284. X    for ( index = 1; index < argc; index++) {
  285. X        if ( argv[index][0] != '-' ) {
  286. X            if ( index == 1 || (argv[index - 1][0] == '-' &&
  287. X            argv[index - 1][0] != 'i' && argv[index - 1][0] != 'D' || index > 2
  288. X            && argv[index - 2][0] == '-' && (argv[index - 2][1] == 'i'
  289. X            || argv[index - 2][1] == 'D')) && !got_file ) {
  290. X                got_file = TRUE;
  291. X                index_file = index;
  292. X            } else {
  293. X                fprintf(stderr, "Option '%s' not allowed.\n", argv[index]);
  294. X                usage(11);
  295. X            }
  296. X        }
  297. X        doo = index_insert != index && index_delim != index
  298. X        && index_file != index;
  299. X        switch ( argv[index][1] ) {
  300. X            case 'i':
  301. X                check_it(&got_insert, "-i", 8, doo, &index_insert, index + 1);
  302. X                break;
  303. X            case 's':
  304. X                check_it(&got_start, "-s", 9, doo, &index_start, index);
  305. X                break;
  306. X            case 'l':
  307. X                check_it(&got_line_len, "-l", 10, doo, &index_line_len, index);
  308. X                break;
  309. X            case 'e':
  310. X                check_it(&got_end, "-e", 10, doo, &index_end, index);
  311. X                break;
  312. X            case 'w':
  313. X                check_it(&got_width, "-w", 10, doo, &index_width, index);
  314. X                break;
  315. X            case 'r':
  316. X                check_it(&got_mrandom, "-r", 37, doo, &index_mrandom, index);
  317. X                break;
  318. X            case 'd':
  319. X                check_it(&got_dyslexi, "-d", 11, doo, &dummy, index);
  320. X                break;
  321. X            case 't':
  322. X                check_it(&got_tab_len, "-t", 13, doo, &index_tab_len, index);
  323. X                break;
  324. X            case 'c':
  325. X                check_it(&got_columns, "-c", 15, doo, &index_columns, index);
  326. X                break;
  327. X            case 'p':
  328. X                check_it(&got_page_len, "-p", 16, doo, &index_page_len, index);
  329. X                break;
  330. X            case 'B':
  331. X                check_it(&got_bot, "-B", 17, doo, &index_bot, index);
  332. X                break;
  333. X            case 'f':
  334. X                check_it(&got_fill, "-f", 33, doo, &dummy, index);
  335. X                break;
  336. X            case 'n':
  337. X                check_it(&got_newlines, "-n", 18, doo, &dummy, index);
  338. X                break;
  339. X            case 'L':
  340. X                check_it(&got_newpage, "-L", 19, doo, &dummy, index);
  341. X                break;
  342. X            case 'D':
  343. X                check_it(&got_delim, "-D", 36, doo, &index_delim, index + 1);
  344. X                break;
  345. X            case '\0':
  346. X                write_err(doo, "Empty flag '-'", 31);
  347. X                break;
  348. X            default:
  349. X                s[12] = argv[index][0];
  350. X                s[13] = argv[index][1];
  351. X                write_err(doo, s, 20);
  352. X                break;
  353. X        }
  354. X    }
  355. X    ext_num(got_start, &start, argv[index_start],
  356. X    "Line zero, for start, not allowed", 21);
  357. X    ext_num(got_page_len, &page_len, argv[index_page_len],
  358. X    "Page length zero, not allowed", 24);
  359. X    ext_num(got_tab_len, &tab_len, argv[index_tab_len],
  360. X    "Tab length zero, not allowed", 27);
  361. X    ext_num(got_line_len, &line_len, argv[index_line_len],
  362. X    "Line length zero, not allowed", 25);
  363. X    write_err(line_len < 2, "Too short line length, not allowed", 32);
  364. X    ext_num(got_end, &end, argv[index_end],
  365. X    "End length zero, not allowed", 25);
  366. X    write_err(got_end && end <= start,
  367. X    "End not greater than start line, not allowed", 33);
  368. X    ext_num(got_width, &width, argv[index_width],
  369. X    "Line length zero, not allowed", 25);
  370. X    ext_num(got_mrandom, &mrandom, argv[index_mrandom],
  371. X    "Zero fill length, not allowed", 36);
  372. X    if ( got_bot ) get_num(&bot_lines, argv[index_bot]);
  373. X    if ( got_file ) {
  374. X        write_err( (fil = fopen(argv[index_file], "r")) == NULL,
  375. X        "Unable to open your text file", 50);
  376. X    }
  377. X    if ( got_insert ) {
  378. X        if ( index_insert < argc ) {
  379. X            insert = argv[index_insert];
  380. X        } else {
  381. X            insert = "";
  382. X        }
  383. X    }
  384. X    if ( got_delim ) {
  385. X        if ( index_delim < argc ) {
  386. X            delim = argv[index_delim];
  387. X        } else {
  388. X            delim = "";
  389. X        }
  390. X    }
  391. X    del_len = str_len(delim);
  392. X    if ( got_columns ) {
  393. X        get_num(&columns, argv[index_columns]);
  394. X        write_err(columns == 0, "columns count zero, not allowed", 26);
  395. X        write_err(line_len % columns,
  396. X        "Lines not an even multiple of columns length", 27);
  397. X    }
  398. /* colu_chars is the chars on one column. colu_lines is the total number of
  399. lines in all the columns in one page. page_len is the number of lines in one
  400. page. */
  401. X    ins_len = str_len(insert);
  402. X    colu_chars = line_len / columns + ins_len;
  403. X    colu_lines = page_len * columns;
  404. X    write_err( !(cur_page = (char**) malloc(colu_lines * sizeof(char*))),
  405. X    "Can not malloc that page length", 39);
  406. X    for ( in = 0; in < colu_lines; in++ ) {
  407. X        if ( !(cur_page[in] = malloc(colu_chars * sizeof(char))) ) {
  408. X            write_err(TRUE, "Can not malloc that page length", 40);
  409. X        }
  410. X    }
  411. X    for ( doo = 0; doo < ins_len; doo++ ) {
  412. X        if ( insert[doo] == '\t' ) {
  413. X            ins_tabs++;
  414. X        }
  415. X    }
  416. X    full_line = line_len + ins_len * columns + del_len * ( columns - 1);
  417. X    full_line += ( tab_len - 1 ) * columns * ins_tabs;
  418. X    line_len = line_len / columns;
  419. X    word_len = line_len;
  420. X    write_err( !(cur_word = malloc(word_len * sizeof(char))),
  421. X    "Can not malloc that word (line?) length", 41);
  422. X    if ( width > full_line ) initrev(width);
  423. X    else initrev(full_line);
  424. /* ************* Write text according to the '-s' flag **** */
  425. X    while ( row_count < start ) {
  426. X        in = getc(fil);
  427. X        if ( in == EOF ) exit(0);
  428. X        if ( in == '\n' ) {
  429. X            if ( got_dyslexi ) {
  430. X                flushrev();
  431. X            }
  432. X            putchar('\n');
  433. X            row_count++;
  434. X        } else if ( got_dyslexi ) {
  435. X            putrev(in);
  436. X        } else {
  437. X            putchar(in);
  438. X        }
  439. X    }
  440. X    if ( !got_end ) end = row_count + 1;
  441. X    lin = ( ( start - 1 ) % page_len ) * columns;
  442. X    new_wo_le = word_len - 1;
  443. /* ******************** The fold follows ******************** */
  444. X    DO_ALL1
  445. X    while ( 1 ) {
  446. X        if ( row_count > end ) {
  447. X            in = EOF;
  448. X        } else if ( j == new_wo_le && tmp_chars == 0 ) {
  449. X            in_2 = getc(fil);
  450. X            if ( in_2 == ' ' || in_2 == '\n' || in_2 == '\t' ) {
  451. X                in = in_2;
  452. X            } else {
  453. X                in_3 = getc(fil);
  454. X                if ( in_3 == ' ' || in_3 == '\n' || in_3 == '\t' ) {
  455. X                    in = in_2;
  456. X                    tmp_chars = 1;
  457. X                } else {
  458. X                    in = '-';
  459. X                    tmp_chars = 2;
  460. X                }
  461. X            }
  462. X        } else if ( j == word_len ) { 
  463. X            in = ' ';
  464. X        } else if ( tmp_chars > 0 ) {
  465. X            if ( tmp_chars == 1 && j == 0 ) {
  466. X                in = in_3;
  467. X                tmp_chars = 0;
  468. X            } else if ( tmp_chars == 1 && j == 1 ) {
  469. X                in_2 = in_3;
  470. X                tmp_chars = 0;
  471. X                if ( line_len != 2 || in_2 == ' ' || in_2 == '\n'
  472. X                || in_2 == '\t' ) {
  473. X                    in = in_2;
  474. X                } else {
  475. X                    in_3 = getc(fil);
  476. X                    if ( in_3 == ' ' || in_3 == '\n' || in_3 == '\t' ) {
  477. X                        in = in_2;
  478. X                        tmp_chars = 1;
  479. X                    } else {
  480. X                        in = '-';
  481. X                        tmp_chars = 2;
  482. X                    }
  483. X                }
  484. X            } else {
  485. X                in = in_2;
  486. X                tmp_chars = 1;
  487. X            }
  488. X        } else { 
  489. X            in = getc(fil);
  490. X        }
  491. X        if ( in != '\n' ) {
  492. X            if ( cnt_nwl > 1 && got_newlines ) {
  493. X                while ( --cnt_nwl ) {
  494. X                    putcolu('\n');
  495. X                    putcolu(' ');
  496. X                }
  497. X                putcolu('\n');
  498. X                DO_ALL1
  499. X            }
  500. X            cnt_nwl = 0;
  501. X            if ( in == '\t' ) in = ' ';
  502. X        } else {
  503. X            if ( got_end ) row_count++;
  504. X            if ( got_newlines ) cnt_nwl++;
  505. X            in = ' ';
  506. X        }
  507. X        if ( in == EOF ) {
  508. X            putcolu('\n');
  509. X            flushpage(columns);
  510. X            if ( !got_end ) exit(0);
  511. X            else break;
  512. X        }
  513. X        if ( in != ' ' ) {
  514. X            write_err( j >= word_len || j < 0 ,
  515. X            "Internal error or to long text word", 3);
  516. X            cur_word[j++] = in;
  517. X        } else {
  518. X            if ( col_pos != POS1 && (col_pos + j) <= line_len &&
  519. X            j != 0 ) {
  520. X                putcolu(' ');
  521. X                col_pos++;
  522. X            } else if ( (col_pos + j) > line_len && col_pos != POS1 ) {
  523. X                putcolu('\n');
  524. X                DO_ALL1
  525. X            }
  526. X            for ( k = 0; k < j; k++ ) {
  527. X                putcolu(cur_word[k]);
  528. X            }
  529. X            col_pos += j;
  530. X            j = 0;
  531. X        }
  532. X    }
  533. /* ***************** End of the fold ********************** */
  534. /* ************* Write text according to the '-e' flag **** */
  535. X    if ( cnt_nwl > 1 && got_newlines ) {
  536. X        while ( --cnt_nwl ) {
  537. X            putcolu('\n');
  538. X            putcolu(' ');
  539. X        }
  540. X        putcolu('\n');
  541. X        flushpage(columns);
  542. X    }
  543. X    while ( 1 ) {
  544. X        in = getc(fil);
  545. X        if ( in == EOF ) exit(0);
  546. X        if ( in == '\n' ) {
  547. X            if ( got_dyslexi ) {
  548. X                flushrev();
  549. X            }
  550. X            putchar('\n');
  551. X        } else if ( got_dyslexi ) {
  552. X            putrev(in);
  553. X        } else {
  554. X            putchar(in);
  555. X        }
  556. X    }
  557. }
  558. X
  559. char *buff;
  560. int gl_i = 0, len;
  561. /* lin is the line index in the one long column before it is pasted out onto the
  562. page. len is the lenght of each line in the one long column. */
  563. X
  564. putrev(c)
  565. {
  566. X    int i;
  567. X
  568. X    if ( gl_i >= 0 && gl_i < len ) {
  569. X        if ( c != '\t' ) {
  570. X            buff[gl_i++] = c;
  571. X        } else {
  572. X            int k = tab_len - gl_i % tab_len;
  573. X            for ( i = 0; i < k; i++ ) {
  574. X                putrev(' ');
  575. X            }
  576. X        }
  577. X    } else {
  578. X        write_err(TRUE,
  579. X        "Internal error in reverse buffer. Specify bigger buffer", 4);
  580. X    }
  581. }
  582. X
  583. flushrev() {
  584. X    int i, first = 0;
  585. X
  586. X    if ( buff[first] == ' ' ) while ( buff[++first] == ' ' );
  587. X    for ( i = len - 1; i >= first; i--) {
  588. X        if ( buff[i] != '\0' ) {
  589. X            putchar(buff[i]);
  590. X            buff[i] = '\0';
  591. X        } else {
  592. X            putchar(' ');
  593. X        }
  594. X    }
  595. X    gl_i = 0;
  596. }
  597. X
  598. initrev(l)
  599. int l;
  600. {
  601. X    int i;
  602. X
  603. X    len = l;
  604. X    write_err( !(buff = malloc((len + 1) * sizeof(char))),
  605. X    "Can not malloc that internal reverse buffer length", 42);
  606. X    for ( i = 0; i < len; i++ ) {
  607. X        buff[i] = '\0';
  608. X    }
  609. X    buff[len] = '#'; /* To help flushrev swallow blank lines */
  610. }
  611. X
  612. check_it(got_flag, s, err, boole, index_flag, index)
  613. int *got_flag, *index_flag;
  614. char *s;
  615. {
  616. X    test(*got_flag, s, err);
  617. X    test_two(boole, index_flag, index, got_flag);
  618. }
  619. X
  620. test(flag, s1, err)
  621. char *s1;
  622. {
  623. X    char *s2 = "Multiple '  ' not allowed";
  624. X
  625. X    s2[10] = s1[0];
  626. X    s2[11] = s1[1];
  627. X    write_err(flag, s2, err);
  628. }
  629. X
  630. test_two(boole, index_flag, index, got_flag)
  631. int *index_flag, *got_flag;
  632. {
  633. X    if ( boole ) {
  634. X        if ( *index_flag && glob_argv[index][2] != '\0' ) {
  635. X            fprintf(stderr, "Flag '%c%c' doesn't want any argument.\n",
  636. X            glob_argv[index][0], glob_argv[index][1]);
  637. X            usage(35);
  638. X        }
  639. X        *index_flag = index;
  640. X        *got_flag = TRUE;
  641. X    }
  642. }
  643. X
  644. write_err(flag, s, err)
  645. char *s;
  646. {
  647. X    if ( flag ) {
  648. X        fprintf(stderr, "%s.\n", s);
  649. X        usage(err);
  650. X    }
  651. }
  652. X
  653. ext_num(bulle, tal, arg, s, err)
  654. int *tal;
  655. char *arg, *s;
  656. {
  657. X    if ( bulle ) {
  658. X        get_num(tal, arg);
  659. X        write_err(*tal == 0, s, err);
  660. X    }
  661. }
  662. X
  663. get_num(number, argv) 
  664. int *number;
  665. char argv[];
  666. {
  667. X    int k, in, tmp;
  668. X    char *s = "Not a number in flag '  '";
  669. X
  670. X    s[22] = argv[0];
  671. X    s[23] = argv[1];
  672. X    *number = 0;
  673. X    k = str_len(argv);
  674. X    write_err(k == 1, s, 9);
  675. X    for( in = 2; in < k; in++) {
  676. X        tmp = argv[in] - '0';
  677. X        write_err(tmp < 0 || tmp > 9, "Bad flag, N-A-P-N", 5);
  678. X        *number = tmp + *number * 10;
  679. X    }
  680. }
  681. X
  682. str_len(s)
  683. char *s;
  684. {
  685. X    int m = 0;
  686. X
  687. X    if ( s[m] != '\0' ) while ( s[++m] != '\0' );
  688. X    return m;
  689. }
  690. X
  691. usage(t) {
  692. X    fprintf(stderr, "[ %d ]  Usage: mfold [ -sn -ln -en -wn -f -d -rn -tn -cn -pn -n -L -Bn\n-D '<text>' -i '<text>' file]\n", t);
  693. X    exit(t);
  694. }
  695. X
  696. int col = 0;
  697. X
  698. putcolu(c)
  699. char c;
  700. {
  701. X    if ( c == '\n' || col == colu_chars ) {
  702. X        advance_line();
  703. X        return;
  704. X    }
  705. X    cur_page[lin][col++] = c;
  706. }
  707. X
  708. advance_line() {
  709. X        col = 0;
  710. X        if ( ++lin == colu_lines ) {
  711. X            flushpage(columns);
  712. X            end_page();
  713. X        }
  714. }
  715. X
  716. end_page() {
  717. X    int i;
  718. X
  719. X    if ( columns > 1 || got_bot ) {
  720. X        for ( i = 0; i < bot_lines; i++ ) {
  721. X            putchar('\n');
  722. X        }
  723. X    }
  724. X    if ( got_newpage ) putchar(12);        /* 12 == ^L  (ascii) */
  725. }
  726. X
  727. flushpage(columns) {
  728. X    int line_sta = 0, cs, tmpl, lin_diff, lin_end;
  729. X    int end_col = columns - 1, lin_sto = colu_lines, end_char = colu_chars - 1;
  730. X
  731. X    for ( lin = 0; lin < colu_lines; lin++ ) {
  732. X        if ( cur_page[lin][0] != '\0' ) {
  733. X            line_sta = lin;
  734. X            break;
  735. X        }
  736. X    }
  737. X    for ( lin = line_sta; lin < colu_lines; lin += columns ) {
  738. X        if ( cur_page[lin][0] == '\0' ) {
  739. X            lin_sto =  lin;
  740. X            break;
  741. X        }
  742. X    }
  743. X    lin_diff = (lin_sto - line_sta) / columns;
  744. X    lin_end = line_sta + lin_diff;
  745. X    for ( lin = line_sta; lin < lin_end; lin++) {
  746. X        if ( cur_page[lin][0] != ' ' || cur_page[lin][1] != '\0'
  747. X        || columns != 1 ) {
  748. X            for ( cs = 0; cs < columns; cs++ ) {
  749. X                tmpl = lin + lin_diff * cs;
  750. X                if ( cur_page[tmpl][end_char] == '\0' && got_mrandom ) {
  751. X                    fill_sp(tmpl, end_char);
  752. X                }
  753. X                for ( col = 0; col < colu_chars; col++ ) {
  754. X                    if ( cur_page[tmpl][col] == '\0' ) {
  755. X                        if ( cs == end_col && !got_fill ) break;
  756. X                        if ( got_dyslexi ) putrev(' ');
  757. X                        else putchar(' ');
  758. X                    } else {
  759. X                        if ( got_dyslexi ) putrev(cur_page[tmpl][col]);
  760. X                        else putchar(cur_page[tmpl][col]);
  761. X                        cur_page[tmpl][col] = '\0';
  762. X                    }
  763. X                }
  764. X                if ( cs < end_col ) {
  765. X                    for ( col = 0; col < del_len; col++ ) {
  766. X                        if ( got_dyslexi ) putrev(delim[col]);
  767. X                        else putchar(delim[col]);
  768. X                    }
  769. X                }
  770. X            }
  771. X            if ( got_dyslexi ) flushrev();
  772. X        }
  773. X        putchar('\n');
  774. X    }
  775. X    lin = col = 0;
  776. }
  777. X
  778. fill_sp(line, end_char) {
  779. X    int pass = 0, last, nulls = end_char, words = 0, i, found_sp = FALSE;
  780. X    int found_word = FALSE, moves, new_end, old_end;
  781. X
  782. X    while ( cur_page[line][--nulls] == '\0' && nulls != 1 );
  783. X    nulls = end_char - nulls;
  784. X    last = end_char - nulls;
  785. X    for ( i = ins_len; i <= last; i++) {
  786. X        if ( cur_page[line][i] != ' ' ) {
  787. X            if ( !found_word ) {
  788. X                words++;
  789. X                found_word = TRUE;
  790. X            }
  791. X        } else {
  792. X            found_word = FALSE;
  793. X        }
  794. X    }
  795. X    if ( words < 2 ) return;
  796. X    old_end = last;
  797. X    while ( ++pass < mrandom ) {
  798. X        if ( words > nulls ) moves = nulls;
  799. X        else moves = words - 1;
  800. X        i = moves;
  801. X        new_end = moves + old_end;
  802. X        last = new_end;
  803. X        while( 1 ) {
  804. X            cur_page[line][new_end--] = cur_page[line][old_end--];
  805. X            if ( old_end < 0 ) break;
  806. X            if ( cur_page[line][old_end] == ' ' ) {
  807. X                if ( !found_sp ) {
  808. X                    if ( moves-- > 0 ) cur_page[line][new_end--] = ' ' ;
  809. X                }
  810. X                found_sp = TRUE;
  811. X            } else {
  812. X                found_sp = FALSE;
  813. X            }
  814. X        }
  815. X        if ( cur_page[line][end_char] != '\0' ) return;
  816. X        nulls = nulls - i;
  817. X        old_end = last;
  818. X    }
  819. }
  820. SHAR_EOF
  821. chmod 0644 mfold.c ||
  822. echo 'restore of mfold.c failed'
  823. Wc_c="`wc -c < 'mfold.c'`"
  824. test 14166 -eq "$Wc_c" ||
  825.     echo 'mfold.c: original size 14166, current size' "$Wc_c"
  826. fi
  827. # ============= mfold_doc ==============
  828. if test -f 'mfold_doc' -a X"$1" != X"-c"; then
  829.     echo 'x - skipping mfold_doc (File already exists)'
  830. else
  831. echo 'x - extracting mfold_doc (Text)'
  832. sed 's/^X//' << 'SHAR_EOF' > 'mfold_doc' &&
  833. The documentation follows:
  834. X
  835. The program has some large main parts:
  836. X
  837. X    1) One part scans the options and their arguments from the command line.
  838. X
  839. X    2) One part reads text input which not should be changed before
  840. X    the folding and writes the text to standard output.
  841. X
  842. X    3) One part does the actual folding and inserts text from
  843. X    the '-i' flag. This part also cuts the words if they are too
  844. X    long and puts a '-' at the end of the cut word.
  845. X
  846. X    4) One part reads input text which not should be changed after
  847. X    the folding, and writes the text to standard output.
  848. X
  849. Variables with names 'got_blabla' and 'index_blabla' refer to
  850. the different flags the program can receive. The program doesn't
  851. use getopts(3) and therefore has a more rigid option format
  852. in the shell. But it's easier to handle errors this way.
  853. X
  854. The '-i' and '-D' options are handled as special cases by mfold.
  855. Any input file is also handled as a special case by mfold.
  856. Remaining options are handled in one separate switch construct.
  857. X
  858. The text which is to be folded is read into an internal two
  859. dimensional 'page' buffer. This buffer has the width of one column
  860. and the length of all the lines in ALL columns on one page. The buffer
  861. is named 'cur_page' and is a global variable.
  862. X
  863. The folding is done in a 'while ( 1 )' loop. The first thing done
  864. in this loop is a large 'if' statement, about 44 lines long. This
  865. 'if' statement checks if a word is larger than the line length and then
  866. cuts the word, saves some characters in some temporary variables, named
  867. 'in_2' and 'in_3'. This construction can handle 2 (two) character
  868. long lines. Then some newline handling is done, see the '-n'
  869. option in the manual to understand the source easier. An 'if'
  870. statement checks if the next character is a blank space or not a
  871. blank space. If it is a space, the word in 'cur_word' is written to
  872. the output, and if it's not, the character is put into 'cur_word'.
  873. When encountering an EOF, mfold exits the 'while ( 1 )' loop.
  874. X
  875. The output is not sent to standard output directly. Instead a
  876. function 'putcolu' is used. 'putcolu' writes to the internal
  877. page buffer 'cur_page'. When 'cur_page' is full, the function
  878. 'flush_page' writes 'cur_page to the output. But if the '-d'
  879. flag is used the output is written to 'putrev' instead, where
  880. the function 'flushrev' flushes the internal reverse script
  881. one line buffer. When the '-r' flag is set, the function
  882. 'fill_sp' fills blank space until every line is right justified.
  883. X
  884. There are some more help functions, but they are very simple
  885. and should be understood without explanation... :-) ?
  886. X
  887. X
  888. Bug reports, ideas, or patches could be sent to;
  889. Peter Smidt   smidt@cd.chalmers.se    or
  890. Peter Smidt   smidt@fy.chalmers.se
  891. X
  892. /Maaniker
  893. SHAR_EOF
  894. chmod 0644 mfold_doc ||
  895. echo 'restore of mfold_doc failed'
  896. Wc_c="`wc -c < 'mfold_doc'`"
  897. test 2727 -eq "$Wc_c" ||
  898.     echo 'mfold_doc: original size 2727, current size' "$Wc_c"
  899. fi
  900. exit 0
  901.  
  902.