/* ************************************************************************* Module: build_choices.c Author: Matt Simpson Arlington, TX matthewsimpson@home.com Date: August, 2000 Description: Builds set defaults choices dynamically based on query. Changes: **************************************************************************** COPYRIGHT (C) 2000 Matt Simpson GNU General Public License See lexgui.c for full notice. **************************************************************************** */ #include #include #include #include #include #include "lexgui.h" #define GCHUNK 32 /* ------------------------------------------------------------------------- allocate_group() Allocates or reallocates memory for groups. ------------------------------------------------------------------------- */ gint allocate_group(dc_struct *dc) { gint j; if(dc->gr == NULL) { dc->gr = (grpch_struct *) malloc(GCHUNK * sizeof(grpch_struct)); if(dc->gr == NULL) return(0); dc->gr_alloc_count = GCHUNK; for(j = 0; j < dc->gr_alloc_count; j++) { dc->gr[j].numchoices_alloc = 0; dc->gr[j].rbutton = NULL; dc->gr[j].choice = NULL; } } else if(dc->gcount >= dc->gr_alloc_count - 1) { dc->gr_alloc_count += GCHUNK; dc->gr = (grpch_struct *) realloc(dc->gr, dc->gr_alloc_count * sizeof(grpch_struct)); if(dc->gr == NULL) return(0); for(j = dc->gr_alloc_count - GCHUNK; j < dc->gr_alloc_count; j++) { dc->gr[j].numchoices_alloc = 0; dc->gr[j].rbutton = NULL; dc->gr[j].choice = NULL; } } return(1); } /* ------------------------------------------------------------------------- set_group() Allocate & set group, set heading name, initialize things. ------------------------------------------------------------------------- */ gint set_group(dc_struct *dc, gchar *sptr1, gchar *sptr2) { gint i; if(!allocate_group(dc)) return(0); /* Set things */ dc->gr[dc->gcount].group = NULL; strncpy(dc->gr[dc->gcount].name, sptr1, sptr2 - sptr1); /* heading name */ dc->gr[dc->gcount].name[sptr2 - sptr1] = 0; dc->gr[dc->gcount].ac_ptr = &(dc->ac_button); dc->gr[dc->gcount].fc_ptr = &(dc->fc_button); dc->gr[dc->gcount].msgbox_ptr = dc->msgbox_ptr; /* initialize things */ dc->gr[dc->gcount].nochangebutton = NULL; strcpy(dc->gr[dc->gcount].new, "\0"); dc->gr[dc->gcount].check = NULL; dc->gr[dc->gcount].adjustment = NULL; dc->gr[dc->gcount].scale = NULL; dc->gr[dc->gcount].rtype = 0; for(i = 0; i < NF; i++) dc->gr[dc->gcount].fset[i] = 0.0; dc->gr[dc->gcount].changed = 0; return(1); } /* ------------------------------------------------------------------------- set_current() Set group's current choice returned by the printer. ------------------------------------------------------------------------- */ void set_current(dc_struct *dc, gchar *sptr1, gchar *sptr2) { gint j; strncpy(dc->gr[dc->gcount].current, sptr1, sptr2 - sptr1); dc->gr[dc->gcount].current[sptr2 - sptr1] = 0; j = sptr2 - sptr1 - 1; while(j > 0 && (dc->gr[dc->gcount].current[j] == ' ')) { dc->gr[dc->gcount].current[j] = 0; /* chop off trailing blanks */ j--; } } #ifdef NOTUSED /* ------------------------------------------------------------------------- setonly() Looks for things known to be "set only", e.g. a temp setting that cannot be set as a permanent default. ------------------------------------------------------------------------- */ gint setonly(gchar *choice) { gint i; static gchar *setonlyvar[] = {"PCL LFONTPRIORITY"}; gint setonlyvarnum = 1; /* set to number of things in *setonlyvar[] */ for(i = 0; i < setonlyvarnum; i++) { if(strstr(choice, setonlyvar[i])) return(1); } return(0); } #endif /* ------------------------------------------------------------------------- skipit() Looks for things to skip making a group from. These are skipped either because they can't be changed, they affect something else if changed, something else affects them, or it is too dangerous to allow a change. This list is based on my Optra 40 and also from reading the Lexmark PJL manual. It is by no means inclusive; I could have missed something and I don't have a PJL manual for HP. If anyone decides something should be skipped, put it in this list (and increment skipnum) and email me: matthewsimpson@home.com ------------------------------------------------------------------------- */ gint skipit(gchar *choice) { gint i, found; static gchar *skip[] = {"@PJL", "?", "READONLY", "SETONLY", "PASSWORD", "LADVANCEDSTATUS", "INTRAY1SIZE", "INTRAY2SIZE", "INTRAY3SIZE", "INTRAY4SIZE", "INTRAY5SIZE", "LRESOURCESAVE", "RESOURCESAVE", "LPPDS", "LDOWNLOADTARGET", "PCL LFONTPRIORITY", "TESTPAGE"}; gint skipnum = 17; /* set to number of things in *skip[] */ for(i = 0; i < skipnum; i++) { if(strstr(choice, skip[i])) return(1); } /* If blank or NULL, we don't want to include it either. */ found = 0; for(i = 0; i < strlen(choice); i++) { if(choice[i] != ' ' && choice[i] != 0) { found = 1; break; } } if(found) return(0); else return(1); } /* ------------------------------------------------------------------------- parse_heading() If a heading, parse it and start setting up the group[] for this heading. If we don't like anything we just ignore the group by returning before we set numchoices. ------------------------------------------------------------------------- */ gint parse_heading(dc_struct *dc, gchar *choice) { gint sn; gchar *sptr1, *sptr2; gchar typstr[JMAX]; dc->gr[dc->gcount].numchoices = 0; /* if numchoices is still 0 upon returning then we won't look for choices */ sptr1 = choice; while(sptr1[0] && isspace((int)sptr1[0])) sptr1 += 1; /* get rid of any preceeding blank spaces */ if(!sptr1[0]) return(1); sptr2 = strchr(choice, '='); /* we already know there is a '=' in choice */ if(!set_group(dc, sptr1, sptr2)) return(0); sptr1 = sptr2 + 1; sptr2 = strchr(choice, '['); if(sptr2) { set_current(dc, sptr1, sptr2); sptr2 += 1; sscanf(sptr2, "%d %s", &sn, typstr);/* sn is the stated # of choices */ if(sn <= 1 || sn > 100) /* test for reasonableness */ return(1); if(strstr(typstr, "ENUMERATED") || strstr(typstr, "enumerated")) dc->gr[dc->gcount].choicetype = 0; else if(strstr(typstr, "RANGE") || strstr(typstr, "range")) dc->gr[dc->gcount].choicetype = 1; else return(1); } else return(1); /* If the [ is not found, ignore this group */ #ifdef NOTUSED if(setonly(choice)) dc->gr[dc->gcount].sonly = 1; else dc->gr[dc->gcount].sonly = 0; #endif /* set numchoices only if all above is ok. After testing sn above, the minimum possible number of choices is 2. */ dc->gr[dc->gcount].numchoices = sn; return(1); } /* ------------------------------------------------------------------------- allocate_choices() Allocates or reallocates memory for choices if needed. ------------------------------------------------------------------------- */ gint allocate_choices(dc_struct *dc) { if(dc->gr[dc->gcount].choicetype == 0) /* enumerated choices */ { if(dc->gr[dc->gcount].numchoices_alloc == 0) { dc->gr[dc->gcount].rbutton = (GtkWidget **) malloc(dc->gr[dc->gcount].numchoices * sizeof(GtkWidget *)); dc->gr[dc->gcount].choice = (gchar (*)[JMAX]) malloc(dc->gr[dc->gcount].numchoices * sizeof(gchar[JMAX])); if(dc->gr[dc->gcount].rbutton == NULL || dc->gr[dc->gcount].choice == NULL) return(0); dc->gr[dc->gcount].numchoices_alloc = dc->gr[dc->gcount].numchoices; } else if(dc->gr[dc->gcount].numchoices > dc->gr[dc->gcount].numchoices_alloc) { dc->gr[dc->gcount].rbutton = (GtkWidget **) realloc(dc->gr[dc->gcount].rbutton, dc->gr[dc->gcount].numchoices * sizeof(GtkWidget *)); dc->gr[dc->gcount].choice = (gchar (*)[JMAX]) realloc(dc->gr[dc->gcount].choice, dc->gr[dc->gcount].numchoices * sizeof (gchar[JMAX])); if(dc->gr[dc->gcount].rbutton == NULL || dc->gr[dc->gcount].choice == NULL) { dc->gr[dc->gcount].numchoices_alloc = 0; return(0); } dc->gr[dc->gcount].numchoices_alloc = dc->gr[dc->gcount].numchoices; } } return(1); } /* ------------------------------------------------------------------------- parse_choice() If a choice, parse it and finish setting up the group this choice belongs to. ------------------------------------------------------------------------- */ void parse_choice(dc_struct *dc, gchar *choice, gint j) { gchar *sptr1; if(dc->gr[dc->gcount].choicetype == 0) /* enumerated choice */ { sptr1 = choice; while(sptr1[0] && isspace((int)sptr1[0])) sptr1 += 1; /* get rid of any preceeding blank spaces */ strcpy(dc->gr[dc->gcount].choice[j - 1], sptr1); } else /* range choice */ { if(strchr(dc->gr[dc->gcount].current, '.')) dc->gr[dc->gcount].rtype = 1; /* gfloat */ if(j == 1) { /* set current */ if(!strcmp(dc->gr[dc->gcount].current, "OFF") || !strcmp(dc->gr[dc->gcount].current, "DISABLED")) dc->gr[dc->gcount].fset[2] = 0.0; else { sscanf(dc->gr[dc->gcount].current, "%f", &(dc->gr[dc->gcount].fset[2])); /* Printer does not seem to like neg numbers so set these to zero. */ if(dc->gr[dc->gcount].fset[2] < 0.0) dc->gr[dc->gcount].fset[2] = 0.0; } /* set min */ sscanf(choice, "%f", &(dc->gr[dc->gcount].fset[0])); /* Printer does not seem to like neg numbers so set these to zero. */ if(dc->gr[dc->gcount].fset[0] < 0.0) dc->gr[dc->gcount].fset[0] = 0.0; } else /* set max */ { sscanf(choice, "%f", &(dc->gr[dc->gcount].fset[1])); /* Printer does not seem to like neg numbers so set these to zero. */ if(dc->gr[dc->gcount].fset[1] < 0.0) dc->gr[dc->gcount].fset[1] = 0.0; } } } /* ------------------------------------------------------------------------- process_h_c() Determines which parse functions to call from the separate string extracted from the larger query string. ------------------------------------------------------------------------- */ gint process_h_c(dc_struct *dc, gchar *choice, gint check) { static gint ccount; if(check == 1) { ccount = 0; return(1); } else if(check == 2) { if(ccount) { /* Should be 0. If not, the last group ran out of choices before finishing so it did not properly increment gcount. */ dc->gr[dc->gcount].numchoices = ccount - 1; ccount = 0; dc->gcount++; } return(1); } if(!skipit(choice)) { if(strchr(choice, '=')) /* We are at a heading */ { if(ccount) { /* We expected a choice but instead came upon a heading, meaning there are not as many choices as determined in the previous call to parse_heading(). So adjust numchoices accordingly and increment the group to a new one. */ dc->gr[dc->gcount].numchoices = ccount - 1; ccount = 0; dc->gcount++; } if(!parse_heading(dc, choice)) return(0); /* if numchoices is 0 then parse_heading() did not like something */ if(dc->gr[dc->gcount].numchoices > 0) ccount++; } else /* we are at a choice */ { if(ccount == 0) { /* We expected a heading but instead came upon a choice, meaning there are more choices than determined in the previous call to parse_heading(), or there is no previous heading, or parse_heading() did not like the previous heading and ignored it (which would have choices following to also ignore). So ignore by returning. */ return(1); } if(!allocate_choices(dc)) return(0); parse_choice(dc, choice, ccount); if(ccount >= dc->gr[dc->gcount].numchoices) { ccount = 0; dc->gcount ++; /* Done with group, increment group counter */ } else ccount++; } } return(1); } /* ------------------------------------------------------------------------- parse_query() Each choice heading and choice is parsed from the string io->query into a separate string which is then used to set up each group's heading or choices for that heading. Strings longer than JMAX are truncated. ------------------------------------------------------------------------- */ gint parse_query(io_struct *io) { gint i, j; gchar choice[JMAX] = "\0"; j = 0; (io->dc_ptr)->gcount = 0; if(!allocate_group(io->dc_ptr)) return(0); process_h_c(io->dc_ptr, "\0", 1); /* initialize ccount */ for(i = 0; i < io->j; i++) { if(io->query[i] == '\n' || io->query[i] == 0) { choice[j] = 0; j = 0; /* We now have a heading or a choice */ if(!process_h_c(io->dc_ptr, choice, 0)) return(0); if(io->query[i] == 0) break; else continue; } choice[j] = io->query[i]; j++; if(j > JMAX - 1) j = JMAX - 1; /* Truncates strings longer than JMAX. Last char keeps getting overwritten until it gets the terminator. */ } process_h_c(io->dc_ptr, "\0", 2); /* check final ccount */ return(1); } /* ------------------------------------------------------------------------- choice_CB() Radio button callback for choices. ------------------------------------------------------------------------- */ void choice_CB(GtkWidget *widget, grpch_struct *gr) { int i; /* This callback may be called twice when a radio button is clicked-- once for the toggle-off of the previously active button in the group, and once for the toggle-on of the radio button clicked. The following if((widget)->active) passes only for the toggle-on portion, then the if((gr->rbutton[i])->active finds the choice selected. */ if (GTK_TOGGLE_BUTTON(widget)->active) { gr->new[0] = 0; if(GTK_IS_WIDGET(gr->nochangebutton)) /* for non dynamic */ { if (GTK_TOGGLE_BUTTON (gr->nochangebutton)->active) { gr->changed = 0; return; } } gr->changed = 1; for(i = 0; i < gr->numchoices; i++) { if (GTK_TOGGLE_BUTTON (gr->rbutton[i])->active) { if(!GTK_IS_WIDGET(gr->nochangebutton) && /* if dynamic and if */ !strcmp(gr->current, gr->choice[i])) /* already set as default */ { gr->changed = 0; } else { gtk_widget_set_sensitive(*(gr->ac_ptr), TRUE); gtk_widget_set_sensitive(*(gr->fc_ptr), TRUE); strcpy(gr->new, gr->choice[i]); } clear_msgbox(gr->msgbox_ptr); } } } } /* ------------------------------------------------------------------------- choice_scale_CB() Scale button callback for range choices. Note the value is automatically set in the adjustment and is extracted when needed in applychanges_CB(). Therefore the only thing this callback is used for is toggling the check button to FALSE. ------------------------------------------------------------------------- */ void choice_scale_CB(GtkAdjustment *adj, grpch_struct *gr) { /* If the value is ever needed here, it is adj->value */ if(!gr->changed) gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(gr->check), FALSE); /* The above will emit the "toggled" signal for the check button, thus calling choice_scale_check_CB() and going to the "else" part. */ } /* ------------------------------------------------------------------------- choice_check_scale_CB() Check button callback for "No Change" toggle button. Called whenever the "toggle" signal is emitted. ------------------------------------------------------------------------- */ void choice_scale_check_CB(GtkWidget *widget, grpch_struct *gr) { if (GTK_TOGGLE_BUTTON(widget)->active) { gtk_adjustment_set_value(GTK_ADJUSTMENT(gr->adjustment), gr->fset[2]); /* The above will emit the "value_changed" signal for the scale, thus calling choice_scale_CB(). But since gr->changed is not set to 0 until the following line, choice_scale_CB() will not do anything. */ gr->changed = 0; } else { gr->changed = 1; gtk_widget_set_sensitive(*(gr->ac_ptr), TRUE); gtk_widget_set_sensitive(*(gr->fc_ptr), TRUE); clear_msgbox(gr->msgbox_ptr); } /* If the value of the scale is ever needed here, it is (GTK_ADJUSTMENT(gr->adjustment))->value */ } /* ------------------------------------------------------------------------- clear_choices() Removes list from dynamic choices window. ------------------------------------------------------------------------- */ void clear_choices(dc_struct *dc) { gint i, j; if(GTK_IS_WIDGET(dc->dc_vbox)) { for(i = 0; i < dc->gcount; i++) { if(dc->gr[i].choicetype == 0) /* enumerated choice */ { if(dc->fixq) /* For non dynamic */ { gtk_widget_destroy(dc->gr[i].nochangebutton); dc->gr[i].nochangebutton = NULL; } for(j = 0; j < dc->gr[i].numchoices; j++) { gtk_widget_destroy(dc->gr[i].rbutton[j]); dc->gr[i].rbutton[j] = NULL; } } else /* range choice */ { gtk_widget_destroy(dc->gr[i].check); gtk_widget_destroy(dc->gr[i].scale); dc->gr[i].check = NULL; dc->gr[i].scale = NULL; } } gtk_widget_destroy(dc->dc_vbox); dc->dc_vbox = NULL; /* uncomment the following to have the scrollbars reset when clearing the page */ /* gtk_adjustment_set_value(dc->sw.aj.hadj, 0); gtk_adjustment_set_value(dc->sw.aj.vadj, 0); */ } } /* ------------------------------------------------------------------------- build_choice_widgets() Builds choices widgets. ------------------------------------------------------------------------- */ void build_choice_widgets(dc_struct *dc) { gint i, j, step, digits, active; static GtkWidget *note, *label, *hbox, *lhbox, *rhbox; static gchar message[] = { "Note on Color Correction: For the Lexmark Optra 40,\n" "the AUTO setting only applies to printers with a\n" "firmware version of 322.03 or above, and for the\n" "Optra 45 to version 312.03 or above. The firmware\n" "version can be found with Pup's 'Query Printer'\n" "window under @PJL INFO CONFIG or on the printed\n" "settings page under 'Printer Information -- Base.'" }; for(i = 0; i < dc->gcount; i++) { make_separator(dc->dc_vbox); hbox = gtk_hbox_new(FALSE, 0); gtk_box_pack_start (GTK_BOX(dc->dc_vbox), hbox, FALSE, FALSE, 0); gtk_widget_show(hbox); label = gtk_label_new(dc->gr[i].name); gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_LEFT); gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); gtk_widget_show(label); /* The following is specific to the Lexmark Optra 40 & 45, in the fixed choices window only. */ if(dc->fixq && !strcmp(dc->gr[i].name, "LCOLORCORRECTION") && (dc->top)->prefs.index == 0) { hbox = gtk_hbox_new(FALSE, 0); gtk_box_pack_start (GTK_BOX(dc->dc_vbox), hbox, FALSE, FALSE, 0); gtk_widget_show(hbox); note = gtk_label_new(message); gtk_label_set_justify(GTK_LABEL(note), GTK_JUSTIFY_LEFT); gtk_box_pack_start(GTK_BOX(hbox), note, FALSE, FALSE, 0); gtk_widget_show(note); } #ifdef NOTUSED if(dc->gr[i].sonly == 1) { label = gtk_label_new("Temporary Change Only"); gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_RIGHT); gtk_box_pack_end(GTK_BOX(hbox), label, FALSE, FALSE, 0); gtk_widget_show(label); } #endif if(dc->gr[i].choicetype == 0) /* enumerated choice */ { if(dc->fixq) /* for non dynamic */ { hbox = gtk_hbox_new(FALSE, 0); gtk_box_pack_start (GTK_BOX(dc->dc_vbox), hbox, FALSE, FALSE, 0); gtk_widget_show(hbox); dc->gr[i].nochangebutton = gtk_radio_button_new(dc->gr[i].group); gtk_box_pack_start(GTK_BOX(hbox), dc->gr[i].nochangebutton, FALSE, FALSE, 0); dc->gr[i].group = gtk_radio_button_group(GTK_RADIO_BUTTON(dc->gr[i].nochangebutton)); set_color(&(dc->gr[i].nochangebutton), YELLOW, BG, ACTIVE); gtk_signal_connect(GTK_OBJECT(dc->gr[i].nochangebutton), "toggled", GTK_SIGNAL_FUNC(choice_CB), (gpointer)&(dc->gr[i])); gtk_widget_show(dc->gr[i].nochangebutton); label = gtk_label_new("No Change"); gtk_container_add(GTK_CONTAINER(dc->gr[i].nochangebutton), label); gtk_widget_show(label); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(dc->gr[i].nochangebutton), TRUE); } active = -1; for(j = 0; j < dc->gr[i].numchoices; j++) { hbox = gtk_hbox_new(FALSE, 0); gtk_box_pack_start (GTK_BOX(dc->dc_vbox), hbox, FALSE, FALSE, 0); gtk_widget_show(hbox); dc->gr[i].rbutton[j] = gtk_radio_button_new(dc->gr[i].group); gtk_box_pack_start(GTK_BOX(hbox), dc->gr[i].rbutton[j], FALSE, FALSE, 0); dc->gr[i].group = gtk_radio_button_group(GTK_RADIO_BUTTON(dc->gr[i].rbutton[j])); set_color(&(dc->gr[i].rbutton[j]), YELLOW, BG, ACTIVE); gtk_signal_connect(GTK_OBJECT(dc->gr[i].rbutton[j]), "toggled", GTK_SIGNAL_FUNC(choice_CB), (gpointer)&(dc->gr[i])); gtk_widget_show(dc->gr[i].rbutton[j]); label = gtk_label_new(dc->gr[i].choice[j]); if(!dc->fixq) /* Don't highlight if non-dynamic */ { if(!strcmp(dc->gr[i].current, dc->gr[i].choice[j])) { set_color(&label, RED, FG, NORMAL); set_color(&label, RED, FG, ACTIVE); set_font(&label, 8); active = j; } } gtk_container_add(GTK_CONTAINER(dc->gr[i].rbutton[j]), label); gtk_widget_show(label); } if(active >= 0) gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(dc->gr[i].rbutton[active]), TRUE); } else /* range choice */ { hbox = gtk_hbox_new(TRUE, 0); gtk_box_pack_start (GTK_BOX(dc->dc_vbox), hbox, FALSE, FALSE, 0); gtk_widget_show(hbox); lhbox = gtk_hbox_new(FALSE, 0); gtk_box_pack_start (GTK_BOX(hbox), lhbox, TRUE, TRUE, 0); gtk_widget_show(lhbox); if(!dc->fixq) { label = gtk_label_new(dc->gr[i].current); set_color(&label, RED, FG, NORMAL); set_font(&label, 8); gtk_box_pack_start (GTK_BOX(lhbox), label, FALSE, FALSE, 0); gtk_widget_show(label); } rhbox = gtk_hbox_new(FALSE, 0); gtk_box_pack_start (GTK_BOX(hbox), rhbox, TRUE, TRUE, 0); gtk_widget_show(rhbox); dc->gr[i].check = gtk_check_button_new_with_label("No Change"); set_color(&(dc->gr[i].check), YELLOW, BG, ACTIVE); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dc->gr[i].check), TRUE); gtk_box_pack_start(GTK_BOX(rhbox), dc->gr[i].check, FALSE, FALSE, 0); gtk_signal_connect(GTK_OBJECT(dc->gr[i].check), "toggled", GTK_SIGNAL_FUNC(choice_scale_check_CB), (gpointer)&(dc->gr[i])); gtk_widget_show(dc->gr[i].check); if(dc->gr[i].rtype == 0) { step = 1; digits = 0; } else { step = .01; digits = 2; } if(dc->fixq) /* If non-dynamic, set current to min */ dc->gr[i].fset[2] = dc->gr[i].fset[0]; dc->gr[i].adjustment = gtk_adjustment_new(dc->gr[i].fset[2], dc->gr[i].fset[0], dc->gr[i].fset[1], step, 1, 0); gtk_signal_connect(GTK_OBJECT(dc->gr[i].adjustment), "value_changed", GTK_SIGNAL_FUNC (choice_scale_CB), (gpointer)&(dc->gr[i])); dc->gr[i].scale = gtk_hscale_new(GTK_ADJUSTMENT(dc->gr[i].adjustment)); gtk_scale_set_digits(GTK_SCALE(dc->gr[i].scale), digits); gtk_box_pack_start(GTK_BOX(dc->dc_vbox), dc->gr[i].scale, FALSE, FALSE, 0); gtk_widget_show(dc->gr[i].scale); } } if(dc->numtochange && !dc->fixq) put_msg(dc->msgbox_ptr, "Changes Applied !", GREEN, 0); } /* ------------------------------------------------------------------------- build_choices() Builds list of choices for setting defaults. For the dynamic choices window, the query was packed dynamically just before getting here. For the fixed choices window the query was pre-packed. ------------------------------------------------------------------------- */ void build_choices(io_struct *io) { dc_struct *dc; static GtkWidget *space, *note, *hbox; gint width_return, height_return; dc = io->dc_ptr; if(dc->fixq) /* non dynamic mode */ { if(dc->fixinit) { /* if already initialized, just clear the selected changes and return */ forgetchanges(dc); if(dc->numtochange) put_msg(dc->msgbox_ptr, "Changes Sent !", GREEN, 0); return; } else dc->fixinit = 1; } clear_choices(dc); /* clear previous window if any */ if(!parse_query(io)) { report_alloc_err(io, 10); return; } dc->dc_vbox = gtk_vbox_new(FALSE, 0); gtk_box_pack_start(GTK_BOX(dc->sw.sc_vbox), dc->dc_vbox, FALSE, FALSE, 0); space = gtk_label_new(""); gtk_widget_set_usize(space, 320, 10); gtk_box_pack_start (GTK_BOX(dc->dc_vbox), space, FALSE, FALSE, 0); gtk_widget_show(space); if(!dc->fixq) { hbox = gtk_hbox_new(FALSE, 0); gtk_box_pack_start (GTK_BOX(dc->dc_vbox), hbox, FALSE, FALSE, 0); gtk_widget_show(hbox); note = gtk_label_new("Current settings shown in "); gtk_label_set_justify(GTK_LABEL(note), GTK_JUSTIFY_LEFT); set_font(¬e, 8); gtk_box_pack_start (GTK_BOX(hbox), note, FALSE, FALSE, 0); gtk_widget_show(note); note = gtk_label_new("Red"); gtk_label_set_justify(GTK_LABEL(note), GTK_JUSTIFY_LEFT); set_color(¬e, RED, FG, NORMAL); set_font(¬e, 8); gtk_box_pack_start (GTK_BOX(hbox), note, FALSE, FALSE, 0); gtk_widget_show(note); note = gtk_label_new("."); gtk_label_set_justify(GTK_LABEL(note), GTK_JUSTIFY_LEFT); set_font(¬e, 8); gtk_box_pack_start (GTK_BOX(hbox), note, FALSE, FALSE, 0); gtk_widget_show(note); } hbox = gtk_hbox_new(FALSE, 0); gtk_box_pack_start (GTK_BOX(dc->dc_vbox), hbox, FALSE, FALSE, 0); gtk_widget_show(hbox); note = gtk_label_new("Select desired defaults and click"); gtk_label_set_justify(GTK_LABEL(note), GTK_JUSTIFY_LEFT); set_font(¬e, 8); gtk_box_pack_start (GTK_BOX(hbox), note, FALSE, FALSE, 0); gtk_widget_show(note); hbox = gtk_hbox_new(FALSE, 0); gtk_box_pack_start (GTK_BOX(dc->dc_vbox), hbox, FALSE, FALSE, 0); gtk_widget_show(hbox); note = gtk_label_new("Apply Changes button."); gtk_label_set_justify(GTK_LABEL(note), GTK_JUSTIFY_LEFT); set_font(¬e, 8); gtk_box_pack_start (GTK_BOX(hbox), note, FALSE, FALSE, 0); gtk_widget_show(note); build_choice_widgets(dc); gtk_widget_show(dc->dc_vbox); /* The following is a workaround for a problem where some of the things do not get redrawn in the window when building the list more than once. Setting the size refreshes the window. Also we can't do this for the fixed choices window because in this case build_choices() is called immediately (with a pre-packed query) instead of with a callback like the dynamic query. Therefore for the fixed choices window the top scrolled win widget is not yet realized (the window has to be realized to get the size). That's ok because we don't need to refresh the fixed choices window. */ if(!dc->fixq) { gdk_window_get_size(GTK_WIDGET(dc->sw.topwin)->window, &width_return, &height_return); gtk_widget_set_usize(dc->sw.topwin, width_return, height_return); } }