Index: trunk/doc-rnd/TODO =================================================================== --- trunk/doc-rnd/TODO (revision 1576) +++ trunk/doc-rnd/TODO (revision 1577) @@ -1,9 +1,11 @@ +- test before release: gsch2pcb-rnd + - random breaks: - gpmi plugin make is not triggered when gpmi is a buildin - gpmi packages are not installed in plugins/pcb-rnd-gpmi -- vemdordrill conversion: - - test vendordrill if it works +- vendordrill conversion: + + test vendordrill if it works - vendordrill: free at exit (check for leaks) - resource conv cleanup: @@ -39,6 +41,7 @@ - gui load dialog with tags listed - reduce + - centralize all keyeq() calls - replace hid_load_settings() with lihata - hash in hid_attrib.c? - hash in hid_color.c; test: eps Index: trunk/scconfig/plugins.h =================================================================== --- trunk/scconfig/plugins.h (revision 1576) +++ trunk/scconfig/plugins.h (revision 1577) @@ -17,7 +17,7 @@ plugin_header("\nFootprint backends:\n") plugin_def("fp_fs", "filesystem footprints", sbuildin) -plugin_def("fp_wget", "web footprints", sdisable) +plugin_def("fp_wget", "web footprints", sbuildin) plugin_header("\nImport plugins:\n") plugin_def("import_sch", "import sch", sbuildin) Index: trunk/src/data.c =================================================================== --- trunk/src/data.c (revision 1576) +++ trunk/src/data.c (revision 1577) @@ -49,7 +49,6 @@ int LayerStack[MAX_LAYER]; /* determines the layer draw order */ BufferType Buffers[MAX_BUFFER]; /* my buffers */ -LibraryType Library; /* the library */ bool Bumped; /* if the undo serial number has changed */ int addedLines; Index: trunk/src/data.h =================================================================== --- trunk/src/data.h (revision 1576) +++ trunk/src/data.h (revision 1577) @@ -55,8 +55,6 @@ extern BufferType Buffers[MAX_BUFFER]; -extern LibraryType Library; - /*extern DeviceInfoType PrintingDevice[];*/ extern char *Progname; Index: trunk/src/global.h =================================================================== --- trunk/src/global.h (revision 1576) +++ trunk/src/global.h (revision 1577) @@ -255,8 +255,10 @@ *Package, /* package */ *Value, /* the value field */ *Description; /* some descritional text */ +#if 0 fp_type_t Type; void **Tags; /* an array of void * tag IDs; last tag ID is NULL */ +#endif }; /* If the internal flag is set, the only field that is valid is Name, Index: trunk/src/main.c =================================================================== --- trunk/src/main.c (revision 1576) +++ trunk/src/main.c (revision 1577) @@ -1598,7 +1598,7 @@ uninit_strflags_buf(); uninit_strflags_layerlist(); - FreeLibraryMemory(&Library); + fp_free_children(&library); fp_uninit(); file_uninit(); funchash_uninit(); @@ -1813,7 +1813,7 @@ /* read the library file and display it if it's not empty */ - if (!fp_read_lib_all() && Library.MenuN) + if (!fp_read_lib_all() && library.data.dir.children.used) hid_action("LibraryChanged"); if (Settings.ScriptFilename) { Index: trunk/src/mymem.c =================================================================== --- trunk/src/mymem.c (revision 1576) +++ trunk/src/mymem.c (revision 1577) @@ -716,8 +716,6 @@ free(entry->AllocatedMemory); if (!entry->ListEntry_dontfree) free(entry->ListEntry); - if (entry->Tags != NULL) - free(entry->Tags); } END_LOOP; free(menu->Entry); Index: trunk/src/plug_footprint.c =================================================================== --- trunk/src/plug_footprint.c (revision 1576) +++ trunk/src/plug_footprint.c (revision 1577) @@ -38,6 +38,7 @@ #include plug_fp_t *plug_fp_chain = NULL; +library_t library; int fp_dupname(const char *name, char **basename, char **params) { @@ -111,12 +112,15 @@ fctx->backend->fclose(fctx->backend, f, fctx); } -LibraryEntryType *fp_append_entry(LibraryMenuType *parent, const char *dirname, const char *name, fp_type_t type, void *tags[]) +library_t *fp_append_entry(library_t *parent, const char *dirname, const char *name, fp_type_t type, void *tags[]) { - LibraryEntryType *entry; /* Pointer to individual menu entry */ + library_t *entry; /* Pointer to individual menu entry */ size_t len; - entry = GetLibraryEntryMemory(parent); + assert(parent->type == LIB_DIR); + entry = get_library_memory(parent); + if (entry == NULL) + return NULL; /* * entry->AllocatedMemory points to abs path to the footprint. @@ -123,36 +127,158 @@ * entry->ListEntry points to fp name itself. */ len = strlen(dirname) + strlen("/") + strlen(name) + 8; - entry->AllocatedMemory = (char *) calloc(1, len); - strcat(entry->AllocatedMemory, dirname); - strcat(entry->AllocatedMemory, PCB_DIR_SEPARATOR_S); + entry->data.fp.full_path = malloc(len); + strcpy(entry->data.fp.full_path, dirname); + strcat(entry->data.fp.full_path, PCB_DIR_SEPARATOR_S); /* store pointer to start of footprint name */ - entry->ListEntry = entry->AllocatedMemory + strlen(entry->AllocatedMemory); - entry->ListEntry_dontfree = 1; + entry->name = entry->data.fp.full_path + strlen(entry->data.fp.full_path); + entry->dontfree_name = 1; /* Now place footprint name into AllocatedMemory */ - strcat(entry->AllocatedMemory, name); + strcat(entry->data.fp.full_path, name); if (type == PCB_FP_PARAMETRIC) - strcat(entry->AllocatedMemory, "()"); + strcat(entry->data.fp.full_path, "()"); - entry->Type = type; + entry->type = LIB_FOOTPRINT; + entry->data.fp.type = type; + entry->data.fp.tags = tags; +} - entry->Tags = tags; +library_t *fp_lib_search_len(library_t *dir, const char *name, int name_len) +{ + library_t *l; + int n; + + if (dir->type != LIB_DIR) + return NULL; + + for(n = 0, l = dir->data.dir.children.array; n < dir->data.dir.children.used; n++, l++) + if (strncmp(l->name, name, name_len) == 0) + return l; + + return NULL; } -LibraryMenuType *fp_append_topdir(const char *parent_dir, const char *dir_name, int *menuidx) +library_t *fp_lib_search(library_t *dir, const char *name) { - LibraryMenuType *menu; + library_t *l; + int n; - /* Get pointer to memory holding menu */ - menu = GetLibraryMenuMemory(&Library, menuidx); + if (dir->type != LIB_DIR) + return NULL; - /* Populate menuname and path vars */ - menu->Name = strdup(dir_name); - menu->directory = strdup(parent_dir); + for(n = 0, l = dir->data.dir.children.array; n < dir->data.dir.children.used; n++, l++) + if (strcmp(l->name, name) == 0) + return l; - return menu; + return NULL; } + +library_t *fp_mkdir_len(library_t *parent, const char *name, int name_len) +{ + library_t *l = get_library_memory(parent); + + if (name_len > 0) + l->name = strndup(name, name_len); + else + l->name = strdup(name); + l->dontfree_name = 0; + l->parent = parent; + + return l; +} + +library_t *fp_mkdir_p(const char *path) +{ + library_t *l, *parent = NULL; + const char *next; + + /* search for the last existing dir in the path */ + + while(*path == '/') path++; + for(parent = l = &library; l != NULL; parent = l,path = next) { + next = strchr(path, '/'); + if (next == NULL) + l = fp_lib_search(l, path); + else + l = fp_lib_search_len(l, path, next-path); + + /* skip path sep */ + if (next != NULL) { + while(*next == '/') next++; + if (*next == '\0') + next = NULL; + } + + /* last elem of the path */ + if (next == NULL) { + if (l != NULL) + return l; + break; /* found a non-existing node */ + } + + if (l == NULL) + break; + } + + /* by now path points to the first non-existing dir, under parent */ + for(;path != NULL; path = next) { + next = strchr(path, '/'); + parent = fp_mkdir_len(parent, path, next-path); + if (next != NULL) { + while(*next == '/') next++; + if (*next == '\0') + next = NULL; + } + } + + return parent; +} + +void fp_free_children(library_t *parent) +{ + +} + + +void fp_sort_children(library_t *parent) +{ +/* int i; + qsort(lib->Menu, lib->MenuN, sizeof(lib->Menu[0]), netlist_sort); + for (i = 0; i < lib->MenuN; i++) + qsort(lib->Menu[i].Entry, lib->Menu[i].EntryN, sizeof(lib->Menu[i].Entry[0]), netnode_sort);*/ +} + +void fp_rmdir(library_t *dir) +{ + +} + +/* Debug functions */ +void fp_dump_dir(library_t *dir, int level) +{ + library_t *l; + int n, p; + + for(n = 0, l = dir->data.dir.children.array; n < dir->data.dir.children.used; n++, l++) { + for(p = 0; p < level; p++) + putchar(' '); + if (l->type == LIB_DIR) { + printf("%s/\n", l->name); + fp_dump_dir(l, level+1); + } + else if (l->type == LIB_FOOTPRINT) + printf("%s\n", l->name); + else + printf("*INVALID*\n"); + } +} + +void fp_dump() +{ + fp_dump_dir(&library, 0); +} + Index: trunk/src/plug_footprint.h =================================================================== --- trunk/src/plug_footprint.h (revision 1576) +++ trunk/src/plug_footprint.h (revision 1577) @@ -2,6 +2,7 @@ #define PCB_PLUG_FOOTPRINT_H #include +#include "vtlibrary.h" typedef struct plug_fp_s plug_fp_t; @@ -17,14 +18,6 @@ FILE *fp_fopen(const char *path, const char *name, fp_fopen_ctx_t *fctx); void fp_fclose(FILE * f, fp_fopen_ctx_t *fctx); - -typedef enum { - PCB_FP_INVALID, - PCB_FP_DIR, - PCB_FP_FILE, - PCB_FP_PARAMETRIC -} fp_type_t; - /* duplicates the name and splits it into a basename and params; params is NULL if the name is not parametric (and "" if parameter list is empty) returns 1 if name is parametric, 0 if file element. @@ -72,16 +65,24 @@ /* Optional pcb-rnd-side glue for some implementations */ +extern library_t library; /* the footprint library */ + +#define get_library_memory(parent) vtlib_alloc_append(((parent) == NULL ? &library.data.dir.children : &(parent)->data.dir.children), 1); + +void fp_free_children(library_t *parent); +void fp_sort_children(library_t *parent); +void fp_rmdir(library_t *dir); +library_t *fp_mkdir_p(const char *path); + #ifndef PCB_NO_GLUE /* Return the library shell string (from Settings) */ const char *fp_get_library_shell(void); /* Append a menu entry in the tree */ -LibraryEntryType *fp_append_entry(LibraryMenuType *parent, const char *dirname, const char *name, fp_type_t type, void *tags[]); +library_t *fp_append_entry(library_t *parent, const char *dirname, const char *name, fp_type_t type, void *tags[]); -LibraryMenuType *fp_append_topdir(const char *parent_dir, const char *dir_name, int *menuidx); - /* walk through all lib paths and build the library menu */ int fp_read_lib_all(void); + #endif #endif Index: trunk/src/plug_footprint_host.c =================================================================== --- trunk/src/plug_footprint_host.c (revision 1576) +++ trunk/src/plug_footprint_host.c (revision 1577) @@ -103,7 +103,7 @@ * library. */ if (fp_read_lib_all_(Settings.LibrarySearchPaths) > 0 || resultFP != NULL) { - sort_library(&Library); + fp_sort_children(&library); return 0; } Index: trunk/src_plugins/fp_fs/fp_fs.c =================================================================== --- trunk/src_plugins/fp_fs/fp_fs.c (revision 1576) +++ trunk/src_plugins/fp_fs/fp_fs.c (revision 1577) @@ -70,7 +70,7 @@ }; typedef struct { - LibraryMenuTypePtr menu; + library_t *menu; list_dir_t *subdirs; int children; } list_st_t; @@ -98,7 +98,7 @@ return 0; } -static int fp_fs_list(const char *subdir, int recurse, +static int fp_fs_list(library_t *pl, const char *subdir, int recurse, int (*cb) (void *cookie, const char *subdir, const char *name, fp_type_t type, void *tags[]), void *cookie, int subdir_may_not_exist, int need_tags) { @@ -120,6 +120,9 @@ return 0; } + if (strcmp(subdir, ".svn") == 0) + return 0; + if (chdir(subdir)) { if (!subdir_may_not_exist) ChdirErrorMessage(subdir); @@ -194,7 +197,7 @@ if ((S_ISDIR(buffer.st_mode)) || (WRAP_S_ISLNK(buffer.st_mode))) { cb(cookie, new_subdir, subdirentry->d_name, PCB_FP_DIR, NULL); if (recurse) { - n_footprints += fp_fs_list(fn, recurse, cb, cookie, 0, need_tags); + n_footprints += fp_fs_list(pl, fn, recurse, cb, cookie, 0, need_tags); } continue; } @@ -208,11 +211,11 @@ return n_footprints; } -static int fp_fs_load_dir_(const char *subdir, const char *toppath, int is_root) +static int fp_fs_load_dir_(library_t *pl, const char *subdir, const char *toppath, int is_root) { list_st_t l; list_dir_t *d, *nextd; - char working_[MAXPATHLEN + 1]; + char working_[MAXPATHLEN + 1], *visible_subdir; char *working; /* String holding abs path to working dir */ int menuidx; @@ -219,24 +222,30 @@ sprintf(working_, "%s%c%s", toppath, PCB_DIR_SEPARATOR_C, subdir); resolve_path(working_, &working, 0); - l.menu = fp_append_topdir(pcb_basename(toppath), pcb_basename(subdir), &menuidx); + if (strcmp(subdir, ".") == 0) + visible_subdir = "fs"; + else + visible_subdir = subdir; + + l.menu = fp_lib_search(pl, visible_subdir); + if (l.menu == NULL) + l.menu = fp_mkdir_len(pl, visible_subdir, -1); l.subdirs = NULL; l.children = 0; - fp_fs_list(working, 0, list_cb, &l, is_root, 1); + fp_fs_list(l.menu, working, 0, list_cb, &l, is_root, 1); /* now recurse to each subdirectory mapped in the previous call; by now we don't care if menu is ruined by the realloc() in GetLibraryMenuMemory() */ for (d = l.subdirs; d != NULL; d = nextd) { - l.children += fp_fs_load_dir_(d->subdir, d->parent, 0); + l.children += fp_fs_load_dir_(l.menu, d->subdir, d->parent, 0); nextd = d->next; free(d->subdir); free(d->parent); free(d); } - if (l.children == 0) { - DeleteLibraryMenuMemory(&Library, menuidx); - } + if (l.children == 0) + fp_rmdir(l.menu); free(working); return l.children; } @@ -244,7 +253,7 @@ static int fp_fs_load_dir(plug_fp_t *ctx, const char *path) { - return fp_fs_load_dir_(".", path, 1); + return fp_fs_load_dir_(&library, ".", path, 1); } typedef struct { @@ -296,7 +305,7 @@ resolve_path(path, &fpath, 0); /* fprintf(stderr, " in '%s'\n", fpath);*/ - fp_fs_list(fpath, 1, fp_search_cb, &ctx, 1, 0); + fp_fs_list(&library, fpath, 1, fp_search_cb, &ctx, 1, 0); if (ctx.path != NULL) { sprintf(path, "%s%c%s", ctx.path, PCB_DIR_SEPARATOR_C, ctx.real_name); free(ctx.path); Index: trunk/src_plugins/fp_wget/README =================================================================== --- trunk/src_plugins/fp_wget/README (revision 1576) +++ trunk/src_plugins/fp_wget/README (revision 1577) @@ -2,6 +2,5 @@ http://gedasymbols.org #state: works -#lstate: TODO: need to rewrite library memory handling -#default: disabled +#default: buildin #implements: fp Index: trunk/src_plugins/fp_wget/gedasymbols.c =================================================================== --- trunk/src_plugins/fp_wget/gedasymbols.c (revision 1576) +++ trunk/src_plugins/fp_wget/gedasymbols.c (revision 1577) @@ -68,19 +68,12 @@ return changed; } -static int keyeq(char *a, char *b) -{ - return !strcmp(a, b); -} - int fp_gedasymbols_load_dir(plug_fp_t *ctx, const char *path) { FILE *f; int fctx; char *md5_last, *md5_new; - LibraryMenuType *top; int tmp; - htsp_t *path2menu; char line[1024]; fp_get_mode mode; gds_t vpath; @@ -119,15 +112,12 @@ gds_init(&vpath); gds_append_str(&vpath, REQUIRE_PATH_PREFIX); - path2menu = htsp_alloc(strhash, keyeq); - htsp_set(path2menu, strdup(vpath.array), top); - gds_append(&vpath, '/'); vpath_base_len = vpath.used; while(fgets(line, sizeof(line), f) != NULL) { char *end, *fn; - LibraryMenuType *l, *parent; + library_t *l, *parent; if (*line == '#') continue; @@ -136,6 +126,7 @@ continue; *end = '\0'; + /* split path and fn; path stays in vpath.array, fn is a ptr to the file name */ gds_truncate(&vpath, vpath_base_len); gds_append_str(&vpath, line); end = vpath.array + vpath.used - 1; @@ -145,18 +136,8 @@ end++; fn = end; - fprintf(stderr, "FP WGET: '%s' '%s'\n", vpath.array, fn); - l = htsp_get(path2menu, vpath.array); - fprintf(stderr, " vpath='%s' l=%p\n", vpath.array, l); - - if (l == NULL) { - char *new_dir = vpath.array + vpath_base_len; - l = fp_append_topdir(REQUIRE_PATH_PREFIX, new_dir, &tmp); - htsp_set(path2menu, strdup(vpath.array), l); - fprintf(stderr, " added: '%s' -> %p\n", new_dir, l); - } - - fprintf(stderr, " fp: '%s' '%s' under %p\n", vpath.array, fn, l); + /* add to the database */ + l = fp_mkdir_p(vpath.array); fp_append_entry(l, vpath.array, fn, PCB_FP_FILE, NULL); } fp_wget_close(&f, &fctx); Index: trunk/src_plugins/hid_gtk/gui-library-window.c =================================================================== --- trunk/src_plugins/hid_gtk/gui-library-window.c (revision 1576) +++ trunk/src_plugins/hid_gtk/gui-library-window.c (revision 1577) @@ -98,8 +98,7 @@ enum { MENU_NAME_COLUMN, /* Text to display in the tree */ - MENU_LIBRARY_COLUMN, /* Pointer to the LibraryMenuType */ - MENU_ENTRY_COLUMN, /* Pointer to the LibraryEntryType */ + MENU_ENTRY_COLUMN, /* Pointer to the library_t */ N_MENU_COLUMNS }; @@ -273,9 +272,9 @@ ret = g_pattern_match_simple(pattern, compname_upper); if ((tags != NULL) && ret) { - LibraryEntryType *entry = NULL; + library_t *entry = NULL; gtk_tree_model_get(model, iter, MENU_ENTRY_COLUMN, &entry, -1); - if ((entry != NULL) && (entry->Tags != NULL)) { + if ((entry != NULL) && (entry->type == LIB_FOOTPRINT) && (entry->data.fp.tags != NULL)) { char *next, *tag; int found; void **t; @@ -296,7 +295,7 @@ break; } found = 0; - for (t = entry->Tags; *t != NULL; t++) { + for (t = entry->data.fp.tags; *t != NULL; t++) { if (*t == need) { found = 1; break; @@ -388,14 +387,20 @@ return TRUE; } -static void library_window_preview_refresh(GhidLibraryWindow * library_window, const char *name, LibraryEntryType * entry) +static void library_window_preview_refresh(GhidLibraryWindow * library_window, const char *name, library_t * entry) { GString *pt; + char *fullp; /* -1 flags this is an element file part and the file path is in | entry->AllocateMemory. */ - if (LoadElementToBuffer(PASTEBUFFER, name == NULL ? entry->AllocatedMemory : name)) + if (name == NULL) { + if ((entry == NULL) || (entry->type != LIB_FOOTPRINT)) + return; + fullp = entry->data.fp.full_path; + } + if (LoadElementToBuffer(PASTEBUFFER, name == NULL ? fullp : name)) SetMode(PASTEBUFFER_MODE); /* update the preview with new symbol data */ @@ -407,11 +412,10 @@ /* update the text */ pt = g_string_new("Tags:"); - if ((entry != NULL) && (entry->Tags != NULL)) { + if ((entry != NULL) && (entry->type == LIB_FOOTPRINT) && (entry->data.fp.tags != NULL)) { void **t; - - for (t = entry->Tags; *t != NULL; t++) { + for (t = entry->data.fp.tags; *t != NULL; t++) { const char *name = fp_tagname(*t); if (name != NULL) { g_string_append(pt, "\n "); @@ -439,7 +443,7 @@ GtkTreeModel *model; GtkTreeIter iter; GhidLibraryWindow *library_window = (GhidLibraryWindow *) user_data; - LibraryEntryType *entry = NULL; + library_t *entry = NULL; if (!gtk_tree_selection_get_selected(selection, &model, &iter)) return; @@ -557,57 +561,28 @@ * Creates a tree where the branches are the available library * sources and the leaves are the footprints. */ -static GtkTreeModel *create_lib_tree_model(GhidLibraryWindow * library_window) +static GtkTreeModel *create_lib_tree_model_recurse(GtkTreeStore *tree, GhidLibraryWindow *library_window, library_t *parent, GtkTreeIter *iter_parent) { - GtkTreeStore *tree; - GtkTreeIter iter, p_iter, e_iter, c_iter; - gchar *name; - gboolean exists; + GtkTreeIter p_iter; + library_t *menu, *entry; + int n, m; - tree = gtk_tree_store_new(N_MENU_COLUMNS, G_TYPE_STRING, G_TYPE_POINTER, G_TYPE_POINTER); - - MENU_LOOP(&Library); + for(menu = parent->data.dir.children.array, n = 0; n < parent->data.dir.children.used; n++, menu++) { - /* Watch for directory changes of library parts and create new - | parent iter at each change. - */ - if (!menu->directory) /* Shouldn't happen */ - menu->directory = g_strdup("???"); - - exists = FALSE; - if (gtk_tree_model_get_iter_first(GTK_TREE_MODEL(tree), &e_iter)) - do { - gtk_tree_model_get(GTK_TREE_MODEL(tree), &e_iter, MENU_NAME_COLUMN, &name, -1); - if (!strcmp(name, menu->directory)) { - exists = TRUE; - break; - } - } - while (gtk_tree_model_iter_next(GTK_TREE_MODEL(tree), &e_iter)); - - if (exists) - p_iter = e_iter; - else { - gtk_tree_store_append(tree, &p_iter, NULL); - gtk_tree_store_set(tree, &p_iter, - MENU_NAME_COLUMN, menu->directory, MENU_LIBRARY_COLUMN, NULL, MENU_ENTRY_COLUMN, NULL, -1); - } - gtk_tree_store_append(tree, &iter, &p_iter); - gtk_tree_store_set(tree, &iter, MENU_NAME_COLUMN, menu->Name, MENU_LIBRARY_COLUMN, menu, MENU_ENTRY_COLUMN, NULL, -1); - ENTRY_LOOP(menu); - { - gtk_tree_store_append(tree, &c_iter, &iter); - gtk_tree_store_set(tree, &c_iter, - MENU_NAME_COLUMN, entry->ListEntry, MENU_LIBRARY_COLUMN, menu, MENU_ENTRY_COLUMN, entry, -1); - } - END_LOOP; - + gtk_tree_store_append(tree, &p_iter, iter_parent); + gtk_tree_store_set(tree, &p_iter, MENU_NAME_COLUMN, menu->name, MENU_ENTRY_COLUMN, menu, -1); + if (menu->type == LIB_DIR) + create_lib_tree_model_recurse(tree, library_window, menu, &p_iter); } - END_LOOP; return (GtkTreeModel *) tree; } +static GtkTreeModel *create_lib_tree_model(GhidLibraryWindow *library_window) +{ + GtkTreeStore *tree = gtk_tree_store_new(N_MENU_COLUMNS, G_TYPE_STRING, G_TYPE_POINTER, G_TYPE_POINTER); + return create_lib_tree_model_recurse(tree, library_window, &library, NULL); +} #if 0 /* \brief On-demand refresh of the footprint library. Index: trunk/src_plugins/hid_lesstif/library.c =================================================================== --- trunk/src_plugins/hid_lesstif/library.c (revision 1576) +++ trunk/src_plugins/hid_lesstif/library.c (revision 1577) @@ -15,6 +15,8 @@ #include "misc.h" #include "set.h" #include "buffer.h" +#include "vtptr.h" +#include "stdarg.h" #include "hid.h" #include "lesstif.h" @@ -22,10 +24,6 @@ RCSID("$Id$"); -static Arg args[30]; -static int n; -#define stdarg(t,v) XtSetArg(args[n], t, v); n++ - static Widget library_dialog = 0; static Widget library_list, libnode_list; @@ -33,10 +31,13 @@ static XmString *libnode_strings = 0; static int last_pick = -1; +vtptr_t picks; /* of library_t * */ +vtptr_t pick_names; /* of char * */ + static void pick_net(int pick) { - LibraryMenuType *menu = Library.Menu + pick; - int i; + library_t *menu = (library_t *)picks.array[pick]; + int i, found; if (pick == last_pick) return; @@ -44,13 +45,19 @@ if (libnode_strings) free(libnode_strings); - libnode_strings = (XmString *) malloc(menu->EntryN * sizeof(XmString)); - for (i = 0; i < menu->EntryN; i++) - libnode_strings[i] = XmStringCreatePCB(menu->Entry[i].ListEntry); - n = 0; + + libnode_strings = (XmString *) malloc(menu->data.dir.children.used * sizeof(XmString)); + for (found = 0, i = 0; i < menu->data.dir.children.used; i++) { + if (menu->data.dir.children.array[i].type == LIB_FOOTPRINT) { + libnode_strings[i] = XmStringCreatePCB(menu->data.dir.children.array[i].name); + found++; + } + } + + stdarg_n = 0; stdarg(XmNitems, libnode_strings); - stdarg(XmNitemCount, menu->EntryN); - XtSetValues(libnode_list, args, n); + stdarg(XmNitemCount, found); + XtSetValues(libnode_list, stdarg_args, stdarg_n); } static void library_browse(Widget w, void *v, XmListCallbackStruct * cbs) @@ -61,9 +68,9 @@ static void libnode_select(Widget w, void *v, XmListCallbackStruct * cbs) { char *args; - LibraryEntryType *e = Library.Menu[last_pick].Entry + cbs->item_position - 1; - - if (LoadElementToBuffer(PASTEBUFFER, e->AllocatedMemory)) + library_t *e = picks.array[last_pick]; + e = &e->data.dir.children.array[cbs->item_position - 1]; + if (LoadElementToBuffer(PASTEBUFFER, e->data.fp.full_path)) SetMode(PASTEBUFFER_MODE); } @@ -74,27 +81,27 @@ if (library_dialog) return 0; - n = 0; + stdarg_n = 0; stdarg(XmNresizePolicy, XmRESIZE_GROW); stdarg(XmNtitle, "Element Library"); - library_dialog = XmCreateFormDialog(mainwind, "library", args, n); + library_dialog = XmCreateFormDialog(mainwind, "library", stdarg_args, stdarg_n); - n = 0; + stdarg_n = 0; stdarg(XmNtopAttachment, XmATTACH_FORM); stdarg(XmNbottomAttachment, XmATTACH_FORM); stdarg(XmNleftAttachment, XmATTACH_FORM); stdarg(XmNvisibleItemCount, 10); - library_list = XmCreateScrolledList(library_dialog, "nets", args, n); + library_list = XmCreateScrolledList(library_dialog, "nets", stdarg_args, stdarg_n); XtManageChild(library_list); XtAddCallback(library_list, XmNbrowseSelectionCallback, (XtCallbackProc) library_browse, 0); - n = 0; + stdarg_n = 0; stdarg(XmNtopAttachment, XmATTACH_FORM); stdarg(XmNbottomAttachment, XmATTACH_FORM); stdarg(XmNrightAttachment, XmATTACH_FORM); stdarg(XmNleftAttachment, XmATTACH_WIDGET); stdarg(XmNleftWidget, library_list); - libnode_list = XmCreateScrolledList(library_dialog, "nodes", args, n); + libnode_list = XmCreateScrolledList(library_dialog, "nodes", stdarg_args, stdarg_n); XtManageChild(libnode_list); XtAddCallback(libnode_list, XmNbrowseSelectionCallback, (XtCallbackProc) libnode_select, 0); @@ -101,23 +108,57 @@ return 0; } +static void lib_dfs(library_t *parent, int level) +{ + library_t *l; + char *s; + int n, len; + + if (parent->type != LIB_DIR) + return; + + if (parent->name != NULL) { + vtptr_append(&picks, parent); + len = strlen(parent->name); + s = malloc(len+level+1); + for(n = 0; n < level-1; n++) s[n] = ' '; + strcpy(s+level-1, parent->name); + vtptr_append(&pick_names, s); + } + + for(l = parent->data.dir.children.array, n = 0; n < parent->data.dir.children.used; n++,l++) + lib_dfs(l, level+1); +} + static int LibraryChanged(int argc, char **argv, Coord x, Coord y) { int i; - if (!Library.MenuN) + if (library.data.dir.children.used == 0) return 0; if (build_library_dialog()) return 0; last_pick = -1; + + for (i = 0; i < pick_names.used; i++) + free(pick_names.array[i]); + + vtptr_truncate(&picks, 0); + vtptr_truncate(&pick_names, 0); + + lib_dfs(&library, 0); + + if (library_strings) free(library_strings); - library_strings = (XmString *) malloc(Library.MenuN * sizeof(XmString)); - for (i = 0; i < Library.MenuN; i++) - library_strings[i] = XmStringCreatePCB(Library.Menu[i].Name); - n = 0; + library_strings = (XmString *) malloc(picks.used * sizeof(XmString)); + for (i = 0; i < picks.used; i++) + library_strings[i] = XmStringCreatePCB(pick_names.array[i]); + + stdarg_n = 0; stdarg(XmNitems, library_strings); - stdarg(XmNitemCount, Library.MenuN); - XtSetValues(library_list, args, n); + stdarg(XmNitemCount, picks.used); + XtSetValues(library_list, stdarg_args, stdarg_n); + pick_net(0); return 0; } Index: trunk/util/Makefile.in =================================================================== --- trunk/util/Makefile.in (revision 1576) +++ trunk/util/Makefile.in (revision 1577) @@ -30,8 +30,8 @@ FP_LDFLAGS = @/local/pcb/LDFLAGS@ FP_CFLAGS = @/local/pcb/CFLAGS@ -gsch2pcb-rnd$(EXE): gsch2pcb.o ../src/compat_fs.o ../src/paths.o $(HASHOBJ) $(VECTOBJ) $(LISTOBJ) $(SCCFOBJ) $(QPARSE) $(FP_OBJS) - $(CC) gsch2pcb.o ../src/compat_fs.o ../src/paths.o $(HASHOBJ) $(VECTOBJ) $(LISTOBJ) $(SCCFOBJ) $(QPARSE) $(FP_OBJS) -o gsch2pcb-rnd$(EXE) $(LDFLAGS) $(FP_LDFLAGS) +gsch2pcb-rnd$(EXE): gsch2pcb.o ../src/vtlibrary.o ../src/compat_fs.o ../src/paths.o $(HASHOBJ) $(VECTOBJ) $(LISTOBJ) $(SCCFOBJ) $(QPARSE) $(FP_OBJS) + $(CC) gsch2pcb.o ../src/vtlibrary.o ../src/compat_fs.o ../src/paths.o $(HASHOBJ) $(VECTOBJ) $(LISTOBJ) $(SCCFOBJ) $(QPARSE) $(FP_OBJS) -o gsch2pcb-rnd$(EXE) $(LDFLAGS) $(FP_LDFLAGS) gsch2pcb.o: gsch2pcb.c ../config.h ../config.manual.h ../config.auto.h $(CC) -c $(CFLAGS) $(FP_CFLAGS) gsch2pcb.c -o gsch2pcb.o