int join = 1; /* can input lines be joined? */
int indent = 0; /* how many spaces to indent */
int tindent = 0; /* temporary extra indent */
int length = 70; /* how many columns per output line */
int maxtab = 8;
Biobuf bin;
Biobuf bout;
int col = 0; /* output column number */
int bol = 1; /* at beginning of output line? */
int punct = 0; /* last character out was punctuation? */
int newline = 1; /* last char read was newline */
int nspace = 0; /* number of spaces beginning this line */
void
outchar(Rune c)
{
switch(c){
case '\0':
break;
case '\n':
switch(newline){
case 0:
if(join)
outword();
else
flush();
break;
case 1:
flush();
case 2:
tindent = 0;
Bputc(&bout, '\n');
wp = 0;
}
newline = 1;
break;
case ' ':
case '\t':
switch(newline) {
case 0:
outword();
break;
case 1:
nspace = addspace(nspace, c);
outword();
break;
}
break;
default:
if(nspace > 0){
if(!newline && tindent != nspace){
nextline();
newline = 1;
}
tindent = nspace;
nspace = 0;
}else
if(newline){
if(tindent)
nextline();
tindent = 0;
}
addrune(c);
newline = 0;
}
}
void
addrune(Rune c)
{
if(wp==mword) {
if(mword == 0)
mword = 10;
else
mword *= 2;
word = realloc(word, sizeof(Rune)*mword);
if(word == nil) {
fprint(2, "fmt: out of memory\n");
exits("out of memory");
}
}
word[wp++] = c;
}
void
outword(void)
{
int i;
if(wp == 0)
return;
if(wp+col+(bol?0:punct?2:1) > length){
Bputc(&bout, '\n');
col = 0;
bol = 1;
}
if(col == 0){
for(i=0; i+maxtab <= indent+tindent; i+=maxtab)
Bputc(&bout, '\t');
while(i++ < indent+tindent)
Bputc(&bout, ' ');
col = indent+tindent;
}
if(bol)
bol = 0;
else{
if(punct){
Bputc(&bout, ' ');
col++;
}
Bputc(&bout, ' ');
col++;
}
puncttest();
for (i = 0; i < wp; i++)
Bputrune(&bout, word[i]);
col += i;
wp = 0;
}
/* is the word followed by major punctuation, .?:! */
/* disregard short things followed by periods; they are probably
initials or titles like Mrs. and Dr. */
void
puncttest(void)
{
int rp;
punct = 0;
for(rp=wp; --rp>=0; ) {
switch(word[rp]) {
case ')': case '\'': case '"':
continue;
case '.':
if(isupper(*word)&&rp<=3)
return;
case '?': case '!': /*case ':':*/
punct = 1;
default:
return;
}
}
}
void
nextline(void)
{
Bputc(&bout, '\n');
col = 0;
bol = 1;
}
void
flush(void)
{
outword();
if(col != 0)
nextline();
}