/** * pango_bidi_type_for_unichar: * @ch: a Unicode character * * Determines the normative bidirectional character type of a * character, as specified in the Unicode Character Database. * * A simplified version of this function is available as * pango_unichar_direction(). * * Return value: the bidirectional character type, as used in the * Unicode bidirectional algorithm. * * Since: 1.22 */ PangoBidiType pango_bidi_type_for_unichar (gunichar ch) { FriBidiCharType fribidi_ch_type; G_STATIC_ASSERT (sizeof (FriBidiChar) == sizeof (gunichar)); fribidi_ch_type = fribidi_get_bidi_type (ch); switch (fribidi_ch_type) { case FRIBIDI_TYPE_LTR: return PANGO_BIDI_TYPE_L; case FRIBIDI_TYPE_LRE: return PANGO_BIDI_TYPE_LRE; case FRIBIDI_TYPE_LRO: return PANGO_BIDI_TYPE_LRO; case FRIBIDI_TYPE_RTL: return PANGO_BIDI_TYPE_R; case FRIBIDI_TYPE_AL: return PANGO_BIDI_TYPE_AL; case FRIBIDI_TYPE_RLE: return PANGO_BIDI_TYPE_RLE; case FRIBIDI_TYPE_RLO: return PANGO_BIDI_TYPE_RLO; case FRIBIDI_TYPE_PDF: return PANGO_BIDI_TYPE_PDF; case FRIBIDI_TYPE_EN: return PANGO_BIDI_TYPE_EN; case FRIBIDI_TYPE_ES: return PANGO_BIDI_TYPE_ES; case FRIBIDI_TYPE_ET: return PANGO_BIDI_TYPE_ET; case FRIBIDI_TYPE_AN: return PANGO_BIDI_TYPE_AN; case FRIBIDI_TYPE_CS: return PANGO_BIDI_TYPE_CS; case FRIBIDI_TYPE_NSM: return PANGO_BIDI_TYPE_NSM; case FRIBIDI_TYPE_BN: return PANGO_BIDI_TYPE_BN; case FRIBIDI_TYPE_BS: return PANGO_BIDI_TYPE_B; case FRIBIDI_TYPE_SS: return PANGO_BIDI_TYPE_S; case FRIBIDI_TYPE_WS: return PANGO_BIDI_TYPE_WS; case FRIBIDI_TYPE_ON: return PANGO_BIDI_TYPE_ON; default: g_assert_not_reached (); return PANGO_BIDI_TYPE_ON; } }
/** * pango_unichar_direction: * @ch: a Unicode character * * Determines the inherent direction of a character; either * %PANGO_DIRECTION_LTR, %PANGO_DIRECTION_RTL, or * %PANGO_DIRECTION_NEUTRAL. * * This function is useful to categorize characters into left-to-right * letters, right-to-left letters, and everything else. If full * Unicode bidirectional type of a character is needed, * pango_bidi_type_for_unichar() can be used instead. * * Return value: the direction of the character. */ PangoDirection pango_unichar_direction (gunichar ch) { FriBidiCharType fribidi_ch_type; G_STATIC_ASSERT (sizeof (FriBidiChar) == sizeof (gunichar)); fribidi_ch_type = fribidi_get_bidi_type (ch); if (!FRIBIDI_IS_STRONG (fribidi_ch_type)) return PANGO_DIRECTION_NEUTRAL; else if (FRIBIDI_IS_RTL (fribidi_ch_type)) return PANGO_DIRECTION_RTL; else return PANGO_DIRECTION_LTR; }
/** * @internal * Checks if the string has RTL characters. * * @param str The string to be checked * @return #EINA_TRUE if true, #EINA_FALSE otherwise. */ Eina_Bool evas_bidi_is_rtl_str(const Eina_Unicode *str) { EvasBiDiCharType type; if (!str) return EINA_FALSE; for ( ; *str ; str++) { type = fribidi_get_bidi_type((FriBidiChar) *str); if (FRIBIDI_IS_RTL(type)) { return EINA_TRUE; } } return EINA_FALSE; }
/** * pango_log2vis_get_embedding_levels: * @text: the text to itemize. * @length: the number of bytes (not characters) to process, or -1 * if @text is nul-terminated and the length should be calculated. * @pbase_dir: input base direction, and output resolved direction. * * This will return the bidirectional embedding levels of the input paragraph * as defined by the Unicode Bidirectional Algorithm available at: * * http://www.unicode.org/reports/tr9/ * * If the input base direction is a weak direction, the direction of the * characters in the text will determine the final resolved direction. * * Return value: a newly allocated array of embedding levels, one item per * character (not byte), that should be freed using g_free. * * Since: 1.4 */ guint8 * pango_log2vis_get_embedding_levels (const gchar *text, int length, PangoDirection *pbase_dir) { glong n_chars, i; guint8 *embedding_levels_list; const gchar *p; FriBidiParType fribidi_base_dir; FriBidiCharType *bidi_types; #ifdef USE_FRIBIDI_EX_API FriBidiBracketType *bracket_types; #endif FriBidiLevel max_level; G_STATIC_ASSERT (sizeof (FriBidiLevel) == sizeof (guint8)); G_STATIC_ASSERT (sizeof (FriBidiChar) == sizeof (gunichar)); switch (*pbase_dir) { case PANGO_DIRECTION_LTR: case PANGO_DIRECTION_TTB_RTL: fribidi_base_dir = FRIBIDI_PAR_LTR; break; case PANGO_DIRECTION_RTL: case PANGO_DIRECTION_TTB_LTR: fribidi_base_dir = FRIBIDI_PAR_RTL; break; case PANGO_DIRECTION_WEAK_RTL: fribidi_base_dir = FRIBIDI_PAR_WRTL; break; case PANGO_DIRECTION_WEAK_LTR: case PANGO_DIRECTION_NEUTRAL: default: fribidi_base_dir = FRIBIDI_PAR_WLTR; break; } if (length < 0) length = strlen (text); n_chars = g_utf8_strlen (text, length); bidi_types = g_new (FriBidiCharType, n_chars); #ifdef USE_FRIBIDI_EX_API bracket_types = g_new (FriBidiBracketType, n_chars); #endif embedding_levels_list = g_new (guint8, n_chars); for (i = 0, p = text; p < text + length; p = g_utf8_next_char(p), i++) { gunichar ch = g_utf8_get_char (p); bidi_types[i] = fribidi_get_bidi_type (ch); #ifdef USE_FRIBIDI_EX_API if (G_UNLIKELY(bidi_types[i] == FRIBIDI_TYPE_ON)) bracket_types[i] = fribidi_get_bracket (ch); else bracket_types[i] = FRIBIDI_NO_BRACKET; #endif } #ifdef USE_FRIBIDI_EX_API max_level = fribidi_get_par_embedding_levels_ex (bidi_types, bracket_types, n_chars, &fribidi_base_dir, (FriBidiLevel*)embedding_levels_list); g_free (bracket_types); #else max_level = fribidi_get_par_embedding_levels (bidi_types, n_chars, &fribidi_base_dir, (FriBidiLevel*)embedding_levels_list); #endif g_free (bidi_types); if (G_UNLIKELY(max_level == 0)) { /* fribidi_get_par_embedding_levels() failed, * is this the best thing to do? */ memset (embedding_levels_list, 0, length); } *pbase_dir = (fribidi_base_dir == FRIBIDI_PAR_LTR) ? PANGO_DIRECTION_LTR : PANGO_DIRECTION_RTL; return embedding_levels_list; }
static void init_cap_rtl ( void ) { int request[_FRIBIDI_NUM_TYPES]; FriBidiCharType to_type[_FRIBIDI_NUM_TYPES]; int num_types = 0, count = 0; FriBidiCharType i; char mark[CAPRTL_CHARS]; caprtl_to_unicode = (FriBidiChar *) fribidi_malloc (CAPRTL_CHARS * sizeof caprtl_to_unicode[0]); for (i = 0; i < CAPRTL_CHARS; i++) if (CapRTLCharTypes[i] == fribidi_get_bidi_type (i)) { caprtl_to_unicode[i] = i; mark[i] = 1; } else { int j; caprtl_to_unicode[i] = FRIBIDI_UNICODE_CHARS; mark[i] = 0; if (fribidi_get_mirror_char (i, NULL)) { DBG ("warning: I could not map mirroring character map to itself in CapRTL"); } for (j = 0; j < num_types; j++) if (to_type[j] == CapRTLCharTypes[i]) break; if (j == num_types) { num_types++; to_type[j] = CapRTLCharTypes[i]; request[j] = 0; } request[j]++; count++; } for (i = 0; i < 0x10000 && count; i++) /* Assign BMP chars to CapRTL entries */ if (!fribidi_get_mirror_char (i, NULL) && !(i < CAPRTL_CHARS && mark[i])) { int j, k; FriBidiCharType t = fribidi_get_bidi_type (i); for (j = 0; j < num_types; j++) if (to_type[j] == t) break; if (!request[j]) /* Do not need this type */ continue; for (k = 0; k < CAPRTL_CHARS; k++) if (caprtl_to_unicode[k] == FRIBIDI_UNICODE_CHARS && to_type[j] == CapRTLCharTypes[k]) { request[j]--; count--; caprtl_to_unicode[k] = i; break; } } if (count) { int j; DBG ("warning: could not find a mapping for CapRTL to Unicode:"); for (j = 0; j < num_types; j++) if (request[j]) { DBG2 (" need this type: %s", fribidi_get_bidi_type_name (to_type[j])); } } }
FriBidiStrIndex fribidi_unicode_to_cap_rtl ( /* input */ const FriBidiChar *us, FriBidiStrIndex len, /* output */ char *s ) { FriBidiStrIndex i; int j; j = 0; for (i = 0; i < len; i++) { FriBidiChar ch = us[i]; if (!FRIBIDI_IS_EXPLICIT (fribidi_get_bidi_type (ch)) && ch != '_' && ch != FRIBIDI_CHAR_LRM && ch != FRIBIDI_CHAR_RLM) s[j++] = fribidi_unicode_to_cap_rtl_c (ch); else { s[j++] = '_'; switch (ch) { case FRIBIDI_CHAR_LRM: s[j++] = '>'; break; case FRIBIDI_CHAR_RLM: s[j++] = '<'; break; case FRIBIDI_CHAR_LRE: s[j++] = 'l'; break; case FRIBIDI_CHAR_RLE: s[j++] = 'r'; break; case FRIBIDI_CHAR_PDF: s[j++] = 'o'; break; case FRIBIDI_CHAR_LRO: s[j++] = 'L'; break; case FRIBIDI_CHAR_RLO: s[j++] = 'R'; break; case '_': s[j++] = '_'; break; default: j--; if (ch < 256) s[j++] = fribidi_unicode_to_cap_rtl_c (ch); else s[j++] = '?'; break; } } } s[j] = 0; return j; }
int main (int argc, char **argv) { GError *error; int next_arg; GIOChannel *channel; GIOStatus status; const char *filename; gchar *line = NULL; gsize length, terminator_pos; int numerrs = 0; int line_no = 0; FriBidiChar *code_points = NULL; int code_points_len = 0; int expected_ltor_len = 0; int base_dir_mode = 0, paragraph_dir; FriBidiLevel *expected_levels = NULL; int *expected_ltor = NULL; int resolved_paragraph_embedding_level; FriBidiLevel *levels = NULL; FriBidiCharType *types = NULL; FriBidiBracketType *bracket_types = NULL; FriBidiStrIndex *ltor = NULL; int ltor_len; gboolean debug = FALSE; if (argc < 2) { g_printerr ("usage: %s [--debug] test-file-name\n", argv[0]); exit (1); } next_arg = 1; while(next_arg < argc && argv[next_arg][0]=='-') { const char *arg = argv[next_arg++]; if (strcmp(arg, "--debug")==0) { debug=TRUE; continue; } die("Unknown option %s!\n", arg); } filename = argv[next_arg++]; error = NULL; channel = g_io_channel_new_file (filename, "r", &error); if (!channel) { g_printerr ("%s\n", error->message); exit (1); } fribidi_set_debug(debug); while (TRUE) { error = NULL; g_free (line); status = g_io_channel_read_line (channel, &line, &length, &terminator_pos, &error); switch (status) { case G_IO_STATUS_ERROR: g_printerr ("%s\n", error->message); exit (1); case G_IO_STATUS_EOF: goto done; case G_IO_STATUS_AGAIN: continue; case G_IO_STATUS_NORMAL: line[terminator_pos] = '\0'; break; } line_no++; if (line[0] == '#' || line[0] == '\0') continue; parse_test_line (line, line_no, &code_points, /* Field 0 */ &code_points_len, ¶graph_dir, /* Field 1 */ &resolved_paragraph_embedding_level, /* Field 2 */ &expected_levels, /* Field 3 */ &expected_ltor, /* Field 4 */ &expected_ltor_len ); /* Test it */ g_free(bracket_types); bracket_types = g_malloc ( sizeof(FriBidiBracketType) * code_points_len); g_free(types); types = g_malloc ( sizeof(FriBidiCharType) * code_points_len); g_free(levels); levels = g_malloc (sizeof (FriBidiLevel) * code_points_len); g_free (ltor); ltor = g_malloc (sizeof (FriBidiStrIndex) * code_points_len); { FriBidiParType base_dir; int i, j; gboolean matches; int types_len = code_points_len; int levels_len = types_len; FriBidiBracketType NoBracket = FRIBIDI_NO_BRACKET; for (i=0; i<code_points_len; i++) { types[i] = fribidi_get_bidi_type(code_points[i]); /* Note the optimization that a bracket is always of type neutral */ if (types[i] == FRIBIDI_TYPE_ON) bracket_types[i] = fribidi_get_bracket(code_points[i]); else bracket_types[i] = NoBracket; } if ((paragraph_dir & (1<<base_dir_mode)) == 0) continue; switch (paragraph_dir) { case 0: base_dir = FRIBIDI_PAR_LTR; break; case 1: base_dir = FRIBIDI_PAR_RTL; break; case 2: base_dir = FRIBIDI_PAR_ON; break; } if (fribidi_get_par_embedding_levels_ex (types, bracket_types, types_len, &base_dir, levels)) ; for (i = 0; i < types_len; i++) ltor[i] = i; if (fribidi_reorder_line (0 /*FRIBIDI_FLAG_REORDER_NSM*/, types, types_len, 0, base_dir, levels, NULL, ltor)) ; j = 0; for (i = 0; i < types_len; i++) if (!FRIBIDI_IS_EXPLICIT_OR_BN (types[ltor[i]])) ltor[j++] = ltor[i]; ltor_len = j; /* Compare */ matches = TRUE; if (matches) for (i = 0; i < code_points_len; i++) if (levels[i] != expected_levels[i] && expected_levels[i] != (FriBidiLevel) -1) { matches = FALSE; break; } if (ltor_len != expected_ltor_len) matches = FALSE; if (matches) for (i = 0; i < ltor_len; i++) if (ltor[i] != expected_ltor[i]) { matches = FALSE; break; } if (!matches) { numerrs++; g_printerr ("failure on line %d\n", line_no); g_printerr ("input is: %s\n", line); g_printerr ("base dir: %s\n", paragraph_dir==0 ? "LTR" : paragraph_dir==1 ? "RTL" : "AUTO"); g_printerr ("expected levels:"); for (i = 0; i < code_points_len; i++) if (expected_levels[i] == (FriBidiLevel) -1) g_printerr (" x"); else g_printerr (" %d", expected_levels[i]); g_printerr ("\n"); g_printerr ("returned levels:"); for (i = 0; i < levels_len; i++) g_printerr (" %d", levels[i]); g_printerr ("\n"); g_printerr ("expected order:"); for (i = 0; i < expected_ltor_len; i++) g_printerr (" %d", expected_ltor[i]); g_printerr ("\n"); g_printerr ("returned order:"); for (i = 0; i < ltor_len; i++) g_printerr (" %d", ltor[i]); g_printerr ("\n"); if (debug) { FriBidiParType base_dir; fribidi_set_debug (1); switch (base_dir_mode) { case 0: base_dir = FRIBIDI_PAR_ON; break; case 1: base_dir = FRIBIDI_PAR_LTR; break; case 2: base_dir = FRIBIDI_PAR_RTL; break; } if (fribidi_get_par_embedding_levels_ex (types, bracket_types, types_len, &base_dir, levels)) ; fribidi_set_debug (0); } g_printerr ("\n"); } } } done: if (error) g_error_free (error); if (numerrs) g_printerr ("%d errors\n", numerrs); else printf("No errors found! :-)\n"); return numerrs; }
char *FBidiConvert( const char *logical_str, const char *charset, int str_len, Bool *is_rtl, int *out_len, superimpose_char_t *comb_chars, int *l_to_v) { char *visual_str; FriBidiCharSet fribidi_charset; FriBidiChar *logical_unicode_str; FriBidiChar *visual_unicode_str; FriBidiParType pbase_dir = FRIBIDI_TYPE_ON; FriBidiStrIndex *pos_l_to_v; int i; if (logical_str == NULL || charset == NULL) { return NULL; } if (str_len < 0) { str_len = strlen(logical_str); } if (is_rtl != NULL) { *is_rtl = False; } fribidi_charset = fribidi_parse_charset((char *)charset); if (fribidi_charset == FRIBIDI_CHAR_SET_NOT_FOUND) { return NULL; } /* it is possible that we allocate a bit more here, if utf-8 */ logical_unicode_str = (FriBidiChar *)safemalloc((str_len + 1) * sizeof(FriBidiChar)); /* convert to unicode first */ str_len = fribidi_charset_to_unicode( fribidi_charset, (char *)logical_str, str_len, logical_unicode_str); visual_unicode_str = (FriBidiChar *)safemalloc((str_len + 1) * sizeof(FriBidiChar)); /* apply bidi algorithm, convert logical string to visual string */ /* also keep track of how characters are reordered here, to reorder combing characters accordingly */ pos_l_to_v = (FriBidiStrIndex *)safemalloc((str_len + 1) * sizeof(FriBidiStrIndex)); fribidi_log2vis( logical_unicode_str, str_len, &pbase_dir, visual_unicode_str, pos_l_to_v, NULL, NULL); /* remap mapping from logical to visual to "compensate" for BIDI */ if (comb_chars != NULL) { for (i = 0; comb_chars[i].c.byte1 != 0 || comb_chars[i].c.byte2 != 0; i++) { /* if input string is zero characters => only combining chars, set position to zero */ comb_chars[i].position = str_len != 0 ? pos_l_to_v[comb_chars[i].position] : 0; } } if (l_to_v != NULL) { /* values in the previuos mapping gives the position of input characters after combining step */ /* mapping from BIDI conversion maps from the positions in the output from combining */ int orig_len; int *l_to_v_temp; for (i = 0; l_to_v[i] != -1; i++) { } orig_len = i; l_to_v_temp = (int *)safemalloc(orig_len * sizeof(int)); for (i = 0; i < orig_len; i++) { l_to_v_temp[i] = pos_l_to_v[l_to_v[i]]; } for (i = 0; i < orig_len; i++) { l_to_v[i] = l_to_v_temp[i]; } free(l_to_v_temp); } free(pos_l_to_v); /* character shape/join - will get pulled into fribidi with time */ str_len = shape_n_join(visual_unicode_str, str_len); visual_str = (char *)safemalloc((4 * str_len + 1) * sizeof(char)); /* convert from unicode finally */ *out_len = fribidi_unicode_to_charset( fribidi_charset, visual_unicode_str, str_len, visual_str); if (is_rtl != NULL && fribidi_get_bidi_type(*visual_unicode_str) == FRIBIDI_TYPE_RTL) { *is_rtl = True; } free(logical_unicode_str); free(visual_unicode_str); return visual_str; }
int main ( int argc, char *argv[] ) { int exit_val; fribidi_boolean file_found; char *s; FILE *IN; text_width = 80; do_break = true; do_pad = true; do_mirror = true; do_clean = false; do_reorder_nsm = false; show_input = false; show_visual = true; show_basedir = false; show_ltov = false; show_vtol = false; show_levels = false; char_set = "UTF-8"; bol_text = NULL; eol_text = NULL; input_base_direction = FRIBIDI_PAR_ON; if ((s = (char *) getenv ("COLUMNS"))) { int i; i = atoi (s); if (i > 0) text_width = i; } #define CHARSETDESC 257 #define CAPRTL 258 /* Parse the command line with getopt library */ /* Must set argv[0], getopt uses it to generate error messages */ argv[0] = appname; while (1) { int option_index = 0, c; static struct option long_options[] = { {"help", 0, 0, 'h'}, {"version", 0, 0, 'V'}, {"verbose", 0, 0, 'v'}, {"debug", 0, 0, 'd'}, {"test", 0, 0, 't'}, {"charset", 1, 0, 'c'}, #if FRIBIDI_MAIN_USE_ICONV_H+0 #else {"charsetdesc", 1, 0, CHARSETDESC}, {"caprtl", 0, 0, CAPRTL}, #endif /* FRIBIDI_MAIN_USE_ICONV_H */ {"showinput", 0, (int *) (void *) &show_input, true}, {"nopad", 0, (int *) (void *) &do_pad, false}, {"nobreak", 0, (int *) (void *) &do_break, false}, {"width", 1, 0, 'w'}, {"bol", 1, 0, 'B'}, {"eol", 1, 0, 'E'}, {"nomirror", 0, (int *) (void *) &do_mirror, false}, {"reordernsm", 0, (int *) (void *) &do_reorder_nsm, true}, {"clean", 0, (int *) (void *) &do_clean, true}, {"ltr", 0, (int *) (void *) &input_base_direction, FRIBIDI_PAR_LTR}, {"rtl", 0, (int *) (void *) &input_base_direction, FRIBIDI_PAR_RTL}, {"wltr", 0, (int *) (void *) &input_base_direction, FRIBIDI_PAR_WLTR}, {"wrtl", 0, (int *) (void *) &input_base_direction, FRIBIDI_PAR_WRTL}, {"basedir", 0, (int *) (void *) &show_basedir, true}, {"ltov", 0, (int *) (void *) &show_ltov, true}, {"vtol", 0, (int *) (void *) &show_vtol, true}, {"levels", 0, (int *) (void *) &show_levels, true}, {"novisual", 0, (int *) (void *) &show_visual, false}, {0, 0, 0, 0} }; c = getopt_long (argc, argv, "hVvdtc:w:B:E:", long_options, &option_index); if (c == -1) break; switch (c) { case 0: break; case 'h': help (); break; case 'V': version (); break; case 'v': show_basedir = show_ltov = show_vtol = show_levels = true; break; case 'w': text_width = atoi (optarg); if (text_width <= 0) die2 ("invalid screen width `%s'\n", optarg); break; case 'B': bol_text = optarg; break; case 'E': eol_text = optarg; break; case 'd': if (!fribidi_set_debug (true)) die1 ("lib" FRIBIDI " must be compiled with DEBUG option to enable\nturn debug info on.\n"); break; case 't': do_clean = show_input = do_reorder_nsm = true; do_break = false; break; case 'c': char_set = my_fribidi_strdup (optarg); if (!char_set) die1 ("memory allocation failed for char_set!"); break; #if FRIBIDI_MAIN_USE_ICONV_H+0 #else case CAPRTL: char_set = "CapRTL"; break; case CHARSETDESC: char_set = optarg; char_set_num = fribidi_parse_charset (char_set); if (!char_set_num) die2 ("unrecognized character set `%s'\n", char_set); if (!fribidi_char_set_desc (char_set_num)) die2 ("no description available for character set `%s'\n", fribidi_char_set_name (char_set_num)); else printf ("Descriptions for character set %s:\n" "\n" "%s", fribidi_char_set_title (char_set_num), fribidi_char_set_desc (char_set_num)); exit (0); break; #endif /* !FRIBIDI_MAIN_USE_ICONV_H */ case ':': case '?': die2 (NULL, NULL); break; default: break; } } #if FRIBIDI_MAIN_USE_ICONV_H+0 to_ucs4 = iconv_open ("WCHAR_T", char_set); from_ucs4 = iconv_open (char_set, "WCHAR_T"); #else /* !FRIBIDI_MAIN_USE_ICONV_H */ char_set_num = fribidi_parse_charset (char_set); #endif /* !FRIBIDI_MAIN_USE_ICONV_H */ #if FRIBIDI_MAIN_USE_ICONV_H+0 if (to_ucs4 == (iconv_t) (-1) || from_ucs4 == (iconv_t) (-1)) #else /* !FRIBIDI_MAIN_USE_ICONV_H */ if (!char_set_num) #endif /* !FRIBIDI_MAIN_USE_ICONV_H */ die2 ("unrecognized character set `%s'\n", char_set); fribidi_set_mirroring (do_mirror); fribidi_set_reorder_nsm (do_reorder_nsm); exit_val = 0; file_found = false; while (optind < argc || !file_found) { const char *filename; filename = optind < argc ? argv[optind++] : "-"; file_found = true; /* Open the infile for reading */ if (filename[0] == '-' && !filename[1]) { IN = stdin; } else { IN = fopen (filename, "r"); if (!IN) { fprintf (stderr, "%s: %s: no such file or directory\n", appname, filename); exit_val = 1; continue; } } /* Read and process input one line at a time */ { char S_[MAX_STR_LEN]; int padding_width, break_width; padding_width = show_input ? (text_width - 10) / 2 : text_width; break_width = do_break ? padding_width : 3 * MAX_STR_LEN; while (fgets (S_, sizeof (S_) - 1, IN)) { const char *new_line, *nl_found; FriBidiChar logical[MAX_STR_LEN]; char outstring[MAX_STR_LEN]; FriBidiParType base; FriBidiStrIndex len; nl_found = ""; S_[sizeof (S_) - 1] = 0; len = strlen (S_); /* chop */ if (S_[len - 1] == '\n') { len--; S_[len] = '\0'; new_line = "\n"; } else new_line = ""; /* TODO: handle \r */ #if FRIBIDI_MAIN_USE_ICONV_H+0 { char *st = S_, *ust = (char *) logical; int in_len = (int) len; len = sizeof logical; iconv (to_ucs4, &st, &in_len, &ust, (int *) &len); len = (FriBidiChar *) ust - logical; } #else /* !FRIBIDI_MAIN_USE_ICONV_H */ len = fribidi_charset_to_unicode (char_set_num, S_, len, logical); #endif /* !FRIBIDI_MAIN_USE_ICONV_H */ { FriBidiChar *visual; FriBidiStrIndex *ltov, *vtol; FriBidiLevel *levels; FriBidiStrIndex new_len; fribidi_boolean log2vis; visual = show_visual ? ALLOCATE (FriBidiChar, len + 1 ) : NULL; ltov = show_ltov ? ALLOCATE (FriBidiStrIndex, len + 1 ) : NULL; vtol = show_vtol ? ALLOCATE (FriBidiStrIndex, len + 1 ) : NULL; levels = show_levels ? ALLOCATE (FriBidiLevel, len + 1 ) : NULL; /* Create a bidi string. */ base = input_base_direction; log2vis = fribidi_log2vis (logical, len, &base, /* output */ visual, ltov, vtol, levels); if (log2vis) { if (show_input) printf ("%-*s => ", padding_width, S_); new_len = len; /* Remove explicit marks, if asked for. */ if (do_clean) len = fribidi_remove_bidi_marks (visual, len, ltov, vtol, levels); if (show_visual) { printf ("%s", nl_found); if (bol_text) printf ("%s", bol_text); /* Convert it to input charset and print. */ { FriBidiStrIndex idx, st; for (idx = 0; idx < len;) { FriBidiStrIndex wid, inlen; wid = break_width; st = idx; #if FRIBIDI_MAIN_USE_ICONV_H+0 #else if (char_set_num != FRIBIDI_CHAR_SET_CAP_RTL) #endif /* !FRIBIDI_MAIN_USE_ICONV_H */ while (wid > 0 && idx < len) { wid -= FRIBIDI_IS_EXPLICIT_OR_BN_OR_NSM (fribidi_get_bidi_type (visual[idx])) ? 0 : 1; idx++; } #if FRIBIDI_MAIN_USE_ICONV_H+0 #else else while (wid > 0 && idx < len) { wid--; idx++; } #endif /* !FRIBIDI_MAIN_USE_ICONV_H */ if (wid < 0 && idx > st + 1) idx--; inlen = idx - st; #if FRIBIDI_MAIN_USE_ICONV_H+0 { char *str = outstring, *ust = (char *) (visual + st); int in_len = inlen * sizeof visual[0]; new_len = sizeof outstring; iconv (from_ucs4, &ust, &in_len, &str, (int *) &new_len); *str = '\0'; new_len = str - outstring; } #else /* !FRIBIDI_MAIN_USE_ICONV_H */ new_len = fribidi_unicode_to_charset (char_set_num, visual + st, inlen, outstring); #endif /* !FRIBIDI_MAIN_USE_ICONV_H */ if (FRIBIDI_IS_RTL (base)) printf ("%*s", (int) (do_pad ? (padding_width + strlen (outstring) - (break_width - wid)) : 0), outstring); else printf ("%s", outstring); if (idx < len) printf ("\n"); } } if (eol_text) printf ("%s", eol_text); nl_found = "\n"; } if (show_basedir) { printf ("%s", nl_found); printf ("Base direction: %s", (FRIBIDI_DIR_TO_LEVEL (base) ? "R" : "L")); nl_found = "\n"; } if (show_ltov) { FriBidiStrIndex i; printf ("%s", nl_found); for (i = 0; i < len; i++) printf ("%ld ", (long) ltov[i]); nl_found = "\n"; } if (show_vtol) { FriBidiStrIndex i; printf ("%s", nl_found); for (i = 0; i < len; i++) printf ("%ld ", (long) vtol[i]); nl_found = "\n"; } if (show_levels) { FriBidiStrIndex i; printf ("%s", nl_found); for (i = 0; i < len; i++) printf ("%d ", (int) levels[i]); nl_found = "\n"; } } else { exit_val = 2; } if (show_visual) free (visual); if (show_ltov) free (ltov); if (show_vtol) free (vtol); if (show_levels) free (levels); } if (*nl_found) printf (new_line); } } } return exit_val; }