owl_filter *owl_filter_new(const char *name, int argc, const char *const *argv) { owl_filter *f; f = g_new(owl_filter, 1); f->name=g_strdup(name); f->fgcolor=OWL_COLOR_DEFAULT; f->bgcolor=OWL_COLOR_DEFAULT; /* first take arguments that have to come first */ /* set the color */ while ( argc>=2 && ( !strcmp(argv[0], "-c") || !strcmp(argv[0], "-b") ) ) { if (owl_util_string_to_color(argv[1])==OWL_COLOR_INVALID) { owl_function_error("The color '%s' is not available, using default.", argv[1]); } else { switch (argv[0][1]) { case 'c': f->fgcolor=owl_util_string_to_color(argv[1]); break; case 'b': f->bgcolor=owl_util_string_to_color(argv[1]); break; } } argc-=2; argv+=2; } if (!(f->root = owl_filter_parse_expression(argc, argv, NULL))) { owl_filter_delete(f); return NULL; } /* Now check for recursion. */ if (owl_filter_is_toodeep(f)) { owl_function_error("Filter loop!"); owl_filter_delete(f); return NULL; } return f; }
/* Append the text 'text' to 'f' and interpret the zephyr style * formatting syntax to set appropriate attributes. */ void owl_fmtext_append_ztext(owl_fmtext *f, const char *text) { int stacksize, curattrs, curcolor; const char *ptr, *txtptr, *tmpptr; char *buff; int attrstack[32], chrstack[32], colorstack[32]; curattrs=OWL_FMTEXT_ATTR_NONE; curcolor=OWL_COLOR_DEFAULT; stacksize=0; txtptr=text; while (1) { ptr=strpbrk(txtptr, "@{[<()>]}"); if (!ptr) { /* add all the rest of the text and exit */ owl_fmtext_append_attr(f, txtptr, curattrs, curcolor, OWL_COLOR_DEFAULT); return; } else if (ptr[0]=='@') { /* add the text up to this point then deal with the stack */ buff=owl_malloc(ptr-txtptr+20); strncpy(buff, txtptr, ptr-txtptr); buff[ptr-txtptr]='\0'; owl_fmtext_append_attr(f, buff, curattrs, curcolor, OWL_COLOR_DEFAULT); owl_free(buff); /* update pointer to point at the @ */ txtptr=ptr; /* now the stack */ /* if we've hit our max stack depth, print the @ and move on */ if (stacksize==32) { owl_fmtext_append_attr(f, "@", curattrs, curcolor, OWL_COLOR_DEFAULT); txtptr++; continue; } /* if it's an @@, print an @ and continue */ if (txtptr[1]=='@') { owl_fmtext_append_attr(f, "@", curattrs, curcolor, OWL_COLOR_DEFAULT); txtptr+=2; continue; } /* if there's no opener, print the @ and continue */ tmpptr=strpbrk(txtptr, "(<[{ "); if (!tmpptr || tmpptr[0]==' ') { owl_fmtext_append_attr(f, "@", curattrs, curcolor, OWL_COLOR_DEFAULT); txtptr++; continue; } /* check what command we've got, push it on the stack, start using it, and continue ... unless it's a color command */ buff=owl_malloc(tmpptr-ptr+20); strncpy(buff, ptr, tmpptr-ptr); buff[tmpptr-ptr]='\0'; if (!strcasecmp(buff, "@bold")) { attrstack[stacksize]=OWL_FMTEXT_ATTR_BOLD; chrstack[stacksize]=tmpptr[0]; colorstack[stacksize]=curcolor; stacksize++; curattrs|=OWL_FMTEXT_ATTR_BOLD; txtptr+=6; owl_free(buff); continue; } else if (!strcasecmp(buff, "@b")) { attrstack[stacksize]=OWL_FMTEXT_ATTR_BOLD; chrstack[stacksize]=tmpptr[0]; colorstack[stacksize]=curcolor; stacksize++; curattrs|=OWL_FMTEXT_ATTR_BOLD; txtptr+=3; owl_free(buff); continue; } else if (!strcasecmp(buff, "@i")) { attrstack[stacksize]=OWL_FMTEXT_ATTR_UNDERLINE; chrstack[stacksize]=tmpptr[0]; colorstack[stacksize]=curcolor; stacksize++; curattrs|=OWL_FMTEXT_ATTR_UNDERLINE; txtptr+=3; owl_free(buff); continue; } else if (!strcasecmp(buff, "@italic")) { attrstack[stacksize]=OWL_FMTEXT_ATTR_UNDERLINE; chrstack[stacksize]=tmpptr[0]; colorstack[stacksize]=curcolor; stacksize++; curattrs|=OWL_FMTEXT_ATTR_UNDERLINE; txtptr+=8; owl_free(buff); continue; } else if (!strcasecmp(buff, "@")) { attrstack[stacksize]=OWL_FMTEXT_ATTR_NONE; chrstack[stacksize]=tmpptr[0]; colorstack[stacksize]=curcolor; stacksize++; txtptr+=2; owl_free(buff); continue; /* if it's a color read the color, set the current color and continue */ } else if (!strcasecmp(buff, "@color") && owl_global_get_hascolors(&g) && owl_global_is_colorztext(&g)) { owl_free(buff); txtptr+=7; tmpptr=strpbrk(txtptr, "@{[<()>]}"); if (tmpptr && ((txtptr[-1]=='(' && tmpptr[0]==')') || (txtptr[-1]=='<' && tmpptr[0]=='>') || (txtptr[-1]=='[' && tmpptr[0]==']') || (txtptr[-1]=='{' && tmpptr[0]=='}'))) { /* grab the color name */ buff=owl_malloc(tmpptr-txtptr+20); strncpy(buff, txtptr, tmpptr-txtptr); buff[tmpptr-txtptr]='\0'; /* set it as the current color */ curcolor=owl_util_string_to_color(buff); if (curcolor == OWL_COLOR_INVALID) curcolor = OWL_COLOR_DEFAULT; owl_free(buff); txtptr=tmpptr+1; continue; } else { } } else { /* if we didn't understand it, we'll print it. This is different from zwgc * but zwgc seems to be smarter about some screw cases than I am */ owl_fmtext_append_attr(f, "@", curattrs, curcolor, OWL_COLOR_DEFAULT); txtptr++; continue; } } else if (ptr[0]=='}' || ptr[0]==']' || ptr[0]==')' || ptr[0]=='>') { /* add the text up to this point first */ buff=owl_malloc(ptr-txtptr+20); strncpy(buff, txtptr, ptr-txtptr); buff[ptr-txtptr]='\0'; owl_fmtext_append_attr(f, buff, curattrs, curcolor, OWL_COLOR_DEFAULT); owl_free(buff); /* now deal with the closer */ txtptr=ptr; /* first, if the stack is empty we must bail (just print and go) */ if (stacksize==0) { buff=owl_malloc(5); buff[0]=ptr[0]; buff[1]='\0'; owl_fmtext_append_attr(f, buff, curattrs, curcolor, OWL_COLOR_DEFAULT); owl_free(buff); txtptr++; continue; } /* if the closing char is what's on the stack, turn off the attribue and pop the stack */ if ((ptr[0]==')' && chrstack[stacksize-1]=='(') || (ptr[0]=='>' && chrstack[stacksize-1]=='<') || (ptr[0]==']' && chrstack[stacksize-1]=='[') || (ptr[0]=='}' && chrstack[stacksize-1]=='{')) { int i; stacksize--; curattrs=OWL_FMTEXT_ATTR_NONE; curcolor = colorstack[stacksize]; for (i=0; i<stacksize; i++) { curattrs|=attrstack[i]; } txtptr+=1; continue; } else { /* otherwise print and continue */ buff=owl_malloc(5); buff[0]=ptr[0]; buff[1]='\0'; owl_fmtext_append_attr(f, buff, curattrs, curcolor, OWL_COLOR_DEFAULT); owl_free(buff); txtptr++; continue; } } else { /* we've found an unattached opener, print everything and move on */ buff=owl_malloc(ptr-txtptr+20); strncpy(buff, txtptr, ptr-txtptr+1); buff[ptr-txtptr+1]='\0'; owl_fmtext_append_attr(f, buff, curattrs, curcolor, OWL_COLOR_DEFAULT); owl_free(buff); txtptr=ptr+1; continue; } } }