gschem

x_autonumber.c

Go to the documentation of this file.
00001 /* gEDA - GPL Electronic Design Automation
00002  * gschem - gEDA Schematic Capture
00003  * Copyright (C) 1998-2010 Ales Hvezda
00004  * Copyright (C) 1998-2011 gEDA Contributors (see ChangeLog for details)
00005  *
00006  * This program is free software; you can redistribute it and/or modify
00007  * it under the terms of the GNU General Public License as published by
00008  * the Free Software Foundation; either version 2 of the License, or
00009  * (at your option) any later version.
00010  *
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License
00017  * along with this program; if not, write to the Free Software
00018  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
00019  */
00020 
00021 #include <config.h>
00022 
00023 #include <stdio.h>
00024 #include <ctype.h>
00025 #ifdef HAVE_STDLIB_H
00026 #include <stdlib.h>
00027 #endif
00028 #ifdef HAVE_STRING_H
00029 #include <string.h>
00030 #endif
00031 
00032 #include "gschem.h"
00033 #include <gdk/gdkkeysyms.h>
00034 
00035 #ifdef HAVE_LIBDMALLOC
00036 #include <dmalloc.h>
00037 #endif
00038 
00039 #define GLADE_HOOKUP_OBJECT(component,widget,name) \
00040   g_object_set_data_full (G_OBJECT (component), name, \
00041     gtk_widget_ref (widget), (GDestroyNotify) gtk_widget_unref)
00042 
00044 #define HISTORY_LENGTH      15
00045 
00046 /* autonumber text structs and enums */
00047 enum {
00048   AUTONUMBER_SORT_DIAGONAL,
00049   AUTONUMBER_SORT_YX, 
00050   AUTONUMBER_SORT_YX_REV, 
00051   AUTONUMBER_SORT_XY, 
00052   AUTONUMBER_SORT_XY_REV, 
00053   AUTONUMBER_SORT_FILE 
00054 };
00055 
00056 enum {
00057   AUTONUMBER_IGNORE, 
00058   AUTONUMBER_RENUMBER, 
00059   AUTONUMBER_RESPECT
00060 };
00061 
00062 enum {
00063   SCOPE_SELECTED, 
00064   SCOPE_PAGE, 
00065   SCOPE_HIERARCHY 
00066 };
00067 
00068 typedef struct autonumber_text_t AUTONUMBER_TEXT;
00069 
00071 struct autonumber_text_t {
00073   GList *scope_text;
00074 
00076   gint scope_skip;
00077 
00079   gint scope_number;
00080 
00082   gboolean scope_overwrite;
00083 
00085   gint order;
00086 
00088   gint startnum;
00089 
00091   gboolean removenum;
00092 
00094   gboolean slotting;
00095 
00097   GtkWidget *dialog;
00098 
00100   GSCHEM_TOPLEVEL *w_current;
00101 
00102   /* variables used while autonumbering */
00103   gchar * current_searchtext;
00104   gint root_page;      /* flag whether its the root page or not */
00105   GList *used_numbers; /* list of used numbers */ 
00106   GList *free_slots;   /* list of FREE_SLOT objects */
00107   GList *used_slots;   /* list of USED_SLOT objects */
00108 };
00109 
00110 typedef struct autonumber_slot_t AUTONUMBER_SLOT;
00111 
00112 struct autonumber_slot_t {
00113   gchar *symbolname;     /* or should I use the device name? (Werner) */
00114   gint number;           /* usually this is the refdes number */
00115   gint slotnr;      /* just the number of the free slot */
00116 };
00117 
00118 
00119 
00120 /* ***** BACK-END CODE ***************************************************** */
00121 
00122 /********** compare functions for g_list_sort, ... ***********************/
00128 gint autonumber_sort_numbers(gconstpointer a, gconstpointer b) {
00129   if (GPOINTER_TO_INT(a) < GPOINTER_TO_INT(b))
00130     return -1;
00131   if (GPOINTER_TO_INT(a) > GPOINTER_TO_INT(b))
00132     return 1;
00133   return 0;
00134 }
00135 
00143 gint autonumber_sort_xy(gconstpointer a, gconstpointer b) {
00144   OBJECT *aa, *bb;
00145   aa=(OBJECT *) a;  bb=(OBJECT *) b;
00146   if (aa->text->x < bb->text->x)
00147     return -1;
00148   if (aa->text->x > bb->text->x)
00149     return 1;
00150   /* x == x */
00151   if (aa->text->y > bb->text->y)
00152     return -1;
00153   if (aa->text->y < bb->text->y)
00154     return 1;
00155   return 0;
00156 }
00157 
00166 gint autonumber_sort_xy_rev(gconstpointer a, gconstpointer b) {
00167   OBJECT *aa, *bb;
00168   aa=(OBJECT *) a;  bb=(OBJECT *) b;
00169   if (aa->text->x < bb->text->x)
00170     return 1;
00171   if (aa->text->x > bb->text->x)
00172     return -1;
00173   /* x == x */
00174   if (aa->text->y < bb->text->y)
00175     return 1;
00176   if (aa->text->y > bb->text->y)
00177     return -1;
00178   return 0;
00179 }
00180 
00188 int autonumber_sort_yx(gconstpointer a, gconstpointer b) {
00189   OBJECT *aa, *bb;
00190   aa=(OBJECT *) a;  bb=(OBJECT *) b;
00191   if (aa->text->y > bb->text->y)
00192     return -1;
00193   if (aa->text->y < bb->text->y)
00194     return 1;
00195   /* y == y */
00196   if (aa->text->x < bb->text->x)
00197     return -1;
00198   if (aa->text->x > bb->text->x)
00199     return 1;
00200   return 0;
00201 }
00202 
00211 int autonumber_sort_yx_rev(gconstpointer a, gconstpointer b) {
00212   OBJECT *aa, *bb;
00213   aa=(OBJECT *) a;  bb=(OBJECT *) b;
00214   if (aa->text->y > bb->text->y)
00215     return 1;
00216   if (aa->text->y < bb->text->y)
00217     return -1;
00218   /* y == y */
00219   if (aa->text->x > bb->text->x)
00220     return 1;
00221   if (aa->text->x < bb->text->x)
00222     return -1;
00223   return 0;
00224 }
00225 
00233 int autonumber_sort_diagonal(gconstpointer a, gconstpointer b) {
00234   OBJECT *aa, *bb;
00235   aa=(OBJECT *) a;  bb=(OBJECT *) b;
00236   if (aa->text->x - aa->text->y < bb->text->x - bb->text->y)
00237     return -1;
00238   if (aa->text->x - aa->text->y > bb->text->x - bb->text->y)
00239     return 1;
00240   return 0;
00241 }
00242 
00251 gint freeslot_compare(gconstpointer a, gconstpointer b) 
00252 {
00253   AUTONUMBER_SLOT *aa, *bb;
00254   gint res;
00255   aa = (AUTONUMBER_SLOT *) a;  bb = (AUTONUMBER_SLOT *) b;
00256   
00257   if ((res = strcmp(aa->symbolname, bb->symbolname)) != 0)
00258     return res;
00259 
00260   /* aa->symbolname == bb->symbolname */
00261   if (aa->number == 0 || bb->number == 0)
00262     return 0;
00263   if (aa->number > bb->number)
00264     return 1;
00265   if (aa->number < bb->number)
00266     return -1;
00267 
00268   /* aa->number == bb->number */
00269   if (aa->slotnr == 0 || bb->slotnr == 0)
00270     return 0;
00271   if (aa->slotnr > bb->slotnr)
00272     return 1;
00273   if (aa->slotnr < bb->slotnr)
00274     return -1;
00275 
00276   return 0;
00277 }
00278 
00284 void freeslot_print(GList *list) {
00285   GList *item;
00286   AUTONUMBER_SLOT *fs;
00287   
00288   printf("freeslot_print(): symname, number, slot\n");
00289   for (item = list; item != NULL; item = g_list_next(item)) {
00290     fs = item ->data;
00291     printf("  %s, %d, %d\n",fs->symbolname, fs->number, fs->slotnr);
00292   }
00293 }
00294 
00295 
00300 void autonumber_clear_database (AUTONUMBER_TEXT *autotext)
00301 {
00302   /* cleanup everything for the next searchtext */
00303   if (autotext->used_numbers != NULL) {
00304     g_list_free(autotext->used_numbers);
00305     autotext->used_numbers = NULL;
00306   }
00307   if (autotext->free_slots != NULL) {
00308     g_list_foreach(autotext->free_slots, (GFunc) g_free, NULL);
00309     g_list_free(autotext->free_slots);
00310     autotext->free_slots = NULL;
00311   }
00312   if (autotext->used_slots != NULL) {
00313     g_list_foreach(autotext->used_slots, (GFunc) g_free, NULL);
00314     g_list_free(autotext->used_slots);
00315     autotext->used_slots = NULL;
00316   }
00317 }
00318 
00328 gint autonumber_match(AUTONUMBER_TEXT *autotext, OBJECT *o_current, gint *number)
00329 {
00330   gint i, len, isnumbered=1; 
00331   const gchar *str = NULL;
00332 
00333   len = strlen(autotext->current_searchtext);
00334   /* first find out whether we can ignore that object */
00335   if (o_current->type != OBJ_TEXT)  /* text object */
00336     return AUTONUMBER_IGNORE;
00337 
00338   str = o_text_get_string (autotext->w_current->toplevel, o_current);
00339 
00340   if (!(strlen(str) - len > 0)
00341       || !g_str_has_prefix(str, autotext->current_searchtext))
00342     return AUTONUMBER_IGNORE;
00343 
00344   /* the string object matches with its leading characters to the searchtext */
00345   /* now look for the extension, either a number or the "?" */
00346   if (g_str_has_suffix (str,"?")) {
00347     isnumbered = 0;
00348     /* There must not be any character between the "?" and the searchtext */
00349     if (strlen(str) != len+1)
00350       return AUTONUMBER_IGNORE;
00351   }
00352   else {
00353     if (!isdigit( (int) (str[len]) )) /* has at least one digit */
00354       return AUTONUMBER_IGNORE;
00355     
00356     for (i=len+1; str[i]; i++) /* and only digits */
00357       if (!isdigit( (int) (str[i]) ))
00358     return AUTONUMBER_IGNORE;
00359   }
00360   
00361   /* we have six cases, 3 from focus multiplied by 2 selection cases */
00362   if ((autotext->root_page || autotext->scope_number == SCOPE_HIERARCHY)
00363       && (o_current->selected 
00364       || autotext->scope_number == SCOPE_HIERARCHY || autotext->scope_number == SCOPE_PAGE)
00365       && (!isnumbered || (autotext->scope_overwrite)))
00366     return AUTONUMBER_RENUMBER;
00367   
00368   if (isnumbered
00369       && !(autotext->scope_skip == SCOPE_SELECTED 
00370        && !(o_current->selected)  && autotext->root_page)) {
00371     sscanf(&(str[len])," %d", number);
00372     return AUTONUMBER_RESPECT; /* numbered objects which we don't renumber */
00373   }
00374   else
00375     return AUTONUMBER_IGNORE;  /* unnumbered objects outside the focus */
00376 }
00377 
00378 
00388 void autonumber_get_used(GSCHEM_TOPLEVEL *w_current, AUTONUMBER_TEXT *autotext)
00389 {
00390   gint number, numslots, slotnr, i;
00391   OBJECT *o_current, *o_parent;
00392   AUTONUMBER_SLOT *slot;
00393   GList *slot_item;
00394   char *numslot_str, *slot_str;
00395   const GList *iter;
00396   
00397   for (iter = s_page_objects (w_current->toplevel->page_current);
00398        iter != NULL;
00399        iter = g_list_next (iter)) {
00400     o_current = iter->data;
00401     if (autonumber_match(autotext, o_current, &number) == AUTONUMBER_RESPECT) {
00402       /* check slot and maybe add it to the lists */
00403       o_parent = o_current->attached_to;
00404       if (autotext->slotting && o_parent != NULL) {
00405     /* check for slotted symbol */
00406     numslot_str =
00407       o_attrib_search_object_attribs_by_name (o_parent, "numslots", 0);
00408     if (numslot_str != NULL) {
00409       sscanf(numslot_str," %d",&numslots);
00410       g_free(numslot_str);
00411 
00412       if (numslots > 0) { 
00413         slot_str = o_attrib_search_object_attribs_by_name (o_parent, "slot", 0);
00414         if (slot_str == NULL) {
00415           s_log_message(_("slotted object without slot attribute may cause "
00416                   "problems when autonumbering slots\n"));
00417         }
00418         else {
00419           sscanf(slot_str, " %d", &slotnr);
00420           slot = g_new(AUTONUMBER_SLOT,1);
00421           slot->number = number;
00422           slot->slotnr = slotnr;
00423           slot->symbolname = o_parent->complex_basename;
00424     
00425 
00426           slot_item = g_list_find_custom(autotext->used_slots,
00427                          slot,
00428                          (GCompareFunc) freeslot_compare);
00429           if (slot_item != NULL) { /* duplicate slot in used_slots */
00430         s_log_message(_("duplicate slot may cause problems: "
00431                 "[symbolname=%s, number=%d, slot=%d]\n"),
00432                 slot->symbolname, slot->number, slot->slotnr);
00433         g_free(slot);
00434           }
00435           else {
00436         autotext->used_slots = g_list_insert_sorted(autotext->used_slots,
00437                                 slot,
00438                                 (GCompareFunc) freeslot_compare);
00439         
00440         slot_item = g_list_find_custom(autotext->free_slots,
00441                            slot,
00442                            (GCompareFunc) freeslot_compare);
00443         if (slot_item == NULL) {
00444           /* insert all slots to the list, except of the current one */
00445           for (i=1; i <= numslots; i++) {
00446             if (i != slotnr) {
00447               slot = g_memdup(slot, sizeof(AUTONUMBER_SLOT));
00448               slot->slotnr = i;
00449               autotext->free_slots = g_list_insert_sorted(autotext->free_slots,
00450                                   slot,
00451                                   (GCompareFunc) freeslot_compare);
00452             }
00453           }
00454         }
00455         else {
00456           g_free(slot_item->data);
00457           autotext->free_slots = g_list_delete_link(autotext->free_slots, slot_item);
00458         }
00459           }
00460         }
00461       }
00462     }
00463       }
00464       /* put number into the used list */
00465       autotext->used_numbers = g_list_insert_sorted(autotext->used_numbers,
00466                             GINT_TO_POINTER(number),
00467                             (GCompareFunc) autonumber_sort_numbers);
00468     }
00469   }
00470 }
00471 
00472 
00482 void autonumber_get_new_numbers(AUTONUMBER_TEXT *autotext, OBJECT *o_current, 
00483                 gint *number, gint *slot)
00484 {
00485   GList *item;
00486   gint new_number, numslots, i;
00487   AUTONUMBER_SLOT *freeslot;
00488   OBJECT *o_parent = NULL;
00489   GList *freeslot_item;
00490   gchar *numslot_str;
00491 
00492   new_number = autotext->startnum;
00493   
00494   /* Check for slots first */
00495   /* 1. are there any unused slots in the database? */
00496   o_parent = o_current->attached_to;
00497   if (autotext->slotting && o_parent != NULL) {
00498     freeslot = g_new(AUTONUMBER_SLOT,1);
00499     freeslot->symbolname = o_parent->complex_basename;
00500     freeslot->number = 0;
00501     freeslot->slotnr = 0;
00502     freeslot_item = g_list_find_custom(autotext->free_slots,
00503                        freeslot,
00504                        (GCompareFunc) freeslot_compare);
00505     g_free(freeslot);
00506     /* Yes! -> remove from database, apply it */
00507     if (freeslot_item != NULL) {
00508       freeslot = freeslot_item->data;
00509       *number = freeslot->number;
00510       *slot = freeslot->slotnr;
00511       g_free(freeslot);
00512       autotext->free_slots = g_list_delete_link(autotext->free_slots, freeslot_item);
00513       
00514       return;
00515     }
00516   }
00517 
00518   /* get a new number */
00519   item = autotext->used_numbers; 
00520   while (1) {
00521     while (item != NULL && GPOINTER_TO_INT(item->data) < new_number)
00522       item = g_list_next(item);
00523 
00524     if (item == NULL || GPOINTER_TO_INT(item->data) > new_number)
00525       break;
00526     else  /* new_number == item->data */
00527       new_number++;
00528   }
00529   *number = new_number;
00530   *slot = 0;
00531   
00532   /* insert the new number to the used list */
00533   autotext->used_numbers = g_list_insert_sorted(autotext->used_numbers,
00534                         GINT_TO_POINTER(new_number),
00535                         (GCompareFunc) autonumber_sort_numbers);
00536 
00537   /* 3. is o_current a slotted object ? */
00538   if ((autotext->slotting) && o_parent != NULL) {
00539     numslot_str =
00540       o_attrib_search_object_attribs_by_name (o_parent, "numslots", 0);
00541     if (numslot_str != NULL) {
00542       sscanf(numslot_str," %d",&numslots);
00543       g_free(numslot_str);
00544       if (numslots > 0) { 
00545     /* Yes! -> new number and slot=1; add the other slots to the database */
00546     *slot = 1;
00547     for (i=2; i <=numslots; i++) {
00548       freeslot = g_new(AUTONUMBER_SLOT,1);
00549       freeslot->symbolname = o_parent->complex_basename;
00550       freeslot->number = new_number;
00551       freeslot->slotnr = i;
00552       autotext->free_slots = g_list_insert_sorted(autotext->free_slots,
00553                               freeslot,
00554                               (GCompareFunc) freeslot_compare);
00555     }
00556       }
00557     }
00558   }
00559 }
00560 
00569 void autonumber_remove_number(AUTONUMBER_TEXT * autotext, OBJECT *o_current)
00570 {
00571   OBJECT *o_parent, *o_slot;
00572   gchar *slot_str;
00573   gchar *str = NULL;
00574 
00575   /* replace old text */
00576   str = g_strdup_printf("%s?", autotext->current_searchtext);
00577   o_text_set_string (autotext->w_current->toplevel, o_current, str);
00578   g_free (str);
00579 
00580   /* remove the slot attribute if slotting is active */
00581   if (autotext->slotting) {
00582     /* get the slot attribute */
00583     o_parent = o_current->attached_to;
00584     if (o_parent != NULL) {
00585       slot_str = s_slot_search_slot (o_parent, &o_slot);
00586       g_free (slot_str);
00587       /* Only attempt to remove non-inherited slot attributes */
00588       if (o_slot != NULL && !o_attrib_is_inherited (o_slot)) {
00589         /* delete the slot attribute */
00590         o_delete (autotext->w_current, o_slot);
00591       }
00592     }
00593   }
00594   autotext->w_current->toplevel->page_current->CHANGED = 1;
00595 }
00596 
00603 void autonumber_apply_new_text(AUTONUMBER_TEXT * autotext, OBJECT *o_current,
00604                    gint number, gint slot)
00605 {
00606   char *str;
00607 
00608   /* update the slot on the owning object */
00609   str = g_strdup_printf ("slot=%d", slot);
00610   o_slot_end (autotext->w_current, o_current->attached_to, str);
00611   g_free (str);
00612 
00613   /* replace old text */
00614   str = g_strdup_printf("%s%d", autotext->current_searchtext, number);
00615   o_text_set_string (autotext->w_current->toplevel, o_current, str);
00616   g_free (str);
00617 
00618   autotext->w_current->toplevel->page_current->CHANGED = 1;
00619 }
00620 
00621 
00631 void autonumber_text_autonumber(AUTONUMBER_TEXT *autotext)
00632 {
00633   GList *pages;
00634   GList *searchtext_list=NULL;
00635   GList *text_item, *obj_item, *page_item;
00636   OBJECT *o_current;
00637   GSCHEM_TOPLEVEL *w_current;
00638   gchar *searchtext;
00639   gchar *scope_text;
00640   gchar *new_searchtext;
00641   gint i, number, slot;
00642   GList *o_list = NULL;
00643   const GList *iter;
00644   
00645   w_current = autotext->w_current;
00646   autotext->current_searchtext = NULL;
00647   autotext->root_page = 1;
00648   autotext->used_numbers = NULL;
00649   autotext->free_slots = NULL;
00650   autotext->used_slots = NULL;
00651 
00652   scope_text = g_list_first(autotext->scope_text)->data;
00653 
00654   /* Step1: get all pages of the hierarchy */
00655   pages = s_hierarchy_traversepages (w_current->toplevel,
00656                                      w_current->toplevel->page_current,
00657                                      HIERARCHY_NODUPS);
00658 
00659   /*  g_list_foreach(pages, (GFunc) s_hierarchy_print_page, NULL); */
00660 
00661   /* Step2: if searchtext has an asterisk at the end we have to find
00662      all matching searchtextes. 
00663 
00664      Example:  "refdes=*" will match each text that starts with "refdes="
00665      and has a trailing "?" or a trailing number if the "all"-option is set.
00666      We get a list of possible prefixes: refdes=R, refdes=C.
00667 
00668      If there is only one search pattern, it becomes a single item
00669      in the searchtext list */
00670   
00671   if (strlen(scope_text) == 0) {
00672     s_log_message(_("No searchstring given in autonumber text.\n"));
00673     return; /* error */
00674   }
00675   else if (g_str_has_suffix(scope_text,"?") == TRUE) {
00676     /* single searchtext, strip of the "?" */
00677     searchtext = g_strndup(scope_text, strlen(scope_text)-1);
00678     searchtext_list=g_list_append (searchtext_list, searchtext);
00679   }
00680   else if (g_str_has_suffix(scope_text,"*") == TRUE) {
00681     /* strip of the "*" */
00682     searchtext = g_strndup(scope_text, strlen(scope_text)-1);
00683     /* collect all the possible searchtexts in all pages of the hierarchy */
00684     for (page_item = pages; page_item != NULL; page_item = g_list_next(page_item)) {
00685       s_page_goto(w_current->toplevel, page_item->data);
00686       /* iterate over all objects an look for matching searchtext's */
00687       for (iter = s_page_objects (w_current->toplevel->page_current);
00688            iter != NULL;
00689            iter = g_list_next (iter)) {
00690     o_current = iter->data;
00691     if (o_current->type == OBJ_TEXT) {
00692       if (autotext->scope_number == SCOPE_HIERARCHY
00693           || autotext->scope_number == SCOPE_PAGE
00694           || ((autotext->scope_number == SCOPE_SELECTED) && (o_current->selected))) {
00695             const gchar *str = o_text_get_string (w_current->toplevel, o_current);
00696         if (g_str_has_prefix (str, searchtext)) {
00697           /* the beginnig of the current text matches with the searchtext now */
00698           /* strip of the trailing [0-9?] chars and add it too the searchtext */
00699           for (i = strlen (str)-1;
00700            (i >= strlen(searchtext))
00701              && (str[i] == '?'
00702              || isdigit( (int) (str[i]) ));
00703            i--)
00704         ; /* void */
00705         
00706           new_searchtext = g_strndup (str, i+1);
00707           if (g_list_find_custom(searchtext_list, new_searchtext,
00708                      (GCompareFunc) strcmp) == NULL ) {
00709         searchtext_list = g_list_append(searchtext_list, new_searchtext);
00710           }
00711           else {
00712         g_free(new_searchtext);
00713           }
00714         }
00715       }
00716     }
00717       }
00718       if (autotext->scope_number == SCOPE_SELECTED || autotext->scope_number == SCOPE_PAGE)
00719     break; /* search only in the first page */
00720     }
00721     g_free(searchtext);
00722   }
00723   else {
00724     s_log_message(_("No '*' or '?' given at the end of the autonumber text.\n"));
00725     return;
00726   }
00727 
00728   /* Step3: iterate over the search items in the list */
00729   for (text_item=searchtext_list; text_item !=NULL; text_item=g_list_next(text_item)) {
00730     autotext->current_searchtext = text_item->data;
00731     /* printf("autonumber_text_autonumber: searchtext %s\n", autotext->current_searchtext); */
00732     /* decide whether to renumber page by page or get a global used-list */
00733     if (autotext->scope_skip == SCOPE_HIERARCHY) {  /* whole hierarchy database */
00734       /* renumbering all means that no db is required */
00735       if (!(autotext->scope_number == SCOPE_HIERARCHY
00736         && autotext->scope_overwrite)) {
00737     for (page_item = pages; page_item != NULL; page_item = g_list_next(page_item)) {
00738       autotext->root_page = (pages->data == page_item->data);
00739       s_page_goto(w_current->toplevel, page_item->data);
00740       autonumber_get_used(w_current, autotext);
00741     }
00742       }
00743     }
00744     
00745     /* renumber the elements */
00746     for (page_item = pages; page_item != NULL; page_item = g_list_next(page_item)) {
00747       s_page_goto(w_current->toplevel, page_item->data);
00748       autotext->root_page = (pages->data == page_item->data);
00749       /* build a page database if we're numbering pagebypage or selection only*/
00750       if (autotext->scope_skip == SCOPE_PAGE || autotext->scope_skip == SCOPE_SELECTED) {
00751     autonumber_get_used(w_current, autotext);
00752       }
00753       
00754       /* RENUMBER CODE FOR ONE PAGE AND ONE SEARCHTEXT*/
00755       /* 1. get objects to renumber */
00756       for (iter = s_page_objects (w_current->toplevel->page_current);
00757            iter != NULL;
00758            iter = g_list_next (iter)) {
00759         o_current = iter->data;
00760     if (autonumber_match(autotext, o_current, &number) == AUTONUMBER_RENUMBER) {
00761       /* put number into the used list */
00762       o_list = g_list_append(o_list, o_current);
00763     }
00764       }
00765 
00766       /* 2. sort object list */
00767       switch (autotext->order) {
00768       case AUTONUMBER_SORT_YX:
00769     o_list=g_list_sort(o_list, autonumber_sort_yx);
00770     break;
00771       case AUTONUMBER_SORT_YX_REV:
00772     o_list=g_list_sort(o_list, autonumber_sort_yx_rev);
00773     break;
00774       case AUTONUMBER_SORT_XY:
00775     o_list=g_list_sort(o_list, autonumber_sort_xy);
00776     break;
00777       case AUTONUMBER_SORT_XY_REV:
00778     o_list=g_list_sort(o_list, autonumber_sort_xy_rev);
00779     break;
00780       case AUTONUMBER_SORT_DIAGONAL:
00781     o_list=g_list_sort(o_list, autonumber_sort_diagonal);
00782     break;
00783       default:
00784     ; /* unsorted file order */
00785       }
00786      
00787       /* 3. renumber/reslot the objects */
00788       for(obj_item=o_list; obj_item != NULL; obj_item=g_list_next(obj_item)) {
00789     o_current= obj_item->data;
00790         if(autotext->removenum) {
00791       autonumber_remove_number(autotext, o_current);        
00792     } else {
00793       /* get valid numbers from the database */
00794       autonumber_get_new_numbers(autotext, o_current, &number, &slot);
00795       /* and apply it. TODO: join these two functions */
00796       autonumber_apply_new_text(autotext, o_current, number, slot);
00797     }
00798       }
00799       g_list_free(o_list);
00800       o_list = NULL;
00801 
00802       /* destroy the page database */
00803       if (autotext->scope_skip == SCOPE_PAGE 
00804       || autotext->scope_skip == SCOPE_SELECTED) 
00805     autonumber_clear_database(autotext);
00806 
00807       if (autotext->scope_number == SCOPE_SELECTED 
00808       || autotext->scope_number == SCOPE_PAGE)
00809     break; /* only renumber the parent page (the first page) */
00810     }
00811     autonumber_clear_database(autotext);   /* cleanup */
00812   }
00813 
00814   /* cleanup and redraw all*/
00815   g_list_foreach(searchtext_list, (GFunc) g_free, NULL);
00816   g_list_free(searchtext_list);
00817   s_page_goto(w_current->toplevel, pages->data); /* go back to the root page */
00818   o_invalidate_all (w_current);
00819   g_list_free(pages);
00820   o_undo_savestate(w_current, UNDO_ALL);
00821 }
00822 
00823 /* ***** UTILITY GUI FUNCTIONS (move to a separate file in the future?) **** */
00824 
00830 GtkWidget* lookup_widget(GtkWidget *widget, const gchar *widget_name)
00831 {
00832   GtkWidget *found_widget;
00833 
00834   found_widget = (GtkWidget*) g_object_get_data(G_OBJECT(widget), 
00835                         widget_name);
00836 
00837   return found_widget;
00838 }
00839 
00845 void autonumber_sortorder_create(GSCHEM_TOPLEVEL *w_current, GtkWidget *sort_order)
00846 {
00847   GtkListStore *store;
00848   GtkTreeIter iter;
00849   GtkCellRenderer *renderer;
00850   GdkPixbuf *pixbuf;
00851   gchar *path;
00852   GError *error=NULL;
00853 
00854   gchar *filenames[] = {"gschem-diagonal.png", 
00855             "gschem-top2bottom.png", "gschem-bottom2top.png",
00856             "gschem-left2right.png", "gschem-right2left.png",
00857             "gschem-fileorder.png",
00858             NULL};
00859   gchar *names[] = {N_("Diagonal"),
00860             N_("Top to bottom"), N_("Bottom to top"),
00861             N_("Left to right"), N_("Right to left"),
00862             N_("File order"),
00863             NULL};
00864   gint i;
00865 
00866   store = gtk_list_store_new(2, G_TYPE_STRING, GDK_TYPE_PIXBUF); 
00867 
00868   for (i=0; filenames[i] != NULL; i++) {
00869     path=g_build_filename(w_current->toplevel->bitmap_directory,
00870              filenames[i], NULL);
00871     pixbuf = gdk_pixbuf_new_from_file(path, &error);
00872     g_free(path);
00873     gtk_list_store_append(store, &iter);
00874     gtk_list_store_set(store, &iter, 
00875                0, _(names[i]),
00876                1, pixbuf,
00877                -1);
00878   }
00879 
00880   gtk_combo_box_set_model(GTK_COMBO_BOX(sort_order), GTK_TREE_MODEL(store));
00881   renderer = gtk_cell_renderer_text_new ();
00882 
00883   gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (sort_order),
00884                   renderer, TRUE);
00885   gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (sort_order),
00886                   renderer, "text", 0, NULL);
00887   renderer = gtk_cell_renderer_pixbuf_new();
00888   g_object_set(G_OBJECT(renderer), "xpad", 5, "ypad", 5, NULL);
00889 
00890   gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (sort_order),
00891                   renderer, FALSE);
00892   gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (sort_order),
00893                   renderer, "pixbuf", 1, NULL);
00894 }
00895 
00896 /* ***** STATE STRUCT HANDLING (interface between GUI and backend code) **** */
00897 
00903 GList *autonumber_history_add(GList *history, gchar *text)
00904 {
00905   /* Search for this text in history and delete it (so we don't have
00906    * duplicate entries) */
00907 
00908   GList *cur;
00909 
00910   cur=history;
00911   while(cur!=NULL) {
00912     if(!strcmp(text, cur->data)) {
00913       history=g_list_remove_link(history, cur);
00914 
00915       g_free(cur->data);
00916       g_list_free(cur);
00917       break;
00918     }
00919     cur=g_list_next(cur);
00920   }
00921 
00922   /* Add the new text at the beginning of the list */
00923 
00924   history=g_list_prepend(history, text);
00925 
00926   /* Truncate history */
00927   while(g_list_length(history) > HISTORY_LENGTH) {
00928     GList *last = g_list_last(history);
00929 
00930     history = g_list_remove_link(history, last);
00931 
00932     g_free(last->data);
00933     g_list_free(last);
00934   }
00935 
00936   return history;
00937 }
00938 
00943 AUTONUMBER_TEXT *autonumber_init_state()
00944 {
00945   AUTONUMBER_TEXT *autotext;
00946 
00947   /* Default contents of the combo box history */
00948   gchar *default_text[] = {
00949     "refdes=*", 
00950     "refdes=C?", 
00951     "refdes=D?", 
00952     "refdes=I?",
00953     "refdes=L?", 
00954     "refdes=Q?", 
00955     "refdes=R?", 
00956     "refdes=T?",
00957     "refdes=U?", 
00958     "refdes=X?", 
00959     "netname=*", 
00960     "netname=A?",
00961     "netname=D?", 
00962     NULL
00963   };
00964   gchar **t;
00965 
00966   autotext = g_new(AUTONUMBER_TEXT, 1);
00967 
00968   if(autotext==NULL) return NULL;
00969 
00970   autotext->scope_text = NULL;
00971   t=default_text;
00972   while(*t!=NULL) {
00973     autotext->scope_text=g_list_append(autotext->scope_text, 
00974                        g_strdup(*t));
00975     t++;
00976   }
00977 
00978   autotext->scope_skip = SCOPE_PAGE;
00979   autotext->scope_number = SCOPE_SELECTED;
00980 
00981   autotext->scope_overwrite = 0;
00982   autotext->order = AUTONUMBER_SORT_DIAGONAL;
00983 
00984   autotext->startnum=1;
00985 
00986   autotext->removenum=0;
00987   autotext->slotting=0;
00988 
00989   autotext->dialog = NULL;
00990 
00991   return autotext;
00992 }
00993 
00998 void autonumber_set_state(AUTONUMBER_TEXT *autotext)
00999 {
01000   GtkWidget *widget;
01001   GtkTreeModel *model;
01002   GList *el;
01003   /* Scope */
01004 
01005   /* Search text history */
01006   widget = lookup_widget(autotext->dialog, "scope_text");
01007 
01008   /* Simple way to clear the ComboBox. Owen from #gtk+ says: 
01009    *
01010    * Yeah, it's just slightly "shady" ... if you want to stick to fully 
01011    * advertised API, you need to remember how many rows you added and 
01012    * use gtk_combo_box_remove_text() */
01013 
01014   model = gtk_combo_box_get_model(GTK_COMBO_BOX(widget));
01015   gtk_list_store_clear(GTK_LIST_STORE(model));
01016 
01017   for (el= autotext->scope_text; el != NULL; el=g_list_next(el)) {
01018     gtk_combo_box_append_text(GTK_COMBO_BOX(widget), el->data);
01019   }
01020 
01021   widget = gtk_bin_get_child(GTK_BIN(widget));
01022   gtk_entry_set_text(GTK_ENTRY(widget), g_list_first(autotext->scope_text)->data);
01023 
01024   widget = lookup_widget(autotext->dialog, "scope_skip");
01025   gtk_combo_box_set_active(GTK_COMBO_BOX(widget),
01026                autotext->scope_skip);
01027 
01028   widget = lookup_widget(autotext->dialog, "scope_number");
01029   gtk_combo_box_set_active(GTK_COMBO_BOX(widget), 
01030                autotext->scope_number);
01031 
01032   widget = lookup_widget(autotext->dialog, "scope_overwrite");
01033   gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), 
01034                    autotext->scope_overwrite);
01035 
01036   /* Options */
01037   widget = lookup_widget(autotext->dialog, "opt_startnum");
01038   gtk_spin_button_set_value(GTK_SPIN_BUTTON(widget), 
01039                 autotext->startnum);
01040 
01041   widget = lookup_widget(autotext->dialog, "sort_order");
01042   gtk_combo_box_set_active(GTK_COMBO_BOX(widget), autotext->order);
01043 
01044   widget = lookup_widget(autotext->dialog, "opt_removenum");
01045   gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), 
01046                    autotext->removenum);
01047 
01048   widget = lookup_widget(autotext->dialog, "opt_slotting");
01049   gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget),
01050                    autotext->slotting);
01051 }
01052 
01060 void autonumber_get_state(AUTONUMBER_TEXT *autotext)
01061 {
01062   GtkWidget *widget;
01063   gchar *text;
01064 
01065   /* Scope */
01066 
01067   /* Search text history */
01068   widget = lookup_widget(autotext->dialog, "scope_text");
01069   widget = gtk_bin_get_child(GTK_BIN(widget));
01070   text = g_strdup(gtk_entry_get_text( GTK_ENTRY(widget)));
01071 
01072   autotext->scope_text=autonumber_history_add(autotext->scope_text, text);
01073 
01074   widget = lookup_widget(autotext->dialog, "scope_skip");
01075   autotext->scope_skip = gtk_combo_box_get_active( GTK_COMBO_BOX(widget) );
01076 
01077   widget = lookup_widget(autotext->dialog, "scope_number");
01078   autotext->scope_number = gtk_combo_box_get_active(GTK_COMBO_BOX(widget) );
01079 
01080   widget = lookup_widget(autotext->dialog, "scope_overwrite");
01081   autotext->scope_overwrite = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
01082 
01083   /* Sort order */
01084   widget = lookup_widget(autotext->dialog, "sort_order");
01085   autotext->order= gtk_combo_box_get_active(GTK_COMBO_BOX(widget));
01086 
01087   /* Options */
01088   widget = lookup_widget(autotext->dialog, "opt_startnum");
01089   autotext->startnum=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(widget));
01090 
01091   widget = lookup_widget(autotext->dialog, "opt_removenum");
01092   autotext->removenum = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
01093 
01094   widget = lookup_widget(autotext->dialog, "opt_slotting");
01095   autotext->slotting = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
01096 }
01097 
01098 /* ***** CALLBACKS (functions that get called directly from the GTK) ******* */
01099 
01106 void autonumber_text_response(GtkWidget * widget, gint response,
01107                   AUTONUMBER_TEXT *autotext)
01108 {
01109   switch (response) {
01110   case GTK_RESPONSE_ACCEPT:
01111     autonumber_get_state(autotext);
01112     if (autotext->removenum == TRUE && autotext->scope_overwrite == FALSE) {
01113       /* temporarly set the overwrite flag */
01114       autotext->scope_overwrite = TRUE;
01115       autonumber_text_autonumber(autotext);
01116       autotext->scope_overwrite = FALSE;
01117     }
01118     else {
01119       autonumber_text_autonumber(autotext);
01120     }
01121     break;
01122   case GTK_RESPONSE_REJECT:
01123   case GTK_RESPONSE_DELETE_EVENT:
01124     gtk_widget_destroy(autotext->dialog);
01125     autotext->dialog = NULL;
01126     break;
01127   default:
01128     printf("ERROR: autonumber_text_response(): strange signal %d\n",response);
01129   }
01130 }
01131 
01132 
01138 void autonumber_removenum_toggled(GtkWidget * opt_removenum, 
01139                   AUTONUMBER_TEXT *autotext)
01140 {
01141   GtkWidget *scope_overwrite;
01142 
01143   scope_overwrite=lookup_widget(autotext->dialog, "scope_overwrite");
01144 
01145   /* toggle activity of scope overwrite with respect to removenum */
01146   if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(opt_removenum))) {
01147     gtk_widget_set_sensitive(scope_overwrite, 0);
01148   } else {
01149     gtk_widget_set_sensitive(scope_overwrite, 1);
01150   }
01151 }
01152 
01153 
01154 /* ***** DIALOG SET-UP ***************************************************** */
01155 
01170 GtkWidget* autonumber_create_dialog(GSCHEM_TOPLEVEL *w_current)
01171 {
01172   GtkWidget *autonumber_text;
01173   GtkWidget *vbox1;
01174   GtkWidget *alignment1;
01175   GtkWidget *vbox3;
01176   GtkWidget *table1;
01177   GtkWidget *label4;
01178   GtkWidget *scope_text;
01179   GtkWidget *label8;
01180   GtkWidget *label6;
01181   GtkWidget *scope_number;
01182   GtkWidget *scope_skip;
01183   GtkWidget *scope_overwrite;
01184   GtkWidget *label1;
01185   GtkWidget *alignment3;
01186   GtkWidget *vbox4;
01187   GtkWidget *table3;
01188   GtkWidget *label12;
01189   GtkWidget *label13;
01190   GtkObject *opt_startnum_adj;
01191   GtkWidget *opt_startnum;
01192   GtkWidget *sort_order;
01193   GtkWidget *opt_removenum;
01194   GtkWidget *opt_slotting;
01195   GtkWidget *label3;
01196 
01197 
01198   autonumber_text = gschem_dialog_new_with_buttons(_("Autonumber text"),
01199                                                    GTK_WINDOW(w_current->main_window),
01200                                                    0, /* not modal */
01201                                                    "autonumber", w_current,
01202                                                    GTK_STOCK_CLOSE,
01203                                                    GTK_RESPONSE_REJECT,
01204                                                    GTK_STOCK_APPLY,
01205                                                    GTK_RESPONSE_ACCEPT,
01206                                                    NULL);
01207   /* Set the alternative button order (ok, cancel, help) for other systems */
01208   gtk_dialog_set_alternative_button_order(GTK_DIALOG(autonumber_text),
01209                       GTK_RESPONSE_ACCEPT,
01210                       GTK_RESPONSE_REJECT,
01211                       -1);
01212 
01213   gtk_window_position (GTK_WINDOW (autonumber_text),
01214                GTK_WIN_POS_MOUSE);
01215   
01216   gtk_container_border_width(GTK_CONTAINER(autonumber_text), 
01217                  DIALOG_BORDER_SPACING);
01218   vbox1 = GTK_DIALOG(autonumber_text)->vbox;
01219   gtk_box_set_spacing(GTK_BOX(vbox1), DIALOG_V_SPACING);
01220 
01221   /* scope section */
01222   label1 = gtk_label_new (_("<b>Scope</b>"));
01223   gtk_label_set_use_markup (GTK_LABEL (label1), TRUE);
01224   gtk_misc_set_alignment (GTK_MISC(label1), 0, 0);
01225   gtk_box_pack_start (GTK_BOX(vbox1), label1, TRUE, TRUE, 0);
01226   gtk_widget_show (label1);
01227 
01228   alignment1 = gtk_alignment_new (0, 0, 1, 1);
01229   gtk_widget_show (alignment1);
01230   gtk_box_pack_start (GTK_BOX (vbox1), alignment1, TRUE, TRUE, 0);
01231   gtk_alignment_set_padding (GTK_ALIGNMENT (alignment1), 
01232                  0, 0, DIALOG_INDENTATION, 0);
01233 
01234   vbox3 = gtk_vbox_new (FALSE, 0);
01235   gtk_widget_show (vbox3);
01236   gtk_container_add (GTK_CONTAINER (alignment1), vbox3);
01237 
01238   table1 = gtk_table_new (3, 2, FALSE);
01239   gtk_widget_show (table1);
01240   gtk_box_pack_start (GTK_BOX (vbox3), table1, TRUE, TRUE, 0);
01241   gtk_table_set_row_spacings (GTK_TABLE (table1), DIALOG_V_SPACING);
01242   gtk_table_set_col_spacings (GTK_TABLE (table1), DIALOG_H_SPACING);
01243 
01244   label4 = gtk_label_new (_("Search for:"));
01245   gtk_widget_show (label4);
01246   gtk_table_attach (GTK_TABLE (table1), label4, 0, 1, 0, 1,
01247                     (GtkAttachOptions) (GTK_FILL),
01248                     (GtkAttachOptions) (0), 0, 0);
01249   gtk_misc_set_alignment (GTK_MISC (label4), 0, 0.5);
01250 
01251   scope_text = gtk_combo_box_entry_new_text ();
01252   gtk_entry_set_activates_default(GTK_ENTRY(gtk_bin_get_child(GTK_BIN(scope_text))), TRUE);
01253   gtk_widget_show (scope_text);
01254   gtk_table_attach (GTK_TABLE (table1), scope_text, 1, 2, 0, 1,
01255                     (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
01256                     (GtkAttachOptions) (GTK_FILL), 0, 0);
01257 
01258   label8 = gtk_label_new (_("Autonumber text in:"));
01259   gtk_widget_show (label8);
01260   gtk_table_attach (GTK_TABLE (table1), label8, 0, 1, 1, 2,
01261                     (GtkAttachOptions) (GTK_FILL),
01262                     (GtkAttachOptions) (0), 0, 0);
01263   gtk_misc_set_alignment (GTK_MISC (label8), 0, 0.5);
01264 
01265   label6 = gtk_label_new (_("Skip numbers found in:"));
01266   gtk_widget_show (label6);
01267   gtk_table_attach (GTK_TABLE (table1), label6, 0, 1, 2, 3,
01268                     (GtkAttachOptions) (GTK_FILL),
01269                     (GtkAttachOptions) (0), 0, 0);
01270   gtk_misc_set_alignment (GTK_MISC (label6), 0, 0.5);
01271 
01272   scope_number = gtk_combo_box_new_text ();
01273   gtk_widget_show (scope_number);
01274   gtk_table_attach (GTK_TABLE (table1), scope_number, 1, 2, 1, 2,
01275                     (GtkAttachOptions) (GTK_FILL),
01276                     (GtkAttachOptions) (GTK_FILL), 0, 0);
01277   gtk_combo_box_append_text (GTK_COMBO_BOX (scope_number), _("Selected objects"));
01278   gtk_combo_box_append_text (GTK_COMBO_BOX (scope_number), _("Current page"));
01279   gtk_combo_box_append_text (GTK_COMBO_BOX (scope_number), _("Whole hierarchy"));
01280 
01281   scope_skip = gtk_combo_box_new_text ();
01282   gtk_widget_show (scope_skip);
01283   gtk_table_attach (GTK_TABLE (table1), scope_skip, 1, 2, 2, 3,
01284                     (GtkAttachOptions) (GTK_FILL),
01285                     (GtkAttachOptions) (GTK_FILL), 0, 0);
01286   gtk_combo_box_append_text (GTK_COMBO_BOX (scope_skip), _("Selected objects"));
01287   gtk_combo_box_append_text (GTK_COMBO_BOX (scope_skip), _("Current page"));
01288   gtk_combo_box_append_text (GTK_COMBO_BOX (scope_skip), _("Whole hierarchy"));
01289 
01290   scope_overwrite = gtk_check_button_new_with_mnemonic (_("Overwrite existing numbers"));
01291   gtk_widget_show (scope_overwrite);
01292   gtk_box_pack_start (GTK_BOX (vbox3), scope_overwrite, FALSE, FALSE, 6);
01293 
01294   /* Options section */
01295   label3 = gtk_label_new (_("<b>Options</b>"));
01296   gtk_label_set_use_markup (GTK_LABEL (label3), TRUE);
01297   gtk_misc_set_alignment(GTK_MISC(label3), 0, 0);
01298   gtk_widget_show (label3);
01299   gtk_box_pack_start(GTK_BOX(vbox1), label3, TRUE, TRUE, 0);
01300 
01301   alignment3 = gtk_alignment_new (0, 0, 1, 1);
01302   gtk_widget_show (alignment3);
01303   gtk_box_pack_start(GTK_BOX(vbox1), alignment3, TRUE, TRUE, 0);
01304   gtk_alignment_set_padding (GTK_ALIGNMENT (alignment3), 
01305                  0, 0, DIALOG_INDENTATION, 0);
01306 
01307   vbox4 = gtk_vbox_new (FALSE, 3);
01308   gtk_widget_show (vbox4);
01309   gtk_container_add (GTK_CONTAINER (alignment3), vbox4);
01310 
01311   table3 = gtk_table_new (2, 2, FALSE);
01312   gtk_widget_show (table3);
01313   gtk_box_pack_start (GTK_BOX (vbox4), table3, TRUE, TRUE, 0);
01314   gtk_table_set_row_spacings (GTK_TABLE (table3), DIALOG_V_SPACING);
01315   gtk_table_set_col_spacings (GTK_TABLE (table3), DIALOG_H_SPACING);
01316 
01317   label12 = gtk_label_new (_("Starting number:"));
01318   gtk_widget_show (label12);
01319   gtk_table_attach (GTK_TABLE (table3), label12, 0, 1, 0, 1,
01320                     (GtkAttachOptions) (GTK_FILL),
01321                     (GtkAttachOptions) (0), 0, 0);
01322   gtk_misc_set_alignment (GTK_MISC (label12), 0, 0.5);
01323 
01324   label13 = gtk_label_new (_("Sort order:"));
01325   gtk_widget_show (label13);
01326   gtk_table_attach (GTK_TABLE (table3), label13, 0, 1, 1, 2,
01327                     (GtkAttachOptions) (GTK_FILL),
01328                     (GtkAttachOptions) (0), 0, 0);
01329   gtk_misc_set_alignment (GTK_MISC (label13), 0, 0.5);
01330 
01331   opt_startnum_adj = gtk_adjustment_new (1, 0, 10000, 1, 10, 10);
01332   opt_startnum = gtk_spin_button_new (GTK_ADJUSTMENT (opt_startnum_adj), 1, 0);
01333   gtk_entry_set_activates_default(GTK_ENTRY(opt_startnum), TRUE);
01334   gtk_widget_show (opt_startnum);
01335   gtk_table_attach (GTK_TABLE (table3), opt_startnum, 1, 2, 0, 1,
01336                     (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
01337                     (GtkAttachOptions) (0), 0, 0);
01338 
01339   sort_order = gtk_combo_box_new();
01340   gtk_widget_show (sort_order);
01341   gtk_table_attach (GTK_TABLE (table3), sort_order, 1, 2, 1, 2,
01342                     (GtkAttachOptions) (GTK_FILL),
01343                     (GtkAttachOptions) (GTK_FILL), 0, 0);
01344 
01345   opt_removenum = gtk_check_button_new_with_mnemonic (_("Remove numbers"));
01346   gtk_widget_show (opt_removenum);
01347   gtk_box_pack_start (GTK_BOX (vbox4), opt_removenum, FALSE, FALSE, 0);
01348 
01349   opt_slotting = gtk_check_button_new_with_mnemonic (_("Automatic slotting"));
01350   gtk_widget_show (opt_slotting);
01351   gtk_box_pack_start (GTK_BOX (vbox4), opt_slotting, FALSE, FALSE, 0);
01352 
01353   /* Store pointers to all widgets, for use by lookup_widget(). */
01354   GLADE_HOOKUP_OBJECT (autonumber_text, scope_text, "scope_text");
01355   GLADE_HOOKUP_OBJECT (autonumber_text, scope_number, "scope_number");
01356   GLADE_HOOKUP_OBJECT (autonumber_text, scope_skip, "scope_skip");
01357   GLADE_HOOKUP_OBJECT (autonumber_text, scope_overwrite, "scope_overwrite");
01358   GLADE_HOOKUP_OBJECT (autonumber_text, opt_startnum, "opt_startnum");
01359   GLADE_HOOKUP_OBJECT (autonumber_text, sort_order, "sort_order");
01360   GLADE_HOOKUP_OBJECT (autonumber_text, opt_removenum, "opt_removenum");
01361   GLADE_HOOKUP_OBJECT (autonumber_text, opt_slotting, "opt_slotting");
01362 
01363   return autonumber_text;
01364 }
01365 
01373 void autonumber_text_dialog(GSCHEM_TOPLEVEL *w_current)
01374 {
01375   static AUTONUMBER_TEXT *autotext = NULL;
01376 
01377   GtkWidget *opt_removenum = NULL;
01378   GtkWidget *sort_order = NULL;
01379 
01380   if(autotext == NULL) {
01381     /* first call of this function, init dialog structure */
01382     autotext=autonumber_init_state();
01383   }
01384 
01385   /* set the GSCHEM_TOPLEVEL always. Can it be changed between the calls??? */
01386   autotext->w_current = w_current;
01387 
01388   if(autotext->dialog == NULL) {
01389     /* Dialog is not currently displayed - create it */
01390 
01391     autotext->dialog = autonumber_create_dialog(w_current);
01392 
01393     opt_removenum = lookup_widget(autotext->dialog, "opt_removenum");
01394     sort_order = lookup_widget(autotext->dialog, "sort_order");
01395 
01396     autonumber_sortorder_create(w_current, sort_order);
01397 
01398     gtk_dialog_set_default_response (GTK_DIALOG (autotext->dialog), 
01399                                      GTK_RESPONSE_ACCEPT);
01400 
01401     g_signal_connect (G_OBJECT (autotext->dialog), "response",
01402                       G_CALLBACK (autonumber_text_response),
01403                       autotext);
01404 
01405     g_signal_connect (G_OBJECT (opt_removenum), "clicked",
01406                       G_CALLBACK (autonumber_removenum_toggled),
01407                       autotext);
01408 
01409     autonumber_set_state(autotext);
01410 
01411     gtk_widget_show_all(autotext->dialog);
01412   }
01413 
01414   /* if the dialog is in the background or minimized: show it */
01415   gtk_window_present(GTK_WINDOW(autotext->dialog));
01416 }
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines