[svn] r6434 - in trunk/rpms: alpine collectd perl-Algorithm-Cluster perl-Algorithm-MedianSelect-XS perl-Alien-wxWidgets testdisk

packagers at lists.rpmforge.net packagers at lists.rpmforge.net
Thu Jul 31 02:54:18 CEST 2008


Author: dag
Date: 2008-07-31 01:54:17 +0100 (Thu, 31 Jul 2008)
New Revision: 6434

Added:
   trunk/rpms/alpine/alpine-1.10-fillpara.patch
   trunk/rpms/alpine/alpine-1.10-maildir.patch
   trunk/rpms/alpine/alpine-1.10-rules.patch
   trunk/rpms/alpine/alpine-1.10-select-bold-x.patch
Modified:
   trunk/rpms/alpine/alpine.spec
   trunk/rpms/collectd/collectd.spec
   trunk/rpms/perl-Algorithm-Cluster/perl-Algorithm-Cluster.spec
   trunk/rpms/perl-Algorithm-MedianSelect-XS/perl-Algorithm-MedianSelect-XS.spec
   trunk/rpms/perl-Alien-wxWidgets/perl-Alien-wxWidgets.spec
   trunk/rpms/testdisk/testdisk.spec
Log:
Updates

Added: trunk/rpms/alpine/alpine-1.10-fillpara.patch
===================================================================
--- trunk/rpms/alpine/alpine-1.10-fillpara.patch	                        (rev 0)
+++ trunk/rpms/alpine/alpine-1.10-fillpara.patch	2008-07-31 00:54:17 UTC (rev 6434)
@@ -0,0 +1,3930 @@
+diff -rc alpine-1.10/alpine/mailview.c alpine-1.10.fillpara/alpine/mailview.c
+*** alpine-1.10/alpine/mailview.c	2008-03-03 13:37:30.000000000 -0800
+--- alpine-1.10.fillpara/alpine/mailview.c	2008-05-19 16:31:06.000000000 -0700
+***************
+*** 205,211 ****
+--- 205,219 ----
+  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
+***************
+*** 296,301 ****
+--- 304,320 ----
+  	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);
+***************
+*** 459,464 ****
+--- 478,485 ----
+      }
+      while(ps->next_screen == SCREEN_FUN_NULL);
+  
++     if (prefix && *prefix)
++        fs_give((void **)&prefix);
+      if(we_cancel)
+        cancel_busy_cue(-1);
+  
+diff -rc alpine-1.10/pico/basic.c alpine-1.10.fillpara/pico/basic.c
+*** alpine-1.10/pico/basic.c	2007-11-26 15:45:22.000000000 -0800
+--- alpine-1.10.fillpara/pico/basic.c	2008-05-19 16:31:06.000000000 -0700
+***************
+*** 25,33 ****
+   * framing, are hard.
+   */
+  #include        "headers.h"
+! 
+  #include "osdep/terminal.h"
+  
+  
+  /*
+   * Move the cursor to the
+--- 25,34 ----
+   * 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
+***************
+*** 284,290 ****
+  gotobop(int f, int n)
+  {
+      int quoted, qlen;
+!     UCS qstr[NLINE], qstr2[NLINE];
+  
+      if (n < 0)	/* the other way...*/
+        return(gotoeop(f, -n));
+--- 285,291 ----
+  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));
+***************
+*** 296,301 ****
+--- 297,310 ----
+  	    curwp->w_dotp = lback(curwp->w_dotp);
+  	    curwp->w_doto = 0;
+  	}
++ 
++ 	if (indent_match(default_qstr(), 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>
+***************
+*** 303,322 ****
+  	 * PLUS: if there's a quote string, a quoted-to-non-quoted
+  	 *	 line transition.
+  	 */
+! 	quoted = glo_quote_str ? quote_match(glo_quote_str, curwp->w_dotp, qstr, NLINE) : 0;
+! 	qlen   = quoted ? ucs4_strlen(qstr) : 0;
+  	while(lback(curwp->w_dotp) != curbp->b_linep
+  	      && llength(lback(curwp->w_dotp)) > qlen
+! 	      && (glo_quote_str
+! 		  ? (quoted == quote_match(glo_quote_str,
+! 					   lback(curwp->w_dotp),
+! 					   qstr2, NLINE)
+! 		     && !ucs4_strcmp(qstr, qstr2))
+! 		  : 1)
+  	      && 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)
+--- 312,371 ----
+  	 * PLUS: if there's a quote string, a quoted-to-non-quoted
+  	 *	 line transition.
+  	 */
+! 	quoted = quote_match(default_qstr(), 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(),
+! 			lback(curwp->w_dotp), qstr2, NLINE, 0))
+! 	      && !strcmp(qstr, qstr2)   /* processed string */
+! 	      && (quoted == quote_match(default_qstr(),
+! 			lback(curwp->w_dotp), qstr2, NLINE, 1))
+! 	      && !strcmp(qstr, qstr2)   /* raw string */
+! 	      && !indent_match(default_qstr(),
+! 			lback(curwp->w_dotp),ind_str, NLINE, 0)
+  	      && lgetc(curwp->w_dotp, qlen).c != TAB
+  	      && 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 shell 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(), curwp->w_dotp, qstr, NLINE, 1);
++ 	   quote_match(default_qstr(), 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(), 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(),
++ 				lback(curwp->w_dotp), pqstr, NLINE, 0))
++ 		 && !strcmp(qstr, pqstr)
++ 		 && lgetc(curwp->w_dotp, qlen).c != TAB
++ 		 && 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)
+***************
+*** 329,335 ****
+  	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);
+--- 378,384 ----
+  	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);
+***************
+*** 352,359 ****
+  int
+  gotoeop(int f, int n)
+  {
+!     int quoted, qlen;
+!     UCS qstr[NLINE], qstr2[NLINE];
+  
+      if (n < 0)	/* the other way...*/
+        return(gotobop(f, -n));
+--- 401,409 ----
+  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));
+***************
+*** 366,390 ****
+  	      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 = glo_quote_str
+! 	  ? quote_match(glo_quote_str,
+! 			curwp->w_dotp, qstr, NLINE) : 0;
+! 	qlen   = quoted ? ucs4_strlen(qstr) : 0;
+  	
+  	while(curwp->w_dotp != curbp->b_linep
+  	      && llength(lforw(curwp->w_dotp)) > qlen
+! 	      && (glo_quote_str
+! 		  ? (quoted == quote_match(glo_quote_str,
+! 					   lforw(curwp->w_dotp),
+! 					   qstr2, NLINE)
+! 		     && !ucs4_strcmp(qstr, qstr2))
+! 		  : 1)
+  	      && lgetc(lforw(curwp->w_dotp), qlen).c != TAB
+  	      && lgetc(lforw(curwp->w_dotp), qlen).c != ' ')
+  	  curwp->w_dotp = lforw(curwp->w_dotp);
+--- 416,484 ----
+  	      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(), curwp->w_dotp, qstr, NLINE, 1);
++ 	   quote_match(default_qstr(), lforw(curwp->w_dotp), qstr2, NLINE, 1);
++ 	   indented = indent_match(default_qstr(), 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(), 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(), 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(),
+! 				lforw(curwp->w_dotp), qstr2, NLINE, fli))
+! 	      && !strcmp(qstr, qstr2)
+! 	      && (quoted == quote_match(default_qstr(),
+! 				lforw(curwp->w_dotp), qstr2, NLINE, 1))
+! 	      && !strcmp(qstr, qstr2)
+! 	      && !indent_match(default_qstr(),
+! 				lforw(curwp->w_dotp), ind_str, NLINE, 0)
+  	      && lgetc(lforw(curwp->w_dotp), qlen).c != TAB
+  	      && lgetc(lforw(curwp->w_dotp), qlen).c != ' ')
+  	  curwp->w_dotp = lforw(curwp->w_dotp);
+diff -rc alpine-1.10/pico/efunc.h alpine-1.10.fillpara/pico/efunc.h
+*** alpine-1.10/pico/efunc.h	2007-11-06 15:51:13.000000000 -0800
+--- alpine-1.10.fillpara/pico/efunc.h	2008-05-19 16:31:06.000000000 -0700
+***************
+*** 248,257 ****
+  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 */
+--- 248,264 ----
+  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	char *default_qstr(void);
+! 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-1.10/pico/line.c alpine-1.10.fillpara/pico/line.c
+*** alpine-1.10/pico/line.c	2007-08-15 16:07:18.000000000 -0700
+--- alpine-1.10.fillpara/pico/line.c	2008-05-19 16:31:06.000000000 -0700
+***************
+*** 607,620 ****
+  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))
+  	return(FALSE);
+  
+      return(TRUE);
+--- 607,618 ----
+  lisblank(LINE *line)
+  {
+      int n = 0;
+!     char qstr[NLINE];
+  
+!     n = quote_match(default_qstr(), line, qstr, NLINE, 1);
+  
+      for(; n < llength(line); n++)
+!       if(!ISspace(lgetc(line, n).c))
+  	return(FALSE);
+  
+      return(TRUE);
+diff -rc alpine-1.10/pico/search.c alpine-1.10.fillpara/pico/search.c
+*** alpine-1.10/pico/search.c	2008-01-04 14:49:15.000000000 -0800
+--- alpine-1.10.fillpara/pico/search.c	2008-05-19 16:31:06.000000000 -0700
+***************
+*** 35,41 ****
+  int     readpattern(char *, int);
+  int     replace_pat(UCS *, int *);
+  int     replace_all(UCS *, UCS *);
+! 
+  
+  #define	FWS_RETURN(RV)	{				\
+  			    thisflag |= CFSRCH;		\
+--- 35,41 ----
+  int     readpattern(char *, int);
+  int     replace_pat(UCS *, int *);
+  int     replace_all(UCS *, UCS *);
+! int	deletepara(int, int);
+  
+  #define	FWS_RETURN(RV)	{				\
+  			    thisflag |= CFSRCH;		\
+***************
+*** 231,236 ****
+--- 231,241 ----
+  	    mlerase();
+  	    FWS_RETURN(TRUE);
+  
++ 	  case (CTRL|'P'):
++ 	    deletepara(0, 1);
++ 	    mlerase();
++ 	    FWS_RETURN(TRUE);
++ 
+  	  case  (CTRL|'R'):        /* toggle replacement option */
+  	    repl_mode = !repl_mode;
+  	    break;
+***************
+*** 597,603 ****
+  	UCS         *b;
+  	UCS	     prompt[NPMT];
+  	UCS         *promptp;
+! 	EXTRAKEYS    menu_pat[8];
+  
+  	menu_pat[i = 0].name = "^Y";
+  	menu_pat[i].label    = N_("FirstLine");
+--- 602,608 ----
+  	UCS         *b;
+  	UCS	     prompt[NPMT];
+  	UCS         *promptp;
+! 	EXTRAKEYS    menu_pat[9];
+  
+  	menu_pat[i = 0].name = "^Y";
+  	menu_pat[i].label    = N_("FirstLine");
+***************
+*** 631,636 ****
+--- 636,646 ----
+  	    menu_pat[i].key    = (CTRL|'O');
+  	    KS_OSDATASET(&menu_pat[i], KS_NONE);
+  
++ 	    menu_pat[++i].name = "^P";
++ 	    menu_pat[i].label  = N_("Delete Para");
++ 	    menu_pat[i].key    = (CTRL|'P');
++ 	    KS_OSDATASET(&menu_pat[i], KS_NONE);
++ 
+  	    menu_pat[++i].name = "^U";
+  	    /* TRANSLATORS: Instead of justifying (formatting) just a
+  	       single paragraph, Full Justify justifies the entire
+***************
+*** 766,772 ****
+  	UCS         *b;
+  	UCS	     tpat[NPAT+20];
+  	UCS         *tpatp;
+! 	EXTRAKEYS    menu_pat[7];
+  
+  	menu_pat[i = 0].name = "^Y";
+  	menu_pat[i].label    = N_("FirstLine");
+--- 776,782 ----
+  	UCS         *b;
+  	UCS	     tpat[NPAT+20];
+  	UCS         *tpatp;
+! 	EXTRAKEYS    menu_pat[8];
+  
+  	menu_pat[i = 0].name = "^Y";
+  	menu_pat[i].label    = N_("FirstLine");
+***************
+*** 794,799 ****
+--- 804,814 ----
+  	    menu_pat[i].key    = (CTRL|'O');
+  	    KS_OSDATASET(&menu_pat[i], KS_NONE);
+  
++ 	    menu_pat[++i].name = "^P";
++ 	    menu_pat[i].label  = N_("Delete Para");
++ 	    menu_pat[i].key    = (CTRL|'P');
++ 	    KS_OSDATASET(&menu_pat[i], KS_NONE);
++ 
+  	    menu_pat[++i].name = "^U";
+  	    menu_pat[i].label  = N_("FullJustify");
+  	    menu_pat[i].key    = (CTRL|'U');
+***************
+*** 1032,1034 ****
+--- 1047,1071 ----
+  
+      curwp->w_flag |= WFEDIT;
+  }
++ 
++ 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-1.10/pico/word.c alpine-1.10.fillpara/pico/word.c
+*** alpine-1.10/pico/word.c	2007-08-20 12:46:37.000000000 -0700
+--- alpine-1.10.fillpara/pico/word.c	2008-05-19 16:33:00.000000000 -0700
+***************
+*** 24,33 ****
+   */
+  
+  #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);
+  
+--- 24,33 ----
+   */
+  
+  #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);
+  
+***************
+*** 430,471 ****
+      return 0;
+  }
+  
+  
+  /*
+   * Return number of quotes if whatever starts the line matches the quote string
+   */
+  int
+! quote_match(UCS *q, LINE *l, UCS *buf, size_t buflen)
+  {
+!     register int i, n, j, qb;
+  
+!     *buf = '\0';
+!     if(*q == '\0')
+!       return(1);
+! 
+!     qb = (ucs4_strlen(q) > 1 && q[ucs4_strlen(q)-1] == ' ') ? 1 : 0;
+!     for(n = 0, j = 0; ;){
+! 	for(i = 0; j <= llength(l) && qb ? q[i+1] : q[i]; i++, j++)
+! 	  if(q[i] != lgetc(l, j).c)
+! 	    return(n);
+! 
+! 	n++;
+! 	if((!qb && q[i] == '\0') || (qb && q[i+1] == '\0')){
+! 	    if(ucs4_strlen(buf) + ucs4_strlen(q) + 1 < buflen){
+! 		ucs4_strncat(buf, q, buflen-ucs4_strlen(q)-1);
+! 		buf[buflen-1] = '\0';
+! 		if(qb && (j > llength(l) || lgetc(l, j).c != ' '))
+! 		  buf[ucs4_strlen(buf)-1] = '\0';
+! 	    }
+! 	}
+! 	if(j > llength(l))
+! 	  return(n);
+! 	else if(qb && lgetc(l, j).c == ' ')
+! 	  j++;
+      }
+!     return(n);  /* never reached */
+  }
+  
+  
+  /* Justify the entire buffer instead of just a paragraph */
+  int
+--- 430,600 ----
+      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))
++ #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_strlenis(UCS *);
++ void     linencpy(char *, LINE *, int);
++ 
++ 
++ char *
++ default_qstr(void)
++ {
++   char *default_qs;
++   static char ucs_def[NSTRING] = {'\0'};
++ 
++   if(ucs_def[0] == '\0'){
++      default_qs = ucs4_to_utf8_cpystr(glo_quote_str);
++      strncpy(ucs_def, (default_qs ? default_qs : ""), NSTRING);
++      fs_give((void **)&default_qs);
++   }
++ 
++   return glo_quote_str ? ucs_def : "";
++ }
++ 
++ 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
++  * rqstring is  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);
+!     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_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
+***************
+*** 720,725 ****
+--- 849,855 ----
+      }
+  
+      if(action == 'R' && curwp->w_markp){
++ 	char qstrfl[NSTRING];
+  	/* let yank() know that it may be restoring a paragraph */
+  	thisflag |= CFFILL;
+  
+***************
+*** 732,752 ****
+  
+  	/* determine if we're justifying quoted text or not */
+  	qstr = (glo_quote_str
+! 		&& 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.
+--- 862,886 ----
+  
+  	/* determine if we're justifying quoted text or not */
+  	qstr = (glo_quote_str
+! 		&& quote_match(default_qstr(), 
+! 			       (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.
+***************
+*** 758,774 ****
+  	if(gotoeop(FALSE, 1) == FALSE)
+  	  return(FALSE);
+  
+- 	/* determine if we're justifying quoted text or not */
+- 	qstr = (glo_quote_str
+- 		&& 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);
+  
+--- 892,907 ----
+  	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(), curwp->w_dotp, ind_str, NSTRING, 0)
++ 	   && *ind_str  ? utf8_to_ucs4_cpystr(ind_str) : NULL;
++ 	qstr = (quote_match(default_qstr(), 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);
+  
+***************
+*** 782,790 ****
+  	/*
+  	 * 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 */
+--- 915,929 ----
+  	/*
+  	 * 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 */
+***************
+*** 826,841 ****
+   * 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 */
+--- 965,980 ----
+   * 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 */
+***************
+*** 846,851 ****
+--- 985,1020 ----
+      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_strlenis(quoid) - ucs4_strlenis(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';
++ /*	if (!qstr)*/
++ 	   qstr = qstr2;
++     }
++ 
+      /* cut the paragraph into our fill buffer */
+      fdelete();
+      if(!getregion(&region, curwp->w_markp, curwp->w_marko))
+***************
+*** 862,886 ****
+  
+      /* 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);
+        }
+--- 1031,1055 ----
+  
+      /* Now insert it back wrapped */
+      spaces = word_len = word_ind = line_len = same_word = 0;
+  
+      /* Beginning with leading quoting... */
+!     if(qstr || istr){
+  	i = 0;
+! 	while(quoid[i]){
+! 	  ww = wcellwidth(quoid[i]);
+  	  line_len += (ww >= 0 ? ww : 1);
+! 	  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
+!       for(i = ucs4_strlen(quoid); (c = fremove(i)) == ' ' || c == TAB; i++){
+  	  linsert(1, line_last = (UCS) c);
+  	  line_len += ((c == TAB) ? (~line_len & 0x07) + 1 : 1);
+        }
+***************
+*** 911,925 ****
+  
+  	  default :
+  	    if(spaces){				/* flush word? */
+! 		if((line_len - qlen > 0)
+  		   && line_len + word_len + 1 > fillcol
+! 		   && ((ucs4_isspace(line_last))
+  		       || (linsert(1, ' ')))
+  		   && (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++;
+  		    }
+--- 1080,1094 ----
+  
+  	  default :
+  	    if(spaces){				/* flush word? */
+! 		if((line_len - qlenis > 0)
+  		   && line_len + word_len + 1 > fillcol
+! 		   && ((ISspace(line_last))
+  		       || (linsert(1, ' ')))
+  		   && (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++;
+  		    }
+***************
+*** 941,948 ****
+  
+  	    if(word_ind + 1 >= NSTRING){
+  		/* Magic!  Fake that we output a wrapped word */
+! 		if((line_len - qlen > 0) && !same_word++){
+! 		    if(!ucs4_isspace(line_last))
+  		      linsert(1, ' ');
+  		    line_len = fpnewline(qstr);
+  		}
+--- 1110,1117 ----
+  
+  	    if(word_ind + 1 >= NSTRING){
+  		/* Magic!  Fake that we output a wrapped word */
+! 		if((line_len - qlenis > 0) && !same_word++){
+! 		    if(!ISspace(line_last))
+  		      linsert(1, ' ');
+  		    line_len = fpnewline(qstr);
+  		}
+***************
+*** 964,975 ****
+      }
+  
+      if(word_len){
+! 	if((line_len - qlen > 0) && (line_len + word_len + 1 > fillcol)){
+! 	    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++)
+--- 1133,1144 ----
+      }
+  
+      if(word_len){
+! 	if((line_len - qlenis > 0) && (line_len + word_len + 1 > fillcol)){
+! 	    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++)
+***************
+*** 1027,1037 ****
+      int len;
+  
+      lnewline();
+!     for(len = 0; quote && *quote; quote++){
+  	int ww;
+  
+! 	ww = wcellwidth(*quote);
+! 	len += (ww >= 0 ? ww : 1);
+  	linsert(1, *quote);
+      }
+  
+--- 1196,1206 ----
+      int len;
+  
+      lnewline();
+!     for(len = ucs4_strlenis(quote); quote && *quote; quote++){
+  	int ww;
+  
+! /*	ww = wcellwidth(*quote);
+! 	len += (ww >= 0 ? ww : 1);*/
+  	linsert(1, *quote);
+      }
+  
+***************
+*** 1175,1179 ****
+--- 1344,1388 ----
+  	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-1.10/pith/charconv/utf8.c alpine-1.10.fillpara/pith/charconv/utf8.c
+*** alpine-1.10/pith/charconv/utf8.c	2008-01-08 09:04:58.000000000 -0800
+--- alpine-1.10.fillpara/pith/charconv/utf8.c	2008-05-19 16:31:06.000000000 -0700
+***************
+*** 1048,1053 ****
+--- 1048,1103 ----
+  
+  
+  /*
++  * 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-1.10/pith/charconv/utf8.h alpine-1.10.fillpara/pith/charconv/utf8.h
+*** alpine-1.10/pith/charconv/utf8.h	2008-01-08 09:04:58.000000000 -0800
+--- alpine-1.10.fillpara/pith/charconv/utf8.h	2008-05-19 16:31:06.000000000 -0700
+***************
+*** 80,85 ****
+--- 80,86 ----
+  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-1.10/pith/color.c alpine-1.10.fillpara/pith/color.c
+*** alpine-1.10/pith/color.c	2007-08-15 13:28:09.000000000 -0700
+--- alpine-1.10.fillpara/pith/color.c	2008-05-19 16:31:06.000000000 -0700
+***************
+*** 20,26 ****
+  #include "../pith/state.h"
+  #include "../pith/conf.h"
+  #include "../pith/filter.h"
+! 
+  
+  char *
+  color_embed(char *fg, char *bg)
+--- 20,27 ----
+  #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)
+***************
+*** 69,91 ****
+      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;
+  
+  	/*
+--- 70,179 ----
+      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;
+  
+  	/*
+***************
+*** 134,140 ****
+        free_color_pair(&col);
+  
+      cp = NULL;
+!     while(*p == '>'){
+  	cp = (cp && cp->next) ? cp->next : colors;
+  
+  	if(countem > 0)
+--- 222,228 ----
+        free_color_pair(&col);
+  
+      cp = NULL;
+!     while(buf[i]){
+  	cp = (cp && cp->next) ? cp->next : colors;
+  
+  	if(countem > 0)
+***************
+*** 144,153 ****
+  
+  	countem = (countem == 1) ? 0 : countem;
+  
+! 	p++;
+! 	if(!is_flowed)
+! 	  for(; isspace((unsigned char)*p); p++)
+! 	    ;
+      }
+  
+      if(colors){
+--- 232,240 ----
+  
+  	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){
+***************
+*** 210,216 ****
+  	}
+      }
+  
+!     return(0);
+  }
+  
+  
+--- 297,303 ----
+  	}
+      }
+  
+!     return(1);
+  }
+  
+  
+diff -rc alpine-1.10/pith/color.h alpine-1.10.fillpara/pith/color.h
+*** alpine-1.10/pith/color.h	2007-05-08 16:38:08.000000000 -0700
+--- alpine-1.10.fillpara/pith/color.h	2008-05-19 16:31:06.000000000 -0700
+***************
+*** 21,26 ****
+--- 21,44 ----
+  #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 */
+***************
+*** 80,85 ****
+--- 98,104 ----
+  /* exported protoypes */
+  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-1.10/pith/filter.c alpine-1.10.fillpara/pith/filter.c
+*** alpine-1.10/pith/filter.c	2008-03-07 11:30:14.000000000 -0800
+--- alpine-1.10.fillpara/pith/filter.c	2008-05-19 16:31:06.000000000 -0700
+***************
+*** 45,50 ****
+--- 45,51 ----
+  #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"
+***************
+*** 8705,8710 ****
+--- 8706,8716 ----
+  		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)
+***************
+*** 8746,8751 ****
+--- 8752,8763 ----
+  #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;	\
+***************
+*** 8823,8828 ****
+--- 8835,8842 ----
+  	      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)){
+***************
+*** 8916,8922 ****
+  
+  	      case BOL :
+  		if(WRAP_FLOW(f)){
+! 		    if(c == '>'){
+  			WRAP_FL_QC(f) = 1;		/* init it */
+  			state = FL_QLEV;		/* go collect it */
+  		    }
+--- 8930,8940 ----
+  
+  	      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 */
+  		    }
+***************
+*** 8930,8936 ****
+  			}
+  
+  			/* 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;
+--- 8948,8963 ----
+  			}
+  
+  			/* 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;
+***************
+*** 8982,8989 ****
+  		break;
+  
+  	      case  FL_QLEV :
+! 		if(c == '>'){				/* another level */
+! 		    WRAP_FL_QC(f)++;
+  		}
+  		else {
+  		    /* if EMBEDed, process it and return here */
+--- 9009,9020 ----
+  		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 */
+***************
+*** 8995,9001 ****
+  		    }
+  
+  		    /* 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 */
+--- 9026,9041 ----
+  		    }
+  
+  		    /* 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 */
+***************
+*** 9052,9057 ****
+--- 9092,9104 ----
+  		    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 */
+***************
+*** 9068,9074 ****
+  					     &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 */
+  			}
+  
+--- 9115,9121 ----
+  					     &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 */
+  			}
+  
+***************
+*** 9565,9571 ****
+  		    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 */
+  		}
+  
+--- 9612,9618 ----
+  		    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 */
+  		}
+  
+***************
+*** 9638,9643 ****
+--- 9685,9697 ----
+  	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 */
+***************
+*** 9988,9994 ****
+  {
+      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);
+--- 10042,10049 ----
+  {
+      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);
+***************
+*** 9997,10006 ****
+  	    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,
+--- 10052,10073 ----
+  	    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,
+***************
+*** 10008,10014 ****
+  	       && 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,
+--- 10075,10081 ----
+  	       && 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,
+***************
+*** 10016,10022 ****
+  		    && 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,
+--- 10083,10089 ----
+  		    && 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,
+***************
+*** 10030,10072 ****
+  	    }
+  	}
+  
+  	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;
+  }
+--- 10097,10156 ----
+  	    }
+  	}
+  
++ 	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++);
+! 	if(!wrap_qstr[i]){
+! 	  f->n += i - j;
+! 	  for (; j < i; j++)
+! 		GF_PUTC_GLO(f->next, ' '); 
+! 	}
+!         else{
+! 	   if((WRAP_LV_FLD(f)
+! 		|| !ps_global->VAR_QUOTE_REPLACE_STRING || !prefix)
+! 		|| !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;
+! 	   }
+  	}
++ 	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;
+  }
+***************
+*** 10098,10103 ****
+--- 10182,10193 ----
+      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);
+  }
+***************
+*** 10541,10547 ****
+--- 10631,10839 ----
+  			    } \
+  			}
+  
++ #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)++;					\
++ 	}								\
++ }
++ 
++ /* 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'))\
++ 	  *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';\
++ 	for (i = 0; ((F)->oldline)[i] && ((F)->oldline)[i] != '\015'; i++);	\
++ 	if (((F)->oldline)[i]){\
++ 	   i += (((F)->oldline)[i+1] == '\012') ? 2 : 1;\
++ 	   line = (F)->oldline + i;\
++ 	}\
++ 	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);\
++ 	for (i = 0; line[i] && line[i] != '\015' && line[i] != '\012'; i++); \
++ 	if ((line[i] == '\012') && ((i == 0) || ((i > 0) && line[i-1] != '\015'))){\
++ 	   i++;\
++ 	  for (; line[i] && line[i] != '\015' && line[i] != '\012'; i++); \
++ 	}\
++ 	if (line[i]){\
++ 	   (line[i]) = '\0';\
++ 	   i+= (line[i+1] == '\012') ? 2 : 1;\
++ 	}\
++ 	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)){
++ 
++ 	    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;
++ 		continue;
++ 	    }
++ 	    if(c == '\015'){
++ 	      state++;
++ 	      if (state == 1)
++ 		 GF_LINE_TEST_ADD(f, c);
++ 	    }
++ 	    else
++ 	      GF_LINE_TEST_ADD(f, c);
++ 	}
++ 
++ 	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-1.10/pith/filter.h alpine-1.10.fillpara/pith/filter.h
+*** alpine-1.10/pith/filter.h	2008-03-05 10:56:28.000000000 -0800
+--- alpine-1.10.fillpara/pith/filter.h	2008-05-19 16:31:06.000000000 -0700
+***************
+*** 194,199 ****
+--- 194,200 ----
+  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);
+  
+  
+diff -rc alpine-1.10/pith/filttype.h alpine-1.10.fillpara/pith/filttype.h
+*** alpine-1.10/pith/filttype.h	2007-04-25 21:06:02.000000000 -0700
+--- alpine-1.10.fillpara/pith/filttype.h	2008-05-19 16:31:06.000000000 -0700
+***************
+*** 35,40 ****
+--- 35,42 ----
+      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-1.10/pith/mailview.c alpine-1.10.fillpara/pith/mailview.c
+*** alpine-1.10/pith/mailview.c	2008-03-05 10:56:28.000000000 -0800
+--- alpine-1.10.fillpara/pith/mailview.c	2008-05-19 16:31:06.000000000 -0700
+***************
+*** 50,56 ****
+  #include "../pith/ablookup.h"
+  #include "../pith/escapes.h"
+  #include "../pith/keyword.h"
+! 
+  
+  #define FBUF_LEN	(50)
+  
+--- 50,59 ----
+  #include "../pith/ablookup.h"
+  #include "../pith/escapes.h"
+  #include "../pith/keyword.h"
+! #include "../pith/osdep/color.h"
+! #include "../pico/estruct.h"
+! #include "../pico/pico.h"
+! #include "../pico/efunc.h"
+  
+  #define FBUF_LEN	(50)
+  
+***************
+*** 282,288 ****
+  	       && 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)
+--- 285,291 ----
+  	       && 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)
+***************
+*** 290,297 ****
+  	       && 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;
+--- 293,302 ----
+  	       && 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;
+***************
+*** 1071,1097 ****
+  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,
+--- 1076,1164 ----
+  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;
++     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')) *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';
++ 
++     plb = line_isblank((ps_global->prefix && *ps_global->prefix 
++ 			? ps_global->prefix : ">"), PLine, GLine, PPLine, NSTRING);
++     qs = do_quote_match((ps_global->prefix && *ps_global->prefix 
++ 			? ps_global->prefix : ">"),
++                        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,
+***************
+*** 1651,1656 ****
+--- 1718,1794 ----
+  }
+  
+  
++ /* 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';
++ 
++ 
++      plb = line_isblank((ps_global->prefix && *ps_global->prefix 
++ 		? ps_global->prefix : ">"), PLine, GLine, PPLine, NSTRING);
++ 
++      qs = do_quote_match((ps_global->prefix && *ps_global->prefix 
++ 		? ps_global->prefix : ">"), GLine, NLine, PLine, 
++ 							rqstr, NSTRING, plb);
++      if (raw)
++         strncpy(buf, rqstr, NSTRING);
++      else
++         flatten_qstring(qs, buf, NSTRING);
++      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-1.10/pith/mailview.h alpine-1.10.fillpara/pith/mailview.h
+*** alpine-1.10/pith/mailview.h	2008-03-05 10:56:28.000000000 -0800
+--- alpine-1.10.fillpara/pith/mailview.h	2008-05-19 16:31:06.000000000 -0700
+***************
+*** 141,146 ****
+--- 141,147 ----
+  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-1.10/pith/osdep/color.c alpine-1.10.fillpara/pith/osdep/color.c
+*** alpine-1.10/pith/osdep/color.c	2006-09-26 12:30:49.000000000 -0700
+--- alpine-1.10.fillpara/pith/osdep/color.c	2008-05-19 16:31:06.000000000 -0700
+***************
+*** 31,37 ****
+  
+  #include <system.h>
+  #include "./color.h"
+! 
+  
+  
+  /*
+--- 31,37 ----
+  
+  #include <system.h>
+  #include "./color.h"
+! #include "./collate.h"
+  
+  
+  /*
+***************
+*** 91,93 ****
+--- 91,1268 ----
+  {
+      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. This 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))
++ #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      advance_quote_string(char *, char *, int);
++ int	 isaword(char *,int ,int);
++ int	 isamailbox(char *,int ,int);
++ 
++ 
++ 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(qs, word, typeqs, beginw, endw, offset, neednext)
++    char *qs;
++    char word[NSTRING];
++    QStrType   typeqs;
++    int beginw, endw, offset, 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(cl)
++   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(cl)
++   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(cl)
++     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(cl)
++   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);
++ 
++    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 reaelly 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;
++    }
++    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;
++    }
++    if (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';
++ }
++ 
++ /*
++  * 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 || !word[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!.
++         */
++        i += advance_quote_string(qs, word, i);
++        if (!word[i]) /* went too far? */
++           return qs_add(qs, word, qsNormal, 0, i, 0, 0);
++ 
++       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(word,i,j)
++  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(word,i,j)
++ char word[NSTRING];
++ int i, 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(cl)
++   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 (cl)
++   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(q, GLine, NLine, PLine, rqstr, rqstrlen, plb)
++   char *q,  *GLine, *NLine, *PLine, *rqstr;
++   int   rqstrlen, 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(q, l, i)
++    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 (word, plb)
++  char word[NSTRING];
++   int  plb;
++ {
++   int i = 0, finished = 0, c, nxt, j, k, digit = 0, bdigits = -1, alpha = 0;
++ 
++    if (!word || !word[0])
++       return i;
++ 
++    for (i = 0, j = 0; ISspace(word[i]); i++, j++);
++    while ((i < NSTRING - 2) && !finished){
++       switch (c = 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 = 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;
++ 
++             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;
++ 
++      i = is_indent(GLine+k, plb);
++ 
++      for (j = 0; j < i && j < buflen && (buf[j] = GLine[j + k]); j++);
++      buf[j] = '\0';
++ 
++      return i;
++ }
++ 
+diff -rc alpine-1.10/pith/osdep/color.h alpine-1.10.fillpara/pith/osdep/color.h
+*** alpine-1.10/pith/osdep/color.h	2007-05-08 16:38:08.000000000 -0700
+--- alpine-1.10.fillpara/pith/osdep/color.h	2008-05-19 16:31:06.000000000 -0700
+***************
+*** 43,48 ****
+--- 43,69 ----
+  #define PSC_REV		0x2
+  #define PSC_RET		0x4	/* return an allocated copy of previous color */
+  
++ /*
++  * 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)
++ 
++ 
+  
+  /*
+   * MATCH_NORM_COLOR means that the color that is set to this value
+***************
+*** 95,100 ****
+--- 116,126 ----
+  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 *);
+  
+  
+  #endif /* PITH_OSDEP_COLOR_INCLUDED */
+diff -rc alpine-1.10/pith/pine.hlp alpine-1.10.fillpara/pith/pine.hlp
+*** alpine-1.10/pith/pine.hlp	2008-03-14 11:34:08.000000000 -0700
+--- alpine-1.10.fillpara/pith/pine.hlp	2008-05-19 16:31:06.000000000 -0700
+***************
+*** 6408,6413 ****
+--- 6408,6453 ----
+  &quot;type the character ^&quot;.
+  
+  <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 &quot;&gt;&quot;.
++ 
++ <P>
++ Some other constructions of quote strings are recognized only if they
++ appear enough in the text. For example &quot;Peter :&quot; 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 e