Back to index

tetex-bin  3.0
topic-window.c
Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2004 Stefan Ulrich
00003  *
00004  * Permission is hereby granted, free of charge, to any person obtaining a copy
00005  * of this software and associated documentation files (the "Software"), to
00006  * deal in the Software without restriction, including without limitation the
00007  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
00008  * sell copies of the Software, and to permit persons to whom the Software is
00009  * furnished to do so, subject to the following conditions:
00010  *
00011  * The above copyright notice and this permission notice shall be included in
00012  * all copies or substantial portions of the Software.
00013  *
00014  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00015  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00016  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
00017  * PAUL VOJTA OR ANY OTHER AUTHOR OF THIS SOFTWARE BE LIABLE FOR ANY CLAIM,
00018  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
00019  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
00020  * OTHER DEALINGS IN THE SOFTWARE.
00021  *
00022  */
00023 
00024 /*
00025  * `Topics' window framework used by help and preferences windows.
00026  * Contains a list of topics on the left-hand side, and corresponding
00027  * contents on the right-hand side.
00028  */
00029 
00030 #include "xdvi-config.h"
00031 #include "xdvi.h"
00032 
00033 #if MOTIF
00034 # include <Xm/Xm.h>
00035 # include <Xm/Form.h>
00036 # include <Xm/DialogS.h>
00037 # include <Xm/PushB.h>
00038 # include <Xm/Frame.h>
00039 # include <Xm/PanedW.h>
00040 # include <Xm/LabelG.h>
00041 # include <Xm/Label.h>
00042 # include <Xm/Protocols.h>
00043 # include <Xm/List.h>
00044 # include <Xm/AtomMgr.h>
00045 #else /* MOTIF */
00046 # include <X11/Xaw/Paned.h>
00047 # include <X11/Xaw/Box.h>
00048 # include <X11/Xaw/Form.h>
00049 # include <X11/Xaw/Cardinals.h>
00050 # include <X11/Xaw/Command.h>
00051 # include <X11/Xaw/List.h>
00052 #endif /* MOTIF */
00053 
00054 #include "version.h"
00055 #include "topic-window.h"
00056 #include "string-utils.h"
00057 #include "util.h"
00058 #include "x_util.h"
00059 
00060 #if MOTIF
00061 
00062 /* special formatting for headings in right window, if desired */
00063 const char *const TAG_NORMAL = "NORMAL";
00064 const char *const TAG_TOPIC_HEADING = "TOPIC_HEADING";
00065 const char *const TAG_TOPIC_LABEL = "TOPIC_LABEL";
00066 
00067 # define SHELL_WIDGET_CLASS xmDialogShellWidgetClass
00068 # define PANED_WIDGET_CLASS xmPanedWindowWidgetClass
00069 # define FORM_WIDGET_CLASS  xmFormWidgetClass
00070   
00071 # define FORM_ARGS          XmNhorizontalSpacing, 10,   \
00072                             NULL
00073 # define HELP_SHELL_ARGS    XmNdeleteResponse, XmDO_NOTHING,   \
00074                             XtNmappedWhenManaged, False,              \
00075                             NULL
00076 # define HELP_PANED_ARGS    XmNsashWidth, 1,     \
00077                             XmNuserData, info,   \
00078                             XmNsashHeight, 1,    \
00079                             NULL
00080 # define LEFT_FORM_ARGS            XmNtopAttachment, XmATTACH_FORM,   \
00081                             XmNleftAttachment, XmATTACH_FORM,  \
00082                             XmNbottomAttachment, XmATTACH_FORM,       \
00083                             XmNtopOffset, 9,            \
00084                             XmNbottomOffset, 10,        \
00085                             NULL
00086 # define RIGHT_FORM_ARGS    XmNtopAttachment, XmATTACH_FORM,   \
00087                             XmNleftAttachment, XmATTACH_WIDGET,              \
00088                             XmNleftWidget, left_form,                 \
00089                             XmNrightAttachment, XmATTACH_FORM,        \
00090                             XmNbottomAttachment, XmATTACH_FORM,              \
00091                             XmNbottomOffset, 10,        \
00092                             NULL
00093 # define ACTION_AREA_ARGS   NULL
00094 
00095 #else /* MOTIF */
00096 
00097 # define SHELL_WIDGET_CLASS transientShellWidgetClass
00098 # define PANED_WIDGET_CLASS panedWidgetClass
00099 # define FORM_WIDGET_CLASS  formWidgetClass
00100   
00101 # define FORM_ARGS          XtNdefaultDistance, 14,                   \
00102                             NULL
00103 # define HELP_SHELL_ARGS    XtNx, 60,                          \
00104                             XtNy, 80,                          \
00105                             XtNtransientFor, globals.widgets.top_level,             \
00106                             XtNtranslations, xlats,                   \
00107                             XtNtransientFor, parent,           \
00108                             XtNallowShellResize, False,        \
00109                             NULL
00110 # define HELP_PANED_ARGS    NULL
00111 # define LEFT_FORM_ARGS            XtNtop, XtChainTop,         \
00112                             XtNbottom, XtChainBottom,   \
00113                             XtNleft, XtChainLeft,              \
00114                             XtNright, XtChainLeft,             \
00115                             XtNborderWidth, 0,          \
00116                             NULL
00117 # define RIGHT_FORM_ARGS    XtNfromHoriz, left_form,    \
00118                             XtNtop, XtChainTop,         \
00119                             XtNbottom, XtChainBottom,   \
00120                             XtNleft, XtChainLeft,              \
00121                             XtNright, XtChainRight,            \
00122                             XtNborderWidth, 0,          \
00123                             NULL
00124 # define ACTION_AREA_ARGS   XtNdefaultDistance, 6,      \
00125                             XtNshowGrip, False,  \
00126                             XtNskipAdjust, True, \
00127                             NULL
00128 #endif /* MOTIF */
00129 
00130 
00131 static void
00132 ok_cb(Widget w, XtPointer client_data, XtPointer call_data)
00133 {
00134     struct topic_info *info = (struct topic_info *)client_data;
00135 
00136     UNUSED(w);
00137     UNUSED(call_data);
00138     
00139     ASSERT(info != NULL, "No info passed to callback!");
00140 
00141     if (info->ok_callback != NULL)
00142        info->ok_callback(info);
00143     XtPopdown(info->shell);
00144 }
00145 
00146 static void
00147 cancel_cb(Widget w, XtPointer client_data, XtPointer call_data)
00148 {
00149     struct topic_info *info = (struct topic_info *)client_data;
00150 
00151     UNUSED(w);
00152     UNUSED(call_data);
00153 
00154     ASSERT(info != NULL, "No info passed to callback!");
00155 
00156     if (info->cancel_callback != NULL)
00157        info->cancel_callback(info);
00158     XtPopdown(info->shell);
00159 }
00160 
00161 #if MOTIF
00162 /*
00163  * We are overriding this since otherwise the Text widget would attempt to
00164  * first move the invisible cursor instead of the scroll bars.
00165  */
00166 /* FIXME: This gives a warning:
00167    Warning: Actions not found: scroll-one-line-down, scroll-one-line-up
00168 */
00169 /* "<Key>osfUp: scroll-one-line-down()\n" */
00170 /* "<Key>osfDown: scroll-one-line-up()\n" */
00171 #endif
00172 
00173 #if MOTIF
00174 static XmString
00175 #else
00176 static char *
00177 #endif
00178 create_label_string(const char *title, const char *subtitle)
00179 {
00180 #if MOTIF
00181     XmString label;
00182     if (subtitle == NULL) { /* simple bold label */
00183        label = XmStringCreate((char *)title, (char *)TAG_TOPIC_LABEL);
00184     }
00185     else { /* two-part title with subheading */
00186        XmString s1, s2, s3, s4;
00187        s1 = XmStringCreate((char *)title, (char *)TAG_TOPIC_HEADING);
00188        s2 = XmStringCreate((char *)"   ", (char *)TAG_NORMAL);
00189        s3 = XmStringCreate((char *)subtitle, (char *)TAG_NORMAL);
00190        s4 = XmStringConcat(s1, s2);
00191        label = XmStringConcat(s4, s3);
00192        XmStringFree(s1);
00193        XmStringFree(s2);
00194        XmStringFree(s3);
00195        XmStringFree(s4);
00196     }
00197 #else
00198     char *label = xstrdup(title);
00199     if (subtitle != NULL && strlen(subtitle) > 0) {
00200        label = xstrcat(label, "   -   ");
00201        label = xstrcat(label, subtitle);
00202     }
00203 #endif
00204     return label;
00205 }
00206 
00207 static Widget
00208 create_label_widget(Widget parent, const char *name, struct topic_info *info)
00209 {
00210     Widget label;
00211     
00212 #if MOTIF
00213 
00214     XmString label_string = create_label_string(info->items[0].topic, info->items[0].title);
00215     label = XtVaCreateWidget(name, xmLabelWidgetClass, parent,
00216                           XmNtopAttachment, XmATTACH_FORM,
00217                           XmNtopOffset, 14,
00218                           XmNleftAttachment, XmATTACH_FORM,
00219                           XmNrightAttachment, XmATTACH_FORM,
00220                           XmNlabelString, label_string,
00221                           XmNalignment, XmALIGNMENT_BEGINNING,
00222                           NULL);
00223     XmStringFree(label_string);
00224     
00225 #else /* MOTIF */
00226     
00227     char *label_string = create_label_string(info->items[0].topic, info->items[0].title);
00228     label = XtVaCreateWidget(name, labelWidgetClass, parent,
00229                           XtNlabel, label_string,
00230                           XtNborderWidth, 0,
00231                           /* XtNinternalHeight, 2, */
00232                           XtNjustify, XtJustifyLeft,
00233                           NULL);
00234     free(label_string);
00235     
00236 #endif /* MOTIF */
00237     
00238     return label;
00239 }
00240 
00241 void
00242 select_topic(struct topic_info *info, size_t idx)
00243 {
00244 #if MOTIF
00245     XmString label;
00246 #else
00247     char *label;
00248 #endif
00249 
00250     /* change the heading in right window */
00251     label = create_label_string(info->items[idx].topic, info->items[idx].title);
00252     XtVaSetValues(info->topic_label,
00253 #if MOTIF
00254                 XmNlabelString,
00255 #else
00256                 XtNlabel,
00257 #endif
00258                 label, NULL);
00259 
00260 #if MOTIF
00261     XmStringFree(label);
00262     XmListSelectPos(info->topics_list, idx + 1, False);
00263 #else
00264     free(label);
00265     XawListHighlight(info->topics_list, idx);
00266 #endif
00267     
00268     if (info->curr_selected != 0) {
00269        XtUnmanageChild(info->curr_selected);
00270     }
00271     else {
00272        /* Note: doesn't matter if not managed yet */
00273 /*     XtUnmanageChild(info->items[0].widget); */
00274     }
00275 
00276     XtManageChild(info->items[idx].widget);
00277     info->curr_selected = info->items[idx].widget;
00278 
00279 #if MOTIF
00280     XmUpdateDisplay(info->shell);
00281 #endif
00282 }
00283 
00284 static void
00285 select_topic_cb(Widget w, XtPointer client_data, XtPointer call_data)
00286 {
00287     struct topic_info *info = (struct topic_info *)client_data;
00288     size_t idx;
00289 
00290 #if MOTIF
00291     idx = ((XmListCallbackStruct *)call_data)->item_position - 1;
00292 #else
00293     idx = ((XawListReturnStruct *)call_data)->list_index;
00294 #endif
00295     UNUSED(w);
00296 
00297     /* ASSERT(idx < info->items_size, "list position exceeds items_size!"); */
00298 
00299     select_topic(info, idx);
00300 }
00301 
00302 static Widget
00303 create_button(Widget parent, const char *name, Boolean show_as_default, Boolean left_position)
00304 {
00305     Widget button;
00306 #if MOTIF
00307     XmString s1 = XmStringCreateLocalized((char *)name);
00308     button = XtVaCreateWidget(name, xmPushButtonWidgetClass, parent,
00309                            XmNlabelString, s1,
00310                            XmNdefaultButtonShadowThickness, 1,
00311                            XmNtopAttachment, XmATTACH_FORM,
00312                            XmNbottomAttachment, XmATTACH_FORM,
00313                            XmNmarginWidth, 6,
00314                            XmNmarginHeight, 4,
00315                            XmNtopOffset, 10,
00316                            XmNbottomOffset, 10,
00317                            NULL);
00318     if (left_position)
00319        XtVaSetValues(button,
00320                     XmNleftAttachment, XmATTACH_FORM,
00321                     XmNleftOffset, 10,
00322                     NULL);
00323     else
00324        XtVaSetValues(button,
00325                     XmNrightAttachment, XmATTACH_FORM,
00326                     XmNrightOffset, 10,
00327                     NULL);
00328     if (show_as_default)
00329        XtVaSetValues(button, XmNshowAsDefault, True, NULL);
00330 
00331     XtManageChild(button);
00332     XmStringFree(s1);
00333 #else /* MOTIF */
00334     UNUSED(show_as_default);
00335     button = XtVaCreateManagedWidget(name, commandWidgetClass, parent,
00336                                  XtNtop, XtChainTop,
00337                                  XtNbottom, XtChainBottom,
00338                                  NULL);
00339     if (left_position)
00340        XtVaSetValues(button,
00341                     XtNleft, XtChainLeft,
00342                     XtNright, XtChainLeft,
00343                     NULL);
00344     else
00345        XtVaSetValues(button,
00346                     XtNleft, XtChainRight,
00347                     XtNright, XtChainRight,
00348                     NULL);
00349 #endif /* MOTIF */
00350     return button;
00351 }
00352 
00353 static void
00354 close_topic_window(Widget w, XEvent *event, String *params, Cardinal *num_params)
00355 {
00356     Widget button;
00357     void *ptr;
00358     struct topic_info *info;
00359     
00360     UNUSED(w);
00361     UNUSED(event);
00362     
00363     if (*num_params < 1) {
00364        XDVI_WARNING((stderr, "Wrong argument number (%d) in callback!", *num_params));
00365        return;
00366     }
00367 
00368     sscanf(*params, "%p", &ptr);
00369     info = (struct topic_info *)ptr;
00370 
00371     /* get a callback to close the button, in decreasing order of preference */
00372     if (get_widget_by_name(&button, info->shell, "Cancel", False)
00373        || get_widget_by_name(&button, info->shell, "Close", False)
00374        || get_widget_by_name(&button, info->shell, "OK", False)) {
00375        XtCallCallbacks(button,
00376 #if MOTIF
00377                      XmNactivateCallback,
00378 #else
00379                      XtNcallback,
00380 #endif
00381                      info);
00382     }
00383     else {
00384        XDVI_WARNING((stderr, "No button found for widget %p!\n", (void *)info->shell));
00385     }
00386 }
00387 
00388 static XtActionsRec popdown_actions[] = {
00389 #if !MOTIF
00390     { "WM_popdown", close_topic_window },
00391 #endif
00392     { "close-topic-window", close_topic_window },
00393 };
00394 
00395 static Widget
00396 create_list_widget(Widget parent, const char *w_name, struct topic_info *info)
00397 {
00398     Widget list;
00399     size_t tnum;
00400 #if MOTIF
00401     XmString *topics = NULL;
00402 #else
00403     static char **topics = NULL;
00404 #endif
00405 
00406     for (tnum = 0; info->items[tnum].topic != NULL; tnum++) {
00407        /* 1 more for terminating NULL needed for Xaw */
00408        topics = xrealloc(topics, (tnum + 2) * sizeof *topics);
00409 #if MOTIF
00410        topics[tnum] = XmStringCreateLocalized(info->items[tnum].topic);
00411 #else
00412        topics[tnum] = xstrdup(info->items[tnum].topic);
00413 #endif
00414     }
00415 
00416 #ifndef MOTIF
00417     /* list needs to be terminated for Xaw */
00418     topics[tnum] = NULL;
00419 #endif
00420     
00421 #if MOTIF
00422     {
00423        size_t i;
00424        Arg args[20];
00425        int n = 0;
00426        XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); n++;
00427        XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); n++;
00428        XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); n++;
00429        XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
00430        XtSetArg(args[n], XmNlistSpacing, 4); n++;
00431        XtSetArg(args[n], XmNlistMarginHeight, 4); n++;
00432        XtSetArg(args[n], XmNlistMarginWidth, 4); n++;
00433        XtSetArg(args[n], XmNhighlightThickness, 0); n++;
00434        XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
00435        
00436        list = XmCreateScrolledList(parent, (char *)w_name, args, n);
00437 
00438 #if defined(__GNUC__) && DEVEL_MODE
00439 #warning TODO: make up/down scroll the list, and PgUp/PgDown scroll help text
00440 #warning TODO: add wheel mouse bindings
00441        /*
00442         * also fix bug with arrow keys first moving invisible cursor, then scrollbars
00443         */
00444 #endif
00445        
00446        XmListDeleteAllItems(list);
00447        XmListAddItems(list, topics, tnum, 0);
00448        
00449        for (i = 0; i < tnum; ++i) {
00450            XmStringFree(topics[i]);
00451        }
00452        free(topics);
00453     }
00454     XtAddCallback(list, XmNbrowseSelectionCallback, select_topic_cb, info);
00455     XmListSelectPos(list, 1, False); /* default position */
00456 #else /* MOTIF */
00457     list = XtVaCreateWidget(w_name, listWidgetClass, parent,
00458                          XtNlist, topics,
00459                          XtNdefaultColumns, 1,
00460                          XtNforceColumns, True,
00461                          XtNverticalList, True,
00462                          XtNrowSpacing, 4,
00463                          XtNheight, 429,
00464                          NULL);
00465     XtAddCallback(list, XtNcallback, select_topic_cb, info);
00466     XawListHighlight(list, 0); /* default position */
00467 #endif /* MOTIF */
00468     XtManageChild(list);
00469     return list;
00470 }
00471 
00472 
00473 Widget
00474 create_topic_window(Widget parent,
00475                   const char *window_title,
00476                   const char *widget_name,
00477                   struct topic_info *info,
00478                   void (*init_items_func)(struct topic_info *info),
00479                   /* OK button/callbacks */
00480                   const char *ok_label,
00481                   /* Cancel button/callbacks (can be NULL) */
00482                   const char *cancel_label)
00483 {
00484     Widget topic_window, topics_list, topic_label;
00485     Widget pane, form, left_form, right_container_form, right_form;
00486     Widget action_area, ok_button, cancel_button;
00487     XtTranslations xlats;
00488 
00489     XtAppContext app = NULL;
00490     Atom WM_DELETE_WINDOW;
00491 
00492     char *translation_str;
00493     size_t i;
00494     
00495 #if !MOTIF
00496     translation_str = get_string_va("<Message>WM_PROTOCOLS: WM_popdown(%p)", info);
00497     xlats = XtParseTranslationTable(translation_str);
00498     free(translation_str);
00499 #endif
00500        
00501     topic_window = XtVaCreatePopupShell(widget_name, SHELL_WIDGET_CLASS,
00502                                    parent,
00503                                    XtNtitle, window_title,
00504                                    HELP_SHELL_ARGS);
00505 
00506 #if MOTIF
00507     /* make the window manager destroy action pop down the window */
00508     WM_DELETE_WINDOW = XmInternAtom(XtDisplay(topic_window), "WM_DELETE_WINDOW", False);
00509     XmAddWMProtocolCallback(topic_window, WM_DELETE_WINDOW, cancel_cb, info);
00510 #else
00511     WM_DELETE_WINDOW = XInternAtom(XtDisplay(topic_window), "WM_DELETE_WINDOW", False);
00512 #endif
00513     app = XtWidgetToApplicationContext(topic_window);
00514     XtAppAddActions(app, popdown_actions, XtNumber(popdown_actions));
00515 
00516     pane = XtVaCreateWidget("topic_pane", PANED_WIDGET_CLASS, topic_window, HELP_PANED_ARGS);
00517 
00518     form = XtVaCreateWidget("form", FORM_WIDGET_CLASS, pane, FORM_ARGS);
00519 
00520     /* left pane for topics selection */
00521     left_form = XtVaCreateWidget("left_form", FORM_WIDGET_CLASS, form, LEFT_FORM_ARGS);
00522 
00523     /* right form for topics display */
00524     right_container_form = XtVaCreateWidget("right_container_form", FORM_WIDGET_CLASS, form, RIGHT_FORM_ARGS);
00525 
00526     /*
00527       Initialize the topic label and title string with dummy values - the real values
00528       are only known inside init_items_func(). For Xaw, the size of the widget will be
00529       adjusted below (for Motif it's always the full width of the right form, which is
00530       what we want).
00531     */
00532     /* FIXME: Motif label is still chopped off if it's longer than right form -
00533        work around by putting longest possible lable here ... */
00534     /* Also, not all children will be sized correctly, e.g. the colors - work around
00535        by specifying a rather large dummy text ... */
00536     info->items[0].topic = "text text text";
00537     info->items[0].title = "text text text text text text text text text text text text text text text text text";
00538     topic_label = create_label_widget(right_container_form, "topic_label", info);
00539     info->topic_label = topic_label;
00540 
00541     right_form = XtVaCreateWidget("right_form", FORM_WIDGET_CLASS,
00542                               right_container_form,
00543 #if MOTIF
00544                               XmNtopAttachment, XmATTACH_WIDGET,
00545                               XmNtopWidget, topic_label,
00546                               XmNtopOffset, 10,
00547                               XmNleftAttachment, XmATTACH_FORM,
00548                               XmNrightAttachment, XmATTACH_FORM,
00549                               XmNbottomAttachment, XmATTACH_FORM,
00550 #else
00551                               XtNborderWidth, 0,
00552                               XtNfromVert, topic_label,
00553                               XtNvertDistance, 6,
00554 #endif /* MOTIF */
00555                               NULL);
00556     info->right_form = right_form;
00557     
00558     /*
00559       Call the init_items_func callback. This will populate the info->items list
00560       with the appropriate info, and create the forms (info->items[i].widget)
00561       which are the children of right_form (which is accessed inside init_items_func()
00562       through info->right_form), and all their subchildren.
00563 
00564       It is important that every child form is already managed inside init_items_func
00565       so that the total size of the preferences window is set to the maximum size of
00566       the children. (The children will be unmanaged again below). All these widgets
00567       are never destroyed, and are managed by demand via the list selection callback
00568       (select_topic_cb).
00569     */
00570     init_items_func(info);
00571 
00572     XtManageChild(topic_label);
00573     
00574     topics_list = create_list_widget(left_form, "topics_list", info);
00575     info->topics_list = topics_list;
00576 
00577     translation_str = get_string_va("#override \n"
00578                                 "<Key>q:close-topic-window(%p)\n"
00579 #ifdef MOTIF
00580                                 "<Key>osfCancel:close-topic-window(%p)\n"
00581 #else
00582                                 "<Key>Escape:close-topic-window(%p)\n"
00583 #endif
00584                                 "<Key>Return:close-topic-window(%p)",
00585                                 info, info, info);
00586     xlats = XtParseTranslationTable(translation_str);
00587     free(translation_str);
00588     translation_str = NULL;
00589 
00590     XtOverrideTranslations(pane, xlats);
00591     XtOverrideTranslations(topics_list, xlats);
00592 
00593     XtManageChild(left_form);
00594     
00595     XtManageChild(right_form);
00596     XtManageChild(right_container_form);
00597 
00598     /* action area at bottom */
00599     action_area = XtVaCreateWidget("action_area", FORM_WIDGET_CLASS, pane, ACTION_AREA_ARGS);
00600        
00601     ok_button = create_button(action_area, ok_label, True, True);
00602     XtOverrideTranslations(ok_button, xlats);
00603     
00604     if (cancel_label != NULL) {
00605        cancel_button = create_button(action_area, cancel_label, False, False);
00606        adjust_width(ok_button, cancel_button);
00607 #if MOTIF
00608        XtAddCallback(cancel_button, XmNactivateCallback, cancel_cb, info);
00609 #else
00610        XtAddCallback(cancel_button, XtNcallback, cancel_cb, info);
00611 #endif
00612        XtOverrideTranslations(cancel_button, xlats);
00613     }
00614        
00615     XtManageChild(action_area);
00616 
00617     XtManageChild(form);
00618 
00619     XtManageChild(pane);
00620        
00621     XtRealizeWidget(topic_window);
00622     
00623     /* Now unmanage all children of right_form, as described above. */
00624     for (i = 0; info->items[i].topic != NULL; i++) {
00625        XtUnmanageChild(info->items[i].widget);
00626     }
00627     info->curr_selected = 0;
00628     
00629 #if MOTIF
00630     /* enable OK button */
00631     XmProcessTraversal(ok_button, XmTRAVERSE_CURRENT);
00632     XtOverrideTranslations(ok_button,
00633                         XtParseTranslationTable("<Key>Return:ArmAndActivate()\n"
00634                                              "<Key>q:ArmAndActivate()"));
00635     XtAddCallback(ok_button, XmNactivateCallback, ok_cb, info);
00636     XmAddWMProtocolCallback(topic_window, WM_DELETE_WINDOW, cancel_cb, info);
00637     { /* disable resizing of lower part of pane (and button) */
00638        Dimension h;
00639        XtVaGetValues(ok_button, XmNheight, &h, NULL);
00640        XtVaSetValues(action_area,
00641                     XmNpaneMaximum, h + 20,
00642                     XmNpaneMinimum, h + 20,
00643                     NULL);
00644     }
00645 #else
00646     XSetWMProtocols(XtDisplay(topic_window), XtWindow(topic_window), &WM_DELETE_WINDOW, 1);
00647     XtAddCallback(ok_button, XtNcallback, ok_cb, info);
00648 #endif
00649     return topic_window;
00650 }