diff options
-rw-r--r-- | badroff.c | 96 |
1 files changed, 59 insertions, 37 deletions
@@ -26,22 +26,41 @@ char* chrmult(char c, size_t ct){ FILE* in; buf* inbuf; +int addchr(void){ + int c = fgetc(in); + if (c != EOF) inschrbuf(inbuf, c); + return c; +} + size_t fillbuf(size_t len){ // returns real len int c; size_t set; - for (set = buflen(inbuf); set < len && (c = fgetc(in)) != EOF;set++) - inschrbuf(inbuf, c); + for (set = buflen(inbuf); set < len && (c = addchr()) != EOF;set++); return set; } size_t chrfill(char chr){ - size_t line; size_t len = buflen(inbuf); char* str = peekstrbuf(inbuf, 0, len); + size_t line; for (line = 0; line < len; line++) if (str[line] == chr) return line+1; - for (int c = 0; c != chr && (c = fgetc(in)) != EOF; line++) - inschrbuf(inbuf, c); + for (int c = 0; c != chr && (c = addchr()) != EOF; line++); + return line; +} + +#define min(a,b) a < b ? a : b + +size_t chrnfill(char chr, size_t sz){//fills to first of chr or sz + size_t len = buflen(inbuf); + size_t lim = min(len,sz); + char* str = peekstrbuf(inbuf, 0, lim); + size_t line; + for (line = 0; line < lim; line++) + if (str[line] == chr) return line+1; + free(str); + for (int c = 0; c != chr && (c = addchr()) != EOF + && line<sz; line++); return line; } @@ -53,10 +72,11 @@ char* center(char* txt){ size_t len = strlen(txt); int max = width/2 + len/2; // excluding terminator int min = max-len+1; // first index of *txt - char* str = malloc(sizeof(char)*(max + 1)); + char* str = malloc(sizeof(char)*(max + 2)); memset(str, ' ', min); memcpy(str+min, txt, len); - str[max] = 0; + str[max] = '\n'; + str[max+1] = 0; return str; } char* setwidth(char* txt){ @@ -79,44 +99,46 @@ char* cmd(void){ high = mid - 1; else if (cmp > 0) low = mid + 1; - else return call[mid](dat+strlen(mval)); + else + return call[mid](dat+strlen(mval)); } + free(dat); return NULL; } // normal typesetting -char* cleanup(char* line){ // cleans up trailing whitespace && ^\n$ - for (ws = len-1; line[ws] == ' '; ws--, len--); // rethink - if (ws < len-1){ - line[ws] = '\n' - line[ws+1] = '\0'; - } else if (line[len-1] != '\n'){ - len++; - line = realloc(line, len); - } - if (line[len-1] != '\n'){ - line[len-1] = '\n'; - line[len] = '\0'; - } - return line; -} +bool cont_typst = false; // communicates with line() for broken lines. -char* fold(char* line){ // inserts \n to limit line length - +size_t nextws(size_t start){//searches for \n or [^ \n]-1 in buffer + //starts at `start` (if not whitespace, returns start-1) + size_t len = buflen(inbuf); + char* str = peekstrbuf(inbuf, start, len-start); + size_t i; + for (i = 0; i<len-start; i++){ + if (str[i] == '\n') return start+i; + if (str[i] != ' ') return start+i-1; + } + free(str); + for (int c = 0; c != '\n' && ( c = addchr() ) != EOF && c == ' '; + len++); // if this is a newline, exit late (len is last, !(len-1)). + return len; } -char* typeset(void){ - size_t len; size_t nl; - for (nl = 0; (len = chrfill('\n')) == 1; nl++) - popstrbuf(inbuf, len); - if (nl) return chrmult('\n', nl+1); - char* line = popstrbuf(inbuf, len); - size_t ws; - line = cleanup(line); - if (brk && line[len-1] == '\n') line[len-1] = ' '; - if (brk) for (; *line == ' '; line++); //remove preceding whitespace - return fold(line); +char* typeset(void){ // brk is completely unimplemented + size_t len = chrnfill('\n', width+1); //+1 for \n on 81-char lines + char* next = peekstrbuf(inbuf, 0, len); + size_t wsend = 0; + if (next[--len] == '\n') wsend = len; + if (next[len] == ' ') wsend = nextws(len); + for (; next[len] == ' ' && wsend; len--){ + if (!wsend && next[len] == ' ') wsend = len; + } // len should be last letter + if (peekchrbuf(inbuf, wsend) == '\n') cont_typst = false; + else cont_typst = true; + free(next); + char* ln = popstrbuf(inbuf, wsend+1); ln[len] = '\n'; ln[len+1] = 0; + return ln; } // a parser to choose when to typeset and when to run a command @@ -126,7 +148,7 @@ char* line(void){ if ( (sz = fillbuf(2)) == 0) return ""; char* twobytes = peekstrbuf(inbuf, 0, 2); // .., .\n, or ^.? - if (sz == 1 || twobytes[1] == '\n') return typeset(); + if (sz == 1 || twobytes[1] == '\n' || cont_typst) return typeset(); if (twobytes[0] == '.') popchrbuf(inbuf); if (twobytes[0] == '.' && twobytes[1] != '.'){ char* data = cmd(); |