~ubuntu-branches/ubuntu/gutsy/vnc4/gutsy

« back to all changes in this revision

Viewing changes to unix/xc/programs/Xserver/hw/xfree86/xf86cfg/vidmode.c

  • Committer: Bazaar Package Importer
  • Author(s): Ola Lundqvist
  • Date: 2006-05-15 20:35:17 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20060515203517-l4lre1ku942mn26k
Tags: 4.1.1+X4.3.0-10
* Correction of critical security issue. Thanks to Martin Kogler
  <e9925248@student.tuwien.ac.at> that informed me about the issue,
  and provided the patch.
  This flaw was originally found by Steve Wiseman of intelliadmin.com.
* Applied patch from Javier Kohen <jkohen@users.sourceforge.net> that
  inform the user that only 8 first characters of the password will
  actually be used when typing more than 8 characters, closes:
  #355619.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (c) 2000 by Conectiva S.A. (http://www.conectiva.com)
 
3
 * 
 
4
 * Permission is hereby granted, free of charge, to any person obtaining a
 
5
 * copy of this software and associated documentation files (the "Software"),
 
6
 * to deal in the Software without restriction, including without limitation
 
7
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 
8
 * and/or sell copies of the Software, and to permit persons to whom the
 
9
 * Software is furnished to do so, subject to the following conditions:
 
10
 * 
 
11
 * The above copyright notice and this permission notice shall be included in
 
12
 * all copies or substantial portions of the Software.
 
13
 *  
 
14
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 
15
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 
16
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 
17
 * CONECTIVA LINUX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 
18
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
 
19
 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 
20
 * SOFTWARE.
 
21
 * 
 
22
 * Except as contained in this notice, the name of Conectiva Linux shall
 
23
 * not be used in advertising or otherwise to promote the sale, use or other
 
24
 * dealings in this Software without prior written authorization from
 
25
 * Conectiva Linux.
 
26
 *
 
27
 * Author: Paulo C�sar Pereira de Andrade <pcpa@conectiva.com.br>
 
28
 *
 
29
 * $XFree86: xc/programs/Xserver/hw/xfree86/xf86cfg/vidmode.c,v 1.7 2001/07/07 23:00:43 paulo Exp $
 
30
 */
 
31
 
 
32
/*
 
33
 * Most of the code here is based on the xvidtune code.
 
34
 */
 
35
 
 
36
#include "vidmode.h"
 
37
#include <X11/Xaw/Command.h>
 
38
#include <X11/Xaw/Form.h>
 
39
#include <X11/Xaw/Label.h>
 
40
#include <X11/Xaw/MenuButton.h>
 
41
#include <X11/Xaw/Repeater.h>
 
42
#include <X11/Shell.h>
 
43
#include <X11/Xaw/AsciiText.h>
 
44
#include <X11/Xaw/Dialog.h>
 
45
#include <X11/Xaw/SimpleMenP.h>
 
46
#include <X11/Xaw/SmeBSB.h>
 
47
#include <X11/Xaw/Toggle.h>
 
48
#include "xf86config.h"
 
49
 
 
50
#define V_FLAG_MASK     0x1FF
 
51
#define V_PHSYNC        0x001 
 
52
#define V_NHSYNC        0x002
 
53
#define V_PVSYNC        0x004
 
54
#define V_NVSYNC        0x008
 
55
#define V_INTERLACE     0x010 
 
56
#define V_DBLSCAN       0x020
 
57
#define V_CSYNC         0x040
 
58
#define V_PCSYNC        0x080
 
59
#define V_NCSYNC        0x100
 
60
 
 
61
#define LEFT            0
 
62
#define RIGHT           1
 
63
#define UP              2
 
64
#define DOWN            3
 
65
#define WIDER           4
 
66
#define TALLER          5
 
67
#define NARROWER        6
 
68
#define SHORTER         7
 
69
 
 
70
#define HDISPLAY        0
 
71
#define VDISPLAY        1
 
72
#define HSYNCSTART      2
 
73
#define HSYNCEND        3
 
74
#define HTOTAL          4
 
75
#define VSYNCSTART      5
 
76
#define VSYNCEND        6
 
77
#define VTOTAL          7
 
78
#define FLAGS           8
 
79
#define CLOCK           9
 
80
#define HSYNC           10
 
81
#define VSYNC           11
 
82
 
 
83
#define MINMAJOR         2
 
84
#define MINMINOR         0
 
85
 
 
86
/*
 
87
 * Types
 
88
 */
 
89
typedef struct {
 
90
    char *ident;
 
91
    XF86VidModeModeInfo info;
 
92
} xf86cfgVesaModeInfo;
 
93
 
 
94
/*
 
95
 * Prototypes
 
96
 */
 
97
static Bool GetModeLine(Bool);
 
98
static void StartAdjustMonitorCallback(Widget, XtPointer, XtPointer);
 
99
static void AdjustMonitorCallback(Widget, XtPointer, XtPointer);
 
100
static void EndAdjustMonitorCallback(Widget, XtPointer, XtPointer);
 
101
static void SetLabel(int, int);
 
102
static void UpdateSyncRates(Bool);
 
103
static int VidmodeError(Display*, XErrorEvent*);
 
104
static void CleanUp(Display*);
 
105
static void ApplyCallback(Widget, XtPointer, XtPointer);
 
106
static void AutoCallback(Widget, XtPointer, XtPointer);
 
107
static void RestoreCallback(Widget, XtPointer, XtPointer);
 
108
static void SelectCallback(Widget, XtPointer, XtPointer);
 
109
static void SelectMonitorCallback(Widget, XtPointer, XtPointer);
 
110
static void SwitchCallback(Widget, XtPointer, XtPointer);
 
111
static void SetLabels(void);
 
112
static void UpdateCallback(Widget, XtPointer, XtPointer);
 
113
static void ChangeScreenCallback(Widget, XtPointer, XtPointer);
 
114
static void SetLabelAndModeline(void);
 
115
static void AddVesaModeCallback(Widget, XtPointer, XtPointer);
 
116
static void GetModes(void);
 
117
static void AddModeCallback(Widget, XtPointer, XtPointer);
 
118
static void TestCallback(Widget, XtPointer, XtPointer);
 
119
static void TestTimeout(XtPointer, XtIntervalId*);
 
120
static void StopTestCallback(Widget, XtPointer, XtPointer);
 
121
static int ForceAddMode(void);
 
122
static int AddMode(void);
 
123
/*
 
124
 * Initialization
 
125
 */
 
126
extern Widget work;
 
127
Widget vtune;
 
128
static Widget apply, automatic, restore, mode, menu, screenb, screenp;
 
129
static Bool autoflag;
 
130
static xf86cfgVidmode *vidtune;
 
131
static XF86VidModeModeLine modeline, orig_modeline;
 
132
static int dot_clock, hsync_rate, vsync_rate, hitError;
 
133
static Bool S3Specials;
 
134
static int invert_vclk, blank1, blank2, early_sc, screenno;
 
135
static int (*XtErrorFunc)(Display*, XErrorEvent*);
 
136
static Widget labels[VSYNC + 1], values[VSYNC + 1], repeater, monitor,
 
137
              monitorb, add, text, vesab, vesap, forceshell, testshell, addshell;
 
138
static int MajorVersion, MinorVersion, EventBase, ErrorBase;
 
139
static XtIntervalId timeout;
 
140
 
 
141
/* The information bellow is extracted from
 
142
 * xc/programs/Xserver/hw/xfree86/etc/vesamodes
 
143
 * If that file is changed, please update the table bellow also. Or even
 
144
 * better, write a script to generate the table.
 
145
 */
 
146
static xf86cfgVesaModeInfo vesamodes[] = {
 
147
    {
 
148
        "640x350 @ 85Hz (VESA) hsync: 37.9kHz",
 
149
        {
 
150
            31500, 640, 672, 736, 832, 0, 350, 382, 385, 445,
 
151
            V_PHSYNC | V_NVSYNC
 
152
        }
 
153
    },
 
154
    {
 
155
        "640x400 @ 85Hz (VESA) hsync: 37.9kHz",
 
156
        {
 
157
            31500, 640, 672, 736, 832, 0, 400, 401, 404, 445,
 
158
            V_NHSYNC | V_PVSYNC
 
159
        }
 
160
    },
 
161
    {
 
162
        "720x400 @ 85Hz (VESA) hsync: 37.9kHz",
 
163
        {
 
164
            35500, 720, 756, 828, 936, 0, 400, 401, 404, 446,
 
165
            V_NHSYNC | V_PVSYNC
 
166
        }
 
167
    },
 
168
    {
 
169
        "640x480 @ 60Hz (Industry standard) hsync: 31.5kHz",
 
170
        {
 
171
            25200, 640, 656, 752, 800, 0, 480, 490, 492, 525,
 
172
            V_NHSYNC | V_NVSYNC
 
173
        }
 
174
    },
 
175
    {
 
176
        "640x480 @ 72Hz (VESA) hsync: 37.9kHz",
 
177
        {
 
178
            31500, 640, 664, 704, 832, 0, 480, 489, 491, 520,
 
179
            V_NHSYNC | V_NVSYNC
 
180
        }
 
181
    },
 
182
    {
 
183
        "640x480 @ 75Hz (VESA) hsync: 37.5kHz",
 
184
        {
 
185
            31500, 640, 656, 720, 840, 0, 480, 481, 484, 500,
 
186
            V_NHSYNC | V_NVSYNC
 
187
        }
 
188
    },
 
189
    {
 
190
        "640x480 @ 85Hz (VESA) hsync: 43.3kHz",
 
191
        {
 
192
            36000, 640, 696, 752, 832, 0, 480, 481, 484, 509,
 
193
            V_NHSYNC | V_NVSYNC
 
194
        }
 
195
    },
 
196
    {
 
197
        "800x600 @ 56Hz (VESA) hsync: 35.2kHz",
 
198
        {
 
199
            36000, 800, 824, 896, 1024, 0, 600, 601, 603, 625,
 
200
            V_PHSYNC | V_PVSYNC
 
201
        }
 
202
    },
 
203
    {
 
204
        "800x600 @ 60Hz (VESA) hsync: 37.9kHz",
 
205
        {
 
206
            400000, 800, 840, 968, 1056, 0, 600, 601, 605, 628,
 
207
            V_PHSYNC | V_PVSYNC
 
208
        }
 
209
    },
 
210
    {
 
211
        "800x600 @ 72Hz (VESA) hsync: 48.1kHz",
 
212
        {
 
213
            50000, 800, 856, 976, 1040, 0, 600, 637, 643, 666,
 
214
            V_PHSYNC | V_PVSYNC
 
215
        }
 
216
    },
 
217
    {
 
218
        "800x600 @ 75Hz (VESA) hsync: 46.9kHz",
 
219
        {
 
220
            49500, 800, 816, 896, 1056, 0, 600, 601, 604, 625,
 
221
            V_PHSYNC | V_PVSYNC
 
222
        }
 
223
    },
 
224
    {
 
225
        "800x600 @ 85Hz (VESA) hsync: 53.7kHz",
 
226
        {
 
227
            563000, 800, 832, 896, 1048, 0, 600, 601, 604, 631,
 
228
            V_PHSYNC | V_PVSYNC
 
229
        }
 
230
    },
 
231
    {
 
232
        "1024x768i @ 43Hz (industry standard) hsync: 35.5kHz",
 
233
        {
 
234
            44900, 1024, 1032, 1208, 1264, 0, 768, 768, 776, 817,
 
235
            V_PHSYNC | V_PVSYNC | V_INTERLACE
 
236
        }
 
237
    },
 
238
    {
 
239
        "1024x768 @ 60Hz (VESA) hsync: 48.4kHz",
 
240
        {
 
241
            65000, 1024, 1048, 1184, 1344, 0, 768, 771, 777, 806,
 
242
            V_NHSYNC | V_NVSYNC
 
243
        }
 
244
    },
 
245
    {
 
246
        "1024x768 @ 70Hz (VESA) hsync: 56.5kHz",
 
247
        {
 
248
            75000, 1024, 1048, 1184, 1328, 0, 768, 771, 777, 806,
 
249
            V_NHSYNC | V_NVSYNC
 
250
        }
 
251
    },
 
252
    {
 
253
        "1024x768 @ 75Hz (VESA) hsync: 60.0kHz",
 
254
        {
 
255
            78800, 1024, 1040, 1136, 1312, 0, 768, 769, 772, 800,
 
256
            V_PHSYNC | V_PVSYNC
 
257
        }
 
258
    },
 
259
    {
 
260
        "1024x768 @ 85Hz (VESA) hsync: 68.7kHz",
 
261
        {
 
262
            94500, 1024, 1072, 1168, 1376, 0, 768, 769, 772, 808,
 
263
            V_PHSYNC | V_PVSYNC
 
264
        }
 
265
    },
 
266
    {
 
267
        "1152x864 @ 75Hz (VESA) hsync: 67.5kHz",
 
268
        {
 
269
            108000, 1152, 1216, 1344, 1600, 0, 864, 865, 868, 900,
 
270
            V_PHSYNC | V_PVSYNC
 
271
        }
 
272
    },
 
273
    {
 
274
        "1280x960 @ 60Hz (VESA) hsync: 60.0kHz",
 
275
        {
 
276
            108000, 1280, 1376, 1488, 1800, 0, 960, 961, 964, 1000,
 
277
            V_PHSYNC | V_PVSYNC
 
278
        }
 
279
    },
 
280
    {
 
281
        "1280x960 @ 85Hz (VESA) hsync: 85.9kHz",
 
282
        {
 
283
            148500, 1280, 1344, 1504, 1728, 0, 960, 961, 964, 1011,
 
284
            V_PHSYNC | V_PVSYNC
 
285
        }
 
286
    },
 
287
    {
 
288
        "1280x1024 @ 60Hz (VESA) hsync: 64.0kHz",
 
289
        {
 
290
            108000, 1280, 1328, 1440, 1688, 0, 1024, 1025, 1028, 1066,
 
291
            V_PHSYNC | V_PVSYNC
 
292
        }
 
293
    },
 
294
    {
 
295
        "1280x1024 @ 75Hz (VESA) hsync: 80.0kHz",
 
296
        {
 
297
            135000, 1280, 1296, 1440, 1688, 0, 1024, 1025, 1028, 1066,
 
298
            V_PHSYNC | V_PVSYNC
 
299
        }
 
300
    },
 
301
    {
 
302
        "1280x1024 @ 85Hz (VESA) hsync: 91.1kHz",
 
303
        {
 
304
            157500, 1280, 1344, 1504, 1728, 0, 1024, 1025, 1028, 1072,
 
305
            V_PHSYNC | V_PVSYNC
 
306
        }
 
307
    },
 
308
    {
 
309
        "1600x1200 @ 60Hz (VESA) hsync: 75.0kHz",
 
310
        {
 
311
            162000, 1600, 1664, 1856, 2160, 0, 1200, 1201, 1204, 1250,
 
312
            V_PHSYNC | V_PVSYNC
 
313
        }
 
314
    },
 
315
    {
 
316
        "1600x1200 @ 65Hz (VESA) hsync: 81.3kHz",
 
317
        {
 
318
            175500, 1600, 1664, 1856, 2160, 0, 1200, 1201, 1204, 1250,
 
319
            V_PHSYNC | V_PVSYNC
 
320
        }
 
321
    },
 
322
    {
 
323
        "1600x1200 @ 70Hz (VESA) hsync: 87.5kHz",
 
324
        {
 
325
            189000, 1600, 1664, 1856, 2160, 0, 1200, 1201, 1204, 1250,
 
326
            V_PHSYNC | V_PVSYNC
 
327
        }
 
328
    },
 
329
    {
 
330
        "1600x1200 @ 75Hz (VESA) hsync: 93.8kHz",
 
331
        {
 
332
            202500, 1600, 1664, 1856, 2160, 0, 1200, 1201, 1204, 1250,
 
333
            V_PHSYNC | V_PVSYNC
 
334
        }
 
335
    },
 
336
    {
 
337
        "1600x1200 @ 85Hz (VESA) hsync: 106.3kHz",
 
338
        {
 
339
            229500, 1600, 1664, 1856, 2160, 0, 1200, 1201, 1204, 1250,
 
340
            V_PHSYNC | V_PVSYNC
 
341
        }
 
342
    },
 
343
    {
 
344
        "1792x1344 @ 60Hz (VESA) hsync: 83.6kHz",
 
345
        {
 
346
            204800, 1792, 1920, 2120, 2448, 0, 1344, 1345, 1348, 1394,
 
347
            V_NHSYNC | V_PVSYNC
 
348
        }
 
349
    },
 
350
    {
 
351
        "1792x1344 @ 75Hz (VESA) hsync: 106.3kHz",
 
352
        {
 
353
            261000, 1792, 1888, 2104, 2456, 0, 1344, 1345, 1348, 1417,
 
354
            V_NHSYNC | V_PVSYNC
 
355
        }
 
356
    },
 
357
    {
 
358
        "1856x1392 @ 60Hz (VESA) hsync: 86.3kHz",
 
359
        {
 
360
            218300, 1856, 1952, 2176, 2528, 0, 1392, 1393, 1396, 1439,
 
361
            V_NHSYNC | V_PVSYNC
 
362
        }
 
363
    },
 
364
    {
 
365
        "1856x1392 @ 75Hz (VESA) hsync: 112.5kHz",
 
366
        {
 
367
            288000, 1856, 1984, 2208, 2560, 0, 1392, 1393, 1396, 1500,
 
368
            V_NHSYNC | V_PVSYNC
 
369
        }
 
370
    },
 
371
    {
 
372
        "1920x1440 @ 60Hz (VESA) hsync: 90.0kHz",
 
373
        {
 
374
            234000, 1920, 2048, 2256, 2600, 0, 1440, 1441, 1444, 1500,
 
375
            V_NHSYNC | V_PVSYNC
 
376
        }
 
377
    },
 
378
    {
 
379
        "1920x1440 @ 75Hz (VESA) hsync: 112.5kHz",
 
380
        {
 
381
            297000, 1920, 2064, 2288, 2640, 0, 1440, 1441, 1444, 1500,
 
382
            V_NHSYNC | V_PVSYNC
 
383
        }
 
384
    },
 
385
};
 
386
 
 
387
/*
 
388
 * Implementation
 
389
 */
 
390
Bool
 
391
VideoModeInitialize(void)
 
392
{
 
393
    Widget form;
 
394
    char dispstr[128], *ptr, *tmp;
 
395
 
 
396
    static char *names[] = {
 
397
        NULL,
 
398
        NULL,
 
399
        "hsyncstart",
 
400
        "hsyncend",
 
401
        "htotal",
 
402
        "vsyncstart",
 
403
        "vsyncend",
 
404
        "vtotal",
 
405
        "flags",
 
406
        "clock",
 
407
        "hsync",
 
408
        "vsync",
 
409
    };
 
410
    static char *vnames[] = {
 
411
        NULL,
 
412
        NULL,
 
413
        "v-hsyncstart",
 
414
        "v-hsyncend",
 
415
        "v-htotal",
 
416
        "v-vsyncstart",
 
417
        "v-vsyncend",
 
418
        "v-vtotal",
 
419
        "v-flags",
 
420
        "v-clock",
 
421
        "v-hsync",
 
422
        "v-vsync",
 
423
    };
 
424
    Widget rep;
 
425
    int i;
 
426
 
 
427
    if (!XF86VidModeQueryVersion(XtDisplay(toplevel),
 
428
                                 &MajorVersion, &MinorVersion)) {
 
429
        fprintf(stderr, "Unable to query video extension version\n");
 
430
        return (False);
 
431
    }
 
432
    else if (!XF86VidModeQueryExtension(XtDisplay(toplevel),
 
433
                                        &EventBase, &ErrorBase)) {
 
434
        fprintf(stderr, "Unable to query video extension information\n");
 
435
        return (False);
 
436
    }
 
437
    else if (MajorVersion < MINMAJOR ||
 
438
        (MajorVersion == MINMAJOR && MinorVersion < MINMINOR)) {
 
439
        fprintf(stderr,
 
440
                "Xserver is running an old XFree86-VidModeExtension version"
 
441
                " (%d.%d)\n", MajorVersion, MinorVersion);
 
442
        fprintf(stderr, "Minimum required version is %d.%d\n",
 
443
                MINMAJOR, MINMINOR);
 
444
        return (False);
 
445
    }
 
446
    else
 
447
        InitializeVidmodes();
 
448
 
 
449
    vtune = XtCreateWidget("vidtune", formWidgetClass,
 
450
                           work, NULL, 0);
 
451
 
 
452
    vesab = XtVaCreateManagedWidget("vesaB", menuButtonWidgetClass, vtune,
 
453
                                    XtNmenuName, "vesaP", NULL, 0);
 
454
    vesap = XtCreatePopupShell("vesaP", simpleMenuWidgetClass, vtune, NULL, 0);
 
455
    for (i = 0; i < sizeof(vesamodes) / sizeof(vesamodes[0]); i++) {
 
456
        rep = XtCreateManagedWidget(vesamodes[i].ident, smeBSBObjectClass,
 
457
                                    vesap, NULL, 0);
 
458
        XtAddCallback(rep, XtNcallback, AddVesaModeCallback,
 
459
                      (XtPointer)&vesamodes[i]);
 
460
    }
 
461
 
 
462
    rep = XtCreateManagedWidget("prev", commandWidgetClass, vtune, NULL, 0);
 
463
    XtAddCallback(rep, XtNcallback, SwitchCallback, (XtPointer)-1);
 
464
    mode = XtCreateManagedWidget("mode", menuButtonWidgetClass, vtune, NULL, 0);
 
465
    rep = XtCreateManagedWidget("next", commandWidgetClass, vtune, NULL, 0);
 
466
    XtAddCallback(rep, XtNcallback, SwitchCallback, (XtPointer)1);
 
467
 
 
468
    screenp = XtCreatePopupShell("screenP", simpleMenuWidgetClass, vtune,
 
469
                                 NULL, 0);
 
470
 
 
471
    XmuSnprintf(dispstr, sizeof(dispstr), "%s",
 
472
                DisplayString(XtDisplay(toplevel)));
 
473
    ptr = strrchr(dispstr, '.');
 
474
    tmp = strrchr(dispstr, ':');
 
475
    if (tmp != NULL && ptr != NULL && ptr > tmp)
 
476
        *ptr = '\0';
 
477
 
 
478
    for (i = 0; i < ScreenCount(XtDisplay(toplevel)); i++) {
 
479
        char name[128];
 
480
 
 
481
        XmuSnprintf(name, sizeof(name), "%s.%d", dispstr, i);
 
482
        rep = XtCreateManagedWidget(name, smeBSBObjectClass, screenp,
 
483
                                    NULL, 0);
 
484
        XtAddCallback(rep, XtNcallback, ChangeScreenCallback,
 
485
            (XtPointer)(long)i);
 
486
        if (i == 0) {
 
487
            screenb = XtVaCreateManagedWidget("screenB", menuButtonWidgetClass,
 
488
                                              vtune,
 
489
                                              XtNmenuName, "screenP",
 
490
                                              XtNlabel, name,
 
491
                                              NULL, 0);
 
492
        }
 
493
    }
 
494
    XtRealizeWidget(screenp);
 
495
 
 
496
    rep = XtCreateManagedWidget("up", repeaterWidgetClass,
 
497
                                vtune, NULL, 0);
 
498
    XtAddCallback(rep, XtNstartCallback, StartAdjustMonitorCallback, NULL);
 
499
    XtAddCallback(rep, XtNcallback,
 
500
                  AdjustMonitorCallback, (XtPointer)UP);
 
501
    XtAddCallback(rep, XtNstopCallback, EndAdjustMonitorCallback, NULL);
 
502
    rep = XtCreateManagedWidget("left", repeaterWidgetClass,
 
503
                                vtune, NULL, 0);
 
504
    XtAddCallback(rep, XtNstartCallback, StartAdjustMonitorCallback, NULL);
 
505
    XtAddCallback(rep, XtNcallback,
 
506
                  AdjustMonitorCallback, (XtPointer)LEFT);
 
507
    XtAddCallback(rep, XtNstopCallback, EndAdjustMonitorCallback, NULL);
 
508
    XtCreateManagedWidget("monitor", simpleWidgetClass, vtune, NULL, 0);
 
509
    rep = XtCreateManagedWidget("right", repeaterWidgetClass,
 
510
                                vtune, NULL, 0);
 
511
    XtAddCallback(rep, XtNstartCallback, StartAdjustMonitorCallback, NULL);
 
512
    XtAddCallback(rep, XtNcallback,
 
513
                  AdjustMonitorCallback, (XtPointer)RIGHT);
 
514
    XtAddCallback(rep, XtNstopCallback, EndAdjustMonitorCallback, NULL);
 
515
    rep = XtCreateManagedWidget("down", repeaterWidgetClass,
 
516
                                vtune, NULL, 0);
 
517
    XtAddCallback(rep, XtNstartCallback, StartAdjustMonitorCallback, NULL);
 
518
    XtAddCallback(rep, XtNcallback,
 
519
                  AdjustMonitorCallback, (XtPointer)DOWN);
 
520
    XtAddCallback(rep, XtNstopCallback, EndAdjustMonitorCallback, NULL);
 
521
    rep = XtCreateManagedWidget("wider", repeaterWidgetClass,
 
522
                                vtune, NULL, 0);
 
523
    XtAddCallback(rep, XtNstartCallback, StartAdjustMonitorCallback, NULL);
 
524
    XtAddCallback(rep, XtNcallback,
 
525
                  AdjustMonitorCallback, (XtPointer)WIDER);
 
526
    XtAddCallback(rep, XtNstopCallback, EndAdjustMonitorCallback, NULL);
 
527
    rep = XtCreateManagedWidget("narrower", repeaterWidgetClass,
 
528
                                vtune, NULL, 0);
 
529
    XtAddCallback(rep, XtNstartCallback, StartAdjustMonitorCallback, NULL);
 
530
    XtAddCallback(rep, XtNcallback,
 
531
                  AdjustMonitorCallback, (XtPointer)NARROWER);
 
532
    XtAddCallback(rep, XtNstopCallback, EndAdjustMonitorCallback, NULL);
 
533
    rep = XtCreateManagedWidget("shorter", repeaterWidgetClass,
 
534
                                vtune, NULL, 0);
 
535
    XtAddCallback(rep, XtNstartCallback, StartAdjustMonitorCallback, NULL);
 
536
    XtAddCallback(rep, XtNcallback,
 
537
                  AdjustMonitorCallback, (XtPointer)SHORTER);
 
538
    XtAddCallback(rep, XtNstopCallback, EndAdjustMonitorCallback, NULL);
 
539
    rep = XtCreateManagedWidget("taller", repeaterWidgetClass,
 
540
                                vtune, NULL, 0);
 
541
    XtAddCallback(rep, XtNstartCallback, StartAdjustMonitorCallback, NULL);
 
542
    XtAddCallback(rep, XtNcallback,
 
543
                  AdjustMonitorCallback, (XtPointer)TALLER);
 
544
    XtAddCallback(rep, XtNstopCallback, EndAdjustMonitorCallback, NULL);
 
545
 
 
546
    automatic = XtCreateManagedWidget("auto", toggleWidgetClass, vtune, NULL, 0);
 
547
    XtAddCallback(automatic, XtNcallback, AutoCallback, NULL);
 
548
    apply = XtCreateManagedWidget("apply", commandWidgetClass, vtune, NULL, 0);
 
549
    XtAddCallback(apply, XtNcallback, ApplyCallback, NULL);
 
550
    restore = XtCreateManagedWidget("restore", commandWidgetClass, vtune, NULL, 0);
 
551
    XtAddCallback(restore, XtNcallback, RestoreCallback, NULL);
 
552
    rep = XtCreateManagedWidget("update", commandWidgetClass, vtune, NULL, 0);
 
553
    XtAddCallback(rep, XtNcallback, UpdateCallback, NULL);
 
554
    rep = XtCreateManagedWidget("test", commandWidgetClass, vtune, NULL, 0);
 
555
    XtAddCallback(rep, XtNcallback, TestCallback, NULL);
 
556
 
 
557
    form = XtCreateManagedWidget("form", formWidgetClass, vtune, NULL, 0);
 
558
    for (i = 2; i < VSYNC + 1; i++) {
 
559
        labels[i] = XtCreateManagedWidget(names[i], labelWidgetClass,
 
560
                                          form, NULL, 0);
 
561
        values[i] = XtCreateManagedWidget(vnames[i], labelWidgetClass,
 
562
                                          form, NULL, 0);
 
563
    }
 
564
 
 
565
    add = XtCreateManagedWidget("add", commandWidgetClass, vtune, NULL, 0);
 
566
    XtAddCallback(add, XtNcallback, AddModeCallback, NULL);
 
567
    XtCreateManagedWidget("addto", labelWidgetClass, vtune, NULL, 0);
 
568
    monitorb = XtCreateManagedWidget("ident", menuButtonWidgetClass, vtune,
 
569
                                     NULL, 0);
 
570
    XtCreateManagedWidget("as", labelWidgetClass, vtune, NULL, 0);
 
571
    text = XtVaCreateManagedWidget("text", asciiTextWidgetClass, vtune,
 
572
                                   XtNeditType, XawtextEdit, NULL, 0);
 
573
 
 
574
    XtRealizeWidget(vtune);
 
575
 
 
576
    return (True);
 
577
}
 
578
 
 
579
void
 
580
InitializeVidmodes(void)
 
581
{
 
582
    int i;
 
583
    Display *display = XtDisplay(toplevel);
 
584
 
 
585
    computer.num_vidmodes = ScreenCount(display);
 
586
    computer.vidmodes = (xf86cfgVidmode**)
 
587
        XtMalloc(sizeof(xf86cfgVidmode*) * computer.num_vidmodes);
 
588
    for (i = 0; i < computer.num_vidmodes; i++) {
 
589
 
 
590
        computer.vidmodes[i] = (xf86cfgVidmode*)
 
591
            XtCalloc(1, sizeof(xf86cfgVidmode));
 
592
        computer.vidmodes[i]->screen = i;
 
593
    }
 
594
}
 
595
 
 
596
void
 
597
VideoModeConfigureStart(void)
 
598
{
 
599
    vidtune = computer.vidmodes[screenno];
 
600
 
 
601
    XtSetSensitive(vtune, vidtune != NULL);
 
602
    if (!XtIsManaged(vtune))
 
603
        XtManageChild(vtune);
 
604
    else
 
605
        XtMapWidget(vtune);
 
606
    if (vidtune != NULL) {
 
607
        Arg args[1];
 
608
        Boolean state;
 
609
        XF86ConfMonitorPtr mon;
 
610
        static char menuName[16];
 
611
        static int menuN;
 
612
 
 
613
        XtErrorFunc = XSetErrorHandler(VidmodeError);
 
614
        XF86VidModeLockModeSwitch(XtDisplay(toplevel), vidtune->screen, True);
 
615
        GetModeLine(True);
 
616
        GetModes();
 
617
 
 
618
        SetLabels();
 
619
        XtSetArg(args[0], XtNstate, &state);
 
620
        XtGetValues(automatic, args, 1);
 
621
        XtSetSensitive(apply, !state);
 
622
        autoflag = state;
 
623
 
 
624
        if (monitor)
 
625
            XtDestroyWidget(monitor);
 
626
        XmuSnprintf(menuName, sizeof(menuName), "menuP%d", menuN);
 
627
        menuN = !menuN;
 
628
        monitor = XtCreatePopupShell(menuName, simpleMenuWidgetClass,
 
629
                                     vtune, NULL, 0);
 
630
        XtVaSetValues(monitorb, XtNmenuName, menuName, NULL, 0);
 
631
 
 
632
        mon = XF86Config->conf_monitor_lst;
 
633
        while (mon != NULL) {
 
634
            Widget sme = XtCreateManagedWidget(mon->mon_identifier,
 
635
                                               smeBSBObjectClass,
 
636
                                               monitor, NULL, 0);
 
637
            XtAddCallback(sme, XtNcallback,
 
638
                          SelectMonitorCallback, (XtPointer)mon);
 
639
 
 
640
            /* guess the monitor at a given screen and/or
 
641
             * updates configuration if a monitor was removed from the
 
642
             * configuration.
 
643
             */
 
644
            if (XF86Config->conf_layout_lst) {
 
645
                XF86ConfAdjacencyPtr adj = XF86Config->conf_layout_lst->
 
646
                    lay_adjacency_lst;
 
647
 
 
648
                while (adj != NULL) {
 
649
                    if (adj->adj_screen != NULL) {
 
650
                        if (adj->adj_screen->scrn_monitor == mon &&
 
651
                            adj->adj_scrnum >= 0 &&
 
652
                            adj->adj_scrnum < ScreenCount(XtDisplay(toplevel))) {
 
653
                            if (computer.vidmodes[adj->adj_scrnum]->monitor ==
 
654
                                NULL || computer.vidmodes[adj->adj_scrnum]->
 
655
                                monitor == adj->adj_screen->scrn_monitor) {
 
656
                                computer.vidmodes[adj->adj_scrnum]->monitor =
 
657
                                    adj->adj_screen->scrn_monitor;
 
658
                                break;
 
659
                            }
 
660
                            else
 
661
                                computer.vidmodes[adj->adj_scrnum]->monitor =
 
662
                                    NULL;
 
663
                        }
 
664
                    }
 
665
                    adj = (XF86ConfAdjacencyPtr)(adj->list.next);
 
666
                }
 
667
            }
 
668
            mon = (XF86ConfMonitorPtr)(mon->list.next);
 
669
        }
 
670
        SetLabelAndModeline();
 
671
    }
 
672
}
 
673
 
 
674
void
 
675
VideoModeConfigureEnd(void)
 
676
{
 
677
    XtUnmapWidget(vtune);
 
678
    if (vidtune != NULL) {
 
679
        XF86VidModeLockModeSwitch(XtDisplay(toplevel), vidtune->screen, False);
 
680
        XSetErrorHandler(XtErrorFunc);
 
681
    }
 
682
    vidtune = NULL;
 
683
}
 
684
 
 
685
static void
 
686
SetLabelAndModeline(void)
 
687
{
 
688
    if (vidtune->monitor != NULL) {
 
689
        char string[32];
 
690
 
 
691
        XtVaSetValues(monitorb, XtNlabel,
 
692
                      vidtune->monitor->mon_identifier, NULL);
 
693
        XtSetSensitive(add, True);
 
694
 
 
695
        if (modeline.htotal && modeline.vtotal)
 
696
            XmuSnprintf(string, sizeof(string), "%dx%d@%d",
 
697
                        modeline.hdisplay, modeline.vdisplay,
 
698
                        (int)((double)dot_clock / (double)modeline.htotal * 1000.0 /
 
699
                        (double)modeline.vtotal));
 
700
        else
 
701
            XmuSnprintf(string, sizeof(string), "%dx%d",
 
702
                        modeline.hdisplay, modeline.vdisplay);
 
703
        XtVaSetValues(text, XtNstring, string, NULL);
 
704
    }
 
705
    else {
 
706
        XtVaSetValues(monitorb, XtNlabel, "", NULL);
 
707
        XtSetSensitive(add, False);
 
708
        XtVaSetValues(text, XtNstring, "", NULL);
 
709
    }
 
710
}
 
711
 
 
712
/*ARGSUSED*/
 
713
void
 
714
VidmodeRestoreAction(Widget w, XEvent *event,
 
715
                     String *params, Cardinal *num_params)
 
716
{
 
717
    if (vidtune != NULL) {
 
718
        if (timeout != 0)
 
719
            StopTestCallback(w, NULL, NULL);
 
720
        else
 
721
            RestoreCallback(w, NULL, NULL);
 
722
    }
 
723
}
 
724
 
 
725
static void
 
726
UpdateSyncRates(Bool update)
 
727
{
 
728
    if (modeline.htotal && modeline.vtotal) {
 
729
        hsync_rate = (dot_clock * 1000) / modeline.htotal;
 
730
        vsync_rate = (hsync_rate * 1000) / modeline.vtotal;
 
731
        if (modeline.flags & V_INTERLACE)
 
732
            vsync_rate *= 2;
 
733
        else if (modeline.flags & V_DBLSCAN)
 
734
            vsync_rate /= 2;
 
735
        if (update) {
 
736
            SetLabel(HSYNC, hsync_rate);
 
737
            SetLabel(VSYNC, vsync_rate);
 
738
        }
 
739
    }
 
740
}
 
741
 
 
742
static void
 
743
SetLabel(int ident, int value)
 
744
{
 
745
    Arg args[1];
 
746
    char label[256];
 
747
 
 
748
    if (ident == FLAGS) {
 
749
        int len = 0;
 
750
 
 
751
        *label = '\0';
 
752
        if (value & V_PHSYNC)
 
753
            len += XmuSnprintf(label, sizeof(label), "%s", "+hsync");
 
754
        if (modeline.flags & V_NHSYNC)
 
755
            len += XmuSnprintf(label + len, sizeof(label), "%s%s",
 
756
                               len ? " " : "", "-hsync");
 
757
        if (value & V_PVSYNC)
 
758
            len += XmuSnprintf(label + len, sizeof(label), "%s%s",
 
759
                               len ? " " : "", "+vsync");
 
760
        if (value & V_NVSYNC)
 
761
            len += XmuSnprintf(label + len, sizeof(label), "%s%s",
 
762
                               len ? " " : "", "-vsync");
 
763
        if (value & V_INTERLACE)
 
764
            len += XmuSnprintf(label + len, sizeof(label), "%s%s",
 
765
                               len ? " " : "", "interlace");
 
766
        if (value & V_CSYNC)
 
767
            len += XmuSnprintf(label + len, sizeof(label), "%s%s",
 
768
                               len ? " " : "", "composite");
 
769
        if (value & V_PCSYNC)
 
770
            len += XmuSnprintf(label + len, sizeof(label), "%s%s",
 
771
                               len ? " " : "", "+csync");
 
772
        if (value & V_NCSYNC)
 
773
            len += XmuSnprintf(label + len, sizeof(label), "%s%s",
 
774
                               len ? " " : "", "-csync");
 
775
        if (value & V_DBLSCAN)
 
776
            len += XmuSnprintf(label + len, sizeof(label), "%s%s",
 
777
                               len ? " " : "", "doublescan");
 
778
 
 
779
    }
 
780
    else if (ident == CLOCK || ident == HSYNC || ident == VSYNC)
 
781
        XmuSnprintf(label, sizeof(label), "%6.2f", (float)value / 1000.0);
 
782
    else
 
783
        XmuSnprintf(label, sizeof(label), "%d", value);
 
784
 
 
785
    XtSetArg(args[0], XtNlabel, label);
 
786
    XtSetValues(values[ident], args, 1);
 
787
}
 
788
 
 
789
/*ARGSUSED*/
 
790
static void
 
791
StartAdjustMonitorCallback(Widget w, XtPointer client_data, XtPointer call_data)
 
792
{
 
793
    repeater = w;
 
794
}
 
795
 
 
796
static void
 
797
AdjustMonitorCallback(Widget w, XtPointer client_data, XtPointer call_data)
 
798
{
 
799
    if (repeater != w)
 
800
        return;
 
801
    switch ((long)client_data) {
 
802
        case LEFT:
 
803
            if (modeline.hsyncend + 4 < modeline.htotal) {
 
804
                modeline.hsyncstart += 4;
 
805
                modeline.hsyncend += 4;
 
806
                SetLabel(HSYNCSTART, modeline.hsyncstart);
 
807
                SetLabel(HSYNCEND, modeline.hsyncend);
 
808
            }
 
809
            else
 
810
                XBell(XtDisplay(w), 80);
 
811
            break;
 
812
        case RIGHT:
 
813
            if (modeline.hsyncstart - 4 > modeline.hdisplay) {
 
814
                modeline.hsyncstart -= 4;
 
815
                modeline.hsyncend -= 4;
 
816
                SetLabel(HSYNCSTART, modeline.hsyncstart);
 
817
                SetLabel(HSYNCEND, modeline.hsyncend);
 
818
            }
 
819
            else
 
820
                XBell(XtDisplay(w), 80);
 
821
            break;
 
822
        case NARROWER:
 
823
            modeline.htotal += 4;
 
824
            SetLabel(HTOTAL, modeline.htotal);
 
825
            UpdateSyncRates(True);
 
826
            break;
 
827
        case WIDER:
 
828
            if (modeline.htotal - 4 > modeline.hsyncend) {
 
829
                modeline.htotal -= 4;
 
830
                SetLabel(HTOTAL, modeline.htotal);
 
831
                UpdateSyncRates(True);
 
832
            }
 
833
            else
 
834
                XBell(XtDisplay(w), 80);
 
835
            break;
 
836
        case UP:
 
837
            if (modeline.vsyncend + 4 < modeline.vtotal) {
 
838
                modeline.vsyncstart += 4;
 
839
                modeline.vsyncend += 4;
 
840
                SetLabel(VSYNCSTART, modeline.vsyncstart);
 
841
                SetLabel(VSYNCEND, modeline.vsyncend);
 
842
            }
 
843
            else
 
844
                XBell(XtDisplay(w), 80);
 
845
            break;
 
846
        case DOWN:
 
847
            if (modeline.vsyncstart - 4 > modeline.vdisplay) {
 
848
                modeline.vsyncstart -= 4;
 
849
                modeline.vsyncend -= 4;
 
850
                SetLabel(VSYNCSTART, modeline.vsyncstart);
 
851
                SetLabel(VSYNCEND, modeline.vsyncend);
 
852
            }
 
853
            else
 
854
                XBell(XtDisplay(w), 80);
 
855
            break;
 
856
        case SHORTER:
 
857
            modeline.vtotal += 4;
 
858
            SetLabel(VTOTAL, modeline.vtotal);
 
859
            UpdateSyncRates(True);
 
860
            break;
 
861
        case TALLER:
 
862
            if (modeline.vtotal - 4 >  modeline.vsyncend) {
 
863
                modeline.vtotal -= 4;
 
864
                SetLabel(VTOTAL, modeline.vtotal);
 
865
                UpdateSyncRates(True);
 
866
            }
 
867
            else
 
868
                XBell(XtDisplay(w), 80);
 
869
            break;
 
870
    }
 
871
 
 
872
    if (autoflag)
 
873
        ApplyCallback(w, call_data, client_data);
 
874
}
 
875
 
 
876
/*ARGSUSED*/
 
877
static void
 
878
EndAdjustMonitorCallback(Widget w, XtPointer client_data, XtPointer call_data)
 
879
{
 
880
    repeater = NULL;
 
881
}
 
882
 
 
883
static Bool
 
884
GetModeLine(Bool save)
 
885
{
 
886
    if (XF86VidModeGetModeLine(XtDisplay(toplevel), vidtune->screen,
 
887
                               &dot_clock, &modeline)) {
 
888
        if (save)
 
889
            memcpy(&orig_modeline, &modeline, sizeof(XF86VidModeModeLine));
 
890
        UpdateSyncRates(False);
 
891
        if (modeline.privsize != 0 && modeline.private != NULL) {
 
892
            S3Specials = True;
 
893
            invert_vclk = modeline.private[1];
 
894
            blank1 = modeline.private[2] & 7;
 
895
            blank2 = (modeline.private[2] >> 4) & 7;
 
896
            early_sc = modeline.private[3];
 
897
        }
 
898
        else
 
899
            S3Specials = False;
 
900
        return (True);
 
901
    }
 
902
 
 
903
    return (False);
 
904
}
 
905
 
 
906
static void
 
907
CleanUp(Display *display)
 
908
{
 
909
    /* Make sure mode switching is not locked out at exit */
 
910
    XF86VidModeLockModeSwitch(display, vidtune->screen, False);
 
911
    XFlush(display);
 
912
}
 
913
 
 
914
static int
 
915
VidmodeError(Display *display, XErrorEvent *error)
 
916
{
 
917
    if ((error->error_code >= ErrorBase &&
 
918
         error->error_code < ErrorBase + XF86VidModeNumberErrors) ||
 
919
         error->error_code == BadValue) {
 
920
         hitError = 1;
 
921
    }
 
922
    else {
 
923
        CleanUp(display);
 
924
        if (XtErrorFunc) 
 
925
            (*XtErrorFunc)(display, error);
 
926
    }
 
927
    return (0);
 
928
}
 
929
 
 
930
/*ARGSUSED*/
 
931
static void
 
932
ApplyCallback(Widget w, XtPointer call_data, XtPointer client_data)
 
933
{
 
934
    hitError = 0;
 
935
    XF86VidModeModModeLine(XtDisplay(w), vidtune->screen, &modeline);
 
936
    XSync(XtDisplay(w), False);
 
937
    if (hitError) {
 
938
        if (repeater != NULL) {
 
939
            XtCallActionProc(repeater, "unset", NULL, NULL, 0);
 
940
            XtCallActionProc(repeater, "stop", NULL, NULL, 0);
 
941
            repeater = NULL;
 
942
        }
 
943
        XBell(XtDisplay(w), 80);
 
944
        if (timeout)
 
945
            StopTestCallback(w, NULL, NULL);
 
946
        GetModeLine(False);
 
947
        SetLabels();
 
948
    }
 
949
}
 
950
 
 
951
/*ARGSUSED*/
 
952
static void
 
953
AutoCallback(Widget w, XtPointer call_data, XtPointer client_data)
 
954
{
 
955
    autoflag = (Bool)(long)client_data;
 
956
    XtSetSensitive(apply, !autoflag);
 
957
}
 
958
 
 
959
static void
 
960
RestoreCallback(Widget w, XtPointer call_data, XtPointer client_data)
 
961
{
 
962
    memcpy(&modeline, &orig_modeline, sizeof(XF86VidModeModeLine));
 
963
    if (autoflag)
 
964
        ApplyCallback(w, call_data, client_data);
 
965
    SetLabels();
 
966
}
 
967
 
 
968
static void
 
969
SelectCallback(Widget w, XtPointer call_data, XtPointer client_data)
 
970
{
 
971
    XF86VidModeModeInfo *info = (XF86VidModeModeInfo*)call_data;
 
972
    Arg args[1];
 
973
    Bool result;
 
974
 
 
975
    XF86VidModeLockModeSwitch(XtDisplay(toplevel), vidtune->screen, False);
 
976
    result = XF86VidModeSwitchToMode(XtDisplay(toplevel), vidtune->screen, info);
 
977
    XF86VidModeLockModeSwitch(XtDisplay(toplevel), vidtune->screen, True);
 
978
    if (!result)
 
979
        return;
 
980
 
 
981
    XtSetArg(args[0], XtNlabel, XtName(w));
 
982
    XtSetValues(mode, args, 1);
 
983
    UpdateCallback(w, call_data, client_data);
 
984
}
 
985
 
 
986
static void
 
987
SwitchCallback(Widget w, XtPointer call_data, XtPointer client_data)
 
988
{
 
989
    int direction = (long)call_data;
 
990
    Arg args[1];
 
991
    Bool result;
 
992
    char label[32];
 
993
 
 
994
    XF86VidModeLockModeSwitch(XtDisplay(toplevel), vidtune->screen, False);
 
995
    result = XF86VidModeSwitchMode(XtDisplay(toplevel), vidtune->screen,
 
996
                                   direction);
 
997
    XF86VidModeLockModeSwitch(XtDisplay(toplevel), vidtune->screen, True);
 
998
    if (!result)
 
999
        return;
 
1000
 
 
1001
    UpdateCallback(w, call_data, client_data);
 
1002
 
 
1003
    if (modeline.htotal && modeline.vtotal)
 
1004
        XmuSnprintf(label, sizeof(label), "%dx%d @ %d Hz",
 
1005
                    modeline.hdisplay, modeline.vdisplay,
 
1006
                    (int)((double)dot_clock / (double)modeline.htotal * 1000.0 /
 
1007
                    (double)modeline.vtotal));
 
1008
    else
 
1009
        XmuSnprintf(label, sizeof(label), "%dx%d",
 
1010
                    modeline.hdisplay, modeline.vdisplay);
 
1011
    XtSetArg(args[0], XtNlabel, label);
 
1012
    XtSetValues(mode, args, 1);
 
1013
}
 
1014
 
 
1015
/*ARGSUSED*/
 
1016
static void
 
1017
UpdateCallback(Widget w, XtPointer call_data, XtPointer client_data)
 
1018
{
 
1019
    GetModeLine(True);
 
1020
    SetLabels();
 
1021
    SetLabelAndModeline();
 
1022
}
 
1023
 
 
1024
static void
 
1025
SetLabels(void)
 
1026
{
 
1027
    SetLabel(HSYNCSTART, modeline.hsyncstart);
 
1028
    SetLabel(VSYNCSTART, modeline.vsyncstart);
 
1029
    SetLabel(HSYNCEND, modeline.hsyncend);
 
1030
    SetLabel(VSYNCEND, modeline.vsyncend);
 
1031
    SetLabel(HTOTAL, modeline.htotal);
 
1032
    SetLabel(VTOTAL, modeline.vtotal);
 
1033
    SetLabel(FLAGS, modeline.flags);
 
1034
    SetLabel(CLOCK, dot_clock);
 
1035
    UpdateSyncRates(True);
 
1036
}
 
1037
 
 
1038
/*ARGSUSED*/
 
1039
static void
 
1040
ChangeScreenCallback(Widget w, XtPointer call_data, XtPointer client_data)
 
1041
{
 
1042
    Arg args[1];
 
1043
 
 
1044
    screenno = (long)call_data;
 
1045
    if (screenno > computer.num_vidmodes || screenno < 0 ||
 
1046
        vidtune == computer.vidmodes[screenno])
 
1047
        return;
 
1048
 
 
1049
    XF86VidModeLockModeSwitch(XtDisplay(toplevel), vidtune->screen, False);
 
1050
    vidtune = computer.vidmodes[screenno];
 
1051
    XF86VidModeLockModeSwitch(XtDisplay(toplevel), vidtune->screen, True);
 
1052
    UpdateCallback(w, call_data, client_data);
 
1053
    GetModes();
 
1054
 
 
1055
    XtSetArg(args[0], XtNlabel, XtName(w));
 
1056
    XtSetValues(screenb, args, 1);
 
1057
 
 
1058
    SetLabelAndModeline();
 
1059
}
 
1060
 
 
1061
/*ARGSUSED*/
 
1062
static void
 
1063
SelectMonitorCallback(Widget w, XtPointer call_data, XtPointer client_data)
 
1064
{
 
1065
    vidtune->monitor = (XF86ConfMonitorPtr)(call_data);
 
1066
    SetLabelAndModeline();
 
1067
}
 
1068
 
 
1069
/*ARGSUSED*/
 
1070
static void
 
1071
AddVesaModeCallback(Widget w, XtPointer call_data, XtPointer client_data)
 
1072
{
 
1073
    xf86cfgVesaModeInfo *vesa = (xf86cfgVesaModeInfo*)call_data;
 
1074
    XF86VidModeModeInfo mode;
 
1075
    int num_infos = vidtune->num_infos;
 
1076
 
 
1077
    memcpy(&mode, &vesa->info, sizeof(XF86VidModeModeInfo));
 
1078
    if (XF86VidModeAddModeLine(XtDisplay(toplevel), vidtune->screen,
 
1079
                               &vesa->info, &mode)) {
 
1080
        XSync(XtDisplay(toplevel), False);
 
1081
        GetModes();
 
1082
    }
 
1083
    else {
 
1084
        XBell(XtDisplayOfObject(w), 80);
 
1085
        return;
 
1086
    }
 
1087
 
 
1088
    if (vidtune && num_infos == vidtune->num_infos) {
 
1089
        /* XF86VidModeAddModeLine returned True, but no modeline was added */
 
1090
        XBell(XtDisplayOfObject(w), 80);
 
1091
        if (vidtune->monitor && AddMode()) {
 
1092
            XF86ConfModeLinePtr mode;
 
1093
            char label[256], *ptr, *str;
 
1094
 
 
1095
            XmuSnprintf(label, sizeof(label), "%s", vesa->ident);
 
1096
 
 
1097
            /* format mode name to not have spaces */
 
1098
            ptr = strchr(label, ')');
 
1099
            if (ptr)
 
1100
                *++ptr = '\0';
 
1101
            ptr = str = label;
 
1102
            while (*ptr) {
 
1103
                if (*ptr != ' ')
 
1104
                    *str++ = *ptr;
 
1105
                ++ptr;
 
1106
            }
 
1107
            *str = '\0';
 
1108
 
 
1109
            if (xf86findModeLine(label, vidtune->monitor->mon_modeline_lst)
 
1110
                != NULL && !ForceAddMode())
 
1111
                return;
 
1112
 
 
1113
            mode = (XF86ConfModeLinePtr)XtCalloc(1, sizeof(XF86ConfModeLineRec));
 
1114
            mode->ml_identifier = XtNewString(label);
 
1115
            mode->ml_clock = vesa->info.dotclock;
 
1116
            mode->ml_hdisplay = vesa->info.hdisplay;
 
1117
            mode->ml_hsyncstart = vesa->info.hsyncstart;
 
1118
            mode->ml_hsyncend = vesa->info.hsyncend;
 
1119
            mode->ml_htotal = vesa->info.htotal;
 
1120
            mode->ml_vdisplay = vesa->info.vdisplay;
 
1121
            mode->ml_vsyncstart = vesa->info.vsyncstart;
 
1122
            mode->ml_vsyncend = vesa->info.vsyncend;
 
1123
            mode->ml_vtotal = vesa->info.vtotal;
 
1124
/*          mode->ml_vscan = ???;*/
 
1125
            mode->ml_flags = vesa->info.flags;
 
1126
            mode->ml_hskew = vesa->info.hskew;
 
1127
            vidtune->monitor->mon_modeline_lst =
 
1128
                xf86addModeLine(vidtune->monitor->mon_modeline_lst, mode);
 
1129
        }
 
1130
    }
 
1131
}
 
1132
 
 
1133
static void
 
1134
GetModes(void)
 
1135
{
 
1136
    int i;
 
1137
    char label[32];
 
1138
    Arg args[1];
 
1139
    static char menuName[16];
 
1140
    static int menuN;
 
1141
 
 
1142
    XFree(vidtune->infos);
 
1143
    XF86VidModeGetAllModeLines(XtDisplay(toplevel), vidtune->screen,
 
1144
                               &vidtune->num_infos, &vidtune->infos);
 
1145
 
 
1146
    XmuSnprintf(menuName, sizeof(menuName), "menu%d", menuN);
 
1147
    menuN = !menuN;
 
1148
    if (menu)
 
1149
        XtDestroyWidget(menu);
 
1150
    menu = XtCreatePopupShell(menuName, simpleMenuWidgetClass, vtune, NULL, 0);
 
1151
    XtVaSetValues(mode, XtNmenuName, menuName, NULL, 0);
 
1152
    for (i = 0; i < vidtune->num_infos; i++) {
 
1153
        Widget sme;
 
1154
 
 
1155
        if ((double)vidtune->infos[i]->htotal &&
 
1156
            (double)vidtune->infos[i]->vtotal)
 
1157
            XmuSnprintf(label, sizeof(label), "%dx%d @ %d Hz",
 
1158
                        vidtune->infos[i]->hdisplay,
 
1159
                        vidtune->infos[i]->vdisplay,
 
1160
                        (int)((double)vidtune->infos[i]->dotclock /
 
1161
                        (double)vidtune->infos[i]->htotal * 1000.0 /
 
1162
                        (double)vidtune->infos[i]->vtotal));
 
1163
        else
 
1164
            XmuSnprintf(label, sizeof(label), "%dx%d",
 
1165
                        vidtune->infos[i]->hdisplay,
 
1166
                        vidtune->infos[i]->vdisplay);
 
1167
        sme = XtCreateManagedWidget(label, smeBSBObjectClass, menu, NULL, 0);
 
1168
        XtAddCallback(sme, XtNcallback, SelectCallback,
 
1169
                      (XtPointer)vidtune->infos[i]);
 
1170
    }
 
1171
 
 
1172
    if (modeline.htotal && modeline.vtotal)
 
1173
        XmuSnprintf(label, sizeof(label), "%dx%d @ %d Hz",
 
1174
                    modeline.hdisplay, modeline.vdisplay,
 
1175
                    (int)((double)dot_clock / (double)modeline.htotal * 1000.0 /
 
1176
                    (double)modeline.vtotal));
 
1177
    else
 
1178
        XmuSnprintf(label, sizeof(label), "%dx%d",
 
1179
                    modeline.hdisplay, modeline.vdisplay);
 
1180
    XtSetArg(args[0], XtNlabel, label);
 
1181
    XtSetValues(mode, args, 1);
 
1182
}
 
1183
 
 
1184
static int do_force, asking_force;
 
1185
 
 
1186
static void
 
1187
PopdownForce(Widget w, XtPointer user_data, XtPointer call_data)
 
1188
{
 
1189
    asking_force = 0;
 
1190
    XtPopdown(forceshell);
 
1191
    do_force = (long)user_data;
 
1192
}
 
1193
 
 
1194
static int
 
1195
ForceAddMode(void)
 
1196
{
 
1197
    if (forceshell == NULL) {
 
1198
        Widget dialog;
 
1199
 
 
1200
        forceshell = XtCreatePopupShell("force", transientShellWidgetClass,
 
1201
                                        toplevel, NULL, 0);
 
1202
        dialog = XtVaCreateManagedWidget("dialog", dialogWidgetClass,
 
1203
                                         forceshell, XtNvalue, NULL, NULL, 0);
 
1204
        XawDialogAddButton(dialog, "yes", PopdownForce, (XtPointer)True);
 
1205
        XawDialogAddButton(dialog, "no", PopdownForce, (XtPointer)False);
 
1206
        XtRealizeWidget(forceshell);
 
1207
        XSetWMProtocols(DPY, XtWindow(forceshell), &wm_delete_window, 1);
 
1208
    }
 
1209
 
 
1210
    asking_force = 1;
 
1211
 
 
1212
    XtPopup(forceshell, XtGrabExclusive);
 
1213
    while (asking_force)
 
1214
        XtAppProcessEvent(XtWidgetToApplicationContext(forceshell), XtIMAll);
 
1215
 
 
1216
    return (do_force);
 
1217
}
 
1218
 
 
1219
static int do_add, asking_add;
 
1220
 
 
1221
static void
 
1222
PopdownAdd(Widget w, XtPointer user_data, XtPointer call_data)
 
1223
{
 
1224
    asking_add = 0;
 
1225
    XtPopdown(addshell);
 
1226
    do_add = (long)user_data;
 
1227
}
 
1228
 
 
1229
void
 
1230
CancelAddModeAction(Widget w, XEvent *event,
 
1231
                       String *params, Cardinal *num_params)
 
1232
{
 
1233
    if (asking_force)
 
1234
        PopdownForce(w, (XtPointer)False, NULL);
 
1235
    else if (asking_add)
 
1236
        PopdownAdd(w, (XtPointer)False, NULL);
 
1237
}
 
1238
 
 
1239
static int
 
1240
AddMode(void)
 
1241
{
 
1242
    if (addshell == NULL) {
 
1243
        Widget dialog;
 
1244
 
 
1245
        addshell = XtCreatePopupShell("addMode", transientShellWidgetClass,
 
1246
                                      toplevel, NULL, 0);
 
1247
        dialog = XtVaCreateManagedWidget("dialog", dialogWidgetClass,
 
1248
                                         addshell, XtNvalue, NULL, NULL, 0);
 
1249
        XawDialogAddButton(dialog, "yes", PopdownAdd, (XtPointer)True);
 
1250
        XawDialogAddButton(dialog, "no", PopdownAdd, (XtPointer)False);
 
1251
        XtRealizeWidget(addshell);
 
1252
        XSetWMProtocols(DPY, XtWindow(addshell), &wm_delete_window, 1);
 
1253
    }
 
1254
 
 
1255
    asking_add = 1;
 
1256
 
 
1257
    XtPopup(addshell, XtGrabExclusive);
 
1258
    while (asking_add)
 
1259
        XtAppProcessEvent(XtWidgetToApplicationContext(addshell), XtIMAll);
 
1260
 
 
1261
    return (do_add);
 
1262
}
 
1263
 
 
1264
/*ARGSUSED*/
 
1265
static void
 
1266
AddModeCallback(Widget w, XtPointer call_data, XtPointer client_data)
 
1267
{
 
1268
    if (vidtune && vidtune->monitor) {
 
1269
        char *label;
 
1270
        Arg args[1];
 
1271
        XF86ConfModeLinePtr mode;
 
1272
 
 
1273
        XtSetArg(args[0], XtNstring, &label);
 
1274
        XtGetValues(text, args, 1);
 
1275
        if (*label == '\0') {
 
1276
            XBell(XtDisplay(w), 80);
 
1277
            return;
 
1278
        }           
 
1279
        if (xf86findModeLine(label, vidtune->monitor->mon_modeline_lst)
 
1280
            != NULL && !ForceAddMode())
 
1281
            return;
 
1282
 
 
1283
        mode = (XF86ConfModeLinePtr)XtCalloc(1, sizeof(XF86ConfModeLineRec));
 
1284
        mode->ml_identifier = XtNewString(label);
 
1285
        mode->ml_clock = dot_clock;
 
1286
        mode->ml_hdisplay = modeline.hdisplay;
 
1287
        mode->ml_hsyncstart = modeline.hsyncstart;
 
1288
        mode->ml_hsyncend = modeline.hsyncend;
 
1289
        mode->ml_htotal = modeline.htotal;
 
1290
        mode->ml_vdisplay = modeline.vdisplay;
 
1291
        mode->ml_vsyncstart = modeline.vsyncstart;
 
1292
        mode->ml_vsyncend = modeline.vsyncend;
 
1293
        mode->ml_vtotal = modeline.vtotal;
 
1294
/*      mode->ml_vscan = ???;*/
 
1295
        mode->ml_flags = modeline.flags;
 
1296
        mode->ml_hskew = modeline.hskew;
 
1297
        vidtune->monitor->mon_modeline_lst =
 
1298
            xf86addModeLine(vidtune->monitor->mon_modeline_lst, mode);
 
1299
    }
 
1300
    else
 
1301
        XBell(XtDisplay(w), 80);
 
1302
}
 
1303
 
 
1304
/*ARGSUSED*/
 
1305
static void
 
1306
StopTestCallback(Widget w, XtPointer call_data, XtPointer client_data)
 
1307
{
 
1308
    XtRemoveTimeOut(timeout);
 
1309
    TestTimeout((XtPointer)w, NULL);
 
1310
}
 
1311
 
 
1312
/*ARGSUSED*/
 
1313
void
 
1314
CancelTestModeAction(Widget w, XEvent *event,
 
1315
                     String *params, Cardinal *num_params)
 
1316
{
 
1317
    StopTestCallback(w, NULL, NULL);
 
1318
}
 
1319
 
 
1320
static void
 
1321
TestTimeout(XtPointer client_data, XtIntervalId* id)
 
1322
{
 
1323
    XF86VidModeModeLine mode;
 
1324
 
 
1325
    XtPopdown(testshell);
 
1326
    timeout = 0;
 
1327
    memcpy(&mode, &modeline, sizeof(XF86VidModeModeLine));
 
1328
    memcpy(&modeline, &orig_modeline, sizeof(XF86VidModeModeLine));
 
1329
    ApplyCallback((Widget)client_data, NULL, NULL);
 
1330
/*    if (hitError == 0)*/
 
1331
        memcpy(&modeline, &mode, sizeof(XF86VidModeModeLine));
 
1332
    SetLabels();
 
1333
}
 
1334
 
 
1335
static void
 
1336
TestCallback(Widget w, XtPointer call_data, XtPointer client_data)
 
1337
{
 
1338
    if (testshell == NULL) {
 
1339
        Widget dialog;
 
1340
 
 
1341
        testshell = XtCreatePopupShell("test", transientShellWidgetClass,
 
1342
                                        toplevel, NULL, 0);
 
1343
        dialog = XtVaCreateManagedWidget("dialog", dialogWidgetClass,
 
1344
                                         testshell, XtNvalue, NULL, NULL, 0);
 
1345
        XawDialogAddButton(dialog, "stop", StopTestCallback, NULL);
 
1346
        XtRealizeWidget(testshell);
 
1347
        XSetWMProtocols(DPY, XtWindow(testshell), &wm_delete_window, 1);
 
1348
    }
 
1349
 
 
1350
    XtPopup(testshell, XtGrabExclusive);
 
1351
 
 
1352
    XSync(XtDisplay(toplevel), False);
 
1353
    timeout = XtAppAddTimeOut(XtWidgetToApplicationContext(w),
 
1354
    /* the timeout probably shoud be converted to a resource */
 
1355
                              4000, TestTimeout, (XtPointer)w);
 
1356
    ApplyCallback(w, call_data, client_data);
 
1357
}