2 * fribidi-main.c - command line program for libfribidi
4 * $Id: fribidi-main.c,v 1.15 2006-01-31 03:23:12 behdad Exp $
6 * $Date: 2006-01-31 03:23:12 $
8 * $Source: /home/behdad/src/fdo/fribidi/togit/git/../fribidi/fribidi2/bin/fribidi-main.c,v $
11 * Behdad Esfahbod, 2001, 2002, 2004
12 * Dov Grobgeld, 1999, 2000
14 * Copyright (C) 2004 Sharif FarsiWeb, Inc
15 * Copyright (C) 2001,2002 Behdad Esfahbod
16 * Copyright (C) 1999,2000 Dov Grobgeld
18 * This library is free software; you can redistribute it and/or
19 * modify it under the terms of the GNU Lesser General Public
20 * License as published by the Free Software Foundation; either
21 * version 2.1 of the License, or (at your option) any later version.
23 * This library is distributed in the hope that it will be useful,
24 * but WITHOUT ANY WARRANTY; without even the implied warranty of
25 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
26 * Lesser General Public License for more details.
28 * You should have received a copy of the GNU Lesser General Public License
29 * along with this library, in a file named COPYING; if not, write to the
30 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
31 * Boston, MA 02110-1301, USA
33 * For licensing issues, contact <license@farsiweb.info>.
39 #if FRIBIDI_CHARSETS+0
41 # if FRIBIDI_MAIN_USE_ICONV_H
43 # else /* !FRIBIDI_MAIN_USE_ICONV_H */
44 # include <fribidi-char-sets.h>
45 # endif /* FRIBIDI_MAIN_USE_ICONV_H */
46 #endif /* !FRIBIDI_CHARSETS */
58 # if STDC_HEADERS && HAVE_MEMORY_H
70 #define appname "fribidi"
72 #define MAX_STR_LEN 65000
75 #define ALLOCATE(tp,ln) ((tp *) fribidi_malloc (sizeof (tp) * (ln)))
83 fprintf (stderr, "%s: ", appname);
85 fprintf (stderr, fmt, arg);
86 fprintf (stderr, "Try `%s --help' for more information.\n", appname);
90 #define die1(msg) die2("%s", msg)
92 fribidi_boolean do_break, do_pad, do_mirror, do_reorder_nsm, do_clean;
93 fribidi_boolean show_input, show_visual, show_basedir;
94 fribidi_boolean show_ltov, show_vtol, show_levels;
95 const int default_text_width = 80;
98 const char *bol_text, *eol_text;
99 FriBidiParType input_base_direction;
100 #if FRIBIDI_MAIN_USE_ICONV_H+0
101 iconv_t to_ucs4, from_ucs4;
102 #else /* !FRIBIDI_MAIN_USE_ICONV_H */
104 #endif /* !FRIBIDI_MAIN_USE_ICONV_H */
111 /* Break help string into little ones, to assure ISO C89 conformance */
112 printf ("Usage: " appname " [OPTION]... [FILE]...\n"
113 "A command line interface for the " FRIBIDI_NAME " library.\n"
114 "Convert a logical string to visual.\n"
116 " -h, --help Display this information and exit\n"
117 " -V, --version Display version information and exit\n"
118 " -v, --verbose Verbose mode, same as --basedir --ltov --vtol\n"
119 " --levels --changes\n");
120 printf (" -d, --debug Output debug information\n"
121 " -t, --test Test " FRIBIDI_NAME
122 ", same as --clean --nobreak\n"
123 " --showinput --reordernsm --width %d\n",
125 #if FRIBIDI_MAIN_USE_ICONV_H+0
126 printf (" -c, --charset CS Specify character set, default is %s.\n"
127 " CS should be a valid iconv character set name\n",
129 #else /* !FRIBIDI_MAIN_USE_ICONV_H */
130 printf (" -c, --charset CS Specify character set, default is %s\n"
131 " --charsetdesc CS Show descriptions for character set CS and exit\n"
132 " --caprtl Old style: set character set to CapRTL\n",
134 #endif /* !FRIBIDI_MAIN_USE_ICONV_H */
135 printf (" --showinput Output the input string too\n"
136 " --nopad Do not right justify RTL lines\n"
137 " --nobreak Do not break long lines\n"
138 " -w, --width W Screen width for padding, default is %d, but if\n"
139 " environment variable COLUMNS is defined, its value\n"
140 " will be used, --width overrides both of them.\n",
143 (" -B, --bol BOL Output string BOL before the visual string\n"
144 " -E, --eol EOL Output string EOL after the visual string\n"
145 " --rtl Force base direction to RTL\n"
146 " --ltr Force base direction to LTR\n"
147 " --wrtl Set base direction to RTL if no strong character found\n");
149 (" --wltr Set base direction to LTR if no strong character found\n"
151 " --nomirror Turn mirroring off, to do it later\n"
152 " --reordernsm Reorder NSM sequences to follow their base character\n"
153 " --clean Remove explicit format codes in visual string\n"
154 " output, currently does not affect other outputs\n"
155 " --basedir Output Base Direction\n");
156 printf (" --ltov Output Logical to Visual position map\n"
157 " --vtol Output Visual to Logical position map\n"
158 " --levels Output Embedding Levels\n"
159 " --novisual Do not output the visual string, to be used with\n"
160 " --basedir, --ltov, --vtol, --levels, --changes\n");
161 printf (" All string indexes are zero based\n" "\n" "Output:\n"
162 " For each line of input, output something like this:\n"
163 " [input-str` => '][BOL][[padding space]visual-str][EOL]\n"
164 " [\\n base-dir][\\n ltov-map][\\n vtol-map][\\n levels][\\n changes]\n");
166 #if FRIBIDI_MAIN_USE_ICONV_H+0
170 printf ("\n" "Available character sets:\n");
171 for (i = 1; i <= FRIBIDI_CHAR_SETS_NUM; i++)
172 printf (" * %-10s: %-25s%1s\n",
173 fribidi_char_set_name (i), fribidi_char_set_title (i),
174 (fribidi_char_set_desc (i) ? "X" : ""));
176 (" X: Character set has descriptions, use --charsetdesc to see\n");
178 #endif /* !FRIBIDI_MAIN_USE_ICONV_H */
180 printf ("\nReport bugs online at\n<" FRIBIDI_BUGREPORT ">.\n");
189 printf (appname " %s", fribidi_version_info);
200 m = fribidi_malloc (strlen (s) + 1);
216 fribidi_boolean file_found;
220 text_width = default_text_width;
225 do_reorder_nsm = false;
228 show_basedir = false;
235 input_base_direction = FRIBIDI_PAR_ON;
237 if ((s = (char *) getenv ("COLUMNS")))
246 #define CHARSETDESC 257
249 /* Parse the command line with getopt library */
250 /* Must set argv[0], getopt uses it to generate error messages */
254 int option_index = 0, c;
255 static struct option long_options[] = {
257 {"version", 0, 0, 'V'},
258 {"verbose", 0, 0, 'v'},
259 {"debug", 0, 0, 'd'},
261 {"charset", 1, 0, 'c'},
262 #if FRIBIDI_MAIN_USE_ICONV_H+0
264 {"charsetdesc", 1, 0, CHARSETDESC},
265 {"caprtl", 0, 0, CAPRTL},
266 #endif /* FRIBIDI_MAIN_USE_ICONV_H */
267 {"showinput", 0, (int *) (void *) &show_input, true},
268 {"nopad", 0, (int *) (void *) &do_pad, false},
269 {"nobreak", 0, (int *) (void *) &do_break, false},
270 {"width", 1, 0, 'w'},
273 {"nomirror", 0, (int *) (void *) &do_mirror, false},
274 {"reordernsm", 0, (int *) (void *) &do_reorder_nsm, true},
275 {"clean", 0, (int *) (void *) &do_clean, true},
276 {"ltr", 0, (int *) (void *) &input_base_direction, FRIBIDI_PAR_LTR},
277 {"rtl", 0, (int *) (void *) &input_base_direction, FRIBIDI_PAR_RTL},
278 {"wltr", 0, (int *) (void *) &input_base_direction,
280 {"wrtl", 0, (int *) (void *) &input_base_direction,
282 {"basedir", 0, (int *) (void *) &show_basedir, true},
283 {"ltov", 0, (int *) (void *) &show_ltov, true},
284 {"vtol", 0, (int *) (void *) &show_vtol, true},
285 {"levels", 0, (int *) (void *) &show_levels, true},
286 {"novisual", 0, (int *) (void *) &show_visual, false},
291 getopt_long (argc, argv, "hVvdtc:w:B:E:", long_options,
307 show_basedir = show_ltov = show_vtol = show_levels = true;
310 text_width = atoi (optarg);
312 die2 ("invalid screen width `%s'\n", optarg);
321 if (!fribidi_set_debug (true))
324 " must be compiled with DEBUG option to enable\nturn debug info on.\n");
327 do_clean = show_input = do_reorder_nsm = true;
329 text_width = default_text_width;
332 char_set = my_fribidi_strdup (optarg);
334 die1 ("memory allocation failed for char_set!");
336 #if FRIBIDI_MAIN_USE_ICONV_H+0
343 char_set_num = fribidi_parse_charset (char_set);
345 die2 ("unrecognized character set `%s'\n", char_set);
346 if (!fribidi_char_set_desc (char_set_num))
347 die2 ("no description available for character set `%s'\n",
348 fribidi_char_set_name (char_set_num));
350 printf ("Descriptions for character set %s:\n"
351 "\n" "%s", fribidi_char_set_title (char_set_num),
352 fribidi_char_set_desc (char_set_num));
355 #endif /* !FRIBIDI_MAIN_USE_ICONV_H */
365 #if FRIBIDI_MAIN_USE_ICONV_H+0
366 to_ucs4 = iconv_open ("WCHAR_T", char_set);
367 from_ucs4 = iconv_open (char_set, "WCHAR_T");
368 #else /* !FRIBIDI_MAIN_USE_ICONV_H */
369 char_set_num = fribidi_parse_charset (char_set);
370 #endif /* !FRIBIDI_MAIN_USE_ICONV_H */
372 #if FRIBIDI_MAIN_USE_ICONV_H+0
373 if (to_ucs4 == (iconv_t) (-1) || from_ucs4 == (iconv_t) (-1))
374 #else /* !FRIBIDI_MAIN_USE_ICONV_H */
376 #endif /* !FRIBIDI_MAIN_USE_ICONV_H */
377 die2 ("unrecognized character set `%s'\n", char_set);
379 fribidi_set_mirroring (do_mirror);
380 fribidi_set_reorder_nsm (do_reorder_nsm);
383 while (optind < argc || !file_found)
385 const char *filename;
387 filename = optind < argc ? argv[optind++] : "-";
390 /* Open the infile for reading */
391 if (filename[0] == '-' && !filename[1])
397 IN = fopen (filename, "r");
400 fprintf (stderr, "%s: %s: no such file or directory\n",
407 /* Read and process input one line at a time */
409 char S_[MAX_STR_LEN];
410 int padding_width, break_width;
412 padding_width = show_input ? (text_width - 10) / 2 : text_width;
413 break_width = do_break ? padding_width : 3 * MAX_STR_LEN;
415 while (fgets (S_, sizeof (S_) - 1, IN))
417 const char *new_line, *nl_found;
418 FriBidiChar logical[MAX_STR_LEN];
419 char outstring[MAX_STR_LEN];
424 S_[sizeof (S_) - 1] = 0;
427 if (S_[len - 1] == '\n')
435 /* TODO: handle \r */
437 #if FRIBIDI_MAIN_USE_ICONV_H+0
439 char *st = S_, *ust = (char *) logical;
440 int in_len = (int) len;
441 len = sizeof logical;
442 iconv (to_ucs4, &st, &in_len, &ust, (int *) &len);
443 len = (FriBidiChar *) ust - logical;
445 #else /* !FRIBIDI_MAIN_USE_ICONV_H */
446 len = fribidi_charset_to_unicode (char_set_num, S_, len, logical);
447 #endif /* !FRIBIDI_MAIN_USE_ICONV_H */
451 FriBidiStrIndex *ltov, *vtol;
452 FriBidiLevel *levels;
453 FriBidiStrIndex new_len;
454 fribidi_boolean log2vis;
456 visual = show_visual ? ALLOCATE (FriBidiChar,
459 ltov = show_ltov ? ALLOCATE (FriBidiStrIndex,
462 vtol = show_vtol ? ALLOCATE (FriBidiStrIndex,
465 levels = show_levels ? ALLOCATE (FriBidiLevel,
469 /* Create a bidi string. */
470 base = input_base_direction;
471 log2vis = fribidi_log2vis (logical, len, &base,
473 visual, ltov, vtol, levels);
478 printf ("%-*s => ", padding_width, S_);
482 /* Remove explicit marks, if asked for. */
485 fribidi_remove_bidi_marks (visual, len, ltov, vtol,
490 printf ("%s", nl_found);
493 printf ("%s", bol_text);
495 /* Convert it to input charset and print. */
497 FriBidiStrIndex idx, st;
498 for (idx = 0; idx < len;)
500 FriBidiStrIndex wid, inlen;
504 #if FRIBIDI_MAIN_USE_ICONV_H+0
506 if (char_set_num != FRIBIDI_CHAR_SET_CAP_RTL)
507 #endif /* !FRIBIDI_MAIN_USE_ICONV_H */
508 while (wid > 0 && idx < len)
511 FRIBIDI_IS_EXPLICIT_OR_BN_OR_NSM
512 (fribidi_get_bidi_type (visual[idx])) ? 0
516 #if FRIBIDI_MAIN_USE_ICONV_H+0
519 while (wid > 0 && idx < len)
524 #endif /* !FRIBIDI_MAIN_USE_ICONV_H */
525 if (wid < 0 && idx - st > 1)
529 #if FRIBIDI_MAIN_USE_ICONV_H+0
531 char *str = outstring, *ust =
532 (char *) (visual + st);
533 int in_len = inlen * sizeof visual[0];
534 new_len = sizeof outstring;
535 iconv (from_ucs4, &ust, &in_len, &str,
538 new_len = str - outstring;
540 #else /* !FRIBIDI_MAIN_USE_ICONV_H */
542 fribidi_unicode_to_charset (char_set_num,
545 #endif /* !FRIBIDI_MAIN_USE_ICONV_H */
546 if (FRIBIDI_IS_RTL (base))
548 (int) (do_pad ? (padding_width +
554 printf ("%s", outstring);
560 printf ("%s", eol_text);
566 printf ("%s", nl_found);
567 printf ("Base direction: %s",
568 (FRIBIDI_DIR_TO_LEVEL (base) ? "R" : "L"));
575 printf ("%s", nl_found);
576 for (i = 0; i < len; i++)
577 printf ("%ld ", (long) ltov[i]);
584 printf ("%s", nl_found);
585 for (i = 0; i < len; i++)
586 printf ("%ld ", (long) vtol[i]);
593 printf ("%s", nl_found);
594 for (i = 0; i < len; i++)
595 printf ("%d ", (int) levels[i]);
615 printf ("%s", new_line);
623 /* Editor directions:
624 * vim:textwidth=78:tabstop=8:shiftwidth=2:autoindent:cindent