Initial import of gattrib 20040806
[geda-gaf/whiteaudio.git] / gattrib / NOTES
blobe7f94de9eb9fe2a35f7ea532981bcfd92fef1aab
1 -----------------------------------------------------------------------
2 This file contains a few notes I made while creating
3 gattrib.  These notes were useful to me in coming to grips with
4 understanding gEDA's data structures and gnetlist's operation.
5 The were also useful when architecting the workings of gattrib.
6  
7 A spreadsheet holding function names is held in the file
8 called "ProgramArchitecture.gnumeric", which should live in the
9 toplevel directory.  This spreadsheet should help you wade
10 through the various fcns used during processing.
12 No guarantee is made that these notes are accurate, useful,
13 or even understandable to anybody else.  -- SDB 12.5.2003
14                                             sdb@cloud9.net
16 Updated on 7.17.2004.  SDB.
19 -----------------------------------------------------------------------
20 gattrib algorithm:
21 1.  Input sheets as in gnetlist.  Use fcns from libgeda.  Result is 
22     linked list of TOPLEVEL entries.  (*pr_current)  This data structure
23     comes from libgeda.
25     The file is opened and read using:
26         libgeda/noweb/f_basic.nw:f_open(TOPLEVEL *w_current, char *filename)
28     f_open invokes o_read, which fills out the objects:
29         libgeda/noweb/a_basic.nw:o_read(TOPLEVEL *w_current, 
30                                         OBJECT *object_list, char *filename)
31         
32     At the end of this process, we have filled out (TOPLEVEL pr_current).
34 2.  Create (SHEET_DATA *sheet_head), which is the data structure intermediating
35     between gEDA's TOPLEVEL and GtkSheet's gtk_sheet.  It holds all info
36     important to drive the spreadsheet app in a form easy to access.  
38 3.  Build master lists which are part of SHEET_DATA.  The master lists
39     are used when building the row and column label cells, and for
40     keeping track of which components and attribtues are in play.
42     Master lists are built for each of these objects:
43     *  Component refdeses found in the design.  
44         sheet_head->master_comp_list_head
45     *  Component attributes found in the design.  
46         sheet_head->master_comp_attrib_list_head
47     *  Netnames found in the design.   
48         sheet_head->master_net_list_head  (TBD) 
49     *  Net attributes found in the design.  
50         sheet_head->master_net_attrib_list_head (TBD)
51     *  Component pins found in the design (TBD)
53     *  Component pins attributes found in the design (TBD)
55     Each master list is stored using a STRING_DATA struct.
56     Attach pointers to these master lists inside SHEET_DATA.
57     This stage of processing also counts up the number of each
58     item.  These lists are used to index the table entries, and form the 
59     row and column labels on the gtk_sheet.
61 4.  Create TABLE, which is the data structure holding the info to be displayed
62     in the gtk_sheet cells.  TABLE is basically a 2D array of structs.  
64     Tables are built for the following types of objects:
65     *  Component refdeses & attached attributes.
66         sheet_head->component_table
67     *  Netnames and attached attributes.  (TBD)
68         sheet_head->net_table 
69     *  Component pins and attached attributes.  (TBD)
71     After creation, attach TABLE inside SHEET_DATA.  The fcns which add components
72     and nets to the internal data structs are called s_*_set_*"  Items in the table
73     are referenced using a construct like:
74     sheet_head->component_table)[i][j].attrib_value
76 5.  Then build gtk_sheet using fcns available in x_gtksheet.  They 
77     take the data from SHEET_DATA and stick them into the gtk_sheet
78     widget for display on the spreadsheet.
80 6.  Run gtk_main.  Wait for user clicks & invoke appropriate callbacks. 
81     Callback fcns are specified in include/menu.h
83 7.  The save callback is x_fileselect_*.  Upon a save/saveas event invoked
84     from the menu, take all data out of gtk_sheet and stick it into SHEET_DATA
85     using various fcns named "s_*_update_*".  Then take data out of SHEET_DATA
86     and stick it into (TOPLEVEL *pr_current).  Then use standard gEDA
87     fcns to save out the data in .sch format.
91 -----------------------------------------------------------------------
92 gattrib data structures:
94 TOPLEVEL: 
95   Toplevel holds page info, and is a linked list with one entry per page/window.
96   Defined in libgeda/include/struct.h, fcns to manipulate TOPLEVEL data live in 
97   libgeda/src/s_project.c
100 SHEET_DATA:
101   Holds data taken from TOPLEVEL in form relevant for display in spreadsheet.
102   Definition:
104 struct st_sheet_data {
105   STRING_LIST *master_comp_list_head;           /* Sorted list of all components used in design */
106   int comp_count;                               /* number of components in design */
107   STRING_LIST *master_comp_attrib_list_head;    /* Sorted list of all component attribs used in design */
108   int comp_attrib_count;                        /* number of component attribs in design */
110   STRING_LIST *master_net_list_head;            /* Sorted list of all nets used in design */
111   int net_count;                                /* number of nets in design */
112   STRING_LIST *master_net_attrib_list_head;     /* Sorted list of all net attribss used in design */
113   int net_attrib_count;                         /* number of net attribss in design */
115   STRING_LIST *master_pin_list_head;            /* Sorted list of all pins used in design */
116   int pin_count;                                /* number of pins in design */
117   STRING_LIST *master_pin_attrib_list_head;     /* Sorted list of all pin attribss used in design */
118   int pin_attrib_count;                         /* number of pin attribss in design */
120   TABLE **component_table;                      /* points to 2d array of component attribs */ 
121   TABLE **net_table;                            /* points to 2d array of net attribs */
122   TABLE **pin_table;                            /* points to 2d array of pin attribs */
126 TABLE:
127   Is 2D array of structs.  Each struct member holds info about
128   one particular attrib.
130 STRING_LIST:
131   A linked list of strings.  Used to create the component and net
132   master lists.
134 GtkWidget **sheets:
135   These are the spreadsheet widgets themselves.  There are thre of them:
136   1.  Comp attribs
137   2.  Net attribs (currently TBD)
138   3.  Pin attribs (i.e. pinseq and so on).
141 ---------------------------------------------------------------------------------
142 ********         How data gets from TOPLEVEL into GtkSheet               ********
143 ---------------------------------------------------------------------------------
144 Here's what happens when the program starts, or file->save is invoked from the menu
145 and the data is read in.  (I handle data structure initialization elsewhere.)  Keep
146 in mind that gattrib is a thin layer between GtkSheet and TOPLEVEL.  When you read
147 in a design, libgeda functions are used to fill out the TOPLEVEL data structure.  The
148 the purpose of gattrib is to take all teh stuff out of TOPLEVEL and stick it into
149 GtkSheet for user manipulation.
151 1.  Loop on each page.  For each page in the design, read it in using 
152     s_toplevel_read_page.  Then invoke s_sheet_data_add_master_*_list items.
154 2.  Create the tables using s_table_new.
156 3.  Load the tables using s_sheet_data_add_*_table_items.
163 ---------------------------------------------------------------------------------
164 ********  How data gets from GtkSheet into TOPLEVEL upon saving a sheet  ********
165 ---------------------------------------------------------------------------------
166 Here's what happens when file->save is invoked from the menu.  Please keep in 
167 mind that gattrib is a thin layer between GtkSheet and TOPLEVEL.  When you save
168 out a design, the purpose of gattrib is to take all the stuff out of GtkSheet
169 and stick it into TOPLEVEL and then save it.
171 1.  Selecting "save" from the menubar invokes the callback s_toplevel_menubar_file_save.
172     (callbacks are defined in includes/x_menu.h)
173     This calls s_toplevel_gtksheet_to_toplevel.  
175 2.  s_toplevel_gtksheet_to_toplevel calls s_sheet_data_gtksheet_to_sheetdata. 
176     Then it loops on all pages and calls s_toplevel_sheetdata_to_toplevel.  (Described 
177     starting in item 6 below.)
179 3.  s_sheet_data_gtksheet_to_sheetdata calls s_table_gtksheet_to_all_tables.
181 4.  s_table_gtksheet_to_all_tables calls s_table_gtksheet_to_table individually 
182     for each sheet (comps, nets, pins)
184 5.  s_table_gtksheet_to_table loops on the gtksheet and loads all the stuff it 
185     finds back into TABLE (part of sheet_data).
187 6.  Back in s_toplevel_gtksheet_to_toplevel.  Now that the tables are loaded, 
188     we loop on all pages and call s_toplevel_sheetdata_to_toplevel with a pointer
189     to the first obj on the page as the calling arg.
191 7.  Inside s_toplevel_sheetdata_to_toplevel, we loop on all objs in teh page, 
192     find the corresponding entry in TABLE, and then copy all attribs out of
193     TABLE and back into the object's attrib list.
195 8.  Finally, the libgeda fcn s_page_save_all is called.  This saves out all
196     pages in the design.
199 -----------------------------------------------------------------------
200 Data structures used in gEDA.
202 These notes attempt to document the data structures used in gEDA.  I
203 present them here because they may not be familiar to those interested
204 in hacking gattrib.  I also want to record these findings somewhere
205 because it took me some time to figure this out. 
207 TOPLEVEL:       The basic data structure in gschem.  Basically holds info
208                 about the entire design.
209 PAGE:           Self explanatory.  The entire design is held as a
210                 doubly linked list of PAGEs under TOPLEVEL.
211 OBJECT:         A graphical object on the gschem page.  Can be a net
212                 segment, a component complex, a bit of text, a
213                 component's pin, or whatever.  Each page holds a
214                 doubly linked list of OBJECTs present on that page.
215 TILE:           A section of the graphical page.  Important in
216                 gschem, a TILE holds a single linked list of OBJECTs
217                 present in its subsection of the page.  Each page
218                 holds a two dimensional doubly linked list of TILEs.  
219                 A TILE is used to quickly locate a particular object 
220                 when handling the graphical drawing of a schematic.
221 NETLIST:        Important in gnetlist.  This is a doubly linked list
222                 of component objects and pins.
225 -----------------------------------------------------------------------------
226 Represenatation of components, component attributes, & pins in gattrib & gEDA.
229 From the top down to a particular graphical object on a schematic page:
231 (TOPLEVEL *pr_current)->(PAGE page_current)->(OBJECT o_current) 
233 That is, all objects in the design are graphical objects, and are held 
234 in a linked list.  Note that an object is any graphical object, 
235 such as text, a component (COMPLEX), an attribute, a line, a net, etc.
236 Stuff attached below the OBJECT level determine
237 what kind of object the graphic is, its visibility, its name, etc. etc. etc.  
240 ----  Components with attributes  ----
241 Starting from a component (COMPLEX), an attribute is represented like this:
242 (OBJECT *component)->(ATTRIB *attribs)->(OBJECT *attrib_graphic)->(TEXT *text)->(char *string) // name=value string
243                                                                               ->(int x, y)     // which coords?
244                                                                               ->(int screen_x) // ???
245                                                                                 etc . . .
246                                                                 ->(int type)   // types defined in o_types.h
247                                                                 ->(int sid)    // unique identifier
248                                                                 ->(char *name) // something like text.3732
250 Note that ATTRIB is a linked list of (pointers to) attributes.
251 (OBJECT *component) points to the ATTRIB list, and "attrib_graphic" points
252 to the attrib OBJECT itself (which is a graphical element like everything else).  
255 ----  Attributes  ----
256 Since each attribute is itself a graphical object present in the design, 
257 an attribute graphic is represented like this:
258 (OBJECT *attribute)->(TEXT *text)->(char *string) // name=value string
259                                  ->(int x, y)     // which coords?
260                                  ->(int screen_x) // ???
261                                     etc . . .
262                    ->(int type)  // for attribute, type is text
263                                  // #define OBJ_TEXT       'T'
264                    ->(int sid)
265                    ->(char *name)
266                    ->(ATTRIB *attached_to)  // points back to (OBJECT *component)
267                    ->(int attribute)        // = 1 for attribute, = 0 otherwise.
268                    ->(int show_name_value)  // #define SHOW_NAME_VALUE         0
269                                             // #define SHOW_VALUE              1
270                                             // #define SHOW_NAME               2
271                    ->(int visibility)       // #define INVISIBLE       0
272                                             // #define VISIBLE         1
274 Attrib_graphic is stored internally as a "name=value" string, and is disassembled
275 by various fcns when needed.
278 ----  Pins  ----
279 As for pins, they are attached to components (COMPLEX) in the following way.
280 Starting from the component:
281 (OBJECT *component)->(COMPLEX *complex)->(OBJECT *prim_objs)->(int type)        // #define OBJ_PIN  'P'
282                                                             ->(ATTRIB *attribs) // pin attrib list.
283                                                             ->(int sid)         // unique identifier
284                                                             ->(char *name)      // something like pin.3372
287 Pins also are held in the NETLIST data structure, which is a separate data structure.
288 NETLIST is more important in gnetlist than in gschem.  A pin is held in the following 
289 way:
290 (NETLIST *node)->(OBJECT *object_ptr)
291                ->(CPINLIST *cpins)->(char *pin_number)
292                                   ->(char *net_name)
293                                   ->(char *pin_label)
297 ----  Example  ----
298 Component objects (COMPLEX) have lots of other other fields in teh struct.
299 Here's an example taken  from a real design:
301 (OBJECT *component)->name                                 = complex.188       // unique ID of component
303                    ->attribs->object->name                = complex.188       // first "attribs" points back to component
304                    ->attribs->next->object->name          = text.272          // attrib text
305                    ->attribs->next->object->text->string  = refdes=C1         // actual attrib
306                    
307                    ->complex->prim_objs->name             = complex-head.189  // head of prim_objs list                      
308                    ->complex->prim_objs->next->name       = pin.190           // actual object
310 Each list attached to a component has a head, followed by the actual list
311 items.
314 -----------------------------------------------------------------------
315 From include/struct.h:
317 /* ----------- SDB note about philosophy behind globals -------------- *
318  * I made the "TOPLEVEL project" and all the GTK window stuff into
319  * global variables.  I know that this is supposedly bad programming form.    
320  * However, here are some observations:
321  * -- I wanted to use gEDA's TOPLEVEL structure as much as possible, at
322  *    least to hold info about the design's netlist & components.  
323  *    The TOPLEVEL strucuture is architected to hold info about gschem's 
324  *    window also.  HOwever, gschem's windows are architected differently
325  *    than mine in gattrib.  This is because my windowing system does
326  *    completely different things, and also uses the GtkSheet widget, which
327  *    is architected completely differently from TOPLEVEL.
328  * -- Since I couldn't easily or naturally cram my windowing scheme into 
329  *    TOPLEVEL (or so I think), I decided to use a separate set of windows 
330  *    from those defined under TOPLEVEL for my application.
331  * -- The problem arises when using callbacks.  Callbacks from GTK allow
332  *    only one argument to be passed.  Given the way I set up the menu bar, 
333  *    I didn't have easy acces to the information inside both the GtkSHeet
334  *    objects *and* the TOPLEVEL stuff while only having one callback
335  *    argument.  This makes it hard to have access to e.g. a GtkSheet window 
336  *    and a list of files (in TOPLEVEL) simultaneously.
337  * -- Therefore, I decided to make both the window stuff and TOPLEVEL 
338  *    globals.
339  * -- Similarly, because I couldn't cram the SHEET_DATA struct into any
340  *    hook in TOPLEVEL, I just made it a global also.
341  * -- Finally, in my defense, in gschem and gnetlist, (TOPLEVEL *w_current 
342  *    or pr_current) is passed  to almost every function.  Since it 
343  *    is just a pointer to a huge struct of stuff, manipulating 
344  *    the stuff in the struct has a global
345  *    effect.  That is, manipulating w_current (or pr_current) has side 
346  *    effects, so it is basically a global anyway.  The real problem with 
347  *    globals occurs when you have a global variable caled "i" or "temp"
348  *    which conflicts with a global in a module written by somebody else.
349  *    Since pr_current is a very uncommon name, this should not be a 
350  *    problem here.  Therefore, I decided 
351  *    to make life easy for myself dealing with callbacks by making both 
352  *    the windows and TOPLEVEL global variables.
353  * If there is a better way to solve this problem, I'd like to hear it.
354  * ------------------------------------------------------------------ */
357 -----------------------------------------------------------------------
358 To be done:
359 1.  Before building spreadsheet, create and sort component and net 
360     master lists.  They are used to index components in the TABLE,
361     and also label the gtk_sheet rows and cols.
362 2.  How to handle attribute visibility?  Maybe right-click on cell & set 
363     vis.  Default = invisible and "both name and value".
364 3.  Need fcns to allow for adding and deleting of entire attrib
365     columns.  Don't need to allow for adding/deleting components
366     -- users should use gschem to add/delete components because 
367     gattrib can't do anything about the graphical position data
368     required for this.
372 -----------------------------------------------------------------------
373 Here's what the filename prefix letters mean:
375         a_ : Action (this was a really poor choice, and will be removed)
376         g_ : Guile related functions
377         i_ : Interface related functions
378         o_ : graphic Object related functions
379         x_ : X related functions
380         f_ : File related functions
381         m_ : Math related functions
382         s_ : data Structure related functions
384         I've tried to keep the function names in the files correct, but
385         sometimes I failed.  (look at libgeda/a_basic.c for an example of
386         a file which has a bunch of functions which shouldn't be in there)
388                                                                 -Ales
389 -----------------------------------------------------------------------