| 1 | /* The lwlib interface to Athena widgets. |
| 2 | Copyright (C) 1993 Chuck Thompson <cthomp@cs.uiuc.edu> |
| 3 | |
| 4 | This file is part of the Lucid Widget Library. |
| 5 | |
| 6 | The Lucid Widget Library is free software; you can redistribute it and/or |
| 7 | modify it under the terms of the GNU General Public License as published by |
| 8 | the Free Software Foundation; either version 1, or (at your option) |
| 9 | any later version. |
| 10 | |
| 11 | The Lucid Widget Library is distributed in the hope that it will be useful, |
| 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 14 | GNU General Public License for more details. |
| 15 | |
| 16 | You should have received a copy of the GNU General Public License |
| 17 | along with GNU Emacs; see the file COPYING. If not, write to |
| 18 | the Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
| 19 | Boston, MA 02111-1307, USA. */ |
| 20 | |
| 21 | #ifdef HAVE_CONFIG_H |
| 22 | #include <config.h> |
| 23 | #endif |
| 24 | |
| 25 | #include <stdio.h> |
| 26 | |
| 27 | #include "../src/lisp.h" |
| 28 | |
| 29 | #include "lwlib-Xaw.h" |
| 30 | |
| 31 | #include <X11/StringDefs.h> |
| 32 | #include <X11/IntrinsicP.h> |
| 33 | #include <X11/CoreP.h> |
| 34 | #include <X11/Shell.h> |
| 35 | |
| 36 | #include <X11/Xaw/Scrollbar.h> |
| 37 | #include <X11/Xaw/Paned.h> |
| 38 | #include <X11/Xaw/Dialog.h> |
| 39 | #include <X11/Xaw/Form.h> |
| 40 | #include <X11/Xaw/Command.h> |
| 41 | #include <X11/Xaw/Label.h> |
| 42 | |
| 43 | #include <X11/Xatom.h> |
| 44 | |
| 45 | static void xaw_generic_callback (/*Widget, XtPointer, XtPointer*/); |
| 46 | |
| 47 | |
| 48 | Boolean |
| 49 | lw_xaw_widget_p (widget) |
| 50 | Widget widget; |
| 51 | { |
| 52 | return (XtIsSubclass (widget, scrollbarWidgetClass) || |
| 53 | XtIsSubclass (widget, dialogWidgetClass)); |
| 54 | } |
| 55 | |
| 56 | #if 0 |
| 57 | static void |
| 58 | xaw_update_scrollbar (instance, widget, val) |
| 59 | widget_instance *instance; |
| 60 | Widget widget; |
| 61 | widget_value *val; |
| 62 | { |
| 63 | if (val->scrollbar_data) |
| 64 | { |
| 65 | scrollbar_values *data = val->scrollbar_data; |
| 66 | Dimension height, width; |
| 67 | Dimension pos_x, pos_y; |
| 68 | int widget_shown, widget_topOfThumb; |
| 69 | float new_shown, new_topOfThumb; |
| 70 | |
| 71 | XtVaGetValues (widget, |
| 72 | XtNheight, &height, |
| 73 | XtNwidth, &width, |
| 74 | XtNx, &pos_x, |
| 75 | XtNy, &pos_y, |
| 76 | XtNtopOfThumb, &widget_topOfThumb, |
| 77 | XtNshown, &widget_shown, |
| 78 | NULL); |
| 79 | |
| 80 | /* |
| 81 | * First size and position the scrollbar widget. |
| 82 | * We need to position it to second-guess the Paned widget's notion |
| 83 | * of what should happen when the WMShell gets resized. |
| 84 | */ |
| 85 | if (height != data->scrollbar_height || pos_y != data->scrollbar_pos) |
| 86 | { |
| 87 | XtConfigureWidget (widget, pos_x, data->scrollbar_pos, |
| 88 | width, data->scrollbar_height, 0); |
| 89 | |
| 90 | XtVaSetValues (widget, |
| 91 | XtNlength, data->scrollbar_height, |
| 92 | XtNthickness, width, |
| 93 | NULL); |
| 94 | } |
| 95 | |
| 96 | /* |
| 97 | * Now the size the scrollbar's slider. |
| 98 | */ |
| 99 | new_shown = (float) data->slider_size / |
| 100 | (float) (data->maximum - data->minimum); |
| 101 | |
| 102 | new_topOfThumb = (float) (data->slider_position - data->minimum) / |
| 103 | (float) (data->maximum - data->minimum); |
| 104 | |
| 105 | if (new_shown > 1.0) |
| 106 | new_shown = 1.0; |
| 107 | if (new_shown < 0) |
| 108 | new_shown = 0; |
| 109 | |
| 110 | if (new_topOfThumb > 1.0) |
| 111 | new_topOfThumb = 1.0; |
| 112 | if (new_topOfThumb < 0) |
| 113 | new_topOfThumb = 0; |
| 114 | |
| 115 | if (new_shown != widget_shown || new_topOfThumb != widget_topOfThumb) |
| 116 | XawScrollbarSetThumb (widget, new_topOfThumb, new_shown); |
| 117 | } |
| 118 | } |
| 119 | #endif |
| 120 | |
| 121 | void |
| 122 | #ifdef PROTOTYPES |
| 123 | xaw_update_one_widget (widget_instance *instance, Widget widget, |
| 124 | widget_value *val, Boolean deep_p) |
| 125 | #else |
| 126 | xaw_update_one_widget (instance, widget, val, deep_p) |
| 127 | widget_instance *instance; |
| 128 | Widget widget; |
| 129 | widget_value *val; |
| 130 | Boolean deep_p; |
| 131 | #endif |
| 132 | { |
| 133 | #if 0 |
| 134 | if (XtIsSubclass (widget, scrollbarWidgetClass)) |
| 135 | { |
| 136 | xaw_update_scrollbar (instance, widget, val); |
| 137 | } |
| 138 | #endif |
| 139 | if (XtIsSubclass (widget, dialogWidgetClass)) |
| 140 | { |
| 141 | Arg al[1]; |
| 142 | int ac = 0; |
| 143 | XtSetArg (al[ac], XtNlabel, val->contents->value); ac++; |
| 144 | XtSetValues (widget, al, ac); |
| 145 | } |
| 146 | else if (XtIsSubclass (widget, commandWidgetClass)) |
| 147 | { |
| 148 | Dimension bw = 0; |
| 149 | Arg al[3]; |
| 150 | |
| 151 | XtVaGetValues (widget, XtNborderWidth, &bw, NULL); |
| 152 | if (bw == 0) |
| 153 | /* Don't let buttons end up with 0 borderwidth, that's ugly... |
| 154 | Yeah, all this should really be done through app-defaults files |
| 155 | or fallback resources, but that's a whole different can of worms |
| 156 | that I don't feel like opening right now. Making Athena widgets |
| 157 | not look like shit is just entirely too much work. |
| 158 | */ |
| 159 | { |
| 160 | XtSetArg (al[0], XtNborderWidth, 1); |
| 161 | XtSetValues (widget, al, 1); |
| 162 | } |
| 163 | |
| 164 | XtSetSensitive (widget, val->enabled); |
| 165 | XtSetArg (al[0], XtNlabel, val->value); |
| 166 | /* Force centered button text. Se above. */ |
| 167 | XtSetArg (al[1], XtNjustify, XtJustifyCenter); |
| 168 | XtSetValues (widget, al, 2); |
| 169 | XtRemoveAllCallbacks (widget, XtNcallback); |
| 170 | XtAddCallback (widget, XtNcallback, xaw_generic_callback, instance); |
| 171 | } |
| 172 | } |
| 173 | |
| 174 | void |
| 175 | xaw_update_one_value (instance, widget, val) |
| 176 | widget_instance *instance; |
| 177 | Widget widget; |
| 178 | widget_value *val; |
| 179 | { |
| 180 | /* This function is not used by the scrollbars and those are the only |
| 181 | Athena widget implemented at the moment so do nothing. */ |
| 182 | return; |
| 183 | } |
| 184 | |
| 185 | void |
| 186 | xaw_destroy_instance (instance) |
| 187 | widget_instance *instance; |
| 188 | { |
| 189 | if (XtIsSubclass (instance->widget, dialogWidgetClass)) |
| 190 | /* Need to destroy the Shell too. */ |
| 191 | XtDestroyWidget (XtParent (instance->widget)); |
| 192 | else |
| 193 | XtDestroyWidget (instance->widget); |
| 194 | } |
| 195 | |
| 196 | void |
| 197 | xaw_popup_menu (widget, event) |
| 198 | Widget widget; |
| 199 | XEvent *event; |
| 200 | { |
| 201 | /* An Athena menubar has not been implemented. */ |
| 202 | return; |
| 203 | } |
| 204 | |
| 205 | void |
| 206 | #ifdef PROTOTYPES |
| 207 | xaw_pop_instance (widget_instance *instance, Boolean up) |
| 208 | #else |
| 209 | xaw_pop_instance (instance, up) |
| 210 | widget_instance *instance; |
| 211 | Boolean up; |
| 212 | #endif |
| 213 | { |
| 214 | Widget widget = instance->widget; |
| 215 | |
| 216 | if (up) |
| 217 | { |
| 218 | if (XtIsSubclass (widget, dialogWidgetClass)) |
| 219 | { |
| 220 | /* For dialogs, we need to call XtPopup on the parent instead |
| 221 | of calling XtManageChild on the widget. |
| 222 | Also we need to hack the shell's WM_PROTOCOLS to get it to |
| 223 | understand what the close box is supposed to do!! |
| 224 | */ |
| 225 | Display *dpy = XtDisplay (widget); |
| 226 | Widget shell = XtParent (widget); |
| 227 | Atom props [2]; |
| 228 | int i = 0; |
| 229 | props [i++] = XInternAtom (dpy, "WM_DELETE_WINDOW", False); |
| 230 | XChangeProperty (dpy, XtWindow (shell), |
| 231 | XInternAtom (dpy, "WM_PROTOCOLS", False), |
| 232 | XA_ATOM, 32, PropModeAppend, |
| 233 | (unsigned char *) props, i); |
| 234 | |
| 235 | /* Center the widget in its parent. Why isn't this kind of crap |
| 236 | done automatically? I thought toolkits were supposed to make |
| 237 | life easier? |
| 238 | */ |
| 239 | { |
| 240 | unsigned int x, y, w, h; |
| 241 | Widget topmost = instance->parent; |
| 242 | Arg args[2]; |
| 243 | |
| 244 | w = shell->core.width; |
| 245 | h = shell->core.height; |
| 246 | while (topmost->core.parent && XtIsRealized (topmost->core.parent)) |
| 247 | topmost = topmost->core.parent; |
| 248 | if (topmost->core.width < w) x = topmost->core.x; |
| 249 | else x = topmost->core.x + ((topmost->core.width - w) / 2); |
| 250 | if (topmost->core.height < h) y = topmost->core.y; |
| 251 | else y = topmost->core.y + ((topmost->core.height - h) / 2); |
| 252 | /* Using XtMoveWidget caused the widget to come |
| 253 | out in the wrong place with vtwm. |
| 254 | Question of virtual vs real coords, perhaps. */ |
| 255 | XtSetArg (args[0], XtNx, x); |
| 256 | XtSetArg (args[1], XtNy, y); |
| 257 | XtSetValues (shell, args, 2); |
| 258 | } |
| 259 | |
| 260 | /* Finally, pop it up. */ |
| 261 | XtPopup (shell, XtGrabNonexclusive); |
| 262 | } |
| 263 | else |
| 264 | XtManageChild (widget); |
| 265 | } |
| 266 | else |
| 267 | { |
| 268 | if (XtIsSubclass (widget, dialogWidgetClass)) |
| 269 | XtUnmanageChild (XtParent (widget)); |
| 270 | else |
| 271 | XtUnmanageChild (widget); |
| 272 | } |
| 273 | } |
| 274 | |
| 275 | \f |
| 276 | /* Dialog boxes */ |
| 277 | |
| 278 | static char overrideTrans[] = |
| 279 | "<Message>WM_PROTOCOLS: lwlib_delete_dialog()"; |
| 280 | static void wm_delete_window(); |
| 281 | static XtActionsRec xaw_actions [] = { |
| 282 | {"lwlib_delete_dialog", wm_delete_window} |
| 283 | }; |
| 284 | static Boolean actions_initted = False; |
| 285 | |
| 286 | static Widget |
| 287 | make_dialog (name, parent, pop_up_p, shell_title, icon_name, text_input_slot, radio_box, list, left_buttons, right_buttons) |
| 288 | char* name; |
| 289 | Widget parent; |
| 290 | Boolean pop_up_p; |
| 291 | char* shell_title; |
| 292 | char* icon_name; |
| 293 | Boolean text_input_slot; |
| 294 | Boolean radio_box; |
| 295 | Boolean list; |
| 296 | int left_buttons; |
| 297 | int right_buttons; |
| 298 | { |
| 299 | Arg av [20]; |
| 300 | int ac = 0; |
| 301 | int i, bc; |
| 302 | char button_name [255]; |
| 303 | Widget shell; |
| 304 | Widget dialog; |
| 305 | Widget button; |
| 306 | XtTranslations override; |
| 307 | |
| 308 | if (! pop_up_p) abort (); /* not implemented */ |
| 309 | if (text_input_slot) abort (); /* not implemented */ |
| 310 | if (radio_box) abort (); /* not implemented */ |
| 311 | if (list) abort (); /* not implemented */ |
| 312 | |
| 313 | if (! actions_initted) |
| 314 | { |
| 315 | XtAppContext app = XtWidgetToApplicationContext (parent); |
| 316 | XtAppAddActions (app, xaw_actions, |
| 317 | sizeof (xaw_actions) / sizeof (xaw_actions[0])); |
| 318 | actions_initted = True; |
| 319 | } |
| 320 | |
| 321 | override = XtParseTranslationTable (overrideTrans); |
| 322 | |
| 323 | ac = 0; |
| 324 | XtSetArg (av[ac], XtNtitle, shell_title); ac++; |
| 325 | XtSetArg (av[ac], XtNallowShellResize, True); ac++; |
| 326 | |
| 327 | /* Don't allow any geometry request from the user. */ |
| 328 | XtSetArg (av[ac], XtNgeometry, 0); ac++; |
| 329 | |
| 330 | shell = XtCreatePopupShell ("dialog", transientShellWidgetClass, |
| 331 | parent, av, ac); |
| 332 | XtOverrideTranslations (shell, override); |
| 333 | |
| 334 | ac = 0; |
| 335 | dialog = XtCreateManagedWidget (name, dialogWidgetClass, shell, av, ac); |
| 336 | |
| 337 | bc = 0; |
| 338 | button = 0; |
| 339 | for (i = 0; i < left_buttons; i++) |
| 340 | { |
| 341 | ac = 0; |
| 342 | XtSetArg (av [ac], XtNfromHoriz, button); ac++; |
| 343 | XtSetArg (av [ac], XtNleft, XtChainLeft); ac++; |
| 344 | XtSetArg (av [ac], XtNright, XtChainLeft); ac++; |
| 345 | XtSetArg (av [ac], XtNtop, XtChainBottom); ac++; |
| 346 | XtSetArg (av [ac], XtNbottom, XtChainBottom); ac++; |
| 347 | XtSetArg (av [ac], XtNresizable, True); ac++; |
| 348 | sprintf (button_name, "button%d", ++bc); |
| 349 | button = XtCreateManagedWidget (button_name, commandWidgetClass, |
| 350 | dialog, av, ac); |
| 351 | } |
| 352 | if (right_buttons) |
| 353 | { |
| 354 | /* Create a separator |
| 355 | |
| 356 | I want the separator to take up the slack between the buttons on |
| 357 | the right and the buttons on the left (that is I want the buttons |
| 358 | after the separator to be packed against the right edge of the |
| 359 | window) but I can't seem to make it do it. |
| 360 | */ |
| 361 | ac = 0; |
| 362 | XtSetArg (av [ac], XtNfromHoriz, button); ac++; |
| 363 | /* XtSetArg (av [ac], XtNfromVert, XtNameToWidget (dialog, "label")); ac++; */ |
| 364 | XtSetArg (av [ac], XtNleft, XtChainLeft); ac++; |
| 365 | XtSetArg (av [ac], XtNright, XtChainRight); ac++; |
| 366 | XtSetArg (av [ac], XtNtop, XtChainBottom); ac++; |
| 367 | XtSetArg (av [ac], XtNbottom, XtChainBottom); ac++; |
| 368 | XtSetArg (av [ac], XtNlabel, ""); ac++; |
| 369 | XtSetArg (av [ac], XtNwidth, 30); ac++; /* #### aaack!! */ |
| 370 | XtSetArg (av [ac], XtNborderWidth, 0); ac++; |
| 371 | XtSetArg (av [ac], XtNshapeStyle, XmuShapeRectangle); ac++; |
| 372 | XtSetArg (av [ac], XtNresizable, False); ac++; |
| 373 | XtSetArg (av [ac], XtNsensitive, False); ac++; |
| 374 | button = XtCreateManagedWidget ("separator", |
| 375 | /* labelWidgetClass, */ |
| 376 | /* This has to be Command to fake out |
| 377 | the Dialog widget... */ |
| 378 | commandWidgetClass, |
| 379 | dialog, av, ac); |
| 380 | } |
| 381 | for (i = 0; i < right_buttons; i++) |
| 382 | { |
| 383 | ac = 0; |
| 384 | XtSetArg (av [ac], XtNfromHoriz, button); ac++; |
| 385 | XtSetArg (av [ac], XtNleft, XtChainRight); ac++; |
| 386 | XtSetArg (av [ac], XtNright, XtChainRight); ac++; |
| 387 | XtSetArg (av [ac], XtNtop, XtChainBottom); ac++; |
| 388 | XtSetArg (av [ac], XtNbottom, XtChainBottom); ac++; |
| 389 | XtSetArg (av [ac], XtNresizable, True); ac++; |
| 390 | sprintf (button_name, "button%d", ++bc); |
| 391 | button = XtCreateManagedWidget (button_name, commandWidgetClass, |
| 392 | dialog, av, ac); |
| 393 | } |
| 394 | |
| 395 | return dialog; |
| 396 | } |
| 397 | |
| 398 | Widget |
| 399 | xaw_create_dialog (instance) |
| 400 | widget_instance* instance; |
| 401 | { |
| 402 | char *name = instance->info->type; |
| 403 | Widget parent = instance->parent; |
| 404 | Widget widget; |
| 405 | Boolean pop_up_p = instance->pop_up_p; |
| 406 | char *shell_name = 0; |
| 407 | char *icon_name = 0; |
| 408 | Boolean text_input_slot = False; |
| 409 | Boolean radio_box = False; |
| 410 | Boolean list = False; |
| 411 | int total_buttons; |
| 412 | int left_buttons = 0; |
| 413 | int right_buttons = 1; |
| 414 | |
| 415 | switch (name [0]) { |
| 416 | case 'E': case 'e': |
| 417 | icon_name = "dbox-error"; |
| 418 | shell_name = "Error"; |
| 419 | break; |
| 420 | |
| 421 | case 'I': case 'i': |
| 422 | icon_name = "dbox-info"; |
| 423 | shell_name = "Information"; |
| 424 | break; |
| 425 | |
| 426 | case 'L': case 'l': |
| 427 | list = True; |
| 428 | icon_name = "dbox-question"; |
| 429 | shell_name = "Prompt"; |
| 430 | break; |
| 431 | |
| 432 | case 'P': case 'p': |
| 433 | text_input_slot = True; |
| 434 | icon_name = "dbox-question"; |
| 435 | shell_name = "Prompt"; |
| 436 | break; |
| 437 | |
| 438 | case 'Q': case 'q': |
| 439 | icon_name = "dbox-question"; |
| 440 | shell_name = "Question"; |
| 441 | break; |
| 442 | } |
| 443 | |
| 444 | total_buttons = name [1] - '0'; |
| 445 | |
| 446 | if (name [3] == 'T' || name [3] == 't') |
| 447 | { |
| 448 | text_input_slot = False; |
| 449 | radio_box = True; |
| 450 | } |
| 451 | else if (name [3]) |
| 452 | right_buttons = name [4] - '0'; |
| 453 | |
| 454 | left_buttons = total_buttons - right_buttons; |
| 455 | |
| 456 | widget = make_dialog (name, parent, pop_up_p, |
| 457 | shell_name, icon_name, text_input_slot, radio_box, |
| 458 | list, left_buttons, right_buttons); |
| 459 | |
| 460 | return widget; |
| 461 | } |
| 462 | |
| 463 | |
| 464 | static void |
| 465 | xaw_generic_callback (widget, closure, call_data) |
| 466 | Widget widget; |
| 467 | XtPointer closure; |
| 468 | XtPointer call_data; |
| 469 | { |
| 470 | widget_instance *instance = (widget_instance *) closure; |
| 471 | Widget instance_widget; |
| 472 | LWLIB_ID id; |
| 473 | XtPointer user_data; |
| 474 | |
| 475 | lw_internal_update_other_instances (widget, closure, call_data); |
| 476 | |
| 477 | if (! instance) |
| 478 | return; |
| 479 | if (widget->core.being_destroyed) |
| 480 | return; |
| 481 | |
| 482 | instance_widget = instance->widget; |
| 483 | if (!instance_widget) |
| 484 | return; |
| 485 | |
| 486 | id = instance->info->id; |
| 487 | |
| 488 | #if 0 |
| 489 | user_data = NULL; |
| 490 | XtVaGetValues (widget, XtNuserData, &user_data, NULL); |
| 491 | #else |
| 492 | /* Damn! Athena doesn't give us a way to hang our own data on the |
| 493 | buttons, so we have to go find it... I guess this assumes that |
| 494 | all instances of a button have the same call data. */ |
| 495 | { |
| 496 | widget_value *val = instance->info->val->contents; |
| 497 | char *name = XtName (widget); |
| 498 | while (val) |
| 499 | { |
| 500 | if (val->name && !strcmp (val->name, name)) |
| 501 | break; |
| 502 | val = val->next; |
| 503 | } |
| 504 | if (! val) abort (); |
| 505 | user_data = val->call_data; |
| 506 | } |
| 507 | #endif |
| 508 | |
| 509 | if (instance->info->selection_cb) |
| 510 | instance->info->selection_cb (widget, id, user_data); |
| 511 | } |
| 512 | |
| 513 | static void |
| 514 | wm_delete_window (shell, closure, call_data) |
| 515 | Widget shell; |
| 516 | XtPointer closure; |
| 517 | XtPointer call_data; |
| 518 | { |
| 519 | LWLIB_ID id; |
| 520 | Cardinal nkids; |
| 521 | int i; |
| 522 | Widget *kids = 0; |
| 523 | Widget widget; |
| 524 | if (! XtIsSubclass (shell, shellWidgetClass)) |
| 525 | abort (); |
| 526 | XtVaGetValues (shell, XtNnumChildren, &nkids, NULL); |
| 527 | XtVaGetValues (shell, XtNchildren, &kids, NULL); |
| 528 | if (!kids || !*kids) |
| 529 | abort (); |
| 530 | for (i = 0; i < nkids; i++) |
| 531 | { |
| 532 | widget = kids[i]; |
| 533 | if (XtIsSubclass (widget, dialogWidgetClass)) |
| 534 | break; |
| 535 | } |
| 536 | id = lw_get_widget_id (widget); |
| 537 | if (! id) abort (); |
| 538 | |
| 539 | { |
| 540 | widget_info *info = lw_get_widget_info (id); |
| 541 | if (! info) abort (); |
| 542 | if (info->selection_cb) |
| 543 | info->selection_cb (widget, id, (XtPointer) -1); |
| 544 | } |
| 545 | |
| 546 | lw_destroy_all_widgets (id); |
| 547 | } |
| 548 | |
| 549 | \f |
| 550 | /* Scrollbars */ |
| 551 | |
| 552 | #if 0 |
| 553 | static void |
| 554 | xaw_scrollbar_scroll (widget, closure, call_data) |
| 555 | Widget widget; |
| 556 | XtPointer closure; |
| 557 | XtPointer call_data; |
| 558 | { |
| 559 | widget_instance *instance = (widget_instance *) closure; |
| 560 | LWLIB_ID id; |
| 561 | scroll_event event_data; |
| 562 | |
| 563 | if (!instance || widget->core.being_destroyed) |
| 564 | return; |
| 565 | |
| 566 | id = instance->info->id; |
| 567 | event_data.slider_value = 0; |
| 568 | event_data.time = 0; |
| 569 | |
| 570 | if ((int) call_data > 0) |
| 571 | event_data.action = SCROLLBAR_PAGE_DOWN; |
| 572 | else |
| 573 | event_data.action = SCROLLBAR_PAGE_UP; |
| 574 | |
| 575 | if (instance->info->pre_activate_cb) |
| 576 | instance->info->pre_activate_cb (widget, id, (XtPointer) &event_data); |
| 577 | } |
| 578 | #endif |
| 579 | |
| 580 | #if 0 |
| 581 | static void |
| 582 | xaw_scrollbar_jump (widget, closure, call_data) |
| 583 | Widget widget; |
| 584 | XtPointer closure; |
| 585 | XtPointer call_data; |
| 586 | { |
| 587 | widget_instance *instance = (widget_instance *) closure; |
| 588 | LWLIB_ID id; |
| 589 | scroll_event event_data; |
| 590 | scrollbar_values *val = |
| 591 | (scrollbar_values *) instance->info->val->scrollbar_data; |
| 592 | float percent; |
| 593 | |
| 594 | if (!instance || widget->core.being_destroyed) |
| 595 | return; |
| 596 | |
| 597 | id = instance->info->id; |
| 598 | |
| 599 | percent = * (float *) call_data; |
| 600 | event_data.slider_value = |
| 601 | (int) (percent * (float) (val->maximum - val->minimum)) + val->minimum; |
| 602 | |
| 603 | event_data.time = 0; |
| 604 | event_data.action = SCROLLBAR_DRAG; |
| 605 | |
| 606 | if (instance->info->pre_activate_cb) |
| 607 | instance->info->pre_activate_cb (widget, id, (XtPointer) &event_data); |
| 608 | } |
| 609 | #endif |
| 610 | |
| 611 | static Widget |
| 612 | xaw_create_scrollbar (instance) |
| 613 | widget_instance *instance; |
| 614 | { |
| 615 | #if 0 |
| 616 | Arg av[20]; |
| 617 | int ac = 0; |
| 618 | Dimension width; |
| 619 | Widget scrollbar; |
| 620 | |
| 621 | XtVaGetValues (instance->parent, XtNwidth, &width, NULL); |
| 622 | |
| 623 | XtSetArg (av[ac], XtNshowGrip, 0); ac++; |
| 624 | XtSetArg (av[ac], XtNresizeToPreferred, 1); ac++; |
| 625 | XtSetArg (av[ac], XtNallowResize, True); ac++; |
| 626 | XtSetArg (av[ac], XtNskipAdjust, True); ac++; |
| 627 | XtSetArg (av[ac], XtNwidth, width); ac++; |
| 628 | XtSetArg (av[ac], XtNmappedWhenManaged, True); ac++; |
| 629 | |
| 630 | scrollbar = |
| 631 | XtCreateWidget (instance->info->name, scrollbarWidgetClass, |
| 632 | instance->parent, av, ac); |
| 633 | |
| 634 | /* We have to force the border width to be 0 otherwise the |
| 635 | geometry manager likes to start looping for awhile... */ |
| 636 | XtVaSetValues (scrollbar, XtNborderWidth, 0, NULL); |
| 637 | |
| 638 | XtRemoveAllCallbacks (scrollbar, "jumpProc"); |
| 639 | XtRemoveAllCallbacks (scrollbar, "scrollProc"); |
| 640 | |
| 641 | XtAddCallback (scrollbar, "jumpProc", xaw_scrollbar_jump, |
| 642 | (XtPointer) instance); |
| 643 | XtAddCallback (scrollbar, "scrollProc", xaw_scrollbar_scroll, |
| 644 | (XtPointer) instance); |
| 645 | |
| 646 | return scrollbar; |
| 647 | #else |
| 648 | return NULL; |
| 649 | #endif |
| 650 | } |
| 651 | |
| 652 | static Widget |
| 653 | xaw_create_main (instance) |
| 654 | widget_instance *instance; |
| 655 | { |
| 656 | Arg al[1]; |
| 657 | int ac; |
| 658 | |
| 659 | /* Create a vertical Paned to hold menubar */ |
| 660 | ac = 0; |
| 661 | XtSetArg (al[ac], XtNborderWidth, 0); ac++; |
| 662 | return XtCreateWidget (instance->info->name, panedWidgetClass, |
| 663 | instance->parent, al, ac); |
| 664 | } |
| 665 | |
| 666 | widget_creation_entry |
| 667 | xaw_creation_table [] = |
| 668 | { |
| 669 | {"scrollbar", xaw_create_scrollbar}, |
| 670 | {"main", xaw_create_main}, |
| 671 | {NULL, NULL} |
| 672 | }; |
| 673 | |
| 674 | /* arch-tag: fbbd3589-ae1c-41a0-9142-f628cfee6564 |
| 675 | (do not change this comment) */ |