Frame windows and tab collections

Tables may be grouped together in one window as resizable panes or frames (like CPU), or as the tab collection where only one table is visible at once (Search). Both are described by the structure t_frame.


Frame windows

The layout of the frame window is defined by the linked tree of structures of type t_block:

typedef struct t_block {               // Block descriptor
  int            index;                // Index of pos record in the .ini file
  int            type;                 // One of BLK_xxx
  int            percent;              // Percent of block in left/top subblock
  int            offset;               // Offset of dividing line, pixels
  struct t_block *blk1;                // Top/left subblock, NULL if leaf
  int            minp1;                // Min size of 1st subblock, pixels
  int            maxc1;                // Max size of 1st subblock, chars, or 0
  struct t_block *blk2;                // Bottom/right subblock, NULL if leaf
  int            minp2;                // Min size of 2nd subblock, pixels
  int            maxc2;                // Max size of 2nd subblock, chars, or 0
  t_table        *table;               // Descriptor of table window
  wchar_t        tabname[SHORTNAME];   // Tab (tab window only)
  wchar_t        title[TEXTLEN];       // Title (tab window) or speech name
  wchar_t        status[TEXTLEN];      // Status (tab window only)
} t_block;

Each node in the tree describes either a separator (horizontal BLK_HDIV or vertical (BLK_VDIV) or a table (BLK_TABLE). Table is always a leaf node. Separator points to two other nodes, blk1 and blk2, which may itself be separators, tables, or a mix of two.

Let's have a look on the tree that describes the layout of the CPU window:

t_block cpu[] = {
  { 0, BLK_HDIV,  60, 0, cpu+1, 6, 0, cpu+3, 3, 0,     NULL,             L"", L"",             L"" },
  { 1, BLK_VDIV,  65, 0, cpu+2, 3, 0, cpu+6, 3, 0,     NULL,             L"", L"",             L"" },
  { 2, BLK_HDIV,  50, 0, cpu+4, 3, 0, cpu+5, 3, NINFO, NULL,             L"", L"",             L"" },
  { 3, BLK_VDIV,  50, 0, cpu+7, 3, 0, cpu+8, 3, 0,     NULL,             L"", L"",             L"" },
  { 4, BLK_TABLE,  0, 0, NULL,  0, 0, NULL,  0, 0,     &cpudisasm.table, L"", L"Disassembler", L"" },
  { 5, BLK_TABLE,  0, 0, NULL,  0, 0, NULL,  0, 0,     &cpuinfo,         L"", L"Info",         L"" },
  { 6, BLK_TABLE,  0, 0, NULL,  0, 0, NULL,  0, 0,     &cpuregs,         L"", L"Registers",    L"" },
  { 7, BLK_TABLE,  0, 0, NULL,  0, 0, NULL,  0, 0,     &cpudump.table,   L"", L"Dump",         L"" },
  { 8, BLK_TABLE,  0, 0, NULL,  0, 0, NULL,  0, 0,     &cpustack.table,  L"", L"Stack",        L"" }
};

Here is the same structure, graphically:

CPU frame tree

Node 0 is a horizontal separator. blk1 (top part) points to the node 1 (Disassembler, Info and Register), blk2 (bottom part) - to the node 3 (Dump and Stack). Default space distribution is set to 60% for the top part and rest for the bottom part. Note that default distribution is important only when OllyDbg starts for the first time because frame window saves its layout to the initialization file (section t_frame.name).

Node 1 is a vertical separator. blk1 (left part) points to the node 2 (Disassembler and Info), blk2 (right part) - to the node 6. Node 6 is a leaf with blk1=blk2=NULL and defined table pointer. Frame has no influence on the properties of this table, it only can resize the window. What will be shown in the window depends on the table, and only on it. In our case, table cpuregs displays the contents of registers.

Nodes 4, 7 and 8 are dumps. Dump descriptor t_dump includes t_table as its member, and frame must address this member. Note that dump tables keep pointer to the original dump descriptor in t_table.customdata.

Member t_block.index is a unique identifier used when saving data to the initialization file. When indices change, previous appearance can't be restored.

If
flag TABLE_GRAYTEXT in t_frame.mode is set, all tables except for one with focus are grayed. To prevent this, table must set TABLE_NOGRAY.


Tab collections

Tab collections are described by
the linked chain of structures of type t_block. All nodes must be of type BLK_TABLE. Unlike frames, where tables are leafs, tab collections use blk1 to link to the next tab. End of the chain is marked by blk1=NULL. Member t_block.index is ignored and can be reused. For example, Search window sets it to the zero-based sequential number of the tab in the chain.

Tab windows support menu (t_frame.menu) that opens with the right click on the tab itself. Menu function receives fake table descriptor where t_table.custommode is set to the index of clicked tab and t_table.customdata points to t_block.


Frame creation

Before you can create table window, you must prepare all necessary structures:
  • Initialize descriptors of all tables that comprise the frame (structures t_table or t_dump)
  • Initialize the linked tree of block descriptors (structures t_block). Point t_block.table in leaf nodes to table descriptors
  • Fill frame descriptor (structure t_frame) and point t_frame.block to the root node of the tree
This must be done only once. Now, any time you want to create the window, call Createframewindow(). That's all.

Creation of tab collections is similar. You only need to call Createtabwindow() instead of
Createframewindow().


API functions:

HWND Createframewindow(t_frame *pf,wchar_t *icon,wchar_t *title);
void Updateframe(t_frame *pf,int redrawnow);
t_table * Getactiveframe(t_frame *pf);

HWND Createtabwindow(t_frame *pf,wchar_t *icon,wchar_t *title);
int Updatetabs(t_frame *pf);
t_table * Getactivetab(t_frame *pf);
int Gettabcount(t_frame *pf,int *index);
int Setactivetab(t_frame *pf,int index);


See also:
Dumps, menus, tables, t_block, t_dump, t_frame, t_table