diff -C 2 -P ../owl-1.1.1/Makefile.in ./Makefile.in
*** ../owl-1.1.1/Makefile.in	Tue Jun 11 23:09:03 2002
--- ./Makefile.in	Sun Jun 16 21:18:54 2002
***************
*** 8,12 ****
       global.o text.o fmtext.o editwin.o util.o logging.o readconfig.o keys.o \
       functions.o zwrite.o viewwin.o help.o filter.o regex.o history.o view.o \
!      dict.o variable.o varstubs.o filterelement.o
  
  AUTOGEN=owl_prototypes.h varstubs.c
--- 8,12 ----
       global.o text.o fmtext.o editwin.o util.o logging.o readconfig.o keys.o \
       functions.o zwrite.o viewwin.o help.o filter.o regex.o history.o view.o \
!      dict.o variable.o varstubs.o filterelement.o color.o
  
  AUTOGEN=owl_prototypes.h varstubs.c
diff -C 2 -P ../owl-1.1.1/README-COLOR ./README-COLOR
*** ../owl-1.1.1/README-COLOR	Wed Dec 31 19:00:00 1969
--- ./README-COLOR	Mon Jun 17 20:01:32 2002
***************
*** 0 ****
--- 1,59 ----
+ I've mostly finished a color patch to owl.  The files are all in
+ /mit/jdaniel/project/owl/owl-1.1.1-color/ with README-COLOR containing
+ these comments.  I put most of the new code in color.c, but there are
+ also definitions in owl.h, an init function called from owl.c, and
+ substantial changes to fmtext.c.
+ 
+ It currently understands @color{NAME} where NAME must be one of black,
+ red, green, yellow, blue, magenta, cyan, white.  Since zwgc really
+ contains no idiom for setting backgrounds on a per character basis I
+ came up with @bgcolor(NAME), which accepts the same values.  Any color
+ it doesn't understand should be printed as before, and any
+ non-readable color such as an attempt to set foreground to green
+ within a green background region will also print literally.  These can
+ of course be used in a format section in .owlconf to color messages
+ according to the user's preferences.
+ 
+ The version I have built here is for sun, and I can't get it to do
+ anything interesting unless I run it with a TERM value that knows it
+ has colors.  The best one I've found for this is "dtterm" (thanks
+ mitchb), but this one only seems to do the basic fg on black colors (I
+ suspect it has a limit of 8 pairs).  Alternatively you can use
+ "sun-color" to see all of them, but that deals poorly with redraws,
+ and I wasn't sure how to change owl_function_full_redisplay() to fix
+ that.  If there are other terminal possibilities I should try please
+ recommend them.
+ 
+ The definitions added to owl.h were all of the form OWL_COLOR_*.  Also
+ of note is the addition of *color to struct owl_fmtext.  My first
+ version of the code changed *fmbuff to an unsigned short, but I
+ decided adding a new element to the struct was cleaner when I rewrote
+ the second time.  There are only 64 possible color pairs, so the color
+ attribute is only using 6 bits.  A single color (as returned by
+ owl_parse_color_name()) however needs 4 bits, one of which is to
+ distinguish black from an unparseable color.
+ 
+ I made substantial changes to owl_fmtext_curs_waddstr() which I think
+ make it much easier to follow what it's actually doing.  I also made a
+ few minor changes to the codepath in owl_fmtext_append_ztext().  Most
+ notably moving buff outside the loop to save code mallocing and
+ freeing it.  I replaced strcmp() with strcasecmp() since man zwgc
+ documents @ expressions to be case insensitive.  In addition to
+ @color() and @bgcolor() I also added matching of @beep() and @(empty
+ command).  Any command not matched now creates an environment whose
+ only difference is that it's bracket will be printed.  chrpstack[]
+ tracks this and colorstack[] was created to track colors.
+ 
+ Please send me any comments on this code, I'd be happy to make any
+ changes you feel necessary before accepting the patch.
+ 
+ Here's a sample color zephyr to see how it comes out:
+ @color(red)o@color(green)w@color(yellow)l@color(blue)-
+ @color(magenta)c@color(cyan)o@bgcolor(red)l@color(black)o@color(green)r
+ 
+ BUGS: (thanks to nim)
+ 
+ fixed @color(red) baz @bold(foo) bar
+ 
+ fixed @(@color(red) blah @(@color(blue) baz) bar)
+ 
diff -C 2 -P ../owl-1.1.1/color.c ./color.c
*** ../owl-1.1.1/color.c	Wed Dec 31 19:00:00 1969
--- ./color.c	Mon Jun 17 01:30:08 2002
***************
*** 0 ****
--- 1,117 ----
+ #include "owl.h"
+ 
+ char owl_make_color(char fg, char bg) {
+   /* a color is a char that looks like 00bbbfff (in base 2) where b
+      and f are foreground and background.  The color 0 represents no
+      color, or one that won't be visible (same fg and bg) */
+   if ((fg&OWL_COLOR_MASK) == (bg&OWL_COLOR_MASK)) {
+     return(0);
+   }
+   return(fg|(bg<<3));
+ }
+ 
+ char owl_get_fg_color(char color) {
+   return(color & OWL_COLOR_MASK);
+ }
+ 
+ char owl_get_bg_color(char color) {
+   return((color>>3) & OWL_COLOR_MASK);
+ }
+ 
+ char owl_set_fg_color(char color, char fg) {
+   char bg;
+ 
+   if (color) {
+     bg=owl_get_bg_color(color);
+   } else {
+     bg=OWL_COLOR_DEFAULT_BG;
+   }
+   return(owl_make_color(fg,bg));
+ }
+ 
+ char owl_set_bg_color(char color, char bg) {
+   char fg;
+ 
+   if (color) {
+     fg=owl_get_fg_color(color);
+   } else {
+     fg=OWL_COLOR_DEFAULT_FG;
+   }
+   return(owl_make_color(fg,bg));
+ }
+ 
+ int owl_get_color_pair(char color) {
+   /* I technically shouldn't be returning anything over COLOR_PAIRS
+      which is defined to be the maximum, but but it seems to do no
+      harm, and sometimes that value is wrong because the termcap is
+      poorly defined.  */
+ 
+   return(color&OWL_COLOR_PAIR);
+ }
+ 
+ void owl_wattron_color(WINDOW *w, char color) {
+   int pair;
+ 
+   pair = owl_get_color_pair(color);
+   if (pair) {
+     wattron(w, COLOR_PAIR(pair));
+   } 
+ }
+ 
+ void owl_init_colors() {
+   /* Create all the color pairs so they can be used later.
+      I technically should be checking has_colors() before doing any of
+      this, but it seems to do no harm, and sometimes that value is
+      wrong because the termcap is poorly defined */
+ 
+   /* use two arrays here so I don't depend on owl and curses using the
+      same values for each color */
+ 
+   unsigned short curses_color[8] = {COLOR_BLACK, COLOR_RED, 
+                                     COLOR_GREEN, COLOR_YELLOW, 
+                                     COLOR_BLUE, COLOR_MAGENTA, 
+                                     COLOR_CYAN, COLOR_WHITE};
+   unsigned short owl_color[8] = {OWL_COLOR_BLACK, OWL_COLOR_RED, 
+                                  OWL_COLOR_GREEN, OWL_COLOR_YELLOW, 
+                                  OWL_COLOR_BLUE, OWL_COLOR_MAGENTA, 
+                                  OWL_COLOR_CYAN, OWL_COLOR_WHITE};
+   int fg, bg, pair;
+   char color;
+ 
+   start_color();
+   for (bg=0; bg<=7; bg++) {
+     for (fg=0; fg<=7; fg++) {
+       color = owl_make_color(owl_color[fg], owl_color[bg]);
+       pair = owl_get_color_pair(color);
+       if (pair) {
+         init_pair(pair, curses_color[fg], curses_color[bg]);
+       }
+     }
+   }
+ }
+ 
+ char owl_parse_color_name (char *name) {
+   char color;
+ 
+   if (!strcmp(name,"black")) {
+     color=OWL_COLOR_BLACK;
+   } else if (!strcmp(name,"red")) {
+     color=OWL_COLOR_RED;
+   } else if (!strcmp(name,"green")) {
+     color=OWL_COLOR_GREEN;
+   } else if (!strcmp(name,"yellow")) {
+     color=OWL_COLOR_YELLOW;
+   } else if (!strcmp(name,"blue")) {
+     color=OWL_COLOR_BLUE;
+   } else if (!strcmp(name,"magenta")) {
+     color=OWL_COLOR_MAGENTA;
+   } else if (!strcmp(name,"cyan")) {
+     color=OWL_COLOR_CYAN;
+   } else if (!strcmp(name,"white")) {
+     color=OWL_COLOR_WHITE;
+   } else {
+     return 0;
+   }
+   return (color|OWL_COLOR_SET);
+ }
+     
Common subdirectories: ../owl-1.1.1/doc and ./doc
Common subdirectories: ../owl-1.1.1/examples and ./examples
diff -C 2 -P ../owl-1.1.1/fmtext.c ./fmtext.c
*** ../owl-1.1.1/fmtext.c	Tue Jun 11 23:09:03 2002
--- ./fmtext.c	Mon Jun 17 19:55:51 2002
***************
*** 8,23 ****
    f->fmbuff=owl_malloc(5);
    f->fmbuff[0]=OWL_FMTEXT_ATTR_NONE;
  }
  
  
! void _owl_fmtext_set_attr(owl_fmtext *f, int attr, int first, int last) {
    int i;
    for (i=first; i<=last; i++) {
      f->fmbuff[i]=(unsigned char) attr;
    }
  }
  
! 
! void owl_fmtext_append_attr(owl_fmtext *f, char *text, int attr) {
    int newlen;
  
--- 8,25 ----
    f->fmbuff=owl_malloc(5);
    f->fmbuff[0]=OWL_FMTEXT_ATTR_NONE;
+   f->color=owl_malloc(5);
+   f->color[0]=OWL_COLOR_NONE;
  }
  
  
! void _owl_fmtext_set_attr(owl_fmtext *f, int attr, int color, int first, int last) {
    int i;
    for (i=first; i<=last; i++) {
      f->fmbuff[i]=(unsigned char) attr;
+     f->color[i]=(unsigned char) color;
    }
  }
  
! void owl_fmtext_append_attr(owl_fmtext *f, char *text, int attr, int color) {
    int newlen;
  
***************
*** 25,31 ****
    f->textbuff=owl_realloc(f->textbuff, newlen+2);
    f->fmbuff=owl_realloc(f->fmbuff, newlen+2);
  
    strcat(f->textbuff, text);
!   _owl_fmtext_set_attr(f, attr, f->textlen, newlen);
    f->textlen=newlen;
  }
--- 27,34 ----
    f->textbuff=owl_realloc(f->textbuff, newlen+2);
    f->fmbuff=owl_realloc(f->fmbuff, newlen+2);
+   f->color=owl_realloc(f->color, newlen+2);
  
    strcat(f->textbuff, text);
!   _owl_fmtext_set_attr(f, attr, color, f->textlen, newlen);
    f->textlen=newlen;
  }
***************
*** 33,52 ****
  
  void owl_fmtext_append_normal(owl_fmtext *f, char *text) {
!   owl_fmtext_append_attr(f, text, OWL_FMTEXT_ATTR_NONE);
  }
  
  
  void owl_fmtext_append_bold(owl_fmtext *f, char *text) {
!   owl_fmtext_append_attr(f, text, OWL_FMTEXT_ATTR_BOLD);
  }
  
  
  void owl_fmtext_append_reverse(owl_fmtext *f, char *text) {
!   owl_fmtext_append_attr(f, text, OWL_FMTEXT_ATTR_REVERSE);
  }
  
  
  void owl_fmtext_append_reversebold(owl_fmtext *f, char *text) {
!   owl_fmtext_append_attr(f, text, OWL_FMTEXT_ATTR_REVERSE | OWL_FMTEXT_ATTR_BOLD);
  }
  
--- 36,55 ----
  
  void owl_fmtext_append_normal(owl_fmtext *f, char *text) {
!   owl_fmtext_append_attr(f, text, OWL_FMTEXT_ATTR_NONE, OWL_COLOR_NONE);
  }
  
  
  void owl_fmtext_append_bold(owl_fmtext *f, char *text) {
!   owl_fmtext_append_attr(f, text, OWL_FMTEXT_ATTR_BOLD, OWL_COLOR_NONE);
  }
  
  
  void owl_fmtext_append_reverse(owl_fmtext *f, char *text) {
!   owl_fmtext_append_attr(f, text, OWL_FMTEXT_ATTR_REVERSE, OWL_COLOR_NONE);
  }
  
  
  void owl_fmtext_append_reversebold(owl_fmtext *f, char *text) {
!   owl_fmtext_append_attr(f, text, OWL_FMTEXT_ATTR_REVERSE | OWL_FMTEXT_ATTR_BOLD, OWL_COLOR_NONE);
  }
  
***************
*** 65,87 ****
  void owl_fmtext_append_ztext(owl_fmtext *f, char *text) {
    int stacksize, curattrs;
!   char *ptr, *txtptr, *buff, *tmpptr;
!   int attrstack[32], chrstack[32];
  
    curattrs=OWL_FMTEXT_ATTR_NONE;
    stacksize=0;
    txtptr=text;
    while (1) {
      ptr=strpbrk(txtptr, "@{[<()>]}");
      if (!ptr) {
        /* add all the rest of the text and exit */
!       owl_fmtext_append_attr(f, txtptr, curattrs);
!       return;
      } else if (ptr[0]=='@') {
        /* add the text up to this point then deal with the stack */
-       buff=owl_malloc(ptr-txtptr+20);
        strncpy(buff, txtptr, ptr-txtptr);
        buff[ptr-txtptr]='\0';
!       owl_fmtext_append_attr(f, buff, curattrs);
!       owl_free(buff);
  
        /* now the stack */
--- 68,91 ----
  void owl_fmtext_append_ztext(owl_fmtext *f, char *text) {
    int stacksize, curattrs;
!   char curcolor, color;
!   char *ptr, *txtptr, *buff, *tmpptr, *tmpptr2;
!   int attrstack[32], chrstack[32], colorstack[32], chrpstack[32];
  
    curattrs=OWL_FMTEXT_ATTR_NONE;
+   curcolor=OWL_COLOR_NONE;
    stacksize=0;
    txtptr=text;
+   buff=owl_malloc(strlen(text)+5);
    while (1) {
      ptr=strpbrk(txtptr, "@{[<()>]}");
      if (!ptr) {
        /* add all the rest of the text and exit */
!       owl_fmtext_append_attr(f, txtptr, curattrs, curcolor);
!       break;
      } else if (ptr[0]=='@') {
        /* add the text up to this point then deal with the stack */
        strncpy(buff, txtptr, ptr-txtptr);
        buff[ptr-txtptr]='\0';
!       owl_fmtext_append_attr(f, buff, curattrs, curcolor);
  
        /* now the stack */
***************
*** 90,94 ****
        /* if we've hit our max stack depth, print the @ and move on */
        if (stacksize==32) {
! 	owl_fmtext_append_attr(f, "@", curattrs);
  	txtptr++;
  	continue;
--- 94,98 ----
        /* if we've hit our max stack depth, print the @ and move on */
        if (stacksize==32) {
! 	owl_fmtext_append_attr(f, "@", curattrs, curcolor);
  	txtptr++;
  	continue;
***************
*** 97,101 ****
        /* if it's an @@, print an @ and continue */
        if (txtptr[1]=='@') {
! 	owl_fmtext_append_attr(f, "@", curattrs);
  	txtptr+=2;
  	continue;
--- 101,105 ----
        /* if it's an @@, print an @ and continue */
        if (txtptr[1]=='@') {
! 	owl_fmtext_append_attr(f, "@", curattrs, curcolor);
  	txtptr+=2;
  	continue;
***************
*** 105,109 ****
        tmpptr=strpbrk(txtptr, "(<[{ ");
        if (!tmpptr || tmpptr[0]==' ') {
! 	owl_fmtext_append_attr(f, "@", curattrs);
  	txtptr++;
  	continue;
--- 109,113 ----
        tmpptr=strpbrk(txtptr, "(<[{ ");
        if (!tmpptr || tmpptr[0]==' ') {
! 	owl_fmtext_append_attr(f, "@", curattrs, curcolor);
  	txtptr++;
  	continue;
***************
*** 112,166 ****
        /* check what command we've got, push it on the stack, start
  	 using it, and continue */
-       buff=owl_malloc(tmpptr-ptr+20);
        strncpy(buff, ptr, tmpptr-ptr);
        buff[tmpptr-ptr]='\0';
!       if (!strcmp(buff, "@bold")) {
  	attrstack[stacksize]=OWL_FMTEXT_ATTR_BOLD;
  	chrstack[stacksize]=tmpptr[0];
  	stacksize++;
  	curattrs|=OWL_FMTEXT_ATTR_BOLD;
  	txtptr+=6;
- 	owl_free(buff);
  	continue;
!       } else if (!strcmp(buff, "@b")) {
  	attrstack[stacksize]=OWL_FMTEXT_ATTR_BOLD;
  	chrstack[stacksize]=tmpptr[0];
  	stacksize++;
  	curattrs|=OWL_FMTEXT_ATTR_BOLD;
  	txtptr+=3;
- 	owl_free(buff);
  	continue;
!       } else if (!strcmp(buff, "@i")) {
  	attrstack[stacksize]=OWL_FMTEXT_ATTR_UNDERLINE;
  	chrstack[stacksize]=tmpptr[0];
  	stacksize++;
  	curattrs|=OWL_FMTEXT_ATTR_UNDERLINE;
  	txtptr+=3;
- 	owl_free(buff);
  	continue;
!       } else if (!strcmp(buff, "@italic")) {
  	attrstack[stacksize]=OWL_FMTEXT_ATTR_UNDERLINE;
  	chrstack[stacksize]=tmpptr[0];
  	stacksize++;
  	curattrs|=OWL_FMTEXT_ATTR_UNDERLINE;
  	txtptr+=8;
- 	owl_free(buff);
  	continue;
! 
!       } else {
! 	/* if we didn't understand it, we'll print it.  This is different from zwgc
! 	   but zwgc seems to be smarter about some screw cases than I am */
! 	owl_fmtext_append_attr(f, "@", curattrs);
! 	txtptr++;
  	continue;
        }
  
      } else if (ptr[0]=='}' || ptr[0]==']' || ptr[0]==')' || ptr[0]=='>') {
        /* add the text up to this point first */
-       buff=owl_malloc(ptr-txtptr+20);
        strncpy(buff, txtptr, ptr-txtptr);
        buff[ptr-txtptr]='\0';
!       owl_fmtext_append_attr(f, buff, curattrs);
!       owl_free(buff);
  
        /* now deal with the closer */
--- 116,246 ----
        /* check what command we've got, push it on the stack, start
  	 using it, and continue */
        strncpy(buff, ptr, tmpptr-ptr);
        buff[tmpptr-ptr]='\0';
!       if (!strcasecmp(buff, "@bold")) {
  	attrstack[stacksize]=OWL_FMTEXT_ATTR_BOLD;
+ 	colorstack[stacksize]=curcolor;
  	chrstack[stacksize]=tmpptr[0];
+ 	chrpstack[stacksize]=0;  /* don't print the closer */
  	stacksize++;
  	curattrs|=OWL_FMTEXT_ATTR_BOLD;
  	txtptr+=6;
  	continue;
!       } else if (!strcasecmp(buff, "@b")) {
  	attrstack[stacksize]=OWL_FMTEXT_ATTR_BOLD;
+ 	colorstack[stacksize]=curcolor;
  	chrstack[stacksize]=tmpptr[0];
+ 	chrpstack[stacksize]=0;  /* don't print the closer */
  	stacksize++;
  	curattrs|=OWL_FMTEXT_ATTR_BOLD;
  	txtptr+=3;
  	continue;
!       } else if (!strcasecmp(buff, "@i")) {
  	attrstack[stacksize]=OWL_FMTEXT_ATTR_UNDERLINE;
+ 	colorstack[stacksize]=curcolor;
  	chrstack[stacksize]=tmpptr[0];
+ 	chrpstack[stacksize]=0;  /* don't print the closer */
  	stacksize++;
  	curattrs|=OWL_FMTEXT_ATTR_UNDERLINE;
  	txtptr+=3;
  	continue;
!       } else if (!strcasecmp(buff, "@italic")) {
  	attrstack[stacksize]=OWL_FMTEXT_ATTR_UNDERLINE;
+ 	colorstack[stacksize]=curcolor;
  	chrstack[stacksize]=tmpptr[0];
+ 	chrpstack[stacksize]=0;  /* don't print the closer */
  	stacksize++;
  	curattrs|=OWL_FMTEXT_ATTR_UNDERLINE;
  	txtptr+=8;
  	continue;
!       } else if (!strcasecmp(buff, "@color")) {
!         tmpptr2 = strpbrk(txtptr, ")>]}");
!         if (tmpptr2 &&
!             ((tmpptr2[0]==')' && tmpptr[0]=='(') ||
!              (tmpptr2[0]=='>' && tmpptr[0]=='<') ||
!              (tmpptr2[0]==']' && tmpptr[0]=='[') ||
!              (tmpptr2[0]=='}' && tmpptr[0]=='{'))) {
!           tmpptr+=1;
!           strncpy(buff, tmpptr, tmpptr2-tmpptr);
!           buff[tmpptr2-tmpptr]='\0';
!           color=owl_parse_color_name(buff);
!           if (color) {
!             color=owl_set_fg_color(curcolor,color);
!             if (color) {
!               curcolor=color;
!               colorstack[stacksize]=color;
!               /* colors don't increase the stack */
!               txtptr=tmpptr2+1;
!               continue;
!             }
!           }
!         }
!       } else if (!strcasecmp(buff, "@bgcolor")) {
!         tmpptr2 = strpbrk(txtptr, ")>]}");
!         if (tmpptr2 &&
!             ((tmpptr2[0]==')' && tmpptr[0]=='(') ||
!              (tmpptr2[0]=='>' && tmpptr[0]=='<') ||
!              (tmpptr2[0]==']' && tmpptr[0]=='[') ||
!              (tmpptr2[0]=='}' && tmpptr[0]=='{'))) {
!           tmpptr+=1;
!           strncpy(buff, tmpptr, tmpptr2-tmpptr);
!           buff[tmpptr2-tmpptr]='\0';
!           color=owl_parse_color_name(buff);
!           if (color) {
!             color=owl_set_bg_color(curcolor,color);
!             if (color) {
!               curcolor=color;
!               colorstack[stacksize]=color;
!               /* colors don't increase the stack */
!               txtptr=tmpptr2+1;
!               continue;
!             }
!           }
!         }
!       } else if (!strcasecmp(buff, "@")) {
!         /* Deal with empty command names, creates a new environment
!            with no changes.  Useful for temporary changes to font or
!            color, or for escaping a closing bracket that would
!            otherwise end an active environment.  Ex. @< ... > */
! 	attrstack[stacksize]=OWL_FMTEXT_ATTR_NONE;
! 	colorstack[stacksize]=curcolor;
! 	chrstack[stacksize]=tmpptr[0];
! 	chrpstack[stacksize]=0;  /* don't print the closer */
! 	stacksize++;
! 	curattrs|=OWL_FMTEXT_ATTR_NONE;
! 	txtptr+=2;
! 	continue;
!       } else if (!strcasecmp(buff, "@beep")) {
!         owl_function_beep();
! 	attrstack[stacksize]=OWL_FMTEXT_ATTR_NONE;
! 	colorstack[stacksize]=curcolor;
! 	chrstack[stacksize]=tmpptr[0];
! 	chrpstack[stacksize]=0;  /* don't print the closer */
! 	stacksize++;
! 	curattrs|=OWL_FMTEXT_ATTR_NONE;
! 	txtptr+=6;
  	continue;
        }
  
+       /* If we didn't interpret it above we'll print it.  This is
+          different from zwgc, but potentially more useful.  Create a
+          new environment so the close bracket matches properly.
+          Ex. @i(1 @test(2) 3) prints sort of like _1_@test(2)_3_ */
+       strncpy(buff, ptr, tmpptr-ptr+1);
+       buff[tmpptr-ptr+1]='\0';
+       owl_fmtext_append_attr(f, buff, curattrs, curcolor);
+       attrstack[stacksize]=OWL_FMTEXT_ATTR_NONE;
+       colorstack[stacksize]=curcolor;
+       chrstack[stacksize]=tmpptr[0];
+       chrpstack[stacksize]=1;  /* print the closer */
+       stacksize++;
+       txtptr+=strlen(buff);
+       continue;
+ 
      } else if (ptr[0]=='}' || ptr[0]==']' || ptr[0]==')' || ptr[0]=='>') {
        /* add the text up to this point first */
        strncpy(buff, txtptr, ptr-txtptr);
        buff[ptr-txtptr]='\0';
!       owl_fmtext_append_attr(f, buff, curattrs, curcolor);
  
        /* now deal with the closer */
***************
*** 169,177 ****
        /* first, if the stack is empty we must bail (just print and go) */
        if (stacksize==0) {
- 	buff=owl_malloc(5);
  	buff[0]=ptr[0];
  	buff[1]='\0';
! 	owl_fmtext_append_attr(f, buff, curattrs);
! 	owl_free(buff);
  	txtptr++;
  	continue;
--- 249,255 ----
        /* first, if the stack is empty we must bail (just print and go) */
        if (stacksize==0) {
  	buff[0]=ptr[0];
  	buff[1]='\0';
! 	owl_fmtext_append_attr(f, buff, curattrs, curcolor);
  	txtptr++;
  	continue;
***************
*** 186,202 ****
  	int i;
  	stacksize--;
  	curattrs=OWL_FMTEXT_ATTR_NONE;
  	for (i=0; i<stacksize; i++) {
  	  curattrs|=attrstack[i];
  	}
  	txtptr+=1;
  	continue;
        } else {
  	/* otherwise print and continue */
- 	buff=owl_malloc(5);
  	buff[0]=ptr[0];
  	buff[1]='\0';
! 	owl_fmtext_append_attr(f, buff, curattrs);
! 	owl_free(buff);
  	txtptr++;
  	continue;
--- 264,287 ----
  	int i;
  	stacksize--;
+         if (chrpstack[stacksize]) {
+           /* This is the closing bracket to an opener we printed
+              earlier so we should print it also */
+           buff[0]=ptr[0];
+           buff[1]='\0';
+           owl_fmtext_append_attr(f, buff, curattrs, curcolor);
+         }
  	curattrs=OWL_FMTEXT_ATTR_NONE;
+         curcolor=OWL_COLOR_NONE;
  	for (i=0; i<stacksize; i++) {
  	  curattrs|=attrstack[i];
  	}
+         curcolor=colorstack[stacksize];
  	txtptr+=1;
  	continue;
        } else {
  	/* otherwise print and continue */
  	buff[0]=ptr[0];
  	buff[1]='\0';
! 	owl_fmtext_append_attr(f, buff, curattrs, curcolor);
  	txtptr++;
  	continue;
***************
*** 204,212 ****
      } else {
        /* we've found an unattached opener, print everything and move on */
-       buff=owl_malloc(ptr-txtptr+20);
        strncpy(buff, txtptr, ptr-txtptr+1);
        buff[ptr-txtptr+1]='\0';
!       owl_fmtext_append_attr(f, buff, curattrs);
!       owl_free(buff);
        txtptr=ptr+1;
        continue;
--- 289,295 ----
      } else {
        /* we've found an unattached opener, print everything and move on */
        strncpy(buff, txtptr, ptr-txtptr+1);
        buff[ptr-txtptr+1]='\0';
!       owl_fmtext_append_attr(f, buff, curattrs, curcolor);
        txtptr=ptr+1;
        continue;
***************
*** 214,217 ****
--- 297,301 ----
    }
  
+     owl_free(buff);
  }
  
***************
*** 222,225 ****
--- 306,310 ----
    f->textbuff=owl_realloc(f->textbuff, newlen+1);
    f->fmbuff=owl_realloc(f->fmbuff, newlen+1);
+   f->color=owl_realloc(f->color, newlen+1);
  
    strncat(f->textbuff, in->textbuff+start, stop-start+1);
***************
*** 227,230 ****
--- 312,316 ----
    for (i=start; i<=stop; i++) {
      f->fmbuff[f->textlen+(i-start)]=in->fmbuff[i];
+     f->color[f->textlen+(i-start)]=in->color[i];
    }
    f->textlen=newlen;
***************
*** 236,272 ****
  }
  
- 
  void owl_fmtext_curs_waddstr(owl_fmtext *f, WINDOW *w) {
!   char *ptr1, *ptr2, *last;
    char *tmpbuff;
  
    tmpbuff=owl_malloc(f->textlen+10);
  
!   ptr1=f->fmbuff;
!   last=f->fmbuff+f->textlen-1;
!   while (ptr1<=last) {
!     /* find the last char with the current fmt */
!     ptr2=ptr1+owl_util_find_trans(ptr1, f->textlen-(ptr1-f->fmbuff));
  
      /* set the current format */
      wattrset(w, A_NORMAL);
!     if (ptr1[0] & OWL_FMTEXT_ATTR_BOLD) {
        wattron(w, A_BOLD);
      }
!     if (ptr1[0] & OWL_FMTEXT_ATTR_REVERSE) {
        wattron(w, A_REVERSE);
      }
!     if (ptr1[0] & OWL_FMTEXT_ATTR_UNDERLINE) {
        wattron(w, A_UNDERLINE);
      }
      
!     strncpy(tmpbuff, f->textbuff + (ptr1 - ((char *) (f->fmbuff))), ptr2-ptr1+1);
!     tmpbuff[ptr2-ptr1+1]='\0';
!     /* printf("Diff is %i\r\n", owl_util_find_trans(ptr1)); */
      waddstr(w, tmpbuff);
  
!     ptr1=ptr2+1;
    }
    owl_free(tmpbuff);
  }
  
--- 322,362 ----
  }
  
  void owl_fmtext_curs_waddstr(owl_fmtext *f, WINDOW *w) {
!   int i, len;
    char *tmpbuff;
  
    tmpbuff=owl_malloc(f->textlen+10);
  
!   i=0;
!   while (i<f->textlen) {
!     /* find where the format changes again */
!     len=owl_util_find_trans(f->fmbuff+i, f->textlen-i);
!     len=owl_util_find_trans(f->color+i, len);
  
      /* set the current format */
      wattrset(w, A_NORMAL);
!     if (f->fmbuff[i] & OWL_FMTEXT_ATTR_BOLD) {
        wattron(w, A_BOLD);
      }
!     if (f->fmbuff[i] & OWL_FMTEXT_ATTR_REVERSE) {
        wattron(w, A_REVERSE);
      }
!     if (f->fmbuff[i] & OWL_FMTEXT_ATTR_UNDERLINE) {
        wattron(w, A_UNDERLINE);
      }
+     if (f->color[i] & OWL_COLOR_PAIR) {
+       owl_wattron_color(w, f->color[i]);
+     }
      
!     strncpy(tmpbuff, f->textbuff+i, len+1);
!     tmpbuff[len+1]='\0';
!     /*printf("Vars are %d %d '%s' '%s'\r\n", i, len, tmpbuff, f->textbuff);*/
      waddstr(w, tmpbuff);
  
!     i+=len+1;
    }
    owl_free(tmpbuff);
+   /* Clear attrs so the pointer doesn't get tainted */
+   wattrset(w, A_NORMAL);
  }
  
***************
*** 379,382 ****
--- 469,473 ----
    if (f->textbuff) owl_free(f->textbuff);
    if (f->fmbuff) owl_free(f->fmbuff);
+   if (f->color) owl_free(f->color);
  }
  
***************
*** 386,390 ****
--- 477,483 ----
    dst->textbuff=owl_malloc(src->textlen+5);
    dst->fmbuff=owl_malloc(src->textlen+5);
+   dst->color=owl_malloc(src->textlen+5);
    memcpy(dst->textbuff, src->textbuff, src->textlen);
    memcpy(dst->fmbuff, src->fmbuff, src->textlen);
+   memcpy(dst->color, src->color, src->textlen);
  }
diff -C 2 -P ../owl-1.1.1/owl.c ./owl.c
*** ../owl-1.1.1/owl.c	Tue Jun 11 23:09:03 2002
--- ./owl.c	Sun Jun 16 21:47:44 2002
***************
*** 100,103 ****
--- 100,104 ----
    putenv(buff);
    initscr();
+   owl_init_colors();
    raw();
    noecho();
diff -C 2 -P ../owl-1.1.1/owl.h ./owl.h
*** ../owl-1.1.1/owl.h	Tue Jun 11 23:09:03 2002
--- ./owl.h	Mon Jun 17 20:02:15 2002
***************
*** 11,15 ****
  
  #define OWL_VERSION         1.1.1
! #define OWL_VERSION_STRING "1.1.1"
  
  #define OWL_DEBUG 0
--- 11,15 ----
  
  #define OWL_VERSION         1.1.1
! #define OWL_VERSION_STRING "1.1.1-color-b2"
  
  #define OWL_DEBUG 0
***************
*** 21,24 ****
--- 21,40 ----
  #define OWL_FMTEXT_ATTR_UNDERLINE 4
  
+ #define	OWL_COLOR_BLACK       0
+ #define	OWL_COLOR_RED         1
+ #define	OWL_COLOR_GREEN       2
+ #define	OWL_COLOR_YELLOW      3
+ #define	OWL_COLOR_BLUE        4
+ #define	OWL_COLOR_MAGENTA     5
+ #define	OWL_COLOR_CYAN        6
+ #define	OWL_COLOR_WHITE       7
+ 
+ #define OWL_COLOR_DEFAULT_BG  OWL_COLOR_BLACK
+ #define OWL_COLOR_DEFAULT_FG  OWL_COLOR_WHITE
+ #define OWL_COLOR_NONE        0
+ #define OWL_COLOR_MASK        7
+ #define OWL_COLOR_PAIR        63
+ #define OWL_COLOR_SET         64
+ 
  #define OWL_EDITWIN_STYLE_MULTILINE 0
  #define OWL_EDITWIN_STYLE_ONELINE   1
***************
*** 112,115 ****
--- 128,132 ----
    char *textbuff;
    char *fmbuff;
+   char *color;
  } owl_fmtext;
  
