diff src/dialogs.c @ 2956:b68c648618a3

[gaim-migrate @ 2969] I Love Rock & Roll.... committer: Tailor Script <tailor@pidgin.im>
author Rob Flynn <gaim@robflynn.com>
date Sun, 17 Feb 2002 18:08:12 +0000
parents 538c58b43eff
children a67cae459b01
line wrap: on
line diff
--- a/src/dialogs.c	Wed Feb 13 15:23:13 2002 +0000
+++ b/src/dialogs.c	Sun Feb 17 18:08:12 2002 +0000
@@ -4209,3 +4209,523 @@
 
 	return 0;
 }
+
+/*------------------------------------------------------------------------*/
+/*  The dialog for setting V-Card info                                    */
+/*------------------------------------------------------------------------*/
+/*
+ * There are actually two "chunks" of code following:  generic "multi-entry dialog"
+ * support and V-Card dialog specific support.
+ *
+ * At first blush, this may seem like an unnecessary duplication of effort given
+ * that a "set dir info" dialog already exists.  However, this is not so because:
+ *
+ *	1. V-Cards can have a lot more data in them than what the current
+ *	   "set dir" dialog supports.
+ *
+ *	2. V-Card data, at least with respect to Jabber, is currently in a
+ *	   state of flux.  As the data and format changes, all that need be
+ *	   changed with the V-Card support I've written is the "template"
+ *	   data.
+ *
+ *	3. The "multi entry dialog" support itself was originally written
+ *	   to support Jabber server user registration (TBD).  A "dynamically
+ *	   configurable" multi-entry dialog is needed for that, as different
+ *	   servers may require different registration information.  It just
+ *	   turned out to be well-suited to adding V-Card setting support, as
+ *	   well :-).
+ *
+ * TBD: Add check-box support to the generic multi-entry dialog support so that
+ *      it can be used to "replace" the "set dir info" support?
+ *
+ *      Multiple-language support.  Currently Not In There.  I think this should
+ *      be easy.  Note that when it's added: if anybody saved their data in
+ *      English, it'll be lost when MLS is added and they'll have to re-enter it.
+ *
+ * More "TBDs" noted in the code.
+ */
+
+
+/*------------------------------------*/
+/* generic multi-entry dialog support */
+/*------------------------------------*/
+
+/*
+ * Print all multi-entry items
+ *
+ * Note: Simply a debug helper
+ */
+void multi_entry_item_print_all(const GSList *list) {
+
+	int cnt = 0;
+
+	/* While there's something to print... */
+	while(list != NULL) {
+		fprintf(stderr, "label %2d: \"%s\"", ++cnt, ((MultiEntryData *) (list->data))->label);
+		if(((MultiEntryData *) (list->data))->text != NULL) {
+			fprintf(stderr, ", text: \"%s\"", ((MultiEntryData *) (list->data))->text);
+		}
+		fputs("\n", stderr);
+		list = list->next;
+	}
+}
+
+/*
+ * Print all multi-text items
+ *
+ * Note: Simply a debug helper
+ */
+void multi_text_item_print_all(const GSList *list) {
+
+	int cnt = 0;
+
+	/* While there's something to print... */
+	while(list != NULL) {
+		fprintf(stderr, "label %2d: \"%s\"", ++cnt, ((MultiTextData *) (list->data))->label);
+		if(((MultiTextData *) (list->data))->text != NULL) {
+			fprintf(stderr, ", text: \"%s\"", ((MultiTextData *) (list->data))->text);
+		}
+		fputs("\n", stderr);
+		list = list->next;
+	}
+}
+
+
+/*
+ * Free all multi-entry item allocs and NULL the list pointer
+ */
+void multi_entry_items_free_all(GSList **list)
+{
+
+	GSList *next = *list;
+	MultiEntryData *data;
+
+	/* While there's something to free() ... */
+	while(next != NULL) {
+		data = (MultiEntryData *) next->data;
+		g_free(data->label);
+		g_free(data->text);
+		g_free(data);
+		next = next->next;
+	}
+	g_slist_free(*list);
+	*list = NULL;
+}
+
+/*
+ * Free all multi-text item allocs and NULL the list pointer
+ */
+void multi_text_items_free_all(GSList **list)
+{
+
+	GSList *next = *list;
+	MultiTextData *data;
+
+	/* While there's something to free() ... */
+	while(next != NULL) {
+		data = (MultiTextData *) next->data;
+		g_free(data->label);
+		g_free(data->text);
+		g_free(data);
+		next = next->next;
+	}
+	g_slist_free(*list);
+	*list = NULL;
+}
+
+/*
+ * See if a MultiEntryData item contains a given label
+ *
+ * See: glib docs for g_slist_compare_custom() for details
+ */
+static gint multi_entry_data_label_compare(gconstpointer data, gconstpointer label)
+{
+	return(strcmp(((MultiEntryData *) (data))->label, (char *) label));
+}
+
+/*
+ * Add a new multi-entry item to list
+ *
+ * If adding to existing list: will search the list for existence of 
+ * "label" and change/create "text" entry if necessary.
+ */
+
+MultiEntryData *multi_entry_list_update(GSList **list, const char *label, const char *text, int add_it)
+{
+	GSList *found;
+	MultiEntryData *data;
+
+	if((found = g_slist_find_custom(*list, label, multi_entry_data_label_compare)) == NULL) {
+		if(add_it) {
+			data = (MultiEntryData *) g_slist_last(*list =
+				g_slist_append(*list, g_malloc(sizeof(MultiEntryData))))->data;
+			data->label = strcpy(g_malloc(strlen(label) +1), label);
+			data->text = NULL;
+			/*
+			 * default to setting "visible" and editable to TRUE - they can be
+			 * overridden later, of course.
+			 */
+			data->visible  = TRUE;
+			data->editable = TRUE;
+		} else {
+			data = NULL;
+		}
+	} else {
+		data = found->data;
+	}
+
+	if(data != NULL && text != NULL && text[0] != '\0') {
+		if(data->text == NULL) {
+			data->text = g_malloc(strlen(text) + 1);
+		} else {
+			data->text = g_realloc(data->text, strlen(text) + 1);
+		}
+		strcpy(data->text, text);
+	}
+
+	return(data);
+}
+
+/*
+ * See if a MultiTextData item contains a given label
+ *
+ * See: glib docs for g_slist_compare_custom() for details
+ */
+static gint multi_text_data_label_compare(gconstpointer data, gconstpointer label)
+{
+	return(strcmp(((MultiTextData *) (data))->label, (char *) label));
+}
+
+/*
+ * Add a new multi-text item to list
+ *
+ * If adding to existing list: will search the list for existence of 
+ * "label" and change/create "text" text if necessary.
+ */
+
+MultiTextData *multi_text_list_update(GSList **list, const char *label, const char *text, int add_it)
+{
+	GSList *found;
+	MultiTextData *data;
+
+	if((found = g_slist_find_custom(*list, label, multi_text_data_label_compare)) == NULL) {
+		if(add_it) {
+			data = (MultiTextData *) g_slist_last(*list =
+				g_slist_append(*list, g_malloc(sizeof(MultiTextData))))->data;
+			data->label = strcpy(g_malloc(strlen(label) +1), label);
+			data->text = NULL;
+		} else {
+			data = NULL;
+		}
+	} else {
+		data = found->data;
+	}
+
+	if(data != NULL && text != NULL && text[0] != '\0') {
+		if(data->text == NULL) {
+			data->text = g_malloc(strlen(text) + 1);
+		} else {
+			data->text = g_realloc(data->text, strlen(text) + 1);
+		}
+		strcpy(data->text, text);
+	}
+
+	return(data);
+}
+
+/*
+ * Free-up the multi-entry item list and the MultiEntryDlg
+ * struct alloc.
+ */
+void multi_entry_free(struct multi_entry_dlg *b)
+{
+	multi_entry_items_free_all(&(b->multi_entry_items));
+	multi_text_items_free_all(&(b->multi_text_items));
+	g_free(b->instructions->text);
+	g_free(b->instructions);
+	g_free(b);
+}
+
+/*
+ * Multi-Entry dialog "destroyed" catcher
+ *
+ * Free-up the multi-entry item list, destroy the dialog widget
+ * and free the MultiEntryDlg struct alloc.
+ *
+ */
+void multi_entry_dialog_destroy(GtkWidget *widget, gpointer  data)
+{
+	MultiEntryDlg *b = data;
+
+	multi_entry_free(b);
+}
+
+/*
+ * Show/Re-show instructions
+ */
+void re_show_multi_entry_instr(MultiInstrData *instructions)
+{
+	if(instructions->label != NULL) {
+		if(instructions->text == NULL) {
+			gtk_widget_hide(instructions->label);
+		} else {
+			gtk_label_set_text(GTK_LABEL (instructions->label), instructions->text);
+			gtk_widget_show(instructions->label);
+		}
+	}
+}
+
+/*
+ * Show/Re-show entry boxes
+ */
+void re_show_multi_entry_entries(GtkWidget **entries_table,
+				 GtkWidget *entries_frame,
+				 GSList *multi_entry_items)
+{
+	GtkWidget *label;
+	GSList *multi_entry;
+	MultiEntryData *med;
+	int rows = 0;
+	int rowNum;
+
+	/* Figure-out number of rows needed for table */
+	rows = g_slist_length(multi_entry_items);
+
+	if(*entries_table != NULL) {
+		gtk_widget_destroy(GTK_WIDGET (*entries_table));
+	}
+	*entries_table = gtk_table_new(rows, 3, FALSE);
+	gtk_container_add(GTK_CONTAINER (entries_frame), *entries_table);
+
+	for(rowNum = 0, multi_entry = multi_entry_items;
+		multi_entry != NULL; ++rowNum, multi_entry = multi_entry->next) {
+
+		med = (MultiEntryData *) multi_entry->data;
+
+		label = gtk_label_new(med->label);
+		gtk_misc_set_alignment(GTK_MISC(label), (gfloat) 1.0, (gfloat) 0.5);
+		gtk_table_attach_defaults(GTK_TABLE (*entries_table), label, 0, 1, rowNum, rowNum +1);
+		gtk_widget_show(label);
+
+		label = gtk_label_new(": ");
+		gtk_misc_set_alignment(GTK_MISC(label), (gfloat) 0.0, (gfloat) 0.5);
+		gtk_table_attach_defaults(GTK_TABLE (*entries_table), label, 1, 2, rowNum, rowNum +1);
+		gtk_widget_show(label);
+
+		med->widget = gtk_entry_new_with_max_length(50);
+		if(med->text != NULL) {
+			gtk_entry_set_text(GTK_ENTRY (med->widget), med->text);
+		}
+		gtk_entry_set_visibility(GTK_ENTRY (med->widget), med->visible);
+		gtk_entry_set_editable(GTK_ENTRY (med->widget), med->editable);
+		gtk_table_attach_defaults(GTK_TABLE (*entries_table),
+			med->widget, 2, 3, rowNum, rowNum +1);
+		gtk_widget_show(med->widget);
+	}
+
+	gtk_widget_show(*entries_table);
+}
+
+/*
+ * Show/Re-show textboxes
+ */
+void re_show_multi_entry_textboxes(GtkWidget **texts_ibox,
+				   GtkWidget *texts_obox,
+				   GSList *multi_text_items)
+{
+	GSList *multi_text;
+	MultiTextData *mtd;
+        GtkWidget *frame;
+	GtkWidget *hbox;
+	GtkWidget *vscrollbar;
+
+	if(*texts_ibox != NULL) {
+		gtk_widget_destroy(GTK_WIDGET (*texts_ibox));
+	}
+	*texts_ibox = gtk_vbox_new(FALSE, 5);
+	gtk_container_add(GTK_CONTAINER (texts_obox), *texts_ibox);
+
+	for(multi_text = multi_text_items; multi_text != NULL; multi_text = multi_text->next) {
+		mtd = (MultiTextData *) multi_text->data;
+		frame = gtk_frame_new(mtd->label);
+		gtk_container_add(GTK_CONTAINER (*texts_ibox), frame);
+		hbox = gtk_hbox_new(FALSE, 0);
+		gtk_container_add(GTK_CONTAINER (frame), hbox);
+		mtd->textbox = gtk_text_new(NULL, NULL);
+		gtk_text_set_editable(GTK_TEXT(mtd->textbox), TRUE);
+		gtk_text_set_word_wrap(GTK_TEXT(mtd->textbox), TRUE);
+		gtk_widget_set_usize(mtd->textbox, 300, 100);
+		gtk_text_insert(GTK_TEXT(mtd->textbox), NULL, NULL, NULL, mtd->text, -1);
+		gtk_box_pack_start(GTK_BOX (hbox), mtd->textbox, FALSE, FALSE, 0);
+		vscrollbar = gtk_vscrollbar_new (GTK_TEXT(mtd->textbox)->vadj);
+		gtk_box_pack_start(GTK_BOX (hbox), vscrollbar, FALSE, FALSE, 0);
+		gtk_widget_show(mtd->textbox);
+		gtk_widget_show (vscrollbar);
+		gtk_widget_show(hbox);
+		gtk_widget_show(frame);
+	}
+
+	gtk_widget_show(*texts_ibox);
+}
+
+/*
+ *  Create and initialize a new Multi-Entry Dialog struct
+ */
+MultiEntryDlg *multi_entry_dialog_new()
+{
+	MultiEntryDlg *b = g_new0(MultiEntryDlg, 1);
+	b->instructions = g_new0(MultiInstrData, 1);
+	b->multi_entry_items = NULL;
+	b->multi_text_items = NULL;
+	return(b);
+}
+
+/*
+ * Instantiate a new multi-entry dialog
+ *
+ * data == pointer to MultiEntryDlg with the following
+ *         initialized:
+ *
+ *           wmclass_name
+ *           wmclass_class
+ *           title
+ *	     user
+ *           multi_entry_items - pointers to MultiEntryData list
+ *	       and MultiTextData list
+ *           instructions (optional)
+ *           ok function pointer
+ *           cancel function pointer (actually used to set
+ *             window destroy signal--cancel asserts destroy)
+ *
+ *         sets the following in the MultiEntryDialog struct:
+ *
+ *           window
+ */
+void show_multi_entry_dialog(gpointer data)
+{
+	GtkWidget *vbox, *hbox;
+	GtkWidget *button;
+	MultiEntryDlg *b = data;
+
+	GAIM_DIALOG(b->window);
+	gtk_window_set_wmclass(GTK_WINDOW(b->window), b->wmclass_name, b->wmclass_class);
+	gtk_window_set_title(GTK_WINDOW (b->window), b->title);
+	/* Clean up if user dismisses window via window manager! */
+	gtk_signal_connect(GTK_OBJECT(b->window), "destroy", GTK_SIGNAL_FUNC(b->cancel), (gpointer) b);
+	gtk_widget_realize(b->window);
+	aol_icon(b->window->window);
+
+	vbox = gtk_vbox_new(FALSE, 5);
+	gtk_container_add(GTK_CONTAINER (b->window), vbox);
+
+	b->instructions->label = gtk_label_new(NULL);
+	gtk_label_set_line_wrap(GTK_LABEL (b->instructions->label), TRUE);
+	gtk_box_pack_start(GTK_BOX (vbox), b->instructions->label, TRUE, TRUE, 5);
+	re_show_multi_entry_instr(b->instructions);
+
+	b->entries_frame = gtk_frame_new(NULL);
+	gtk_box_pack_start(GTK_BOX (vbox), b->entries_frame, TRUE, TRUE, 5);
+	gtk_widget_show(b->entries_frame);
+	b->entries_table = NULL;
+	re_show_multi_entry_entries(&(b->entries_table), b->entries_frame, b->multi_entry_items);
+
+	b->texts_obox = gtk_vbox_new(FALSE, 0);
+	gtk_box_pack_start(GTK_BOX (vbox), b->texts_obox, TRUE, TRUE, 0);
+	gtk_widget_show(b->texts_obox);
+	b->texts_ibox = NULL;
+	re_show_multi_entry_textboxes(&(b->texts_ibox), b->texts_obox, b->multi_text_items);
+
+	hbox = gtk_hbox_new(FALSE, 0);
+	gtk_box_pack_start(GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
+	gtk_widget_show(hbox);
+
+	button = picture_button(b->window, _("Cancel"), cancel_xpm);
+	/* Let "destroy handling" (set above) handle cleanup */
+	gtk_signal_connect_object(GTK_OBJECT (button), "clicked",
+		GTK_SIGNAL_FUNC (gtk_widget_destroy), GTK_OBJECT (b->window));
+	gtk_box_pack_end(GTK_BOX (hbox), button, FALSE, FALSE, 0);
+	gtk_widget_show(button);
+
+	button = picture_button(b->window, _("Save"), save_xpm);
+	gtk_signal_connect(GTK_OBJECT (button), "clicked",
+		GTK_SIGNAL_FUNC (b->ok), (gpointer) b);
+	gtk_box_pack_end(GTK_BOX (hbox), button, FALSE, FALSE, 0);
+	gtk_widget_show(button);
+
+	gtk_widget_show(vbox);
+	gtk_widget_show(b->window);
+}
+
+
+/*------------------------------------*/
+/* V-Card dialog specific support     */
+/*------------------------------------*/
+
+/*
+ * V-Card "set info" dialog "Save" clicked
+ *
+ * Copy data from GTK+ dialogs into GSLists, call protocol-specific
+ * formatter and save the user info data.
+ */
+void set_vcard_dialog_ok_clicked(GtkWidget *widget, gpointer  data)
+{
+	MultiEntryDlg *b = (MultiEntryDlg *) data;
+	struct gaim_connection *gc;
+	gchar *tmp;
+	GSList *list;
+
+	for(list = b->multi_entry_items; list != NULL; list = list->next) {
+		if(((MultiEntryData *) list->data)->text != NULL) {
+			g_free(((MultiEntryData *) list->data)->text);
+		}
+		((MultiEntryData *) list->data)->text =
+			g_strdup(gtk_entry_get_text(GTK_ENTRY(((MultiEntryData *) list->data)->widget)));
+	}
+
+	for(list = b->multi_text_items; list != NULL; list = list->next) {
+		if(((MultiTextData *) list->data)->text != NULL) {
+			g_free(((MultiTextData *) list->data)->text);
+		}
+		((MultiTextData *) list->data)->text =
+			gtk_editable_get_chars((GtkEditable *) (((MultiTextData *) list->data)->textbox),
+				0, -1);
+	}
+
+
+	tmp = b->custom(b);
+
+	/*
+	 * Set the user info and (possibly) send to the server
+	 */
+        if (b->user) {
+                strncpy(b->user->user_info, tmp, sizeof b->user->user_info);
+                gc = b->user->gc;
+
+                save_prefs();
+
+                if (gc)
+                        serv_set_info(gc, b->user->user_info);
+        }
+
+	g_free(tmp);
+
+	/* Let multi-edit dialog window "destroy" event catching handle remaining cleanup */
+	gtk_widget_destroy(GTK_WIDGET (b->window));
+}
+
+/*
+ * Instantiate a v-card dialog
+ */
+void show_set_vcard(MultiEntryDlg *b)
+{
+	b->ok = set_vcard_dialog_ok_clicked;
+	b->cancel = multi_entry_dialog_destroy;
+
+	show_multi_entry_dialog(b);
+}
+
+
+/*------------------------------------------------------------------------*/
+/*  End dialog for setting v-card info                                    */
+/*------------------------------------------------------------------------*/
+