summaryrefslogtreecommitdiff
path: root/frm
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2005-02-28 21:22:05 +0000
committerSergey Poznyakoff <gray@gnu.org.ua>2005-02-28 21:22:05 +0000
commit0575858a61c4ffcdb4fad7bae6853992e3d43913 (patch)
tree63751a7026f5d1c041b6820b09828b80196698b1 /frm
parent8206377e1bf56a5a86ec18e16e226d808d6123b8 (diff)
downloadmailutils-0575858a61c4ffcdb4fad7bae6853992e3d43913.tar.gz
mailutils-0575858a61c4ffcdb4fad7bae6853992e3d43913.tar.bz2
Rewritten output routines using FriBidi. Arabic
subject lines look almost OK, except that all characters are displayed in isolated variant.
Diffstat (limited to 'frm')
-rw-r--r--frm/frm.c469
1 files changed, 307 insertions, 162 deletions
diff --git a/frm/frm.c b/frm/frm.c
index 576d061ce..73078da93 100644
--- a/frm/frm.c
+++ b/frm/frm.c
@@ -42,6 +42,10 @@
42#include <mbswidth.h> 42#include <mbswidth.h>
43#include <xalloc.h> 43#include <xalloc.h>
44 44
45#ifdef HAVE_FRIBIDI_FRIBIDI_H
46# include <fribidi/fribidi.h>
47#endif
48
45#include <mailutils/address.h> 49#include <mailutils/address.h>
46#include <mailutils/argp.h> 50#include <mailutils/argp.h>
47#include <mailutils/attribute.h> 51#include <mailutils/attribute.h>
@@ -80,6 +84,7 @@ static int select_attribute;
80static int selected; 84static int selected;
81 85
82static int action (observer_t, size_t); 86static int action (observer_t, size_t);
87void init_output (size_t s);
83 88
84const char *program_version = "frm (" PACKAGE_STRING ")"; 89const char *program_version = "frm (" PACKAGE_STRING ")";
85static char doc[] = N_("GNU frm -- display From: lines"); 90static char doc[] = N_("GNU frm -- display From: lines");
@@ -182,6 +187,36 @@ decode_attr (char *arg)
182 187
183 188
184 189
190/* Get the number of columns on the screen
191 First try an ioctl() call, not all shells set the COLUMNS environ.
192 If ioctl does not succeed on stdout, try it on /dev/tty, as we
193 may work via a pipe.
194
195 This function was taken from mail/util.c. It should probably reside
196 in the library */
197int
198util_getcols (void)
199{
200 struct winsize ws;
201
202 ws.ws_col = ws.ws_row = 0;
203 if (ioctl (1, TIOCGWINSZ, (char *) &ws) < 0)
204 {
205 int fd = open ("/dev/tty", O_RDWR);
206 ioctl (fd, TIOCGWINSZ, (char *) &ws);
207 close (fd);
208 }
209 if (ws.ws_row == 0)
210 {
211 const char *columns = getenv ("COLUMNS");
212 if (columns)
213 ws.ws_col = strtol (columns, NULL, 10);
214 }
215 return ws.ws_col;
216}
217
218
219
185static struct argp_option options[] = { 220static struct argp_option options[] = {
186 {"debug", 'd', NULL, 0, N_("Enable debugging output"), 0}, 221 {"debug", 'd', NULL, 0, N_("Enable debugging output"), 0},
187 {"field", 'f', N_("NAME"), 0, N_("Header field to display"), 0}, 222 {"field", 'f', N_("NAME"), 0, N_("Header field to display"), 0},
@@ -195,6 +230,237 @@ static struct argp_option options[] = {
195 {0, 0, 0, 0} 230 {0, 0, 0, 0}
196}; 231};
197 232
233static error_t
234parse_opt (int key, char *arg, struct argp_state *state)
235{
236 switch (key)
237 {
238 case 'd':
239 dbug++;
240 break;
241
242 case 'f':
243 show_field = arg;
244 align = 0;
245 break;
246
247 case 'l':
248 show_to = 1;
249 break;
250
251 case 'n':
252 show_number = 1;
253 break;
254
255 case 'Q':
256 /* Very silent. */
257 be_quiet += 2;
258 break;
259
260 case 'q':
261 be_quiet++;
262 show_query = 1;
263 break;
264
265 case 'S':
266 show_summary = 1;
267 break;
268
269 case 's':
270 select_attribute = decode_attr (arg);
271 break;
272
273 case 't':
274 align = 1;
275 break;
276
277 case ARGP_KEY_FINI:
278 {
279 size_t s;
280 if (align && (s = util_getcols ()))
281 init_output (s);
282 else
283 init_output (0);
284 }
285 break;
286
287 default:
288 return ARGP_ERR_UNKNOWN;
289 }
290 return 0;
291}
292
293static struct argp argp = {
294 options,
295 parse_opt,
296 N_("[URL ...]"),
297 doc,
298 NULL,
299 NULL, NULL
300};
301
302static const char *frm_argp_capa[] = {
303 "common",
304 "license",
305 "mailbox",
306#ifdef WITH_TLS
307 "tls",
308#endif
309 NULL
310};
311
312
313/* Charset magic */
314static char *output_charset = NULL;
315
316const char *
317get_charset ()
318{
319 char *tmp;
320
321 if (!output_charset)
322 {
323 char locale[32];
324
325 memset (locale, 0, sizeof (locale));
326
327 /* Try to deduce the charset from LC_ALL or LANG variables */
328
329 tmp = getenv ("LC_ALL");
330 if (!tmp)
331 tmp = getenv ("LANG");
332
333 if (tmp)
334 {
335 char *sp = NULL;
336 char *lang;
337 char *terr;
338
339 strncpy (locale, tmp, sizeof (locale) - 1);
340
341 lang = strtok_r (locale, "_", &sp);
342 terr = strtok_r (NULL, ".", &sp);
343 output_charset = strtok_r (NULL, "@", &sp);
344
345 if (output_charset)
346 output_charset = xstrdup (output_charset);
347 else
348 output_charset = mu_charset_lookup (lang, terr);
349
350 if (!output_charset)
351 output_charset = "ASCII";
352 }
353 }
354 return output_charset;
355}
356
357
358/* BIDI support (will be moved to lib when it's ready) */
359#ifdef HAVE_LIBFRIBIDI
360
361static int fb_charset_num = -1;
362FriBidiChar *logical;
363char *outstring;
364size_t logical_size;
365
366void
367alloc_logical (size_t size)
368{
369 logical = xmalloc (size * sizeof (logical[0]));
370 logical_size = size;
371 outstring = xmalloc (size);
372}
373
374void
375puts_bidi (char *string)
376{
377 if (fb_charset_num == -1)
378 {
379 fb_charset_num = fribidi_parse_charset (get_charset ());
380 if (fb_charset_num && dbug)
381 mu_error (_("fribidi failed to recognize charset `%s'"),
382 get_charset ());
383 }
384
385 if (fb_charset_num == 0)
386 puts (string);
387 else
388 {
389 FriBidiStrIndex len;
390 FriBidiCharType base = FRIBIDI_TYPE_ON;
391 fribidi_boolean log2vis;
392
393 static FriBidiChar *visual;
394 static size_t visual_size;
395
396
397 len = fribidi_charset_to_unicode (fb_charset_num,
398 string, strlen (string),
399 logical);
400
401 if (len + 1 > visual_size)
402 {
403 visual_size = len + 1;
404 visual = xrealloc (visual, visual_size * sizeof *visual);
405 }
406
407 /* Create a bidi string. */
408 log2vis = fribidi_log2vis (logical, len, &base,
409 /* output */
410 visual, NULL, NULL, NULL);
411
412 if (log2vis)
413 {
414 FriBidiStrIndex idx, st;