2 * fribidi-main.c - command line program for libfribidi
5 * Behdad Esfahbod, 2001, 2002, 2004
6 * Dov Grobgeld, 1999, 2000
8 * Copyright (C) 2004 Sharif FarsiWeb, Inc
9 * Copyright (C) 2001,2002 Behdad Esfahbod
10 * Copyright (C) 1999,2000 Dov Grobgeld
12 * This library is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU Lesser General Public
14 * License as published by the Free Software Foundation; either
15 * version 2.1 of the License, or (at your option) any later version.
17 * This library is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * Lesser General Public License for more details.
22 * You should have received a copy of the GNU Lesser General Public License
23 * along with this library, in a file named COPYING; if not, write to the
24 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
25 * Boston, MA 02110-1301, USA
27 * For licensing issues, contact <fribidi.license@gmail.com>.
33 #include <fribidi-deprecated.h>
45 # if STDC_HEADERS && HAVE_MEMORY_H
57 #define appname "fribidi"
59 #define MAX_STR_LEN 65000
62 #define ALLOCATE(tp,ln) ((tp *) fribidi_malloc (sizeof (tp) * (ln)))
70 fprintf (stderr, "%s: ", appname);
72 fprintf (stderr, fmt, arg);
73 fprintf (stderr, "Try `%s --help' for more information.\n", appname);
77 #define die1(msg) die2("%s", msg)
79 fribidi_boolean do_break, do_pad, do_mirror, do_reorder_nsm, do_clean;
80 fribidi_boolean show_input, show_visual, show_basedir;
81 fribidi_boolean show_ltov, show_vtol, show_levels;
82 const int default_text_width = 80;
85 const char *bol_text, *eol_text;
86 FriBidiParType input_base_direction;
94 /* Break help string into little ones, to assure ISO C89 conformance */
95 printf ("Usage: " appname " [OPTION]... [FILE]...\n"
96 "A command line interface for the " FRIBIDI_NAME " library.\n"
97 "Convert a logical string to visual.\n"
99 " -h, --help Display this information and exit\n"
100 " -V, --version Display version information and exit\n"
101 " -v, --verbose Verbose mode, same as --basedir --ltov --vtol\n"
102 " --levels --changes\n");
103 printf (" -d, --debug Output debug information\n"
104 " -t, --test Test " FRIBIDI_NAME
105 ", same as --clean --nobreak\n"
106 " --showinput --reordernsm --width %d\n",
108 printf (" -c, --charset CS Specify character set, default is %s\n"
109 " --charsetdesc CS Show descriptions for character set CS and exit\n"
110 " --caprtl Old style: set character set to CapRTL\n",
112 printf (" --showinput Output the input string too\n"
113 " --nopad Do not right justify RTL lines\n"
114 " --nobreak Do not break long lines\n"
115 " -w, --width W Screen width for padding, default is %d, but if\n"
116 " environment variable COLUMNS is defined, its value\n"
117 " will be used, --width overrides both of them.\n",
120 (" -B, --bol BOL Output string BOL before the visual string\n"
121 " -E, --eol EOL Output string EOL after the visual string\n"
122 " --rtl Force base direction to RTL\n"
123 " --ltr Force base direction to LTR\n"
124 " --wrtl Set base direction to RTL if no strong character found\n");
126 (" --wltr Set base direction to LTR if no strong character found\n"
128 " --nomirror Turn mirroring off, to do it later\n"
129 " --reordernsm Reorder NSM sequences to follow their base character\n"
130 " --clean Remove explicit format codes in visual string\n"
131 " output, currently does not affect other outputs\n"
132 " --basedir Output Base Direction\n");
133 printf (" --ltov Output Logical to Visual position map\n"
134 " --vtol Output Visual to Logical position map\n"
135 " --levels Output Embedding Levels\n"
136 " --novisual Do not output the visual string, to be used with\n"
137 " --basedir, --ltov, --vtol, --levels, --changes\n");
138 printf (" All string indexes are zero based\n" "\n" "Output:\n"
139 " For each line of input, output something like this:\n"
140 " [input-str` => '][BOL][[padding space]visual-str][EOL]\n"
141 " [\\n base-dir][\\n ltov-map][\\n vtol-map][\\n levels][\\n changes]\n");
145 printf ("\n" "Available character sets:\n");
146 for (i = 1; i <= FRIBIDI_CHAR_SETS_NUM; i++)
147 printf (" * %-10s: %-25s%1s\n",
148 fribidi_char_set_name (i), fribidi_char_set_title (i),
149 (fribidi_char_set_desc (i) ? "X" : ""));
151 (" X: Character set has descriptions, use --charsetdesc to see\n");
154 printf ("\nReport bugs online at\n<" FRIBIDI_BUGREPORT ">.\n");
163 printf (appname " %s", fribidi_version_info);
174 m = fribidi_malloc (strlen (s) + 1);
190 fribidi_boolean file_found;
194 text_width = default_text_width;
199 do_reorder_nsm = false;
202 show_basedir = false;
209 input_base_direction = FRIBIDI_PAR_ON;
211 if ((s = (char *) getenv ("COLUMNS")))
220 #define CHARSETDESC 257
223 /* Parse the command line with getopt library */
224 /* Must set argv[0], getopt uses it to generate error messages */
228 int option_index = 0, c;
229 static struct option long_options[] = {
231 {"version", 0, 0, 'V'},
232 {"verbose", 0, 0, 'v'},
233 {"debug", 0, 0, 'd'},
235 {"charset", 1, 0, 'c'},
236 {"charsetdesc", 1, 0, CHARSETDESC},
237 {"caprtl", 0, 0, CAPRTL},
238 {"showinput", 0, (int *) (void *) &show_input, true},
239 {"nopad", 0, (int *) (void *) &do_pad, false},
240 {"nobreak", 0, (int *) (void *) &do_break, false},
241 {"width", 1, 0, 'w'},
244 {"nomirror", 0, (int *) (void *) &do_mirror, false},
245 {"reordernsm", 0, (int *) (void *) &do_reorder_nsm, true},
246 {"clean", 0, (int *) (void *) &do_clean, true},
247 {"ltr", 0, (int *) (void *) &input_base_direction, FRIBIDI_PAR_LTR},
248 {"rtl", 0, (int *) (void *) &input_base_direction, FRIBIDI_PAR_RTL},
249 {"wltr", 0, (int *) (void *) &input_base_direction,
251 {"wrtl", 0, (int *) (void *) &input_base_direction,
253 {"basedir", 0, (int *) (void *) &show_basedir, true},
254 {"ltov", 0, (int *) (void *) &show_ltov, true},
255 {"vtol", 0, (int *) (void *) &show_vtol, true},
256 {"levels", 0, (int *) (void *) &show_levels, true},
257 {"novisual", 0, (int *) (void *) &show_visual, false},
262 getopt_long (argc, argv, "hVvdtc:w:B:E:", long_options,
278 show_basedir = show_ltov = show_vtol = show_levels = true;
281 text_width = atoi (optarg);
283 die2 ("invalid screen width `%s'\n", optarg);
292 if (!fribidi_set_debug (true))
295 " must be compiled with DEBUG option to enable\nturn debug info on.\n");
298 do_clean = show_input = do_reorder_nsm = true;
300 text_width = default_text_width;
303 char_set = my_fribidi_strdup (optarg);
305 die1 ("memory allocation failed for char_set!");
312 char_set_num = fribidi_parse_charset (char_set);
314 die2 ("unrecognized character set `%s'\n", char_set);
315 if (!fribidi_char_set_desc (char_set_num))
316 die2 ("no description available for character set `%s'\n",
317 fribidi_char_set_name (char_set_num));
319 printf ("Descriptions for character set %s:\n"
320 "\n" "%s", fribidi_char_set_title (char_set_num),
321 fribidi_char_set_desc (char_set_num));
333 char_set_num = fribidi_parse_charset (char_set);
336 die2 ("unrecognized character set `%s'\n", char_set);
338 FRIBIDI_BEGIN_IGNORE_DEPRECATIONS
339 fribidi_set_mirroring (do_mirror);
340 fribidi_set_reorder_nsm (do_reorder_nsm);
341 FRIBIDI_END_IGNORE_DEPRECATIONS
344 while (optind < argc || !file_found)
346 const char *filename;
348 filename = optind < argc ? argv[optind++] : "-";
351 /* Open the infile for reading */
352 if (filename[0] == '-' && !filename[1])
358 IN = fopen (filename, "r");
361 fprintf (stderr, "%s: %s: no such file or directory\n",
368 /* Read and process input one line at a time */
370 char S_[MAX_STR_LEN];
371 int padding_width, break_width;
373 padding_width = show_input ? (text_width - 10) / 2 : text_width;
374 break_width = do_break ? padding_width : 3 * MAX_STR_LEN;
376 while (fgets (S_, sizeof (S_) - 1, IN))
378 const char *new_line, *nl_found;
379 FriBidiChar logical[MAX_STR_LEN];
380 char outstring[MAX_STR_LEN];
385 S_[sizeof (S_) - 1] = 0;
388 if (S_[len - 1] == '\n')
396 /* TODO: handle \r */
398 len = fribidi_charset_to_unicode (char_set_num, S_, len, logical);
402 FriBidiStrIndex *ltov, *vtol;
403 FriBidiLevel *levels;
404 fribidi_boolean log2vis;
406 visual = show_visual ? ALLOCATE (FriBidiChar,
409 ltov = show_ltov ? ALLOCATE (FriBidiStrIndex,
412 vtol = show_vtol ? ALLOCATE (FriBidiStrIndex,
415 levels = show_levels ? ALLOCATE (FriBidiLevel,
419 /* Create a bidi string. */
420 base = input_base_direction;
421 FRIBIDI_BEGIN_IGNORE_DEPRECATIONS
422 log2vis = fribidi_log2vis (logical, len, &base,
424 visual, ltov, vtol, levels);
425 FRIBIDI_END_IGNORE_DEPRECATIONS
430 printf ("%-*s => ", padding_width, S_);
432 /* Remove explicit marks, if asked for. */
433 FRIBIDI_BEGIN_IGNORE_DEPRECATIONS
436 fribidi_remove_bidi_marks (visual, len, ltov, vtol,
438 FRIBIDI_END_IGNORE_DEPRECATIONS
442 printf ("%s", nl_found);
445 printf ("%s", bol_text);
447 /* Convert it to input charset and print. */
449 FriBidiStrIndex idx, st;
450 for (idx = 0; idx < len;)
452 FriBidiStrIndex wid, inlen;
456 if (char_set_num != FRIBIDI_CHAR_SET_CAP_RTL)
457 while (wid > 0 && idx < len)
460 FRIBIDI_IS_EXPLICIT_OR_ISOLATE_OR_BN_OR_NSM
461 (fribidi_get_bidi_type (visual[idx])) ? 0
466 while (wid > 0 && idx < len)
471 if (wid < 0 && idx - st > 1)
475 fribidi_unicode_to_charset (char_set_num,
478 if (FRIBIDI_IS_RTL (base))
480 (int) (do_pad ? (padding_width +
486 printf ("%s", outstring);
492 printf ("%s", eol_text);
498 printf ("%s", nl_found);
499 printf ("Base direction: %s",
500 (FRIBIDI_DIR_TO_LEVEL (base) ? "R" : "L"));
507 printf ("%s", nl_found);
508 for (i = 0; i < len; i++)
509 printf ("%ld ", (long) ltov[i]);
516 printf ("%s", nl_found);
517 for (i = 0; i < len; i++)
518 printf ("%ld ", (long) vtol[i]);
525 printf ("%s", nl_found);
526 for (i = 0; i < len; i++)
527 printf ("%d ", (int) levels[i]);
547 printf ("%s", new_line);
555 /* Editor directions:
556 * vim:textwidth=78:tabstop=8:shiftwidth=2:autoindent:cindent