diff options
Diffstat (limited to 'frm/common.c')
-rw-r--r-- | frm/common.c | 599 |
1 files changed, 599 insertions, 0 deletions
diff --git a/frm/common.c b/frm/common.c new file mode 100644 index 000000000..bc6ad1a3a --- /dev/null +++ b/frm/common.c | |||
@@ -0,0 +1,599 @@ | |||
1 | /* GNU Mailutils -- a suite of utilities for electronic mail | ||
2 | Copyright (C) 1999, 2000, 2001, 2002, 2003, | ||
3 | 2004, 2005 Free Software Foundation, Inc. | ||
4 | |||
5 | GNU Mailutils is free software; you can redistribute it and/or modify | ||
6 | it under the terms of the GNU General Public License as published by | ||
7 | the Free Software Foundation; either version 2, or (at your option) | ||
8 | any later version. | ||
9 | |||
10 | GNU Mailutils is distributed in the hope that it will be useful, | ||
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | GNU General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with GNU Mailutils; if not, write to the Free Software | ||
17 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ | ||
18 | |||
19 | #include <frm.h> | ||
20 | |||
21 | char *show_field; /* Show this header field instead of the default | ||
22 | `From: Subject:' pair. -f option */ | ||
23 | int show_to; /* Additionally display To: field. -l option */ | ||
24 | int show_number; /* Prefix each line with the message number. -n */ | ||
25 | int frm_debug; | ||
26 | |||
27 | |||
28 | |||
29 | /* Get the number of columns on the screen | ||
30 | First try an ioctl() call, not all shells set the COLUMNS environ. | ||
31 | If ioctl does not succeed on stdout, try it on /dev/tty, as we | ||
32 | may work via a pipe. | ||
33 | |||
34 | This function was taken from mail/util.c. It should probably reside | ||
35 | in the library */ | ||
36 | int | ||
37 | util_getcols (void) | ||
38 | { | ||
39 | struct winsize ws; | ||
40 | |||
41 | ws.ws_col = ws.ws_row = 0; | ||
42 | if (ioctl (1, TIOCGWINSZ, (char *) &ws) < 0) | ||
43 | { | ||
44 | int fd = open ("/dev/tty", O_RDWR); | ||
45 | ioctl (fd, TIOCGWINSZ, (char *) &ws); | ||
46 | close (fd); | ||
47 | } | ||
48 | if (ws.ws_row == 0) | ||
49 | { | ||
50 | const char *columns = getenv ("COLUMNS"); | ||
51 | if (columns) | ||
52 | ws.ws_col = strtol (columns, NULL, 10); | ||
53 | } | ||
54 | return ws.ws_col; | ||
55 | } | ||
56 | |||
57 | |||
58 | /* Charset magic */ | ||
59 | static char *output_charset = NULL; | ||
60 | |||
61 | const char * | ||
62 | get_charset () | ||
63 | { | ||
64 | char *tmp; | ||
65 | |||
66 | if (!output_charset) | ||
67 | { | ||
68 | char locale[32]; | ||
69 | |||
70 | memset (locale, 0, sizeof (locale)); | ||
71 | |||
72 | /* Try to deduce the charset from LC_ALL or LANG variables */ | ||
73 | |||
74 | tmp = getenv ("LC_ALL"); | ||
75 | if (!tmp) | ||
76 | tmp = getenv ("LANG"); | ||
77 | |||
78 | if (tmp) | ||
79 | { | ||
80 | char *sp = NULL; | ||
81 | char *lang; | ||
82 | char *terr; | ||
83 | |||
84 | strncpy (locale, tmp, sizeof (locale) - 1); | ||
85 | |||
86 | lang = strtok_r (locale, "_", &sp); | ||
87 | terr = strtok_r (NULL, ".", &sp); | ||
88 | output_charset = strtok_r (NULL, "@", &sp); | ||
89 | |||
90 | if (output_charset) | ||
91 | output_charset = xstrdup (output_charset); | ||
92 | else | ||
93 | output_charset = mu_charset_lookup (lang, terr); | ||
94 | |||
95 | if (!output_charset) | ||
96 | output_charset = "ASCII"; | ||
97 | } | ||
98 | } | ||
99 | return output_charset; | ||
100 | } | ||
101 | |||
102 | |||
103 | /* BIDI support (will be moved to lib when it's ready) */ | ||
104 | #ifdef HAVE_LIBFRIBIDI | ||
105 | |||
106 | static int fb_charset_num = -1; | ||
107 | FriBidiChar *logical; | ||
108 | char *outstring; | ||
109 | size_t logical_size; | ||
110 | |||
111 | void | ||
112 | alloc_logical (size_t size) | ||
113 | { | ||
114 | logical = xmalloc (size * sizeof (logical[0])); | ||
115 | logical_size = size; | ||
116 | outstring = xmalloc (size); | ||
117 | } | ||
118 | |||
119 | void | ||
120 | puts_bidi (char *string) | ||
121 | { | ||
122 | if (fb_charset_num == -1) | ||
123 | { | ||
124 | fb_charset_num = fribidi_parse_charset (get_charset ()); | ||
125 | if (fb_charset_num && frm_debug) | ||
126 | mu_error (_("fribidi failed to recognize charset `%s'"), | ||
127 | get_charset ()); | ||
128 | } | ||
129 | |||
130 | if (fb_charset_num == 0) | ||
131 | puts (string); | ||
132 | else | ||
133 | { | ||
134 | FriBidiStrIndex len; | ||
135 | FriBidiCharType base = FRIBIDI_TYPE_ON; | ||
136 | fribidi_boolean log2vis; | ||
137 | |||
138 | static FriBidiChar *visual; | ||
139 | static size_t visual_size; | ||
140 | |||
141 | |||
142 | len = fribidi_charset_to_unicode (fb_charset_num, | ||
143 | string, strlen (string), | ||
144 | logical); | ||
145 | |||
146 | if (len + 1 > visual_size) | ||
147 | { | ||
148 | visual_size = len + 1; | ||
149 | visual = xrealloc (visual, visual_size * sizeof *visual); | ||
150 | } | ||
151 | |||
152 | /* Create a bidi string. */ | ||
153 | log2vis = fribidi_log2vis (logical, len, &base, | ||
154 | /* output */ | ||
155 | visual, NULL, NULL, NULL); | ||
156 | |||
157 | if (log2vis) | ||
158 | { | ||
159 | FriBidiStrIndex idx, st; | ||
160 | FriBidiStrIndex new_len; | ||
161 | |||
162 | for (idx = 0; idx < len;) | ||
163 | { | ||
164 | FriBidiStrIndex wid, inlen; | ||
165 | |||
166 | wid = 3 * logical_size; | ||
167 | st = idx; | ||
168 | |||
169 | if (fb_charset_num != FRIBIDI_CHARSET_CAP_RTL) | ||
170 | { | ||
171 | while (wid > 0 && idx < len) | ||
172 | wid -= fribidi_wcwidth (visual[idx++]); | ||
173 | } | ||
174 | else | ||
175 | { | ||
176 | while (wid > 0 && idx < len) | ||
177 | { | ||
178 | wid--; | ||
179 | idx++; | ||
180 | } | ||
181 | } | ||
182 | |||
183 | if (wid < 0 && idx > st + 1) | ||
184 | idx--; | ||
185 | inlen = idx - st; | ||
186 | |||
187 | new_len = fribidi_unicode_to_charset (fb_charset_num, | ||
188 | visual + st, inlen, | ||
189 | outstring); | ||
190 | printf ("%s", outstring); | ||
191 | } | ||
192 | putchar ('\n'); | ||
193 | } | ||
194 | else | ||
195 | { | ||
196 | /* Print the string as is */ | ||
197 | puts (string); | ||
198 | } | ||
199 | } | ||
200 | } | ||
201 | #else | ||
202 | # define alloc_logical(s) | ||
203 | # define puts_bidi puts | ||
204 | #endif | ||
205 | |||
206 | |||
207 | /* Output functions */ | ||
208 | |||
209 | /* Number of columns in output: | ||
210 | |||
211 | Maximum 4 message number, to, from, subject -ln | ||
212 | Default 2 from, subject [none] | ||
213 | Minimum 1 FIELD -f FIELD | ||
214 | */ | ||
215 | |||
216 | static int numfields; /* Number of output fields */ | ||
217 | static int fieldwidth[4]; /* Field start positions */ | ||
218 | static char *linebuf; /* Output line buffer */ | ||
219 | static size_t linemax; /* Size of linebuf */ | ||
220 | static size_t linepos; /* Position in the output line buffer */ | ||
221 | static int curfield; /* Current output field */ | ||
222 | static int nextstart; /* Start position of the next field */ | ||
223 | static int curcol; /* Current output column */ | ||
224 | |||
225 | typedef void (*fmt_formatter) (const char *fmt, ...); | ||
226 | |||
227 | static fmt_formatter format_field; | ||
228 | |||
229 | void | ||
230 | print_line () | ||
231 | { | ||
232 | if (linebuf) | ||
233 | { | ||
234 | puts_bidi (linebuf); | ||
235 | linebuf[0] = 0; | ||
236 | linepos = 0; | ||
237 | curcol = nextstart = 0; | ||
238 | } | ||
239 | else | ||
240 | putchar ('\n'); | ||
241 | curfield = 0; | ||
242 | } | ||
243 | |||
244 | void | ||
245 | format_field_simple (const char *fmt, ...) | ||
246 | { | ||
247 | va_list ap; | ||
248 | if (curfield++) | ||
249 | putchar ('\t'); |