XmTextSetString (text_output, buf);
XtFree (string);
XtFree (search_pat);
XtFree (new_pat);
}
In this routine, the pattern search starts at the beginning of the text and searches all of the text in the widget. We are
not interested in the cursor position and do not attempt to move it. The main loop of the function only needs to find
the specified pattern and replace each occurrence with the new text. After each call to XmTextReplace(), we
reread the text, since the old value is no longer valid. As with the search_text() routine, we could easily use
XmTextFindString() to search for the pattern, as we do in the text editor in Section #stexteditor.
15.2.5 Output−only Text
The Text and TextField widgets can be used in an output−only mode by setting the XmN-editable resource to
False. If the user tries to edit the text in a read−only widget, the widget beeps and does not allow the modification.
We used an output−only Text widget in our file browsing application.
Our next example addresses a common need for many developers: a method for displaying text messages while an
application is running. These messages may include status messages about application actions, as well as error
messages from Xlib, Xt, and functions internal to the application. The message area is an important part of the main
window of many applications, as discussed in Chapter 4, The Main Window. While a message area can be
-implemented using a Label widget, an output−only ScrolledText object is better suited for use as a message area
because the user can scroll back to previous messages.
the source code shows the wprint() function that we wrote to handle displaying messages. The function acts like
printf() in that it takes variable arguments and understands the standard string formatting characters. The output
goes to a ScrolledText widget so the user can review previous messages. All new text is appended to the end of the
output, so it is immediately visible and the user does not have to manually scroll to the end of the display.
#include <stdio.h>
#include <varargs.h> /* or <stdarg.h> */
/* global variable */
Widget text_output;
main(argc, argv)
int argc;
char *argv[];
{
Arg args[10];
int n;
...
/* Create output_text as a ScrolledText window */
n = 0;
XtSetArg(args[n], XmNrows, 6); n++;
XtSetArg(args[n], XmNcolumns, 80); n++;
XtSetArg(args[n], XmNeditable, False); n++;
XtSetArg(args[n], XmNeditMode, XmMULTI_LINE_EDIT); n++;
XtSetArg(args[n], XmNwordWrap, True); n++;
XtSetArg(args[n], XmNscrollHorizontal, False); n++;
XtSetArg(args[n], XmNcursorPositionVisible, False); n++;
text_output = XmCreateScrolledText(rowcol, "text_output", args, n);
XtManageChild (text_output);
15 Text Widgets 15.2.5 Output−only Text
396
...
}
/*VARARGS*/
void
wprint(va_alist)
va_dcl
{
char msgbuf[256];
char *fmt;
static XmTextPosition wpr_position;
va_list args;
va_start (args);
fmt = va_arg (args, char *);
#ifndef NO_VPRINTF
(void) vsprintf (msgbuf, fmt, args);
#else /* !NO_VPRINTF */
{
FILE foo;
foo._cnt = 256;
foo._base = foo._ptr = msgbuf; /* (unsigned char *) ?? */
foo._flag = _IOWRT+_IOSTRG;
(void) _doprnt (fmt, args, &foo);
*foo._ptr = ' '; /* plant terminating null character */
}
#endif /* NO_VPRINTF */
va_end (args);
XmTextInsert (text_output, wpr_position, msgbuf);
wpr_position = wpr_position + strlen (msgbuf);
XtVaSetValues (text_output, XmNcursorPosition, wpr_position, NULL);
XmTextShowPosition (text_output, wpr_position);
}
Since the wprint() function acts like printf(), it takes a variable−length argument list, which requires the
inclusion of either <varargs.h> or <stdarg.h>. If you have access to the source code for X, you could include
<X11/VarargsI.h> instead. This file is used by the X Toolkit whenever variable−length argument lists are used; it
includes the appropriate file for the current operating system. The function wprint() takes va_alist as its only
parameter. This argument is a pointer to the first of a list of arguments passed to the function; it is declared as
va_dcl in accordance with the standards for functions that take variable−length argument lists.
The va_start() and va_arg() macros are used to extract the first parameter from the argument list. Since
wprint() is supposed to act like printf(), we know that the first parameter is going to be a char pointer. The
call to va_arg() causes fmt to point to the format string, which may or may not contain % formatting characters
that expand to other strings depending on the other arguments to the function.
The rest of the arguments are read and parsed by either vsprintf() or _doprnt(), depending on the C library
that you are using. vsprintf() is a varargs version of sprintf() that exists on most modern UNIX machines.
System V has vsprintf(), as does SunOS, but Ultrix and older BSD machines typically use _doprnt(). If your
machine does not have vsprintf(), you can use _doprnt() as shown in the source code Both of these functions
consume all of the arguments in the list and leave the result in msgbuf.
Now that we have the complete string in msgbuf, we can append it to the existing text in the Text widget. We keep
track of the end of text_output with wpr_position. Each time msgbuf is concatenated to the end of the text,
the value of wpr_position is incremented appropriately. The new text is added using the convenience routine
15 Text Widgets 15.2.5 Output−only Text
397
XmTextInsert(), which takes the following form:
void
XmTextInsert(text_w, position, string)
Widget text_w;
XmTextPosition position;
char *string;
The function simply inserts the given text at the specified position. Finally, we call XmTextShowPosition() to
make the end position visible within the Text widget. This routine may cause the Text widget to adjust its text so that
the new text is visible, as a convenience to the user so that he does not have to scroll the window to view new
messages.
The routines in the source code show how wprint() can be used to reset the error handling functions for Xlib and
Xt so that the messages are printed in a Text widget rather than to stderr.
extern void wprint();
static void
x_error(dpy, err_event)
Display *dpy;
XErrorEvent *err_event;
{
char buf[256];
XGetErrorText (dpy, err_event−>error_code, buf, (sizeof buf));
wprint("X Error: <%s>0, buf);
}
static void
xt_error(message)
char *message;
{
wprint ("Xt Error: %s0, message);
}
main(argc, argv)
int argc;
char *argv[];
{
XtAppContext app;
...
/* catch Xt errors */
XtAppSetErrorHandler (app, xt_error);
XtAppSetWarningHandler (app, xt_error);
/* and Xlib errors */
XSetErrorHandler (x_error);
...
}
Using XtAppSetErrorHandler(), XtAppSetWarningHandler(), and XSetErrorHandler(), we send
all X−related error messages to a Text widget through wprint(). You can also use wprint() to send any
application−specific messages to the ScrolledText area.
15 Text Widgets 15.2.5 Output−only Text
398
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.