/*
 *  Copyright (c) 2001, Lyonel Vincent <vincentl@ec-lyon.fr>
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2, or (at your option)
 *  any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */

#include <X11/Xlib.h>
#include <X11/extensions/xf86dga.h>
#include <X11/extensions/xf86vmode.h>
#include <stdio.h>

#define VERSION "0.1"

Display *dpy;
XF86VidModeModeInfo **vm_modelines;
int vm_count;

int current_mode()
{
	int i=0;
	int dotclock;
	XF86VidModeModeLine modeline;

	/* Get the current mode */
	XF86VidModeGetModeLine(dpy,XDefaultScreen(dpy),&dotclock,&modeline);

	for(i=0; i<vm_count; i++)
		if( dotclock             ==  vm_modelines[i]->dotclock    &&
                    modeline.hdisplay    ==  vm_modelines[i]->hdisplay    &&
                    modeline.hsyncstart  ==  vm_modelines[i]->hsyncstart  &&
                    modeline.hsyncend    ==  vm_modelines[i]->hsyncend    &&
                    modeline.htotal      ==  vm_modelines[i]->htotal      &&
                    modeline.vdisplay    ==  vm_modelines[i]->vdisplay    &&
                    modeline.vsyncstart  ==  vm_modelines[i]->vsyncstart  &&
                    modeline.vsyncend    ==  vm_modelines[i]->vsyncend    &&
                    modeline.vtotal      ==  vm_modelines[i]->vtotal      &&
                    modeline.flags       ==  vm_modelines[i]->flags )
			printf("%dx%d@%d\n",
				vm_modelines[i]->hdisplay,
				vm_modelines[i]->vdisplay,
				vm_modelines[i]->dotclock);
	return 0;
}

int list_modes()
{
	int i=0;

	for(i=0; i<vm_count; i++)
		printf("%dx%d@%d\n",
			vm_modelines[i]->hdisplay,
			vm_modelines[i]->vdisplay,
			vm_modelines[i]->dotclock);
	return 0;
}

int set_mode(const char * mode)
{
	int x=0;
	int y=0;
	int dc=0;
	int i=0;

	sscanf(mode, "%dx%d@%d", &x, &y, &dc);
	
	for(i=0; i<vm_count; i++)
		if((x==vm_modelines[i]->hdisplay) &&
			(y==vm_modelines[i]->vdisplay) &&
			((dc==vm_modelines[i]->dotclock) || (dc==0)))
		{
			XF86VidModeSwitchToMode(dpy,XDefaultScreen(dpy),vm_modelines[i]);
			XFlush(dpy);
			return 0;
		}

	return 1;
}

void usage(const char * argv0)
{
	printf("chgres version %s\n", VERSION);
	printf("Usage:\n");

	printf("\t%s get\n", argv0);
	printf("\t%s list\n", argv0);
	printf("\t%s set <mode>\n", argv0);
	exit(1);
}

int main(int argc, char * const argv[])
{
	dpy = XOpenDisplay("");

	if(dpy)
	{
		int result = 1;

		XF86VidModeGetAllModeLines(dpy,XDefaultScreen(dpy),&vm_count,&vm_modelines);

		if((argc>3)||(argc<2))
			usage(argv[0]);

		if((argc==2)&&!strcasecmp(argv[1],"get"))
			result = current_mode();
		else
		if((argc==2)&&!strcasecmp(argv[1],"list"))
			result = list_modes();
		else
		if((argc==3)&&!strcasecmp(argv[1],"set"))
			result = set_mode(argv[2]);

		XCloseDisplay(dpy);
		
		if(result)
			usage(argv[0]);
		return result;
	}
	else
		return 1;
}
