heddle@clas01.cebaf.gov (David Heddle) (11/13/90)
Dear friends:
I am new to Motif programming and could use a jump start from some
experts. Let me describe where I am.
I am working on a Dec Station 5000 with 8 bit color. I am in the process
of writing event-displays for nuclear physics experiments at CEBAF
( a national lab). I am NOT in the business of developing commercial software.
Please couch your answers with the knowledge that I am a physicist,
not a CS type. For purposes of answering my questions, if you are kind
enough to try,
you can assume that I am only interested in the most trivial kind of
application with just one window that will mostly display graphics --
i.e. drawings of detectors -- plots of magnetic fields, charged particle
tracks, etc.
I have succeeded in constructing a minimal shell that opens a single
window using resources from a X11/app-defaults file. It has a couple
of menus including both push buttons and toggle buttons as well as
separators.
I have also incorporated several dialog boxes for warnings, info, etc.
This simple shell works fine -- although I have a basic question to start
off with:
******* QUESTION 1: My main program is:
-------------------------------------------
toplevel = XtInitialize (argv[0], "Mshell", NULL, 0, &argc, argv);
display = XtDisplay(toplevel); /* find the display pointer for this
particular cpu */
/* create managed form. */
form = XmCreateForm(toplevel, "form", (ArgList)args, 0);
XtManageChild(form);
main_window = XtWindow(form); /* main window */
MakeMenus(); /* create menus */
XtRealizeWidget (toplevel); /* realize the top level shell widget */
Initialize(); /* initializations of global variables */
/* If argc is greater than, then unknown command line options were specified */
if (argc > 1)
InvalidOptions(argc, argv);
/* Display a welcome and the time stamp */
XDrawString(display, main_window, main_gc, 5, 45, "Welcome to Mshell", 17);
XDrawString(display, main_window, main_gc, 5, 65, time_str,
strlen(time_str) - 1);
XtMainLoop(); /* get and dispatch events */
--------------------------------------------
My question really has to do with the my program's main
window. It seems that the drawable I want to pass to graphics routines
is
main_window = XtWindow(form); /* main window */
is that right? I don't really understand why (although it seems
to work, where main_window = XtWindow(toplevel); doesn't. That is,
this program will actually write the two lines of text at the end
of the main program, where if I use main_window = XtWindow(toplevel);
it won't. Clearly I don't really understand what is going on... perhaps
because I don't really understand the form widget.
Several of the following questions also deal with those two lines of text
resulting from the two lines of code before the call to XtMainLoop.
******* QUESTION 2
Actually this program doesn't always write out the two lines of text --
sometimes the window just pops up with no text. It always works if I
supply a background color via the command line i.e., $mshell -bg red
EVEN if I use the same background color as in the resource file. Any
idea why?
******* QUESTION 3
On a related topic, why is the text always black? I thought it should
be controlled by the foreground color of my GC, which, bt the way, is
created as:
GC CreateGC()
{
Arg args[MAX_ARGS]; /* Args are used to set/retrieve properties of
resources*/
int n; /* argument counter */
XGCValues values; /* to set gc fields */
Pixel fg; /* foreground color of app shell */
Pixel bg; /* background color of app shell */
GC gc; /* returned GC */
n = 0;
XtSetArg(args[n], XmNforeground, &fg); n++;
XtSetArg(args[n], XmNbackground, &bg); n++;
XtGetValues(toplevel, args, n);
values.line_width = 1;
values.foreground = fg;
values.background = bg;
gc = XCreateGC(display, main_window,
(GCBackground |GCForeground | GCLineWidth), &values);
return(gc);
}
******* QUESTION 4
I have tried to change the font of the text that is displayed on those
two lines --- without luck. How would that be done? When creating the GC?
Via a resource?
******* QUESTION 5
I have also tried to to write text using XmStringDraw -- which would seem
to be the preferred manner. First, I create a fontlist by calling
this procedure:
GlobalFonts()
{
char *fb14name = "variable";
if ((g_font_bold_14 = XLoadQueryFont(display,fb14name))== NULL)
{
fprintf(dbgfile, "g_font_bold_14 load: UNSUCCESSFUL. MUST EXIT.\n");
exit(-1);
}
else
{
fprintf(dbgfile, "g_font_bold_14 load: SUCCESSFUL.\n");
g_font_list_bold_14 = XmFontListCreate(g_font_bold_14, CHARSET);
}
}
This seems to be ok -- the font gets loaded and I was able to use
g_font_list_bold_14 elsewhere with the expected results. Then I wrote
a convenience function for displaying text:
/* -------- DrawString --------------- */
void DrawString(w, fnt, st, gc, x, y)
Window w;
XmFontList fnt;
char *st;
GC gc;
Position x;
Position y;
{
Dimension width;
XmString xmst;
xmst = XmStringCreate(st, CHARSET);
width = XmStringWidth(fnt, xmst);
XmStringDraw(display, w, fnt, xmst, gc, x, y, width,
XmALIGNMENT_BEGINNING, XmALIGNMENT_BEGINNING, NULL);
}
Now, if I replace the calls to XDrawString in my main program with
calls to this procedure, e.g.,
DrawString(main_window, g_font_list_bold_14,
"Welcome to Mshell", main_gc, 5, 45);
here's what happens: The window pops up, I brielfy see the text (in the
correct font and at the correct place) and the the window closes and I get
the following bomb info:
X Protocol error detected by server: BadFont - parameter not a Font
Failed request major op code 56 (X_ChangeGC)
Failed request minor op code 0 (if applicable)
ResourceID 0xffffffff in failed request (if applicable)
Serial number of failed request 193
Current serial number in output stream 196
Any idea what I am doing wrong?
If have any of the following tools available I would greatly appreciate
hearing about them -- I don't want to reinvent any wheels.
* Updating the screen using an off screen pixmap. On the Macintosh I wrote
two procedures: TakePicture and Develop, the first of which copied the screen
onto an off-screen pixmap and the second of which did the inverse. On the
Mac there was some integer arithmetic gymnastics one used to determine
the required
size of the pixmap (i.e. not just (width x height x depth) / 8). Do I
need to do that here?
* Convenience procedures for drawing objects in specified colors such as
ColorMoveToLineTo(x1, y1, x2, y2, WhatColor, WhatWidth)
/* moves to point x1,y1 and draws a line of color WhatColor
and width WhatWidth to point x2, y2 */
and similar constructs for rectangles, circles, arcs, etc.
* Convenience procedure for drawing text. On the Mac I wrote something
like:
DrawText(Str, x, y, font, size, style, color, orientation)
where the argumemts have their obvoius meanings. Orientation could
take on one of only two values: HORIZONTAL or VERTICAL. For vertical
text I created a buffer, wrote the text into it, then copied (and
simultaneously transposed) onto the screen. I need vertical text
for plots. Text at arbitrary angles would be nice, too.
* In general, I would be more than delighted if you would share any
useful graphics procedures that you have.
cheers,
David P. Heddle
clas01.cebaf.gov
(804) 249-7432
or via bitnet: HEDDLE@CEBAFVAX
p.s. Any of my old Carnegie Mellon buddies out there?jan@ECHO.CANBERRA.EDU.AU (Jan Newmarch) (11/14/90)
> > XDrawString(display, main_window, main_gc, 5, 45, "Welcome to Mshell", 17); > XDrawString(display, main_window, main_gc, 5, 65, time_str, > strlen(time_str) - 1); > > XtMainLoop(); /* get and dispatch events */ > -------------------------------------------- > > My question really has to do with the my program's main > window. It seems that the drawable I want to pass to graphics routines > is > > main_window = XtWindow(form); /* main window */ > > is that right? I don't really understand why (although it seems I won't attempt to answer all questions because I don't have time or knowledge about them all. This one looks fairly typical though. In brief, don't try to do Xlib operations on Motif objects. The `form' is for geometry management, so just use it for that. Don't try drawing into it because it wasn't designed for that. The things that you can place text into are labels, text widgets, lists and drawing areas. To place text into a label, use the labelString resource. To place text into a text widget, use the XmTextSetString function. To place things in lists, use the items resource. For none of these do you use the Xlib stuff. The drawing area is yours to play with, and for these you should probably use things like XmDrawString. I would replace the form with a drawing area and retry the rest - maybe some of your other problems would just go away. Hope this little bit helps. +----------------------+---+ Jan Newmarch, Information Science and Engineering, University of Canberra, PO Box 1, Belconnen, Act 2616 Australia. Tel: (Aust) 6-2522422. Fax: (Aust) 6-2522999 ACSnet: jan@ise.canberra.edu.au ARPA: jan%ise.canberra.edu.au@uunet.uu.net UUCP: {uunet,ukc}!munnari!ise.canberra.edu.au!jan JANET: jan%au.edu.canberra.ise@EAN-RELAY +--------------------------+