[ Previous | Next | Contents | Glossary | Home | Search ]
Motif 2.1 Programmer's Guide



The Structure of a Compound String

A compound string is an opaque data structure consisting of one or more pieces of encoded text, and information about how to display each piece.

  1. XmString

    This information consists of the direction in which to draw the text, and the name (also called the "tag") of one or more "renditions," which specify attributes of the drawn text, such as the font, the color of the text and its background, whether the text should be underlined or struck through, and a list of tab stops. The data type for a compound string is XmString.

    A compound string is divided into "components," which identify the various parts of the compound string. A compound string component could be the text itself, without the rendition and direction, or it could be the direction indicator alone, or the rendition tag itself.

    There are several different kinds of compound string components.

    1. XmStringComponentType

    2. XmStringDirection

    3. XmStringTag

      Each of them consists of a component identifier (data type XmStringComponentType), and the component value, usually in the form of a text string. The text string might contain the text of the compound string, but it also might contain the tag of a rendition to use, the name of a character set, or the name of the current locale. For a complete list of the possible values of XmStringComponentType, and the order in which they should appear, please refer to the XmStringComponentType page of the Motif Programmer's Reference.

      The direction of a compound string is stored so that the data structure will be equally useful for describing text in left-to-right languages such as English, Spanish, French, and German, and for text in right-to-left languages such as Hebrew and Arabic. The direction is stored as data type XmStringDirection, which may have the values XmSTRING_DIRECTION_L_TO_R or XmSTRING_DIRECTION_R_TO_L. A widget may itself have a default direction, called its "layout direction." For information about the interaction between a widget's layout direction and the string direction of a compound string to be displayed in that widget, please see chapter 11 of this manual, "Internationalization."

      Another important compound string component is the "separator," which contains no text. When displayed, a separator usually maps to a line break. Do not confuse these with the Separator widget, which is also called XmSeparator.

      An XmStringTag indicates the name, or "tag," of a particular rendition. The rendition describes several attributes to use when rendering a compound string, such as the font to use, the color, a list of tab stops, and whether the text is to be displayed underlined or struck out. Each rendition contains an XmStringTag that must match the tag included in the string itself.

      Note:

      The rendition tag should not be confused with the charset tag, which exists for compatibility with previous releases of Motif, or the locale tag, which specifies the locale for internationalized applications. In a compound string, these tags are specified with the XmSTRING_COMPONENT_TAG component, while the rendition tags are specified in the XmSTRING_COMPONENT_RENDITION_BEGIN and XmSTRING_COMPONENT_RENDITION_END components. The charset tag was called the fontlist tag in previous releases of Motif.

      Several renditions together make up a render table, and a compound string component can actually be associated with more than one tag, indicating more than one rendition. Multiple renditions will be merged when the text is displayed. (See section 9.2.3 for a more complete description of the merging process.)

      A rendition may also be indicated through a locale specification. See the chapter of this manual on Internationalization for more information about locales.

      The rendition table and rendition tag structure parallels the old font list and font list element tag structure of earlier releases of Motif. The rendition structure has augmented, not supplanted, the font list. Font Lists should be considered obsolete, and their use should be avoided. However, for the purposes of compatibility with existing software, the font management function calls and data structures still exist. If both a font list and a render table are specified for some widget, the render table will take precedence, and the font list will be ignored.

    4. Creating a Compound String

      There are several different functions available to create a compound string.

      1. XmStringGenerate

      2. XmStringComponentCreate

        The most basic such function is XmStringGenerate, which accepts as arguments the text to be encoded, and a rendition tag to use to display it. It also accepts information about the locale or charset to use in rendering the text. The function returns an encoded XmString.

        The XmStringComponentCreate function is used to create individual components of a compound string, such as the text, the tag, the direction, or the separator, which can then be concatenated into a single longer string.

        There are a few functions that create a compound string which are obsolete, but are included for compatibility with earlier releases of Motif.

        1. XmStringCreate

        2. XmStringSegmentCreate

        3. XmStringSeparatorCreate

          XmStringCreate may also be used to create a compound string of charset type with a specified font tag, with no rendition specified. The XmStringCreate function has been superseded, but is included for backward compatibility. Its function can be easily duplicated by calling XmStringGenerate with the text type XmCHARSET_TEXT, a charset tag, and a NULL rendition tag. XmStringSegmentCreate functions in the same manner to XmStringCreate, but allows the programmer to specify the string direction, and whether a separator should be appended to the returned XmString.

          Earlier releases of Motif also included the functions XmStringCreateLtoR and XmStringCreate. These are still available, but again only for purposes of backward compatibility with existing code. Use XmStringGenerate instead.

          The XmStringSeparatorCreate function may also be used instead of XmStringSegmentCreate to create a separator component for a compound string. In display, the separator would typically be mapped to a line break. Note that this function will not do anything more than XmStringSegmentCreate would if called with an empty text string.

          The application that calls the compound string creation functions is responsible for performing its own memory management. The creation functions all must allocate space in which to return the strings.

          1. XmStringFree

            When an application is finished with a compound string, the XmStringFree function should be used to free the memory that had been used for that string, and to make it available for some other purpose.

            The following code sample demonstrates the use of XmStringGenerate and XmStringFree to create and display a compound string in a PushButton gadget.

            void RendCB(Widget, XtPointer, XtPointer);
            XmString        rend_label1, rend_label2;
            widget  rend_button1, rend_button2;
            XmRenderTable RenderTable;
             
            /* RenderTable created with two renditions:
             * Rendition1 and Rendition2 */
             
            RendPullDown = (Widget)XmCreatePulldownMenu(menubar, "RendPullDown",
                                                        NULL, 0);
             
            rend_label1=XmStringGenerate("render1", NULL, XmCHARSET_TEXT,
                                         "Rendition1");
            rend_label2=XmStringGenerate("render2", NULL, XmCHARSET_TEXT,
                                         "Rendition2");
             
            rend_button1 = XtVaCreateManagedWidget("rend1", xmPushButtonGadgetClass,
                                            RendPullDown,
                                            XmNrenderTable, RenderTable,
                                            XmNlabelString, rend_label1,
                                            NULL);
            rend_button2 = XtVaCreateManagedWidget("rend2", xmPushButtonGadgetClass,
                                            RendPullDown,
                                            XmNrenderTable, RenderTable,
                                            XmNlabelString, rend_label2,
                                            NULL);
            XtAddCallback(rend_button1, XmNactivateCallback, RendCB, (XtPointer) 0);
            XtAddCallback(rend_button2, XmNactivateCallback, RendCB, (XtPointer) 1);
             
            XmStringFree(rend_label1);
            XmStringFree(rend_label2);

            Note that the description of Rendition1 and Rendition2 must be explicitly sent to the widgets by using the XmNrenderTable resource to specify the render table containing these renditions. See section 9.2 about renditions and render tables. Also note that rend1 and rend2 are the names of the PushButton widgets; they are not the labels that will appear on those widget.

          2. Compound Strings and Resource Files

            In an internationalized program, the labels and messages used to communicate with the user should be stored independently of the binary code of the compiled application, generally in external files. Under these conditions, adapting a program to different locales becomes as simple as replacing the external files. The compound strings used in Motif button labels and menu titles can be retrieved from X resource files.

            In the preceding code example, the button label could have come from a resource file instead of being coded into the program. For this example, assume that the PushButtons are children of a widget called RendPullDown. The following example specifies two compound strings with the same rendition.

            *RendPullDown.rend_button1.labelString:  render1
            *RendPullDown.rend_button2.labelString:  render2

            Here, Motif's string-to-compound-string converter produces a compound string from the resource file text. If the rendition is not specified, as in this example, the converter uses the rendition corresponding to the tag _MOTIF_DEFAULT_LOCALE. The format for specifying a rendition tag is analogous to the format for specifying a widget. The following example will draw the render1 label with the rendition tagged by rendition1, and draw the render2 label with the rendition2 rendition. A later section of this chapter describes how a rendition and render table can be specified in a resource file.

            *RendPullDown.rend_button1.renderTable.rendition1:  render1
            *RendPullDown.rend_button2.renderTable.rendition2:  render2

            Note that, when a compound string is specified in this manner, the string direction is inherited from the widget XmNlayoutDirection resource.

            Compound String Manipulation

            To make working with compound strings as simple as using regular character strings, Motif contains a number of functions analogous to the basic string manipulation functions generally available with C.

            1. XmStringCompare

            2. XmStringConcat

            3. XmStringConcatAndFree

            4. XmStringCopy

            5. XmStringEmpty

            6. XmStringIsVoid

              Use XmStringCompare to determine whether its two input compound strings are identical. XmStringConcat creates a third string by concatenating its two input strings. XmStringConcatAndFree does the same thing, except that it also deletes the two input strings and frees the memory occupied by them. XmStringCopy allocates enough memory to hold a copy of its input string, and returns a copy there. The XmStringEmpty function returns a Boolean value of True if there is no printable text in the input compound string. The XmStringIsVoid function is the same as the XmStringEmpty function except that it will only return True if there is no text at all in the string, printable or unprintable.

              The following example takes an existing compound string called string, and sandwiches it with a new rendition, called rendition. This may also be accomplished with the XmStringPutRendition function (see section 9.2.3.1).

              XmString  string;
              XmString  tmp1, tmp2;
               
              tmp1 = XmStringComponentCreate(
                           XmSTRING_COMPONENT_RENDITION_BEGIN, "rendition");
              tmp2 = XmStringComponentCreate(
                           XmSTRING_COMPONENT_RENDITION_END, "rendition");
               
              string = XmStringConcat(tmp1, string);
              XmStringFree(tmp1);
              string = XmStringConcat(string, tmp2);
              XmStringFree(tmp2);

              Display of the new string will use a composite rendition formed through a merge of the pre-existing rendition with the rendition rendition. See section 9.2.3 on render tables for the rules of merging renditions.

            7. Reading a Compound String

              Motif provides two different functions to read the contents of a compound string.

              1. XmStringGetNextTriple

              2. XmStringPeekNextTriple

                The XmStringGetNextTriple function is the most basic of the compound string readers. Given an initialized "compound string context," the function returns successive of the nominated compound string on successive calls. Use XmStringPeekNextTriple to determine the type of the next component without reading it, and without advancing the counter. A subsequent call to XmStringGetNextTriple would return the value of the component just peeked at.

                In order to read a compound string with XmStringGetNextTriple, or to peek forward with XmStringPeekNextTriple, a program must first establish a "compound string context" to use. This is just a state structure used to keep track of how far into a compound string the program has read.

                1. XmStringInitContext

                2. XmStringFreeContext

                  Motif provides the XmStringInitContext function to read a compound string and allocate a buffer long enough to handle any of its components. As with all of the other Motif calls that allocate memory, the calling application is responsible for doing its own memory management. Motif provides a function, XmStringFreeContext, to free the memory associated with the context.

                  Two convenient functions are also provided to do two commonly needed tasks: searching for a substring and counting the lines of text.

                  1. XmStringHasSubString

                  2. XmStringLineCount

                    The XmStringHasSubString function takes two compound strings, the target string and the search string, as its arguments. The function returns True if the search string (which can only have one text component) is found in the target string.

                    The XmStringLineCount function simply returns the number of separators found in the input compound string, plus one. Since the separators usually map to a line terminator, this would be the number of lines in the displayed compound string.

                  3. Storing a Compound String in a File

                    The XmString data type is opaque to the application programmer. In addition to the text, a compound string also contains data to tell a widget how to render the string. Some of this data may be in the form of pointers to various addresses, while other data may contain values.

                    If a program needs to store a compound string, or pass it to some other program, it must first convert the string to some more portable format, independent of any memory references. Motif provides two functions to convert a compound string into a byte stream, and to reverse the process.

                    1. XmCvtXmStringToByteStream

                    2. XmCvtByteStreamToXmString

                    3. XmStringByteStreamLength

                      The XmCvtXmStringToByteStream function converts the text of a compound string and all its ancillary information, including rendition tags, direction indicators, and separators, into a byte sequence in an ASN.1-compliant format. This output string can then be written to a file, or passed to some other program. The size of the returned byte stream is internally specified in the ASN.1-format header, and can be returned with the XmStringByteStreamLength function. Once in hand, a program can call XmCvtByteStreamToXmString to convert the given byte stream back into a compound string.

                      Note that the compound string may contain rendition tags, and these are not resolved into the renditions they indicate. The text of the rendition tags is actually transcribed into the byte stream output of XmCvtXmStringToByteStream. For any other program to make sense of the given data, it may need a copy of the render table, too. Motif provides two functions to convert render tables to and from a portable format:

                      1. XmRenderTableCvtFromProp

                      2. XmRenderTableCvtToProp

                        The XmRenderTableCvtToProp function takes a render table and outputs a character string containing the resource functions and values for each of the render table's renditions. Use XmRenderTableCvtFromProp to convert such a character string table back into a Motif render table. Refer to section 9.2.3 for more information about renditions and render tables.

                      3. Displaying a Compound String

                        In most cases, a programmer need not worry about displaying a compound string. If the string is submitted to a widget, that widget is responsible for figuring out how to draw its own labels and text. Therefore, the functions described in this section are not used by most Motif applications. However, if a programmer chooses to write a widget, these functions will be quite useful.

                        1. XmStringDraw

                        2. XmStringDrawImage

                        3. XmStringDrawUnderline

                          The XmStringDraw function draws a compound string in a specified window, in a specified display. The XmStringDrawImage function is nearly identical, except that, when drawing the string, it uses both the foreground and background bits of each character, where XmStringDraw only uses the specified foreground color.

                          XmStringDrawUnderline is the same as XmStringDraw, with the addition of one more argument, also a compound string. If this compound string matches any pattern in the compound string to be drawn, that part of the drawn string will be underlined.

                          In order to draw a string properly, it may be necessary to predict the drawn string's dimensions.

                          1. XmStringExtent

                          2. XmStringHeight

                          3. XmStringWidth

                          4. XmStringBaseLine

                            The XmStringExtent function returns the height and width of the smallest rectangle that could enclose the given compound string. The XmStringHeight and XmStringWidth functions return only the height or width of the string. Use XmStringBaseLine to find the number of pixels between the tallest possible letter and the baseline of the first line of text in the input compound string.

                          5. Compound String Tables

                            Motif now provides support for a table of compound strings. This is simply an array of compound strings, typically to be used to display or accept tabular information. Motif provides functions for creating and manipulating such arrays.

                            1. XmStringToXmStringTable

                            2. XmStringTableToXmString

                              The XmStringToXmStringTable function takes a single compound string as its input, along with a compound string component, break_component. Upon return, the string is broken up, wherever the specified break_component appears, and the function returns an array (table) of the resulting compound strings. The component marking the breaks will not appear in the output table.

                              Use XmStringTableToXmString to convert a table of compound strings back into a single compound string. This function also uses a break_component argument, which it inserts into the resulting compound string between each of the elements of the input table.

                              The following two functions convert regular text to a table of compound strings and back again. They both use the parsing capabilities of Motif, which are described in section 9.4.

                              1. XmStringTableParseStringArray

                              2. XmStringTableUnparse

                                The XmStringTableParseStringArray function accepts an array of simple text strings, calls XmStringParseString on each one with the given parse table, and puts the result into a table of compound strings. The XmStringTableUnparse function also uses an input parse table, to convert the elements of the input compound string table back into regular text strings. See section 9.4 for more information about parsing and parse tables.


                              3. [ Previous | Next | Contents | Glossary | Home | Search ]