smidt@fy.chalmers.se (Peter Smidt) (09/09/90)
Submitted-by: smidt@cd.chalmers.se Archive-name: mfold.shar/part01 (one part) ---- Cut Here and unpack ---- #!/bin/sh # This is mfold.shar, a shell archive (shar 3.21) # made 09/09/1990 14:40 UTC by smidt@sponsz # Source directory /nfs/alcazar/u/smidt/src/mfold/exp # # existing files will NOT be overwritten # # This shar contains: # length mode name # ------ ---------- ------------------------------------------ # 351 -rw-r--r-- README # 94 -rw-r--r-- makefile # 3621 -rw-r--r-- mfold.1 # 13825 -rw-r--r-- mfold.c # if touch 2>&1 | fgrep '[-amc]' > /dev/null then TOUCH=touch else TOUCH=true fi # ============= README ============== if test X"$1" != X"-c" -a -f 'README'; then echo "File already exists: skipping 'README'" else echo "x - extracting README (Text)" sed 's/^Y//' << 'XXX' > README && YThe program mfold is a simpel folding and column making program. Yunpack the files from the shar file put them in a empty Ydirectory, type 'make' and you'll get the executable. A manual Yis included in the shar file. Y YBug reports, ideas, or patches could be sent to; YPeter Smidt smidt@cd.chalmers.se or YPeter Smidt smidt@fy.chalmers.se Y Y/Maaniker XXX $TOUCH -am 0909162990 README && chmod 0644 README || echo "restore of README failed" set `wc -c README`;Wc_c=$1 if test "$Wc_c" != "351"; then echo original size 351, current size $Wc_c fi fi # ============= makefile ============== if test X"$1" != X"-c" -a -f 'makefile'; then echo "File already exists: skipping 'makefile'" else echo "x - extracting makefile (Text)" sed 's/^Y//' << 'XXX' > makefile && Ynyfold: nyfold.o Y cc nyfold.o -o mfold Y rm -f nyfold.o Y Ynyfold.o: nyfold.c Y cc -c nyfold.c -g XXX $TOUCH -am 0909162690 makefile && chmod 0644 makefile || echo "restore of makefile failed" set `wc -c makefile`;Wc_c=$1 if test "$Wc_c" != "94"; then echo original size 94, current size $Wc_c fi fi # ============= mfold.1 ============== if test X"$1" != X"-c" -a -f 'mfold.1'; then echo "File already exists: skipping 'mfold.1'" else echo "x - extracting mfold.1 (Text)" sed 's/^Y//' << 'XXX' > mfold.1 && Y.\" Shareware 1990 of Chalmers Computer Society. Y.\" Y.\" @(#)mfold.1 (G|teborg) 1990-09-07 Y.\" Y.TH MFOLD 1 "September 7, 1990" Y.UC Y.SH NAME Ymfold \- Maaniker's fold and column making Y.SH SYNOPSIS Y.B mfold Y[ Y.B \-sn -ln -en -wn -f -d Y.B -rn Y.B -tn -cn -pn -n -L -Bn Y.B -D '<text>' -i '<text>' Y] Y.SH DESCRIPTION Y.I Mfold Yreads text files from standard input and writes to standard Youtput. Y.I Mfold Yconcatenates and folds the text in one or more columns Ywithout breaking in the middle of a word. Tabs and newlines are Yconverted to blank space. Multiple blank space is substituted with Yone single blank space. Some flags don't do anything if they aren't Yused together with either '-c' or '-d'. Y.PP YThere is a limited amount of options: Y.TP Y.B \-sn YStart line for Y.I mfold, Ywhere n is the line number. The preceding text Yis passed through Y.I mfold Ywithout being changed. If an end-of-file character is encountered Ybefore line n, Y.I mfold Ywill end the execution. Y.TP Y.B \-i YInsert text at the beginning of every line, or with '\-c', at every Ycolumn. This option as the last flag doesn't need any argument if Ya null argument is wanted. A space is required between the flag Yand the argument. Tabs may be present in the insert text. Default Yinsert text is a tab. Y.TP Y.B \-ln YLenght for output lines, excluding any insert text and excluding Yany delimiter text. Where n is the number of characters. Default Ylength is 76. Y.TP Y.B \-en Y.I Mfold Ywill end the folding at input line n. Text coming after this Yline is not being changed by Y.I mfold. Y.TP Y.B \-wn YSpecify the width n, of the not folded lines to avoid overrunning the Yinternal reverse buffer when using the '-d' flag. '-w' is not always Yprovided. Run Y.I mfold, Ylook at the result and decide if you want to specify the full Ywidth. Default is 80 characters. Y.TP Y.B \-f YFill each line with blank space to its full line length. Y.TP Y.B \-rn YFills the lines with extra blank space up to an amount of Yn blank spaces, to get an even right margin. The words will get Ya little random placement on the lines. Y.TP Y.B \-d YReverse the text for dyslexics. Y.TP Y.B \-tn YExpanding the tabs to spaces. Where n is the number of Yspaces. Default is four spaces. Use only with '-d'. Y.TP Y.B \-cn YSpecifies columns where n is the number of columns. Text is inserted at Yevery column. Y.TP Y.B \-pn YSpecifies page length n, meaningfull when used with the '-c' Yflag. Default are 40 lines per page. Y.TP Y.B \-n YMany newlines in a row is not substituted with one single Yblank space, which is otherwise the default. Instead they are Yleft without change, but may be put in a separate column. Y.TP Y.B \-L YWrite a ^L (newpage) at the end of each page. Use with '-c'. Y.TP Y.B \-Bn YWrite n newlines at the bottom (end) of the page. Default is Yone newline. Use when the number of columns are greater then one. Y.TP Y.B \-D YSpecify column delimiter. Default is three blank spaces. Tabs may be Ypresent in the delimiter. This option as the last flag doesn't need Yany argument if a null argument is wanted. Y.SH ERRORS YYou will notice them, when you give bad flags. Y.SH AUTHOR YPeter Smidt, Chalmers Computer Society. Y.SH SEE ALSO Yawk(1), sed(1), lex(1), nroff(1), fmt(1), fold(1), rev(1) Y.SH BUGS YIf underlining is present it will get messed up with the Ytext. The '-c' and the '-d' flags Y.I may Yproduce some extra Yunnecessary blank space at the end of the lines. When Ya word is longer than the line length, the word may be Ycut at an inappropriate place. Everything except blank space, Ynewline and tab counts as parts of words. Y.SH BUG REPORTS TO YPeter Smidt smidt@cd.chalmers.se or Y.br YPeter Smidt smidt@fy.chalmers.se XXX $TOUCH -am 0909162690 mfold.1 && chmod 0644 mfold.1 || echo "restore of mfold.1 failed" set `wc -c mfold.1`;Wc_c=$1 if test "$Wc_c" != "3621"; then echo original size 3621, current size $Wc_c fi fi # ============= mfold.c ============== if test X"$1" != X"-c" -a -f 'mfold.c'; then echo "File already exists: skipping 'mfold.c'" else echo "x - extracting mfold.c (Text)" sed 's/^Y//' << 'XXX' > mfold.c && Y#include <stdio.h> Y#include <curses.h> Y#include <strings.h> Y Y#define DEF_LINE_LEN 76 Y#define DEF_WORD_LEN 40 Y#define DEF_TAB_LEN 4 Y#define FULL_WIDTH 80 Y#define PAGE_LEN 40 Y#define POS1 1 Y#define DO_ALL1 \ Y col_pos = POS1;\ Y for ( doo = 0; doo < ins_len; doo++ ) {\ Y putcolu(insert[doo]);\ Y } Y#define BOT_LINES 1 Y#define STR 15 Y#define TEST_STR 25 Y#define GET_NUM_STR 25 Y Yint colu_chars, colu_lines; Yint page_len = PAGE_LEN, columns = 1, lin = 0, bot_lines = BOT_LINES; Yint got_newpage = FALSE, got_dyslexi = FALSE, full_line = FULL_WIDTH; Yint tab_len = DEF_TAB_LEN, ins_tabs = 0, del_len, got_fill = FALSE; Yint got_mrandom = FALSE, got_bot = FALSE, ins_len, mrandom = 1; Ychar **cur_page, *malloc(), *delim = " ", **glob_argv; Y Ymain(argc, argv) Ychar *argv[]; Yint argc; Y{ Y int col_pos = 1, j = 0, k, in, doo, line_len = DEF_LINE_LEN, row_count = 1; Y int cnt_nwl = 0, new_wo_le, dummy = TRUE, end = 2; Y int width = FULL_WIDTH, err = FALSE, in_2 = 0, in_3 = 0, tmp_chars = 0; Y char *cur_word, *insert = "\t", *s = "Bad option ' '"; Y int index, start = 1, word_len = DEF_WORD_LEN; Y int got_start = FALSE, got_line_len = FALSE, got_insert = FALSE; Y int got_tab_len = FALSE, got_end = FALSE, got_width = FALSE; Y int got_columns = FALSE, got_page_len = FALSE; Y int got_newlines = FALSE, got_delim = FALSE; Y int index_start = 0, index_insert = 0, index_line_len = 0; Y int index_tab_len = 0, index_end = 0, index_width = 0; Y int index_columns = 0, index_page_len = 0, index_delim = 0; Y int index_bot = 0, index_mrandom = 0; Y glob_argv = argv; Y for ( index = 1; index < argc; index++) { Y if ( argv[index][0] != '-' ) { Y if ( index != 1 ) { Y if ( argv[index - 1][0] == '-' ) { Y if ( argv[index - 1][1] == 'i' ) { Y index_insert = index; Y } else if ( argv[index - 1][1] == 'D' ) { Y index_delim = index; Y } else { Y err = TRUE; Y } Y } else { Y err = TRUE; Y } Y } else { Y err = TRUE; Y } Y if ( err ) { Y fprintf(stderr, "Flag '%s' not allowed.\n", argv[index]); Y usage(11); Y } Y } Y doo = index_insert != index && index_delim != index; Y switch ( argv[index][1] ) { Y case 'i': Y check_it(&got_insert, "-i", 8, doo, &index_insert, index + 1); Y break; Y case 's': Y check_it(&got_start, "-s", 9, doo, &index_start, index); Y break; Y case 'l': Y check_it(&got_line_len, "-l", 10, doo, &index_line_len, index); Y break; Y case 'e': Y check_it(&got_end, "-e", 10, doo, &index_end, index); Y break; Y case 'w': Y check_it(&got_width, "-w", 10, doo, &index_width, index); Y break; Y case 'r': Y check_it(&got_mrandom, "-r", 37, doo, &index_mrandom, index); Y break; Y case 'd': Y check_it(&got_dyslexi, "-d", 11, doo, &dummy, index); Y break; Y case 't': Y check_it(&got_tab_len, "-t", 13, doo, &index_tab_len, index); Y break; Y case 'c': Y check_it(&got_columns, "-c", 15, doo, &index_columns, index); Y break; Y case 'p': Y check_it(&got_page_len, "-p", 16, doo, &index_page_len, index); Y break; Y case 'B': Y check_it(&got_bot, "-B", 17, doo, &index_bot, index); Y break; Y case 'f': Y check_it(&got_fill, "-f", 33, doo, &dummy, index); Y break; Y case 'n': Y check_it(&got_newlines, "-n", 18, doo, &dummy, index); Y break; Y case 'L': Y check_it(&got_newpage, "-L", 19, doo, &dummy, index); Y break; Y case 'D': Y check_it(&got_delim, "-D", 36, doo, &index_delim, index + 1); Y break; Y case '\0': Y write_err(doo, "Empty flag '-'", 31); Y break; Y default: Y s[12] = argv[index][0]; Y s[13] = argv[index][1]; Y write_err(doo, s, 20); Y break; Y } Y } Y ext_num(got_start, &start, argv[index_start], Y "Line zero, for start, not allowed", 21); Y ext_num(got_page_len, &page_len, argv[index_page_len], Y "Page length zero, not allowed", 24); Y ext_num(got_tab_len, &tab_len, argv[index_tab_len], Y "Tab length zero, not allowed", 27); Y ext_num(got_line_len, &line_len, argv[index_line_len], Y "Line length zero, not allowed", 25); Y write_err(line_len < 2, "Too short line length, not allowed", 32); Y ext_num(got_end, &end, argv[index_end], Y "End length zero, not allowed", 25); Y write_err(got_end && end <= start, Y "End not greater than start line, not allowed", 33); Y ext_num(got_width, &width, argv[index_width], Y "Line length zero, not allowed", 25); Y ext_num(got_mrandom, &mrandom, argv[index_mrandom], Y "Zero fill length, not allowed", 36); Y if ( got_bot ) get_num(&bot_lines, argv[index_bot]); Y if ( got_insert ) { Y if ( index_insert < argc ) { Y insert = argv[index_insert]; Y } else { Y insert = ""; Y } Y } Y if ( got_delim ) { Y if ( index_insert < argc ) { Y delim = argv[index_delim]; Y } else { Y delim = ""; Y } Y } Y del_len = strlen(delim); Y if ( got_columns ) { Y get_num(&columns, argv[index_columns]); Y write_err(columns == 0, "columns count zero, not allowed", 26); Y write_err(line_len % columns, Y "Lines not an even multiple of columns length", 27); Y } Y/* colu_chars is the chars on one column. colu_lines is the total number of Ylines in all the columns in one page. page_len is the number of lines in one Ypage. */ Y ins_len = strlen(insert); Y colu_chars = line_len / columns + ins_len; Y colu_lines = page_len * columns; Y write_err( !(cur_page = (char**) malloc(colu_lines * sizeof(char*))), Y "Can not malloc that page length", 39); Y for ( in = 0; in < colu_lines; in++ ) { Y if ( !(cur_page[in] = malloc(colu_chars * sizeof(char))) ) { Y write_err(TRUE, "Can not malloc that page length", 40); Y } Y } Y for ( doo = 0; doo < ins_len; doo++ ) { Y if ( insert[doo] == '\t' ) { Y ins_tabs++; Y } Y } Y full_line = line_len + ins_len * columns + del_len * ( columns - 1); Y full_line += ( tab_len - 1 ) * columns * ins_tabs; Y line_len = line_len / columns; Y word_len = line_len; Y write_err( !(cur_word = malloc(word_len * sizeof(char))), Y "Can not malloc that word (line?) length", 41); Y if ( width > full_line ) initrev(width); Y else initrev(full_line); Y while ( row_count < start ) { Y in = getchar(); Y if ( in == EOF ) exit(0); Y if ( in == '\n' ) { Y if ( got_dyslexi ) { Y flushrev(); Y } Y putchar('\n'); Y row_count++; Y } else if ( got_dyslexi ) { Y putrev(in); Y } else { Y putchar(in); Y } Y } Y if ( !got_end ) end = row_count + 1; Y lin = ( ( start - 1 ) % page_len ) * columns; Y new_wo_le = word_len - 1; Y/* ******************** The fold follows ******************** */ Y while ( 1 ) { Y DO_ALL1 Y while ( 1 ) { Y if ( row_count > end ) { Y in = EOF; Y } else if ( j == new_wo_le && tmp_chars == 0 ) { Y in_2 = getchar(); Y if ( in_2 == ' ' || in_2 == '\n' || in_2 == '\t' ) { Y in = in_2; Y } else { Y in_3 = getchar(); Y if ( in_3 == ' ' || in_3 == '\n' || in_3 == '\t' ) { Y in = in_2; Y tmp_chars = 1; Y } else { Y in = '-'; Y tmp_chars = 2; Y } Y } Y } else if ( j == word_len ) { Y in = ' '; Y } else if ( tmp_chars > 0 ) { Y if ( tmp_chars == 1 && j == 0 ) { Y in = in_3; Y tmp_chars = 0; Y } else if ( tmp_chars == 1 && j == 1 ) { Y in_2 = in_3; Y tmp_chars = 0; Y if ( line_len != 2 || in_2 == ' ' || in_2 == '\n' Y || in_2 == '\t' ) { Y in = in_2; Y } else { Y in_3 = getchar(); Y if ( in_3 == ' ' || in_3 == '\n' || in_3 == '\t' ) { Y in = in_2; Y tmp_chars = 1; Y } else { Y in = '-'; Y tmp_chars = 2; Y } Y } Y } else { Y in = in_2; Y tmp_chars = 1; Y } Y } else { Y in = getchar(); Y } Y if ( cnt_nwl > 1 && got_newlines && in != '\n' ) { Y putcolu('\n'); Y while ( --cnt_nwl ) { Y putcolu(' '); Y putcolu('\n'); Y } Y DO_ALL1 Y } Y if ( in != '\n' ) cnt_nwl = 0; Y if ( in == '\n' || in == '\t' ) { Y if ( in == '\n' ) { Y if ( got_end ) row_count++; Y if ( got_newlines ) cnt_nwl++; Y } Y in = ' '; Y } Y if ( in == EOF ) { Y putcolu('\n'); Y flushpage(columns); Y if ( !got_end ) exit(0); Y else break; Y } Y if ( in != ' ' ) { Y write_err( j >= word_len || j < 0 , Y "Internal error or to long text word", 3); Y cur_word[j++] = in; Y } else { Y if ( col_pos != POS1 && (col_pos + j) <= line_len && Y j != 0 ) { Y putcolu(' '); Y col_pos++; Y } else if ( (col_pos + j) > line_len && col_pos != POS1 ) { Y putcolu('\n'); Y DO_ALL1 Y } Y for ( k = 0; k < j; k++ ) { Y putcolu(cur_word[k]); Y } Y col_pos += j; Y j = 0; Y } Y if ( col_pos == line_len ) break; Y } Y if ( in == EOF ) break; Y putcolu('\n'); Y } Y if ( cnt_nwl > 1 && got_newlines ) { Y while ( cnt_nwl-- ) putcolu('\n'); Y } Y while ( 1 ) { Y in = getchar(); Y if ( in == EOF ) exit(0); Y if ( in == '\n' ) { Y if ( got_dyslexi ) { Y flushrev(); Y } Y putchar('\n'); Y } else if ( got_dyslexi ) { Y putrev(in); Y } else { Y putchar(in); Y } Y } Y} Y Ychar *buff; Yint gl_i = 0, len; Y/* lin is the line index in the one long column before it is pasted out onto the Ypage. len is the lenght of each line in the one long column. */ Y Yputrev(c) Y{ Y int i; Y Y if ( gl_i >= 0 && gl_i < len ) { Y if ( c != '\t' ) { Y buff[gl_i++] = c; Y } else { Y int k = tab_len - gl_i % tab_len; Y for ( i = 0; i < k; i++ ) { Y putrev(' '); Y } Y } Y } else { Y write_err(TRUE, Y "Internal error in reverse buffer. Specify bigger buffer", 4); Y } Y} Y Yflushrev() { Y int i; Y Y for ( i = len - 1; i > 0; i--) { Y if ( buff[i] != '\0' ) { Y putchar(buff[i]); Y buff[i] = '\0'; Y } else { Y putchar(' '); Y } Y } Y if ( buff[0] != ' ' ) { Y putchar(buff[0]); Y } Y gl_i = 0; Y} Y Yinitrev(l) Yint l; Y{ Y int i; Y Y len = l; Y write_err( !(buff = malloc(len * sizeof(char))), Y "Can not malloc that internal reverse buffer length", 42); Y for ( i = 0; i < len; i++ ) { Y buff[i] = '\0'; Y } Y} Y Ycheck_it(got_flag, s, err, boole, index_flag, index) Yint *got_flag, *index_flag; Ychar *s; Y{ Y test(*got_flag, s, err); Y test_two(boole, index_flag, index, got_flag); Y} Y Ytest(flag, s1, err) Ychar *s1; Y{ Y char *s2 = "Multiple ' ' not allowed"; Y Y s2[10] = s1[0]; Y s2[11] = s1[1]; Y write_err(flag, s2, err); Y} Y Ytest_two(boole, index_flag, index, got_flag) Yint *index_flag, *got_flag; Y{ Y if ( boole ) { Y if ( *index_flag && glob_argv[index][2] != '\0' ) { Y fprintf(stderr, "Flag '%c%c' doesn't want any argument.\n", Y glob_argv[index][0], glob_argv[index][1]); Y usage(35); Y } Y *index_flag = index; Y *got_flag = TRUE; Y } Y} Y Ywrite_err(flag, s, err) Ychar *s; Y{ Y if ( flag ) { Y fprintf(stderr, "%s.\n", s); Y usage(err); Y } Y} Y Yext_num(bulle, tal, arg, s, err) Yint *tal; Ychar *arg, *s; Y{ Y if ( bulle ) { Y get_num(tal, arg); Y write_err(*tal == 0, s, err); Y } Y} Y Yget_num(number, argv) Yint *number; Ychar argv[]; Y{ Y int k, in, tmp; Y char *s = "Not a number in flag ' '"; Y Y s[22] = argv[0]; Y s[23] = argv[1]; Y *number = 0; Y k = strlen(argv); Y write_err(k == 1, s, 9); Y for( in = 2; in < k; in++) { Y tmp = argv[in] - '0'; Y write_err(tmp < 0 || tmp > 9, "Bad flag, N-A-P-N", 5); Y *number = tmp + *number * 10; Y } Y} Y Yusage(t) { Y fprintf(stderr, "[ %d ] Usage: mfold [ -sn -ln -en -wn -f -d -rn -tn -cn -pn -n -L -Bn\n-D '<text>' -i '<text>' ]\n", t); Y exit(t); Y} Y Yint col = 0; Y Yputcolu(c) Ychar c; Y{ Y if ( c == '\n' || col == colu_chars ) { Y advance_line(); Y return; Y } Y cur_page[lin][col++] = c; Y} Y Yadvance_line() { Y col = 0; Y if ( ++lin == colu_lines ) { Y flushpage(columns); Y end_page(); Y } Y} Y Yend_page() { Y int i; Y Y if ( columns > 1 || got_bot ) { Y for ( i = 0; i < bot_lines; i++ ) { Y putchar('\n'); Y } Y } Y if ( got_newpage ) putchar(12); /* 12 == ^L (ascii) */ Y} Y Yflushpage(columns) { Y int line_sta = 0, cs, tmpl, lin_diff, lin_end; Y int end_col = columns - 1, lin_sto = colu_lines, end_char = colu_chars - 1; Y Y for ( lin = 0; lin < colu_lines; lin++ ) { Y if ( cur_page[lin][0] != '\0' ) { Y line_sta = lin; Y break; Y } Y } Y for ( lin = line_sta; lin < colu_lines; lin += columns ) { Y if ( cur_page[lin][0] == '\0' ) { Y lin_sto = lin; Y break; Y } Y } Y lin_diff = (lin_sto - line_sta) / columns; Y lin_end = line_sta + lin_diff; Y for ( lin = line_sta; lin < lin_end; lin++) { Y if ( cur_page[lin][0] == ' ' && cur_page[lin][1] == '\0' Y && columns == 1 ) { Y putchar('\n'); Y } else { Y for ( cs = 0; cs < columns; cs++ ) { Y tmpl = lin + lin_diff * cs; Y if ( cur_page[tmpl][end_char] == '\0' && got_mrandom ) { Y fill_sp(tmpl, end_char); Y } Y for ( col = 0; col < colu_chars; col++ ) { Y if ( cur_page[tmpl][col] == '\0' ) { Y if ( cs == end_col && !got_fill ) break; Y if ( got_dyslexi ) putrev(' '); Y else putchar(' '); Y } else { Y if ( got_dyslexi ) putrev(cur_page[tmpl][col]); Y else putchar(cur_page[tmpl][col]); Y cur_page[tmpl][col] = '\0'; Y } Y } Y if ( cs < end_col ) { Y for ( col = 0; col < del_len; col++ ) { Y if ( got_dyslexi ) putrev(delim[col]); Y else putchar(delim[col]); Y } Y } Y } Y } Y if ( got_dyslexi ) flushrev(); Y putchar('\n'); Y } Y lin = col = 0; Y} Y Yfill_sp(line, end_char) { Y int pass = 0, last, nulls = end_char, words = 0, i, found_sp = FALSE; Y int found_word = FALSE, moves, new_end, old_end; Y Y while ( cur_page[line][--nulls] == '\0' && nulls != 1 ); Y nulls = end_char - nulls; Y last = end_char - nulls; Y for ( i = ins_len; i <= last; i++) { Y if ( cur_page[line][i] != ' ' ) { Y if ( !found_word ) { Y words++; Y found_word = TRUE; Y } Y } else { Y found_word = FALSE; Y } Y } Y if ( words < 2 ) return; Y old_end = last; Y while ( ++pass < mrandom ) { Y if ( words > nulls ) moves = nulls; Y else moves = words - 1; Y i = moves; Y new_end = moves + old_end; Y last = new_end; Y while( 1 ) { Y cur_page[line][new_end--] = cur_page[line][old_end--]; Y if ( old_end < 0 ) break; Y if ( cur_page[line][old_end] == ' ' ) { Y if ( !found_sp ) { Y if ( moves-- > 0 ) cur_page[line][new_end--] = ' ' ; Y } Y found_sp = TRUE; Y } else { Y found_sp = FALSE; Y } Y } Y if ( cur_page[line][end_char] != '\0' ) return; Y nulls = nulls - i; Y old_end = last; Y } Y} XXX $TOUCH -am 0909162690 mfold.c && chmod 0644 mfold.c || echo "restore of mfold.c failed" set `wc -c mfold.c`;Wc_c=$1 if test "$Wc_c" != "13825"; then echo original size 13825, current size $Wc_c fi fi exit 0 -- +=======================================+ "The whole valley is like a smorgasbord." -- TREMORS
smidt@fy.chalmers.se (Peter Smidt) (09/15/90)
Submitted-by: smidt@sponsz.cd.chalmers.se Archive-name: mfold.shar/part01 Mfold have previously been published in alt.sources. A bug have been fixed and a better documentation have been created. There have been some small changes to the man pages and the makefile. ---- Cut Here and feed the following to sh ---- #!/bin/sh # This is mfold.shar, a shell archive (produced by shar 3.49) # To extract the files from this archive, save it to a file, remove # everything above the "!/bin/sh" line above, and type "sh file_name". # # made 09/15/1990 08:55 UTC by smidt@sponsz # Source directory /nfs/alcazar/u/smidt/src/mfold/exp # # existing files will NOT be overwritten unless -c is specified # This format requires very little intelligence at unshar time. # "if test", "echo", "true", and "sed" may be needed. # # This shar contains: # length mode name # ------ ---------- ------------------------------------------ # 87 -rw-r--r-- makefile # 3626 -rw-r--r-- mfold.1 # 13693 -rw-r--r-- mfold.c # 2613 -rw-r--r-- mfold_doc # 499 -rw-r--r-- README # # ============= makefile ============== if test -f 'makefile' -a X"$1" != X"-c"; then echo 'x - skipping makefile (File already exists)' else echo 'x - extracting makefile (Text)' sed 's/^X//' << 'SHAR_EOF' > 'makefile' && Xmfold: mfold.o X cc mfold.o -o mfold X rm -f mfold.o X Xmfold.o: mfold.c X cc -c mfold.c -O SHAR_EOF true || echo 'restore of makefile failed' fi # ============= mfold.1 ============== if test -f 'mfold.1' -a X"$1" != X"-c"; then echo 'x - skipping mfold.1 (File already exists)' else echo 'x - extracting mfold.1 (Text)' sed 's/^X//' << 'SHAR_EOF' > 'mfold.1' && X.\" Public Domain 1990 of Chalmers Computer Society. X.\" X.\" @(#)mfold.1 (G|teborg) 1990-09-11 X.\" X.TH MFOLD 1 "September 11, 1990" X.UC X.SH NAME Xmfold \- Maaniker's fold and column making X.SH SYNOPSIS X.B mfold X[ X.B \-sn -ln -en -wn -f -d X.B -rn X.B -tn -cn -pn -n -L -Bn X.B -D '<text>' -i '<text>' X] X.SH DESCRIPTION X.I Mfold Xreads text files from standard input and writes to standard Xoutput. X.I Mfold Xconcatenates and folds the text in one or more columns Xwithout breaking in the middle of a word. Tabs and newlines are Xconverted to blank space. Multiple blank space is substituted with Xone single blank space. Some flags don't do anything if they aren't Xused together with either '-c' or '-d'. X.PP XThere is a limited amount of options: X.TP X.B \-sn XStart line for X.I mfold, Xwhere n is the line number. The preceding text Xis passed through X.I mfold Xwithout being changed. If an end-of-file character is encountered Xbefore line n, X.I mfold Xwill end the execution. X.TP X.B \-i XInsert text at the beginning of every line, or with '\-c', at every Xcolumn. This option as the last flag doesn't need any argument if Xa null argument is wanted. A space is required between the flag Xand the argument. Tabs may be present in the insert text. Default Xinsert text is a tab. X.TP X.B \-ln XLenght for output lines, excluding any insert text and excluding Xany delimiter text. Where n is the number of characters. Default Xlength is 76. X.TP X.B \-en X.I Mfold Xwill end the folding at input line n. Text coming after this Xline is not being changed by X.I mfold. X.TP X.B \-wn XSpecify the width n, of the not folded lines to avoid overrunning the Xinternal reverse buffer when using the '-d' flag. '-w' is not always Xprovided. Run X.I mfold, Xlook at the result and decide if you want to specify the full Xwidth. Default is 80 characters. X.TP X.B \-f XFill each line with blank space to its full line length. X.TP X.B \-rn XFills the lines with extra blank space up to an amount of Xn blank spaces, to get an even right margin. The words will get Xa little random placement on the lines. X.TP X.B \-d XReverse the text for dyslexics. X.TP X.B \-tn XExpanding the tabs to spaces. Where n is the number of Xspaces. Default is four spaces. Use only with '-d'. X.TP X.B \-cn XSpecifies columns where n is the number of columns. Text is inserted at Xevery column. X.TP X.B \-pn XSpecifies page length n, meaningfull when used with the '-c' Xflag. Default are 40 lines per page. X.TP X.B \-n XMany newlines in a row is not substituted with one single Xblank space, which is otherwise the default. Instead they are Xleft without change, but may be put in a separate column. X.TP X.B \-L XWrite a ^L (newpage) at the end of each page. Use with '-c'. X.TP X.B \-Bn XWrite n newlines at the bottom (end) of the page. Default is Xone newline. Use when the number of columns are greater then one. X.TP X.B \-D XSpecify column delimiter. Default is three blank spaces. Tabs may be Xpresent in the delimiter. This option as the last flag doesn't need Xany argument if a null argument is wanted. X.SH ERRORS XYou will notice them, when you give bad flags. X.SH AUTHOR XPeter Smidt, Chalmers Computer Society. X.SH SEE ALSO Xawk(1), sed(1), lex(1), nroff(1), fmt(1), fold(1), rev(1) X.SH BUGS XIf underlining is present it will get messed up with the Xtext. The '-c' and the '-d' flags X.I may Xproduce some extra Xunnecessary blank space at the end of the lines. When Xa word is longer than the line length, the word may be Xcut at an inappropriate place. Everything except blank space, Xnewline and tab counts as parts of words. X.SH BUG REPORTS TO XPeter Smidt smidt@cd.chalmers.se or X.br XPeter Smidt smidt@fy.chalmers.se SHAR_EOF true || echo 'restore of mfold.1 failed' fi # ============= mfold.c ============== if test -f 'mfold.c' -a X"$1" != X"-c"; then echo 'x - skipping mfold.c (File already exists)' else echo 'x - extracting mfold.c (Text)' sed 's/^X//' << 'SHAR_EOF' > 'mfold.c' && X#include <stdio.h> X#include <curses.h> X#include <strings.h> X X#define DEF_LINE_LEN 76 X#define DEF_WORD_LEN 40 X#define DEF_TAB_LEN 4 X#define FULL_WIDTH 80 X#define PAGE_LEN 40 X#define POS1 1 X#define DO_ALL1 \ X col_pos = POS1;\ X for ( doo = 0; doo < ins_len; doo++ ) {\ X putcolu(insert[doo]);\ X } X#define BOT_LINES 1 X#define STR 15 X#define TEST_STR 25 X#define GET_NUM_STR 25 X Xint colu_chars, colu_lines; Xint page_len = PAGE_LEN, columns = 1, lin = 0, bot_lines = BOT_LINES; Xint got_newpage = FALSE, got_dyslexi = FALSE, full_line = FULL_WIDTH; Xint tab_len = DEF_TAB_LEN, ins_tabs = 0, del_len, got_fill = FALSE; Xint got_mrandom = FALSE, got_bot = FALSE, ins_len, mrandom = 1; Xchar **cur_page, *malloc(), *delim = " ", **glob_argv; X Xmain(argc, argv) Xchar *argv[]; Xint argc; X{ X int col_pos = 1, j = 0, k, in, doo, line_len = DEF_LINE_LEN, row_count = 1; X int cnt_nwl = 0, new_wo_le, dummy = TRUE, end = 2; X int width = FULL_WIDTH, err = FALSE, in_2 = 0, in_3 = 0, tmp_chars = 0; X char *cur_word, *insert = "\t", *s = "Bad option ' '"; X int index, start = 1, word_len = DEF_WORD_LEN; X int got_start = FALSE, got_line_len = FALSE, got_insert = FALSE; X int got_tab_len = FALSE, got_end = FALSE, got_width = FALSE; X int got_columns = FALSE, got_page_len = FALSE; X int got_newlines = FALSE, got_delim = FALSE; X int index_start = 0, index_insert = 0, index_line_len = 0; X int index_tab_len = 0, index_end = 0, index_width = 0; X int index_columns = 0, index_page_len = 0, index_delim = 0; X int index_bot = 0, index_mrandom = 0; X glob_argv = argv; X for ( index = 1; index < argc; index++) { X if ( argv[index][0] != '-' ) { X if ( index != 1 ) { X if ( argv[index - 1][0] == '-' ) { X if ( argv[index - 1][1] == 'i' ) { X index_insert = index; X } else if ( argv[index - 1][1] == 'D' ) { X index_delim = index; X } else { X err = TRUE; X } X } else { X err = TRUE; X } X } else { X err = TRUE; X } X if ( err ) { X fprintf(stderr, "Flag '%s' not allowed.\n", argv[index]); X usage(11); X } X } X doo = index_insert != index && index_delim != index; X switch ( argv[index][1] ) { X case 'i': X check_it(&got_insert, "-i", 8, doo, &index_insert, index + 1); X break; X case 's': X check_it(&got_start, "-s", 9, doo, &index_start, index); X break; X case 'l': X check_it(&got_line_len, "-l", 10, doo, &index_line_len, index); X break; X case 'e': X check_it(&got_end, "-e", 10, doo, &index_end, index); X break; X case 'w': X check_it(&got_width, "-w", 10, doo, &index_width, index); X break; X case 'r': X check_it(&got_mrandom, "-r", 37, doo, &index_mrandom, index); X break; X case 'd': X check_it(&got_dyslexi, "-d", 11, doo, &dummy, index); X break; X case 't': X check_it(&got_tab_len, "-t", 13, doo, &index_tab_len, index); X break; X case 'c': X check_it(&got_columns, "-c", 15, doo, &index_columns, index); X break; X case 'p': X check_it(&got_page_len, "-p", 16, doo, &index_page_len, index); X break; X case 'B': X check_it(&got_bot, "-B", 17, doo, &index_bot, index); X break; X case 'f': X check_it(&got_fill, "-f", 33, doo, &dummy, index); X break; X case 'n': X check_it(&got_newlines, "-n", 18, doo, &dummy, index); X break; X case 'L': X check_it(&got_newpage, "-L", 19, doo, &dummy, index); X break; X case 'D': X check_it(&got_delim, "-D", 36, doo, &index_delim, index + 1); X break; X case '\0': X write_err(doo, "Empty flag '-'", 31); X break; X default: X s[12] = argv[index][0]; X s[13] = argv[index][1]; X write_err(doo, s, 20); X break; X } X } X ext_num(got_start, &start, argv[index_start], X "Line zero, for start, not allowed", 21); X ext_num(got_page_len, &page_len, argv[index_page_len], X "Page length zero, not allowed", 24); X ext_num(got_tab_len, &tab_len, argv[index_tab_len], X "Tab length zero, not allowed", 27); X ext_num(got_line_len, &line_len, argv[index_line_len], X "Line length zero, not allowed", 25); X write_err(line_len < 2, "Too short line length, not allowed", 32); X ext_num(got_end, &end, argv[index_end], X "End length zero, not allowed", 25); X write_err(got_end && end <= start, X "End not greater than start line, not allowed", 33); X ext_num(got_width, &width, argv[index_width], X "Line length zero, not allowed", 25); X ext_num(got_mrandom, &mrandom, argv[index_mrandom], X "Zero fill length, not allowed", 36); X if ( got_bot ) get_num(&bot_lines, argv[index_bot]); X if ( got_insert ) { X if ( index_insert < argc ) { X insert = argv[index_insert]; X } else { X insert = ""; X } X } X if ( got_delim ) { X if ( index_delim < argc ) { X delim = argv[index_delim]; X } else { X delim = ""; X } X } X del_len = strlen(delim); X if ( got_columns ) { X get_num(&columns, argv[index_columns]); X write_err(columns == 0, "columns count zero, not allowed", 26); X write_err(line_len % columns, X "Lines not an even multiple of columns length", 27); X } X/* colu_chars is the chars on one column. colu_lines is the total number of Xlines in all the columns in one page. page_len is the number of lines in one Xpage. */ X ins_len = strlen(insert); X colu_chars = line_len / columns + ins_len; X colu_lines = page_len * columns; X write_err( !(cur_page = (char**) malloc(colu_lines * sizeof(char*))), X "Can not malloc that page length", 39); X for ( in = 0; in < colu_lines; in++ ) { X if ( !(cur_page[in] = malloc(colu_chars * sizeof(char))) ) { X write_err(TRUE, "Can not malloc that page length", 40); X } X } X for ( doo = 0; doo < ins_len; doo++ ) { X if ( insert[doo] == '\t' ) { X ins_tabs++; X } X } X full_line = line_len + ins_len * columns + del_len * ( columns - 1); X full_line += ( tab_len - 1 ) * columns * ins_tabs; X line_len = line_len / columns; X word_len = line_len; X write_err( !(cur_word = malloc(word_len * sizeof(char))), X "Can not malloc that word (line?) length", 41); X if ( width > full_line ) initrev(width); X else initrev(full_line); X while ( row_count < start ) { X in = getchar(); X if ( in == EOF ) exit(0); X if ( in == '\n' ) { X if ( got_dyslexi ) { X flushrev(); X } X putchar('\n'); X row_count++; X } else if ( got_dyslexi ) { X putrev(in); X } else { X putchar(in); X } X } X if ( !got_end ) end = row_count + 1; X lin = ( ( start - 1 ) % page_len ) * columns; X new_wo_le = word_len - 1; X/* ******************** The fold follows ******************** */ X DO_ALL1 X while ( 1 ) { X if ( row_count > end ) { X in = EOF; X } else if ( j == new_wo_le && tmp_chars == 0 ) { X in_2 = getchar(); X if ( in_2 == ' ' || in_2 == '\n' || in_2 == '\t' ) { X in = in_2; X } else { X in_3 = getchar(); X if ( in_3 == ' ' || in_3 == '\n' || in_3 == '\t' ) { X in = in_2; X tmp_chars = 1; X } else { X in = '-'; X tmp_chars = 2; X } X } X } else if ( j == word_len ) { X in = ' '; X } else if ( tmp_chars > 0 ) { X if ( tmp_chars == 1 && j == 0 ) { X in = in_3; X tmp_chars = 0; X } else if ( tmp_chars == 1 && j == 1 ) { X in_2 = in_3; X tmp_chars = 0; X if ( line_len != 2 || in_2 == ' ' || in_2 == '\n' X || in_2 == '\t' ) { X in = in_2; X } else { X in_3 = getchar(); X if ( in_3 == ' ' || in_3 == '\n' || in_3 == '\t' ) { X in = in_2; X tmp_chars = 1; X } else { X in = '-'; X tmp_chars = 2; X } X } X } else { X in = in_2; X tmp_chars = 1; X } X } else { X in = getchar(); X } X if ( cnt_nwl > 1 && got_newlines && in != '\n' ) { X putcolu('\n'); X while ( --cnt_nwl ) { X putcolu(' '); X putcolu('\n'); X } X DO_ALL1 X } X if ( in != '\n' ) cnt_nwl = 0; X if ( in == '\n' || in == '\t' ) { X if ( in == '\n' ) { X if ( got_end ) row_count++; X if ( got_newlines ) cnt_nwl++; X } X in = ' '; X } X if ( in == EOF ) { X putcolu('\n'); X flushpage(columns); X if ( !got_end ) exit(0); X else break; X } X if ( in != ' ' ) { X write_err( j >= word_len || j < 0 , X "Internal error or to long text word", 3); X cur_word[j++] = in; X } else { X if ( col_pos != POS1 && (col_pos + j) <= line_len && X j != 0 ) { X putcolu(' '); X col_pos++; X } else if ( (col_pos + j) > line_len && col_pos != POS1 ) { X putcolu('\n'); X DO_ALL1 X } X for ( k = 0; k < j; k++ ) { X putcolu(cur_word[k]); X } X col_pos += j; X j = 0; X } X } X/* ************** End of the fold ****************** */ X if ( cnt_nwl > 1 && got_newlines ) { X while ( cnt_nwl-- ) putcolu('\n'); X } X while ( 1 ) { X in = getchar(); X if ( in == EOF ) exit(0); X if ( in == '\n' ) { X if ( got_dyslexi ) { X flushrev(); X } X putchar('\n'); X } else if ( got_dyslexi ) { X putrev(in); X } else { X putchar(in); X } X } X} X Xchar *buff; Xint gl_i = 0, len; X/* lin is the line index in the one long column before it is pasted out onto the Xpage. len is the lenght of each line in the one long column. */ X Xputrev(c) X{ X int i; X X if ( gl_i >= 0 && gl_i < len ) { X if ( c != '\t' ) { X buff[gl_i++] = c; X } else { X int k = tab_len - gl_i % tab_len; X for ( i = 0; i < k; i++ ) { X putrev(' '); X } X } X } else { X write_err(TRUE, X "Internal error in reverse buffer. Specify bigger buffer", 4); X } X} X Xflushrev() { X int i; X X for ( i = len - 1; i > 0; i--) { X if ( buff[i] != '\0' ) { X putchar(buff[i]); X buff[i] = '\0'; X } else { X putchar(' '); X } X } X if ( buff[0] != ' ' ) { X putchar(buff[0]); X } X gl_i = 0; X} X Xinitrev(l) Xint l; X{ X int i; X X len = l; X write_err( !(buff = malloc(len * sizeof(char))), X "Can not malloc that internal reverse buffer length", 42); X for ( i = 0; i < len; i++ ) { X buff[i] = '\0'; X } X} X Xcheck_it(got_flag, s, err, boole, index_flag, index) Xint *got_flag, *index_flag; Xchar *s; X{ X test(*got_flag, s, err); X test_two(boole, index_flag, index, got_flag); X} X Xtest(flag, s1, err) Xchar *s1; X{ X char *s2 = "Multiple ' ' not allowed"; X X s2[10] = s1[0]; X s2[11] = s1[1]; X write_err(flag, s2, err); X} X Xtest_two(boole, index_flag, index, got_flag) Xint *index_flag, *got_flag; X{ X if ( boole ) { X if ( *index_flag && glob_argv[index][2] != '\0' ) { X fprintf(stderr, "Flag '%c%c' doesn't want any argument.\n", X glob_argv[index][0], glob_argv[index][1]); X usage(35); X } X *index_flag = index; X *got_flag = TRUE; X } X} X Xwrite_err(flag, s, err) Xchar *s; X{ X if ( flag ) { X fprintf(stderr, "%s.\n", s); X usage(err); X } X} X Xext_num(bulle, tal, arg, s, err) Xint *tal; Xchar *arg, *s; X{ X if ( bulle ) { X get_num(tal, arg); X write_err(*tal == 0, s, err); X } X} X Xget_num(number, argv) Xint *number; Xchar argv[]; X{ X int k, in, tmp; X char *s = "Not a number in flag ' '"; X X s[22] = argv[0]; X s[23] = argv[1]; X *number = 0; X k = strlen(argv); X write_err(k == 1, s, 9); X for( in = 2; in < k; in++) { X tmp = argv[in] - '0'; X write_err(tmp < 0 || tmp > 9, "Bad flag, N-A-P-N", 5); X *number = tmp + *number * 10; X } X} X Xusage(t) { X fprintf(stderr, "[ %d ] Usage: mfold [ -sn -ln -en -wn -f -d -rn -tn -cn -pn -n -L -Bn\n-D '<text>' -i '<text>' ]\n", t); X exit(t); X} X Xint col = 0; X Xputcolu(c) Xchar c; X{ X if ( c == '\n' || col == colu_chars ) { X advance_line(); X return; X } X cur_page[lin][col++] = c; X} X Xadvance_line() { X col = 0; X if ( ++lin == colu_lines ) { X flushpage(columns); X end_page(); X } X} X Xend_page() { X int i; X X if ( columns > 1 || got_bot ) { X for ( i = 0; i < bot_lines; i++ ) { X putchar('\n'); X } X } X if ( got_newpage ) putchar(12); /* 12 == ^L (ascii) */ X} X Xflushpage(columns) { X int line_sta = 0, cs, tmpl, lin_diff, lin_end; X int end_col = columns - 1, lin_sto = colu_lines, end_char = colu_chars - 1; X X for ( lin = 0; lin < colu_lines; lin++ ) { X if ( cur_page[lin][0] != '\0' ) { X line_sta = lin; X break; X } X } X for ( lin = line_sta; lin < colu_lines; lin += columns ) { X if ( cur_page[lin][0] == '\0' ) { X lin_sto = lin; X break; X } X } X lin_diff = (lin_sto - line_sta) / columns; X lin_end = line_sta + lin_diff; X for ( lin = line_sta; lin < lin_end; lin++) { X if ( cur_page[lin][0] == ' ' && cur_page[lin][1] == '\0' X && columns == 1 ) { X putchar('\n'); X } else { X for ( cs = 0; cs < columns; cs++ ) { X tmpl = lin + lin_diff * cs; X if ( cur_page[tmpl][end_char] == '\0' && got_mrandom ) { X fill_sp(tmpl, end_char); X } X for ( col = 0; col < colu_chars; col++ ) { X if ( cur_page[tmpl][col] == '\0' ) { X if ( cs == end_col && !got_fill ) break; X if ( got_dyslexi ) putrev(' '); X else putchar(' '); X } else { X if ( got_dyslexi ) putrev(cur_page[tmpl][col]); X else putchar(cur_page[tmpl][col]); X cur_page[tmpl][col] = '\0'; X } X } X if ( cs < end_col ) { X for ( col = 0; col < del_len; col++ ) { X if ( got_dyslexi ) putrev(delim[col]); X else putchar(delim[col]); X } X } X } X } X if ( got_dyslexi ) flushrev(); X putchar('\n'); X } X lin = col = 0; X} X Xfill_sp(line, end_char) { X int pass = 0, last, nulls = end_char, words = 0, i, found_sp = FALSE; X int found_word = FALSE, moves, new_end, old_end; X X while ( cur_page[line][--nulls] == '\0' && nulls != 1 ); X nulls = end_char - nulls; X last = end_char - nulls; X for ( i = ins_len; i <= last; i++) { X if ( cur_page[line][i] != ' ' ) { X if ( !found_word ) { X words++; X found_word = TRUE; X } X } else { X found_word = FALSE; X } X } X if ( words < 2 ) return; X old_end = last; X while ( ++pass < mrandom ) { X if ( words > nulls ) moves = nulls; X else moves = words - 1; X i = moves; X new_end = moves + old_end; X last = new_end; X while( 1 ) { X cur_page[line][new_end--] = cur_page[line][old_end--]; X if ( old_end < 0 ) break; X if ( cur_page[line][old_end] == ' ' ) { X if ( !found_sp ) { X if ( moves-- > 0 ) cur_page[line][new_end--] = ' ' ; X } X found_sp = TRUE; X } else { X found_sp = FALSE; X } X } X if ( cur_page[line][end_char] != '\0' ) return; X nulls = nulls - i; X old_end = last; X } X} SHAR_EOF true || echo 'restore of mfold.c failed' fi # ============= mfold_doc ============== if test -f 'mfold_doc' -a X"$1" != X"-c"; then echo 'x - skipping mfold_doc (File already exists)' else echo 'x - extracting mfold_doc (Text)' sed 's/^X//' << 'SHAR_EOF' > 'mfold_doc' && XThe documentation follows: X XThe program have some large main parts: X X 1) One part scans the options and their arguments from the command line. X X 2) One part reads text input which not should be changed and X writes the text to standard output. X X 3) One part does the actual folding and inserts text from X the '-i' flag. This part does also cut the words if they are too X long and puts a '-' at the end of the cut word. X X 4) One part reads input text which not should be changed after X the folding, writes to standard output. X XVariables with names 'got_blabla' and 'index_blabla' refers to Xthe different flags the programs can receive. The program don't Xuse getopts(3) and have therefore a more rigid option format Xin the shell. But it's easier to handle errors this way. X XThe '-i' and '-D' options are handled as special cases by mfold. XRemaining options are handled in one separate switch construction. X XThe text which is to be folded is read into an internal 'page' buffer. XThis buffer has the width of one column and the length of all the Xlines in ALL columns on one page. The buffer is named 'cur_page' and Xis a global variable. X XThe folding is done in a 'while ( 1 )' loop. The first thing done Xin this loop is a large 'if' statment, about 44 lines long. This X'if' stament looks if a word is larger than the line length and then Xcuts the word, saves some charcters in som temporary variables, X'in_2' and 'in_3'. This construction can handle 2 (two) character Xlong lines. Then some newline handeling is done, see the '-n' Xoption in the manual to understand the source easier. A 'if' Xstatement look if the next charcter is a blank space or not a Xblank space. If it is a space, the word in 'cur_word' is written to Xthe output, and if it's not, the character is put into 'cur_word'. XWhen encountering an EOF, mfold exits the 'while ( 1 )' loop. X XThe output is not sent to standard output directly. Instead a Xfuntion 'putcolu' is used. 'putcolu' writes to the internal Xpage buffer 'cur_page'. When 'cur_page' is full, the function X'flush_page' writes 'cur_page to the output. But if the '-d' Xflag is used the output is written to 'putrev' instead, where Xthe function 'flushrev' flushes the internal reverse script Xbuffer, one line. When the '-r' flag is set, the function X'fill_sp' fills blank space until every line is right justified. X XThere is some more help functions, but they are very simple Xand should be understand without explanation... :-) ? X X XBug reports, ideas, or patches could be sent to; XPeter Smidt smidt@cd.chalmers.se or XPeter Smidt smidt@fy.chalmers.se X X/Maaniker SHAR_EOF true || echo 'restore of mfold_doc failed' fi # ============= README ============== if test -f 'README' -a X"$1" != X"-c"; then echo 'x - skipping README (File already exists)' else echo 'x - extracting README (Text)' sed 's/^X//' << 'SHAR_EOF' > 'README' && XThe program mfold is a simpel folding and column making program. Xunpack the files from the shar file put them in a empty Xdirectory, type 'make' and you'll get the executable. A manual Xis included in the shar file. X XA bug have been removed and some optimization have been done since the first Xposting to alt.sources. X XA more exact documentation is in mfold_doc. X X XBug reports, ideas, or patches could be sent to; XPeter Smidt smidt@cd.chalmers.se or XPeter Smidt smidt@fy.chalmers.se X X/Maaniker SHAR_EOF true || echo 'restore of README failed' fi exit 0 -- +=======================================+ "The whole valley is like a smorgasbord." -- TREMORS
smidt@fy.chalmers.se (Peter Smidt) (09/20/90)
The first version of mfold was sent to alt.sources. the second was sent to comp.sources.misc. This version has some changed options. Default insert text is by now a null string. Some bugs have been fixed. I hope this version will work on System V. Submitted-by: smidt@cd.chalmers.se Archive-name: mfold.shar/part01 ---- Cut Here and feed the following to sh ---- #!/bin/sh # This is mfold.shar, a shell archive (produced by shar 3.49) # To extract the files from this archive, save it to a file, remove # everything above the "!/bin/sh" line above, and type "sh file_name". # # made 09/19/1990 17:51 UTC by smidt@sponsz # Source directory /nfs/alcazar/u/smidt/src/mfold/exp # # existing files will NOT be overwritten unless -c is specified # # This shar contains: # length mode name # ------ ---------- ------------------------------------------ # 499 -rw-r--r-- README # 87 -rw-r--r-- makefile # 3676 -rw-r--r-- mfold.1 # 13960 -rw-r--r-- mfold.c # 2613 -rw-r--r-- mfold_doc # # ============= README ============== if test -f 'README' -a X"$1" != X"-c"; then echo 'x - skipping README (File already exists)' else echo 'x - extracting README (Text)' sed 's/^X//' << 'SHAR_EOF' > 'README' && The program mfold is a simpel folding and column making program. unpack the files from the shar file put them in a empty directory, type 'make' and you'll get the executable. A manual is included in the shar file. X A bug have been removed and some optimization have been done since the first posting to alt.sources. X A more exact documentation is in mfold_doc. X X Bug reports, ideas, or patches could be sent to; Peter Smidt smidt@cd.chalmers.se or Peter Smidt smidt@fy.chalmers.se X /Maaniker SHAR_EOF chmod 0644 README || echo 'restore of README failed' Wc_c="`wc -c < 'README'`" test 499 -eq "$Wc_c" || echo 'README: original size 499, current size' "$Wc_c" fi # ============= makefile ============== if test -f 'makefile' -a X"$1" != X"-c"; then echo 'x - skipping makefile (File already exists)' else echo 'x - extracting makefile (Text)' sed 's/^X//' << 'SHAR_EOF' > 'makefile' && mfold: mfold.o X cc mfold.o -o mfold X rm -f mfold.o X mfold.o: mfold.c X cc -c mfold.c -O SHAR_EOF chmod 0644 makefile || echo 'restore of makefile failed' Wc_c="`wc -c < 'makefile'`" test 87 -eq "$Wc_c" || echo 'makefile: original size 87, current size' "$Wc_c" fi # ============= mfold.1 ============== if test -f 'mfold.1' -a X"$1" != X"-c"; then echo 'x - skipping mfold.1 (File already exists)' else echo 'x - extracting mfold.1 (Text)' sed 's/^X//' << 'SHAR_EOF' > 'mfold.1' && .\" Public Domain 1990 of Chalmers Computer Society. .\" .\" @(#)mfold.1 (G|teborg) 1990-09-11 .\" .TH MFOLD 1 "September 11, 1990" .UC .SH NAME mfold \- Maaniker's fold and column making .SH SYNOPSIS .B mfold [ .B \-sn -ln -en -wn -f -d .B -rn .B -tn -cn -pn -n -L -Bn .B -D '<text>' -i '<text>' ] .SH DESCRIPTION .I Mfold reads text files from standard input and writes to standard output. .I Mfold concatenates and folds the text in one or more columns without breaking in the middle of a word. Tabs and newlines are converted to blank space. Multiple blank space is substituted with one single blank space. Some flags don't do anything if they aren't used together with either '-c' or '-d'. .PP There is a limited amount of options: .TP .B \-sn Start line for .I mfold, where n is the line number. The preceding text is passed through .I mfold without being changed. If an end-of-file character is encountered before line n, .I mfold will end the execution. .TP .B \-i Insert text at the beginning of every line, or with '\-c', at every column. This option as the last flag doesn't need any argument if a null argument is wanted. A space is required between the flag and the argument. Tabs may be present in the insert text. Default insert text is a null string. .TP .B \-ln Lenght for output lines, excluding any insert text and excluding any delimiter text. Where n is the number of characters. Default length is 80. .TP .B \-en .I Mfold will end the folding at input line n. Text coming after this line is not being changed by .I mfold. .TP .B \-wn Specify the width n, of the not folded lines to avoid overrunning the internal reverse buffer when using the '-d' flag. '-w' is not always provided. Run .I mfold, look at the result and decide if you want to specify the full width. Default is 80 characters. .TP .B \-f Fill each line with blank space to its full line length. .TP .B \-rn Fills the lines with extra blank space up to an amount of n blank spaces, to get an even right margin. The words will get a little random placement on the lines. If the text looks very ugly specify a little smaller n. .TP .B \-d Reverse the text for dyslexics. .TP .B \-tn Expanding the tabs to spaces. Where n is the number of spaces. Default is four spaces. Use only with '-d'. .TP .B \-cn Specifies columns where n is the number of columns. Text is inserted at every column. .TP .B \-pn Specifies page length n, meaningfull when used with the '-c' flag. Default are 40 lines per page. .TP .B \-n Many newlines in a row is not substituted with one single blank space, which is otherwise the default. Instead they are left without change, but may be put in a separate column. .TP .B \-L Write a ^L (newpage) at the end of each page. Use with '-c'. .TP .B \-Bn Write n newlines at the bottom (end) of the page. Default is one newline. Use when the number of columns are greater then one. .TP .B \-D Specify column delimiter. Default is three blank spaces. Tabs may be present in the delimiter. This option as the last flag doesn't need any argument if a null argument is wanted. .SH ERRORS You will notice them, when you give bad flags. .SH AUTHOR Peter Smidt, Chalmers Computer Society. .SH SEE ALSO awk(1), sed(1), lex(1), nroff(1), fmt(1), fold(1), rev(1) .SH BUGS If underlining is present it will get messed up with the text. The '-c' flag .I may produce some extra unnecessary blank space at the end of the lines. When a word is longer than the line length, the word may be cut at an inappropriate place. Everything except blank space, newline and tab counts as parts of words. .SH BUG REPORTS TO Peter Smidt smidt@cd.chalmers.se or .br Peter Smidt smidt@fy.chalmers.se SHAR_EOF chmod 0644 mfold.1 || echo 'restore of mfold.1 failed' Wc_c="`wc -c < 'mfold.1'`" test 3676 -eq "$Wc_c" || echo 'mfold.1: original size 3676, current size' "$Wc_c" fi # ============= mfold.c ============== if test -f 'mfold.c' -a X"$1" != X"-c"; then echo 'x - skipping mfold.c (File already exists)' else echo 'x - extracting mfold.c (Text)' sed 's/^X//' << 'SHAR_EOF' > 'mfold.c' && #include <stdio.h> #include <curses.h> X #define DEF_LINE_LEN 80 #define DEF_WORD_LEN 40 #define DEF_TAB_LEN 4 #define FULL_WIDTH 80 #define PAGE_LEN 40 #define POS1 1 #define DO_ALL1 \ X col_pos = POS1;\ X for ( doo = 0; doo < ins_len; doo++ ) {\ X putcolu(insert[doo]);\ X } #define BOT_LINES 1 #define STR 15 #define TEST_STR 25 #define GET_NUM_STR 25 X int colu_chars, colu_lines; int page_len = PAGE_LEN, columns = 1, lin = 0, bot_lines = BOT_LINES; int got_newpage = FALSE, got_dyslexi = FALSE, full_line = FULL_WIDTH; int tab_len = DEF_TAB_LEN, ins_tabs = 0, del_len, got_fill = FALSE; int got_mrandom = FALSE, got_bot = FALSE, ins_len, mrandom = 1; char **cur_page, *malloc(), *delim = " ", **glob_argv; X main(argc, argv) char *argv[]; int argc; { X int col_pos = 1, j = 0, k, in, doo, line_len = DEF_LINE_LEN, row_count = 1; X int cnt_nwl = 0, new_wo_le, dummy = TRUE, end = 2; X int width = FULL_WIDTH, err = FALSE, in_2 = 0, in_3 = 0, tmp_chars = 0; X char *cur_word, *insert = "", *s = "Bad option ' '"; X int index, start = 1, word_len = DEF_WORD_LEN; X int got_start = FALSE, got_line_len = FALSE, got_insert = FALSE; X int got_tab_len = FALSE, got_end = FALSE, got_width = FALSE; X int got_columns = FALSE, got_page_len = FALSE; X int got_newlines = FALSE, got_delim = FALSE; X int index_start = 0, index_insert = 0, index_line_len = 0; X int index_tab_len = 0, index_end = 0, index_width = 0; X int index_columns = 0, index_page_len = 0, index_delim = 0; X int index_bot = 0, index_mrandom = 0; X glob_argv = argv; X for ( index = 1; index < argc; index++) { X if ( argv[index][0] != '-' ) { X if ( index != 1 && argv[index - 1][0] == '-' ) { X if ( argv[index - 1][1] == 'i' ) { X index_insert = index; X } else if ( argv[index - 1][1] == 'D' ) { X index_delim = index; X } else { X err = TRUE; X } X } else { X err = TRUE; X } X if ( err ) { X fprintf(stderr, "Flag '%s' not allowed.\n", argv[index]); X usage(11); X } X } X doo = index_insert != index && index_delim != index; X switch ( argv[index][1] ) { X case 'i': X check_it(&got_insert, "-i", 8, doo, &index_insert, index + 1); X break; X case 's': X check_it(&got_start, "-s", 9, doo, &index_start, index); X break; X case 'l': X check_it(&got_line_len, "-l", 10, doo, &index_line_len, index); X break; X case 'e': X check_it(&got_end, "-e", 10, doo, &index_end, index); X break; X case 'w': X check_it(&got_width, "-w", 10, doo, &index_width, index); X break; X case 'r': X check_it(&got_mrandom, "-r", 37, doo, &index_mrandom, index); X break; X case 'd': X check_it(&got_dyslexi, "-d", 11, doo, &dummy, index); X break; X case 't': X check_it(&got_tab_len, "-t", 13, doo, &index_tab_len, index); X break; X case 'c': X check_it(&got_columns, "-c", 15, doo, &index_columns, index); X break; X case 'p': X check_it(&got_page_len, "-p", 16, doo, &index_page_len, index); X break; X case 'B': X check_it(&got_bot, "-B", 17, doo, &index_bot, index); X break; X case 'f': X check_it(&got_fill, "-f", 33, doo, &dummy, index); X break; X case 'n': X check_it(&got_newlines, "-n", 18, doo, &dummy, index); X break; X case 'L': X check_it(&got_newpage, "-L", 19, doo, &dummy, index); X break; X case 'D': X check_it(&got_delim, "-D", 36, doo, &index_delim, index + 1); X break; X case '\0': X write_err(doo, "Empty flag '-'", 31); X break; X default: X s[12] = argv[index][0]; X s[13] = argv[index][1]; X write_err(doo, s, 20); X break; X } X } X ext_num(got_start, &start, argv[index_start], X "Line zero, for start, not allowed", 21); X ext_num(got_page_len, &page_len, argv[index_page_len], X "Page length zero, not allowed", 24); X ext_num(got_tab_len, &tab_len, argv[index_tab_len], X "Tab length zero, not allowed", 27); X ext_num(got_line_len, &line_len, argv[index_line_len], X "Line length zero, not allowed", 25); X write_err(line_len < 2, "Too short line length, not allowed", 32); X ext_num(got_end, &end, argv[index_end], X "End length zero, not allowed", 25); X write_err(got_end && end <= start, X "End not greater than start line, not allowed", 33); X ext_num(got_width, &width, argv[index_width], X "Line length zero, not allowed", 25); X ext_num(got_mrandom, &mrandom, argv[index_mrandom], X "Zero fill length, not allowed", 36); X if ( got_bot ) get_num(&bot_lines, argv[index_bot]); X if ( got_insert ) { X if ( index_insert < argc ) { X insert = argv[index_insert]; X } else { X insert = ""; X } X } X if ( got_delim ) { X if ( index_delim < argc ) { X delim = argv[index_delim]; X } else { X delim = ""; X } X } X del_len = str_len(delim); X if ( got_columns ) { X get_num(&columns, argv[index_columns]); X write_err(columns == 0, "columns count zero, not allowed", 26); X write_err(line_len % columns, X "Lines not an even multiple of columns length", 27); X } /* colu_chars is the chars on one column. colu_lines is the total number of lines in all the columns in one page. page_len is the number of lines in one page. */ X ins_len = str_len(insert); X colu_chars = line_len / columns + ins_len; X colu_lines = page_len * columns; X write_err( !(cur_page = (char**) malloc(colu_lines * sizeof(char*))), X "Can not malloc that page length", 39); X for ( in = 0; in < colu_lines; in++ ) { X if ( !(cur_page[in] = malloc(colu_chars * sizeof(char))) ) { X write_err(TRUE, "Can not malloc that page length", 40); X } X } X for ( doo = 0; doo < ins_len; doo++ ) { X if ( insert[doo] == '\t' ) { X ins_tabs++; X } X } X full_line = line_len + ins_len * columns + del_len * ( columns - 1); X full_line += ( tab_len - 1 ) * columns * ins_tabs; X line_len = line_len / columns; X word_len = line_len; X write_err( !(cur_word = malloc(word_len * sizeof(char))), X "Can not malloc that word (line?) length", 41); X if ( width > full_line ) initrev(width); X else initrev(full_line); /* ************* Write text according to the '-s' flag **** */ X while ( row_count < start ) { X in = getchar(); X if ( in == EOF ) exit(0); X if ( in == '\n' ) { X if ( got_dyslexi ) { X flushrev(); X } X putchar('\n'); X row_count++; X } else if ( got_dyslexi ) { X putrev(in); X } else { X putchar(in); X } X } X if ( !got_end ) end = row_count + 1; X lin = ( ( start - 1 ) % page_len ) * columns; X new_wo_le = word_len - 1; /* ******************** The fold follows ******************** */ X DO_ALL1 X while ( 1 ) { X if ( row_count > end ) { X in = EOF; X } else if ( j == new_wo_le && tmp_chars == 0 ) { X in_2 = getchar(); X if ( in_2 == ' ' || in_2 == '\n' || in_2 == '\t' ) { X in = in_2; X } else { X in_3 = getchar(); X if ( in_3 == ' ' || in_3 == '\n' || in_3 == '\t' ) { X in = in_2; X tmp_chars = 1; X } else { X in = '-'; X tmp_chars = 2; X } X } X } else if ( j == word_len ) { X in = ' '; X } else if ( tmp_chars > 0 ) { X if ( tmp_chars == 1 && j == 0 ) { X in = in_3; X tmp_chars = 0; X } else if ( tmp_chars == 1 && j == 1 ) { X in_2 = in_3; X tmp_chars = 0; X if ( line_len != 2 || in_2 == ' ' || in_2 == '\n' X || in_2 == '\t' ) { X in = in_2; X } else { X in_3 = getchar(); X if ( in_3 == ' ' || in_3 == '\n' || in_3 == '\t' ) { X in = in_2; X tmp_chars = 1; X } else { X in = '-'; X tmp_chars = 2; X } X } X } else { X in = in_2; X tmp_chars = 1; X } X } else { X in = getchar(); X } X if ( in != '\n' ) { X if ( cnt_nwl > 1 && got_newlines ) { X while ( --cnt_nwl ) { X putcolu('\n'); X putcolu(' '); X } X putcolu('\n'); X DO_ALL1 X } X cnt_nwl = 0; X if ( in == '\t' ) in = ' '; X } else { X if ( got_end ) row_count++; X if ( got_newlines ) cnt_nwl++; X in = ' '; X } X if ( in == EOF ) { X putcolu('\n'); X flushpage(columns); X if ( !got_end ) exit(0); X else break; X } X if ( in != ' ' ) { X write_err( j >= word_len || j < 0 , X "Internal error or to long text word", 3); X cur_word[j++] = in; X } else { X if ( col_pos != POS1 && (col_pos + j) <= line_len && X j != 0 ) { X putcolu(' '); X col_pos++; X } else if ( (col_pos + j) > line_len && col_pos != POS1 ) { X putcolu('\n'); X DO_ALL1 X } X for ( k = 0; k < j; k++ ) { X putcolu(cur_word[k]); X } X col_pos += j; X j = 0; X } X } /* ***************** End of the fold ********************** */ /* ************* Write text according to the '-e' flag **** */ X if ( cnt_nwl > 1 && got_newlines ) { X while ( --cnt_nwl ) { X putcolu('\n'); X putcolu(' '); X } X putcolu('\n'); X flushpage(columns); X } X while ( 1 ) { X in = getchar(); X if ( in == EOF ) exit(0); X if ( in == '\n' ) { X if ( got_dyslexi ) { X flushrev(); X } X putchar('\n'); X } else if ( got_dyslexi ) { X putrev(in); X } else { X putchar(in); X } X } } X char *buff; int gl_i = 0, len; /* lin is the line index in the one long column before it is pasted out onto the page. len is the lenght of each line in the one long column. */ X putrev(c) { X int i; X X if ( gl_i >= 0 && gl_i < len ) { X if ( c != '\t' ) { X buff[gl_i++] = c; X } else { X int k = tab_len - gl_i % tab_len; X for ( i = 0; i < k; i++ ) { X putrev(' '); X } X } X } else { X write_err(TRUE, X "Internal error in reverse buffer. Specify bigger buffer", 4); X } } X flushrev() { X int i, first = 0; X X if ( buff[first] == ' ' ) while ( buff[++first] == ' ' ); X for ( i = len - 1; i >= first; i--) { X if ( buff[i] != '\0' ) { X putchar(buff[i]); X buff[i] = '\0'; X } else { X putchar(' '); X } X } X gl_i = 0; } X initrev(l) int l; { X int i; X X len = l; X write_err( !(buff = malloc(len * sizeof(char) + 1)), X "Can not malloc that internal reverse buffer length", 42); X for ( i = 0; i < len; i++ ) { X buff[i] = '\0'; X } X buff[len] = '#'; /* To help flushrev swallow blank lines */ } X check_it(got_flag, s, err, boole, index_flag, index) int *got_flag, *index_flag; char *s; { X test(*got_flag, s, err); X test_two(boole, index_flag, index, got_flag); } X test(flag, s1, err) char *s1; { X char *s2 = "Multiple ' ' not allowed"; X X s2[10] = s1[0]; X s2[11] = s1[1]; X write_err(flag, s2, err); } X test_two(boole, index_flag, index, got_flag) int *index_flag, *got_flag; { X if ( boole ) { X if ( *index_flag && glob_argv[index][2] != '\0' ) { X fprintf(stderr, "Flag '%c%c' doesn't want any argument.\n", X glob_argv[index][0], glob_argv[index][1]); X usage(35); X } X *index_flag = index; X *got_flag = TRUE; X } } X write_err(flag, s, err) char *s; { X if ( flag ) { X fprintf(stderr, "%s.\n", s); X usage(err); X } } X ext_num(bulle, tal, arg, s, err) int *tal; char *arg, *s; { X if ( bulle ) { X get_num(tal, arg); X write_err(*tal == 0, s, err); X } } X get_num(number, argv) int *number; char argv[]; { X int k, in, tmp; X char *s = "Not a number in flag ' '"; X X s[22] = argv[0]; X s[23] = argv[1]; X *number = 0; X k = str_len(argv); X write_err(k == 1, s, 9); X for( in = 2; in < k; in++) { X tmp = argv[in] - '0'; X write_err(tmp < 0 || tmp > 9, "Bad flag, N-A-P-N", 5); X *number = tmp + *number * 10; X } } X str_len(s) char *s; { X int m = 0; X X if ( s[m] != '\0' ) while ( s[++m] != '\0' ); X return m; } X usage(t) { X fprintf(stderr, "[ %d ] Usage: mfold [ -sn -ln -en -wn -f -d -rn -tn -cn -pn -n -L -Bn\n-D '<text>' -i '<text>' ]\n", t); X exit(t); } X int col = 0; X putcolu(c) char c; { X if ( c == '\n' || col == colu_chars ) { X advance_line(); X return; X } X cur_page[lin][col++] = c; } X advance_line() { X col = 0; X if ( ++lin == colu_lines ) { X flushpage(columns); X end_page(); X } } X end_page() { X int i; X X if ( columns > 1 || got_bot ) { X for ( i = 0; i < bot_lines; i++ ) { X putchar('\n'); X } X } X if ( got_newpage ) putchar(12); /* 12 == ^L (ascii) */ } X flushpage(columns) { X int line_sta = 0, cs, tmpl, lin_diff, lin_end; X int end_col = columns - 1, lin_sto = colu_lines, end_char = colu_chars - 1; X X for ( lin = 0; lin < colu_lines; lin++ ) { X if ( cur_page[lin][0] != '\0' ) { X line_sta = lin; X break; X } X } X for ( lin = line_sta; lin < colu_lines; lin += columns ) { X if ( cur_page[lin][0] == '\0' ) { X lin_sto = lin; X break; X } X } X lin_diff = (lin_sto - line_sta) / columns; X lin_end = line_sta + lin_diff; X for ( lin = line_sta; lin < lin_end; lin++) { X if ( cur_page[lin][0] != ' ' || cur_page[lin][1] != '\0' X || columns != 1 ) { X for ( cs = 0; cs < columns; cs++ ) { X tmpl = lin + lin_diff * cs; X if ( cur_page[tmpl][end_char] == '\0' && got_mrandom ) { X fill_sp(tmpl, end_char); X } X for ( col = 0; col < colu_chars; col++ ) { X if ( cur_page[tmpl][col] == '\0' ) { X if ( cs == end_col && !got_fill ) break; X if ( got_dyslexi ) putrev(' '); X else putchar(' '); X } else { X if ( got_dyslexi ) putrev(cur_page[tmpl][col]); X else putchar(cur_page[tmpl][col]); X cur_page[tmpl][col] = '\0'; X } X } X if ( cs < end_col ) { X for ( col = 0; col < del_len; col++ ) { X if ( got_dyslexi ) putrev(delim[col]); X else putchar(delim[col]); X } X } X } X if ( got_dyslexi ) flushrev(); X } X putchar('\n'); X } X lin = col = 0; } X fill_sp(line, end_char) { X int pass = 0, last, nulls = end_char, words = 0, i, found_sp = FALSE; X int found_word = FALSE, moves, new_end, old_end; X X while ( cur_page[line][--nulls] == '\0' && nulls != 1 ); X nulls = end_char - nulls; X last = end_char - nulls; X for ( i = ins_len; i <= last; i++) { X if ( cur_page[line][i] != ' ' ) { X if ( !found_word ) { X words++; X found_word = TRUE; X } X } else { X found_word = FALSE; X } X } X if ( words < 2 ) return; X old_end = last; X while ( ++pass < mrandom ) { X if ( words > nulls ) moves = nulls; X else moves = words - 1; X i = moves; X new_end = moves + old_end; X last = new_end; X while( 1 ) { X cur_page[line][new_end--] = cur_page[line][old_end--]; X if ( old_end < 0 ) break; X if ( cur_page[line][old_end] == ' ' ) { X if ( !found_sp ) { X if ( moves-- > 0 ) cur_page[line][new_end--] = ' ' ; X } X found_sp = TRUE; X } else { X found_sp = FALSE; X } X } X if ( cur_page[line][end_char] != '\0' ) return; X nulls = nulls - i; X old_end = last; X } } SHAR_EOF chmod 0644 mfold.c || echo 'restore of mfold.c failed' Wc_c="`wc -c < 'mfold.c'`" test 13960 -eq "$Wc_c" || echo 'mfold.c: original size 13960, current size' "$Wc_c" fi # ============= mfold_doc ============== if test -f 'mfold_doc' -a X"$1" != X"-c"; then echo 'x - skipping mfold_doc (File already exists)' else echo 'x - extracting mfold_doc (Text)' sed 's/^X//' << 'SHAR_EOF' > 'mfold_doc' && The documentation follows: X The program have some large main parts: X X 1) One part scans the options and their arguments from the command line. X X 2) One part reads text input which not should be changed and X writes the text to standard output. X X 3) One part does the actual folding and inserts text from X the '-i' flag. This part does also cut the words if they are too X long and puts a '-' at the end of the cut word. X X 4) One part reads input text which not should be changed after X the folding, writes to standard output. X Variables with names 'got_blabla' and 'index_blabla' refers to the different flags the programs can receive. The program don't use getopts(3) and have therefore a more rigid option format in the shell. But it's easier to handle errors this way. X The '-i' and '-D' options are handled as special cases by mfold. Remaining options are handled in one separate switch construction. X The text which is to be folded is read into an internal 'page' buffer. This buffer has the width of one column and the length of all the lines in ALL columns on one page. The buffer is named 'cur_page' and is a global variable. X The folding is done in a 'while ( 1 )' loop. The first thing done in this loop is a large 'if' statment, about 44 lines long. This 'if' stament looks if a word is larger than the line length and then cuts the word, saves some charcters in som temporary variables, 'in_2' and 'in_3'. This construction can handle 2 (two) character long lines. Then some newline handeling is done, see the '-n' option in the manual to understand the source easier. A 'if' statement look if the next charcter is a blank space or not a blank space. If it is a space, the word in 'cur_word' is written to the output, and if it's not, the character is put into 'cur_word'. When encountering an EOF, mfold exits the 'while ( 1 )' loop. X The output is not sent to standard output directly. Instead a funtion 'putcolu' is used. 'putcolu' writes to the internal page buffer 'cur_page'. When 'cur_page' is full, the function 'flush_page' writes 'cur_page to the output. But if the '-d' flag is used the output is written to 'putrev' instead, where the function 'flushrev' flushes the internal reverse script buffer, one line. When the '-r' flag is set, the function 'fill_sp' fills blank space until every line is right justified. X There is some more help functions, but they are very simple and should be understand without explanation... :-) ? X X Bug reports, ideas, or patches could be sent to; Peter Smidt smidt@cd.chalmers.se or Peter Smidt smidt@fy.chalmers.se X /Maaniker SHAR_EOF chmod 0644 mfold_doc || echo 'restore of mfold_doc failed' Wc_c="`wc -c < 'mfold_doc'`" test 2613 -eq "$Wc_c" || echo 'mfold_doc: original size 2613, current size' "$Wc_c" fi exit 0 -- +=======================================+ "The whole valley is like a smorgasbord." -- TREMORS
smidt@fy.chalmers.se (Peter Smidt) (10/11/90)
No big changes. The doc and man pages have got improved english thanks to some helpsome people. Mfold now reads input from the command line (one doesn't need to write 'mfold < my_file'). A bug (or two?) are removed. mfold (version 1.04) Submitted-by: smidt@tapioca Archive-name: mfold/part01 ---- Cut Here and feed the following to sh ---- #!/bin/sh # This is -V, a shell archive (produced by shar 3.49) # To extract the files from this archive, save it to a file, remove # everything above the "!/bin/sh" line above, and type "sh file_name". # # made 10/11/1990 06:25 UTC by smidt@tapioca # Source directory /nfs/alcazar/u/smidt/src/mfold/exp # # existing files will NOT be overwritten unless -c is specified # # This shar contains: # length mode name # ------ ---------- ------------------------------------------ # 597 -rw-r--r-- README # 87 -rw-r--r-- makefile # 3817 -rw-r--r-- mfold.1 # 14166 -rw-r--r-- mfold.c # 2727 -rw-r--r-- mfold_doc # # ============= README ============== if test -f 'README' -a X"$1" != X"-c"; then echo 'x - skipping README (File already exists)' else echo 'x - extracting README (Text)' sed 's/^X//' << 'SHAR_EOF' > 'README' && Version 1.04, last change 30 september 1990. X The program mfold is a simple folding and column making program. unpack the files from the shar file put them in a empty directory, type 'make' and you'll get the executable. A manual is included in the shar file. X A bug have been removed and some optimization have been done since the first posting to alt.sources. X Thanks to all the people who have sent typo fixes. X A more exact documentation is in mfold_doc. X X Bug reports, ideas, or patches could be sent to; Peter Smidt smidt@cd.chalmers.se or Peter Smidt smidt@fy.chalmers.se X /Maaniker SHAR_EOF chmod 0644 README || echo 'restore of README failed' Wc_c="`wc -c < 'README'`" test 597 -eq "$Wc_c" || echo 'README: original size 597, current size' "$Wc_c" fi # ============= makefile ============== if test -f 'makefile' -a X"$1" != X"-c"; then echo 'x - skipping makefile (File already exists)' else echo 'x - extracting makefile (Text)' sed 's/^X//' << 'SHAR_EOF' > 'makefile' && mfold: mfold.o X cc mfold.o -o mfold X rm -f mfold.o X mfold.o: mfold.c X cc -c mfold.c -O SHAR_EOF chmod 0644 makefile || echo 'restore of makefile failed' Wc_c="`wc -c < 'makefile'`" test 87 -eq "$Wc_c" || echo 'makefile: original size 87, current size' "$Wc_c" fi # ============= mfold.1 ============== if test -f 'mfold.1' -a X"$1" != X"-c"; then echo 'x - skipping mfold.1 (File already exists)' else echo 'x - extracting mfold.1 (Text)' sed 's/^X//' << 'SHAR_EOF' > 'mfold.1' && .\" Public Domain 1990 of Chalmers Computer Society. .\" .\" @(#)mfold.1 (G|teborg) 1990-09-11 .\" .TH MFOLD 1 "September 11, 1990" .UC .SH NAME mfold \- Maaniker's fold and column making .SH SYNOPSIS .B mfold [ .B \-sn -ln -en -wn -f -d .B -rn .B -tn -cn -pn -n -L -Bn .B -D '<text>' -i '<text>' .B file ] .SH DESCRIPTION .I Mfold reads text files from standard input and writes to standard output. A filename 'file' could be used instead of standard input. .I Mfold concatenates and folds the text in one or more columns without breaking in the middle of a word. Tabs and newlines are converted to blank space. Multiple blank space is substituted with one single blank space. Some flags don't do anything if they aren't used together with either '-c' or '-d'. .PP There is a limited amount of options: .TP .B \-sn Start line for .I mfold, where n is the line number. The preceding text is passed through .I mfold without being changed. If an end-of-file character is encountered before line n, .I mfold will end the execution. .TP .B \-i Insert text at the beginning of every line, or with '\-c', at every column. This option as the last flag doesn't need any argument if a null argument is wanted. A space is required between the flag and the argument. Tabs may be present in the insert text. Default insert text is a null string. .TP .B \-ln Length for output lines, excluding any insert text and excluding any delimiter text. Where n is the number of characters. Default length is 80. .TP .B \-en .I Mfold will end the folding at input line n. Text coming after this line is not being changed by .I mfold. .TP .B \-wn Specify the width n, of the not folded lines to avoid overrunning the internal reverse buffer when using the '-d' flag. '-w' is not always provided. Run .I mfold, look at the result and decide if you want to specify the full width. Default is 80 characters. .TP .B \-f Fill each line with blank space to its full line length. .TP .B \-rn Fill the space between the words in the lines with .br (n \- 1) extra blank spaces, until the lines get an even right margin. The words will get a little random placement on the lines. If the lines become very ugly, specify a smaller n. .TP .B \-d Reverse the text for dyslexics. .TP .B \-tn Expand the tabs to spaces, where n is the number of spaces. Default is four spaces. Use only with '-d'. .TP .B \-cn Specify columns where n is the number of columns. Text is inserted at every column. .TP .B \-pn Specify page length n. Meaningful when used with the '-c' flag. Default is 40 lines per page. .TP .B \-n Many newlines in a row is not substituted with one single blank space, which is otherwise the default. Instead they are left without change, but may be put in a separate column. .TP .B \-L Write a ^L (newpage) at the end of each page. Use with '-c'. .TP .B \-Bn Write n newlines at the bottom of each page. Default is one newline. Use when the number of columns is greater then one. .TP .B \-D Specify column delimiter. Default is three blank spaces. Tabs may be present in the delimiter. This option as the last flag doesn't need any argument if a null argument is wanted. .SH ERRORS You will notice them, when you give bad flags. .SH AUTHOR Peter Smidt, Chalmers Computer Society. .SH SEE ALSO awk(1), sed(1), lex(1), nroff(1), fmt(1), fold(1), rev(1) .SH BUGS If underlining is present it will get messed up with the text. The '-c' flag .I may produce some extra unnecessary blank space at the end of the lines. When a word is longer than the line length, the word may be cut at an inappropriate place. Everything except blank space, newline and tab counts as parts of words. .I Mfold doesn't want the input file to begin with the '-' character. .SH BUG REPORTS TO Peter Smidt smidt@cd.chalmers.se or .br Peter Smidt smidt@fy.chalmers.se SHAR_EOF chmod 0644 mfold.1 || echo 'restore of mfold.1 failed' Wc_c="`wc -c < 'mfold.1'`" test 3817 -eq "$Wc_c" || echo 'mfold.1: original size 3817, current size' "$Wc_c" fi # ============= mfold.c ============== if test -f 'mfold.c' -a X"$1" != X"-c"; then echo 'x - skipping mfold.c (File already exists)' else echo 'x - extracting mfold.c (Text)' sed 's/^X//' << 'SHAR_EOF' > 'mfold.c' && #include <stdio.h> #include <curses.h> X #define DEF_LINE_LEN 80 #define DEF_WORD_LEN 40 #define DEF_TAB_LEN 4 #define FULL_WIDTH 80 #define PAGE_LEN 40 #define POS1 1 #define DO_ALL1 \ X col_pos = POS1;\ X for ( doo = 0; doo < ins_len; doo++ ) {\ X putcolu(insert[doo]);\ X } #define BOT_LINES 1 #define STR 15 #define TEST_STR 25 #define GET_NUM_STR 25 X int colu_chars, colu_lines; int page_len = PAGE_LEN, columns = 1, lin = 0, bot_lines = BOT_LINES; int got_newpage = FALSE, got_dyslexi = FALSE, full_line = FULL_WIDTH; int tab_len = DEF_TAB_LEN, ins_tabs = 0, del_len, got_fill = FALSE; int got_mrandom = FALSE, got_bot = FALSE, ins_len, mrandom = 1; char **cur_page, *malloc(), *delim = " ", **glob_argv; X main(argc, argv) char *argv[]; int argc; { X int col_pos = 1, j = 0, k, in, doo, line_len = DEF_LINE_LEN, row_count = 1; X int cnt_nwl = 0, new_wo_le, dummy = TRUE, end = 2; X int width = FULL_WIDTH, in_2 = 0, in_3 = 0, tmp_chars = 0; X char *cur_word, *insert = "", *s = "Bad option ' '"; X int index, start = 1, word_len = DEF_WORD_LEN; X int got_start = FALSE, got_line_len = FALSE, got_insert = FALSE; X int got_tab_len = FALSE, got_end = FALSE, got_width = FALSE; X int got_columns = FALSE, got_page_len = FALSE; X int got_newlines = FALSE, got_delim = FALSE, got_file = FALSE; X int index_start = 0, index_insert = 0, index_line_len = 0; X int index_tab_len = 0, index_end = 0, index_width = 0; X int index_columns = 0, index_page_len = 0, index_delim = 0; X int index_bot = 0, index_mrandom = 0, index_file = 0; X FILE *fil = stdin; X glob_argv = argv; X for ( index = 1; index < argc; index++) { X if ( argv[index][0] != '-' ) { X if ( index == 1 || (argv[index - 1][0] == '-' && X argv[index - 1][0] != 'i' && argv[index - 1][0] != 'D' || index > 2 X && argv[index - 2][0] == '-' && (argv[index - 2][1] == 'i' X || argv[index - 2][1] == 'D')) && !got_file ) { X got_file = TRUE; X index_file = index; X } else { X fprintf(stderr, "Option '%s' not allowed.\n", argv[index]); X usage(11); X } X } X doo = index_insert != index && index_delim != index X && index_file != index; X switch ( argv[index][1] ) { X case 'i': X check_it(&got_insert, "-i", 8, doo, &index_insert, index + 1); X break; X case 's': X check_it(&got_start, "-s", 9, doo, &index_start, index); X break; X case 'l': X check_it(&got_line_len, "-l", 10, doo, &index_line_len, index); X break; X case 'e': X check_it(&got_end, "-e", 10, doo, &index_end, index); X break; X case 'w': X check_it(&got_width, "-w", 10, doo, &index_width, index); X break; X case 'r': X check_it(&got_mrandom, "-r", 37, doo, &index_mrandom, index); X break; X case 'd': X check_it(&got_dyslexi, "-d", 11, doo, &dummy, index); X break; X case 't': X check_it(&got_tab_len, "-t", 13, doo, &index_tab_len, index); X break; X case 'c': X check_it(&got_columns, "-c", 15, doo, &index_columns, index); X break; X case 'p': X check_it(&got_page_len, "-p", 16, doo, &index_page_len, index); X break; X case 'B': X check_it(&got_bot, "-B", 17, doo, &index_bot, index); X break; X case 'f': X check_it(&got_fill, "-f", 33, doo, &dummy, index); X break; X case 'n': X check_it(&got_newlines, "-n", 18, doo, &dummy, index); X break; X case 'L': X check_it(&got_newpage, "-L", 19, doo, &dummy, index); X break; X case 'D': X check_it(&got_delim, "-D", 36, doo, &index_delim, index + 1); X break; X case '\0': X write_err(doo, "Empty flag '-'", 31); X break; X default: X s[12] = argv[index][0]; X s[13] = argv[index][1]; X write_err(doo, s, 20); X break; X } X } X ext_num(got_start, &start, argv[index_start], X "Line zero, for start, not allowed", 21); X ext_num(got_page_len, &page_len, argv[index_page_len], X "Page length zero, not allowed", 24); X ext_num(got_tab_len, &tab_len, argv[index_tab_len], X "Tab length zero, not allowed", 27); X ext_num(got_line_len, &line_len, argv[index_line_len], X "Line length zero, not allowed", 25); X write_err(line_len < 2, "Too short line length, not allowed", 32); X ext_num(got_end, &end, argv[index_end], X "End length zero, not allowed", 25); X write_err(got_end && end <= start, X "End not greater than start line, not allowed", 33); X ext_num(got_width, &width, argv[index_width], X "Line length zero, not allowed", 25); X ext_num(got_mrandom, &mrandom, argv[index_mrandom], X "Zero fill length, not allowed", 36); X if ( got_bot ) get_num(&bot_lines, argv[index_bot]); X if ( got_file ) { X write_err( (fil = fopen(argv[index_file], "r")) == NULL, X "Unable to open your text file", 50); X } X if ( got_insert ) { X if ( index_insert < argc ) { X insert = argv[index_insert]; X } else { X insert = ""; X } X } X if ( got_delim ) { X if ( index_delim < argc ) { X delim = argv[index_delim]; X } else { X delim = ""; X } X } X del_len = str_len(delim); X if ( got_columns ) { X get_num(&columns, argv[index_columns]); X write_err(columns == 0, "columns count zero, not allowed", 26); X write_err(line_len % columns, X "Lines not an even multiple of columns length", 27); X } /* colu_chars is the chars on one column. colu_lines is the total number of lines in all the columns in one page. page_len is the number of lines in one page. */ X ins_len = str_len(insert); X colu_chars = line_len / columns + ins_len; X colu_lines = page_len * columns; X write_err( !(cur_page = (char**) malloc(colu_lines * sizeof(char*))), X "Can not malloc that page length", 39); X for ( in = 0; in < colu_lines; in++ ) { X if ( !(cur_page[in] = malloc(colu_chars * sizeof(char))) ) { X write_err(TRUE, "Can not malloc that page length", 40); X } X } X for ( doo = 0; doo < ins_len; doo++ ) { X if ( insert[doo] == '\t' ) { X ins_tabs++; X } X } X full_line = line_len + ins_len * columns + del_len * ( columns - 1); X full_line += ( tab_len - 1 ) * columns * ins_tabs; X line_len = line_len / columns; X word_len = line_len; X write_err( !(cur_word = malloc(word_len * sizeof(char))), X "Can not malloc that word (line?) length", 41); X if ( width > full_line ) initrev(width); X else initrev(full_line); /* ************* Write text according to the '-s' flag **** */ X while ( row_count < start ) { X in = getc(fil); X if ( in == EOF ) exit(0); X if ( in == '\n' ) { X if ( got_dyslexi ) { X flushrev(); X } X putchar('\n'); X row_count++; X } else if ( got_dyslexi ) { X putrev(in); X } else { X putchar(in); X } X } X if ( !got_end ) end = row_count + 1; X lin = ( ( start - 1 ) % page_len ) * columns; X new_wo_le = word_len - 1; /* ******************** The fold follows ******************** */ X DO_ALL1 X while ( 1 ) { X if ( row_count > end ) { X in = EOF; X } else if ( j == new_wo_le && tmp_chars == 0 ) { X in_2 = getc(fil); X if ( in_2 == ' ' || in_2 == '\n' || in_2 == '\t' ) { X in = in_2; X } else { X in_3 = getc(fil); X if ( in_3 == ' ' || in_3 == '\n' || in_3 == '\t' ) { X in = in_2; X tmp_chars = 1; X } else { X in = '-'; X tmp_chars = 2; X } X } X } else if ( j == word_len ) { X in = ' '; X } else if ( tmp_chars > 0 ) { X if ( tmp_chars == 1 && j == 0 ) { X in = in_3; X tmp_chars = 0; X } else if ( tmp_chars == 1 && j == 1 ) { X in_2 = in_3; X tmp_chars = 0; X if ( line_len != 2 || in_2 == ' ' || in_2 == '\n' X || in_2 == '\t' ) { X in = in_2; X } else { X in_3 = getc(fil); X if ( in_3 == ' ' || in_3 == '\n' || in_3 == '\t' ) { X in = in_2; X tmp_chars = 1; X } else { X in = '-'; X tmp_chars = 2; X } X } X } else { X in = in_2; X tmp_chars = 1; X } X } else { X in = getc(fil); X } X if ( in != '\n' ) { X if ( cnt_nwl > 1 && got_newlines ) { X while ( --cnt_nwl ) { X putcolu('\n'); X putcolu(' '); X } X putcolu('\n'); X DO_ALL1 X } X cnt_nwl = 0; X if ( in == '\t' ) in = ' '; X } else { X if ( got_end ) row_count++; X if ( got_newlines ) cnt_nwl++; X in = ' '; X } X if ( in == EOF ) { X putcolu('\n'); X flushpage(columns); X if ( !got_end ) exit(0); X else break; X } X if ( in != ' ' ) { X write_err( j >= word_len || j < 0 , X "Internal error or to long text word", 3); X cur_word[j++] = in; X } else { X if ( col_pos != POS1 && (col_pos + j) <= line_len && X j != 0 ) { X putcolu(' '); X col_pos++; X } else if ( (col_pos + j) > line_len && col_pos != POS1 ) { X putcolu('\n'); X DO_ALL1 X } X for ( k = 0; k < j; k++ ) { X putcolu(cur_word[k]); X } X col_pos += j; X j = 0; X } X } /* ***************** End of the fold ********************** */ /* ************* Write text according to the '-e' flag **** */ X if ( cnt_nwl > 1 && got_newlines ) { X while ( --cnt_nwl ) { X putcolu('\n'); X putcolu(' '); X } X putcolu('\n'); X flushpage(columns); X } X while ( 1 ) { X in = getc(fil); X if ( in == EOF ) exit(0); X if ( in == '\n' ) { X if ( got_dyslexi ) { X flushrev(); X } X putchar('\n'); X } else if ( got_dyslexi ) { X putrev(in); X } else { X putchar(in); X } X } } X char *buff; int gl_i = 0, len; /* lin is the line index in the one long column before it is pasted out onto the page. len is the lenght of each line in the one long column. */ X putrev(c) { X int i; X X if ( gl_i >= 0 && gl_i < len ) { X if ( c != '\t' ) { X buff[gl_i++] = c; X } else { X int k = tab_len - gl_i % tab_len; X for ( i = 0; i < k; i++ ) { X putrev(' '); X } X } X } else { X write_err(TRUE, X "Internal error in reverse buffer. Specify bigger buffer", 4); X } } X flushrev() { X int i, first = 0; X X if ( buff[first] == ' ' ) while ( buff[++first] == ' ' ); X for ( i = len - 1; i >= first; i--) { X if ( buff[i] != '\0' ) { X putchar(buff[i]); X buff[i] = '\0'; X } else { X putchar(' '); X } X } X gl_i = 0; } X initrev(l) int l; { X int i; X X len = l; X write_err( !(buff = malloc((len + 1) * sizeof(char))), X "Can not malloc that internal reverse buffer length", 42); X for ( i = 0; i < len; i++ ) { X buff[i] = '\0'; X } X buff[len] = '#'; /* To help flushrev swallow blank lines */ } X check_it(got_flag, s, err, boole, index_flag, index) int *got_flag, *index_flag; char *s; { X test(*got_flag, s, err); X test_two(boole, index_flag, index, got_flag); } X test(flag, s1, err) char *s1; { X char *s2 = "Multiple ' ' not allowed"; X X s2[10] = s1[0]; X s2[11] = s1[1]; X write_err(flag, s2, err); } X test_two(boole, index_flag, index, got_flag) int *index_flag, *got_flag; { X if ( boole ) { X if ( *index_flag && glob_argv[index][2] != '\0' ) { X fprintf(stderr, "Flag '%c%c' doesn't want any argument.\n", X glob_argv[index][0], glob_argv[index][1]); X usage(35); X } X *index_flag = index; X *got_flag = TRUE; X } } X write_err(flag, s, err) char *s; { X if ( flag ) { X fprintf(stderr, "%s.\n", s); X usage(err); X } } X ext_num(bulle, tal, arg, s, err) int *tal; char *arg, *s; { X if ( bulle ) { X get_num(tal, arg); X write_err(*tal == 0, s, err); X } } X get_num(number, argv) int *number; char argv[]; { X int k, in, tmp; X char *s = "Not a number in flag ' '"; X X s[22] = argv[0]; X s[23] = argv[1]; X *number = 0; X k = str_len(argv); X write_err(k == 1, s, 9); X for( in = 2; in < k; in++) { X tmp = argv[in] - '0'; X write_err(tmp < 0 || tmp > 9, "Bad flag, N-A-P-N", 5); X *number = tmp + *number * 10; X } } X str_len(s) char *s; { X int m = 0; X X if ( s[m] != '\0' ) while ( s[++m] != '\0' ); X return m; } X usage(t) { 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); X exit(t); } X int col = 0; X putcolu(c) char c; { X if ( c == '\n' || col == colu_chars ) { X advance_line(); X return; X } X cur_page[lin][col++] = c; } X advance_line() { X col = 0; X if ( ++lin == colu_lines ) { X flushpage(columns); X end_page(); X } } X end_page() { X int i; X X if ( columns > 1 || got_bot ) { X for ( i = 0; i < bot_lines; i++ ) { X putchar('\n'); X } X } X if ( got_newpage ) putchar(12); /* 12 == ^L (ascii) */ } X flushpage(columns) { X int line_sta = 0, cs, tmpl, lin_diff, lin_end; X int end_col = columns - 1, lin_sto = colu_lines, end_char = colu_chars - 1; X X for ( lin = 0; lin < colu_lines; lin++ ) { X if ( cur_page[lin][0] != '\0' ) { X line_sta = lin; X break; X } X } X for ( lin = line_sta; lin < colu_lines; lin += columns ) { X if ( cur_page[lin][0] == '\0' ) { X lin_sto = lin; X break; X } X } X lin_diff = (lin_sto - line_sta) / columns; X lin_end = line_sta + lin_diff; X for ( lin = line_sta; lin < lin_end; lin++) { X if ( cur_page[lin][0] != ' ' || cur_page[lin][1] != '\0' X || columns != 1 ) { X for ( cs = 0; cs < columns; cs++ ) { X tmpl = lin + lin_diff * cs; X if ( cur_page[tmpl][end_char] == '\0' && got_mrandom ) { X fill_sp(tmpl, end_char); X } X for ( col = 0; col < colu_chars; col++ ) { X if ( cur_page[tmpl][col] == '\0' ) { X if ( cs == end_col && !got_fill ) break; X if ( got_dyslexi ) putrev(' '); X else putchar(' '); X } else { X if ( got_dyslexi ) putrev(cur_page[tmpl][col]); X else putchar(cur_page[tmpl][col]); X cur_page[tmpl][col] = '\0'; X } X } X if ( cs < end_col ) { X for ( col = 0; col < del_len; col++ ) { X if ( got_dyslexi ) putrev(delim[col]); X else putchar(delim[col]); X } X } X } X if ( got_dyslexi ) flushrev(); X } X putchar('\n'); X } X lin = col = 0; } X fill_sp(line, end_char) { X int pass = 0, last, nulls = end_char, words = 0, i, found_sp = FALSE; X int found_word = FALSE, moves, new_end, old_end; X X while ( cur_page[line][--nulls] == '\0' && nulls != 1 ); X nulls = end_char - nulls; X last = end_char - nulls; X for ( i = ins_len; i <= last; i++) { X if ( cur_page[line][i] != ' ' ) { X if ( !found_word ) { X words++; X found_word = TRUE; X } X } else { X found_word = FALSE; X } X } X if ( words < 2 ) return; X old_end = last; X while ( ++pass < mrandom ) { X if ( words > nulls ) moves = nulls; X else moves = words - 1; X i = moves; X new_end = moves + old_end; X last = new_end; X while( 1 ) { X cur_page[line][new_end--] = cur_page[line][old_end--]; X if ( old_end < 0 ) break; X if ( cur_page[line][old_end] == ' ' ) { X if ( !found_sp ) { X if ( moves-- > 0 ) cur_page[line][new_end--] = ' ' ; X } X found_sp = TRUE; X } else { X found_sp = FALSE; X } X } X if ( cur_page[line][end_char] != '\0' ) return; X nulls = nulls - i; X old_end = last; X } } SHAR_EOF chmod 0644 mfold.c || echo 'restore of mfold.c failed' Wc_c="`wc -c < 'mfold.c'`" test 14166 -eq "$Wc_c" || echo 'mfold.c: original size 14166, current size' "$Wc_c" fi # ============= mfold_doc ============== if test -f 'mfold_doc' -a X"$1" != X"-c"; then echo 'x - skipping mfold_doc (File already exists)' else echo 'x - extracting mfold_doc (Text)' sed 's/^X//' << 'SHAR_EOF' > 'mfold_doc' && The documentation follows: X The program has some large main parts: X X 1) One part scans the options and their arguments from the command line. X X 2) One part reads text input which not should be changed before X the folding and writes the text to standard output. X X 3) One part does the actual folding and inserts text from X the '-i' flag. This part also cuts the words if they are too X long and puts a '-' at the end of the cut word. X X 4) One part reads input text which not should be changed after X the folding, and writes the text to standard output. X Variables with names 'got_blabla' and 'index_blabla' refer to the different flags the program can receive. The program doesn't use getopts(3) and therefore has a more rigid option format in the shell. But it's easier to handle errors this way. X The '-i' and '-D' options are handled as special cases by mfold. Any input file is also handled as a special case by mfold. Remaining options are handled in one separate switch construct. X The text which is to be folded is read into an internal two dimensional 'page' buffer. This buffer has the width of one column and the length of all the lines in ALL columns on one page. The buffer is named 'cur_page' and is a global variable. X The folding is done in a 'while ( 1 )' loop. The first thing done in this loop is a large 'if' statement, about 44 lines long. This 'if' statement checks if a word is larger than the line length and then cuts the word, saves some characters in some temporary variables, named 'in_2' and 'in_3'. This construction can handle 2 (two) character long lines. Then some newline handling is done, see the '-n' option in the manual to understand the source easier. An 'if' statement checks if the next character is a blank space or not a blank space. If it is a space, the word in 'cur_word' is written to the output, and if it's not, the character is put into 'cur_word'. When encountering an EOF, mfold exits the 'while ( 1 )' loop. X The output is not sent to standard output directly. Instead a function 'putcolu' is used. 'putcolu' writes to the internal page buffer 'cur_page'. When 'cur_page' is full, the function 'flush_page' writes 'cur_page to the output. But if the '-d' flag is used the output is written to 'putrev' instead, where the function 'flushrev' flushes the internal reverse script one line buffer. When the '-r' flag is set, the function 'fill_sp' fills blank space until every line is right justified. X There are some more help functions, but they are very simple and should be understood without explanation... :-) ? X X Bug reports, ideas, or patches could be sent to; Peter Smidt smidt@cd.chalmers.se or Peter Smidt smidt@fy.chalmers.se X /Maaniker SHAR_EOF chmod 0644 mfold_doc || echo 'restore of mfold_doc failed' Wc_c="`wc -c < 'mfold_doc'`" test 2727 -eq "$Wc_c" || echo 'mfold_doc: original size 2727, current size' "$Wc_c" fi exit 0 -- +=======================================+ "The whole valley is like a smorgasbord." -- TREMORS