From 118995a315863961f7b3a8a4509f06279b039b75 Mon Sep 17 00:00:00 2001 From: Holden Rohrer Date: Wed, 13 May 2020 16:04:07 -0400 Subject: added badroff nbsp and merge --- badroff.c | 84 ++++++++++++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 70 insertions(+), 14 deletions(-) diff --git a/badroff.c b/badroff.c index a1255d9..6a630ed 100644 --- a/badroff.c +++ b/badroff.c @@ -67,6 +67,7 @@ size_t chrnfill(char chr, size_t sz){//fills to first of chr or sz // typesetting config and commands to change. int width = 80; +char nbsp = 0; char* center(char* txt){ size_t len = strlen(txt); @@ -103,7 +104,7 @@ char* leader(char* txt){ fin[i] = repeat[i % rptln]; return fin; } -bool endlineset = false; +bool endgroup = false; llnode* freenext(llnode* node){ llnode* tmp = node->next; node->next = tmp->next; @@ -125,7 +126,6 @@ void multbreak(sb* buffer, size_t start, } else { char tmp = str[len]; str[len] = 0; // truncate str at max length - //printf("string %s\n",str); insstr(buffer, str); // insert that insstr(buffer, "\n"); str[len] = tmp; // restore string @@ -138,14 +138,14 @@ llnode* accumlines(size_t* ct){ // returns tail of linked list (*ct) = 0; while (true){ tail->next = appendll(tail, line()); - if (endlineset) break; + if (endgroup) break; (*ct)++; tail = tail->next; } free(tail->next->str); free(tail->next); //.ELS cmd tail->next = head->next; // loop linked list free(head); - endlineset = false; // prevents false positive on next run + endgroup = false; // prevents false positive on next run return tail; } char* lineset(char* txt){ @@ -173,7 +173,6 @@ char* lineset(char* txt){ tail = tail->next; } while (tail != orig); if (valid) brk = i; - //printf("brk %d\n",brk); if (done || (!valid && i-oldbrk >= width)){ // either all strings are done // or it has hit a non-space column and accum enough space @@ -185,20 +184,61 @@ char* lineset(char* txt){ char* lines = decompose(buf); return lines; } -char* finlineset(char* txt){ +char* emptalloc(void){ // need a null string so it can be freed later char* str = malloc(sizeof(char)); str[0] = 0; - endlineset = true; return str; } +char* fingroup(char* txt){ + endgroup = true; + return emptalloc(); +} char* vert(char* txt){ int ln; sscanf(txt, "%d", &ln); return chrmult('\n', ln); } +char* nbrkspc(char* txt){ + if (txt[0] == '\n') txt[0] = 0; + if (txt[1] == '\n') txt[1] = 0; + if (txt[0] != 0 && txt[1] != 0) + nbsp = txt[1]; + else if (txt[0] != 0) + nbsp = txt[0]; + else + nbsp = 0; + return NULL; +} +char* merge(char* txt){ // merges until an endgroup + // gather lines + size_t ct; + llnode* head = accumlines(&ct)->next; + // count total length (for malloc) + size_t len = 0; + for (size_t i = 0; i < ct; i++, head = head->next){ + size_t slen = strlen(head->str)-1; + head->str[slen] = 0; // remove the nl character at the end + len += slen; // add the (new) length of string + } + char *str, *pos; + pos = str = malloc(sizeof(char)*(len+2)); + str[len] = '\n'; str[len+1] = 0; // str = "***********\n" + for (size_t i = 0; i < ct; i++){ + wsclean(head->str); + size_t slen = strlen(head->str); + memcpy(pos, head->str, slen); + pos += slen; + llnode* tmp = head; + head = head->next; + free(tmp->str); + free(tmp); + } + return str; +} char* cmds[] = // MUST be sorted alphabetically - {"CT ", "ELS", "FIL ", "LD ", "LS", "V ", "W "}; + {"CT ", "EG", "FIL ", "LD ", "LS", "MRG", "NBSP", "V ", "W "}; char* (*call[])(char* txt) = - {center, finlineset, fillline, leader, lineset, vert, setwidth}; + {center, fingroup, fillline, leader, lineset, merge, nbrkspc, + vert, setwidth}; char* cmd(void){ char* dat = popstrbuf(inbuf, chrfill('\n')); @@ -237,22 +277,29 @@ void wsclean(char* txt){ txt[i-disp] = txt[i]; } } +#define nbspchr (char) 255 +void nbspclean(char* txt){ + for (; *txt != 0; txt++){ + if (*txt == nbspchr) *txt = ' '; + } +} char* wordset(char* txt){ char* orig = txt; // txt will be manipulated - size_t ws = width; + size_t ws = 0; // zero means do not cut for (size_t i=0; txt[i] != 0; i++){ // turn into a nested loop if (txt[i] == ' ' || txt[i] == '\n') ws = i; // nl's (multiline input) and spaces are proper linebreaks - if (txt[i] == '\n' || (i >= width && ws != i) ){ + if (txt[i] == '\n' || (ws && i >= width && ws != i) ){ txt += ws; txt[0] = '\n'; - ws = width; + ws = 0; i = 0; } } wsclean(orig); // remove trailing whitespace + nbspclean(orig); return orig; } @@ -264,6 +311,12 @@ char* norm(void){ // a parser to choose when to typeset and when to run a command +void nbspsub(char* txt){ + for (; (*txt) != 0; txt++){ + if (*txt == nbsp) *txt = nbspchr; + } +} + char* line(void){ size_t sz; if ( (sz = fillbuf(2)) == 0) @@ -271,13 +324,16 @@ char* line(void){ char* twobytes = peekstrbuf(inbuf, 0, 2); // .., .\n, or ^.? if (sz == 1 || twobytes[1] == '\n') return norm(); if (twobytes[0] == '.') popchrbuf(inbuf); + char* out; if (twobytes[0] == '.' && twobytes[1] != '.'){ char* data = cmd(); if (data) return data; - return line(); + out = line(); } else { - return norm(); + out = norm(); } + nbspsub(out); + return out; } // orchestration -- cgit