source: fmtext.c @ 919535f

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