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