Check dirty var.
[doldaconnect.git] / config / dolconf.c
index 3cec63e..629752f 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  Dolda Connect - Modular multiuser Direct Connect-style client
- *  Copyright (C) 2007 Fredrik Tolf (fredrik@dolda2000.com)
+ *  Copyright (C) 2007 Fredrik Tolf <fredrik@dolda2000.com>
  *  
  *  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
@@ -25,6 +25,7 @@
 #include <signal.h>
 #include <errno.h>
 #include <gtk/gtk.h>
+#include <gdk/gdkkeysyms.h>
 #include <locale.h>
 #include <libintl.h>
 #include <pwd.h>
@@ -52,7 +53,7 @@ struct cfvar {
 char *cfname;
 GtkWindow *rootwnd = NULL;
 GtkListStore *shares;
-int state;
+int state, dirty = 1;
 int ignoreclose = 0;
 
 void astcancel(GtkWidget *widget, gpointer uudata);
@@ -67,8 +68,8 @@ void cb_cfw_mode_act_toggled(GtkWidget *widget, gpointer uudata);
 void cb_cfw_orport_toggled(GtkWidget *widget, gpointer uudata);
 void cb_cfw_oraddr_toggled(GtkWidget *widget, gpointer uudata);
 void cb_cfw_uinet_toggled(GtkWidget *widget, gpointer uudata);
-void cb_cfw_save_clicked(GtkWidget *widget, gpointer uudata);
-void cb_cfw_quit_clicked(GtkWidget *widget, gpointer uudata);
+void cb_cfw_save_activate(GtkWidget *widget, gpointer uudata);
+void cb_cfw_quit_activate(GtkWidget *widget, gpointer uudata);
 void cb_cfw_shareadd_clicked(GtkWidget *widget, gpointer uudata);
 void cb_cfw_sharerem_clicked(GtkWidget *widget, gpointer uudata);
 
@@ -190,8 +191,11 @@ void setcfvar(char *name, const char *val)
     struct cfvar *v;
     
     v = findcfvar(name);
+    if(!strcmp(v->val, val))
+       return;
     free(v->val);
     v->val = sstrdup(val);
+    dirty = 1;
 }
 
 int msgbox(int type, int buttons, char *format, ...)
@@ -353,6 +357,7 @@ int readconfig(void)
     if(val != NULL)
        free(val);
     fclose(cf);
+    dirty = 0;
     return(rv);
 }
 
@@ -403,6 +408,7 @@ void writeconfig(void)
        } while(gtk_tree_model_iter_next(GTK_TREE_MODEL(shares), &iter));
     }
     fclose(cf);
+    dirty = 0;
 }
 
 void fillcfw(void)
@@ -456,11 +462,16 @@ void ast2conf(void)
 void cfw2conf(void)
 {
     struct cfvar *var;
+    const char *val;
     
     for(var = config; var->name != NULL; var++) {
        if(var->cfww != NULL) {
+           val = gtk_entry_get_text(GTK_ENTRY(*(var->cfww)));
+           if(!strcmp(var->val, val))
+               continue;
            free(var->val);
-           var->val = sstrdup(gtk_entry_get_text(GTK_ENTRY(*(var->cfww))));
+           var->val = sstrdup(val);
+           dirty = 1;
        }
     }
     if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(cfw_mode_act))) {
@@ -487,6 +498,23 @@ void cfw2conf(void)
     }
 }
 
+struct cfvar *cfwvalid(void)
+{
+    struct cfvar *cv;
+    
+    for(cv = config; cv->name != NULL; cv++) {
+       if((cv->vld != NULL) && !cv->vld->check(cv->val)) {
+           if(cv->rname) {
+               return(cv);
+           } else {
+               msgbox(GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, _("Internal error (Auto-generated variable %s has an invalid value \"%s\")"), cv->name, cv->val);
+               abort();
+           }
+       }
+    }
+    return(NULL);
+}
+
 void astcancel(GtkWidget *widget, gpointer uudata)
 {
     if(ignoreclose)
@@ -688,34 +716,34 @@ void cb_cfw_uinet_toggled(GtkWidget *widget, gpointer uudata)
     gtk_widget_set_sensitive(GTK_WIDGET(cfw_uibox), gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)));
 }
 
-void cb_cfw_save_clicked(GtkWidget *widget, gpointer uudata)
+void cb_cfw_save_activate(GtkWidget *widget, gpointer uudata)
 {
     struct cfvar *cv;
     
-    for(cv = config; cv->name != NULL; cv++) {
-       if((cv->vld != NULL) && !cv->vld->check(cv->val)) {
-           if(cv->rname) {
-               msgbox(GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, cv->vld->invmsg, cv->rname);
-           } else {
-               msgbox(GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, _("Internal error (Auto-generated variable %s has an invalid value \"%s\")"), cv->name, cv->val);
-           }
-           return;
-       }
+    if((cv = cfwvalid()) != NULL) {
+       msgbox(GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, cv->vld->invmsg, cv->rname);
+       return;
     }
     cfw2conf();
     writeconfig();
 }
 
-void cb_cfw_quit_clicked(GtkWidget *widget, gpointer uudata)
+void cb_cfw_quit_activate(GtkWidget *widget, gpointer uudata)
 {
+    
+    cfw2conf();
+    if(dirty) {
+       if(msgbox(GTK_MESSAGE_QUESTION, GTK_BUTTONS_YES_NO, _("There are unsaved settings. Do you wish to discard the changes and exit anyway?")) == GTK_RESPONSE_NO)
+           return;
+    }
     gtk_main_quit();
     state = -1;
 }
 
 int main(int argc, char **argv)
 {
+    int i, c, ex;
     struct passwd *pwd;
-    int i;
     
     setlocale(LC_ALL, "");
     bindtextdomain(PACKAGE, LOCALEDIR);
@@ -723,6 +751,22 @@ int main(int argc, char **argv)
     prepstatic();
     
     gtk_init(&argc, &argv);
+    state = -1;
+    while((c = getopt(argc, argv, "haw")) != -1) {
+       switch(c) {
+       case 'a':
+           state = 1;
+           break;
+       case 'w':
+           state = 0;
+           break;
+       case 'h':
+       default:
+           fprintf((c == 'h')?stdout:stderr, "usage: dolconf [-haw]\n");
+           exit((c == 'h')?0:1);
+       }
+    }
+    
     create_ast_wnd();
     create_cfw_wnd();
     shares = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_STRING);
@@ -741,19 +785,25 @@ int main(int argc, char **argv)
        exit(1);
     }
     
-    if(access(cfname, F_OK)) {
-       if(msgbox(GTK_MESSAGE_QUESTION, GTK_BUTTONS_YES_NO, _("It appears that you have not run this setup program before. Would you like to run the first-time setup assistant?")) == GTK_RESPONSE_YES) {
-           state = 1;
+    ex = !access(cfname, F_OK);
+    if(state == -1) {
+       if(!ex) {
+           if(msgbox(GTK_MESSAGE_QUESTION, GTK_BUTTONS_YES_NO, _("It appears that you have not run this setup program before. Would you like to run the first-time setup assistant?")) == GTK_RESPONSE_YES)
+               state = 1;
+           else
+               state = 0;
        } else {
            state = 0;
        }
-    } else {
-       state = 0;
+    }
+    
+    if(ex && (state == 0)) {
        if(readconfig() == 1) {
            if(msgbox(GTK_MESSAGE_QUESTION, GTK_BUTTONS_YES_NO, _("The configuration file appears to have been edited outside the control of this program. If you continue using this program, all settings not handled by it will be lost. Do you wish to continue?")) == GTK_RESPONSE_NO)
                exit(1);
        }
     }
+    
     while(state != -1) {
        if(state == 0) {
            gtk_window_set_default_size(GTK_WINDOW(cfw_wnd), 500, 350);