gschem
|
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 }