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