13.3.6 An Example
In this section, we pull together all of the functions we have described in the preceding sections. This example builds
on alpha_list.c, the program that adds items that are input by the user to a ScrolledList in alphabetical order. Using
another Text widget, the user can also search for items in the list. The searching method uses regular expression
pattern−matching functions intrinsic to UNIX systems. the source code shows the new application.
XtSetLanguageProc() is only available in X11R5; there is no corresponding function in X11R4.
XmStringCreateLocalized() is only available in Motif 1.2; XmStringCreateSimple() is the
corresponding function in Motif 1.1. XmFONTLIST_DEFAULT_TAG replaces XmSTRING_DEFAULT_CHARSET in
Motif 1.2.
/* search_list.c −− search for items in a List and select them */
#include <stdio.h>
#include <Xm/List.h>
#include <Xm/LabelG.h>
#include <Xm/Label.h>
#include <Xm/RowColumn.h>
#include <Xm/PanedW.h>
#include <Xm/TextF.h>
main(argc, argv)
int argc;
char *argv[];
{
Widget toplevel, rowcol, list_w, text_w;
XtAppContext app;
Arg args[5];
int n = 0;
XmString label;
void add_item(), search_item();
XtSetLanguageProc (NULL, NULL, NULL);
toplevel = XtVaAppInitialize (&app, "Demos", NULL, 0,
&argc, argv, NULL, NULL);
rowcol = XtVaCreateWidget ("rowcol",
xmPanedWindowWidgetClass, toplevel, NULL);
label = XmStringCreateLocalized ("List:");
XtVaCreateManagedWidget ("list_lable", xmLabelWidgetClass, rowcol,
XmNlabelString, label,
NULL);
XmStringFree (label);
XtSetArg (args[n], XmNvisibleItemCount, 10); n++;
XtSetArg (args[n], XmNselectionPolicy, XmEXTENDED_SELECT); n++;
list_w = XmCreateScrolledList (rowcol, "scrolled_list", args, n);
XtManageChild (list_w);
label = XmStringCreateLocalized ("Add:");
XtVaCreateManagedWidget ("add_label", xmLabelWidgetClass, rowcol,
XmNlabelString, label,
NULL);
XmStringFree (label);
text_w = XtVaCreateManagedWidget ("add_text",
xmTextFieldWidgetClass, rowcol,
XmNcolumns, 25,
NULL);
13 The List Widget 13.3.6 An Example
355
XtAddCallback (text_w, XmNactivateCallback, add_item, list_w);
label = XmStringCreateLocalized ("Search:");
XtVaCreateManagedWidget ("search_label", xmLabelWidgetClass, rowcol,
XmNlabelString, label,
NULL);
XmStringFree (label);
text_w = XtVaCreateManagedWidget ("search_text",
xmTextFieldWidgetClass, rowcol,
XmNcolumns, 25,
NULL);
XtAddCallback (text_w, XmNactivateCallback, search_item, list_w);
XtManageChild (rowcol);
XtRealizeWidget (toplevel);
XtAppMainLoop (app);
}
/* Add item to the list in alphabetical order. Perform binary
* search to find the correct location for the new item position.
* This is the callback routine for the Add: TextField widget.
*/
void
add_item(text_w, client_data, call_data)
Widget text_w;
XtPointer client_data;
XtPointer call_data;
{
Widget list_w = (Widget) client_data;
char *text, *newtext = XmTextFieldGetString (text_w);
XmString str, *strlist;
int u_bound, l_bound = 0;
if (!newtext || !*newtext) {
/* non−null strings must be entered */
XtFree (newtext);
return;
}
XtVaGetValues (list_w,
XmNitemCount, &u_bound,
XmNitems, &strlist,
NULL);
u_bound−−;
/* perform binary search */
while (u_bound >= l_bound) {
int i = l_bound + (u_bound − l_bound)/2;
if (!XmStringGetLtoR (strlist[i], XmFONTLIST_DEFAULT_TAG, &text))
break;
if (strcmp (text, newtext) > 0)
u_bound = i−1; /* newtext comes before item */
else
l_bound = i+1; /* newtext comes after item */
XtFree (text);
}
str = XmStringCreateLocalized (newtext);
XtFree (newtext);
/* positions indexes start at 1, so increment accordingly */
XmListAddItemUnselected (list_w, str, l_bound+1);
XmStringFree (str);
XmTextFieldSetString (text_w, "");
}
13 The List Widget 13.3.6 An Example
356
/* find the item in the list that matches the specified pattern */
void
search_item(text_w, client_data, call_data)
Widget text_w;
XtPointer client_data;
XtPointer call_data;
{
Widget list_w = (Widget) client_data;
char *exp, *text, *newtext = XmTextFieldGetString (text_w);
XmString *strlist, *selectlist = NULL;
int matched, cnt, j = 0;
#ifndef SYSV
extern char *re_comp();
#endif /* SYSV */
if (!newtext || !*newtext) {
/* non−null strings must be entered */
XtFree (newtext);
return;
}
/* compile expression into pattern matching library */
#ifdef SYSV
if (!(exp = regcmp (newtext, NULL))) {
printf ("Error with regcmp(%s)0, newtext);
XtFree (newtext);
return;
}
#else /* BSD */
if (exp = re_comp (newtext)) {
printf ("Error with re_comp(%s): %s0, newtext, exp);
XtFree (newtext);
return;
}
#endif /* SYSV */
/* get all the items in the list ... we're going to search each one */
XtVaGetValues (list_w,
XmNitemCount, &cnt,
XmNitems, &strlist,
NULL);
while (cnt−−) {
/* convert item to C string */
if (!XmStringGetLtoR (strlist[cnt], XmFONTLIST_DEFAULT_TAG, &text))
break;
/* do pattern match against search string */
#ifdef SYSV
/* returns NULL if match failed */
matched = regex (exp, text, NULL) != NULL;
#else /* BSD */
/* −1 on error, 0 if no−match, 1 if match */
matched = re_exec (text) > 0;
#endif /* SYSV */
if (matched) {
selectlist = (XmString *) XtRealloc (selectlist,
(j+1) * (sizeof (XmString *)));
selectlist[j++] = XmStringCopy (strlist[cnt]);
}
XtFree (text);
}
13 The List Widget 13.3.6 An Example
357
#ifdef SYSV
free (exp); /* this must be freed for regcmp() */
#endif /* SYSV */
XtFree (newtext);
/* set the actual selected items to be those that matched */
XtVaSetValues (list_w,
XmNselectedItems, selectlist,
XmNselectedItemCount, j,
NULL);
while (j−−)
XmStringFree (selectlist[j]);
XmTextFieldSetString (text_w, "");
}
The output of this program is shown in the figure. The TextField widget that is used to search for items in the List
widget works identically to the one that is used to add new items. Its callback routine, search_item(), searches
the list for the specified pattern. The version of UNIX you are running (System V or BSD) dictates which kind of
regular expression matching is done. System V machines use the function regcmp() to compile the pattern and
regex() to search for the pattern within another string, while BSD UNIX systems use the functions re_comp()
and re_exec() to do the same thing. Systems that support both BSD and System V may support one, the other, or
both methods of regular expression handling. You should consult your system's documentation for more information
on these functions.
The items in the list are retrieved using XtVaGetValues() and the strlist parameter. This variable points to
the internal list used by the List widget, so it is important that we do not change any of these elements or free these
pointers when we are through with them. Changing the value of XmNselectedItems causes the internal list to
change. Since the internal list is referenced by strlist, it is important to copy any values that we want to use
elsewhere. If the pattern matches a list item, the item is copied using XmStringCopy() and is later added to the
List's XmNselectedItems.
13 The List Widget 13.3.6 An Example
358
Get Volume 6A: Motif Programming Manual now with the O’Reilly learning platform.
O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.