From: Rob F. <rob...@us...> - 2002-02-17 18:08:15
|
Update of /cvsroot/gaim/gaim/src In directory usw-pr-cvs1:/tmp/cvs-serv1918 Modified Files: buddy_chat.c dialogs.c gaim.h multi.c multi.h prpl.h ui.h util.c Log Message: I Love Rock & Roll.... Index: buddy_chat.c =================================================================== RCS file: /cvsroot/gaim/gaim/src/buddy_chat.c,v retrieving revision 1.140 retrieving revision 1.141 diff -u -d -r1.140 -r1.141 --- buddy_chat.c 20 Dec 2001 09:26:12 -0000 1.140 +++ buddy_chat.c 17 Feb 2002 18:08:12 -0000 1.141 @@ -808,8 +808,30 @@ static void chat_press_info(GtkObject *obj, struct conversation *b) { - if (b->gc) - b->gc->prpl->get_info(b->gc, gtk_object_get_user_data(obj)); + if (b->gc) { + /* + * If there are special needs for getting info on users in + * buddy chat "rooms"... + */ + if(b->gc->prpl->get_cb_info != NULL) { + b->gc->prpl->get_cb_info(b->gc, b->id, gtk_object_get_user_data(obj)); + } else { + b->gc->prpl->get_info(b->gc, gtk_object_get_user_data(obj)); + } + } +} + + +static void chat_press_away(GtkObject *obj, struct conversation *b) +{ + if (b->gc) { + /* + * May want to expand this to work similarly to chat_press_info? + */ + if(b->gc->prpl->get_cb_away != NULL) { + b->gc->prpl->get_cb_away(b->gc, b->id, gtk_object_get_user_data(obj)); + } + } } static gint right_click_chat(GtkObject *obj, GdkEventButton *event, struct conversation *b) @@ -849,34 +871,53 @@ gtk_widget_show(button); } + if (b->gc && b->gc->prpl->get_cb_away) { + button = gtk_menu_item_new_with_label(_("Get Away Msg")); + gtk_signal_connect(GTK_OBJECT(button), "activate", + GTK_SIGNAL_FUNC(chat_press_away), b); + gtk_object_set_user_data(GTK_OBJECT(button), gtk_object_get_user_data(obj)); + gtk_menu_append(GTK_MENU(menu), button); + gtk_widget_show(button); + } + gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, event->button, event->time); return TRUE; } return TRUE; } +/* + * Common code for adding a chat buddy to the list + */ +static void add_chat_buddy_common(struct conversation *b, char *name, int pos) +{ + char tmp[BUF_LONG]; + GtkWidget *list_item; + + if (ignored(b, name)) { + g_snprintf(tmp, sizeof(tmp), "X %s", name); + list_item = gtk_list_item_new_with_label(tmp); + } else + list_item = gtk_list_item_new_with_label(name); + + gtk_object_set_user_data(GTK_OBJECT(list_item), name); + gtk_signal_connect(GTK_OBJECT(list_item), "button_press_event", + GTK_SIGNAL_FUNC(right_click_chat), b); + gtk_list_insert_items(GTK_LIST(b->list), g_list_append(NULL, list_item), pos); + gtk_widget_show(list_item); +} + void add_chat_buddy(struct conversation *b, char *buddy) { char *name = g_strdup(buddy); char tmp[BUF_LONG]; - GtkWidget *list_item; int pos; plugin_event(event_chat_buddy_join, b->gc, (void *)b->id, name, 0); b->in_room = g_list_insert_sorted(b->in_room, name, insertname); pos = g_list_index(b->in_room, name); - if (ignored(b, buddy)) { - g_snprintf(tmp, sizeof(tmp), "X %s", name); - list_item = gtk_list_item_new_with_label(tmp); - } else - list_item = gtk_list_item_new_with_label(name); - - gtk_object_set_user_data(GTK_OBJECT(list_item), name); - gtk_signal_connect(GTK_OBJECT(list_item), "button_press_event", - GTK_SIGNAL_FUNC(right_click_chat), b); - gtk_list_insert_items(GTK_LIST(b->list), g_list_append(NULL, list_item), pos); - gtk_widget_show(list_item); + add_chat_buddy_common(b, name, pos); g_snprintf(tmp, sizeof(tmp), _("%d %s in room"), g_list_length(b->in_room), g_list_length(b->in_room) == 1 ? "person" : "people"); @@ -898,7 +939,6 @@ GList *items = GTK_LIST(b->list)->children; char *name = g_strdup(new); - GtkWidget *list_item; char *ign; int pos; @@ -940,8 +980,6 @@ if (!ignored(b, new)) b->ignored = g_list_append(b->ignored, g_strdup(name)); - g_snprintf(tmp, sizeof(tmp), "X %s", name); - list_item = gtk_list_item_new_with_label(tmp); } else { if ((ign = ignored(b, new)) != NULL) { /* if they weren't ignored and change to someone who is ignored, @@ -950,14 +988,9 @@ g_free(ign); b->ignored = g_list_remove(b->ignored, ign); } - list_item = gtk_list_item_new_with_label(name); } - gtk_object_set_user_data(GTK_OBJECT(list_item), name); - gtk_signal_connect(GTK_OBJECT(list_item), "button_press_event", - GTK_SIGNAL_FUNC(right_click_chat), b); - gtk_list_insert_items(GTK_LIST(b->list), g_list_append(NULL, list_item), pos); - gtk_widget_show(list_item); + add_chat_buddy_common(b, name, pos); if (chat_options & OPT_CHAT_LOGON) { g_snprintf(tmp, sizeof(tmp), _("%s is now known as %s"), old, new); @@ -1050,8 +1083,6 @@ GList *i; char *ign; int pos; - GtkWidget *list_item; - char tmp[80]; i = GTK_LIST(b->list)->selection; if (i) { @@ -1067,19 +1098,12 @@ if (ign) { g_free(ign); b->ignored = g_list_remove(b->ignored, ign); - g_snprintf(tmp, sizeof tmp, "%s", name); } else { b->ignored = g_list_append(b->ignored, g_strdup(name)); - g_snprintf(tmp, sizeof tmp, "X %s", name); } - list_item = gtk_list_item_new_with_label(tmp); - gtk_object_set_user_data(GTK_OBJECT(list_item), name); - gtk_list_insert_items(GTK_LIST(b->list), g_list_append(NULL, list_item), pos); gtk_widget_destroy(i->data); - gtk_widget_show(list_item); - gtk_signal_connect(GTK_OBJECT(list_item), "button_press_event", - GTK_SIGNAL_FUNC(right_click_chat), b); + add_chat_buddy_common(b, name, pos); } void show_new_buddy_chat(struct conversation *b) @@ -1476,21 +1500,8 @@ while (r) { char *name = r->data; - GtkWidget *list_item; - char tmp[BUF_LONG]; - - if (ignored(c, name)) { - g_snprintf(tmp, sizeof(tmp), "X %s", name); - list_item = gtk_list_item_new_with_label(tmp); - } else - list_item = gtk_list_item_new_with_label(name); - gtk_object_set_user_data(GTK_OBJECT(list_item), name); - gtk_signal_connect(GTK_OBJECT(list_item), "button_press_event", - GTK_SIGNAL_FUNC(right_click_chat), c); - gtk_list_insert_items(GTK_LIST(c->list), - g_list_append(NULL, list_item), pos); - gtk_widget_show(list_item); + add_chat_buddy_common(c, name, pos); r = r->next; pos++; @@ -1522,21 +1533,8 @@ while (r) { char *name = r->data; - GtkWidget *list_item; - char tmp[BUF_LONG]; - - if (ignored(c, name)) { - g_snprintf(tmp, sizeof(tmp), "X %s", name); - list_item = gtk_list_item_new_with_label(tmp); - } else - list_item = gtk_list_item_new_with_label(name); - gtk_object_set_user_data(GTK_OBJECT(list_item), name); - gtk_signal_connect(GTK_OBJECT(list_item), "button_press_event", - GTK_SIGNAL_FUNC(right_click_chat), c); - gtk_list_insert_items(GTK_LIST(c->list), - g_list_append(NULL, list_item), pos); - gtk_widget_show(list_item); + add_chat_buddy_common(c, name, pos); r = r->next; pos++; Index: dialogs.c =================================================================== RCS file: /cvsroot/gaim/gaim/src/dialogs.c,v retrieving revision 1.297 retrieving revision 1.298 diff -u -d -r1.297 -r1.298 --- dialogs.c 21 Dec 2001 10:23:04 -0000 1.297 +++ dialogs.c 17 Feb 2002 18:08:12 -0000 1.298 @@ -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 */ +/*------------------------------------------------------------------------*/ + Index: gaim.h =================================================================== RCS file: /cvsroot/gaim/gaim/src/gaim.h,v retrieving revision 1.304 retrieving revision 1.305 diff -u -d -r1.304 -r1.305 --- gaim.h 21 Dec 2001 10:23:04 -0000 1.304 +++ gaim.h 17 Feb 2002 18:08:12 -0000 1.305 @@ -411,6 +411,7 @@ extern char *gaim_user_dir(); extern void strncpy_nohtml(gchar *, const gchar *, size_t); extern void strncpy_withhtml(gchar *, const gchar *, size_t); +extern gchar *strdup_withhtml(const gchar *); extern void away_on_login(char *); extern void system_log(enum log_event, struct gaim_connection *, struct buddy *, int); extern unsigned char *utf8_to_str(unsigned char *); @@ -418,5 +419,84 @@ extern char *add_cr(char *); extern void strip_linefeed(char *); extern time_t get_time(int, int, int, int, int, int); + +/*------------------------------------------------------------------------*/ +/* Multi-Entry dialog and vCard dialog support */ +/*------------------------------------------------------------------------*/ + +/* + * Struct for "instructions" dialog data + */ +typedef struct multi_instr_dlg { + GtkWidget *label; /* dialog instructions widget */ + gchar *text; /* dialog instructions */ +} MultiInstrData; + +/* + * Struct for multiple-entry dialog data + */ +typedef struct multi_entry_data { + GtkWidget *widget; /* entry widget object */ + char *label; /* label text pointer */ + char *text; /* entry text pointer */ + int visible; /* should entry field be "visible?" */ + int editable; /* should entry field be editable? */ +} MultiEntryData; + +/* + * Struct for multiple-textbox dialog data + */ +typedef struct multi_text_data { + char *label; /* frame label */ + GtkWidget *textbox; /* text entry widget object */ + char *text; /* textbox text pointer */ +} MultiTextData; + +/* + * Struct to create a multi-entry dialog + */ +typedef struct multi_entry_dlg { + GtkWidget *window; /* dialog main window */ + gchar *wmclass_name; /* window name */ + gchar *wmclass_class; /* window class */ + char *title; /* window title */ + + struct aim_user *user; /* user info - needed for most everything */ + + MultiInstrData *instructions; /* instructions (what else?) */ + + GtkWidget *entries_table; /* table widget containing m-e lables & entries */ + GtkWidget *entries_frame; /* frame widget containing the table widget */ + GSList *multi_entry_items; /* entry dialogs parameters */ + + GtkWidget *texts_ibox; /* inner vbox containing multi-text frames */ + GtkWidget *texts_obox; /* outer vbox containing multi-text frames */ + GSList *multi_text_items; /* text dialogs parameters */ + + void * (*custom)(struct multi_entry_dlg *); /* Custom function that may be used by */ + /* multi-entry dialog "wrapper" functions */ + /* (Not used by multi-entry dialog routines) */ + + void (*ok)(GtkWidget *, gpointer); /* "Save/OK" action */ + void (*cancel)(GtkWidget *, gpointer); /* "Cancel" action */ +} MultiEntryDlg; + +extern MultiTextData *multi_text_list_update(GSList **, const char *, const char *, int); +extern void multi_text_items_free_all(GSList **); +extern MultiEntryData *multi_entry_list_update(GSList **, const char *, const char *, int); +extern void multi_entry_items_free_all(GSList **); + +extern void re_show_multi_entry_instr(MultiInstrData *); +extern void re_show_multi_entry_entries(GtkWidget **, GtkWidget *, GSList *); +extern void re_show_multi_entry_textboxes(GtkWidget **, GtkWidget *, GSList *); + +extern MultiEntryDlg *multi_entry_dialog_new(void); +extern void show_multi_entry_dialog(gpointer); + +extern void show_set_vcard(MultiEntryDlg *); + +/*------------------------------------------------------------------------*/ +/* End Multi-Entry dialog and vCard dialog support */ +/*------------------------------------------------------------------------*/ #endif /* _GAIM_H_ */ Index: multi.c =================================================================== RCS file: /cvsroot/gaim/gaim/src/multi.c,v retrieving revision 1.106 retrieving revision 1.107 diff -u -d -r1.106 -r1.107 --- multi.c 15 Nov 2001 22:47:03 -0000 1.106 +++ multi.c 17 Feb 2002 18:08:12 -0000 1.107 @@ -238,6 +238,7 @@ const char *txt; int i; struct aim_user *a; + struct prpl *p; if (!u->user) { txt = gtk_entry_get_text(GTK_ENTRY(u->name)); @@ -278,9 +279,24 @@ gtk_widget_destroy(u->icondlg); u->icondlg = NULL; - gtk_widget_destroy(u->mod); + /* + * See if user registration is supported/required + */ + if((p = find_prpl(u->protocol)) == NULL) { + /* TBD: error dialog here! (This should never happen, you know...) */ + fprintf(stderr, "dbg: couldn't find protocol for protocol number %d!\n", u->protocol); + fflush(stderr); + } else { + if(p->register_user != NULL && + gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(u->register_user)) == TRUE) { + + p->register_user(a); + } + } save_prefs(); + + gtk_widget_destroy(u->mod); } static void cancel_mod(GtkWidget *w, struct mod_user *u) @@ -648,6 +664,14 @@ g_free(puo); op = op->next; } + + if(p->register_user != NULL) { + u->register_user = gtk_check_button_new_with_label("Register with server"); + gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(u->register_user), FALSE); + gtk_box_pack_start(GTK_BOX(vbox), u->register_user, FALSE, FALSE, 0); + gtk_widget_show(u->register_user); + } + g_list_free(tmp); } @@ -1218,17 +1242,23 @@ g_free(k); } -void hide_login_progress(struct gaim_connection *gc, char *why) +/* + * Common code for hide_login_progress(), and hide_login_progress_info() + */ +static void hide_login_progress_common(struct gaim_connection *gc, + char *details, + char *title, + char *prologue) { char buf[2048]; struct kick_dlg *k = find_kick_dlg(gc->user); struct signon_meter *meter = find_signon_meter(gc); - sprintf(buf, _("%s\n%s was unable to sign on: %s"), full_date(), gc->username, why); + sprintf(buf, _("%s\n%s: %s"), full_date(), prologue, details); if (k) gtk_widget_destroy(k->dlg); k = g_new0(struct kick_dlg, 1); k->user = gc->user; - k->dlg = do_error_dialog(buf, _("Signon Error")); + k->dlg = do_error_dialog(buf, title); kicks = g_slist_append(kicks, k); gtk_signal_connect(GTK_OBJECT(k->dlg), "destroy", GTK_SIGNAL_FUNC(set_kick_null), k); if (meter) { @@ -1236,6 +1266,24 @@ meters = g_slist_remove(meters, meter); g_free(meter); } +} + +void hide_login_progress(struct gaim_connection *gc, char *why) +{ + char buf[2048]; + + sprintf(buf, _("%s was unable to sign on"), gc->username); + hide_login_progress_common(gc, why, _("Signon Error"), buf); +} + +/* + * Like hide_login_progress(), but for informational, not error/warning, + * messages. + * + */ +void hide_login_progress_notice(struct gaim_connection *gc, char *why) +{ + hide_login_progress_common(gc, why, _("Notice"), gc->username); } void signoff_all() Index: multi.h =================================================================== RCS file: /cvsroot/gaim/gaim/src/multi.h,v retrieving revision 1.39 retrieving revision 1.40 diff -u -d -r1.39 -r1.40 --- multi.h 22 Dec 2001 08:08:36 -0000 1.39 +++ multi.h 17 Feb 2002 18:08:12 -0000 1.40 @@ -111,5 +111,6 @@ void set_login_progress(struct gaim_connection *, float, char *); void hide_login_progress(struct gaim_connection *, char *); +void hide_login_progress_notice(struct gaim_connection *, char *); #endif /* _MULTI_H_ */ Index: prpl.h =================================================================== RCS file: /cvsroot/gaim/gaim/src/prpl.h,v retrieving revision 1.58 retrieving revision 1.59 diff -u -d -r1.58 -r1.59 --- prpl.h 2 Dec 2001 00:35:34 -0000 1.58 +++ prpl.h 17 Feb 2002 18:08:12 -0000 1.59 @@ -144,7 +144,11 @@ void (* keepalive) (struct gaim_connection *); /* new user registration */ - void (* register_user) (struct gaim_connection *); + void (* register_user) (struct aim_user *); + + /* get "chat buddy" info and away message */ + void (* get_cb_info) (struct gaim_connection *, int, char *who); + void (* get_cb_away) (struct gaim_connection *, int, char *who); void (* buddy_free) (struct buddy *); Index: ui.h =================================================================== RCS file: /cvsroot/gaim/gaim/src/ui.h,v retrieving revision 1.28 retrieving revision 1.29 diff -u -d -r1.28 -r1.29 --- ui.h 25 Jan 2002 04:49:39 -0000 1.28 +++ ui.h 17 Feb 2002 18:08:12 -0000 1.29 @@ -232,6 +232,9 @@ /* stuff for mail check prompt */ GtkWidget *checkmail; + + /* stuff for register with server */ + GtkWidget *register_user; }; #define EDIT_GC 0 Index: util.c =================================================================== RCS file: /cvsroot/gaim/gaim/src/util.c,v retrieving revision 1.112 retrieving revision 1.113 diff -u -d -r1.112 -r1.113 --- util.c 1 Dec 2001 01:48:26 -0000 1.112 +++ util.c 17 Feb 2002 18:08:12 -0000 1.113 @@ -912,6 +912,33 @@ } +/* + * Like strncpy_withhtml (above), but malloc()'s the necessary space + * + * The caller is responsible for freeing the space pointed to by the + * return value. + */ + +gchar *strdup_withhtml(const gchar *src) +{ + char *sp, *dest; + gulong destsize; + + /* + * All we need do is multiply the number of newlines by 3 (the + * additional length of "<BR>" over "\n"), account for the + * terminator, malloc the space and call strncpy_withhtml. + */ + for(destsize = 0, sp = src; (sp = strchr(sp, '\n')) != NULL; ++sp, ++destsize) + ; + destsize *= 3; + destsize += strlen(src) + 1; + dest = g_malloc(destsize); + strncpy_withhtml(dest, src, destsize); + + return(dest); +} + void away_on_login(char *mesg) { GSList *awy = away_messages; |