Index: fmtext.c
===================================================================
--- fmtext.c	(revision a0a517919ef86311a49f1e5652564bf3c3408ef0)
+++ fmtext.c	(revision 8fa9562d57e3973e92ad34c23fc4eb965a550e47)
@@ -11,7 +11,9 @@
   f->textbuff=owl_strdup("");
   f->fmbuff=owl_malloc(5);
-  f->colorbuff=owl_malloc(5);
+  f->fgcolorbuff=owl_malloc(5);
+  f->bgcolorbuff=owl_malloc(5);
   f->fmbuff[0]=OWL_FMTEXT_ATTR_NONE;
-  f->colorbuff[0]=OWL_COLOR_DEFAULT;
+  f->fgcolorbuff[0]=OWL_COLOR_DEFAULT;
+  f->bgcolorbuff[0]=OWL_COLOR_DEFAULT;
 }
 
@@ -41,9 +43,17 @@
  * to index 'last
  */
-void _owl_fmtext_set_color(owl_fmtext *f, int color, int first, int last)
+void _owl_fmtext_set_fgcolor(owl_fmtext *f, int color, int first, int last)
 {
   int i;
   for (i=first; i<=last; i++) {
-    f->colorbuff[i]=(unsigned char) color;
+    f->fgcolorbuff[i]=(unsigned char) color;
+  }
+}
+
+void _owl_fmtext_set_bgcolor(owl_fmtext *f, int color, int first, int last)
+{
+  int i;
+  for (i=first; i<=last; i++) {
+    f->bgcolorbuff[i]=(unsigned char) color;
   }
 }
@@ -52,5 +62,5 @@
  * 'color'
  */
-void owl_fmtext_append_attr(owl_fmtext *f, char *text, int attr, int color)
+void owl_fmtext_append_attr(owl_fmtext *f, char *text, int attr, int fgcolor, int bgcolor)
 {
   int newlen;
@@ -59,9 +69,11 @@
   f->textbuff=owl_realloc(f->textbuff, newlen+2);
   f->fmbuff=owl_realloc(f->fmbuff, newlen+2);
-  f->colorbuff=owl_realloc(f->colorbuff, newlen+2);
+  f->fgcolorbuff=owl_realloc(f->fgcolorbuff, newlen+2);
+  f->bgcolorbuff=owl_realloc(f->bgcolorbuff, newlen+2);
 
   strcat(f->textbuff, text);
   _owl_fmtext_set_attr(f, attr, f->textlen, newlen);
-  _owl_fmtext_set_color(f, color, f->textlen, newlen);
+  _owl_fmtext_set_fgcolor(f, fgcolor, f->textlen, newlen);
+  _owl_fmtext_set_bgcolor(f, bgcolor, f->textlen, newlen);
   f->textlen=newlen;
 }
@@ -70,11 +82,11 @@
 void owl_fmtext_append_normal(owl_fmtext *f, char *text)
 {
-  owl_fmtext_append_attr(f, text, OWL_FMTEXT_ATTR_NONE, OWL_COLOR_DEFAULT);
+  owl_fmtext_append_attr(f, text, OWL_FMTEXT_ATTR_NONE, OWL_COLOR_DEFAULT, OWL_COLOR_DEFAULT);
 }
 
 /* Append normal text 'text' to 'f' with color 'color' */
-void owl_fmtext_append_normal_color(owl_fmtext *f, char *text, int color)
-{
-  owl_fmtext_append_attr(f, text, OWL_FMTEXT_ATTR_NONE, color);
+void owl_fmtext_append_normal_color(owl_fmtext *f, char *text, int fgcolor, int bgcolor)
+{
+  owl_fmtext_append_attr(f, text, OWL_FMTEXT_ATTR_NONE, fgcolor, bgcolor);
 }
 
@@ -82,5 +94,5 @@
 void owl_fmtext_append_bold(owl_fmtext *f, char *text)
 {
-  owl_fmtext_append_attr(f, text, OWL_FMTEXT_ATTR_BOLD, OWL_COLOR_DEFAULT);
+  owl_fmtext_append_attr(f, text, OWL_FMTEXT_ATTR_BOLD, OWL_COLOR_DEFAULT, OWL_COLOR_DEFAULT);
 }
 
@@ -88,5 +100,5 @@
 void owl_fmtext_append_reverse(owl_fmtext *f, char *text)
 {
-  owl_fmtext_append_attr(f, text, OWL_FMTEXT_ATTR_REVERSE, OWL_COLOR_DEFAULT);
+  owl_fmtext_append_attr(f, text, OWL_FMTEXT_ATTR_REVERSE, OWL_COLOR_DEFAULT, OWL_COLOR_DEFAULT);
 }
 
@@ -94,5 +106,5 @@
 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_DEFAULT);
+  owl_fmtext_append_attr(f, text, OWL_FMTEXT_ATTR_REVERSE | OWL_FMTEXT_ATTR_BOLD, OWL_COLOR_DEFAULT, OWL_COLOR_DEFAULT);
 }
 
@@ -114,10 +126,21 @@
 void owl_fmtext_colorize(owl_fmtext *f, int color)
 {
-  /* everywhere the color is OWL_COLOR_DEFAULT, change it to be 'color' */
+  /* everywhere the fgcolor is OWL_COLOR_DEFAULT, change it to be 'color' */
   int i, j;
 
   j=f->textlen;
   for(i=0; i<j; i++) {
-    if (f->colorbuff[i]==OWL_COLOR_DEFAULT) f->colorbuff[i] = color;
+    if (f->fgcolorbuff[i]==OWL_COLOR_DEFAULT) f->fgcolorbuff[i] = color;
+  }
+}
+
+void owl_fmtext_colorizebg(owl_fmtext *f, int color)
+{
+  /* everywhere the bgcolor is OWL_COLOR_DEFAULT, change it to be 'color' */
+  int i, j;
+
+  j=f->textlen;
+  for(i=0; i<j; i++) {
+    if (f->bgcolorbuff[i]==OWL_COLOR_DEFAULT) f->bgcolorbuff[i] = color;
   }
 }
@@ -133,5 +156,6 @@
   f->textbuff=owl_realloc(f->textbuff, newlen+1);
   f->fmbuff=owl_realloc(f->fmbuff, newlen+1);
-  f->colorbuff=owl_realloc(f->colorbuff, newlen+1);
+  f->fgcolorbuff=owl_realloc(f->fgcolorbuff, newlen+1);
+  f->bgcolorbuff=owl_realloc(f->bgcolorbuff, newlen+1);
 
   strncat(f->textbuff, in->textbuff+start, stop-start+1);
@@ -139,5 +163,6 @@
   for (i=start; i<=stop; i++) {
     f->fmbuff[f->textlen+(i-start)]=in->fmbuff[i];
-    f->colorbuff[f->textlen+(i-start)]=in->colorbuff[i];
+    f->fgcolorbuff[f->textlen+(i-start)]=in->fgcolorbuff[i];
+    f->bgcolorbuff[f->textlen+(i-start)]=in->bgcolorbuff[i];
   }
   f->textlen=newlen;
@@ -174,5 +199,5 @@
 {
   char *tmpbuff;
-  int position, trans1, trans2, len, lastsame;
+  int position, trans1, trans2, trans3, len, lastsame;
 
   if (w==NULL) {
@@ -188,11 +213,10 @@
     /* find the last char with the current format and color */
     trans1=owl_util_find_trans(f->fmbuff+position, len-position);
-    trans2=owl_util_find_trans(f->colorbuff+position, len-position);
-
-    if (trans1<trans2) {
-      lastsame=position+trans1;
-    } else {
-      lastsame=position+trans2;
-    }
+    trans2=owl_util_find_trans(f->fgcolorbuff+position, len-position);
+    trans3=owl_util_find_trans(f->bgcolorbuff+position, len-position);
+
+    lastsame = (trans1 < trans2) ? trans1 : trans2;
+    lastsame = (lastsame < trans3) ? lastsame : trans3;
+    lastsame += position;
 
     /* set the format */
@@ -211,6 +235,12 @@
     /* warning, this is sort of a hack */
     if (owl_global_get_hascolors(&g)) {
-      if (f->colorbuff[position]!=OWL_COLOR_DEFAULT) {
-	wattron(w, COLOR_PAIR(f->colorbuff[position]));
+      int pair, fg, bg;
+      fg = f->fgcolorbuff[position];
+      bg = f->bgcolorbuff[position];
+      owl_function_debugmsg("waddstr: fg(%i) bg(%i).", fg, bg);
+
+      pair = owl_fmtext_get_colorpair(fg, bg);
+      if (pair != -1) {
+	wattron(w, COLOR_PAIR(pair));
       }
     }
@@ -355,8 +385,10 @@
   dst->textbuff=owl_malloc(mallocsize);
   dst->fmbuff=owl_malloc(mallocsize);
-  dst->colorbuff=owl_malloc(mallocsize);
+  dst->fgcolorbuff=owl_malloc(mallocsize);
+  dst->bgcolorbuff=owl_malloc(mallocsize);
   memcpy(dst->textbuff, src->textbuff, src->textlen+1);
   memcpy(dst->fmbuff, src->fmbuff, src->textlen);
-  memcpy(dst->colorbuff, src->colorbuff, src->textlen);
+  memcpy(dst->fgcolorbuff, src->fgcolorbuff, src->textlen);
+  memcpy(dst->bgcolorbuff, src->bgcolorbuff, src->textlen);
 }
 
@@ -415,5 +447,5 @@
     if (!ptr) {
       /* add all the rest of the text and exit */
-      owl_fmtext_append_attr(f, txtptr, curattrs, curcolor);
+      owl_fmtext_append_attr(f, txtptr, curattrs, curcolor, OWL_COLOR_DEFAULT);
       return;
     } else if (ptr[0]=='@') {
@@ -422,5 +454,5 @@
       strncpy(buff, txtptr, ptr-txtptr);
       buff[ptr-txtptr]='\0';
-      owl_fmtext_append_attr(f, buff, curattrs, curcolor);
+      owl_fmtext_append_attr(f, buff, curattrs, curcolor, OWL_COLOR_DEFAULT);
       owl_free(buff);
 
@@ -432,5 +464,5 @@
       /* if we've hit our max stack depth, print the @ and move on */
       if (stacksize==32) {
-	owl_fmtext_append_attr(f, "@", curattrs, curcolor);
+	owl_fmtext_append_attr(f, "@", curattrs, curcolor, OWL_COLOR_DEFAULT);
 	txtptr++;
 	continue;
@@ -439,5 +471,5 @@
       /* if it's an @@, print an @ and continue */
       if (txtptr[1]=='@') {
-	owl_fmtext_append_attr(f, "@", curattrs, curcolor);
+	owl_fmtext_append_attr(f, "@", curattrs, curcolor, OWL_COLOR_DEFAULT);
 	txtptr+=2;
 	continue;
@@ -447,5 +479,5 @@
       tmpptr=strpbrk(txtptr, "(<[{ ");
       if (!tmpptr || tmpptr[0]==' ') {
-	owl_fmtext_append_attr(f, "@", curattrs, curcolor);
+	owl_fmtext_append_attr(f, "@", curattrs, curcolor, OWL_COLOR_DEFAULT);
 	txtptr++;
 	continue;
@@ -524,5 +556,5 @@
 	 * but zwgc seems to be smarter about some screw cases than I am
 	 */
-	owl_fmtext_append_attr(f, "@", curattrs, curcolor);
+	owl_fmtext_append_attr(f, "@", curattrs, curcolor, OWL_COLOR_DEFAULT);
 	txtptr++;
 	continue;
@@ -534,5 +566,5 @@
       strncpy(buff, txtptr, ptr-txtptr);
       buff[ptr-txtptr]='\0';
-      owl_fmtext_append_attr(f, buff, curattrs, curcolor);
+      owl_fmtext_append_attr(f, buff, curattrs, curcolor, OWL_COLOR_DEFAULT);
       owl_free(buff);
 
@@ -545,5 +577,5 @@
 	buff[0]=ptr[0];
 	buff[1]='\0';
-	owl_fmtext_append_attr(f, buff, curattrs, curcolor);
+	owl_fmtext_append_attr(f, buff, curattrs, curcolor, OWL_COLOR_DEFAULT);
 	owl_free(buff);
 	txtptr++;
@@ -570,5 +602,5 @@
 	buff[0]=ptr[0];
 	buff[1]='\0';
-	owl_fmtext_append_attr(f, buff, curattrs, curcolor);
+	owl_fmtext_append_attr(f, buff, curattrs, curcolor, OWL_COLOR_DEFAULT);
 	owl_free(buff);
 	txtptr++;
@@ -580,5 +612,5 @@
       strncpy(buff, txtptr, ptr-txtptr+1);
       buff[ptr-txtptr+1]='\0';
-      owl_fmtext_append_attr(f, buff, curattrs, curcolor);
+      owl_fmtext_append_attr(f, buff, curattrs, curcolor, OWL_COLOR_DEFAULT);
       owl_free(buff);
       txtptr=ptr+1;
@@ -621,5 +653,77 @@
   if (f->textbuff) owl_free(f->textbuff);
   if (f->fmbuff) owl_free(f->fmbuff);
-  if (f->colorbuff) owl_free(f->colorbuff);
-}
-
+  if (f->fgcolorbuff) owl_free(f->fgcolorbuff);
+  if (f->bgcolorbuff) owl_free(f->bgcolorbuff);
+}
+
+/*** Color Pair manager ***/
+void owl_fmtext_init_colorpair_mgr(owl_colorpair_mgr *cpmgr)
+{
+  // This could be a bitarray if we wanted to save memory.
+  int i, j, colors;
+  cpmgr->used = owl_malloc(COLOR_PAIRS * sizeof(char));
+  memset(cpmgr->used, 0, COLOR_PAIRS * sizeof(char));
+
+  colors = COLORS + 1; // 1 to account for "default".
+  cpmgr->pairs = owl_malloc(colors * sizeof(int*));
+  for(i = 0; i < colors; i++) {
+    // Because we're going to have a pair set for any fg and the
+    // default bg, we don't need to account for default here.
+    cpmgr->pairs[i] = owl_malloc(COLORS * sizeof(int));
+    for(j = 0; j < COLORS; j++) {
+      cpmgr->pairs[i][j] = -1;
+    }
+  }
+}
+
+/* Reset used list */
+void owl_fmtext_reset_colorpairs()
+{
+  memset(owl_global_get_colorpair_mgr(&g)->used, 0, COLOR_PAIRS * sizeof(char));  
+}
+
+/* Assign pairs by request */
+int owl_fmtext_get_colorpair(int fg, int bg)
+{
+  owl_colorpair_mgr *cpmgr;
+  short pair, i;
+  if (fg == OWL_COLOR_DEFAULT) fg = -1;
+  if (bg == OWL_COLOR_DEFAULT) {
+    pair = fg;
+  } else {
+    cpmgr = owl_global_get_colorpair_mgr(&g);
+    pair = cpmgr->pairs[fg+1][bg];
+    if (pair != -1) {
+      short oldfg, oldbg;
+      pair_content(pair, &oldfg, &oldbg);
+      if (cpmgr->pairs[oldfg+1][oldbg] == pair) {
+	cpmgr->pairs[oldfg+1][oldbg] = -1;
+      }
+      init_pair(pair, fg, bg);
+      cpmgr->pairs[fg+1][bg] = pair;
+      cpmgr->used[pair] = 1;
+    } else {
+      // Skip the first COLORS, sicne they're static.
+      for(i = COLORS; i < COLOR_PAIRS; i++) {
+	if (0 == cpmgr->used[i]) {
+	  pair = i;
+	  break;
+	}
+      }
+      if (pair != -1) {
+	short oldfg, oldbg;
+	pair_content(pair, &oldfg, &oldbg);
+	if (cpmgr->pairs[oldfg+1][oldbg] == pair) {
+	  cpmgr->pairs[oldfg+1][oldbg] = -1;
+	}
+	init_pair(pair, fg, bg);
+	cpmgr->pairs[fg+1][bg] = pair;
+	cpmgr->used[pair] = 1;
+      } else {
+	// Fail to skipping background.
+	pair = fg;
+      }
+    }
+  }
+  return pair;
+}
