/* grdesktop - gtk rdesktop frontend
 * Copyright (C) 2002 Thorsten Sauter <tsauter@gmx.net>
 *
 * $Id: rdpparse.c,v 1.15 2004/02/03 10:46:50 tsauter Exp $
 *
 * 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 of the License, 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 "rdpparse.h"


void sig_file_open(GtkWidget *widget, gpointer data) {
	GtkFileSelection *filesel;
	gchar *filename;

	filesel = GTK_FILE_SELECTION(data);
	filename = g_strdup(gtk_file_selection_get_filename(filesel));
	if(filename[strlen(filename)-1] == '/') {
		gnome_error_dialog(_("Please select a valid rdp file!"));
		sig_loadbtn(widget, NULL);
		return;
	}

	parse_file(filename);
	return;
}

void sig_file_save(GtkWidget *widget, gpointer data) {
	GtkFileSelection *filesel;
	FILE *file;
	gchar *filename;

	filesel = GTK_FILE_SELECTION(data);
	filename = g_strdup(gtk_file_selection_get_filename(filesel));
	if(filename[strlen(filename)-1] == '/') {
		gnome_error_dialog(_("Please select a valid rdp file!"));
		sig_savebtn(widget, NULL);
		return;
	}

	if(g_file_test(filename, G_FILE_TEST_EXISTS)) {
		GtkWidget *dlg;
		gint result;

		dlg = gtk_message_dialog_new(GTK_WINDOW(window_main),
			GTK_DIALOG_DESTROY_WITH_PARENT,
			GTK_MESSAGE_QUESTION,
			GTK_BUTTONS_YES_NO,
			_("Really override the already existing file?"));
		result = gtk_dialog_run(GTK_DIALOG(dlg));
		gtk_widget_destroy(dlg);

		if(result != GTK_RESPONSE_YES) {
#ifdef _DEBUG_
			g_warning("Don't override existing file: %s", filename);
#endif
			return;
		}
	}

	file = fopen(filename, "w");
	if(file == NULL) {
		gnome_error_dialog(g_strdup_printf(_("Unable to save rdp-file: %s"),
			filename));
		return;
	}

#ifdef _DEBUG_
	g_warning("Writing rdp-file: %s", filename);
#endif

	if(SHASH("geometry") != NULL) {
		if(!g_strcasecmp(SHASH("geometry"), _("Fullscreen"))) {
			fprintf(file, "screen mode id:i:%d\n", 2);
			fprintf(file, "desktopwidth:i:%d\n", 640);
			fprintf(file, "desktopheight:i:%d\n", 480);
		} else {
			fprintf(file, "screen mode id:i:%d\n", 1);
			fprintf(file, "desktopwidth:i:%s\n",
				ext_geometry(SHASH("geometry"), 'W'));
			fprintf(file, "desktopheight:i:%s\n",
				ext_geometry(SHASH("geometry"), 'H'));
		}
	}

	fprintf(file, "session bpp:i:%s\n",
		ext_colorsize(iSHASH("color")));
	
	if(SHASH("hostname") != NULL) {
		fprintf(file, "full address:s:%s\n", SHASH("hostname"));
	}

	if(SHASH("username") != NULL) {
		fprintf(file, "username:s:%s\n", SHASH("username"));
	}

	if(SHASH("domain") != NULL) {
		fprintf(file, "domain:s:%s\n", SHASH("domain"));
	}

	if(SHASH("program") != NULL) {
		fprintf(file, "alternate shell:s:%s\n", SHASH("program"));
	}

	if(SHASH("ppath") != NULL) {
		fprintf(file, "shell working directory:s:%s\n", SHASH("ppath"));
	}

	if(iSHASH("bitmapupd") == TRUE)
		fprintf(file, "bitmapcachepersistentable:i:%d\n", 0);

	fclose(file);
	return;
}

gint parse_file(gchar *filename) {
	FILE *file;
	char line[MAX_LINE_BUF];
	char tmpbuf[2];
	gboolean unicode;
	gint i, ch;

	if(!g_file_test(filename, G_FILE_TEST_EXISTS|G_FILE_TEST_IS_REGULAR)) {
		gnome_error_dialog(g_strdup_printf(_("Unable to open rdp-file: %s"),
			filename));
		return(1);
	}

	file = fopen(filename, "r");
	if(file == NULL) {
		gnome_error_dialog(g_strdup_printf(_("Unable to open rdp-file: %s"),
			filename));
		return(1);
	}

	/* determe, if we have an unicode file */
	if(fgets(line, MAX_LINE_BUF, file) == NULL) {
		fclose(file);
		g_warning(_("File %s is empty!"), filename);
		return(1);
	}
	unicode = ((line[0] == (char)255) && (line[1] == (char)254));

	rewind(file);
	if(!unicode) {			/* non unicode */
		while(fgets(line, MAX_LINE_BUF, file) != NULL) {
			gchar *item;

			item = (gchar*) g_malloc(sizeof(gchar)*MAX_LINE_BUF);
			if(item == NULL)
				g_error("Unable to allocate memory!");

			parse_line(g_strndup(line, sizeof(char)*(strlen(line)-1)));

			if(item != NULL)
				g_free(item);
		}
	} else {			/* UNICODE */
		ch = -1;
		line[0] = '\0';
		for(i=0; (i < 1000000 && feof(file) == 0); i++) {
			ch = fgetc(file);
			if(ch > 0 && (ch != 255 && ch != 254 && ch != 10)) {
				if(ch == 13) {
					parse_line(line);
					line[0] = '\0';
				} else {
					g_unichar_to_utf8(ch, tmpbuf);
					tmpbuf[1] = '\0';
					strcat(line, tmpbuf);
					memset(tmpbuf, '\0', sizeof(char)*2);
				}
			}
		}
	}

	fclose(file);
	
	fill_dialog();
	return(0);
}

void parse_line(const gchar *line) {
	gchar **items = NULL;

	if(strlen(line) <= 0)
		return;

	items = g_strsplit(line, ":", 3);
	if((items[0] <= (char*)0 ) || (items[2] <=  (char*)0))
		return;

#ifdef _DEBUG_
	g_warning("RDP: line: %s [%s -> %s]", line, items[0], items[2]);
#endif

	if(!g_strcasecmp(items[0], "username"))
		insert_option("username", items[2]);
	else if(!g_strcasecmp(items[0], "domain"))
		insert_option("domain", items[2]);
	else if(!g_strcasecmp(items[0], "alternate shell"))
		insert_option("program", items[2]);
	else if(!g_strcasecmp(items[0], "shell working directory"))
		insert_option("ppath", items[2]);
	else if(!g_strcasecmp(items[0], "full address"))
		insert_option("hostname", items[2]);
	else if(!g_strcasecmp(items[0], "session bpp"))
		insert_option("colorsize", mod_color(items[2]));
	else if(!g_strcasecmp(items[0], "bitmapcachepersistenable"))
		insert_option("bitmapupd", mod_bitmapupd(items[2]));
	else if(!g_strcasecmp(items[0], "desktopwidth"))
		insert_option("geometry",
			mod_geometry(items[2], SHASH("geometry"), 'W'));
	else if(!g_strcasecmp(items[0], "desktopheight"))
		insert_option("geometry",
			mod_geometry(items[2], SHASH("geometry"), 'H'));
	else if(!g_strcasecmp(items[0], "screen mode id"))
		insert_option("fullscreen", mod_fullscreen(items[2]));

	if(items != NULL)
		g_strfreev(items);

	return;
}

void insert_option(const gchar *key, const gchar *value) {
#ifdef _DEBUG_
	g_warning("RDP: old value: %s -> %s", key, SHASH(key));
#endif

	if(SHASH(key) != NULL) {
		g_hash_table_replace(config, (gchar*)key, g_strdup(value));
	} else {
		g_hash_table_insert(config, (gchar*)key, g_strdup(value));
	}

#ifdef _DEBUG_
	g_warning("RDP: new value: %s -> %s", key, SHASH(key));
#endif
}

gchar *mod_color(const gchar *colorstr) {
	switch(atoi(colorstr)) {
		case 8:
			return("0");
		case 15:
			return("1");
		case 16:
			return("2");
		case 24:
			return("3");
		default:
			return("0");
	}

	/* default color 256 */
	return("0");
}

gchar *mod_bitmapupd(const gchar *bitmapstr) {
	if(bitmapstr[0] == '0')
		return("1");
	return("0");
}

gchar *mod_geometry(const gchar *value, const gchar *old, const char typ) {
	gchar **parts = NULL;

	parts = g_strsplit(old, "x", 2);

	if(typ == 'W')
		return(g_strdup_printf("%sx%s", value, parts[1]));
	else
		return(g_strdup_printf("%sx%s", parts[0], value));

	if(parts != NULL)
		g_strfreev(parts);

	return(NULL);
}

gchar *mod_fullscreen(const gchar *value) {
	if(atoi(value) == 2)
		return("1");

	return("0");
}

gchar *ext_geometry(const gchar *value, const char typ) {
	gchar **parts = NULL;

	parts = g_strsplit(value, "x", 2);

	if(typ == 'W')
		return(g_strdup_printf(parts[0]));
	else
		return(g_strdup_printf(parts[1]));

	if(parts != NULL)
		g_strfreev(parts);

	return(NULL);
}

gchar *ext_colorsize(const gint value) {
	switch(value) {
		case 0:
			return("8");
		case 1:
			return("15");
		case 2:
			return("16");
		case 3:
			return("24");
		default:
			return("8");
	}

	return("8");
}

