tor 2002-09-05 klockan 02.31 skrev Michael Cardenas: Now I've tested it, and I get a segfault after the password dialog. Let's have a look at some of the code. I hope my comments are useful ;) > +void passwd_callback( GtkWidget *widget, > + GtkWidget *entry ) > +{ > + const char *entrytext; > + entrytext = gtk_entry_get_text (GTK_ENTRY (entry)); > + > + gPassword = malloc(strlen(entrytext)); > + strcpy(gPassword, entrytext); Why not just strdup? > + printf("Password captured.\n"); > +} > +gint delete_event( GtkWidget *widget, > + GdkEvent *event, > + gpointer data ) > +{ > + /* If you return FALSE in the "delete_event" signal handler, > + * GTK will emit the "destroy" signal. Returning TRUE means > + * you don't want the window to be destroyed. > + * This is useful for popping up 'are you sure you want to quit?' > + * type dialogs. */ > + > + g_print ("delete event occurred\n"); > + > + /* Change TRUE to FALSE and the main window will be destroyed with > + * a "delete_event". */ > + > + return TRUE; > +} As I said, clicking Finish on a dialog box doesn't close the dialog box. I'm not sure this is good or bad. I think it gets cluttered fast. > +/* > + * Function: gtkhandler_boolean > + * Input: struct frontend *obj - frontend object > + * struct question *q - question to ask > + * Output: int - DC_OK, DC_NOTOK > + * Description: handler for the boolean question type > + * Assumptions: none > + */ > +static int gtkhandler_boolean(struct frontend *obj, struct question *q) > +{ > + int ans = -1; > + int def = -1; > + const char *defval; > + GtkWidget *window; > + GtkWidget *boolButton; > + GtkWidget *hboxtop, *hboxbottom, *bigbox; > + > + defval = question_defaultval(q); > + if (defval) > + { > + if (strcmp(defval, "true") == 0) > + def = 1; > + else > + def = 0; > + } > + > + //create the window for the question > + window = gtk_window_new (GTK_WINDOW_TOPLEVEL); > + > + bigbox = gtk_vbox_new(FALSE, 0); > + hboxtop = gtk_hbox_new(0, 0); > + hboxbottom = gtk_hbox_new(0, 0); > + > + //add a checkbox for the boolean, we wouldn't really want a whole dialog for one boolean, > + // but this is a start, in the future, I'll have to step through the questions and make > + // intelligent groupings > + > + boolButton = gtk_check_button_new_with_label ( (gchar *)question_description(q) ); > + g_signal_connect (G_OBJECT (boolButton), "clicked", > + G_CALLBACK (check_callback), NULL); Instead of global variables, why not pass in a pointer to ans instead of NULL? That's the 'data' argument in the callback, right? > + gtk_box_pack_start(GTK_BOX(hboxtop), boolButton, FALSE, 5, 5); > + gtk_widget_show (boolButton); > + > + add_common_buttons(window, hboxbottom, bigbox, q); > + > + gtk_box_pack_start(GTK_BOX(bigbox), hboxtop, FALSE, 5, 5); > + gtk_box_pack_start(GTK_BOX(bigbox), hboxbottom, FALSE, 5, 5); > + > + gtk_container_add(GTK_CONTAINER(window), bigbox); > + > + //show the dialog containing the question > + gtk_widget_show (hboxbottom); > + gtk_widget_show (hboxtop); > + gtk_widget_show (bigbox); > + gtk_widget_show (window); > + > + gtk_main (); > + > + if(gBool) > + { > + ans = 1; > + } > + else > + { > + ans = 0; > + } Meaning you wouldn't have to do this... > + question_setvalue(q, (ans ? "true" : "false")); > + return DC_OK; > +} > +static int gtkhandler_multiselect(struct frontend *obj, struct question *q) > +{ > + char *choices[100] = {0}; > + char *defaults[100] = {0}; > + char selected[100] = {0}; > + char answer[1024]; > + int i, j, count, dcount; > + GtkWidget *window; > + GtkWidget *hboxtop, *hboxbottom, *bigbox; > + GtkWidget **choiceButtons; > + > + count = strchoicesplit(question_choices(q), choices, DIM(choices)); > + dcount = strchoicesplit(question_defaultval(q), defaults, DIM(defaults)); > + > + choiceButtons = (GtkWidget **)malloc( (count * (sizeof(GtkWidget *)) + 1) ); Hmm, shouldn't that be count * (sizeof(GtkWidget*) + 1)? You want n+1 pointers, don't you? > + for(i = 0; i < count; i++) > + choiceButtons[i] = (GtkWidget *)malloc(sizeof(GtkWidget *)); Eh? Why do you want to do this? You want to use gtk_*_new functions to do this. > + choiceButtons[count + 1] = 0; And this should be [count], since it's zero-based, right? > + if (dcount > 0) > + for (i = 0; i < count; i++) > + for (j = 0; j < dcount; j++) > + if (strcmp(choices[i], defaults[j]) == 0) > + { > + selected[i] = 1; > + gMultiChoices[i] = 1; > + } > + > + //create the window for the question > + window = gtk_window_new (GTK_WINDOW_TOPLEVEL); > + bigbox = gtk_vbox_new(FALSE, 0); > + hboxbottom = gtk_hbox_new(0, 0); > + hboxtop = gtk_vbox_new(0, 0); > + > + //add the next and back buttons > + > + add_common_buttons(window, hboxbottom, bigbox, q); > + > + for (i = 0; i < count; i++) > + { > + //create a button for each choice here and init the global place to store them > + > + choiceButtons[i] = gtk_check_button_new_with_label ( (gchar *)choices[i] ); And you "overwrite" the pointers here, so your malloc was pretty unnecessary in the first place :) > + g_signal_connect (G_OBJECT (choiceButtons[i]), "clicked", > + G_CALLBACK (multicheck_callback), choiceButtons); This is where you'd want a higher-level language so you could pass in a list of pairs instead <wink> Seriously, a list of structs with both widget and result value might be nice? I don't know how allergic others are to global variables, but I'm pretty damn allergic ;) Another idea would be to actually create our own full-blown gtk2 type and create an object for it to make it even more object-oriented. Just an idea :) > + gtk_box_pack_start(GTK_BOX(hboxtop), choiceButtons[i], FALSE, 5, 0); > + gtk_widget_show (choiceButtons[i]); > + > + } > + > + gtk_box_pack_start(GTK_BOX(bigbox), hboxtop, FALSE, 5, 5); > + gtk_box_pack_start(GTK_BOX(bigbox), hboxbottom, FALSE, 5, 5); > + > + //add the main box to the layout > + gtk_container_add(GTK_CONTAINER(window), bigbox); > + > + //show the dialog containing the question > + gtk_widget_show (hboxbottom); > + gtk_widget_show (hboxtop); > + gtk_widget_show (bigbox); > + gtk_widget_show (window); > + > + gtk_main(); > + > + //once the dialog returns, handle the result > + > + *answer = 0; > + j = 0; > + > + for (i = 0; i < count; i++) > + { > + if(gMultiChoices[i]) > + { > + if(j) > + { > + strcat(answer, ", "); > + } > + > + strcat(answer, choices[i]); > + j++; > + } > + } > + > + for (i = 0; i < count; i++) > + free(choiceButtons[i]); This is where it segfaults. > + printf("%s", answer); > + > + question_setvalue(q, answer); > + > + return DC_OK; > +} > +static int gtkhandler_password(struct frontend *obj, struct question *q) > +{ > + char passwd[256] = {0}; > + GtkWidget *window, *hboxbottom, *hboxtop, *bigbox; > + GtkWidget *entry; > + > + //create the window for the question > + window = gtk_window_new (GTK_WINDOW_TOPLEVEL); > + bigbox = gtk_vbox_new(FALSE, 0); > + hboxbottom = gtk_hbox_new(0, 0); > + hboxtop = gtk_hbox_new(0, 0); > + > + add_common_buttons(window, hboxbottom, bigbox, q); > + > + //add actual password field > + entry = gtk_entry_new (); > + gtk_entry_set_max_length (GTK_ENTRY (entry), 50); > + g_signal_connect (G_OBJECT (entry), "activate", > + G_CALLBACK (passwd_callback), > + entry); Err. Why pass in entry here? Won't entry be 'widget' in the callback? > + gtk_box_pack_start (GTK_BOX (hboxtop), entry, TRUE, TRUE, 0); > + gtk_widget_show (entry); > + > + gtk_entry_set_visibility(GTK_ENTRY(entry), FALSE); > + > + gtk_box_pack_start(GTK_BOX(bigbox), hboxtop, FALSE, 5, 5); > + gtk_box_pack_start(GTK_BOX(bigbox), hboxbottom, FALSE, 5, 5); > + > + //add main box to layout > + gtk_container_add(GTK_CONTAINER(window), bigbox); > + > + //show the dialog containing the question > + gtk_widget_show (hboxbottom); > + gtk_widget_show (hboxtop); > + gtk_widget_show (bigbox); > + gtk_widget_show (window); > + > + gtk_main(); > + > + strcpy(passwd, gPassword); This segfaults if gPassword is NULL. > + question_setvalue(q, passwd); > + return DC_OK; > +} > +static int gtkhandler_select(struct frontend *obj, struct question *q) Many of the comments for multiselect apply here too. > +static int gtkhandler_string(struct frontend *obj, struct question *q) And here, for passwd. > +static int gtkhandler_text(struct frontend *obj, struct question *q) > +{ > + char buf[1024]; > + GtkWidget *window; > + GtkWidget *hboxtop, *hboxbottom, *bigbox; > + GtkWidget *view; > + GtkTextBuffer *buffer; > + char *text; > + GtkTextIter start, end; > + > + //create the window for the question > + window = gtk_window_new (GTK_WINDOW_TOPLEVEL); > + bigbox = gtk_vbox_new(FALSE, 0); > + hboxbottom = gtk_hbox_new(0, 0); > + hboxtop = gtk_vbox_new(0, 0); > + > + add_common_buttons(window, hboxbottom, bigbox, q); > + > + //add the text entry field > + view = gtk_text_view_new (); > + gtk_box_pack_start(GTK_BOX(hboxtop), view, FALSE, 5, 5); > + gtk_widget_show (view); > + > + buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view)); > + gtk_text_buffer_get_start_iter (buffer, &start); > + gtk_text_buffer_get_end_iter (buffer, &end); > + > + //adjust the size > + > + gtk_widget_set_size_request(view, 200, 100); > + > + //add the boxes to the main layout object > + gtk_box_pack_start(GTK_BOX(bigbox), hboxtop, FALSE, 5, 5); > + gtk_box_pack_start(GTK_BOX(bigbox), hboxbottom, FALSE, 5, 5); > + > + //add main box to layout > + gtk_container_add(GTK_CONTAINER(window), bigbox); > + > + //show the dialog containing the question > + gtk_widget_show (hboxbottom); > + gtk_widget_show (hboxtop); > + gtk_widget_show (bigbox); > + gtk_widget_show (window); > + > + gtk_main(); > + > + text = gtk_text_buffer_get_text(buffer, &start, &end, FALSE); > + > + printf("text captured: %s.\n", text); > + > + strcpy(buf, text); This segfaults too. But this time I did enter text! > + question_setvalue(q, buf); > + > + return DC_OK; > +}
Attachment:
signature.asc
Description: Detta =?ISO-8859-1?Q?=E4r?= en digitalt signerad meddelandedel