Index: trunk/src/plug_io.c =================================================================== --- trunk/src/plug_io.c (revision 2641) +++ trunk/src/plug_io.c (revision 2642) @@ -148,35 +148,52 @@ return f1->prio > f2->prio; } -/* Find the plugin that offers the highest write prio for the format */ -static plug_io_t *find_writer(plug_iot_t typ, const char *fmt) +/* Find all plugins that can handle typ/wr and build an ordered list in available[], + highest prio first. If fmt is NULL, use the default fmt for each plugin. + Return the length of the array. */ +static int find_io(find_t *available, int avail_len, plug_iot_t typ, const char *fmt) { - find_t available[32]; /* wish we had more than 32 IO plugins... */ int len = 0; - if (fmt == NULL) { -#warning TODO: rather save format information on load - fmt = "pcb"; - } #define cb_append(pl, pr) \ do { \ if (pr > 0) { \ - assert(len < sizeof(available)/sizeof(available[0])); \ + assert(len < avail_len ); \ available[len].plug = pl; \ available[len++].prio = pr; \ } \ } while(0) - HOOK_CALL_ALL(plug_io_t, plug_io_chain, fmt_support_prio, cb_append, typ, 1, fmt); + HOOK_CALL_ALL(plug_io_t, plug_io_chain, fmt_support_prio, cb_append, typ, 1, (fmt == NULL ? __ch__->default_fmt : fmt)); + + if (len > 0) + qsort(available, len, sizeof(available[0]), find_prio_cmp); +#undef cb_append + + return len; +} + +/* Find the plugin that offers the highest write prio for the format */ +static plug_io_t *find_writer(plug_iot_t typ, const char *fmt) +{ + find_t available[PCB_IO_MAX_FORMATS]; + int len; + + if (fmt == NULL) { +#warning TODO: rather save format information on load + fmt = "pcb"; + } + + len = find_io(available, sizeof(available)/sizeof(available[0]), typ, fmt); + if (len == 0) return NULL; - qsort(available, len, sizeof(available[0]), find_prio_cmp); return available[0].plug; -#undef cb_append } + int WriteBuffer(FILE *f, BufferType *buff, const char *fmt) { int res; @@ -781,3 +798,38 @@ return (fclose(fp) ? STATUS_ERROR : result); } + +int pcb_io_list(pcb_io_formats_t *out, plug_iot_t typ, int wr, int do_digest) +{ + find_t available[PCB_IO_MAX_FORMATS]; + int n; + + memset(out, 0, sizeof(pcb_io_formats_t)); + out->len = find_io(available, sizeof(available)/sizeof(available[0]), typ, NULL); + + if (out->len == 0) + return 0; + + for(n = 0; n < out->len; n++) + out->plug[n] = available[n].plug; + + if (do_digest) { + for(n = 0; n < out->len; n++) + out->digest[n] = pcb_strdup_printf("%s (%s)", out->plug[n]->default_fmt, out->plug[n]->description); + out->digest[n] = NULL; + } + return out->len; +} + +void pcb_io_list_free(pcb_io_formats_t *out) +{ + int n; + + for(n = 0; n < out->len; n++) { + if (out->digest[n] != NULL) { + free(out->digest[n]); + out->digest[n] = NULL; + } + } +} + Index: trunk/src/plug_io.h =================================================================== --- trunk/src/plug_io.h (revision 2641) +++ trunk/src/plug_io.h (revision 2642) @@ -31,7 +31,7 @@ #include "global.h" #include "conf.h" -typedef enum { +typedef enum { /* I/O type bitmask; each bit is one thing to save or load, not all formats support all things */ PCB_IOT_PCB = 1, PCB_IOT_FOOTPRINT = 2, PCB_IOT_FONT = 4, @@ -111,4 +111,23 @@ void RemoveTMPData(void); #endif +/********** helpers **********/ + +/* wish we had more than 32 IO plugins... */ +#define PCB_IO_MAX_FORMATS 32 + +/* A list of format plugins available for a given purpose */ +typedef struct { + int len; + const plug_io_t *plug[PCB_IO_MAX_FORMATS+1]; + char *digest[PCB_IO_MAX_FORMATS+1]; /* string that contains the format identifier and the description */ +} pcb_io_formats_t; + +/* Search all io plugins to see if typ/wr is supported. Return an ordered + list in out. If do_digest is non-zero, fill in the digest field. Returns + number of suitable io plugins. Call pcb_io_list_free() on out when it is not + needed anymore. */ +int pcb_io_list(pcb_io_formats_t *out, plug_iot_t typ, int wr, int do_digest); +void pcb_io_list_free(pcb_io_formats_t *out); + #endif