source: fmtext.c @ e98a9f9

barnowl_perlaimdebianrelease-1.10release-1.4release-1.5release-1.6release-1.7release-1.8release-1.9
Last change on this file since e98a9f9 was 801b7ac, checked in by Alejandro R. Sedeño <asedeno@mit.edu>, 17 years ago
functions.c: tweak owl_function_calculate_topmsg_normal to not suck as much. This resolves the delay in jumping from the first message to the last message. fmtext.c: get rid of a debug message and an unused variable. view.c: Convert another linear search to binary search.
  • Property mode set to 100644
File size: 20.1 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
242      pair = owl_fmtext_get_colorpair(fg, bg);
243      if (pair != -1) {
244        wattron(w, COLOR_PAIR(pair));
245      }
246    }
247
248    /* add the text */
249    strncpy(tmpbuff, f->textbuff + position, lastsame-position+1);
250    tmpbuff[lastsame-position+1]='\0';
251    waddstr(w, tmpbuff);
252
253    position=lastsame+1;
254  }
255  owl_free(tmpbuff);
256}
257
258
259/* start with line 'aline' (where the first line is 0) and print
260 * 'lines' number of lines into 'out'
261 */
262int owl_fmtext_truncate_lines(owl_fmtext *in, int aline, int lines, owl_fmtext *out)
263{
264  char *ptr1, *ptr2;
265  int i, offset;
266 
267  /* find the starting line */
268  ptr1=in->textbuff;
269  if (aline!=0) {
270    for (i=0; i<aline; i++) {
271      ptr1=strchr(ptr1, '\n');
272      if (!ptr1) return(-1);
273      ptr1++;
274    }
275  }
276  /* ptr1 now holds the starting point */
277
278  /* copy in the next 'lines' lines */
279  if (lines<1) return(-1);
280
281  for (i=0; i<lines; i++) {
282    offset=ptr1-in->textbuff;
283    ptr2=strchr(ptr1, '\n');
284    if (!ptr2) {
285      _owl_fmtext_append_fmtext(out, in, offset, (in->textlen)-1);
286      return(-1);
287    }
288    _owl_fmtext_append_fmtext(out, in, offset, (ptr2-ptr1)+offset);
289    ptr1=ptr2+1;
290  }
291  return(0);
292}
293
294/* Truncate the message so that each line begins at column 'acol' and
295 * ends at 'bcol' or sooner.  The first column is number 0.  The new
296 * message is placed in 'out'.  The message is * expected to end in a
297 * new line for now
298 */
299void owl_fmtext_truncate_cols(owl_fmtext *in, int acol, int bcol, owl_fmtext *out)
300{
301  char *ptr1, *ptr2, *last;
302  int len, offset;
303
304  last=in->textbuff+in->textlen-1;
305  ptr1=in->textbuff;
306  while (ptr1<=last) {
307    ptr2=strchr(ptr1, '\n');
308    if (!ptr2) {
309      /* but this shouldn't happen if we end in a \n */
310      break;
311    }
312   
313    if (ptr2==ptr1) {
314      owl_fmtext_append_normal(out, "\n");
315      ptr1++;
316      continue;
317    }
318
319    /* we need to check that we won't run over here */
320    len=bcol-acol;
321    if (len > (ptr2-(ptr1+acol))) {
322      /* the whole line fits with room to spare, don't take a full 'len' */
323      len=ptr2-(ptr1+acol);
324    }
325    if (len>last-ptr1) {
326      /* the whole rest of the text fits with room to spare, adjust for it */
327      len-=(last-ptr1);
328    }
329    if (len<=0) {
330      /* saftey check */
331      owl_fmtext_append_normal(out, "\n");
332      ptr1=ptr2+1;
333      continue;
334    }
335
336    offset=ptr1-in->textbuff;
337    _owl_fmtext_append_fmtext(out, in, offset+acol, offset+acol+len);
338
339    ptr1=ptr2+1;
340  }
341}
342
343/* Return the number of lines in 'f' */
344int owl_fmtext_num_lines(owl_fmtext *f)
345{
346  int lines, i;
347
348  if (f->textlen==0) return(0);
349 
350  lines=0;
351  for (i=0; i<f->textlen; i++) {
352    if (f->textbuff[i]=='\n') lines++;
353  }
354
355  /* if the last char wasn't a \n there's one more line */
356  if (f->textbuff[i-1]!='\n') lines++;
357
358  return(lines);
359}
360
361char *owl_fmtext_get_text(owl_fmtext *f)
362{
363  return(f->textbuff);
364}
365
366/* set the charater at 'index' to be 'char'.  If index is out of
367 * bounds don't do anything */
368void owl_fmtext_set_char(owl_fmtext *f, int index, int ch)
369{
370  if ((index < 0) || (index > f->textlen-1)) return;
371  f->textbuff[index]=ch;
372}
373
374/* Make a copy of the fmtext 'src' into 'dst' */
375void owl_fmtext_copy(owl_fmtext *dst, owl_fmtext *src)
376{
377  int mallocsize;
378
379  if (src->textlen==0) {
380    mallocsize=5;
381  } else {
382    mallocsize=src->textlen+2;
383  }
384  dst->textlen=src->textlen;
385  dst->textbuff=owl_malloc(mallocsize);
386  dst->fmbuff=owl_malloc(mallocsize);
387  dst->fgcolorbuff=owl_malloc(mallocsize);
388  dst->bgcolorbuff=owl_malloc(mallocsize);
389  memcpy(dst->textbuff, src->textbuff, src->textlen+1);
390  memcpy(dst->fmbuff, src->fmbuff, src->textlen);
391  memcpy(dst->fgcolorbuff, src->fgcolorbuff, src->textlen);
392  memcpy(dst->bgcolorbuff, src->bgcolorbuff, src->textlen);
393}
394
395/* highlight all instances of "string".  Return the number of
396 * instances found.  This is a case insensitive search.
397 */
398int owl_fmtext_search_and_highlight(owl_fmtext *f, char *string)
399{
400
401  int found, len;
402  char *ptr1, *ptr2;
403
404  len=strlen(string);
405  found=0;
406  ptr1=f->textbuff;
407  while (ptr1-f->textbuff <= f->textlen) {
408    ptr2=stristr(ptr1, string);
409    if (!ptr2) return(found);
410
411    found++;
412    _owl_fmtext_add_attr(f, OWL_FMTEXT_ATTR_REVERSE,
413                         ptr2 - f->textbuff,
414                         ptr2 - f->textbuff + len - 1);
415
416    ptr1=ptr2+len;
417  }
418  return(found);
419}
420
421/* return 1 if the string is found, 0 if not.  This is a case
422 *  insensitive search.
423 */
424int owl_fmtext_search(owl_fmtext *f, char *string)
425{
426
427  if (stristr(f->textbuff, string)) return(1);
428  return(0);
429}
430
431
432/* Append the text 'text' to 'f' and interpret the zephyr style
433 * formatting syntax to set appropriate attributes.
434 */
435void owl_fmtext_append_ztext(owl_fmtext *f, char *text)
436{
437  int stacksize, curattrs, curcolor;
438  char *ptr, *txtptr, *buff, *tmpptr;
439  int attrstack[32], chrstack[32];
440
441  curattrs=OWL_FMTEXT_ATTR_NONE;
442  curcolor=OWL_COLOR_DEFAULT;
443  stacksize=0;
444  txtptr=text;
445  while (1) {
446    ptr=strpbrk(txtptr, "@{[<()>]}");
447    if (!ptr) {
448      /* add all the rest of the text and exit */
449      owl_fmtext_append_attr(f, txtptr, curattrs, curcolor, OWL_COLOR_DEFAULT);
450      return;
451    } else if (ptr[0]=='@') {
452      /* add the text up to this point then deal with the stack */
453      buff=owl_malloc(ptr-txtptr+20);
454      strncpy(buff, txtptr, ptr-txtptr);
455      buff[ptr-txtptr]='\0';
456      owl_fmtext_append_attr(f, buff, curattrs, curcolor, OWL_COLOR_DEFAULT);
457      owl_free(buff);
458
459      /* update pointer to point at the @ */
460      txtptr=ptr;
461
462      /* now the stack */
463
464      /* if we've hit our max stack depth, print the @ and move on */
465      if (stacksize==32) {
466        owl_fmtext_append_attr(f, "@", curattrs, curcolor, OWL_COLOR_DEFAULT);
467        txtptr++;
468        continue;
469      }
470
471      /* if it's an @@, print an @ and continue */
472      if (txtptr[1]=='@') {
473        owl_fmtext_append_attr(f, "@", curattrs, curcolor, OWL_COLOR_DEFAULT);
474        txtptr+=2;
475        continue;
476      }
477       
478      /* if there's no opener, print the @ and continue */
479      tmpptr=strpbrk(txtptr, "(<[{ ");
480      if (!tmpptr || tmpptr[0]==' ') {
481        owl_fmtext_append_attr(f, "@", curattrs, curcolor, OWL_COLOR_DEFAULT);
482        txtptr++;
483        continue;
484      }
485
486      /* check what command we've got, push it on the stack, start
487         using it, and continue ... unless it's a color command */
488      buff=owl_malloc(tmpptr-ptr+20);
489      strncpy(buff, ptr, tmpptr-ptr);
490      buff[tmpptr-ptr]='\0';
491      if (!strcasecmp(buff, "@bold")) {
492        attrstack[stacksize]=OWL_FMTEXT_ATTR_BOLD;
493        chrstack[stacksize]=tmpptr[0];
494        stacksize++;
495        curattrs|=OWL_FMTEXT_ATTR_BOLD;
496        txtptr+=6;
497        owl_free(buff);
498        continue;
499      } else if (!strcasecmp(buff, "@b")) {
500        attrstack[stacksize]=OWL_FMTEXT_ATTR_BOLD;
501        chrstack[stacksize]=tmpptr[0];
502        stacksize++;
503        curattrs|=OWL_FMTEXT_ATTR_BOLD;
504        txtptr+=3;
505        owl_free(buff);
506        continue;
507      } else if (!strcasecmp(buff, "@i")) {
508        attrstack[stacksize]=OWL_FMTEXT_ATTR_UNDERLINE;
509        chrstack[stacksize]=tmpptr[0];
510        stacksize++;
511        curattrs|=OWL_FMTEXT_ATTR_UNDERLINE;
512        txtptr+=3;
513        owl_free(buff);
514        continue;
515      } else if (!strcasecmp(buff, "@italic")) {
516        attrstack[stacksize]=OWL_FMTEXT_ATTR_UNDERLINE;
517        chrstack[stacksize]=tmpptr[0];
518        stacksize++;
519        curattrs|=OWL_FMTEXT_ATTR_UNDERLINE;
520        txtptr+=8;
521        owl_free(buff);
522        continue;
523
524        /* if it's a color read the color, set the current color and
525           continue */
526      } else if (!strcasecmp(buff, "@color") 
527                 && owl_global_get_hascolors(&g)
528                 && owl_global_is_colorztext(&g)) {
529        owl_free(buff);
530        txtptr+=7;
531        tmpptr=strpbrk(txtptr, "@{[<()>]}");
532        if (tmpptr &&
533            ((txtptr[-1]=='(' && tmpptr[0]==')') ||
534             (txtptr[-1]=='<' && tmpptr[0]=='>') ||
535             (txtptr[-1]=='[' && tmpptr[0]==']') ||
536             (txtptr[-1]=='{' && tmpptr[0]=='}'))) {
537
538          /* grab the color name */
539          buff=owl_malloc(tmpptr-txtptr+20);
540          strncpy(buff, txtptr, tmpptr-txtptr);
541          buff[tmpptr-txtptr]='\0';
542
543          /* set it as the current color */
544          curcolor=owl_util_string_to_color(buff);
545          if (curcolor==-1) curcolor=OWL_COLOR_DEFAULT;
546          owl_free(buff);
547          txtptr=tmpptr+1;
548          continue;
549
550        } else {
551
552        }
553
554      } else {
555        /* if we didn't understand it, we'll print it.  This is different from zwgc
556         * but zwgc seems to be smarter about some screw cases than I am
557         */
558        owl_fmtext_append_attr(f, "@", curattrs, curcolor, OWL_COLOR_DEFAULT);
559        txtptr++;
560        continue;
561      }
562
563    } else if (ptr[0]=='}' || ptr[0]==']' || ptr[0]==')' || ptr[0]=='>') {
564      /* add the text up to this point first */
565      buff=owl_malloc(ptr-txtptr+20);
566      strncpy(buff, txtptr, ptr-txtptr);
567      buff[ptr-txtptr]='\0';
568      owl_fmtext_append_attr(f, buff, curattrs, curcolor, OWL_COLOR_DEFAULT);
569      owl_free(buff);
570
571      /* now deal with the closer */
572      txtptr=ptr;
573
574      /* first, if the stack is empty we must bail (just print and go) */
575      if (stacksize==0) {
576        buff=owl_malloc(5);
577        buff[0]=ptr[0];
578        buff[1]='\0';
579        owl_fmtext_append_attr(f, buff, curattrs, curcolor, OWL_COLOR_DEFAULT);
580        owl_free(buff);
581        txtptr++;
582        continue;
583      }
584
585      /* if the closing char is what's on the stack, turn off the
586         attribue and pop the stack */
587      if ((ptr[0]==')' && chrstack[stacksize-1]=='(') ||
588          (ptr[0]=='>' && chrstack[stacksize-1]=='<') ||
589          (ptr[0]==']' && chrstack[stacksize-1]=='[') ||
590          (ptr[0]=='}' && chrstack[stacksize-1]=='{')) {
591        int i;
592        stacksize--;
593        curattrs=OWL_FMTEXT_ATTR_NONE;
594        for (i=0; i<stacksize; i++) {
595          curattrs|=attrstack[i];
596        }
597        txtptr+=1;
598        continue;
599      } else {
600        /* otherwise print and continue */
601        buff=owl_malloc(5);
602        buff[0]=ptr[0];
603        buff[1]='\0';
604        owl_fmtext_append_attr(f, buff, curattrs, curcolor, OWL_COLOR_DEFAULT);
605        owl_free(buff);
606        txtptr++;
607        continue;
608      }
609    } else {
610      /* we've found an unattached opener, print everything and move on */
611      buff=owl_malloc(ptr-txtptr+20);
612      strncpy(buff, txtptr, ptr-txtptr+1);
613      buff[ptr-txtptr+1]='\0';
614      owl_fmtext_append_attr(f, buff, curattrs, curcolor, OWL_COLOR_DEFAULT);
615      owl_free(buff);
616      txtptr=ptr+1;
617      continue;
618    }
619  }
620}
621
622/* requires that the list values are strings or NULL.
623 * joins the elements together with join_with.
624 * If format_fn is specified, passes it the list element value
625 * and it will return a string which this needs to free. */
626void owl_fmtext_append_list(owl_fmtext *f, owl_list *l, char *join_with, char *(format_fn)(void*))
627{
628  int i, size;
629  void *elem;
630  char *text;
631
632  size = owl_list_get_size(l);
633  for (i=0; i<size; i++) {
634    elem = (char*)owl_list_get_element(l,i);
635    if (elem && format_fn) {
636      text = format_fn(elem);
637      if (text) {
638        owl_fmtext_append_normal(f, text);
639        owl_free(text);
640      }
641    } else if (elem) {
642      owl_fmtext_append_normal(f, elem);
643    }
644    if ((i < size-1) && join_with) {
645      owl_fmtext_append_normal(f, join_with);
646    }
647  }
648}
649
650/* Free all memory allocated by the object */
651void owl_fmtext_free(owl_fmtext *f)
652{
653  if (f->textbuff) owl_free(f->textbuff);
654  if (f->fmbuff) owl_free(f->fmbuff);
655  if (f->fgcolorbuff) owl_free(f->fgcolorbuff);
656  if (f->bgcolorbuff) owl_free(f->bgcolorbuff);
657}
658
659/*** Color Pair manager ***/
660void owl_fmtext_init_colorpair_mgr(owl_colorpair_mgr *cpmgr)
661{
662  // This could be a bitarray if we wanted to save memory.
663  int i, j, colors;
664  cpmgr->next = COLORS;
665
666  colors = COLORS + 1; // 1 to account for "default".
667  cpmgr->pairs = owl_malloc(colors * sizeof(int*));
668  for(i = 0; i < colors; i++) {
669    // Because we're going to have a pair set for any fg and the
670    // default bg, we don't need to account for default here.
671    cpmgr->pairs[i] = owl_malloc(COLORS * sizeof(int));
672    for(j = 0; j < COLORS; j++) {
673      cpmgr->pairs[i][j] = -1;
674    }
675  }
676}
677
678/* Reset used list */
679void owl_fmtext_reset_colorpairs()
680{
681  int i, j, colors;
682  owl_colorpair_mgr *cpmgr = owl_global_get_colorpair_mgr(&g);
683  cpmgr->next = COLORS;
684
685  colors = COLORS + 1; // 1 to account for "default".
686  for(i = 0; i < colors; i++) {
687    for(j = 0; j < COLORS; j++) {
688      cpmgr->pairs[i][j] = -1;
689    }
690  }
691}
692
693/* Assign pairs by request */
694short owl_fmtext_get_colorpair(int fg, int bg)
695{
696  owl_colorpair_mgr *cpmgr;
697  short pair, default_bg;
698
699#ifdef HAVE_USE_DEFAULT_COLORS
700  if (fg == OWL_COLOR_DEFAULT) fg = -1;
701  default_bg = OWL_COLOR_DEFAULT;
702#else
703  if (fg == OWL_COLOR_DEFAULT) fg = 0;
704  if (bg == OWL_COLOR_DEFAULT) bg = 0;
705  default_bg = COLOR_BLACK;
706#endif
707
708  if (bg == default_bg) {
709    // default bg -> use color pairs initialized by owl.c
710    pair = fg;
711  } else {
712    // looking for a pair we already set up for this draw.
713    cpmgr = owl_global_get_colorpair_mgr(&g);
714    pair = cpmgr->pairs[fg+1][bg];
715    if (!(pair != -1 && pair < cpmgr->next)) {
716      // If we didn't find a pair, search for a free one to assign.
717      // Skip the first COLORS, since they're static.
718      // If we ever get 256 color curses, this will need more thought.
719      pair = (cpmgr->next < COLOR_PAIRS) ? cpmgr->next : -1;
720      if (pair != -1) {
721        // We found a free pair, initialize it.
722        init_pair(pair, fg, bg);
723        cpmgr->pairs[fg+1][bg] = pair;
724        cpmgr->next++;
725      } else {
726        // We still don't have a pair, drop the background color. Too bad.
727        pair = fg;
728      }
729    }
730  }
731  return pair;
732}
Note: See TracBrowser for help on using the repository browser.