1 #ifndef production
2 static char rcsId[]="$Header$";
3 #endif
4 /*****
5 * XmHTML.c : XmHTML main routines, Xt/Motif version
6 *
7 * This file Version $Revision$
8 *
9 * Creation date: Thu Nov 21 05:02:44 GMT+0100 1996
10 * Last modification: $Date$
11 * By: $Author$
12 * Current State: $State$
13 *
14 * Author: newt
15 * (C)Copyright 1995-1996 Ripley Software Development
16 * All Rights Reserved
17 *
18 * This file is part of the XmHTML Widget Library.
19 *
20 * This library is free software; you can redistribute it and/or
21 * modify it under the terms of the GNU Library General Public
22 * License as published by the Free Software Foundation; either
23 * version 2 of the License, or (at your option) any later version.
24 *
25 * This library is distributed in the hope that it will be useful,
26 * but WITHOUT ANY WARRANTY; without even the implied warranty of
27 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
28 * Library General Public License for more details.
29 *
30 * You should have received a copy of the GNU Library General Public
31 * License along with this library; if not, write to the Free
32 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
33 *
34 *****/
35 /*****
36 * ChangeLog
37 * $Log$
38 * Revision 1.1 2011/06/30 16:10:30 rwcox
39 * Cadd
40 *
41 * Revision 1.19 1998/04/27 06:56:21 newt
42 * tka: extracted all toolkit independent functions to private.c and public.c
43 *
44 * Revision 1.18 1998/04/04 06:27:51 newt
45 * XmHTML Beta 1.1.3
46 *
47 * Revision 1.17 1997/10/26 23:49:18 newt
48 * Bugfixes 10/22/97-01, 10/26/97-01
49 *
50 * Revision 1.16 1997/08/31 17:32:33 newt
51 * Again some fixes in _XmHTMLMoveToPos
52 *
53 * Revision 1.15 1997/08/30 00:38:58 newt
54 * Anchor Highlighting, form component traversal action routines, alpha
55 * channel support, loads of fixes in _XmHTMLMoveToPos, DrawRedisplay and
56 * SetValues.
57 *
58 * Revision 1.14 1997/08/01 12:54:48 newt
59 * Progressive image loading changes.
60 *
61 * Revision 1.13 1997/05/28 01:38:30 newt
62 * Added a check on the value of the XmNmaxImageColors resource. Added a check
63 * on the scrollbar dimensions. Modified the SetValues method to properly deal
64 * with the XmNbodyImage resource. Modified XmHTMLImageFreeImageInfo to call
65 * _XmHTMLFreeImageInfo.
66 *
67 * Revision 1.12 1997/04/29 14:22:14 newt
68 * A lot of changes in SetValues, Layout, XmHTMLTextSetString.
69 * Added XmHTMLXYToInfo.
70 *
71 * Revision 1.11 1997/04/03 05:31:02 newt
72 * Modified XmHTMLImageReplace and XmHTMLImageUpdate to immediatly render an
73 * image whenever possible. Added the XmHTMLFrameGetChild convenience function.
74 *
75 * Revision 1.10 1997/03/28 07:05:28 newt
76 * Frame interface added.
77 * Horizontal scrolling bugfix.
78 * Added all remaining action routines and adjusted translation table.
79 *
80 * Revision 1.9 1997/03/20 08:04:38 newt
81 * XmHTMLImageFreeImageInfo, XmNrepeatDelay, changes in public image functions
82 *
83 * Revision 1.8 1997/03/11 19:49:53 newt
84 * Fix 03/11/97-01, SetValues.
85 * Added XmHTMLImageGetType, updated XmHTMLImageReplace and XmHTMLImageUpdate
86 *
87 * Revision 1.7 1997/03/04 18:45:15 newt
88 * ?
89 *
90 * Revision 1.6 1997/03/04 00:55:54 newt
91 * Delayed Image Loading changes: XmHTMLReplaceImage, XmHTMLUpdateImage
92 * and XmHTMLRedisplay added
93 *
94 * Revision 1.5 1997/03/02 23:06:35 newt
95 * Added image/imagemap support; changed expose method; added background
96 * image painting
97 *
98 * Revision 1.4 1997/02/11 02:05:44 newt
99 * Changes related to autosizing, exposure and scrolling
100 *
101 * Revision 1.3 1997/01/09 06:54:53 newt
102 * expanded copyright marker
103 *
104 * Revision 1.2 1997/01/09 06:42:40 newt
105 * XmNresizeWidth and XmNresizeHeight updates
106 *
107 * Revision 1.1 1996/12/19 02:17:03 newt
108 * Initial Revision
109 *
110 *****/
111 #ifdef HAVE_CONFIG_H
112 #include "config.h"
113 #endif
114
115 #include <stdio.h>
116 #include <stdlib.h>
117 #include <string.h>
118 #include <ctype.h>
119
120 #include <X11/IntrinsicP.h> /* Fast macros */
121 #include <X11/keysym.h> /* for keycodes in HTMLProcessInput */
122 #include <X11/Xmu/StdSel.h>
123
124 #include <Xm/XmP.h> /* XmField, XmPartOffset and private motif funcs. */
125 #include <Xm/DrawP.h>
126 #include <Xm/XmStrDefs.h> /* For motif XmN macros */
127
128 /*****
129 * Test if these macros are present. They are required for conversion of the
130 * enumeration resource values. I don't know if they are present in Motif 1.2.X.
131 * If not here, spit out an error message.
132 * If you can't compile this because this error occurs, please contact us
133 * at the address given below and state what version of Motif you are using.
134 * Note: these are explicit syntax errors...
135 *****/
136 #ifndef XmPartOffset
137 XmPartOffset macro undefined. Please contact ripley@xs4all.nl
138 #endif
139 #ifndef XmField
140 XmField macro undefined. Please contact ripley@xs4all.nl
141 #endif
142
143 #include <Xm/DrawingA.h>
144 #include <Xm/ScrollBar.h>
145 #include <Xm/ScrolledW.h>
146 #include <Xm/RepType.h>
147
148 /* Our private header files */
149 #include "toolkit.h"
150 #include XmHTMLPrivateHeader
151
152 /* This is the anchor cursor */
153 #include "bitmaps/fingers.xbm"
154 #include "bitmaps/fingers_m.xbm"
155
156 /*** External Function Prototype Declarations ***/
157 /*
158 * undocumented motif functions used: (declared in XmP.h):
159 * _XmRedisplayGadgets (Widget, XEvent*, Region);
160 */
161
162 /*** Public Variable Declarations ***/
163
164 /*** Private Datatype Declarations ****/
165 /* Static resources */
166 #include "resources.h"
167
168 /*** Private Function Prototype Declarations ****/
169 /***
170 * Private functions
171 ***/
172 static void CreateAnchorCursor(XmHTMLWidget html);
173 static void CreateHTMLWidget(XmHTMLWidget html);
174 static void CheckAnchorUnderlining(XmHTMLWidget html, XmHTMLWidget req);
175 static void CheckAlignment(XmHTMLWidget html, XmHTMLWidget req);
176 static void ScrollCB(Widget w, XtPointer arg1, XtPointer arg2);
177
178 /* manage scrollbars if necessary */
179 #define SetScrollBars(HTML) { \
180 if(ATTR_HTML(HTML, needs_hsb) && \
181 !(ATTR_HTML(HTML,tka)->IsManaged(ATTR_HTML(HTML,hsb)))) \
182 ATTR_HTML(HTML,tka)->ManageChild(ATTR_HTML(HTML, hsb)); \
183 if(ATTR_HTML(HTML, needs_vsb) && \
184 !(ATTR_HTML(HTML,tka)->IsManaged(ATTR_HTML(HTML,vsb)))) \
185 ATTR_HTML(HTML,tka)->ManageChild(ATTR_HTML(HTML, vsb)); \
186 }
187
188 /***
189 * Class methods
190 ***/
191 /* Primary ClassInitialize method */
192 static void ClassInitialize(void);
193
194 /* ClassPartInitialize method */
195 static void ClassPartInitialize(WidgetClass wc);
196
197 /* class initialize method */
198 static void Initialize(Widget request, Widget init, ArgList args,
199 Cardinal *num_args);
200
201 /* class expose method */
202 static void Redisplay(Widget w, XEvent *event, Region region);
203
204 /* Expose event handler for the work area */
205 static void DrawRedisplay(Widget w, XmHTMLWidget html, XEvent *event);
206
207 /* VisibilityNotify event handler for the work area */
208 static void VisibilityHandler(Widget w, XmHTMLWidget html, XEvent *event);
209
210 /* MapNotify action routine for the work area */
211 static void Mapped(Widget w, XmHTMLWidget html, XEvent *event);
212
213 /* class set_values method */
214 static Boolean SetValues(Widget current, Widget request, Widget set,
215 ArgList args, Cardinal *num_args);
216
217 /* class get_values_hook method */
218 static void GetValues(Widget w, ArgList args, Cardinal *num_args);
219
220 /* class geometry_manager method */
221 static XtGeometryResult GeometryManager(Widget w, XtWidgetGeometry *request,
222 XtWidgetGeometry *geometry_return);
223
224 /* class destroy method */
225 static void Destroy(Widget w);
226
227 /* Action routines */
228 static void ExtendStart(Widget w, XEvent *event, String *params,
229 Cardinal *num_params);
230 static void ExtendAdjust(Widget w, XEvent *event, String *params,
231 Cardinal *num_params);
232 static void ExtendEnd(Widget w, XEvent *event, String *params,
233 Cardinal *num_params);
234 static void TrackMotion(Widget w, XEvent *event, String *params,
235 Cardinal *num_params);
236 static void TrackFocus(Widget w, XEvent *event, String *params,
237 Cardinal *num_params);
238 static void HTMLProcessInput(Widget w, XEvent *event, String *params,
239 Cardinal *num_params);
240 static void HTMLPageUpOrLeft(Widget w, XEvent *event, String *params,
241 Cardinal *num_params);
242 static void HTMLPageDownOrRight(Widget w, XEvent *event, String *params,
243 Cardinal *num_params);
244 static void HTMLIncrementUpOrLeft(Widget w, XEvent *event, String *params,
245 Cardinal *num_params);
246 static void HTMLIncrementDownOrRight(Widget w, XEvent *event, String *params,
247 Cardinal *num_params);
248 static void HTMLTopOrBottom(Widget w, XEvent *event, String *params,
249 Cardinal *num_params);
250 static void HTMLTraverseCurrent(Widget w, XEvent *event, String *params,
251 Cardinal *num_params);
252 static void HTMLTraverseNext(Widget w, XEvent *event, String *params,
253 Cardinal *num_params);
254 static void HTMLTraversePrev(Widget w, XEvent *event, String *params,
255 Cardinal *num_params);
256 static void HTMLTraverseNextOrPrev(Widget w, XEvent *event, String *params,
257 Cardinal *num_params);
258
259 /*** Private Variable Declarations ***/
260 static XmRepTypeId underline_repid, sb_policy_repid;
261 static XmRepTypeId sb_placement_repid, string_repid, icon_repid;
262 static XmRepTypeId enable_repid, conv_repid, load_repid;
263
264 /*****
265 * default translations
266 * Order of key translations is important: placing c <Key>osfPageUp after
267 * <key>osfPageUp will mask of the Ctrl key.
268 * XmHTML explicitly masks off all key modifiers it does not need for a
269 * certain action. This allows application programmers to use the same keys
270 * with modifiers for their own purposes and prevents that these key sequences
271 * are handled by these specific XmHTML action routines.
272 * This looks ugly, since it's a static block of text it doesn't take up that
273 * much data space.
274 *****/
275 static char translations[] =
276 "Ctrl <Key>osfPageUp: page-up-or-left(1)\n\
277 Ctrl <Key>osfPageDown: page-down-or-right(1)\n\
278 Ctrl <Key>osfBeginLine: top-or-bottom(0)\n\
279 Ctrl <Key>osfEndLine: top-or-bottom(1)\n\
280 ~Shift ~Meta ~Alt <Btn1Down>: extend-start() ManagerGadgetArm()\n\
281 ~Shift ~Meta ~Alt <Btn1Motion>: extend-adjust() ManagerGadgetButtonMotion()\n\
282 ~Shift ~Meta ~Alt <Btn1Up>: extend-end(PRIMARY, CUT_BUFFER0) ManagerGadgetActivate() traverse-current()\n\
283 ~Shift ~Meta ~Alt <Btn2Down>:extend-start()\n\
284 ~Shift ~Meta ~Alt <Btn2Motion>: extend-adjust()\n\
285 ~Shift ~Meta ~Alt <Btn2Up>: extend-end(PRIMARY, CUT_BUFFER0)\n\
286 ~Shift ~Meta ~Alt <Key>osfPageUp: page-up-or-left(0)\n\
287 ~Shift ~Meta ~Alt <Key>osfPageDown: page-down-or-right(0)\n\
288 ~Shift ~Meta ~Alt <Key>osfUp: increment-up-or-left(0)\n\
289 ~Shift ~Meta ~Alt <Key>osfLeft: increment-up-or-left(1)\n\
290 ~Shift ~Meta ~Alt <Key>osfDown: increment-down-or-right(0)\n\
291 ~Shift ~Meta ~Alt <Key>osfRight: increment-down-or-right(1)\n\
292 <Key>osfHelp: ManagerGadgetHelp()\n\
293 Shift Ctrl <Key>Tab: ManagerGadgetPrevTabGroup()\n\
294 Ctrl <Key>Tab: ManagerGadgetNextTabGroup()\n\
295 <Key>Tab: traverse-next()\n\
296 <Motion>: track-motion()\n\
297 <Leave>: track-focus()\n\
298 <FocusIn>: track-focus()\n\
299 <FocusOut>: track-focus()\n\
300 <KeyDown>: process-html-input()\n\
301 <KeyUp>: process-html-input()";
302
303 /* Action routines provided by XmHTML */
304 static XtActionsRec actions[] =
305 {
306 {"extend-start", (XtActionProc)ExtendStart},
307 {"extend-adjust", (XtActionProc)ExtendAdjust},
308 {"extend-end", (XtActionProc)ExtendEnd},
309 {"page-up-or-left", (XtActionProc)HTMLPageUpOrLeft},
310 {"page-down-or-right", (XtActionProc)HTMLPageDownOrRight},
311 {"increment-up-or-left", (XtActionProc)HTMLIncrementUpOrLeft},
312 {"increment-down-or-right", (XtActionProc)HTMLIncrementDownOrRight},
313 {"top-or-bottom", (XtActionProc)HTMLTopOrBottom},
314 {"track-motion", (XtActionProc)TrackMotion},
315 {"track-focus", (XtActionProc)TrackFocus},
316 {"process-html-input", (XtActionProc)HTMLProcessInput},
317 {"traverse-current", (XtActionProc)HTMLTraverseCurrent},
318 {"traverse-next", (XtActionProc)HTMLTraverseNext},
319 {"traverse-prev", (XtActionProc)HTMLTraversePrev},
320 {"traverse-next-or-prev", (XtActionProc)HTMLTraverseNextOrPrev}
321 };
322
323 /*
324 * copy of original list. Motif destroys the original list and therefore
325 * XmHTML crashes when we try to use the above list again.
326 */
327 static XtActionsRec spareActions[] =
328 {
329 {"extend-start", (XtActionProc)ExtendStart},
330 {"extend-adjust", (XtActionProc)ExtendAdjust},
331 {"extend-end", (XtActionProc)ExtendEnd},
332 {"page-up-or-left", (XtActionProc)HTMLPageUpOrLeft},
333 {"page-down-or-right", (XtActionProc)HTMLPageDownOrRight},
334 {"increment-up-or-left", (XtActionProc)HTMLIncrementUpOrLeft},
335 {"increment-down-or-right", (XtActionProc)HTMLIncrementDownOrRight},
336 {"top-or-bottom", (XtActionProc)HTMLTopOrBottom},
337 {"track-motion", (XtActionProc)TrackMotion},
338 {"track-focus", (XtActionProc)TrackFocus},
339 {"process-html-input", (XtActionProc)HTMLProcessInput},
340 {"traverse-current", (XtActionProc)HTMLTraverseCurrent},
341 {"traverse-next", (XtActionProc)HTMLTraverseNext},
342 {"traverse-prev", (XtActionProc)HTMLTraversePrev},
343 {"traverse-next-or-prev", (XtActionProc)HTMLTraverseNextOrPrev}
344 };
345
346 /****
347 * Define the CompositeClassExtension record so we can accept objects.
348 ****/
349 static CompositeClassExtensionRec htmlCompositeExtension = {
350 NULL, /* next_extension */
351 NULLQUARK, /* record_type */
352 XtCompositeExtensionVersion, /* version */
353 sizeof(CompositeClassExtensionRec), /* record_size */
354 True /* accept_objects */
355 #if XtSpecificationRelease >= 6
356 , False /* allows_change_managed_set */
357 #endif
358 };
359
360 /****
361 * Define the widget class record.
362 ****/
363 XmHTMLClassRec xmHTMLClassRec = {
364 /* core class fields */
365 {
366 #ifdef MOTIF_IN_DLL
367 /*****
368 * If Motif is in a DLL on Windows (VC++ 5.0), attempting to initialize
369 * this with &xmManagerClassRec gives a compiler error telling us that
370 * it's not a constant (there's some indirection going on there). In
371 * that case, we have to initialize this to NULL and set it in
372 * XmCreateHTML before calling XtCreateWidget. This means that
373 * XmCreateHTML will be the only valid way to create an XmHTML widget,
374 * but that's a small price to pay
375 * -- DCW, 6 Jul 98
376 *****/
377 (WidgetClass) NULL, /* superclass */
378 #else
379 (WidgetClass) &xmManagerClassRec, /* superclass */
380 #endif
381 "XmHTML", /* class_name */
382 sizeof(XmHTMLRec), /* widget_size */
383 ClassInitialize, /* class_initialize */
384 ClassPartInitialize, /* class_part_init */
385 FALSE, /* class_inited */
386 (XtInitProc)Initialize, /* initialize */
387 NULL, /* initialize_hook */
388 XtInheritRealize, /* realize */
389 actions, /* actions */
390 XtNumber(actions), /* num_actions */
391 resources, /* resources */
392 XtNumber(resources), /* num_resources */
393 NULLQUARK, /* xrm_class */
394 TRUE, /* compress_motion */
395 XtExposeCompressMaximal, /* compress_exposure */
396 TRUE, /* compress_enterleave */
397 FALSE, /* visible_interest */
398 Destroy, /* destroy */
399 (XtWidgetProc)_XmHTMLResize, /* resize */
400 (XtExposeProc)Redisplay, /* expose */
401 (XtSetValuesFunc)SetValues, /* set_values */
402 NULL, /* set_values_hook */
403 XtInheritSetValuesAlmost, /* set_values_almost */
404 GetValues, /* get_values_hook */
405 XtInheritAcceptFocus, /* accept_focus */
406 XtVersion, /* version */
407 NULL, /* callback_private */
408 translations, /* tm_table */
409 XtInheritQueryGeometry, /* query_geometry */
410 XtInheritDisplayAccelerator, /* display_accelerator */
411 NULL /* extension */
412 },
413 /* composite_class fields */
414 {
415 GeometryManager, /* geometry_manager */
416 NULL, /* change_managed */
417 XtInheritInsertChild, /* insert_child */
418 XtInheritDeleteChild, /* delete_child */
419 NULL, /* set by ClassPartInit */
420 },
421 /* constraint_class fields */
422 {
423 NULL, /* resource list */
424 0, /* num resources */
425 0, /* constraint size */
426 NULL, /* init proc */
427 NULL, /* destroy proc */
428 NULL, /* set values proc */
429 NULL /* extension */
430 },
431 /* manager_class fields */
432 {
433 XtInheritTranslations, /* translations */
434 NULL, /* syn_resources */
435 0, /* num_syn_resources */
436 NULL, /* syn_cont_resources */
437 0, /* num_syn_cont_resources*/
438 XmInheritParentProcess, /* parent_process */
439 NULL /* extension */
440 },
441 /* html_class fields */
442 {
443 0 /* none */
444 }
445 };
446
447 /* Establish the widget class name as an externally accessible symbol. */
448 WidgetClass xmHTMLWidgetClass = (WidgetClass) &xmHTMLClassRec;
449
450 static void
TestRepId(XmRepTypeId id,String name)451 TestRepId(XmRepTypeId id, String name)
452 {
453 if(id == XmREP_TYPE_INVALID)
454 _XmHTMLWarning(__WFUNC__(NULL, "TestRepId"), XMHTML_MSG_8, name);
455 }
456
457 /*****
458 * Name: ClassInitialize
459 * Return Type: void
460 * Description: Called by Intrinsics the first time a widget of this class
461 * is instantiated
462 * In:
463 * nothing
464 * Returns:
465 * nothing
466 *****/
467 static void
ClassInitialize(void)468 ClassInitialize(void)
469 {
470 static char *enable_models[] = {"automatic", "always", "never"};
471 static char *conv_models[] = {"quick", "best", "fast", "slow", "disabled"};
472 static char *line_styles[] = {"no_line", "single_line", "double_line",
473 "single_dashed_line", "double_dashed_line"};
474 static char *load_types[] = {"normal", "load_normal",
475 "progressive", "load_progressive",
476 "incremental", "load_incremental",
477 "suspend", "load_suspend",
478 "abort", "load_abort"};
479 static Byte load_values[] = {XmLOAD_NORMAL, XmLOAD_NORMAL,
480 XmLOAD_PROGRESSIVE, XmLOAD_PROGRESSIVE,
481 XmLOAD_INCREMENTAL, XmLOAD_INCREMENTAL,
482 XmLOAD_SUSPEND, XmLOAD_SUSPEND,
483 XmLOAD_ABORT, XmLOAD_ABORT};
484
485 /* Usefull sanity: check compile version against current header version */
486 if(XmHTMLVersion != VERSION)
487 {
488 _XmHTMLWarning(__WFUNC__(NULL, "ClassInitialize"),
489 "Version number mismatch: this library was compiled as\n"
490 " version %i using XmHTML.h version %i.",
491 VERSION, XmHTMLVersion);
492 }
493
494 /* Get appropriate representation type convertor id's */
495
496 /* ScrollBar converters. */
497 sb_policy_repid = XmRepTypeGetId(XmCScrollBarDisplayPolicy);
498 TestRepId(sb_policy_repid, XmCScrollBarDisplayPolicy);
499
500 sb_placement_repid = XmRepTypeGetId(XmCScrollBarPlacement);
501 TestRepId(sb_placement_repid, XmCScrollBarPlacement);
502
503 /* string direction converter */
504 string_repid = XmRepTypeGetId(XmCAlignment);
505 TestRepId(string_repid, XmCAlignment);
506
507 /* vertical icon alignment */
508 icon_repid = XmRepTypeGetId(XmCVerticalAlignment);
509 TestRepId(icon_repid, XmCVerticalAlignment);
510
511 /* XmCEnableMode resource class converter */
512 XmRepTypeRegister(XmCEnableMode, enable_models, NULL, 3);
513 enable_repid = XmRepTypeGetId(XmCEnableMode);
514 TestRepId(enable_repid, XmCEnableMode);
515
516 /* XmCConversionMode resource class converter */
517 XmRepTypeRegister(XmCConversionMode, conv_models, NULL, 5);
518 conv_repid = XmRepTypeGetId(XmCConversionMode);
519 TestRepId(conv_repid, XmCConversionMode);
520
521 /* XmCAnchorUnderlineType resource class converter */
522 XmRepTypeRegister(XmCAnchorUnderlineType, line_styles, NULL, 5);
523 underline_repid = XmRepTypeGetId(XmCAnchorUnderlineType);
524 TestRepId(underline_repid, XmCAnchorUnderlineType);
525
526 /* XmCLoadType resource class converter */
527 XmRepTypeRegister(XmCLoadType, load_types, load_values, 10);
528 load_repid = XmRepTypeGetId(XmCLoadType);
529 TestRepId(load_repid, XmCLoadType);
530
531 /* Register the XmNenableBadHTMLWarnings converter */
532 XtSetTypeConverter(XmRString, XmRHTMLWarningMode,
533 (XtTypeConverter)_XmHTMLCvtStringToWarning, NULL, 0, XtCacheAll, NULL);
534 }
535
536 /*****
537 * Name: ClassPartInitialize
538 * Return Type: void
539 * Description: object class method to initialize class part structure fields.
540 * In:
541 * subclass: pointer to a widget class structure.
542 * Returns:
543 * nothing.
544 * Note:
545 * This routine initializes the Composite extension. XmHTML *must* be a
546 * subclass of composite if we want to have it accept any type of Object
547 * (including real Objects, Gadgets and Widgets).
548 * Kindly donated by Youssef Ouaghli <Youssef.Ouaghli@elec.rma.ac.be>
549 *****/
550 static void
ClassPartInitialize(WidgetClass wc)551 ClassPartInitialize(WidgetClass wc)
552 {
553 XmHTMLWidgetClass html_wc = (XmHTMLWidgetClass)wc;
554
555 htmlCompositeExtension.next_extension = html_wc->composite_class.extension;
556 htmlCompositeExtension.accepts_objects = True;
557
558 html_wc->composite_class.extension = (XtPointer)&htmlCompositeExtension;
559 }
560
561 /*****
562 * Name: Initialize
563 * Return Type: void
564 * Description: Called when the widget is instantiated
565 * In:
566 * request: widget with resource values set as requested by the argument
567 * list, resource database and widget defaults
568 * init: same widget with values as modified by superclass initialize()
569 * methods
570 * args: argument list passed to XtCreateWidget
571 * num_args: number of entries in the argument list
572 * Returns:
573 * nothing, but init is updated with checked/updated resource values.
574 *****/
575 static void
Initialize(Widget request,Widget init,ArgList args,Cardinal * num_args)576 Initialize(Widget request, Widget init, ArgList args, Cardinal *num_args)
577 {
578 XmHTMLWidget html = (XmHTMLWidget)init;
579 XmHTMLWidget req = (XmHTMLWidget)request;
580
581 /* Initialize the global HTMLpart */
582
583 /* select debug levels */
584 _XmHTMLSelectDebugLevels(req->html.debug_levels);
585 _XmHTMLSetFullDebug(req->html.debug_full_output);
586
587 #ifdef DEBUG
588 if(req->html.debug_disable_warnings)
589 debug_disable_warnings = True;
590 else
591 debug_disable_warnings = False;
592 #endif
593
594 _XmHTMLDebug(1, ("XmHTML.c: Initialize Start\n"));
595
596 /* private widget resources */
597
598 /* Initialize ToolkitAbstraction */
599 HTML_ATTR(tka) = XmHTMLTkaCreate();
600
601 /* Store display */
602 XmHTMLTkaSetDisplay(HTML_ATTR(tka), (Widget)html);
603
604 HTML_ATTR(needs_vsb) = False;
605 HTML_ATTR(needs_hsb) = False;
606 HTML_ATTR(scroll_x) = 0;
607 HTML_ATTR(scroll_y) = 0;
608
609 CheckAnchorUnderlining(html, html);
610
611 /* ScrollBarDisplayPolicy */
612 if(!XmRepTypeValidValue(sb_policy_repid, HTML_ATTR(sb_policy),
613 (Widget)html))
614 HTML_ATTR(sb_policy) = XmAS_NEEDED;
615 else if(HTML_ATTR(sb_policy) == XmSTATIC)
616 HTML_ATTR(needs_vsb) = True;
617
618 /* ScrollBarPlacement */
619 if(!XmRepTypeValidValue(sb_placement_repid, HTML_ATTR(sb_placement),
620 (Widget)html))
621 HTML_ATTR(sb_placement) = XmBOTTOM_RIGHT;
622
623 /* perfectColors */
624 if(!XmRepTypeValidValue(enable_repid, HTML_ATTR(perfect_colors),
625 (Widget)html))
626 HTML_ATTR(perfect_colors) = XmAUTOMATIC;
627
628 /* AlphaChannelProcessing */
629 if(!XmRepTypeValidValue(enable_repid, HTML_ATTR(alpha_processing),
630 (Widget)html))
631 HTML_ATTR(alpha_processing) = XmALWAYS;
632
633 /* ImageRGBConversion */
634 if(!XmRepTypeValidValue(conv_repid, HTML_ATTR(rgb_conv_mode),
635 (Widget)html) || HTML_ATTR(rgb_conv_mode) == XmDISABLED)
636 HTML_ATTR(rgb_conv_mode) = XmBEST;
637
638 /* ImageMapToPalette */
639 if(!XmRepTypeValidValue(conv_repid, HTML_ATTR(map_to_palette),
640 (Widget)html))
641 HTML_ATTR(map_to_palette) = XmDISABLED;
642
643 /* LoadType */
644 if(!XmRepTypeValidValue(load_repid, HTML_ATTR(load_type),
645 (Widget)html))
646 HTML_ATTR(load_type) = XmLOAD_NORMAL;
647
648 /* Vertical icon alignment */
649 if(!XmRepTypeValidValue(icon_repid, HTML_ATTR(icon_valign),
650 (Widget)html))
651 HTML_ATTR(icon_valign) = XmALIGNMENT_CENTER;
652
653 /* repeat delay. Must be positive */
654 if(HTML_ATTR(repeat_delay) < 1)
655 {
656 _XmHTMLWarning(__WFUNC__(init, "Initialize"), XMHTML_MSG_9,
657 "XmNrepeatDelay", HTML_ATTR(repeat_delay),
658 XmHTML_DEFAULT_REPEAT_DELAY);
659 HTML_ATTR(repeat_delay) = XmHTML_DEFAULT_REPEAT_DELAY;
660 }
661
662 /* tabwidth, must be a positive, non-zero number */
663 if(HTML_ATTR(tabwidth) < 1)
664 {
665 _XmHTMLWarning(__WFUNC__(init, "Initialize"), XMHTML_MSG_9,
666 "XmNtabWidth", HTML_ATTR(tabwidth),
667 XmHTML_DEFAULT_TABWIDTH);
668 HTML_ATTR(tabwidth) = XmHTML_DEFAULT_TABWIDTH;
669 }
670
671 /* Set default text alignment */
672 CheckAlignment(html, html);
673
674 /* source input is always complete */
675 HTML_ATTR(input_complete) = True;
676
677 /****
678 * Initialize private resources.
679 ****/
680 /* Formatted document resources */
681 HTML_ATTR(formatted_width) = 1;
682 HTML_ATTR(formatted_height) = 1;
683 HTML_ATTR(elements) = (XmHTMLObject*)NULL;
684 HTML_ATTR(last_element) = (XmHTMLObject*)NULL;
685 HTML_ATTR(formatted) = (XmHTMLObjectTable*)NULL;
686 HTML_ATTR(last_formatted) = (XmHTMLObjectTable*)NULL;
687 HTML_ATTR(paint_start) = (XmHTMLObjectTable*)NULL;
688 HTML_ATTR(paint_end) = (XmHTMLObjectTable*)NULL;
689 HTML_ATTR(nlines) = 0;
690 HTML_ATTR(line_table) = (XmHTMLLineTable*)NULL;
691
692 /* body image */
693 HTML_ATTR(body_image) = (XmHTMLImage*)NULL;
694 HTML_ATTR(body_image_url) = (String)NULL;
695
696 /* layout & paint engine resources */
697 HTML_ATTR(in_layout) = False;
698 HTML_ATTR(paint_x) = 0;
699 HTML_ATTR(paint_y) = 0;
700 HTML_ATTR(paint_width) = 0;
701 HTML_ATTR(paint_height) = 0;
702 HTML_ATTR(body_fg) = MGR_ATTR(foreground);
703 HTML_ATTR(body_bg) = CORE_ATTR(background_pixel);
704 HTML_ATTR(images) = (XmHTMLImage*)NULL;
705 HTML_ATTR(image_maps) = (XmHTMLImageMap*)NULL;
706 HTML_ATTR(xcc) = (XCC)NULL;
707 HTML_ATTR(bg_gc) = (GC)NULL;
708 HTML_ATTR(form_data) = (XmHTMLFormData*)NULL;
709 HTML_ATTR(delayed_creation) = False; /* no delayed image creation */
710 HTML_ATTR(embedded) = (XmHTMLExtObj*)NULL;
711
712 /*****
713 * Original colors must be stored. They can be altered by the
714 * <BODY> element, so if we get a body without any or some of these
715 * colors specified, we can use the proper default values for the
716 * unspecified elements.
717 *****/
718 HTML_ATTR(body_fg_save) = HTML_ATTR(body_fg);
719 HTML_ATTR(body_bg_save) = HTML_ATTR(body_bg);
720 HTML_ATTR(anchor_fg_save) = HTML_ATTR(anchor_fg);
721 HTML_ATTR(anchor_target_fg_save) = HTML_ATTR(anchor_target_fg);
722 HTML_ATTR(anchor_visited_fg_save) = HTML_ATTR(anchor_visited_fg);
723 HTML_ATTR(anchor_activated_fg_save) = HTML_ATTR(anchor_activated_fg);
724 HTML_ATTR(anchor_activated_bg_save) = HTML_ATTR(anchor_activated_bg);
725
726 /* anchor resources */
727 HTML_ATTR(anchor_position_x) = 0;
728 HTML_ATTR(anchor_position_y) = 0;
729 HTML_ATTR(anchor_current_cursor_element) = (XmHTMLAnchor*)NULL;
730 HTML_ATTR(armed_anchor) = (XmHTMLObjectTable*)NULL;
731 HTML_ATTR(current_anchor) = (XmHTMLObjectTable*)NULL;
732 HTML_ATTR(num_named_anchors) = 0;
733 HTML_ATTR(anchors) = (XmHTMLWord*)NULL;
734 HTML_ATTR(anchor_words) = 0;
735 HTML_ATTR(named_anchors) = (XmHTMLObjectTable*)NULL;
736 HTML_ATTR(anchor_data) = (XmHTMLAnchor*)NULL;
737 HTML_ATTR(press_x) = 0;
738 HTML_ATTR(press_y) = 0;
739 HTML_ATTR(pressed_time) = 0;
740 HTML_ATTR(selected_time) = 0;
741 HTML_ATTR(selected) = (XmHTMLAnchor*)NULL;
742
743 /* Text selection resources */
744 HTML_ATTR(selection) = (XmHTMLObjectTable*)NULL;
745 HTML_ATTR(select_start) = 0;
746 HTML_ATTR(select_end) = 0;
747
748 /* HTML Frame resources */
749 HTML_ATTR(nframes) = 0;
750 HTML_ATTR(frames) = NULL;
751 HTML_ATTR(is_frame) = False;
752
753 /* PLC resources */
754 HTML_ATTR(plc_buffer) = (PLCPtr)NULL;
755 HTML_ATTR(num_plcs) = 0;
756 HTML_ATTR(plc_proc_id) = None;
757 HTML_ATTR(plc_suspended) = True;
758 HTML_ATTR(plc_gc) = (GC)NULL;
759
760 /* Table resources */
761 HTML_ATTR(tables) = (XmHTMLTable*)NULL;
762
763 /* HTML4.0 Event database */
764 HTML_ATTR(events) = (HTEvent**)NULL;
765 HTML_ATTR(nevents) = 0;
766 HTML_ATTR(body_events) = (AllEvents*)NULL;
767 HTML_ATTR(event_mask) = 0L;
768
769 /* initial mimetype */
770 if(!(strcasecmp(HTML_ATTR(mime_type), "text/html")))
771 HTML_ATTR(mime_id) = XmPLC_DOCUMENT;
772 else if(!(strcasecmp(HTML_ATTR(mime_type), "text/html-perfect")))
773 HTML_ATTR(mime_id) = XmPLC_DOCUMENT;
774 else if(!(strcasecmp(HTML_ATTR(mime_type), "text/plain")))
775 HTML_ATTR(mime_id) = XmHTML_NONE;
776 else if(!(strncasecmp(HTML_ATTR(mime_type), "image/", 6)))
777 HTML_ATTR(mime_id) = XmPLC_IMAGE;
778
779 /* alpha channel stuff */
780 HTML_ATTR(alpha_buffer) = (AlphaPtr)NULL;
781
782 if(!HTML_ATTR(anchor_track_callback) && !HTML_ATTR(anchor_cursor) &&
783 !HTML_ATTR(highlight_on_enter) && !HTML_ATTR(motion_track_callback) &&
784 !HTML_ATTR(focus_callback) && !HTML_ATTR(losing_focus_callback))
785 HTML_ATTR(need_tracking) = False;
786 else
787 HTML_ATTR(need_tracking) = True;
788
789 /* verify plc timing intervals */
790 _XmHTMLPLCCheckIntervals(html);
791
792 /* Misc. resources */
793 HTML_ATTR(gc) = (GC)NULL;
794
795 /* set maximum amount of colors for this display (also creates the XCC) */
796 _XmHTMLCheckMaxColorSetting(html);
797
798 /* Create the anchor cursor (if any) */
799 if(HTML_ATTR(anchor_display_cursor) && !(HTML_ATTR(anchor_cursor)))
800 CreateAnchorCursor(html);
801
802 /* set cursor to None if we don't have to use or have a cursor */
803 if(!HTML_ATTR(anchor_display_cursor) || !HTML_ATTR(anchor_cursor))
804 HTML_ATTR(anchor_cursor) = None;
805
806 /* Select & initialize appropriate font cache */
807 HTML_ATTR(default_font) = _XmHTMLSelectFontCache(html, True);
808
809 /*****
810 * if no width or height was specified, default to the width of 20 em
811 * (TeX measure for average character width) in the default font and the
812 * height of a single line. We need to do this check since the Core
813 * initialize() method doesn't do it.
814 *****/
815 if(CORE_ATTR(width) <= 0)
816 {
817 unsigned long value = 0;
818 if(!(XGetFontProperty(HTML_ATTR(default_font)->xfont, XA_QUAD_WIDTH,
819 &value)))
820 {
821 value = XTextWidth(HTML_ATTR(default_font)->xfont, "m", 1);
822
823 /* sanity for non-ISO fonts */
824 if(value <= 0)
825 value = 16;
826 }
827 CORE_ATTR(width) = (Dimension)(20*(Dimension)value +
828 2*HTML_ATTR(margin_width));
829 }
830 if(CORE_ATTR(height) <= 0)
831 CORE_ATTR(height) = HTML_ATTR(default_font)->lineheight +
832 2*HTML_ATTR(margin_height);
833
834 /*****
835 * Now create all private widgets: drawing area and scrollbars.
836 * We couldn't do this until we knew for sure the widget dimensions were
837 * set; creation of the work_area uses them.
838 *****/
839 CreateHTMLWidget(html);
840
841 /* Parse the raw HTML text */
842 if(ATTR_HTML(req, value))
843 {
844 HTML_ATTR(source) = strdup(ATTR_HTML(req, value));
845 HTML_ATTR(elements) = _XmHTMLparseHTML(req, NULL, ATTR_HTML(req, value),
846 html);
847
848 /* check for frames */
849 HTML_ATTR(nframes) = _XmHTMLCheckForFrames(html, HTML_ATTR(elements));
850
851 /* and create them */
852 if(!_XmHTMLCreateFrames(NULL, html))
853 {
854 HTML_ATTR(frames) = NULL;
855 HTML_ATTR(nframes) = 0;
856 }
857 /* Trigger link callback */
858 if(HTML_ATTR(link_callback))
859 _XmHTMLLinkCallback(html);
860
861 /* do initial document markup */
862 _XmHTMLformatObjects(html, html);
863
864 /* check for possible delayed external imagemaps */
865 _XmHTMLCheckImagemaps(html);
866 }
867 else
868 {
869 HTML_ATTR(source) = (String)NULL;
870 HTML_ATTR(elements) = (XmHTMLObject*)NULL;
871 HTML_ATTR(nframes) = 0;
872 HTML_ATTR(formatted) = (XmHTMLObjectTable*)NULL;
873 }
874
875 /* reset scrollbars (this will also resize the work_area) */
876 _XmHTMLCheckScrollBars(html);
877
878 /* Final step: add a palette if we must dither */
879 if(HTML_ATTR(map_to_palette) != XmDISABLED)
880 _XmHTMLAddPalette(html);
881
882 _XmHTMLDebug(1, ("XmHTML.c: Initialize End.\n"));
883 }
884
885 /*****
886 * Name: CreateAnchorCursor
887 * Return Type: void
888 * Description: creates the built-in anchor cursor
889 * In:
890 * html: XmHTMLWidget for which to create a cursor
891 * Returns:
892 * nothing.
893 *****/
894 static void
CreateAnchorCursor(XmHTMLWidget html)895 CreateAnchorCursor(XmHTMLWidget html)
896 {
897 _XmHTMLDebug(1, ("XmHTML.c: CreateAnchorCursor Start\n"));
898
899 if(HTML_ATTR(anchor_cursor) == None)
900 {
901 Pixmap shape, mask;
902 XColor white_def, black_def;
903 Window window = XtWindow((Widget)html);
904 Display *display = XtDisplay((Widget)html);
905 Screen *screen = XtScreen((Widget)html);
906
907 if(!window)
908 window = RootWindowOfScreen(screen);
909
910 shape = XCreatePixmapFromBitmapData(display, window,
911 (char*)fingers_bits, fingers_width, fingers_height, 1, 0, 1);
912
913 mask = XCreatePixmapFromBitmapData(display, window,
914 (char*)fingers_m_bits, fingers_m_width, fingers_m_height, 1, 0, 1);
915
916 (void)XParseColor(display, TkaGetColormap(html), "white", &white_def);
917
918 (void)XParseColor(display, TkaGetColormap(html), "black", &black_def);
919
920 HTML_ATTR(anchor_cursor) = XCreatePixmapCursor(display, shape, mask,
921 &white_def, &black_def, fingers_x_hot, fingers_y_hot);
922 }
923 _XmHTMLDebug(1, ("XmHTML.c: CreateAnchorCursor End\n"));
924 }
925
926 static void
LowerFormWidgets(XmHTMLWidget html)927 LowerFormWidgets(XmHTMLWidget html)
928 {
929 XmHTMLFormData *form;
930 XmHTMLForm *entry;
931 XmHTMLExtObj *uentry;
932
933 for(form = HTML_ATTR(form_data); form != NULL; form = form->next)
934 {
935 for(entry = form->components; entry != NULL; entry = entry->next)
936 if(entry->w && entry->mapped)
937 XtUnmapWidget(entry->w);
938 }
939 for(uentry = HTML_ATTR(embedded); uentry != NULL; uentry = uentry->next)
940 {
941 if(uentry->w && uentry->mapped)
942 XtUnmapWidget(uentry->w);
943 }
944 }
945
946 void
_XmHTMLRaiseFormWidgets(XmHTMLWidget html)947 _XmHTMLRaiseFormWidgets(XmHTMLWidget html)
948 {
949 XmHTMLFormData *form;
950 XmHTMLForm *entry;
951 XmHTMLExtObj *uentry;
952
953 for(form = HTML_ATTR(form_data); form != NULL; form = form->next)
954 {
955 for(entry = form->components; entry != NULL; entry = entry->next)
956 if(entry->w && entry->mapped)
957 XtMapWidget(entry->w);
958 }
959 for(uentry = HTML_ATTR(embedded); uentry != NULL; uentry = uentry->next)
960 {
961 if(uentry->w && uentry->mapped)
962 XtMapWidget(uentry->w);
963 }
964 }
965
966 /*****
967 * Name: OverrideExposure
968 * Return Type: void
969 * Description: expose event filter when HTML form widgets are being scrolled.
970 * In:
971 * w: unused;
972 * client_..: unused;
973 * event: XEvent info;
974 * continu..: flag to tell X whether or not to propagate this event;
975 * Returns:
976 * nothing.
977 * Note:
978 * this routine is only activated when XmHTML is moving widgets on it's own
979 * display area. It filters out any Exposure events that are generated by
980 * moving these widgets around.
981 *****/
982 static void
OverrideExposure(Widget w,XtPointer client_data,XEvent * event,Boolean * continue_to_dispatch)983 OverrideExposure(Widget w, XtPointer client_data, XEvent *event,
984 Boolean *continue_to_dispatch)
985 {
986 if(event->xany.type == Expose || event->xany.type == GraphicsExpose)
987 {
988 XEvent expose;
989
990 #ifdef DEBUG
991 _XmHTMLDebug(1, ("XmHTML.c: OverrideExposure, ignoring %s event\n"
992 "\t(x = %i, y = %i, width = %i, height = %i)\n",
993 (event->xany.type == Expose ? "Expose" : "GraphicsExpose"),
994 event->xexpose.x, event->xexpose.y,
995 event->xexpose.width, event->xexpose.height));
996 if(event->xany.type == GraphicsExpose &&
997 NULL != XtWindowToWidget(XtDisplay(w),
998 event->xgraphicsexpose.drawable))
999 _XmHTMLDebug(1, ("XmHTML.c: OverrideExposure, event was destined "
1000 "for %s (%i events still pending)\n",
1001 XtName(XtWindowToWidget(XtDisplay(w),
1002 event->xgraphicsexpose.drawable)),
1003 event->xgraphicsexpose.count));
1004 #endif
1005 /*****
1006 * A GraphicsExpose event is generated for the entire area covered
1007 * by the form widgets when scrolling: the CopyArea call in
1008 * _XmHTMLMoveToPos fails 'cause the source is overlapped by
1009 * the form widgets. Therefore we must allow this event or text
1010 * will disappear.
1011 *****/
1012 if(event->xany.type == GraphicsExpose &&
1013 event->xgraphicsexpose.count == 0)
1014 return;
1015
1016 /* Gather all other pending events and disallow continuation */
1017 while((XCheckWindowEvent(XtDisplay(w), XtWindow(w), ExposureMask,
1018 &expose)) == True)
1019 ;
1020 *continue_to_dispatch = False;
1021 }
1022 #ifdef DEBUG
1023 else
1024 _XmHTMLDebug(1, ("XmHTML.c: OverrideExposure, wrong event %i\n",
1025 (int)(event->xany.type)));
1026 #endif
1027 }
1028
1029 /*****
1030 * Name: _XmHTMLScrollForm
1031 * Return Type: void
1032 * Description: scrolls all widgets of all forms in the current document.
1033 * In:
1034 * html: XmHTML widget id
1035 * Returns:
1036 * nothing.
1037 *****/
1038 void
_XmHTMLScrollForm(XmHTMLWidget html)1039 _XmHTMLScrollForm(XmHTMLWidget html)
1040 {
1041 int x, y, xs, ys;
1042 XmHTMLFormData *form;
1043 XmHTMLForm *entry;
1044 Boolean did_anything = False;
1045 ToolkitAbstraction *tka = HTML_ATTR(tka);
1046
1047 #ifndef UNMAP_FORMS
1048 Widget *forms;
1049 Cardinal nforms;
1050
1051 _XmHTMLDebug(1, ("XmHTML.c: _XmHTMLScrollForm, Start\n"));
1052
1053 XtVaGetValues(HTML_ATTR(work_area),
1054 XmNchildren, &forms,
1055 XmNnumChildren, &nforms,
1056 NULL);
1057
1058 while(nforms--)
1059 {
1060 /* compute new widget position */
1061 xs = ATTR_CORE(forms[nforms],x) - HTML_ATTR(scroll_x);
1062 ys = ATTR_CORE(forms[nforms],y) - HTML_ATTR(scroll_y);
1063 tka->MoveWidget(forms[nforms],
1064 ATTR_CORE(forms[nforms],x) + xs,
1065 ATTR_CORE(forms[nforms],y) + ys);
1066 }
1067
1068 #else
1069 /*****
1070 * To prevent the X exposure handling from going haywire, we simply
1071 * override *any* exposure events generated by moving the widgets
1072 * around.
1073 *****/
1074 XtInsertEventHandler(HTML_ATTR(work_area), ExposureMask, True,
1075 (XtEventHandler)OverrideExposure, NULL, XtListHead);
1076
1077 for(form = HTML_ATTR(form_data); form != NULL; form = form->next)
1078 {
1079 for(entry = form->components; entry != NULL; entry = entry->next)
1080 {
1081 if(entry->w)
1082 {
1083 /* save current widget position */
1084 x = entry->x;
1085 y = entry->y;
1086
1087 /* compute new widget position */
1088 xs = entry->data->x - HTML_ATTR(scroll_x);
1089 ys = entry->data->y - HTML_ATTR(scroll_y);
1090
1091 /* check if we need to show this widget */
1092 if(xs + entry->width > 0 && xs < HTML_ATTR(work_width) &&
1093 ys + entry->height > 0 && ys < HTML_ATTR(work_height))
1094 {
1095 _XmHTMLDebug(1, ("XmHTML.c: _XmHTMLScrollForm, moving "
1096 "widget %s from %ix%i to %ix%i (wxh = %ix%i)\n",
1097 entry->name, entry->x, entry->y, xs, ys,
1098 entry->width, entry->height));
1099
1100 /* save new widget position */
1101 entry->x = xs;
1102 entry->y = ys;
1103
1104 /* and move to it */
1105 tka->MoveWidget(entry->w, xs, ys);
1106
1107 /* show it */
1108 if(!entry->mapped)
1109 {
1110 tka->SetMappedWhenManaged(entry->w, True);
1111 entry->mapped = True;
1112 }
1113 /****
1114 * FIXME!!
1115 * This code is terribly slow for pages with a great deal of form widgets
1116 * in them.
1117 ****/
1118 #ifdef UNMAP_FORMS_AND_REFRESH
1119 /* restore background at previously obscured position */
1120 _XmHTMLRefresh(html, x, y, entry->width, entry->height);
1121 #endif
1122
1123 did_anything = True;
1124 }
1125 else
1126 {
1127 /* hide by unmapping it */
1128 if(entry->mapped)
1129 {
1130 _XmHTMLDebug(1, ("XmHTML.c: _XmHTMLScrollForm, hiding "
1131 "widget %s\n", entry->name));
1132
1133 tka->SetMappedWhenManaged(entry->w, False);
1134 entry->mapped = False;
1135 /****
1136 * FIXME!!
1137 * This code is terribly slow for pages with a great deal of form widgets
1138 * in them.
1139 ****/
1140 #ifdef UNMAP_FORMS_AND_REFRESH
1141 /* restore background at previously obscured position */
1142 _XmHTMLRefresh(html, x, y, entry->width, entry->height);
1143 #endif
1144
1145 did_anything = True;
1146 }
1147 }
1148 }
1149 }
1150 }
1151 XtRemoveEventHandler(HTML_ATTR(work_area), ExposureMask, True,
1152 (XtEventHandler)OverrideExposure, NULL);
1153 #endif
1154 /* only do this if we actually did something */
1155 if(did_anything)
1156 {
1157 tka->Sync(tka->dpy, False);
1158 XmUpdateDisplay((Widget)html);
1159 }
1160
1161 _XmHTMLDebug(1, ("XmHTML.c: _XmHTMLScrollForm, End\n"));
1162 }
1163
1164 /*****
1165 * Name: _XmHTMLScrollObjects
1166 * Return Type: void
1167 * Description: scrolls all external objects forms in the current document.
1168 * In:
1169 * html: XmHTML widget id
1170 * Returns:
1171 * nothing.
1172 *****/
1173 void
_XmHTMLScrollObjects(XmHTMLWidget html)1174 _XmHTMLScrollObjects(XmHTMLWidget html)
1175 {
1176 int x, y, xs, ys;
1177 XmHTMLExtObj *entry;
1178 Boolean did_anything = False;
1179 ToolkitAbstraction *tka = HTML_ATTR(tka);
1180
1181 #ifndef UNMAP_FORMS
1182 Widget *forms;
1183 Cardinal nforms;
1184
1185 _XmHTMLDebug(1, ("XmHTML.c: _XmHTMLScrollObjects, Start\n"));
1186
1187 XtVaGetValues(HTML_ATTR(work_area),
1188 XmNchildren, &forms,
1189 XmNnumChildren, &nforms,
1190 NULL);
1191
1192 while(nforms--)
1193 {
1194 /* compute new widget position */
1195 xs = ATTR_CORE(forms[nforms],x) - HTML_ATTR(scroll_x);
1196 ys = ATTR_CORE(forms[nforms],y) - HTML_ATTR(scroll_y);
1197 tka->MoveWidget(forms[nforms],
1198 ATTR_CORE(forms[nforms],x) + xs,
1199 ATTR_CORE(forms[nforms],y) + ys);
1200 }
1201
1202 #else
1203 /*****
1204 * To prevent the X exposure handling from going haywire, we simply
1205 * override *any* exposure events generated by moving the widgets
1206 * around.
1207 *****/
1208 XtInsertEventHandler(HTML_ATTR(work_area), ExposureMask, True,
1209 (XtEventHandler)OverrideExposure, NULL, XtListHead);
1210
1211 for(entry = HTML_ATTR(embedded); entry != NULL; entry = entry->next)
1212 {
1213 if(entry->w)
1214 {
1215 /* save current widget position */
1216 x = entry->x;
1217 y = entry->y;
1218
1219 /* compute new widget position */
1220 xs = entry->data->x - HTML_ATTR(scroll_x);
1221 ys = entry->data->y - HTML_ATTR(scroll_y);
1222
1223 /* check if we need to show this widget */
1224 if(xs + entry->width > 0 && xs < HTML_ATTR(work_width) &&
1225 ys + entry->height > 0 && ys < HTML_ATTR(work_height))
1226 {
1227 _XmHTMLDebug(1, ("XmHTML.c: _XmHTMLScrollForm, moving "
1228 "widget %s from %ix%i to %ix%i (wxh = %ix%i)\n",
1229 entry->name, entry->x, entry->y, xs, ys,
1230 entry->width, entry->height));
1231
1232 /* save new widget position */
1233 entry->x = xs;
1234 entry->y = ys;
1235
1236 /* and move to it */
1237 tka->MoveWidget(entry->w, xs, ys);
1238
1239 /* show it */
1240 if(!entry->mapped)
1241 {
1242 tka->SetMappedWhenManaged(entry->w, True);
1243 entry->mapped = True;
1244 }
1245 /****
1246 * FIXME!!
1247 * This code is terribly slow for pages with a great deal of form widgets
1248 * in them.
1249 ****/
1250 #ifdef UNMAP_FORMS_AND_REFRESH
1251 /* restore background at previously obscured position */
1252 _XmHTMLRefresh(html, x, y, entry->width, entry->height);
1253 #endif
1254
1255 did_anything = True;
1256 }
1257 else
1258 {
1259 /* hide by unmapping it */
1260 if(entry->mapped)
1261 {
1262 _XmHTMLDebug(1, ("XmHTML.c: _XmHTMLScrollForm, hiding "
1263 "widget %s\n", entry->name));
1264
1265 tka->SetMappedWhenManaged(entry->w, False);
1266 entry->mapped = False;
1267 /****
1268 * FIXME!!
1269 * This code is terribly slow for pages with a great deal of form widgets
1270 * in them.
1271 ****/
1272 #ifdef UNMAP_FORMS_AND_REFRESH
1273 /* restore background at previously obscured position */
1274 _XmHTMLRefresh(html, x, y, entry->width, entry->height);
1275 #endif
1276
1277 did_anything = True;
1278 }
1279 }
1280 }
1281 }
1282 XtRemoveEventHandler(HTML_ATTR(work_area), ExposureMask, True,
1283 (XtEventHandler)OverrideExposure, NULL);
1284 #endif
1285 /* only do this if we actually did something */
1286 if(did_anything)
1287 {
1288 tka->Sync(tka->dpy, False);
1289 XmUpdateDisplay((Widget)html);
1290 }
1291
1292 _XmHTMLDebug(1, ("XmHTML.c: _XmHTMLScrollForm, End\n"));
1293 }
1294
1295 /*****
1296 * Name: ScrollCB
1297 * Return Type: void
1298 * Description: callback procedure for scrollbar movement
1299 * In:
1300 * w: originator
1301 * arg1: client_data, in this case a XmHTMLWidget
1302 * arg2: event specific callback structure.
1303 * Returns:
1304 * nothing
1305 *****/
1306 static void
ScrollCB(Widget w,XtPointer arg1,XtPointer arg2)1307 ScrollCB(Widget w, XtPointer arg1, XtPointer arg2)
1308 {
1309 XmScrollBarCallbackStruct *cbs = (XmScrollBarCallbackStruct *)arg2;
1310 XEvent *event = cbs->event;
1311 XmHTMLWidget html = (XmHTMLWidget)arg1;
1312
1313 /* Fix 05/27/98-01, eb */
1314 if(event && event->type == MotionNotify && !HTML_ATTR(smooth_scroll))
1315 {
1316 /****
1317 * Try to collapse motion events.
1318 * In case there are some other motion events in the queue,
1319 * so ignore this one and let the latter one do the job.
1320 *****/
1321 XEvent next_event ;
1322 Display *dpy = HTML_ATTR(tka)->dpy ;
1323
1324 /****
1325 * Look for a would-be MotionNotify event in the queue.
1326 * Use XCheckTypedWindowEvent() instead of XWindowEvent(), as
1327 * XWindowEvent() blocks if there is no event in the queue.
1328 * The only drawback is that the event is withdrawn from the queue,
1329 * and thus we have to put it back.
1330 *****/
1331 if(XCheckTypedWindowEvent(dpy, XtWindow(w), event->type, &next_event))
1332 {
1333 /* if found, put the event back in the queue and return */
1334 XPutBackEvent(dpy, &next_event);
1335 _XmHTMLDebug(1, ("XmHTML.c: ScrollCB, pushed back an outstanding "
1336 "MotionNotify event.\n"));
1337 return ;
1338 }
1339 }
1340
1341 _XmHTMLDebug(1, ("XmHTML.c: ScrollCB, calling _XmHTMLMoveToPos\n"));
1342 _XmHTMLMoveToPos(w, (XmHTMLWidget)arg1, cbs->value);
1343 }
1344
1345 /*****
1346 * Name: CreateHTMLWidget
1347 * Return Type: void
1348 * Description: creates the HTML widget
1349 * The actual area we use to draw into is a drawingAreaWidget.
1350 * In:
1351 * html: widget to be created.
1352 * Returns:
1353 * nothing
1354 *****/
1355 static void
CreateHTMLWidget(XmHTMLWidget html)1356 CreateHTMLWidget(XmHTMLWidget html)
1357 {
1358 Arg args[15];
1359 Dimension argc = 0;
1360 int vsb_width, hsb_height;
1361 static XtTranslations trans = NULL;
1362
1363 _XmHTMLDebug(1, ("XmHTML.c: CreateHTMLWidget Start\n"));
1364
1365 /* Check if user provided a work area */
1366 if(HTML_ATTR(work_area) == NULL)
1367 {
1368 HTML_ATTR(work_area) = XtVaCreateWidget("workWindow",
1369 xmDrawingAreaWidgetClass, (Widget)html,
1370 XmNwidth, CORE_ATTR(width),
1371 XmNheight, CORE_ATTR(height),
1372 NULL);
1373 }
1374 /* catch all exposure events on the render window */
1375 XtAddEventHandler((Widget)HTML_ATTR(work_area), ExposureMask, True,
1376 (XtEventHandler)DrawRedisplay, (XtPointer)html);
1377
1378 /* we want to know when to handle GraphicsExpose events */
1379 XtAddEventHandler((Widget)HTML_ATTR(work_area), VisibilityChangeMask, True,
1380 (XtEventHandler)VisibilityHandler, (XtPointer)html);
1381
1382 XtAddEventHandler((Widget)html, SubstructureNotifyMask,
1383 True, (XtEventHandler)Mapped, (XtPointer)html);
1384
1385 /*
1386 * For some reason, Motif fucks up the original action list, so we
1387 * need to use a fallback copy instead.
1388 * Crash happens in XrmStringToQuark().
1389 */
1390 XtAppAddActions(XtWidgetToApplicationContext(HTML_ATTR(work_area)),
1391 spareActions, XtNumber(spareActions));
1392
1393 /* add translations for the actions */
1394 if(trans == NULL)
1395 trans = XtParseTranslationTable(translations);
1396 XtSetArg(args[0], XtNtranslations, trans);
1397 XtSetValues(HTML_ATTR(work_area), args, 1);
1398
1399 argc = 0;
1400 XtManageChild(HTML_ATTR(work_area));
1401
1402 if(HTML_ATTR(vsb) == NULL)
1403 {
1404 argc = 0;
1405 XtSetArg(args[argc], XmNorientation, XmVERTICAL); argc++;
1406 XtSetArg(args[argc], XmNrepeatDelay, HTML_ATTR(repeat_delay)); argc++;
1407 /* make them a little bit more responsive */
1408 XtSetArg(args[argc], XmNinitialDelay, 100); argc++;
1409 HTML_ATTR(vsb) = XtCreateWidget("verticalScrollBar",
1410 xmScrollBarWidgetClass, (Widget)html, args, argc);
1411 }
1412 XtManageChild(HTML_ATTR(vsb));
1413 /* Catch vertical scrollbar movement */
1414 XtAddCallback(HTML_ATTR(vsb), XmNvalueChangedCallback,
1415 (XtCallbackProc)ScrollCB, (XtPointer)html);
1416 XtAddCallback(HTML_ATTR(vsb), XmNdragCallback,
1417 (XtCallbackProc)ScrollCB, (XtPointer)html);
1418
1419 if(HTML_ATTR(hsb) == NULL)
1420 {
1421 argc = 0;
1422 XtSetArg(args[argc], XmNorientation, XmHORIZONTAL); argc++;
1423 XtSetArg(args[argc], XmNrepeatDelay, HTML_ATTR(repeat_delay)); argc++;
1424 /* make them a little bit more responsive */
1425 XtSetArg(args[argc], XmNinitialDelay, 100); argc++;
1426 HTML_ATTR(hsb) = XtCreateWidget("horizontalScrollBar",
1427 xmScrollBarWidgetClass, (Widget)html, args, argc);
1428 }
1429 XtManageChild(HTML_ATTR(hsb));
1430 /* Catch horizontal scrollbar movement */
1431 XtAddCallback(HTML_ATTR(hsb), XmNvalueChangedCallback,
1432 (XtCallbackProc)ScrollCB, (XtPointer)html);
1433 XtAddCallback(HTML_ATTR(hsb), XmNdragCallback,
1434 (XtCallbackProc)ScrollCB, (XtPointer)html);
1435
1436 /*
1437 * subtract margin_width once to minimize number of calcs in
1438 * the paint routines: every thing rendered starts at an x position
1439 * of margin_width.
1440 */
1441 _XmHTMLGetScrollDim(html, &hsb_height, &vsb_width);
1442
1443 HTML_ATTR(work_width) = CORE_ATTR(width) - HTML_ATTR(margin_width) -
1444 vsb_width;
1445 HTML_ATTR(work_height)= CORE_ATTR(height);
1446
1447 /* store window of *drawingarea* in the toolkit abstraction */
1448 XmHTMLTkaSetDrawable(HTML_ATTR(tka),
1449 XtWindow(HTML_ATTR(work_area)));
1450
1451 _XmHTMLDebug(1, ("XmHTML.c: CreateHTMLWidget End\n"));
1452 return;
1453 }
1454
1455 /*****
1456 * Name: _XmHTMLGetScrollDim
1457 * Return Type: void
1458 * Description: retrieves width & height of the scrollbars
1459 * In:
1460 * html: XmHTMLWidget for which to retrieve these values
1461 * hsb_height: thickness of horizontal scrollbar, filled upon return
1462 * vsb_width: thickness of vertical scrollbar, filled upon return
1463 * Returns:
1464 * nothing
1465 * Note:
1466 * I had a nicely working caching version of this routine under Linux &
1467 * Motif 2.0.1, but under HPUX with 1.2.0 this never worked. This does.
1468 *****/
1469 void
_XmHTMLGetScrollDim(XmHTMLWidget html,int * hsb_height,int * vsb_width)1470 _XmHTMLGetScrollDim(XmHTMLWidget html, int *hsb_height, int *vsb_width)
1471 {
1472 Arg args[1];
1473 Dimension height = 0, width = 0;
1474
1475 if(HTML_ATTR(hsb))
1476 {
1477 #ifdef NO_XLIB_ILLEGAL_ACCESS
1478 XtSetArg(args[0], XmNheight, &height);
1479 XtGetValues(HTML_ATTR(hsb), args, 1);
1480 #else
1481 height = ATTR_CORE(HTML_ATTR(hsb), height);
1482 #endif
1483
1484 /*
1485 * Sanity check if the scrollbar dimensions exceed the widget dimensions
1486 * Not doing this would lead to X Protocol errors whenever text is set
1487 * into the widget: the size of the workArea will be less than or equal
1488 * to zero when scrollbars are required.
1489 * We always need to do this check since it's possible that some
1490 * user has been playing with the dimensions of the scrollbars.
1491 */
1492 if(height >= CORE_ATTR(height))
1493 {
1494 _XmHTMLWarning(__WFUNC__(HTML_ATTR(hsb), "_XmHTMLGetScrollDim"),
1495 XMHTML_MSG_11, "Height", "horizontal", height, "height",
1496 CORE_ATTR(height), 15);
1497 height = 15;
1498 XtSetArg(args[0], XmNheight, height);
1499 XtSetValues(HTML_ATTR(hsb), args, 1);
1500 }
1501 }
1502
1503 if(HTML_ATTR(vsb))
1504 {
1505 #ifdef NO_XLIB_ILLEGAL_ACCESS
1506 XtSetArg(args[0], XmNwidth, &width);
1507 XtGetValues(HTML_ATTR(vsb), args, 1);
1508 #else
1509 width = ATTR_CORE(HTML_ATTR(vsb), width);
1510 #endif
1511
1512 if(width >= CORE_ATTR(width))
1513 {
1514 _XmHTMLWarning(__WFUNC__(HTML_ATTR(vsb), "_XmHTMLGetScrollDim"),
1515 XMHTML_MSG_11, "Width", "vertical", width, "width",
1516 CORE_ATTR(width), 15);
1517 width = 15;
1518 XtSetArg(args[0], XmNwidth, width);
1519 XtSetValues(HTML_ATTR(vsb), args, 1);
1520 }
1521 }
1522
1523 _XmHTMLDebug(1, ("XmHTML.c: _XmHTMLGetScrollDim; height = %i, width = %i\n",
1524 height, width));
1525
1526 *hsb_height = height;
1527 *vsb_width = width;
1528 }
1529
1530 /*****
1531 * Name: _XmHTMLCheckScrollBars
1532 * Return Type: void
1533 * Description: (re)configures scrollbars
1534 * In:
1535 * html: HTML widget to configure
1536 * Returns:
1537 * nothing.
1538 *****/
1539 void
_XmHTMLCheckScrollBars(XmHTMLWidget html)1540 _XmHTMLCheckScrollBars(XmHTMLWidget html)
1541 {
1542 int dx, dy, hsb_height, vsb_width, st;
1543 Boolean hsb_on_top, vsb_on_left;
1544 /* forced display of scrollbars: XmSTATIC or frames with scrolling = yes */
1545 Boolean force_vsb = False, force_hsb = False;
1546 Arg args[10];
1547 Dimension argc = 0;
1548 ToolkitAbstraction *tka = HTML_ATTR(tka);
1549
1550 _XmHTMLDebug(1, ("XmHTML.c: _XmHTMLCheckScrollBars, start\n"));
1551
1552 /* don't do a thing if we aren't managed yet */
1553 if(!(tka->IsManaged((Widget)html)))
1554 return;
1555
1556 /* Initial work area offset */
1557 st = dx = dy = MGR_ATTR(shadow_thickness);
1558 _XmHTMLGetScrollDim(html, &hsb_height, &vsb_width);
1559
1560 /* check if we need a vertical scrollbar */
1561 if(HTML_ATTR(formatted_height) < CORE_ATTR(height))
1562 {
1563 HTML_ATTR(needs_vsb) = False;
1564 /* don't forget! */
1565 HTML_ATTR(scroll_y) = 0;
1566 tka->UnmanageChild(HTML_ATTR(vsb));
1567 }
1568 else
1569 HTML_ATTR(needs_vsb) = True;
1570
1571 /* add a scrollbar if we must and it isn't already here */
1572 if(!HTML_ATTR(needs_vsb) && HTML_ATTR(sb_policy) == XmSTATIC)
1573 {
1574 HTML_ATTR(needs_vsb) = True;
1575 force_vsb = True;
1576 }
1577
1578 /*
1579 * check if we need a horizontal scrollbar. If we have a vertical
1580 * scrollbar, we must add it's width or text might be lost.
1581 */
1582 if(HTML_ATTR(formatted_width) < CORE_ATTR(width) -
1583 (HTML_ATTR(needs_vsb) ? vsb_width : 0)) /* fix 04/27/97-01, kdh */
1584 {
1585 HTML_ATTR(needs_hsb) = False;
1586 /* don't forget! */
1587 HTML_ATTR(scroll_x) = 0;
1588 tka->UnmanageChild(HTML_ATTR(hsb));
1589 }
1590 else
1591 HTML_ATTR(needs_hsb) = True;
1592
1593 /* add a scrollbar if we must and it isn't already here */
1594 if(!HTML_ATTR(needs_hsb) && HTML_ATTR(sb_policy) == XmSTATIC)
1595 {
1596 HTML_ATTR(needs_hsb) = True;
1597 force_hsb = True;
1598 }
1599
1600 /* if this is a frame, check what type of scrolling is requested */
1601 if(HTML_ATTR(is_frame))
1602 {
1603 if(HTML_ATTR(scroll_type) == FRAME_SCROLL_NONE)
1604 {
1605 HTML_ATTR(needs_hsb) = False;
1606 HTML_ATTR(needs_vsb) = False;
1607 HTML_ATTR(scroll_x) = 0;
1608 HTML_ATTR(scroll_y) = 0;
1609 tka->UnmanageChild(HTML_ATTR(hsb));
1610 tka->UnmanageChild(HTML_ATTR(vsb));
1611 }
1612 else if(HTML_ATTR(scroll_type) == FRAME_SCROLL_YES)
1613 {
1614 HTML_ATTR(needs_vsb) = True;
1615 HTML_ATTR(needs_hsb) = True;
1616 force_vsb = True;
1617 force_hsb = True;
1618 }
1619 /* else scrolling is auto, just proceed */
1620 }
1621
1622 /* return if we don't need any scrollbars */
1623 if(!HTML_ATTR(needs_hsb) && !HTML_ATTR(needs_vsb))
1624 {
1625 _XmHTMLDebug(1, ("XmHTML.c: _XmHTMLCheckScrollBars, end, no bars "
1626 "needed.\n"));
1627 /* move work_area to it's correct position */
1628 tka->ConfigureWidget(HTML_ATTR(work_area), dx, dy, CORE_ATTR(width),
1629 CORE_ATTR(height), ATTR_CORE(HTML_ATTR(work_area), border_width));
1630 return;
1631 }
1632
1633 /* see if we have to put hsb on top */
1634 hsb_on_top = (HTML_ATTR(sb_placement) == XmTOP_LEFT ||
1635 HTML_ATTR(sb_placement) == XmTOP_RIGHT);
1636 /* see if we have top put vsb on left */
1637 vsb_on_left = (HTML_ATTR(sb_placement) == XmTOP_LEFT ||
1638 HTML_ATTR(sb_placement) == XmBOTTOM_LEFT);
1639
1640 /* horizontal sb on top */
1641 if(HTML_ATTR(needs_hsb) && hsb_on_top)
1642 dy += hsb_height;
1643
1644 /* vertical sb on left */
1645 if(HTML_ATTR(needs_vsb) && vsb_on_left)
1646 dx += vsb_width;
1647
1648 /* move work_area to it's correct position */
1649 tka->MoveWidget(HTML_ATTR(work_area), dx, dy);
1650
1651 /* See what space we have to reserve for the scrollbars */
1652 if(HTML_ATTR(needs_hsb) && hsb_on_top == False)
1653 dy += hsb_height;
1654 if(HTML_ATTR(needs_vsb) && vsb_on_left == False)
1655 dx += vsb_width;
1656
1657 tka->ResizeWidget(HTML_ATTR(work_area),
1658 CORE_ATTR(width) - dx, CORE_ATTR(height) - dy,
1659 ATTR_CORE(HTML_ATTR(work_area), border_width));
1660
1661 if(HTML_ATTR(needs_hsb) == True)
1662 {
1663 int pinc;
1664
1665 _XmHTMLDebug(1, ("XmHTML.c: _XmHTMLCheckScrollBars, setting hsb\n"));
1666
1667 /* Set hsb size; adjust x-position if we have a vsb */
1668 dx = (HTML_ATTR(needs_vsb) ? vsb_width : 0);
1669 tka->ResizeWidget(HTML_ATTR(hsb),
1670 CORE_ATTR(width) - dx - 2*st,
1671 ATTR_CORE(HTML_ATTR(hsb), height),
1672 ATTR_CORE(HTML_ATTR(hsb), border_width));
1673
1674 /* pageIncrement == sliderSize */
1675 pinc = HTML_ATTR(work_width) - 2*(HTML_ATTR(default_font) ?
1676 HTML_ATTR(default_font)->m_width :
1677 XmHTML_HORIZONTAL_SCROLL_INCREMENT);
1678 /* sanity check */
1679 if(pinc < 1)
1680 pinc = XmHTML_HORIZONTAL_SCROLL_INCREMENT;
1681
1682 /* adjust horizontal scroll if necessary */
1683 if(HTML_ATTR(scroll_x) > HTML_ATTR(formatted_width) - pinc)
1684 HTML_ATTR(scroll_x) = HTML_ATTR(formatted_width) - pinc;
1685 /* fix 01/23/97-02, kdh */
1686
1687 /*
1688 * Adjust if a horizontal scrollbar has been forced
1689 * (can only happen for frames with scrolling = yes)
1690 */
1691 if(force_hsb && pinc > HTML_ATTR(formatted_width))
1692 {
1693 pinc = HTML_ATTR(formatted_width);
1694 HTML_ATTR(scroll_x) = 0;
1695 }
1696
1697 argc = 0;
1698 XtSetArg(args[argc], XmNminimum, 0); argc++;
1699 XtSetArg(args[argc], XmNmaximum, HTML_ATTR(formatted_width)); argc++;
1700 XtSetArg(args[argc], XmNvalue, HTML_ATTR(scroll_x)); argc++;
1701 XtSetArg(args[argc], XmNsliderSize, pinc); argc++;
1702 XtSetArg(args[argc], XmNincrement, (HTML_ATTR(default_font) ?
1703 HTML_ATTR(default_font)->m_width :
1704 XmHTML_HORIZONTAL_SCROLL_INCREMENT));
1705 argc++;
1706 XtSetArg(args[argc], XmNpageIncrement, pinc); argc++;
1707 XtSetValues(HTML_ATTR(hsb), args, argc);
1708
1709 /* adjust x-position if vsb is on left */
1710 dx = (HTML_ATTR(needs_vsb) && vsb_on_left ? vsb_width : 0);
1711
1712 /* place it */
1713 if(hsb_on_top)
1714 tka->MoveWidget(HTML_ATTR(hsb), dx, 0);
1715 else
1716 tka->MoveWidget(HTML_ATTR(hsb), dx,
1717 (CORE_ATTR(height) - hsb_height));
1718 }
1719 if(HTML_ATTR(needs_vsb) == True)
1720 {
1721 int pinc;
1722
1723 _XmHTMLDebug(1, ("XmHTML.c: _XmHTMLCheckScrollBars, setting vsb\n"));
1724
1725 /* Set vsb size; adjust y-position if we have a hsb */
1726 dy = (HTML_ATTR(needs_hsb) ? hsb_height : 0);
1727 tka->ResizeWidget(HTML_ATTR(vsb),
1728 ATTR_CORE(HTML_ATTR(vsb), width),
1729 CORE_ATTR(height) - dy - 2*st,
1730 ATTR_CORE(HTML_ATTR(vsb), border_width));
1731
1732 /* pageIncrement == sliderSize */
1733 pinc = HTML_ATTR(work_height) - 2*(HTML_ATTR(default_font) ?
1734 HTML_ATTR(default_font)->height : XmHTML_VERTICAL_SCROLL_INCREMENT);
1735 /* sanity check */
1736 if(pinc < 1)
1737 pinc = XmHTML_VERTICAL_SCROLL_INCREMENT;
1738
1739 /* adjust vertical scroll if necessary */
1740 if(HTML_ATTR(scroll_y) > HTML_ATTR(formatted_height) - pinc)
1741 HTML_ATTR(scroll_y) = HTML_ATTR(formatted_height) - pinc;
1742
1743 /*
1744 * Adjust if a vertical scrollbar has been forced
1745 * (can only happen if scrollBarDisplayPolicy == XmSTATIC)
1746 */
1747 if(force_vsb && pinc > HTML_ATTR(formatted_height))
1748 {
1749 pinc = HTML_ATTR(formatted_height);
1750 HTML_ATTR(scroll_y) = 0;
1751 }
1752
1753 argc = 0;
1754 XtSetArg(args[argc], XmNminimum, 0); argc++;
1755 XtSetArg(args[argc], XmNmaximum, HTML_ATTR(formatted_height)); argc++;
1756 XtSetArg(args[argc], XmNvalue, HTML_ATTR(scroll_y)); argc++;
1757 XtSetArg(args[argc], XmNsliderSize, pinc); argc++;
1758 XtSetArg(args[argc], XmNincrement, (HTML_ATTR(default_font) ?
1759 HTML_ATTR(default_font)->height :
1760 XmHTML_VERTICAL_SCROLL_INCREMENT)); argc++;
1761 XtSetArg(args[argc], XmNpageIncrement, pinc); argc++;
1762 XtSetValues(HTML_ATTR(vsb), args, argc);
1763
1764 /* adjust y-position if hsb is on top */
1765 dy = (HTML_ATTR(needs_hsb) && hsb_on_top ? hsb_height : 0);
1766
1767 /* place it */
1768 if(vsb_on_left)
1769 tka->MoveWidget(HTML_ATTR(vsb), 0, dy);
1770 else
1771 tka->MoveWidget(HTML_ATTR(vsb), (CORE_ATTR(width)- vsb_width), dy);
1772 }
1773 _XmHTMLDebug(1, ("XmHTML.c: _XmHTMLCheckScrollBars, end\n"));
1774 }
1775
1776 /*****
1777 * Name: Mapped
1778 * Return Type: void
1779 * Description: event handler for CreateNotify events.
1780 * In:
1781 * w: owner of this eventhandler
1782 * html: client data, XmHTMLWidget to which w belongs
1783 * event: CreateNotify event data
1784 * Returns:
1785 * nothing
1786 * Note:
1787 * We want to be notified when the window gets created. Motif seems to block
1788 * the CreateNotify event, so we work with the MapNotify event. This is
1789 * required to get the text rendered correctly when it has been
1790 * set inside the Xt[Va]Create[Managed]Widget and before XtRealizeWidget
1791 * has been called: we do not have a window yet and thus no valid gc. Bad
1792 * things happen otherwise.
1793 *****/
1794 /*ARGSUSED*/
1795 static void
Mapped(Widget w,XmHTMLWidget html,XEvent * event)1796 Mapped(Widget w, XmHTMLWidget html, XEvent *event)
1797 {
1798 /* wrong event, just return */
1799 if(event->type != MapNotify)
1800 return;
1801
1802 _XmHTMLDebug(1, ("XmHTML.c: Mapped start\n"));
1803
1804 _XmHTMLDebug(1, ("XmHTML.c: Mapped, work area dimensions: %ix%i\n",
1805 HTML_ATTR(work_width), HTML_ATTR(work_height)));
1806
1807 /* store window of *drawingarea* in the toolkit abstraction */
1808 XmHTMLTkaSetDrawable(HTML_ATTR(tka), XtWindow(HTML_ATTR(work_area)));
1809
1810 /* create a gc */
1811 _XmHTMLCheckGC(html);
1812
1813 /* save new height */
1814 HTML_ATTR(work_height) = CORE_ATTR(height);
1815 /* and width as well, fix 10/26/97-01, kdh */
1816 HTML_ATTR(work_width) = CORE_ATTR(width) - HTML_ATTR(margin_width) -
1817 ATTR_CORE(HTML_ATTR(vsb), width);
1818
1819 _XmHTMLDebug(1, ("XmHTML.c: Mapped, new work area dimensions: %ix%i\n",
1820 HTML_ATTR(work_width), HTML_ATTR(work_height)));
1821
1822 /* configure the scrollbars, will also resize work_area */
1823 _XmHTMLCheckScrollBars(html);
1824
1825 _XmHTMLLayout(html);
1826
1827 /* no longer needed now, so remove it */
1828 XtRemoveEventHandler(w, SubstructureNotifyMask, True,
1829 (XtEventHandler)Mapped, (XtPointer)html);
1830
1831 /*****
1832 * IRIX seems to have problems with this. Trigger a Redisplay by
1833 * clearing the entire area.
1834 *****/
1835 #ifdef __sgi
1836 _XmHTMLClearArea(html, 0, 0, CORE_ATTR(width), CORE_ATTR(height));
1837 #endif
1838
1839 _XmHTMLDebug(1, ("XmHTML.c: Mapped end.\n"));
1840 }
1841
1842 /*****
1843 * Name: VisibilityHandler
1844 * Return Type: void
1845 * Description: VisibilityChangeMask event handler. Used to store the
1846 * visibility state of the work_area so we know when to
1847 * serve or ignore GraphicsExpose requests: if we're partially
1848 * obscured we need to respond to them, in all other cases we
1849 * can ignore them.
1850 * In:
1851 * w: owner of this eventhandler
1852 * html: client data, XmHTMLWidget to which w belongs
1853 * event: VisibilityNotify event data
1854 * Returns:
1855 * nothing, but sets the visibility field in the widget's instance structure.
1856 *****/
1857 /*ARGSUSED*/
1858 static void
VisibilityHandler(Widget w,XmHTMLWidget html,XEvent * event)1859 VisibilityHandler(Widget w, XmHTMLWidget html, XEvent *event)
1860 {
1861 if(event->type != VisibilityNotify)
1862 return;
1863
1864 _XmHTMLDebug(1, ("XmHTML.c: VisibilityHandler start\n"));
1865
1866 HTML_ATTR(visibility) = event->xvisibility.state;
1867
1868 _XmHTMLDebug(1, ("XmHTML.c: VisibilityHandler end\n"));
1869 }
1870
1871 /*****
1872 * Name: _XmHTMLAutoSizeWidget
1873 * Return Type: void
1874 * Description: computes XmHTML's widget dimensions if we have to autosize
1875 * in either direction.
1876 * In:
1877 * html: XmHTMLWidget id
1878 * Returns:
1879 * nothing.
1880 * Note:
1881 * This routine is fairly complicated due to the fact that the dimensions
1882 * of the work area are partly determined by the presence of possible
1883 * scrollbars.
1884 *****/
1885 void
_XmHTMLAutoSizeWidget(XmHTMLWidget html)1886 _XmHTMLAutoSizeWidget(XmHTMLWidget html)
1887 {
1888 int max_w, max_h, width, height, core_w, core_h;
1889 int hsb_height = 0, vsb_width = 0, h_reserved, w_reserved;
1890 Boolean done = False, granted = False, has_vsb = False, has_hsb = False;
1891 Dimension new_h, new_w, width_return, height_return;
1892 ToolkitAbstraction *tka = HTML_ATTR(tka);
1893
1894 /* get dimensions of the scrollbars */
1895 _XmHTMLGetScrollDim(html, &hsb_height, &vsb_width);
1896
1897 /* maximum allowable widget height: 80% of screen height */
1898 max_h = (int)(0.8*tka->height);
1899
1900 /* make a guess at the initial widget width */
1901 max_w = _XmHTMLGetMaxLineLength(html) + 2*HTML_ATTR(margin_width);
1902
1903 /* save original widget dimensions in case our resize request is denied */
1904 core_w = CORE_ATTR(width);
1905 core_h = CORE_ATTR(height);
1906
1907 /* set initial dimensions */
1908 height = (core_h > max_h ? max_h : core_h);
1909 width = max_w;
1910
1911 /*
1912 * Since we are making geometry requests, we need to compute the total
1913 * width and height required to make all text visible.
1914 * If we succeed, we don't require any scrollbars to be present.
1915 * This does complicate things considerably.
1916 * The dimensions of the work area are given by the widget dimensions
1917 * minus possible margins and possible scrollbars.
1918 */
1919 h_reserved = HTML_ATTR(margin_height) + hsb_height;
1920 w_reserved = 2*HTML_ATTR(margin_width) + vsb_width;
1921
1922 do
1923 {
1924 /* work_width *always* includes room for a vertical scrollbar */
1925 HTML_ATTR(work_width) = width - w_reserved;
1926
1927 /* Check if we need to add a vertical scrollbar. */
1928 if(height - h_reserved > max_h)
1929 has_vsb = True;
1930 else /* no vertical scrollbar needed */
1931 has_vsb = False;
1932
1933 _XmHTMLDebug(1, ("XmHTML.c: autoSizeWidget, initial dimension: "
1934 "%ix%i. has_vsb: %s\n", width, height,
1935 has_vsb ? "yes" : "no"));
1936
1937 /* Compute new screen layout. */
1938 _XmHTMLComputeLayout(html);
1939
1940 /*
1941 * We have made a pass on the document, so we know now the formatted
1942 * dimensions. If the formatted width exceeds the maximum allowable
1943 * width, we need to add a horizontal scrollbar, and if the formatted
1944 * height exceeds the maximum allowable height we need to add a
1945 * vertical scrollbar. Order of these checks is important: if a vertical
1946 * scrollbar is present, the width of the vertical scrollbar must be
1947 * added as well.
1948 * formatted_height includes the vertical margin twice.
1949 * formatted_width includes the horizontal margin once.
1950 */
1951
1952 /* higher than available height, need a vertical scrollbar */
1953 if(HTML_ATTR(formatted_height) > max_h)
1954 {
1955 has_vsb = True;
1956 height = max_h;
1957 }
1958 else
1959 {
1960 has_vsb = False;
1961 height = HTML_ATTR(formatted_height);
1962 }
1963
1964 /* wider than available width, need a horizontal scrollbar */
1965 if(HTML_ATTR(formatted_width) + HTML_ATTR(margin_width) > max_w)
1966 {
1967 has_hsb = True;
1968 width = max_w;
1969 }
1970 else
1971 {
1972 has_hsb = False;
1973 width = HTML_ATTR(formatted_width) + HTML_ATTR(margin_width);
1974 }
1975
1976 /* add width of vertical scrollbar if we are to have one */
1977 if(has_vsb)
1978 width += vsb_width;
1979
1980 /*
1981 * With the above checks we *know* width and height are positive
1982 * integers smaller than 2^16 (max value of an unsigned short), so we
1983 * don't have to check for a possible wraparound of the new dimensions.
1984 */
1985 new_h = (Dimension)height;
1986 new_w = (Dimension)width;
1987 width_return = 0;
1988 height_return = 0;
1989
1990 _XmHTMLDebug(1, ("XmHTML.c: autoSizeWidget, geometry request with "
1991 "dimensions: %hix%hi. has_vsb = %s, has_hsb = %s\n", new_w, new_h,
1992 has_vsb ? "yes" : "no", has_hsb ? "yes" : "no"));
1993
1994 /* make the resize request and check return value */
1995 switch(XtMakeResizeRequest((Widget)html, new_w, new_h,
1996 &width_return, &height_return))
1997 {
1998 case XtGeometryAlmost:
1999 /*
2000 * partially granted. Set the returned width and height
2001 * as the new widget dimensions and recompute the
2002 * widget layout. The next time the resizeRequest is made
2003 * it *will* be granted.
2004 */
2005 width = (int)width_return;
2006 height= (int)height_return;
2007 break;
2008 case XtGeometryNo:
2009 /* revert to original widget dimensions */
2010 new_h = core_h;
2011 new_w = core_w;
2012 granted = False;
2013 done = True;
2014 break;
2015 case XtGeometryYes:
2016 /* Resize request was granted. */
2017 granted = True;
2018 done = True;
2019 break;
2020 default: /* not reached, XtGeometryDone is never returned */
2021 done = True;
2022 break;
2023 }
2024 }
2025 while(!done);
2026
2027 CORE_ATTR(width) = new_w;
2028 CORE_ATTR(height) = HTML_ATTR(work_height) = new_h;
2029 /* work_width *always* includes room for a vertical scrollbar */
2030 HTML_ATTR(work_width) = new_w - w_reserved;
2031
2032 /* Make sure scrollbars don't appear when they are not needed. */
2033 if(!has_hsb && granted)
2034 HTML_ATTR(formatted_height) = new_h - HTML_ATTR(margin_height) -
2035 hsb_height - 1;
2036 if(!has_vsb && granted)
2037 HTML_ATTR(formatted_width) = new_w - 1;
2038
2039 /*
2040 * If a vertical scrollbar is present, CheckScrollBars will add a horizontal
2041 * scrollbar if the formatted_width + vsb_width exceeds the widget width.
2042 * To make sure a horizontal scrollbar does not appear when one is not
2043 * needed, we need to adjust the formatted width accordingly.
2044 */
2045 if(has_vsb && granted)
2046 HTML_ATTR(formatted_width) -= vsb_width;
2047
2048 /*
2049 * If our resize request was denied we need to recompute the text
2050 * layout using the original widget dimensions. The previous layout is
2051 * invalid since it used guessed widget dimensions instead of the previous
2052 * dimensions and thus it will look bad if we don't recompute it.
2053 */
2054 if(!granted)
2055 _XmHTMLComputeLayout(html);
2056
2057 _XmHTMLDebug(1, ("XmHTML.c: autoSizeWidget, results:\n"
2058 "\tRequest granted: %s\n"
2059 "\tcore height = %i, core width = %i, work_width = %i\n"
2060 "\tformatted_width = %i, formatted_height = %i.\n"
2061 "\thas_vsb = %s, has_hsb = %s\n",
2062 granted ? "yes" : "no",
2063 CORE_ATTR(height), CORE_ATTR(width), HTML_ATTR(work_width),
2064 HTML_ATTR(formatted_width), HTML_ATTR(formatted_height),
2065 has_vsb ? "yes" : "no", has_hsb ? "yes" : "no"));
2066 }
2067
2068 /*****
2069 * Name: DrawRedisplay
2070 * Return Type: void
2071 * Description: Eventhandler for exposure events on the work_area
2072 * In:
2073 * w: owner of this eventhandler
2074 * html: client data, XmHTMLWidget to which w belongs
2075 * event: expose event data.
2076 * Returns:
2077 * nothing
2078 * Note:
2079 * This routine makes a rough guess on which ObjectTable elements
2080 * should be used as vertical start and end points for the paint engine.
2081 * Finetuning is done by the DrawText routine in paint.c, which uses
2082 * the paint_x, paint_y, paint_width and paint_height fields in the
2083 * htmlRec to determine what should be painted exactly.
2084 *****/
2085 static void
DrawRedisplay(Widget w,XmHTMLWidget html,XEvent * event)2086 DrawRedisplay(Widget w, XmHTMLWidget html, XEvent *event)
2087 {
2088 /*
2089 * must use int for y-positions. The Position and Dimension typedefs
2090 * are shorts, which may produce bad results if the scrolled position
2091 * exceeds the size of a short
2092 */
2093 int y1, y2, height, x1, x2, width;
2094 XEvent expose;
2095
2096 _XmHTMLDebug(1, ("XmHTML.c: DrawRedisplay Start\n"));
2097
2098 /*****
2099 * No needless exposures. Kick out graphics exposures, I don't know
2100 * who invented these, sure as hell don't know what to do with them...
2101 *
2102 * Update August 26: I do know now what to do with these suckers:
2103 * they are generated whenever a XCopyArea or XCopyPlane request couldn't
2104 * be completed 'cause the destination area is (partially) obscured.
2105 * This happens when some other window is placed over our display area.
2106 * So when we get a GraphicsExpose event, we check our visibility state
2107 * and only draw something when we are partially obscured: when we are
2108 * fully visibile we won't get any GraphicsExpose events, and when we
2109 * are fully obscured we won't even get Expose Events.
2110 * The reason behind all of this are the images & anchor drawing: sometimes
2111 * they overlap an already painted area, and drawing will then generate
2112 * a GraphicsExpose, which in turn will trigger a redisplay of these anchors
2113 * and then it starts all over again. Ergo: bad screen flickering. And we
2114 * DO NOT want this.
2115 *****/
2116 if(((event->xany.type != Expose) && (event->xany.type != GraphicsExpose))
2117 || HTML_ATTR(formatted) == NULL || HTML_ATTR(nframes))
2118 {
2119 /* display scrollbars if we are in a frame */
2120 if(HTML_ATTR(is_frame))
2121 _XmHTMLSetScrollBars(html);
2122 _XmHTMLDebug(1, ("XmHTML.c: DrawRedisplay End: wrong event "
2123 "(%i).\n", event->xany.type));
2124 return;
2125 }
2126 if(event->xany.type == GraphicsExpose &&
2127 HTML_ATTR(visibility) != VisibilityPartiallyObscured &&
2128 !HTML_ATTR(form_data))
2129 {
2130 _XmHTMLDebug(1, ("XmHTML.c: DrawRedisplay End: bad GraphicsExpose, "
2131 "window not partially obscured.\n"));
2132 return;
2133 }
2134
2135 x1 = event->xexpose.x;
2136 y1 = event->xexpose.y;
2137 width = event->xexpose.width;
2138 height = event->xexpose.height;
2139 x2 = x1 + width;
2140
2141 _XmHTMLDebug(1, ("XmHTML.c: DrawRedisplay, y-position of region: %i, "
2142 "height of region: %i\n", y1, height));
2143
2144 _XmHTMLDebug(1, ("XmHTML.c: DrawRedisplay, event type: %s\n",
2145 event->xany.type == Expose ? "Expose" : "GraphicsExpose"));
2146
2147 _XmHTMLDebug(1, ("XmHTML.c: DrawRedisplay %i Expose events waiting.\n",
2148 event->xexpose.count));
2149
2150 /*
2151 * coalesce multiple expose events into one.
2152 */
2153 while((XCheckWindowEvent(XtDisplay(w), XtWindow(w), ExposureMask,
2154 &expose)) == True)
2155 {
2156 int dx, dy, dh, dw;
2157
2158 /*****
2159 * GraphicsExpose events are only honored when we are partially
2160 * obscured.
2161 *****/
2162 if(expose.xany.type == NoExpose ||
2163 (event->xany.type == GraphicsExpose &&
2164 HTML_ATTR(visibility) != VisibilityPartiallyObscured))
2165 continue;
2166
2167 dx = expose.xexpose.x;
2168 dy = expose.xexpose.y;
2169 dw = expose.xexpose.width;
2170 dh = expose.xexpose.height;
2171
2172 _XmHTMLDebug(1, ("XmHTML.c: DrawRedisplay, next event, geometry of "
2173 "exposed region: %ix%i:%i,%i\n", dx, dy, dw, dh));
2174
2175 /* right side of region */
2176 x2 = x1 + width;
2177
2178 /* leftmost x-position of exposure region */
2179 if(x1 > dx)
2180 x1 = dx;
2181
2182 /* rightmost x-position of exposure region */
2183 if(x2 < (dx + dw))
2184 x2 = dx + dw;
2185
2186 /* width of exposure region */
2187 width = x2 - x1;
2188
2189 /* bottom of region */
2190 y2 = y1 + height;
2191
2192 /* topmost y-position of exposure region */
2193 if(y1 > dy)
2194 y1 = dy;
2195
2196 /* bottommost y-position of exposure region */
2197 if(y2 < (dy + dh))
2198 y2 = dy + dh;
2199
2200 /* height of exposure region */
2201 height = y2 - y1;
2202 }
2203
2204 _XmHTMLDebug(1, ("XmHTML.c: DrawRedisplay, total region geometry: "
2205 "%ix%i:%i,%i.\n", x1, y1, width, height));
2206
2207 _XmHTMLRefresh(html, x1, y1, width, height);
2208
2209 _XmHTMLDebug(1, ("XmHTML.c: DrawRedisplay End\n"));
2210 }
2211
2212 /*****
2213 * Name: Redisplay
2214 * Return Type: void
2215 * Description: xmHTMLWidgetClass expose method.
2216 * In:
2217 * w: widget to expose
2218 * event: description of event that triggered an expose
2219 * region: region to display.
2220 * Returns:
2221 * nothing
2222 *****/
2223 static void
Redisplay(Widget w,XEvent * event,Region region)2224 Redisplay(Widget w, XEvent *event, Region region)
2225 {
2226 _XmHTMLDebug(1, ("XmHTML.c: Redisplay Start\n"));
2227
2228 /* Pass exposure events down to the children */
2229 _XmRedisplayGadgets(w, (XEvent*)event, region);
2230
2231 _XmHTMLDebug(1, ("XmHTML.c: Redisplay End\n"));
2232 return;
2233 }
2234
2235 /*****
2236 * Name: SetValues
2237 * Return Type: Boolean
2238 * Description: xmHTMLWidgetClass SetValues method.
2239 * In:
2240 * current: copy of widget before any set_values methods are called
2241 * request: copy of widget after resources have changed but before any
2242 * set_values methods are called
2243 * set: widget with resources set and as modified by any superclass
2244 * methods that have called XtSetValues()
2245 * args: argument list passed to XtSetValues, done by programmer
2246 * num_args: no of args
2247 * Returns:
2248 * True if a changed resource requires a redisplay, False otherwise.
2249 *****/
2250 static Boolean
SetValues(Widget current,Widget request,Widget set,ArgList args,Cardinal * num_args)2251 SetValues(Widget current, Widget request, Widget set,
2252 ArgList args, Cardinal *num_args)
2253 {
2254 XmHTMLWidget w_curr = (XmHTMLWidget)current;
2255 XmHTMLWidget w_req = (XmHTMLWidget)request;
2256 XmHTMLWidget w_new = (XmHTMLWidget)set;
2257
2258 Boolean redraw = False, parse = False;
2259 Boolean need_reformat = False;
2260 Boolean need_layout = False;
2261 Boolean free_images = False;
2262
2263 unsigned long event_to_check = 0L;
2264
2265 /* fix 06/17/97-01, aj */
2266 int i;
2267 int valueReq = False;
2268
2269 _XmHTMLDebug(1, ("XmHTML.c: SetValues Start\n"));
2270
2271 /*****
2272 * Note on processing of the onLoad/onUnload events.
2273 * For the onLoad event, the spec states the following:
2274 * ``The onload event occurs when the user agent finished loading a
2275 * window or all frames within a frameset''.
2276 * Therefore the onLoad event will be the last action to be carried
2277 * out when a new source has been supplied.
2278 *
2279 * For the onUnload event: the spec doesn't state when this event
2280 * should be executed. We take the easy way out and execute this event
2281 * right before the document is unloaded.
2282 *****/
2283
2284
2285 #ifdef DEBUG
2286 if(ATTR_HTML(w_req, debug_levels) != ATTR_HTML(w_curr, debug_levels))
2287 {
2288 _XmHTMLSelectDebugLevels(ATTR_HTML(w_req, debug_levels));
2289 ATTR_HTML(w_new, debug_levels) = ATTR_HTML(w_req, debug_levels);
2290 }
2291 _XmHTMLSetFullDebug(ATTR_HTML(w_req, debug_full_output));
2292
2293 if(ATTR_HTML(w_req, debug_disable_warnings))
2294 debug_disable_warnings = True;
2295 else
2296 debug_disable_warnings = False;
2297 #endif
2298
2299 /*****
2300 * We always use a copy of the HTML source text that is set into
2301 * the widget to prevent a crash when the user has freed it before we
2302 * had a chance of parsing it, and we ensure new text will get set
2303 * properly.
2304 *
2305 * fix 06/17/97-01, aj
2306 * Patch to fix clearing if doing setvalues without XmNvalue
2307 * Determine if we have a set value request and only check new source
2308 * if it has been supplied explicitly.
2309 *
2310 * Addition 10/10/97, kdh: changing the palette at run-time is *never*
2311 * allowed.
2312 *****/
2313 for(i = 0; i < *num_args; i++)
2314 {
2315 if(!strcmp(XmNvalue, args[i].name))
2316 valueReq = True;
2317
2318 /* Check for read-only resources */
2319 if(!strcmp(XmNimagePalette, args[i].name) ||
2320 !strcmp(XmNhorizontalScrollBar, args[i].name) ||
2321 !strcmp(XmNverticalScrollBar, args[i].name) ||
2322 !strcmp(XmNworkWindow, args[i].name))
2323 {
2324 _XmHTMLWarning(__WFUNC__(w_curr, "SetValues"), XMHTML_MSG_12,
2325 args[i].name);
2326 return(False);
2327 }
2328 }
2329
2330 /* we have a new source request */
2331 if(valueReq)
2332 {
2333 /* we had a previous source */
2334 if(ATTR_HTML(w_curr, source))
2335 {
2336 /* new text has been supplied */
2337 if(ATTR_HTML(w_req, value))
2338 {
2339 /* see if it differs */
2340 if(strcmp(ATTR_HTML(w_req, value), ATTR_HTML(w_curr, source)))
2341 {
2342 parse = True; /* it does */
2343
2344 /* free previous source text */
2345 free(ATTR_HTML(w_curr, source));
2346
2347 /* copy new source text */
2348 ATTR_HTML(w_new, source) = strdup(ATTR_HTML(w_req, value));
2349
2350 /* Required to do both onLoad and onUnload events */
2351 event_to_check = EVENT_LOAD | EVENT_UNLOAD;
2352 }
2353 else
2354 parse = False; /* it doesn't */
2355 }
2356 else /* have to clear current text */
2357 {
2358 parse = True;
2359
2360 /* free previous source text */
2361 free(ATTR_HTML(w_curr, source));
2362
2363 /* reset to NULL */
2364 ATTR_HTML(w_new, source) = NULL;
2365
2366 /* Required to check onUnLoad event */
2367 event_to_check = EVENT_UNLOAD;
2368 }
2369 }
2370 else /* we didn't have any source */
2371 {
2372 if(ATTR_HTML(w_req, value))
2373 {
2374 /* new text */
2375 parse = True;
2376
2377 /* copy new source text */
2378 ATTR_HTML(w_new, source) = strdup(ATTR_HTML(w_req, value));
2379
2380 /* Required to check onLoad event */
2381 event_to_check = EVENT_LOAD;
2382 }
2383 else
2384 parse = False; /* still empty */
2385 }
2386 /* input is always complete */
2387 ATTR_HTML(w_new, input_complete) = True;
2388 }
2389
2390 /*****
2391 * Whoa!! String direction changed!!! All text will be reversed
2392 * and default alignment changes to the other margin as well.
2393 * Needs full reformat as this changes things profoundly...
2394 * This requires a full reparsing of the document data as string reversal
2395 * is done at the lowest possible level: in the parser.
2396 *****/
2397 if(ATTR_HTML(w_req,string_direction) != ATTR_HTML(w_curr,string_direction))
2398 {
2399 parse = True;
2400
2401 /* check for alignment */
2402 CheckAlignment(w_new, w_req);
2403 }
2404
2405 /*****
2406 * Enabling/disabling icon entity support requires a complete reparsing
2407 * of the input as the icons are translated at parse-time.
2408 *****/
2409 if(ATTR_HTML(w_req, icon_entities_enabled) !=
2410 ATTR_HTML(w_curr, icon_entities_enabled))
2411 {
2412 parse = True;
2413 }
2414
2415 /*****
2416 * Check if vertical icon alignment has changed. Same note as with
2417 * enabling/disabling icon entities applies here as well.
2418 *****/
2419 if(ATTR_HTML(w_req, icon_valign) != ATTR_HTML(w_curr, icon_valign))
2420 {
2421 /* verify new value */
2422 if(!XmRepTypeValidValue(icon_repid, ATTR_HTML(w_req, icon_valign),
2423 (Widget)w_req))
2424 ATTR_HTML(w_new, icon_valign) = ATTR_HTML(w_curr, icon_valign);
2425 else
2426 /*****
2427 * Reparsing only required if support for icon entities is
2428 * enabled.
2429 *****/
2430 parse = ATTR_HTML(w_req, icon_entities_enabled);
2431 }
2432
2433 if(parse)
2434 {
2435 _XmHTMLDebug(1, ("XmHTML.c: SetValues, parsing new text\n"));
2436
2437 /* Check if we have to execute the onUnload event */
2438 if((event_to_check & EVENT_UNLOAD) &&
2439 ATTR_HTML(w_curr, event_mask) & EVENT_UNLOAD)
2440 {
2441 /*****
2442 * Event processing of the onUnload event can *never*
2443 * modify the document content. EventProcess explicitly
2444 * *exits* if it does happen.
2445 *****/
2446 _XmHTMLEventProcess(w_curr, NULL,
2447 ATTR_HTML(w_curr, body_events)->onUnload);
2448 }
2449 /* clear the unload bit */
2450 event_to_check &= ~EVENT_UNLOAD;
2451
2452 /* new text has been set, kill of any existing PLC's */
2453 _XmHTMLKillPLCCycler(w_curr);
2454
2455 /* release event database */
2456 _XmHTMLEventFreeDatabase(w_curr, w_new);
2457
2458 /* destroy any form data */
2459 _XmHTMLFreeForm(w_curr, ATTR_HTML(w_curr, form_data));
2460 ATTR_HTML(w_curr, form_data) = (XmHTMLFormData*)NULL;
2461 ATTR_HTML(w_new, form_data) = (XmHTMLFormData*)NULL;
2462
2463 /*****
2464 * Destroy any external object data inside frames before new
2465 * ones are created.
2466 *****/
2467 #ifdef HAVE_EXTERNAL_OBJECTS
2468 _XmHTMLFrameDestroyExternalObjects(w_curr);
2469 _XmHTMLDestroyExternalObjects(w_curr);
2470 #endif
2471
2472 /* Parse the raw HTML text */
2473 ATTR_HTML(w_new, elements) = _XmHTMLparseHTML(w_req,
2474 ATTR_HTML(w_curr, elements), ATTR_HTML(w_req, value), w_new);
2475
2476 /* reset topline */
2477 ATTR_HTML(w_new, top_line) = 0;
2478
2479 /* keep current frame setting and check if new frames are allowed */
2480 ATTR_HTML(w_new, is_frame) = ATTR_HTML(w_curr, is_frame);
2481 ATTR_HTML(w_new, nframes) = _XmHTMLCheckForFrames(w_new,
2482 ATTR_HTML(w_new, elements));
2483
2484 /* Trigger link callback */
2485 if(ATTR_HTML(w_new, link_callback))
2486 _XmHTMLLinkCallback(w_new);
2487
2488 /* needs layout, a redraw and current images must be freed */
2489 need_reformat = True;
2490 redraw = True;
2491 free_images = True;
2492
2493 _XmHTMLDebug(1, ("XmHTML.c: SetValues, done parsing\n"));
2494 }
2495
2496 if((ATTR_HTML(w_req, enable_outlining)
2497 != ATTR_HTML(w_curr, enable_outlining)) ||
2498 (ATTR_HTML(w_req, alignment) != ATTR_HTML(w_curr, alignment)))
2499 {
2500 /* Needs full reformat, default alignment is a text property */
2501 CheckAlignment(w_new, w_req);
2502 need_reformat = True;
2503 }
2504
2505 /*****
2506 * Check if tabwidth has been changed. Always needs a recomputation
2507 * of the layout since we don't know if the current text contains
2508 * preformatted text or not.
2509 *****/
2510 if(ATTR_HTML(w_req, tabwidth) != ATTR_HTML(w_curr, tabwidth))
2511 {
2512 /*****
2513 * tabwidth must be a positive, non-zero number.
2514 * If not, issue a warning and keep the current tabwidth.
2515 *****/
2516 if(ATTR_HTML(w_req, tabwidth) < 1)
2517 {
2518 _XmHTMLWarning(__WFUNC__(w_req, "SetValues"), XMHTML_MSG_9,
2519 "XmNtabWidth", ATTR_HTML(w_req, tabwidth),
2520 ATTR_HTML(w_curr, tabwidth));
2521 ATTR_HTML(w_new, tabwidth) = ATTR_HTML(w_curr, tabwidth);
2522 }
2523 else
2524 need_reformat = True;
2525 }
2526
2527 /*****
2528 * see if fonts have changed. The bloody problem with resources of type
2529 * String is that it's very well possible that a user is using some
2530 * static space to store these things. In these cases, the simple
2531 * comparisons are bound to be True every time, even though the content
2532 * might have changed (which we won't see cause it's all in static user
2533 * space!!), so to catch changes to this type of resources, we *MUST*
2534 * scan the array of provided args to check if it's specified. Sigh.
2535 *****/
2536 valueReq = False;
2537 for(i = 0; i < *num_args; i++)
2538 {
2539 if(!strcmp(XmNcharset, args[i].name) ||
2540 !strcmp(XmNfontFamily, args[i].name) ||
2541 !strcmp(XmNfontFamilyFixed, args[i].name) ||
2542 !strcmp(XmNfontSizeFixedList, args[i].name) ||
2543 !strcmp(XmNfontSizeList, args[i].name))
2544 valueReq = True;
2545 }
2546 if(valueReq ||
2547 ATTR_HTML(w_req, font_sizes) != ATTR_HTML(w_curr, font_sizes) ||
2548 ATTR_HTML(w_req, font_family) != ATTR_HTML(w_curr, font_family) ||
2549 ATTR_HTML(w_req, font_sizes_fixed) != ATTR_HTML(w_curr, font_sizes_fixed) ||
2550 ATTR_HTML(w_req, font_family_fixed)!= ATTR_HTML(w_curr, font_family_fixed)||
2551 ATTR_HTML(w_req, charset) != ATTR_HTML(w_curr, charset))
2552 {
2553 /* reset font cache */
2554 ATTR_HTML(w_new, default_font) = _XmHTMLSelectFontCache(w_new, True);
2555 need_reformat = True;
2556 }
2557
2558 /*
2559 * Body colors. Original body colors are restored when body colors are
2560 * disabled.
2561 */
2562 if(ATTR_HTML(w_req, body_colors_enabled)
2563 != ATTR_HTML(w_curr, body_colors_enabled))
2564 {
2565 /* restore original body colors */
2566 if(!ATTR_HTML(w_req, body_colors_enabled))
2567 {
2568 ATTR_HTML(w_new, body_fg) = ATTR_HTML(w_req, body_fg_save);
2569 ATTR_HTML(w_new, body_bg) = ATTR_HTML(w_req, body_bg_save);
2570 ATTR_HTML(w_new, anchor_fg) = ATTR_HTML(w_req, anchor_fg_save);
2571 ATTR_HTML(w_new, anchor_visited_fg) =
2572 ATTR_HTML(w_req, anchor_visited_fg_save);
2573 ATTR_HTML(w_new, anchor_activated_fg) =
2574 ATTR_HTML(w_req, anchor_activated_fg_save);
2575
2576 /* recompute top, bottom & highlight colors */
2577 XmHTMLTkaRecomputeColors(w_new, ATTR_HTML(w_new, body_bg));
2578 }
2579 need_reformat = True;
2580 }
2581
2582 /*
2583 * Colors. For now we redo the layout since all colors are stored
2584 * in the ObjectTable data.
2585 * Not that effective, perhaps use multiple GC's, but thats a lot of
2586 * resource consuming going on then...
2587 */
2588 if((ATTR_MGR(w_req,foreground) !=
2589 ATTR_MGR(w_curr, foreground)) ||
2590 (ATTR_CORE(w_req, background_pixel) !=
2591 ATTR_CORE(w_curr, background_pixel)) ||
2592 (ATTR_HTML(w_req, anchor_fg) !=
2593 ATTR_HTML(w_curr, anchor_fg)) ||
2594 (ATTR_HTML(w_req, anchor_target_fg) !=
2595 ATTR_HTML(w_curr, anchor_target_fg)) ||
2596 (ATTR_HTML(w_req, anchor_visited_fg) !=
2597 ATTR_HTML(w_curr, anchor_visited_fg)) ||
2598 (ATTR_HTML(w_req, anchor_activated_fg) !=
2599 ATTR_HTML(w_curr, anchor_activated_fg)) ||
2600 (ATTR_HTML(w_req, anchor_activated_bg) !=
2601 ATTR_HTML(w_curr, anchor_activated_bg)))
2602 {
2603 /* back and foreground pixels */
2604 ATTR_MGR(w_new, foreground) =
2605 ATTR_MGR(w_req, foreground);
2606 ATTR_CORE(w_new, background_pixel) =
2607 ATTR_CORE(w_req, background_pixel);
2608 ATTR_HTML(w_new, body_fg) =
2609 ATTR_MGR(w_new, foreground);
2610 ATTR_HTML(w_new, body_bg) =
2611 ATTR_CORE(w_new, background_pixel);
2612 ATTR_HTML(w_new, anchor_fg) =
2613 ATTR_HTML(w_req, anchor_fg);
2614 ATTR_HTML(w_new, anchor_target_fg) =
2615 ATTR_HTML(w_req, anchor_target_fg);
2616 ATTR_HTML(w_new, anchor_visited_fg) =
2617 ATTR_HTML(w_req, anchor_visited_fg);
2618 ATTR_HTML(w_new, anchor_activated_fg) =
2619 ATTR_HTML(w_req, anchor_activated_fg);
2620 ATTR_HTML(w_new, anchor_activated_bg) =
2621 ATTR_HTML(w_req, anchor_activated_bg);
2622
2623 /* save as new default colors */
2624 ATTR_HTML(w_new, body_fg_save) =
2625 ATTR_HTML(w_new, body_fg);
2626 ATTR_HTML(w_new, body_bg_save) =
2627 ATTR_HTML(w_new, body_bg);
2628 ATTR_HTML(w_new, anchor_fg_save) =
2629 ATTR_HTML(w_new, anchor_fg);
2630 ATTR_HTML(w_new, anchor_target_fg_save) =
2631 ATTR_HTML(w_new, anchor_target_fg);
2632 ATTR_HTML(w_new, anchor_visited_fg_save) =
2633 ATTR_HTML(w_new, anchor_visited_fg);
2634 ATTR_HTML(w_new, anchor_activated_fg_save) =
2635 ATTR_HTML(w_new, anchor_activated_fg);
2636 ATTR_HTML(w_new, anchor_activated_bg_save) =
2637 ATTR_HTML(w_new, anchor_activated_bg);
2638
2639 /* get new values for top, bottom & highlight colors */
2640 XmHTMLTkaRecomputeColors(w_new, ATTR_HTML(w_new, body_bg));
2641 need_reformat = True;
2642 }
2643
2644 /*
2645 * anchor highlighting, must invalidate any current selection
2646 * No need to do a redraw if the highlightcolor changes: since the
2647 * SetValues method is chained, Manager's SetValues takes care of that.
2648 */
2649 if(ATTR_HTML(w_req, highlight_on_enter) !=
2650 ATTR_HTML(w_curr, highlight_on_enter))
2651 ATTR_HTML(w_new, armed_anchor) = (XmHTMLObjectTable*)NULL;
2652
2653 /*
2654 * anchor underlining. Also needs a full layout computation as
2655 * underlining data is stored in the ObjectTable data
2656 */
2657 if( (ATTR_HTML(w_req, anchor_underline_type) !=
2658 ATTR_HTML(w_curr, anchor_underline_type)) ||
2659 (ATTR_HTML(w_req, anchor_visited_underline_type) !=
2660 ATTR_HTML(w_curr, anchor_visited_underline_type)) ||
2661 (ATTR_HTML(w_req, anchor_target_underline_type) !=
2662 ATTR_HTML(w_curr, anchor_target_underline_type)))
2663 {
2664 CheckAnchorUnderlining(w_new, w_req);
2665 need_reformat = True;
2666 }
2667 else
2668 {
2669 /*
2670 * Support for color & font attributes. Needs a redo of the layout
2671 * if changed. We only need to check for this if the above test
2672 * failed as that will also trigger a redo of the layout.
2673 */
2674 if(ATTR_HTML(w_req, allow_color_switching) !=
2675 ATTR_HTML(w_curr, allow_color_switching) ||
2676 ATTR_HTML(w_req, allow_font_switching) !=
2677 ATTR_HTML(w_curr, allow_font_switching))
2678 need_reformat = True;
2679 }
2680
2681 /*
2682 * on-the-fly enable/disable of dithering.
2683 */
2684 if(ATTR_HTML(w_req, map_to_palette) != ATTR_HTML(w_curr, map_to_palette))
2685 {
2686 /* from on to off or off to on */
2687 if(ATTR_HTML(w_curr, map_to_palette) == XmDISABLED ||
2688 ATTR_HTML(w_req, map_to_palette) == XmDISABLED)
2689 {
2690 /* free current stuff */
2691 XCCFree(ATTR_HTML(w_curr, xcc));
2692
2693 /* and create a new one */
2694 ATTR_HTML(w_new, xcc) = NULL;
2695 _XmHTMLCheckXCC(w_new);
2696
2697 /* add palette if necessary */
2698 if(ATTR_HTML(w_req, map_to_palette) != XmDISABLED)
2699 _XmHTMLAddPalette(w_new);
2700 }
2701 else
2702 {
2703 /* fast & best methods require precomputed error matrices */
2704 if(ATTR_HTML(w_req, map_to_palette) == XmBEST ||
2705 ATTR_HTML(w_req, map_to_palette) == XmFAST)
2706 {
2707 XCCInitDither(ATTR_HTML(w_new, xcc));
2708 }
2709 else
2710 XCCFreeDither(ATTR_HTML(w_new, xcc));
2711 }
2712 /* and in *all* cases we need a full reformat */
2713 need_reformat = True;
2714 }
2715
2716 /*
2717 * maximum amount of allowable image colors. Needs a full redo
2718 * of the layout if the current doc has got images with more colors
2719 * than allowed or it has images which have been dithered to fit
2720 * the previous setting.
2721 */
2722 if((ATTR_HTML(w_req, max_image_colors) !=
2723 ATTR_HTML(w_curr, max_image_colors)))
2724 {
2725 _XmHTMLCheckMaxColorSetting(w_new);
2726
2727 /*
2728 * check if we have any images with more colors than allowed or
2729 * we had images that were dithered. If so we need to redo the layout
2730 */
2731 if(!need_reformat)
2732 {
2733 XmHTMLImage *image;
2734 int prev_max = ATTR_HTML(w_curr, max_image_colors);
2735 int new_max = ATTR_HTML(w_req, max_image_colors);
2736
2737 for(image = ATTR_HTML(w_new, images); image != NULL && !free_images;
2738 image = image->next)
2739 {
2740 /* ImageInfo is still available. Compare against it */
2741 if(!ImageInfoFreed(image))
2742 {
2743 /*
2744 * redo image composition if any of the following
2745 * conditions is True:
2746 * - current image has more colors than allowed;
2747 * - current image has less colors than allowed but the
2748 * original image had more colors than allowed previously.
2749 */
2750 if(image->html_image->ncolors > new_max ||
2751 (image->html_image->scolors < new_max &&
2752 image->html_image->scolors > prev_max))
2753 free_images = True;
2754 }
2755 /* info no longer available. Check against allocated colors */
2756 else
2757 if(image->npixels > new_max)
2758 free_images = True;
2759 }
2760 /* need to redo the layout if we are to redo the images */
2761 need_reformat = free_images;
2762 }
2763 }
2764
2765 /* Are images enabled? */
2766 if(ATTR_HTML(w_req, images_enabled) != ATTR_HTML(w_curr, images_enabled))
2767 {
2768 /*****
2769 * we always need to free the images if this changes. A full
2770 * layout recomputation will load all images.
2771 *****/
2772 free_images = True;
2773 need_reformat = True;
2774 }
2775
2776 /* PLC timing intervals */
2777 if(ATTR_HTML(w_req, plc_min_delay) != ATTR_HTML(w_curr, plc_min_delay) ||
2778 ATTR_HTML(w_req, plc_max_delay) != ATTR_HTML(w_curr, plc_max_delay) ||
2779 ATTR_HTML(w_req, plc_delay) != ATTR_HTML(w_curr, plc_def_delay))
2780 _XmHTMLPLCCheckIntervals(w_new);
2781
2782 /*****
2783 * Now format the list of parsed objects.
2784 * Don't do a bloody thing if we are already in layout as this will
2785 * cause unnecessary reloading and screen flickering.
2786 *****/
2787 if(need_reformat && !ATTR_HTML(w_curr, in_layout))
2788 {
2789 _XmHTMLDebug(1, ("XmHTML.c: SetValues, need layout\n"));
2790
2791 /*****
2792 * It the current document makes heavy use of images we first need
2793 * to clear it. Not doing this would cause a shift in the colors of
2794 * the current document (as they are being released) which does not
2795 * look nice. Therefore first clear the entire display* area *before*
2796 * freeing anything at all.
2797 *****/
2798 if(ATTR_HTML(w_new, gc) != NULL)
2799 {
2800 ATTR_HTML(w_curr, tka)->ClearArea(ATTR_HTML(w_new, tka)->dpy,
2801 ATTR_HTML(w_new, tka)->win, 0, 0,
2802 ATTR_CORE(w_new, width), ATTR_CORE(w_new, height), False);
2803 }
2804
2805 /* destroy any form data */
2806 _XmHTMLFreeForm(w_curr, ATTR_HTML(w_curr, form_data));
2807 ATTR_HTML(w_new, form_data) = (XmHTMLFormData*)NULL;
2808
2809 /*****
2810 * Destroy any external object data inside frames before new
2811 * ones are created.
2812 *****/
2813 #ifdef HAVE_EXTERNAL_OBJECTS
2814 _XmHTMLFrameDestroyExternalObjects(w_curr);
2815 _XmHTMLDestroyExternalObjects(w_curr);
2816 #endif
2817
2818 /* Free all non-persistent resources */
2819 _XmHTMLFreeExpendableResources(w_curr, free_images);
2820
2821 /* reset some important vars */
2822 _XmHTMLReset(w_new, free_images);
2823
2824 /* check for an xcc, it might have been destroyed by now */
2825 if(free_images)
2826 _XmHTMLCheckXCC(w_new);
2827
2828 /* get new values for top, bottom & highlight */
2829 XmHTMLTkaRecomputeColors(w_new, ATTR_HTML(w_new, body_bg));
2830
2831 /* go and format the parsed HTML data */
2832 if(!_XmHTMLCreateFrames(w_curr, w_new))
2833 {
2834 ATTR_HTML(w_new, frames) = NULL;
2835 ATTR_HTML(w_new, nframes) = 0;
2836 /* keep current frame setting */
2837 ATTR_HTML(w_new, is_frame) = ATTR_HTML(w_curr, is_frame);
2838 }
2839
2840 _XmHTMLformatObjects(w_curr, w_new);
2841
2842 /* Check for the onload event */
2843 if(ATTR_HTML(w_new, event_mask) & EVENT_LOAD)
2844 {
2845 /*****
2846 * Check event return value. If it returns True the document
2847 * has changed from under us!
2848 *****/
2849 if(_XmHTMLEventProcess(w_new, NULL,
2850 ATTR_HTML(w_new, body_events)->onLoad))
2851 return(False);
2852 }
2853
2854 /* and check for possible external imagemaps */
2855 _XmHTMLCheckImagemaps(w_new);
2856
2857 _XmHTMLDebug(1, ("XmHTML.c: SetValues, computing new layout.\n"));
2858
2859 /* compute new screen layout */
2860 _XmHTMLLayout(w_new);
2861
2862 _XmHTMLDebug(1, ("XmHTML.c: SetValues, done with layout.\n"));
2863
2864 /* if new text has been set, fire up the PLCCycler */
2865 if(parse)
2866 {
2867 ATTR_HTML(w_new, plc_suspended) = False;
2868 _XmHTMLPLCCycler((XtPointer)w_new , NULL);
2869 }
2870
2871 free_images = False;
2872 redraw = True;
2873 need_layout = False;
2874 }
2875 /*****
2876 * Default background image changed. We don't need to do this when a
2877 * layout recomputation was required as it will have been taken care
2878 * of already.
2879 *****/
2880 else if
2881 (ATTR_HTML(w_req, body_images_enabled) !=
2882 ATTR_HTML(w_curr, body_images_enabled) ||
2883 ATTR_HTML(w_req, def_body_image_url) !=
2884 ATTR_HTML(w_curr, def_body_image_url))
2885 {
2886
2887 /* check if body images display status is changed */
2888 if(ATTR_HTML(w_req, body_images_enabled) !=
2889 ATTR_HTML(w_curr, body_images_enabled))
2890 {
2891 if(!free_images && ATTR_HTML(w_curr, body_image))
2892 ATTR_HTML(w_curr, body_image)->options |= IMG_ORPHANED;
2893 ATTR_HTML(w_new, body_image) = NULL;
2894 }
2895
2896 /* a new body image has been specified, check it */
2897 if(ATTR_HTML(w_req, def_body_image_url) !=
2898 ATTR_HTML(w_curr, def_body_image_url))
2899 {
2900 /* do we have a new image? */
2901 if(ATTR_HTML(w_req, def_body_image_url))
2902 {
2903 /* yes we do */
2904 ATTR_HTML(w_new, def_body_image_url) =
2905 strdup(ATTR_HTML(w_req, def_body_image_url));
2906 }
2907 else /* no we don't */
2908 ATTR_HTML(w_new, def_body_image_url) = NULL;
2909
2910 /* did we have a previous image? */
2911 if(ATTR_HTML(w_curr, def_body_image_url))
2912 {
2913 /* we did, free it */
2914 free(ATTR_HTML(w_curr, def_body_image_url));
2915
2916 /* make it an orphan */
2917 if(!free_images && ATTR_HTML(w_curr, body_image))
2918 ATTR_HTML(w_curr, body_image)->options |= IMG_ORPHANED;
2919 }
2920 }
2921
2922 /*
2923 * only load background image if image support is enabled and if
2924 * we are instructed to show a background image.
2925 */
2926 if(ATTR_HTML(w_req, images_enabled) &&
2927 ATTR_HTML(w_req, body_images_enabled))
2928 {
2929 /* current document has a background image of it's own. */
2930 if(ATTR_HTML(w_new, body_image_url))
2931 _XmHTMLLoadBodyImage(w_new, ATTR_HTML(w_new, body_image_url));
2932 /*
2933 * Only load the default background image if the doc didn't have
2934 * it's colors changed.
2935 */
2936 else if(ATTR_HTML(w_new, def_body_image_url) &&
2937 ATTR_HTML(w_new, body_fg) ==
2938 ATTR_HTML(w_new, body_fg_save) &&
2939 ATTR_HTML(w_new, body_bg) ==
2940 ATTR_HTML(w_new, body_bg_save) &&
2941 ATTR_HTML(w_new, anchor_fg) ==
2942 ATTR_HTML(w_new, anchor_fg_save) &&
2943 ATTR_HTML(w_new, anchor_visited_fg) ==
2944 ATTR_HTML(w_new, anchor_visited_fg_save) &&
2945 ATTR_HTML(w_new, anchor_activated_fg) ==
2946 ATTR_HTML(w_new, anchor_activated_fg_save))
2947 _XmHTMLLoadBodyImage(w_new,
2948 ATTR_HTML(w_new, def_body_image_url));
2949 }
2950 /*****
2951 * When a body image is present it is very likely that a highlight
2952 * color based upon the current background actually makes an anchor
2953 * invisible when highlighting is selected. Therefore we base the
2954 * highlight color on the activated anchor background when we have a
2955 * body image, and on the document background when no body image is
2956 * present.
2957 *****/
2958 if(ATTR_HTML(w_new, body_image))
2959 XmHTMLTkaRecomputeHighlightColor(w_new,
2960 ATTR_HTML(w_new, anchor_activated_fg));
2961 else
2962 XmHTMLTkaRecomputeHighlightColor(w_new, ATTR_HTML(w_new, body_bg));
2963
2964 /* only redraw if the new body image differs from the old one */
2965 if(ATTR_HTML(w_new, body_image) != ATTR_HTML(w_curr, body_image))
2966 {
2967 /* set alpha channel processing if not yet done */
2968 free_images = !parse && !need_reformat;
2969 redraw = True;
2970 }
2971 }
2972
2973 /* anchor button state */
2974 if((ATTR_HTML(w_req, anchor_buttons) != ATTR_HTML(w_curr, anchor_buttons)))
2975 redraw = True;
2976
2977 /*****
2978 * cursor state changes. Note that we always free the current cursor,
2979 * even if it's created by the user.
2980 *****/
2981 if((ATTR_HTML(w_req, anchor_cursor) != ATTR_HTML(w_curr, anchor_cursor)) ||
2982 (ATTR_HTML(w_req, anchor_display_cursor) !=
2983 ATTR_HTML(w_curr, anchor_display_cursor)))
2984 {
2985 /* set cursor to None if we don't have to use or have a cursor */
2986 if(!ATTR_HTML(w_new, anchor_display_cursor) ||
2987 !ATTR_HTML(w_new, anchor_cursor))
2988 {
2989 if(ATTR_HTML(w_curr, anchor_cursor) != None)
2990 XFreeCursor(XtDisplay((Widget)w_curr),
2991 ATTR_HTML(w_curr, anchor_cursor));
2992 ATTR_HTML(w_new, anchor_cursor) = None;
2993 }
2994 /* no redraw required */
2995 }
2996
2997 /*
2998 * Scroll to the requested line or restore previous line if it has been
2999 * messed up as the result of a resource change requiring a recompuation
3000 * of the layout.
3001 */
3002 if(ATTR_HTML(w_req, top_line) != ATTR_HTML(w_curr, top_line))
3003 {
3004 _XmHTMLScrollToLine(w_new, ATTR_HTML(w_req, top_line));
3005 redraw = True;
3006 }
3007 else if(need_reformat && !parse &&
3008 ATTR_HTML(w_new, top_line) != ATTR_HTML(w_curr, top_line))
3009 {
3010 _XmHTMLScrollToLine(w_new, ATTR_HTML(w_curr, top_line));
3011 redraw = True;
3012 }
3013
3014 /* check and set scrolling delay */
3015 if(ATTR_HTML(w_req, repeat_delay) != ATTR_HTML(w_curr, repeat_delay))
3016 {
3017 if(ATTR_HTML(w_new, vsb) && XtIsManaged(ATTR_HTML(w_new, vsb)))
3018 XtVaSetValues(ATTR_HTML(w_new, vsb),
3019 XmNrepeatDelay, ATTR_HTML(w_new, repeat_delay), NULL);
3020 if(ATTR_HTML(w_new, hsb) && XtIsManaged(ATTR_HTML(w_new, hsb)))
3021 XtVaSetValues(ATTR_HTML(w_new, hsb),
3022 XmNrepeatDelay, ATTR_HTML(w_new, repeat_delay), NULL);
3023 }
3024 /* see if we have to restart the animations if they were frozen */
3025 if(!ATTR_HTML(w_req, freeze_animations) &&
3026 ATTR_HTML(w_curr, freeze_animations))
3027 _XmHTMLRestartAnimations(w_new);
3028
3029 /* do we still need pointer tracking? */
3030 if(!ATTR_HTML(w_new, anchor_track_callback) &&
3031 !ATTR_HTML(w_new, anchor_cursor) &&
3032 !ATTR_HTML(w_new, highlight_on_enter) &&
3033 !ATTR_HTML(w_new, motion_track_callback) &&
3034 !ATTR_HTML(w_new, focus_callback) &&
3035 !ATTR_HTML(w_new, losing_focus_callback))
3036 ATTR_HTML(w_new, need_tracking) = False;
3037 else
3038 ATTR_HTML(w_new, need_tracking) = True;
3039
3040 /* only recompute new layout if we haven't done so already */
3041 if(need_layout && !ATTR_HTML(w_curr, in_layout) && !need_reformat)
3042 {
3043 _XmHTMLLayout(w_new);
3044 redraw = True;
3045 }
3046
3047 if(redraw)
3048 {
3049 /*
3050 * If free_images is still set when we get here, check if some
3051 * images need their delayed_creation bit set.
3052 */
3053 if(free_images)
3054 {
3055 XmHTMLImage *img;
3056 for(img = ATTR_HTML(w_new, images); img != NULL; img = img->next)
3057 {
3058 if(!ImageInfoFreed(img) &&
3059 ImageInfoDelayedCreation(img->html_image))
3060 {
3061 img->options |= IMG_DELAYED_CREATION;
3062 ATTR_HTML(w_new, delayed_creation) = True;
3063 }
3064 }
3065 if(ATTR_HTML(w_new, delayed_creation))
3066 _XmHTMLImageCheckDelayedCreation(w_new);
3067 }
3068
3069 _XmHTMLDebug(1, ("XmHTML.c: SetValues, calling _XmHTMLClearArea.\n"));
3070 /*****
3071 * To make sure the new text is displayed, we need to clear
3072 * the current contents and generate an expose event to render
3073 * the new text.
3074 * We can only do this when we have been realized. If we don't have
3075 * a gc, it means we haven't been realized yet. (fix 01/26/97-01, kdh)
3076 *****/
3077 if(ATTR_HTML(w_new, gc) != NULL)
3078 _XmHTMLClearArea(w_new, 0, 0, ATTR_CORE(w_new, width),
3079 ATTR_CORE(w_new, height));
3080 }
3081
3082 /* Check for the onload event */
3083 if((event_to_check & EVENT_LOAD) &&
3084 ATTR_HTML(w_new, event_mask) & EVENT_LOAD)
3085 {
3086 /*****
3087 * Don't bother to check return value. It's forbidden to modify
3088 * the document content during processing of the onLoad event.
3089 * (EventProcess exits if it does happen)
3090 *****/
3091 _XmHTMLEventProcess(w_new, NULL,
3092 ATTR_HTML(w_new, body_events)->onLoad);
3093 }
3094
3095 _XmHTMLDebug(1, ("XmHTML.c: SetValues End\n"));
3096
3097 return(redraw);
3098 }
3099
3100 /*****
3101 * Name: GetValues
3102 * Return Type: void
3103 * Description: XmHTMLWidgetClass get_values_hook method.
3104 * In:
3105 *
3106 * Returns:
3107 * nothing
3108 *****/
3109 static void
GetValues(Widget w,ArgList args,Cardinal * num_args)3110 GetValues(Widget w, ArgList args, Cardinal *num_args)
3111 {
3112 register int i;
3113
3114 _XmHTMLDebug(1, ("XmHTML.c: GetValues Start\n"));
3115
3116 /*****
3117 * Note on args filling:
3118 * the value field (which is of type long int) represents a pointer to
3119 * another pointer. Thus, updating a value requires updating the
3120 * location the second pointer points to. That's why a double pointer
3121 * cast is required.
3122 *****/
3123
3124 for(i = 0; i < *num_args; i++)
3125 {
3126 _XmHTMLDebug(1, ("XmHTML.c: GetValues, requested for %s.\n",
3127 args[i].name));
3128
3129 /*
3130 * We return a pointer to the source text instead of letting X do it
3131 * since the user might have freed the original text by now.
3132 */
3133 if(!(strcmp(args[i].name, XmNvalue)))
3134 {
3135 *((char**)args[i].value) = XmHTMLTextGetSource(w);
3136 }
3137 else if(!(strcmp(args[i].name, XmNtopLine)))
3138 {
3139 XmHTMLObjectTableElement tmp;
3140 XmHTMLWidget html = (XmHTMLWidget)w;
3141
3142 /* get current linenumber */
3143 tmp = _XmHTMLGetLineObject(html, HTML_ATTR(scroll_y));
3144
3145 if(tmp != NULL)
3146 *((int*)args[i].value) = tmp->line;
3147 else
3148 *((int*)args[i].value) = 0;
3149 }
3150 }
3151 _XmHTMLDebug(1, ("XmHTML.c: GetValues End\n"));
3152 return;
3153 }
3154
3155 /*****
3156 * Name: GeometryManager
3157 * Return Type: XtGeometryResult
3158 * Description: XmHTMLWidgetClass geometry_manager method
3159 * In:
3160 *
3161 * Returns:
3162 * Don't care. Just pass everything on.
3163 *****/
3164 static XtGeometryResult
GeometryManager(Widget w,XtWidgetGeometry * request,XtWidgetGeometry * geometry_return)3165 GeometryManager(Widget w, XtWidgetGeometry *request,
3166 XtWidgetGeometry *geometry_return)
3167 {
3168 _XmHTMLDebug(1, ("XmHTML.c: GeometryManager Start\n"));
3169
3170 if(request->request_mode & CWX)
3171 geometry_return->x = request->x;
3172 if(request->request_mode & CWY)
3173 geometry_return->y = request->y;
3174 if(request->request_mode & CWWidth)
3175 geometry_return->width = request->width;
3176 if(request->request_mode & CWHeight)
3177 geometry_return->height = request->height;
3178 if(request->request_mode & CWBorderWidth)
3179 geometry_return->border_width = request->border_width;
3180 geometry_return->request_mode = request->request_mode;
3181
3182 _XmHTMLDebug(1, ("XmHTML.c: GeometryManager End\n"));
3183
3184 return(XtGeometryYes);
3185 }
3186
3187 /*****
3188 * Name: Destroy
3189 * Return Type: void
3190 * Description: XmHTMLWidgetClass destroy method. Frees up allocated resources.
3191 * In:
3192 * w: widget to destroy
3193 * Returns:
3194 * nothing
3195 *****/
3196 static void
Destroy(Widget w)3197 Destroy(Widget w)
3198 {
3199 XmHTMLWidget html = (XmHTMLWidget)w;
3200
3201 _XmHTMLDebug(1, ("XmHTML.c: Destroy Start\n"));
3202
3203 /* destroy common resources */
3204 _XmHTMLDestroyPhaseZero(html);
3205
3206 /* remove all callbacks */
3207 XtRemoveAllCallbacks(w, XmNactivateCallback);
3208 XtRemoveAllCallbacks(w, XmNarmCallback);
3209 XtRemoveAllCallbacks(w, XmNanchorTrackCallback);
3210 XtRemoveAllCallbacks(w, XmNframeCallback);
3211 XtRemoveAllCallbacks(w, XmNformCallback);
3212 XtRemoveAllCallbacks(w, XmNinputCallback);
3213 XtRemoveAllCallbacks(w, XmNlinkCallback);
3214 XtRemoveAllCallbacks(w, XmNmotionTrackCallback);
3215 XtRemoveAllCallbacks(w, XmNimagemapCallback);
3216 XtRemoveAllCallbacks(w, XmNdocumentCallback);
3217 XtRemoveAllCallbacks(w, XmNfocusCallback);
3218 XtRemoveAllCallbacks(w, XmNlosingFocusCallback);
3219 XtRemoveAllCallbacks(w, XmNeventCallback);
3220
3221 /* Destroy our ToolkitAbstraction */
3222 XmHTMLTkaDestroy(HTML_ATTR(tka));
3223
3224 /* invalidate this widget */
3225 w = NULL;
3226
3227 _XmHTMLDebug(1, ("XmHTML.c: Destroy End\n"));
3228 return;
3229 }
3230
3231 /*****
3232 * Name: HTMLProcessInput
3233 * Return Type: void
3234 * Description: handles keyboard input for the HTML widget.
3235 * In:
3236 * w: XmHTMLWidget
3237 * event: ButtonEvent structure
3238 * params: additional args, unused
3239 * num_params: no of addition args, unused
3240 * Returns:
3241 * nothing
3242 * Note:
3243 * This routine calls any installed XmNinputCallback callback resources.
3244 *****/
3245 static void
HTMLProcessInput(Widget w,XEvent * event,String * params,Cardinal * num_params)3246 HTMLProcessInput(Widget w, XEvent *event, String *params, Cardinal *num_params)
3247 {
3248 XmHTMLWidget html;
3249 /*
3250 * If this action proc is called directly from within application code,
3251 * w is a html widget. In all other cases this action proc is called
3252 * for the translations installed on the work_area, and thus we need to
3253 * use XtParent to get our html widget.
3254 */
3255 if(XmIsHTML(w))
3256 html = (XmHTMLWidget)w;
3257 else
3258 html = (XmHTMLWidget)XtParent(w);
3259
3260 /* pass down if callback is installed */
3261 if(HTML_ATTR(input_callback))
3262 _XmHTMLInputCallback(html, event);
3263
3264 _XmHTMLDebug(1, ("XmHTML.c: ProcessInput End\n"));
3265 }
3266
3267 /*****
3268 * Name: HTMLPageUpOrLeft
3269 * Return Type: void
3270 * Description: keyboard navigation action routine
3271 * In:
3272 * w: widget id; XmHTMLWidget id if called from within application
3273 * code, work_area if handled by XmHTML itself;
3274 * event: key event;
3275 * params: 0 for pageUp, 1 for pageLeft
3276 * num_params: always 1
3277 * Returns:
3278 * nothing
3279 * Note:
3280 * This routine also honors the repeatDelay resource.
3281 *****/
3282 static void
HTMLPageUpOrLeft(Widget w,XEvent * event,String * params,Cardinal * num_params)3283 HTMLPageUpOrLeft(Widget w, XEvent *event, String *params,
3284 Cardinal *num_params)
3285 {
3286 int which;
3287 XmHTMLWidget html;
3288 static Time prev_time = 0;
3289
3290 if(XmIsHTML(w))
3291 html = (XmHTMLWidget)w;
3292 else
3293 html = (XmHTMLWidget)XtParent(w);
3294
3295 if(*num_params != 1 || !XtIsRealized(w))
3296 {
3297 if(*num_params != 1)
3298 _XmHTMLWarning(__WFUNC__(w, "HTMLPageUpOrLeft"), XMHTML_MSG_13,
3299 "page-up-or-left");
3300 return;
3301 }
3302
3303 /* check repeat delay */
3304 if(event->xkey.time - prev_time < HTML_ATTR(repeat_delay))
3305 return;
3306 prev_time = event->xkey.time;
3307
3308 which = atoi(params[0]);
3309
3310 _XmHTMLDebug(1, ("XmHTML.c: HTMLPageUpOrLeft, which = %i\n", which));
3311
3312 if(which == 0 && XtIsManaged(HTML_ATTR(vsb)))
3313 XtCallActionProc(HTML_ATTR(vsb), "PageUpOrLeft", event, params, 1);
3314 else if(which == 1 && XtIsManaged(HTML_ATTR(hsb)))
3315 XtCallActionProc(HTML_ATTR(hsb), "PageUpOrLeft", event, params, 1);
3316 }
3317
3318 /*****
3319 * Name: HTMLDownOrRight
3320 * Return Type: void
3321 * Description: keyboard navigation action routine
3322 * In:
3323 * w: widget id; XmHTMLWidget id if called from within application
3324 * code, work_area if handled by XmHTML itself;
3325 * event: key event;
3326 * params: 0 for pageDown, 1 for pageRight
3327 * num_params: always 1
3328 * Returns:
3329 * nothing
3330 * Note:
3331 * This routine also honors the repeatDelay resource.
3332 *****/
3333 static void
HTMLPageDownOrRight(Widget w,XEvent * event,String * params,Cardinal * num_params)3334 HTMLPageDownOrRight(Widget w, XEvent *event, String *params,
3335 Cardinal *num_params)
3336 {
3337 int which;
3338 XmHTMLWidget html;
3339 static Time prev_time = 0;
3340
3341 if(XmIsHTML(w))
3342 html = (XmHTMLWidget)w;
3343 else
3344 html = (XmHTMLWidget)XtParent(w);
3345
3346 if(*num_params != 1 || !XtIsRealized(w))
3347 {
3348 if(*num_params != 1)
3349 _XmHTMLWarning(__WFUNC__(w, "HTMLPageDownOrRight"), XMHTML_MSG_13,
3350 "page-down-or-right");
3351 return;
3352 }
3353
3354 /* check repeat delay */
3355 if(event->xkey.time - prev_time < HTML_ATTR(repeat_delay))
3356 return;
3357 prev_time = event->xkey.time;
3358
3359 which = atoi(params[0]);
3360
3361 _XmHTMLDebug(1, ("XmHTML.c: HTMLPageDownOrRight, which = %i\n", which));
3362
3363 if(which == 0 && XtIsManaged(HTML_ATTR(vsb)))
3364 XtCallActionProc(HTML_ATTR(vsb), "PageDownOrRight", event, params, 1);
3365 else if(which == 1 && XtIsManaged(HTML_ATTR(hsb)))
3366 XtCallActionProc(HTML_ATTR(hsb), "PageDownOrRight", event, params, 1);
3367 }
3368
3369 /*****
3370 * Name: HTMLIncrementUpOrLeft
3371 * Return Type: void
3372 * Description: keyboard navigation action routine
3373 * In:
3374 * w: widget id; XmHTMLWidget id if called from within application
3375 * code, work_area if handled by XmHTML itself;
3376 * event: key event;
3377 * params: 0 for IncrementUp, 1 for IncrementLeft
3378 * num_params: always 1
3379 * Returns:
3380 * nothing
3381 * Note:
3382 * This routine also honors the repeatDelay resource.
3383 *****/
3384 static void
HTMLIncrementUpOrLeft(Widget w,XEvent * event,String * params,Cardinal * num_params)3385 HTMLIncrementUpOrLeft(Widget w, XEvent *event, String *params,
3386 Cardinal *num_params)
3387 {
3388 int which;
3389 XmHTMLWidget html;
3390 static Time prev_time = 0;
3391
3392 if(XmIsHTML(w))
3393 html = (XmHTMLWidget)w;
3394 else
3395 html = (XmHTMLWidget)XtParent(w);
3396
3397 if(*num_params != 1 || !XtIsRealized(w))
3398 {
3399 if(*num_params != 1)
3400 _XmHTMLWarning(__WFUNC__(w, "HTMLIncrementUpOrLeft"), XMHTML_MSG_13,
3401 "increment-up-or-left");
3402 return;
3403 }
3404
3405 /* check repeat delay */
3406 if(event->xkey.time - prev_time < HTML_ATTR(repeat_delay))
3407 return;
3408 prev_time = event->xkey.time;
3409
3410 which = atoi(params[0]);
3411
3412 _XmHTMLDebug(1, ("XmHTML.c: HTMLIncrementUpOrLeft, which = %i\n", which));
3413
3414 if(which == 0 && XtIsManaged(HTML_ATTR(vsb)))
3415 XtCallActionProc(HTML_ATTR(vsb), "IncrementUpOrLeft", event,
3416 params, 1);
3417 else if(which == 1 && XtIsManaged(HTML_ATTR(hsb)))
3418 XtCallActionProc(HTML_ATTR(hsb), "IncrementUpOrLeft", event,
3419 params, 1);
3420 }
3421
3422 /*****
3423 * Name: HTMLIncrementDownOrRight
3424 * Return Type: void
3425 * Description: keyboard navigation action routine
3426 * In:
3427 * w: widget id; XmHTMLWidget id if called from within application
3428 * code, work_area if handled by XmHTML itself;
3429 * event: key event;
3430 * params: 0 for IncrementDown, 1 for IncrementRight
3431 * num_params: always 1
3432 * Returns:
3433 * nothing
3434 * Note:
3435 * This routine also honors the repeatDelay resource.
3436 *****/
3437 static void
HTMLIncrementDownOrRight(Widget w,XEvent * event,String * params,Cardinal * num_params)3438 HTMLIncrementDownOrRight(Widget w, XEvent *event, String *params,
3439 Cardinal *num_params)
3440 {
3441 int which;
3442 XmHTMLWidget html;
3443 static Time prev_time = 0;
3444
3445 if(XmIsHTML(w))
3446 html = (XmHTMLWidget)w;
3447 else
3448 html = (XmHTMLWidget)XtParent(w);
3449
3450 if(*num_params != 1 || !XtIsRealized(w))
3451 {
3452 if(*num_params != 1)
3453 _XmHTMLWarning(__WFUNC__(w, "HTMLIncrementDownOrRight"),
3454 XMHTML_MSG_13, "increment-down-or-right");
3455 return;
3456 }
3457
3458 /* check repeat delay */
3459 if(event->xkey.time - prev_time < HTML_ATTR(repeat_delay))
3460 return;
3461 prev_time = event->xkey.time;
3462
3463 which = atoi(params[0]);
3464
3465 _XmHTMLDebug(1, ("XmHTML.c: HTMLIncrementDownOrRight, which = %i\n",
3466 which));
3467
3468 if(which == 0 && XtIsManaged(HTML_ATTR(vsb)))
3469 XtCallActionProc(HTML_ATTR(vsb), "IncrementDownOrRight", event,
3470 params, 1);
3471 else if(which == 1 && XtIsManaged(HTML_ATTR(hsb)))
3472 XtCallActionProc(HTML_ATTR(hsb), "IncrementDownOrRight", event,
3473 params, 1);
3474 }
3475
3476 /*****
3477 * Name: HTMLTopOrBottom
3478 * Return Type: void
3479 * Description: keyboard navigation action routine
3480 * In:
3481 * w: widget id; XmHTMLWidget id if called from within application
3482 * code, work_area if handled by XmHTML itself;
3483 * event: key event;
3484 * params: 0 for top, 1 for bottom
3485 * num_params: always 1
3486 * Returns:
3487 * nothing
3488 * Note:
3489 * no repeatDelay by this action routine, it only moves from top to bottom
3490 * or vice-versa
3491 *****/
3492 static void
HTMLTopOrBottom(Widget w,XEvent * event,String * params,Cardinal * num_params)3493 HTMLTopOrBottom(Widget w, XEvent *event, String *params,
3494 Cardinal *num_params)
3495 {
3496 int which;
3497 XmHTMLWidget html;
3498
3499 if(XmIsHTML(w))
3500 html = (XmHTMLWidget)w;
3501 else
3502 html = (XmHTMLWidget)XtParent(w);
3503
3504 if(*num_params != 1 || !XtIsRealized(w))
3505 {
3506 if(*num_params != 1)
3507 _XmHTMLWarning(__WFUNC__(w, "HTMLTopOrBottom"), XMHTML_MSG_13,
3508 "top-or-bottom");
3509 return;
3510 }
3511 which = atoi(params[0]);
3512
3513 _XmHTMLDebug(1, ("XmHTML.c: HTMLTopOrBottom, which = %i\n", which));
3514
3515 if(which == 0 && XtIsManaged(HTML_ATTR(vsb)))
3516 {
3517 /* no move if already on top */
3518 if(HTML_ATTR(top_line) == 0)
3519 return;
3520
3521 HTML_ATTR(top_line) = 0;
3522 _XmHTMLMoveToPos(HTML_ATTR(vsb), html, 0);
3523 }
3524 else if(which == 1 && XtIsManaged(HTML_ATTR(vsb)))
3525 {
3526 int value;
3527
3528 /* no move if already on bottom */
3529 if(HTML_ATTR(top_line) == HTML_ATTR(nlines))
3530 return;
3531
3532 HTML_ATTR(top_line) = HTML_ATTR(nlines);
3533 value = HTML_ATTR(formatted_height);
3534
3535 /* fix 01/30/97-04, kdh */
3536 _XmHTMLAdjustVerticalScrollValue(HTML_ATTR(vsb), &value);
3537
3538 _XmHTMLMoveToPos(HTML_ATTR(vsb), html, value);
3539 }
3540 }
3541
3542 static void
HTMLTraverseCurrent(Widget w,XEvent * event,String * params,Cardinal * num_params)3543 HTMLTraverseCurrent(Widget w, XEvent *event, String *params,
3544 Cardinal *num_params)
3545 {
3546 if(!XtIsRealized(w))
3547 return;
3548 _XmHTMLProcessTraversal(w, XmTRAVERSE_CURRENT);
3549 }
3550
3551 static void
HTMLTraverseNext(Widget w,XEvent * event,String * params,Cardinal * num_params)3552 HTMLTraverseNext(Widget w, XEvent *event, String *params,
3553 Cardinal *num_params)
3554 {
3555 if(!XtIsRealized(w))
3556 return;
3557 _XmHTMLProcessTraversal(w, XmTRAVERSE_NEXT);
3558 }
3559
3560 static void
HTMLTraversePrev(Widget w,XEvent * event,String * params,Cardinal * num_params)3561 HTMLTraversePrev(Widget w, XEvent *event, String *params,
3562 Cardinal *num_params)
3563 {
3564 if(!XtIsRealized(w))
3565 return;
3566
3567 _XmHTMLProcessTraversal(w, XmTRAVERSE_PREV);
3568 }
3569
3570 static void
HTMLTraverseNextOrPrev(Widget w,XEvent * event,String * params,Cardinal * num_params)3571 HTMLTraverseNextOrPrev(Widget w, XEvent *event, String *params,
3572 Cardinal *num_params)
3573 {
3574 int which;
3575
3576 if(*num_params != 1 || !XtIsRealized(w))
3577 {
3578 if(*num_params != 1)
3579 _XmHTMLWarning(__WFUNC__(w, "HTMLTraverseNextOrPrev"),
3580 XMHTML_MSG_13, "traverse-next-or-prev");
3581 return;
3582 }
3583 which = atoi(params[0]);
3584 if(which == 0)
3585 _XmHTMLProcessTraversal(w, XmTRAVERSE_NEXT_TAB_GROUP);
3586 else
3587 _XmHTMLProcessTraversal(w, XmTRAVERSE_PREV_TAB_GROUP);
3588 }
3589
3590 /*****
3591 * Name: ExtendStart
3592 * Return Type: void
3593 * Description: buttonPress action routine. Initializes a selection when
3594 * not over an anchor, else paints the anchor as being selected.
3595 * In:
3596 *
3597 * Returns:
3598 * nothing.
3599 *****/
3600 static void
ExtendStart(Widget w,XEvent * event,String * params,Cardinal * num_params)3601 ExtendStart(Widget w, XEvent *event, String *params, Cardinal *num_params)
3602 {
3603 /* need to use XtParent since we only get button events from work_area */
3604 XmHTMLWidget html = (XmHTMLWidget)XtParent(w);
3605 XButtonPressedEvent *pressed = (XButtonPressedEvent*)event;
3606 XmHTMLAnchor *anchor = NULL;
3607 XmHTMLWord *anchor_word = NULL;
3608 XmHTMLImage anchor_img;
3609 int x,y;
3610
3611 /* no needless lingering in this routine */
3612 if(XtClass(XtParent(w)) != xmHTMLWidgetClass)
3613 return;
3614
3615 /* we don't do a thing with events generated by button3 */
3616 if(pressed->button == Button3 && HTML_ATTR(arm_callback) == NULL)
3617 return;
3618
3619 _XmHTMLFullDebug(1, ("XmHTML.c: ExtendStart Start\n"));
3620
3621 /* Get coordinates of button event and add core offsets */
3622 x = pressed->x;
3623 y = pressed->y;
3624
3625 /* try to get current anchor element */
3626 if(pressed->button != Button3 &&
3627 (((anchor_word = _XmHTMLGetAnchor(html, x, y, &anchor_img)) != NULL) ||
3628 ((anchor = _XmHTMLGetImageAnchor(html, x, y, &anchor_img)) != NULL)))
3629 {
3630 /*****
3631 * User has selected an anchor. Get the text for this anchor.
3632 * Note: if anchor is NULL it means the user was over a real anchor
3633 * (regular anchor, anchored image or a form image button) and
3634 * anchor_word is non-NULL (this object the referenced URL). If it
3635 * is non-NULL the mouse was over an imagemap, in which case we
3636 * may not show visual feedback to the user.
3637 * I admit, the naming of the variables is rather confusing.
3638 ******/
3639 if(anchor == NULL)
3640 {
3641 /* store anchor & paint as selected */
3642 anchor = anchor_word->owner->anchor;
3643 /*****
3644 * uncheck currently selected anchor if it's not the same as
3645 * the current anchor (mouse dragging)
3646 *****/
3647 if(HTML_ATTR(current_anchor) != NULL &&
3648 HTML_ATTR(current_anchor) != anchor_word->owner)
3649 _XmHTMLPaintAnchorUnSelected(html);
3650 _XmHTMLPaintAnchorSelected(html, anchor_word);
3651 }
3652 else if(HTML_ATTR(selected) != NULL &&
3653 HTML_ATTR(selected) != anchor)
3654 _XmHTMLPaintAnchorUnSelected(html);
3655
3656 /* check for the onMouseDown event */
3657 if(anchor->event_mask & EVENT_MOUSEDOWN)
3658 {
3659 /*****
3660 * Check return value, document might have changed from under
3661 * us upon return.
3662 *****/
3663 if(_XmHTMLEventProcess(html, event, anchor->events->onMouseDown))
3664 return;
3665 }
3666
3667 HTML_ATTR(selected) = anchor;
3668
3669 _XmHTMLFullDebug(1, ("XmHTML.c: ExtendStart, anchor selected is %s\n",
3670 anchor->href));
3671 }
3672 else if(HTML_ATTR(current_anchor) != NULL)
3673 {
3674 ToolkitAbstraction *tka = HTML_ATTR(tka);
3675 /* not over an anchor, unselect current anchor and reset cursor */
3676 _XmHTMLPaintAnchorUnSelected(html);
3677 tka->UndefineCursor(tka->dpy, tka->win);
3678 }
3679
3680 /* remember pointer position and time */
3681 HTML_ATTR(press_x) = pressed->x;
3682 HTML_ATTR(press_y) = pressed->y;
3683 HTML_ATTR(pressed_time) = pressed->time;
3684
3685 if(anchor_word == NULL && anchor == NULL && HTML_ATTR(arm_callback))
3686 _XmHTMLArmCallback(html, event);
3687
3688 _XmHTMLFullDebug(1, ("XmHTML.c: ExtendStart End\n"));
3689 }
3690
3691 /*****
3692 * Name: ExtendAdjust
3693 * Return Type: void
3694 * Description: buttondrag action routine. Adjusts the selection initiated
3695 * by ExtendStart.
3696 * In:
3697 *
3698 * Returns:
3699 * nothing.
3700 *****/
3701 static void
ExtendAdjust(Widget w,XEvent * event,String * params,Cardinal * num_params)3702 ExtendAdjust(Widget w, XEvent *event, String *params, Cardinal *num_params)
3703 {
3704 XmHTMLWidget html;
3705
3706 /* need to use XtParent since we only get motion events from work_area */
3707 if(XtClass(XtParent(w)) != xmHTMLWidgetClass)
3708 return;
3709
3710 html = (XmHTMLWidget)XtParent(w);
3711
3712 _XmHTMLFullDebug(1, ("XmHTML.c: ExtendAdjust Start\n"));
3713
3714 _XmHTMLFullDebug(1, ("XmHTML.c: ExtendAdjust End\n"));
3715
3716 return;
3717 }
3718
3719 /*****
3720 * Name: ExtendEnd
3721 * Return Type: void
3722 * Description: buttonrelease tracking action routine. Terminates the selection
3723 * initiated by ExtendStart. When over an anchor, paints the
3724 * anchor as being deselected. XmNactivateCallback or
3725 * XmNarmCallback callback resources are only called if the
3726 * buttonpress and release occur within a certain time limit
3727 * (XmHTML_MAX_BUTTON_RELEASE_TIME, defined XmHTMLfuncs.h)
3728 * In:
3729 *
3730 * Returns:
3731 * nothing
3732 *****/
3733 static void
ExtendEnd(Widget w,XEvent * event,String * params,Cardinal * num_params)3734 ExtendEnd(Widget w, XEvent *event, String *params, Cardinal *num_params)
3735 {
3736 /* need to use XtParent since we only get button events from work_area */
3737 XmHTMLWidget html = (XmHTMLWidget)XtParent(w);
3738 XButtonReleasedEvent *release = (XButtonReleasedEvent*)event;
3739 XmHTMLAnchor *anchor = NULL;
3740 XmHTMLWord *anchor_word = NULL;
3741 XmHTMLImage anchor_img;
3742 int x,y;
3743
3744 /* no needless lingering in this routine */
3745 if(XtClass(XtParent(w)) != xmHTMLWidgetClass)
3746 return;
3747
3748 /* we don't do a thing with events generated by button3 */
3749 if(release->button == Button3)
3750 return;
3751
3752 _XmHTMLFullDebug(1, ("XmHTML.c: ExtendEnd Start\n"));
3753
3754 /* Get coordinates of button event */
3755 x = release->x;
3756 y = release->y;
3757
3758 /* try to get current anchor element */
3759 if(((anchor_word = _XmHTMLGetAnchor(html, x, y, &anchor_img)) != NULL) ||
3760 ((anchor = _XmHTMLGetImageAnchor(html, x, y, &anchor_img)) != NULL))
3761 {
3762 /*
3763 * OK, release took place over an anchor, see if it falls within the
3764 * allowable time limit and we are still over the anchor selected by
3765 * ExtendStart.
3766 */
3767 if(anchor == NULL)
3768 anchor = anchor_word->owner->anchor;
3769
3770 /*
3771 * If we already have an active anchor and it's different from the
3772 * current anchor, deselect it.
3773 */
3774 if(HTML_ATTR(current_anchor) &&
3775 HTML_ATTR(current_anchor) != anchor_word->owner)
3776 _XmHTMLPaintAnchorUnSelected(html);
3777
3778 /* see if we need to serve the mouseUp event */
3779 if(anchor->event_mask & EVENT_MOUSEUP)
3780 {
3781 /*****
3782 * Process this event. If we get a non-zero return value it
3783 * means that the document has been changed from under us
3784 * so we won't perform any other processing as we most
3785 * likely will be referencing invalid data.
3786 *****/
3787 if(_XmHTMLEventProcess(html, event, anchor->events->onMouseUp))
3788 return;
3789 }
3790
3791 /* this anchor is still in selection */
3792 if(anchor_word)
3793 if(HTML_ATTR(highlight_on_enter))
3794 _XmHTMLPaintAnchorEntry(html, anchor_word->owner);
3795 else
3796 _XmHTMLPaintAnchorUnSelected(html);
3797
3798 _XmHTMLFullDebug(1, ("XmHTML.c: ExtendEnd, anchor selected is %s\n",
3799 anchor->href));
3800 /*
3801 * if we had a selected anchor and it's equal to the current anchor
3802 * and the button was released in time, trigger the activation callback.
3803 */
3804 if(HTML_ATTR(selected) != NULL && anchor == HTML_ATTR(selected) &&
3805 (release->time - HTML_ATTR(pressed_time)) < XmHTML_BUTTON_RELEASE_TIME)
3806 {
3807 /* check for the onClick event */
3808 if(anchor->event_mask & EVENT_CLICK)
3809 {
3810 _XmHTMLDebug(1, ("XmHTML.c:ExtendEnd, onClick: anchor=%x ->\n"
3811 "events=%x -> onClick = %x -> (type=%d, data=%x)\n",
3812 anchor, anchor->events, anchor->events->onClick,
3813 anchor->events->onClick->type,
3814 anchor->events->onClick->data));
3815
3816 /*****
3817 * Process this event. If we get a non-zero return value it
3818 * means that the document has been changed from under us
3819 * so we won't perform any other processing as we most
3820 * likely will be referencing invalid data.
3821 *****/
3822 if(_XmHTMLEventProcess(html, event, anchor->events->onClick))
3823 return;
3824 }
3825
3826 /*****
3827 * Trigger form callback
3828 * No need to check return value, we return after this call.
3829 *****/
3830 if(anchor->url_type == ANCHOR_FORM_IMAGE)
3831 _XmHTMLFormActivate(html, event, anchor_word->form);
3832 else if(HTML_ATTR(activate_callback))
3833 {
3834 /*****
3835 * Trigger activation callback
3836 * No need to check return value, we return after this call.
3837 *****/
3838 _XmHTMLActivateCallback(html, event, anchor);
3839
3840 _XmHTMLFullDebug(1, ("XmHTML.c: ExtendEnd End\n"));
3841 }
3842 return;
3843 }
3844 }
3845
3846 /* unset any previously selected anchor */
3847 if(HTML_ATTR(current_anchor) != NULL)
3848 {
3849 /* keep current anchor selection or unset it */
3850 if(anchor_word)
3851 _XmHTMLPaintAnchorEntry(html, anchor_word->owner);
3852 else
3853 _XmHTMLPaintAnchorUnSelected(html);
3854 }
3855 _XmHTMLFullDebug(1, ("XmHTML.c: ExtendEnd End\n"));
3856
3857 return;
3858 }
3859
3860 /*****
3861 * Name: TrackMotion
3862 * Return Type: void
3863 * Description: mouse tracker; calls XmNanchorTrackCallback and/or HTML4.0
3864 * event processing if entering/leaving an anchor.
3865 * Also calls XmNmotionTrackCallback when installed.
3866 * In:
3867 * w: XmHTMLWidget
3868 * event: MotionEvent structure
3869 * params: additional args, unused
3870 * num_parmas: no of additional args, unused
3871 * Returns:
3872 * nothing
3873 *****/
3874 static void
TrackMotion(Widget w,XEvent * event,String * params,Cardinal * num_params)3875 TrackMotion(Widget w, XEvent *event, String *params, Cardinal *num_params)
3876 {
3877 /* need to use XtParent since we only get motion events from work_area */
3878 XmHTMLWidget html = (XmHTMLWidget)XtParent(w);
3879 XMotionEvent *motion = (XMotionEvent*)event;
3880 XmHTMLAnchor *anchor = NULL;
3881 XmHTMLWord *anchor_word = NULL;
3882 XmHTMLImage anchor_img;
3883 int x = 0, y = 0;
3884 ToolkitAbstraction *tka = NULL;
3885
3886 /* no needless lingering in this routine */
3887 if(XtClass(XtParent(w)) != xmHTMLWidgetClass)
3888 return;
3889
3890 /* ignore if we don't have to make any more feedback to the user */
3891 if(!HTML_ATTR(need_tracking) || event->xany.type != MotionNotify)
3892 return;
3893
3894 /* get handle to the ToolkitAbstraction */
3895 tka = HTML_ATTR(tka);
3896
3897 /* we are already on the correct anchor, just return */
3898 _XmHTMLFullDebug(1, ("XmHTML.c: TrackMotion Start.\n"));
3899
3900 /* save x and y position, we need it to get anchor data */
3901 /* pass down to motion tracker callback if installed */
3902 if(HTML_ATTR(motion_track_callback))
3903 _XmHTMLMotionCallback(html, event);
3904
3905 x = motion->x;
3906 y = motion->y;
3907
3908 /* try to get current anchor element (if any) */
3909 if(((anchor_word = _XmHTMLGetAnchor(html, x, y, &anchor_img)) == NULL) &&
3910 ((anchor = _XmHTMLGetImageAnchor(html, x, y, &anchor_img)) == NULL))
3911 {
3912 _XmHTMLFullDebug(1, ("XmHTML.c: TrackMotion, no current anchor.\n"));
3913
3914 /* invalidate current selection or check event mask if there is one */
3915 if(HTML_ATTR(anchor_current_cursor_element))
3916 {
3917 XmHTMLAnchor *pa = HTML_ATTR(anchor_current_cursor_element);
3918 /*****
3919 * First check for onMouseOut event. Return if document has
3920 * been modified during event processing.
3921 *****/
3922 if(pa->event_mask & EVENT_MOUSEOUT)
3923 {
3924 if(_XmHTMLEventProcess(html, event, pa->events->onMouseOut))
3925 return;
3926 }
3927 if(HTML_ATTR(anchor_track_callback))
3928 _XmHTMLTrackCallback(html, event, NULL);
3929 }
3930
3931 if(HTML_ATTR(highlight_on_enter) && HTML_ATTR(armed_anchor))
3932 _XmHTMLPaintAnchorLeave(html);
3933
3934 HTML_ATTR(armed_anchor) = NULL;
3935 HTML_ATTR(anchor_current_cursor_element) = NULL;
3936 tka->UndefineCursor(tka->dpy, tka->win);
3937 return;
3938 }
3939
3940 if(anchor == NULL)
3941 anchor = anchor_word->owner->anchor;
3942
3943 /* Trigger callback and set cursor if we are entering a new element */
3944 if(anchor != HTML_ATTR(anchor_current_cursor_element))
3945 {
3946 _XmHTMLFullDebug(1, ("XmHTML.c: TrackMotion, new anchor.\n"));
3947
3948 /*****
3949 * When anchors are painted next to each other or the user is
3950 * moving the mouse very fast from one anchor to another, the previous
3951 * check (anchor_word and anchor == NULL) will fail, thereby leaving
3952 * a few loose ends (possible HTML4.0 events and anchor tracking).
3953 * So if we had a current anchor, we need to check if it a mouseOut
3954 * event was present and if so, we need to process this event.
3955 * After that we call the TrackCallback so the application will be
3956 * notified of the fact that the current anchor is no longer valid
3957 * and that the user is moving towards a new anchor.
3958 *****/
3959 if(HTML_ATTR(anchor_current_cursor_element))
3960 {
3961 XmHTMLAnchor *pa = HTML_ATTR(anchor_current_cursor_element);
3962 /*****
3963 * First check for onMouseOut event. Return if document has
3964 * been modified during event processing.
3965 *****/
3966 if(pa->event_mask & EVENT_MOUSEOUT)
3967 {
3968 if(_XmHTMLEventProcess(html, event, pa->events->onMouseOut))
3969 return;
3970 }
3971 if(HTML_ATTR(anchor_track_callback))
3972 _XmHTMLTrackCallback(html, event, NULL);
3973 }
3974
3975 /* Check for onMouseOver event */
3976 if(anchor->event_mask & EVENT_MOUSEOVER)
3977 {
3978 /* Check return value of event processing */
3979 if(_XmHTMLEventProcess(html, event, anchor->events->onMouseOver))
3980 return;
3981 }
3982
3983 /* remove highlight of previous anchor */
3984 if(HTML_ATTR(highlight_on_enter))
3985 {
3986 if(anchor_word)
3987 {
3988 /* unarm previous selection */
3989 if(HTML_ATTR(armed_anchor) &&
3990 HTML_ATTR(armed_anchor) != anchor_word->owner)
3991 _XmHTMLPaintAnchorLeave(html);
3992 /* highlight new selection */
3993 _XmHTMLPaintAnchorEntry(html, anchor_word->owner);
3994 }
3995 else /* unarm previous selection */
3996 if(HTML_ATTR(armed_anchor))
3997 _XmHTMLPaintAnchorLeave(html);
3998 }
3999
4000 HTML_ATTR(anchor_current_cursor_element) = anchor;
4001 _XmHTMLTrackCallback(html, event, anchor);
4002 tka->DefineCursor(tka->dpy, tka->win, HTML_ATTR(anchor_cursor));
4003 return;
4004 }
4005 else if(anchor->event_mask & EVENT_MOUSEMOVE)
4006 {
4007 /*****
4008 * Current anchor. Need to call onMouseMove event if defined.
4009 * No need to check return value as we return immediatly after
4010 * event processing.
4011 *****/
4012 _XmHTMLEventProcess(html, event, anchor->events->onMouseMove);
4013 }
4014 /* we are already on the correct anchor, just return */
4015 _XmHTMLFullDebug(1, ("XmHTML.c: TrackMotion End, over current anchor\n"));
4016 }
4017
4018 /*****
4019 * Name: TrackFocus
4020 * Return Type: void
4021 * Description: focus tracker; calls XmNanchorTrackCallback if
4022 * entering/leaving an anchor.
4023 * Also calls XmNfocusCallback when installed.
4024 * In:
4025 * w: XmHTMLWidget
4026 * event: FocusIn/FocusOut/Leave/Event structure
4027 * params: additional args, unused
4028 * num_parmas: no of additional args, unused
4029 * Returns:
4030 * nothing
4031 *****/
4032 static void
TrackFocus(Widget w,XEvent * event,String * params,Cardinal * num_params)4033 TrackFocus(Widget w, XEvent *event, String *params, Cardinal *num_params)
4034 {
4035 /* need to use XtParent since we only get motion events from work_area */
4036 XmHTMLWidget html = (XmHTMLWidget)XtParent(w);
4037 ToolkitAbstraction *tka = NULL;
4038
4039 /* no needless lingering in this routine */
4040 if(XtClass(XtParent(w)) != xmHTMLWidgetClass)
4041 return;
4042
4043 /* ignore if we don't have to make any feedback to the user */
4044 if(!HTML_ATTR(need_tracking))
4045 return;
4046
4047 /* get handle to the ToolkitAbstraction */
4048 tka = HTML_ATTR(tka);
4049
4050 /* we are already on the correct anchor, just return */
4051 _XmHTMLFullDebug(1, ("XmHTML.c: TrackFocus Start.\n"));
4052
4053 /* check event and act accordingly */
4054 switch(event->type)
4055 {
4056 case FocusIn:
4057 _XmHTMLFullDebug(1, ("XmHTML.c: TrackFocus, FocusIn.\n"));
4058
4059 _XmHTMLFocusInCallback(html, event);
4060
4061 /*****
4062 * Might seem silly to test for the presence of a window in the
4063 * current tka, but in some very rare cases it can happen that a
4064 * FocusIn event is generated *before* a SubStructure event is
4065 * generated. This leads to the weird possibility that we have an
4066 * event on a window which has yet to be mapped to the screen!
4067 * This leads to a BadValue error and so we need to check if we have
4068 * a valid window id before doing anything with it.
4069 *****/
4070 if(tka->win)
4071 tka->UndefineCursor(tka->dpy, tka->win);
4072 break;
4073 case LeaveNotify:
4074 /*****
4075 * LeaveNotify Events occur when the pointer focus is transferred
4076 * from the DrawingArea child to another window. This can occur
4077 * when the pointer is moved outside the Widget *OR* when a
4078 * ButtonPress event occurs ON the drawingArea. When that happens,
4079 * the pointer focus is transferred from the drawingArea to it's
4080 * parent, being the Widget itself. In this case the detail
4081 * detail member of the XEnterWindowEvent will be NotifyAncestor,
4082 * and we would want to ignore this event (as it will cause a
4083 * flicker of the screen or an unnecessary call to any installed
4084 * callbacks).
4085 *****/
4086 if(((XEnterWindowEvent*)event)->detail == NotifyAncestor)
4087 return;
4088 /* else fall through */
4089 case FocusOut:
4090 _XmHTMLFullDebug(1, ("XmHTML.c: TrackFocus, "
4091 "%s.\n", event->type == LeaveNotify ?
4092 "LeaveNotify" : "FocusOut"));
4093
4094 /* invalidate current selection if there is one */
4095 if(HTML_ATTR(anchor_track_callback) &&
4096 HTML_ATTR(anchor_current_cursor_element))
4097 _XmHTMLTrackCallback(html, event, NULL);
4098
4099 /* loses focus, remove anchor highlight */
4100 if(HTML_ATTR(highlight_on_enter) && HTML_ATTR(armed_anchor))
4101 _XmHTMLPaintAnchorLeave(html);
4102
4103 HTML_ATTR(armed_anchor) = NULL;
4104 HTML_ATTR(anchor_current_cursor_element) = NULL;
4105 tka->UndefineCursor(tka->dpy, tka->win);
4106
4107 /* final step: call focusOut callback */
4108 if(event->type == FocusOut)
4109 _XmHTMLFocusOutCallback(html, event);
4110 /* fall through */
4111 default:
4112 /* uninteresting event, throw away */
4113 break;
4114 }
4115 }
4116
4117 /*****
4118 * Name: CheckAnchorUnderlining
4119 * Return Type: void
4120 * Description: validate anchor underlining enumeration values.
4121 * In:
4122 * html: target widget
4123 * req: requester widget
4124 * Returns:
4125 * nothing.
4126 *****/
4127 static void
CheckAnchorUnderlining(XmHTMLWidget html,XmHTMLWidget req)4128 CheckAnchorUnderlining(XmHTMLWidget html, XmHTMLWidget req)
4129 {
4130 /* Anchor Underlining values */
4131 if(!XmRepTypeValidValue(underline_repid, req->html.anchor_underline_type,
4132 (Widget)html))
4133 HTML_ATTR(anchor_underline_type) = XmSINGLE_LINE;
4134 else
4135 HTML_ATTR(anchor_underline_type) = ATTR_HTML(req,anchor_underline_type);
4136
4137 /* Set corresponding private resources */
4138 switch(HTML_ATTR(anchor_underline_type))
4139 {
4140 case XmNO_LINE:
4141 HTML_ATTR(anchor_line) = NO_LINE;
4142 break;
4143 case XmSINGLE_DASHED_LINE:
4144 HTML_ATTR(anchor_line) = LINE_DASHED|LINE_UNDER|LINE_SINGLE;
4145 break;
4146 case XmDOUBLE_LINE:
4147 HTML_ATTR(anchor_line) = LINE_SOLID|LINE_UNDER|LINE_DOUBLE;;
4148 break;
4149 case XmDOUBLE_DASHED_LINE:
4150 HTML_ATTR(anchor_line) = LINE_DASHED|LINE_UNDER|LINE_DOUBLE;;
4151 break;
4152 case XmSINGLE_LINE: /* default */
4153 default:
4154 HTML_ATTR(anchor_line) = LINE_SOLID | LINE_UNDER | LINE_SINGLE;
4155 break;
4156 }
4157
4158 /* Visited Anchor Underlining values */
4159 if(!XmRepTypeValidValue(underline_repid,
4160 ATTR_HTML(req, anchor_visited_underline_type), (Widget)html))
4161 HTML_ATTR(anchor_visited_underline_type) = XmSINGLE_LINE;
4162 else
4163 HTML_ATTR(anchor_visited_underline_type) =
4164 ATTR_HTML(req, anchor_visited_underline_type);
4165
4166 /* Set corresponding private resources */
4167 switch(HTML_ATTR(anchor_visited_underline_type))
4168 {
4169 case XmNO_LINE:
4170 HTML_ATTR(anchor_visited_line) = NO_LINE;
4171 break;
4172 case XmSINGLE_DASHED_LINE:
4173 HTML_ATTR(anchor_visited_line) = LINE_DASHED|LINE_UNDER|LINE_SINGLE;
4174 break;
4175 case XmDOUBLE_LINE:
4176 HTML_ATTR(anchor_visited_line) = LINE_SOLID|LINE_UNDER|LINE_DOUBLE;
4177 break;
4178 case XmDOUBLE_DASHED_LINE:
4179 HTML_ATTR(anchor_visited_line) = LINE_DASHED|LINE_UNDER|LINE_DOUBLE;
4180 break;
4181 case XmSINGLE_LINE: /* default */
4182 default:
4183 HTML_ATTR(anchor_visited_line) = LINE_SOLID|LINE_UNDER|LINE_SINGLE;
4184 break;
4185 }
4186
4187 /* Target Anchor Underlining values */
4188 if(!XmRepTypeValidValue(underline_repid,
4189 HTML_ATTR(anchor_target_underline_type), (Widget)html))
4190 ATTR_HTML(req, anchor_target_underline_type) = XmSINGLE_DASHED_LINE;
4191 else
4192 HTML_ATTR(anchor_target_underline_type) =
4193 ATTR_HTML(req, anchor_target_underline_type);
4194
4195 /* Set corresponding private resources */
4196 switch(HTML_ATTR(anchor_target_underline_type))
4197 {
4198 case XmNO_LINE:
4199 HTML_ATTR(anchor_target_line) = NO_LINE;
4200 break;
4201 case XmSINGLE_LINE:
4202 HTML_ATTR(anchor_target_line) = LINE_SOLID|LINE_UNDER|LINE_SINGLE;
4203 break;
4204 case XmDOUBLE_LINE:
4205 HTML_ATTR(anchor_target_line) = LINE_SOLID|LINE_UNDER|LINE_DOUBLE;
4206 break;
4207 case XmDOUBLE_DASHED_LINE:
4208 HTML_ATTR(anchor_target_line) = LINE_DASHED|LINE_UNDER|LINE_DOUBLE;
4209 break;
4210 case XmSINGLE_DASHED_LINE: /* default */
4211 default:
4212 HTML_ATTR(anchor_target_line) = LINE_DASHED|LINE_UNDER|LINE_SINGLE;
4213 break;
4214 }
4215 }
4216
4217 /*****
4218 * Name: CheckAlignment
4219 * Return Type: void
4220 * Description: checks and sets the alignment resources
4221 * In:
4222 * html: target widget
4223 * req: requestor widget
4224 * Returns:
4225 * nothing.
4226 *****/
4227 static void
CheckAlignment(XmHTMLWidget html,XmHTMLWidget req)4228 CheckAlignment(XmHTMLWidget html, XmHTMLWidget req)
4229 {
4230 /* Set default alignment */
4231 if(ATTR_HTML(req, enable_outlining))
4232 HTML_ATTR(default_halign) = XmHALIGN_JUSTIFY;
4233 else
4234 {
4235 /* default alignment depends on string direction */
4236 if(HTML_ATTR(string_direction) == XmSTRING_DIRECTION_R_TO_L)
4237 HTML_ATTR(default_halign) = XmHALIGN_RIGHT;
4238 else
4239 HTML_ATTR(default_halign) = XmHALIGN_LEFT;
4240
4241 /* verify alignment */
4242 if(XmRepTypeValidValue(string_repid, ATTR_HTML(req, alignment),
4243 (Widget)html))
4244 {
4245 if(HTML_ATTR(alignment) == XmALIGNMENT_BEGINNING)
4246 HTML_ATTR(default_halign) = XmHALIGN_LEFT;
4247 if(HTML_ATTR(alignment) == XmALIGNMENT_END)
4248 HTML_ATTR(default_halign) = XmHALIGN_RIGHT;
4249 else if(HTML_ATTR(alignment) == XmALIGNMENT_CENTER)
4250 HTML_ATTR(default_halign) = XmHALIGN_CENTER;
4251 }
4252 }
4253 }
4254
4255 /*****
4256 * Name: _XmHTMLCvtStringToWarning
4257 * Return Type: Boolean
4258 * Description: converts a XmHTML XmCHTMLWarningType to it's internal value.
4259 * In:
4260 * dpy: display with which this conversion is associated;
4261 * args: any XrmValue arguments to this converter. Always NULL;
4262 * num_args: no of args. Always 0;
4263 * from_val: address and size of value to be converted;
4264 * to_val: address where the converted value must be stored;
4265 * convert..: data to be passed to the destructor routine. Since this
4266 * converter doesn't allocate any data, this argument is ignored.
4267 * Returns:
4268 * True when the conversion was successfull, False if not.
4269 *****/
4270 Boolean
_XmHTMLCvtStringToWarning(Display * dpy,XrmValuePtr args,Cardinal * num_args,XrmValuePtr from_val,XrmValuePtr to_val,XtPointer * converter_data)4271 _XmHTMLCvtStringToWarning(Display *dpy, XrmValuePtr args, Cardinal *num_args,
4272 XrmValuePtr from_val, XrmValuePtr to_val, XtPointer *converter_data)
4273 {
4274 static String warn_styles[] = {"unknown_element", "bad", "open_block",
4275 "close_block", "open_element", "nested", "violation"};
4276 Byte warn_values[] = {XmHTML_UNKNOWN_ELEMENT, XmHTML_BAD,
4277 XmHTML_OPEN_BLOCK, XmHTML_CLOSE_BLOCK, XmHTML_OPEN_ELEMENT,
4278 XmHTML_NESTED, XmHTML_VIOLATION};
4279
4280 String warning = NULL;
4281 int i;
4282 String ptr = (String)from_val->addr;
4283 Byte ret_val = XmHTML_NONE;
4284
4285 if(*num_args != 0)
4286 {
4287 _XmHTMLWarning(__WFUNC__(NULL, "_XmHTMLCvtStringToWarning"),
4288 XMHTML_MSG_19);
4289 return(False);
4290 }
4291
4292 /* hmm, shouldn't happen */
4293 if(ptr == NULL || *ptr == '\0' || from_val->size < 3)
4294 goto end;
4295
4296 /* copy so we scan it safely */
4297 warning = my_strndup(ptr, from_val->size);
4298
4299 /* check if we have NONE */
4300 if(my_strcasestr(warning, "none"))
4301 goto end;
4302
4303 /* check if we have HTML_ALL */
4304 if(my_strcasestr(warning, "all"))
4305 {
4306 ret_val = XmHTML_ALL;
4307 goto end;
4308 }
4309
4310 #define NUM_WARNINGS 7
4311 /* now scan the string for the possible warning types */
4312 for(i = 0; i < NUM_WARNINGS; i++)
4313 {
4314 if(my_strcasestr(warning, warn_styles[i]))
4315 ret_val |= warn_values[i];
4316 }
4317 #undef NUM_WARNINGS
4318
4319 /* this is an error */
4320 if(ret_val == XmHTML_NONE)
4321 {
4322 _XmHTMLWarning(__WFUNC__(NULL, "_XmHTMLCvtStringToWarning"),
4323 XMHTML_MSG_20, warning);
4324 free(warning);
4325 return(False);
4326 }
4327
4328 end:
4329 /* no longer needed, free it */
4330 if(warning != NULL)
4331 free(warning);
4332
4333 if(to_val->addr != NULL)
4334 {
4335 if(to_val->size < sizeof(Byte))
4336 {
4337 to_val->size = sizeof(Byte);
4338 return(False);
4339 }
4340 *(Byte*)to_val->addr = ret_val;
4341 return(True);
4342 }
4343 else
4344 {
4345 static Byte static_val;
4346 static_val = ret_val;
4347 to_val->addr = (char *)&static_val;
4348 to_val->size = sizeof(Byte);
4349 return(True);
4350 }
4351 }
4352
4353 /*****
4354 * Name: _XmHTMLAdjustVerticalScrollValue
4355 * Return Type: void
4356 * Description: adjust slider value so it does not exceed the maximum
4357 * slider value.
4358 * In:
4359 * vsb: vertical scrollbar widget id;
4360 * value: current slider value.
4361 * Returns:
4362 * nothing, but value can be updated upon return.
4363 *****/
4364 void
_XmHTMLAdjustVerticalScrollValue(Widget vsb,int * value)4365 _XmHTMLAdjustVerticalScrollValue(Widget vsb, int *value)
4366 {
4367 int max = 0, size = 0;
4368 XtVaGetValues(vsb,
4369 XmNmaximum, &max,
4370 XmNsliderSize, &size,
4371 NULL);
4372 if(*value > (max - size))
4373 *value = (max - size);
4374 }
4375
4376 /********
4377 ****** Public XmHTML Functions
4378 ********/
4379
4380 /*****
4381 * Name: XmCreateHTML
4382 * Return Type: Widget
4383 * Description: creates a XmHTML widget
4384 * In:
4385 * parent: widget to act as parent for this new XmHTMLWidget
4386 * name: name for the new widget
4387 * arglist: arguments for this new XmHTMLWidget
4388 * argcount: no of arguments
4389 * Returns:
4390 * a newly created widget. This routine exits if parent is NULL or a subclass
4391 * of XmGadget.
4392 *****/
4393 Widget
XmCreateHTML(Widget parent,String name,ArgList arglist,Cardinal argcount)4394 XmCreateHTML(Widget parent, String name, ArgList arglist, Cardinal argcount)
4395 {
4396 #ifdef MOTIF_IN_DLL
4397 /*****
4398 * See comment above (search for other instance of this ifdef)
4399 * We must do this BEFORE creating the widget or we'd have serious
4400 * problems...
4401 *****/
4402 xmHTMLClassRec.core_class.superclass = (WidgetClass)&xmManagerClassRec;
4403 #endif
4404
4405 if(parent && !XmIsGadget(parent))
4406 return(XtCreateWidget(name, xmHTMLWidgetClass, parent,
4407 arglist, argcount));
4408
4409 /* invalid parent, needs a widget, not a gadget */
4410 __XmHTMLWarning(__WFUNC__(parent, "XmCreateHTML"),
4411 XMHTML_MSG_34, (parent ? "Invalid" : "NULL"), "XmCreateHTML");
4412
4413 /* keep compiler happy */
4414 return(NULL);
4415 }
4416