/*
 * Initial main.c file generated by Glade. Edit as required.
 * Glade will not overwrite this file.
 */

/*
  petite remarque sur la gestion de la memoire dans wmccc: on utilise un
  garbage-collector très puissant. Pour le mettre en action, il suffit
  d'appeler exit(0). Side-effect: met fin au programme.
*/

#ifdef HAVE_CONFIG_H
#  include <config.h>
#endif

#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <signal.h>
#include <ctype.h>
#include <unistd.h>
#define GLOBALS_HERE
#define WMCCC_C
#include "wmccc.h"
#include "wmccc_interface.h"
#include "wmccc_support.h"
#include "myprintf.h"

GtkWidget *my_lookup_widget(GtkWidget *widget, const gchar *widget_name_) {
  char *s = strdup(widget_name_), *p;
  GtkWidget *parent, *found_widget;
  for (p = s; *p; ++p) if (*p == '.' || *p == '[' || *p == ']') *p = '_';
  for (;;)
    {
      if (GTK_IS_MENU (widget))
        parent = gtk_menu_get_attach_widget (GTK_MENU (widget));
      else
        parent = widget->parent;
      if (!parent)
        parent = (GtkWidget*) g_object_get_data (G_OBJECT (widget), "GladeParentKey");
      if (parent == NULL)
        break;
      widget = parent;
    }

  found_widget = (GtkWidget*) g_object_get_data (G_OBJECT (widget),
                                                 s);
  free(s);
  return found_widget;
}

GtkWidget *my_lookup_widget_assert(GtkWidget *widget, const gchar *widget_name_) {
  GtkWidget *w = my_lookup_widget(widget, widget_name_); assert(w);
  return w;
}

GdkColor*
irgb_to_gdkcolor(unsigned icol) {
  static GdkColor color;
  color.red   = ((icol & 0xff0000) >> 16) * 256+ 127;
  color.green = ((icol & 0x00ff00) >> 8) * 256 + 127;
  color.blue  = ((icol & 0x0000ff)     ) * 256 + 127;
    
  gdk_colormap_alloc_color( gdk_colormap_get_system(), &color, FALSE, TRUE);
  return &color;
}

unsigned gdkcolor_to_irgb(GdkColor *c) {
  g_assert(c);
  return ((c->red/256) << 16) + ((c->green/256) << 8) + (c->blue/256);
}

GtkWidget *messagebox_dialog(char *widget) {
  static GtkWidget *d = NULL;
  if (!d) { d = create_messagebox_dialog(); g_assert(d); }
  return (widget == NULL) ? d : my_lookup_widget_assert(d, widget); 
}

GtkWidget *new_board_dialog(char *widget) {
  GtkWidget *d = getdlg(DLG_NEW_BOARD);
  return (widget == NULL) ? d : my_lookup_widget_assert(d, widget); 
}

GtkWidget *new_rss_dialog(char *widget) {
  GtkWidget *d = getdlg(DLG_NEW_RSS);
  return (widget == NULL) ? d : my_lookup_widget_assert(d, widget); 
}

GtkWidget *new_pop_dialog(char *widget) {
  GtkWidget *d = getdlg(DLG_NEW_POP);
  return (widget == NULL) ? d : my_lookup_widget_assert(d, widget); 
}

/*GtkWidget *pinnipede_dialog(char *widget) {
  static GtkWidget *d = NULL;
  if (!d) { d = create_pinnipede_dialog(); g_assert(d); }
  return (widget == NULL) ? d : my_lookup_widget_assert(d, widget); 
  }*/

GtkWidget *pinnipede_site_colors_dialog(char *widget) {
  GtkWidget *d = getdlg(DLG_SITE_COLORS);
  return (widget == NULL) ? d : my_lookup_widget_assert(d, widget); 
}

GtkWidget *edit_dialog(char *widget) {
  GtkWidget *d = getdlg(DLG_EDIT_OPTIONS);
  return (widget == NULL) ? d : my_lookup_widget_assert(d, widget); 
}

GtkWidget *change_board_settings_dialog(char *widget) {
  GtkWidget *d = getdlg(DLG_CHANGE_BOARD_SETTINGS);
  return (widget == NULL) ? d : my_lookup_widget_assert(d, widget); 
}

GtkWidget *change_rss_settings_dialog(char *widget) {
  GtkWidget *d = getdlg(DLG_CHANGE_RSS_SETTINGS);
  return (widget == NULL) ? d : my_lookup_widget_assert(d, widget); 
}

GtkWidget *change_pop_settings_dialog(char *widget) {
  GtkWidget *d = getdlg(DLG_CHANGE_POP_SETTINGS);
  return (widget == NULL) ? d : my_lookup_widget_assert(d, widget); 
}

GtkWidget *bronson_wizard(const char *widget) {
  GtkWidget *d = getdlg(DLG_BRONSON_WIZARD);
  return (widget == NULL) ? d : my_lookup_widget_assert(d, widget); 
}

/*GtkWidget *grab_cookie_dialog(char *widget) {
  static GtkWidget *d = NULL;
  if (!d) { d = create_grab_cookie_dialog(); g_assert(d); }
  return (widget == NULL) ? d : my_lookup_widget_assert(d, widget); 
  }*/

GtkWidget *sitelist_dialog(char *widget) {
  GtkWidget *d = getdlg(DLG_SITELIST);
  return (widget == NULL) ? d : my_lookup_widget_assert(d, widget); 
}

void bidouille_prefs_site_name(SitePrefs *sp) {
  int i;
  sp->all_names = g_renew(char *, sp->all_names, MAX(4, sp->nb_names));
  for (i = sp->nb_names; i < 4; i++) sp->all_names[i] = NULL;
  sp->site_name = NULL;
}

int bidouille_prefs_site_names() {
  /* petite bidouille pour les alias de sites et le nom de site */
  int snum;
  for (snum = 0; snum < Prefs->nb_sites; snum++) {
    bidouille_prefs_site_name(Prefs->site[snum]);
  }
  return 0;
}

/* lit out relit les prefs */
int read_prefs() {
  char *err;
  if (Prefs && glob.nb_selected_sites) { 
    quick_message("you should not be able to do that!"); exit(1); 
  }
  if (Prefs) wmcc_prefs_destroy(Prefs);
  Prefs = g_new0(GeneralPrefs, 1);
  wmcc_prefs_set_default(Prefs);

  err = wmcc_prefs_read_options(Prefs, glob.options_file,1);
  if (err || Prefs->nb_sites == 0) {
    if (!err && Prefs->nb_sites == 0) err = "no site..";
    quick_message("error reading %s: %s", glob.options_file, err); return 2;
  }
  bidouille_prefs_site_names();
  return 0;
}

int new_options_from_string(const char *s) {
  FILE *f;
  char *err;
  int old_nb_site = Prefs->nb_sites, i;
  char *congratulations = NULL;
  if (!s || strlen(s) == 0) return -1;
  f = open_wfile(glob.tmp_options_file);
  if (!f) {
    quick_message("could not create temporary file '%s' : %s", glob.tmp_options_file, strerror(errno));
    return -1;
  }
  if (fputs(s,f) == EOF) {
    quick_message("could not create temporary file '%s' : %s", glob.tmp_options_file, strerror(errno));
    return -1;
  }
  fclose(f);
  err = wmcc_prefs_read_options(Prefs, glob.tmp_options_file, 1);
  if (err) {
    g_print("error while parsing preferences: %s\n", err);
    if (read_prefs() != 0) { // on remet celles d'avant
      fprintf(stderr, "ça commence a bien faire.\n"); exit(1); 
    }    
    return 2;
  }
  for (i = old_nb_site; i < Prefs->nb_sites; ++i) {
    congratulations = str_cat_printf(congratulations, "%s%s", Prefs->site[i]->site_name, (i?"":", "));
  }
  quick_message("Congratulations !\nThe options were successfully parsed\n%d sites were added: %s",
                Prefs->nb_sites-old_nb_site,congratulations);
  free(congratulations);
  return 0;
}

/* Function to open a dialog box displaying the message provided. */
void quick_message(gchar *message_fmt, ...) {
  va_list ap;
  char s[1024];
  va_start(ap, message_fmt);
  vsnprintf(s,1024,message_fmt,ap);
  va_end(ap);
  messagebox_dialog("messagebox_label");
  gtk_label_set_text(GTK_LABEL(messagebox_dialog("messagebox_label")), s);
  gtk_dialog_run (GTK_DIALOG(messagebox_dialog(NULL)));
}

GtkWidget *colorselection_dialog() {
  static GtkWidget *d = NULL;
  if (!d) { d = gtk_color_selection_dialog_new("select a color"); g_assert(d); }
  return d;
}

int change_or_create_site_prefs(int sid, SitePrefs *sp0) {
  for (sp0->nb_names = 0; sp0->all_names[sp0->nb_names] && sp0->nb_names < 4; ++sp0->nb_names) /*plop*/ ;
  if (sid == -1 || sid > Prefs->nb_sites-1) {
    sid = Prefs->nb_sites++;
    if (Prefs->nb_sites == MAX_SITES) {
      quick_message("too much sites!");
      return -1;
    }  
    Prefs->site[sid] = g_new0(SitePrefs,1);
    wmcc_site_prefs_set_default(Prefs->site[sid],1);
  }
  wmcc_site_prefs_copy(Prefs->site[sid], sp0);  
  bidouille_prefs_site_name(Prefs->site[sid]);
  //printf("created new site, name = %s %s\n", sp0->all_names[0], Prefs->site[sid]->all_names[0]);
  return 0;
}

void colorize_grab_cookie_dialog(GtkWidget *view) {
  GtkTextIter start, end;
  GtkTextBuffer *buffer;
  static GtkTextTag *tags[4] = { NULL, };
  char *txt; // utf8 :/
  int lcount;
  buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW (view)); g_assert(buffer);
  //if (tags[1] == 0) {
    tags[0] = NULL;
    tags[1] = gtk_text_buffer_create_tag(buffer, "cookiefile",
                                         "foreground", "#804000", NULL);
    tags[2] = gtk_text_buffer_create_tag(buffer, "cookieok",
                                         "foreground", "#008000", "weight", PANGO_WEIGHT_BOLD, NULL);
    tags[3] = gtk_text_buffer_create_tag(buffer, "cookiedead",
                                         "foreground", "#808080", NULL);
    //}
  lcount = 0;
  for (lcount = 0; lcount < gtk_text_buffer_get_line_count(buffer); ++lcount) {
    char *p; int state, i0, i1;
    gtk_text_buffer_get_iter_at_line(buffer, &start, lcount);
    gtk_text_buffer_get_iter_at_line(buffer, &end, lcount+1);
    txt = gtk_text_buffer_get_slice(buffer, &start, &end, TRUE);
    if (str_startswith(txt, "Search")) {
      for (p=txt; *p; ++p) *p = 1;
    } else {
      char *p = strchr(txt,'=');
      while (p && p > txt && !isspace(*p)) --p;
      
      if (p) {
        char *q = p+1;
        int exp = 0;
        for (p=q; p && !isspace(*p); ++p) /*plop*/;
        sscanf(p, " %*s %*s %d", &exp);
        for (p=q; p && !isspace(*p); ++p) *p = (exp < 0) ? 3 : 2;
      }
    }
    int col;
    for (col = 0, state = 0, i0 = 0; col <= (int)strlen(txt); ++col) { /* on prend le 0 */
      int next_state = (txt[col] >= 1 && txt[col] <= 3) ? txt[col] : 0;
      p = txt + col;
      if (next_state != state) {
        if (state) {
          i1 = p-txt;
          gtk_text_buffer_get_iter_at_line_index(buffer, &start, lcount, i0);
          gtk_text_buffer_get_iter_at_line_index(buffer, &end, *p == 0 ? lcount+1 : lcount, *p == 0 ? 0 : i1);
          gtk_text_buffer_apply_tag (buffer, tags[state], &start, &end);
        }
        i0 = p-txt;
        state = next_state;
      }
    }
    free(txt);
  } 
}


void grab_cookie_bt_clicked(GtkWidget *bt UNUSED, GtkWidget *user_cookie_widget UNUSED) {  
  char searched[200]; searched[0] = 0;
  FILE *f;
  if (glob.nb_selected_sites != 0 && !str_is_empty(glob.selected_sites[0]->backend_url)) {
    SplittedURL su; 
    if (split_url(glob.selected_sites[0]->backend_url, &su) == 0) {
      strcpy(searched, su.host);
    }
  }
  if (strlen(searched) == 0) 
    strcpy(searched,"linuxfr.org");

  char cmd[300];
  char *tmp = shell_quote(searched);    
  snprintf(cmd, sizeof cmd, "wmcoincoin-search-cookies %s", tmp);
  free(tmp);
  myprintf("wmccc is running: %<YEL %s>\n", cmd);
  f = popen(cmd, "r");

  if (f == NULL) { quick_message("uh ? failed to launch %s (%s)", cmd, strerror(errno)); return; }
  GtkWidget *d = create_grab_cookie_dialog();
  GtkWidget *view = lookup_widget(d,"cookies");
  GtkTextBuffer *buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW (view)); g_assert(buffer);
  PangoFontDescription *ttfdesc = pango_font_description_copy(GTK_WIDGET(view)->style->font_desc);
  GtkTextIter start, end;
  gtk_text_buffer_get_bounds(buffer, &start, &end);
  gtk_text_buffer_delete(buffer, &start, &end);

  //gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(view), GTK_WRAP_WORD);
  gtk_text_view_set_left_margin(GTK_TEXT_VIEW(view), 5);
  pango_font_description_set_family (ttfdesc, "monospace");
  pango_font_description_set_weight( ttfdesc, PANGO_WEIGHT_NORMAL);
  pango_font_description_set_size ( ttfdesc, PANGO_SCALE * 8);
  gtk_widget_modify_font(view, ttfdesc);  
  
  char *msg = str_printf("   output of %s ... \n", cmd);
  gtk_text_buffer_insert_at_cursor(buffer, msg, strlen(msg));
  errno = 0;
  do {
    int i;
    unsigned char *l = str_fget_line(f);
    for (i=0; l[i]; ++i) if (l[i] >= 127) l[i] = ' '; 
    gtk_text_buffer_insert_at_cursor(buffer, l, strlen(l));
    gtk_text_buffer_insert_at_cursor(buffer, "\n", 1);    
  } while (!feof(f));
  pclose(f);
  colorize_grab_cookie_dialog(view);

  g_signal_connect_swapped (lookup_widget(d,"close_bt"), "clicked", G_CALLBACK(gtk_widget_destroy), d);
  gtk_widget_show(d);
  //gtk_window_set_transient_for(GTK_WINDOW(grab_cookie_dialog(NULL)), GTK_WINDOW(GTK_WIDGET(bt)->parent));
}

/* ------ widget management ------*/

typedef struct TouchedInfo_ {
  int touched;
  int multivalued;
  GtkWidget *feedback_label;
} TouchedInfo;

gboolean
widget_value_changed_callback(GtkWidget *w, TouchedInfo *ti) {
  g_assert(ti);
  if (ti->touched == -1) return FALSE;
  //printf("ptouiched=%d\n", ti->touched);
  (ti->touched)++;
  if (ti->feedback_label) {
    gtk_widget_modify_fg(ti->feedback_label, GTK_STATE_NORMAL, &glob.modif_widget_color);
    gtk_widget_modify_text(w, GTK_STATE_NORMAL, &glob.modif_widget_color);
    gtk_label_set_text(GTK_LABEL(ti->feedback_label), "[changed]");
    gtk_widget_set_sensitive(ti->feedback_label, TRUE);
  }
  /*gtk_widget_modify_bg(w, GTK_STATE_NORMAL, &glob.modif_widget_color);
  gtk_widget_modify_bg(w, GTK_STATE_SELECTED, &glob.modif_widget_color);
  gtk_button_set_label(GTK_BUTTON(w), "plop!");*/
  return FALSE;
}

/* ---------------- toggle buttons ----------------*/
void multi_set_toggle_button(GtkWidget *w, GtkWidget *feedback_label, int value, int count) {
  TouchedInfo *ti = NULL;
  //printf("multi set toggle : count = %d, val = %d\n",count,value);
  if (count == 0) {
    if (!(ti = g_object_get_data(G_OBJECT(w),"touched"))) {
      ti = g_new0(TouchedInfo,1);
      g_object_set_data(G_OBJECT(w), "touched", ti);
      g_signal_connect ((gpointer) w, "toggled",
                        G_CALLBACK (widget_value_changed_callback),
                        g_object_get_data(G_OBJECT(w), "touched"));
    }
    ti->feedback_label = feedback_label; ti->multivalued = 0;
    ti->touched = -1;
    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w), value);
  } else {
    ti = g_object_get_data(G_OBJECT(w), "touched");
    if (value != gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w)) && !ti->multivalued) 
      ti->multivalued = 1;
    /*    if (!gtk_toggle_button_get_inconsistent(GTK_TOGGLE_BUTTON(w)) &&
        gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w)) != value) {
      gtk_toggle_button_set_inconsistent(GTK_TOGGLE_BUTTON(w), TRUE);
    }
    */
  }
  if (ti->feedback_label) {
    if (ti->multivalued) {
      gtk_widget_modify_fg(ti->feedback_label, GTK_STATE_NORMAL, &glob.modif_widget_color);
    } else gtk_widget_set_style (ti->feedback_label, NULL);
    gtk_label_set_text(GTK_LABEL(ti->feedback_label), ti->multivalued ? "[different values!]" : "[unchanged]");
    gtk_widget_set_sensitive(ti->feedback_label, FALSE);
  }
  ti->touched = 0;
}

int multi_get_toggle_button(GtkWidget *w, gboolean *value) {
  TouchedInfo *ti = g_object_get_data(G_OBJECT(w), "touched"); g_assert(ti);
  if (ti->touched) {
    *value = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w));
  }
  return ti->touched;
}
/* ---------------- option menus ----------------*/
void multi_set_option_menu(GtkWidget *w, int value, int count) {
  TouchedInfo *ti = NULL;

  value--; /* pour backend_flavour qui varie entre 1 et 3 */

  //printf("multi_set_option_menu(%p,%d,%d)\n", w, value, count);
  if (count == 0) {
    if (!(ti = g_object_get_data(G_OBJECT(w),"touched"))) {
      ti = g_new0(TouchedInfo,1);
      g_object_set_data(G_OBJECT(w), "touched", ti);
      g_signal_connect ((gpointer) w, "changed",
                        G_CALLBACK (widget_value_changed_callback),
                        g_object_get_data(G_OBJECT(w), "touched"));
    }
    ti->feedback_label = NULL; ti->multivalued = 0;
    ti->touched = -1;
    gtk_option_menu_set_history(GTK_OPTION_MENU(w), value);
  } else {
    ti = g_object_get_data(G_OBJECT(w), "touched");
    if (value != gtk_option_menu_get_history(GTK_OPTION_MENU(w)) && !ti->multivalued) {
      ti->multivalued = 1;
      gtk_widget_set_sensitive(w, FALSE);
    }
  }
  ti->touched = 0;
}

int multi_get_option_menu(GtkWidget *w, gboolean *value) {
  TouchedInfo *ti = g_object_get_data(G_OBJECT(w), "touched"); g_assert(ti);
  if (ti->touched) {
    *value = gtk_option_menu_get_history(GTK_OPTION_MENU(w))+1;
  }
  return ti->touched;
}

/* ------------------- text entry ---------------------------- */
int check_for_non_ascii(const char *s) {
  unsigned i;
  for (i = 0; i < strlen(s); ++i) 
    if (s[i] < 0 || s[i] == 127) {
      quick_message("Please, please, please !!!\n Avoid non-ASCII characters in wmccc...\n"
                    "Since gtk2 is all-UTF8, and wmcc is all-iso8859 everything is going to break "
                    "if you put accentuated character everywhere... So for now, it is restricted to pure ascii.\nYes, it sux.");
      return -1;
    }
  return 0;
}

char *gtk_entry_get_text_iso8859(GtkEntry *w) {
  /*int new_len;
  const char *s = gtk_entry_get_text(w);
  char *s2 = g_convert(s, -1, "iso-8859-15", "utf8", NULL, &new_len, NULL);
  return s2 == NULL ? "invalid!!" : s2;*/
  const char *s = gtk_entry_get_text(w);
  check_for_non_ascii(s); return (char*)s;
}

void multi_set_text_entry(GtkWidget *w, GtkWidget *feedback_label, char *value, int count) {
  TouchedInfo *ti = NULL;
  //printf("multi set text entry : count = %d, val = %s\n",count,value);
  assert(value);
  if (count == 0) {
    if (!(ti = g_object_get_data(G_OBJECT(w),"touched"))) {
      ti = g_new0(TouchedInfo,1);
      g_object_set_data(G_OBJECT(w), "touched", ti);
      g_signal_connect ((gpointer) w, "changed",
                        G_CALLBACK (widget_value_changed_callback),
                        g_object_get_data(G_OBJECT(w), "touched"));
    }
    ti->feedback_label = feedback_label; ti->multivalued = 0;
    ti->touched = -1;
    gtk_entry_set_text(GTK_ENTRY(w), value);
  } else {
    ti = g_object_get_data(G_OBJECT(w), "touched");
    if (strcmp(value, gtk_entry_get_text_iso8859(GTK_ENTRY(w))) && !ti->multivalued) {
      ti->multivalued = 1;
      if (feedback_label == NULL) gtk_entry_set_text(GTK_ENTRY(w), "[multiple values]");
    }
  }
  if (ti->feedback_label) {
    if (ti->multivalued) {
      gtk_widget_modify_fg(ti->feedback_label, GTK_STATE_NORMAL, &glob.modif_widget_color);
    } else gtk_widget_set_style (ti->feedback_label, NULL);
    gtk_label_set_text(GTK_LABEL(ti->feedback_label), ti->multivalued ? "[different values!]" : "[unchanged]");
    gtk_widget_set_sensitive(ti->feedback_label, FALSE);
  }
  ti->touched = 0;  
}


int multi_get_text_entry(GtkWidget *w, char **pstr) {
  TouchedInfo *ti = g_object_get_data(G_OBJECT(w), "touched"); g_assert(ti);
  if (ti->touched) {
    //printf("multi_get_text_entry: %s <- %s\n", *pstr,  gtk_entry_get_text(GTK_ENTRY(w)));
    ASSIGN_STRING_VAL(*pstr, gtk_entry_get_text_iso8859(GTK_ENTRY(w)));
  }
  return ti->touched;
}
/* ------------------- spin button ---------------------------- */
void multi_set_spin_button(GtkWidget *w, GtkWidget *feedback_label, int value, int count) {
  TouchedInfo *ti = NULL;
  //printf("multi set spin button : count = %d, val = %d\n",count, value);
  if (count == 0) {
    if (!(ti = g_object_get_data(G_OBJECT(w),"touched"))) {
      ti = g_new0(TouchedInfo,1);
      g_object_set_data(G_OBJECT(w), "touched", ti);
      g_signal_connect ((gpointer) w, "changed",
                        G_CALLBACK (widget_value_changed_callback),
                        g_object_get_data(G_OBJECT(w), "touched"));
    }
    ti->feedback_label = feedback_label; ti->multivalued = 0;
    ti->touched = -1;
    gtk_spin_button_set_value(GTK_SPIN_BUTTON(w), (gdouble)value);
  } else {
    ti = g_object_get_data(G_OBJECT(w), "touched");
    if ((value != gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(w))) && !ti->multivalued) {
      ti->multivalued = 1;
    }
  }
  if (ti->feedback_label) {
    if (ti->multivalued) {
      gtk_widget_modify_fg(ti->feedback_label, GTK_STATE_NORMAL, &glob.modif_widget_color);
    } else gtk_widget_set_style (ti->feedback_label, NULL);
    gtk_label_set_text(GTK_LABEL(ti->feedback_label), ti->multivalued ? "[different values!]" : "[unchanged]");
    gtk_widget_set_sensitive(ti->feedback_label, FALSE);
  }
  ti->touched = 0;
}

int multi_get_spin_button(GtkWidget *w, int *pvalue) {
  TouchedInfo *ti = g_object_get_data(G_OBJECT(w), "touched"); g_assert(ti);
  if (ti->touched) {
    *pvalue = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(w));
  }
  return ti->touched;
}
/* ------------------- color button -------------------------- */

void color_button_update_color(GtkWidget *w, GdkColor *c, int value_store) {
  if (value_store) g_object_set_data(G_OBJECT(w), "value", GINT_TO_POINTER(gdkcolor_to_irgb(c)));
  gtk_widget_modify_bg(w, GTK_STATE_PRELIGHT, c);
  gtk_widget_modify_bg(w, GTK_STATE_NORMAL, c);
}

void color_button_clicked_callback(GtkWidget *w, TouchedInfo *ti) {
  GdkColor c;
  
  GtkWidget *colorsel = GTK_COLOR_SELECTION_DIALOG(colorselection_dialog())->colorsel;
  
  gtk_color_selection_set_current_color(GTK_COLOR_SELECTION(colorsel), 
                                        irgb_to_gdkcolor(GPOINTER_TO_INT(g_object_get_data(G_OBJECT(w), "value"))));
  gtk_color_selection_set_has_palette(GTK_COLOR_SELECTION(colorsel), TRUE);
  int rep = gtk_dialog_run(GTK_DIALOG(colorselection_dialog()));

  gtk_color_selection_get_current_color(GTK_COLOR_SELECTION(colorsel), &c);
  gtk_widget_hide(GTK_WIDGET(colorselection_dialog()));
  
  if (rep == GTK_RESPONSE_OK) {
    //printf("colorselection_dialog returned %d %d/%d/%d\n", rep, c.red, c.green, c.blue);
    color_button_update_color(w,&c,1);
    widget_value_changed_callback(w,ti);
  }
}

void multi_set_color_button(GtkWidget *w, unsigned value, int count) {
  TouchedInfo *ti = NULL;
  //printf("multi set color button : count = %d, val = %d\n",count,value);
  if (count == 0) {
    if (!(ti = g_object_get_data(G_OBJECT(w),"touched"))) {
      ti = g_new0(TouchedInfo,1);
      g_object_set_data(G_OBJECT(w), "touched", ti);
      g_signal_connect ((gpointer) w, "clicked",
                        G_CALLBACK (color_button_clicked_callback),
                        g_object_get_data(G_OBJECT(w), "touched"));
    }
    ti->feedback_label = GTK_BIN(w)->child; ti->multivalued = 0;
    ti->touched = -1;
    //printf("bgcolor : %06x\n", value);
    //gtk_widget_modify_text(ti->feedback_label, GTK_STATE_NORMAL, irgb_to_gdkcolor(value));
    color_button_update_color(w, irgb_to_gdkcolor(value), 1);
  } else {
    ti = g_object_get_data(G_OBJECT(w), "touched");
    if (value != (unsigned)GPOINTER_TO_INT(g_object_get_data(G_OBJECT(w), "value")) && !ti->multivalued) {
      gtk_widget_set_style (ti->feedback_label, NULL);
      ti->multivalued = 1;
    }
  }
  if (ti->multivalued) {
    //gtk_widget_set_style(w, NULL); // marche pô 
    color_button_update_color(w, irgb_to_gdkcolor(0x808080), 0);
  }
  gtk_label_set_text(GTK_LABEL(ti->feedback_label), ti->multivalued ? "[*val!]" : "       ");
  ti->touched = 0;
}

int multi_get_color_button(GtkWidget *w, unsigned *value) {
  TouchedInfo *ti = g_object_get_data(G_OBJECT(w), "touched"); g_assert(ti);
  if (ti->touched) {
    *value =  GPOINTER_TO_INT(g_object_get_data(G_OBJECT(w), "value"));
    //printf("multi_get_color_button got %06x, stored in %p\n", *value, value);
  }
  return ti->touched;
}


int validate_cookies(const char *cookies, SitePrefs *sp) { 
  ASSIGN_STRING_VAL(sp->user_cookie, cookies); return 0; 
}
int validate_post_url(const char *url, SitePrefs *sp) { 
  SplittedURL su;
  if (split_url(url, &su)) {
    quick_message("malformed post url");
    return -1;
  } else {
    ASSIGN_STRING_VAL(sp->post_url, url);
    return 0;
  }
}
int validate_backend_url(const char *url, SitePrefs *sp) {
  SplittedURL su;
  if (split_url(url, &su)) {
    quick_message("malformed backend url");
    return -1;
  } else {
    ASSIGN_STRING_VAL(sp->backend_url, url);
    return 0;
  }
}
int validate_post_template(const char *url, SitePrefs *sp) { 
  ASSIGN_STRING_VAL(sp->post_template, url); 
  return 0; 
}
    

int validate_site_name(const char *s, SitePrefs *sp, int check_new_site) {
  if (str_is_empty(s)) { quick_message("Empty site name"); return -1; }
  if (check_for_non_ascii(s)) return -1;
  if (check_new_site) {
    char *s2 = strdup(s); str_trim(s2);
    int i;
    for (i=0; i < Prefs->nb_sites; ++i) {
      int j;
      assert(Prefs->site[i]);
      for (j=0; j < Prefs->site[i]->nb_names; ++j)
        if (strcasecmp(Prefs->site[i]->all_names[j], s) == 0) {
          printf("oups\n");
          quick_message("there is already a site called %s", s); return -1;
        }
    }
    free(s2);
  }
  if (sp->all_names == NULL) { sp->all_names = g_new0(char*,4); }
  if (s != sp->all_names[0]) ASSIGN_STRING_VAL(sp->all_names[0], s);
  return 0;
}

int pfc_toggle_button(GtkWidget *win, const char *widget_name, int *pvalue, int index, int finalize) {
  GtkWidget *w, *w_fb;
  if ((w=my_lookup_widget(win, widget_name))) {
    char *name_fb = str_printf("%s_fb", widget_name);
    //printf("dialog[%s] F=%d, V=%d (toggle button)\n", widget_name, finalize, *pvalue);
    w_fb = my_lookup_widget(win, name_fb);
    FREE_STRING(name_fb);
    if (finalize == 0) {
      multi_set_toggle_button(w, w_fb, *pvalue, index);
    } else multi_get_toggle_button(w, pvalue);
    return 1;
  } else return 0;
}

int pfc_option_menu(GtkWidget *win, const char *widget_name, int *pvalue, int index, int finalize) {
  GtkWidget *w;
  if ((w=my_lookup_widget(win, widget_name))) {
    if (finalize == 0) {
      multi_set_option_menu(w, *pvalue, index);
    } else multi_get_option_menu(w, pvalue);
    return 1;
  } else return 0;
}

int pfc_color_button(GtkWidget *win, const char *widget_name, unsigned *value, int index, int finalize) {
  GtkWidget *w;
  if ((w=my_lookup_widget(win, widget_name))) {
    if (finalize == 0) {
      multi_set_color_button(w, *value, index);
    } else multi_get_color_button(w, value);
    return 1;
  } else return 0;
}

int pfc_text_entry(GtkWidget *win, const char *widget_name, gchar **pstr, int index, int finalize) {
  GtkWidget *w, *w_fb;
  //printf("text entry lookup(%s) = %p\n", widget_name, my_lookup_widget(win, widget_name));
  if ((w=my_lookup_widget(win, widget_name))) {
    char *name_fb = str_printf("%s_fb", widget_name);
    //printf("dialog[%s] F=%d, V=%s (text entry)\n", widget_name, finalize, *pstr);
    w_fb = my_lookup_widget(win, name_fb);
    FREE_STRING(name_fb);
    if (finalize == 0) {
      multi_set_text_entry(w, w_fb, *pstr == NULL ? "" : *pstr, index);
    } else multi_get_text_entry(w, pstr);
    return 1;
  } else return 0;
}

int pfc_spin_button(GtkWidget *win, const char *widget_name, int *pvalue, int index, int finalize) {
  GtkWidget *w, *w_fb;
  if ((w=my_lookup_widget(win, widget_name))) {
    char *name_fb = str_printf("%s_fb", widget_name);
    //printf("dialog[%s] F=%d, V=%d (spin button)\n", widget_name, finalize, *pvalue);
    w_fb = my_lookup_widget(win, name_fb);
    FREE_STRING(name_fb);
    if (finalize == 0) {
      multi_set_spin_button(w, w_fb, *pvalue, index);
    } else multi_get_spin_button(w, pvalue);
    return 1;
  } else return 0;
}

#define PFC_TOGGLE_BUTTON_G(pname) { pfc_toggle_button(dialog, #pname, &Prefs->pname, 0, finalize); }
#define PFC_TOGGLE_BUTTON_S(pname) { int i__; for (i__=0; i__ < glob.nb_selected_sites; ++i__) { \
                                       pfc_toggle_button(dialog, #pname, &glob.selected_sites[i__]->pname, i__, finalize); }}
#define PFC_OPTION_MENU_G(pname) { pfc_option_menu(dialog, #pname, &Prefs->pname, 0, finalize); }
#define PFC_OPTION_MENU_S(pname) { int i__; for (i__=0; i__ < glob.nb_selected_sites; ++i__) { \
                                     pfc_option_menu(dialog, #pname, (int*)&glob.selected_sites[i__]->pname, i__, finalize); }}
#define PFC_COLOR_BUTTON_S(pname) { int i__; for (i__=0; i__ < glob.nb_selected_sites; ++i__) { \
                                       pfc_color_button(dialog, #pname, &glob.selected_sites[i__]->pname, i__, finalize); }}
#define PFC_TEXT_ENTRY_G(pname) { pfc_text_entry(dialog, #pname, &Prefs->pname, 0, finalize); }
#define PFC_TEXT_ENTRY_S(pname) { int i__; for (i__=0; i__ < glob.nb_selected_sites; ++i__) \
                                       pfc_text_entry(dialog, #pname, &glob.selected_sites[i__]->pname, i__, finalize); }
#define PFC_SPIN_BUTTON_G(pname) { pfc_spin_button(dialog, #pname, &Prefs->pname, 0, finalize); }
#define PFC_SPIN_BUTTON_S(pname) { int i__; for (i__=0; i__ < glob.nb_selected_sites; ++i__) \
                                       pfc_spin_button(dialog, #pname, &glob.selected_sites[i__]->pname, i__, finalize); }
static int prepare_or_finalize_conf_dialog_(GtkWidget *dialog, int finalize) {
  PFC_TEXT_ENTRY_S(all_names[0]);
  PFC_TEXT_ENTRY_S(all_names[1]);
  PFC_TEXT_ENTRY_S(all_names[2]);
  PFC_TEXT_ENTRY_S(all_names[3]);
  PFC_TEXT_ENTRY_S(backend_url);
  PFC_OPTION_MENU_S(backend_flavour);
  PFC_TEXT_ENTRY_S(post_url);
  PFC_TEXT_ENTRY_S(post_template);
  PFC_SPIN_BUTTON_S(board_check_delay);
  PFC_TEXT_ENTRY_S(user_cookie);
  PFC_TEXT_ENTRY_S(user_login);
  PFC_TEXT_ENTRY_S(user_agent);
  PFC_TEXT_ENTRY_S(proxy_name);
  PFC_SPIN_BUTTON_S(proxy_port);
  PFC_TEXT_ENTRY_S(proxy_auth_user);
  PFC_TEXT_ENTRY_S(proxy_auth_pass);
  PFC_TOGGLE_BUTTON_S(proxy_nocache);
  PFC_TOGGLE_BUTTON_S(use_if_modified_since);
  PFC_TEXT_ENTRY_G(pp_fn_family);
  PFC_SPIN_BUTTON_G(pp_fn_size);
  PFC_TOGGLE_BUTTON_S(rss_ignore_description);
  PFC_TOGGLE_BUTTON_G(pinnipede_open_on_start);
  PFC_TOGGLE_BUTTON_G(pp_use_classical_tabs);
  PFC_TOGGLE_BUTTON_G(pp_use_colored_tabs);
  PFC_OPTION_MENU_G(pp_tabs_pos);
  PFC_TOGGLE_BUTTON_G(hungry_boitakon);
  PFC_TOGGLE_BUTTON_G(disable_xft_antialiasing);
  PFC_TOGGLE_BUTTON_S(mark_id_gaps);
  PFC_TOGGLE_BUTTON_G(auto_swallow);
  PFC_TOGGLE_BUTTON_G(enable_troll_detector);
  PFC_TOGGLE_BUTTON_G(pp_show_sec_mode);
  PFC_TOGGLE_BUTTON_G(board_enable_hfr_pictures);
  PFC_TOGGLE_BUTTON_G(board_auto_dl_pictures);
  PFC_TEXT_ENTRY_G(board_totoz_server);
  PFC_TOGGLE_BUTTON_G(hunt_opened);
  PFC_TOGGLE_BUTTON_S(hunt_opened_on_site);
  PFC_SPIN_BUTTON_G(hunt_max_duck);
  PFC_TEXT_ENTRY_G(browser_cmd);
  PFC_TEXT_ENTRY_G(browser2_cmd);
  PFC_COLOR_BUTTON_S(pp_bgcolor);
  PFC_COLOR_BUTTON_S(pp_fgcolor.opaque);
  PFC_COLOR_BUTTON_S(pp_trollscore_color.opaque);
  PFC_COLOR_BUTTON_S(pp_login_color.opaque);
  PFC_COLOR_BUTTON_S(pp_tstamp_color.opaque);
  PFC_COLOR_BUTTON_S(pp_useragent_color.opaque);
  PFC_COLOR_BUTTON_S(pp_useragent_color.opaque);
  PFC_COLOR_BUTTON_S(pp_url_color.opaque);
  PFC_COLOR_BUTTON_S(pp_visited_url_color.opaque);
  PFC_COLOR_BUTTON_S(pp_fgcolor.transp);
  PFC_COLOR_BUTTON_S(pp_trollscore_color.transp);
  PFC_COLOR_BUTTON_S(pp_login_color.transp);
  PFC_COLOR_BUTTON_S(pp_tstamp_color.transp);
  PFC_COLOR_BUTTON_S(pp_useragent_color.transp);
  PFC_COLOR_BUTTON_S(pp_useragent_color.transp);
  PFC_COLOR_BUTTON_S(pp_url_color.transp);
  PFC_COLOR_BUTTON_S(pp_visited_url_color.transp);
  if (!finalize && my_lookup_widget(dialog, "user_cookie") && my_lookup_widget(dialog, "grab_cookie_bt")) 
    g_signal_connect ((gpointer) my_lookup_widget(dialog, "grab_cookie_bt"), "clicked",
                      G_CALLBACK (grab_cookie_bt_clicked), my_lookup_widget(dialog, "user_cookie"));
  if (!finalize && my_lookup_widget(dialog, "edit_options_bt")) 
    g_signal_connect ((gpointer) my_lookup_widget(dialog, "edit_options_bt"), "clicked",
                      G_CALLBACK (run_edit_dialog), NULL);
  return 0;
}

int prepare_conf_dialog(GtkWidget *dialog) { return prepare_or_finalize_conf_dialog_(dialog, 0); }

int finalize_conf_dialog(GtkWidget *dialog) { return prepare_or_finalize_conf_dialog_(dialog, 1); }

/* --------------------- new board dialog ------------------------*/

static SitePrefs *new_board_sp = 0;

int prepare_new_board_dialog() {
  if (new_board_sp == 0) new_board_sp = g_new0(SitePrefs, 1);
  wmcc_site_prefs_set_default(new_board_sp,1);
  bidouille_prefs_site_name(new_board_sp);
  ASSIGN_STRING_VAL(new_board_sp->all_names[0], "dlfp");
  glob.nb_selected_sites = 1; glob.selected_sites[0] = new_board_sp;
  prepare_conf_dialog(new_board_dialog(NULL));
  glob.nb_selected_sites = 0;
  return 0;
}

int validate_new_board_dialog()
{
  glob.nb_selected_sites = 1; glob.selected_sites[0] = new_board_sp;
  if (finalize_conf_dialog(new_board_dialog(NULL)) == 0 &&
      validate_site_name(new_board_sp->all_names[0], new_board_sp, TRUE) == 0) {
    change_or_create_site_prefs(-1, new_board_sp);
    return 0;
  } else return 1;
}

/* --------------------- new rss dialog ------------------------*/

static SitePrefs *new_rss_sp = 0;

int prepare_new_rss_dialog() {
  if (new_rss_sp == 0) new_rss_sp = g_new0(SitePrefs, 1);
  SitePrefs *sp = new_rss_sp;
  wmcc_site_prefs_set_default(sp,1); 
  bidouille_prefs_site_name(sp);
  ASSIGN_STRING_VAL(sp->all_names[0], "dlfpnews");
  ASSIGN_STRING_VAL(sp->backend_url, "http://linuxfr.org/backend.rss");
  sp->backend_type = BACKEND_TYPE_RSS; sp->board_check_delay = 600;
  glob.nb_selected_sites = 1; glob.selected_sites[0] = sp;
  prepare_conf_dialog(new_rss_dialog(NULL));
  glob.nb_selected_sites = 0;
  return 0;
}

int validate_new_rss_dialog()
{
  glob.nb_selected_sites = 1; glob.selected_sites[0] = new_rss_sp;
  if (finalize_conf_dialog(new_rss_dialog(NULL)) == 0) {
    change_or_create_site_prefs(-1, new_rss_sp);
    return 0;
  } else return 1;
}

/* --------------------- new pop dialog ------------------------*/

static SitePrefs *new_pop_sp = 0;

int prepare_new_pop_dialog() {
  if (new_pop_sp == 0) new_pop_sp = g_new0(SitePrefs, 1);
  SitePrefs *sp = new_pop_sp;
  wmcc_site_prefs_set_default(sp,1); 
  bidouille_prefs_site_name(sp);
  ASSIGN_STRING_VAL(sp->all_names[0], "altern");
  ASSIGN_STRING_VAL(sp->backend_url, "pop://mail.altern.org");
  new_pop_sp->backend_type = BACKEND_TYPE_POP; sp->board_check_delay = 600;
  glob.nb_selected_sites = 1; glob.selected_sites[0] = sp;
  prepare_conf_dialog(new_pop_dialog(NULL));
  glob.nb_selected_sites = 0;
  return 0;
}

int validate_new_pop_dialog()
{
  glob.nb_selected_sites = 1; glob.selected_sites[0] = new_pop_sp;
  if (finalize_conf_dialog(new_pop_dialog(NULL)) == 0) {
    change_or_create_site_prefs(-1, new_pop_sp);
    return 0;
  } else return 1;
}

/* ---------------- pinnipede_dialog -------------------*/

/*
int run_pinnipede_dialog() {
  if (prepare_conf_dialog(pinnipede_dialog(NULL)) == 0) {
    do {
      int rep = gtk_dialog_run(GTK_DIALOG(pinnipede_dialog(NULL)));
      if (rep != GTK_RESPONSE_OK) break;        
      printf("pinni finished\n");
    } while (finalize_conf_dialog(pinnipede_dialog(NULL)));
  }
  gtk_widget_hide(GTK_WIDGET(pinnipede_dialog(NULL)));
  return 0;
}
*/
/* ------------------ edit dialog -------------------*/
void colorize_edit_dialog() {
  /* should be made utf8 aware .. */
  GtkTextIter start, end;
  GtkWidget *view = edit_dialog("textview");
  GtkTextBuffer *buffer;
  static GtkTextTag *tags[7] = { NULL, };
  char *txt; // utf8 :/
  int lcount;
  buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW (view)); g_assert(buffer);
  //if (tags[1] == 0) {
    tags[0] = NULL;
    tags[1] = gtk_text_buffer_create_tag(buffer, "comment_tag",
                                         "foreground", "#804000", NULL);
    tags[2] = gtk_text_buffer_create_tag(buffer, "string_tag",
                                         "foreground", "#008000", NULL);
    tags[3] = gtk_text_buffer_create_tag(buffer, "kwdot",
                                         "foreground", "#A0A0F0", NULL);
    tags[4] = gtk_text_buffer_create_tag(buffer, "kwlev1",
                                         "foreground", "blue", NULL);
    tags[5] = gtk_text_buffer_create_tag(buffer, "kwlev2",
                                         "foreground", "#0080A0", NULL);
    tags[6] = gtk_text_buffer_create_tag(buffer, "triple_comment",
                                         "foreground", "#301010", "family", "sans", NULL);
    //}
  lcount = 0;
  for (lcount = 0; lcount < gtk_text_buffer_get_line_count(buffer); ++lcount) {
    char *p; int state, i0, i1;
    gtk_text_buffer_get_iter_at_line(buffer, &start, lcount);
    gtk_text_buffer_get_iter_at_line(buffer, &end, lcount+1);
    txt = gtk_text_buffer_get_slice(buffer, &start, &end, TRUE);

    if ((p=strstr(txt, "###"))) {
      for (p+=3; *p; ++p) *p = 6;
    }

    if ((p=strchr(txt, '#'))) {
      for (; *(unsigned char*)p >= ' '; ++p) *p = 1;
    }

    for (p = txt, state = 0; *p; ++p) {
      if (*p == '"') { if (!(p > txt && *(p-1) == '\\')) state = 1-state; }
      if (state == 1 && *p != '"') *p = 2;
    }
    if ((p = strstr(txt, ": "))) {
      char *q = txt;
      state = 4;
      for (q = txt; q <= p; ++q) {
        if (*q == '.' || *q == ':') {
          *q = 3; state = 5;
        } else {
          *q = state;
        }
      }
    }
    int col;
    for (col = 0, state = 0, i0 = 0; col <= (int)strlen(txt); ++col) { /* on prend le 0 */
      int next_state = (txt[col] >= 1 && txt[col] <= 6) ? txt[col] : 0;
      p = txt + col;
      if (next_state != state) {
        if (state) {
          i1 = p-txt;
          gtk_text_buffer_get_iter_at_line_index(buffer, &start, lcount, i0);
          gtk_text_buffer_get_iter_at_line_index(buffer, &end, *p == 0 ? lcount+1 : lcount, *p == 0 ? 0 : i1);
          gtk_text_buffer_apply_tag (buffer, tags[state], &start, &end);
        }
        i0 = p-txt;
        state = next_state;
      }
    }
    free(txt);
  } 
}

GtkTextBuffer *buffer;

int edit_dialog_insert_file(const char *fname, gboolean remove_uncommented) {
  FILE *f;
  if (!(f = fopen(fname, "r"))) {
    quick_message("uh ? cannot find %s", fname); return -1;
  } else {
    char rd[10000];
    int lcnt = 1;
    int got_warning = 0;
    int is_new_line = 1;
    while (fgets(rd, sizeof rd, f)) {
      char *utf8, *p;
      gsize utf8_len;

      if (is_new_line && remove_uncommented && rd[0] != '#' && !str_is_empty(rd)) continue;

      is_new_line = 0;
      for (p = rd; *p; ++p) if (*p == '\n') { is_new_line = 1; lcnt++; }
 
      //utf8 = g_locale_to_utf8(rd, -1, NULL, &utf8_len, NULL);
      utf8 = g_convert(rd, -1, "utf8", "iso-8859-15", NULL, &utf8_len, NULL);
      if (!utf8 || utf8_len == 0) {
        if (!got_warning) {
          quick_message("gtk could not convert your option file to utf8 -- "
                        "check your locales, check for fucking caracters in your file (around line %d)..\n"
                        "I am now going to patiently strip all non ascii caracters. You have been warned.", lcnt);
          got_warning = 1;
        }
        for (p = rd; *p; ++p) { if (*p < 0) *p = ' '; }
        utf8 = g_locale_to_utf8(rd, -1, NULL, &utf8_len, NULL); g_assert(utf8); g_assert(utf8_len);
      }
      //gtk_text_buffer_get_bounds(buffer, &start, &end);
      gtk_text_buffer_insert_at_cursor(buffer, utf8, utf8_len);
      g_free(utf8);
    }
  }
  return 0;
}

int prepare_edit_dialog() {
  GtkTextIter it1, it2, start, end;
  GtkWidget *view = edit_dialog("textview");
  PangoFontDescription *ttfdesc;

  if (!glob.wmcc_pid) gtk_widget_set_sensitive(edit_dialog("apply_bt"),FALSE);

  buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW (view)); g_assert(buffer);
  gtk_text_buffer_get_bounds(buffer, &start, &end);
  gtk_text_buffer_delete(buffer, &start, &end);

  gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(view), GTK_WRAP_WORD);
  gtk_text_view_set_left_margin(GTK_TEXT_VIEW(view), 5);
  ttfdesc = pango_font_description_copy(GTK_WIDGET(view)->style->font_desc);
  pango_font_description_set_family (ttfdesc, "monospace");
  gtk_widget_modify_font(view, ttfdesc);

  if (edit_dialog_insert_file(glob.options_file, FALSE) != 0) return -1;
  gtk_text_buffer_insert_at_cursor(buffer, "\n\n# append your new options here (or edit the values above)\n\n\n", -1);

  //gtk_text_buffer_get_bounds(buffer, &start, &end);
  //GtkTextMark *end_mark =  gtk_text_buffer_create_mark(buffer, "end", &end, 0); g_assert(end_mark);
  int lcount = gtk_text_buffer_get_line_count(buffer);

  gtk_text_buffer_insert_at_cursor(buffer, "# Below you will find the content of the options file shipped with wmcc\n"
                                   "# You will find there some options that wmccc does not show\n"
                                   "# Everything is commented by default, so just uncomment them\n",
                                   -1);
  edit_dialog_insert_file(WMCCDATADIR "/options", TRUE);

  colorize_edit_dialog();

  gtk_text_buffer_get_iter_at_line(buffer, &it1, lcount+3);
  gtk_text_buffer_get_iter_at_line(buffer, &it2, lcount-2);
  GtkTextMark *mark =  gtk_text_buffer_create_mark(buffer, "plop", &it1, 0); g_assert(mark);
  gtk_text_view_scroll_mark_onscreen(GTK_TEXT_VIEW(view), mark);
  gtk_text_buffer_place_cursor(buffer, &it2);
  gtk_text_buffer_set_modified(buffer, FALSE);
  return 0;
}

int edit_options_dialog_commit_changes_to_wmccc() {
  GtkTextIter start, end;
  char *tmpfname = str_printf("%s/.wmcoincoin/wmccc_editted_options", getenv("HOME"));
  gtk_text_buffer_get_bounds(buffer, &start, &end);
  gchar *txt = gtk_text_buffer_get_text(buffer, &start, &end, FALSE);
  FILE *f = fopen(tmpfname, "w");
  if (f == NULL) { quick_message("could not write to '%s'..", tmpfname); return -1; }
  fprintf(f, "#temp file for wmccc\n%s", txt);
  
  fclose(f);
  
  GeneralPrefs *Prefs2 = g_new0(GeneralPrefs, 1);
  wmcc_prefs_set_default(Prefs2);

  char *err = wmcc_prefs_read_options(Prefs2, tmpfname,1);
  if (err == NULL) {
    err = wmcc_prefs_read_options_auth(Prefs2, glob.options_file);
  }
  if (err || Prefs2->nb_sites == 0) {
    if (!err && Prefs2->nb_sites == 0) err = "no site found!!";
    quick_message("You fucked up the prefs!\nThe error is: %s\nPlease correct that and try again", err); 
    wmcc_prefs_destroy(Prefs2);
    return -1;
  }
  wmcc_prefs_destroy(Prefs); glob.nb_selected_sites = 0;
  Prefs = Prefs2;
  bidouille_prefs_site_names();
  free(tmpfname);
  return 0;
}

void run_new_board_dialog() {
  wmccc_run_dialog(DLG_NEW_BOARD,TRUE);
}

void run_new_rss_dialog() {
  wmccc_run_dialog(DLG_NEW_RSS,TRUE);
}

void run_new_pop_dialog() {
  wmccc_run_dialog(DLG_NEW_POP,TRUE);
}

void run_edit_dialog() {
  wmccc_run_dialog(DLG_EDIT_OPTIONS,FALSE);
}

int prepare_bronson_wizard(int isinit UNUSED) {

  return 0;
}
/*
int run_pinnipede_site_colors_dialog() {
  GtkWidget *pp = pinnipede_site_colors_dialog(NULL);
  prepare_conf_dialog(pp);
  int rep = gtk_dialog_run(GTK_DIALOG(pp));
  if (rep == GTK_RESPONSE_APPLY) {
    finalize_conf_dialog(pp);
    apply_prefs();
  }
  gtk_widget_hide(GTK_WIDGET(pp));
  return 0;
}
*/
/*
int run_change_board_settings_dialog() {
  GtkWidget *dlg = change_board_settings_dialog(NULL);
  prepare_or_finalize_conf_dialog(dlg,0);
  assert(lookup_widget(dlg,"all_names_0_"));
  assert(my_lookup_widget(dlg,"all_names[0]"));
  int rep = gtk_dialog_run(GTK_DIALOG(dlg));
  if (rep == GTK_RESPONSE_APPLY) {
    prepare_or_finalize_conf_dialog(dlg,1);
    apply_prefs();
  }
  gtk_widget_hide(GTK_WIDGET(dlg));
  return 0;
}
*/


enum { SITE_ENABLED_COLUMN, SITE_NAME_COLUMN, BACKEND_COLUMN, REFRESH_COLUMN, N_COLUMN };

/*static void
tree_selection_changed_cb (GtkTreeSelection *selection, gpointer data)
{
        GtkTreeIter iter;
        GtkTreeModel *model;
        gchar *author;

        if (gtk_tree_selection_get_selected (selection, &model, &iter))
        {
                gtk_tree_model_get (model, &iter, AUTHOR_COLUMN, &author, -1);

                g_print ("You selected a book by %s\n", author);

                g_free (author);
        }
}
*/

typedef struct SiteListModel {
  GtkListStore *store;
  GtkTreeSelection *select;
} SiteListModel;

int sitelist_iter_to_sid(GtkTreeModel *store, GtkTreeIter *iter) {
  gchar *site_name = NULL;
  int id;
  gtk_tree_model_get(store, iter, SITE_NAME_COLUMN, &site_name, -1);
  id = wmcc_prefs_find_site_id(Prefs, site_name);
  g_free(site_name);
  return id;
}

void sitelist_update_site_order() {
  GtkTreeView *view = GTK_TREE_VIEW(sitelist_dialog("treeview"));
  GtkTreeModel *store = gtk_tree_view_get_model(view);
  GtkTreeIter iter;
  int count, i=0;
  SitePrefs *tmpp[MAX_SITES];
  memset(tmpp, 0, sizeof tmpp);
  if (gtk_tree_model_get_iter_first(store, &iter)) {
    do {
      gchar *site_name;
      count = sitelist_iter_to_sid(store,&iter);
      gtk_tree_model_get(store, &iter, 
                         SITE_NAME_COLUMN, &site_name,
                         -1);
      //printf("site(%02d)=%s %s\n", i, site_name, Prefs->site[count]->all_names[0]);
      tmpp[i] = Prefs->site[count];
      ++i;
    } while (gtk_tree_model_iter_next(store, &iter));
    memcpy(Prefs->site, tmpp, sizeof(SitePrefs*)*MAX_SITES);
  }
}

void sitelist_remove_cb(GtkWidget *button UNUSED, SiteListModel *mdl) {
  GtkTreeIter iter;
  int count, j;
  sitelist_update_site_order();
  if (gtk_tree_model_get_iter_first(GTK_TREE_MODEL(mdl->store), &iter)) {
    do {
      if (gtk_tree_selection_iter_is_selected(mdl->select,&iter) &&
          (count = sitelist_iter_to_sid(GTK_TREE_MODEL(mdl->store), &iter)) != -1) {
        wmcc_site_prefs_destroy(Prefs->site[count]);
        Prefs->site[count] = NULL;
      }
    } while (gtk_tree_model_iter_next(GTK_TREE_MODEL(mdl->store), &iter));
  }
  for (count = 0, j=0; count < Prefs->nb_sites; ++count) {
    if (Prefs->site[count]) {
      Prefs->site[j++] = Prefs->site[count];
    }
  }
  Prefs->nb_sites = j;
  gtk_dialog_response(GTK_DIALOG(sitelist_dialog(NULL)),1); 
}

void sitelist_edit_cb(GtkWidget *button UNUSED, SiteListModel *mdl) {
  GtkTreeIter iter;
  int count, count2 = 0;
  glob.nb_selected_sites = 0;
  if (gtk_tree_model_get_iter_first(GTK_TREE_MODEL(mdl->store), &iter)) {
    do {
      count = sitelist_iter_to_sid(GTK_TREE_MODEL(mdl->store),&iter);
      if (gtk_tree_selection_iter_is_selected(mdl->select,&iter) &&
          (count = sitelist_iter_to_sid(GTK_TREE_MODEL(mdl->store),&iter)) != -1) {
        if (glob.nb_selected_sites && 
            Prefs->site[count]->backend_type != glob.selected_sites[0]->backend_type) {
          quick_message("You are not allowed to edit multiple sites with different backend types");
          return;
        }
        glob.selected_sites[glob.nb_selected_sites++] = Prefs->site[count];
        count2++;
      }
    } while (gtk_tree_model_iter_next(GTK_TREE_MODEL(mdl->store), &iter));
  }
  if (count2) {
    switch (glob.selected_sites[0]->backend_type) {
      case BACKEND_TYPE_BOARD: wmccc_run_dialog(DLG_CHANGE_BOARD_SETTINGS, FALSE); break;
      case BACKEND_TYPE_RSS: wmccc_run_dialog(DLG_CHANGE_RSS_SETTINGS, FALSE); break;
      case BACKEND_TYPE_POP: wmccc_run_dialog(DLG_CHANGE_POP_SETTINGS, FALSE); break;
      default: assert(0);
    }
    /*run_change_board_settings_dialog();
      gtk_dialog_response(GTK_DIALOG(sitelist_dialog(NULL)),1);*/
  } else quick_message("Please concentrate yourself!\nYou forgot to select (at least) one site");
}

void sitelist_colors_cb(GtkWidget *button UNUSED, SiteListModel *mdl) {
  GtkTreeIter iter;
  int count = 0, count2 = 0;
  glob.nb_selected_sites = 0;
  if (gtk_tree_model_get_iter_first(GTK_TREE_MODEL(mdl->store), &iter)) {
    do {
      if (gtk_tree_selection_iter_is_selected(mdl->select,&iter) &&
          (count = sitelist_iter_to_sid(GTK_TREE_MODEL(mdl->store),&iter)) != -1) {
        glob.selected_sites[glob.nb_selected_sites++] = Prefs->site[count];
        count2++;
      }
    } while (gtk_tree_model_iter_next(GTK_TREE_MODEL(mdl->store), &iter));
  }
  if (count2) {
    wmccc_run_dialog(DLG_SITE_COLORS, FALSE);
  } else quick_message("Please concentrate yourself!\nYou forgot to select (at least) one site");
}

void sitelist_proxy_cb(GtkWidget *button UNUSED, SiteListModel *mdl) {
  GtkTreeIter iter;
  int count = 0, count2 = 0;
  glob.nb_selected_sites = 0;
  if (gtk_tree_model_get_iter_first(GTK_TREE_MODEL(mdl->store), &iter)) {
    do {
      if (gtk_tree_selection_iter_is_selected(mdl->select,&iter) &&
          (count = sitelist_iter_to_sid(GTK_TREE_MODEL(mdl->store),&iter)) != -1) {
        glob.selected_sites[glob.nb_selected_sites++] = Prefs->site[count];
        count2++;
      }
    } while (gtk_tree_model_iter_next(GTK_TREE_MODEL(mdl->store), &iter));
  }
  if (count2) {
    wmccc_run_dialog(DLG_PROXY, FALSE);
  } else quick_message("Please concentrate yourself!\nYou forgot to select (at least) one site. \n"
                       "If you may to change proxy settings for all sites, select them all.");
}

void sitelist_new_site_cb(GtkWidget *button UNUSED, SiteListModel *mdl UNUSED) {
  wmccc_run_dialog(DLG_BRONSON_WIZARD,TRUE);
}

void pinnipede_settings_cb(GtkWidget *button UNUSED, SiteListModel *mdl UNUSED) {
  wmccc_run_dialog(DLG_GLOBAL_PINNIPEDE_OPTIONS,FALSE);
}

void sitelist_set_row(GtkListStore *store, GtkTreeIter *iter, SitePrefs *sp) {
  char s[30]; sprintf(s, "%d", sp->board_check_delay);
  gtk_list_store_set(store, iter, 
                     SITE_ENABLED_COLUMN, sp->check_board,
                     SITE_NAME_COLUMN, sp->all_names[0],
                     BACKEND_COLUMN, sp->backend_url, 
                     REFRESH_COLUMN, s, -1);
}

void sitelist_site_name_edited_cb(GtkCellRendererText *cell UNUSED,
                                  gchar               *path_string,
                                  gchar               *new_text,
                                  GtkListStore *store) {
  GtkTreeIter   iter;
  int i;
  gtk_tree_model_get_iter_from_string(GTK_TREE_MODEL(store), &iter, path_string);
  printf("edited %s, new value : %s\n", path_string, new_text);
  i = sitelist_iter_to_sid(GTK_TREE_MODEL(store),&iter);assert(i >= 0);
  if (strcmp(Prefs->site[i]->all_names[0], new_text))
    validate_site_name(new_text, Prefs->site[i], TRUE);
  sitelist_set_row(store, &iter, Prefs->site[i]);
}

void sitelist_site_enabled_toggled_cb(GtkCellRendererToggle *cell UNUSED,
                                      gchar                 *path_string,
                                      GtkListStore *store) {
  GtkTreeIter   iter;
  int i;
  gtk_tree_model_get_iter_from_string(GTK_TREE_MODEL(store), &iter, path_string);
  i = sitelist_iter_to_sid(GTK_TREE_MODEL(store),&iter);assert(i >= 0);
  //i = atoi(path_string);
  Prefs->site[i]->check_board = Prefs->site[i]->check_board ? 0 : 1;
  sitelist_set_row(store, &iter, Prefs->site[i]);
}


int prepare_sitelist_dialog(int isinit) {
  static SiteListModel mdl = {0,0};
  GtkTreeIter   iter;
  GtkCellRenderer *renderer;
  GtkTreeViewColumn *column;
  int i;
  char title[512];
  assert(glob.options_file);
  if (glob.wmcc_pid == 0) {
    snprintf(title, sizeof title, "<span size=\"x-small\">Editing <tt>%s</tt></span>", shorten_path(glob.options_file));
  } else {
    snprintf(title, sizeof title, "<span size=\"x-small\">Editing <tt>%s</tt>, wmcc pid is <b>%d</b>, temporary options stored in <tt>%s</tt></span>", 
             shorten_path(glob.options_file), glob.wmcc_pid, shorten_path(glob.tmp_options_file));
  }
  gtk_label_set_markup(GTK_LABEL(sitelist_dialog("title_lbl")), title);

  if (!glob.wmcc_pid) gtk_widget_set_sensitive(sitelist_dialog("apply_bt"), FALSE);

  if (isinit) gtk_list_store_clear(mdl.store);
  else mdl.store = gtk_list_store_new (N_COLUMN, G_TYPE_BOOLEAN, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
  for (i = 0; i < Prefs->nb_sites; ++i) {
    gtk_list_store_append (mdl.store, &iter);
    sitelist_set_row(mdl.store, &iter, Prefs->site[i]);
  }
  if (!isinit) {
    gtk_tree_view_set_model(GTK_TREE_VIEW(sitelist_dialog("treeview")), GTK_TREE_MODEL(mdl.store));
    renderer = gtk_cell_renderer_toggle_new();  
    g_object_set(renderer, "activatable", TRUE, NULL);
    g_signal_connect(renderer, "toggled", (GCallback) sitelist_site_enabled_toggled_cb, mdl.store);
    column = gtk_tree_view_column_new_with_attributes ("Enabled",
                                                       renderer,
                                                       "active", SITE_ENABLED_COLUMN,
                                                       NULL);
    gtk_tree_view_append_column (GTK_TREE_VIEW (sitelist_dialog("treeview")), column);
    
    renderer = gtk_cell_renderer_text_new ();

    g_object_set(renderer, "editable", TRUE, NULL);
    g_signal_connect(renderer, "edited", (GCallback) sitelist_site_name_edited_cb, mdl.store);

    column = gtk_tree_view_column_new_with_attributes ("Site Name",
                                                       renderer,
                                                       "text", SITE_NAME_COLUMN,
                                                       NULL);
    gtk_tree_view_append_column (GTK_TREE_VIEW (sitelist_dialog("treeview")), column);
    
    renderer = gtk_cell_renderer_text_new ();
    //g_object_set(renderer, "editable", TRUE, NULL); // incompatible with dnd
    column = gtk_tree_view_column_new_with_attributes ("Backend",
                                                       renderer,
                                                       "text", BACKEND_COLUMN,
                                                       NULL);
    gtk_tree_view_append_column (GTK_TREE_VIEW (sitelist_dialog("treeview")), column);

    renderer = gtk_cell_renderer_text_new ();
    column = gtk_tree_view_column_new_with_attributes ("Refresh",
                                                       renderer,
                                                       "text", REFRESH_COLUMN,
                                                       NULL);
    gtk_tree_view_append_column (GTK_TREE_VIEW (sitelist_dialog("treeview")), column);

    mdl.select = gtk_tree_view_get_selection (GTK_TREE_VIEW(sitelist_dialog("treeview")));
    gtk_tree_selection_set_mode(mdl.select, GTK_SELECTION_MULTIPLE);

    gtk_tree_view_set_reorderable(GTK_TREE_VIEW (sitelist_dialog("treeview")), TRUE);
    g_signal_connect(G_OBJECT(sitelist_dialog("remove_bt")), "clicked",
                     G_CALLBACK(sitelist_remove_cb),
                     (gpointer)&mdl);
    g_signal_connect(G_OBJECT(sitelist_dialog("edit_bt")), "clicked",
                     G_CALLBACK(sitelist_edit_cb),
                     (gpointer)&mdl);
    g_signal_connect(G_OBJECT(sitelist_dialog("colors_bt")), "clicked",
                     G_CALLBACK(sitelist_colors_cb),
                     (gpointer)&mdl);
    g_signal_connect(G_OBJECT(sitelist_dialog("proxy_bt")), "clicked",
                     G_CALLBACK(sitelist_proxy_cb),
                     (gpointer)&mdl);
    g_signal_connect(G_OBJECT(sitelist_dialog("new_site_bt")), "clicked",
                     G_CALLBACK(sitelist_new_site_cb),
                     (gpointer)&mdl);
    g_signal_connect(G_OBJECT(sitelist_dialog("pinnipede_settings_bt")), "clicked",
                     G_CALLBACK(pinnipede_settings_cb),
                     (gpointer)&mdl);    
    g_signal_connect(G_OBJECT(sitelist_dialog("edit_options_bt")), "clicked",
                     G_CALLBACK(run_edit_dialog),
                     (gpointer)&mdl);    
  }
  for (i = 0; i < glob.nb_selected_sites; ++i) {
    int j;
    for (j = 0; j < Prefs->nb_sites; ++j) if (Prefs->site[j] == glob.selected_sites[i]) break;
    gtk_tree_selection_select_path(mdl.select, gtk_tree_path_new_from_indices(j, -1));
  }
  return 0;
}

char *abs_options_filename(const char *fname) {
  if (str_startswith(fname, "./") || fname[0] == '/') return strdup(fname);
  else return str_printf("%s/.wmcoincoin/%s", getenv("HOME"),fname);
}

int
main (int argc, char *argv[])
{
  enum { ADD_NEW_BOARD, ADD_NEW_RSS, EDIT_SITE_COLORS, CONFIG_PINNI, ABORT_WMCCC, EDIT_CONFIG, BRONSON_WIZARD, SITELIST } action;
#ifdef ENABLE_NLS_POUR_WMCCC
  bindtextdomain (GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR);
  bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
  textdomain (GETTEXT_PACKAGE);
#endif

  glob.current_site = 0;
  glob.main_win = NULL;
  glob.nb_selected_sites = 0;
  //  gtk_set_locale ();

  umask(077);
  gtk_set_locale ();
  gtk_init (&argc, &argv);

  add_pixmap_directory (WMCCDATADIR);
  add_pixmap_directory ("pixmaps");
  add_pixmap_directory ("xpms");

  glob.modif_widget_color.red = 32000;
  glob.modif_widget_color.green = 000;
  glob.modif_widget_color.blue = 000;
  gdk_colormap_alloc_color(gdk_colormap_get_system(), &glob.modif_widget_color, FALSE, TRUE);

  glob.wmcc_pid = 0;    
  glob.options_file = abs_options_filename("options");
  glob.tmp_options_file = NULL;

  if (argc > 1) {
    if (strcmp(argv[1], "-wmccpid")==0) {
      printf("wmc³ (pid=%d) launched from wmc²\n", (int)getpid()); g_assert(argc >= 5);
      glob.wmcc_pid = atoi(argv[2]);
      glob.options_file = abs_options_filename(argv[3]);
      glob.tmp_options_file = abs_options_filename(argv[4]);
      argc-=4; argv+=4;
    } else {
      glob.wmcc_pid = 0;    
      if (argc < 2 || strcmp(argv[1],"-o")) {
        g_print("missing -o option_file");
        return -1;
      } 
      glob.options_file = abs_options_filename(argv[2]);
      argc -= 2; argv += 2;
    }
  }

  Prefs = NULL;
  read_prefs();

  //action = ABORT_WMCCC;
  action = SITELIST;
  if (argc > 1) {
    if (strcasecmp(argv[1], "-new-board")==0) {
      action = ADD_NEW_BOARD; argc--; argv++;
    } else if (strcasecmp(argv[1], "-new-rss")==0) {
      action = ADD_NEW_RSS; argc--; argv++;
    } else if (strcasecmp(argv[1], "-config-pinni")==0) {
      action = CONFIG_PINNI; argc--; argv++;
    } else if (strcasecmp(argv[1], "-site-colors")==0) {
      action = EDIT_SITE_COLORS; argc--; argv++;
    } else if (strcasecmp(argv[1], "-edit")==0) {
      action = EDIT_CONFIG; argc--; argv++;
    } else if (strcasecmp(argv[1], "-wizard")==0 || strcasecmp(argv[1], "-charles-bronson")==0) {
      action = BRONSON_WIZARD; argc--; argv++;
    } 
  }

  while (argc > 1 && strcasecmp(argv[1], "-site")==0) {
    assert(argc > 2);
    char *sname = argv[2];
    SitePrefs *sp =  wmcc_prefs_find_site(Prefs, sname);
    if (sp) {
      glob.selected_sites[glob.nb_selected_sites++] = sp;
    } else {
      printf("wanring: site %s not found!\n", sname);
    }
    argc -=2; argv += 2;
  }

  switch (action) {
    case ABORT_WMCCC:
    case ADD_NEW_RSS:
      break;
    case ADD_NEW_BOARD: {
      //grab_cookie_bt_clicked(NULL,NULL);
      run_new_board_dialog();
    } break;
    case EDIT_SITE_COLORS: {
      wmccc_run_dialog(DLG_SITE_COLORS, TRUE); //run_pinnipede_site_colors_dialog();
    } break;
    case CONFIG_PINNI: {
      //wmccc_run_dialog(DLG_PINNI_CONFIG,TRUE);
    } break;
    case EDIT_CONFIG: {
      wmccc_run_dialog(DLG_EDIT_OPTIONS,TRUE);
    } break;
    case BRONSON_WIZARD: {
      wmccc_run_dialog(DLG_BRONSON_WIZARD,TRUE);
    } break;
    case SITELIST: {
      wmccc_run_dialog(DLG_SITELIST,TRUE);
    }break;
    default: g_assert(0);
  }
  gtk_main();
  return 0;
}

