1 /* $XFree86: xc/programs/xvidtune/xvidtune.c,v 3.35tsi Exp $ */
2 
3 /*
4 
5 Copyright (c) 1995  Kaleb S. KEITHLEY
6 
7 Permission is hereby granted, free of charge, to any person obtaining
8 a copy of this software and associated documentation files (the
9 "Software"), to deal in the Software without restriction, including
10 without limitation the rights to use, copy, modify, merge, publish,
11 distribute, sublicense, and/or sell copies of the Software, and to
12 permit persons to whom the Software is furnished to do so, subject to
13 the following conditions:
14 
15 The above copyright notice and this permission notice shall be
16 included in all copies or substantial portions of the Software.
17 
18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
21 IN NO EVENT SHALL Kaleb S. KEITHLEY BE LIABLE FOR ANY CLAIM, DAMAGES
22 OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
23 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
24 OTHER DEALINGS IN THE SOFTWARE.
25 
26 Except as contained in this notice, the name of Kaleb S. KEITHLEY
27 shall not be used in advertising or otherwise to promote the sale, use
28 or other dealings in this Software without prior written authorization
29 from Kaleb S. KEITHLEY.
30 
31 */
32 
33 #include <X11/Intrinsic.h>
34 #include <X11/Shell.h>
35 #include <X11/StringDefs.h>
36 #include <X11/Xatom.h>
37 #include <X11/Xaw/Form.h>
38 #include <X11/Xaw/Scrollbar.h>
39 #include <X11/Xaw/Label.h>
40 #include <X11/Xaw/Command.h>
41 #include <X11/Xaw/AsciiText.h>
42 #include <X11/Xaw/Box.h>
43 #include <X11/Xaw/Toggle.h>
44 #include <X11/Xmu/StdSel.h>
45 #include <X11/Xmd.h>
46 #include <X11/extensions/xf86vmode.h>
47 #include <ctype.h>
48 #include <stdio.h>
49 #include <stdlib.h>
50 #include <signal.h>
51 
52 static int MajorVersion, MinorVersion;
53 static int EventBase, ErrorBase;
54 static int dot_clock, mode_flags;
55 static unsigned long TestTimeout=5000;  /* Default test timeout */
56 static XtSignalId sigId;
57 
58 /* Minimum extension version required */
59 #define MINMAJOR 0
60 #define MINMINOR 5
61 
62 /* Mode flags -- ignore flags not in V_FLAG_MASK */
63 #define V_FLAG_MASK	0x1FF;
64 #define V_PHSYNC	0x001
65 #define V_NHSYNC	0x002
66 #define V_PVSYNC	0x004
67 #define V_NVSYNC	0x008
68 #define V_INTERLACE	0x010
69 #define V_DBLSCAN	0x020
70 #define V_CSYNC		0x040
71 #define V_PCSYNC	0x080
72 #define V_NCSYNC	0x100
73 
74 typedef enum { HDisplay, HSyncStart, HSyncEnd, HTotal,
75 	VDisplay, VSyncStart, VSyncEnd, VTotal, Flags,
76 	InvertVclk, BlankDelay1, BlankDelay2, EarlySc,
77 	PixelClock, HSyncRate, VSyncRate, fields_num } fields;
78 
79 typedef struct {
80     fields	me;
81     fields	use;
82     int		val;
83     int		lastpercent;
84     int		range;
85     Widget	textwidget;
86     Widget	scrollwidget;
87 } ScrollData;
88 
89 static struct _AppResources {
90     ScrollData	field[fields_num];
91     Bool	ad_installed;
92     int		orig[fields_num];
93     int		old[fields_num];
94 } AppRes = {
95     {
96 	{ HDisplay, },
97 	{ HSyncStart, HDisplay, },
98 	{ HSyncEnd, HDisplay, },
99 	{ HTotal, HDisplay, },
100 	{ VDisplay, },
101 	{ VSyncStart, VDisplay, },
102 	{ VSyncEnd, VDisplay, },
103 	{ VTotal, VDisplay, },
104 	{ Flags, },
105 	{ InvertVclk, },
106 	{ BlankDelay1, },
107 	{ BlankDelay2, },
108 	{ EarlySc, },
109 	{ PixelClock, },
110 	{ HSyncRate, },
111 	{ VSyncRate, },
112     },
113 };
114 
115 static XtResource Resources[] = {
116     { "adInstalled", "AdInstalled", XtRBool, sizeof(Bool),
117 	XtOffsetOf(struct _AppResources, ad_installed),
118 	XtRImmediate, (XtPointer)FALSE },
119     { "hSyncStartRange", "SyncStartRange", XtRInt, sizeof(int),
120 	XtOffsetOf(struct _AppResources, field[HSyncStart].range),
121 	XtRImmediate, (XtPointer)200 },
122     { "hSyncEndRange", "SyncEndRange", XtRInt, sizeof(int),
123 	XtOffsetOf(struct _AppResources, field[HSyncEnd].range),
124 	XtRImmediate, (XtPointer)400 },
125     { "hTotalRange", "TotalRange", XtRInt, sizeof(int),
126 	XtOffsetOf(struct _AppResources, field[HTotal].range),
127 	XtRImmediate, (XtPointer)400 },
128     { "vSyncStartRange", "SyncStartRange", XtRInt, sizeof(int),
129 	XtOffsetOf(struct _AppResources, field[VSyncStart].range),
130 	XtRImmediate, (XtPointer)20 },
131     { "vSyncEndRange", "SyncEndRange", XtRInt, sizeof(int),
132 	XtOffsetOf(struct _AppResources, field[VSyncEnd].range),
133 	XtRImmediate, (XtPointer)40 },
134     { "vTotalRange", "TotalRange", XtRInt, sizeof(int),
135 	XtOffsetOf(struct _AppResources, field[VTotal].range),
136 	XtRImmediate, (XtPointer)80 },
137 };
138 
139 static XtTranslations trans;
140 
141 static Atom wm_delete_window;
142 static Widget invalid_mode_popup;
143 static Widget testing_popup;
144 static Widget Top;
145 static Widget auto_apply_toggle;
146 
147 static Bool S3Specials = False;
148 static char modebuf[160];
149 
150 static void UpdateSyncRates(Bool dolabels);
151 
152 static void
CleanUp(Display * dpy)153 CleanUp(Display *dpy)
154 {
155     /* Make sure mode switching is not locked out at exit */
156     XF86VidModeLockModeSwitch(dpy, DefaultScreen(dpy), FALSE);
157     XFlush(dpy);
158 }
159 
160 static void
CatchSig(int signal)161 CatchSig(int signal)
162 {
163     XtNoticeSignal(sigId);
164 }
165 
166 static void
CatchXtSig(XtPointer closure,XtSignalId * id)167 CatchXtSig(XtPointer closure, XtSignalId *id)
168 {
169     CleanUp(XtDisplay(Top));
170     exit(3);
171 }
172 
173 static Bool
GetModeLine(Display * dpy,int scrn)174 GetModeLine (Display* dpy, int scrn)
175 {
176     XF86VidModeModeLine mode_line;
177     fields i;
178 
179     if (!XF86VidModeGetModeLine (dpy, scrn, &dot_clock, &mode_line))
180 	return FALSE;
181 
182     AppRes.field[HDisplay].val = mode_line.hdisplay;
183     AppRes.field[HSyncStart].val = mode_line.hsyncstart;
184     AppRes.field[HSyncEnd].val = mode_line.hsyncend;
185     AppRes.field[HTotal].val = mode_line.htotal;
186     AppRes.field[VDisplay].val = mode_line.vdisplay;
187     AppRes.field[VSyncStart].val = mode_line.vsyncstart;
188     AppRes.field[VSyncEnd].val = mode_line.vsyncend;
189     AppRes.field[VTotal].val = mode_line.vtotal;
190     mode_flags = mode_line.flags;
191     AppRes.field[Flags].val = mode_flags & V_FLAG_MASK;
192     AppRes.field[PixelClock].val = dot_clock;
193     UpdateSyncRates(FALSE);
194     if (mode_line.privsize && mode_line.private) {
195 	S3Specials = True;
196 	AppRes.field[InvertVclk].val = mode_line.private[1];
197 	AppRes.field[BlankDelay1].val = mode_line.private[2] & 7;
198 	AppRes.field[BlankDelay2].val = (mode_line.private[2] >> 4) & 7;
199 	AppRes.field[EarlySc].val = mode_line.private[3];
200     }
201 
202     for (i = HDisplay; i < fields_num; i++)
203 	AppRes.orig[i] = AppRes.field[i].val;
204     return TRUE;
205 }
206 
207 static Bool
GetMonitor(Display * dpy,int scrn)208 GetMonitor (Display* dpy, int scrn)
209 {
210     XF86VidModeMonitor monitor;
211     int i;
212 
213     if (!XF86VidModeGetMonitor (dpy, scrn, &monitor))
214 	return FALSE;
215 
216     printf("Vendor: %s, Model: %s\n", monitor.vendor, monitor.model);
217     printf("Num hsync: %d, Num vsync: %d\n", monitor.nhsync, monitor.nvsync);
218     for (i = 0; i < monitor.nhsync; i++) {
219 	printf("hsync range %d: %6.2f - %6.2f\n", i, monitor.hsync[i].lo,
220 	       monitor.hsync[i].hi);
221     }
222     for (i = 0; i < monitor.nvsync; i++) {
223 	printf("vsync range %d: %6.2f - %6.2f\n", i, monitor.vsync[i].lo,
224 	       monitor.vsync[i].hi);
225     }
226     return TRUE;
227 }
228 
229 static Bool
ModeSettable(void)230 ModeSettable(void)
231 {
232     if (AppRes.field[HTotal].val == 0 || AppRes.field[VTotal].val == 0)
233 	return FALSE;
234     return TRUE;
235 }
236 
237 static int hitError = 0;
238 static int (*xtErrorfunc)(Display *, XErrorEvent *);
239 
240 static int
vidmodeError(Display * dis,XErrorEvent * err)241 vidmodeError(Display *dis, XErrorEvent *err)
242 {
243   if ((err->error_code >= ErrorBase &&
244       err->error_code < ErrorBase + XF86VidModeNumberErrors) ||
245       err->error_code == BadValue) {
246      hitError=1;
247   } else {
248      CleanUp(dis);
249      if (xtErrorfunc)
250 	(*xtErrorfunc)(dis, err);
251   }
252   return 0; /* ignored */
253 }
254 
255 static void
SetScrollbars(void)256 SetScrollbars (void)
257 {
258     fields i;
259 
260     for (i = HDisplay; i <= Flags; i++) {
261 
262 	ScrollData* sdp = &AppRes.field[i];
263 
264 	if (sdp->scrollwidget != (Widget) NULL) {
265 	    int base;
266 	    float percent;
267 
268 	    base = AppRes.field[sdp->use].val;
269 	    percent = ((float)(sdp->val - base)) / ((float)sdp->range);
270 	    XawScrollbarSetThumb (sdp->scrollwidget, percent, 0.0);
271 	}
272     }
273 }
274 
275 static void
QuitCB(Widget w,XtPointer client,XtPointer call)276 QuitCB (Widget w, XtPointer client, XtPointer call)
277 {
278     CleanUp(XtDisplay(w));
279 #if XtSpecificationRelease < 6
280     exit (0);
281 #else
282     XtAppSetExitFlag (XtWidgetToApplicationContext (w));
283 #endif
284 }
285 
286 static void
popdownInvalid(Widget w,XtPointer client,XtPointer call)287 popdownInvalid(Widget w, XtPointer client, XtPointer call)
288 {
289    XtPopdown((Widget)client);
290 }
291 
292 static void
ApplyCB(Widget w,XtPointer client,XtPointer call)293 ApplyCB (Widget w, XtPointer client, XtPointer call)
294 {
295     XF86VidModeModeLine mode_line;
296     INT32 S3private[4];
297     unsigned int i;
298     char* string;
299     Boolean state;
300 
301     mode_line.hdisplay = AppRes.field[HDisplay].val;
302     mode_line.hsyncstart = AppRes.field[HSyncStart].val;
303     mode_line.hsyncend = AppRes.field[HSyncEnd].val;
304     mode_line.htotal = AppRes.field[HTotal].val;
305     mode_line.vdisplay = AppRes.field[VDisplay].val;
306     mode_line.vsyncstart = AppRes.field[VSyncStart].val;
307     mode_line.vsyncend = AppRes.field[VSyncEnd].val;
308     mode_line.vtotal = AppRes.field[VTotal].val;
309     /* Don't read flags from widget */
310 #if 0
311     XtVaGetValues (AppRes.field[Flags].textwidget,
312 		XtNstring, &string, NULL);
313     (void) sscanf (string, "%x", &i);
314 #endif
315     mode_line.flags = mode_flags;
316     if (S3Specials) {
317 	mode_line.privsize = 4;
318 	mode_line.private = S3private;
319 	mode_line.private[0] = (1 << 1) | (1 << 2) | (1 << 3);
320 	XtVaGetValues(AppRes.field[InvertVclk].textwidget,
321 			XtNstate, &state, NULL);
322 	AppRes.field[InvertVclk].val = state ? 1 : 0;
323 	mode_line.private[1] = AppRes.field[InvertVclk].val;
324 	XtVaGetValues (AppRes.field[BlankDelay1].textwidget,
325 			XtNstring, &string, NULL);
326 	(void) sscanf (string, "%x", &i);
327 	AppRes.field[BlankDelay1].val = i;
328 	mode_line.private[2] = AppRes.field[BlankDelay1].val;
329 	XtVaGetValues (AppRes.field[BlankDelay2].textwidget,
330 			XtNstring, &string, NULL);
331 	(void) sscanf (string, "%x", &i);
332 	AppRes.field[BlankDelay2].val = i;
333 	mode_line.private[2] |= AppRes.field[BlankDelay2].val << 4;
334 	XtVaGetValues(AppRes.field[EarlySc].textwidget,
335 			XtNstate, &state, NULL);
336 	AppRes.field[EarlySc].val = state ? 1 : 0;
337 	mode_line.private[3] = AppRes.field[EarlySc].val;
338     } else
339 	mode_line.privsize = 0;
340 
341    hitError = 0;
342 
343    XF86VidModeModModeLine (XtDisplay (w), DefaultScreen (XtDisplay (w)),
344 		&mode_line);
345    XSync(XtDisplay (w), False); /* process errors  */
346    if (hitError) {
347        XBell(XtDisplay (w), 80);
348        XtPopup(invalid_mode_popup, XtGrabExclusive /*XtGrabNone*/);
349    }
350 }
351 
352 
353 static void
SetLabel(fields i)354 SetLabel(fields i)
355 {
356    ScrollData* sdp = &AppRes.field[i];
357 
358    if (sdp->textwidget != (Widget) NULL) {
359       char buf[10];
360       Boolean state;
361 
362       /*
363        * Disable AutoApply so that the apply doesn't happen more than
364        * once as a consequence of callbacks being called because of the
365        * XtSetValues calls
366        */
367 
368       XtVaGetValues(auto_apply_toggle, XtNstate, &state, NULL);
369       if (state)
370 	 XtVaSetValues(auto_apply_toggle, XtNstate, 0, NULL);
371 
372       if (i == Flags)
373 	 (void) snprintf (buf, sizeof(buf), "%04x", sdp->val);
374       else if (i >= PixelClock && i <= VSyncRate)
375 	 (void) snprintf (buf, sizeof(buf), "%6.2f", (float)sdp->val / 1000.0);
376       else if (i == BlankDelay1 || i == BlankDelay2) {
377 	 (void) snprintf (buf, sizeof(buf), "%d", sdp->val);
378       } else
379 	 (void) snprintf (buf, sizeof(buf), "%5d", sdp->val);
380 
381       sdp->lastpercent = -1;
382       if (i == Flags) {
383 	 XawTextBlock text;
384 
385 	 text.firstPos = 0;
386 	 text.length = 4;
387 	 text.ptr = buf;
388 	 text.format = XawFmt8Bit;
389 	 XawTextReplace (sdp->textwidget, 0, 4, &text);
390       } else if (i == BlankDelay1 || i == BlankDelay2) {
391 	 XawTextBlock text;
392 
393 	 text.firstPos = 0;
394 	 text.length = 1;
395 	 text.ptr = buf;
396 	 XawTextReplace (sdp->textwidget, 0, 1, &text);
397       } else if (i == InvertVclk || i == EarlySc) {
398 	XtVaSetValues (sdp->textwidget, XtNstate, sdp->val, NULL);
399       } else
400 	XtVaSetValues (sdp->textwidget, XtNlabel, buf, NULL);
401 
402       if (state)
403 	 XtVaSetValues(auto_apply_toggle, XtNstate, 1, NULL);
404    }
405 
406 }
407 
408 static void
UpdateSyncRates(Bool dolabels)409 UpdateSyncRates(Bool dolabels)
410 {
411     if (!ModeSettable())
412 	return;
413 
414     AppRes.field[HSyncRate].val = AppRes.field[PixelClock].val * 1000 /
415 				  AppRes.field[HTotal].val;
416     AppRes.field[VSyncRate].val = AppRes.field[HSyncRate].val * 1000 /
417 				  AppRes.field[VTotal].val;
418     if (mode_flags & V_INTERLACE)
419 	AppRes.field[VSyncRate].val *= 2;
420     else if (mode_flags & V_DBLSCAN)
421 	AppRes.field[VSyncRate].val /= 2;
422     if (dolabels) {
423 	SetLabel(HSyncRate);
424 	SetLabel(VSyncRate);
425     }
426 }
427 
428 static void
RestoreCB(Widget w,XtPointer client,XtPointer call)429 RestoreCB (Widget w, XtPointer client, XtPointer call)
430 {
431     fields i;
432     Boolean state;
433 
434     for (i = HDisplay; i < fields_num; i++) {
435 	AppRes.field[i].val = AppRes.orig[i];
436 	SetLabel(i);
437     }
438     SetScrollbars ();
439     XtVaGetValues(auto_apply_toggle, XtNstate, &state, NULL);
440     if (state)
441 	 ApplyCB (w, client, call);
442 }
443 
444 
445 static void
ApplyIfAutoCB(Widget w,XtPointer client,XtPointer call)446 ApplyIfAutoCB (Widget w, XtPointer client, XtPointer call)
447 {
448    Boolean state;
449 
450    XtVaGetValues(auto_apply_toggle, XtNstate, &state, NULL);
451    if (state)
452        ApplyCB (w, client, call);
453 }
454 
455 
456 static void
FetchCB(Widget w,XtPointer client,XtPointer call)457 FetchCB (Widget w, XtPointer client, XtPointer call)
458 {
459     fields i;
460     (void) GetModeLine(XtDisplay (w), DefaultScreen (XtDisplay (w)));
461     SetScrollbars ();
462     for (i = HDisplay; i < fields_num; i++) {
463         SetLabel(i);
464     }
465 }
466 
467 static XtIntervalId TOid;
468 
469 static void
TestTO(XtPointer client,XtIntervalId * id)470 TestTO (XtPointer client, XtIntervalId* id)
471 {
472     fields i;
473     for (i = HDisplay; i < fields_num; i++)
474 	AppRes.field[i].val = AppRes.orig[i];
475 
476     ApplyCB ((Widget) client, NULL, NULL);
477 
478     for (i = HDisplay; i < fields_num; i++)
479 	AppRes.field[i].val = AppRes.old[i];
480     SetScrollbars ();
481 
482     XtPopdown(testing_popup);
483 }
484 
485 static void
TestTOCB(Widget w,XtPointer client,XtPointer call)486 TestTOCB (Widget w, XtPointer client, XtPointer call)
487 {
488   XtRemoveTimeOut(TOid);
489   TestTO(w, (XtIntervalId *) NULL);
490 }
491 
492 static void
TestCB(Widget w,XtPointer client,XtPointer call)493 TestCB (Widget w, XtPointer client, XtPointer call)
494 {
495     fields i;
496     for (i = HDisplay; i < fields_num; i++)
497 	AppRes.old[i] = AppRes.field[i].val;
498 
499     XtPopup(testing_popup, XtGrabExclusive /*XtGrabNone*/);
500     XSync(XtDisplay(w), False);
501     TOid = XtAppAddTimeOut (XtWidgetToApplicationContext (w),
502 		TestTimeout, TestTO, (XtPointer) w);
503 
504     ApplyCB (w, client, call);
505 }
506 
507 static Boolean
ConvertSelection(Widget w,Atom * selection,Atom * target,Atom * type,XtPointer * value,unsigned long * length,int * format)508 ConvertSelection(
509     Widget w,
510     Atom *selection, Atom *target, Atom *type,
511     XtPointer *value,
512     unsigned long *length,
513     int *format)
514 {
515     if (XmuConvertStandardSelection(w, CurrentTime, selection, target, type,
516                                     (XPointer *) value, length, format))
517         return True;
518 
519     if (*target == XA_STRING) {
520         *type = XA_STRING;
521         *value = modebuf;
522         *length = strlen(*value);
523         *format = 8;
524         return True;
525     }
526     return False;
527 }
528 
529 static void
ShowCB(Widget w,XtPointer client,XtPointer call)530 ShowCB(Widget w, XtPointer client, XtPointer call)
531 {
532     Time time;
533     char tmpbuf[16];
534 
535     snprintf(tmpbuf, sizeof(tmpbuf), "\"%dx%d\"",
536 	   AppRes.field[HDisplay].val, AppRes.field[VDisplay].val);
537     snprintf(modebuf, sizeof(modebuf),
538 	   "%-11s   %6.2f   %4d %4d %4d %4d   %4d %4d %4d %4d",
539 	   tmpbuf, (float)dot_clock/1000.0,
540 	   AppRes.field[HDisplay].val,
541 	   AppRes.field[HSyncStart].val,
542 	   AppRes.field[HSyncEnd].val,
543 	   AppRes.field[HTotal].val,
544 	   AppRes.field[VDisplay].val,
545 	   AppRes.field[VSyncStart].val,
546 	   AppRes.field[VSyncEnd].val,
547 	   AppRes.field[VTotal].val);
548     /* Print out the flags (if any) */
549     if (mode_flags & V_PHSYNC)    strcat(modebuf, " +hsync");
550     if (mode_flags & V_NHSYNC)    strcat(modebuf, " -hsync");
551     if (mode_flags & V_PVSYNC)    strcat(modebuf, " +vsync");
552     if (mode_flags & V_NVSYNC)    strcat(modebuf, " -vsync");
553     if (mode_flags & V_INTERLACE) strcat(modebuf, " interlace");
554     if (mode_flags & V_CSYNC)     strcat(modebuf, " composite");
555     if (mode_flags & V_PCSYNC)    strcat(modebuf, " +csync");
556     if (mode_flags & V_NCSYNC)    strcat(modebuf, " -csync");
557     if (mode_flags & V_DBLSCAN)   strcat(modebuf, " doublescan");
558     printf("%s\n", modebuf);
559     time = XtLastTimestampProcessed(XtDisplay(w));
560     XtOwnSelection(w, XA_PRIMARY, time, ConvertSelection, NULL, NULL);
561     if (S3Specials) {
562 	unsigned int i;
563 	Boolean state;
564 	char *string;
565 
566 	XtVaGetValues(AppRes.field[InvertVclk].textwidget,
567 			XtNstate, &state, NULL);
568 	AppRes.field[InvertVclk].val = state ? 1 : 0;
569 	XtVaGetValues (AppRes.field[BlankDelay1].textwidget,
570 			XtNstring, &string, NULL);
571 	(void) sscanf (string, "%x", &i);
572 	AppRes.field[BlankDelay1].val = i;
573 	XtVaGetValues (AppRes.field[BlankDelay2].textwidget,
574 			XtNstring, &string, NULL);
575 	(void) sscanf (string, "%x", &i);
576 	AppRes.field[BlankDelay2].val = i;
577 	XtVaGetValues(AppRes.field[EarlySc].textwidget,
578 			XtNstate, &state, NULL);
579 	AppRes.field[EarlySc].val = state ? 1 : 0;
580 	if (AppRes.field[InvertVclk].val != AppRes.orig[InvertVclk])
581 	    printf("InvertVCLK\t\"%dx%d\" %d\n", AppRes.field[HDisplay].val,
582 		AppRes.field[VDisplay].val, AppRes.field[InvertVclk].val);
583 	if (AppRes.field[EarlySc].val != AppRes.orig[EarlySc])
584 	    printf("EarlySC\t\t\"%dx%d\" %d\n", AppRes.field[HDisplay].val,
585 		AppRes.field[VDisplay].val, AppRes.field[EarlySc].val);
586 	if (AppRes.field[BlankDelay1].val != AppRes.orig[BlankDelay1]
587 	    || AppRes.field[BlankDelay2].val != AppRes.orig[BlankDelay2])
588 	    printf("BlankDelay\t\"%dx%d\" %d %d\n", AppRes.field[HDisplay].val,
589 		AppRes.field[VDisplay].val, AppRes.field[BlankDelay1].val,
590 		AppRes.field[BlankDelay2].val);
591     }
592     printf("\n");
593 }
594 
595 static void
AdjustCB(Widget w,XtPointer client,XtPointer call)596 AdjustCB(Widget w, XtPointer client, XtPointer call)
597 {
598    int what = (long) client;
599    Boolean state;
600 
601    switch (what) {
602     case HSyncStart:
603       if (AppRes.field[HSyncEnd].val + 4 < AppRes.field[HTotal].val) {
604 	 AppRes.field[HSyncEnd].val += 4;
605 	 AppRes.field[HSyncStart].val += 4;
606 	 SetLabel(HSyncStart);
607 	 SetLabel(HSyncEnd);
608       } else
609 	XBell(XtDisplay(w), 80);
610       break;
611     case -HSyncStart:
612       if (AppRes.field[HSyncStart].val - 4 > AppRes.field[HDisplay].val) {
613 	 AppRes.field[HSyncEnd].val -= 4;
614 	 AppRes.field[HSyncStart].val -= 4;
615 	 SetLabel(HSyncStart);
616 	 SetLabel(HSyncEnd);
617       } else
618 	XBell(XtDisplay(w), 80);
619       break;
620     case HTotal:
621       AppRes.field[HTotal].val += 4;
622       SetLabel(HTotal);
623       UpdateSyncRates(TRUE);
624       break;
625     case -HTotal:
626       if (AppRes.field[HTotal].val - 4 >  AppRes.field[HSyncEnd].val) {
627 	AppRes.field[HTotal].val -= 4;
628 	SetLabel(HTotal);
629 	UpdateSyncRates(TRUE);
630       } else
631 	XBell(XtDisplay(w), 80);
632       break;
633     case VSyncStart:
634       if (AppRes.field[VSyncEnd].val + 4 < AppRes.field[VTotal].val) {
635 	 AppRes.field[VSyncEnd].val += 4;
636 	 AppRes.field[VSyncStart].val += 4;
637 	 SetLabel(VSyncStart);
638 	 SetLabel(VSyncEnd);
639       } else
640 	XBell(XtDisplay(w), 80);
641       break;
642     case -VSyncStart:
643       if (AppRes.field[VSyncStart].val - 4 > AppRes.field[VDisplay].val) {
644 	 AppRes.field[VSyncEnd].val -= 4;
645 	 AppRes.field[VSyncStart].val -= 4;
646 	 SetLabel(VSyncStart);
647 	 SetLabel(VSyncEnd);
648       } else
649 	XBell(XtDisplay(w), 80);
650       break;
651     case VTotal:
652       AppRes.field[VTotal].val += 4;
653       SetLabel(VTotal);
654       UpdateSyncRates(TRUE);
655       break;
656     case -VTotal:
657       if (AppRes.field[VTotal].val - 4 >  AppRes.field[VSyncEnd].val) {
658 	AppRes.field[VTotal].val -= 4;
659 	SetLabel(VTotal);
660 	UpdateSyncRates(TRUE);
661       } else
662 	XBell(XtDisplay(w), 80);
663       break;
664    }
665    SetScrollbars ();
666    XtVaGetValues(auto_apply_toggle, XtNstate, &state, NULL);
667    if (state)
668        ApplyCB (w, client, call);
669 }
670 
671 
672 #if 0
673 static void
674 EditCB (Widget w, XtPointer client, XtPointer call)
675 {
676     int base, current, i, len;
677     int lower, upper;
678     float percent;
679     ScrollData* sdp = (ScrollData*) client;
680 
681     len = strlen (sdp->string);
682 
683     for (i = 0; i < len; i++) {
684 	if (!(isdigit (sdp->string[i]) || isspace (sdp->string[i]))) {
685 	    XBell (XtDisplay(XtParent(w)), 100);
686 	    return;
687 	}
688     }
689     switch (sdp->me) {
690     case HSyncStart:
691 	lower = atoi (AppRes.field[HDisplay].string);
692 	upper = atoi (AppRes.field[HSyncEnd].string);
693 	break;
694 
695     case HSyncEnd:
696 	lower = atoi (AppRes.field[HSyncStart].string);
697 	upper = atoi (AppRes.field[HTotal].string);
698 	break;
699 
700     case HTotal:
701 	lower = atoi (AppRes.field[HSyncEnd].string);
702 	upper = atoi (AppRes.field[HDisplay].string) +
703 		AppRes.field[HTotal].range;
704 	break;
705 
706     case VSyncStart:
707 	lower = atoi (AppRes.field[VDisplay].string);
708 	upper = atoi (AppRes.field[VSyncEnd].string);
709 	break;
710 
711     case VSyncEnd:
712 	lower = atoi (AppRes.field[VSyncStart].string);
713 	upper = atoi (AppRes.field[VTotal].string);
714 	break;
715 
716     case VTotal:
717 	lower = atoi (AppRes.field[VSyncEnd].string);
718 	upper = atoi (AppRes.field[VDisplay].string) +
719 		AppRes.field[VTotal].range;
720 	break;
721     }
722     current = atoi (sdp->string);
723     if (current < lower || current > upper) {
724 	XawTextBlock text;
725 	char tmp[6];
726 
727 	if (current < lower) {
728 	    (void) snprintf (tmp, sizeof(tmp), "%5d", lower);
729 	    current = lower;
730 	} else {
731 	    (void) snprintf (tmp, sizeof(tmp), "%5d", upper);
732 	    current = upper;
733 	}
734 	text.firstPos = 0;
735 	text.length = strlen (tmp);
736 	text.ptr = tmp;
737 	text.format = XawFmt8Bit;
738 	XawTextReplace (sdp->textwidget, 0, text.length, &text);
739     }
740     base = atoi (AppRes.field[sdp->use].string);
741     percent = ((float)(current - base)) / ((float)sdp->range);
742     XawScrollbarSetThumb (sdp->scrollwidget, percent, 0.0);
743 }
744 #endif
745 
746 static void
FlagsEditCB(Widget w,XtPointer client,XtPointer call)747 FlagsEditCB (Widget w, XtPointer client, XtPointer call)
748 {
749     int i, len;
750     char* string;
751     fields findex = (fields) (unsigned long) client;
752     ScrollData* sdp = &AppRes.field[findex];
753 
754     XtVaGetValues (w, XtNstring, &string, NULL);
755     len = strlen (string);
756     if (len > 4) {
757 	char buf[5];
758 
759 	XBell (XtDisplay(XtParent(w)), 100);
760 	(void) strncpy (buf, string, 4);
761 	buf[4] = '\0';
762 	XtVaSetValues (sdp->textwidget, XtNstring, buf, NULL);
763 	XawTextSetInsertionPoint (sdp->textwidget, 4);
764     }
765 
766     for (i = 0; i < len; i++) {
767 	if (!isxdigit (string[i])) {
768 	    XBell (XtDisplay(XtParent(w)), 100);
769 	}
770     }
771 }
772 
773 static void
BlankEditCB(Widget w,XtPointer client,XtPointer call)774 BlankEditCB (Widget w, XtPointer client, XtPointer call)
775 {
776     int len;
777     char* string;
778     fields findex = (fields) (unsigned long) client;
779     ScrollData* sdp = &AppRes.field[findex];
780     char buf[2], old;
781     Boolean state;
782     Boolean noAuto = False;
783 
784     XtVaGetValues (w, XtNstring, &string, NULL);
785     len = strlen (string);
786     if (len == 0) {
787 	XBell (XtDisplay(XtParent(w)), 100);
788 	strcpy(buf, "0");
789 	XtVaSetValues (sdp->textwidget, XtNstring, buf, NULL);
790 	XawTextSetInsertionPoint (sdp->textwidget, 1);
791         return;
792     }
793     if (len > 1) {
794 	if (XawTextGetInsertionPoint(sdp->textwidget) < 1) {
795 	    buf[0] = string[0];
796 	    old = string[1];
797 	} else {
798 	    buf[0] = string[1];
799 	    old = string[0];
800 	}
801 	if (buf[0] == '+' && old < '7')
802 	    buf[0] = old + 1;
803 	else if (buf[0] == '-' && old > '0')
804 	    buf[0] = old - 1;
805 	if (!isdigit(buf[0]) || buf[0] > '7') {
806 	    XBell (XtDisplay(XtParent(w)), 100);
807 	    buf[0] = old;
808 	    if (!isdigit(buf[0]) || buf[0] > '7')
809 		buf[0] = '0';
810 	    noAuto = True;
811 	}
812 	buf[1] = '\0';
813 	XtVaSetValues (sdp->textwidget, XtNstring, buf, NULL);
814 	XawTextSetInsertionPoint (sdp->textwidget, 1);
815     }
816     XtVaGetValues(auto_apply_toggle, XtNstate, &state, NULL);
817     if (state && !noAuto)
818 	ApplyCB (sdp->textwidget, client, call);
819 }
820 
821 static void
ChangeBlankCB(Widget w,XtPointer client,XtPointer call)822 ChangeBlankCB (Widget w, XtPointer client, XtPointer call)
823 {
824     char* string;
825     char buf[2];
826     fields findex;
827     ScrollData* sdp;
828     Boolean state;
829     int what = (long) client;
830 
831 
832     if (what < 0)
833 	findex = (fields)-what;
834     else
835 	findex = (fields)what;
836     sdp = &AppRes.field[findex];
837 
838     XtVaGetValues (sdp->textwidget, XtNstring, &string, NULL);
839     if (what > 0)
840 	string[0]++;
841     else
842 	string[0]--;
843 
844     if (string[0] < '0' || string[0] > '7') {
845 	XBell (XtDisplay(XtParent(w)), 100);
846 	return;
847     }
848 
849     buf[0] = string[0];
850     buf[1] = '\0';
851     XtVaSetValues (sdp->textwidget, XtNstring, buf, NULL);
852     XawTextSetInsertionPoint (sdp->textwidget, 1);
853 
854     XtVaGetValues(auto_apply_toggle, XtNstate, &state, NULL);
855     if (state)
856 	ApplyCB (sdp->textwidget, client, call);
857 }
858 
859 static int
isValid(int val,int field)860 isValid(int val, int field)
861 {
862    switch(field) {
863      case HSyncStart:
864 	if (val+8 > AppRes.field[HSyncEnd].val)
865 	   val = AppRes.field[HSyncEnd].val - 8;
866         break;
867      case HSyncEnd:
868         if (val-8 < AppRes.field[HSyncStart].val)
869 	    val = AppRes.field[HSyncStart].val + 8;
870         if (val > AppRes.field[HTotal].val)
871 	    val = AppRes.field[HTotal].val;
872         break;
873      case HTotal:
874 	if (val < AppRes.field[HSyncEnd].val)
875 	   val = AppRes.field[HSyncEnd].val;
876          break;
877      case VSyncStart:
878 	if (val+8 > AppRes.field[VSyncEnd].val)
879 	   val = AppRes.field[VSyncEnd].val - 8;
880         break;
881      case VSyncEnd:
882         if (val-8 < AppRes.field[VSyncStart].val)
883 	    val = AppRes.field[VSyncStart].val + 8;
884         if (val > AppRes.field[VTotal].val)
885 	    val = AppRes.field[VTotal].val;
886         break;
887      case VTotal:
888 	if (val < AppRes.field[VSyncEnd].val)
889 	   val = AppRes.field[VSyncEnd].val;
890         break;
891    }
892    return val;
893 }
894 
895 static void
ScrollCB(Widget w,XtPointer client,XtPointer call)896 ScrollCB (Widget w, XtPointer client, XtPointer call)
897 {
898     float percent = *(float*) call;
899     int ipercent = percent * 100;
900     int fieldindex = (long) client;
901     ScrollData* sdp = &AppRes.field[fieldindex];
902 
903 
904 
905     if (ipercent != sdp->lastpercent) {
906         int tmp_val;
907 	char buf[6];
908 
909 	tmp_val = AppRes.field[sdp->use].val;
910 	tmp_val += (int) (((float)sdp->range) * percent);
911 
912         sdp->val = isValid(tmp_val, fieldindex);
913 
914 	sdp->lastpercent = ipercent;
915 	(void) snprintf (buf, sizeof(buf), "%5d", sdp->val);
916 	XtVaSetValues (sdp->textwidget, XtNlabel, buf, NULL);
917         if (sdp->val != tmp_val) {
918             int base;
919             float percent;
920 
921             base = AppRes.field[sdp->use].val;
922             percent = ((float)(sdp->val - base)) / ((float)sdp->range);
923             /* This doesn't always work, why? */
924             XawScrollbarSetThumb (sdp->scrollwidget, percent, 0.0);
925 	}
926 	if (fieldindex == HTotal || fieldindex == VTotal)
927 	    UpdateSyncRates(TRUE);
928     }
929 }
930 
931 static void
SwitchCB(Widget w,XtPointer client,XtPointer call)932 SwitchCB (Widget w, XtPointer client, XtPointer call)
933 {
934     XF86VidModeLockModeSwitch(XtDisplay(w), DefaultScreen (XtDisplay (w)),
935 			      FALSE);
936     XF86VidModeSwitchMode(XtDisplay(w), DefaultScreen (XtDisplay (w)),
937 			  (int)(long) client);
938     XF86VidModeLockModeSwitch(XtDisplay(w), DefaultScreen (XtDisplay (w)),
939 			      TRUE);
940     FetchCB(w, NULL, NULL);
941 }
942 
943 static void
AddCallback(Widget w,String callback_name,XtCallbackProc callback,XtPointer client_data)944 AddCallback (
945     Widget w,
946     String  callback_name,
947     XtCallbackProc callback,
948     XtPointer client_data)
949 {
950     Widget src;
951 
952     XtVaGetValues (w, XtNtextSource, &src, NULL);
953     XtAddCallback (src, callback_name, callback, client_data);
954 }
955 
956 static void
CreateTyp(Widget form,fields findex,String w1name,String w2name,String w3name)957 CreateTyp (
958     Widget form,
959     fields findex,
960     String w1name,
961     String w2name,
962     String w3name)
963 {
964     Widget wids[3];
965     char buf[10];
966 
967     wids[0] = XtCreateWidget (w1name, labelWidgetClass, form, NULL, 0);
968     if (findex >= PixelClock && findex <= VSyncRate)
969 	(void) snprintf(buf, sizeof(buf), "%6.2f",
970 			(float)AppRes.field[findex].val / 1000.0);
971     else
972 	(void) snprintf (buf, sizeof(buf), "%5d", AppRes.field[findex].val);
973     wids[1] = XtVaCreateWidget (w2name, labelWidgetClass,
974 		form, XtNlabel, buf, NULL);
975     if (w3name != NULL) {
976 	wids[2] = XtCreateWidget (w3name, scrollbarWidgetClass, form, NULL, 0);
977 	XtAddCallback (wids[2], XtNjumpProc, ScrollCB, (XtPointer) findex);
978 	XtManageChildren (wids, 3);
979     } else {
980 	wids[2] = (Widget) NULL;
981 	XtManageChildren (wids, 2);
982     }
983     AppRes.field[findex].textwidget = wids[1];
984     AppRes.field[findex].scrollwidget = wids[2];
985 }
986 
987 
988 static void
AckWarn(Widget w,XtPointer client,XtPointer call)989 AckWarn (Widget w, XtPointer client, XtPointer call)
990 {
991     XtPopdown((Widget) client);
992     XtDestroyWidget((Widget) client);
993 }
994 
995 static void
AckNoTune(Widget w,XtPointer client,XtPointer call)996 AckNoTune (Widget w, XtPointer client, XtPointer call)
997 {
998     CleanUp(XtDisplay(w));
999 #if XtSpecificationRelease < 6
1000     exit (0);
1001 #else
1002     XtAppSetExitFlag (XtWidgetToApplicationContext (w));
1003 #endif
1004 }
1005 
1006 static void
displayWarning(Widget top)1007 displayWarning(Widget top)
1008 {
1009     Widget w, popup, popupBox;
1010     int x, y;
1011 
1012     x =  DisplayWidth(XtDisplay (top),DefaultScreen (XtDisplay (top))) / 3;
1013     y =  DisplayHeight(XtDisplay (top),DefaultScreen (XtDisplay (top))) / 3;
1014 
1015     popup = XtVaCreatePopupShell("Warning",
1016 			    transientShellWidgetClass, top,
1017 			    XtNtitle, "WARNING",
1018 			    XtNx, x,
1019 			    XtNy, y,
1020 			    NULL);
1021 
1022     popupBox = XtVaCreateManagedWidget(
1023                "WarningBox",
1024                boxWidgetClass,
1025                popup,
1026                NULL);
1027 
1028     w = XtVaCreateManagedWidget( "WarnLabel",
1029                                      labelWidgetClass,
1030 				     popupBox,
1031                                      NULL);
1032 
1033     w = XtVaCreateManagedWidget( "WarnOK",
1034                                      commandWidgetClass,
1035 				     popupBox,
1036                                      NULL);
1037 
1038     XtAddCallback (w, XtNcallback, AckWarn, (XtPointer)popup);
1039 
1040     w = XtVaCreateManagedWidget( "WarnCancel",
1041                                      commandWidgetClass,
1042 				     popupBox,
1043                                      NULL);
1044     XtAddCallback (w, XtNcallback, QuitCB, (XtPointer)NULL);
1045 
1046     XtPopup(popup, XtGrabExclusive);
1047 
1048 }
1049 
1050 static void
displayNoTune(Widget top)1051 displayNoTune(Widget top)
1052 {
1053     Widget w, popup, popupBox;
1054 
1055     popup = XtCreateWidget ("Notice", formWidgetClass, top, NULL, 0);
1056     popupBox = XtVaCreateManagedWidget(
1057                "WarningBox",
1058                boxWidgetClass,
1059                popup,
1060                NULL);
1061 
1062     w = XtVaCreateManagedWidget( "NoTuneLabel",
1063                                      labelWidgetClass,
1064 				     popupBox,
1065                                      NULL);
1066 
1067     w = XtVaCreateManagedWidget( "NoTuneOK",
1068                                      commandWidgetClass,
1069 				     popupBox,
1070                                      NULL);
1071 
1072     XtAddCallback (w, XtNcallback, AckNoTune, (XtPointer)popup);
1073 
1074     XtManageChild (popup);
1075 }
1076 
1077 #if 0
1078 static void
1079 s3Special(Widget top)
1080 {
1081     Widget w, popup, form, invert_vclk_toggle, wids[6];
1082     char buf1[5] = {'\0',};
1083     int x, y;
1084 
1085     x =  DisplayWidth(XtDisplay (top),DefaultScreen (XtDisplay (top))) / 3;
1086     y =  DisplayHeight(XtDisplay (top),DefaultScreen (XtDisplay (top))) / 3;
1087 
1088     popup = XtVaCreatePopupShell("S3Adjust",
1089 			    transientShellWidgetClass, top,
1090 			    XtNtitle, "S3Adjust",
1091 			    XtNx, x,
1092 			    XtNy, y,
1093 			    NULL);
1094 
1095     form = XtVaCreateManagedWidget(
1096                "S3Box",
1097                formWidgetClass,
1098                popup,
1099                NULL);
1100 
1101     w = XtVaCreateManagedWidget( "S3Title",
1102                                      labelWidgetClass,
1103 				     form,
1104                                      NULL);
1105 
1106     invert_vclk_toggle = XtVaCreateManagedWidget( "InvertVclk-toggle",
1107                                      toggleWidgetClass,
1108 				     form,
1109                                      NULL);
1110 
1111     wids[0] = XtCreateWidget ("Blank1-label", labelWidgetClass,
1112 		form, NULL, 0);
1113     wids[1] = XtVaCreateWidget ("Blank1-text", asciiTextWidgetClass,
1114 		form, XtNstring, buf1, NULL);
1115     AddCallback (wids[1], XtNcallback, FlagsEditCB, (XtPointer) NULL);
1116 
1117     XtManageChildren (wids, 2);
1118 
1119     XtPopup(popup, XtGrabNone);
1120 
1121 }
1122 #endif
1123 
1124 
1125 
1126 static void
CreateHierarchy(Widget top)1127 CreateHierarchy(Widget top)
1128 {
1129     char buf[5];
1130     Widget form, forms[14], s3form;
1131     Widget wids[10];
1132     Widget boxW, popdownW, w;
1133     int i;
1134     int x, y;
1135     static String form_names[] = {
1136 	"HDisplay-form",
1137 	"HSyncStart-form",
1138 	"HSyncEnd-form",
1139 	"HTotal-form",
1140 	"VDisplay-form",
1141 	"VSyncStart-form",
1142 	"VSyncEnd-form",
1143 	"VTotal-form",
1144 	"Flags-form",
1145 	"Buttons-form",
1146 	"PixelClock-form",
1147 	"HSyncRate-form",
1148 	"VSyncRate-form",
1149 	"Buttons2-form",
1150 	};
1151 
1152     form = XtCreateWidget ("form", formWidgetClass, top, NULL, 0);
1153     for (i = 0; i < 14; i++)
1154 	forms[i] = XtCreateWidget (form_names[i], formWidgetClass,
1155 		form, NULL, 0);
1156 
1157     CreateTyp (forms[0], HDisplay, "HDisplay-label", "HDisplay-text", NULL);
1158     CreateTyp (forms[1], HSyncStart, "HSyncStart-label",
1159 		"HSyncStart-text", "HSyncStart-scrollbar");
1160     CreateTyp (forms[2], HSyncEnd, "HSyncEnd-label", "HSyncEnd-text",
1161 		"HSyncEnd-scrollbar");
1162     CreateTyp (forms[3], HTotal, "HTotal-label", "HTotal-text",
1163 		"HTotal-scrollbar");
1164 
1165     w = XtVaCreateManagedWidget(
1166                                      "Left-button",
1167                                      commandWidgetClass,
1168                                      forms[3],
1169                                      NULL);
1170     XtAddCallback (w, XtNcallback, AdjustCB, (XtPointer)HSyncStart);
1171     w = XtVaCreateManagedWidget(
1172                                      "Right-button",
1173                                      commandWidgetClass,
1174                                      forms[3],
1175                                      NULL);
1176     XtAddCallback (w, XtNcallback, AdjustCB, (XtPointer)-HSyncStart);
1177     w=  XtVaCreateManagedWidget(
1178                                      "Wider-button",
1179                                      commandWidgetClass,
1180                                      forms[3],
1181                                      NULL);
1182     XtAddCallback (w, XtNcallback, AdjustCB, (XtPointer)-HTotal);
1183     w = XtVaCreateManagedWidget(
1184                                      "Narrower-button",
1185                                      commandWidgetClass,
1186                                      forms[3],
1187                                      NULL);
1188     XtAddCallback (w, XtNcallback, AdjustCB, (XtPointer)HTotal);
1189     CreateTyp (forms[4], VDisplay, "VDisplay-label", "VDisplay-text", NULL);
1190     CreateTyp (forms[5], VSyncStart, "VSyncStart-label",
1191 		"VSyncStart-text", "VSyncStart-scrollbar");
1192     CreateTyp (forms[6], VSyncEnd, "VSyncEnd-label", "VSyncEnd-text",
1193 		"VSyncEnd-scrollbar");
1194     CreateTyp (forms[7], VTotal, "VTotal-label", "VTotal-text",
1195 		"VTotal-scrollbar");
1196     w = XtVaCreateManagedWidget(
1197                                      "Up-button",
1198                                      commandWidgetClass,
1199                                      forms[7],
1200                                      NULL);
1201     XtAddCallback (w, XtNcallback, AdjustCB, (XtPointer)VSyncStart);
1202     w = XtVaCreateManagedWidget(
1203                                      "Down-button",
1204                                      commandWidgetClass,
1205                                      forms[7],
1206                                      NULL);
1207     XtAddCallback (w, XtNcallback, AdjustCB, (XtPointer)-VSyncStart);
1208     w=  XtVaCreateManagedWidget(
1209                                      "Shorter-button",
1210                                      commandWidgetClass,
1211                                      forms[7],
1212                                      NULL);
1213     XtAddCallback (w, XtNcallback, AdjustCB, (XtPointer)VTotal);
1214     w = XtVaCreateManagedWidget(
1215                                      "Taller-button",
1216                                      commandWidgetClass,
1217                                      forms[7],
1218                                      NULL);
1219     XtAddCallback (w, XtNcallback, AdjustCB, (XtPointer)-VTotal);
1220 
1221     (void) snprintf (buf, sizeof(buf), "%04x", AppRes.field[Flags].val);
1222     wids[0] = XtCreateWidget ("Flags-label", labelWidgetClass,
1223 		forms[8], NULL, 0);
1224     wids[1] = XtVaCreateWidget ("Flags-text", asciiTextWidgetClass,
1225 		forms[8], XtNstring, buf, XtNtranslations, trans, NULL);
1226     AddCallback (wids[1], XtNcallback, FlagsEditCB, (XtPointer) Flags);
1227     XtManageChildren (wids, 2);
1228     AppRes.field[Flags].textwidget = wids[1];
1229 
1230     wids[0] = XtCreateWidget ("Quit-button", commandWidgetClass,
1231 		forms[9], NULL, 0);
1232     XtAddCallback (wids[0], XtNcallback, QuitCB, NULL);
1233 
1234     wids[1] = XtCreateWidget ("Apply-button", commandWidgetClass,
1235 		forms[9], NULL, 0);
1236     XtAddCallback (wids[1], XtNcallback, ApplyCB, NULL);
1237 
1238     wids[2] = XtCreateWidget ("AutoApply-toggle", toggleWidgetClass,
1239 		forms[9], NULL, 0);
1240     auto_apply_toggle = wids[2];
1241 
1242     wids[3] = XtCreateWidget ("Test-button", commandWidgetClass,
1243 		forms[9], NULL, 0);
1244     XtAddCallback (wids[3], XtNcallback, TestCB, NULL);
1245 
1246     wids[4] = XtCreateWidget ("Restore-button", commandWidgetClass,
1247 		forms[9], NULL, 0);
1248     XtAddCallback (wids[4], XtNcallback, RestoreCB, NULL);
1249 
1250     XtManageChildren (wids, 5);
1251 
1252 
1253     CreateTyp (forms[10], PixelClock, "PixelClock-label", "PixelClock-text",
1254 	       NULL);
1255     CreateTyp (forms[11], HSyncRate, "HSyncRate-label", "HSyncRate-text",
1256 	       NULL);
1257     CreateTyp (forms[12], VSyncRate, "VSyncRate-label", "VSyncRate-text",
1258 	       NULL);
1259 
1260     wids[0] = XtCreateWidget ("Fetch-button", commandWidgetClass,
1261 		forms[13], NULL, 0);
1262     XtAddCallback (wids[0], XtNcallback, FetchCB, NULL);
1263 
1264     wids[1] = XtCreateWidget ("Show-button", commandWidgetClass,
1265 		forms[13], NULL, 0);
1266     XtAddCallback (wids[1], XtNcallback, ShowCB, NULL);
1267 
1268     wids[2] = XtCreateWidget ("Next-button", commandWidgetClass,
1269 		forms[13], NULL, 0);
1270     XtAddCallback (wids[2], XtNcallback, SwitchCB, (XtPointer)1);
1271 
1272     wids[3] = XtCreateWidget ("Prev-button", commandWidgetClass,
1273 		forms[13], NULL, 0);
1274     XtAddCallback (wids[3], XtNcallback, SwitchCB, (XtPointer)-1);
1275 
1276     XtManageChildren (wids, 4);
1277 
1278     XtManageChildren (forms, 14);
1279 
1280     if (S3Specials) {
1281 	s3form = XtCreateWidget ("S3-form", formWidgetClass,
1282 		form, NULL, 0);
1283 	wids[0] = XtVaCreateWidget("InvertVclk-toggle", toggleWidgetClass,
1284 			s3form, XtNstate, AppRes.field[InvertVclk].val, NULL);
1285 	XtAddCallback (wids[0], XtNcallback, ApplyIfAutoCB, NULL);
1286 	AppRes.field[InvertVclk].textwidget = wids[0];
1287 	wids[1] = XtVaCreateWidget("EarlySc-toggle", toggleWidgetClass,
1288 			s3form, XtNstate, AppRes.field[EarlySc].val, NULL);
1289 	XtAddCallback (wids[1], XtNcallback, ApplyIfAutoCB, NULL);
1290 	AppRes.field[EarlySc].textwidget = wids[1];
1291 	wids[2] = XtCreateWidget("Blank1-label", labelWidgetClass, s3form,
1292 			NULL, 0);
1293 	wids[3] = XtVaCreateWidget("Blank1Dec-button", commandWidgetClass,
1294 				   s3form, NULL);
1295 	XtAddCallback (wids[3], XtNcallback, ChangeBlankCB,
1296 			(XtPointer)-BlankDelay1);
1297 	(void) snprintf (buf, sizeof(buf), "%d", AppRes.field[BlankDelay1].val);
1298 	wids[4] = XtVaCreateWidget("Blank1-text", asciiTextWidgetClass,
1299 			s3form, XtNstring, buf, XtNtranslations, trans, NULL);
1300 	AddCallback(wids[4], XtNcallback, BlankEditCB, (XPointer) BlankDelay1);
1301 	AppRes.field[BlankDelay1].textwidget = wids[4];
1302 	wids[5] = XtVaCreateWidget("Blank1Inc-button", commandWidgetClass,
1303 				   s3form, NULL);
1304 	XtAddCallback (wids[5], XtNcallback, ChangeBlankCB,
1305 			(XtPointer)BlankDelay1);
1306 
1307 	wids[6] = XtCreateWidget("Blank2-label", labelWidgetClass, s3form,
1308 			NULL, 0);
1309 	wids[7] = XtVaCreateWidget("Blank2Dec-button", commandWidgetClass,
1310 				   s3form, NULL);
1311 	XtAddCallback (wids[7], XtNcallback, ChangeBlankCB,
1312 			(XtPointer)-BlankDelay2);
1313 	(void) snprintf (buf, sizeof(buf), "%d", AppRes.field[BlankDelay2].val);
1314 	wids[8] = XtVaCreateWidget("Blank2-text", asciiTextWidgetClass,
1315 			s3form, XtNstring, buf, XtNtranslations, trans, NULL);
1316 	AddCallback(wids[8], XtNcallback, BlankEditCB, (XPointer) BlankDelay2);
1317 	AppRes.field[BlankDelay2].textwidget = wids[8];
1318 	wids[9] = XtVaCreateWidget("Blank2Inc-button", commandWidgetClass,
1319 				   s3form, NULL);
1320 	XtAddCallback (wids[9], XtNcallback, ChangeBlankCB,
1321 			(XtPointer)BlankDelay2);
1322 	XtManageChildren (wids, 10);
1323 	XtManageChild(s3form);
1324     }
1325 
1326     XtManageChild (form);
1327 
1328     SetScrollbars ();
1329     x = DisplayWidth(XtDisplay (top),DefaultScreen (XtDisplay (top))) / 2;
1330     y = DisplayHeight(XtDisplay (top),DefaultScreen (XtDisplay (top))) / 2;
1331 
1332     invalid_mode_popup = XtVaCreatePopupShell("invalidMode",
1333 			    transientShellWidgetClass, top,
1334 			    XtNtitle, "Invalid Mode requested",
1335 			    XtNx, x - 20,
1336 			    XtNy, y - 40,
1337 			    NULL);
1338 
1339     testing_popup = XtVaCreatePopupShell("testing",
1340 			    transientShellWidgetClass, top,
1341 			    XtNtitle, "Testing_1_2_3",
1342 			    XtNx, x - 20,
1343 			    XtNy, y - 40,
1344 			    NULL);
1345     boxW = XtVaCreateManagedWidget(
1346                                    "TestingBox",
1347                                    boxWidgetClass,
1348                                    testing_popup,
1349                                    NULL);
1350 
1351     w = XtVaCreateManagedWidget(
1352 		   "testingMessage",
1353                    labelWidgetClass,
1354                    boxW,
1355                    NULL);
1356 
1357     w = XtVaCreateManagedWidget(
1358                                "Abort",
1359                                 commandWidgetClass,
1360                                 boxW,
1361                                 NULL);
1362 
1363     XtAddCallback (w, XtNcallback, (XtCallbackProc) TestTOCB,
1364 		  (XtPointer) NULL);
1365 
1366     boxW = XtVaCreateManagedWidget(
1367                                    "invalidBox",
1368                                    boxWidgetClass,
1369                                    invalid_mode_popup,
1370                                    NULL);
1371 
1372     (void) XtVaCreateManagedWidget(
1373 		   "ErrorMessage",
1374                    labelWidgetClass,
1375                    boxW,
1376                    NULL);
1377 
1378     popdownW = XtVaCreateManagedWidget(
1379                                      "AckError",
1380                                      commandWidgetClass,
1381                                      boxW,
1382                                      NULL);
1383 
1384     XtAddCallback (popdownW, XtNcallback, (XtCallbackProc)popdownInvalid,
1385 		   (XtPointer) invalid_mode_popup);
1386 }
1387 
1388 static void
QuitAction(Widget w,XEvent * e,String * vector,Cardinal * count)1389 QuitAction (Widget w, XEvent* e, String* vector, Cardinal* count)
1390 {
1391     if ((e->type == ClientMessage
1392       && e->xclient.data.l[0] == (long) wm_delete_window)
1393 	|| e->type == KeyPress)
1394 	QuitCB(w, NULL, NULL);
1395 }
1396 
1397 static void
RestoreAction(Widget w,XEvent * e,String * vector,Cardinal * count)1398 RestoreAction (Widget w, XEvent* e, String* vector, Cardinal* count)
1399 {
1400     Boolean state;
1401 
1402     RestoreCB(w, NULL, NULL);
1403     XtVaGetValues(auto_apply_toggle, XtNstate, &state, NULL);
1404     if (!state)
1405 	ApplyCB (w, NULL, NULL);
1406 }
1407 
1408 
1409 static void
ShowAction(Widget w,XEvent * e,String * vector,Cardinal * count)1410 ShowAction(Widget w, XEvent* e, String* vector, Cardinal* count)
1411 {
1412     ShowCB(w, NULL, NULL);
1413 }
1414 
1415 static void
MoveLeftAction(Widget w,XEvent * e,String * vector,Cardinal * count)1416 MoveLeftAction(Widget w, XEvent* e, String* vector, Cardinal* count)
1417 {
1418     AdjustCB(w, (XtPointer)HSyncStart, NULL);
1419 }
1420 
1421 static void
MoveRightAction(Widget w,XEvent * e,String * vector,Cardinal * count)1422 MoveRightAction(Widget w, XEvent* e, String* vector, Cardinal* count)
1423 {
1424     AdjustCB(w, (XtPointer)-HSyncStart, NULL);
1425 }
1426 
1427 static void
NarrowerAction(Widget w,XEvent * e,String * vector,Cardinal * count)1428 NarrowerAction(Widget w, XEvent* e, String* vector, Cardinal* count)
1429 {
1430     AdjustCB(w, (XtPointer)HTotal, NULL);
1431 }
1432 
1433 static void
WiderAction(Widget w,XEvent * e,String * vector,Cardinal * count)1434 WiderAction(Widget w, XEvent* e, String* vector, Cardinal* count)
1435 {
1436     AdjustCB(w, (XtPointer)-HTotal, NULL);
1437 }
1438 
1439 static void
MoveUpAction(Widget w,XEvent * e,String * vector,Cardinal * count)1440 MoveUpAction(Widget w, XEvent* e, String* vector, Cardinal* count)
1441 {
1442     AdjustCB(w, (XtPointer)VSyncStart, NULL);
1443 }
1444 
1445 static void
MoveDownAction(Widget w,XEvent * e,String * vector,Cardinal * count)1446 MoveDownAction(Widget w, XEvent* e, String* vector, Cardinal* count)
1447 {
1448     AdjustCB(w, (XtPointer)-VSyncStart, NULL);
1449 }
1450 
1451 static void
TallerAction(Widget w,XEvent * e,String * vector,Cardinal * count)1452 TallerAction(Widget w, XEvent* e, String* vector, Cardinal* count)
1453 {
1454     AdjustCB(w, (XtPointer)-VTotal, NULL);
1455 }
1456 
1457 static void
ShorterAction(Widget w,XEvent * e,String * vector,Cardinal * count)1458 ShorterAction(Widget w, XEvent* e, String* vector, Cardinal* count)
1459 {
1460     AdjustCB(w, (XtPointer)VTotal, NULL);
1461 }
1462 
1463 static void
NextModeAction(Widget w,XEvent * e,String * vector,Cardinal * count)1464 NextModeAction(Widget w, XEvent* e, String* vector, Cardinal* count)
1465 {
1466 	SwitchCB(w, (XPointer) 1, NULL);
1467 }
1468 
1469 static void
PrevModeAction(Widget w,XEvent * e,String * vector,Cardinal * count)1470 PrevModeAction(Widget w, XEvent* e, String* vector, Cardinal* count)
1471 {
1472 	SwitchCB(w, (XPointer) -1, NULL);
1473 }
1474 
1475 
1476 
1477 static void
usage(void)1478 usage(void)
1479 {
1480     fprintf(stderr, "Usage: xvidtune [option]\n");
1481     fprintf(stderr, "    where option is one of:\n");
1482     fprintf(stderr, "        -show                             Print current modeline to stdout\n");
1483     fprintf(stderr, "        -next                             Switch to next video mode\n");
1484     fprintf(stderr, "        -prev                             Switch to previous video mode\n");
1485     fprintf(stderr, "        -unlock                           Enable mode switch hot-keys\n");
1486     fprintf(stderr, "        -timeout [seconds]                Set testmode timeout in seconds,\n");
1487     exit(1);
1488 }
1489 
1490 
1491 int
main(int argc,char ** argv)1492 main (int argc, char** argv)
1493 {
1494     Widget top;
1495     XtAppContext app;
1496     Display* dpy;
1497     Bool modeSettable = TRUE;
1498 
1499     static XtActionsRec actions[] = { { "xvidtune-quit", QuitAction },
1500 				      { "xvidtune-restore", RestoreAction },
1501 				      { "xvidtune-show", ShowAction },
1502 				      {	"xvidtune-moveleft", MoveLeftAction },
1503 				      {	"xvidtune-moveright", MoveRightAction },
1504 				      {	"xvidtune-wider", WiderAction },
1505 				      {	"xvidtune-narrower", NarrowerAction },
1506 				      {	"xvidtune-moveup", MoveUpAction },
1507 				      {	"xvidtune-movedown", MoveDownAction },
1508 				      {	"xvidtune-taller", TallerAction },
1509 				      {	"xvidtune-shorter", ShorterAction },
1510 				      {	"xvidtune-nextmode", NextModeAction },
1511 				      {	"xvidtune-prevmode", PrevModeAction } };
1512 
1513     Top = top = XtVaOpenApplication (&app, "Xvidtune", NULL, 0, &argc, argv,
1514 		NULL, applicationShellWidgetClass,
1515 		XtNmappedWhenManaged, False, NULL);
1516 
1517     XtGetApplicationResources (top, (XtPointer)&AppRes,
1518 		Resources, XtNumber(Resources),
1519 		NULL, 0);
1520 
1521     if (!AppRes.ad_installed) {
1522 	fprintf(stderr, "Please install the program before using\n");
1523 	return 3;
1524     }
1525 
1526     if (!XF86VidModeQueryVersion(XtDisplay (top), &MajorVersion, &MinorVersion)) {
1527 	fprintf(stderr, "Unable to query video extension version\n");
1528 	return 2;
1529     }
1530 
1531     if (!XF86VidModeQueryExtension(XtDisplay (top), &EventBase, &ErrorBase)) {
1532 	fprintf(stderr, "Unable to query video extension information\n");
1533 	return 2;
1534     }
1535 
1536     /* Fail if the extension version in the server is too old */
1537     if (MajorVersion < MINMAJOR ||
1538 	(MajorVersion == MINMAJOR && MinorVersion < MINMINOR)) {
1539 	fprintf(stderr,
1540 		"Xserver is running an old XFree86-VidModeExtension version"
1541 		" (%d.%d)\n", MajorVersion, MinorVersion);
1542 	fprintf(stderr, "Minimum required version is %d.%d\n",
1543 		MINMAJOR, MINMINOR);
1544 	exit(2);
1545     }
1546 
1547     /* This should probably be done differently */
1548 
1549     if(  argc == 3  ) { /* this can only be the timeout case */
1550         if(  (!strcmp(argv[1], "-timeout"))  ) {
1551             TestTimeout = ((unsigned long) atol( argv[2] )) * 1000L;
1552 	}
1553 	else
1554 	    usage();
1555     }
1556 
1557     if (argc > 1) {
1558 	int i = 0;
1559 
1560 	if (argc != 2)
1561 		usage();
1562 	if (!strcmp(argv[1], "-show")) {
1563 	  if (!GetModeLine(XtDisplay (top), DefaultScreen (XtDisplay (top)))) {
1564 	    fprintf(stderr, "Unable to get mode info\n");
1565 	    CleanUp(XtDisplay (top));
1566 	    return 2;
1567 	  }
1568 	  ShowCB(top, NULL, NULL);
1569 	  return 0;
1570 	} else if (!strcmp(argv[1], "-next"))
1571 	    i = 1;
1572 	else if (!strcmp(argv[1], "-prev"))
1573 	    i = -1;
1574 	else if (!strcmp(argv[1], "-unlock")) {
1575 	    CleanUp(XtDisplay (top));
1576 	    XSync(XtDisplay (top), True);
1577 	    return 0;
1578 	} else
1579 		usage();
1580 	if (i != 0) {
1581 	    XF86VidModeSwitchMode(XtDisplay (top),
1582 				  DefaultScreen (XtDisplay (top)), i);
1583 	    XSync(XtDisplay (top), True);
1584 	    return 0;
1585 	}
1586     }
1587     if (!GetMonitor(XtDisplay (top), DefaultScreen (XtDisplay (top)))) {
1588 	fprintf(stderr, "Unable to query monitor info\n");
1589 	return 2;
1590     }
1591 
1592     if (!XF86VidModeLockModeSwitch(XtDisplay (top),
1593 				   DefaultScreen (XtDisplay (top)), TRUE)) {
1594 	fprintf(stderr, "Failed to disable mode-switch hot-keys\n");
1595 	return 2;
1596     }
1597 
1598     signal(SIGINT, CatchSig);
1599     signal(SIGQUIT, CatchSig);
1600     signal(SIGTERM, CatchSig);
1601     signal(SIGHUP, CatchSig);
1602     sigId = XtAppAddSignal(app, CatchXtSig, NULL);
1603 
1604     if (!GetModeLine(XtDisplay (top), DefaultScreen (XtDisplay (top)))) {
1605 	fprintf(stderr, "Unable to get mode info\n");
1606 	CleanUp(XtDisplay (top));
1607 	return 2;
1608     }
1609 
1610     xtErrorfunc = XSetErrorHandler(vidmodeError);
1611 
1612     trans = XtParseTranslationTable ("\
1613 	<Key>0: insert-char()\n<Key>1: insert-char()\n\
1614 	<Key>2: insert-char()\n<Key>3: insert-char()\n\
1615 	<Key>4: insert-char()\n<Key>5: insert-char()\n\
1616 	<Key>6: insert-char()\n<Key>7: insert-char()\n\
1617 	<Key>8: insert-char()\n<Key>9: insert-char()\n\
1618 	<Key>a: insert-char()\n<Key>b: insert-char()\n\
1619 	<Key>c: insert-char()\n<Key>d: insert-char()\n\
1620 	<Key>e: insert-char()\n<Key>f: insert-char()\n\
1621 	<Key>+: insert-char()\n<Key>-: insert-char()\n\
1622 	<Key>r: xvidtune-restore()\n<Key>q: xvidtune-quit()\n\
1623 	<Key>BackSpace: delete-previous-character()\n\
1624 	<Key>Right: forward-character()\n<Key>KP_Right: forward-character()\n\
1625 	<Key>Left: backward-character()\n<Key>KP_Left: backward-character()\n\
1626 	<Key>Delete: delete-previous-character()\n\
1627 	<Key>KP_Delete: delete-previous-character()\n\
1628 	<EnterWindow>: enter-window()\n<LeaveWindow>: leave-window()\n\
1629 	<FocusIn>: focus-in()\n<FocusOut>: focus-out()\n\
1630 	<Btn1Down>: select-start()\n");
1631 
1632     if (!ModeSettable()) {
1633 	printf("Video modes are not settable on this chip\n");
1634 	displayNoTune(top);
1635 	modeSettable = FALSE;
1636     } else
1637 	CreateHierarchy (top);
1638 
1639 
1640     XtAppAddActions (app, actions, XtNumber(actions));
1641 
1642     XtOverrideTranslations (top,
1643 		XtParseTranslationTable ("<Message>WM_PROTOCOLS: xvidtune-quit()"));
1644 
1645     XtRealizeWidget (top);
1646 
1647     dpy = XtDisplay(top);
1648 
1649     wm_delete_window = XInternAtom (dpy, "WM_DELETE_WINDOW", False);
1650 
1651     (void) XSetWMProtocols (dpy, XtWindow (top), &wm_delete_window, 1);
1652 
1653     XtMapWidget (top);
1654 
1655     if (modeSettable)
1656 	displayWarning(top);
1657 
1658     /* really we should run our own event dispatching here until the
1659      * warning has been read...
1660      */
1661     XtAppMainLoop (app);
1662 
1663     return 0;
1664 }
1665