diff options
Diffstat (limited to 'badroff.c')
-rw-r--r-- | badroff.c | 110 |
1 files changed, 77 insertions, 33 deletions
@@ -1,19 +1,16 @@ #include <stdio.h> #include <string.h> #include <stdlib.h> +#include <stdbool.h> #include "buf.h" +#include "sb.h" #include "ll.h" char* line(void); char* wordset(char* txt); void wsclean(char* txt); -typedef enum { - false, - true -} bool; - FILE* getfile(int argc, char** argv){ if (argc >= 2) return fopen(argv[1], "r"); @@ -107,38 +104,85 @@ char* leader(char* txt){ return fin; } bool endlineset = false; -char* lineset(char* txt){ +llnode* freenext(llnode* node){ + llnode* tmp = node->next; + node->next = tmp->next; + free(tmp->str); + free(tmp); + if (tmp == node) return NULL; + return node->next; +} +void multbreak(sb* buffer, size_t start, + size_t len, llnode** tail, size_t* ct){ + for (size_t i = *ct; i > 0; i--){ + char* str = (*tail)->next->str + start; + // tail->next is used so it can be gracefully freed + if (strlen(str) < len){ // if node is smaller than len, + insstr(buffer, str); // put the whole thing in the buffer + // and remove the node, switching to next + *tail = freenext(*tail); + (*ct)--; + } 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 + *tail = (*tail)->next; // iter + } + } +} +llnode* accumlines(size_t* ct){ // returns tail of linked list llnode *head, *tail; head = tail = appendll(NULL, NULL); - size_t ct, len; ct = len = 0; + (*ct) = 0; while (true){ tail->next = appendll(tail, line()); if (endlineset) break; + (*ct)++; tail = tail->next; - ct++; - len += strlen(tail->str); } free(tail->next->str); free(tail->next); //.ELS cmd - tail = tail->next = head->next; // loop linked list + tail->next = head->next; // loop linked list free(head); + endlineset = false; // prevents false positive on next run + return tail; +} +char* lineset(char* txt){ + size_t ct; + llnode* tail = accumlines(&ct); + sb* buf = newsb(100); - char *lines, *pos; - lines = malloc((sizeof(char)*(len+1))); - // construct lines - int jmp; - for (pos = lines; pos-lines < len; pos += jmp, tail = tail->next){ - char* str = tail->str + tail->loc; - char* loc = memchr(str, '\n', strlen(str)); - jmp = (loc == NULL) ? 0 : loc-str+1; - memcpy(pos, str, jmp); - tail->loc += jmp; + size_t oldbrk = 0, brk = 0; + for (size_t i = 0; tail; i++){ // check every column until all rows + // are removed. + bool valid = true; // if stays true, this is a space + bool done = true; // if stays true, all strings are complete + llnode* orig = tail; + do { // check every string + if (tail->end) goto iter; + if (tail->str[i] == 0){ + tail->end = true; + goto iter; + } // ignore strings that have already finished + done = false; + if (tail->str[i] != ' ') + valid = false; + // doesn't break because tail needs to return to orig + iter: + 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 + multbreak(buf, oldbrk, brk-oldbrk+1, &tail, &ct); + oldbrk = brk+1; // tells offset from previous cut + } } - llnode* last = NULL; - /*for (size_t i = 0; i<=ct; i++, last = tail, tail = tail->next){ - free(tail->str); - free(last); - }*/ - endlineset = false; - wsclean(lines); + + char* lines = decompose(buf); return lines; } char* finlineset(char* txt){ @@ -182,7 +226,7 @@ char* cmd(void){ void wsclean(char* txt){ size_t disp = 0; - int firstws; + size_t firstws = 0; for (size_t i = 0; i == 0 || txt[i-1] != 0; i++){ if ( (txt[i] == ' ' || txt[i] == '\n') && txt[i-1] != ' '){ firstws = i; @@ -195,11 +239,12 @@ void wsclean(char* txt){ } char* wordset(char* txt){ - char* orig = txt; + char* orig = txt; // txt will be manipulated size_t ws = width; for (size_t i=0; txt[i] != 0; i++){ // turn into a nested loop - if (txt[i] == ' ') ws = i; - if (i >= width && ws != i){ + 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) ){ txt += ws; txt[0] = '\n'; ws = width; @@ -207,7 +252,7 @@ char* wordset(char* txt){ } } - wsclean(orig); + wsclean(orig); // remove trailing whitespace return orig; } @@ -238,7 +283,6 @@ char* line(void){ // orchestration int main(int argc, char** argv){ - int c; in = getfile(argc, argv); inbuf = newbuf(256); if (in == NULL){ |