diff -rc alpine-2.26/alpine/confscroll.c alpine-2.26.colortext/alpine/confscroll.c *** alpine-2.26/alpine/confscroll.c 2022-06-02 18:14:00.463274817 -0600 --- alpine-2.26.colortext/alpine/confscroll.c 2022-06-02 18:15:04.147118665 -0600 *************** *** 5246,5251 **** --- 5246,5254 ---- clear_index_cache(ps->mail_stream, 0); } + else if(var == &ps->vars[V_SPECIAL_TEXT]){ + regex_pattern(ps->VAR_SPECIAL_TEXT); + } else if(var == &ps->vars[V_INIT_CMD_LIST]){ if(!revert) q_status_message(SM_ASYNC, 0, 3, diff -rc alpine-2.26/pith/conf.c alpine-2.26.colortext/pith/conf.c *** alpine-2.26/pith/conf.c 2022-06-02 18:14:00.491274749 -0600 --- alpine-2.26.colortext/pith/conf.c 2022-06-02 18:15:04.151118655 -0600 *************** *** 229,234 **** --- 229,236 ---- CONF_TXT_T cf_text_fillcol[] = "Specifies the column of the screen where the composer should wrap."; + CONF_TXT_T cf_special_text_color[] = "Specifies a comma separated list of text and regular expresions that Pine\n# will highlight"; + CONF_TXT_T cf_text_replystr[] = "Specifies the string to insert when replying to a message."; CONF_TXT_T cf_text_quotereplstr[] = "Specifies the string to replace quotes with when viewing a message."; *************** *** 585,590 **** --- 587,594 ---- #endif /* _WINDOWS */ {"composer-wrap-column", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, NULL, cf_text_fillcol}, + {"special-text-color", 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0, + NULL, cf_special_text_color}, {"reply-indent-string", 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, NULL, cf_text_replystr}, {"reply-leadin", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, *************** *** 864,869 **** --- 868,875 ---- {"incoming-unseen-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0}, {"signature-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0}, {"signature-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0}, + {"special-text-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0}, + {"special-text-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0}, {"prompt-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0}, {"prompt-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0}, {"header-general-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0}, *************** *** 2115,2120 **** --- 2121,2128 ---- set_current_val(&vars[V_DICTIONARY], TRUE, TRUE); #endif /* _WINDOWS */ set_current_val(&vars[V_IMAGE_VIEWER], TRUE, TRUE); + set_current_val(&vars[V_SPECIAL_TEXT], TRUE, TRUE); + regex_pattern(VAR_SPECIAL_TEXT); set_current_val(&vars[V_BROWSER], TRUE, TRUE); set_current_val(&vars[V_HISTORY], TRUE, TRUE); set_current_val(&vars[V_SMTP_SERVER], TRUE, TRUE); *************** *** 6685,6690 **** --- 6693,6699 ---- set_color_val(&vars[V_IND_OP_FORE_COLOR], 0); set_color_val(&vars[V_INCUNSEEN_FORE_COLOR], 0); set_color_val(&vars[V_SIGNATURE_FORE_COLOR], 0); + set_color_val(&vars[V_SPECIAL_TEXT_FORE_COLOR], 0); set_current_val(&ps->vars[V_INDEX_TOKEN_COLORS], TRUE, TRUE); set_current_val(&ps->vars[V_VIEW_HDR_COLORS], TRUE, TRUE); *************** *** 7934,7939 **** --- 7943,7950 ---- return(h_config_scroll_margin); case V_DEADLETS : return(h_config_deadlets); + case V_SPECIAL_TEXT : + return(h_config_special_text_to_color); case V_FILLCOL : return(h_config_composer_wrap_column); case V_TCPOPENTIMEO : *************** *** 8119,8124 **** --- 8130,8138 ---- case V_SIGNATURE_FORE_COLOR : case V_SIGNATURE_BACK_COLOR : return(h_config_signature_color); + case V_SPECIAL_TEXT_FORE_COLOR : + case V_SPECIAL_TEXT_BACK_COLOR : + return(h_config_special_text_color); case V_PROMPT_FORE_COLOR : case V_PROMPT_BACK_COLOR : return(h_config_prompt_color); diff -rc alpine-2.26/pith/conf.h alpine-2.26.colortext/pith/conf.h *** alpine-2.26/pith/conf.h 2022-06-02 18:14:00.491274749 -0600 --- alpine-2.26.colortext/pith/conf.h 2022-06-02 18:15:04.187118567 -0600 *************** *** 176,181 **** --- 176,183 ---- #define VAR_DICTIONARY vars[V_DICTIONARY].current_val.l #define GLO_DICTIONARY vars[V_DICTIONARY].global_val.l #endif /* _WINDOWS */ + #define VAR_SPECIAL_TEXT vars[V_SPECIAL_TEXT].current_val.l + #define GLO_SPECIAL_TEXT vars[V_SPECIAL_TEXT].global_val.l #define VAR_FILLCOL vars[V_FILLCOL].current_val.p #define GLO_FILLCOL vars[V_FILLCOL].global_val.p #define VAR_DEADLETS vars[V_DEADLETS].current_val.p *************** *** 475,480 **** --- 477,484 ---- #define GLO_SIGNATURE_FORE_COLOR vars[V_SIGNATURE_FORE_COLOR].global_val.p #define VAR_SIGNATURE_BACK_COLOR vars[V_SIGNATURE_BACK_COLOR].current_val.p #define GLO_SIGNATURE_BACK_COLOR vars[V_SIGNATURE_BACK_COLOR].global_val.p + #define VAR_SPECIAL_TEXT_FORE_COLOR vars[V_SPECIAL_TEXT_FORE_COLOR].current_val.p + #define VAR_SPECIAL_TEXT_BACK_COLOR vars[V_SPECIAL_TEXT_BACK_COLOR].current_val.p #define VAR_PROMPT_FORE_COLOR vars[V_PROMPT_FORE_COLOR].current_val.p #define VAR_PROMPT_BACK_COLOR vars[V_PROMPT_BACK_COLOR].current_val.p #define VAR_VIEW_HDR_COLORS vars[V_VIEW_HDR_COLORS].current_val.l diff -rc alpine-2.26/pith/conftype.h alpine-2.26.colortext/pith/conftype.h *** alpine-2.26/pith/conftype.h 2022-06-02 18:14:00.491274749 -0600 --- alpine-2.26.colortext/pith/conftype.h 2022-06-02 18:15:04.235118450 -0600 *************** *** 83,88 **** --- 83,89 ---- , V_DICTIONARY #endif /* _WINDOWS */ , V_FILLCOL + , V_SPECIAL_TEXT , V_REPLY_STRING , V_REPLY_INTRO , V_QUOTE_REPLACE_STRING *************** *** 246,251 **** --- 247,254 ---- , V_INCUNSEEN_BACK_COLOR , V_SIGNATURE_FORE_COLOR , V_SIGNATURE_BACK_COLOR + , V_SPECIAL_TEXT_FORE_COLOR + , V_SPECIAL_TEXT_BACK_COLOR , V_PROMPT_FORE_COLOR , V_PROMPT_BACK_COLOR , V_HEADER_GENERAL_FORE_COLOR diff -rc alpine-2.26/pith/mailview.c alpine-2.26.colortext/pith/mailview.c *** alpine-2.26/pith/mailview.c 2022-06-02 18:14:00.491274749 -0600 --- alpine-2.26.colortext/pith/mailview.c 2022-06-02 18:15:04.251118410 -0600 *************** *** 632,637 **** --- 632,645 ---- if((flgs & FM_DISPLAY) && !(flgs & FM_NOCOLOR) && pico_usingcolor() + && ps_global->VAR_SPECIAL_TEXT_FORE_COLOR + && ps_global->VAR_SPECIAL_TEXT_BACK_COLOR){ + gf_link_filter(gf_line_test, gf_line_test_opt(color_this_text, NULL)); + } + + if((flgs & FM_DISPLAY) + && !(flgs & FM_NOCOLOR) + && pico_usingcolor() && ps_global->VAR_SIGNATURE_FORE_COLOR && ps_global->VAR_SIGNATURE_BACK_COLOR){ gf_link_filter(gf_line_test, gf_line_test_opt(color_signature, &is_in_sig)); *************** *** 2864,2869 **** --- 2872,3061 ---- return(color_pair); } + void + interval_free(IVAL_S **ival) + { + if (!(*ival)) + return; + + if ((*ival)->next) + interval_free(&((*ival)->next)); + + fs_give((void **)(ival)); + } + + IVAL_S * + compute_interval (char *string, int endm) + { + IVAL_S *ival = NULL; + regmatch_t pmatch; + + if(ps_global->paterror == 0 && + regexec(&ps_global->colorpat, string + endm, 1, &pmatch, 0) == 0){ + ival = (IVAL_S *) fs_get(sizeof(IVAL_S)); + ival->start = endm + pmatch.rm_so; + ival->end = endm + pmatch.rm_eo; + ival->next = compute_interval(string, ival->end); + } + return ival; + } + + void + regex_pattern(char **plist) + { + int i = 0, j = 0, len = 0; + char *pattern = NULL; + regex_t preg; + + if(ps_global->paterror == 0) + regfree(&ps_global->colorpat); + + if(plist && *plist && *plist){ + for (i = 0; plist[i] && plist[i][0]; i++) + len += strlen(plist[i]) + 1; + pattern = (char *) fs_get(len * sizeof(char)); + *pattern = '\0'; + for (j = 0; j < i; j++){ + strcat(pattern, plist[j]); + strcat(pattern, (j < i - 1) ? "|" : ""); + } + if ((ps_global->paterror = regcomp(&preg, pattern, REG_EXTENDED)) != 0) + regfree(&preg); + else + ps_global->colorpat = preg; + } + if(pattern) + fs_give((void **)&pattern); + } + + LT_INS_S ** + insert_color_special_text(LT_INS_S **ins, char **p, IVAL_S *ival, int last_end, + COLOR_PAIR *col) + { + struct variable *vars = ps_global->vars; + + if (ival){ + *p += ival->start - last_end; + ins = gf_line_test_new_ins(ins, *p, color_embed(col->fg, col->bg), + (2 * RGBLEN) + 4); + *p += ival->end - ival->start; + ins = gf_line_test_new_ins(ins, *p, color_embed(VAR_NORM_FORE_COLOR, + VAR_NORM_BACK_COLOR), (2 * RGBLEN) + 4); + ins = insert_color_special_text(ins, p, ival->next, ival->end, col); + } + return ins; + } + + int + length_color(char *p, int begin_color) + { + int len = 0, done = begin_color ? 0 : -1; + char *orig = p; + + while (*p && done <= 0){ + switch(*p++){ + case TAG_HANDLE : + p += *p + 1; + done++; + break; + + case TAG_FGCOLOR : + case TAG_BGCOLOR : + p += RGBLEN; + if (!begin_color) + done++; + break; + + default : + break; + } + } + len = p - orig; + return len; + } + + int + any_color_in_string(char *p) + { + int rv = 0; + char *orig = p; + while (*p && !rv) + if (*p++ == TAG_EMBED) + rv = p - orig; + return rv; + } + + void + remove_spaces_ival(IVAL_S **ivalp, char *p) + { + IVAL_S *ival; + int i; + if (!ivalp || !*ivalp) + return; + ival = *ivalp; + for (i = 0; isspace((unsigned char) p[ival->start + i]); i++); + if (ival->start + i < ival->end) /* do not do this if match only spaces */ + ival->start += i; + else + return; + for (i = 0; isspace((unsigned char) p[ival->end - i - 1]); i++); + ival->end -= i; + if (ival->next) + remove_spaces_ival(&(ival->next), p); + } + + int + color_this_text(long linenum, char *line, LT_INS_S **ins, void *local) + { + struct variable *vars = ps_global->vars; + COLOR_PAIR *col = NULL; + char *p; + int i = 0; + static char *pattern = NULL; + + /* select_quote(linenum, line, ins, (void *) &i); + for (i = 0; tmp_20k_buf[i] != '\0'; i++); */ + p = line + i; + + if(VAR_SPECIAL_TEXT_FORE_COLOR && VAR_SPECIAL_TEXT_BACK_COLOR + && (col = new_color_pair(VAR_SPECIAL_TEXT_FORE_COLOR, + VAR_SPECIAL_TEXT_BACK_COLOR)) + && !pico_is_good_colorpair(col)) + free_color_pair(&col); + + if(ps_global->VAR_SPECIAL_TEXT && *ps_global->VAR_SPECIAL_TEXT + && **ps_global->VAR_SPECIAL_TEXT && col){ + IVAL_S *ival; + int done = 0, begin_color = 0; + + while (!done){ + if ((i = any_color_in_string(p))){ + begin_color = (begin_color + 1) % 2; + if (begin_color){ + p[i - 1] = '\0'; + ival = compute_interval(p, 0); + remove_spaces_ival(&ival, p); + p[i - 1] = TAG_EMBED; + ins = insert_color_special_text(ins, &p, ival, 0, col); + } + for (;*p++ != TAG_EMBED; ); + p += length_color(p, begin_color); + } + else{ + ival = compute_interval(p, 0); + remove_spaces_ival(&ival, p); + ins = insert_color_special_text(ins, &p, ival, 0, col); + done++; + } + interval_free(&ival); + if (!*p) + done++; + } + free_color_pair(&col); + } + + return 0; + } /* * The argument fieldname is something like "Subject:..." or "Subject". diff -rc alpine-2.26/pith/mailview.h alpine-2.26.colortext/pith/mailview.h *** alpine-2.26/pith/mailview.h 2022-06-02 18:14:00.491274749 -0600 --- alpine-2.26.colortext/pith/mailview.h 2022-06-02 18:15:04.263118380 -0600 *************** *** 30,35 **** --- 30,41 ---- #include "../pith/color.h" + typedef struct IVAL { + int start; + int end; + struct IVAL *next; + } IVAL_S; + /* format_message flags */ #define FM_DISPLAY 0x0001 /* result is headed for display */ #define FM_NEW_MESS 0x0002 /* a new message so zero out attachment descrip */ *************** *** 130,135 **** --- 136,150 ---- int url_hilite(long, char *, LT_INS_S **, void *); int handle_start_color(char *, size_t, int *, int); int handle_end_color(char *, size_t, int *); + IVAL_S *compute_interval(char *, int); + void remove_spaces_ival(IVAL_S **, char *); + void interval_free(IVAL_S **); + void regex_pattern(char **); + LT_INS_S **insert_color_special_text(LT_INS_S **, char **, IVAL_S *, + int, COLOR_PAIR *); + int any_color_in_string(char *); + int length_color(char *, int); + int color_this_text(long, char *, LT_INS_S **, void *); /* * BUG: BELOW IS UNIX/PC ONLY since config'd browser means nothing to webpine diff -rc alpine-2.26/pith/pine.hlp alpine-2.26.colortext/pith/pine.hlp *** alpine-2.26/pith/pine.hlp 2022-06-02 18:14:00.491274749 -0600 --- alpine-2.26.colortext/pith/pine.hlp 2022-06-02 18:15:04.299118293 -0600 *************** *** 5290,5295 **** --- 5290,5296 ----
  • OPTION:
  • OPTION:
  • OPTION: +
  • OPTION:
  • OPTION:
  • OPTION: Print-Font-Char-Set
  • OPTION: Print-Font-Name *************** *** 5318,5323 **** --- 5319,5325 ----
  • OPTION:
  • OPTION:
  • OPTION: Signature Color +
  • OPTION: Special Text Color
  • OPTION:
  • OPTION:
  • OPTION: *************** *** 25158,25163 **** --- 25160,25202 ---- <End of help on this topic> + ====== h_config_special_text_to_color ===== + + + OPTION: <!--#echo var="VAR_special-text-color"--> + + +

    OPTION:

    + + Use this option to enter patterns (text or regular expressions) that + Alpine will highlight in the body of the text that is not part of a handle + (an internal or external link that Alpine paints in a different color). + +

    + Enter each pattern in a different line. Pine will internally merge these + patterns (by adding a "|" character), or you can add them all in one line + by separating them by a "|" character. There is only a set of regular expressions that are matched. + +

    + Pine will use the colors defined in the + Special Text Color variable. + to paint any match. + +

    + If the Special Text Color is not set, setting this variable will not + cause that special text to be indicated in any special way. It will look + like any normal text. You must set those colors in order to make Pine + paint the screen differently when it finds the patterns specified in this + variable. + +

    +

    + <End of help on this topic> + + ====== h_config_display_filters ===== *************** *** 33778,33783 **** --- 33817,33846 ----

    Descriptions of the available commands +

    + Look here + to see the available Editing and Navigation commands. +

    + <End of help on this topic> + + + ====== h_config_special_text_color ===== + + + OPTION: Special Text Color + + +

    OPTION: Special Text Color

    + + Sets the color Pine uses for coloring any text in the body of the message + that is not part of a handle (and internal or external link that Pine + paints in a different color). By default, this variable is not defined, + which means that text that matches the pattern is not painted in any + particular way. This variable must be set in a special form if you + want text to be painted. + +

    + Descriptions of the available commands

    Look here to see the available Editing and Navigation commands. diff -rc alpine-2.26/pith/state.c alpine-2.26.colortext/pith/state.c *** alpine-2.26/pith/state.c 2022-06-02 18:14:00.491274749 -0600 --- alpine-2.26.colortext/pith/state.c 2022-06-02 18:15:04.299118293 -0600 *************** *** 140,145 **** --- 140,148 ---- if((*pps)->html_dir_list != NULL) free_html_log(&(*pps)->html_dir_list); + if((*pps)->paterror == 0) + regfree(&(*pps)->colorpat); + if((*pps)->ui.homedir) fs_give((void **)&(*pps)->ui.homedir); diff -rc alpine-2.26/pith/state.h alpine-2.26.colortext/pith/state.h *** alpine-2.26/pith/state.h 2022-06-02 18:14:00.491274749 -0600 --- alpine-2.26.colortext/pith/state.h 2022-06-02 18:15:04.303118282 -0600 *************** *** 351,356 **** --- 351,358 ---- char *display_charmap; /* needs to be freed */ char *keyboard_charmap; /* needs to be freed */ void *input_cs; + regex_t colorpat; + int paterror; char *posting_charmap; /* needs to be freed */ diff -rc alpine-2.26/pith/text.c alpine-2.26.colortext/pith/text.c *** alpine-2.26/pith/text.c 2022-06-02 18:14:00.491274749 -0600 --- alpine-2.26.colortext/pith/text.c 2022-06-02 18:15:04.315118253 -0600 *************** *** 167,172 **** --- 167,181 ---- gf_url_hilite_opt(&uh,handlesp,0)); } + if((flags & FM_DISPLAY) + && !(flags & FM_NOCOLOR) + && pico_usingcolor() + && VAR_SPECIAL_TEXT_FORE_COLOR + && VAR_SPECIAL_TEXT_BACK_COLOR){ + filters[filtcnt].filter = gf_line_test; + filters[filtcnt++].data = gf_line_test_opt(color_this_text, NULL); + } + /* * First, paint the signature. * Disclaimers noted below for coloring quotes apply here as well.