1 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2  *
3  * ***** BEGIN LICENSE BLOCK *****
4  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5  *
6  * The contents of this file are subject to the Mozilla Public License Version
7  * 1.1 (the "License"); you may not use this file except in compliance with
8  * the License. You may obtain a copy of the License at
9  * http://www.mozilla.org/MPL/
10  *
11  * Software distributed under the License is distributed on an "AS IS" basis,
12  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13  * for the specific language governing rights and limitations under the
14  * License.
15  *
16  * The Original Code is the Microline Widget Library, originally made available under the NPL by Neuron Data <http://www.neurondata.com>.
17  *
18  * The Initial Developer of the Original Code is
19  * Netscape Communications Corporation.
20  * Portions created by the Initial Developer are Copyright (C) 1998
21  * the Initial Developer. All Rights Reserved.
22  *
23  * Contributor(s):
24  *
25  * Alternatively, the contents of this file may be used under the terms of
26  * either the GNU General Public License Version 2 or later (the "GPL"), or
27  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
28  * in which case the provisions of the GPL or the LGPL are applicable instead
29  * of those above. If you wish to allow use of your version of this file only
30  * under the terms of either the GPL or the LGPL, and not to allow others to
31  * use your version of this file under the terms of the MPL, indicate your
32  * decision by deleting the provisions above and replace them with the notice
33  * and other provisions required by the GPL or the LGPL. If you do not delete
34  * the provisions above, a recipient may use your version of this file under
35  * the terms of any one of the MPL, the GPL or the LGPL.
36  *
37  * In addition, as a special exception to the GNU GPL, the copyright holders
38  * give permission to link the code of this program with the Motif and Open
39  * Motif libraries (or with modified versions of these that use the same
40  * license), and distribute linked combinations including the two. You
41  * must obey the GNU General Public License in all respects for all of
42  * the code used other than linking with Motif/Open Motif. If you modify
43  * this file, you may extend this exception to your version of the file,
44  * but you are not obligated to do so. If you do not wish to do so,
45  * delete this exception statement from your version.
46  *
47  * ***** END LICENSE BLOCK ***** */
48 
49 #include "ProgressP.h"
50 #include <stdio.h>
51 #include <sys/time.h>
52 #include <time.h>
53 
54 static void ClassInitialize(void);
55 static void Initialize(Widget , Widget, ArgList, Cardinal *);
56 static void Resize(Widget);
57 static void Destroy(Widget);
58 static void Realize(Widget w, XtValueMask *valueMask,
59 	XSetWindowAttributes *attr);
60 static void Redisplay(Widget, XEvent *, Region);
61 static Boolean SetValues(Widget, Widget, Widget, ArgList, Cardinal *);
62 static void CopyFontList(XmLProgressWidget p);
63 static void TimeStr(char *, int);
64 static void DrawBarMeter(XmLProgressWidget p, XRectangle *rect);
65 static void DrawBoxesMeter(XmLProgressWidget p, XRectangle *rect);
66 static void DrawString(XmLProgressWidget, XmString, int, int,
67 	int, XRectangle *, XRectangle *);
68 static Boolean CvtStringToMeterStyle(Display *dpy, XrmValuePtr args,
69 	Cardinal *numArgs, XrmValuePtr fromVal, XrmValuePtr toVal,
70 	XtPointer *data);
71 
72 static XtResource resources[] =
73 	{
74 		{
75 		XmNcompleteValue, XmCCompleteValue,
76 		XtRInt, sizeof(int),
77 		XtOffset(XmLProgressWidget, progress.completeValue),
78 		XtRImmediate, (caddr_t)100
79 		},
80 		{
81 		XmNnumBoxes, XmCNumBoxes,
82 		XtRInt, sizeof(int),
83 		XtOffset(XmLProgressWidget, progress.numBoxes),
84 		XtRImmediate, (caddr_t)10
85 		},
86 		{
87 		XmNvalue, XmCValue,
88 		XtRInt, sizeof(int),
89 		XtOffset(XmLProgressWidget, progress.value),
90 		XtRImmediate, (caddr_t)0
91 		},
92 		{
93 		XmNfontList, XmCFontList,
94 		XmRFontList, sizeof(XmFontList),
95 		XtOffset(XmLProgressWidget, progress.fontList),
96 		XmRImmediate, (XtPointer)0,
97 		},
98 		{
99 		XmNmeterStyle, XmCMeterStyle,
100 		XmRMeterStyle, sizeof(unsigned char),
101 		XtOffset(XmLProgressWidget, progress.meterStyle),
102 		XmRImmediate, (XtPointer)XmMETER_BAR,
103 		},
104 		{
105 		XmNshowTime, XmCShowTime,
106 		XmRBoolean, sizeof(Boolean),
107 		XtOffset(XmLProgressWidget, progress.showTime),
108 		XmRImmediate, (XtPointer)False
109 		},
110 		{
111 		XmNshowPercentage, XmCShowPercentage,
112 		XmRBoolean, sizeof(Boolean),
113 		XtOffset(XmLProgressWidget, progress.showPercentage),
114 		XmRImmediate, (XtPointer)True
115 		}
116 	};
117 
118 XmLProgressClassRec xmlProgressClassRec =
119 	{
120 		{ /* Core */
121 		(WidgetClass)&xmPrimitiveClassRec,      /* superclass */
122 		"XmLProgress",                          /* class_name */
123 		sizeof(XmLProgressRec),                 /* widget_size */
124 		ClassInitialize,                        /* class_initialize */
125 		NULL,                                   /* class_part_initialize */
126 		FALSE,                                  /* class_inited */
127 		(XtInitProc)Initialize,                 /* initialize */
128 		NULL,                                   /* initialize_hook */
129 		(XtRealizeProc)Realize,                 /* realize */
130 		NULL,                                   /* actions */
131 		0,                                      /* num_actions */
132 		resources,                              /* resources */
133 		XtNumber(resources),                    /* num_resources */
134 		NULLQUARK,                              /* xrm_class */
135 		TRUE,                                   /* compress_motion */
136 		FALSE,                                  /* compress_exposure */
137 		TRUE,                                   /* compress_enterleave */
138 		TRUE,                                   /* visible_interest */
139 		(XtWidgetProc)Destroy,                  /* destroy */
140 		(XtWidgetProc)Resize,                   /* resize */
141 		(XtExposeProc)Redisplay,                /* expose */
142 		(XtSetValuesFunc)SetValues,             /* set_values */
143 		NULL,                                   /* set_values_hook */
144 		XtInheritSetValuesAlmost,               /* set_values_almost */
145 		NULL,                                   /* get_values_hook */
146 		NULL,                                   /* accept_focus */
147 		XtVersion,                              /* version */
148 		NULL,                                   /* callback_private */
149 		XtInheritTranslations,                  /* tm_table */
150 		NULL,                                   /* query_geometry */
151 		NULL,                                   /* display_accelerator */
152 		NULL,                                   /* extension */
153 		},
154 		{ /* Primitive */
155 		(XtWidgetProc)_XtInherit,               /* border_highlight */
156 		(XtWidgetProc)_XtInherit,               /* border_unhighlight */
157 		XtInheritTranslations,                  /* translations */
158 		NULL,                                   /* arm_and_activate */
159 		NULL,                                   /* syn_resources */
160 		0,                                      /* num_syn_resources */
161 		NULL,                                   /* extension */
162 		},
163 		{ /* Progress */
164 		0,                                      /* unused */
165 		}
166 	};
167 
168 WidgetClass xmlProgressWidgetClass = (WidgetClass)&xmlProgressClassRec;
169 
170 static void
ClassInitialize(void)171 ClassInitialize(void)
172 	{
173 	XmLInitialize();
174 
175 	XtSetTypeConverter(XmRString, XmRMeterStyle, CvtStringToMeterStyle,
176 		0, 0, XtCacheNone, 0);
177 	}
178 
179 static void
Initialize(Widget reqW,Widget newW,ArgList args,Cardinal * narg)180 Initialize(Widget reqW,
181 	   Widget newW,
182 	   ArgList args,
183 	   Cardinal *narg)
184 	{
185 	XmLProgressWidget p;
186 
187 	p = (XmLProgressWidget)newW;
188 
189 	if (!p->core.width)
190 		p->core.width = 200;
191 	if (!p->core.height)
192 		p->core.height = 30;
193 
194 	p->progress.gc = 0;
195 	p->progress.startTime = time(0);
196 	CopyFontList(p);
197 	if (p->progress.completeValue < 1)
198 		{
199 		XmLWarning(newW, "Initialize() - complete value can't be < 1");
200 		p->progress.completeValue = 1;
201 		}
202 	if (p->progress.numBoxes < 1)
203 		{
204 		XmLWarning(newW, "Initialize() - number of boxes can't be < 1");
205 		p->progress.numBoxes = 1;
206 		}
207 	if (p->progress.value < 0)
208 		{
209 		XmLWarning(newW, "Initialize() - value can't be < 0");
210 		p->progress.value = 0;
211 		}
212 	if (p->progress.value > p->progress.completeValue)
213 		{
214 		XmLWarning(newW, "Initialize() - value can't be > completeValue");
215 		p->progress.value = p->progress.completeValue;
216 		}
217 	XtVaSetValues(newW, XmNtraversalOn, False, NULL);
218 	}
219 
220 static void
Resize(Widget w)221 Resize(Widget w)
222 	{
223 	Display *dpy;
224 	Window win;
225 
226 	if (!XtIsRealized(w))
227 		return;
228 	dpy = XtDisplay(w);
229 	win = XtWindow(w);
230 	XClearArea(dpy, win, 0, 0, 0, 0, True);
231 	}
232 
233 static void
Destroy(Widget w)234 Destroy(Widget w)
235 	{
236 	Display *dpy;
237 	XmLProgressWidget p;
238 
239 	p = (XmLProgressWidget)w;
240 	dpy = XtDisplay(w);
241 	if (p->progress.gc)
242 		{
243 		XFreeGC(dpy, p->progress.gc);
244 		XFreeFont(dpy, p->progress.fallbackFont);
245 		}
246 	XmFontListFree(p->progress.fontList);
247 	}
248 
249 static void
Realize(Widget w,XtValueMask * valueMask,XSetWindowAttributes * attr)250 Realize(Widget w,
251 	XtValueMask *valueMask,
252 	XSetWindowAttributes *attr)
253 	{
254 	XmLProgressWidget p;
255 	Display *dpy;
256 	WidgetClass superClass;
257 	XtRealizeProc realize;
258 	XGCValues values;
259 	/*	XtGCMask mask;*/
260 
261 	p = (XmLProgressWidget)w;
262 	dpy = XtDisplay(p);
263 	superClass = xmlProgressWidgetClass->core_class.superclass;
264 	realize = superClass->core_class.realize;
265 	(*realize)(w, valueMask, attr);
266 
267 	if (!p->progress.gc)
268 		{
269 		p->progress.fallbackFont = XLoadQueryFont(dpy, "fixed");
270 		values.font = p->progress.fallbackFont->fid;
271 		p->progress.gc = XCreateGC(dpy, XtWindow(p), GCFont, &values);
272 		}
273 	}
274 
275 static void
Redisplay(Widget w,XEvent * event,Region region)276 Redisplay(Widget w,
277 	  XEvent *event,
278 	  Region region)
279 	{
280 	XmLProgressWidget p;
281 	Display *dpy;
282 	Window win;
283 	XRectangle rect;
284 	int st;
285 
286 	if (!XtIsRealized(w) || !w->core.visible)
287 		return;
288 
289 	p = (XmLProgressWidget)w;
290 	dpy = XtDisplay(w);
291 	win = XtWindow(w);
292 	st = p->primitive.shadow_thickness;
293 	rect.x = st;
294 	rect.y = st;
295 	rect.width = p->core.width - st * 2;
296 	rect.height = p->core.height - st * 2;
297 
298 	if (p->progress.meterStyle == XmMETER_BAR)
299 		DrawBarMeter(p, &rect);
300 	else if (p->progress.meterStyle == XmMETER_BOXES)
301 		DrawBoxesMeter(p, &rect);
302 
303 #ifdef MOTIF11
304 	_XmDrawShadow(dpy, win,
305 		p->primitive.bottom_shadow_GC,
306 		p->primitive.top_shadow_GC,
307 		p->primitive.shadow_thickness,
308 		0, 0, p->core.width, p->core.height);
309 #else
310 	_XmDrawShadows(dpy, win,
311 		p->primitive.top_shadow_GC,
312 		p->primitive.bottom_shadow_GC,
313 		0, 0, p->core.width, p->core.height,
314 		p->primitive.shadow_thickness,
315 		XmSHADOW_IN);
316 #endif
317 	}
318 
319 static void
DrawBoxesMeter(XmLProgressWidget p,XRectangle * rect)320 DrawBoxesMeter(XmLProgressWidget p,
321 	       XRectangle *rect)
322 	{
323 	Display *dpy;
324 	Window win;
325 	int i, j, st, nb, x1, x2;
326 
327 	dpy = XtDisplay(p);
328 	win = XtWindow(p);
329 	st = p->primitive.shadow_thickness;
330 	nb = p->progress.numBoxes;
331 	if (nb * st * 2 > (int)rect->width)
332 		return;
333 
334 	if (p->progress.completeValue)
335 		j = (int)((long)nb * (long)p->progress.value /
336 			(long)p->progress.completeValue);
337 	else
338 		j = 0;
339 	x2 = 0;
340 	for (i = 0; i < nb; i++)
341 		{
342 		if (i < j)
343 			XSetForeground(dpy, p->progress.gc, p->primitive.foreground);
344 		else
345 			XSetForeground(dpy, p->progress.gc, p->core.background_pixel);
346 		x1 = x2;
347 		if (i == nb - 1)
348 			x2 = rect->width;
349 		else
350 			x2 = ((int)rect->width * (i + 1)) / nb;
351 		XFillRectangle(dpy, win, p->progress.gc,
352 			rect->x + x1 + st, rect->y + st,
353 			x2 - x1 - st * 2, rect->height - st * 2);
354 #ifdef MOTIF11
355 		_XmDrawShadow(dpy, win,
356 			p->primitive.bottom_shadow_GC,
357 			p->primitive.top_shadow_GC,
358 			p->primitive.shadow_thickness,
359 			rect->x + x1, rect->y,
360 			x2 - x1, rect->height);
361 #else
362 		_XmDrawShadows(dpy, win,
363 			p->primitive.top_shadow_GC,
364 			p->primitive.bottom_shadow_GC,
365 			rect->x + x1, rect->y,
366 			x2 - x1, rect->height,
367 			p->primitive.shadow_thickness,
368 			XmSHADOW_IN);
369 #endif
370 		}
371 	}
372 
373 static void
DrawBarMeter(XmLProgressWidget p,XRectangle * rect)374 DrawBarMeter(XmLProgressWidget p,
375 	     XRectangle *rect)
376 	{
377 	Display *dpy;
378 	Window win;
379 	int timeLeft, timeSoFar;
380 	time_t currentTime;
381 	XmString str;
382 	Dimension strWidth, strHeight;
383 	XRectangle lRect, rRect;
384 	int percent;
385 	char c[10];
386 	long l;
387 
388 	dpy = XtDisplay(p);
389 	win = XtWindow(p);
390 
391 	/* Left Rect */
392 	if (p->progress.completeValue)
393 		l = (long)rect->width * (long)p->progress.value /
394 			(long)p->progress.completeValue;
395 	else
396 		l = 0;
397 	lRect.x = rect->x;
398 	lRect.y = rect->y;
399 	lRect.width = (Dimension)l;
400 	lRect.height = rect->height;
401 	XSetForeground(dpy, p->progress.gc, p->primitive.foreground);
402 	XFillRectangle(dpy, win, p->progress.gc, lRect.x, lRect.y,
403 		lRect.width, lRect.height);
404 
405 	/* Right Rect */
406 	rRect.x = rect->x + (int)l;
407 	rRect.y = rect->y;
408 	rRect.width = rect->width - (Dimension)l;
409 	rRect.height = rect->height;
410 	XSetForeground(dpy, p->progress.gc, p->core.background_pixel);
411 	XFillRectangle(dpy, win, p->progress.gc, rRect.x, rRect.y,
412 		rRect.width, rRect.height);
413 
414 	if (p->progress.completeValue)
415 		percent = (int)(((long)p->progress.value * 100) /
416 			(long)p->progress.completeValue);
417 	else
418 		percent = 0;
419 
420 	/* percent complete */
421 	sprintf(c, "%d%c", percent, '%');
422 	str = XmStringCreateSimple(c);
423 	XmStringExtent(p->progress.fontList, str, &strWidth, &strHeight);
424 	if (p->progress.showPercentage)
425 		DrawString(p, str, rect->x + rect->width / 2 - (int)strWidth / 2,
426 			rect->y + rect->height / 2 - (int)strHeight / 2, strWidth,
427 			&lRect, &rRect);
428 	XmStringFree(str);
429 
430 	/* Left Time */
431 	currentTime = time(0);
432 	timeSoFar = (int)(currentTime - p->progress.startTime);
433 	if (p->progress.showTime && p->progress.value &&
434 		p->progress.value != p->progress.completeValue && timeSoFar)
435 		{
436 		TimeStr(c, timeSoFar);
437 		str = XmStringCreateSimple(c);
438 		XmStringExtent(p->progress.fontList, str,
439 			&strWidth, &strHeight);
440 		DrawString(p, str, rect->x + 5, rect->y + rect->height / 2 -
441 			(int)strHeight / 2, strWidth, &lRect, &rRect);
442 		XmStringFree(str);
443 		}
444 
445 	/* Right Time */
446 	timeLeft = 0;
447 	if (percent)
448 		timeLeft = (timeSoFar * 100 / percent) - timeSoFar;
449 	if (p->progress.showTime && percent && percent != 100 && timeLeft)
450 		{
451 		TimeStr(c, timeLeft);
452 		str = XmStringCreateSimple(c);
453 		XmStringExtent(p->progress.fontList, str,
454 			&strWidth, &strHeight);
455 		DrawString(p, str, rect->x + rect->width - strWidth - 5,
456 			rect->y + rect->height / 2 - (int)strHeight / 2,
457 			strWidth, &lRect, &rRect);
458 		XmStringFree(str);
459 		}
460 	}
461 
462 static void
DrawString(XmLProgressWidget p,XmString str,int x,int y,int strWidth,XRectangle * lRect,XRectangle * rRect)463 DrawString(XmLProgressWidget p,
464 	   XmString str,
465 	   int x,
466 	   int y,
467 	   int strWidth,
468 	   XRectangle *lRect,
469 	   XRectangle *rRect)
470 	{
471 	Display *dpy;
472 	Window win;
473 
474 	dpy = XtDisplay(p);
475 	win = XtWindow(p);
476 	if (lRect->width && lRect->height)
477 		{
478 		XSetForeground(dpy, p->progress.gc, p->core.background_pixel);
479 		XSetClipRectangles(dpy, p->progress.gc, 0, 0, lRect, 1, Unsorted);
480 		XmStringDraw(dpy, win, p->progress.fontList, str,
481 			p->progress.gc, x, y, strWidth, XmALIGNMENT_BEGINNING,
482 			XmSTRING_DIRECTION_L_TO_R, 0);
483 		XSetClipMask(dpy, p->progress.gc, None);
484 		}
485 	if (rRect->width && rRect->height)
486 		{
487 		XSetForeground(dpy, p->progress.gc, p->primitive.foreground);
488 		XSetClipRectangles(dpy, p->progress.gc, 0, 0, rRect, 1, Unsorted);
489 		XmStringDraw(dpy, win, p->progress.fontList, str,
490 			p->progress.gc, x, y, strWidth, XmALIGNMENT_BEGINNING,
491 			XmSTRING_DIRECTION_L_TO_R, 0);
492 		XSetClipMask(dpy, p->progress.gc, None);
493 		}
494 	}
495 
496 static void
TimeStr(char * c,int seconds)497 TimeStr(char *c,
498 	int seconds)
499 	{
500 	int h, m, s;
501 
502 	s = seconds;
503 	m = s / 60;
504 	s -= m * 60;
505 	h = m / 60;
506 	m -= h * 60;
507 	if (h > 99)
508 		h = 99;
509 	if (h > 0 && m < 10)
510 		sprintf(c, "%d:0%d hr", h, m);
511 	else if (h > 0)
512 		sprintf(c, "%d:%d hr", h, m);
513 	else if (m > 0 && s < 10)
514 		sprintf(c, "%d:0%d min", m, s);
515 	else if (m > 0)
516 		sprintf(c, "%d:%d min", m, s);
517 	else
518 		sprintf(c, "%d sec", s);
519 	}
520 
521 static Boolean
SetValues(Widget curW,Widget reqW,Widget newW,ArgList args,Cardinal * narg)522 SetValues(Widget curW,
523 	  Widget reqW,
524 	  Widget newW,
525 	  ArgList args,
526 	  Cardinal *narg)
527 	{
528 	XmLProgressWidget cur, p;
529 	XtAppContext app;
530 
531 	cur = (XmLProgressWidget)curW;
532 	p = (XmLProgressWidget)newW;
533 	app = XtWidgetToApplicationContext(curW);
534 	if (p->progress.value == 0)
535 		p->progress.startTime = time(0);
536 	if (p->progress.completeValue < 1)
537 		{
538 		XmLWarning(newW, "SetValues() - complete value can't be < 1");
539 		p->progress.completeValue = 1;
540 		}
541 	if (p->progress.numBoxes < 1)
542 		{
543 		XmLWarning(newW, "SetValues() - number of boxes can't be < 1");
544 		p->progress.numBoxes = 1;
545 		}
546 	if (p->progress.value < 0)
547 		{
548 		XmLWarning(newW, "SetValues() - value can't be < 0");
549 		p->progress.value = 0;
550 		}
551 	if (p->progress.value > p->progress.completeValue)
552 		{
553 		XmLWarning(newW, "SetValues() - value can't be > completeValue");
554 		p->progress.value = p->progress.completeValue;
555 		}
556 	if (p->progress.fontList != cur->progress.fontList)
557 		{
558 		XmFontListFree(cur->progress.fontList);
559 		CopyFontList(p);
560 		}
561 	/* display changes immediately since we may be not get back
562 	   to XNextEvent if the calling application is computing */
563 	if (p->core.background_pixel != cur->core.background_pixel ||
564 		p->primitive.foreground != cur->primitive.foreground ||
565 		p->progress.value != cur->progress.value ||
566 		p->progress.completeValue != cur->progress.completeValue ||
567 		p->progress.fontList != cur->progress.fontList ||
568 		p->progress.showTime != cur->progress.showTime ||
569 		p->progress.showPercentage != cur->progress.showPercentage ||
570 		p->progress.meterStyle != cur->progress.meterStyle ||
571 		p->progress.numBoxes != cur->progress.numBoxes ||
572 		p->primitive.shadow_thickness != cur->primitive.shadow_thickness)
573 		{
574 		Redisplay(newW, 0, 0);
575 		XFlush(XtDisplay(newW));
576 		XmUpdateDisplay(newW);
577 		}
578 	return FALSE;
579 	}
580 
581 static void
CopyFontList(XmLProgressWidget p)582 CopyFontList(XmLProgressWidget p)
583 	{
584 	if (!p->progress.fontList)
585 		p->progress.fontList = XmLFontListCopyDefault((Widget)p);
586 	else
587 		p->progress.fontList = XmFontListCopy(p->progress.fontList);
588 	if (!p->progress.fontList)
589 		XmLWarning((Widget)p, "- fatal error - font list NULL");
590 	}
591 
592 static Boolean
CvtStringToMeterStyle(Display * dpy,XrmValuePtr args,Cardinal * narg,XrmValuePtr fromVal,XrmValuePtr toVal,XtPointer * data)593 CvtStringToMeterStyle(Display *dpy,
594 		      XrmValuePtr args,
595 		      Cardinal *narg,
596 		      XrmValuePtr fromVal,
597 		      XrmValuePtr toVal,
598 		      XtPointer *data)
599 	{
600 	static XmLStringToUCharMap map[] =
601 		{
602 		{ "METER_BAR", XmMETER_BAR },
603 		{ "METER_BOXES", XmMETER_BOXES },
604 		{ 0, 0 },
605 		};
606 
607 	return XmLCvtStringToUChar(dpy, "XmRMeterStyle", map, fromVal, toVal);
608 	}
609 
610 /*
611    Public Functions
612 */
613 
614 Widget
XmLCreateProgress(Widget parent,char * name,ArgList arglist,Cardinal argcount)615 XmLCreateProgress(Widget parent,
616 		  char *name,
617 		  ArgList arglist,
618 		  Cardinal argcount)
619 	{
620 	return XtCreateWidget(name, xmlProgressWidgetClass, parent,
621 		arglist, argcount);
622 	}
623 
624 
625