Stop pretending to use an explicit printing origin.
[geda-gaf/berndj.git] / gattrib / NOTES
blob71c60c09815ee5ed02b2612c5229f30f91432520
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 design directory.  This spreadsheet should help you wade
10 through the various fcns used during processing.  Note that this
11 spreadsheet might be a little out of date.  The source code is the
12 final documentation.  
14 No guarantee is made that these notes are accurate, useful,
15 or even understandable to anybody else.  -- SDB 12.5.2003
16                                             sdb@cloud9.net
18 Last updated on 11.10.2004.  SDB.
21 -----------------------------------------------------------------------
22 gattrib algorithm:
23 1.  Input sheets as in gnetlist.  Use fcns from libgeda.  Result is 
24     linked list of TOPLEVEL entries.  (*pr_current)  This data structure
25     comes from libgeda.
27     The file is opened and read using:
28         libgeda/noweb/f_basic.nw:f_open(TOPLEVEL *w_current, char *filename)
30     f_open invokes o_read, which fills out the objects:
31         libgeda/noweb/a_basic.nw:o_read(TOPLEVEL *w_current, 
32                                         OBJECT *object_list, char *filename)
33         
34     At the end of this process, we have filled out (TOPLEVEL pr_current).
36 2.  Create (SHEET_DATA *sheet_head), which is the data structure intermediating
37     between gEDA's TOPLEVEL and GtkSheet's gtk_sheet.  It holds all info
38     important to drive the spreadsheet app in a form easy to access.  
40 3.  Build master lists which are part of SHEET_DATA.  The master lists
41     are used when building the row and column label cells, and for
42     keeping track of which components and attribtues are in play.
44     Master lists are built for each of these objects:
45     *  Component refdeses found in the design.  
46         sheet_head->master_comp_list_head
47     *  Component attributes found in the design.  
48         sheet_head->master_comp_attrib_list_head
49     *  Netnames found in the design.   
50         sheet_head->master_net_list_head  (TBD) 
51     *  Net attributes found in the design.  
52         sheet_head->master_net_attrib_list_head (TBD)
53     *  Component pins found in the design 
54         sheet_head->master_pin_list_head
55     *  Component pins attributes found in the design
56         sheet_head->master_pin_attrib_list_head
58     Each master list is stored using a STRING_DATA struct.
59     Attach pointers to these master lists inside SHEET_DATA.
60     This stage of processing also counts up the number of each
61     item.  These lists are used to index the table entries, and form the 
62     row and column labels on the gtk_sheet.
64 4.  Create TABLE, which is the data structure holding the info to be displayed
65     in the gtk_sheet cells.  TABLE is basically a 2D array of structs.  
67     Tables are built for the following types of objects:
68     *  Component refdeses & attached attributes.
69         sheet_head->component_table
70     *  Netnames and attached attributes.  (TBD)
71         sheet_head->net_table 
72     *  Component pins and attached attributes.
74     After creation, attach TABLE inside SHEET_DATA.  The fcns which add components
75     and nets to the internal data structs are called s_*_set_*"  Items in the table
76     are referenced using a construct like:
77     sheet_head->component_table)[i][j].attrib_value
79 5.  Then build gtk_sheet using fcns available in x_gtksheet.  They 
80     take the data from SHEET_DATA and stick them into the gtk_sheet
81     widget for display on the spreadsheet.
83 6.  Run gtk_main.  Wait for user clicks & invoke appropriate callbacks. 
84     Callback fcns are specified in include/menu.h
86 7.  The save callback is x_fileselect_*.  Upon a save/saveas event invoked
87     from the menu, take all data out of gtk_sheet and stick it into SHEET_DATA
88     using various fcns named "s_*_update_*".  Then take data out of SHEET_DATA
89     and stick it into (TOPLEVEL *pr_current).  Then use standard gEDA
90     fcns to save out the data in .sch format.
94 -----------------------------------------------------------------------
95 gattrib data structures:
97 TOPLEVEL: 
98   Toplevel holds page info, and is a linked list with one entry per page/window.
99   Defined in libgeda/include/struct.h, fcns to manipulate TOPLEVEL data live in 
100   libgeda/src/s_project.c
103 SHEET_DATA:
104   Holds data taken from TOPLEVEL in form relevant for display in spreadsheet.
105   Definition:
107 struct st_sheet_data {
108   STRING_LIST *master_comp_list_head;           /* Sorted list of all components used in design */
109   int comp_count;                               /* number of components in design */
110   STRING_LIST *master_comp_attrib_list_head;    /* Sorted list of all component attribs used in design */
111   int comp_attrib_count;                        /* number of component attribs in design */
113   STRING_LIST *master_net_list_head;            /* Sorted list of all nets used in design */
114   int net_count;                                /* number of nets in design */
115   STRING_LIST *master_net_attrib_list_head;     /* Sorted list of all net attribss used in design */
116   int net_attrib_count;                         /* number of net attribss in design */
118   STRING_LIST *master_pin_list_head;            /* Sorted list of all pins used in design */
119   int pin_count;                                /* number of pins in design */
120   STRING_LIST *master_pin_attrib_list_head;     /* Sorted list of all pin attribss used in design */
121   int pin_attrib_count;                         /* number of pin attribss in design */
123   TABLE **component_table;                      /* points to 2d array of component attribs */ 
124   TABLE **net_table;                            /* points to 2d array of net attribs */
125   TABLE **pin_table;                            /* points to 2d array of pin attribs */
129 TABLE:
130   Is 2D array of structs.  Each struct member holds info about
131   one particular attrib.
133 STRING_LIST:
134   A linked list of strings.  Used to create the component and net
135   master lists.
137 GtkWidget **sheets:
138   These are the spreadsheet widgets themselves.  There are three of them:
139   1.  Comp attribs
140   2.  Net attribs (currently TBD)
141   3.  Pin attribs (i.e. pinseq and so on).
144 ---------------------------------------------------------------------------------
145 ********         How data gets from TOPLEVEL into GtkSheet               ********
146 ---------------------------------------------------------------------------------
147 Here's what happens when the program starts, or file->open is invoked from the menu
148 and the data is read in.  (I handle data structure initialization elsewhere.)  Keep
149 in mind that gattrib's data structures (in particular, SHEET_DATA) are
150 a thin layer between GtkSheet and TOPLEVEL.  When you read in a
151 design, libgeda functions are used to fill out the TOPLEVEL data
152 structure.  The the purpose of gattrib is to take all the stuff out of
153 TOPLEVEL run it throught SHEET_DATA, and finally stick it into
154 GtkSheet for user manipulation.  
156 1.  Loop on each page.  For each page in the design, do this:
157     *  Read in the page using s_toplevel_read_page.
158     *  Invoke s_sheet_data_add_master_*_list items and 
159        s_sheet_data_add_master_*_attrib_list items.  This fills out the lists in 
160        SHEET__DATA.
162 2.  Sort the master lists.
164 3.  Create the tables: sheet_head->*_table = s_table_new(. . . .)
166 4.  Loop on pages again. Fill out the tables using 
167     s_table_add_toplevel_*_items_to_*_table(. . . .)
169 5.  Transfer data from tables to gtksheet using x_window_add_items.  
170     This fcn does the following:
171     * Create a new gtksheet having the current dimensions.
172     * Call x_gktsheet_add_row_labels(*_count, master_*_list_head)
173     * Call x_gktsheet_add_col_labels(*_attrib_count, master_*_attrib_list_head)
174     * loop on i, j -- call x_gtksheet_add_entry(i, j, attrib_value), taking the 
175       values out of sheet_heat->*_table.
176     * Call gtk_widget_show(window) to show new window.
179 ---------------------------------------------------------------------------------
180 ********  How data gets from GtkSheet into TOPLEVEL upon saving a sheet  ********
181 ---------------------------------------------------------------------------------
182 Here's what happens when file->save is invoked from the menu.  Please keep in 
183 mind that gattrib is a thin layer between GtkSheet and TOPLEVEL.  When you save
184 out a design, the purpose of gattrib is to take all the stuff out of GtkSheet 
185 and put it temporarily into sheet_data->*_table.  From there, it can then
186 stick it into TOPLEVEL.  Thereafter, libgeda fcns are used to save it.
188 1.  Selecting "save" from the menubar invokes the callback 
189     s_toplevel_menubar_file_save.
190     (callbacks are defined in includes/x_menu.h)
191     This calls s_toplevel_gtksheet_to_toplevel.  
193 2.  s_toplevel_gtksheet_to_toplevel calls s_sheet_data_gtksheet_to_sheetdata. 
194     Then it loops on all pages and calls s_toplevel_sheetdata_to_toplevel.  (Described 
195     starting in item 6 below.)
197 3.  s_sheet_data_gtksheet_to_sheetdata calls s_table_gtksheet_to_all_tables.
199 4.  s_table_gtksheet_to_all_tables calls s_table_gtksheet_to_table individually 
200     for each sheet (comps, nets, pins)
202 5.  s_table_gtksheet_to_table loops over all cells in the the gtksheet 
203     and loads all the stuff it finds back into sheet_data->*_table.
205 6.  Back in s_toplevel_gtksheet_to_toplevel.  Now that the tables are loaded, 
206     we loop on all pages and call s_toplevel_sheetdata_to_toplevel with a pointer
207     to the first obj on the page as the calling arg.
209 7.  Inside s_toplevel_sheetdata_to_toplevel, we loop on all objs in the page, 
210     find the corresponding entry in sheet_data->*_table, and then copy 
211     all attribs out of sheet_data->*_table and back into the object's attrib list.
213 8.  Finally, the libgeda fcn s_page_save_all is called.  This saves out all
214     pages in the design.
217 -----------------------------------------------------------------------
218 Data structures used in gEDA.
220 These notes attempt to document the data structures used in gEDA.  I
221 present them here because they may not be familiar to those interested
222 in hacking gattrib.  I also want to record these findings somewhere
223 because it took me some time to figure this out. 
225 TOPLEVEL:       The basic data structure in gschem.  Basically holds info
226                 about the entire design.
227 PAGE:           Self explanatory.  The entire design is held as a
228                 doubly linked list of PAGEs under TOPLEVEL.
229 OBJECT:         A graphical object on the gschem page.  Can be a net
230                 segment, a component complex, a bit of text, a
231                 component's pin, or whatever.  Each page holds a
232                 doubly linked list of OBJECTs present on that page.
233 TILE:           A section of the graphical page.  Important in
234                 gschem, a TILE holds a single linked list of OBJECTs
235                 present in its subsection of the page.  Each page
236                 holds a two dimensional doubly linked list of TILEs.  
237                 A TILE is used to quickly locate a particular object 
238                 when handling the graphical drawing of a schematic.
239 NETLIST:        Important in gnetlist.  This is a doubly linked list
240                 of component objects and pins.
243 -----------------------------------------------------------------------------
244 Represenatation of components, component attributes, & pins in gattrib & gEDA.
247 From the top down to a particular graphical object on a schematic page:
249 (TOPLEVEL *pr_current)->(PAGE page_current)->(OBJECT o_current) 
251 That is, all objects in the design are graphical objects, and are held 
252 in a linked list.  Note that an object is any graphical object, 
253 such as text, a component (COMPLEX), an attribute, a line, a net, etc.
254 Stuff attached below the OBJECT level determine
255 what kind of object the graphic is, its visibility, its name, etc. etc. etc.  
258 ----  Components with attributes  ----
259 Starting from a component (COMPLEX), an attribute is represented like this:
260 (OBJECT *component)->(ATTRIB *attribs)->(OBJECT *attrib_graphic)->(TEXT *text)->(char *string) // name=value string
261                                                                               ->(int x, y)     // which coords?
262                                                                               ->(int screen_x) // ???
263                                                                                 etc . . .
264                                                                 ->(int type)   // types defined in o_types.h
265                                                                 ->(int sid)    // unique identifier
266                                                                 ->(char *name) // something like text.3732
268 Note that ATTRIB is a linked list of (pointers to) attributes.
269 (OBJECT *component) points to the ATTRIB list, and "attrib_graphic" points
270 to the attrib OBJECT itself (which is a graphical element like everything else).  
273 ----  Attributes  ----
274 Since each attribute is itself a graphical object present in the design, 
275 an attribute graphic is represented like this:
276 (OBJECT *attribute)->(TEXT *text)->(char *string) // name=value string
277                                  ->(int x, y)     // which coords?
278                                  ->(int screen_x) // ???
279                                     etc . . .
280                    ->(int type)  // for attribute, type is text
281                                  // #define OBJ_TEXT       'T'
282                    ->(int sid)
283                    ->(char *name)
284                    ->(ATTRIB *attached_to)  // points back to (OBJECT *component)
285                    ->(int attribute)        // = 1 for attribute, = 0 otherwise.
286                    ->(int show_name_value)  // #define SHOW_NAME_VALUE         0
287                                             // #define SHOW_VALUE              1
288                                             // #define SHOW_NAME               2
289                    ->(int visibility)       // #define INVISIBLE       0
290                                             // #define VISIBLE         1
292 Attrib_graphic is stored internally as a "name=value" string, and is disassembled
293 by various fcns when needed.
296 ----  Pins  ----
297 As for pins, they are attached to components (COMPLEX) in the following way.
298 Starting from the component:
299 (OBJECT *component)->(COMPLEX *complex)->(OBJECT *prim_objs)->(int type)        // #define OBJ_PIN  'P'
300                                                             ->(ATTRIB *attribs) // pin attrib list.
301                                                             ->(int sid)         // unique identifier
302                                                             ->(char *name)      // something like pin.3372
305 Pins also are held in the NETLIST data structure, which is a separate data structure.
306 NETLIST is more important in gnetlist than in gschem.  A pin is held in the following 
307 way:
308 (NETLIST *node)->(OBJECT *object_ptr)
309                ->(CPINLIST *cpins)->(char *pin_number)
310                                   ->(char *net_name)
311                                   ->(char *pin_label)
315 ----  Example  ----
316 Component objects (COMPLEX) have lots of other other fields in teh struct.
317 Here's an example taken  from a real design:
319 (OBJECT *component)->name                                 = complex.188       // unique ID of component
321                    ->attribs->object->name                = complex.188       // first "attribs" points back to component
322                    ->attribs->next->object->name          = text.272          // attrib text
323                    ->attribs->next->object->text->string  = refdes=C1         // actual attrib
324                    
325                    ->complex->prim_objs->name             = complex-head.189  // head of prim_objs list                      
326                    ->complex->prim_objs->next->name       = pin.190           // actual object
328 Each list attached to a component has a head, followed by the actual list
329 items.
332 -----------------------------------------------------------------------
333 From include/struct.h:
335 /* ----------- SDB note about philosophy behind globals -------------- *
336  * I made the "TOPLEVEL project" and all the GTK window stuff into
337  * global variables.  I know that this is supposedly bad programming form.    
338  * However, here are some observations:
339  * -- I wanted to use gEDA's TOPLEVEL structure as much as possible, at
340  *    least to hold info about the design's netlist & components.  
341  *    The TOPLEVEL strucuture is architected to hold info about gschem's 
342  *    window also.  HOwever, gschem's windows are architected differently
343  *    than mine in gattrib.  This is because my windowing system does
344  *    completely different things, and also uses the GtkSheet widget, which
345  *    is architected completely differently from TOPLEVEL.
346  * -- Since I couldn't easily or naturally cram my windowing scheme into 
347  *    TOPLEVEL (or so I think), I decided to use a separate set of windows 
348  *    from those defined under TOPLEVEL for my application.
349  * -- The problem arises when using callbacks.  Callbacks from GTK allow
350  *    only one argument to be passed.  Given the way I set up the menu bar, 
351  *    I didn't have easy acces to the information inside both the GtkSHeet
352  *    objects *and* the TOPLEVEL stuff while only having one callback
353  *    argument.  This makes it hard to have access to e.g. a GtkSheet window 
354  *    and a list of files (in TOPLEVEL) simultaneously.
355  * -- Therefore, I decided to make both the window stuff and TOPLEVEL 
356  *    globals.
357  * -- Similarly, because I couldn't cram the SHEET_DATA struct into any
358  *    hook in TOPLEVEL, I just made it a global also.
359  * -- Finally, in my defense, in gschem and gnetlist, (TOPLEVEL *w_current 
360  *    or pr_current) is passed  to almost every function.  Since it 
361  *    is just a pointer to a huge struct of stuff, manipulating 
362  *    the stuff in the struct has a global
363  *    effect.  That is, manipulating w_current (or pr_current) has side 
364  *    effects, so it is basically a global anyway.  The real problem with 
365  *    globals occurs when you have a global variable caled "i" or "temp"
366  *    which conflicts with a global in a module written by somebody else.
367  *    Since pr_current is a very uncommon name, this should not be a 
368  *    problem here.  Therefore, I decided 
369  *    to make life easy for myself dealing with callbacks by making both 
370  *    the windows and TOPLEVEL global variables.
371  * If there is a better way to solve this problem, I'd like to hear it.
372  * ------------------------------------------------------------------ */
375 -----------------------------------------------------------------------
376 To be done:
377 1.  Before building spreadsheet, create and sort component and net 
378     master lists.  They are used to index components in the TABLE,
379     and also label the gtk_sheet rows and cols.
380 2.  How to handle attribute visibility?  Maybe right-click on cell & set 
381     vis.  Default = invisible and "both name and value".
382 3.  Need fcns to allow for adding and deleting of entire attrib
383     columns.  Don't need to allow for adding/deleting components
384     -- users should use gschem to add/delete components because 
385     gattrib can't do anything about the graphical position data
386     required for this.
390 -----------------------------------------------------------------------
391 Here's what the filename prefix letters mean:
393         a_ : Action (this was a really poor choice, and will be removed)
394         g_ : Guile related functions
395         i_ : Interface related functions
396         o_ : graphic Object related functions
397         x_ : X related functions
398         f_ : File related functions
399         m_ : Math related functions
400         s_ : data Structure related functions
402         I've tried to keep the function names in the files correct, but
403         sometimes I failed.  (look at libgeda/a_basic.c for an example of
404         a file which has a bunch of functions which shouldn't be in there)
406                                                                 -Ales
407 -----------------------------------------------------------------------