Hi.
This will help you build a shared library that will let you display, in the proper visual way, strings that have a mix of languages, like a mix of Arabic and Latin. FriBidi is the library which does it. This page has a C code that you have to build to bind Tcl with FriBidi.
/* Author: auriocus */ #include <tcl.h> #include <fribidi.h> static int fribidi_log2visCmd( ClientData clientData, /* Not used. */ Tcl_Interp *interp, /* Current interpreter */ int objc, /* Number of arguments */ Tcl_Obj *const objv[] /* Argument strings */ ) { if (objc != 2) { Tcl_WrongNumArgs (interp, 1, objv, "string"); return TCL_ERROR; } /* convert arg1 to FriBidiChar = UTF32 */ int len; char *str = Tcl_GetStringFromObj(objv[1], &len); /* the string can have at most len characters */ FriBidiChar *frstr = ckalloc(sizeof(FriBidiChar)*len); int len_res = len, ind = 0; while (len_res >0) { Tcl_UniChar ch; int nbytes = Tcl_UtfToUniChar(str, &ch); str += nbytes; len_res -= nbytes; frstr[ind++] = ch; } int nchar = ind; /* nr. of characters in this string */ /* I don't understand FriBidiCharType. Does it need a chartype for every single char? */ FriBidiCharType *pbase_dir = ckalloc(sizeof(FriBidiCharType)*(nchar+1)); for (ind = 0; ind < nchar; ind ++) { pbase_dir[ind] = FRIBIDI_TYPE_ON; } /* alloc buffer for result */ FriBidiChar *visual_str = ckalloc(sizeof(FriBidiChar)*(nchar+1)); fribidi_boolean result = fribidi_log2vis( /* input */ frstr, nchar, pbase_dir, /* output */ visual_str, NULL, NULL, NULL ); /* free input */ ckfree(pbase_dir); ckfree(frstr); /* Does the result indicate failure? */ if (result) { /* Success ? */ /* copy output to new string in Tcl_UniChar format */ Tcl_UniChar *uniresult = ckalloc(sizeof(Tcl_UniChar)*(nchar+1)); for (ind=0; ind < nchar; ind++) { uniresult[ind] = visual_str[ind]; } Tcl_SetObjResult(interp, Tcl_NewUnicodeObj(uniresult, nchar)); ckfree(uniresult); ckfree(visual_str); return TCL_OK; } else { /* Failure ? */ Tcl_SetResult(interp, "fribidi failed", NULL); ckfree(visual_str); return TCL_ERROR; } } int Tclfribidi_Init(Tcl_Interp *interp) { /* * This may work with 8.0, but we are using strictly stubs here, * which requires 8.1. */ if (Tcl_InitStubs(interp, "8.5", 0) == NULL) { return TCL_ERROR; } Tcl_CreateObjCommand(interp, "fribidi_log2vis", (Tcl_ObjCmdProc *) fribidi_log2visCmd, (ClientData)NULL, (Tcl_CmdDeleteProc *)NULL); return TCL_OK; }
Before anything: Don't forget to change the Tcl version number from 8.6 to 8.5 in the following gcc commands if you have Tcl8.5 .
32 bit systems and using the debian package tcl8.6-dev, run the following command on the terminal:
/usr/bin/gcc -shared -DUSE_TCL_STUBS -I/usr/include/fribidi -I/usr/include/tcl8.6 -lfribidi -o tclfribidi.so tclfribidi.c -ltclstub8.6
32 bit systems and using the ActiveTcl8.6, run the following command on the terminal:
/usr/bin/gcc -shared -DUSE_TCL_STUBS -I/usr/include/fribidi -I/opt/ActiveTcl-8.6/include/ -lfribidi -o tclfribidi.so tclfribidi.c -L/opt/ActiveTcl-8.6/lib/ -ltclstub8.6
64 bit systems and using the debian package tcl8.6-dev, run the following command on the terminal:
/usr/bin/gcc -shared -DUSE_TCL_STUBS -I/usr/include/fribidi -I/usr/include/tcl8.6 -fPIC -lfribidi -o tclfribidi.so tclfribidi.c -ltclstub8.6
64 bit systems and using the ActiveTcl8.6, run the following command on the terminal:
/usr/bin/gcc -shared -DUSE_TCL_STUBS -I/usr/include/fribidi -I/opt/ActiveTcl-8.6/include/ -fPIC -lfribidi -o tclfribidi.so tclfribidi.c -L/opt/ActiveTcl-8.6/lib/ -ltclstub8.6
Assume that you wrote a Tcl script in the same directory of the shared library file tclfribidi.so, then:
load ./tclfribidi.so #the Arabic in following string , when you type in tkcon or tclsh, should look separated and reversed. '''Don't copy the code below.''' Please use your own string. fribidi_log2vis "Rani fayez ahmad ي ن ا ر ز ي ا ف د م ح ا" #output is : Rani fayez ahmad راني فايز