[comp.windows.x.motif] Questions from a beginning Motif programmer

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

+--------------------------+