david@jpl-devvax.jpl.nasa.gov (David E. Smyth) (12/18/90)
Submitted-by: david@jpl-devvax.jpl.nasa.gov (David E. Smyth) Posting-number: Volume 10, Issue 52 Archive-name: wcl/part04 Submitted-by: david@jpl-devvax.jpl.nasa.gov (David E. Smyth) Posting-number: Volume 10, Issue 50 Archive-name: wcl/part02 # to unbundle, "sh" this file -- DO NOT use csh # SHAR archive format. Archive created Fri Oct 19 09:32:06 PDT 1990 echo x - 7thREADME sed 's/^X//' > 7thREADME <<'+FUNKY+STUFF+' XWriting Callback Functions X-------------------------- X XYour application will consist of two fairly independent parts: the Xresource file which describes the look and alot of the feel of the Xapplication, and the callbacks which you write in C (of course, Xyou can use languages other than C, but C is probably the easiest). X XIn order to bind the widgets created due to resource specifications Xto your callbacks implemented in C, you need to write the callbacks Xso they adhere to the standard Xt callback proc typedef, and you Xneed to register your callbacks with the Widget Creation Library's Xstring-to-callback converter. X XXtCallbackProc X-------------- X XAs defined by the XtIntrinsics, widget callback procedures must match Xthis typedef: X Xtypedef void (*XtCallbackProc)( X#if NeedFunctionPrototypes X Widget /* widget */, X XtPointer /* closure */, /* data the application registered */ X XtPointer /* call_data */ /* callback specific data */ X#endif X); X XHere is an example callback proc which does nothing with its Xarguments: X Xvoid MyExitCB ( w, ignored, unused ) X Widget w; X caddr_t ignored; X caddr_t unused; X{ X exit(); X} X XYou must register this function with the Widget Creation Library Xbefore creating any widgets which might want to bind to it. XIn general, register your callbacks after calling XtInitialize() Xand before calling WcCreateWidgets(). Here is an example of Xhow you register a callback: X X#define RCALL( name, func ) WcRegisterCallback ( app, name, func, NULL ) X X RCALL( "MyExitCB", MyExitCB ); X XAll registered callbacks can be bound to widget callback resources Xwithin the resource database. For example: X X *foo.activateCallback: MyExitCB X XMost callbacks really want to do something with the data they Xget as arguments. The closure data, often called client data, Xcan be specified as a string within the resource database. XThe string is passed as the second argument. For example: X Xvoid WcSystemCB ( w, shellCmdString, unused ) X Widget w; X char* shellCmdString; X caddr_t unused; X{ X system( shellCmdString ); X} X XNote that leading and trailing whitespace is NOT filtered out before Xthe callback gets it. For example, the resource specification: X X *foo.activateCallback: WcSystemCB( echo Howdy ) X Xpasses the string " echo Howdy " to the callback. The resource Xspecification: X X *foo.activateCallback: WcSystemCB( echo Howdy \ X and hello thar) X Xpasses the string " echo Howdy \t\t\t\tand hello thar" (where `\t' means Xthe tab character) to the callback. Since the callbacks usually need Xto parse these argument strings, several Widget Creation Library Xfunctions are provided in the hope of making your life easier: X Xchar* WcCleanName( char* src, char* clean ) X------------------------------------------- X XThis takes two pointers to char as arguments. The leading whitespace Xcharacters from src are skipped, and then all characters up to but Xnot including a whitespace are copied into the buffer pointed to by Xclean. Note the caller must provide storage for clean. The function Xreturns a pointer to the first whitespace following what got copied Xto clean, so this function may be used in a loop. X XWidget WcFullNameToWidget ( Widget ref, char* name ) X---------------------------------------------------- X XThis function uses the reference Widget for relative naming, and to Xdetermine the widget tree for converting full pathnames to a widget. XFor example, one may need to get the actual widget which is named by X"*Foo*bar.glorp" The ref widget is used to find the root of the widget Xtree, and start the name search from there. X XThe last component MUST be a widget instance name, it cannot be a Xwidget class name. X XAmbiguous names are resolved as done by XtNameToWidget() upon which XWcFullNameToWidget() is derived. X XVery frequently, one gets a name from an argument list using XWcCleanName() and then passes that name on to WcFullNameToWidget in Xorder to manipulate that widget. For example: X Xvoid MyPopupCB( w, name, unused ) X Widget w; X char* name; X caddr_t unused; X{ X Widget widget; X char clean[MAX_XRMNAME]; X X (void)WcCleanName ( name, cleanName ); X widget = WcFullNameToWidget ( w, cleanName ); X X if (XtIsShell(widget)) X XtPopup ( widget, XtGrabNonexclusive ); X} X XEfficiency Considerations X------------------------- X XI know parsing string arguments on every callback invocation is not so Xincredibly efficient. When Motif runs on Xt release 4, then I will Xre-write the string-to-widget converter so it caches the results, and Xthen callbacks can invoke the caching converter. X XAlso, if you are very interested in performance for a real application X(after you have fleshed out the interface using Ari or Mri), you Xshould write additional callbacks which are more intelligent, and Xdetect being called repeatedly from the same widget with the same Xargument. X XYou may want to consider using the XrmQuark functions for keeping Xtrack of strings as well. XrmQuarks are effectively indexes into Xa string symbol table kept by Xrm (part of Xlib). Doing comparisions Xand assingments using Quarks is substantially faster at run-time than Xusing character strings. XrmQuarkToString() and XrmStringToQuark() Xare used to convert between Quarks and Strings. +FUNKY+STUFF+ echo '-rw-r--r-- 1 david 5304 Aug 6 09:36 7thREADME (as sent)' chmod u=rw,g=r,o=r 7thREADME ls -l 7thREADME echo x - A01.Hello sed 's/^X//' > A01.Hello <<'+FUNKY+STUFF+' X This resource file represents a very basic application: a single X button which, when pressed, causes the application to exit. X XAri.wcChildren: command XAri.title: Ari using A1.Hello X X*command.wcClass: commandWidgetClass X*command.Label: Click the left mouse button here X*command.callback: WcExitCB +FUNKY+STUFF+ echo '-rw-r--r-- 1 david 302 Aug 6 09:36 A01.Hello (as sent)' chmod u=rw,g=r,o=r A01.Hello ls -l A01.Hello echo x - A02.Scrollbar sed 's/^X//' > A02.Scrollbar <<'+FUNKY+STUFF+' X This provides similar functionality as that shown by the Xaw example X named xscroll, which demonstrates how to use the Scrollbar widget. X XAri.wcChildren: box XAri.title: Ari using A2.Scrollbar X X*box.wcClassName: Box X*Box*allowResize: True X*box.wcChildren: quit, scrollbar X X*quit.wcClass: commandWidgetClass X*quit.Label: Quit X*quit.callback: WcExitCB X X*scrollbar.wcClass: scrollbarWidgetClass X*scrollbar.orientation: horizontal X*scrollbar.topOfThumb: 0.5 X*scrollbar.length: 300 X*scrollbar.jumpProc: WcSystemCB(echo Jumped) X*scrollbar.scrollProc: WcSystemCB( echo Scrolled) X +FUNKY+STUFF+ echo '-rw-r--r-- 1 david 581 Aug 6 09:36 A02.Scrollbar (as sent)' chmod u=rw,g=r,o=r A02.Scrollbar ls -l A02.Scrollbar echo x - A03.Box sed 's/^X//' > A03.Box <<'+FUNKY+STUFF+' X This provides similar functionality as that shown by the Xaw example X named xbuttonbox. The Box widget is used to introduce the programmer to X a widget hierarchy. X X Unlike the Shell widget a Box widget can accept more than one child. X By using boxes and other composites it is possible to create an X arbitrarily complex application with hundreds or event thousands of X widgets. X XAri.wcChildren: box XAri.title: Ari using A3.Box X X*box.wcClassName: Box X*box.wcChildren: quit, \ X lab1, lab2, lab3, lab4, lab5, \ X lab6, lab7, lab8, lab9, lab10 X X*quit.wcClassName: Command X*quit.callback: WcExitCB X*Command.Label: Click the left mouse button here to quit X X*lab1.wcClass: labelWidgetClass X*lab2.wcClass: labelWidgetClass X*lab3.wcClass: labelWidgetClass X*lab4.wcClass: labelWidgetClass X*lab5.wcClass: labelWidgetClass X*lab6.wcClass: labelWidgetClass X*lab7.wcClass: labelWidgetClass X*lab8.wcClass: labelWidgetClass X*lab9.wcClass: labelWidgetClass X*lab10.wcClass: labelWidgetClass +FUNKY+STUFF+ echo '-rw-r--r-- 1 david 1071 Aug 6 09:36 A03.Box (as sent)' chmod u=rw,g=r,o=r A03.Box ls -l A03.Box echo x - A04.Paned sed 's/^X//' > A04.Paned <<'+FUNKY+STUFF+' XAri.wcChildren: paned X X*paned.wcClassName: Paned X*paned.wcChildren: quit, label X X*quit.wcClassName: Command X*quit.callback: WcExitCB X*quit.font: *-courier-bold-r-*-240-* X*quit.translations: <EnterWindow>: highlight() \n\ X <LeaveWindow>: reset() \n\ X <Btn1Down>: set() \n\ X <Btn1Up>: notify() unset() \n\ X <Key>Return: WcSetValueACT(*quit.label:Quit) \n\ X <Key>Tab: WcSetValueACT(*quit.label: Go) X X*label.wcClassName: Label X*label.label: Paned, Command, & Label X*label.font: *lucida-bold-i-*-240-* X*label.translations: +FUNKY+STUFF+ echo '-rw-rw-r-- 1 david 538 Oct 9 19:38 A04.Paned (as sent)' chmod u=rw,g=rw,o=r A04.Paned ls -l A04.Paned echo x - A05.Menu sed 's/^X//' > A05.Menu <<'+FUNKY+STUFF+' X! Example showing how to use Athena Menus X XAri.wcChildren: menuButton, menu X X*menuButton.wcClass: menuButtonWidgetClass X X*menu.wcClass: simpleMenuWidgetClass X*menu.wcManaged: False X*menu.wcChildren: menuEntry1, menuEntry2, menuLine, \ X menuEntry3, menuEntry4, menuEntry5 X X*menuLine.wcClass: smeLineObjectClass X*menuEntry1.wcClass: smeBSBObjectClass X*menuEntry2.wcClass: smeBSBObjectClass X*menuEntry3.wcClass: smeBSBObjectClass X*menuEntry4.wcClass: smeBSBObjectClass X*menuEntry5.wcClass: smeBSBObjectClass X*menuEntry5.label: quit X*menuEntry5.callback: WcExitCB X +FUNKY+STUFF+ echo '-rw-rw-r-- 1 david 584 Sep 30 10:15 A05.Menu (as sent)' chmod u=rw,g=rw,o=r A05.Menu ls -l A05.Menu echo x - A06.Dialog sed 's/^X//' > A06.Dialog <<'+FUNKY+STUFF+' XAri.wcChildren: dialog X X*dialog.wcClassName: Dialog X*dialog.wcChildren: ok X*dialog*Font: *times-bold-i-*-80-* X X*dialog.label: I am a Dialog widget. X*dialog.label.font: *new century schoolbook-bold-r-*-140-* X X*dialog.value: Enter new value here. X X*ok.wcClassName: Command X*ok.callback: WcExitCB +FUNKY+STUFF+ echo '-rw-rw-r-- 1 david 299 Oct 9 19:44 A06.Dialog (as sent)' chmod u=rw,g=rw,o=r A06.Dialog ls -l A06.Dialog echo x - A07.Form sed 's/^X//' > A07.Form <<'+FUNKY+STUFF+' XAri.wcChildren: form X X*font: *times-bold-i-*-140-* X X*form.wcClassName: Form X*form.wcChildren: label, one, two, three, go X X*label.wcClassName: Label X*label.label: Form with Buttons X X*one.wcClassName: Command X*one.fromVert: *label X X*two.wcClassName: Command X*two.fromHoriz: *label X X*three.wcClassName: Command X*three.fromHoriz: *one X*three.fromVert: *label X X*go.wcClassName: Command X*go.fromHoriz: *three X*go.fromVert: *two X*go.callback: WcExitCB +FUNKY+STUFF+ echo '-rw-rw-r-- 1 david 454 Oct 9 19:49 A07.Form (as sent)' chmod u=rw,g=rw,o=r A07.Form ls -l A07.Form echo x - A08.ClkLogo sed 's/^X//' > A08.ClkLogo <<'+FUNKY+STUFF+' XAri.wcChildren: box X X*box.wcClassName: Box X*box.wcChildren: clock, logo, label X*box.translations: <Key>Return: WcExitACT() \n\ X <Key>Tab: WcSystemACT( echo Yo Dude! ) \n\ X <Key>Delete: WcSystemACT( Ari & ) X X*clock.wcClassName: ClockWidget X X*logo.wcClassName: LogoWidget X X*label.wcClassName: Label X*label.label: Try hitting Delete, Tab, and Return +FUNKY+STUFF+ echo '-rw-rw-r-- 1 david 353 Oct 15 16:21 A08.ClkLogo (as sent)' chmod u=rw,g=rw,o=r A08.ClkLogo ls -l A08.ClkLogo echo x - A09.Text sed 's/^X//' > A09.Text <<'+FUNKY+STUFF+' XAri.wcChildren: paned X X*paned.wcClassName: Paned X*paned.wcChildren: quit, textFile X X*quit.wcClassName: Command X*quit.callback: WcExitCB X X*textFile.wcClassName: AsciiText X*textFile*type: file X*textFile*string: /etc/motd X*textFile.scrollVertical: whenNeeded X*textFile.scrollHorizontal: whenNeeded X*textFile.height: 100 X*textFile*font: *clean-medium-r-*-150-* +FUNKY+STUFF+ echo '-rw-rw-r-- 1 david 371 Oct 9 20:26 A09.Text (as sent)' chmod u=rw,g=rw,o=r A09.Text ls -l A09.Text echo x - App.c sed 's/^X//' > App.c <<'+FUNKY+STUFF+' X/* X** Copyright (c) 1990 David E. Smyth X** X** Redistribution and use in source and binary forms are permitted X** provided that the above copyright notice and this paragraph are X** duplicated in all such forms and that any documentation, advertising X** materials, and other materials related to such distribution and use X** acknowledge that the software was developed by David E. Smyth. The X** name of David E. Smyth may not be used to endorse or promote products X** derived from this software without specific prior written permission. X** THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED X** WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF X** MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. X** X*/ X X/****************************************************************************** X** X** SCCS_data: @(#)Ari.c 1.0 ( 19 June 1990 ) X** X** Description: This file contains a sample application which uses X** Athena widgets. The example functionally mimics the X** xwidgets.c example provided in examples/Xaw on the X** X11R4 tape from MIT. The Widget Creation library X** is used. X** X** Several application specific callbacks are registered X** with the Wc library, and bound to the interface by X** specifications within the application resource file. X** X** Note that this application has NO fallback resources. X** Since the resource file actually defines the complete X** widget tree, the resource file(s) MUST be found, X** eliminating the raison d'etre of the fallbacks. X** X** Notes: This program uses the Xrm (X resource management) database X** for widget tree definition and management. X** X******************************************************************************/ X X/****************************************************************************** X** Include_files. X******************************************************************************/ X X/* -- Minimum include files to use WidgetCreate Library */ X#include <X11/Intrinsic.h> X#include <WcCreate.h> X X/* -- application specific include files */ X#include <stdio.h> X#include <ctype.h> X#include <X11/Xaw/Dialog.h> X#include <X11/StringDefs.h> X X/****************************************************************************** X** Private Functions X******************************************************************************/ X Xextern void AriRegisterAthena (); X X/* X -- Tied to Dialog `Okay' button X****************************************************************************** X Adds an entry to the List widget whose name is passed as clientData. X*/ X Xstatic void MyOkayCB( widget, widgetName, unused ) X Widget widget; X char* widgetName; X caddr_t unused; X{ X Widget list_widget = WcFullNameToWidget( widget, widgetName ); X static String * list = NULL; X static int num_items = 0, allocated_items = 0; X X if (num_items == allocated_items) { X allocated_items += 10; X list = (String *) XtRealloc(list, sizeof(String) * allocated_items); X } X X /* X * The value returned by XawDialogGetValueString() does not remain good X * forever so we must store is somewhere. This creates a memory leak X * since I don't remember these values, and free them later. I know about X * it, but it doesn't seem worth fixing in this example. X */ X X list[num_items++] = XtNewString(XawDialogGetValueString(XtParent(widget))); X XawListChange(list_widget, list, num_items, 0, True); X} X X/* X -- MyQuitCB X****************************************************************************** X This function destroys the widget tree. X*/ X Xstatic void MyQuitCB( widget, widgetName, ignored ) X Widget widget; X char* widgetName; X caddr_t ignored; X{ X Widget condemmed = WcFullNameToWidget( widget, widgetName ); X fprintf(stderr, "MyQuitCB(%s)\n", widgetName ); X if (condemmed == NULL) X XtDestroyWidget( WcRootWidget( widget ) ); X else X XtDestroyWidget( condemmed ); X} X X/* X -- MyTimeSinceTouchedCB Tied to the strip chart widget. X****************************************************************************** X This function returns the number of 10s of seconds since the user X caused an event in this application. X Note that the StripChart requires a return value. X*/ X Xstatic void MyTimeSinceTouchedCB( widget, ignored, value_ptr ) X Widget widget; X caddr_t ignored; X double* value_ptr; X{ X double *value = (double *) value_ptr; X static double old_value = 0.0; X static Time old_stamp = 1; X Time new_stamp; X X new_stamp = XtLastTimestampProcessed( XtDisplay( widget ) ); X X if (old_stamp != new_stamp) X { X old_stamp = new_stamp; X old_value = 0.0; X } X else X { X Arg args[1]; X int update; X X XtSetArg(args[0], XtNupdate, &update); X XtGetValues(widget, args, 1); X old_value += (double) update / 10.0; X } X X *value = old_value; X} X X/* X -- MyCountCB Tied to button, increments counter and displays. X****************************************************************************** X The argument is interpreted as a widget which must be a label. X The count, after being incremented, is displayed in this label X widget. (Actually, it may be anything derived from Label). X*/ X Xstatic void MyCountCB( widget, widgetName, ignored ) X Widget widget; X char* widgetName; X caddr_t ignored; X{ X Arg arg[1]; X char text[10]; X static int count = 0; X X sprintf( text, " %d ", ++count ); X XtSetArg( arg[0], XtNlabel, text ); X XtSetValues( WcFullNameToWidget( widget, widgetName ), arg, 1 ); X} X X/* X -- MyThumbedCB Tied to scrollbar's jumpProc X****************************************************************************** X Prints location of the thumb as a percentage of the height of the X scrollbar into the labe widget named by the widgetName argument. X*/ X Xstatic void MyThumbedCB( widget, widgetName, top_ptr ) X Widget widget; X char* widgetName; /* string from resource database (resource file) */ X float* top_ptr; /* scrollbar callback call data: a pointer to a float X ** containing the location of the scrollbar's thumb. X */ X{ X Widget label = WcFullNameToWidget( widget, widgetName ); X Arg args[1]; X char message[BUFSIZ]; X X sprintf( message, " Thumbed to %d%% ", (int)((*top_ptr)*100) ); X XtSetArg( args[0], XtNlabel, message ); X XtSetValues( label, args, 1 ); X} X X/* X -- MyScrolledCB Tied to scrollbar's scrollProc X****************************************************************************** X Prints location of the pointer into the named label widget. X*/ X Xstatic void MyScrolledCB( widget, widgetName, num_pixels ) X Widget widget; X char* widgetName; /* string from resource database (resource file) */ X int* num_pixels; /* scrollbar callback call data: the number of X ** pixels the bar has been scrolled. X */ X{ X Widget label = WcFullNameToWidget( widget, widgetName ); X Arg args[1]; X char message[BUFSIZ]; X X sprintf( message, " Scrolled at %d pixels", num_pixels); X XtSetArg( args[0], XtNlabel, message ); X XtSetValues( label, args, 1 ); X} X X/* X -- MyDestroyedCB Destroy callback of application shell X****************************************************************************** X This is a Destroy callback that prints the name of the destroyed widget. X*/ X Xstatic void MyDestroyedCB( widget, client, unused ) X Widget widget; X char* client; /* as registered or from resource database */ X caddr_t unused; X{ X fprintf( stderr, "%s : Widget %s now destroyed.\n", X client, WcWidgetToFullName(widget)); X} X X/* X -- RegisterApplicationCallbacks X****************************************************************************** X Register all the callbacks which define the application's behaviors. X*/ X Xstatic void RegisterApplicationCallbacks ( app ) X XtAppContext app; X{ X#define RCALL(name, func, client) WcRegisterCallback(app, name, func, client) X X RCALL( "MyOkayCB", MyOkayCB, NULL ); X RCALL( "MyQuitCB", MyQuitCB, NULL ); X RCALL( "MyTimeSinceTouchedCB", MyTimeSinceTouchedCB, NULL ); X RCALL( "MyCountCB", MyCountCB, NULL ); X RCALL( "MyThumbedCB", MyThumbedCB, NULL ); X RCALL( "MyScrolledCB", MyScrolledCB, "Scroll" ); X RCALL( "MyDestroyedCB", MyDestroyedCB, "Destroy" ); X} X X/****************************************************************************** X* MAIN function X******************************************************************************/ X Xmain ( argc, argv ) X int argc; X char* argv[]; X{ X char* appClass; X XtAppContext app; X Widget appShell; X X appClass = (char*) XtMalloc ( strlen ( argv[0] ) + 1 ); X strcpy (appClass, argv[0]); X /* initialize first letter to make class, or first two if X ** first is already capitalized, or don't worry about it. X */ X if (islower(appClass[0])) X appClass[0] = toupper(appClass[0]); X else if (islower(appClass[1])) X appClass[1] = toupper(appClass[1]); X X /* With the Athena widgets, we MUST register the Wc X ** converters first, so WcCvtStringToWidget is invoked X ** instead of the far less useful XmuCvtStringToWidget. X */ X WcAddConverters(NULL); X X /* -- Intialize Toolkit creating the application shell */ X appShell = XtInitialize ( X argv[0], appClass, /* app name and class */ X NULL, 0, /* description of cmd line options */ X &argc, argv X ); X app = XtWidgetToApplicationContext(appShell); X X /* -- Register all application specific callbacks and widget classes */ X RegisterApplicationCallbacks ( app ); X X /* -- Register all Athena widget classes */ X AriRegisterAthena ( app ); X X /* -- Create widget tree below toplevel shell using Xrm database */ X WcWidgetCreation ( appShell ); X X /* -- Realize the widget tree and enter the main application loop */ X XtRealizeWidget ( appShell ); X XtMainLoop ( ); X} +FUNKY+STUFF+ echo '-rw-r--r-- 1 david 9941 Oct 9 17:05 App.c (as sent)' chmod u=rw,g=r,o=r App.c ls -l App.c echo x - App1.All sed 's/^X//' > App1.All <<'+FUNKY+STUFF+' X#ifdef Xrm_COMMENT X---------------------------------------------------------------------- X XThis demos is intended to show something about every single XAthena widget. At least one of each is instantiated. This Xexample is derived from xwidgets.c in X11R4/examples/Xaw X XNote that we do not bind the destroy callback to the application Xshell. This is because the Wc converters are not registered yet Xwhen the application shell is created by XtInitialize. We get Xfunctionally identical results by binding the destroyCallback of Xthe application shell's only child. X XThere is nothing which prevents the Wc converters from being Xregistered early, except that most programmers would rather take Xadvantage of XtInitialize() rather than programming an equivalent Xsequence of Xt... calls themselves. X X---------------------------------------------------------------------- X#endif X X# Think of these as fallback resources X# X X*input: True X XApp.wcChildren: paned XApp.title: App using App1.All X XApp*label.destroyCallback: MyDestroyedCB(Gone) XApp.paned.quit.destroyCallback: MyDestroyedCB() XApp.paned.dialog.destroyCallback: MyDestroyedCB X# X# Most of the widgets are children of the paned window. X# X X*paned.wcClass: panedWidgetClass X*paned.wcChildren: quit, label, dialog, viewport, form, \ X box, stripChart, text, box2, textFile X*Paned.width: 350 X X*quit.wcClass: commandWidgetClass X*quit.callback: MyQuitCB( App ) X*quit.font: -*-courier-bold-r-*-240-* X X*label.wcClass: labelWidgetClass X*label.label: At least one of each Athena Widget. X*label.font: *lucida-bold-i-*-240-* X X# X# A Dialog with an Ok button which changes the list X# contents when pressed via the MyOkayCB() callback. X# X X*dialog.wcClass: dialogWidgetClass X*dialog.wcChildren: command X*Dialog*Font: *times-bold-i-*-180-* X*Dialog.label: I am a Dialog widget. X*Dialog.label.font: *new century schoolbook-bold-r-*-180-* X*Dialog.value: Enter new value here. X*Dialog*resizable: True X X*Dialog.command.wcClass: commandWidgetClass X*Dialog*command*label: ok X*Dialog*command*callback: MyOkayCB( *list ) X X# X# A Viewport with a List child X# X X*viewport.wcClass: viewportWidgetClass X*viewport.wcChildren: list X*Viewport*allowVert: True X X*list.wcClass: listWidgetClass X*list*Font: *new century schoolbook-bold-i-*-140-* X X# X# Create a Form with Buttons Including a MenuButton with Menu X# X X#*form*wcTrace: True X X*form.wcClass: formWidgetClass X*form.wcChildren: formLabel, command, toggle, menuButton, menu X*Form*resizable: True X*form*Font: *lucidabright-demibold-*-180-* X X*form.formLabel.wcClass: labelWidgetClass X*Form*formLabel.label: 0 X X*form.command.wcClass: commandWidgetClass X*form.command.fromHoriz: *formLabel X*form.command.callback: MyCountCB( *formLabel ) X X*form.toggle.wcClass: toggleWidgetClass X*form.toggle.fromHoriz: *form.command X*form.toggle.callback: MyCountCB( *formLabel ) X X*form.menuButton.wcClass: menuButtonWidgetClass X*form.menuButton.fromHoriz: *form.toggle X X*menu.wcClass: simpleMenuWidgetClass X*menu.wcManaged: False X*menu.wcChildren: menuEntry1, menuEntry2, menuLine, \ X menuEntry3, menuEntry4, menuEntry5 X X*menuEntry1.wcClass: smeBSBObjectClass X*menuEntry2.wcClass: smeBSBObjectClass X*menuEntry3.wcClass: smeBSBObjectClass X*menuEntry4.wcClass: smeBSBObjectClass X*menuEntry5.wcClass: smeBSBObjectClass X*menuLine.wcClass: smeLineObjectClass X X# X# Create a box with a clock and a logo. X# X X*Box*allowResize: True X*box.wcClass: boxWidgetClass X*box.wcChildren: clock, logo X X*clock.wcClass: clockWidgetClass X*logo.wcClass: logoWidgetClass X X# X# Create a Box widget with a label and a scrollbar. X# X X*box2.wcClass: boxWidgetClass X*box2.wcChildren: scrollbar, scroll_label X X*scrollbar.wcClass: scrollbarWidgetClass X*scrollbar.jumpProc: MyThumbedCB(*scroll_label) X*scrollbar.scrollProc: MyScrolledCB(*scroll_label) X*scrollbar*orientation: horizontal X*scrollbar*length: 100 X X*scroll_label.wcClass: labelWidgetClass X*scroll_label.Font: *-charter-bold-i-*-180-* X X# X# Create a strip chart Note that we X# need to exit, not destroy, with SriptCharts, X# because there is a bug in StripChart`DestroyGC. X# X X*stripChart.wcClass: stripChartWidgetClass X*stripChart.getValue: MyTimeSinceTouchedCB X*StripChart*update: 1 X*StripChart*jumpScroll: 1 X*StripChart.destroyCallback: WcExitCB X X# X# Text widget X# X X*text.wcClass: asciiTextWidgetClass X*text*height: 75 X*text*string: Look ma, a text widget! X*text*editType: edit X*text*scrollVertical: whenNeeded X*text*scrollHorizonal: whenNeeded X*text*Font: *-lucidatypewriter-bold-r-*-190-* X X# X# Text widget tied to a file X# X X*textFile.wcClass: asciiTextWidgetClass X*textFile*type: file X*textFile*string: /etc/motd X*textFile*scrollVertical: whenNeeded X*textFile*scrollHorizonal: whenNeeded X*textFile*height: 75 X*textFile*Font: *clean-medium-r-*-150-* +FUNKY+STUFF+ echo '-rw-r--r-- 1 david 4911 Oct 9 16:42 App1.All (as sent)' chmod u=rw,g=r,o=r App1.All ls -l App1.All echo x - Ari.c sed 's/^X//' > Ari.c <<'+FUNKY+STUFF+' X/* X** Copyright (c) 1990 David E. Smyth X** X** Redistribution and use in source and binary forms are permitted X** provided that the above copyright notice and this paragraph are X** duplicated in all such forms and that any documentation, advertising X** materials, and other materials related to such distribution and use X** acknowledge that the software was developed by David E. Smyth. The X** name of David E. Smyth may not be used to endorse or promote products X** derived from this software without specific prior written permission. X** THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED X** WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF X** MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. X** X*/ X X/****************************************************************************** X** X** SCCS_data: @(#)Ari.c 1.0 ( 19 June 1990 ) X** X** Description: This file contains main() for a Athena Resource Interpreter X** which allows prototype interfaces to be built from X** resource files. The Widget Creation library is used. X** X** Besides the Athena widgets, Ari also knows about Table X** widgets, simply because they are so dang useful! X** X** Notes: This program uses the Xrm (X resource management) database X** for widget tree definition and management. This program X** is dependent on the Athena widget set only because the X** Athena classes and constructors are registered, which X** causes the Athena libs to be linked in. Someday I'll X** get a shared lib version of Motif and the Athena widgets, X** and even the OpenLook widget set, and then there will X** be no reason that widgets could not be mixed and matched. X** Doing that without shared libs makes for a HUGE executable. X** X******************************************************************************/ X X/****************************************************************************** X** Include_files. X******************************************************************************/ X X#include <X11/Intrinsic.h> X#include <ctype.h> X#include <WcCreate.h> X X#include <Table.h> X X/****************************************************************************** X** Private Functions X******************************************************************************/ X Xextern void AriRegisterAthena (); X Xstatic void RegisterTable ( app ) X XtAppContext app; X{ X#define RCN( name, class ) WcRegisterClassName ( app, name, class ); X#define RCP( name, class ) WcRegisterClassPtr ( app, name, class ); X X RCN( "Table", tableWidgetClass ); X RCP( "tableWidgetClass", tableWidgetClass ); X X#undef RCN X#undef RCP X} X X/****************************************************************************** X* MAIN function X******************************************************************************/ X Xmain ( argc, argv ) X int argc; X char* argv[]; X{ X char* appClass; X XtAppContext app; X Widget appShell; X X appClass = (char*) XtMalloc ( strlen ( argv[0] ) + 1 ); X strcpy (appClass, argv[0]); X /* initialize first letter to make class, or first two if X ** first is already capitalized, or don't worry about it. X */ X if (islower(appClass[0])) X appClass[0] = toupper(appClass[0]); X else if (islower(appClass[1])) X appClass[1] = toupper(appClass[1]); X X /* -- Intialize Toolkit creating the application shell */ X appShell = XtInitialize ( X argv[0], appClass, /* app name and class */ X NULL, 0, /* description of cmd line options */ X &argc, argv X ); X app = XtWidgetToApplicationContext(appShell); X X /* -- Register all application specific callbacks and widget classes */ X RegisterTable ( app ); X X /* -- Register all Athena widget classes */ X AriRegisterAthena ( app ); X X /* -- Create widget tree below toplevel shell using Xrm database */ X WcWidgetCreation ( appShell ); X X /* -- Realize the widget tree and enter the main application loop */ X XtRealizeWidget ( appShell ); X XtMainLoop ( ); X} +FUNKY+STUFF+ echo '-rw-r--r-- 1 david 4022 Aug 6 09:36 Ari.c (as sent)' chmod u=rw,g=r,o=r Ari.c ls -l Ari.c echo x - AriRegAll.c sed 's/^X//' > AriRegAll.c <<'+FUNKY+STUFF+' X/* X** Copyright (c) 1990 David E. Smyth X** X** Redistribution and use in source and binary forms are permitted X** provided that the above copyright notice and this paragraph are X** duplicated in all such forms and that any documentation, advertising X** materials, and other materials related to such distribution and use X** acknowledge that the software was developed by David E. Smyth. The X** name of David E. Smyth may not be used to endorse or promote products X** derived from this software without specific prior written permission. X** THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED X** WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF X** MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. X** X*/ X X/* X* SCCS_data: @(#)AriRegAll.c 1.0 ( 19 June 1990 ) X* X* Subsystem_group: X* X* Widget Creation Library - Athena Resource Interpreter X* X* Module_description: X* X* This module contains registration routine for all Athena X* widget constructors and classes. X* X* Module_interface_summary: X* X* void AriRegisterAthena ( XtAppContext app ) X* X* Module_history: X* X* mm/dd/yy initials function action X* -------- -------- -------- --------------------------------------------- X* 06/19/90 D.Smyth all create. X* X* Design_notes: X* X******************************************************************************* X*/ X/* X******************************************************************************* X* Include_files. X******************************************************************************* X*/ X X#include <X11/Xatom.h> X#include <X11/Intrinsic.h> X#include <X11/StringDefs.h> X X#include <X11/Xaw/AsciiText.h> X#include <X11/Xaw/Box.h> X#include <X11/Xaw/Clock.h> X#include <X11/Xaw/Command.h> X#include <X11/Xaw/Dialog.h> X#include <X11/Xaw/Form.h> X#include <X11/Xaw/Grip.h> X#include <X11/Xaw/Label.h> X#include <X11/Xaw/List.h> X#include <X11/Xaw/Logo.h> X#include <X11/Xaw/MenuButton.h> X#include <X11/Xaw/Scrollbar.h> X#include <X11/Xaw/SimpleMenu.h> X#include <X11/Xaw/SmeBSB.h> X#include <X11/Xaw/SmeLine.h> X#include <X11/Xaw/StripChart.h> X#include <X11/Xaw/Paned.h> X#include <X11/Xaw/Toggle.h> X#include <X11/Xaw/Viewport.h> X X#include <X11/Xaw/Cardinals.h> X Xvoid AriRegisterAthena ( app ) X XtAppContext app; X{ X X#define RCN( name, class ) WcRegisterClassName ( app, name, class ); X#define RCP( name, class ) WcRegisterClassPtr ( app, name, class ); X X /* -- register all Athena widget classes */ X /* Simple Widgets (Chapt 3) */ X RCN("Command", commandWidgetClass ); X RCP("commandWidgetClass", commandWidgetClass ); X RCN("Grip", gripWidgetClass ); X RCP("gripWidgetClass", gripWidgetClass ); X RCN("Label", labelWidgetClass ); X RCP("labelWidgetClass", labelWidgetClass ); X RCN("List", listWidgetClass ); X RCP("listWidgetClass", listWidgetClass ); X RCN("Scrollbar", scrollbarWidgetClass ); X RCP("scrollbarWidgetClass", scrollbarWidgetClass ); X RCN("Simple", simpleWidgetClass ); X RCP("simpleWidgetClass", simpleWidgetClass ); X RCN("StripChart", stripChartWidgetClass ); X RCP("stripChartWidgetClass", stripChartWidgetClass ); X RCN("Toggle", toggleWidgetClass ); X RCP("toggleWidgetClass", toggleWidgetClass ); X X /* Menus (Chapt 4) */ X RCN("SimpleMenu", simpleMenuWidgetClass ); X RCP("simpleMenuWidgetClass", simpleMenuWidgetClass ); X RCN("SmeBSB", smeBSBObjectClass ); X RCP("smeBSBObjectClass", smeBSBObjectClass ); X RCN("SmeLine", smeLineObjectClass ); X RCP("smeLineObjectClass", smeLineObjectClass ); X RCN("Sme", smeObjectClass ); X RCP("smeObjectClass", smeObjectClass ); X RCN("MenuButton", menuButtonWidgetClass ); X RCP("menuButtonWidgetClass", menuButtonWidgetClass ); X X /* Text Widgets (Chapt 5) */ X RCN("AsciiText", asciiTextWidgetClass ); /* NB name */ X RCP("asciiTextWidgetClass", asciiTextWidgetClass ); X RCN("AsciiSrc", asciiSrcObjectClass ); X RCP("asciiSrcObjectClass", asciiSrcObjectClass ); X RCN("AsciiSink", asciiSinkObjectClass ); X RCP("asciiSinkObjectClass", asciiSinkObjectClass ); X RCN("Text", textWidgetClass ); X RCP("textWidgetClass", textWidgetClass ); X X /* Composite and Constraint Widgets (Chapt 6) */ X RCN("Box", boxWidgetClass ); X RCP("boxWidgetClass", boxWidgetClass ); X RCN("Dialog", dialogWidgetClass ); X RCP("dialogWidgetClass", dialogWidgetClass ); X RCN("Form", formWidgetClass ); X RCP("formWidgetClass", formWidgetClass ); X RCN("Paned", panedWidgetClass ); X RCP("panedWidgetClass", panedWidgetClass ); X RCN("Viewport", viewportWidgetClass ); X RCP("viewportWidgetClass", viewportWidgetClass ); X X /* Other Interestng Widgets (not in ref manual) */ X RCN("ClockWidget", clockWidgetClass ); X RCP("clockWidgetClass", clockWidgetClass ); X RCN("LogoWidget", logoWidgetClass ); X RCP("logoWidgetClass", logoWidgetClass ); X X#undef RCN X#undef RCP X} +FUNKY+STUFF+ echo '-rw-r--r-- 1 david 5023 Aug 6 09:36 AriRegAll.c (as sent)' chmod u=rw,g=r,o=r AriRegAll.c ls -l AriRegAll.c echo x - COPY sed 's/^X//' > COPY <<'+FUNKY+STUFF+' X/* X** Copyright (c) 1990 David E. Smyth X** X** Redistribution and use in source and binary forms are permitted X** provided that the above copyright notice and this paragraph are X** duplicated in all such forms and that any documentation, advertising X** materials, and other materials related to such distribution and use X** acknowledge that the software was developed by David E. Smyth. The X** name of David E. Smyth may not be used to endorse or promote products X** derived from this software without specific prior written permission. X** THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED X** WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF X** MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. X** X*/ +FUNKY+STUFF+ echo '-rw-r--r-- 1 david 746 Aug 6 09:36 COPY (as sent)' chmod u=rw,g=r,o=r COPY ls -l COPY echo x - COPY_DERIVED sed 's/^X//' > COPY_DERIVED <<'+FUNKY+STUFF+' X/* X** Copyright (c) 1990 David E. Smyth X** X** This file was derived from work performed by Martin Brunecky at X** Auto-trol Technology Corporation, Denver, Colorado, under the X** following copyright: X** X******************************************************************************* X* Copyright 1990 by Auto-trol Technology Corporation, Denver, Colorado. X* X* All Rights Reserved X* X* Permission to use, copy, modify, and distribute this software and its X* documentation for any purpose and without fee is hereby granted, provided X* that the above copyright notice appears on all copies and that both the X* copyright and this permission notice appear in supporting documentation X* and that the name of Auto-trol not be used in advertising or publicity X* pertaining to distribution of the software without specific, prior written X* permission. X* X* Auto-trol disclaims all warranties with regard to this software, including X* all implied warranties of merchantability and fitness, in no event shall X* Auto-trol be liable for any special, indirect or consequential damages or X* any damages whatsoever resulting from loss of use, data or profits, whether X* in an action of contract, negligence or other tortious action, arising out X* of or in connection with the use or performance of this software. X******************************************************************************* X** X** Redistribution and use in source and binary forms are permitted X** provided that the above copyright notice and this paragraph are X** duplicated in all such forms and that any documentation, advertising X** materials, and other materials related to such distribution and use X** acknowledge that the software was developed by David E. Smyth. The X** name of David E. Smyth may not be used to endorse or promote products X** derived from this software without specific prior written permission. X** THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED X** WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF X** MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. X** X*/ +FUNKY+STUFF+ echo '-rw-r--r-- 1 david 2102 Aug 6 09:36 COPY_DERIVED (as sent)' chmod u=rw,g=r,o=r COPY_DERIVED ls -l COPY_DERIVED echo x - Imakefile sed 's/^X//' > Imakefile <<'+FUNKY+STUFF+' X# Assumes that your Imake site.cf defines -DHAVE_MOTIF if you have motif. X# Otherwise, you will have to add a line which says: X# #define HAVE_MOTIF X# X# Note how Motif version numbers are defined: Motif 1.1 or Motif 1.1.1 X# is defined: X# MOTIF_VER = -DMOTIF=1 -DMOTIF_MINOR=1 X# and when Motif 2.7 comes out, MOTIF_VER gets define as: X# MOTIF_VER = -DMOTIF=2 -DMOTIF_MINOR=7 X# X# If your C compiler does not know how to use prototypes, you may X# need to add -D_NO_PROTO to the MOTIF_VER macros. This may be X# needed because many sites do not put Motif specific defines X# in their site.cf files used by Imake. X# X# Some Table.c and Table_m.c both include Xmu.h. If you are using X# Motif 1.0 and you have installed the X11R4 Xmu libraries, then X# you musr provide the XT_VER macro as shown. In all other cases, X# I think that the XT_VER macro is not needed. X# X# Also, if you have Motif installed in a non-standard place, set MOTIFDIR to X# point to it. The value of MOTIFDIR gets pre-pended to /include and /lib. X# X# Motif 1.0 required a special Xt Intrinsics, commonly named libXtm. If X# you are building for 1.0, MOTIFLIB should be -lXtm X X# X# typical for Motif 1.0 X# X MOTIF_VER = -DMOTIF=1 -DMOTIF_MINOR=0 X XT_VER = -DXtSpecificationRelease=4 X MOTIFDIR = /usr X MOTIFXT = -lXtm X MOTIFXTLIB = $(MOTIFDIR)/lib/libXtm.a X X# X# typical for Motif 1.1: X# X# MOTIF_VER = -DMOTIF=1 -DMOTIF_MINOR=1 -D_NO_PROTO X# MOTIFDIR = /usr X# MOTIFXT = -lXt X# MOTIFXTLIB = $(MOTIFDIR)/lib/libXt.a X X IMAKE_DEFINES = -DHAVE_MOTIF X X SYSLIBS = -lm X INSTALLLIBDIR = UsrLibDir X INSTALLINCDIR = $(INCDIR)/Wc X X WCLIB = -L. -lWc X DEPWCLIB = ./libWc.a X X WCMLIB = -L. -lWcm X DEPWCMLIB = ./libWcm.a X X STD_INCLUDES = -I. X CDEBUGFLAGS = -g -Bstatic -DDEBUG X XAllTarget(libWc.a App Ari MDathena libWcm.a Mri MDmotif) X X# X# Rules for App X# X X APP_LIBS = $(WCLIB) XawClientLibs X APP_DEPLIBS = $(DEPWCLIB) XawClientDepLibs X X APP_OBJS = App.o AriRegAll.o X XNormalProgramTarget(App, $(APP_OBJS), $(APP_DEPLIBS), $(APP_LIBS), $(SYSLIBS)) X X# X# Rules for MDathena X# X XMDA_OBJS = MDathena.o AriRegAll.o Table.o X XMDathena.o: MD.c X $(RM) $@ X $(CC) -c $(CFLAGS) MD.c -o MDathena.o X XNormalProgramTarget(MDathena, $(MDA_OBJS), $(APP_DEPLIBS), \ X $(APP_LIBS), $(SYSLIBS)) X X# X# Rules for Ari X# X X ARI_LIBS = $(WCLIB) XawClientLibs X ARI_DEPLIBS = $(DEPWCLIB) XawClientDepLibs X X ARI_OBJS = Ari.o AriRegAll.o Table.o X XNormalProgramTarget(Ari, $(ARI_OBJS), $(ARI_DEPLIBS), $(ARI_LIBS), $(SYSLIBS)) X X# X# Rules for libWc.a X# X X LIBWC_INCS = WcCreate.h WcCreateP.h X LIBWC_OBJS = WcCreate.o WcCallb.o WcConvert.o WcName.o \ X WcReg.o WcActions.o WcRegXt.o X XNormalLibraryObjectRule() X XNormalLibraryTarget(Wc, $(LIBWC_OBJS)) XMakeDirectories(install, $(INSTALLIBDIR)) XInstallLibrary(Wc, $(INSTALLLIBDIR)) XMakeDirectories(install, $(INSTALLINCDIR)) XInstallMultiple($(LIBWC_INCS), $(INSTALLINCDIR)) X X############################################################################### X#ifdef HAVE_MOTIF X############################################################################### X# Note that Motif doesn't provide Xmu, so pick it up from R4 X# X# Rules for Mri X# X X MRI_LIBS = $(WCMLIB) $(MOTIFLIB) X MRI_DEPLIBS = $(DEPWCMLIB) $(DEPMOTIFLIB) X X MOTIFLIB = -L$(MOTIFDIR)/lib -lXm $(MOTIFXT) $(XLIB) X DEPMOTIFLIB = $(MOTIFDIR)/lib/libXm.a $(MOTIFXTLIB) $(DEPXLIB) X X MRI_OBJS = Mri.o MriRegAll.o Table_m.o X MRI_INCLUDES = -I$(MOTIFDIR)/include/Xm -I$(MOTIFDIR)/include X X MRI_DEFINES = $(MOTIF_VER) $(MRI_INCLUDES) X XTable_m.o: Table_m.c X $(RM) $@ X $(CC) -c $(XT_VER) $(MRI_DEFINES) $(CFLAGS) $*.c XMri.o: Mri.c X $(RM) $@ X $(CC) -c $(MRI_DEFINES) $(CFLAGS) $*.c XMriRegAll.o: MriRegAll.c X $(RM) $@ X $(CC) -c $(MRI_DEFINES) $(CFLAGS) $*.c X XNormalProgramTarget(Mri, $(MRI_OBJS), $(MRI_DEPLIBS), $(MRI_LIBS), $(SYSLIBS)) X X# X# Rules for MDmotif X# X XMDM_OBJS = MDmotif.o MriRegAll.o Table_m.o X XMDmotif.o: MD.c X $(RM) $@ X $(CC) -c $(MRI_DEFINES) $(CFLAGS) MD.c -o MDmotif.o X XNormalProgramTarget(MDmotif, $(MDM_OBJS), $(MRI_DEPLIBS), \ X $(MRI_LIBS), $(SYSLIBS)) X X XMDM_OBJS = MDmotif.o MriRegAll.o Table_m.o X# X# Rules for libWcm.a X# X X LIBWCM_OBJS = WcmCreate.o WcmCallb.o WcmConvert.o \ X WcmName.o WcmReg.o WcmActions.o WcmRegXt.o X XWcmCreate.o: WcCreate.c X $(RM) $@ X $(CC) -c $(MRI_DEFINES) $(CFLAGS) WcCreate.c -o WcmCreate.o XWcmCallb.o: WcCallb.c X $(RM) $@ X $(CC) -c $(MRI_DEFINES) $(CFLAGS) WcCallb.c -o WcmCallb.o XWcmConvert.o: WcConvert.c X $(RM) $@ X $(CC) -c $(MRI_DEFINES) $(CFLAGS) WcConvert.c -o WcmConvert.o XWcmName.o: WcName.c X $(RM) $@ X $(CC) -c $(MRI_DEFINES) $(CFLAGS) WcName.c -o WcmName.o XWcmReg.o: WcReg.c X $(RM) $@ X $(CC) -c $(MRI_DEFINES) $(CFLAGS) WcReg.c -o WcmReg.o XWcmActions.o: WcActions.c X $(RM) $@ X $(CC) -c $(MRI_DEFINES) $(CFLAGS) WcActions.c -o WcmActions.o XWcmRegXt.o: WcRegXt.c X $(RM) $@ X $(CC) -c $(MRI_DEFINES) $(CFLAGS) WcRegXt.c -o WcmRegXt.o X XNormalLibraryTarget(Wcm, $(LIBWCM_OBJS)) XInstallLibrary(Wcm, $(INSTALLLIBDIR)) X X#endif +FUNKY+STUFF+ echo '-rw-r--r-- 1 david 5054 Oct 18 16:44 Imakefile (as sent)' chmod u=rw,g=r,o=r Imakefile ls -l Imakefile echo x - M1.Hello sed 's/^X//' > M1.Hello <<'+FUNKY+STUFF+' X This resource file represents a very basic application: a single X button which, when pressed, causes the application to exit. X XMri.wcChildren: push X X*push.wcClass: xmPushButtonWidgetClass X*push.labelString: Hello World X*push.activateCallback: WcExitCB +FUNKY+STUFF+ echo '-rw-r--r-- 1 david 257 Aug 6 09:36 M1.Hello (as sent)' chmod u=rw,g=r,o=r M1.Hello ls -l M1.Hello echo x - M2.Goodbye sed 's/^X//' > M2.Goodbye <<'+FUNKY+STUFF+' X This resource file represents a very basic application: a single button X which changes its own behavior and label. The first time it is X pressed, it changes its label and its activate callback. Subsequent X presses cause a confirmation dialog to pop-up. X X This example uses WcSetValueCB(). The argument looks exactly like a X resource specification. The WcSetValueCB() callback actually does an X XtSetValue to set the value in the target (named) widget. X X This example also uses WcManageCB(). The argument is the name of a X widget. Wildcards work in names exactly as in resource X specifications. The name resoultion search begins at the root widget. X X Note that if there are multiple callbacks being invoked in a callback X list, as in the button's activateCallback resource below, then each X specification is separated by a comma. In the below example, the X specifications are also put on separate lines (the `\' escapes the X newline in resource files just like in C), with additional whitepspace X (tabs and blanks) for stylistic reasons. X X Note also that the dialog is created using one of the Motif X constructors, and the constructor introduces a dialogShell. Since we X want the button to manage the child of the shell, not simply the shell, X we must use the seemingly redundant specification: X X *push.activateCallback: WcManageCB( *exitDialog.exitDialog ) X X If we had used the more intuitive but wrong: X X *push.activateCallback: WcManageCB( *exitDialog ) X X then a small, empty dialog shell would appear at the upper left corner X of the display. This is a VERY common mistake made by Mri beginners. X X Finally, note that the dialog is created unmanaged. If you forget to X do this, the dialog will show up in the upper left corner of the screen X at start-up. This is another VERY common mistake made by Mri X beginners. X XMri.wcChildren: exitDialog, push XMri.title: Mri using M2.Goodbye X X*exitDialog.wcConstructor: XmCreateQuestionDialog X*exitDialog.wcManaged: False X*exitDialog.messageString: Do you really want to exit? X*exitDialog.okCallback: WcExitCB(1) X X*push.wcClass: xmPushButtonWidgetClass X*push.labelString: Hello World, I'm Mri. Please Push Me! X*push.activateCallback: WcSetValueCB( *push.activateCallback: \ X WcManageCB( *exitDialog.exitDialog )),\ X WcSetValueCB( *push.labelString: Goodbye! ) +FUNKY+STUFF+ echo '-rw-r--r-- 1 david 2358 Aug 6 09:36 M2.Goodbye (as sent)' chmod u=rw,g=r,o=r M2.Goodbye ls -l M2.Goodbye echo x - M3.Menubar sed 's/^X//' > M3.Menubar <<'+FUNKY+STUFF+' X Ordering X -------- X X The order of the lines in the resource file are completely stylistic: a X matter of taste. The ordering is lost when the resources are loaded X into the Xrm database, and the Widget Creation library works only from X the database, not directy from the resource files. X X Note that the ordering of the names within the wcChildren resources is X significant: it is the order the children will be created, from left to X right, depth first. One needs to consider this in several cases: X pulldown menus are a good example. X X Pulldown Menus X -------------- X X The pulldowns can be created before or after their activating cascade X button: as an example, lets look at the difference between the X menuBar.file and menuBar.fileMenu specifications versus the X menuBar.help and menuBar.helpMenu specifications. X X The *menuBar.wcChildren resource specifies that the first of its X children to be created is `file' (which has no children), then X `fileMenu' and all its children, then `helpMenu' and all its children, X and finally `help'. X X *menuBar.wcChildren: file, fileMenu, helpMenu, help X X The `fileMenu', being created after the `file' cascade, sets the subMenuId X resource on the `file' cascade when it is created: X X *fileMenu.wcCallback: WcSetValueCB(*file.subMenuId: this) X X The `help' cascade is created after the `helpMenu', so it can specify the X `helpMenu' as its subMenuId directly: X X *help.subMenuId: *helpMenu X X Note that the pulldown menus must be explicitly NOT managed when they X are created. They are automagically managed by the cascade buttons. X X Note also that the separator types are NOT XmSHADOW_ETCHED_IN and X XmDOUBLE_DASHED_LINE as one might guess from Motif documents, but X instead one must leave the Xm off the front. Motif 1.1 is supposed to X support both spellings, so XmSHADOW_ETCHED_IN and SHADOW_ETCHED_IN will X work eventually. Also, the values are case insensitive. X X Multiple Level Cascading Menus X ------------------------------ X X The saveAsMenu pulldown connected to the saveAs button demonstrates X this. See the discussion below. X X---------------------------------------------------------------------- X#endif X X#*wcTrace: True X XMri.wcChildren: menuBar XMri.title: Mri using M3.Menubar X X*menuBar.wcConstructor: XmCreateMenuBar X*menuBar.wcChildren: file, fileMenu, helpMenu, help X X*file.wcConstructor: XmCreateCascadeButton X*file.labelString: File Pulldown Menu X*file.mnemonic: F X X*fileMenu.wcConstructor: XmCreatePulldownMenu X*fileMenu.wcManaged: False X*fileMenu.wcCallback: WcSetValueCB(*file.subMenuId: this) X*fileMenu.wcChildren: load, sep1, save, saveAsMenu, saveAs, sep2, quit X X*helpMenu.wcConstructor: XmCreatePulldownMenu X*helpMenu.wcManaged: False X*helpMenu.wcChildren: mbHelp, cpHelp, daHelp, tHelp X X*helpMenu.mbHelp.wcConstructor: XmCreateCascadeButton X*helpMenu.mbHelp.labelString: on Menu Bar X*helpMenu.mbHelp.mnemonic: M X X*helpMenu.cpHelp.wcConstructor: XmCreateCascadeButton X*helpMenu.cpHelp.labelString: on Control Panel X*helpMenu.cpHelp.mnemonic: C X X*helpMenu.daHelp.wcConstructor: XmCreateCascadeButton X*helpMenu.daHelp.labelString: on Drawing Area X*helpMenu.daHelp.mnemonic: D X X*helpMenu.tHelp.wcConstructor: XmCreateCascadeButton X*helpMenu.tHelp.labelString: on Text Area X*helpMenu.tHelp.mnemonic: T X X*help.wcConstructor: XmCreateCascadeButton X*help.subMenuId: *helpMenu X*help.labelString: Help Pulldown Menu X*help.mnemonic: H X X*load.wcConstructor: XmCreateCascadeButton X*load.labelString: Load ... X*load.mnemonic: L X X*sep1.wcConstructor: XmCreateSeparator X*sep1.separatorType: Shadow_Etched_In X X*save.wcConstructor: XmCreateCascadeButton X*save.labelString: Save X*save.mnemonic: S X X# X# The saveAsMenu has already been created. X# It is specified at the bottom of this file. X# X*saveAs.wcConstructor: XmCreateCascadeButton X*saveAs.labelString: Save As X*saveAs.mnemonic: A X*saveAs.subMenuId: *saveAsMenu X X*sep2.wcConstructor: XmCreateSeparator X*sep2.separatorType: DOUBLE_DASHED_LINE X X*quit.wcConstructor: XmCreateCascadeButton X*quit.labelString: Quit X*quit.mnemonic: Q X*quit.activateCallback: WcExitCB X X ---------------------------------------------------------------------- X X More on Callback Functions X -------------------------- X X One does not strictly need to specify any arguments to callbacks, nor X the parenthesis. For example: X X *quit.activateCallback: WcExitCB X X In this situation, a NULL string is passed to the callback function as X client data. WcExitCB invokes exit(0) when it gets a NULL argument. X X It is up to the callback to decide the appropriate action when a NULL X string is received as client data. The Wc library does guarantee that X the callback will receive a NULL string (the first character is a X '\0'), and not a null pointer (pointer == 0). X X Multiple Level Cascading Menus X ------------------------------ X X ---------------------------------------------------------------------- X X# All of the nested menus in this example have two buttons: X# Go and More to come. Note that we must be specific about X# which pulldown menu gets tied to each one! X# X X*go.wcConstructor: XmCreateCascadeButton X*go.labelString: Go X X*more.wcConstructor: XmCreateCascadeButton X*more.labelString: More to come X X*saveAsMenu.wcConstructor: XmCreatePulldownMenu X*saveAsMenu.wcManaged: False X*saveAsMenu.wcChildren: level3, go, more X*saveAsMenu.more.subMenuId: *level3 X X*level3.wcConstructor: XmCreatePulldownMenu X*level3.wcManaged: False X*level3.wcChildren: level4, go, more X*level3.more.subMenuId: *level4 X X*level4.wcConstructor: XmCreatePulldownMenu X*level4.wcManaged: False X*level4.wcChildren: level5, go, more X*level4.more.subMenuId: *level5 X X*level5.wcConstructor: XmCreatePulldownMenu X*level5.wcManaged: False X*level5.wcChildren: level6, go, more X*level5.more.subMenuId: *level6 X X*level6.wcConstructor: XmCreatePulldownMenu X*level6.wcManaged: False X*level6.wcChildren: level7, go, more X*level6.more.subMenuId: *level7 X X*level7.wcConstructor: XmCreatePulldownMenu X*level7.wcManaged: False X*level7.wcChildren: go, more X*level7.go.labelString: You could go on forever like this... X*level7.more.labelString: But please don't! +FUNKY+STUFF+ echo '-rw-r--r-- 1 david 6184 Aug 6 09:36 M3.Menubar (as sent)' chmod u=rw,g=r,o=r M3.Menubar ls -l M3.Menubar echo x - M4.OptMenu sed 's/^X//' > M4.OptMenu <<'+FUNKY+STUFF+' X Option Menus X ------------ X X Option Menus are a topic which deserves special consideration, because X they are abit different from what you might expect. As the Pulldown X example resource file demonstrates, one may create a cascade button X before or after the menu which is controlled by the cascade. One might X reasonably assume that the same is true for option menus. X X Unfortunately, this is an incorrect assumption. One MUST first create X the pulldown menu which displays the available options, and THEN invoke X the convenience function XmCreateOptionMenu. This may or may not be a X bug, depending on your point of view. X X The widget called an OptionMenu is really a row column with two managed X children: a label, and a cascade. The significant issue is the size of X the cascade: it is forced to be wide enough for the longest selection X on the pulldown menu. One cannot after the fact set the subMenuId on X the cascade, because the cascade does not generally size itself based X on the subMenu elements: normally cascade buttons size themselves based X on their label. X X One might assume that the RowColumn created by XmCreateOptionMenu would X have a special set_values() method which does the appropriate thing X when subMenuId is set, but this is clearly not the case: the set_values() X method does something, but it certainly is not appropriate. Expect a X core dump if you try it. X X So, if you want to use option menus, do it as shown in this example: X first create the pulldown menu using XmCreatePulldownMenu, then create X the `OptionMenu' using XmCreateOptionMenu. The order of creation is X determined by the order of the widget names in the parent's wcChildren X resource: X X *com.wcChildren: doMenu, undoMenu, doOption, undoOption X X Here is a trouble shooting tip: if you use XmCreateOptionMenu and the X cascade button's label is `<optMenName>_cascadeBtn' then you do not X have the subMenuId set properly on the option menu. Check for spelling X on the resource name, on the resource value, and possibly use X `*wcTrace: True' to make sure you give the right name for the pulldown X menu. X X Also, remember to make the menu's initially unmanaged by setting X wcManaged: False on each menu. You can't do this globally, X unfortunately, because there is no actual Motif widget class named X XmPulldownMenu. Sigh. X X---------------------------------------------------------------------- X X#*wcTrace: True X XMri.wcChildren: com XMri.title: Mri using M4.OptMenu X X*com.wcClassName: XmRowColumn X*com.wcChildren: quit, doMenu, undoMenu, nextMenu, doOption, undoOption, next X X*quit.wcClassName: XmPushButton X*quit.labelString: Push this button to quit the Option Menu demo X*quit.activateCallback: WcExitCB X X*doOption.wcConstructor: XmCreateOptionMenu X*doOption.labelString: Do It X*doOption.subMenuId: *doMenu X X*undoOption.wcConstructor: XmCreateOptionMenu X*undoOption.labelString: Undo It X*undoOption.subMenuId: *undoMenu X X*next.wcConstructor: XmCreateOptionMenu X*next.subMenuId: *nextMenu X X*doMenu.wcConstructor: XmCreatePulldownMenu X*doMenu.wcManaged: False X*doMenu.wcChildren: opt1, opt2 X X*undoMenu.wcConstructor: XmCreatePulldownMenu X*undoMenu.wcManaged: False X*undoMenu.wcChildren: opt1, opt2, opt3 X X*nextMenu.wcConstructor: XmCreatePulldownMenu X*nextMenu.wcManaged: False X*nextMenu.wcChildren: opt2, opt1, opt2, opt3, opt1 X X! Note that the specification for buttons opt1 and opt2 are actually used X! twice each: both menus have children named opt1 and opt2, so the X! children of both menus will have these same resources, and thus, will X! use the following resource specifications: X X*opt1.wcClassName: XmPushButton X*opt1.labelString: Now X X*opt2.wcClassName: XmPushButton X*opt2.labelString: Wat's the rush!! X X*opt3.wcClassName: XmPushButton X*opt3.labelString: My Mistake... +FUNKY+STUFF+ echo '-rw-r--r-- 1 david 3848 Aug 6 09:36 M4.OptMenu (as sent)' chmod u=rw,g=r,o=r M4.OptMenu ls -l M4.OptMenu exit 0 dan ---------------------------------------------------- O'Reilly && Associates argv@sun.com / argv@ora.com Opinions expressed reflect those of the author only. -- dan ---------------------------------------------------- O'Reilly && Associates argv@sun.com / argv@ora.com Opinions expressed reflect those of the author only.