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 +--------------------------+