28e917644a
OBS-URL: https://build.opensuse.org/package/show/server:mail/alpine?expand=0&rev=999e2ea8b36d85950ddb53f2f40ba78d
4123 lines
127 KiB
Diff
4123 lines
127 KiB
Diff
diff -rc alpine-2.26/alpine/mailview.c alpine-2.26.fillpara/alpine/mailview.c
|
|
*** alpine-2.26/alpine/mailview.c 2022-06-02 18:14:00.463274817 -0600
|
|
--- alpine-2.26.fillpara/alpine/mailview.c 2022-06-02 18:14:56.983136230 -0600
|
|
***************
|
|
*** 203,209 ****
|
|
--- 203,217 ----
|
|
int pcpine_view_cursor(int, long);
|
|
#endif
|
|
|
|
+ static char *prefix;
|
|
+ #define NO_FLOWED 0x0000
|
|
+ #define IS_FLOWED 0x0001
|
|
+ #define DELETEQUO 0x0010
|
|
+ #define COLORAQUO 0x0100
|
|
+ #define RAWSTRING 0x1000
|
|
|
|
+ int is_word (char *, int, int);
|
|
+ int is_mailbox(char *, int, int);
|
|
|
|
/*----------------------------------------------------------------------
|
|
Format a buffer with the text of the current message for browser
|
|
***************
|
|
*** 294,299 ****
|
|
--- 302,318 ----
|
|
else
|
|
ps->unseen_in_view = !mc->seen;
|
|
|
|
+ prefix = reply_quote_str(env);
|
|
+ /* Make sure the prefix is not only made of spaces, so that we do not
|
|
+ * paint the screen incorrectly
|
|
+ */
|
|
+ if (prefix && *prefix){
|
|
+ int i;
|
|
+ for (i = 0; isspace((unsigned char) prefix[i]); i++);
|
|
+ if (i == strlen(prefix))
|
|
+ fs_give((void **)&prefix);
|
|
+ }
|
|
+
|
|
init_handles(&handles);
|
|
|
|
store = so_get(src, NULL, EDIT_ACCESS);
|
|
***************
|
|
*** 478,483 ****
|
|
--- 497,504 ----
|
|
}
|
|
while(ps->next_screen == SCREEN_FUN_NULL);
|
|
|
|
+ if (prefix && *prefix)
|
|
+ fs_give((void **)&prefix);
|
|
if(we_cancel)
|
|
cancel_busy_cue(-1);
|
|
|
|
diff -rc alpine-2.26/pico/basic.c alpine-2.26.fillpara/pico/basic.c
|
|
*** alpine-2.26/pico/basic.c 2022-06-02 18:14:00.487274758 -0600
|
|
--- alpine-2.26.fillpara/pico/basic.c 2022-06-02 18:14:56.983136230 -0600
|
|
***************
|
|
*** 22,30 ****
|
|
* framing, are hard.
|
|
*/
|
|
#include "headers.h"
|
|
!
|
|
#include "osdep/terminal.h"
|
|
|
|
|
|
/*
|
|
* Move the cursor to the
|
|
--- 22,31 ----
|
|
* framing, are hard.
|
|
*/
|
|
#include "headers.h"
|
|
! #include "../pith/osdep/color.h"
|
|
#include "osdep/terminal.h"
|
|
|
|
+ int indent_match(char **, LINE *, char *, int, int);
|
|
|
|
/*
|
|
* Move the cursor to the
|
|
***************
|
|
*** 281,287 ****
|
|
gotobop(int f, int n)
|
|
{
|
|
int quoted, qlen;
|
|
! UCS qstr[NLINE], qstr2[NLINE];
|
|
|
|
if (n < 0) /* the other way...*/
|
|
return(gotoeop(f, -n));
|
|
--- 282,288 ----
|
|
gotobop(int f, int n)
|
|
{
|
|
int quoted, qlen;
|
|
! char qstr[NLINE], qstr2[NLINE], ind_str[NLINE], pqstr[NLINE];;
|
|
|
|
if (n < 0) /* the other way...*/
|
|
return(gotoeop(f, -n));
|
|
***************
|
|
*** 293,298 ****
|
|
--- 294,307 ----
|
|
curwp->w_dotp = lback(curwp->w_dotp);
|
|
curwp->w_doto = 0;
|
|
}
|
|
+
|
|
+ if (indent_match(default_qstr(glo_quote_str, 1), curwp->w_dotp,ind_str, NLINE, 0)){
|
|
+ if (n){ /* look for another paragraph ? */
|
|
+ curwp->w_dotp = lback(curwp->w_dotp);
|
|
+ continue;
|
|
+ }
|
|
+ break;
|
|
+ }
|
|
|
|
/* scan line by line until we come to a line ending with
|
|
* a <NL><NL> or <NL><TAB> or <NL><SPACE>
|
|
***************
|
|
*** 300,317 ****
|
|
* PLUS: if there's a quote string, a quoted-to-non-quoted
|
|
* line transition.
|
|
*/
|
|
! quoted = quote_match(glo_quote_str, curwp->w_dotp, qstr, NLINE);
|
|
! qlen = quoted ? ucs4_strlen(qstr) : 0;
|
|
while(lback(curwp->w_dotp) != curbp->b_linep
|
|
&& llength(lback(curwp->w_dotp)) > qlen
|
|
! && quoted == quote_match(glo_quote_str,
|
|
lback(curwp->w_dotp),
|
|
! qstr2, NLINE)
|
|
! && !ucs4_strcmp(qstr, qstr2)
|
|
! && lgetc(curwp->w_dotp, qlen).c != TAB
|
|
! && lgetc(curwp->w_dotp, qlen).c != ' ')
|
|
curwp->w_dotp = lback(curwp->w_dotp);
|
|
|
|
if(n){
|
|
/* keep looking */
|
|
if(lback(curwp->w_dotp) == curbp->b_linep)
|
|
--- 309,367 ----
|
|
* PLUS: if there's a quote string, a quoted-to-non-quoted
|
|
* line transition.
|
|
*/
|
|
! quoted = quote_match(default_qstr(glo_quote_str, 1), curwp->w_dotp, qstr, NLINE, 0);
|
|
! qlen = quoted ? strlen(qstr) : 0;
|
|
while(lback(curwp->w_dotp) != curbp->b_linep
|
|
&& llength(lback(curwp->w_dotp)) > qlen
|
|
! && (quoted == quote_match(default_qstr(glo_quote_str, 1),
|
|
lback(curwp->w_dotp),
|
|
! qstr2, NLINE, 0))
|
|
! && !strcmp(qstr, qstr2) /* processed string */
|
|
! && (quoted == quote_match(default_qstr(glo_quote_str, 1),
|
|
! lback(curwp->w_dotp), qstr2, NLINE, 1))
|
|
! && !strcmp(qstr, qstr2) /* raw string */
|
|
! && !indent_match(default_qstr(glo_quote_str, 1),
|
|
! lback(curwp->w_dotp),ind_str, NLINE, 0)
|
|
! && !ISspace(lgetc(curwp->w_dotp, qlen).c))
|
|
curwp->w_dotp = lback(curwp->w_dotp);
|
|
|
|
+ /*
|
|
+ * Ok, we made it here and we assume that we are at the begining
|
|
+ * of the paragraph. Let's double check this now. In order to do
|
|
+ * so we shall check if the first line was indented in a special
|
|
+ * way.
|
|
+ */
|
|
+ if(lback(curwp->w_dotp) == curbp->b_linep)
|
|
+ break;
|
|
+ else{
|
|
+ int i, j;
|
|
+
|
|
+ /*
|
|
+ * First we test if the preceding line is indented.
|
|
+ * for the following test we need to have the raw values,
|
|
+ * not the processed values
|
|
+ */
|
|
+ quote_match(default_qstr(glo_quote_str, 1), curwp->w_dotp, qstr, NLINE, 1);
|
|
+ quote_match(default_qstr(glo_quote_str, 1), lback(curwp->w_dotp), qstr2, NLINE, 1);
|
|
+ for (i = 0, j = 0;
|
|
+ qstr[i] && qstr2[i] && (qstr[i] == qstr2[i]); i++, j++);
|
|
+ for (; ISspace(qstr2[i]); i++);
|
|
+ for (; ISspace(qstr[j]); j++);
|
|
+ if ((indent_match(default_qstr(glo_quote_str, 1), lback(curwp->w_dotp),
|
|
+ ind_str, NLINE, 1)
|
|
+ && (strlenis(qstr2)
|
|
+ + strlenis(ind_str) >= strlenis(qstr)))
|
|
+ || ((lback(curwp->w_dotp) != curbp->b_linep
|
|
+ && llength(lback(curwp->w_dotp)) > qlen
|
|
+ && (quoted == quote_match(default_qstr(glo_quote_str, 1),
|
|
+ lback(curwp->w_dotp), pqstr, NLINE, 0))
|
|
+ && !strcmp(qstr, pqstr)
|
|
+ && !ISspace(lgetc(curwp->w_dotp, qlen).c)
|
|
+ && strlenis(qstr2) > strlenis(qstr))
|
|
+ && !qstr2[i] && !qstr[j]))
|
|
+ curwp->w_dotp = lback(curwp->w_dotp);
|
|
+ }
|
|
+
|
|
if(n){
|
|
/* keep looking */
|
|
if(lback(curwp->w_dotp) == curbp->b_linep)
|
|
***************
|
|
*** 324,330 ****
|
|
else{
|
|
/* leave cursor on first word in para */
|
|
curwp->w_doto = 0;
|
|
! while(ucs4_isspace(lgetc(curwp->w_dotp, curwp->w_doto).c))
|
|
if(++curwp->w_doto >= llength(curwp->w_dotp)){
|
|
curwp->w_doto = 0;
|
|
curwp->w_dotp = lforw(curwp->w_dotp);
|
|
--- 374,380 ----
|
|
else{
|
|
/* leave cursor on first word in para */
|
|
curwp->w_doto = 0;
|
|
! while(ISspace(lgetc(curwp->w_dotp, curwp->w_doto).c))
|
|
if(++curwp->w_doto >= llength(curwp->w_dotp)){
|
|
curwp->w_doto = 0;
|
|
curwp->w_dotp = lforw(curwp->w_dotp);
|
|
***************
|
|
*** 347,354 ****
|
|
int
|
|
gotoeop(int f, int n)
|
|
{
|
|
! int quoted, qlen;
|
|
! UCS qstr[NLINE], qstr2[NLINE];
|
|
|
|
if (n < 0) /* the other way...*/
|
|
return(gotobop(f, -n));
|
|
--- 397,405 ----
|
|
int
|
|
gotoeop(int f, int n)
|
|
{
|
|
! int quoted, qlen, indented, changeqstr = 0;
|
|
! int i,j, fli = 0; /* fli = first line indented a boolean variable */
|
|
! char qstr[NLINE], qstr2[NLINE], ind_str[NLINE];
|
|
|
|
if (n < 0) /* the other way...*/
|
|
return(gotobop(f, -n));
|
|
***************
|
|
*** 361,384 ****
|
|
break;
|
|
}
|
|
|
|
! /* scan line by line until we come to a line ending with
|
|
! * a <NL><NL> or <NL><TAB> or <NL><SPACE>
|
|
! *
|
|
! * PLUS: if there's a quote string, a quoted-to-non-quoted
|
|
! * line transition.
|
|
*/
|
|
! quoted = quote_match(glo_quote_str,
|
|
! curwp->w_dotp, qstr, NLINE);
|
|
! qlen = quoted ? ucs4_strlen(qstr) : 0;
|
|
|
|
while(curwp->w_dotp != curbp->b_linep
|
|
&& llength(lforw(curwp->w_dotp)) > qlen
|
|
! && (quoted == quote_match(glo_quote_str,
|
|
! lforw(curwp->w_dotp),
|
|
! qstr2, NLINE)
|
|
! && !ucs4_strcmp(qstr, qstr2))
|
|
! && lgetc(lforw(curwp->w_dotp), qlen).c != TAB
|
|
! && lgetc(lforw(curwp->w_dotp), qlen).c != ' ')
|
|
curwp->w_dotp = lforw(curwp->w_dotp);
|
|
|
|
curwp->w_doto = llength(curwp->w_dotp);
|
|
--- 412,481 ----
|
|
break;
|
|
}
|
|
|
|
! /*
|
|
! * We need to figure out if this line is the first line of
|
|
! * a paragraph that has been indented in a special way. If this
|
|
! * is the case, we advance one more line before we use the
|
|
! * algorithm below
|
|
! */
|
|
!
|
|
! if(curwp->w_dotp != curbp->b_linep){
|
|
! quote_match(default_qstr(glo_quote_str, 1), curwp->w_dotp, qstr, NLINE, 1);
|
|
! quote_match(default_qstr(glo_quote_str, 1), lforw(curwp->w_dotp), qstr2, NLINE, 1);
|
|
! indented = indent_match(default_qstr(glo_quote_str, 1), curwp->w_dotp, ind_str,
|
|
! NLINE, 1);
|
|
! if (strlenis(qstr)
|
|
! + strlenis(ind_str) < strlenis(qstr2)){
|
|
! curwp->w_doto = llength(curwp->w_dotp);
|
|
! if(n){ /* this line is a paragraph by itself */
|
|
! curwp->w_dotp = lforw(curwp->w_dotp);
|
|
! continue;
|
|
! }
|
|
! break;
|
|
! }
|
|
! for (i=0,j=0; qstr[i] && qstr2[i] && (qstr[i] == qstr2[i]);i++,j++);
|
|
! for (; ISspace(qstr[i]); i++);
|
|
! for (; ISspace(qstr2[j]); j++);
|
|
! if (!qstr[i] && !qstr2[j] && indented){
|
|
! fli++;
|
|
! if (indent_match(default_qstr(glo_quote_str, 1), lforw(curwp->w_dotp),
|
|
! ind_str, NLINE, 0)){
|
|
! if (n){ /* look for another paragraph ? */
|
|
! curwp->w_dotp = lforw(curwp->w_dotp);
|
|
! continue;
|
|
! }
|
|
! }
|
|
! else{
|
|
! if (!lisblank(lforw(curwp->w_dotp)))
|
|
! curwp->w_dotp = lforw(curwp->w_dotp);
|
|
! }
|
|
! }
|
|
! }
|
|
!
|
|
! /* scan line by line until we come to a line ending with
|
|
! * a <NL><NL> or <NL><TAB> or <NL><SPACE>
|
|
! *
|
|
! * PLUS: if there's a quote string, a quoted-to-non-quoted
|
|
! * line transition.
|
|
! */
|
|
! /* if the first line is indented (fli == 1), then the test below
|
|
! is on the second line, and in that case we will need the raw
|
|
! string, not the processed string
|
|
*/
|
|
! quoted = quote_match(default_qstr(glo_quote_str, 1), curwp->w_dotp, qstr, NLINE, fli);
|
|
! qlen = quoted ? strlen(qstr) : 0;
|
|
|
|
while(curwp->w_dotp != curbp->b_linep
|
|
&& llength(lforw(curwp->w_dotp)) > qlen
|
|
! && (quoted == quote_match(default_qstr(glo_quote_str, 1),
|
|
! lforw(curwp->w_dotp), qstr2, NLINE, fli))
|
|
! && !strcmp(qstr, qstr2)
|
|
! && (quoted == quote_match(default_qstr(glo_quote_str, 1),
|
|
! lforw(curwp->w_dotp), qstr2, NLINE, 1))
|
|
! && !strcmp(qstr, qstr2)
|
|
! && !indent_match(default_qstr(glo_quote_str, 1),
|
|
! lforw(curwp->w_dotp), ind_str, NLINE, 0)
|
|
! && !ISspace(lgetc(lforw(curwp->w_dotp), qlen).c))
|
|
curwp->w_dotp = lforw(curwp->w_dotp);
|
|
|
|
curwp->w_doto = llength(curwp->w_dotp);
|
|
diff -rc alpine-2.26/pico/efunc.h alpine-2.26.fillpara/pico/efunc.h
|
|
*** alpine-2.26/pico/efunc.h 2022-06-02 18:14:00.487274758 -0600
|
|
--- alpine-2.26.fillpara/pico/efunc.h 2022-06-02 18:14:56.983136230 -0600
|
|
***************
|
|
*** 253,262 ****
|
|
extern int fillpara(int, int);
|
|
extern int fillbuf(int, int);
|
|
extern int inword(void);
|
|
! extern int quote_match(UCS *, LINE *, UCS *, size_t);
|
|
extern int ucs4_isalnum(UCS);
|
|
extern int ucs4_isalpha(UCS);
|
|
extern int ucs4_isspace(UCS);
|
|
extern int ucs4_ispunct(UCS);
|
|
|
|
#endif /* EFUNC_H */
|
|
--- 253,268 ----
|
|
extern int fillpara(int, int);
|
|
extern int fillbuf(int, int);
|
|
extern int inword(void);
|
|
! extern int quote_match(char **, LINE *, char *, size_t, int);
|
|
! extern void flatten_qstring(QSTRING_S *, char *, int);
|
|
! extern void free_qs(QSTRING_S **);
|
|
! extern QSTRING_S *do_quote_match (char **, char *, char *, char *, char *, int, int);
|
|
! extern QSTRING_S *do_raw_quote_match(char **, char *, char *, char *, QSTRING_S **, QSTRING_S **);
|
|
! extern int indent_match(char **, LINE *, char *, int, int);
|
|
extern int ucs4_isalnum(UCS);
|
|
extern int ucs4_isalpha(UCS);
|
|
extern int ucs4_isspace(UCS);
|
|
extern int ucs4_ispunct(UCS);
|
|
|
|
#endif /* EFUNC_H */
|
|
+
|
|
diff -rc alpine-2.26/pico/line.c alpine-2.26.fillpara/pico/line.c
|
|
*** alpine-2.26/pico/line.c 2022-06-02 18:14:00.487274758 -0600
|
|
--- alpine-2.26.fillpara/pico/line.c 2022-06-02 18:14:57.007136171 -0600
|
|
***************
|
|
*** 608,623 ****
|
|
lisblank(LINE *line)
|
|
{
|
|
int n = 0;
|
|
! UCS qstr[NLINE];
|
|
|
|
! n = (glo_quote_str
|
|
! && quote_match(glo_quote_str, line, qstr, NLINE))
|
|
! ? ucs4_strlen(qstr) : 0;
|
|
|
|
for(; n < llength(line); n++)
|
|
! if(!ucs4_isspace(lgetc(line, n).c)
|
|
! || lgetc(line, n).c >= 0xff
|
|
! || (unsigned char) lgetc(line,n).c != (unsigned char) NBSPC)
|
|
return(FALSE);
|
|
|
|
return(TRUE);
|
|
--- 608,619 ----
|
|
lisblank(LINE *line)
|
|
{
|
|
int n = 0;
|
|
! char qstr[NLINE];
|
|
|
|
! n = quote_match(default_qstr(glo_quote_str, 1), line, qstr, NLINE, 1);
|
|
|
|
for(; n < llength(line); n++)
|
|
! if(!ISspace(lgetc(line, n).c))
|
|
return(FALSE);
|
|
|
|
return(TRUE);
|
|
diff -rc alpine-2.26/pico/osdep/color.h alpine-2.26.fillpara/pico/osdep/color.h
|
|
*** alpine-2.26/pico/osdep/color.h 2022-06-02 18:14:00.491274749 -0600
|
|
--- alpine-2.26.fillpara/pico/osdep/color.h 2022-06-02 18:14:57.007136171 -0600
|
|
***************
|
|
*** 33,38 ****
|
|
--- 33,39 ----
|
|
void pico_toggle_color(int);
|
|
void pico_set_nfg_color(void);
|
|
void pico_set_nbg_color(void);
|
|
+ char **default_qstr(void *, int);
|
|
|
|
|
|
#endif /* PICO_OSDEP_COLOR_INCLUDED */
|
|
diff -rc alpine-2.26/pico/search.c alpine-2.26.fillpara/pico/search.c
|
|
*** alpine-2.26/pico/search.c 2022-06-02 18:14:00.487274758 -0600
|
|
--- alpine-2.26.fillpara/pico/search.c 2022-06-02 18:14:57.015136151 -0600
|
|
***************
|
|
*** 32,37 ****
|
|
--- 32,38 ----
|
|
int readpattern(char *, int, int);
|
|
int replace_pat(UCS *, int *, int);
|
|
int replace_all(UCS *, UCS *, int);
|
|
+ int deletepara(int, int);
|
|
void reverse_line(LINE *);
|
|
void reverse_buffer(void);
|
|
void reverse_ucs4(UCS *);
|
|
***************
|
|
*** 67,73 ****
|
|
{"^W", N_("Start of Para"), (CTRL|'W')},
|
|
{"^O", N_("End of Para"), (CTRL|'O')},
|
|
{"^U", N_("FullJustify"), (CTRL|'U')},
|
|
! {NULL, NULL, 0},
|
|
{NULL, NULL, 0}
|
|
};
|
|
|
|
--- 68,74 ----
|
|
{"^W", N_("Start of Para"), (CTRL|'W')},
|
|
{"^O", N_("End of Para"), (CTRL|'O')},
|
|
{"^U", N_("FullJustify"), (CTRL|'U')},
|
|
! {"^P", N_("Delete Para"), (CTRL|'P')},
|
|
{NULL, NULL, 0}
|
|
};
|
|
|
|
***************
|
|
*** 216,224 ****
|
|
|
|
case (CTRL|'P'):
|
|
if(flags & SR_ORIGMEN){
|
|
! /* Undefined still */
|
|
}
|
|
! if(flags & SR_OPTNMEN){
|
|
if(flags & SR_FORWARD){
|
|
flags &= ~SR_FORWARD;
|
|
flags |= SR_BACKWRD;
|
|
--- 217,227 ----
|
|
|
|
case (CTRL|'P'):
|
|
if(flags & SR_ORIGMEN){
|
|
! deletepara(0, 1);
|
|
! mlerase();
|
|
! FWS_RETURN(TRUE);
|
|
}
|
|
! else if(flags & SR_OPTNMEN){
|
|
if(flags & SR_FORWARD){
|
|
flags &= ~SR_FORWARD;
|
|
flags |= SR_BACKWRD;
|
|
***************
|
|
*** 1416,1418 ****
|
|
--- 1419,1443 ----
|
|
if(bsearch) reverse_ucs4(orig);
|
|
return utf8;
|
|
}
|
|
+
|
|
+ int
|
|
+ deletepara(int f, int n) /* Delete the current paragraph */
|
|
+ {
|
|
+ if(curbp->b_mode&MDVIEW) /* don't allow this command if */
|
|
+ return(rdonly()); /* we are in read only mode */
|
|
+
|
|
+ if(!lisblank(curwp->w_dotp))
|
|
+ gotobop(FALSE, 1);
|
|
+
|
|
+ curwp->w_markp = curwp->w_dotp;
|
|
+ curwp->w_marko = 0;
|
|
+
|
|
+ gotoeop(FALSE, 1);
|
|
+ if (curwp->w_dotp != curbp->b_linep){ /* if we are not at the end of buffer */
|
|
+ curwp->w_dotp = lforw(curwp->w_dotp); /* get one more line */
|
|
+ curwp->w_doto = 0; /* but only the beginning */
|
|
+ }
|
|
+ killregion(f,n);
|
|
+ return(TRUE);
|
|
+ }
|
|
+
|
|
diff -rc alpine-2.26/pico/word.c alpine-2.26.fillpara/pico/word.c
|
|
*** alpine-2.26/pico/word.c 2022-06-02 18:14:00.487274758 -0600
|
|
--- alpine-2.26.fillpara/pico/word.c 2022-06-02 18:14:57.019136141 -0600
|
|
***************
|
|
*** 21,30 ****
|
|
*/
|
|
|
|
#include "headers.h"
|
|
!
|
|
|
|
int fpnewline(UCS *quote);
|
|
! int fillregion(UCS *qstr, REGION *addedregion);
|
|
int setquotelevelinregion(int quotelevel, REGION *addedregion);
|
|
int is_user_separator(UCS c);
|
|
|
|
--- 21,30 ----
|
|
*/
|
|
|
|
#include "headers.h"
|
|
! #include "../pith/osdep/color.h"
|
|
|
|
int fpnewline(UCS *quote);
|
|
! int fillregion(UCS *qstr, UCS *istr, REGION *addedregion);
|
|
int setquotelevelinregion(int quotelevel, REGION *addedregion);
|
|
int is_user_separator(UCS c);
|
|
|
|
***************
|
|
*** 427,551 ****
|
|
return 0;
|
|
}
|
|
|
|
! void
|
|
! do_quote_match(UCS *q, LINE *l, UCS *buf, size_t buflen)
|
|
! {
|
|
! register int i, j;
|
|
! int qstart, qend, k;
|
|
!
|
|
! /*
|
|
! * The method for determining the quote string is:
|
|
! * 1) strip leading and trailing whitespace from q
|
|
! * 2) add all leading whitespace to buf
|
|
! * 3) check for q
|
|
! * 4) if q, append q to buf and any trailing whitespace
|
|
! * 5) repeat steps 3 and 4 as necessary
|
|
! *
|
|
! * q in the future could be made to be an array of (UCS *)'s
|
|
! * (">" and whatever the user's quote_string is)
|
|
! */
|
|
!
|
|
! *buf = '\0';
|
|
|
|
! if(l == NULL)
|
|
! return;
|
|
|
|
! /* count leading whitespace as part of the quote */
|
|
! for(j = 0; j <= llength(l) && lgetc(l, j).c == ' ' && j+1 < buflen; j++)
|
|
! buf[j] = lgetc(l, j).c;
|
|
! buf[j] = '\0';
|
|
!
|
|
! if(q == NULL || *q == '\0')
|
|
! return;
|
|
!
|
|
! /* pare down q so it contains no leading or trailing whitespace */
|
|
! for(i = 0; q[i] == ' '; i++);
|
|
! qstart = i;
|
|
! for(i = ucs4_strlen(q); i > 0 && q[i-1] == ' '; i--);
|
|
! qend = i;
|
|
!
|
|
! /* for quote strings that are blanks, chop buf to the length of q */
|
|
! if(qend <= qstart){
|
|
! if(ucs4_strlen(q) < buflen)
|
|
! buf[ucs4_strlen(q)] = '\0';
|
|
! return;
|
|
! }
|
|
!
|
|
! while(j <= llength(l)){
|
|
! for(i = qstart; j <= llength(l) && i < qend; i++, j++)
|
|
! if(q[i] != lgetc(l, j).c)
|
|
! return;
|
|
!
|
|
! if(i >= qend){
|
|
! if(ucs4_strlen(buf) + qend - qstart < (buflen - 1))
|
|
! ucs4_strncat(buf, q + qstart, qend - qstart);
|
|
! }
|
|
!
|
|
! /*
|
|
! * if we're this far along, we've matched a quote string,
|
|
! * and should now add the following white space.
|
|
! */
|
|
! for(k = ucs4_strlen(buf);
|
|
! j <= llength(l) && lgetc(l,j).c == ' ' && (k + 1 < buflen);
|
|
! j++, k++){
|
|
! buf[k] = lgetc(l,j).c;
|
|
! }
|
|
! buf[k] = '\0';
|
|
!
|
|
! if(j > llength(l))
|
|
! return;
|
|
! }
|
|
}
|
|
|
|
/*
|
|
* Return number of quotes if whatever starts the line matches the quote string
|
|
*/
|
|
int
|
|
! quote_match(UCS *q, LINE *gl, UCS *bufl, size_t buflen)
|
|
{
|
|
! LINE *nl = gl != curbp->b_linep ? lforw(gl) : NULL;
|
|
! LINE *pl = lback(gl) != curbp->b_linep ? lback(gl) : NULL;
|
|
! UCS bufp[NSTRING], bufn[NSTRING];
|
|
! int i, j, qstart, qend;
|
|
! int quoted_line = 0;
|
|
!
|
|
! do_quote_match(q, pl, bufp, sizeof(bufp)); /* previous line */
|
|
! do_quote_match(q, gl, bufl, buflen); /* given line */
|
|
! do_quote_match(q, nl, bufn, sizeof(bufn)); /* next line */
|
|
!
|
|
! if(!ucs4_strcmp(bufp, bufl) || !ucs4_strcmp(bufl, bufn))
|
|
! return ucs4_strlen(bufl);
|
|
!
|
|
! /* is this line quoted? */
|
|
! if(q && *q){
|
|
! /* pare down q so it contains no leading or trailing whitespace */
|
|
! for(i = 0; q[i] == ' '; i++);
|
|
! qstart = i;
|
|
! for(i = ucs4_strlen(q); i > 0 && q[i-1] == ' '; i--);
|
|
! qend = i;
|
|
! for(i = 0; i < llength(gl)
|
|
! && i + qstart < qend
|
|
! && lgetc(gl, i).c == q[i+qstart]; i++);
|
|
! if(i + qstart == qend)
|
|
! quoted_line = 1;
|
|
! }
|
|
!
|
|
! /* compare bufl and bufn */
|
|
! for(i = 0; bufl[i] && bufn[i] && bufl[i] == bufn[i]; i++);
|
|
!
|
|
! /* go back to last non-space character */
|
|
! for(; i > 0 && bufl[i-1] == ' '; i--);
|
|
!
|
|
! /* do bufl and bufn differ only in spaces? */
|
|
! for(j = i; bufl[j] && bufl[j] == ' '; j++);
|
|
!
|
|
! /* if they differ only on trailing spaces, chop bufl to agree with bufn */
|
|
! if (!bufl[j] )
|
|
! bufl[Pmaster && quoted_line ? (j > i ? i+1 : i) : i] = '\0';
|
|
|
|
! return ucs4_strlen(bufl);
|
|
}
|
|
|
|
|
|
/* Justify the entire buffer instead of just a paragraph */
|
|
int
|
|
--- 427,591 ----
|
|
return 0;
|
|
}
|
|
|
|
! /* Support of indentation of paragraphs */
|
|
! #define is_indent_char(c) (((c) == '.' || (c) == '}' || (c) == RPAREN || \
|
|
! (c) == '*' || (c) == '+' || is_a_digit(c) || \
|
|
! ISspace(c) || (c) == '-' || \
|
|
! (c) == ']') ? 1 : 0)
|
|
! #define allowed_after_digit(c,word,k) ((((c) == '.' && \
|
|
! allowed_after_period(next((word),(k)))) ||\
|
|
! (c) == RPAREN || (c) == '}' || (c) == ']' ||\
|
|
! ISspace(c) || is_a_digit(c) || \
|
|
! ((c) == '-' ) && \
|
|
! allowed_after_dash(next((word),(k)))) \
|
|
! ? 1 : 0)
|
|
! #define allowed_after_period(c) (((c) == RPAREN || (c) == '}' || (c) == ']' ||\
|
|
! ISspace(c) || (c) == '-' || \
|
|
! is_a_digit(c)) ? 1 : 0)
|
|
! #define allowed_after_parenth(c) (ISspace(c) ? 1 : 0)
|
|
! #define allowed_after_space(c) (ISspace(c) ? 1 : 0)
|
|
! #define allowed_after_braces(c) (ISspace(c) ? 1 : 0)
|
|
! #define allowed_after_star(c) ((ISspace(c) || (c) == RPAREN ||\
|
|
! (c) == ']' || (c) == '}') ? 1 : 0)
|
|
! #define allowed_after_dash(c) ((ISspace(c) || is_a_digit(c)) ? 1 : 0)
|
|
! #define EOLchar(c) (((c) == '.' || (c) == ':' || (c) == '?' ||\
|
|
! (c) == '!') ? 1 : 0)
|
|
!
|
|
! int indent_match(char **, LINE *, char *, int, int);
|
|
!
|
|
! /* Extended justification support */
|
|
! #define is_cquote(c) ((c) == '>' || (c) == '|' || (c) == ']' || (c) == ':')
|
|
! #define is_cword(c) ((((c) >= 'a') && ((c) <= 'z')) || \
|
|
! (((c) >= 'A') && ((c) <= 'Z')) || \
|
|
! (((c) >= '0') && ((c) <= '9')) || \
|
|
! ((c) == ' ') || ((c) == '?') || \
|
|
! ((c) == '@') || ((c) == '.') || \
|
|
! ((c) == '!') || ((c) == '\'') || \
|
|
! ((c) == ',') || ((c) == '\"') ? 1 : 0)
|
|
! #define isaquote(c) ((c) == '\"' || (c) == '\'')
|
|
! #define is8bit(c) ((((int) (c)) & 0x80) ? 1 : 0)
|
|
! #define iscontrol(c) (iscntrl(((int) (c)) & 0x7f) ? 1 : 0)
|
|
! #define forbidden(c) (((c) == '\"') || ((c) == '\'') || ((c) == '$') ||\
|
|
! ((c) == ',') || ((c) == '.') || ((c) == '-') ||\
|
|
! ((c) == LPAREN) || ((c) == '/')|| ((c) == '`') ||\
|
|
! ((c) == '{') || ((c) == '\\') || (iscontrol((c))) ||\
|
|
! (((c) >= '0') && ((c) <= '9')) || ((c) == '?'))
|
|
! #define is_cletter(c) ((((c) >= 'a') && ((c) <= 'z'))) ||\
|
|
! ((((c) >= 'A') && ((c) <= 'Z'))||\
|
|
! is8bit(c))
|
|
! #define is_cnumber(c) ((c) >= '0' && (c) <= '9')
|
|
! #define allwd_after_word(c) (((c) == ' ') || ((c) == '>') || is_cletter(c))
|
|
! #define allwd_after_qsword(c) (((c) != '\\') && ((c) != RPAREN) && ((c) != '/'))
|
|
! #define before(word,i) (((i) > 0) ? (word)[(i) - 1] : 0)
|
|
! #define next(w,i) ((((w)[(i)]) != 0) ? ((w)[(i) + 1]) : 0)
|
|
! #define now(w,i) ((w)[(i)])
|
|
! #define is_qsword(c) (((c) == ':') || ((c) == RPAREN) ? 1 : 0)
|
|
! #define is_colon(c) (((c) == ':') ? 1 : 0)
|
|
! #define is_rarrow(c) (((c) == '>') ? 1 : 0)
|
|
! #define is_tilde(c) (((c) == '~') ? 1 : 0)
|
|
! #define is_dash(c) (((c) == '-') ? 1 : 0)
|
|
! #define is_pound(c) (((c) == '#') ? 1 : 0)
|
|
! #define is_a_digit(c) ((((c) >= '0') && ((c) <= '9')) ? 1 : 0)
|
|
! #define is_allowed(c) (is_cquote(c) || is_cword(c) || is_dash(c) || \
|
|
! is_pound(c))
|
|
! #define qs_allowed(a) (((a)->qstype != qsGdb) && ((a)->qstype != qsProg))
|
|
!
|
|
! /* Internal justification functions */
|
|
! QSTRING_S *qs_quote_match(char **, LINE *, char *, int);
|
|
! int ucs4_widthis(UCS *);
|
|
! int ucs4_strlenis(UCS *);
|
|
! void linencpy(char *, LINE *, int);
|
|
|
|
! void
|
|
! linencpy(word, l, buflen)
|
|
! char word[NSTRING];
|
|
! LINE *l;
|
|
! int buflen;
|
|
! {
|
|
! int i;
|
|
! UCS ucs_word[NSTRING];
|
|
! char *utf_word;
|
|
!
|
|
! word[0] = '\0';
|
|
! if(l){
|
|
! for (i = 0; i < buflen && i < llength(l)
|
|
! && (ucs_word[i] = lgetc(l,i).c); i++);
|
|
! ucs_word[i == buflen ? i-1 : i] = '\0';
|
|
! utf_word = ucs4_to_utf8_cpystr(ucs_word);
|
|
! strncpy(word, utf_word, (NSTRING < buflen ? NSTRING : buflen));
|
|
! word[NSTRING-1] = '\0';
|
|
! if(utf_word) fs_give((void **)&utf_word);
|
|
! }
|
|
! }
|
|
!
|
|
! /*
|
|
! * This function returns the quote string as a structure. In this way we
|
|
! * have two ways to get the quote string: as a char * or as a QSTRING_S *
|
|
! * directly.
|
|
! */
|
|
! QSTRING_S *
|
|
! qs_quote_match(char **q, LINE *l, char *rqstr, int rqstrlen)
|
|
! {
|
|
! char GLine[NSTRING], NLine[NSTRING], PLine[NSTRING];
|
|
! LINE *nl = l != curbp->b_linep ? lforw(l) : NULL;
|
|
! LINE *pl = lback(l) != curbp->b_linep ? lback(l) : NULL;
|
|
! int plb = 1;
|
|
!
|
|
! linencpy(GLine, l, NSTRING);
|
|
! linencpy(NLine, nl, NSTRING);
|
|
!
|
|
! if (pl){
|
|
! linencpy(PLine, pl, NSTRING);
|
|
! if(lback(pl) != curbp->b_linep){
|
|
! char PPLine[NSTRING];
|
|
|
|
! linencpy(PPLine, lback(pl), NSTRING);
|
|
! plb = line_isblank(q, PLine, GLine, PPLine, NSTRING);
|
|
! }
|
|
! }
|
|
! return do_quote_match(q, GLine, NLine, PLine, rqstr, rqstrlen, plb);
|
|
}
|
|
|
|
/*
|
|
* Return number of quotes if whatever starts the line matches the quote string
|
|
+ * rqstr is a pointer to raw qstring; buf points to processed qstring
|
|
*/
|
|
int
|
|
! quote_match(char **q, LINE *l, char *buf, size_t buflen, int raw)
|
|
{
|
|
! QSTRING_S *qs;
|
|
! char rqstr[NSTRING];
|
|
|
|
! qs = qs_quote_match(q, l, rqstr, NSTRING);
|
|
! if(qs)
|
|
! record_quote_string(qs);
|
|
! flatten_qstring(qs, buf, buflen);
|
|
! if (qs) free_qs(&qs);
|
|
!
|
|
! if(raw){
|
|
! strncpy(buf, rqstr, buflen < NSTRING ? buflen : NSTRING);
|
|
! buf[buflen-1] = '\0';
|
|
! }
|
|
!
|
|
! return buf && buf[0] ? strlen(buf) : 0;
|
|
}
|
|
|
|
+ int ucs4_widthis(UCS *ucstr)
|
|
+ {
|
|
+ int i, rv = 0;
|
|
+ for (i = 0; ucstr && ucstr[i]; i++)
|
|
+ rv += ((ucstr[i] == TAB) ? (~rv & 0x07) + 1 : wcellwidth((UCS) ucstr[i]));
|
|
+ return rv;
|
|
+ }
|
|
+
|
|
+ int ucs4_strlenis(UCS *ucs_qstr)
|
|
+ {
|
|
+ char *str = ucs4_to_utf8_cpystr(ucs_qstr);
|
|
+ int i = (int) strlenis(str);
|
|
+
|
|
+ if(str) fs_give((void **)&str);
|
|
+ return i;
|
|
+ }
|
|
|
|
/* Justify the entire buffer instead of just a paragraph */
|
|
int
|
|
***************
|
|
*** 800,805 ****
|
|
--- 840,846 ----
|
|
}
|
|
|
|
if(action == 'R' && curwp->w_markp){
|
|
+ char qstrfl[NSTRING];
|
|
/* let yank() know that it may be restoring a paragraph */
|
|
thisflag |= CFFILL;
|
|
|
|
***************
|
|
*** 811,831 ****
|
|
swap_mark_and_dot_if_mark_comes_first();
|
|
|
|
/* determine if we're justifying quoted text or not */
|
|
! qstr = quote_match(glo_quote_str,
|
|
! curwp->w_doto > 0 ? curwp->w_dotp->l_fp : curwp->w_dotp,
|
|
! qstr2, NSTRING)
|
|
! && *qstr2 ? qstr2 : NULL;
|
|
!
|
|
|
|
/*
|
|
* Fillregion moves dot to the end of the filled region.
|
|
*/
|
|
! if(!fillregion(qstr, &addedregion))
|
|
return(FALSE);
|
|
|
|
set_last_region_added(&addedregion);
|
|
! }
|
|
! else if(action == 'P'){
|
|
|
|
/*
|
|
* Justfiy the current paragraph.
|
|
--- 852,877 ----
|
|
swap_mark_and_dot_if_mark_comes_first();
|
|
|
|
/* determine if we're justifying quoted text or not */
|
|
! qstr = (glo_quote_str
|
|
! && quote_match(default_qstr(glo_quote_str, 1),
|
|
! (curwp->w_doto > 0 ? curwp->w_dotp->l_fp : curwp->w_dotp),
|
|
! qstrfl, NSTRING, 0)
|
|
! && *qstrfl) ? utf8_to_ucs4_cpystr(qstrfl) : NULL;
|
|
|
|
/*
|
|
* Fillregion moves dot to the end of the filled region.
|
|
*/
|
|
! if(!fillregion(qstr, NULL, &addedregion))
|
|
return(FALSE);
|
|
|
|
set_last_region_added(&addedregion);
|
|
!
|
|
! if(qstr)
|
|
! fs_give((void **)&qstr);
|
|
! }
|
|
! else if(action == 'P'){
|
|
! char ind_str[NSTRING], qstrfl[NSTRING];
|
|
! UCS *istr;
|
|
|
|
/*
|
|
* Justfiy the current paragraph.
|
|
***************
|
|
*** 837,852 ****
|
|
if(gotoeop(FALSE, 1) == FALSE)
|
|
return(FALSE);
|
|
|
|
- /* determine if we're justifying quoted text or not */
|
|
- qstr = quote_match(glo_quote_str,
|
|
- curwp->w_dotp, qstr2, NSTRING)
|
|
- && *qstr2 ? qstr2 : NULL;
|
|
-
|
|
setmark(0,0); /* mark last line of para */
|
|
|
|
/* jump back to the beginning of the paragraph */
|
|
gotobop(FALSE, 1);
|
|
|
|
/* let yank() know that it may be restoring a paragraph */
|
|
thisflag |= (CFFILL | CFFLPA);
|
|
|
|
--- 883,898 ----
|
|
if(gotoeop(FALSE, 1) == FALSE)
|
|
return(FALSE);
|
|
|
|
setmark(0,0); /* mark last line of para */
|
|
|
|
/* jump back to the beginning of the paragraph */
|
|
gotobop(FALSE, 1);
|
|
|
|
+ istr = indent_match(default_qstr(glo_quote_str, 1), curwp->w_dotp, ind_str, NSTRING, 0)
|
|
+ && *ind_str ? utf8_to_ucs4_cpystr(ind_str) : NULL;
|
|
+ qstr = (quote_match(default_qstr(glo_quote_str, 1), curwp->w_dotp, qstrfl, NSTRING, 0)
|
|
+ && *qstrfl) ? utf8_to_ucs4_cpystr(qstrfl) : NULL;
|
|
+
|
|
/* let yank() know that it may be restoring a paragraph */
|
|
thisflag |= (CFFILL | CFFLPA);
|
|
|
|
***************
|
|
*** 860,868 ****
|
|
/*
|
|
* Fillregion moves dot to the end of the filled region.
|
|
*/
|
|
! if(!fillregion(qstr, &addedregion))
|
|
return(FALSE);
|
|
|
|
set_last_region_added(&addedregion);
|
|
|
|
/* Leave cursor on first char of first line after justified region */
|
|
--- 906,920 ----
|
|
/*
|
|
* Fillregion moves dot to the end of the filled region.
|
|
*/
|
|
! if(!fillregion(qstr, istr, &addedregion))
|
|
return(FALSE);
|
|
|
|
+ if(qstr)
|
|
+ fs_give((void **)&qstr);
|
|
+
|
|
+ if(istr)
|
|
+ fs_give((void **)&istr);
|
|
+
|
|
set_last_region_added(&addedregion);
|
|
|
|
/* Leave cursor on first char of first line after justified region */
|
|
***************
|
|
*** 904,919 ****
|
|
* can delete it and restore the saved part.
|
|
*/
|
|
int
|
|
! fillregion(UCS *qstr, REGION *addedregion)
|
|
{
|
|
long c, sz, last_char = 0;
|
|
! int i, j, qlen, same_word,
|
|
spaces, word_len, word_ind, line_len, ww;
|
|
int starts_midline = 0;
|
|
int ends_midline = 0;
|
|
int offset_into_start;
|
|
LINE *line_before_start, *lp;
|
|
! UCS line_last, word[NSTRING];
|
|
REGION region;
|
|
|
|
/* if region starts midline insert a newline */
|
|
--- 956,971 ----
|
|
* can delete it and restore the saved part.
|
|
*/
|
|
int
|
|
! fillregion(UCS *qstr, UCS *istr, REGION *addedregion)
|
|
{
|
|
long c, sz, last_char = 0;
|
|
! int i, j, qlen, same_word, qi, pqi, qlenis,
|
|
spaces, word_len, word_ind, line_len, ww;
|
|
int starts_midline = 0;
|
|
int ends_midline = 0;
|
|
int offset_into_start;
|
|
LINE *line_before_start, *lp;
|
|
! UCS line_last, word[NSTRING], quoid[NSTRING], qstr2[NSTRING];
|
|
REGION region;
|
|
|
|
/* if region starts midline insert a newline */
|
|
***************
|
|
*** 924,929 ****
|
|
--- 976,1010 ----
|
|
if(curwp->w_marko > 0 && curwp->w_marko < llength(curwp->w_markp))
|
|
ends_midline++;
|
|
|
|
+ for (i = 0; (i < NSTRING) && qstr && (quoid[i] = qstr[i]); i++);
|
|
+ for (j = 0; ((i + j) < NSTRING) && istr && (quoid[i] = istr[j]); i++,j++);
|
|
+ quoid[i] = '\0';
|
|
+ qi = ucs4_strlen(quoid);
|
|
+ if (istr) /* strip trailing spaces */
|
|
+ for (;ISspace(quoid[qi - 1]); qi--);
|
|
+ quoid[qi] = '\0'; /* we have closed quoid at "X" in the first line */
|
|
+
|
|
+ if (ucs4_strlenis(quoid) > fillcol)
|
|
+ return FALSE; /* Too wide, we can't justify this! */
|
|
+
|
|
+ if (qstr && istr){
|
|
+ for (i = ucs4_strlen(qstr) - 1; ISspace(qstr[i]); i--);
|
|
+ qstr[i + 1] = '\0'; /* qstrfl */
|
|
+ }
|
|
+ qlen = ucs4_strlen(qstr); /* qstrfl*/
|
|
+ qlenis = ucs4_strlenis(qstr);
|
|
+
|
|
+ for(i = 0, qstr2[0] = '\0'; qstr && qstr[i] && (qstr2[i] = qstr[i]); i++);
|
|
+
|
|
+ if (istr && ((j = ucs4_widthis(quoid) - ucs4_widthis(qstr)) > 0)){
|
|
+ pqi = ucs4_strlen(qstr);
|
|
+ for (i = 0; (i < j) && (qstr2[pqi + i] = ' '); i++);
|
|
+ if (ISspace(istr[ucs4_strlen(istr) - 1]))
|
|
+ qstr2[pqi + i++] = ' ';
|
|
+ qstr2[pqi + i] = '\0';
|
|
+ qstr = qstr2;
|
|
+ }
|
|
+
|
|
/* cut the paragraph into our fill buffer */
|
|
fdelete();
|
|
if(!getregion(®ion, curwp->w_markp, curwp->w_marko))
|
|
***************
|
|
*** 940,967 ****
|
|
|
|
/* Now insert it back wrapped */
|
|
spaces = word_len = word_ind = line_len = same_word = 0;
|
|
- qlen = qstr ? ucs4_strlen(qstr) : 0;
|
|
|
|
/* Beginning with leading quoting... */
|
|
! if(qstr){
|
|
! i = 0;
|
|
! while(qstr[i]){
|
|
! ww = wcellwidth(qstr[i]);
|
|
! line_len += (ww >= 0 ? ww : 1);
|
|
! linsert(1, qstr[i++]);
|
|
! }
|
|
|
|
line_last = ' '; /* no word-flush space! */
|
|
}
|
|
|
|
/* remove first leading quotes if any */
|
|
if(starts_midline)
|
|
i = 0;
|
|
! else
|
|
! for(i = qlen; (c = fremove(i)) == ' ' || c == TAB; i++){
|
|
linsert(1, line_last = (UCS) c);
|
|
line_len += ((c == TAB) ? (~line_len & 0x07) + 1 : 1);
|
|
}
|
|
|
|
/* then digest the rest... */
|
|
while((c = fremove(i++)) >= 0){
|
|
--- 1021,1056 ----
|
|
|
|
/* Now insert it back wrapped */
|
|
spaces = word_len = word_ind = line_len = same_word = 0;
|
|
|
|
/* Beginning with leading quoting... */
|
|
! if(qstr || istr){
|
|
! for(i = 0; quoid[i] != '\0' ; i++)
|
|
! linsert(1, quoid[i]);
|
|
|
|
line_last = ' '; /* no word-flush space! */
|
|
+ line_len = ucs4_strlenis(quoid); /* we demand a recount! */
|
|
}
|
|
|
|
/* remove first leading quotes if any */
|
|
if(starts_midline)
|
|
i = 0;
|
|
! else{
|
|
! if(qstr || istr){
|
|
! for (i = 0; (c = fremove(i)) != '\0'; i++){
|
|
! word[i] = c;
|
|
! word[i+1] = '\0';
|
|
! if(ucs4_strlenis(word) >= ucs4_strlenis(quoid))
|
|
! break;
|
|
! }
|
|
! i++;
|
|
! }
|
|
! else
|
|
! i = 0;
|
|
! for(; ISspace(c = fremove(i)); i++){
|
|
linsert(1, line_last = (UCS) c);
|
|
line_len += ((c == TAB) ? (~line_len & 0x07) + 1 : 1);
|
|
}
|
|
+ }
|
|
|
|
/* then digest the rest... */
|
|
while((c = fremove(i++)) >= 0){
|
|
***************
|
|
*** 982,1002 ****
|
|
|
|
case TAB :
|
|
case ' ' :
|
|
spaces++;
|
|
break;
|
|
|
|
default :
|
|
if(spaces){ /* flush word? */
|
|
! if((line_len - qlen > 0)
|
|
&& line_len + word_len + 1 > fillcol
|
|
! && ((ucs4_isspace(line_last))
|
|
|| (linsert(1, ' ')))
|
|
&& same_word == 0
|
|
&& (line_len = fpnewline(qstr)))
|
|
line_last = ' '; /* no word-flush space! */
|
|
|
|
if(word_len){ /* word to write? */
|
|
! if(line_len && !ucs4_isspace(line_last)){
|
|
linsert(1, ' '); /* need padding? */
|
|
line_len++;
|
|
}
|
|
--- 1071,1092 ----
|
|
|
|
case TAB :
|
|
case ' ' :
|
|
+ case NBSP:
|
|
spaces++;
|
|
break;
|
|
|
|
default :
|
|
if(spaces){ /* flush word? */
|
|
! if((line_len - qlenis > 0)
|
|
&& line_len + word_len + 1 > fillcol
|
|
! && ((ISspace(line_last))
|
|
|| (linsert(1, ' ')))
|
|
&& same_word == 0
|
|
&& (line_len = fpnewline(qstr)))
|
|
line_last = ' '; /* no word-flush space! */
|
|
|
|
if(word_len){ /* word to write? */
|
|
! if(line_len && !ISspace(line_last)){
|
|
linsert(1, ' '); /* need padding? */
|
|
line_len++;
|
|
}
|
|
***************
|
|
*** 1018,1025 ****
|
|
|
|
if(word_ind + 1 >= NSTRING){
|
|
/* Magic! Fake that we output a wrapped word */
|
|
! if((line_len - qlen > 0) && same_word == 0){
|
|
! if(!ucs4_isspace(line_last))
|
|
linsert(1, ' ');
|
|
line_len = fpnewline(qstr);
|
|
}
|
|
--- 1108,1115 ----
|
|
|
|
if(word_ind + 1 >= NSTRING){
|
|
/* Magic! Fake that we output a wrapped word */
|
|
! if((line_len - qlenis > 0) && same_word == 0){
|
|
! if(!ISspace(line_last))
|
|
linsert(1, ' ');
|
|
line_len = fpnewline(qstr);
|
|
}
|
|
***************
|
|
*** 1041,1052 ****
|
|
}
|
|
|
|
if(word_len){
|
|
! if((line_len - qlen > 0) && (line_len + word_len + 1 > fillcol) && same_word == 0){
|
|
! if(!ucs4_isspace(line_last))
|
|
linsert(1, ' ');
|
|
(void) fpnewline(qstr);
|
|
}
|
|
! else if(line_len && !ucs4_isspace(line_last))
|
|
linsert(1, ' ');
|
|
|
|
for(j = 0; j < word_ind; j++)
|
|
--- 1131,1142 ----
|
|
}
|
|
|
|
if(word_len){
|
|
! if((line_len - qlenis > 0) && (line_len + word_len + 1 > fillcol) && same_word == 0){
|
|
! if(!ISspace(line_last))
|
|
linsert(1, ' ');
|
|
(void) fpnewline(qstr);
|
|
}
|
|
! else if(line_len && !ISspace(line_last))
|
|
linsert(1, ' ');
|
|
|
|
for(j = 0; j < word_ind; j++)
|
|
***************
|
|
*** 1104,1114 ****
|
|
int len;
|
|
|
|
lnewline();
|
|
! for(len = 0; quote && *quote; quote++){
|
|
int ww;
|
|
|
|
! ww = wcellwidth(*quote);
|
|
! len += (ww >= 0 ? ww : 1);
|
|
linsert(1, *quote);
|
|
}
|
|
|
|
--- 1194,1204 ----
|
|
int len;
|
|
|
|
lnewline();
|
|
! for(len = ucs4_strlenis(quote); quote && *quote; quote++){
|
|
int ww;
|
|
|
|
! /* ww = wcellwidth(*quote);
|
|
! len += (ww >= 0 ? ww : 1);*/
|
|
linsert(1, *quote);
|
|
}
|
|
|
|
***************
|
|
*** 1252,1256 ****
|
|
--- 1342,1386 ----
|
|
markregion(1);
|
|
}
|
|
|
|
+ /*
|
|
+ * This puts us at the end of the quoted region instead
|
|
+ * of on the following line. This makes it convenient
|
|
+ * for the user to follow a quotelevel adjustment with
|
|
+ * a Justify if desired.
|
|
+ */
|
|
+ if(backuptoprevline){
|
|
+ curwp->w_doto = 0;
|
|
+ backchar(0, 1);
|
|
+ }
|
|
+
|
|
+ if(ends_midline){ /* doesn't need fixing otherwise */
|
|
+ unmarkbuffer();
|
|
+ markregion(1);
|
|
+ }
|
|
+
|
|
return (TRUE);
|
|
}
|
|
+
|
|
+ /*
|
|
+ * If there is an indent string this function returns
|
|
+ * its length
|
|
+ */
|
|
+ int
|
|
+ indent_match(char **q, LINE *l, char *buf, int buflen, int raw)
|
|
+ {
|
|
+ char GLine[NSTRING];
|
|
+ int i, k, plb;
|
|
+
|
|
+ k = quote_match(q,l, buf, buflen, raw);
|
|
+ linencpy(GLine, l, NSTRING);
|
|
+ plb = (lback(l) != curbp->b_linep) ? lisblank(lback(l)) : 1;
|
|
+ if (!plb){
|
|
+ i = llength(lback(l)) - 1;
|
|
+ for (; i >= 0 && ISspace(lgetc(lback(l), i).c); i--);
|
|
+ if (EOLchar(lgetc(lback(l), i).c))
|
|
+ plb++;
|
|
+ }
|
|
+
|
|
+ return get_indent_raw_line(q, GLine, buf, buflen, k, plb);
|
|
+ }
|
|
+
|
|
diff -rc alpine-2.26/pith/charconv/utf8.c alpine-2.26.fillpara/pith/charconv/utf8.c
|
|
*** alpine-2.26/pith/charconv/utf8.c 2022-06-02 18:14:00.495274738 -0600
|
|
--- alpine-2.26.fillpara/pith/charconv/utf8.c 2022-06-02 18:14:57.019136141 -0600
|
|
***************
|
|
*** 1113,1118 ****
|
|
--- 1113,1168 ----
|
|
|
|
|
|
/*
|
|
+ * Returns the screen cells width of the UTF-8 string argument, treating tabs
|
|
+ * in a special way.
|
|
+ */
|
|
+ unsigned
|
|
+ utf8_widthis(char *str)
|
|
+ {
|
|
+ unsigned width = 0;
|
|
+ int this_width;
|
|
+ UCS ucs;
|
|
+ unsigned long remaining_octets;
|
|
+ char *readptr;
|
|
+
|
|
+ if(!(str && *str))
|
|
+ return(width);
|
|
+
|
|
+ readptr = str;
|
|
+ remaining_octets = readptr ? strlen(readptr) : 0;
|
|
+
|
|
+ while(remaining_octets > 0 && *readptr){
|
|
+
|
|
+ ucs = (UCS) utf8_get((unsigned char **) &readptr, &remaining_octets);
|
|
+
|
|
+ if(ucs & U8G_ERROR){
|
|
+ /*
|
|
+ * This should not happen, but do something to handle it anyway.
|
|
+ * Treat each character as a single width character, which is what should
|
|
+ * probably happen when we actually go to write it out.
|
|
+ */
|
|
+ remaining_octets--;
|
|
+ readptr++;
|
|
+ this_width = 1;
|
|
+ }
|
|
+ else{
|
|
+ this_width = (ucs == TAB) ? ((~width & 0x07) + 1) : wcellwidth(ucs);
|
|
+
|
|
+ /*
|
|
+ * If this_width is -1 that means we can't print this character
|
|
+ * with our current locale. Writechar will print a '?'.
|
|
+ */
|
|
+ if(this_width < 0)
|
|
+ this_width = 1;
|
|
+ }
|
|
+
|
|
+ width += (unsigned) this_width;
|
|
+ }
|
|
+
|
|
+ return(width);
|
|
+ }
|
|
+
|
|
+ /*
|
|
* Copy UTF-8 characters from src into dst.
|
|
* This is intended to be used if you want to truncate a string at
|
|
* the start instead of the end. For example, you have a long string
|
|
diff -rc alpine-2.26/pith/charconv/utf8.h alpine-2.26.fillpara/pith/charconv/utf8.h
|
|
*** alpine-2.26/pith/charconv/utf8.h 2022-06-02 18:14:00.495274738 -0600
|
|
--- alpine-2.26.fillpara/pith/charconv/utf8.h 2022-06-02 18:14:57.023136132 -0600
|
|
***************
|
|
*** 82,87 ****
|
|
--- 82,88 ----
|
|
UCS *ucs4_strchr(UCS *s, UCS c);
|
|
UCS *ucs4_strrchr(UCS *s, UCS c);
|
|
unsigned utf8_width(char *);
|
|
+ unsigned utf8_widthis(char *);
|
|
size_t utf8_to_width_rhs(char *, char *, size_t, unsigned);
|
|
int utf8_snprintf(char *, size_t, char *, ...);
|
|
size_t utf8_to_width(char *, char *, size_t, unsigned, unsigned *);
|
|
diff -rc alpine-2.26/pith/color.c alpine-2.26.fillpara/pith/color.c
|
|
*** alpine-2.26/pith/color.c 2022-06-02 18:14:00.491274749 -0600
|
|
--- alpine-2.26.fillpara/pith/color.c 2022-06-02 18:14:57.023136132 -0600
|
|
***************
|
|
*** 17,23 ****
|
|
#include "../pith/state.h"
|
|
#include "../pith/conf.h"
|
|
#include "../pith/filter.h"
|
|
!
|
|
|
|
char *
|
|
color_embed(char *fg, char *bg)
|
|
--- 17,24 ----
|
|
#include "../pith/state.h"
|
|
#include "../pith/conf.h"
|
|
#include "../pith/filter.h"
|
|
! #include "../pith/mailview.h"
|
|
! #include "../pico/estruct.h"
|
|
|
|
char *
|
|
color_embed(char *fg, char *bg)
|
|
***************
|
|
*** 66,88 ****
|
|
struct quote_colors *next;
|
|
};
|
|
|
|
|
|
int
|
|
color_a_quote(long int linenum, char *line, LT_INS_S **ins, void *is_flowed_msg)
|
|
{
|
|
! int countem = 0;
|
|
struct variable *vars = ps_global->vars;
|
|
! char *p;
|
|
struct quote_colors *colors = NULL, *cp, *next;
|
|
COLOR_PAIR *col = NULL;
|
|
int is_flowed = is_flowed_msg ? *((int *)is_flowed_msg) : 0;
|
|
|
|
p = line;
|
|
! if(!is_flowed)
|
|
! while(isspace((unsigned char)*p))
|
|
! p++;
|
|
|
|
! if(p[0] == '>'){
|
|
struct quote_colors *c;
|
|
|
|
/*
|
|
--- 67,176 ----
|
|
struct quote_colors *next;
|
|
};
|
|
|
|
+ int
|
|
+ is_word (buf, i, j)
|
|
+ char buf[NSTRING];
|
|
+ int i, j;
|
|
+ {
|
|
+ return i <= j && is_letter(buf[i]) ?
|
|
+ (i < j ? is_word(buf,i+1,j) : 1) : 0;
|
|
+ }
|
|
+
|
|
+ int
|
|
+ is_mailbox(buf,i,j)
|
|
+ char buf[NSTRING];
|
|
+ int i, j;
|
|
+ {
|
|
+ return i <= j && (is_letter(buf[i]) || is_digit(buf[i]) || buf[i] == '.')
|
|
+ ? (i < j ? is_mailbox(buf,i+1,j) : 1) : 0;
|
|
+ }
|
|
+
|
|
+ int
|
|
+ next_level_quote(buf, line, i, is_flowed)
|
|
+ char *buf;
|
|
+ char **line;
|
|
+ int i;
|
|
+ int is_flowed;
|
|
+ {
|
|
+ int j;
|
|
+
|
|
+ if (!single_level(buf[i])){
|
|
+ if(is_mailbox(buf,i,i)){
|
|
+ for (j = i; buf[j] && !isspace(buf[j]); j++);
|
|
+ if (is_word(buf,i,j-1) || is_mailbox(buf,i,j-1))
|
|
+ j += isspace(buf[j]) ? 2 : 1;
|
|
+ }
|
|
+ else{
|
|
+ switch(buf[i]){
|
|
+ case ':' :
|
|
+ if (next(buf,i) != RPAREN)
|
|
+ j = i + 1;
|
|
+ else
|
|
+ j = i + 2;
|
|
+ break;
|
|
+
|
|
+ case '-' :
|
|
+ if (next(buf,i) != '-')
|
|
+ j = i + 2;
|
|
+ else
|
|
+ j = i + 3;
|
|
+ break;
|
|
+
|
|
+ case '+' :
|
|
+ case '*' :
|
|
+ if (next(buf,i) != ' ')
|
|
+ j = i + 2;
|
|
+ else
|
|
+ j = i + 3;
|
|
+ break;
|
|
+
|
|
+ default :
|
|
+ for (j = i; buf[j] && !isspace(buf[j])
|
|
+ && (!single_level(buf[i]) && !is_letter(buf[j])); j++);
|
|
+
|
|
+ j += isspace(buf[j]) ? 1 : 0;
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ if (line && *line)
|
|
+ (*line) += j - i;
|
|
+ }
|
|
+ else{
|
|
+ j = i+1;
|
|
+ if (line && *line)
|
|
+ (*line)++;
|
|
+ }
|
|
+ if(!is_flowed){
|
|
+ if(line && *line)
|
|
+ for(; isspace((unsigned char)*(*line)); (*line)++);
|
|
+ for (i = j; isspace((unsigned char) buf[i]); i++);
|
|
+ }
|
|
+ else i = j;
|
|
+ if (is_flowed && i != j)
|
|
+ buf[i] = '\0';
|
|
+ return i;
|
|
+ }
|
|
|
|
int
|
|
color_a_quote(long int linenum, char *line, LT_INS_S **ins, void *is_flowed_msg)
|
|
{
|
|
! int countem = 0, i, j = 0;
|
|
struct variable *vars = ps_global->vars;
|
|
! char *p, buf[NSTRING] = {'\0'};
|
|
struct quote_colors *colors = NULL, *cp, *next;
|
|
COLOR_PAIR *col = NULL;
|
|
int is_flowed = is_flowed_msg ? *((int *)is_flowed_msg) : 0;
|
|
+ int code;
|
|
+
|
|
+ code = (is_flowed ? IS_FLOWED : NO_FLOWED) | COLORAQUO;
|
|
+ select_quote(linenum, line, ins, (void *) &code);
|
|
+ strncpy(buf, tmp_20k_buf, NSTRING < SIZEOF_20KBUF ? NSTRING : SIZEOF_20KBUF);
|
|
+ buf[sizeof(buf)-1] = '\0';
|
|
|
|
p = line;
|
|
! for(i = 0; isspace((unsigned char)buf[i]); i++, p++);
|
|
|
|
! if(buf[i]){
|
|
struct quote_colors *c;
|
|
|
|
/*
|
|
***************
|
|
*** 131,137 ****
|
|
free_color_pair(&col);
|
|
|
|
cp = NULL;
|
|
! while(*p == '>'){
|
|
cp = (cp && cp->next) ? cp->next : colors;
|
|
|
|
if(countem > 0)
|
|
--- 219,225 ----
|
|
free_color_pair(&col);
|
|
|
|
cp = NULL;
|
|
! while(buf[i]){
|
|
cp = (cp && cp->next) ? cp->next : colors;
|
|
|
|
if(countem > 0)
|
|
***************
|
|
*** 141,150 ****
|
|
|
|
countem = (countem == 1) ? 0 : countem;
|
|
|
|
! p++;
|
|
! if(!is_flowed)
|
|
! for(; isspace((unsigned char)*p); p++)
|
|
! ;
|
|
}
|
|
|
|
if(colors){
|
|
--- 229,237 ----
|
|
|
|
countem = (countem == 1) ? 0 : countem;
|
|
|
|
! i = next_level_quote(buf, &p, i, is_flowed);
|
|
! for (; isspace((unsigned char)*p); p++);
|
|
! for (; isspace((unsigned char)buf[i]); i++);
|
|
}
|
|
|
|
if(colors){
|
|
***************
|
|
*** 207,213 ****
|
|
}
|
|
}
|
|
|
|
! return(0);
|
|
}
|
|
|
|
|
|
--- 294,300 ----
|
|
}
|
|
}
|
|
|
|
! return(1);
|
|
}
|
|
|
|
|
|
diff -rc alpine-2.26/pith/color.h alpine-2.26.fillpara/pith/color.h
|
|
*** alpine-2.26/pith/color.h 2022-06-02 18:14:00.495274738 -0600
|
|
--- alpine-2.26.fillpara/pith/color.h 2022-06-02 18:14:57.027136121 -0600
|
|
***************
|
|
*** 22,27 ****
|
|
--- 22,45 ----
|
|
#include "../pith/pattern.h"
|
|
#include "../pith/osdep/color.h"
|
|
|
|
+ #define NO_FLOWED 0x0000
|
|
+ #define IS_FLOWED 0x0001
|
|
+ #define DELETEQUO 0x0010
|
|
+ #define COLORAQUO 0x0100
|
|
+ #define RAWSTRING 0x1000
|
|
+
|
|
+ /* This is needed for justification, I will move it to a better place later
|
|
+ * or maybe not
|
|
+ */
|
|
+ #define is_digit(c) ((((c) >= '0') && ((c) <= '9')) ? 1 : 0)
|
|
+
|
|
+ #define is_letter(c) (((c) >= 'a' && (c) <= 'z') || \
|
|
+ ((c) >= 'A' && (c) <= 'Z'))
|
|
+
|
|
+ #define next(w,i) ((((w)[(i)]) != 0) ? ((w)[(i) + 1]) : 0)
|
|
+
|
|
+ #define single_level(c) (((c) == '>') || ((c) == '|') || ((c) == '~') || \
|
|
+ ((c) == ']'))
|
|
|
|
typedef struct spec_color_s {
|
|
int inherit; /* this isn't a color, it is INHERIT */
|
|
***************
|
|
*** 81,86 ****
|
|
--- 99,105 ----
|
|
/* exported prototypes */
|
|
char *color_embed(char *, char *);
|
|
int colorcmp(char *, char *);
|
|
+ int next_level_quote(char *, char **, int, int);
|
|
int color_a_quote(long, char *, LT_INS_S **, void *);
|
|
void free_spec_colors(SPEC_COLOR_S **);
|
|
|
|
diff -rc alpine-2.26/pith/filter.c alpine-2.26.fillpara/pith/filter.c
|
|
*** alpine-2.26/pith/filter.c 2022-06-02 18:14:00.491274749 -0600
|
|
--- alpine-2.26.fillpara/pith/filter.c 2022-06-02 18:14:57.031136112 -0600
|
|
***************
|
|
*** 42,47 ****
|
|
--- 42,48 ----
|
|
#include "../pith/conf.h"
|
|
#include "../pith/store.h"
|
|
#include "../pith/color.h"
|
|
+ #include "../pith/osdep/color.h"
|
|
#include "../pith/escapes.h"
|
|
#include "../pith/pipe.h"
|
|
#include "../pith/status.h"
|
|
***************
|
|
*** 9503,9508 ****
|
|
--- 9504,9514 ----
|
|
margin_r,
|
|
indent;
|
|
char special[256];
|
|
+ long curlinenum; /* current line number */
|
|
+ int curqstrpos; /* current position in quote string */
|
|
+ long linenum; /* line number */
|
|
+ long qstrlen; /* multiples of 100 */
|
|
+ char **qstrln; /* qstrln[i] = quote string line i - 1 */
|
|
} WRAP_S;
|
|
|
|
#define WRAP_MARG_L(F) (((WRAP_S *)(F)->opt)->margin_l)
|
|
***************
|
|
*** 9544,9549 ****
|
|
--- 9550,9561 ----
|
|
#define WRAP_COLOR(F) (((WRAP_S *)(F)->opt)->color)
|
|
#define WRAP_COLOR_SET(F) ((WRAP_COLOR(F)) && (WRAP_COLOR(F)->fg[0]))
|
|
#define WRAP_SPACES(F) (((WRAP_S *)(F)->opt)->spaces)
|
|
+ #define WRAP_CURLINE(F) (((WRAP_S *)(F)->opt)->curlinenum)
|
|
+ #define WRAP_CURPOS(F) (((WRAP_S *)(F)->opt)->curqstrpos)
|
|
+ #define WRAP_LINENUM(F) (((WRAP_S *)(F)->opt)->linenum)
|
|
+ #define WRAP_QSTRLEN(F) (((WRAP_S *)(F)->opt)->qstrlen)
|
|
+ #define WRAP_QSTRN(F) (((WRAP_S *)(F)->opt)->qstrln)
|
|
+ #define WRAP_QSTR(F, N) (((WRAP_S *)(F)->opt)->qstrln[(N)])
|
|
#define WRAP_PUTC(F,C,W) { \
|
|
if((F)->linep == WRAP_LASTC(F)){ \
|
|
size_t offset = (F)->linep - (F)->line; \
|
|
***************
|
|
*** 9621,9626 ****
|
|
--- 9633,9640 ----
|
|
case CCR : /* CRLF or CR in text ? */
|
|
state = BOL; /* either way, handle start */
|
|
|
|
+ WRAP_CURLINE(f)++;
|
|
+ WRAP_CURPOS(f) = 0;
|
|
if(WRAP_FLOW(f)){
|
|
/* wrapped line? */
|
|
if(f->f2 == 0 && WRAP_SPC_LEN(f) && WRAP_TRL_SPC(f)){
|
|
***************
|
|
*** 9714,9720 ****
|
|
|
|
case BOL :
|
|
if(WRAP_FLOW(f)){
|
|
! if(c == '>'){
|
|
WRAP_FL_QC(f) = 1; /* init it */
|
|
state = FL_QLEV; /* go collect it */
|
|
}
|
|
--- 9728,9738 ----
|
|
|
|
case BOL :
|
|
if(WRAP_FLOW(f)){
|
|
! if(WRAP_CURLINE(f) < WRAP_QSTRLEN(f)
|
|
! && WRAP_QSTR(f, WRAP_CURLINE(f))
|
|
! && WRAP_QSTR(f, WRAP_CURLINE(f))[WRAP_CURPOS(f)]
|
|
! && WRAP_QSTR(f, WRAP_CURLINE(f))[WRAP_CURPOS(f)] == c){
|
|
! WRAP_CURPOS(f)++;
|
|
WRAP_FL_QC(f) = 1; /* init it */
|
|
state = FL_QLEV; /* go collect it */
|
|
}
|
|
***************
|
|
*** 9728,9734 ****
|
|
}
|
|
|
|
/* quote level change implies new paragraph */
|
|
! if(WRAP_FL_QD(f)){
|
|
WRAP_FL_QD(f) = 0;
|
|
if(WRAP_HARD(f) == 0){
|
|
WRAP_HARD(f) = 1;
|
|
--- 9746,9761 ----
|
|
}
|
|
|
|
/* quote level change implies new paragraph */
|
|
! if (WRAP_CURLINE(f) > 0
|
|
! && WRAP_CURLINE(f) < WRAP_QSTRLEN(f)
|
|
! && (WRAP_QSTR(f, WRAP_CURLINE(f)) != NULL
|
|
! || WRAP_QSTR(f, WRAP_CURLINE(f) - 1) != NULL)
|
|
! && ((WRAP_QSTR(f, WRAP_CURLINE(f)) != NULL &&
|
|
! WRAP_QSTR(f, WRAP_CURLINE(f) - 1) == NULL)
|
|
! || (WRAP_QSTR(f, WRAP_CURLINE(f)) == NULL &&
|
|
! WRAP_QSTR(f, WRAP_CURLINE(f) - 1) != NULL)
|
|
! || strcmp(WRAP_QSTR(f, WRAP_CURLINE(f)),
|
|
! WRAP_QSTR(f, WRAP_CURLINE(f) - 1)))){
|
|
WRAP_FL_QD(f) = 0;
|
|
if(WRAP_HARD(f) == 0){
|
|
WRAP_HARD(f) = 1;
|
|
***************
|
|
*** 9780,9787 ****
|
|
break;
|
|
|
|
case FL_QLEV :
|
|
! if(c == '>'){ /* another level */
|
|
! WRAP_FL_QC(f)++;
|
|
}
|
|
else {
|
|
/* if EMBEDed, process it and return here */
|
|
--- 9807,9818 ----
|
|
break;
|
|
|
|
case FL_QLEV :
|
|
! if(WRAP_CURLINE(f) < WRAP_QSTRLEN(f)
|
|
! && WRAP_QSTR(f, WRAP_CURLINE(f))
|
|
! && WRAP_QSTR(f, WRAP_CURLINE(f))[WRAP_CURPOS(f)]
|
|
! && WRAP_QSTR(f, WRAP_CURLINE(f))[WRAP_CURPOS(f)] == c){
|
|
! WRAP_CURPOS(f)++;
|
|
! WRAP_FL_QC(f)++; /* another level */
|
|
}
|
|
else {
|
|
/* if EMBEDed, process it and return here */
|
|
***************
|
|
*** 9793,9799 ****
|
|
}
|
|
|
|
/* quote level change signals new paragraph */
|
|
! if(WRAP_FL_QC(f) != WRAP_FL_QD(f)){
|
|
WRAP_FL_QD(f) = WRAP_FL_QC(f);
|
|
if(WRAP_HARD(f) == 0){ /* add hard newline */
|
|
WRAP_HARD(f) = 1; /* hard newline */
|
|
--- 9824,9839 ----
|
|
}
|
|
|
|
/* quote level change signals new paragraph */
|
|
! if (WRAP_CURLINE(f) > 0
|
|
! && WRAP_CURLINE(f) < WRAP_QSTRLEN(f)
|
|
! && (WRAP_QSTR(f, WRAP_CURLINE(f))
|
|
! || WRAP_QSTR(f, WRAP_CURLINE(f) - 1))
|
|
! && ((WRAP_QSTR(f, WRAP_CURLINE(f)) &&
|
|
! !WRAP_QSTR(f, WRAP_CURLINE(f) - 1))
|
|
! || (!WRAP_QSTR(f, WRAP_CURLINE(f)) &&
|
|
! WRAP_QSTR(f, WRAP_CURLINE(f) - 1))
|
|
! || strcmp(WRAP_QSTR(f, WRAP_CURLINE(f)),
|
|
! WRAP_QSTR(f, WRAP_CURLINE(f) - 1)))){
|
|
WRAP_FL_QD(f) = WRAP_FL_QC(f);
|
|
if(WRAP_HARD(f) == 0){ /* add hard newline */
|
|
WRAP_HARD(f) = 1; /* hard newline */
|
|
***************
|
|
*** 9850,9855 ****
|
|
--- 9890,9902 ----
|
|
state = FL_SIG;
|
|
break;
|
|
|
|
+ case ' ' : /* what? */
|
|
+ if (WRAP_CURLINE(f) < WRAP_QSTRLEN(f)
|
|
+ && WRAP_QSTR(f, WRAP_CURLINE(f))){
|
|
+ WRAP_SPC_LEN(f)++;
|
|
+ so_writec(' ', WRAP_SPACES(f));
|
|
+ }
|
|
+
|
|
default : /* something else */
|
|
state = DFL;
|
|
goto case_dfl; /* handle c like DFL */
|
|
***************
|
|
*** 9866,9872 ****
|
|
&eob); /* note any embedded*/
|
|
wrap_eol(f, 1, &ip, &eib,
|
|
&op, &eob); /* plunk down newline */
|
|
! wrap_bol(f, 1, 1, &ip, &eib,
|
|
&op, &eob); /* write any prefix */
|
|
}
|
|
|
|
--- 9913,9919 ----
|
|
&eob); /* note any embedded*/
|
|
wrap_eol(f, 1, &ip, &eib,
|
|
&op, &eob); /* plunk down newline */
|
|
! wrap_bol(f, 1, WRAP_FLOW(f), &ip, &eib,
|
|
&op, &eob); /* write any prefix */
|
|
}
|
|
|
|
***************
|
|
*** 10363,10369 ****
|
|
wrap_flush_embed(f, &ip, &eib, &op, &eob);
|
|
wrap_eol(f, 1, &ip, &eib, &op,
|
|
&eob); /* plunk down newline */
|
|
! wrap_bol(f,1,1, &ip, &eib, &op,
|
|
&eob); /* write any prefix */
|
|
}
|
|
|
|
--- 10410,10416 ----
|
|
wrap_flush_embed(f, &ip, &eib, &op, &eob);
|
|
wrap_eol(f, 1, &ip, &eib, &op,
|
|
&eob); /* plunk down newline */
|
|
! wrap_bol(f,1,WRAP_FLOW(f), &ip, &eib, &op,
|
|
&eob); /* write any prefix */
|
|
}
|
|
|
|
***************
|
|
*** 10436,10441 ****
|
|
--- 10483,10495 ----
|
|
if(WRAP_COLOR(f))
|
|
free_color_pair(&WRAP_COLOR(f));
|
|
|
|
+ { long i;
|
|
+ for (i = 0L; i < WRAP_QSTRLEN(f); i++)
|
|
+ if (WRAP_QSTR(f,i))
|
|
+ fs_give((void **) &(WRAP_QSTR(f,i)));
|
|
+ fs_give((void **)&WRAP_QSTRN(f));
|
|
+ }
|
|
+
|
|
fs_give((void **) &f->line); /* free temp line buffer */
|
|
so_give(&WRAP_SPACES(f));
|
|
fs_give((void **) &f->opt); /* free wrap widths struct */
|
|
***************
|
|
*** 10786,10792 ****
|
|
{
|
|
int j, i;
|
|
COLOR_PAIR *col = NULL;
|
|
! char *prefix = NULL, *last_prefix = NULL;
|
|
|
|
if(ps_global->VAR_QUOTE_REPLACE_STRING){
|
|
get_pair(ps_global->VAR_QUOTE_REPLACE_STRING, &prefix, &last_prefix, 0, 0);
|
|
--- 10840,10847 ----
|
|
{
|
|
int j, i;
|
|
COLOR_PAIR *col = NULL;
|
|
! char *prefix = NULL, *last_prefix = NULL, *wrap_qstr = NULL;
|
|
! int level = 0, oldj, len;
|
|
|
|
if(ps_global->VAR_QUOTE_REPLACE_STRING){
|
|
get_pair(ps_global->VAR_QUOTE_REPLACE_STRING, &prefix, &last_prefix, 0, 0);
|
|
***************
|
|
*** 10795,10804 ****
|
|
last_prefix = NULL;
|
|
}
|
|
}
|
|
!
|
|
! for(j = 0; j < WRAP_FL_QD(f); j++){
|
|
if(WRAP_USE_CLR(f)){
|
|
! if((j % 3) == 0
|
|
&& ps_global->VAR_QUOTE1_FORE_COLOR
|
|
&& ps_global->VAR_QUOTE1_BACK_COLOR
|
|
&& (col = new_color_pair(ps_global->VAR_QUOTE1_FORE_COLOR,
|
|
--- 10850,10871 ----
|
|
last_prefix = NULL;
|
|
}
|
|
}
|
|
!
|
|
! if(WRAP_CURLINE(f) < WRAP_QSTRLEN(f) && WRAP_QSTR(f, WRAP_CURLINE(f)))
|
|
! wrap_qstr = cpystr(WRAP_QSTR(f, WRAP_CURLINE(f)));
|
|
! len = wrap_qstr ? strlen(wrap_qstr) : 0;
|
|
!
|
|
! for (j = wrap_qstr && *wrap_qstr == ' ' ? 1 : 0;
|
|
! j < len && isspace((unsigned char)wrap_qstr[j]); j++){
|
|
! GF_PUTC_GLO(f->next, wrap_qstr[j]);
|
|
! f->n += ((wrap_qstr[j] == TAB) ? (~f->n & 0x07) + 1 : 1);
|
|
! }
|
|
!
|
|
! for(; j < len && level < len; level++){
|
|
! oldj = j;
|
|
! j = next_level_quote(wrap_qstr, (char **)NULL, j, WRAP_FLOW(f));
|
|
if(WRAP_USE_CLR(f)){
|
|
! if((level % 3) == 0
|
|
&& ps_global->VAR_QUOTE1_FORE_COLOR
|
|
&& ps_global->VAR_QUOTE1_BACK_COLOR
|
|
&& (col = new_color_pair(ps_global->VAR_QUOTE1_FORE_COLOR,
|
|
***************
|
|
*** 10806,10812 ****
|
|
&& pico_is_good_colorpair(col)){
|
|
GF_COLOR_PUTC(f, col);
|
|
}
|
|
! else if((j % 3) == 1
|
|
&& ps_global->VAR_QUOTE2_FORE_COLOR
|
|
&& ps_global->VAR_QUOTE2_BACK_COLOR
|
|
&& (col = new_color_pair(ps_global->VAR_QUOTE2_FORE_COLOR,
|
|
--- 10873,10879 ----
|
|
&& pico_is_good_colorpair(col)){
|
|
GF_COLOR_PUTC(f, col);
|
|
}
|
|
! else if((level % 3) == 1
|
|
&& ps_global->VAR_QUOTE2_FORE_COLOR
|
|
&& ps_global->VAR_QUOTE2_BACK_COLOR
|
|
&& (col = new_color_pair(ps_global->VAR_QUOTE2_FORE_COLOR,
|
|
***************
|
|
*** 10814,10820 ****
|
|
&& pico_is_good_colorpair(col)){
|
|
GF_COLOR_PUTC(f, col);
|
|
}
|
|
! else if((j % 3) == 2
|
|
&& ps_global->VAR_QUOTE3_FORE_COLOR
|
|
&& ps_global->VAR_QUOTE3_BACK_COLOR
|
|
&& (col = new_color_pair(ps_global->VAR_QUOTE3_FORE_COLOR,
|
|
--- 10881,10887 ----
|
|
&& pico_is_good_colorpair(col)){
|
|
GF_COLOR_PUTC(f, col);
|
|
}
|
|
! else if((level % 3) == 2
|
|
&& ps_global->VAR_QUOTE3_FORE_COLOR
|
|
&& ps_global->VAR_QUOTE3_BACK_COLOR
|
|
&& (col = new_color_pair(ps_global->VAR_QUOTE3_FORE_COLOR,
|
|
***************
|
|
*** 10828,10870 ****
|
|
}
|
|
}
|
|
|
|
if(!WRAP_LV_FLD(f)){
|
|
if(!WRAP_FOR_CMPS(f) && ps_global->VAR_QUOTE_REPLACE_STRING && prefix){
|
|
for(i = 0; prefix[i]; i++)
|
|
GF_PUTC_GLO(f->next, prefix[i]);
|
|
! f->n += utf8_width(prefix);
|
|
! }
|
|
! else if(ps_global->VAR_REPLY_STRING
|
|
! && (!strcmp(ps_global->VAR_REPLY_STRING, ">")
|
|
! || !strcmp(ps_global->VAR_REPLY_STRING, "\">\""))){
|
|
! GF_PUTC_GLO(f->next, '>');
|
|
! f->n += 1;
|
|
}
|
|
else{
|
|
! GF_PUTC_GLO(f->next, '>');
|
|
! GF_PUTC_GLO(f->next, ' ');
|
|
! f->n += 2;
|
|
}
|
|
}
|
|
else{
|
|
! GF_PUTC_GLO(f->next, '>');
|
|
! f->n += 1;
|
|
}
|
|
}
|
|
if(j && WRAP_LV_FLD(f)){
|
|
GF_PUTC_GLO(f->next, ' ');
|
|
f->n++;
|
|
}
|
|
! else if(j && last_prefix){
|
|
for(i = 0; last_prefix[i]; i++)
|
|
GF_PUTC_GLO(f->next, last_prefix[i]);
|
|
! f->n += utf8_width(last_prefix);
|
|
}
|
|
|
|
if(prefix)
|
|
fs_give((void **)&prefix);
|
|
if(last_prefix)
|
|
fs_give((void **)&last_prefix);
|
|
|
|
return 0;
|
|
}
|
|
--- 10895,10941 ----
|
|
}
|
|
}
|
|
|
|
+ if (j > 1 && wrap_qstr[j-1] == ' ')
|
|
+ j -= 1;
|
|
+
|
|
if(!WRAP_LV_FLD(f)){
|
|
if(!WRAP_FOR_CMPS(f) && ps_global->VAR_QUOTE_REPLACE_STRING && prefix){
|
|
for(i = 0; prefix[i]; i++)
|
|
GF_PUTC_GLO(f->next, prefix[i]);
|
|
! f->n += utf8_widthis(prefix);
|
|
}
|
|
else{
|
|
! for (i = oldj; i < j; i++)
|
|
! GF_PUTC_GLO(f->next, wrap_qstr[i]);
|
|
! f->n += j - oldj;
|
|
}
|
|
}
|
|
else{
|
|
! for (i = oldj; i < j; i++)
|
|
! GF_PUTC_GLO(f->next, wrap_qstr[i]);
|
|
! f->n += j - oldj;
|
|
}
|
|
+ for (i = j; isspace((unsigned char)wrap_qstr[i]); i++)
|
|
+ GF_PUTC_GLO(f->next, ' ');
|
|
+ f->n += i - j;
|
|
+ for (; isspace((unsigned char)wrap_qstr[j]); j++);
|
|
}
|
|
if(j && WRAP_LV_FLD(f)){
|
|
GF_PUTC_GLO(f->next, ' ');
|
|
f->n++;
|
|
}
|
|
! else if(j && !value_is_space(wrap_qstr) && last_prefix){
|
|
for(i = 0; last_prefix[i]; i++)
|
|
GF_PUTC_GLO(f->next, last_prefix[i]);
|
|
! f->n += utf8_widthis(last_prefix);
|
|
}
|
|
|
|
if(prefix)
|
|
fs_give((void **)&prefix);
|
|
if(last_prefix)
|
|
fs_give((void **)&last_prefix);
|
|
+ if (wrap_qstr)
|
|
+ fs_give((void **)&wrap_qstr);
|
|
|
|
return 0;
|
|
}
|
|
***************
|
|
*** 10896,10901 ****
|
|
--- 10967,10978 ----
|
|
wrap->hdr_color = (GFW_HDRCOLOR & flags) == GFW_HDRCOLOR;
|
|
wrap->for_compose = (GFW_FORCOMPOSE & flags) == GFW_FORCOMPOSE;
|
|
wrap->handle_soft_hyphen = (GFW_SOFTHYPHEN & flags) == GFW_SOFTHYPHEN;
|
|
+ wrap->curlinenum = 0L;
|
|
+ wrap->curqstrpos = 0;
|
|
+ wrap->linenum = 0L;
|
|
+ wrap->qstrlen = 100L;
|
|
+ wrap->qstrln = (char **) fs_get(100*sizeof(char *));
|
|
+ memset(wrap->qstrln, 0, 100*sizeof(char *));
|
|
|
|
return((void *) wrap);
|
|
}
|
|
***************
|
|
*** 11339,11345 ****
|
|
--- 11416,11630 ----
|
|
} \
|
|
}
|
|
|
|
+ #define ADD_QUOTE_STRING(F) { \
|
|
+ int len = tmp_20k_buf[0] ? strlen(tmp_20k_buf) + 1 : 0; \
|
|
+ FILTER_S *fltr; \
|
|
+ \
|
|
+ for(fltr = (F); fltr && fltr->f != gf_wrap; fltr = fltr->next); \
|
|
+ if (fltr){ \
|
|
+ if (WRAP_LINENUM(fltr) >= WRAP_QSTRLEN(fltr)){ \
|
|
+ fs_resize((void **)&WRAP_QSTRN(fltr), \
|
|
+ (WRAP_QSTRLEN(fltr) + 100) * sizeof(char *)); \
|
|
+ memset(WRAP_QSTRN(fltr)+WRAP_QSTRLEN(fltr), 0, \
|
|
+ 100*sizeof(char*)); \
|
|
+ WRAP_QSTRLEN(fltr) += 100L; \
|
|
+ } \
|
|
+ if (len){ \
|
|
+ WRAP_QSTR(fltr, WRAP_LINENUM(fltr)) = \
|
|
+ (char *) fs_get(len*sizeof(char)); \
|
|
+ WRAP_QSTR(fltr, WRAP_LINENUM(fltr)) = cpystr(tmp_20k_buf);\
|
|
+ } \
|
|
+ WRAP_LINENUM(fltr)++; \
|
|
+ } \
|
|
+ }
|
|
+
|
|
+ int end_of_line(char *line)
|
|
+ {
|
|
+ int i;
|
|
+
|
|
+ for(i= 0; line && line[i]; i++){
|
|
+ if((line[i] == '\015' && line[i+1] == '\012') || line[i] == '\012')
|
|
+ break;
|
|
+ }
|
|
+ return i;
|
|
+ }
|
|
+
|
|
+ /* This macro is used in gf_quote_test. It receives a return code
|
|
+ from a filter. All filters that will print something must send
|
|
+ return code 0, except color_a_quote which must send return code
|
|
+ 1
|
|
+ */
|
|
+
|
|
+ #define GF_ADD_QUOTED_LINE(F, line) \
|
|
+ { \
|
|
+ LT_INS_S *ins = NULL, *insp; \
|
|
+ int done; \
|
|
+ char *gline, *cline;\
|
|
+ unsigned char ch;\
|
|
+ register char *cp;\
|
|
+ register int l;\
|
|
+ \
|
|
+ for (gline = cline = line; gline && cline; ){\
|
|
+ if((cline = strchr(gline,'\012')) != NULL)\
|
|
+ *cline = '\0';\
|
|
+ done = (*((LINETEST_S *) (F)->opt)->f)((F)->n++, gline, &ins,\
|
|
+ ((LINETEST_S *) (F)->opt)->local);\
|
|
+ if (done < 2){ \
|
|
+ if(done == 1)\
|
|
+ ADD_QUOTE_STRING((F));\
|
|
+ for(insp = ins, cp = gline; *cp ; ){\
|
|
+ if(insp && cp == insp->where){\
|
|
+ if(insp->len > 0){ \
|
|
+ for(l = 0; l < insp->len; l++){\
|
|
+ ch = (unsigned char) insp->text[l];\
|
|
+ GF_PUTC((F)->next, ch);\
|
|
+ }\
|
|
+ insp = insp->next;\
|
|
+ continue; \
|
|
+ } else if(insp->len < 0){ \
|
|
+ cp -= insp->len; \
|
|
+ insp = insp->next; \
|
|
+ continue; \
|
|
+ } \
|
|
+ }\
|
|
+ GF_PUTC((F)->next, *cp);\
|
|
+ cp++;\
|
|
+ }\
|
|
+ while(insp){\
|
|
+ for(l = 0; l < insp->len; l++){\
|
|
+ ch = (unsigned char) insp->text[l];\
|
|
+ GF_PUTC((F)->next, ch);\
|
|
+ }\
|
|
+ insp = insp->next;\
|
|
+ }\
|
|
+ gf_line_test_free_ins(&ins);\
|
|
+ if(cline){ \
|
|
+ *cline = '\012';\
|
|
+ gline += cline - gline + 1;\
|
|
+ }\
|
|
+ GF_PUTC((F)->next, '\015');\
|
|
+ GF_PUTC((F)->next, '\012');\
|
|
+ }\
|
|
+ }\
|
|
+ }
|
|
+ /* test second line of old line first */
|
|
+ #define SECOND_LINE_QUOTE_TEST(line, F) \
|
|
+ {\
|
|
+ *p = '\0';\
|
|
+ i = end_of_line((F)->oldline); \
|
|
+ if (((F)->oldline)[i]){\
|
|
+ i += (((F)->oldline)[i] == '\015') ? 2 : 1;\
|
|
+ line = (F)->oldline + i;\
|
|
+ i = end_of_line(line); \
|
|
+ if(line[i])\
|
|
+ line[i] = '\0'; \
|
|
+ }\
|
|
+ for (i = 0; ((F)->line) \
|
|
+ && (i < LINE_TEST_BLOCK) \
|
|
+ && (i < SIZEOF_20KBUF)\
|
|
+ && ((F)->line)[i] \
|
|
+ && (((F)->line)[i] != '\015')\
|
|
+ && (((F)->line)[i] != '\012')\
|
|
+ && (tmp_20k_buf[i] = ((F)->line)[i]); i++);\
|
|
+ tmp_20k_buf[i] = '\0';\
|
|
+ GF_ADD_QUOTED_LINE((F), line);\
|
|
+ }
|
|
+
|
|
+ #define FIRST_LINE_QUOTE_TEST(line, F)\
|
|
+ {\
|
|
+ *p = '\0';\
|
|
+ line = (F)->line;\
|
|
+ if ((F)->oldline)\
|
|
+ fs_give((void **)&(F)->oldline);\
|
|
+ (F)->oldline = cpystr(line);\
|
|
+ i = end_of_line(line); \
|
|
+ if (line[i]){ \
|
|
+ j = (line[i] == '\015') ? 2 : 1;\
|
|
+ line[i] = '\0'; \
|
|
+ i += j; \
|
|
+ }\
|
|
+ for (j = 0; ((F)->line) \
|
|
+ && ((i + j) < LINE_TEST_BLOCK) \
|
|
+ && (j < SIZEOF_20KBUF) \
|
|
+ && ((F)->line)[i + j] \
|
|
+ && (((F)->line)[i + j] != '\015')\
|
|
+ && (((F)->line)[i + j] != '\012')\
|
|
+ && (tmp_20k_buf[j] = ((F)->line)[i + j]); j++);\
|
|
+ tmp_20k_buf[j] = '\0';\
|
|
+ GF_ADD_QUOTED_LINE((F), line);\
|
|
+ }
|
|
+
|
|
+
|
|
+ void
|
|
+ gf_quote_test(f, flg)
|
|
+ FILTER_S *f;
|
|
+ int flg;
|
|
+ {
|
|
+ register char *p = f->linep;
|
|
+ register char *eobuf = GF_LINE_TEST_EOB(f);
|
|
+ char *line = NULL;
|
|
+ int i, j;
|
|
+ GF_INIT(f, f->next);
|
|
+
|
|
+ if(flg == GF_DATA){
|
|
+ register unsigned char c;
|
|
+ register int state = f->f1;
|
|
+
|
|
+ while(GF_GETC(f, c)){
|
|
+
|
|
+ GF_LINE_TEST_ADD(f, c);
|
|
+ if(c == '\012')
|
|
+ state++;
|
|
+ if(state == 2){ /* two full lines read */
|
|
+ state = 0;
|
|
+
|
|
+ /* first process the second line of an old line */
|
|
+ if (f->oldline && f->oldline[0])
|
|
+ SECOND_LINE_QUOTE_TEST(line, f);
|
|
+
|
|
+ /* now we process the first line */
|
|
+ FIRST_LINE_QUOTE_TEST(line, f);
|
|
+
|
|
+ p = f->line;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ f->f1 = state;
|
|
+ GF_END(f, f->next);
|
|
+ }
|
|
+ else if(flg == GF_EOD){
|
|
+ /* first process the second line of an old line */
|
|
+ if (f->oldline && f->oldline[0])
|
|
+ SECOND_LINE_QUOTE_TEST(line, f);
|
|
+
|
|
+ /* now we process the first line */
|
|
+ FIRST_LINE_QUOTE_TEST(line, f);
|
|
+
|
|
+ /* We are out of data. In this case we have processed the second
|
|
+ * line of an oldline, then the first line of a line, but we need
|
|
+ * to process the second line of the given line. We do this by
|
|
+ * processing it now!.
|
|
+ */
|
|
+ if (line[i]){
|
|
+ tmp_20k_buf[0] = '\0'; /* No next line */
|
|
+ GF_ADD_QUOTED_LINE(f, line+i);
|
|
+ }
|
|
+
|
|
+ fs_give((void **) &f->oldline); /* free old line buffer */
|
|
+ fs_give((void **) &f->line); /* free line buffer */
|
|
+ fs_give((void **) &f->opt); /* free test struct */
|
|
+ GF_FLUSH(f->next);
|
|
+ (*f->next->f)(f->next, GF_EOD);
|
|
+ }
|
|
+ else if(flg == GF_RESET){
|
|
+ f->f1 = 0; /* state */
|
|
+ f->n = 0L; /* line number */
|
|
+ f->f2 = LINE_TEST_BLOCK; /* size of alloc'd line */
|
|
+ f->line = p = (char *) fs_get(f->f2 * sizeof(char));
|
|
+ }
|
|
|
|
+ f->linep = p;
|
|
+ }
|
|
|
|
/*
|
|
* this simple filter accumulates characters until a newline, offers it
|
|
diff -rc alpine-2.26/pith/filter.h alpine-2.26.fillpara/pith/filter.h
|
|
*** alpine-2.26/pith/filter.h 2022-06-02 18:14:00.491274749 -0600
|
|
--- alpine-2.26.fillpara/pith/filter.h 2022-06-02 18:14:57.031136112 -0600
|
|
***************
|
|
*** 217,222 ****
|
|
--- 217,223 ----
|
|
void *gf_prepend_editorial_opt(prepedtest_t, char *);
|
|
void gf_nvtnl_local(FILTER_S *, int);
|
|
void gf_local_nvtnl(FILTER_S *, int);
|
|
+ void gf_quote_test(FILTER_S *, int);
|
|
void *gf_url_hilite_opt(URL_HILITE_S *, HANDLE_S **, int);
|
|
void free_filter_module_globals(void);
|
|
|
|
diff -rc alpine-2.26/pith/filttype.h alpine-2.26.fillpara/pith/filttype.h
|
|
*** alpine-2.26/pith/filttype.h 2022-06-02 18:14:00.495274738 -0600
|
|
--- alpine-2.26.fillpara/pith/filttype.h 2022-06-02 18:14:57.031136112 -0600
|
|
***************
|
|
*** 36,41 ****
|
|
--- 36,43 ----
|
|
unsigned char t; /* temporary char */
|
|
char *line; /* place for temporary storage */
|
|
char *linep; /* pointer into storage space */
|
|
+ char *oldline; /* the previous line to "line" */
|
|
+ char *oldlinep; /* the previous line to "line" */
|
|
void *opt; /* optional per instance data */
|
|
void *data; /* misc internal data pointer */
|
|
unsigned char queue[1 + GF_MAXBUF];
|
|
diff -rc alpine-2.26/pith/mailview.c alpine-2.26.fillpara/pith/mailview.c
|
|
*** alpine-2.26/pith/mailview.c 2022-06-02 18:14:00.491274749 -0600
|
|
--- alpine-2.26.fillpara/pith/mailview.c 2022-06-02 18:14:57.035136102 -0600
|
|
***************
|
|
*** 51,57 ****
|
|
#include "../pith/escapes.h"
|
|
#include "../pith/keyword.h"
|
|
#include "../pith/smime.h"
|
|
!
|
|
|
|
#define FBUF_LEN (50)
|
|
|
|
--- 51,61 ----
|
|
#include "../pith/escapes.h"
|
|
#include "../pith/keyword.h"
|
|
#include "../pith/smime.h"
|
|
! #include "../pith/osdep/color.h"
|
|
! #include "../pico/osdep/color.h"
|
|
! #include "../pico/estruct.h"
|
|
! #include "../pico/pico.h"
|
|
! #include "../pico/efunc.h"
|
|
|
|
#define FBUF_LEN (50)
|
|
|
|
***************
|
|
*** 634,640 ****
|
|
&& pico_usingcolor()
|
|
&& ps_global->VAR_SIGNATURE_FORE_COLOR
|
|
&& ps_global->VAR_SIGNATURE_BACK_COLOR){
|
|
! gf_link_filter(gf_line_test, gf_line_test_opt(color_signature, &is_in_sig));
|
|
}
|
|
|
|
if((flgs & FM_DISPLAY)
|
|
--- 638,644 ----
|
|
&& pico_usingcolor()
|
|
&& ps_global->VAR_SIGNATURE_FORE_COLOR
|
|
&& ps_global->VAR_SIGNATURE_BACK_COLOR){
|
|
! gf_link_filter(gf_quote_test, gf_line_test_opt(color_signature, &is_in_sig));
|
|
}
|
|
|
|
if((flgs & FM_DISPLAY)
|
|
***************
|
|
*** 642,649 ****
|
|
&& pico_usingcolor()
|
|
&& ps_global->VAR_QUOTE1_FORE_COLOR
|
|
&& ps_global->VAR_QUOTE1_BACK_COLOR){
|
|
! gf_link_filter(gf_line_test, gf_line_test_opt(color_a_quote, NULL));
|
|
}
|
|
|
|
if(!(flgs & FM_NOWRAP)){
|
|
wrapflags = (flgs & FM_DISPLAY) ? (GFW_HANDLES|GFW_SOFTHYPHEN) : GFW_NONE;
|
|
--- 646,655 ----
|
|
&& pico_usingcolor()
|
|
&& ps_global->VAR_QUOTE1_FORE_COLOR
|
|
&& ps_global->VAR_QUOTE1_BACK_COLOR){
|
|
! gf_link_filter(gf_quote_test, gf_line_test_opt(color_a_quote, NULL));
|
|
}
|
|
+ else
|
|
+ gf_link_filter(gf_quote_test,gf_line_test_opt(select_quote, NULL));
|
|
|
|
if(!(flgs & FM_NOWRAP)){
|
|
wrapflags = (flgs & FM_DISPLAY) ? (GFW_HANDLES|GFW_SOFTHYPHEN) : GFW_NONE;
|
|
***************
|
|
*** 1459,1485 ****
|
|
color_signature(long int linenum, char *line, LT_INS_S **ins, void *is_in_sig)
|
|
{
|
|
struct variable *vars = ps_global->vars;
|
|
! int *in_sig_block;
|
|
COLOR_PAIR *col = NULL;
|
|
|
|
if(is_in_sig == NULL)
|
|
return 0;
|
|
|
|
in_sig_block = (int *) is_in_sig;
|
|
|
|
! if(!strcmp(line, SIGDASHES))
|
|
! *in_sig_block = START_SIG_BLOCK;
|
|
! else if(*line == '\0')
|
|
/*
|
|
* Suggested by Eduardo: allow for a blank line right after
|
|
* the sigdashes.
|
|
*/
|
|
*in_sig_block = (*in_sig_block == START_SIG_BLOCK)
|
|
? IN_SIG_BLOCK : OUT_SIG_BLOCK;
|
|
else
|
|
*in_sig_block = (*in_sig_block != OUT_SIG_BLOCK)
|
|
? IN_SIG_BLOCK : OUT_SIG_BLOCK;
|
|
|
|
if(*in_sig_block != OUT_SIG_BLOCK
|
|
&& VAR_SIGNATURE_FORE_COLOR && VAR_SIGNATURE_BACK_COLOR
|
|
&& (col = new_color_pair(VAR_SIGNATURE_FORE_COLOR,
|
|
--- 1465,1552 ----
|
|
color_signature(long int linenum, char *line, LT_INS_S **ins, void *is_in_sig)
|
|
{
|
|
struct variable *vars = ps_global->vars;
|
|
! int *in_sig_block, i, j,same_qstr = 0, plb;
|
|
COLOR_PAIR *col = NULL;
|
|
+ static char GLine[NSTRING] = {'\0'};
|
|
+ static char PLine[NSTRING] = {'\0'};
|
|
+ static char PPLine[NSTRING] = {'\0'};
|
|
+ char NLine[NSTRING] = {'\0'};
|
|
+ char rqstr[NSTRING] = {'\0'};
|
|
+ char *p, *q;
|
|
+ static char *buf, buf2[NSTRING] = {'\0'};
|
|
+ QSTRING_S *qs;
|
|
+ static int qstrlen = 0;
|
|
|
|
if(is_in_sig == NULL)
|
|
return 0;
|
|
|
|
+ if (linenum > 0){
|
|
+ strncpy(PLine, GLine, sizeof(PLine));
|
|
+ PLine[sizeof(PLine)-1] = '\0';
|
|
+ }
|
|
+
|
|
+ if((p = strchr(tmp_20k_buf, '\015')) != NULL) *p = '\0';
|
|
+ strncpy(NLine, tmp_20k_buf, sizeof(NLine));
|
|
+ NLine[sizeof(NLine) - 1] = '\0';
|
|
+ if (p) *p = '\015';
|
|
+
|
|
+ strncpy(GLine, line, sizeof(GLine));
|
|
+ GLine[sizeof(GLine) - 1] = '\0';
|
|
+
|
|
+ ps_global->list_qstr = default_qstr(ps_global->prefix && *ps_global->prefix
|
|
+ ? (void *) ps_global->prefix : (void *) ">", 0);
|
|
+ plb = line_isblank(ps_global->list_qstr, PLine, GLine, PPLine, NSTRING);
|
|
+ qs = do_quote_match(ps_global->list_qstr, GLine, NLine, PLine, rqstr, NSTRING, plb);
|
|
+ if(linenum > 0)
|
|
+ strncpy(PPLine, PLine, NSTRING);
|
|
+ strncpy(buf2, rqstr, NSTRING);
|
|
+ i = buf2 && buf2[0] ? strlen(buf2) : 0;
|
|
+ free_qs(&qs);
|
|
+
|
|
+ /* determine if buf and buf2 are the same quote string */
|
|
+ if (!struncmp(buf, buf2, qstrlen)){
|
|
+ for (j = qstrlen; buf2[j] && isspace((unsigned char)buf2[j]); j++);
|
|
+ if (!buf2[j] || buf2[j] == '|' || (buf2[j] == '*' && buf2[j+1] != '>'))
|
|
+ same_qstr++;
|
|
+ }
|
|
+
|
|
in_sig_block = (int *) is_in_sig;
|
|
|
|
! if (*in_sig_block != OUT_SIG_BLOCK){
|
|
! if (line && *line && (strlen(line) >= qstrlen) && same_qstr)
|
|
! line += qstrlen;
|
|
! else if (strlen(line) < qstrlen)
|
|
! line += i;
|
|
! else if (!same_qstr)
|
|
! *in_sig_block = OUT_SIG_BLOCK;
|
|
! }
|
|
! else
|
|
! line += i;
|
|
!
|
|
! if(!strcmp(line, SIGDASHES) || !strcmp(line, "--")){
|
|
! *in_sig_block = START_SIG_BLOCK;
|
|
! buf = (char *) fs_get((i + 1)*sizeof(char));
|
|
! buf = cpystr(buf2);
|
|
! qstrlen = i;
|
|
! }
|
|
! else if(*line == '\0'){
|
|
/*
|
|
* Suggested by Eduardo: allow for a blank line right after
|
|
* the sigdashes.
|
|
*/
|
|
*in_sig_block = (*in_sig_block == START_SIG_BLOCK)
|
|
? IN_SIG_BLOCK : OUT_SIG_BLOCK;
|
|
+ }
|
|
else
|
|
*in_sig_block = (*in_sig_block != OUT_SIG_BLOCK)
|
|
? IN_SIG_BLOCK : OUT_SIG_BLOCK;
|
|
|
|
+ if (*in_sig_block == OUT_SIG_BLOCK){
|
|
+ qstrlen = 0; /* reset back in case there's another paragraph */
|
|
+ if (buf)
|
|
+ fs_give((void **)&buf);
|
|
+ }
|
|
+
|
|
if(*in_sig_block != OUT_SIG_BLOCK
|
|
&& VAR_SIGNATURE_FORE_COLOR && VAR_SIGNATURE_BACK_COLOR
|
|
&& (col = new_color_pair(VAR_SIGNATURE_FORE_COLOR,
|
|
***************
|
|
*** 2039,2044 ****
|
|
--- 2106,2182 ----
|
|
}
|
|
|
|
|
|
+ /* This filter gives a quote string of a line. It sends its reply back to the
|
|
+ calling filter in the tmp_20k_buf variable. This filter replies with
|
|
+ the full quote string including tailing spaces if any. It is the
|
|
+ responsibility of the calling filter to figure out if thos spaces are
|
|
+ useful for that filter or if they should be removed before doing any
|
|
+ useful work. For example, color_a_quote does not require the trailing
|
|
+ spaces, but gf_wrap does.
|
|
+ */
|
|
+ int
|
|
+ select_quote(long linenum, char *line, LT_INS_S **ins, void *local)
|
|
+ {
|
|
+ int i, plb, *code;
|
|
+ char rqstr[NSTRING] = {'\0'}, buf[NSTRING] = {'\0'};
|
|
+ char GLine[NSTRING] = {'\0'}, PLine[NSTRING] = {'\0'};
|
|
+ char PPLine[NSTRING] = {'\0'}, NLine[NSTRING] = {'\0'};
|
|
+ static char GLine1[NSTRING] = {'\0'};
|
|
+ static char PLine1[NSTRING] = {'\0'};
|
|
+ static char PPLine1[NSTRING] = {'\0'};
|
|
+ static char GLine2[NSTRING] = {'\0'};
|
|
+ static char PLine2[NSTRING] = {'\0'};
|
|
+ static char PPLine2[NSTRING] = {'\0'};
|
|
+ QSTRING_S *qs;
|
|
+ int buflen = NSTRING < SIZEOF_20KBUF ? NSTRING - 1: SIZEOF_20KBUF - 1;
|
|
+ int who, raw;
|
|
+
|
|
+ code = (int *)local;
|
|
+ who = code ? (*code & COLORAQUO) : 0; /* may I ask who is calling? */
|
|
+ raw = code ? (*code & RAWSTRING) : 0; /* return raw string */
|
|
+ strncpy(GLine, (who ? GLine1 : GLine2), buflen);
|
|
+ strncpy(PLine, (who ? PLine1 : PLine2), buflen);
|
|
+ strncpy(PPLine, (who ? PPLine1 : PPLine2), buflen);
|
|
+
|
|
+ if (linenum > 0)
|
|
+ strncpy(PLine, GLine, buflen);
|
|
+
|
|
+ strncpy(NLine, tmp_20k_buf, buflen);
|
|
+
|
|
+ if (line)
|
|
+ strncpy(GLine, line, buflen);
|
|
+ else
|
|
+ GLine[0] = '\0';
|
|
+
|
|
+ ps_global->list_qstr = default_qstr(ps_global->prefix && *ps_global->prefix
|
|
+ ? (void *) ps_global->prefix : (void *) ">", 0);
|
|
+ plb = line_isblank(ps_global->list_qstr, PLine, GLine, PPLine, NSTRING);
|
|
+
|
|
+ qs = do_quote_match(ps_global->list_qstr, GLine, NLine, PLine, rqstr, NSTRING, plb);
|
|
+ if (raw)
|
|
+ strncpy(buf, rqstr, NSTRING);
|
|
+ else
|
|
+ flatten_qstring(qs, buf, NSTRING);
|
|
+ if(qs)
|
|
+ record_quote_string(qs);
|
|
+ free_qs(&qs);
|
|
+
|
|
+ /* do not paint an extra level for a line with a >From string at the
|
|
+ * begining of it
|
|
+ */
|
|
+ if (buf[0]){
|
|
+ i = strlen(buf);
|
|
+ if (strlen(line) >= i + 6 && !strncmp(line+i-1,">From ", 6))
|
|
+ buf[i - 1] = '\0';
|
|
+ }
|
|
+ strncpy(tmp_20k_buf, buf, buflen);
|
|
+ if (linenum > 0)
|
|
+ strncpy((who ? PPLine1 : PPLine2), PLine, buflen);
|
|
+ strncpy((who ? GLine1 : GLine2), GLine, buflen);
|
|
+ strncpy((who ? PLine1 : PLine2), PLine, buflen);
|
|
+ return 1;
|
|
+ }
|
|
+
|
|
|
|
#define UES_LEN 12
|
|
#define UES_MAX 32
|
|
diff -rc alpine-2.26/pith/mailview.h alpine-2.26.fillpara/pith/mailview.h
|
|
*** alpine-2.26/pith/mailview.h 2022-06-02 18:14:00.491274749 -0600
|
|
--- alpine-2.26.fillpara/pith/mailview.h 2022-06-02 18:14:57.035136102 -0600
|
|
***************
|
|
*** 146,151 ****
|
|
--- 146,152 ----
|
|
char *display_parameters(PARAMETER *);
|
|
char *pine_fetch_header(MAILSTREAM *, long, char *, char **, long);
|
|
int color_signature(long, char *, LT_INS_S **, void *);
|
|
+ int select_quote(long, char *, LT_INS_S **, void *);
|
|
int scroll_handle_start_color(char *, size_t, int *);
|
|
int scroll_handle_end_color(char *, size_t, int *, int);
|
|
int width_at_this_position(unsigned char *, unsigned long);
|
|
diff -rc alpine-2.26/pith/osdep/color.c alpine-2.26.fillpara/pith/osdep/color.c
|
|
*** alpine-2.26/pith/osdep/color.c 2022-06-02 18:14:00.495274738 -0600
|
|
--- alpine-2.26.fillpara/pith/osdep/color.c 2022-06-02 18:14:57.039136093 -0600
|
|
***************
|
|
*** 28,34 ****
|
|
|
|
#include <system.h>
|
|
#include "./color.h"
|
|
!
|
|
|
|
|
|
/*
|
|
--- 28,36 ----
|
|
|
|
#include <system.h>
|
|
#include "./color.h"
|
|
! #include "./collate.h"
|
|
! #include "../charconv/utf8.h"
|
|
! #include "../../c-client/c-client.h"
|
|
|
|
|
|
/*
|
|
***************
|
|
*** 88,90 ****
|
|
--- 90,1372 ----
|
|
{
|
|
return(pico_set_colors(col ? col->fg : NULL, col ? col->bg : NULL, flags));
|
|
}
|
|
+
|
|
+
|
|
+ /*
|
|
+ * Extended Justification support also does not belong here
|
|
+ * but otherwise webpine will not build, so we move everything
|
|
+ * here. Hopefully this will be the permanent place for these
|
|
+ * routines. These routines used to be in pico/word.c
|
|
+ */
|
|
+ #define NSTRING 256
|
|
+ #include "../../include/general.h"
|
|
+
|
|
+ /* Support of indentation of paragraphs */
|
|
+ #define is_indent_char(c) (((c) == '.' || (c) == '}' || (c) == RPAREN || \
|
|
+ (c) == '*' || (c) == '+' || is_a_digit(c) || \
|
|
+ ISspace(c) || (c) == '-' || \
|
|
+ (c) == ']') ? 1 : 0)
|
|
+ #define allowed_after_digit(c,word,k) ((((c) == '.' && \
|
|
+ allowed_after_period(next((word),(k)))) ||\
|
|
+ (c) == RPAREN || (c) == '}' || (c) == ']' ||\
|
|
+ ISspace(c) || is_a_digit(c) || \
|
|
+ (((c) == '-' ) && \
|
|
+ allowed_after_dash(next((word),(k))))) \
|
|
+ ? 1 : 0)
|
|
+ #define allowed_after_period(c) (((c) == RPAREN || (c) == '}' || (c) == ']' ||\
|
|
+ ISspace(c) || (c) == '-' || \
|
|
+ is_a_digit(c)) ? 1 : 0)
|
|
+ #define allowed_after_parenth(c) (ISspace(c) ? 1 : 0)
|
|
+ #define allowed_after_space(c) (ISspace(c) ? 1 : 0)
|
|
+ #define allowed_after_braces(c) (ISspace(c) ? 1 : 0)
|
|
+ #define allowed_after_star(c) ((ISspace(c) || (c) == RPAREN ||\
|
|
+ (c) == ']' || (c) == '}') ? 1 : 0)
|
|
+ #define allowed_after_dash(c) ((ISspace(c) || is_a_digit(c)) ? 1 : 0)
|
|
+ #define EOLchar(c) (((c) == '.' || (c) == ':' || (c) == '?' ||\
|
|
+ (c) == '!') ? 1 : 0)
|
|
+
|
|
+
|
|
+ /* Extended justification support */
|
|
+ #define is_cquote(c) ((c) == '>' || (c) == '|' || (c) == ']' || (c) == ':')
|
|
+ #define is_cword(c) ((((c) >= 'a') && ((c) <= 'z')) || \
|
|
+ (((c) >= 'A') && ((c) <= 'Z')) || \
|
|
+ (((c) >= '0') && ((c) <= '9')) || \
|
|
+ ((c) == ' ') || ((c) == '?') || \
|
|
+ ((c) == '@') || ((c) == '.') || \
|
|
+ ((c) == '!') || ((c) == '\'') || \
|
|
+ ((c) == ',') || ((c) == '\"') ? 1 : 0)
|
|
+ #define isaquote(c) ((c) == '\"' || (c) == '\'')
|
|
+ #define is8bit(c) ((((int) (c)) & 0x80) ? 1 : 0)
|
|
+ #define iscontrol(c) (iscntrl(((int) (c)) & 0x7f) ? 1 : 0)
|
|
+ #define forbidden(c) (((c) == '\"') || ((c) == '\'') || ((c) == '$') ||\
|
|
+ ((c) == ',') || ((c) == '.') || ((c) == '-') ||\
|
|
+ ((c) == LPAREN) || ((c) == '/')|| ((c) == '`') ||\
|
|
+ ((c) == '{') || ((c) == '\\') || (iscontrol((c))) ||\
|
|
+ (((c) >= '0') && ((c) <= '9')) || ((c) == '?'))
|
|
+ #define is_cletter(c) (((((c) >= 'a') && ((c) <= 'z'))) ||\
|
|
+ ((((c) >= 'A') && ((c) <= 'Z'))||\
|
|
+ is8bit(c)))
|
|
+ #define is_cnumber(c) ((c) >= '0' && (c) <= '9')
|
|
+ #define allwd_after_word(c) (((c) == ' ') || ((c) == '>') || is_cletter(c))
|
|
+ #define allwd_after_qsword(c) (((c) != '\\') && ((c) != RPAREN) && ((c) != '/'))
|
|
+ #define before(word,i) (((i) > 0) ? (word)[(i) - 1] : 0)
|
|
+ #define next(w,i) ((((w)[(i)]) != 0) ? ((w)[(i) + 1]) : 0)
|
|
+ #define now(w,i) ((w)[(i)])
|
|
+ #define is_qsword(c) (((c) == ':') || ((c) == RPAREN) ? 1 : 0)
|
|
+ #define is_colon(c) (((c) == ':') ? 1 : 0)
|
|
+ #define is_rarrow(c) (((c) == '>') ? 1 : 0)
|
|
+ #define is_tilde(c) (((c) == '~') ? 1 : 0)
|
|
+ #define is_dash(c) (((c) == '-') ? 1 : 0)
|
|
+ #define is_pound(c) (((c) == '#') ? 1 : 0)
|
|
+ #define is_a_digit(c) ((((c) >= '0') && ((c) <= '9')) ? 1 : 0)
|
|
+ #define is_allowed(c) (is_cquote(c) || is_cword(c) || is_dash(c) || \
|
|
+ is_pound(c))
|
|
+ #define qs_allowed(a) (((a)->qstype != qsGdb) && ((a)->qstype != qsProg))
|
|
+
|
|
+ /* Internal justification functions */
|
|
+ QSTRING_S *is_quote(char **, char *, int);
|
|
+ QSTRING_S *qs_normal_part(QSTRING_S *);
|
|
+ QSTRING_S *qs_remove_trailing_spaces(QSTRING_S *);
|
|
+ QSTRING_S *trim_qs_from_cl(QSTRING_S *, QSTRING_S *, QSTRING_S *);
|
|
+ QSTRING_S *fix_qstring(QSTRING_S *, QSTRING_S *, QSTRING_S *);
|
|
+ QSTRING_S *fix_qstring_allowed(QSTRING_S *, QSTRING_S *, QSTRING_S *);
|
|
+ QSTRING_S *qs_add(char **, char *, QStrType, int, int, int, int);
|
|
+ QSTRING_S *remove_qsword(QSTRING_S *);
|
|
+ QSTRING_S *do_raw_quote_match(char **, char *, char *, char *, QSTRING_S **, QSTRING_S **);
|
|
+ void free_qs(QSTRING_S **);
|
|
+ int word_is_prog(char *);
|
|
+ int qstring_is_normal(QSTRING_S *);
|
|
+ int exists_good_part(QSTRING_S *);
|
|
+ int strcmp_qs(char *, char *);
|
|
+ int count_levels_qstring(QSTRING_S *);
|
|
+ int same_qstring(QSTRING_S *, QSTRING_S *);
|
|
+ int isaword(char *,int ,int);
|
|
+ int isamailbox(char *,int ,int);
|
|
+ int double_check_qstr(char *);
|
|
+
|
|
+ int
|
|
+ word_is_prog(char *word)
|
|
+ {
|
|
+ static char *list1[] = {"#include",
|
|
+ "#define",
|
|
+ "#ifdef",
|
|
+ "#ifndef",
|
|
+ "#elif",
|
|
+ "#if",
|
|
+ NULL};
|
|
+ static char *list2[] = {"#else",
|
|
+ "#endif",
|
|
+ NULL};
|
|
+ int i, j = strlen(word), k, rv = 0;
|
|
+
|
|
+ for(i = 0; rv == 0 && list1[i] && (k = strlen(list1[i])) && k < j; i++)
|
|
+ if(!strncmp(list1[i], word, k) && ISspace(word[k]))
|
|
+ rv++;
|
|
+
|
|
+ if(rv)
|
|
+ return rv;
|
|
+
|
|
+ for(i = 0; rv == 0 && list2[i] && (k = strlen(list2[i])) && k <= j; i++)
|
|
+ if(!strncmp(list2[i], word, k) && (!word[k] || ISspace(word[k])))
|
|
+ rv++;
|
|
+
|
|
+ return rv;
|
|
+ }
|
|
+
|
|
+ /*
|
|
+ * This function creates a qstring pointer with the information that
|
|
+ * is_quote handles to it.
|
|
+ * Parameters:
|
|
+ * qs - User supplied quote string
|
|
+ * word - The line of text that the user is trying to read/justify
|
|
+ * beginw - Where we need to start copying from
|
|
+ * endw - Where we end copying
|
|
+ * offset - Any offset in endw that we need to account for
|
|
+ * typeqs - type of the string to be created
|
|
+ * neednext - boolean, indicating if we need to compute the next field
|
|
+ * of leave it NULL
|
|
+ *
|
|
+ * It is a mistake to call this function if beginw >= endw + offset.
|
|
+ * Please note the equality sign in the above inequality (this is because
|
|
+ * we always assume that qstring->value != "").
|
|
+ */
|
|
+ QSTRING_S *
|
|
+ qs_add(char **qs, char word[NSTRING], QStrType typeqs, int beginw, int endw,
|
|
+ int offset, int neednext)
|
|
+ {
|
|
+ QSTRING_S *qstring, *nextqs;
|
|
+ int i;
|
|
+
|
|
+ qstring = (QSTRING_S *) malloc (sizeof(QSTRING_S));
|
|
+ memset (qstring, 0, sizeof(QSTRING_S));
|
|
+ qstring->qstype = qsNormal;
|
|
+
|
|
+ if (beginw == 0){
|
|
+ beginw = endw + offset;
|
|
+ qstring->qstype = typeqs;
|
|
+ }
|
|
+
|
|
+ nextqs = neednext ? is_quote(qs, word+beginw, 1) : NULL;
|
|
+
|
|
+ qstring->value = (char *) malloc((beginw+1)*sizeof(char));
|
|
+ strncpy(qstring->value, word, beginw);
|
|
+ qstring->value[beginw] = '\0';
|
|
+
|
|
+ qstring->next = nextqs;
|
|
+
|
|
+ return qstring;
|
|
+ }
|
|
+
|
|
+ int
|
|
+ qstring_is_normal(QSTRING_S *cl)
|
|
+ {
|
|
+ for (;cl && (cl->qstype == qsNormal); cl = cl->next);
|
|
+ return cl ? 0 : 1;
|
|
+ }
|
|
+
|
|
+ /*
|
|
+ * Given a quote string, this function returns the part that is the leading
|
|
+ * normal part of it. (the normal part is the part that is tagged qsNormal,
|
|
+ * that is to say, the one that is not controversial at all (like qsString
|
|
+ * for example).
|
|
+ */
|
|
+ QSTRING_S *
|
|
+ qs_normal_part(QSTRING_S *cl)
|
|
+ {
|
|
+
|
|
+ if (!cl) /* nothing in, nothing out */
|
|
+ return cl;
|
|
+
|
|
+ if (cl->qstype != qsNormal)
|
|
+ free_qs(&cl);
|
|
+
|
|
+ if (cl)
|
|
+ cl->next = qs_normal_part(cl->next);
|
|
+
|
|
+ return cl;
|
|
+ }
|
|
+
|
|
+ /*
|
|
+ * this function removes trailing spaces from a quote string, but leaves the
|
|
+ * last one if there are trailing spaces
|
|
+ */
|
|
+ QSTRING_S *
|
|
+ qs_remove_trailing_spaces(QSTRING_S *cl)
|
|
+ {
|
|
+ QSTRING_S *rl = cl;
|
|
+ if (!cl) /* nothing in, nothing out */
|
|
+ return cl;
|
|
+
|
|
+ if (cl->next)
|
|
+ cl->next = qs_remove_trailing_spaces(cl->next);
|
|
+ else{
|
|
+ if (value_is_space(cl->value))
|
|
+ free_qs(&cl);
|
|
+ else{
|
|
+ int i, l;
|
|
+ i = l = strlen(cl->value) - 1;
|
|
+ while (cl->value && cl->value[i]
|
|
+ && ISspace(cl->value[i]))
|
|
+ i--;
|
|
+ i += (i < l) ? 2 : 1;
|
|
+ cl->value[i] = '\0';
|
|
+ }
|
|
+ }
|
|
+ return cl;
|
|
+ }
|
|
+
|
|
+ /*
|
|
+ * This function returns if two strings are the same quote string.
|
|
+ * The call is not symmetric. cl must preceed the line nl. This function
|
|
+ * should be called for comparing the last part of cl and nl.
|
|
+ */
|
|
+ int
|
|
+ strcmp_qs(char *valuecl, char *valuenl)
|
|
+ {
|
|
+ int j;
|
|
+
|
|
+ for (j = 0; valuecl[j] && (valuecl[j] == valuenl[j]); j++);
|
|
+ return !strcmp(valuecl, valuenl)
|
|
+ || (valuenl[j] && value_is_space(valuenl+j)
|
|
+ && value_is_space(valuecl+j)
|
|
+ && strlenis(valuecl+j) >= strlenis(valuenl+j))
|
|
+ || (!valuenl[j] && value_is_space(valuecl+j));
|
|
+ }
|
|
+
|
|
+ int
|
|
+ count_levels_qstring(QSTRING_S *cl)
|
|
+ {
|
|
+ int count;
|
|
+ for (count = 0; cl ; count++, cl = cl->next);
|
|
+
|
|
+ return count;
|
|
+ }
|
|
+
|
|
+ int
|
|
+ value_is_space(char *value)
|
|
+ {
|
|
+ for (; value && *value && ISspace(*value); value++);
|
|
+
|
|
+ return value && *value ? 0 : 1;
|
|
+ }
|
|
+
|
|
+ void
|
|
+ free_qs(QSTRING_S **cl)
|
|
+ {
|
|
+ if (!(*cl))
|
|
+ return;
|
|
+
|
|
+ if ((*cl)->next)
|
|
+ free_qs(&((*cl)->next));
|
|
+
|
|
+ (*cl)->next = (QSTRING_S *) NULL;
|
|
+
|
|
+ if ((*cl)->value)
|
|
+ free((void *)(*cl)->value);
|
|
+ (*cl)->value = (char *) NULL;
|
|
+ free((void *)(*cl));
|
|
+ *cl = (QSTRING_S *) NULL;
|
|
+ }
|
|
+
|
|
+ /*
|
|
+ * This function returns the number of agreements between
|
|
+ * cl and nl. The call is not symmetric. cl must be the line
|
|
+ * preceding nl.
|
|
+ */
|
|
+ int
|
|
+ same_qstring(QSTRING_S *cl, QSTRING_S *nl)
|
|
+ {
|
|
+ int same = 0, done = 0;
|
|
+
|
|
+ for (;cl && nl && !done; cl = cl->next, nl = nl->next)
|
|
+ if (cl->qstype == nl->qstype
|
|
+ && (!strcmp(cl->value, nl->value)
|
|
+ || (!cl->next && strcmp_qs(cl->value, nl->value))))
|
|
+ same++;
|
|
+ else
|
|
+ done++;
|
|
+ return same;
|
|
+ }
|
|
+
|
|
+ QSTRING_S *
|
|
+ trim_qs_from_cl(QSTRING_S *cl, QSTRING_S *nl, QSTRING_S *pl)
|
|
+ {
|
|
+ QSTRING_S *cqstring = pl ? pl : nl;
|
|
+ QSTRING_S *tl = pl ? pl : nl;
|
|
+ int p, c;
|
|
+
|
|
+ if (qstring_is_normal(tl))
|
|
+ return tl;
|
|
+
|
|
+ p = same_qstring(pl ? pl : cl, pl ? cl : nl);
|
|
+
|
|
+ for (c = 1; c < p; c++, cl = cl->next, tl = tl->next);
|
|
+
|
|
+ /*
|
|
+ * cl->next and tl->next differ, it may be because cl->next does not
|
|
+ * exist or tl->next does not exist or simply both exist but are
|
|
+ * different. In this last case, it may be that cl->next->value is made
|
|
+ * of spaces. If this is the case, tl advances once more.
|
|
+ */
|
|
+
|
|
+ if (tl->next){
|
|
+ if (cl && cl->next && value_is_space(cl->next->value))
|
|
+ tl = tl->next;
|
|
+ if (tl->next)
|
|
+ free_qs(&(tl->next));
|
|
+ }
|
|
+
|
|
+ if (!p)
|
|
+ free_qs(&cqstring);
|
|
+
|
|
+ return cqstring;
|
|
+ }
|
|
+
|
|
+ /* This function trims cl so that it returns a real quote string based
|
|
+ * on information gathered from the previous and next lines. pl and cl are
|
|
+ * also trimmed, but that is done in another function, not here.
|
|
+ */
|
|
+ QSTRING_S *
|
|
+ fix_qstring(QSTRING_S *cl, QSTRING_S *nl, QSTRING_S *pl)
|
|
+ {
|
|
+ QSTRING_S *cqstring = cl, *nqstring = nl, *pqstring = pl;
|
|
+ int c, n;
|
|
+
|
|
+ if (qstring_is_normal(cl))
|
|
+ return cl;
|
|
+
|
|
+ c = count_levels_qstring(cl);
|
|
+ n = same_qstring(cl,nl);
|
|
+
|
|
+ /* by the definition of n and c above we have n <= c */
|
|
+
|
|
+ if (!n){ /* no next line or no agreement with next line */
|
|
+ int p = same_qstring(pl, cl); /* number of agreements between pl and cl */
|
|
+ QSTRING_S *tl; /* test line */
|
|
+
|
|
+ /*
|
|
+ * Here p <= c, so either p < c or p == c. If p == c, we are done,
|
|
+ * and return cl. If not, there are two cases, either p == 0 or
|
|
+ * 0 < p < c. In the first case, we do not have enough evidence
|
|
+ * to return anything other than the normal part of cl, in the second
|
|
+ * case we can only return p levels of cl.
|
|
+ */
|
|
+
|
|
+ if (p == c)
|
|
+ tl = cqstring;
|
|
+ else{
|
|
+ if (p){
|
|
+ for (c = 1; c < p; c++)
|
|
+ cl = cl->next;
|
|
+ free_qs(&(cl->next));
|
|
+ tl = cqstring;
|
|
+ }
|
|
+ else{
|
|
+ int done = 0;
|
|
+ QSTRING_S *al = cl; /* another line */
|
|
+ /*
|
|
+ * Ok, we really don't have enough evidence to return anything,
|
|
+ * different from the normal part of cl, but it could be possible
|
|
+ * that we may want to accept the not-normal part, so we better
|
|
+ * make an extra test to determine what needs to be freed
|
|
+ */
|
|
+ while (pl && cl && cl->qstype == pl->qstype
|
|
+ && !strucmp(cl->value, pl->value)){
|
|
+ cl = cl->next;
|
|
+ pl = pl->next;
|
|
+ }
|
|
+ if (pl && cl && cl->qstype == pl->qstype
|
|
+ && strcmp_qs(pl->value, cl->value))
|
|
+ cl = cl->next; /* next level differs only in spaces */
|
|
+ while (!done){
|
|
+ while (cl && cl->qstype == qsNormal)
|
|
+ cl = cl->next;
|
|
+ if (cl){
|
|
+ if ((cl->qstype == qsString)
|
|
+ && (cl->value[strlen(cl->value) - 1] == '>'))
|
|
+ cl = cl->next;
|
|
+ else done++;
|
|
+ }
|
|
+ else done++;
|
|
+ }
|
|
+ if (al == cl){
|
|
+ free_qs(&(cl));
|
|
+ tl = cl;
|
|
+ }
|
|
+ else {
|
|
+ while (al && (al->next != cl))
|
|
+ al = al->next;
|
|
+ cl = al;
|
|
+ if (cl && cl->next)
|
|
+ free_qs(&(cl->next));
|
|
+ tl = cqstring;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ return tl;
|
|
+ }
|
|
+
|
|
+ /* so n <= c (see above) hence n < c or n = c. If n < c then n+1 <= c, so we
|
|
+ * either have n == c or n + 1 < c or n + 1 == c. We analyze each case in the
|
|
+ * following code
|
|
+ */
|
|
+
|
|
+ if (n + 1 < c){ /* if there are not enough agreements */
|
|
+ int p = same_qstring(pl, cl); /* number of agreement between pl and cl */
|
|
+ QSTRING_S *tl; /* test line */
|
|
+ /*
|
|
+ * There's no way we can use cl in this case, but we can use
|
|
+ * part of cl, this is if pl does not have more agreements
|
|
+ * with cl.
|
|
+ */
|
|
+ if (p == c)
|
|
+ tl = cqstring;
|
|
+ else{
|
|
+ int m = p < n ? n : p;
|
|
+ for (c = 1; c < m; c++){
|
|
+ pl = pl ? pl->next : (QSTRING_S *) NULL;
|
|
+ nl = nl ? nl->next : (QSTRING_S *) NULL;
|
|
+ cl = cl->next;
|
|
+ }
|
|
+ if (p == n && pl && pl->next && nl && nl->next
|
|
+ && ((cl->next->qstype == pl->next->qstype)
|
|
+ || (cl->next->qstype == nl->next->qstype))
|
|
+ && (strcmp_qs(cl->next->value, pl->next->value)
|
|
+ || strcmp_qs(pl->next->value, cl->next->value)
|
|
+ || strcmp_qs(cl->next->value, nl->next->value)
|
|
+ || strcmp_qs(nl->next->value, cl->next->value)))
|
|
+ cl = cl->next; /* next level differs only in spaces */
|
|
+ if (cl->next)
|
|
+ free_qs(&(cl->next));
|
|
+ tl = cqstring;
|
|
+ }
|
|
+ return tl;
|
|
+ }
|
|
+ if (n + 1 == c){
|
|
+ int p = same_qstring(pl, cl);
|
|
+ QSTRING_S *tl; /* test line */
|
|
+
|
|
+ /*
|
|
+ * p <= c, so p <= n+1, which means p < n + 1 or p == n + 1.
|
|
+ * If p < n + 1, then p <= n.
|
|
+ * so we have three possibilities:
|
|
+ * p == n + 1 or p == n or p < n.
|
|
+ * In the first case we copy p == n + 1 == c levels, in the second
|
|
+ * and third case we copy n levels, and check if we can copy the
|
|
+ * n + 1 == c level.
|
|
+ */
|
|
+ if (p == n + 1) /* p == c, in the above sense of c */
|
|
+ tl = cl; /* use cl, this is enough evidence */
|
|
+ else{
|
|
+ for (c = 1; c < n; c++)
|
|
+ cl = cl->next;
|
|
+ /*
|
|
+ * Here c == n, we only have one more level of cl, and at least one
|
|
+ * more level of nl
|
|
+ */
|
|
+ if (cl->next->qstype == qsNormal)
|
|
+ cl = cl->next;
|
|
+ if (cl->next)
|
|
+ free_qs(&(cl->next));
|
|
+ tl = cqstring;
|
|
+ }
|
|
+ return tl;
|
|
+ }
|
|
+ /* else n == c, Yeah!!! */
|
|
+ return cqstring;
|
|
+ }
|
|
+
|
|
+ QSTRING_S *
|
|
+ fix_qstring_allowed(QSTRING_S *cl, QSTRING_S *nl, QSTRING_S *pl)
|
|
+ {
|
|
+ if(!cl)
|
|
+ return (QSTRING_S *) NULL;
|
|
+
|
|
+ if (qs_allowed(cl))
|
|
+ cl->next = fix_qstring_allowed(cl->next, (nl ? nl->next : NULL),
|
|
+ (pl ? pl->next : NULL));
|
|
+ else
|
|
+ if((nl && cl->qstype == nl->qstype) || (pl && cl->qstype == pl->qstype)
|
|
+ || (!nl && !pl))
|
|
+ free_qs(&cl);
|
|
+ return cl;
|
|
+ }
|
|
+
|
|
+ /*
|
|
+ * This function flattens the quote string returned to us by is_quote. A
|
|
+ * crash in this function implies a bug elsewhere.
|
|
+ */
|
|
+ void
|
|
+ flatten_qstring(QSTRING_S *qs, char *buff, int bufflen)
|
|
+ {
|
|
+ int i, j;
|
|
+ if(!buff || bufflen <= 0)
|
|
+ return;
|
|
+
|
|
+ for (i = 0; qs; qs = qs->next)
|
|
+ for (j = 0; i < bufflen - 1
|
|
+ && (qs->value[j]) && (buff[i++] = qs->value[j]); j++);
|
|
+ buff[i] = '\0';
|
|
+ }
|
|
+
|
|
+ extern int list_len;
|
|
+
|
|
+
|
|
+ int
|
|
+ double_check_qstr(char *q)
|
|
+ {
|
|
+ if(!q || !*q)
|
|
+ return 0;
|
|
+
|
|
+ return (*q == '#') ? 1 : 0;
|
|
+ }
|
|
+
|
|
+ /*
|
|
+ * Given a string, we return the position where the function thinks that
|
|
+ * the quote string is over, if you are ever thinking of fixing something,
|
|
+ * you got to the right place. Memory freed by caller. Experience shows
|
|
+ * that it only makes sense to initialize memory when we need it, not at
|
|
+ * the start of this function.
|
|
+ */
|
|
+ QSTRING_S *
|
|
+ is_quote (char **qs,char *word, int been_here)
|
|
+ {
|
|
+ int i = 0, j, nxt, prev, finished = 0, offset;
|
|
+ unsigned char c;
|
|
+ QSTRING_S *qstring = (QSTRING_S *) NULL;
|
|
+
|
|
+ if (word == NULL || word[0] == '\0')
|
|
+ return (QSTRING_S *) NULL;
|
|
+
|
|
+ while (!finished){
|
|
+ /*
|
|
+ * Before we apply our rules, let's advance past the quote string
|
|
+ * given by the user, this will avoid not recognition of the
|
|
+ * user's indent string and application of the arbitrary rules
|
|
+ * below. Notice that this step may bring bugs into this
|
|
+ * procedure, but these bugs will only appear if the indent string
|
|
+ * is really really strange and the text to be justified
|
|
+ * cooperates a lot too, so in general this will not be a problem.
|
|
+ * If you are concerned about this bug, simply remove the
|
|
+ * following lines after this comment and before the "switch"
|
|
+ * command below and use a more normal quote string!.
|
|
+ */
|
|
+ for(j = 0; j < list_len; j++){
|
|
+ if(!double_check_qstr(qs[j])){
|
|
+ i += advance_quote_string(qs[j], word, i);
|
|
+ if (!word[i]) /* went too far? */
|
|
+ return qs_add(qs, word, qsNormal, 0, i, 0, 0);
|
|
+ }
|
|
+ else
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ switch (c = (unsigned char) now(word,i)){
|
|
+ case NBSP:
|
|
+ case TAB :
|
|
+ case ' ' : { QSTRING_S *nextqs, *d;
|
|
+
|
|
+ for (; ISspace(word[i]); i++); /* FIX ME */
|
|
+ nextqs = is_quote(qs,word+i, 1);
|
|
+ /*
|
|
+ * Merge qstring and nextqs, since this is an artificial
|
|
+ * separation, unless nextqs is of different type.
|
|
+ * What this means in practice is that if
|
|
+ * qs->qstype == qsNormal and qs->next != NULL, then
|
|
+ * qs->next->qstype != qsNormal.
|
|
+ *
|
|
+ * Can't use qs_add to merge because it could lead
|
|
+ * to an infinite loop (e.g a line "^ ^").
|
|
+ */
|
|
+ i += nextqs && nextqs->qstype == qsNormal
|
|
+ ? strlen(nextqs->value) : 0;
|
|
+ qstring = (QSTRING_S *) malloc (sizeof(QSTRING_S));
|
|
+ memset (qstring, 0, sizeof(QSTRING_S));
|
|
+ qstring->value = (char *) malloc((i+1)*sizeof(char));
|
|
+ strncpy(qstring->value, word, i);
|
|
+ qstring->value[i] = '\0';
|
|
+ qstring->qstype = qsNormal;
|
|
+ if(nextqs && nextqs->qstype == qsNormal){
|
|
+ d = nextqs->next;
|
|
+ nextqs->next = NULL;
|
|
+ qstring->next = d;
|
|
+ free_qs(&nextqs);
|
|
+ }
|
|
+ else
|
|
+ qstring->next = nextqs;
|
|
+
|
|
+ return qstring;
|
|
+ }
|
|
+ break;
|
|
+ case RPAREN: /* parenthesis ')' */
|
|
+ if ((i != 0) || ((i == 0) && been_here))
|
|
+ i++;
|
|
+ else
|
|
+ if (i == 0)
|
|
+ return qs_add(qs, word, qsChar, i, i, 1, 1);
|
|
+ else
|
|
+ finished++;
|
|
+ break;
|
|
+
|
|
+ case ':': /* colon */
|
|
+ case '~': nxt = next(word,i);
|
|
+ if ((is_tilde(c) && (nxt == '/'))
|
|
+ || (is_colon(c) && !is_cquote(nxt)
|
|
+ && !is_cword(nxt) && nxt != RPAREN))
|
|
+ finished++;
|
|
+ else if (is_cquote(c)
|
|
+ || is_cquote(nxt)
|
|
+ || (c != '~' && nxt == RPAREN)
|
|
+ || (i != 0 && ISspace(nxt))
|
|
+ || is_cquote(prev = before(word,i))
|
|
+ || (ISspace(prev) && !is_tilde(c))
|
|
+ || (is_tilde(c) && nxt != '/'))
|
|
+ i++;
|
|
+ else if (i == 0 && been_here)
|
|
+ return qs_add(qs, word, qsChar, i, i, 1, 1);
|
|
+ else
|
|
+ finished++;
|
|
+ break;
|
|
+
|
|
+ case '<' :
|
|
+ case '=' :
|
|
+ case '-' : offset = is_cquote(nxt = next(word,i)) ? 2
|
|
+ : (nxt == c && is_cquote(next(word,i+1))) ? 3 : -1;
|
|
+
|
|
+ if (offset > 0)
|
|
+ return qs_add(qs, word, qsString, i, i, offset, 1);
|
|
+ else
|
|
+ finished++;
|
|
+ break;
|
|
+
|
|
+ case '[' :
|
|
+ case '+' : /* accept +>, *> */
|
|
+ case '*' : if (is_rarrow(nxt = next(word, i)) || /* stars */
|
|
+ (ISspace(nxt) && is_rarrow(next(word,i+1))))
|
|
+ i++;
|
|
+ else
|
|
+ finished++;
|
|
+ break;
|
|
+
|
|
+ case '^' :
|
|
+ case '!' :
|
|
+ case '%' : if (next(word,i) != c)
|
|
+ return qs_add(qs, word, qsChar, i, i+1, 0, 1);
|
|
+ else
|
|
+ finished++;
|
|
+ break;
|
|
+
|
|
+ case '_' : if(ISspace(next(word, i)))
|
|
+ return qs_add(qs, word, qsChar, i, i+1, 0, 1);
|
|
+ else
|
|
+ finished++;
|
|
+ break;
|
|
+
|
|
+ case '#' : { QStrType qstype = qsChar;
|
|
+ if((nxt = next(word, i)) != c){
|
|
+ if(isdigit((int) nxt))
|
|
+ qstype = qsGdb;
|
|
+ else
|
|
+ if(word_is_prog(word))
|
|
+ qstype = qsProg;
|
|
+ return qs_add(qs, word, qstype, i, i+1, 0, 1);
|
|
+ }
|
|
+ else
|
|
+ finished++;
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ default:
|
|
+ if (is_cquote(c))
|
|
+ i++;
|
|
+ else if (is_cletter(c)){
|
|
+ for (j = i; (is_cletter(nxt = next(word,j)) || is_cnumber(nxt))
|
|
+ && !(ISspace(nxt));j++);
|
|
+ /*
|
|
+ * The whole reason why we are splitting the quote
|
|
+ * string is so that we will be able to accept quote
|
|
+ * strings that are strange in some way. Here we got to
|
|
+ * a point in which a quote string might exist, but it
|
|
+ * could be strange, so we need to create a "next" field
|
|
+ * for the quote string to warn us that something
|
|
+ * strange is coming. We need to confirm if this is a
|
|
+ * good choice later. For now we will let it pass.
|
|
+ */
|
|
+ if (isaword(word,i,j) || isamailbox(word,i,j)){
|
|
+ int offset;
|
|
+ QStrType qstype;
|
|
+
|
|
+ offset = (is_cquote(c = next(word,j))
|
|
+ || (c == RPAREN)) ? 2
|
|
+ : ((ISspace(c)
|
|
+ && is_cquote(next(word,j+1))) ? 3 : -1);
|
|
+
|
|
+ qstype = (is_cquote(c) || (c == RPAREN))
|
|
+ ? (is_qsword(c) ? qsWord : qsString)
|
|
+ : ((ISspace(c) && is_cquote(next(word,j+1)))
|
|
+ ? (is_qsword(next(word,j+1))
|
|
+ ? qsWord : qsString)
|
|
+ : qsString);
|
|
+
|
|
+ /*
|
|
+ * qsWords are valid quote strings only when
|
|
+ * they are followed by text.
|
|
+ */
|
|
+ if (offset > 0 && qstype == qsWord &&
|
|
+ !allwd_after_qsword(now(word,j + offset)))
|
|
+ offset = -1;
|
|
+
|
|
+ if (offset > 0)
|
|
+ return qs_add(qs, word, qstype, i, j, offset, 1);
|
|
+ }
|
|
+ finished++;
|
|
+ }
|
|
+ else{
|
|
+ if(i > 0)
|
|
+ return qs_add(qs, word, qsNormal, 0, i, 0, 1);
|
|
+ else if(!forbidden(c))
|
|
+ return qs_add(qs, word, qsChar, 0, 1, 0, 1);
|
|
+ else /* chao pescao */
|
|
+ finished++;
|
|
+ }
|
|
+ break;
|
|
+ } /* End Switch */
|
|
+ } /* End while */
|
|
+ if (i > 0)
|
|
+ qstring = qs_add(qs, word, qsNormal, 0, i, 0, 0);
|
|
+ return qstring;
|
|
+ }
|
|
+
|
|
+ int
|
|
+ isaword(char word[NSTRING], int i, int j)
|
|
+ {
|
|
+ return (i <= j && is_cletter(word[i])) ?
|
|
+ (i < j ? isaword(word,i+1,j) : 1) : 0;
|
|
+ }
|
|
+
|
|
+ int
|
|
+ isamailbox(char word[NSTRING], int i, int j)
|
|
+ {
|
|
+ return i <= j && (is_cletter(word[i]) || is_a_digit(word[i])
|
|
+ || word[i] == '.')
|
|
+ ? (i < j ? isamailbox(word,i+1,j) : 1) : 0;
|
|
+ }
|
|
+
|
|
+ /*
|
|
+ This routine removes the last part that is qsword or qschar that is not
|
|
+ followed by a normal part. This means that if a qsword or qschar is
|
|
+ followed by a qsnormal (or qsstring), we accept the qsword (or qschar)
|
|
+ as part of a quote string.
|
|
+ */
|
|
+ QSTRING_S *
|
|
+ remove_qsword(QSTRING_S *cl)
|
|
+ {
|
|
+ QSTRING_S *np = cl;
|
|
+ QSTRING_S *cp = np; /* this variable trails cl */
|
|
+
|
|
+ while(1){
|
|
+ while (cl && cl->qstype == qsNormal)
|
|
+ cl = cl->next;
|
|
+
|
|
+ if (cl){
|
|
+ if (((cl->qstype == qsWord) || (cl->qstype == qsChar))
|
|
+ && !exists_good_part(cl)){
|
|
+ if (np == cl) /* qsword or qschar at the beginning */
|
|
+ free_qs(&cp);
|
|
+ else{
|
|
+ while (np->next != cl)
|
|
+ np = np->next;
|
|
+ free_qs(&(np->next));
|
|
+ }
|
|
+ break;
|
|
+ }
|
|
+ else
|
|
+ cl = cl->next;
|
|
+ }
|
|
+ else
|
|
+ break;
|
|
+ }
|
|
+ return cp;
|
|
+ }
|
|
+
|
|
+ int
|
|
+ exists_good_part (QSTRING_S *cl)
|
|
+ {
|
|
+ return (cl ? (((cl->qstype != qsWord) && (cl->qstype != qsChar)
|
|
+ && qs_allowed(cl) && !value_is_space(cl->value))
|
|
+ ? 1 : exists_good_part(cl->next))
|
|
+ : 0);
|
|
+ }
|
|
+
|
|
+ int
|
|
+ line_isblank(char **q, char *GLine, char *NLine, char *PLine, int buflen)
|
|
+ {
|
|
+ int n = 0;
|
|
+ QSTRING_S *cl;
|
|
+ char qstr[NSTRING];
|
|
+
|
|
+ cl = do_raw_quote_match(q, GLine, NLine, PLine, NULL, NULL);
|
|
+
|
|
+ flatten_qstring(cl, qstr, NSTRING);
|
|
+
|
|
+ free_qs(&cl);
|
|
+
|
|
+ for(n = strlen(qstr); n < buflen && GLine[n]; n++)
|
|
+ if(!ISspace((unsigned char) GLine[n]))
|
|
+ return(FALSE);
|
|
+
|
|
+ return(TRUE);
|
|
+ }
|
|
+
|
|
+ QSTRING_S *
|
|
+ do_raw_quote_match(char **q, char *GLine, char *NLine, char *PLine, QSTRING_S **nlp, QSTRING_S **plp)
|
|
+ {
|
|
+ QSTRING_S *cl, *nl = NULL, *pl = NULL;
|
|
+ char nbuf[NSTRING], pbuf[NSTRING], buf[NSTRING];
|
|
+ int emptypl = 0, emptynl = 0;
|
|
+
|
|
+ if (!(cl = is_quote(q, GLine, 0))) /* if nothing in, nothing out */
|
|
+ return cl;
|
|
+
|
|
+ nl = is_quote(q, NLine, 0); /* Next Line */
|
|
+ if (nlp) *nlp = nl;
|
|
+ pl = is_quote(q, PLine, 0); /* Previous Line */
|
|
+ if (plp) *plp = pl;
|
|
+ /*
|
|
+ * If there's nothing in the preceeding or following line
|
|
+ * there is not enough information to accept it or discard it. In this
|
|
+ * case it's likely to be an isolated line, so we better accept it
|
|
+ * if it does not look like a word.
|
|
+ */
|
|
+ flatten_qstring(pl, pbuf, NSTRING);
|
|
+ emptypl = (!PLine || !PLine[0] ||
|
|
+ (pl && value_is_space(pbuf) && !PLine[strlen(pbuf)])) ? 1 : 0;
|
|
+ if (emptypl){
|
|
+ flatten_qstring(nl, nbuf, NSTRING);
|
|
+ emptynl = (!NLine || !NLine[0] ||
|
|
+ (nl && value_is_space(nbuf) && !NLine[strlen(nbuf)])) ? 1 : 0;
|
|
+ if (emptynl){
|
|
+ cl = remove_qsword(cl);
|
|
+ if((cl = fix_qstring_allowed(cl, NULL, NULL)) != NULL)
|
|
+ cl = qs_remove_trailing_spaces(cl);
|
|
+ free_qs(&nl);
|
|
+ free_qs(&pl);
|
|
+ if(nlp) *nlp = NULL;
|
|
+ if(plp) *plp = NULL;
|
|
+
|
|
+ return cl;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ /*
|
|
+ * If either cl, nl or pl contain suspicious characters that may make
|
|
+ * them (or not) be quote strings, we need to fix them, so that the
|
|
+ * next pass will be done correctly.
|
|
+ */
|
|
+
|
|
+ cl = fix_qstring(cl, nl, pl);
|
|
+ nl = trim_qs_from_cl(cl, nl, NULL);
|
|
+ pl = trim_qs_from_cl(cl, NULL, pl);
|
|
+ if((cl = fix_qstring_allowed(cl, nl, pl)) != NULL){
|
|
+ nl = trim_qs_from_cl(cl, nl, NULL);
|
|
+ pl = trim_qs_from_cl(cl, NULL, pl);
|
|
+ }
|
|
+ else{
|
|
+ free_qs(&nl);
|
|
+ free_qs(&pl);
|
|
+ }
|
|
+ if(nlp)
|
|
+ *nlp = nl;
|
|
+ else
|
|
+ free_qs(&nl);
|
|
+ if(plp)
|
|
+ *plp = pl;
|
|
+ else
|
|
+ free_qs(&pl);
|
|
+ return cl;
|
|
+ }
|
|
+
|
|
+ QSTRING_S *
|
|
+ do_quote_match(char **q, char *GLine, char *NLine, char *PLine, char *rqstr,
|
|
+ int rqstrlen, int plb)
|
|
+ {
|
|
+ QSTRING_S *cl, *nl = NULL, *pl = NULL;
|
|
+ int c, n, p,i, j, NewP, NewC, NewN, clength, same = 0;
|
|
+ char nbuf[NSTRING], pbuf[NSTRING], buf[NSTRING];
|
|
+
|
|
+ if(rqstr)
|
|
+ *rqstr = '\0';
|
|
+
|
|
+ /* if nothing in, nothing out */
|
|
+ cl = do_raw_quote_match(q, GLine, NLine, PLine, &nl, &pl);
|
|
+ if(cl == NULL){
|
|
+ free_qs(&nl);
|
|
+ free_qs(&pl);
|
|
+ return cl;
|
|
+ }
|
|
+
|
|
+ flatten_qstring(cl, rqstr, rqstrlen);
|
|
+ flatten_qstring(cl, buf, NSTRING);
|
|
+ flatten_qstring(nl, nbuf, NSTRING);
|
|
+ flatten_qstring(pl, pbuf, NSTRING);
|
|
+
|
|
+ /*
|
|
+ * Once upon a time, is_quote used to return the length of the quote
|
|
+ * string that it had found. One day, not long ago, black hand came
|
|
+ * and changed all that, and made is_quote return a quote string
|
|
+ * divided in several fields, making the algorithm much more
|
|
+ * complicated. Fortunately black hand left a few comments in the
|
|
+ * source code to make it more understandable. Because of this change
|
|
+ * we need to compute the lengths of the quote strings separately
|
|
+ */
|
|
+ c = buf && buf[0] ? strlen(buf) : 0;
|
|
+ n = nbuf && nbuf[0] ? strlen(nbuf) : 0;
|
|
+ p = pbuf && pbuf[0] ? strlen(pbuf) : 0;
|
|
+ /*
|
|
+ * When quote strings contain only blank spaces (ascii code 32) the
|
|
+ * above count is equal to the length of the quote string, but if
|
|
+ * there are TABS, the length of the quote string as seen by the user
|
|
+ * is different than the number that was just computed. Because of
|
|
+ * this we demand a recount (hmm.. unless you are in Florida, where
|
|
+ * recounts are forbidden)
|
|
+ */
|
|
+ NewP = strlenis(pbuf);
|
|
+ NewC = strlenis(buf);
|
|
+ NewN = strlenis(nbuf);
|
|
+
|
|
+ /*
|
|
+ * For paragraphs with spaces in the first line, but no space in the
|
|
+ * quote string of the second line, we make sure we choose the quote
|
|
+ * string without a space at the end of it.
|
|
+ */
|
|
+ if ((NLine && !NLine[0])
|
|
+ && ((PLine && !PLine[0])
|
|
+ || (((same = same_qstring(pl, cl)) != 0)
|
|
+ && (same != count_levels_qstring(cl)))))
|
|
+ cl = qs_remove_trailing_spaces(cl);
|
|
+ else
|
|
+ if (NewC > NewN){
|
|
+ int agree = 0;
|
|
+ for (j = 0; (j < n) && (GLine[j] == NLine[j]); j++);
|
|
+ clength = j;
|
|
+ /* clength is the common length in which Gline and Nline agree */
|
|
+ /* j < n means that they do not agree fully */
|
|
+ /* GLine = " \tText"
|
|
+ NLine = " Text" */
|
|
+ if(j == n)
|
|
+ agree++;
|
|
+ if (clength < n){ /* see if buf and nbuf are padded with spaces and tabs */
|
|
+ for (i = clength; i < n && ISspace(NLine[i]); i++);
|
|
+ if (i == n){/* padded NLine until the end of spaces? */
|
|
+ for (i = clength; i < c && ISspace(GLine[i]); i++);
|
|
+ if (i == c) /* Padded CLine until the end of spaces? */
|
|
+ agree++;
|
|
+ }
|
|
+ }
|
|
+ if (agree){
|
|
+ for (j = clength; j < c && ISspace(GLine[j]); j++);
|
|
+ if (j == c){
|
|
+ /*
|
|
+ * If we get here, it means that the current line has the same
|
|
+ * quote string (visually) than the next line, but both of them
|
|
+ * are padded with different amount of TABS or spaces at the end.
|
|
+ * The current line (GLine) has more spaces/TABs than the next
|
|
+ * line. This is the typical situation that is found at the
|
|
+ * begining of a paragraph. We need to check this, however, by
|
|
+ * checking the previous line. This avoids that we confuse
|
|
+ * ourselves with being in the last line of a paragraph.
|
|
+ * Example when it should not free_qs(cl)
|
|
+ * " Text in Paragraph 1" (PLine)
|
|
+ * " Text in Paragraph 1" (GLine)
|
|
+ * " Other Paragraph Number 2" (NLine)
|
|
+ *
|
|
+ * Example when it should free_qs(cl):
|
|
+ * ":) " (PLine) p = 3, j = 3
|
|
+ * ":) Text" (GLine) c = 5
|
|
+ * ":) More text" (NLine) n = 3
|
|
+ *
|
|
+ * Example when it should free_qs(cl):
|
|
+ * ":) " (PLine) p = 3, j = 3
|
|
+ * ":) > > > Text" (GLine) c = 11
|
|
+ * ":) > > > More text" (NLine) n = 9
|
|
+ *
|
|
+ * Example when it should free_qs(cl):
|
|
+ * ":) :) " (PLine) p = 6, j = 3
|
|
+ * ":) > > > Text" (GLine) c = 11
|
|
+ * ":) > > > More text" (NLine) n = 9
|
|
+ *
|
|
+ * Example when it should free_qs(cl):
|
|
+ * ":) > > > " (PLine) p = 13, j = 11
|
|
+ * ":) > > > Text" (GLine) c = 11
|
|
+ * ":) > > > More text" (NLine) n = 9
|
|
+ *
|
|
+ * The following example is very interesting. The "Other Text"
|
|
+ * line below should free the quote string an make it equal to the
|
|
+ * quote string of the line below it, but any algorithm trying
|
|
+ * to advance past that line should make it stop there, so
|
|
+ * we need one more check, to check the raw quote string and the
|
|
+ * processed quote string at the same time.
|
|
+ * FREE qs in this example.
|
|
+ * " Some Text" (PLine) p = 3, j = 0
|
|
+ * "\tOther Text" (GLine) c = 1
|
|
+ * " More Text" (NLine) n = 3
|
|
+ *
|
|
+ */
|
|
+ for (j = 0; (j < p) && (GLine[j] == PLine[j]); j++);
|
|
+ if ((p != c || j != p) && NLine[n])
|
|
+ if(!get_indent_raw_line(q, PLine, nbuf, NSTRING, p, plb)
|
|
+ || NewP + strlenis(nbuf) != NewC){
|
|
+ free_qs(&cl);
|
|
+ free_qs(&pl);
|
|
+ return nl;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ free_qs(&nl);
|
|
+ free_qs(&pl);
|
|
+
|
|
+ return cl;
|
|
+ }
|
|
+
|
|
+ /*
|
|
+ * Given a line, an initial position, and a quote string, we advance the
|
|
+ * current line past the quote string, including arbitraty spaces
|
|
+ * contained in the line, except that it removes trailing spaces. We do
|
|
+ * not handle TABs, if any, contained in the quote string. At least not
|
|
+ * yet.
|
|
+ *
|
|
+ * Arguments: q - quote string
|
|
+ * l - a line to process
|
|
+ * i - position in the line to start processing. i = 0 is the
|
|
+ * begining of that line.
|
|
+ */
|
|
+ int
|
|
+ advance_quote_string(char *q, char l[NSTRING], int i)
|
|
+ {
|
|
+ int n = 0, j = 0, is = 0, es = 0;
|
|
+ int k, m, p, adv;
|
|
+ char qs[NSTRING] = {'\0'};
|
|
+ if(!q || !*q)
|
|
+ return(0);
|
|
+ for (p = strlen(q); (p > 0) && (q[p - 1] == ' '); p--, es++);
|
|
+ if (!p){ /* string contains only spaces */
|
|
+ for (k = 0; ISspace(l[i + k]); k++);
|
|
+ k -= k % es;
|
|
+ return k;
|
|
+ }
|
|
+ for (is = 0; ISspace(q[is]); is++); /* count initial spaces */
|
|
+ for (m = 0 ; is + m < p ; m++)
|
|
+ qs[m] = q[is + m]; /* qs = quote string without any space at the end */
|
|
+ /* advance as many spaces as there are at the begining */
|
|
+ for (k = 0; ISspace(l[i + j]); k++, j++);
|
|
+ /* now find the visible string in the line */
|
|
+ for (m = 0; qs[m] && l[i + j] == qs[m]; m++, j++);
|
|
+ if (!qs[m]){ /* no match */
|
|
+ /*
|
|
+ * So far we have advanced at least "is" spaces, plus the visible
|
|
+ * string "qs". Now we need to advance the trailing number of
|
|
+ * spaces "es". If we can do that, we have found the quote string.
|
|
+ */
|
|
+ for (p = 0; ISspace(l[i + j + p]); p++);
|
|
+ adv = advance_quote_string(q, l, i + j + ((p < es) ? p : es));
|
|
+ n = ((p < es) ? 0 : es) + k + m + adv;
|
|
+ }
|
|
+ return n;
|
|
+ }
|
|
+
|
|
+ /*
|
|
+ * This function returns the effective length in screen of the quote
|
|
+ * string. If the string contains a TAB character, it is added here, if
|
|
+ * not, the length returned is the length of the string
|
|
+ */
|
|
+ int strlenis(char *qstr)
|
|
+ {
|
|
+ int i, rv = 0;
|
|
+ for (i = 0; qstr && qstr[i]; i++)
|
|
+ rv += ((qstr[i] == TAB) ? (~rv & 0x07) + 1 : 1);
|
|
+ return rv;
|
|
+ }
|
|
+
|
|
+ int
|
|
+ is_indent (char word[NSTRING], int plb)
|
|
+ {
|
|
+ int i = 0, finished = 0, j, k, digit = 0, bdigits = -1, alpha = 0;
|
|
+ unsigned char c, nxt;
|
|
+
|
|
+ if (!word || !word[0])
|
|
+ return i;
|
|
+
|
|
+ for (i = 0, j = 0; ISspace(word[i]); i++, j++);
|
|
+ while ((i < NSTRING - 2) && !finished){
|
|
+ switch (c = (unsigned char) now(word,i)){
|
|
+ case NBSP:
|
|
+ case TAB :
|
|
+ case ' ' : for (; ISspace(word[i]); i++)
|
|
+ ;
|
|
+ if (!is_indent_char(now(word,i)))
|
|
+ finished++;
|
|
+ break;
|
|
+
|
|
+ case '+' :
|
|
+ case '.' :
|
|
+ case ']' :
|
|
+ case '*' :
|
|
+ case '}' :
|
|
+ case '-' :
|
|
+ case RPAREN:
|
|
+ nxt = (unsigned char) next(word,i);
|
|
+ if ((c == '.' && allowed_after_period(nxt) && alpha)
|
|
+ || (c == '*' && allowed_after_star(nxt))
|
|
+ || (c == '}' && allowed_after_braces(nxt))
|
|
+ || (c == '-' && allowed_after_dash(nxt))
|
|
+ || (c == '+' && allowed_after_dash(nxt))
|
|
+ || (c == RPAREN && allowed_after_parenth(nxt))
|
|
+ || (c == ']' && allowed_after_parenth(nxt)))
|
|
+ i++;
|
|
+ else
|
|
+ finished++;
|
|
+ break;
|
|
+
|
|
+ case 0xE2: /* bullet? */
|
|
+ nxt = (unsigned char) next(word,i);
|
|
+ if(nxt == 0x80){
|
|
+ nxt = (unsigned char) next(word,i+1);
|
|
+ if(nxt == 0xA2){
|
|
+ nxt = (unsigned char) next(word,i+2);
|
|
+ if(allowed_after_star(nxt))
|
|
+ i += 3;
|
|
+ else
|
|
+ finished++;
|
|
+ }
|
|
+ else finished++;
|
|
+ }
|
|
+ else finished++;
|
|
+ break;
|
|
+
|
|
+ default : if (is_a_digit(c) && plb){
|
|
+ if (bdigits < 0)
|
|
+ bdigits = i; /* first digit */
|
|
+ for (k = i; is_a_digit(now(word,k)); k++);
|
|
+ if (k - bdigits > 2){ /* more than 2 digits? */
|
|
+ i = bdigits; /* too many! */
|
|
+ finished++;
|
|
+ }
|
|
+ else{
|
|
+ if(allowed_after_digit(now(word,k),word,k)){
|
|
+ alpha++;
|
|
+ i = k;
|
|
+ }
|
|
+ else{
|
|
+ i = bdigits;
|
|
+ finished++;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ else
|
|
+ finished++;
|
|
+ break;
|
|
+
|
|
+ }
|
|
+ }
|
|
+ if (i == j)
|
|
+ i = 0; /* there must be something more than spaces in an indent string */
|
|
+ return i;
|
|
+ }
|
|
+
|
|
+ int
|
|
+ get_indent_raw_line(char **q, char *GLine, char *buf, int buflen, int k, int plb)
|
|
+ {
|
|
+ int i, j;
|
|
+ char testline[1024];
|
|
+
|
|
+ if(k > 0){
|
|
+ for(j = 0; GLine[j] != '\0'; j++){
|
|
+ testline[j] = GLine[j];
|
|
+ testline[j+1] = '\0';
|
|
+ if(strlenis(testline) >= strlenis(buf))
|
|
+ break;
|
|
+ }
|
|
+ k = ++j; /* reset k */
|
|
+ }
|
|
+ i = is_indent(GLine+k, plb);
|
|
+
|
|
+ for (j = 0; j < i && j < buflen && (buf[j] = GLine[j + k]); j++);
|
|
+ buf[j] = '\0';
|
|
+
|
|
+ return i;
|
|
+ }
|
|
+
|
|
+ /* support for remembering quote strings across messages */
|
|
+ char **allowed_qstr = NULL;
|
|
+ int list_len = 0;
|
|
+
|
|
+ void
|
|
+ free_allowed_qstr(void)
|
|
+ {
|
|
+ int i;
|
|
+ char **q = allowed_qstr;
|
|
+
|
|
+ if(q == NULL)
|
|
+ return;
|
|
+
|
|
+ for(i = 0; i < list_len; i++)
|
|
+ fs_give((void **)&q[i]);
|
|
+
|
|
+ fs_give((void **)q);
|
|
+ list_len = 0;
|
|
+ }
|
|
+
|
|
+ void
|
|
+ add_allowed_qstr(void *q, int type)
|
|
+ {
|
|
+ int i;
|
|
+
|
|
+ if(allowed_qstr == NULL){
|
|
+ allowed_qstr = malloc(sizeof(char *));
|
|
+ list_len = 0;
|
|
+ }
|
|
+
|
|
+ if(type == 0){
|
|
+ allowed_qstr[list_len] = malloc((1+strlen((char *)q))*sizeof(char));
|
|
+ strcpy(allowed_qstr[list_len], (char *)q);
|
|
+ }
|
|
+ else
|
|
+ allowed_qstr[list_len] = (char *) ucs4_to_utf8_cpystr((UCS *)q);
|
|
+
|
|
+ fs_resize((void **)&allowed_qstr, (++list_len + 1)*sizeof(char *));
|
|
+ allowed_qstr[list_len] = NULL;
|
|
+ }
|
|
+
|
|
+ void
|
|
+ record_quote_string (QSTRING_S *qs)
|
|
+ {
|
|
+ int i, j, k;
|
|
+
|
|
+ for(; qs && qs->value; qs = qs->next){
|
|
+ j = 0;
|
|
+ for (; ;){
|
|
+ k = j;
|
|
+ for(i = 0; i < list_len; i++){
|
|
+ j += advance_quote_string(allowed_qstr[i], qs->value, j);
|
|
+ for(; ISspace(qs->value[j]); j++);
|
|
+ }
|
|
+ if(k == j)
|
|
+ break;
|
|
+ }
|
|
+ if(qs->value[j] != '\0')
|
|
+ add_allowed_qstr((void *)(qs->value + j), 0);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ /* type utf8: code 0; ucs4: code 1. */
|
|
+ char **
|
|
+ default_qstr(void *q, int type)
|
|
+ {
|
|
+ if(allowed_qstr == NULL)
|
|
+ add_allowed_qstr(q, type);
|
|
+
|
|
+ return allowed_qstr;
|
|
+ }
|
|
+
|
|
diff -rc alpine-2.26/pith/osdep/color.h alpine-2.26.fillpara/pith/osdep/color.h
|
|
*** alpine-2.26/pith/osdep/color.h 2022-06-02 18:14:00.495274738 -0600
|
|
--- alpine-2.26.fillpara/pith/osdep/color.h 2022-06-02 18:14:57.039136093 -0600
|
|
***************
|
|
*** 17,22 ****
|
|
--- 17,40 ----
|
|
#ifndef PITH_OSDEP_COLOR_INCLUDED
|
|
#define PITH_OSDEP_COLOR_INCLUDED
|
|
|
|
+ /*
|
|
+ * struct that will help us determine what the quote string of a line
|
|
+ * is. The "next" field indicates the presence of a possible continuation.
|
|
+ * The idea is that if a continuation fails, we free it and check for the
|
|
+ * remaining structure left
|
|
+ */
|
|
+
|
|
+ typedef enum {qsNormal, qsString, qsWord, qsChar, qsGdb, qsProg, qsText} QStrType;
|
|
+
|
|
+ typedef struct QSTRING {
|
|
+ char *value; /* possible quote string */
|
|
+ QStrType qstype; /* type of quote string */
|
|
+ struct QSTRING *next; /* possible continuation */
|
|
+ } QSTRING_S;
|
|
+
|
|
+ #define UCH(c) ((unsigned char) (c))
|
|
+ #define NBSP UCH('\240')
|
|
+ #define ISspace(c) (UCH(c) == ' ' || UCH(c) == TAB || UCH(c) == NBSP)
|
|
|
|
#define RGBLEN 11
|
|
#define MAXCOLORLEN 11 /* longest string a color can be */
|
|
***************
|
|
*** 93,98 ****
|
|
char *pico_get_last_bg_color(void);
|
|
char *color_to_canonical_name(char *);
|
|
int pico_count_in_color_table(void);
|
|
!
|
|
|
|
#endif /* PITH_OSDEP_COLOR_INCLUDED */
|
|
--- 111,124 ----
|
|
char *pico_get_last_bg_color(void);
|
|
char *color_to_canonical_name(char *);
|
|
int pico_count_in_color_table(void);
|
|
! int is_indent(char *, int);
|
|
! int get_indent_raw_line (char **, char *, char *, int, int, int);
|
|
! int line_isblank(char **, char *, char *, char *, int);
|
|
! int strlenis(char *);
|
|
! int value_is_space(char *);
|
|
! int advance_quote_string(char *, char *, int);
|
|
! void free_allowed_qstr(void);
|
|
! void add_allowed_qstr(void *, int);
|
|
! void record_quote_string (QSTRING_S *);
|
|
|
|
#endif /* PITH_OSDEP_COLOR_INCLUDED */
|
|
diff -rc alpine-2.26/pith/pine.hlp alpine-2.26.fillpara/pith/pine.hlp
|
|
*** alpine-2.26/pith/pine.hlp 2022-06-02 18:14:00.491274749 -0600
|
|
--- alpine-2.26.fillpara/pith/pine.hlp 2022-06-02 18:14:57.059136043 -0600
|
|
***************
|
|
*** 8510,8515 ****
|
|
--- 8510,8555 ----
|
|
"type the character ^".
|
|
|
|
<P>
|
|
+ This version of Alpine contains an enhanced algorithm for justification,
|
|
+ which allows you to justify text that contains more complicated quote
|
|
+ strings. This algorithm is based on pragmatics, rather than on a theory,
|
|
+ and seems to work well with most messages. Below you will find technical
|
|
+ information on how this algorithm works.
|
|
+
|
|
+ <P>
|
|
+ When justifying, Alpine goes through each line of the text and tries to
|
|
+ determine for each line what the quote string of that line is. The quote
|
|
+ string you provided is always recognized. Among other characters
|
|
+ recognized is ">".
|
|
+
|
|
+ <P>
|
|
+ Some other constructions of quote strings are recognized only if they
|
|
+ appear enough in the text. For example "Peter :" is only
|
|
+ recognized if it appears in two consecutive lines.
|
|
+
|
|
+ <P>
|
|
+ Additionaly, Alpine recognizes indent-strings and justifies text in a
|
|
+ paragraph to the right of indent-string, padding with spaces if necessary.
|
|
+ An indent string is one which you use to delimit elements of a list. For
|
|
+ example, if you were to write a list of groceries, one may write:
|
|
+
|
|
+ <UL>
|
|
+ <LI> Fruit
|
|
+ <LI> Bread
|
|
+ <LI> Eggs
|
|
+ </UL>
|
|
+
|
|
+ <P>
|
|
+ In this case the character "*" is the indent-string. Aline
|
|
+ recognizes numbers (0, 1, 2.5, etc) also as indent-strings, and certain
|
|
+ combinations of spaces, periods, and parenthesis. In any case, numbers are
|
|
+ recognized <B>ONLY</B> if the line preceeding the given line is empty or
|
|
+ ends in one of the characters "." or ":".
|
|
+ In addition to the explanation of what constitutes a paragraph above, a
|
|
+ new paragraph is recognized when an indent-string is found in it (and
|
|
+ validated according to the above stated rules).
|
|
+
|
|
+ <P>
|
|
<End of help on this topic>
|
|
</BODY>
|
|
</HTML>
|
|
diff -rc alpine-2.26/pith/reply.c alpine-2.26.fillpara/pith/reply.c
|
|
*** alpine-2.26/pith/reply.c 2022-06-02 18:14:00.495274738 -0600
|
|
--- alpine-2.26.fillpara/pith/reply.c 2022-06-02 18:14:57.059136043 -0600
|
|
***************
|
|
*** 2834,2839 ****
|
|
--- 2834,2842 ----
|
|
if(flow_res && ps_global->reply.use_flowed)
|
|
wrapflags |= GFW_FLOW_RESULT;
|
|
|
|
+ filters[filtcnt].filter = gf_quote_test;
|
|
+ filters[filtcnt++].data = gf_line_test_opt(select_quote, NULL);
|
|
+
|
|
filters[filtcnt].filter = gf_wrap;
|
|
/*
|
|
* The 80 will cause longer lines than what is likely
|
|
***************
|
|
*** 2927,2933 ****
|
|
dq.do_color = 0;
|
|
dq.delete_all = 1;
|
|
|
|
! filters[filtcnt].filter = gf_line_test;
|
|
filters[filtcnt++].data = gf_line_test_opt(delete_quotes, &dq);
|
|
}
|
|
|
|
--- 2930,2936 ----
|
|
dq.do_color = 0;
|
|
dq.delete_all = 1;
|
|
|
|
! filters[filtcnt].filter = gf_quote_test;
|
|
filters[filtcnt++].data = gf_line_test_opt(delete_quotes, &dq);
|
|
}
|
|
|
|
diff -rc alpine-2.26/pith/state.c alpine-2.26.fillpara/pith/state.c
|
|
*** alpine-2.26/pith/state.c 2022-06-02 18:14:00.491274749 -0600
|
|
--- alpine-2.26.fillpara/pith/state.c 2022-06-02 18:14:57.059136043 -0600
|
|
***************
|
|
*** 231,236 ****
|
|
--- 231,238 ----
|
|
if((*pps)->kw_colors)
|
|
free_spec_colors(&(*pps)->kw_colors);
|
|
|
|
+ free_allowed_qstr();
|
|
+
|
|
if((*pps)->atmts){
|
|
int i;
|
|
|
|
diff -rc alpine-2.26/pith/state.h alpine-2.26.fillpara/pith/state.h
|
|
*** alpine-2.26/pith/state.h 2022-06-02 18:14:00.491274749 -0600
|
|
--- alpine-2.26.fillpara/pith/state.h 2022-06-02 18:14:57.087135974 -0600
|
|
***************
|
|
*** 264,269 ****
|
|
--- 264,271 ----
|
|
SPEC_COLOR_S *hdr_colors; /* list of configured colors for view */
|
|
SPEC_COLOR_S *index_token_colors; /* list of configured colors for index */
|
|
|
|
+ char *prefix; /* prefix for fillpara */
|
|
+ char **list_qstr; /* list of known quote strings */
|
|
short init_context;
|
|
|
|
struct {
|
|
diff -rc alpine-2.26/pith/text.c alpine-2.26.fillpara/pith/text.c
|
|
*** alpine-2.26/pith/text.c 2022-06-02 18:14:00.491274749 -0600
|
|
--- alpine-2.26.fillpara/pith/text.c 2022-06-02 18:14:57.091135965 -0600
|
|
***************
|
|
*** 88,94 ****
|
|
char *err, *charset;
|
|
int filtcnt = 0, error_found = 0, column, wrapit;
|
|
int is_in_sig = OUT_SIG_BLOCK;
|
|
! int is_flowed_msg = 0;
|
|
int is_delsp_yes = 0;
|
|
int filt_only_c0 = 0;
|
|
char *parmval;
|
|
--- 88,94 ----
|
|
char *err, *charset;
|
|
int filtcnt = 0, error_found = 0, column, wrapit;
|
|
int is_in_sig = OUT_SIG_BLOCK;
|
|
! int is_flowed_msg = 0, add_me = 1, doraw = RAWSTRING;
|
|
int is_delsp_yes = 0;
|
|
int filt_only_c0 = 0;
|
|
char *parmval;
|
|
***************
|
|
*** 176,182 ****
|
|
&& pico_usingcolor()
|
|
&& VAR_SIGNATURE_FORE_COLOR
|
|
&& VAR_SIGNATURE_BACK_COLOR){
|
|
! filters[filtcnt].filter = gf_line_test;
|
|
filters[filtcnt++].data = gf_line_test_opt(color_signature,
|
|
&is_in_sig);
|
|
}
|
|
--- 176,182 ----
|
|
&& pico_usingcolor()
|
|
&& VAR_SIGNATURE_FORE_COLOR
|
|
&& VAR_SIGNATURE_BACK_COLOR){
|
|
! filters[filtcnt].filter = gf_quote_test;
|
|
filters[filtcnt++].data = gf_line_test_opt(color_signature,
|
|
&is_in_sig);
|
|
}
|
|
***************
|
|
*** 194,202 ****
|
|
&& pico_usingcolor()
|
|
&& VAR_QUOTE1_FORE_COLOR
|
|
&& VAR_QUOTE1_BACK_COLOR){
|
|
! filters[filtcnt].filter = gf_line_test;
|
|
! filters[filtcnt++].data = gf_line_test_opt(color_a_quote,
|
|
! &is_flowed_msg);
|
|
}
|
|
}
|
|
else if(!strucmp(att->body->subtype, "richtext")){
|
|
--- 194,202 ----
|
|
&& pico_usingcolor()
|
|
&& VAR_QUOTE1_FORE_COLOR
|
|
&& VAR_QUOTE1_BACK_COLOR){
|
|
! add_me = 0;
|
|
! filters[filtcnt].filter = gf_quote_test;
|
|
! filters[filtcnt++].data = gf_line_test_opt(color_a_quote, &is_flowed_msg);
|
|
}
|
|
}
|
|
else if(!strucmp(att->body->subtype, "richtext")){
|
|
***************
|
|
*** 277,282 ****
|
|
--- 277,287 ----
|
|
}
|
|
}
|
|
|
|
+ if (add_me){
|
|
+ filters[filtcnt].filter = gf_quote_test;
|
|
+ filters[filtcnt++].data = gf_line_test_opt(select_quote, &doraw);
|
|
+ }
|
|
+
|
|
/*
|
|
* If the message is not flowed, we do the quote suppression before
|
|
* the wrapping, because the wrapping does not preserve the quote
|
|
***************
|
|
*** 301,307 ****
|
|
dq.handlesp = handlesp;
|
|
dq.do_color = (!(flags & FM_NOCOLOR) && pico_usingcolor());
|
|
|
|
! filters[filtcnt].filter = gf_line_test;
|
|
filters[filtcnt++].data = gf_line_test_opt(delete_quotes, &dq);
|
|
}
|
|
if(ps_global->VAR_QUOTE_REPLACE_STRING
|
|
--- 306,312 ----
|
|
dq.handlesp = handlesp;
|
|
dq.do_color = (!(flags & FM_NOCOLOR) && pico_usingcolor());
|
|
|
|
! filters[filtcnt].filter = gf_quote_test;
|
|
filters[filtcnt++].data = gf_line_test_opt(delete_quotes, &dq);
|
|
}
|
|
if(ps_global->VAR_QUOTE_REPLACE_STRING
|
|
***************
|
|
*** 360,366 ****
|
|
dq.handlesp = handlesp;
|
|
dq.do_color = (!(flags & FM_NOCOLOR) && pico_usingcolor());
|
|
|
|
! filters[filtcnt].filter = gf_line_test;
|
|
filters[filtcnt++].data = gf_line_test_opt(delete_quotes, &dq);
|
|
}
|
|
|
|
--- 365,371 ----
|
|
dq.handlesp = handlesp;
|
|
dq.do_color = (!(flags & FM_NOCOLOR) && pico_usingcolor());
|
|
|
|
! filters[filtcnt].filter = gf_quote_test;
|
|
filters[filtcnt++].data = gf_line_test_opt(delete_quotes, &dq);
|
|
}
|
|
|
|
***************
|
|
*** 565,571 ****
|
|
{
|
|
DELQ_S *dq;
|
|
char *lp;
|
|
! int i, lines, not_a_quote = 0;
|
|
size_t len = 0;
|
|
|
|
dq = (DELQ_S *) local;
|
|
--- 570,576 ----
|
|
{
|
|
DELQ_S *dq;
|
|
char *lp;
|
|
! int i, lines, not_a_quote = 0, code;
|
|
size_t len = 0;
|
|
|
|
dq = (DELQ_S *) local;
|
|
***************
|
|
*** 585,590 ****
|
|
--- 590,597 ----
|
|
for(i = dq->indent_length; i > 0 && !not_a_quote && *lp; i--)
|
|
if(*lp++ != SPACE)
|
|
not_a_quote++;
|
|
+ while(isspace((unsigned char) *lp))
|
|
+ lp++;
|
|
|
|
/* skip over leading tags */
|
|
while(!not_a_quote
|
|
***************
|
|
*** 624,636 ****
|
|
}
|
|
}
|
|
|
|
! /* skip over whitespace */
|
|
! if(!dq->is_flowed)
|
|
! while(isspace((unsigned char) *lp))
|
|
! lp++;
|
|
!
|
|
! /* check first character to see if it is a quote */
|
|
! if(!not_a_quote && *lp != '>')
|
|
not_a_quote++;
|
|
|
|
if(not_a_quote){
|
|
--- 631,642 ----
|
|
}
|
|
}
|
|
|
|
! len = lp - line;
|
|
! if(strlen(tmp_20k_buf) > len)
|
|
! strcpy(tmp_20k_buf, tmp_20k_buf+len);
|
|
! code = (dq->is_flowed ? IS_FLOWED : NO_FLOWED) | DELETEQUO;
|
|
! select_quote(linenum, lp, ins, &code);
|
|
! if (!not_a_quote && !tmp_20k_buf[0])
|
|
not_a_quote++;
|
|
|
|
if(not_a_quote){
|