When one is debugging some tedious structure-based code one often has the locals window open with some structure spread open as if it were on a disection table, revealing its internals in gory detail. Sometimes one would like a snapshot of the data and an abortive visit to the File|Print menu item is then usually followed by a muffled curse. A flurry of context menu examination and menu poking then tends to result in a printscreen and visit to Paint or similar...
Is there a better way of recording the state of variables during a debugging session? Copy to file, print, anything? Could we have something, please?
You could probably write Slick C code to do this yourself. Look at debug_gui_update_locals in debuggui.e in slick macros folder - you'll see this code
tree_wid1._TreeBeginUpdate(TREE_ROOT_INDEX);
status=dbg_update_locals_tree(tree_wid1, TREE_ROOT_INDEX, thread_id, frame_id, null);
tree_wid1._TreeEndUpdate(TREE_ROOT_INDEX);
tree_wid1._TreeSortUserInfo(TREE_ROOT_INDEX,'N');
tree_wid1.debug_gui_reexpand_fields(TREE_ROOT_INDEX);
tree_wid1.debug_warn_if_empty();
tree_wid1._TreeSortCol();
tree_wid1._TreeRefresh();
and see this in debug.sh
/**
* Update the list of local variables for the specified
* stack frame within the given thread.
* Each local has three columns:
* <UL>
* <LI>variable bitmap (variable or parameter)
* <LI>local variable name
* <LI>value of variable
* </UL>
*
* @param tree_wid window ID of tree control
* @param tree_index Index to insert under (TREE_ROOT_INDEX)
* @param thread_id Thread ID to look at stack for
* @param frame_id ID of Stack frame to inspect
* @param local_path (optional) position to start updating tree at
*
* @return 0 on success, <0 on error.
*
* @categories Debugger_Functions
*/
int dbg_update_locals_tree(int tree_wid,int tree_index,
int thread_id,int frame_id,_str local_path=null);
and this
void _tbdebug_locals_form.on_create()
{
dbg_invalidate_views();
int editable_flag=(debug_session_is_implemented("modify_local")==0)? 0:TREE_BUTTON_EDITABLE;
ctl_locals_tree._TreeSetColButtonInfo(0,1500,TREE_BUTTON_PUSHBUTTON|TREE_BUTTON_SORT,0,"Name");
ctl_locals_tree._TreeSetColButtonInfo(1,10000,TREE_BUTTON_PUSHBUTTON|TREE_BUTTON_WRAP|TREE_BUTTON_AUTOSIZE|editable_flag,0,"Value");
ctl_locals_tree._TreeRetrieveColButtonInfo();
ctl_locals_tree.p_user=0;
...
You can also see in debug_gui_locals_tree() that the locals tree control is a _tree_view named ctl_locals_tree. In sysobjs.e you'll see it's a control on the _tbdebug_locals_form form.
In debug_gui_update_locals(), after the call to _TreeRefresh(), you could iterate through the tree yourself and output the variables and values somewhere (e.g. add an extra parameter to the function that defaults to off and when on, it outputs the tree data - or make a new function similar to debug_gui_update_locals(). For info on iterating through a treeview control, see "Macro functions by category" -> tree view methods. You'll see functions like _TreeGetNextSiblingIndex, _TreeGetFirstChildIndex etc. An itemindex of zero specifies the root of the tree but you use the supplied TREE_ROOT_INDEX macro for this.
Update : Oops, I forgot to check if there is a way to get the info back from the tree control - if you look at this function in treeview.e
void _TreeSaveNodes(TREENODESTATE &state, int index=TREE_ROOT_INDEX)
{
_TreeGetInfo(index, state.show_children, state.bm1, state.bm2, state.flags);
state.caption = _TreeGetCaption(index);
state.current = (index == _TreeCurIndex());
state.children._makeempty();
state.user_info = _TreeGetUserInfo(index);
int numChildren=0;
if (state.show_children >= 0) {
int child = _TreeGetFirstChildIndex(index);
while (child > 0) {
_TreeSaveNodes(state.children[numChildren++], child);
child = _TreeGetNextSiblingIndex(child);
}
}
}
struct TREENODESTATE {
_str caption; // node caption
int bm1, bm2; // current and other bitmaps
int show_children; // show children (-1, 0, or 1)
int flags; // TREENODE_* flags
typeless user_info; // user info for node
boolean current; // is this the current item in the tree?
TREENODESTATE children[]; // list of children under this node
};
you can see it iterating through a tree control. I'm guessing that "caption" has the variable name and/or value that you want - you'll have to experiment to find out. user_info might also be interesting because you can see the call to _TreeSortUserInfo further above. Hence you could call tree_wid1._TreeSaveNodes in debug_gui_update_locals() to get the info into a slick c data structure, then output it.
Note - it's probably best not to modify debug_gui_update_locals() itself since it's called from event handlers like _tbdebug_locals_form.on_change - slick treeview code is not re-entrant in my experience and also you could destroy things like the "active window/form" which are still needed by the caller, but you can easily make your own function similar to debug_gui_update_locals() and it probably doesn't need to actually update the treeview info.
Hmm, except that the code you add won't be executed unless you call the function yourself so forget the re-entrant problem - but it's best not to modify slick source if you don't have to so making your own function is best anyway.
Without actually doing it I can't tell if this would be successful but feel free to ask if you want any more help.
Also, you might be able to get the screen co-ordinates and width/height of the locals window (or any window) and find a way to "print" the screen content of that area. Off the top of my head I don't know how to do this - see functions like AutoCompleteShowList(), _GetScreen and _adjust_above_below(). If you're using Windows you might find an API call for printing a region of the screen - or ask on a Windows forum.
Graeme