Previous section.

Portable Layout Services: Context-dependent and Directional Text

Portable Layout Services:
Context-dependent and Directional Text
Copyright © 1997 The Open Group

Implementation Example

This appendix contains examples of possible uses of the layout transformation APIs in Motif 2.0. Internationalised Motif Program to Support Layout APIs is an internationalised program ("hello world") that has been modified in such a way that using modifiers it can be localised in a BIDI environment at run time. Storage to Explicit Controls and Explicit to Visual Buffer show possible usages of the layout APIs to perform the transformations that are depicted in Layout Transformations in Motif . Storage to Explicit Controls handles conversion from storage (implicit in this case) to type XmString (ISO/IEC 6429 standard controls). Explicit to Visual Buffer handles conversions from type XmString to the display (visual) buffer. In Storage to Explicit Controls and Explicit to Visual Buffer four controls are used:

<RTL>
Right-to-left explicit control.

<LTR>
Left-to-right explicit control.

<push>
Start reverse global direction.

<pop>
End push.

Example: Internationalised Motif Program to Support Layout APIs
/*
 *  The following is an example of an internationalised Motif hello
 *  world program that has been modified to support Bidirectional text.
 *  The layout values are passed via a modifier string thus allowing
 *  the internationalised program to be localised at run time.
 */

#include <stdio.h>

#include <Xm/Xm.h>
#include <Xm/Form.h>
#include <Xm/PushB.h>
#include <locale.h>
#include <sys/layout.h>

static void helloworld_button_activate();

Display            *display;
XtAppContext       app_context;
LayoutObject       plh;
char               *inp;

/*
 *  Define layoutModifier resource to allow localisation
 *  of the text being passed to hello world.
 */
#define  XtNlayoutModifier   "layoutModifier"
#define  XtCLayoutModifier   "LayoutModifier"
char               *lo_modifier;
static XtResource lo_resources[] = {
  { XtNlayoutModifier, XtCLayoutModifier, XmRString, sizeof(String),
       0, XmRString, (String) NULL}
};

/*
 *  Main program
 */
int main(argc, argv)
unsigned int argc;
char **argv;
{
    /*
     *   Declare the variables to contain the two widget ids.
     */
    Widget toplevel, bulletin, pushb;
    Arg  arglist[3] ;
    int  n;

    if (argc > 1)
    inp = argv[1];
    else {
    fprintf(stderr,"Incorrect number of arguments");
    exit(0);
    }

    XtSetLanguageProc(NULL,NULL,NULL);

    XtToolkitInitialize();

    app_context    = XtCreateApplicationContext();

    display = XtOpenDisplay(app_context, NULL, argv[0],
                            "helloworldclass",
                             NULL, 0, &argc, argv);
    if (display    == NULL) {
    fprintf(stderr,     "%s:  Can't open display", argv[0]);
    exit(1);
    }

    n =  0;
    XtSetArg(arglist[n], XmNallowShellResize, True);  n++;
    toplevel = XtAppCreateShell(argv[0], NULL,
                                applicationShellWidgetClass,
                                display, arglist,  n);

    /* Set up the lo_modifier */
    XtGetApplicationResources(toplevel,     &lo_modifier, lo_resources,
                   XtNumber(lo_resources), NULL, 0);

    XtSetArg (arglist[0], XmNwidth, 200);
    XtSetArg (arglist[1], XmNheight, 100);
    bulletin = XmCreateBulletinBoard(toplevel, "bulletin", arglist, 2);
    XtManageChild(bulletin);

    XtSetArg (arglist[0], XmNlabelString,
              XmStringCreateLtoR("Press Button...",
         XmSTRING_DEFAULT_CHARSET));
    pushb = XmCreatePushButtonGadget(bulletin, "push", arglist, 1);
    XtAddCallback (pushb, XmNactivateCallback,
                   helloworld_button_activate,NULL);
    XtManageChild(pushb);

    /*
     *  Realise the top-level widget. This will
     *  cause the entire "managed"
     *  widget hierarchy to be displayed.
     */

    XtRealizeWidget(toplevel);

    /*
     *  Loop and process events.
     */

    XtAppMainLoop(app_context);

    /* UNREACHABLE */
    return (0);
}

BooleanValue reorder_or_shaping( plh )
LayoutObject plh;
{
    size_t index = 0;
    LayoutValueRec lo_values[3];
    int rc = 0;
    BooleanValue directional;
    BooleanValue shaping;

    lo_values[0].name = ActiveShapeEditing ;
    lo_values[0].value = (LayoutValue) &shaping ;
    lo_values[1].name = ActiveDirectional ;
    lo_values[1].value = (LayoutValue) &directional ;
    lo_values[2].name = 0;

    rc = m_getvalues_layout(plh, lo_values, &index);
    if (rc)
    {
      perror("m_getvalues_layout");
      exit(1);
    }

    return ( shaping || directional );
}

static void helloworld_button_activate(     widget,   tag,
                                        callback_data )
    Widget    widget;
    char *tag;
    XmAnyCallbackStruct *callback_data;
{
    Arg  arglist[2];

    static int call_count = 0;
    char *label;
    size_t inpsize, label_size;
    size_t index = 0;
    int rc = 0;
    int mask = 0;

    call_count += 1 ;
    switch ( call_count )
    {
    case 1:
        plh   = m_create_layout(NULL,  lo_modifier);

        if ( ! reorder_or_shaping(plh) )
             {
             XtSetArg( arglist[0], XmNlabelString,
              XmStringCreateLocalized(inp));
             }
        else
        {
            inpsize = strlen(inp);
             label = (char *)malloc(inpsize+1);
             memset(label, 0, inpsize+1);
             rc = m_transform_layout(plh, inp, inpsize,
              label, &label_size, NULL, NULL,    NULL, &index);
             if (rc)
             {
              perror("m_transform_layout");
              exit(1);
             }

             XtSetArg( arglist[0], XmNlabelString,
              XmStringCreateLocalized(label));
             free(label);
        }
        m_destroy_layout(plh);
        XtSetArg( arglist[1], XmNx,    11 );
        XtSetValues( widget, arglist, 2 );
        break ;
    case 2:
        exit(0);
        break ;
    }
}

Example: Storage to Explicit Controls
#include <sys/layout.h>
#include <errno.h>
#include <locale.h>

main
{
  LayoutObject plh;
  int rc=0;
  LayoutValues layout;
  LayoutTextDescriptor descr;
  int index;
  char *inpbuff="AB cde 123Z";
  char *outbuff;
  size_t inpsize;
  size_t outsize;
  size_t index=0;

  /* Create layout object */
  plh = m_create_layout(NULL, NULL);

  /* Set the internal "in" and "out" values of the TypeOfText */
  /* descriptor to initiate the "implicit" to "explicit" */
  /* transformation, with character shaping and national numerals */

  layout=malloc(2*sizeof(LayoutValueRec));
  descr=malloc(sizeof(LayoutTextDescriptorRec));

  layout[0].name=TypeOfText;
  layout[0].value=(caddr_t)descr;
  layout[1].name=0;

  descr->in=TEXT_IMPLICIT;
  descr->out=TEXT_EXPLICIT;

  rc = m_setvalues_layout(plh,layout,&index);
  if (rc)
  {
      perror("m_setvalues_layout : ");
      exit(0);
  }

  /* Set the input buffer size */

  inpsize = strlen(inpbuff);

  /* Now, allocate an outbuff large enough to contain the original
     buffer plus the embedded escapes */

  outbuff = (char *)malloc(inpsize*sizeof(char)*2);

  rc = m_transform_layout(plh, inpbuff, inpsize, outbuff, &outsize, 
                          NULL, NULL, NULL, &index);

  if (rc)
  {
      perror("m_transform_layout : ");
      exit(0);
  }

  free(layout);
  free(descr);

  /* Free layout object */

  rc = m_destroy_layout(plh);
  if (rc)
     perror("m_destroy_layout : ");
}

The output of m_transform_layout() is the original string with some embedded escapes:

inpbuff:  AB cde 123Z

Because the original orientation is LTR, the level 1 segment has an RTL orientation.

outbuf:   <LTR>AB <Push><RTL>cde <LTR>123<Pop><LTR>Z


Example: Explicit to Visual Buffer

The next program segment converts the explicit buffer to a visual buffer:

main
{
  LayoutObject plh;
  int rc=0;
  LayoutValues layout;
  LayoutTextDescriptor descr;
  int index;
  char *inpbuff="<LTR>AB <Push><RTL>cde <LTR>123<Pop><LTR>Z";
  char *outbuff;
  size_t inpsize;
  size_t outsize;
  size_t index=0;
  size_t query_size;

  /* Create layout object */

  plh = m_create_layout(NULL, NULL);

  layout=malloc(2*sizeof(LayoutValueRec));
  descr=malloc(sizeof(LayoutTextDescriptorRec));

  /*  Overwrite some of the locale default text descriptor settings.
  /*  But beforehand, query values of shapecharset.
   */
  layout[0].name = ShapeCharset|QueryValueSize;
  layout[0].value = &query_size;
         m_getvalues_layout(plh, layout, &index);

  layout[0].name = ShapeCharset;
  layout[0].value = (char *)malloc(query_size);
     rc = m_getvalues_layout(plh, layout, &index);
         if (rc)
         {
           perror("m_getvalues_layout : ");
            exit(0);
         }

  layout[0].name=TypeOfText|TextShaping|Numerals;
  layout[0].value=(caddr_t)descr;
  layout[1].name=0;

  descr->in=TEXT_EXPLICIT|TEXT_NOMINAL|NUMERALS_NOMINAL;
  descr->out=TEXT_VISUAL|TEXT_SHAPED|NUMERALS_NATIONAL;

  rc = m_setvalues_layout(plh,layout,&index);
  if (rc)
  {
      perror("m_setvalues_layout : ");
      exit(0);
  }

  /* Set the input buffer size and Allocate the output arrays */

  inpsize = strlen(inpbuff);

  outbuff = (char *)malloc(inpsize*sizeof(char));

  rc = m_transform_layout(plh, inpbuff, inpsize, outbuff, &outsize, 
                          NULL, NULL, NULL, &index);

  if (rc)
  {
      perror("m_transform_layout : ");
      exit(0);
  }

  /* user defined function that prints the output arrays to the user */

  free(layout);
  free(descr);
  free(outbuff);

  /* Free layout object */

  rc = m_destroy_layout(plh);
  if (rc)
     perror("m_destroy_layout : ");
}

The output of the transform function is:

AB 456 zyxZ

where 456 are the national numbers for 123, and zyx are the national letters for edc.


Why not acquire a nicely bound hard copy?
Click here to return to the publication details or order a copy of this publication.

Contents Next section Index