summaryrefslogtreecommitdiff
path: root/support/fribidixetex/src
diff options
context:
space:
mode:
Diffstat (limited to 'support/fribidixetex/src')
-rw-r--r--support/fribidixetex/src/fribidixetex-bidi.c1041
-rw-r--r--support/fribidixetex/src/fribidixetex-bidi.h11
-rw-r--r--support/fribidixetex/src/fribidixetex-defines.h24
-rw-r--r--support/fribidixetex/src/fribidixetex-dict.c145
-rw-r--r--support/fribidixetex/src/fribidixetex-dict.h16
-rw-r--r--support/fribidixetex/src/fribidixetex-ignore.c20
-rw-r--r--support/fribidixetex/src/fribidixetex-ignore.h6
-rw-r--r--support/fribidixetex/src/fribidixetex-io.c110
-rw-r--r--support/fribidixetex/src/fribidixetex-io.h15
-rw-r--r--support/fribidixetex/src/fribidixetex-util.c28
-rw-r--r--support/fribidixetex/src/fribidixetex-util.h9
-rw-r--r--support/fribidixetex/src/fribidixetex.c184
12 files changed, 1609 insertions, 0 deletions
diff --git a/support/fribidixetex/src/fribidixetex-bidi.c b/support/fribidixetex/src/fribidixetex-bidi.c
new file mode 100644
index 0000000000..dd3a0ebb67
--- /dev/null
+++ b/support/fribidixetex/src/fribidixetex-bidi.c
@@ -0,0 +1,1041 @@
+#include "fribidixetex-defines.h"
+#include "fribidixetex-bidi.h"
+#include "fribidixetex-util.h"
+#include "fribidixetex-dict.h"
+#include "fribidixetex-ignore.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "fribidixetex-io.h"
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+#ifndef min
+#define min(x,y) ((x) < (y) ? (x) : (y))
+#endif
+
+#ifndef max
+#define max(x,y) ((x) > (y) ? (x) : (y))
+#endif
+
+
+/***********************/
+/* Global Data */
+
+typedef struct COMMAND {
+ char *name;
+ struct COMMAND *next;
+}
+ bidi_cmd_t;
+
+bidi_cmd_t *bidi_command_list;
+
+enum { MODE_BIDIOFF, MODE_BIDION, MODE_BIDILTR };
+
+
+static int bidi_mode;
+static FriBidiLevel bidi_embed[MAX_LINE_SIZE];
+static FriBidiChar translation_buffer[MAX_LINE_SIZE];
+
+/* only ASCII charrecters mirroring are
+ * supported - the coded below 128 according to
+ * http://www.unicode.org/Public/4.1.0/ucd/BidiMirroring.txt */
+
+/* TODO: implement full mirroring list according to unicode
+ * standard */
+static const char *bidi_mirror_list[][2] =
+{
+ {"(", ")"},
+ {")", "("},
+ {"<", ">"},
+ {">", "<"},
+ {"[", "]"},
+ {"]", "["},
+ {"\\{","\\}"},
+ {"\\}","\\{"},
+ {NULL,NULL}
+};
+
+static const char *bidi_hack_list[][2] =
+{
+ {"---","{\\fribidixetexemdash}"},
+ {"--","{\\fribidixetexendash}"},
+ {NULL,NULL}
+};
+
+/********/
+/* TAGS */
+/********/
+
+#define TAG_BIDI_ON "%BIDION"
+#define TAG_BIDI_OFF "%BIDIOFF"
+#define TAG_BIDI_NEW_TAG "%BIDITAG"
+#define TAG_BIDI_LTR "%BIDILTR"
+#define TAG_BIDI_DIC_TAG "%BIDIDICTAG"
+#define TAG_BIDI_DIC_ENV "%BIDIDICENV"
+
+#define TAG_RTL "\\fribidixetexRLE{"
+#define TAG_LTR "\\fribidixetexLRE{"
+#define TAG_CLOSE "}"
+
+#define TAG_LATIN_NUM "\\fribidixetexlatinnumbers{"
+#define TAG_NONLATIN_NUM "\\fribidixetexnonlatinnumbers{"
+
+/***********************/
+
+/* Compares begining of string U and C
+ * for example "Hello!" == "Hel" */
+static int bidi_strieq_u_a(const FriBidiChar *u,const char *c)
+{
+ while(*u && *c) {
+ if(*u!=*c)
+ return 0;
+ u++; c++;
+ }
+ if(*u ==0 && *c!=0) {
+ return 0;
+ }
+ return 1;
+}
+
+static int bidi_strlen(FriBidiChar *in)
+{
+ int len;
+ for(len=0;*in;len++) in++;
+ return len;
+}
+
+/* Safe functions for adding charrecters to buffer
+ * if the line is too long the program just exits */
+
+static void bidi_add_char_u(FriBidiChar *out,int *new_len,
+ int limit,FriBidiChar ch)
+{
+ if(*new_len+2<limit){
+ out[*new_len]=ch;
+ ++*new_len;
+ out[*new_len]=0;
+ }
+ else {
+ fprintf(stderr,"The line is too long: line %d\n",io_line_number);
+ exit(1);
+ }
+}
+static void bidi_add_str_c(FriBidiChar *out,int *new_len,
+ int limit,const char *str)
+{
+ while(*str){
+ bidi_add_char_u(out,new_len,limit,*str);
+ str++;
+ }
+}
+
+/* Function looks if the first charrecter or sequence
+ * in "in" is mirrored charrecter and returns its mirrot
+ * in this case. If it is not mirrored then returns NULL */
+static const char *bidi_one_mirror(FriBidiChar *in,int *size,
+ const char *list[][2])
+{
+ int pos=0;
+ while(list[pos][0]) {
+ if(bidi_strieq_u_a(in,list[pos][0])) {
+ *size=strlen(list[pos][0]);
+ return list[pos][1];
+ }
+ pos++;
+ }
+ return NULL;
+}
+
+static const char *bidi_mirror(FriBidiChar *in,int *size,
+ int replace_minus)
+{
+ const char *ptr;
+ if((ptr=bidi_one_mirror(in,size,bidi_mirror_list))!=NULL) {
+ return ptr;
+ }
+ if(replace_minus) {
+ return bidi_one_mirror(in,size,bidi_hack_list);
+ }
+ return NULL;
+}
+
+
+/* Returns the minimal embedding level for required direction */
+int bidi_basic_level(int is_rtl)
+{
+ if(is_rtl)
+ return 1;
+ return 0;
+}
+
+void bidi_add_command(const char *name)
+{
+ bidi_cmd_t *new_cmd;
+ char *new_text;
+
+ new_cmd=(bidi_cmd_t*)utl_malloc(sizeof(bidi_cmd_t));
+ new_text=(char*)utl_malloc(strlen(name)+1);
+
+ new_cmd->next=bidi_command_list;
+ new_cmd->name=new_text;
+ strcpy(new_text,name);
+ bidi_command_list = new_cmd;
+}
+
+int bidi_is_cmd_char(FriBidiChar ch)
+{
+ if( ('a'<= ch && ch <='z') || ('A' <=ch && ch <= 'Z') )
+ return 1;
+ return 0;
+}
+
+/* Verirfies wether then text of length "len" is
+ * in command list */
+int bidi_in_cmd_list(FriBidiChar *text,int len)
+{
+ int i;
+ bidi_cmd_t *p;
+ for(p=bidi_command_list;p;p=p->next) {
+ for(i=0;i<len;i++) {
+ if(text[i]!=p->name[i])
+ break;
+ }
+ if(i==len && p->name[len]==0){
+ return 1;
+ }
+ }
+ return 0;
+}
+
+
+/* Find special charrecters */
+int bidi_is_latex_special_char(FriBidiChar *text)
+{
+ if(text[0]!='\\')
+ return FALSE;
+ /* Special charrecters according to lshort.pdf
+ * # $ % ^ & _ { } ~ \, "{}" should be mirrored
+ * thus not included to the list */
+ switch (text[1]) {
+ case '#' :
+ case '$' :
+ case '%' :
+ case '^' :
+ case '&' :
+ case '_' :
+ case '\\':
+ return TRUE;
+ default :
+ return FALSE;
+ }
+
+}
+
+
+/*Verifies wether the next string is command
+ * ie: "\\[a-zA-Z]+" or "\\[a-zA-Z]+\*" */
+int bidi_is_command(FriBidiChar *text,int *command_length)
+{
+ int len;
+
+ if(bidi_is_latex_special_char(text)) {
+ /* Charrecters like \\ or \$ that should be treated
+ * as `commands' */
+ *command_length=2;
+ return TRUE;
+ }
+
+ if(*text != '\\' || !bidi_is_cmd_char(text[1])) {
+ return FALSE;
+ }
+ len=1;
+ while(bidi_is_cmd_char(text[len])) {
+ len++;
+ }
+ if(text[len] == '*') {
+ len++;
+ }
+ *command_length = len;
+ return TRUE;
+}
+
+/* This is implementation of state machine with stack
+ * that distinguishs between text and commands */
+
+/* STACK VALUES */
+enum {
+ EMPTY,
+ SQ_BRACKET ,SQ_BRACKET_IGN,
+ BRACKET, BRACKET_IGN,
+ CMD_BRACKET, CMD_BRACKET_IGN
+};
+/* STATES */
+enum { ST_NO, ST_NORM, ST_IGN };
+
+/* Used for ignore commands */
+int bidi_is_ignore(int top)
+{
+ return top == SQ_BRACKET_IGN
+ || top== BRACKET_IGN
+ || top == CMD_BRACKET_IGN;
+}
+
+int bidi_state_on_left_br(int top,int *after_command_state)
+{
+ int ign_addon;
+ int push,state = *after_command_state;
+ if(bidi_is_ignore(top) || state == ST_IGN) {
+ ign_addon = 1;
+ }
+ else {
+ ign_addon = 0;
+ }
+
+ if(state) {
+ push = CMD_BRACKET;
+ }
+ else{
+ push = BRACKET;
+ }
+
+ *after_command_state = ST_NO;
+ return push + ign_addon;
+}
+
+int bidi_state_on_left_sq_br(int top,int *after_command_state)
+{
+ int push;
+ if(bidi_is_ignore(top) || *after_command_state == ST_IGN) {
+ push = SQ_BRACKET_IGN;
+ }
+ else {
+ push = SQ_BRACKET;
+ }
+ *after_command_state = ST_NO;
+ return push;
+}
+
+void bidi_state_on_right_br(int top,int *after_command_state)
+{
+ if(top == CMD_BRACKET) {
+ *after_command_state = ST_NORM;
+ }
+ else if(top == BRACKET || top == BRACKET_IGN) {
+ *after_command_state = ST_NO;
+ }
+ else {/*top == CMD_BRACKET_IGN*/
+ *after_command_state = ST_IGN;
+ }
+}
+
+void bidi_state_on_right_sq_br(int top,int *after_command_state)
+{
+ if(top == SQ_BRACKET_IGN) {
+ *after_command_state = ST_IGN;
+ }
+ else { /* top == SQ_BRACKET */
+ *after_command_state = ST_NORM;
+ }
+}
+/* Using marks "$$" */
+int bidi_calc_equation_inline(FriBidiChar *in)
+{
+ int len=1;
+ while(in[len] && in[len]!='$') {
+ if(in[len]=='\\' && (in[len+1]=='$' || in[len+1]=='\\')) {
+ len+=2;
+ }
+ else {
+ len++;
+ }
+ }
+ if(in[len]=='$')
+ len++;
+ return len;
+}
+
+/* using \[ and \] marks */
+int bidi_calc_equation_display(FriBidiChar *in)
+{
+ int len=2;
+ while(in[len]){
+ if(in[len]=='\\' && in[len+1]=='\\')
+ len+=2;
+ else if(in[len]=='\\' && in[len+1]==']')
+ return len+2;
+ else
+ len++;
+ }
+ return len;
+}
+
+/* Support of equations */
+int bidi_calc_equation(FriBidiChar *in)
+{
+ if(*in=='$')
+ return bidi_calc_equation_inline(in);
+ else
+ return bidi_calc_equation_display(in);
+}
+
+/* This function parses the text "in" in marks places that
+ * should be ignored by fribidi in "is_command" as true */
+void bidi_mark_commands(FriBidiChar *in,int len,char *is_command,int is_rtl)
+{
+
+ char *parthness_stack;
+ int stack_size=0;
+ int cmd_len,top;
+ int after_command_state=ST_NO;
+ int mark,pos,symbol,i,push;
+
+ /* Assumption - depth of stack can not be bigger then text length */
+ parthness_stack = utl_malloc(len);
+
+ pos=0;
+
+ while(pos<len) {
+
+ top = stack_size == 0 ? EMPTY : parthness_stack[stack_size-1];
+ symbol=in[pos];
+#ifdef DEBUG_STATE_MACHINE
+ printf("pos=%d sybol=%c state=%d top=%d\n",
+ pos,(symbol < 127 ? symbol : '#'),after_command_state,top);
+#endif
+ if(bidi_is_command(in+pos,&cmd_len)) {
+ for(i=0;i<cmd_len;i++) {
+ is_command[i+pos]=TRUE;
+ }
+ if(bidi_in_cmd_list(in+pos+1,cmd_len-1)) {
+ after_command_state = ST_IGN;
+ }
+ else {
+ after_command_state = ST_NORM;
+ }
+ pos+=cmd_len;
+ continue;
+ }
+ else if(symbol=='$' || (symbol=='\\' && in[pos+1]=='[')) {
+ cmd_len=bidi_calc_equation(in+pos);
+
+ for(i=0;i<cmd_len;i++) {
+ is_command[i+pos]=TRUE;
+ }
+ pos+=cmd_len;
+ continue;
+ }
+ else if( symbol == '{' ) {
+ push = bidi_state_on_left_br(top,&after_command_state);
+ parthness_stack[stack_size++] = push;
+ mark=TRUE;
+ }
+ else if(symbol == '[' && after_command_state) {
+ push = bidi_state_on_left_sq_br(top,&after_command_state);
+ parthness_stack[stack_size++] = push;
+ mark=TRUE;
+ }
+ else if(symbol == ']' && (top == SQ_BRACKET || top == SQ_BRACKET_IGN)){
+ bidi_state_on_right_sq_br(top,&after_command_state);
+ stack_size--;
+ mark=TRUE;
+ }
+ else if(symbol == '}' && (BRACKET <= top && top <= CMD_BRACKET_IGN)) {
+ bidi_state_on_right_br(top,&after_command_state);
+ stack_size--;
+ mark=TRUE;
+ }
+ else {
+ mark = bidi_is_ignore(top);
+ after_command_state = ST_NO;
+ }
+ is_command[pos++]=mark;
+ }
+
+ utl_free(parthness_stack);
+}
+
+#if ( FRIBIDI_MAJOR_VERSION * 100 + FRIBIDI_MINOR_VERSION ) > 10 // 0.10
+static void get_bidi_levels(FriBidiChar *in,int length,int is_rtl,FriBidiLevel *embed)
+{
+ FriBidiCharType *types = utl_malloc(sizeof(FriBidiCharType)*length);
+ FriBidiParType direction = is_rtl ? FRIBIDI_PAR_RTL : FRIBIDI_PAR_LTR;
+
+ fribidi_get_bidi_types(in,length,types);
+ fribidi_get_par_embedding_levels(types,length,&direction,embed);
+
+ utl_free(types);
+}
+
+#else // old fribidi
+static void get_bidi_levels(FriBidiChar *in,int length,int is_rtl,FriBidiLevel *embed)
+{
+ FriBidiCharType direction;
+ if(is_rtl)
+ direction = FRIBIDI_TYPE_RTL;
+ else
+ direction = FRIBIDI_TYPE_LTR;
+
+ fribidi_log2vis_get_embedding_levels(in,length,&direction,embed);
+}
+#endif
+
+/* This function marks embedding levels at for text "in",
+ * it ignores different tags */
+void bidi_tag_tolerant_fribidi_l2v( FriBidiChar *in,int len,
+ int is_rtl,
+ FriBidiLevel *embed,
+ char *is_command)
+{
+ int in_pos,out_pos,cmd_len,i;
+ FriBidiChar *in_tmp;
+ FriBidiLevel *embed_tmp,fill_level;
+
+ in_tmp=(FriBidiChar*)utl_malloc(sizeof(FriBidiChar)*(len+1));
+ embed_tmp=(FriBidiLevel*)utl_malloc(sizeof(FriBidiLevel)*len);
+
+ /**********************************************
+ * This is main parser that marks commands *
+ * across the text i.e. marks non text *
+ **********************************************/
+ bidi_mark_commands(in,len,is_command,is_rtl);
+
+ /**********************************************/
+ /* Copy all the data without tags for fribidi */
+ /**********************************************/
+ in_pos=0;
+ out_pos=0;
+
+ while(in_pos<len) {
+ if(is_command[in_pos]){
+ in_pos++;
+ continue;
+ }
+ /* Copy to buffer */
+ in_tmp[out_pos]=in[in_pos];
+ out_pos++;
+ in_pos++;
+ }
+
+ /***************
+ * RUN FRIBIDI *
+ ***************/
+
+ /* Note - you must take the new size for firibidi */
+ get_bidi_levels(in_tmp,out_pos,is_rtl,embed_tmp);
+
+ /****************************************************
+ * Return the tags and fill missing embedding level *
+ ****************************************************/
+ in_pos=0;
+ out_pos=0;
+
+ while(in_pos<len) {
+ if(is_command[in_pos]){
+ /* Find the length of the part that
+ * has a command/tag */
+ for(cmd_len=0;in_pos+cmd_len<len;cmd_len++) {
+ if(!is_command[cmd_len+in_pos])
+ break;
+ }
+
+ if(in_pos == 0 || in_pos + cmd_len == len){
+ /* When we on start/end assume basic direction */
+ fill_level = bidi_basic_level(is_rtl);
+ }
+ else {
+ /* Fill with minimum on both sides */
+ fill_level = min(embed_tmp[out_pos-1],embed_tmp[out_pos]);
+ }
+
+ for(i=0;i<cmd_len;i++){
+ embed[in_pos]=fill_level;
+ in_pos++;
+ }
+ continue;
+ }
+ /* Retrieve embedding */
+ embed[in_pos]=embed_tmp[out_pos];
+ out_pos++;
+ in_pos++;
+ }
+
+ /* Not forget to free */
+ utl_free(embed_tmp);
+ utl_free(in_tmp);
+}
+
+int bidi_only_latin_number(FriBidiLevel *levels,FriBidiChar *string)
+{
+ FriBidiChar ch;
+ while(*string && (*levels & 1)==0 ) {
+ ch=*string;
+ if(ch>127) { /* other foreign language */
+ return 0;
+ }
+ if(('a'<=ch && ch<='z') || ('A'<=ch && ch<='Z')) {
+ /* Find latin characters */
+ return 0;
+ }
+ string++;
+ levels++;
+ }
+ return 1;
+}
+
+int bidi_only_nonlatin_number(FriBidiLevel *levels,FriBidiChar *string)
+{
+ FriBidiChar ch;
+ while(*string && (*levels & 1)==0 ) {
+ ch=*string;
+ if('0'<=ch && ch<='9') { /* Find latin numbers */
+ return 0;
+ }
+ if(('a'<=ch && ch<='z') || ('A'<=ch && ch<='Z')) {
+ /* Find latin characters */
+ return 0;
+ }
+ string++;
+ levels++;
+ }
+ return 1;
+}
+
+/* Mark Unicode LRM & RLM charrecters */
+int bidi_is_directional_mark(FriBidiChar c)
+{
+ if(c==0x200F || c==0x200E) {
+ return 1;
+ }
+ return 0;
+}
+
+/* The function that parses line and adds required \R \L tags */
+void bidi_add_tags(FriBidiChar *in,FriBidiChar *out,int limit,
+ int is_rtl,int replace_minus,int no_mirroring)
+{
+ int len,new_len,level,new_level,brakets;
+ int i,size;
+ int is_number_env=0;
+
+ const char *tag;
+ char *is_command;
+
+
+ len=bidi_strlen(in);
+
+ is_command=(char*)utl_malloc(len);
+
+ bidi_tag_tolerant_fribidi_l2v(in,len,is_rtl,bidi_embed,is_command);
+
+ level=bidi_basic_level(is_rtl);
+
+ new_len=0;
+ out[0]=0;
+ brakets=0;
+ for(i=0,new_len=0;i<len;i++){
+ new_level=bidi_embed[i];
+
+ if(new_level>level) {
+ /* LTR Direction according to odd/even value of level */
+ is_number_env=FALSE;
+ if((new_level & 1) == 0) {
+ if(bidi_only_latin_number(bidi_embed+i,in+i)){
+ tag=TAG_LATIN_NUM;
+ is_number_env=TRUE;
+ }
+ else if(bidi_only_nonlatin_number(bidi_embed+i,in+i)){
+ tag=TAG_NONLATIN_NUM;
+ is_number_env=TRUE;
+ }
+ else {
+ tag=TAG_LTR;
+ }
+ }
+ else {
+ tag=TAG_RTL;
+ }
+ brakets++;
+ bidi_add_str_c(out,&new_len,limit,tag);
+ }
+ else if(new_level<level) {
+ bidi_add_str_c(out,&new_len,limit,TAG_CLOSE);
+ brakets--;
+ }
+
+ if(
+ (new_level & 1)!=0
+ && !is_command[i]
+ && !no_mirroring
+ && (tag=bidi_mirror(in+i,&size,replace_minus))!=NULL)
+ {
+ /* Replace charrecter with its mirror only in case
+ * we are in RTL direction */
+
+ /* Note this can be a sequence like "\{" */
+ bidi_add_str_c(out,&new_len,limit,tag);
+ i+=size-1;
+ }
+ else if(
+ (new_level & 1)!=1
+ && is_number_env
+ && replace_minus
+ && !is_command[i]
+ && (tag=bidi_one_mirror(in+i,&size,bidi_hack_list))!=NULL)
+ {
+ /* Replace "--/---" with a tag "\tex{en|em}dash" only in LTR
+ * direction only if this is nubmers environment */
+
+ bidi_add_str_c(out,&new_len,limit,tag);
+ i+=size-1;
+ }
+ else if(bidi_is_directional_mark(in[i])){
+ /* Do nothing -- erase marks that are
+ * not actual charrecters and thus not presented in fonts */
+ }
+ else {
+ bidi_add_char_u(out,&new_len,limit,in[i]);
+ }
+ level=new_level;
+ }
+ /* Fill all missed brakets */
+ while(brakets){
+ bidi_add_str_c(out,&new_len,limit,TAG_CLOSE);
+ brakets--;
+ }
+ utl_free(is_command);
+}
+
+/*************************/
+/* T R A N S L A T I O N */
+/*************************/
+
+static void bidi_error(char *text)
+{
+ fprintf(stderr,"ERROR in line %d: `%s'\n",io_line_number,text);
+ exit(1);
+}
+
+
+static int is_hebrew_tag(FriBidiChar buffer[MAX_COMMAND_LEN],FriBidiChar **ptr)
+{
+ FriBidiChar *tmp_ptr = *ptr;
+ int size=0;
+ if(!dict_is_hebrew_letter(*tmp_ptr)) {
+ return FALSE;
+ }
+ while(dict_is_hebrew_letter(*tmp_ptr)) {
+ if(size<MAX_COMMAND_LEN-1) {
+ buffer[size]=*tmp_ptr;
+ tmp_ptr++;
+ size++;
+ }
+ else {
+ bidi_error("Hebrew tag is too long");
+ return FALSE;
+ }
+ }
+ buffer[size]=0;
+ *ptr=tmp_ptr;
+ return TRUE;
+
+}
+
+static int is_ascii_tag(char buffer[MAX_COMMAND_LEN],FriBidiChar **ptr)
+{
+ FriBidiChar *tmp_ptr = *ptr;
+ int size=0;
+ if(!bidi_is_cmd_char(*tmp_ptr)) {
+ return FALSE;
+ }
+ while(bidi_is_cmd_char(*tmp_ptr)) {
+ if(size<MAX_COMMAND_LEN-1) {
+ buffer[size]=*tmp_ptr;
+ tmp_ptr++;
+ size++;
+ }
+ else {
+ /* No warning need - no limit */
+ return FALSE;
+ }
+ }
+ buffer[size]=0;
+ *ptr=tmp_ptr;
+ return TRUE;
+
+}
+
+
+static char const *is_tag_begin_or_end(FriBidiChar **ptr)
+{
+ char ascii_tag[MAX_COMMAND_LEN];
+ char *trans=NULL;
+ FriBidiChar *tmp_ptr=*ptr;
+ FriBidiChar unicode_tag[MAX_COMMAND_LEN];
+
+ if(is_ascii_tag(ascii_tag,&tmp_ptr) ||
+ (
+ is_hebrew_tag(unicode_tag,&tmp_ptr)
+ && (trans=dict_translate_tag(unicode_tag))
+ )
+ )
+ {
+ if(trans) strcpy(ascii_tag,trans);
+
+ if(strcmp(ascii_tag,"begin")==0){
+ *ptr=tmp_ptr;
+ return "begin";
+ }
+ else if(strcmp(ascii_tag,"end")==0){
+ *ptr=tmp_ptr;
+ return "end";
+ }
+ else {
+ return NULL;
+ }
+ }
+ else {
+ return NULL;
+ }
+}
+
+#define is_open_bracket(x) ( **(x) == '{' ? ++*(x) : FALSE )
+#define is_close_bracket(x) ( **(x) == '}' ? ++*(x) : FALSE )
+
+static const char *is_heb_word(FriBidiChar **ptr,trans_func_t tras_func)
+{
+ FriBidiChar *tmp_ptr=*ptr;
+ FriBidiChar unicode_tag[MAX_COMMAND_LEN];
+ char *trans;
+ if(is_hebrew_tag(unicode_tag,&tmp_ptr)) {
+ if((trans=tras_func(unicode_tag))!=NULL) {
+ *ptr=tmp_ptr;
+ return trans;
+ }
+ else {
+ bidi_error("Unknown hebrew tag - not translated");
+ return NULL;
+ }
+ }
+ else {
+ return NULL;
+ }
+}
+
+#define is_heb_environment(x) is_heb_word((x),dict_translate_env)
+#define is_heb_tag(x) is_heb_word((x),dict_translate_tag)
+
+static char *is_hebrew_command(FriBidiChar *text,int *length)
+{
+ char const *tag_txt,*env_txt;
+
+ static char buffer[MAX_COMMAND_LEN*2+3];
+ /* The command can consist at most of name of tag,
+ * environment and breakets */
+
+ FriBidiChar *end_ptr;
+ if(*text!='\\') {
+ return NULL;
+ }
+
+ end_ptr=text+1;
+ if((tag_txt = is_tag_begin_or_end(&end_ptr))!=NULL
+ && is_open_bracket(&end_ptr)
+ && (env_txt=is_heb_environment(&end_ptr))!=NULL
+ && is_close_bracket(&end_ptr))
+ {
+ *length=end_ptr-text;
+ strcpy(buffer,"\\");
+ strcat(buffer,tag_txt);
+ strcat(buffer,"{");
+ strcat(buffer,env_txt);
+ strcat(buffer,"}");
+ return buffer;
+ }
+
+ end_ptr=text+1;
+ if((tag_txt=is_heb_tag(&end_ptr))!=NULL){
+ *length=end_ptr-text;
+ strcpy(buffer,"\\");
+ strcat(buffer,tag_txt);
+ return buffer;
+ }
+ return NULL;
+}
+
+void bidi_translate_tags(FriBidiChar *in,FriBidiChar *out,int limit)
+{
+ int ptr;
+ int new_length,cmd_len;
+ char *tr_command;
+ ptr=0;
+ new_length=0;
+
+ out[0]=0;
+
+ while(in[ptr]) {
+ /* In case there is \\ before hebrew word */
+ if(in[ptr]=='\\' && in[ptr+1]=='\\'){
+ ptr+=2;
+ bidi_add_str_c(out,&new_length,limit,"\\\\");
+ continue;
+ }
+ else if((tr_command = is_hebrew_command(in+ptr,&cmd_len))!=NULL) {
+ ptr+=cmd_len;
+ bidi_add_str_c(out,&new_length,limit,tr_command);
+ }
+ else {
+ bidi_add_char_u(out,&new_length,limit,in[ptr]);
+ ptr++;
+ }
+ }
+
+}
+
+void bidi_grammar_skip_blank(FriBidiChar **ptr)
+{
+ FriBidiChar ch;
+ while((ch=**ptr)==' ' || ch=='\t' || ch=='\r' || ch=='\n')
+ ++*ptr;
+}
+
+/*
+ * format is following:
+ * "lh" - latin word, hebrew word,
+ * "l" - one latin word
+ * parameters are (FriBidiChar *) for h and (char *) for l
+ */
+int bidi_grammar(FriBidiChar *in,char *tagname,char *format,
+ FriBidiChar hebrew[MAX_COMMAND_LEN],
+ char ascii[MAX_COMMAND_LEN])
+{
+ if(!bidi_strieq_u_a(in,tagname)) {
+ return 0;
+ }
+
+ in+=strlen(tagname);
+
+ bidi_grammar_skip_blank(&in);
+
+ while(*format) {
+ if(*format=='h'){
+ if(!is_hebrew_tag(hebrew,&in)){
+ bidi_error("Hebrew word expected");
+ }
+ }
+ else if(*format == 'l') {
+ if(!is_ascii_tag(ascii,&in)){
+ bidi_error("Latin word expected");
+ }
+ }
+ else {
+ fprintf(stderr,"Internall error\n");
+ exit(1);
+ }
+ format++;
+ bidi_grammar_skip_blank(&in);
+ }
+ if(*in!=0) {
+ bidi_error("Unexpected charrecter");
+ }
+ return 1;
+}
+
+void bidi_parse_fribidixetex_command(FriBidiChar *in)
+{
+ FriBidiChar unicode[MAX_COMMAND_LEN];
+ char ascii[MAX_COMMAND_LEN];
+
+ if(bidi_grammar(in,TAG_BIDI_ON,"",NULL,NULL)) {
+ bidi_mode = MODE_BIDION;
+ }
+ else if(bidi_grammar(in,TAG_BIDI_OFF,"",NULL,NULL)) {
+ bidi_mode = MODE_BIDIOFF;
+ }
+ else if(bidi_grammar(in,TAG_BIDI_LTR,"",NULL,NULL)) {
+ bidi_mode = MODE_BIDILTR;
+ }
+ else if(bidi_grammar(in,TAG_BIDI_NEW_TAG,"l",NULL,ascii)) {
+ bidi_add_command(ascii);
+ }
+ else if(bidi_grammar(in,TAG_BIDI_DIC_TAG,"hl",unicode,ascii)) {
+ dict_add_tans(unicode,ascii,DICT_TAG);
+ }
+ else if(bidi_grammar(in,TAG_BIDI_DIC_ENV,"hl",unicode,ascii)) {
+ dict_add_tans(unicode,ascii,DICT_ENV);
+ }
+ else {
+ bidi_error("Unknown fribidixetex command");
+ }
+}
+
+/*********************
+ * M A I N L O O P *
+ *********************/
+
+/* Main line processing function */
+int bidi_process(FriBidiChar *in,FriBidiChar *out,
+ int replace_minus,int tranlate_only,int no_mirroring)
+{
+ int i,is_rtl;
+
+ if(bidi_strieq_u_a(in,"%BIDI")) {
+ bidi_parse_fribidixetex_command(in);
+ return 0;
+ }
+
+ if(bidi_mode != MODE_BIDIOFF) {
+ is_rtl = (bidi_mode == MODE_BIDION);
+ if(tranlate_only) {
+ /* In case of translation only put directly to output buffer */
+ bidi_translate_tags(in,out,MAX_LINE_SIZE);
+ }
+ else { /* Normal processing */
+ /* Translate hebrew tags to ascii tags */
+ bidi_translate_tags(in,translation_buffer,MAX_LINE_SIZE);
+
+ /* Apply BiDi algorithm */
+ bidi_add_tags(translation_buffer,out,MAX_LINE_SIZE,
+ is_rtl ,replace_minus,no_mirroring);
+ }
+ }
+ else {
+ for(i=0;in[i];i++){
+ out[i]=in[i];
+ }
+ out[i]=0;
+ }
+ return 1;
+}
+
+void bidi_finish(void)
+{
+ bidi_cmd_t *tmp;
+ while(bidi_command_list) {
+ tmp=bidi_command_list;
+ bidi_command_list=bidi_command_list->next;
+ utl_free(tmp->name);
+ utl_free(tmp);
+ }
+ if(bidi_mode != MODE_BIDIOFF) {
+ fprintf(stderr,"Warning: No %%BIDIOFF Tag at the end of the file\n");
+ }
+}
+
+void bidi_init(FILE *f_out)
+{
+ int i;
+
+ bidi_mode = MODE_BIDIOFF;
+
+ for(i=0;ignore_tags_list[i][0];i++) {
+ bidi_add_command(ignore_tags_list[i]);
+ }
+
+}
diff --git a/support/fribidixetex/src/fribidixetex-bidi.h b/support/fribidixetex/src/fribidixetex-bidi.h
new file mode 100644
index 0000000000..9f4e586caf
--- /dev/null
+++ b/support/fribidixetex/src/fribidixetex-bidi.h
@@ -0,0 +1,11 @@
+#ifndef _BIDI_H_
+#define _BIDI_H_
+#include <stdio.h>
+#include <fribidi/fribidi.h>
+
+void bidi_init(FILE *f_out);
+int bidi_process(FriBidiChar *in,FriBidiChar *out,
+ int replace_minus,int tranlate_only,int no_mirroring);
+void bidi_finish(void);
+
+#endif
diff --git a/support/fribidixetex/src/fribidixetex-defines.h b/support/fribidixetex/src/fribidixetex-defines.h
new file mode 100644
index 0000000000..fcbf3c8c29
--- /dev/null
+++ b/support/fribidixetex/src/fribidixetex-defines.h
@@ -0,0 +1,24 @@
+#ifndef _DEFINES_H_
+#define _DEFINES_H_
+
+enum { ENC_UTF_8 , ENC_ISO_8859_8, ENC_CP1255 };
+
+/*******************/
+/* PROJECT DEFINES */
+/*******************/
+
+#define MAX_LINE_SIZE 32768
+/* Maximal size of input/output line in the text */
+
+#define MAX_COMMAND_LEN 128
+/* Maxima length of defined command */
+
+#define ENC_DEFAULT ENC_UTF_8
+/* The default IO encoding - UTF-8 */
+
+
+#define MAX_USER_TRANSLATIONS 500
+
+/*******************/
+
+#endif /* _DEFINES_H_ */
diff --git a/support/fribidixetex/src/fribidixetex-dict.c b/support/fribidixetex/src/fribidixetex-dict.c
new file mode 100644
index 0000000000..fc2225d1c2
--- /dev/null
+++ b/support/fribidixetex/src/fribidixetex-dict.c
@@ -0,0 +1,145 @@
+#include "fribidixetex-dict.h"
+#include "fribidixetex-defines.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+/***********************
+ * D A T A *
+ ***********************/
+
+
+typedef struct
+{
+ wchar_t hebrew[MAX_COMMAND_LEN];
+ char ascii[MAX_COMMAND_LEN];
+}
+ dict_t;
+
+#define LETTER_ALEPH L'א'
+#define LETTER_TAV L'ת'
+
+#define SIZEOF_ARRAY(x) (sizeof(x)/sizeof(x[0]))
+
+dict_t dict_utf8_tags_perm[] =
+{
+ { L"ש", "L" },
+ { L"י", "R" },
+ { L"התחל", "begin" },
+ { L"סיים", "end" },
+ { L"כותרת", "title" },
+ { L"תוכןעניינים", "tableofcontents" },
+ { L"צורכותרת", "maketitle" },
+ { L"מחבר", "author" },
+ { L"תאריך", "date" },
+ { L"חלק", "part" },
+ { L"פרק", "chapter" },
+ { L"סעיף", "section" },
+ { L"תתסעיף", "subsection"},
+ { L"תתתתסעיף", "subsubsection"},
+ { L"הדגש", "emph" },
+ { L"פריט", "item" },
+ { L"נק", "item" },
+ { L"תג", "label" },
+ { L"ראה", "ref" },
+ { L"הערתשוליים", "footnote" },
+ { L"צטט", "cite" },
+ { L"נקודות", "ldots" },
+};
+
+dict_t dict_utf8_envs_perm[] =
+{
+ { L"פירוט","itemize"},
+ { L"תיאור","description" },
+ { L"מספור", "enumerate" },
+ { L"שיר", "verse" },
+ { L"מסמך", "document" },
+ { L"תקציר", "abstract" },
+};
+
+/*************/
+/* User tags */
+/*************/
+
+int user_tags_size=0;
+int user_envs_size=0;
+
+dict_t dict_utf8_tags_user[MAX_USER_TRANSLATIONS];
+dict_t dict_utf8_envs_user[MAX_USER_TRANSLATIONS];
+
+
+/**************/
+
+
+int dict_is_hebrew_letter(FriBidiChar ch)
+{
+ return (LETTER_ALEPH<=ch && ch<=LETTER_TAV);
+ /* Range from alef to tav in Unicode */
+}
+
+char *dict_find(FriBidiChar *str,dict_t *dictionary,int size)
+{
+ wchar_t *wstr;
+ int i;
+ FriBidiChar *bstr;
+
+ for(i=0;i<size;i++){
+ wstr=dictionary[i].hebrew;
+ bstr=str;
+ while(*bstr && *wstr && *bstr == (FriBidiChar)*wstr){
+ bstr++;
+ wstr++;
+ }
+ if(*bstr==0 && *wstr==0){
+ return dictionary[i].ascii;
+ }
+ }
+ return NULL;
+}
+
+
+char *dict_translate_env(FriBidiChar *str)
+{
+ char *ptr;
+ ptr=dict_find(str,dict_utf8_envs_perm,SIZEOF_ARRAY(dict_utf8_envs_perm));
+ if(ptr== NULL)
+ return dict_find(str,dict_utf8_envs_user,user_envs_size);
+ return ptr;
+}
+char *dict_translate_tag(FriBidiChar *str)
+{
+ char *ptr;
+ ptr=dict_find(str,dict_utf8_tags_perm,SIZEOF_ARRAY(dict_utf8_tags_perm));
+ if(ptr==NULL)
+ return dict_find(str,dict_utf8_tags_user,user_tags_size);
+ return ptr;
+}
+
+void dict_set_tag(dict_t *entry,FriBidiChar *uni,char *ascii)
+{
+ int i;
+ for(i=0;uni[i];i++)
+ entry->hebrew[i]=uni[i];
+ entry->hebrew[i]=0;
+ strcpy(entry->ascii,ascii);
+}
+
+void dict_add_tans(FriBidiChar *tag_uni,char *tag_ascii,int type)
+{
+ if(type == DICT_ENV) {
+ if(user_envs_size>=MAX_USER_TRANSLATIONS) {
+ fprintf(stderr,"Too many evironments translations added\n");
+ exit(1);
+ }
+ dict_set_tag(dict_utf8_envs_user+user_envs_size,tag_uni,tag_ascii);
+ user_envs_size++;
+ }
+ else {
+ if(user_tags_size>=MAX_USER_TRANSLATIONS) {
+ fprintf(stderr,"Too many tags translations added\n");
+ exit(1);
+ }
+ dict_set_tag(dict_utf8_tags_user+user_tags_size,tag_uni,tag_ascii);
+ user_tags_size++;
+ }
+}
diff --git a/support/fribidixetex/src/fribidixetex-dict.h b/support/fribidixetex/src/fribidixetex-dict.h
new file mode 100644
index 0000000000..d852a1e7a3
--- /dev/null
+++ b/support/fribidixetex/src/fribidixetex-dict.h
@@ -0,0 +1,16 @@
+#ifndef _DICT_H_
+#define _DICT_H_
+#include <fribidi/fribidi.h>
+
+enum {DICT_ENV, DICT_TAG};
+
+int dict_is_hebrew_letter(FriBidiChar ch);
+
+typedef char *(*trans_func_t)(FriBidiChar *str);
+char *dict_translate_env(FriBidiChar *str);
+char *dict_translate_tag(FriBidiChar *str);
+
+void dict_add_tans(FriBidiChar *tag_uni,char *tag_ascii,int type);
+
+
+#endif
diff --git a/support/fribidixetex/src/fribidixetex-ignore.c b/support/fribidixetex/src/fribidixetex-ignore.c
new file mode 100644
index 0000000000..c155d79303
--- /dev/null
+++ b/support/fribidixetex/src/fribidixetex-ignore.c
@@ -0,0 +1,20 @@
+/* All the tags that their content
+ * should be ignored by fribidixetex */
+const char *ignore_tags_list[] =
+{
+ "begin", "end", "fribidixetexRLE", "fribidixetexLRE", "fribidixetexlatinnumbers", "fribidixetexnonlatinnumbers",
+ "input", "include", "includegraphics", "includeonly",
+ "hspace", "vspace", "hspace*", "vspace*",
+ "ref", "label", "includegraphics",
+ "bibliographystyle",
+ "parbox",
+ "newenvironment", "newtheorem",
+ "persianmathdigitsfamily",
+ "fontfamily", "fontseries", "fontshape",
+ "rmdefault", "sfdefault", "ttdefault",
+ "bfdefault", "itdefault", "sldefault", "scdefault",
+ "pagenumbering", "pagestyle", "thispagestyle",
+ "setcounter", "stepcounter", "setlength", "addtolength"
+ "bibitem", "cite" ,""
+};
+
diff --git a/support/fribidixetex/src/fribidixetex-ignore.h b/support/fribidixetex/src/fribidixetex-ignore.h
new file mode 100644
index 0000000000..3d94f7c483
--- /dev/null
+++ b/support/fribidixetex/src/fribidixetex-ignore.h
@@ -0,0 +1,6 @@
+#ifndef _IGNORE_H_
+#define _IGNORE_H_
+
+extern const char *ignore_tags_list[];
+
+#endif
diff --git a/support/fribidixetex/src/fribidixetex-io.c b/support/fribidixetex/src/fribidixetex-io.c
new file mode 100644
index 0000000000..5d497162ed
--- /dev/null
+++ b/support/fribidixetex/src/fribidixetex-io.c
@@ -0,0 +1,110 @@
+#include <fribidi/fribidi.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "fribidixetex-io.h"
+
+static char text_buffer[MAX_LINE_SIZE];
+int io_line_number;
+
+void io_init(void)
+{
+ io_line_number=0;
+}
+
+int io_read_line(FriBidiChar *text,int encoding,FILE *f)
+{
+ int len_char,len_uni;
+ if(fgets(text_buffer,MAX_LINE_SIZE-1,f)==NULL) {
+ return 0;
+ }
+
+ len_char=strlen(text_buffer);
+
+ if(len_char==MAX_LINE_SIZE - 2) {
+ fprintf(stderr,"Warning: line %d is too long\n",io_line_number+1);
+ }
+ if(len_char>0 && text_buffer[len_char-1]=='\n') {
+ io_line_number++;
+ text_buffer[len_char-1]=0;
+ len_char--;
+ }
+ switch(encoding) {
+ case ENC_ISO_8859_8:
+ len_uni=fribidi_charset_to_unicode(FRIBIDI_CHAR_SET_ISO8859_8,text_buffer,len_char,text);
+ text[len_uni]=0;
+ break;
+ case ENC_CP1255:
+ len_uni=fribidi_charset_to_unicode(FRIBIDI_CHAR_SET_CP1255,text_buffer,len_char,text);
+#if ( FRIBIDI_MAJOR_VERSION * 100 + FRIBIDI_MINOR_VERSION ) <= 10 // 0.10
+ {
+ int i;
+ for(i=0;i<len_uni;i++) {
+ if(text[i]==253 || text[i]==254)
+ text[i] += (0x200E - 253);
+ }
+ }
+#endif
+ text[len_uni]=0;
+ break;
+ case ENC_UTF_8:
+ if(len_char >= 3 && memcmp(text_buffer,"\xEF\xBB\xBF",3) == 0) {
+ // remove BOM, support Win32 Notepad
+ len_uni=fribidi_charset_to_unicode(FRIBIDI_CHAR_SET_UTF8,text_buffer+3,len_char-3,text);
+ }
+ else {
+ len_uni=fribidi_charset_to_unicode(FRIBIDI_CHAR_SET_UTF8,text_buffer,len_char,text);
+ }
+ text[len_uni]=0;
+ break;
+ default:
+ fprintf(stderr,"Internal error - wrong encoding\n");
+ exit(1);
+ }
+ return 1;
+}
+
+void io_write_line(FriBidiChar *text,int encoding,FILE *f)
+{
+ int len,char_len,tmp_len;
+ /* Find legth of buffer */
+ for(len=0;text[len] && len<MAX_LINE_SIZE-1;len++) /* NOTHING */;
+
+ if(len>=MAX_LINE_SIZE-1) {
+ fprintf(stderr,"Internall error - unterminated line\n");
+ exit(1);
+ }
+
+ if(encoding == ENC_ISO_8859_8) {
+ char_len=fribidi_unicode_to_charset(FRIBIDI_CHAR_SET_ISO8859_8,text,len,text_buffer);
+ text_buffer[char_len]=0;
+ fprintf(f,"%s\n",text_buffer);
+ }
+ else if(encoding == ENC_CP1255) {
+ char_len=fribidi_unicode_to_charset(FRIBIDI_CHAR_SET_CP1255,text,len,text_buffer);
+ text_buffer[char_len]=0;
+ fprintf(f,"%s\n",text_buffer);
+ }
+ else if(encoding == ENC_UTF_8) {
+ while(len) {
+ /* Because maybe |unicode| < |utf8|
+ * in order to prevetn overflow */
+ if(len>MAX_LINE_SIZE/8){
+ tmp_len=MAX_LINE_SIZE/8;
+ }
+ else {
+ tmp_len = len;
+ }
+ char_len=fribidi_unicode_to_charset(FRIBIDI_CHAR_SET_UTF8,text,tmp_len,text_buffer);
+ text_buffer[char_len]=0;
+ fprintf(f,"%s",text_buffer);
+ len -= tmp_len;
+ text += tmp_len;
+ }
+ fprintf(f,"\n");
+ }
+ else {
+ fprintf(stderr,"Internal error - wrong encoding\n");
+ exit(1);
+ }
+}
diff --git a/support/fribidixetex/src/fribidixetex-io.h b/support/fribidixetex/src/fribidixetex-io.h
new file mode 100644
index 0000000000..63145d0519
--- /dev/null
+++ b/support/fribidixetex/src/fribidixetex-io.h
@@ -0,0 +1,15 @@
+#ifndef _IO_H_
+#define _IO_H_
+
+#include <stdio.h>
+#include <fribidi/fribidi.h>
+#include "fribidixetex-defines.h"
+
+int io_read_line(FriBidiChar *text,int encoding,FILE *f);
+void io_write_line(FriBidiChar *text,int encoding,FILE *f);
+
+void io_init(void);
+
+extern int io_line_number;
+
+#endif
diff --git a/support/fribidixetex/src/fribidixetex-util.c b/support/fribidixetex/src/fribidixetex-util.c
new file mode 100644
index 0000000000..12ebed6245
--- /dev/null
+++ b/support/fribidixetex/src/fribidixetex-util.c
@@ -0,0 +1,28 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include "fribidixetex-util.h"
+
+void *utl_malloc(size_t size)
+{
+ void *ptr;
+ ptr=malloc(size);
+ if(!ptr) {
+ fprintf(stderr,"Out of memory\n");
+ exit(1);
+ }
+ return ptr;
+}
+void *utl_realloc(void *inptr,size_t size)
+{
+ void *ptr;
+ ptr=realloc(inptr,size);
+ if(!ptr) {
+ fprintf(stderr,"Out of memory\n");
+ exit(1);
+ }
+ return ptr;
+}
+void utl_free(void *ptr)
+{
+ free(ptr);
+}
diff --git a/support/fribidixetex/src/fribidixetex-util.h b/support/fribidixetex/src/fribidixetex-util.h
new file mode 100644
index 0000000000..84eedeb28c
--- /dev/null
+++ b/support/fribidixetex/src/fribidixetex-util.h
@@ -0,0 +1,9 @@
+#ifndef _UTL_H_
+#define _UTL_H_
+#include <stdlib.h>
+
+void *utl_malloc(size_t size);
+void *utl_realloc(void *ptr,size_t size);
+void utl_free(void *ptr);
+
+#endif
diff --git a/support/fribidixetex/src/fribidixetex.c b/support/fribidixetex/src/fribidixetex.c
new file mode 100644
index 0000000000..0df17b4e03
--- /dev/null
+++ b/support/fribidixetex/src/fribidixetex.c
@@ -0,0 +1,184 @@
+/*********************************/
+/* Copyright Vafa Khalighi 2016 */
+/* Copyright Khaled Hosny 2015 */
+/* Copyright Artyom Tonkikh 2007 */
+/* License GPL */
+/*********************************/
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <fribidi/fribidi.h>
+
+#include "fribidixetex-defines.h"
+#include "fribidixetex-io.h"
+#include "fribidixetex-bidi.h"
+
+void help(void)
+{
+ fprintf(stderr,
+ "usage: fribidixetex [ parameters ] [ inputfilename ]\n"
+ " -o file_name.tex - output file name\n"
+ " -e utf8 | iso8859-8 | cp1255 - encoding\n"
+ " -t utf8 | iso8859-8 | cp1255 - output encoding\n"
+ " -d transalte only - not apply bidi\n"
+ " this is usefull for latex2html that has native\n"
+ " bidirectional support\n"
+ " -m replace '--' & '---'\n"
+ " by '\\fribidixetexLRE{--} & \\fribidixetexLRE{'---'}\n"
+ " -n no mirroring - do not mirror parethesis\n"
+ " for engines that do that natively (like XeTeX)\n"
+ );
+ exit(1);
+}
+
+
+/* Read cmd line parameters */
+void read_parameters(int argc,char **argv,
+ char **fname_in,char **fname_out,
+ int *encoding,int *out_encoding,
+ int *replace_minus,int *transalte_only,
+ int *no_mirroring)
+{
+ int i;
+ int cnt1=0,cnt2=0,cnt3=0,cnt4=0;
+ int *ptr;
+
+ for(i=1;i<argc;i++){
+ if(strcmp(argv[i],"-h")==0) {
+ help();
+ }
+ else if(strcmp(argv[i],"-d")==0) {
+ *transalte_only = 1;
+ }
+ else if(strcmp(argv[i],"-m")==0) {
+ *replace_minus = 1;
+ }
+ else if(strcmp(argv[i],"-n")==0) {
+ *no_mirroring = 1;
+ }
+ else if(strcmp(argv[i],"-o")==0) {
+ i++;
+ if(i>=argc){
+ help();
+ }
+ *fname_out = argv[i];
+ cnt1++;
+ }
+ else if(strcmp(argv[i],"-e")==0 || strcmp(argv[i],"-t")==0) {
+ if(i+1>=argc){
+ help();
+ }
+
+ if(argv[i][1]=='e'){
+ ptr=encoding;
+ cnt2++;
+ }
+ else{
+ ptr=out_encoding;
+ cnt4++;
+ }
+ i++;
+ if(strcmp(argv[i],"utf8")==0) {
+ *ptr=ENC_UTF_8;
+ }
+ else if(strcmp(argv[i],"cp1255")==0) {
+ *ptr=ENC_CP1255;
+ }
+ else if(strcmp(argv[i],"iso8859-8")==0) {
+ *ptr=ENC_ISO_8859_8;
+ }
+ else {
+ help();
+ }
+ }
+ else {
+ *fname_in=argv[i];
+ cnt3++;
+ }
+ }
+ if(cnt1>1 || cnt2>1 || cnt3>1 || cnt4>1){
+ help();
+ }
+}
+
+/* Global buffers */
+
+static FriBidiChar text_line_in[MAX_LINE_SIZE];
+static FriBidiChar text_line_out[MAX_LINE_SIZE];
+
+/****************************
+ ******** M A I N ***********
+ ****************************/
+int main(int argc,char **argv)
+{
+ char *fname_in=NULL,*fname_out=NULL;
+ int encoding=ENC_DEFAULT,out_encoding = -1;
+ int replace_minus = 0;
+ int transalte_only = 0;
+ int no_mirroring = 0;
+
+ FILE *f_in,*f_out;
+
+ /******************
+ * Inicialization *
+ ******************/
+
+ read_parameters(argc,argv,&fname_in,&fname_out,
+ &encoding,&out_encoding,
+ &replace_minus,&transalte_only,
+ &no_mirroring);
+ if(out_encoding == -1) {
+ out_encoding = encoding;
+ }
+
+ if(!fname_in) {
+ f_in = stdin;
+ }
+ else {
+ if(!(f_in=fopen(fname_in,"r"))) {
+ fprintf(stderr,"Failed to open %s for reading\n",fname_in);
+ exit(1);
+ }
+ }
+
+ if(!fname_out) {
+ f_out = stdout;
+ }
+ else {
+ if(!(f_out=fopen(fname_out,"w"))) {
+ fprintf(stderr,"Failed to open %s for writing\n",fname_out);
+ exit(1);
+ }
+ }
+
+
+ /*************
+ * Main loop *
+ *************/
+
+ io_init();
+
+ bidi_init(f_out);
+
+ while(io_read_line(text_line_in,encoding,f_in)) {
+
+ if(bidi_process(text_line_in,text_line_out,
+ replace_minus,transalte_only,no_mirroring))
+ {
+ /*If there is something to print */
+ io_write_line(text_line_out,out_encoding,f_out);
+ }
+
+ }
+
+ /**********
+ * Finish *
+ **********/
+
+ if(f_out!=stdout) fclose(f_out);
+ if(f_in!=stdin) fclose(f_in);
+
+ bidi_finish();
+
+ return 0;
+}