* Fix for a better bound check in imap/src/c-client/nntp.c submitted by
[alpine.git] / pith / editorial.c
bloba93051b8b60668f8b5f0e2e14530fb46eccb0dbf
1 /* ========================================================================
2 * Copyright 2013-2022 Eduardo Chappa
3 * Copyright 2006-2007 University of Washington
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * ========================================================================
14 /*======================================================================
16 editorial.c
17 Implements editorial text insertion/formatting
19 ====*/
22 #include "../pith/headers.h"
23 #include "../pith/conf.h"
24 #include "../pith/state.h"
25 #include "../pith/margin.h"
26 #include "../pith/filter.h"
27 #include "../pith/handle.h"
28 #include "../pith/mailview.h"
29 #include "../pith/editorial.h"
32 * Internal prototypes
34 int quote_editorial(long, char *, LT_INS_S **, void *);
38 * Struct to help with editorial comment insertion
40 #define EDITORIAL_MAX 128
41 typedef struct _editorial_s {
42 char prefix[EDITORIAL_MAX];
43 int prelen;
44 char postfix[EDITORIAL_MAX];
45 int postlen;
46 int do_color;
47 } EDITORIAL_S;
50 char *
51 format_editorial(char *s, int width, int flags, HANDLE_S **handlesp, gf_io_t pc)
53 gf_io_t gc;
54 int *margin;
55 EDITORIAL_S es;
56 URL_HILITE_S uh;
58 /* ASSUMPTION #2,341: All MIME-decoding is done by now */
59 gf_set_readc(&gc, s, strlen(s), CharStar, 0);
61 margin = format_view_margin();
62 if(flags & FM_NOINDENT)
63 margin[0] = margin[1] = 0;
65 /* safety net */
66 if(width - (margin[0] + margin[1]) < 5){
67 margin[0] = margin[1] = 0;
68 if(width < 5)
69 width = 80;
72 width -= (margin[0] + margin[1]);
74 if(width > 40){
75 width -= 12;
77 es.prelen = MAX(2, MIN(margin[0] + 6, sizeof(es.prefix) - 3));
78 snprintf(es.prefix, sizeof(es.prefix), "%s[ ", repeat_char(es.prelen - 2, ' '));
79 es.postlen = 2;
80 strncpy(es.postfix, " ]", sizeof(es.postfix));
81 es.postfix[sizeof(es.postfix)-1] = '\0';
83 else if(width > 20){
84 width -= 6;
86 es.prelen = MAX(2, MIN(margin[0] + 3, sizeof(es.prefix) - 3));
87 snprintf(es.prefix, sizeof(es.prefix), "%s[ ", repeat_char(es.prelen - 2, ' '));
88 es.postlen = 2;
89 strncpy(es.postfix, " ]", sizeof(es.postfix));
90 es.postfix[sizeof(es.postfix)-1] = '\0';
92 else{
93 width -= 2;
94 strncpy(es.prefix, "[", sizeof(es.prefix));
95 es.prefix[sizeof(es.prefix)-1] = '\0';
96 strncpy(es.postfix, "]", sizeof(es.postfix));
97 es.postfix[sizeof(es.postfix)-1] = '\0';
98 es.prelen = 1;
99 es.postlen = 1;
102 es.do_color = (!(flags & FM_NOCOLOR) && (flags & FM_DISPLAY) && pico_usingcolor());
104 gf_filter_init();
106 /* catch urls */
107 if((F_ON(F_VIEW_SEL_URL, ps_global)
108 || F_ON(F_VIEW_SEL_URL_HOST, ps_global)
109 || F_ON(F_SCAN_ADDR, ps_global))
110 && handlesp){
111 gf_link_filter(gf_line_test,
112 gf_line_test_opt(url_hilite,
113 gf_url_hilite_opt(&uh,handlesp,0)));
116 gf_link_filter(gf_wrap, gf_wrap_filter_opt(width, width, NULL, 0,
117 (handlesp ? GFW_HANDLES : GFW_NONE)));
118 gf_link_filter(gf_line_test, gf_line_test_opt(quote_editorial, &es));
120 /* If not for display, change to local end of line */
121 if(!(flags & FM_DISPLAY))
122 gf_link_filter(gf_nvtnl_local, NULL);
124 return(gf_pipe(gc, pc));
129 quote_editorial(long int linenum, char *line, LT_INS_S **ins, void *local)
131 COLOR_PAIR *col = NULL;
133 ins = gf_line_test_new_ins(ins, line,
134 ((EDITORIAL_S *)local)->prefix,
135 ((EDITORIAL_S *)local)->prelen);
136 if(((EDITORIAL_S *)local)->do_color
137 && ps_global->VAR_METAMSG_FORE_COLOR
138 && ps_global->VAR_METAMSG_BACK_COLOR
139 && (col = new_color_pair(ps_global->VAR_METAMSG_FORE_COLOR,
140 ps_global->VAR_METAMSG_BACK_COLOR))){
141 if(!pico_is_good_colorpair(col))
142 free_color_pair(&col);
144 if(col){
145 char *p;
146 char normal_embed[(2 * RGBLEN) + 5];
147 char quote_color_embed[(2 * RGBLEN) + 5];
149 strncpy(quote_color_embed,
150 color_embed(col->fg, col->bg),
151 sizeof(quote_color_embed));
152 quote_color_embed[sizeof(quote_color_embed)-1] = '\0';
154 ins = gf_line_test_new_ins(ins, line,
155 quote_color_embed, (2 * RGBLEN) + 4);
158 * If there was already a color change back to normal color
159 * in the line that was passed in, then instead of allowing
160 * that color change back to normal we want to change that
161 * to a color change back to our METAMSG color instead.
162 * Search line for that and modify it.
165 strncpy(normal_embed,
166 color_embed(ps_global->VAR_NORM_FORE_COLOR,
167 ps_global->VAR_NORM_BACK_COLOR),
168 sizeof(normal_embed));
169 normal_embed[sizeof(normal_embed)-1] = '\0';
171 for(p = line; (p = strstr(p, normal_embed)); p++){
174 * Replace the normal color with our special quoting
175 * color. No need to change it if there are no
176 * characters after the color change because we're
177 * going to change the color to normal right below
178 * this anyway.
180 if(strlen(p) > strlen(quote_color_embed))
181 rplstr(p, strlen(p)+1, strlen(quote_color_embed), quote_color_embed);
184 ins = gf_line_test_new_ins(ins, line+strlen(line),
185 normal_embed, (2 * RGBLEN) + 4);
186 free_color_pair(&col);
190 ins = gf_line_test_new_ins(ins, line + strlen(line),
191 ((EDITORIAL_S *)local)->postfix,
192 ((EDITORIAL_S *)local)->postlen);
193 return(0);