Simple.c revision 421c997b
1/*********************************************************** 2 3Copyright 1987, 1988, 1994, 1998 The Open Group 4 5Permission to use, copy, modify, distribute, and sell this software and its 6documentation for any purpose is hereby granted without fee, provided that 7the above copyright notice appear in all copies and that both that 8copyright notice and this permission notice appear in supporting 9documentation. 10 11The above copyright notice and this permission notice shall be included in 12all copies or substantial portions of the Software. 13 14THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 18AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 19CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 21Except as contained in this notice, the name of The Open Group shall not be 22used in advertising or otherwise to promote the sale, use or other dealings 23in this Software without prior written authorization from The Open Group. 24 25 26Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts. 27 28 All Rights Reserved 29 30Permission to use, copy, modify, and distribute this software and its 31documentation for any purpose and without fee is hereby granted, 32provided that the above copyright notice appear in all copies and that 33both that copyright notice and this permission notice appear in 34supporting documentation, and that the name of Digital not be 35used in advertising or publicity pertaining to distribution of the 36software without specific, written prior permission. 37 38DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 39ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 40DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 41ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 42WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 43ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 44SOFTWARE. 45 46******************************************************************/ 47 48#ifdef HAVE_CONFIG_H 49#include <config.h> 50#endif 51#include <stdio.h> 52#include <X11/IntrinsicP.h> 53#include <X11/StringDefs.h> 54#include <X11/Xmu/Drawing.h> 55#include <X11/Xaw/SimpleP.h> 56#include <X11/Xaw/XawInit.h> 57#include "Private.h" 58#ifndef OLDXAW 59#include <X11/Xaw/Tip.h> 60#endif 61 62/* 63 * Class Methods 64 */ 65static Bool ChangeSensitive(Widget); 66static void XawSimpleClassInitialize(void); 67static void XawSimpleClassPartInitialize(WidgetClass); 68#ifndef OLDXAW 69static void XawSimpleInitialize(Widget, Widget, ArgList, Cardinal*); 70static void XawSimpleDestroy(Widget); 71static void XawSimpleExpose(Widget, XEvent*, Region); 72#endif 73static void XawSimpleRealize(Widget, Mask*, XSetWindowAttributes*); 74static Boolean XawSimpleSetValues(Widget, Widget, Widget, ArgList, Cardinal*); 75 76/* 77 * Prototypes 78 */ 79static void ConvertCursor(Widget); 80 81/* 82 * Initialization 83 */ 84#ifndef OLDXAW 85static XtActionsRec actions[] = { 86 {"set-values", XawSetValuesAction}, 87 {"get-values", XawGetValuesAction}, 88 {"declare", XawDeclareAction}, 89 {"call-proc", XawCallProcAction}, 90}; 91#endif 92 93#define offset(field) XtOffsetOf(SimpleRec, simple.field) 94static XtResource resources[] = { 95 { 96 XtNcursor, 97 XtCCursor, 98 XtRCursor, 99 sizeof(Cursor), 100 offset(cursor), 101 XtRImmediate, 102 (XtPointer)None 103 }, 104 { 105 XtNinsensitiveBorder, 106 XtCInsensitive, 107 XtRPixmap, 108 sizeof(Pixmap), 109 offset(insensitive_border), 110 XtRImmediate, 111 NULL 112 }, 113 { 114 XtNpointerColor, 115 XtCForeground, 116 XtRPixel, 117 sizeof(Pixel), 118 offset(pointer_fg), 119 XtRString, 120 XtDefaultForeground 121 }, 122 { 123 XtNpointerColorBackground, 124 XtCBackground, 125 XtRPixel, 126 sizeof(Pixel), 127 offset(pointer_bg), 128 XtRString, 129 XtDefaultBackground 130 }, 131 { 132 XtNcursorName, 133 XtCCursor, 134 XtRString, 135 sizeof(String), 136 offset(cursor_name), 137 XtRString, 138 NULL 139 }, 140 { 141 XtNinternational, 142 XtCInternational, 143 XtRBoolean, 144 sizeof(Boolean), 145 offset(international), 146 XtRImmediate, 147 (XtPointer)False 148 }, 149#ifndef OLDXAW 150 { 151 XawNdisplayList, 152 XawCDisplayList, 153 XawRDisplayList, 154 sizeof(XawDisplayList*), 155 offset(display_list), 156 XtRImmediate, 157 NULL 158 }, 159 { 160 XtNtip, 161 XtCTip, 162 XtRString, 163 sizeof(String), 164 offset(tip), 165 XtRImmediate, 166 NULL 167 }, 168#endif 169#undef offset 170}; 171 172SimpleClassRec simpleClassRec = { 173 /* core */ 174 { 175 (WidgetClass)&widgetClassRec, /* superclass */ 176 "Simple", /* class_name */ 177 sizeof(SimpleRec), /* widget_size */ 178 XawSimpleClassInitialize, /* class_initialize */ 179 XawSimpleClassPartInitialize, /* class_part_initialize */ 180 False, /* class_inited */ 181#ifndef OLDXAW 182 XawSimpleInitialize, /* initialize */ 183#else 184 NULL, /* initialize */ 185#endif 186 NULL, /* initialize_hook */ 187 XawSimpleRealize, /* realize */ 188#ifndef OLDXAW 189 actions, /* actions */ 190 XtNumber(actions), /* num_actions */ 191#else 192 NULL, /* actions */ 193 0, /* num_actions */ 194#endif 195 resources, /* resources */ 196 XtNumber(resources), /* num_resources */ 197 NULLQUARK, /* xrm_class */ 198 True, /* compress_motion */ 199 True, /* compress_exposure */ 200 True, /* compress_enterleave */ 201 False, /* visible_interest */ 202#ifndef OLDXAW 203 XawSimpleDestroy, /* destroy */ 204#else 205 NULL, /* destroy */ 206#endif 207 NULL, /* resize */ 208#ifndef OLDXAW 209 XawSimpleExpose, /* expose */ 210#else 211 NULL, /* expose */ 212#endif 213 XawSimpleSetValues, /* set_values */ 214 NULL, /* set_values_hook */ 215 XtInheritSetValuesAlmost, /* set_values_almost */ 216 NULL, /* get_values_hook */ 217 NULL, /* accept_focus */ 218 XtVersion, /* version */ 219 NULL, /* callback_private */ 220 NULL, /* tm_table */ 221 XtInheritQueryGeometry, /* query_geometry */ 222 XtInheritDisplayAccelerator, /* display_accelerator */ 223 NULL, /* extension */ 224 }, 225 /* simple */ 226 { 227 ChangeSensitive, /* change_sensitive */ 228 }, 229}; 230 231WidgetClass simpleWidgetClass = (WidgetClass)&simpleClassRec; 232 233static void 234XawSimpleClassInitialize(void) 235{ 236 static XtConvertArgRec convertArg[] = { 237 { 238 XtWidgetBaseOffset, 239 (XtPointer)XtOffsetOf(WidgetRec, core.screen), 240 sizeof(Screen *) 241 }, 242 { 243 XtResourceString, 244 (XtPointer)XtNpointerColor, 245 sizeof(Pixel) 246 }, 247 { 248 XtResourceString, 249 (XtPointer)XtNpointerColorBackground, 250 sizeof(Pixel) 251 }, 252 { 253 XtWidgetBaseOffset, 254 (XtPointer)XtOffsetOf(WidgetRec, core.colormap), 255 sizeof(Colormap) 256 }, 257 }; 258 259 XawInitializeWidgetSet(); 260 XtSetTypeConverter(XtRString, XtRColorCursor, XmuCvtStringToColorCursor, 261 convertArg, XtNumber(convertArg), XtCacheByDisplay, NULL); 262} 263 264static void 265XawSimpleClassPartInitialize(WidgetClass cclass) 266{ 267 SimpleWidgetClass c = (SimpleWidgetClass)cclass; 268 SimpleWidgetClass super = (SimpleWidgetClass)c->core_class.superclass; 269 270 if (c->simple_class.change_sensitive == NULL) { 271 char buf[BUFSIZ]; 272 273 snprintf(buf, sizeof(buf), 274 "%s Widget: The Simple Widget class method " 275 "'change_sensitive' is undefined.\n" 276 "A function must be defined or inherited.", 277 c->core_class.class_name); 278 XtWarning(buf); 279 c->simple_class.change_sensitive = ChangeSensitive; 280 } 281 282 if (c->simple_class.change_sensitive == XtInheritChangeSensitive) 283 c->simple_class.change_sensitive = super->simple_class.change_sensitive; 284} 285 286#ifndef OLDXAW 287/*ARGSUSED*/ 288static void 289XawSimpleInitialize(Widget request, Widget cnew, 290 ArgList args, Cardinal *num_args) 291{ 292 SimpleWidget simple = (SimpleWidget)cnew; 293 294 if (simple->simple.tip) 295 simple->simple.tip = XtNewString(simple->simple.tip); 296} 297 298static void 299XawSimpleDestroy(Widget w) 300{ 301 SimpleWidget simple = (SimpleWidget)w; 302 303 if (simple->simple.tip) 304 XtFree((XtPointer)simple->simple.tip); 305} 306#endif 307 308static void 309XawSimpleRealize(Widget w, Mask *valueMask, XSetWindowAttributes *attributes) 310{ 311#ifndef OLDXAW 312 XawPixmap *pixmap; 313#endif 314 Pixmap border_pixmap = CopyFromParent; 315 316 if (!XtIsSensitive(w)) 317 { 318 /* change border to gray; have to remember the old one, 319 * so XtDestroyWidget deletes the proper one */ 320 if (((SimpleWidget)w)->simple.insensitive_border == None) 321 ((SimpleWidget)w)->simple.insensitive_border = 322 XmuCreateStippledPixmap(XtScreen(w), 323 w->core.border_pixel, 324 w->core.background_pixel, 325 w->core.depth); 326 border_pixmap = w->core.border_pixmap; 327 attributes->border_pixmap = 328 w->core.border_pixmap = ((SimpleWidget)w)->simple.insensitive_border; 329 330 *valueMask |= CWBorderPixmap; 331 *valueMask &= ~CWBorderPixel; 332 } 333 334 ConvertCursor(w); 335 336 if ((attributes->cursor = ((SimpleWidget)w)->simple.cursor) != None) 337 *valueMask |= CWCursor; 338 339 XtCreateWindow(w, InputOutput, (Visual *)CopyFromParent, 340 *valueMask, attributes); 341 342 if (!XtIsSensitive(w)) 343 w->core.border_pixmap = border_pixmap; 344 345#ifndef OLDXAW 346 if (w->core.background_pixmap > XtUnspecifiedPixmap) { 347 pixmap = XawPixmapFromXPixmap(w->core.background_pixmap, XtScreen(w), 348 w->core.colormap, w->core.depth); 349 if (pixmap && pixmap->mask) 350 XawReshapeWidget(w, pixmap); 351 } 352 353 if (((SimpleWidget)w)->simple.tip) 354 XawTipEnable(w); 355#endif 356} 357 358/* 359 * Function: 360 * ConvertCursor 361 * 362 * Parameters: 363 * w - simple widget 364 * 365 * Description: 366 * Converts a name to a new cursor. 367 */ 368static void 369ConvertCursor(Widget w) 370{ 371 SimpleWidget simple = (SimpleWidget) w; 372 XrmValue from, to; 373 Cursor cursor = None; 374 375 if (simple->simple.cursor_name == NULL) 376 return; 377 378 from.addr = (XPointer)simple->simple.cursor_name; 379 from.size = strlen((char *)from.addr) + 1; 380 381 to.size = sizeof(Cursor); 382 to.addr = (XPointer)&cursor; 383 384 if (XtConvertAndStore(w, XtRString, &from, XtRColorCursor, &to)) 385 simple->simple.cursor = cursor; 386 else 387 XtAppErrorMsg(XtWidgetToApplicationContext(w), 388 "convertFailed","ConvertCursor","XawError", 389 "Simple: ConvertCursor failed.", 390 NULL, NULL); 391} 392 393 394/*ARGSUSED*/ 395static Boolean 396XawSimpleSetValues(Widget current, Widget request, Widget cnew, 397 ArgList args, Cardinal *num_args) 398{ 399 SimpleWidget s_old = (SimpleWidget)current; 400 SimpleWidget s_new = (SimpleWidget)cnew; 401 Bool new_cursor = False; 402 403 /* this disables user changes after creation */ 404 s_new->simple.international = s_old->simple.international; 405 406 if (XtIsSensitive(current) != XtIsSensitive(cnew)) 407 (*((SimpleWidgetClass)XtClass(cnew))->simple_class.change_sensitive) 408 (cnew); 409 410 if (s_old->simple.cursor != s_new->simple.cursor) 411 new_cursor = True; 412 413 /* 414 * We are not handling the string cursor_name correctly here 415 */ 416 417 if (s_old->simple.pointer_fg != s_new->simple.pointer_fg || 418 s_old->simple.pointer_bg != s_new->simple.pointer_bg || 419 s_old->simple.cursor_name != s_new->simple.cursor_name) { 420 ConvertCursor(cnew); 421 new_cursor = True; 422 } 423 424 if (new_cursor && XtIsRealized(cnew)) { 425 if (s_new->simple.cursor != None) 426 XDefineCursor(XtDisplay(cnew), XtWindow(cnew), s_new->simple.cursor); 427 else 428 XUndefineCursor(XtDisplay(cnew), XtWindow(cnew)); 429 } 430 431#ifndef OLDXAW 432 if (s_old->core.background_pixmap != s_new->core.background_pixmap) { 433 XawPixmap *opix, *npix; 434 435 opix = XawPixmapFromXPixmap(s_old->core.background_pixmap, 436 XtScreen(s_old), s_old->core.colormap, 437 s_old->core.depth); 438 npix = XawPixmapFromXPixmap(s_new->core.background_pixmap, 439 XtScreen(s_new), s_new->core.colormap, 440 s_new->core.depth); 441 if ((npix && npix->mask) || (opix && opix->mask)) 442 XawReshapeWidget(cnew, npix); 443 } 444 445 if (s_old->simple.tip != s_new->simple.tip) { 446 if (s_old->simple.tip) 447 XtFree((XtPointer)s_old->simple.tip); 448 if (s_new->simple.tip) 449 s_new->simple.tip = XtNewString(s_new->simple.tip); 450 } 451 452 if (s_old->simple.tip && !s_new->simple.tip) 453 XawTipDisable(cnew); 454 else if (!s_old->simple.tip && s_new->simple.tip) 455 XawTipEnable(cnew); 456 457 if (s_old->simple.display_list != s_new->simple.display_list) 458 return (True); 459#endif /* OLDXAW */ 460 461 return (False); 462} 463 464#ifndef OLDXAW 465static void 466XawSimpleExpose(Widget w, XEvent *event, Region region) 467{ 468 SimpleWidget xaw = (SimpleWidget)w; 469 470 if (xaw->simple.display_list) 471 XawRunDisplayList(w, xaw->simple.display_list, event, region); 472} 473#endif 474 475static Bool 476ChangeSensitive(Widget w) 477{ 478 if (XtIsRealized(w)) { 479 if (XtIsSensitive(w)) 480 if (w->core.border_pixmap != XtUnspecifiedPixmap) 481 XSetWindowBorderPixmap(XtDisplay(w), XtWindow(w), 482 w->core.border_pixmap); 483 else 484 XSetWindowBorder(XtDisplay(w), XtWindow(w), 485 w->core.border_pixel); 486 else { 487 if (((SimpleWidget)w)->simple.insensitive_border == None) 488 ((SimpleWidget)w)->simple.insensitive_border = 489 XmuCreateStippledPixmap(XtScreen(w), 490 w->core.border_pixel, 491 w->core.background_pixel, 492 w->core.depth); 493 XSetWindowBorderPixmap(XtDisplay(w), XtWindow(w), 494 ((SimpleWidget)w)->simple.insensitive_border); 495 } 496 } 497 498 return (False); 499} 500