This is uformat.c in view mode; [Download] [Up]
/* User text formatting functions
Copyright (C) 1992 Joseph H. Allen
This file is part of JOE (Joe's Own Editor)
JOE is free software; you can redistribute it and/or modify it under the
terms of the GNU General Public License as published by the Free Software
Foundation; either version 1, or (at your option) any later version.
JOE is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
details.
You should have received a copy of the GNU General Public License along with
JOE; see the file COPYING. If not, write to the Free Software Foundation,
675 Mass Ave, Cambridge, MA 02139, USA. */
#include "config.h"
#include "b.h"
#include "bw.h"
#include "zstr.h"
#include "ublock.h"
#include "uformat.h"
/* Center line cursor is on and move cursor to beginning of next line */
int ucenter(bw)
BW *bw;
{
P *p=bw->cursor, *q;
long endcol, begcol, x;
int c;
peol(p);
while(cwhite(c=prgetc(p)));
if(c=='\n') { pgetc(p); goto done; }
if(c==MAXINT) goto done;
pgetc(p); endcol=piscol(p);
pbol(p);
while(cwhite(c=pgetc(p)));
if(c=='\n') { prgetc(p); goto done; }
if(c==MAXINT) goto done;
prgetc(p); begcol=piscol(p);
if(endcol-begcol>bw->o.rmargin+bw->o.lmargin) goto done;
q=pdup(p); pbol(q); bdel(q,p); prm(q);
for(x=0;x!=(bw->o.lmargin+bw->o.rmargin)/2-(endcol-begcol)/2;++x) binsc(p,' ');
done:
if(!pnextl(p))
{
binsc(p,'\n');
pgetc(p);
return -1;
}
else return 0;
}
/* Return true if c is a character which can indent a paragraph */
int cpara(c)
{
if(c==' ' || c=='\t' || c=='\\' ||
c=='>' || c=='|' || c==':' || c=='*' || c=='/' || c==',' || c=='.' ||
c=='?' || c==';' || c==']' || c=='}' || c=='=' || c=='+' || c=='-' ||
c=='_' || c==')' || c=='&' || c=='^' || c=='%' || c=='$' || c=='#' ||
c=='@' || c=='!' || c=='~')
return 1;
else
return 0;
}
/* Return true if line is definitly not a paragraph line.
* Lines which arn't paragraph lines:
* 1) Blank lines
* 2) Lines which begin with '.'
*/
int pisnpara(p)
P *p;
{
P *q;
int c;
q=pdup(p);
pbol(q);
while(cpara(c=pgetc(q)));
prm(q);
if(c=='.' || c=='\r' || c=='\n') return 1;
else return 0;
}
/* Determine amount of indentation on current line */
long nindent(p)
P *p;
{
P *q=pdup(p);
long col;
pbol(q);
do col=q->col; while(cpara(pgetc(q)));
prm(q);
return col;
}
/* Get indentation prefix column */
long prefix(p)
P *p;
{
long len;
P *q=pdup(p);
pbol(q);
while(cpara(brc(q))) pgetc(q);
while(!pisbol(q))
if(!cwhite(prgetc(q)))
{
pgetc(q);
break;
}
len=q->col;
prm(q);
return len;
}
/* Move pointer to beginning of paragraph
*
* This function simply moves backwards until it sees:
* 0) The beginning of the file
* 1) A blank line
* 2) A line with a different indentation prefix
* 3) A line with indentation greater than that of the line we started with
* 4) A line with indentation less than that of the starting line, but with
* a blank line (or beginning of file) preceeding it.
*/
int within=0;
P *pbop(p)
P *p;
{
long indent;
long prelen;
pbol(p); indent=nindent(p); prelen=prefix(p);
while(!pisbof(p) && (!within || !markb || p->byte>markb->byte))
{
long ind;
long len;
pprevl(p); pbol(p); ind=nindent(p); len=prefix(p);
if(pisnpara(p) || len!=prelen) { pnextl(p); break; }
if(ind>indent) break;
if(ind<indent)
{
if(pisbof(p)) break;
pprevl(p); pbol(p);
if(pisnpara(p)) { pnextl(p); break; }
else { pnextl(p); pnextl(p); break; }
}
}
return p;
}
/* Move pointer to end of paragraph. Pointer must already be on first
* line of paragraph for this to work correctly.
*
* This function moves forwards until it sees:
* 0) The end of the file.
* 1) A blank line
* 2) A line with indentation different from the second line of the paragraph
* 3) A line with prefix column different from first line
*/
P *peop(p)
P *p;
{
long indent;
long prelen;
if(!pnextl(p) || pisnpara(p) ||
(within && markk && p->byte>=markk->byte)) return p;
indent=nindent(p);
prelen=prefix(p);
while(pnextl(p) && (!within || !markk || p->byte<markk->byte))
{
long ind=nindent(p);
long len=prefix(p);
if(ind!=indent || len!=prelen || pisnpara(p)) break;
}
return p;
}
/* Motion commands */
int ubop(bw)
BW *bw;
{
P *q=pdup(bw->cursor);
up: while(pisnpara(q) && !pisbof(q) &&
(!within || !markb || q->byte>markb->byte)) pprevl(q);
pbop(q);
if(q->byte!=bw->cursor->byte)
{
pset(bw->cursor,q);
prm(q);
return 0;
}
else if(!pisbof(q))
{
prgetc(q);
goto up;
}
else
{
prm(q);
return -1;
}
}
int ueop(bw)
BW *bw;
{
P *q=pdup(bw->cursor);
up: while(pisnpara(q) && !piseof(q)) pnextl(q);
pbop(q); peop(q);
if(q->byte!=bw->cursor->byte)
{
pset(bw->cursor,q);
prm(q);
return 0;
}
else if(!piseof(q))
{
pnextl(q);
goto up;
}
else
{
prm(q);
return -1;
}
}
/* Wrap word. If 'french' is set, only one space will be placed
* after . ? or !
*/
void wrapword(p,indent,french,indents)
P *p;
long indent;
char *indents;
{
P *q;
int rmf=0;
int c;
long to=p->byte;
/* Get indentation prefix from beginning of line */
if(!indents)
{
int f=0;
P *r=pdup(p);
pbol(r);
q=pdup(r);
while(cpara(c=brc(q)))
{
if(!cwhite(c)) f=1;
pgetc(q);
}
if(f)
{
indents=brs(r,q->byte-r->byte); rmf=1;
if(indents[0]=='/' && indents[1]=='*') indents[0]=' ';
}
prm(r); prm(q);
}
/* Get to beginning of word */
while(!pisbol(p) && piscol(p)>indent && !cwhite(prgetc(p)));
/* If we found the beginning of a word... */
if(!pisbol(p) && piscol(p)>indent)
{
/* Move q to two (or one if 'french' is set) spaces after end of previous
word */
q=pdup(p);
while(!pisbol(q))
if(!cwhite(c=prgetc(q)))
{
pgetc(q);
if((c=='.'||c=='?'||c=='!') && q->byte!=p->byte && !french) pgetc(q);
break;
}
pgetc(p);
/* Delete space between start of word and end of previous word */
to-=p->byte-q->byte;
bdel(q,p);
prm(q);
/* Move word to beginning of next line */
binsc(p,'\n'), ++to;
#ifdef __MSDOS__
++to;
#endif
pgetc(p);
/* Indent to left margin */
if(indents) binss(p,indents), to+=zlen(indents);
else while(indent--) binsc(p,' '), ++to;
if(rmf) free(indents);
}
/* Move cursor back to original position */
pfwrd(p,to-p->byte);
}
/* Reformat paragraph */
int uformat(bw)
BW *bw;
{
long indent;
char *indents;
char *buf, *b;
int len;
long curoff;
int c;
P *p, *q;
p=pdup(bw->cursor); pbol(p);
/* Do nothing if we're not on a paragraph line */
if(pisnpara(p))
{
prm(p);
return 0;
}
/* Move p to beginning of paragraph, bw->cursor to end of paragraph and
* set curoff to original cursor offset within the paragraph */
pbop(p);
curoff=bw->cursor->byte-p->byte;
pset(bw->cursor,p); peop(bw->cursor);
/* Insure that paragraph ends on a beginning of a line */
if(!pisbol(bw->cursor)) binsc(bw->cursor,'\n'), pgetc(bw->cursor);
/* Record indentation of second line of paragraph, of first line if there
* is only one line */
q=pdup(p); pnextl(q);
if(q->line!=bw->cursor->line)
{
indent=nindent(q);
indents=brs(q,indent);
}
else
{
indent=nindent(p);
indents=brs(p,indent);
}
prm(q);
/* But if the left margin is greater, we use that instead */
if(bw->o.lmargin>indent) indent=bw->o.lmargin;
/* Cut paragraph into memory buffer */
buf=(char *)malloc(len=(bw->cursor->byte-p->byte));
brmem(p,buf,len);
bdel(p,bw->cursor);
/* text is in buffer. insert it at cursor */
/* Do first line */
b=buf;
while(len--)
{
/* Set cursor position if we're at original offset */
if(b-buf==curoff) pset(bw->cursor,p);
/* Get character from buffer */
c= *b++;
/* Stop if we found end of line */
if(c=='\n' ||
c=='\r' && len && *b=='\n') { ++len; --b; break; }
/* Stop if we found white-space followed by end of line */
if(cwhite(c))
{
char *r=b;
int rlen=len;
int z;
while(rlen--)
{
z= *r++;
if(z=='\n') break;
if(!cwhite(z)) goto ok;
}
++len; --b; break;
ok:;
}
/* Insert character, advance pointer */
binsc(p,c); pgetc(p);
/* Do word wrap if we reach right margin */
if(piscol(p)>bw->o.rmargin && !cwhite(c))
{
wrapword(p,indent,bw->o.french,indents);
break;
}
}
/* Do rest */
while(len>0)
if(cwhitel(*b) || *b=='\r')
{
int f=0;
/* Set f if there are two spaces after . ? or ! instead of one */
if((b[-1]=='.' || b[-1]=='?' || b[-1]=='!') && cwhitel(b[1])) f=1;
/* Skip past the whitespace. Skip over indentations */
loop:
if(*b=='\r' && len)
{
if(b-buf==curoff) pset(bw->cursor,p);
++b, --len;
}
if(*b=='\n' && len)
{
if(b-buf==curoff) pset(bw->cursor,p);
++b, --len;
while(cpara(*b) && len)
{
if(b-buf==curoff) pset(bw->cursor,p);
++b, --len;
}
}
if(len && cwhite(*b))
{
if(b-buf==curoff) pset(bw->cursor,p);
++b, --len;
goto loop;
}
/* Insert proper amount of whitespace */
if(len)
{
if(f && !bw->o.french) binsc(p,' '), pgetc(p);
binsc(p,' '); pgetc(p);
}
}
else
{
/* Insert characters of word and wrap if necessary */
if(b-buf==curoff) pset(bw->cursor,p);
binsc(p,*b++); --len; pgetc(p);
if(piscol(p)>bw->o.rmargin) wrapword(p,indent,bw->o.french,indents);
}
binsc(p,'\n');
prm(p);
free(buf);
free(indents);
return 0;
}
/* Format entire block */
extern int lightoff;
int ufmtblk(bw)
BW *bw;
{
if(markv(1) && bw->cursor->byte>=markb->byte && bw->cursor->byte<=markk->byte)
{
markk->end=1;
utomarkk(bw);
within=1;
do
ubop(bw), uformat(bw);
while(bw->cursor->byte>markb->byte);
within=0;
markk->end=0;
if(lightoff) unmark(bw);
return 0;
}
else return uformat(bw);
}
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.