source: fmtext.c @ 1aee7d9

barnowl_perlaimdebianowlrelease-1.4release-1.5release-1.6release-1.7release-1.8release-1.9
Last change on this file since 1aee7d9 was 1aee7d9, checked in by Erik Nygren <nygren@mit.edu>, 18 years ago
* Added RCS Id strings to all files. * 'show keymaps' shows details of all keymaps after summary list.
  • Property mode set to 100644
File size: 12.6 KB
Line 
1#include "owl.h"
2#include <stdlib.h>
3#include <string.h>
4
5static const char fileIdent[] = "$Id$";
6
7void owl_fmtext_init_null(owl_fmtext *f) {
8  f->textlen=0;
9  f->textbuff=owl_strdup("");
10  f->fmbuff=owl_malloc(5);
11  f->colorbuff=owl_malloc(5);
12  f->fmbuff[0]=OWL_FMTEXT_ATTR_NONE;
13  f->colorbuff[0]=OWL_COLOR_DEFAULT;
14}
15
16
17void _owl_fmtext_set_attr(owl_fmtext *f, int attr, int first, int last) {
18  int i;
19  for (i=first; i<=last; i++) {
20    f->fmbuff[i]=(unsigned char) attr;
21  }
22}
23
24void _owl_fmtext_set_color(owl_fmtext *f, int color, int first, int last) {
25  int i;
26  for (i=first; i<=last; i++) {
27    f->colorbuff[i]=(unsigned char) color;
28  }
29}
30
31
32void owl_fmtext_append_attr(owl_fmtext *f, char *text, int attr, int color) {
33  int newlen;
34
35  newlen=strlen(f->textbuff)+strlen(text);
36  f->textbuff=owl_realloc(f->textbuff, newlen+2);
37  f->fmbuff=owl_realloc(f->fmbuff, newlen+2);
38  f->colorbuff=owl_realloc(f->colorbuff, newlen+2);
39
40  strcat(f->textbuff, text);
41  _owl_fmtext_set_attr(f, attr, f->textlen, newlen);
42  _owl_fmtext_set_color(f, color, f->textlen, newlen);
43  f->textlen=newlen;
44}
45
46
47void owl_fmtext_append_normal(owl_fmtext *f, char *text) {
48  owl_fmtext_append_attr(f, text, OWL_FMTEXT_ATTR_NONE, OWL_COLOR_DEFAULT);
49}
50
51void owl_fmtext_append_normal_color(owl_fmtext *f, char *text, int color) {
52  owl_fmtext_append_attr(f, text, OWL_FMTEXT_ATTR_NONE, color);
53}
54
55
56void owl_fmtext_append_bold(owl_fmtext *f, char *text) {
57  owl_fmtext_append_attr(f, text, OWL_FMTEXT_ATTR_BOLD, OWL_COLOR_DEFAULT);
58}
59
60
61void owl_fmtext_append_reverse(owl_fmtext *f, char *text) {
62  owl_fmtext_append_attr(f, text, OWL_FMTEXT_ATTR_REVERSE, OWL_COLOR_DEFAULT);
63}
64
65
66void owl_fmtext_append_reversebold(owl_fmtext *f, char *text) {
67  owl_fmtext_append_attr(f, text, OWL_FMTEXT_ATTR_REVERSE | OWL_FMTEXT_ATTR_BOLD, OWL_COLOR_DEFAULT);
68}
69
70
71void owl_fmtext_addattr(owl_fmtext *f, int attr) {
72  /* add the attribute to all text */
73  int i, j;
74
75  j=f->textlen;
76  for (i=0; i<j; i++) {
77    f->fmbuff[i] |= attr;
78  }
79}
80
81void owl_fmtext_colorize(owl_fmtext *f, int color) {
82  /* everywhere the color is OWL_COLOR_DEFAULT, change it to be 'color' */
83  int i, j;
84
85  j=f->textlen;
86  for(i=0; i<j; i++) {
87    if (f->colorbuff[i]==OWL_COLOR_DEFAULT) f->colorbuff[i] = color;
88  }
89}
90
91
92void owl_fmtext_append_ztext(owl_fmtext *f, char *text) {
93  int stacksize, curattrs, curcolor;
94  char *ptr, *txtptr, *buff, *tmpptr;
95  int attrstack[32], chrstack[32];
96
97  curattrs=OWL_FMTEXT_ATTR_NONE;
98  curcolor=OWL_COLOR_DEFAULT;
99  stacksize=0;
100  txtptr=text;
101  while (1) {
102    ptr=strpbrk(txtptr, "@{[<()>]}");
103    if (!ptr) {
104      /* add all the rest of the text and exit */
105      owl_fmtext_append_attr(f, txtptr, curattrs, curcolor);
106      return;
107    } else if (ptr[0]=='@') {
108      /* add the text up to this point then deal with the stack */
109      buff=owl_malloc(ptr-txtptr+20);
110      strncpy(buff, txtptr, ptr-txtptr);
111      buff[ptr-txtptr]='\0';
112      owl_fmtext_append_attr(f, buff, curattrs, curcolor);
113      owl_free(buff);
114
115      /* update pointer to point at the @ */
116      txtptr=ptr;
117
118      /* now the stack */
119
120      /* if we've hit our max stack depth, print the @ and move on */
121      if (stacksize==32) {
122        owl_fmtext_append_attr(f, "@", curattrs, curcolor);
123        txtptr++;
124        continue;
125      }
126
127      /* if it's an @@, print an @ and continue */
128      if (txtptr[1]=='@') {
129        owl_fmtext_append_attr(f, "@", curattrs, curcolor);
130        txtptr+=2;
131        continue;
132      }
133       
134      /* if there's no opener, print the @ and continue */
135      tmpptr=strpbrk(txtptr, "(<[{ ");
136      if (!tmpptr || tmpptr[0]==' ') {
137        owl_fmtext_append_attr(f, "@", curattrs, curcolor);
138        txtptr++;
139        continue;
140      }
141
142      /* check what command we've got, push it on the stack, start
143         using it, and continue ... unless it's a color command */
144      buff=owl_malloc(tmpptr-ptr+20);
145      strncpy(buff, ptr, tmpptr-ptr);
146      buff[tmpptr-ptr]='\0';
147      if (!strcasecmp(buff, "@bold")) {
148        attrstack[stacksize]=OWL_FMTEXT_ATTR_BOLD;
149        chrstack[stacksize]=tmpptr[0];
150        stacksize++;
151        curattrs|=OWL_FMTEXT_ATTR_BOLD;
152        txtptr+=6;
153        owl_free(buff);
154        continue;
155      } else if (!strcasecmp(buff, "@b")) {
156        attrstack[stacksize]=OWL_FMTEXT_ATTR_BOLD;
157        chrstack[stacksize]=tmpptr[0];
158        stacksize++;
159        curattrs|=OWL_FMTEXT_ATTR_BOLD;
160        txtptr+=3;
161        owl_free(buff);
162        continue;
163      } else if (!strcasecmp(buff, "@i")) {
164        attrstack[stacksize]=OWL_FMTEXT_ATTR_UNDERLINE;
165        chrstack[stacksize]=tmpptr[0];
166        stacksize++;
167        curattrs|=OWL_FMTEXT_ATTR_UNDERLINE;
168        txtptr+=3;
169        owl_free(buff);
170        continue;
171      } else if (!strcasecmp(buff, "@italic")) {
172        attrstack[stacksize]=OWL_FMTEXT_ATTR_UNDERLINE;
173        chrstack[stacksize]=tmpptr[0];
174        stacksize++;
175        curattrs|=OWL_FMTEXT_ATTR_UNDERLINE;
176        txtptr+=8;
177        owl_free(buff);
178        continue;
179
180        /* if it's a color read the color, set the current color and
181           continue */
182      } else if (!strcasecmp(buff, "@color") && owl_global_get_hascolors(&g)) {
183        owl_free(buff);
184        txtptr+=7;
185        tmpptr=strpbrk(txtptr, "@{[<()>]}");
186        if (tmpptr &&
187            ((txtptr[-1]=='(' && tmpptr[0]==')') ||
188             (txtptr[-1]=='<' && tmpptr[0]=='>') ||
189             (txtptr[-1]=='[' && tmpptr[0]==']') ||
190             (txtptr[-1]=='{' && tmpptr[0]=='}'))) {
191
192          /* grab the color name */
193          buff=owl_malloc(tmpptr-txtptr+20);
194          strncpy(buff, txtptr, tmpptr-txtptr);
195          buff[tmpptr-txtptr]='\0';
196
197          /* set it as the current color */
198          curcolor=owl_util_string_to_color(buff);
199          owl_free(buff);
200          txtptr=tmpptr+1;
201          continue;
202
203        } else {
204
205        }
206
207      } else {
208        /* if we didn't understand it, we'll print it.  This is different from zwgc
209           but zwgc seems to be smarter about some screw cases than I am */
210        owl_fmtext_append_attr(f, "@", curattrs, curcolor);
211        txtptr++;
212        continue;
213      }
214
215    } else if (ptr[0]=='}' || ptr[0]==']' || ptr[0]==')' || ptr[0]=='>') {
216      /* add the text up to this point first */
217      buff=owl_malloc(ptr-txtptr+20);
218      strncpy(buff, txtptr, ptr-txtptr);
219      buff[ptr-txtptr]='\0';
220      owl_fmtext_append_attr(f, buff, curattrs, curcolor);
221      owl_free(buff);
222
223      /* now deal with the closer */
224      txtptr=ptr;
225
226      /* first, if the stack is empty we must bail (just print and go) */
227      if (stacksize==0) {
228        buff=owl_malloc(5);
229        buff[0]=ptr[0];
230        buff[1]='\0';
231        owl_fmtext_append_attr(f, buff, curattrs, curcolor);
232        owl_free(buff);
233        txtptr++;
234        continue;
235      }
236
237      /* if the closing char is what's on the stack, turn off the
238         attribue and pop the stack */
239      if ((ptr[0]==')' && chrstack[stacksize-1]=='(') ||
240          (ptr[0]=='>' && chrstack[stacksize-1]=='<') ||
241          (ptr[0]==']' && chrstack[stacksize-1]=='[') ||
242          (ptr[0]=='}' && chrstack[stacksize-1]=='{')) {
243        int i;
244        stacksize--;
245        curattrs=OWL_FMTEXT_ATTR_NONE;
246        for (i=0; i<stacksize; i++) {
247          curattrs|=attrstack[i];
248        }
249        txtptr+=1;
250        continue;
251      } else {
252        /* otherwise print and continue */
253        buff=owl_malloc(5);
254        buff[0]=ptr[0];
255        buff[1]='\0';
256        owl_fmtext_append_attr(f, buff, curattrs, curcolor);
257        owl_free(buff);
258        txtptr++;
259        continue;
260      }
261    } else {
262      /* we've found an unattached opener, print everything and move on */
263      buff=owl_malloc(ptr-txtptr+20);
264      strncpy(buff, txtptr, ptr-txtptr+1);
265      buff[ptr-txtptr+1]='\0';
266      owl_fmtext_append_attr(f, buff, curattrs, curcolor);
267      owl_free(buff);
268      txtptr=ptr+1;
269      continue;
270    }
271  }
272
273}
274
275void owl_fmtext_append_fmtext(owl_fmtext *f, owl_fmtext *in, int start, int stop) {
276  int newlen, i;
277
278  newlen=strlen(f->textbuff)+(stop-start+1);
279  f->textbuff=owl_realloc(f->textbuff, newlen+1);
280  f->fmbuff=owl_realloc(f->fmbuff, newlen+1);
281  f->colorbuff=owl_realloc(f->colorbuff, newlen+1);
282
283  strncat(f->textbuff, in->textbuff+start, stop-start+1);
284  f->textbuff[newlen]='\0';
285  for (i=start; i<=stop; i++) {
286    f->fmbuff[f->textlen+(i-start)]=in->fmbuff[i];
287    f->colorbuff[f->textlen+(i-start)]=in->colorbuff[i];
288  }
289  f->textlen=newlen;
290}
291
292void owl_fmtext_append_spaces(owl_fmtext *f, int nspaces) {
293  int i;
294  for (i=0; i<nspaces; i++) {
295    owl_fmtext_append_normal(f, " ");
296  }
297}
298
299/* requires that the list values are strings or NULL.
300 * joins the elements together with join_with.
301 * If format_fn is specified, passes it the list element value
302 * and it will return a string which this needs to free. */
303void owl_fmtext_append_list(owl_fmtext *f, owl_list *l, char *join_with, char *(format_fn)(void*)) {
304  int i, size;
305  void *elem;
306  char *text;
307
308  size = owl_list_get_size(l);
309  for (i=0; i<size; i++) {
310    elem = (char*)owl_list_get_element(l,i);
311    if (elem && format_fn) {
312      text = format_fn(elem);
313      if (text) {
314        owl_fmtext_append_normal(f, text);
315        owl_free(text);
316      }
317    } else if (elem) {
318      owl_fmtext_append_normal(f, elem);
319    }
320    if ((i < size-1) && join_with) {
321      owl_fmtext_append_normal(f, join_with);
322    }
323  }
324}
325
326
327void owl_fmtext_print_plain(owl_fmtext *f, char *buff) {
328  strcpy(buff, f->textbuff);
329}
330
331
332void owl_fmtext_curs_waddstr(owl_fmtext *f, WINDOW *w) {
333  char *tmpbuff;
334  int position, trans1, trans2, len, lastsame;
335
336  tmpbuff=owl_malloc(f->textlen+10);
337
338  position=0;
339  len=f->textlen;
340  while (position<=len) {
341    /* find the last char with the current format and color */
342    trans1=owl_util_find_trans(f->fmbuff+position, len-position);
343    trans2=owl_util_find_trans(f->colorbuff+position, len-position);
344
345    if (trans1<trans2) {
346      lastsame=position+trans1;
347    } else {
348      lastsame=position+trans2;
349    }
350
351    /* set the format */
352    wattrset(w, A_NORMAL);
353    if (f->fmbuff[position] & OWL_FMTEXT_ATTR_BOLD) {
354      wattron(w, A_BOLD);
355    }
356    if (f->fmbuff[position] & OWL_FMTEXT_ATTR_REVERSE) {
357      wattron(w, A_REVERSE);
358    }
359    if (f->fmbuff[position] & OWL_FMTEXT_ATTR_UNDERLINE) {
360      wattron(w, A_UNDERLINE);
361    }
362
363    /* set the color */
364    /* warning, this is sort of a hack */
365    if (owl_global_get_hascolors(&g)) {
366      if (f->colorbuff[position]!=OWL_COLOR_DEFAULT) {
367        wattron(w, COLOR_PAIR(f->colorbuff[position]));
368      }
369    }
370
371    /* add the text */
372    strncpy(tmpbuff, f->textbuff + position, lastsame-position+1);
373    tmpbuff[lastsame-position+1]='\0';
374    waddstr(w, tmpbuff);
375
376    position=lastsame+1;
377  }
378  owl_free(tmpbuff);
379}
380
381
382int owl_fmtext_truncate_lines(owl_fmtext *in, int aline, int lines, owl_fmtext *out) {
383  /* start with line aline (where the first line is 0) and print
384   *  'lines' lines
385   */
386  char *ptr1, *ptr2;
387  int i, offset;
388
389  /* initialize out */
390  owl_fmtext_init_null(out);
391 
392  /* find the starting line */
393  ptr1=in->textbuff;
394  if (aline!=0) {
395    for (i=0; i<aline; i++) {
396      ptr1=strchr(ptr1, '\n');
397      if (!ptr1) return(-1);
398      ptr1++;
399    }
400  }
401  /* ptr1 now holds the starting point */
402
403  /* copy in the next 'lines' lines */
404  if (lines<1) return(-1);
405
406  for (i=0; i<lines; i++) {
407    ptr2=strchr(ptr1, '\n');
408    offset=ptr1-in->textbuff;
409    if (!ptr2) {
410      owl_fmtext_append_fmtext(out, in, offset, in->textlen-1);
411      return(-1);
412    }
413    owl_fmtext_append_fmtext(out, in, offset, (ptr2-ptr1)+offset);
414    ptr1=ptr2+1;
415  }
416  return(0);
417}
418
419
420void owl_fmtext_truncate_cols(owl_fmtext *in, int acol, int bcol, owl_fmtext *out) {
421  char *ptr1, *ptr2, *last;
422  int len, offset;
423 
424  /* the first column is column 0 */
425
426  /* the message is expected to end in a new line for now */
427
428  owl_fmtext_init_null(out);
429
430  last=in->textbuff+in->textlen-1;
431  ptr1=in->textbuff;
432  while (ptr1<=last) {
433    ptr2=strchr(ptr1, '\n');
434    if (!ptr2) {
435      /* but this shouldn't happen if we end in a \n */
436      break;
437    }
438   
439    if (ptr2==ptr1) {
440      owl_fmtext_append_normal(out, "\n");
441      ptr1++;
442      continue;
443    }
444
445    /* we need to check that we won't run over here */
446    len=bcol-acol;
447    if (len > (ptr2-(ptr1+acol))) {
448      len=ptr2-(ptr1+acol);
449    }
450    if (len>last-ptr1) {
451      len-=(last-ptr1);
452    }
453    if (len<=0) {
454      owl_fmtext_append_normal(out, "\n");
455      ptr1=ptr2+1;
456      continue;
457    }
458
459    offset=ptr1-in->textbuff;
460    owl_fmtext_append_fmtext(out, in, offset+acol, offset+acol+len);
461
462    ptr1=ptr2+1;
463  }
464}
465
466
467int owl_fmtext_num_lines(owl_fmtext *f) {
468  int lines, i;
469
470  lines=0;
471  for (i=0; f->textbuff[i]!='\0'; i++) {
472    if (f->textbuff[i]=='\n') lines++;
473  }
474
475  /* if the last char wasn't a \n there's one more line */
476  if (f->textbuff[i-1]!='\n') lines++;
477
478  return(lines);
479}
480
481
482char *owl_fmtext_get_text(owl_fmtext *f) {
483  return(f->textbuff);
484}
485
486void owl_fmtext_free(owl_fmtext *f) {
487  if (f->textbuff) owl_free(f->textbuff);
488  if (f->fmbuff) owl_free(f->fmbuff);
489  if (f->colorbuff) owl_free(f->colorbuff);
490}
491
492
493void owl_fmtext_copy(owl_fmtext *dst, owl_fmtext *src) {
494  dst->textlen=src->textlen;
495  dst->textbuff=owl_malloc(src->textlen+5);
496  dst->fmbuff=owl_malloc(src->textlen+5);
497  dst->colorbuff=owl_malloc(src->textlen+5);
498  memcpy(dst->textbuff, src->textbuff, src->textlen);
499  memcpy(dst->fmbuff, src->fmbuff, src->textlen);
500  memcpy(dst->colorbuff, src->colorbuff, src->textlen);
501}
Note: See TracBrowser for help on using the repository browser.