source: fmtext.c @ 3ce5bdc

barnowl_perlaimdebianrelease-1.10release-1.4release-1.5release-1.6release-1.7release-1.8release-1.9
Last change on this file since 3ce5bdc was 0331c8f, checked in by Alejandro R. Sedeño <asedeno@mit.edu>, 18 years ago
Further simplifications.
  • Property mode set to 100644
File size: 20.2 KB
Line 
1#include "owl.h"
2#include <stdlib.h>
3#include <string.h>
4
5static const char fileIdent[] = "$Id$";
6
7/* initialize an fmtext with no data */
8void owl_fmtext_init_null(owl_fmtext *f)
9{
10  f->textlen=0;
11  f->textbuff=owl_strdup("");
12  f->fmbuff=owl_malloc(5);
13  f->fgcolorbuff=owl_malloc(5);
14  f->bgcolorbuff=owl_malloc(5);
15  f->fmbuff[0]=OWL_FMTEXT_ATTR_NONE;
16  f->fgcolorbuff[0]=OWL_COLOR_DEFAULT;
17  f->bgcolorbuff[0]=OWL_COLOR_DEFAULT;
18}
19
20/* Internal function.  Set the attribute 'attr' from index 'first' to
21 * index 'last'
22 */
23void _owl_fmtext_set_attr(owl_fmtext *f, int attr, int first, int last)
24{
25  int i;
26  for (i=first; i<=last; i++) {
27    f->fmbuff[i]=(unsigned char) attr;
28  }
29}
30
31/* Internal function.  Add the attribute 'attr' to the existing
32 * attributes from index 'first' to index 'last'
33 */
34void _owl_fmtext_add_attr(owl_fmtext *f, int attr, int first, int last)
35{
36  int i;
37  for (i=first; i<=last; i++) {
38    f->fmbuff[i]|=(unsigned char) attr;
39  }
40}
41
42/* Internal function.  Set the color to be 'color' from index 'first'
43 * to index 'last
44 */
45void _owl_fmtext_set_fgcolor(owl_fmtext *f, int color, int first, int last)
46{
47  int i;
48  for (i=first; i<=last; i++) {
49    f->fgcolorbuff[i]=(unsigned char) color;
50  }
51}
52
53void _owl_fmtext_set_bgcolor(owl_fmtext *f, int color, int first, int last)
54{
55  int i;
56  for (i=first; i<=last; i++) {
57    f->bgcolorbuff[i]=(unsigned char) color;
58  }
59}
60
61/* append text to the end of 'f' with attribute 'attr' and color
62 * 'color'
63 */
64void owl_fmtext_append_attr(owl_fmtext *f, char *text, int attr, int fgcolor, int bgcolor)
65{
66  int newlen;
67
68  newlen=strlen(f->textbuff)+strlen(text);
69  f->textbuff=owl_realloc(f->textbuff, newlen+2);
70  f->fmbuff=owl_realloc(f->fmbuff, newlen+2);
71  f->fgcolorbuff=owl_realloc(f->fgcolorbuff, newlen+2);
72  f->bgcolorbuff=owl_realloc(f->bgcolorbuff, newlen+2);
73
74  strcat(f->textbuff, text);
75  _owl_fmtext_set_attr(f, attr, f->textlen, newlen);
76  _owl_fmtext_set_fgcolor(f, fgcolor, f->textlen, newlen);
77  _owl_fmtext_set_bgcolor(f, bgcolor, f->textlen, newlen);
78  f->textlen=newlen;
79}
80
81/* Append normal, uncolored text 'text' to 'f' */
82void owl_fmtext_append_normal(owl_fmtext *f, char *text)
83{
84  owl_fmtext_append_attr(f, text, OWL_FMTEXT_ATTR_NONE, OWL_COLOR_DEFAULT, OWL_COLOR_DEFAULT);
85}
86
87/* Append normal text 'text' to 'f' with color 'color' */
88void owl_fmtext_append_normal_color(owl_fmtext *f, char *text, int fgcolor, int bgcolor)
89{
90  owl_fmtext_append_attr(f, text, OWL_FMTEXT_ATTR_NONE, fgcolor, bgcolor);
91}
92
93/* Append bold text 'text' to 'f' */
94void owl_fmtext_append_bold(owl_fmtext *f, char *text)
95{
96  owl_fmtext_append_attr(f, text, OWL_FMTEXT_ATTR_BOLD, OWL_COLOR_DEFAULT, OWL_COLOR_DEFAULT);
97}
98
99/* Append reverse video text 'text' to 'f' */
100void owl_fmtext_append_reverse(owl_fmtext *f, char *text)
101{
102  owl_fmtext_append_attr(f, text, OWL_FMTEXT_ATTR_REVERSE, OWL_COLOR_DEFAULT, OWL_COLOR_DEFAULT);
103}
104
105/* Append reversed and bold, uncolored text 'text' to 'f' */
106void owl_fmtext_append_reversebold(owl_fmtext *f, char *text)
107{
108  owl_fmtext_append_attr(f, text, OWL_FMTEXT_ATTR_REVERSE | OWL_FMTEXT_ATTR_BOLD, OWL_COLOR_DEFAULT, OWL_COLOR_DEFAULT);
109}
110
111/* Add the attribute 'attr' to all text in 'f' */
112void owl_fmtext_addattr(owl_fmtext *f, int attr)
113{
114  /* add the attribute to all text */
115  int i, j;
116
117  j=f->textlen;
118  for (i=0; i<j; i++) {
119    f->fmbuff[i] |= attr;
120  }
121}
122
123/* Anywhere the color is NOT ALREDY SET, set the color to 'color'.
124 * Other colors are left unchanged
125 */
126void owl_fmtext_colorize(owl_fmtext *f, int color)
127{
128  /* everywhere the fgcolor is OWL_COLOR_DEFAULT, change it to be 'color' */
129  int i, j;
130
131  j=f->textlen;
132  for(i=0; i<j; i++) {
133    if (f->fgcolorbuff[i]==OWL_COLOR_DEFAULT) f->fgcolorbuff[i] = color;
134  }
135}
136
137void owl_fmtext_colorizebg(owl_fmtext *f, int color)
138{
139  /* everywhere the bgcolor is OWL_COLOR_DEFAULT, change it to be 'color' */
140  int i, j;
141
142  j=f->textlen;
143  for(i=0; i<j; i++) {
144    if (f->bgcolorbuff[i]==OWL_COLOR_DEFAULT) f->bgcolorbuff[i] = color;
145  }
146}
147
148/* Internal function.  Append text from 'in' between index 'start' and
149 * 'stop' to the end of 'f'
150 */
151void _owl_fmtext_append_fmtext(owl_fmtext *f, owl_fmtext *in, int start, int stop)
152{
153  int newlen, i;
154
155  newlen=strlen(f->textbuff)+(stop-start+1);
156  f->textbuff=owl_realloc(f->textbuff, newlen+1);
157  f->fmbuff=owl_realloc(f->fmbuff, newlen+1);
158  f->fgcolorbuff=owl_realloc(f->fgcolorbuff, newlen+1);
159  f->bgcolorbuff=owl_realloc(f->bgcolorbuff, newlen+1);
160
161  strncat(f->textbuff, in->textbuff+start, stop-start+1);
162  f->textbuff[newlen]='\0';
163  for (i=start; i<=stop; i++) {
164    f->fmbuff[f->textlen+(i-start)]=in->fmbuff[i];
165    f->fgcolorbuff[f->textlen+(i-start)]=in->fgcolorbuff[i];
166    f->bgcolorbuff[f->textlen+(i-start)]=in->bgcolorbuff[i];
167  }
168  f->textlen=newlen;
169}
170
171/* append fmtext 'in' to 'f' */
172void owl_fmtext_append_fmtext(owl_fmtext *f, owl_fmtext *in)
173{
174  _owl_fmtext_append_fmtext(f, in, 0, in->textlen);
175
176}
177
178/* Append 'nspaces' number of spaces to the end of 'f' */
179void owl_fmtext_append_spaces(owl_fmtext *f, int nspaces)
180{
181  int i;
182  for (i=0; i<nspaces; i++) {
183    owl_fmtext_append_normal(f, " ");
184  }
185}
186
187/* Return a plain version of the fmtext.  Caller is responsible for
188 * freeing the return
189 */
190char *owl_fmtext_print_plain(owl_fmtext *f)
191{
192  return(owl_strdup(f->textbuff));
193}
194
195/* add the formatted text to the curses window 'w'.  The window 'w'
196 * must already be initiatlized with curses
197 */
198void owl_fmtext_curs_waddstr(owl_fmtext *f, WINDOW *w)
199{
200  char *tmpbuff;
201  int position, trans1, trans2, trans3, len, lastsame;
202
203  if (w==NULL) {
204    owl_function_debugmsg("Hit a null window in owl_fmtext_curs_waddstr.");
205    return;
206  }
207
208  tmpbuff=owl_malloc(f->textlen+10);
209
210  position=0;
211  len=f->textlen;
212  while (position<=len) {
213    /* find the last char with the current format and color */
214    trans1=owl_util_find_trans(f->fmbuff+position, len-position);
215    trans2=owl_util_find_trans(f->fgcolorbuff+position, len-position);
216    trans3=owl_util_find_trans(f->bgcolorbuff+position, len-position);
217
218    lastsame = (trans1 < trans2) ? trans1 : trans2;
219    lastsame = (lastsame < trans3) ? lastsame : trans3;
220    lastsame += position;
221
222    /* set the format */
223    wattrset(w, A_NORMAL);
224    if (f->fmbuff[position] & OWL_FMTEXT_ATTR_BOLD) {
225      wattron(w, A_BOLD);
226    }
227    if (f->fmbuff[position] & OWL_FMTEXT_ATTR_REVERSE) {
228      wattron(w, A_REVERSE);
229    }
230    if (f->fmbuff[position] & OWL_FMTEXT_ATTR_UNDERLINE) {
231      wattron(w, A_UNDERLINE);
232    }
233
234    /* set the color */
235    /* warning, this is sort of a hack */
236    if (owl_global_get_hascolors(&g)) {
237      int fg, bg;
238      short pair;
239      fg = f->fgcolorbuff[position];
240      bg = f->bgcolorbuff[position];
241      owl_function_debugmsg("waddstr: fg(%i) bg(%i).", fg, bg);
242
243      pair = owl_fmtext_get_colorpair(fg, bg);
244      if (pair != -1) {
245        wattron(w, COLOR_PAIR(pair));
246      }
247    }
248
249    /* add the text */
250    strncpy(tmpbuff, f->textbuff + position, lastsame-position+1);
251    tmpbuff[lastsame-position+1]='\0';
252    waddstr(w, tmpbuff);
253
254    position=lastsame+1;
255  }
256  owl_free(tmpbuff);
257}
258
259
260/* start with line 'aline' (where the first line is 0) and print
261 * 'lines' number of lines into 'out'
262 */
263int owl_fmtext_truncate_lines(owl_fmtext *in, int aline, int lines, owl_fmtext *out)
264{
265  char *ptr1, *ptr2;
266  int i, offset;
267 
268  /* find the starting line */
269  ptr1=in->textbuff;
270  if (aline!=0) {
271    for (i=0; i<aline; i++) {
272      ptr1=strchr(ptr1, '\n');
273      if (!ptr1) return(-1);
274      ptr1++;
275    }
276  }
277  /* ptr1 now holds the starting point */
278
279  /* copy in the next 'lines' lines */
280  if (lines<1) return(-1);
281
282  for (i=0; i<lines; i++) {
283    offset=ptr1-in->textbuff;
284    ptr2=strchr(ptr1, '\n');
285    if (!ptr2) {
286      _owl_fmtext_append_fmtext(out, in, offset, (in->textlen)-1);
287      return(-1);
288    }
289    _owl_fmtext_append_fmtext(out, in, offset, (ptr2-ptr1)+offset);
290    ptr1=ptr2+1;
291  }
292  return(0);
293}
294
295/* Truncate the message so that each line begins at column 'acol' and
296 * ends at 'bcol' or sooner.  The first column is number 0.  The new
297 * message is placed in 'out'.  The message is * expected to end in a
298 * new line for now
299 */
300void owl_fmtext_truncate_cols(owl_fmtext *in, int acol, int bcol, owl_fmtext *out)
301{
302  char *ptr1, *ptr2, *last;
303  int len, offset;
304
305  last=in->textbuff+in->textlen-1;
306  ptr1=in->textbuff;
307  while (ptr1<=last) {
308    ptr2=strchr(ptr1, '\n');
309    if (!ptr2) {
310      /* but this shouldn't happen if we end in a \n */
311      break;
312    }
313   
314    if (ptr2==ptr1) {
315      owl_fmtext_append_normal(out, "\n");
316      ptr1++;
317      continue;
318    }
319
320    /* we need to check that we won't run over here */
321    len=bcol-acol;
322    if (len > (ptr2-(ptr1+acol))) {
323      /* the whole line fits with room to spare, don't take a full 'len' */
324      len=ptr2-(ptr1+acol);
325    }
326    if (len>last-ptr1) {
327      /* the whole rest of the text fits with room to spare, adjust for it */
328      len-=(last-ptr1);
329    }
330    if (len<=0) {
331      /* saftey check */
332      owl_fmtext_append_normal(out, "\n");
333      ptr1=ptr2+1;
334      continue;
335    }
336
337    offset=ptr1-in->textbuff;
338    _owl_fmtext_append_fmtext(out, in, offset+acol, offset+acol+len);
339
340    ptr1=ptr2+1;
341  }
342}
343
344/* Return the number of lines in 'f' */
345int owl_fmtext_num_lines(owl_fmtext *f)
346{
347  int lines, i;
348
349  if (f->textlen==0) return(0);
350 
351  lines=0;
352  for (i=0; i<f->textlen; i++) {
353    if (f->textbuff[i]=='\n') lines++;
354  }
355
356  /* if the last char wasn't a \n there's one more line */
357  if (f->textbuff[i-1]!='\n') lines++;
358
359  return(lines);
360}
361
362char *owl_fmtext_get_text(owl_fmtext *f)
363{
364  return(f->textbuff);
365}
366
367/* set the charater at 'index' to be 'char'.  If index is out of
368 * bounds don't do anything */
369void owl_fmtext_set_char(owl_fmtext *f, int index, int ch)
370{
371  if ((index < 0) || (index > f->textlen-1)) return;
372  f->textbuff[index]=ch;
373}
374
375/* Make a copy of the fmtext 'src' into 'dst' */
376void owl_fmtext_copy(owl_fmtext *dst, owl_fmtext *src)
377{
378  int mallocsize;
379
380  if (src->textlen==0) {
381    mallocsize=5;
382  } else {
383    mallocsize=src->textlen+2;
384  }
385  dst->textlen=src->textlen;
386  dst->textbuff=owl_malloc(mallocsize);
387  dst->fmbuff=owl_malloc(mallocsize);
388  dst->fgcolorbuff=owl_malloc(mallocsize);
389  dst->bgcolorbuff=owl_malloc(mallocsize);
390  memcpy(dst->textbuff, src->textbuff, src->textlen+1);
391  memcpy(dst->fmbuff, src->fmbuff, src->textlen);
392  memcpy(dst->fgcolorbuff, src->fgcolorbuff, src->textlen);
393  memcpy(dst->bgcolorbuff, src->bgcolorbuff, src->textlen);
394}
395
396/* highlight all instances of "string".  Return the number of
397 * instances found.  This is a case insensitive search.
398 */
399int owl_fmtext_search_and_highlight(owl_fmtext *f, char *string)
400{
401
402  int found, len;
403  char *ptr1, *ptr2;
404
405  len=strlen(string);
406  found=0;
407  ptr1=f->textbuff;
408  while (ptr1-f->textbuff <= f->textlen) {
409    ptr2=stristr(ptr1, string);
410    if (!ptr2) return(found);
411
412    found++;
413    _owl_fmtext_add_attr(f, OWL_FMTEXT_ATTR_REVERSE,
414                         ptr2 - f->textbuff,
415                         ptr2 - f->textbuff + len - 1);
416
417    ptr1=ptr2+len;
418  }
419  return(found);
420}
421
422/* return 1 if the string is found, 0 if not.  This is a case
423 *  insensitive search.
424 */
425int owl_fmtext_search(owl_fmtext *f, char *string)
426{
427
428  if (stristr(f->textbuff, string)) return(1);
429  return(0);
430}
431
432
433/* Append the text 'text' to 'f' and interpret the zephyr style
434 * formatting syntax to set appropriate attributes.
435 */
436void owl_fmtext_append_ztext(owl_fmtext *f, char *text)
437{
438  int stacksize, curattrs, curcolor;
439  char *ptr, *txtptr, *buff, *tmpptr;
440  int attrstack[32], chrstack[32];
441
442  curattrs=OWL_FMTEXT_ATTR_NONE;
443  curcolor=OWL_COLOR_DEFAULT;
444  stacksize=0;
445  txtptr=text;
446  while (1) {
447    ptr=strpbrk(txtptr, "@{[<()>]}");
448    if (!ptr) {
449      /* add all the rest of the text and exit */
450      owl_fmtext_append_attr(f, txtptr, curattrs, curcolor, OWL_COLOR_DEFAULT);
451      return;
452    } else if (ptr[0]=='@') {
453      /* add the text up to this point then deal with the stack */
454      buff=owl_malloc(ptr-txtptr+20);
455      strncpy(buff, txtptr, ptr-txtptr);
456      buff[ptr-txtptr]='\0';
457      owl_fmtext_append_attr(f, buff, curattrs, curcolor, OWL_COLOR_DEFAULT);
458      owl_free(buff);
459
460      /* update pointer to point at the @ */
461      txtptr=ptr;
462
463      /* now the stack */
464
465      /* if we've hit our max stack depth, print the @ and move on */
466      if (stacksize==32) {
467        owl_fmtext_append_attr(f, "@", curattrs, curcolor, OWL_COLOR_DEFAULT);
468        txtptr++;
469        continue;
470      }
471
472      /* if it's an @@, print an @ and continue */
473      if (txtptr[1]=='@') {
474        owl_fmtext_append_attr(f, "@", curattrs, curcolor, OWL_COLOR_DEFAULT);
475        txtptr+=2;
476        continue;
477      }
478       
479      /* if there's no opener, print the @ and continue */
480      tmpptr=strpbrk(txtptr, "(<[{ ");
481      if (!tmpptr || tmpptr[0]==' ') {
482        owl_fmtext_append_attr(f, "@", curattrs, curcolor, OWL_COLOR_DEFAULT);
483        txtptr++;
484        continue;
485      }
486
487      /* check what command we've got, push it on the stack, start
488         using it, and continue ... unless it's a color command */
489      buff=owl_malloc(tmpptr-ptr+20);
490      strncpy(buff, ptr, tmpptr-ptr);
491      buff[tmpptr-ptr]='\0';
492      if (!strcasecmp(buff, "@bold")) {
493        attrstack[stacksize]=OWL_FMTEXT_ATTR_BOLD;
494        chrstack[stacksize]=tmpptr[0];
495        stacksize++;
496        curattrs|=OWL_FMTEXT_ATTR_BOLD;
497        txtptr+=6;
498        owl_free(buff);
499        continue;
500      } else if (!strcasecmp(buff, "@b")) {
501        attrstack[stacksize]=OWL_FMTEXT_ATTR_BOLD;
502        chrstack[stacksize]=tmpptr[0];
503        stacksize++;
504        curattrs|=OWL_FMTEXT_ATTR_BOLD;
505        txtptr+=3;
506        owl_free(buff);
507        continue;
508      } else if (!strcasecmp(buff, "@i")) {
509        attrstack[stacksize]=OWL_FMTEXT_ATTR_UNDERLINE;
510        chrstack[stacksize]=tmpptr[0];
511        stacksize++;
512        curattrs|=OWL_FMTEXT_ATTR_UNDERLINE;
513        txtptr+=3;
514        owl_free(buff);
515        continue;
516      } else if (!strcasecmp(buff, "@italic")) {
517        attrstack[stacksize]=OWL_FMTEXT_ATTR_UNDERLINE;
518        chrstack[stacksize]=tmpptr[0];
519        stacksize++;
520        curattrs|=OWL_FMTEXT_ATTR_UNDERLINE;
521        txtptr+=8;
522        owl_free(buff);
523        continue;
524
525        /* if it's a color read the color, set the current color and
526           continue */
527      } else if (!strcasecmp(buff, "@color") 
528                 && owl_global_get_hascolors(&g)
529                 && owl_global_is_colorztext(&g)) {
530        owl_free(buff);
531        txtptr+=7;
532        tmpptr=strpbrk(txtptr, "@{[<()>]}");
533        if (tmpptr &&
534            ((txtptr[-1]=='(' && tmpptr[0]==')') ||
535             (txtptr[-1]=='<' && tmpptr[0]=='>') ||
536             (txtptr[-1]=='[' && tmpptr[0]==']') ||
537             (txtptr[-1]=='{' && tmpptr[0]=='}'))) {
538
539          /* grab the color name */
540          buff=owl_malloc(tmpptr-txtptr+20);
541          strncpy(buff, txtptr, tmpptr-txtptr);
542          buff[tmpptr-txtptr]='\0';
543
544          /* set it as the current color */
545          curcolor=owl_util_string_to_color(buff);
546          if (curcolor==-1) curcolor=OWL_COLOR_DEFAULT;
547          owl_free(buff);
548          txtptr=tmpptr+1;
549          continue;
550
551        } else {
552
553        }
554
555      } else {
556        /* if we didn't understand it, we'll print it.  This is different from zwgc
557         * but zwgc seems to be smarter about some screw cases than I am
558         */
559        owl_fmtext_append_attr(f, "@", curattrs, curcolor, OWL_COLOR_DEFAULT);
560        txtptr++;
561        continue;
562      }
563
564    } else if (ptr[0]=='}' || ptr[0]==']' || ptr[0]==')' || ptr[0]=='>') {
565      /* add the text up to this point first */
566      buff=owl_malloc(ptr-txtptr+20);
567      strncpy(buff, txtptr, ptr-txtptr);
568      buff[ptr-txtptr]='\0';
569      owl_fmtext_append_attr(f, buff, curattrs, curcolor, OWL_COLOR_DEFAULT);
570      owl_free(buff);
571
572      /* now deal with the closer */
573      txtptr=ptr;
574
575      /* first, if the stack is empty we must bail (just print and go) */
576      if (stacksize==0) {
577        buff=owl_malloc(5);
578        buff[0]=ptr[0];
579        buff[1]='\0';
580        owl_fmtext_append_attr(f, buff, curattrs, curcolor, OWL_COLOR_DEFAULT);
581        owl_free(buff);
582        txtptr++;
583        continue;
584      }
585
586      /* if the closing char is what's on the stack, turn off the
587         attribue and pop the stack */
588      if ((ptr[0]==')' && chrstack[stacksize-1]=='(') ||
589          (ptr[0]=='>' && chrstack[stacksize-1]=='<') ||
590          (ptr[0]==']' && chrstack[stacksize-1]=='[') ||
591          (ptr[0]=='}' && chrstack[stacksize-1]=='{')) {
592        int i;
593        stacksize--;
594        curattrs=OWL_FMTEXT_ATTR_NONE;
595        for (i=0; i<stacksize; i++) {
596          curattrs|=attrstack[i];
597        }
598        txtptr+=1;
599        continue;
600      } else {
601        /* otherwise print and continue */
602        buff=owl_malloc(5);
603        buff[0]=ptr[0];
604        buff[1]='\0';
605        owl_fmtext_append_attr(f, buff, curattrs, curcolor, OWL_COLOR_DEFAULT);
606        owl_free(buff);
607        txtptr++;
608        continue;
609      }
610    } else {
611      /* we've found an unattached opener, print everything and move on */
612      buff=owl_malloc(ptr-txtptr+20);
613      strncpy(buff, txtptr, ptr-txtptr+1);
614      buff[ptr-txtptr+1]='\0';
615      owl_fmtext_append_attr(f, buff, curattrs, curcolor, OWL_COLOR_DEFAULT);
616      owl_free(buff);
617      txtptr=ptr+1;
618      continue;
619    }
620  }
621}
622
623/* requires that the list values are strings or NULL.
624 * joins the elements together with join_with.
625 * If format_fn is specified, passes it the list element value
626 * and it will return a string which this needs to free. */
627void owl_fmtext_append_list(owl_fmtext *f, owl_list *l, char *join_with, char *(format_fn)(void*))
628{
629  int i, size;
630  void *elem;
631  char *text;
632
633  size = owl_list_get_size(l);
634  for (i=0; i<size; i++) {
635    elem = (char*)owl_list_get_element(l,i);
636    if (elem && format_fn) {
637      text = format_fn(elem);
638      if (text) {
639        owl_fmtext_append_normal(f, text);
640        owl_free(text);
641      }
642    } else if (elem) {
643      owl_fmtext_append_normal(f, elem);
644    }
645    if ((i < size-1) && join_with) {
646      owl_fmtext_append_normal(f, join_with);
647    }
648  }
649}
650
651/* Free all memory allocated by the object */
652void owl_fmtext_free(owl_fmtext *f)
653{
654  if (f->textbuff) owl_free(f->textbuff);
655  if (f->fmbuff) owl_free(f->fmbuff);
656  if (f->fgcolorbuff) owl_free(f->fgcolorbuff);
657  if (f->bgcolorbuff) owl_free(f->bgcolorbuff);
658}
659
660/*** Color Pair manager ***/
661void owl_fmtext_init_colorpair_mgr(owl_colorpair_mgr *cpmgr)
662{
663  // This could be a bitarray if we wanted to save memory.
664  int i, j, colors;
665  cpmgr->next = COLORS;
666
667  colors = COLORS + 1; // 1 to account for "default".
668  cpmgr->pairs = owl_malloc(colors * sizeof(int*));
669  for(i = 0; i < colors; i++) {
670    // Because we're going to have a pair set for any fg and the
671    // default bg, we don't need to account for default here.
672    cpmgr->pairs[i] = owl_malloc(COLORS * sizeof(int));
673    for(j = 0; j < COLORS; j++) {
674      cpmgr->pairs[i][j] = -1;
675    }
676  }
677}
678
679/* Reset used list */
680void owl_fmtext_reset_colorpairs()
681{
682  int i, j, colors;
683  owl_colorpair_mgr *cpmgr = owl_global_get_colorpair_mgr(&g);
684  cpmgr->next = COLORS;
685
686  colors = COLORS + 1; // 1 to account for "default".
687  for(i = 0; i < colors; i++) {
688    for(j = 0; j < COLORS; j++) {
689      cpmgr->pairs[i][j] = -1;
690    }
691  }
692}
693
694/* Assign pairs by request */
695short owl_fmtext_get_colorpair(int fg, int bg)
696{
697  owl_colorpair_mgr *cpmgr;
698  short pair, i, default_bg;
699
700#ifdef HAVE_USE_DEFAULT_COLORS
701  if (fg == OWL_COLOR_DEFAULT) fg = -1;
702  default_bg = OWL_COLOR_DEFAULT;
703#else
704  if (fg == OWL_COLOR_DEFAULT) fg = 0;
705  if (bg == OWL_COLOR_DEFAULT) bg = 0;
706  default_bg = COLOR_BLACK;
707#endif
708
709  if (bg == default_bg) {
710    // default bg -> use color pairs initialized by owl.c
711    pair = fg;
712  } else {
713    // looking for a pair we already set up for this draw.
714    cpmgr = owl_global_get_colorpair_mgr(&g);
715    pair = cpmgr->pairs[fg+1][bg];
716    if (!(pair != -1 && pair < cpmgr->next)) {
717      // If we didn't find a pair, search for a free one to assign.
718      // Skip the first COLORS, since they're static.
719      // If we ever get 256 color curses, this will need more thought.
720      pair = (cpmgr->next < COLOR_PAIRS) ? cpmgr->next : -1;
721      if (pair != -1) {
722        // We found a free pair, initialize it.
723        init_pair(pair, fg, bg);
724        cpmgr->pairs[fg+1][bg] = pair;
725        cpmgr->next++;
726      } else {
727        // We still don't have a pair, drop the background color. Too bad.
728        pair = fg;
729      }
730    }
731  }
732  return pair;
733}
Note: See TracBrowser for help on using the repository browser.