Monitor.c revision 6747b715
1/*
2 *
3 * Copyright (c) 1997  Metro Link Incorporated
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18 * THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
19 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
20 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 * SOFTWARE.
22 *
23 * Except as contained in this notice, the name of the Metro Link shall not be
24 * used in advertising or otherwise to promote the sale, use or other dealings
25 * in this Software without prior written authorization from Metro Link.
26 *
27 */
28/*
29 * Copyright (c) 1997-2003 by The XFree86 Project, Inc.
30 *
31 * Permission is hereby granted, free of charge, to any person obtaining a
32 * copy of this software and associated documentation files (the "Software"),
33 * to deal in the Software without restriction, including without limitation
34 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
35 * and/or sell copies of the Software, and to permit persons to whom the
36 * Software is furnished to do so, subject to the following conditions:
37 *
38 * The above copyright notice and this permission notice shall be included in
39 * all copies or substantial portions of the Software.
40 *
41 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
42 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
43 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
44 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
45 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
46 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
47 * OTHER DEALINGS IN THE SOFTWARE.
48 *
49 * Except as contained in this notice, the name of the copyright holder(s)
50 * and author(s) shall not be used in advertising or otherwise to promote
51 * the sale, use or other dealings in this Software without prior written
52 * authorization from the copyright holder(s) and author(s).
53 */
54
55
56/* View/edit this file with tab stops set to 4 */
57
58#ifdef HAVE_XORG_CONFIG_H
59#include <xorg-config.h>
60#endif
61
62#include "xf86Parser.h"
63#include "xf86tokens.h"
64#include "Configint.h"
65
66extern LexRec val;
67
68static xf86ConfigSymTabRec MonitorTab[] =
69{
70	{ENDSECTION, "endsection"},
71	{IDENTIFIER, "identifier"},
72	{VENDOR, "vendorname"},
73	{MODEL, "modelname"},
74	{USEMODES, "usemodes"},
75	{MODELINE, "modeline"},
76	{DISPLAYSIZE, "displaysize"},
77	{HORIZSYNC, "horizsync"},
78	{VERTREFRESH, "vertrefresh"},
79	{MODE, "mode"},
80	{GAMMA, "gamma"},
81	{OPTION, "option"},
82	{-1, ""},
83};
84
85static xf86ConfigSymTabRec ModesTab[] =
86{
87	{ENDSECTION, "endsection"},
88	{IDENTIFIER, "identifier"},
89	{MODELINE, "modeline"},
90	{MODE, "mode"},
91	{-1, ""},
92};
93
94static xf86ConfigSymTabRec TimingTab[] =
95{
96	{TT_INTERLACE, "interlace"},
97	{TT_PHSYNC, "+hsync"},
98	{TT_NHSYNC, "-hsync"},
99	{TT_PVSYNC, "+vsync"},
100	{TT_NVSYNC, "-vsync"},
101	{TT_CSYNC, "composite"},
102	{TT_PCSYNC, "+csync"},
103	{TT_NCSYNC, "-csync"},
104	{TT_DBLSCAN, "doublescan"},
105	{TT_HSKEW, "hskew"},
106	{TT_BCAST, "bcast"},
107	{TT_VSCAN, "vscan"},
108	{TT_CUSTOM, "CUSTOM"},
109	{-1, ""},
110};
111
112static xf86ConfigSymTabRec ModeTab[] =
113{
114	{DOTCLOCK, "dotclock"},
115	{HTIMINGS, "htimings"},
116	{VTIMINGS, "vtimings"},
117	{FLAGS, "flags"},
118	{HSKEW, "hskew"},
119	{BCAST, "bcast"},
120	{VSCAN, "vscan"},
121	{ENDMODE, "endmode"},
122	{-1, ""},
123};
124
125#define CLEANUP xf86freeModeLineList
126
127static void
128xf86freeModeLineList (XF86ConfModeLinePtr ptr)
129{
130	XF86ConfModeLinePtr prev;
131	while (ptr)
132	{
133		TestFree (ptr->ml_identifier);
134		TestFree (ptr->ml_comment);
135		prev = ptr;
136		ptr = ptr->list.next;
137		free (prev);
138	}
139}
140
141static XF86ConfModeLinePtr
142xf86parseModeLine (void)
143{
144	int token;
145	parsePrologue (XF86ConfModeLinePtr, XF86ConfModeLineRec)
146
147	/* Identifier */
148	if (xf86getSubToken (&(ptr->ml_comment)) != STRING)
149		Error ("ModeLine identifier expected", NULL);
150	ptr->ml_identifier = val.str;
151
152	/* DotClock */
153	if (xf86getSubToken (&(ptr->ml_comment)) != NUMBER)
154		Error ("ModeLine dotclock expected", NULL);
155	ptr->ml_clock = (int) (val.realnum * 1000.0 + 0.5);
156
157	/* HDisplay */
158	if (xf86getSubToken (&(ptr->ml_comment)) != NUMBER)
159		Error ("ModeLine Hdisplay expected", NULL);
160	ptr->ml_hdisplay = val.num;
161
162	/* HSyncStart */
163	if (xf86getSubToken (&(ptr->ml_comment)) != NUMBER)
164		Error ("ModeLine HSyncStart expected", NULL);
165	ptr->ml_hsyncstart = val.num;
166
167	/* HSyncEnd */
168	if (xf86getSubToken (&(ptr->ml_comment)) != NUMBER)
169		Error ("ModeLine HSyncEnd expected", NULL);
170	ptr->ml_hsyncend = val.num;
171
172	/* HTotal */
173	if (xf86getSubToken (&(ptr->ml_comment)) != NUMBER)
174		Error ("ModeLine HTotal expected", NULL);
175	ptr->ml_htotal = val.num;
176
177	/* VDisplay */
178	if (xf86getSubToken (&(ptr->ml_comment)) != NUMBER)
179		Error ("ModeLine Vdisplay expected", NULL);
180	ptr->ml_vdisplay = val.num;
181
182	/* VSyncStart */
183	if (xf86getSubToken (&(ptr->ml_comment)) != NUMBER)
184		Error ("ModeLine VSyncStart expected", NULL);
185	ptr->ml_vsyncstart = val.num;
186
187	/* VSyncEnd */
188	if (xf86getSubToken (&(ptr->ml_comment)) != NUMBER)
189		Error ("ModeLine VSyncEnd expected", NULL);
190	ptr->ml_vsyncend = val.num;
191
192	/* VTotal */
193	if (xf86getSubToken (&(ptr->ml_comment)) != NUMBER)
194		Error ("ModeLine VTotal expected", NULL);
195	ptr->ml_vtotal = val.num;
196
197	token = xf86getSubTokenWithTab (&(ptr->ml_comment), TimingTab);
198	while ((token == TT_INTERLACE) || (token == TT_PHSYNC) ||
199		   (token == TT_NHSYNC) || (token == TT_PVSYNC) ||
200		   (token == TT_NVSYNC) || (token == TT_CSYNC) ||
201		   (token == TT_PCSYNC) || (token == TT_NCSYNC) ||
202		   (token == TT_DBLSCAN) || (token == TT_HSKEW) ||
203		   (token == TT_VSCAN) || (token == TT_BCAST))
204	{
205		switch (token)
206		{
207
208		case TT_INTERLACE:
209			ptr->ml_flags |= XF86CONF_INTERLACE;
210			break;
211		case TT_PHSYNC:
212			ptr->ml_flags |= XF86CONF_PHSYNC;
213			break;
214		case TT_NHSYNC:
215			ptr->ml_flags |= XF86CONF_NHSYNC;
216			break;
217		case TT_PVSYNC:
218			ptr->ml_flags |= XF86CONF_PVSYNC;
219			break;
220		case TT_NVSYNC:
221			ptr->ml_flags |= XF86CONF_NVSYNC;
222			break;
223		case TT_CSYNC:
224			ptr->ml_flags |= XF86CONF_CSYNC;
225			break;
226		case TT_PCSYNC:
227			ptr->ml_flags |= XF86CONF_PCSYNC;
228			break;
229		case TT_NCSYNC:
230			ptr->ml_flags |= XF86CONF_NCSYNC;
231			break;
232		case TT_DBLSCAN:
233			ptr->ml_flags |= XF86CONF_DBLSCAN;
234			break;
235		case TT_HSKEW:
236			if (xf86getSubToken (&(ptr->ml_comment)) != NUMBER)
237				Error (NUMBER_MSG, "Hskew");
238			ptr->ml_hskew = val.num;
239			ptr->ml_flags |= XF86CONF_HSKEW;
240			break;
241		case TT_BCAST:
242			ptr->ml_flags |= XF86CONF_BCAST;
243			break;
244		case TT_VSCAN:
245			if (xf86getSubToken (&(ptr->ml_comment)) != NUMBER)
246				Error (NUMBER_MSG, "Vscan");
247			ptr->ml_vscan = val.num;
248			ptr->ml_flags |= XF86CONF_VSCAN;
249			break;
250		case TT_CUSTOM:
251			ptr->ml_flags |= XF86CONF_CUSTOM;
252			break;
253		case EOF_TOKEN:
254			Error (UNEXPECTED_EOF_MSG, NULL);
255			break;
256		default:
257			Error (INVALID_KEYWORD_MSG, xf86tokenString ());
258			break;
259		}
260		token = xf86getSubTokenWithTab (&(ptr->ml_comment), TimingTab);
261	}
262	xf86unGetToken (token);
263
264#ifdef DEBUG
265	printf ("ModeLine parsed\n");
266#endif
267	return ptr;
268}
269
270static XF86ConfModeLinePtr
271xf86parseVerboseMode (void)
272{
273	int token, token2;
274	int had_dotclock = 0, had_htimings = 0, had_vtimings = 0;
275	parsePrologue (XF86ConfModeLinePtr, XF86ConfModeLineRec)
276
277		if (xf86getSubToken (&(ptr->ml_comment)) != STRING)
278		Error ("Mode name expected", NULL);
279	ptr->ml_identifier = val.str;
280	while ((token = xf86getToken (ModeTab)) != ENDMODE)
281	{
282		switch (token)
283		{
284		case COMMENT:
285			ptr->ml_comment = xf86addComment(ptr->ml_comment, val.str);
286			break;
287		case DOTCLOCK:
288			if ((token = xf86getSubToken (&(ptr->ml_comment))) != NUMBER)
289				Error (NUMBER_MSG, "DotClock");
290			ptr->ml_clock = (int) (val.realnum * 1000.0 + 0.5);
291			had_dotclock = 1;
292			break;
293		case HTIMINGS:
294			if (xf86getSubToken (&(ptr->ml_comment)) == NUMBER)
295				ptr->ml_hdisplay = val.num;
296			else
297				Error ("Horizontal display expected", NULL);
298
299			if (xf86getSubToken (&(ptr->ml_comment)) == NUMBER)
300				ptr->ml_hsyncstart = val.num;
301			else
302				Error ("Horizontal sync start expected", NULL);
303
304			if (xf86getSubToken (&(ptr->ml_comment)) == NUMBER)
305				ptr->ml_hsyncend = val.num;
306			else
307				Error ("Horizontal sync end expected", NULL);
308
309			if (xf86getSubToken (&(ptr->ml_comment)) == NUMBER)
310				ptr->ml_htotal = val.num;
311			else
312				Error ("Horizontal total expected", NULL);
313			had_htimings = 1;
314			break;
315		case VTIMINGS:
316			if (xf86getSubToken (&(ptr->ml_comment)) == NUMBER)
317				ptr->ml_vdisplay = val.num;
318			else
319				Error ("Vertical display expected", NULL);
320
321			if (xf86getSubToken (&(ptr->ml_comment)) == NUMBER)
322				ptr->ml_vsyncstart = val.num;
323			else
324				Error ("Vertical sync start expected", NULL);
325
326			if (xf86getSubToken (&(ptr->ml_comment)) == NUMBER)
327				ptr->ml_vsyncend = val.num;
328			else
329				Error ("Vertical sync end expected", NULL);
330
331			if (xf86getSubToken (&(ptr->ml_comment)) == NUMBER)
332				ptr->ml_vtotal = val.num;
333			else
334				Error ("Vertical total expected", NULL);
335			had_vtimings = 1;
336			break;
337		case FLAGS:
338			token = xf86getSubToken (&(ptr->ml_comment));
339			if (token != STRING)
340				Error (QUOTE_MSG, "Flags");
341			while (token == STRING)
342			{
343				token2 = xf86getStringToken (TimingTab);
344				switch (token2)
345				{
346				case TT_INTERLACE:
347					ptr->ml_flags |= XF86CONF_INTERLACE;
348					break;
349				case TT_PHSYNC:
350					ptr->ml_flags |= XF86CONF_PHSYNC;
351					break;
352				case TT_NHSYNC:
353					ptr->ml_flags |= XF86CONF_NHSYNC;
354					break;
355				case TT_PVSYNC:
356					ptr->ml_flags |= XF86CONF_PVSYNC;
357					break;
358				case TT_NVSYNC:
359					ptr->ml_flags |= XF86CONF_NVSYNC;
360					break;
361				case TT_CSYNC:
362					ptr->ml_flags |= XF86CONF_CSYNC;
363					break;
364				case TT_PCSYNC:
365					ptr->ml_flags |= XF86CONF_PCSYNC;
366					break;
367				case TT_NCSYNC:
368					ptr->ml_flags |= XF86CONF_NCSYNC;
369					break;
370				case TT_DBLSCAN:
371					ptr->ml_flags |= XF86CONF_DBLSCAN;
372					break;
373				case TT_CUSTOM:
374					ptr->ml_flags |= XF86CONF_CUSTOM;
375					break;
376				case EOF_TOKEN:
377					Error (UNEXPECTED_EOF_MSG, NULL);
378					break;
379				default:
380					Error ("Unknown flag string", NULL);
381					break;
382				}
383				token = xf86getSubToken (&(ptr->ml_comment));
384			}
385			xf86unGetToken (token);
386			break;
387		case HSKEW:
388			if (xf86getSubToken (&(ptr->ml_comment)) != NUMBER)
389				Error ("Horizontal skew expected", NULL);
390			ptr->ml_flags |= XF86CONF_HSKEW;
391			ptr->ml_hskew = val.num;
392			break;
393		case VSCAN:
394			if (xf86getSubToken (&(ptr->ml_comment)) != NUMBER)
395				Error ("Vertical scan count expected", NULL);
396			ptr->ml_flags |= XF86CONF_VSCAN;
397			ptr->ml_vscan = val.num;
398			break;
399		case EOF_TOKEN:
400			Error (UNEXPECTED_EOF_MSG, NULL);
401			break;
402		default:
403			Error ("Unexepcted token in verbose \"Mode\" entry\n", NULL);
404		}
405	}
406	if (!had_dotclock)
407		Error ("the dotclock is missing", NULL);
408	if (!had_htimings)
409		Error ("the horizontal timings are missing", NULL);
410	if (!had_vtimings)
411		Error ("the vertical timings are missing", NULL);
412
413#ifdef DEBUG
414	printf ("Verbose Mode parsed\n");
415#endif
416	return ptr;
417}
418
419#undef CLEANUP
420
421#define CLEANUP xf86freeMonitorList
422
423XF86ConfMonitorPtr
424xf86parseMonitorSection (void)
425{
426	int has_ident = FALSE;
427	int token;
428	parsePrologue (XF86ConfMonitorPtr, XF86ConfMonitorRec)
429
430		while ((token = xf86getToken (MonitorTab)) != ENDSECTION)
431	{
432		switch (token)
433		{
434		case COMMENT:
435			ptr->mon_comment = xf86addComment(ptr->mon_comment, val.str);
436			break;
437		case IDENTIFIER:
438			if (xf86getSubToken (&(ptr->mon_comment)) != STRING)
439				Error (QUOTE_MSG, "Identifier");
440			if (has_ident == TRUE)
441				Error (MULTIPLE_MSG, "Identifier");
442			ptr->mon_identifier = val.str;
443			has_ident = TRUE;
444			break;
445		case VENDOR:
446			if (xf86getSubToken (&(ptr->mon_comment)) != STRING)
447				Error (QUOTE_MSG, "Vendor");
448			ptr->mon_vendor = val.str;
449			break;
450		case MODEL:
451			if (xf86getSubToken (&(ptr->mon_comment)) != STRING)
452				Error (QUOTE_MSG, "ModelName");
453			ptr->mon_modelname = val.str;
454			break;
455		case MODE:
456			HANDLE_LIST (mon_modeline_lst, xf86parseVerboseMode,
457						 XF86ConfModeLinePtr);
458			break;
459		case MODELINE:
460			HANDLE_LIST (mon_modeline_lst, xf86parseModeLine,
461						 XF86ConfModeLinePtr);
462			break;
463		case DISPLAYSIZE:
464			if (xf86getSubToken (&(ptr->mon_comment)) != NUMBER)
465				Error (DISPLAYSIZE_MSG, NULL);
466			ptr->mon_width = val.realnum;
467			if (xf86getSubToken (&(ptr->mon_comment)) != NUMBER)
468				Error (DISPLAYSIZE_MSG, NULL);
469			ptr->mon_height = val.realnum;
470			break;
471
472		case HORIZSYNC:
473			if (xf86getSubToken (&(ptr->mon_comment)) != NUMBER)
474				Error (HORIZSYNC_MSG, NULL);
475			do {
476				if (ptr->mon_n_hsync >= CONF_MAX_HSYNC)
477					Error ("Sorry. Too many horizontal sync intervals.", NULL);
478				ptr->mon_hsync[ptr->mon_n_hsync].lo = val.realnum;
479				switch (token = xf86getSubToken (&(ptr->mon_comment)))
480				{
481					case COMMA:
482						ptr->mon_hsync[ptr->mon_n_hsync].hi =
483						ptr->mon_hsync[ptr->mon_n_hsync].lo;
484						break;
485					case DASH:
486						if (xf86getSubToken (&(ptr->mon_comment)) != NUMBER ||
487						    (float)val.realnum < ptr->mon_hsync[ptr->mon_n_hsync].lo)
488							Error (HORIZSYNC_MSG, NULL);
489						ptr->mon_hsync[ptr->mon_n_hsync].hi = val.realnum;
490						if ((token = xf86getSubToken (&(ptr->mon_comment))) == COMMA)
491							break;
492						ptr->mon_n_hsync++;
493						goto HorizDone;
494					default:
495						/* We cannot currently know if a '\n' was found,
496						 * or this is a real error
497						 */
498						ptr->mon_hsync[ptr->mon_n_hsync].hi =
499						ptr->mon_hsync[ptr->mon_n_hsync].lo;
500						ptr->mon_n_hsync++;
501						goto HorizDone;
502				}
503				ptr->mon_n_hsync++;
504			} while ((token = xf86getSubToken (&(ptr->mon_comment))) == NUMBER);
505HorizDone:
506			xf86unGetToken (token);
507			break;
508
509		case VERTREFRESH:
510			if (xf86getSubToken (&(ptr->mon_comment)) != NUMBER)
511				Error (VERTREFRESH_MSG, NULL);
512			do {
513				ptr->mon_vrefresh[ptr->mon_n_vrefresh].lo = val.realnum;
514				switch (token = xf86getSubToken (&(ptr->mon_comment)))
515				{
516					case COMMA:
517						ptr->mon_vrefresh[ptr->mon_n_vrefresh].hi =
518						ptr->mon_vrefresh[ptr->mon_n_vrefresh].lo;
519						break;
520					case DASH:
521						if (xf86getSubToken (&(ptr->mon_comment)) != NUMBER ||
522						    (float)val.realnum < ptr->mon_vrefresh[ptr->mon_n_vrefresh].lo)
523							Error (VERTREFRESH_MSG, NULL);
524						ptr->mon_vrefresh[ptr->mon_n_vrefresh].hi = val.realnum;
525						if ((token = xf86getSubToken (&(ptr->mon_comment))) == COMMA)
526							break;
527						ptr->mon_n_vrefresh++;
528						goto VertDone;
529					default:
530						/* We cannot currently know if a '\n' was found,
531						 * or this is a real error
532						 */
533						ptr->mon_vrefresh[ptr->mon_n_vrefresh].hi =
534						ptr->mon_vrefresh[ptr->mon_n_vrefresh].lo;
535						ptr->mon_n_vrefresh++;
536						goto VertDone;
537				}
538				if (ptr->mon_n_vrefresh >= CONF_MAX_VREFRESH)
539					Error ("Sorry. Too many vertical refresh intervals.", NULL);
540				ptr->mon_n_vrefresh++;
541			} while ((token = xf86getSubToken (&(ptr->mon_comment))) == NUMBER);
542VertDone:
543			xf86unGetToken (token);
544			break;
545
546		case GAMMA:
547			if( xf86getSubToken (&(ptr->mon_comment)) != NUMBER )
548			{
549				Error (INVALID_GAMMA_MSG, NULL);
550			}
551			else
552			{
553				ptr->mon_gamma_red = ptr->mon_gamma_green =
554					ptr->mon_gamma_blue = val.realnum;
555				if( xf86getSubToken (&(ptr->mon_comment)) == NUMBER )
556				{
557					ptr->mon_gamma_green = val.realnum;
558					if( xf86getSubToken (&(ptr->mon_comment)) == NUMBER )
559					{
560						ptr->mon_gamma_blue = val.realnum;
561					}
562					else
563					{
564						Error (INVALID_GAMMA_MSG, NULL);
565					}
566				}
567				else
568					xf86unGetToken (token);
569			}
570			break;
571		case OPTION:
572			ptr->mon_option_lst = xf86parseOption(ptr->mon_option_lst);
573			break;
574		case USEMODES:
575		        {
576				XF86ConfModesLinkPtr mptr;
577
578				if ((token = xf86getSubToken (&(ptr->mon_comment))) != STRING)
579					Error (QUOTE_MSG, "UseModes");
580
581				/* add to the end of the list of modes sections
582				   referenced here */
583				mptr = calloc (1, sizeof (XF86ConfModesLinkRec));
584				mptr->list.next = NULL;
585				mptr->ml_modes_str = val.str;
586				mptr->ml_modes = NULL;
587				ptr->mon_modes_sect_lst = (XF86ConfModesLinkPtr)
588					xf86addListItem((GenericListPtr)ptr->mon_modes_sect_lst,
589						    (GenericListPtr)mptr);
590			}
591			break;
592		case EOF_TOKEN:
593			Error (UNEXPECTED_EOF_MSG, NULL);
594			break;
595		default:
596			xf86parseError (INVALID_KEYWORD_MSG, xf86tokenString ());
597			CLEANUP (ptr);
598			return NULL;
599			break;
600		}
601	}
602
603	if (!has_ident)
604		Error (NO_IDENT_MSG, NULL);
605
606#ifdef DEBUG
607	printf ("Monitor section parsed\n");
608#endif
609	return ptr;
610}
611
612#undef CLEANUP
613#define CLEANUP xf86freeModesList
614
615XF86ConfModesPtr
616xf86parseModesSection (void)
617{
618	int has_ident = FALSE;
619	int token;
620	parsePrologue (XF86ConfModesPtr, XF86ConfModesRec)
621
622	while ((token = xf86getToken (ModesTab)) != ENDSECTION)
623	{
624		switch (token)
625		{
626		case COMMENT:
627			ptr->modes_comment = xf86addComment(ptr->modes_comment, val.str);
628			break;
629		case IDENTIFIER:
630			if (xf86getSubToken (&(ptr->modes_comment)) != STRING)
631				Error (QUOTE_MSG, "Identifier");
632			if (has_ident == TRUE)
633				Error (MULTIPLE_MSG, "Identifier");
634			ptr->modes_identifier = val.str;
635			has_ident = TRUE;
636			break;
637		case MODE:
638			HANDLE_LIST (mon_modeline_lst, xf86parseVerboseMode,
639						 XF86ConfModeLinePtr);
640			break;
641		case MODELINE:
642			HANDLE_LIST (mon_modeline_lst, xf86parseModeLine,
643						 XF86ConfModeLinePtr);
644			break;
645		default:
646			xf86parseError (INVALID_KEYWORD_MSG, xf86tokenString ());
647			CLEANUP (ptr);
648			return NULL;
649			break;
650		}
651	}
652
653	if (!has_ident)
654		Error (NO_IDENT_MSG, NULL);
655
656#ifdef DEBUG
657	printf ("Modes section parsed\n");
658#endif
659	return ptr;
660}
661
662#undef CLEANUP
663
664void
665xf86printMonitorSection (FILE * cf, XF86ConfMonitorPtr ptr)
666{
667	int i;
668	XF86ConfModeLinePtr mlptr;
669	XF86ConfModesLinkPtr mptr;
670
671	while (ptr)
672	{
673		mptr = ptr->mon_modes_sect_lst;
674		fprintf (cf, "Section \"Monitor\"\n");
675		if (ptr->mon_comment)
676			fprintf (cf, "%s", ptr->mon_comment);
677		if (ptr->mon_identifier)
678			fprintf (cf, "\tIdentifier   \"%s\"\n", ptr->mon_identifier);
679		if (ptr->mon_vendor)
680			fprintf (cf, "\tVendorName   \"%s\"\n", ptr->mon_vendor);
681		if (ptr->mon_modelname)
682			fprintf (cf, "\tModelName    \"%s\"\n", ptr->mon_modelname);
683		while (mptr) {
684			fprintf (cf, "\tUseModes     \"%s\"\n", mptr->ml_modes_str);
685			mptr = mptr->list.next;
686		}
687		if (ptr->mon_width)
688			fprintf (cf, "\tDisplaySize  %d\t%d\n",
689					 ptr->mon_width,
690					 ptr->mon_height);
691		for (i = 0; i < ptr->mon_n_hsync; i++)
692		{
693			fprintf (cf, "\tHorizSync    %2.1f - %2.1f\n",
694					 ptr->mon_hsync[i].lo,
695					 ptr->mon_hsync[i].hi);
696		}
697		for (i = 0; i < ptr->mon_n_vrefresh; i++)
698		{
699			fprintf (cf, "\tVertRefresh  %2.1f - %2.1f\n",
700					 ptr->mon_vrefresh[i].lo,
701					 ptr->mon_vrefresh[i].hi);
702		}
703		if (ptr->mon_gamma_red) {
704			if (ptr->mon_gamma_red == ptr->mon_gamma_green
705				&& ptr->mon_gamma_red == ptr->mon_gamma_blue)
706			{
707				fprintf (cf, "\tGamma        %.4g\n",
708					ptr->mon_gamma_red);
709			} else {
710				fprintf (cf, "\tGamma        %.4g %.4g %.4g\n",
711					ptr->mon_gamma_red,
712					ptr->mon_gamma_green,
713					ptr->mon_gamma_blue);
714			}
715		}
716		for (mlptr = ptr->mon_modeline_lst; mlptr; mlptr = mlptr->list.next)
717		{
718			fprintf (cf, "\tModeLine     \"%s\" %2.1f ",
719					 mlptr->ml_identifier, mlptr->ml_clock / 1000.0);
720			fprintf (cf, "%d %d %d %d %d %d %d %d",
721					 mlptr->ml_hdisplay, mlptr->ml_hsyncstart,
722					 mlptr->ml_hsyncend, mlptr->ml_htotal,
723					 mlptr->ml_vdisplay, mlptr->ml_vsyncstart,
724					 mlptr->ml_vsyncend, mlptr->ml_vtotal);
725			if (mlptr->ml_flags & XF86CONF_PHSYNC)
726				fprintf (cf, " +hsync");
727			if (mlptr->ml_flags & XF86CONF_NHSYNC)
728				fprintf (cf, " -hsync");
729			if (mlptr->ml_flags & XF86CONF_PVSYNC)
730				fprintf (cf, " +vsync");
731			if (mlptr->ml_flags & XF86CONF_NVSYNC)
732				fprintf (cf, " -vsync");
733			if (mlptr->ml_flags & XF86CONF_INTERLACE)
734				fprintf (cf, " interlace");
735			if (mlptr->ml_flags & XF86CONF_CSYNC)
736				fprintf (cf, " composite");
737			if (mlptr->ml_flags & XF86CONF_PCSYNC)
738				fprintf (cf, " +csync");
739			if (mlptr->ml_flags & XF86CONF_NCSYNC)
740				fprintf (cf, " -csync");
741			if (mlptr->ml_flags & XF86CONF_DBLSCAN)
742				fprintf (cf, " doublescan");
743			if (mlptr->ml_flags & XF86CONF_HSKEW)
744				fprintf (cf, " hskew %d", mlptr->ml_hskew);
745			if (mlptr->ml_flags & XF86CONF_BCAST)
746				fprintf (cf, " bcast");
747			fprintf (cf, "\n");
748		}
749		xf86printOptionList(cf, ptr->mon_option_lst, 1);
750		fprintf (cf, "EndSection\n\n");
751		ptr = ptr->list.next;
752	}
753}
754
755void
756xf86printModesSection (FILE * cf, XF86ConfModesPtr ptr)
757{
758	XF86ConfModeLinePtr mlptr;
759
760	while (ptr)
761	{
762		fprintf (cf, "Section \"Modes\"\n");
763		if (ptr->modes_comment)
764			fprintf (cf, "%s", ptr->modes_comment);
765		if (ptr->modes_identifier)
766			fprintf (cf, "\tIdentifier     \"%s\"\n", ptr->modes_identifier);
767		for (mlptr = ptr->mon_modeline_lst; mlptr; mlptr = mlptr->list.next)
768		{
769			fprintf (cf, "\tModeLine     \"%s\" %2.1f ",
770					 mlptr->ml_identifier, mlptr->ml_clock / 1000.0);
771			fprintf (cf, "%d %d %d %d %d %d %d %d",
772					 mlptr->ml_hdisplay, mlptr->ml_hsyncstart,
773					 mlptr->ml_hsyncend, mlptr->ml_htotal,
774					 mlptr->ml_vdisplay, mlptr->ml_vsyncstart,
775					 mlptr->ml_vsyncend, mlptr->ml_vtotal);
776			if (mlptr->ml_flags & XF86CONF_PHSYNC)
777				fprintf (cf, " +hsync");
778			if (mlptr->ml_flags & XF86CONF_NHSYNC)
779				fprintf (cf, " -hsync");
780			if (mlptr->ml_flags & XF86CONF_PVSYNC)
781				fprintf (cf, " +vsync");
782			if (mlptr->ml_flags & XF86CONF_NVSYNC)
783				fprintf (cf, " -vsync");
784			if (mlptr->ml_flags & XF86CONF_INTERLACE)
785				fprintf (cf, " interlace");
786			if (mlptr->ml_flags & XF86CONF_CSYNC)
787				fprintf (cf, " composite");
788			if (mlptr->ml_flags & XF86CONF_PCSYNC)
789				fprintf (cf, " +csync");
790			if (mlptr->ml_flags & XF86CONF_NCSYNC)
791				fprintf (cf, " -csync");
792			if (mlptr->ml_flags & XF86CONF_DBLSCAN)
793				fprintf (cf, " doublescan");
794			if (mlptr->ml_flags & XF86CONF_HSKEW)
795				fprintf (cf, " hskew %d", mlptr->ml_hskew);
796			if (mlptr->ml_flags & XF86CONF_VSCAN)
797				fprintf (cf, " vscan %d", mlptr->ml_vscan);
798			if (mlptr->ml_flags & XF86CONF_BCAST)
799				fprintf (cf, " bcast");
800			if (mlptr->ml_comment)
801				fprintf (cf, "%s", mlptr->ml_comment);
802			else
803				fprintf (cf, "\n");
804		}
805		fprintf (cf, "EndSection\n\n");
806		ptr = ptr->list.next;
807	}
808}
809
810void
811xf86freeMonitorList (XF86ConfMonitorPtr ptr)
812{
813	XF86ConfMonitorPtr prev;
814
815	while (ptr)
816	{
817		TestFree (ptr->mon_identifier);
818		TestFree (ptr->mon_vendor);
819		TestFree (ptr->mon_modelname);
820		TestFree (ptr->mon_comment);
821		xf86optionListFree (ptr->mon_option_lst);
822		xf86freeModeLineList (ptr->mon_modeline_lst);
823		prev = ptr;
824		ptr = ptr->list.next;
825		free (prev);
826	}
827}
828
829void
830xf86freeModesList (XF86ConfModesPtr ptr)
831{
832	XF86ConfModesPtr prev;
833
834	while (ptr)
835	{
836		TestFree (ptr->modes_identifier);
837		TestFree (ptr->modes_comment);
838		xf86freeModeLineList (ptr->mon_modeline_lst);
839		prev = ptr;
840		ptr = ptr->list.next;
841		free (prev);
842	}
843}
844
845XF86ConfMonitorPtr
846xf86findMonitor (const char *ident, XF86ConfMonitorPtr p)
847{
848	while (p)
849	{
850		if (xf86nameCompare (ident, p->mon_identifier) == 0)
851			return p;
852
853		p = p->list.next;
854	}
855	return NULL;
856}
857
858XF86ConfModesPtr
859xf86findModes (const char *ident, XF86ConfModesPtr p)
860{
861	while (p)
862	{
863		if (xf86nameCompare (ident, p->modes_identifier) == 0)
864			return p;
865
866		p = p->list.next;
867	}
868	return NULL;
869}
870
871XF86ConfModeLinePtr
872xf86findModeLine (const char *ident, XF86ConfModeLinePtr p)
873{
874	while (p)
875	{
876		if (xf86nameCompare (ident, p->ml_identifier) == 0)
877			return p;
878
879		p = p->list.next;
880	}
881	return NULL;
882}
883
884int
885xf86validateMonitor (XF86ConfigPtr p, XF86ConfScreenPtr screen)
886{
887	XF86ConfMonitorPtr monitor = screen->scrn_monitor;
888	XF86ConfModesLinkPtr modeslnk = monitor->mon_modes_sect_lst;
889	XF86ConfModesPtr modes;
890	while(modeslnk)
891	{
892		modes = xf86findModes (modeslnk->ml_modes_str, p->conf_modes_lst);
893		if (!modes)
894		{
895			xf86validationError (UNDEFINED_MODES_MSG,
896					     modeslnk->ml_modes_str,
897					     screen->scrn_identifier);
898			return FALSE;
899		}
900		modeslnk->ml_modes = modes;
901		modeslnk = modeslnk->list.next;
902	}
903	return TRUE;
904}
905