aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--badroff.c96
1 files changed, 59 insertions, 37 deletions
diff --git a/badroff.c b/badroff.c
index ed84760..c2c6515 100644
--- a/badroff.c
+++ b/badroff.c
@@ -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();