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;
97 const char *bol_text, *eol_text;
98 FriBidiParType input_base_direction;
99 #if FRIBIDI_MAIN_USE_ICONV_H+0
100 iconv_t to_ucs4, from_ucs4;
101 #else /* !FRIBIDI_MAIN_USE_ICONV_H */
103 #endif /* !FRIBIDI_MAIN_USE_ICONV_H */
110 /* Break help string into little ones, to assure ISO C89 conformance */
111 printf ("Usage: " appname " [OPTION]... [FILE]...\n"
112 "A command line interface for the " FRIBIDI_NAME " library.\n"
113 "Convert a logical string to visual.\n"
115 " -h, --help Display this information and exit\n"
116 " -V, --version Display version information and exit\n"
117 " -v, --verbose Verbose mode, same as --basedir --ltov --vtol\n"
118 " --levels --changes\n");
119 printf (" -d, --debug Output debug information\n"
120 " -t, --test Test " FRIBIDI_NAME
121 ", same as --clean --nobreak\n"
122 " --showinput --reordernsm\n");
123 #if FRIBIDI_MAIN_USE_ICONV_H+0
124 printf (" -c, --charset CS Specify character set, default is %s.\n"
125 " CS should be a valid iconv character set name\n",
127 #else /* !FRIBIDI_MAIN_USE_ICONV_H */
128 printf (" -c, --charset CS Specify character set, default is %s\n"
129 " --charsetdesc CS Show descriptions for character set CS and exit\n"
130 " --caprtl Old style: set character set to CapRTL\n",
132 #endif /* !FRIBIDI_MAIN_USE_ICONV_H */
133 printf (" --showinput Output the input string too\n"
134 " --nopad Do not right justify RTL lines\n"
135 " --nobreak Do not break long lines\n"
136 " -w, --width W Screen width for padding, default is %d, but if\n"
137 " environment variable COLUMNS is defined, its value\n"
138 " will be used, --width overrides both of them.\n",
141 (" -B, --bol BOL Output string BOL before the visual string\n"
142 " -E, --eol EOL Output string EOL after the visual string\n"
143 " --rtl Force base direction to RTL\n"
144 " --ltr Force base direction to LTR\n"
145 " --wrtl Set base direction to RTL if no strong character found\n");
147 (" --wltr Set base direction to LTR if no strong character found\n"
149 " --nomirror Turn mirroring off, to do it later\n"
150 " --reordernsm Reorder NSM sequences to follow their base character\n"
151 " --clean Remove explicit format codes in visual string\n"
152 " output, currently does not affect other outputs\n"
153 " --basedir Output Base Direction\n");
154 printf (" --ltov Output Logical to Visual position map\n"
155 " --vtol Output Visual to Logical position map\n"
156 " --levels Output Embedding Levels\n"
157 " --novisual Do not output the visual string, to be used with\n"
158 " --basedir, --ltov, --vtol, --levels, --changes\n");
159 printf (" All string indexes are zero based\n" "\n" "Output:\n"
160 " For each line of input, output something like this:\n"
161 " [input-str` => '][BOL][[padding space]visual-str][EOL]\n"
162 " [\\n base-dir][\\n ltov-map][\\n vtol-map][\\n levels][\\n changes]\n");
164 #if FRIBIDI_MAIN_USE_ICONV_H+0
168 printf ("\n" "Available character sets:\n");
169 for (i = 1; i <= FRIBIDI_CHAR_SETS_NUM; i++)
170 printf (" * %-10s: %-25s%1s\n",
171 fribidi_char_set_name (i), fribidi_char_set_title (i),
172 (fribidi_char_set_desc (i) ? "X" : ""));
174 (" X: Character set has descriptions, use --charsetdesc to see\n");
176 #endif /* !FRIBIDI_MAIN_USE_ICONV_H */
178 printf ("\nReport bugs online at\n<" FRIBIDI_BUGREPORT ">.\n");
187 printf (appname " %s", fribidi_version_info);
198 m = fribidi_malloc (strlen (s) + 1);
214 fribidi_boolean file_found;
223 do_reorder_nsm = false;
226 show_basedir = false;
233 input_base_direction = FRIBIDI_PAR_ON;
235 if ((s = (char *) getenv ("COLUMNS")))
244 #define CHARSETDESC 257
247 /* Parse the command line with getopt library */
248 /* Must set argv[0], getopt uses it to generate error messages */
252 int option_index = 0, c;
253 static struct option long_options[] = {
255 {"version", 0, 0, 'V'},
256 {"verbose", 0, 0, 'v'},
257 {"debug", 0, 0, 'd'},
259 {"charset", 1, 0, 'c'},
260 #if FRIBIDI_MAIN_USE_ICONV_H+0
262 {"charsetdesc", 1, 0, CHARSETDESC},
263 {"caprtl", 0, 0, CAPRTL},
264 #endif /* FRIBIDI_MAIN_USE_ICONV_H */
265 {"showinput", 0, (int *) (void *) &show_input, true},
266 {"nopad", 0, (int *) (void *) &do_pad, false},
267 {"nobreak", 0, (int *) (void *) &do_break, false},
268 {"width", 1, 0, 'w'},
271 {"nomirror", 0, (int *) (void *) &do_mirror, false},
272 {"reordernsm", 0, (int *) (void *) &do_reorder_nsm, true},
273 {"clean", 0, (int *) (void *) &do_clean, true},
274 {"ltr", 0, (int *) (void *) &input_base_direction, FRIBIDI_PAR_LTR},
275 {"rtl", 0, (int *) (void *) &input_base_direction, FRIBIDI_PAR_RTL},
276 {"wltr", 0, (int *) (void *) &input_base_direction,
278 {"wrtl", 0, (int *) (void *) &input_base_direction,
280 {"basedir", 0, (int *) (void *) &show_basedir, true},
281 {"ltov", 0, (int *) (void *) &show_ltov, true},
282 {"vtol", 0, (int *) (void *) &show_vtol, true},
283 {"levels", 0, (int *) (void *) &show_levels, true},
284 {"novisual", 0, (int *) (void *) &show_visual, false},
289 getopt_long (argc, argv, "hVvdtc:w:B:E:", long_options,
305 show_basedir = show_ltov = show_vtol = show_levels = true;
308 text_width = atoi (optarg);
310 die2 ("invalid screen width `%s'\n", optarg);
319 if (!fribidi_set_debug (true))
322 " must be compiled with DEBUG option to enable\nturn debug info on.\n");
325 do_clean = show_input = do_reorder_nsm = true;
329 char_set = my_fribidi_strdup (optarg);
331 die1 ("memory allocation failed for char_set!");
333 #if FRIBIDI_MAIN_USE_ICONV_H+0
340 char_set_num = fribidi_parse_charset (char_set);
342 die2 ("unrecognized character set `%s'\n", char_set);
343 if (!fribidi_char_set_desc (char_set_num))
344 die2 ("no description available for character set `%s'\n",
345 fribidi_char_set_name (char_set_num));
347 printf ("Descriptions for character set %s:\n"
348 "\n" "%s", fribidi_char_set_title (char_set_num),
349 fribidi_char_set_desc (char_set_num));
352 #endif /* !FRIBIDI_MAIN_USE_ICONV_H */
362 #if FRIBIDI_MAIN_USE_ICONV_H+0
363 to_ucs4 = iconv_open ("WCHAR_T", char_set);
364 from_ucs4 = iconv_open (char_set, "WCHAR_T");
365 #else /* !FRIBIDI_MAIN_USE_ICONV_H */
366 char_set_num = fribidi_parse_charset (char_set);
367 #endif /* !FRIBIDI_MAIN_USE_ICONV_H */
369 #if FRIBIDI_MAIN_USE_ICONV_H+0
370 if (to_ucs4 == (iconv_t) (-1) || from_ucs4 == (iconv_t) (-1))
371 #else /* !FRIBIDI_MAIN_USE_ICONV_H */
373 #endif /* !FRIBIDI_MAIN_USE_ICONV_H */
374 die2 ("unrecognized character set `%s'\n", char_set);
376 fribidi_set_mirroring (do_mirror);
377 fribidi_set_reorder_nsm (do_reorder_nsm);
380 while (optind < argc || !file_found)
382 const char *filename;
384 filename = optind < argc ? argv[optind++] : "-";
387 /* Open the infile for reading */
388 if (filename[0] == '-' && !filename[1])
394 IN = fopen (filename, "r");
397 fprintf (stderr, "%s: %s: no such file or directory\n",
404 /* Read and process input one line at a time */
406 char S_[MAX_STR_LEN];
407 int padding_width, break_width;
409 padding_width = show_input ? (text_width - 10) / 2 : text_width;
410 break_width = do_break ? padding_width : 3 * MAX_STR_LEN;
412 while (fgets (S_, sizeof (S_) - 1, IN))
414 const char *new_line, *nl_found;
415 FriBidiChar logical[MAX_STR_LEN];
416 char outstring[MAX_STR_LEN];
421 S_[sizeof (S_) - 1] = 0;
424 if (S_[len - 1] == '\n')
432 /* TODO: handle \r */
434 #if FRIBIDI_MAIN_USE_ICONV_H+0
436 char *st = S_, *ust = (char *) logical;
437 int in_len = (int) len;
438 len = sizeof logical;
439 iconv (to_ucs4, &st, &in_len, &ust, (int *) &len);
440 len = (FriBidiChar *) ust - logical;
442 #else /* !FRIBIDI_MAIN_USE_ICONV_H */
443 len = fribidi_charset_to_unicode (char_set_num, S_, len, logical);
444 #endif /* !FRIBIDI_MAIN_USE_ICONV_H */
448 FriBidiStrIndex *ltov, *vtol;
449 FriBidiLevel *levels;
450 FriBidiStrIndex new_len;
451 fribidi_boolean log2vis;
453 visual = show_visual ? ALLOCATE (FriBidiChar,
456 ltov = show_ltov ? ALLOCATE (FriBidiStrIndex,
459 vtol = show_vtol ? ALLOCATE (FriBidiStrIndex,
462 levels = show_levels ? ALLOCATE (FriBidiLevel,
466 /* Create a bidi string. */
467 base = input_base_direction;
468 log2vis = fribidi_log2vis (logical, len, &base,
470 visual, ltov, vtol, levels);
475 printf ("%-*s => ", padding_width, S_);
479 /* Remove explicit marks, if asked for. */
482 fribidi_remove_bidi_marks (visual, len, ltov, vtol,
487 printf ("%s", nl_found);
490 printf ("%s", bol_text);
492 /* Convert it to input charset and print. */
494 FriBidiStrIndex idx, st;
495 for (idx = 0; idx < len;)
497 FriBidiStrIndex wid, inlen;
501 #if FRIBIDI_MAIN_USE_ICONV_H+0
503 if (char_set_num != FRIBIDI_CHAR_SET_CAP_RTL)
504 #endif /* !FRIBIDI_MAIN_USE_ICONV_H */
505 while (wid > 0 && idx < len)
508 FRIBIDI_IS_EXPLICIT_OR_BN_OR_NSM
509 (fribidi_get_bidi_type (visual[idx])) ? 0
513 #if FRIBIDI_MAIN_USE_ICONV_H+0
516 while (wid > 0 && idx < len)
521 #endif /* !FRIBIDI_MAIN_USE_ICONV_H */
522 if (wid < 0 && idx > st + 1)
526 #if FRIBIDI_MAIN_USE_ICONV_H+0
528 char *str = outstring, *ust =
529 (char *) (visual + st);
530 int in_len = inlen * sizeof visual[0];
531 new_len = sizeof outstring;
532 iconv (from_ucs4, &ust, &in_len, &str,
535 new_len = str - outstring;
537 #else /* !FRIBIDI_MAIN_USE_ICONV_H */
539 fribidi_unicode_to_charset (char_set_num,
542 #endif /* !FRIBIDI_MAIN_USE_ICONV_H */
543 if (FRIBIDI_IS_RTL (base))
545 (int) (do_pad ? (padding_width +
551 printf ("%s", outstring);
557 printf ("%s", eol_text);
563 printf ("%s", nl_found);
564 printf ("Base direction: %s",
565 (FRIBIDI_DIR_TO_LEVEL (base) ? "R" : "L"));
572 printf ("%s", nl_found);
573 for (i = 0; i < len; i++)
574 printf ("%ld ", (long) ltov[i]);
581 printf ("%s", nl_found);
582 for (i = 0; i < len; i++)
583 printf ("%ld ", (long) vtol[i]);
590 printf ("%s", nl_found);
591 for (i = 0; i < len; i++)
592 printf ("%d ", (int) levels[i]);
620 /* Editor directions:
621 * vim:textwidth=78:tabstop=8:shiftwidth=2:autoindent:cindent