include "../include/PT8-Main.h"
// Enum representing tree view types, these are embedded in collumn
// number 4 (hidden) in every data view treeview.
enum {
DV_TYPE_NONE,
DV_TYPE_HEX,
DV_TYPE_DISASM,
DV_TYPE_HEAP,
DV_TYPE_ANALYSIS
};
// The data viewer display, and data viewer widgets are used
// to view process information.
// Widget Types:
// Data Viewer DISPLAY == Modified Tree Store Widget
// Data Viewer == Window containing tree store widget
// All functions pertaining to the dataviewer are found here
// any dataviewer functions must be portable in the sense that
// the data viwer source and header may be removed and used in
// other applications utilizing GTK.
// What is a data viewer:?
// A data viewer is a GTK window which is dynamically created to
// display data in a variety of formats. The formats supported
// are Hex, Assembly, Heap, Stack, and Analysis Mode.
// The dataviewer display handles large sets of data by utilizing callbacks
// that act on various build in lists. The callbacks are built into
// the scrolling mechanism.
// Main Range Callback: This range represents the vscrollbar in the
// nested window. What needs to happen is
void DV_MainRangeCallback(GtkRange *range,
gpointer user_data){
// Retrieve parent scrolled window from range
GtkWidget * parentHbox = (GtkWidget *) gtk_widget_get_parent((GtkWidget *) range);
if(parentHbox == NULL)
return;
// Retrieve a widget list from the hbox container
GList * childWidgetList = gtk_container_get_children((GtkContainer *) parentHbox);
if(childWidgetList == NULL)
return;
// Extract child widgets from the hbox
GtkWidget * packedScrollWindow = (GtkWidget *) childWidgetList->data;
if(packedScrollWindow == NULL)
return;
GtkWidget * treeView = (GtkWidget *) gtk_bin_get_child((GtkBin *) packedScrollWindow);
if(treeView == NULL)
return;
GtkWidget * treeModel = (GtkWidget *) gtk_tree_view_get_model((GtkTreeView *) treeView);
if(treeModel == NULL)
return;
// Get the top iter
GtkTreeIter topIter;
int success = gtk_tree_model_get_iter_first((GtkTreeModel *) treeModel, &topIter);
// false if the tree is empty
if(success == false)
return;
// Get the model type first
unsigned int modelType = 0;
gtk_tree_model_get((GtkTreeModel *) treeModel, &topIter, 4, &modelType, -1);
// retrieve new range and round it off
long roundedRange = (long) gtk_range_get_value(range);
printf("\n RANGE = %u", roundedRange);
// Main switch to pass information off to update functions
switch(modelType){
case DV_TYPE_HEX:
printf("\n woo, got hex type");
break;
case DV_TYPE_DISASM:
printf("\n hehe, got asm type");
DV_AsmUpdateDisplay(parentHbox, roundedRange, 100, NULL);
break;
case DV_TYPE_HEAP:
break;
case DV_TYPE_ANALYSIS:
break;
default:
g_print("\n DataView Callback: Erroneous type.");
break;
}
// We are done with the list, so it can be free'd
g_list_free(childWidgetList);
// Ok, now get the tree store's top instruction.
// First, get list first pointer.
// Get scroll window tree view first
// unsigned int instructionCount = X86_32_GetInstructionCount(P_X86_32_DECODED_INSTRUCTION_LIST instructions);
// Extract tree view from the scrolled window
}
// Destroys a data viewer that was created with CreateDataViewer
unsigned int DestroyDataViewer(GtkWidget *dataViewer){
return ERR_SUCCESS;
}
// Create a new data viewer window packed with toolbar to display data
// on the fly.
GtkWidget * CreateDataViewer(unsigned char *data, unsigned int length, unsigned int initialDisplayType, P_DV_HIGHLIGHT_RANGE initialHighlight){
if(data == NULL || length == 0)
return NULL;
// --------------------------------------------------------------
// Window Initialization
// Sets upa lookup path to the default dv window icon
char lookupPath[sizeof(DV_DEFAULT_ICON_PATH) + 500];
memset(lookupPath, 0x00, sizeof(lookupPath));
strncat(lookupPath, DV_DEFAULT_ICON_PATH, sizeof(DV_DEFAULT_ICON_PATH));
strncat(lookupPath, "/dv-icon.png", strlen("/dv-icon.png"));
// Retrieve the windows custom icon
gtk_window_set_default_icon_from_file(lookupPath, NULL);
// create the new window (perhaps proxy function when
// logc is completed)
GtkWidget *window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
g_object_set(G_OBJECT(window),
"title", "[Prototype-8: Data Viewer]",
NULL);
gdk_window_set_back_pixmap(window->window, NULL, FALSE);
// set border width
gtk_container_set_border_width(GTK_CONTAINER(window), 0);
// Connect window to destroy an delete events
g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(DestroyDataViewer), NULL);
// -----------------------------------------------------------
// Create top toolbar
// Create the default HBox (non-homogenous, 0px spacing)
GtkWidget *outermostVbox = gtk_vbox_new(FALSE, 0);
// Create a new toolbar
GtkToolbar *toolBar = (GtkToolbar *) gtk_toolbar_new();
/*
* "expand", false,
"fill", false,
*/
/*
g_object_set(G_OBJECT(toolBar),
"icon-size", GTK_ICON_SIZE_SMALL_TOOLBAR,
"icon-size-set", true,
NULL);
*/
// -----------------------------------------------------------
// Create toolbar buttons
// Icon pointer used to set icons
GtkWidget *winIcon;
// Set Disassemble Button-----------------------------------------
memset(lookupPath, 0x00, sizeof(lookupPath));
strncat(lookupPath, DV_DEFAULT_ICON_PATH, sizeof(DV_DEFAULT_ICON_PATH));
strncat(lookupPath, "/dv-disassemble.png", strlen("/dv-disassemble.png"));
winIcon = gtk_image_new_from_file (lookupPath);
GtkToolItem * disassembleButton = gtk_tool_button_new(winIcon, NULL);
gtk_toolbar_insert(toolBar, disassembleButton, 0);
// Set hex view button-------------------------------------
memset(lookupPath, 0x00, sizeof(lookupPath));
strncat(lookupPath, DV_DEFAULT_ICON_PATH, sizeof(DV_DEFAULT_ICON_PATH));
strncat(lookupPath, "/dv-hex.png", strlen("/dv-hex.png"));
winIcon = gtk_image_new_from_file (lookupPath);
GtkToolItem * hexButton = gtk_tool_button_new(winIcon, NULL);
gtk_toolbar_insert(toolBar, hexButton, 0);
// Set analysis button-------------------------------------
memset(lookupPath, 0x00, sizeof(lookupPath));
strncat(lookupPath, DV_DEFAULT_ICON_PATH, sizeof(DV_DEFAULT_ICON_PATH));
strncat(lookupPath, "/dv-analysis.png", strlen("/dv-analysis.png"));
winIcon = gtk_image_new_from_file (lookupPath);
GtkToolItem * analysisButton = gtk_tool_button_new(winIcon, NULL);
gtk_toolbar_insert(toolBar, analysisButton, 0);
// ------------------------------------------------------------
// Create mainview in conjunction with the init type
GtkWidget * dataViewMain = NULL;
unsigned int scaleTopVal = 0;
switch(initialDisplayType){
case DV_INIT_HEX:
// Create the new image, this is effectively our pixmap
// END ATTEMPT
dataViewMain = DV_HexCreateDisplay(data, length, 0x00, initialHighlight);
break;
case DV_INIT_DISASM:
// fifty rows by default
dataViewMain = DV_AsmCreateDisplay(data, length, 50, 0x00, initialHighlight);
// If the data view is not null, retrieve the total number
// of instructions to be used with the range.
if(dataViewMain != NULL){
printf("\n Retrieved proper data view");
// DV_AsmGetInstructionCount(dataViewMain);
}
// unsigned int X86_32_GetInstructionCount(P_X86_32_DECODED_INSTRUCTION_LIST instructions){
break;
case DV_INIT_HEAP:
break;
case DV_INIT_STACK:
break;
case DV_INIT_ANALYSIS:
break;
}
// -------------------------------------------------------------
// Apply custom widget settings
g_object_set(G_OBJECT(outermostVbox),
"height-request", 400,
"hscrollbar-policy", GTK_POLICY_AUTOMATIC,
NULL);
// gtk_image_get_pixmap((GtkImage*) bgImage, bgPixmap, NULL);
// ATTEMPT TO PAINT WIDGET BACKGROUND
// 1. gtk_widget_realize(widget)
// gtk_widget_realize(dataViewMain);
// 2. gtk_widget_set_app_paintable(widget)
// gtk_widget_set_app_paintable(dataViewMain,TRUE);
// 3. gtk_window_set_back_pixmap(window, winIcon, FALSE);
// gdk_window_set_back_pixmap(dataViewMain->window, *bgPixmap, FALSE);
// ------------------------------------------------------------
// Finish up and Show the Widgets
// Pack Toolbar
gtk_box_pack_start((GtkBox *) outermostVbox, (GtkWidget *) toolBar, FALSE, FALSE, 0);
// pack custom dataview into window
gtk_box_pack_start((GtkBox *) outermostVbox, dataViewMain, false, false, 0);
gtk_widget_show(dataViewMain);
// Add the VBox to the window
gtk_container_add(GTK_CONTAINER(window), outermostVbox);
// Show widget and return
gtk_widget_show_all(window);
return window;
}
// ---------------------------------------------------------------
// HEX DISPLAY FUNCTIONS
// Default rows for the hex tree store (row 5 is always type)
enum {
DV_HEX_ADDR,
DV_HEX_DATA,
DV_HEX_ASCII,
DV_HEX_PTR,
DV_HEX_TYPE
};
// Number of bytes to display at a time in 4 byte increments
// must be divisible by 4.
#define HEX_DISPLAY_COUNT 24
// Retrieves Hex Display suitable for a data viewer widget, set as treeview
// DO NOT DESTROY DATA AFTER CREATING DISPLAY. Pointers from the data
// are stored within the hex display itself.
GtkWidget * DV_HexCreateDisplay(unsigned char *data, unsigned int length, unsigned int base, P_DV_HIGHLIGHT_RANGE initialHighlight){
// -----------------------------------------------------------
// Overall widget creation guidelines:
// -----------------------------------------------------------
// Step one, create tree view
// ------------------------------------------------------------
// Step two, create scale representing the total number of 64
// byte increments found in the hex buffer + 64bytes if
// a remainder is found.
// ---------------------------------------------------------------
// Step three, create custom hBox and pack the scale and tree
// view.
// ---------------------------------------------------------------
// -----------------------------------------------------------
// Step one, create tree view
GtkWidget *view;
GtkTreeModel *model;
GtkTreeStore * store;
GtkTreeModel *mode;
GtkCellRenderer *renderer;
GtkTreeIter iter, child;
// set up an new tree store (5 elements)
store = gtk_tree_store_new(5, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_POINTER, G_TYPE_INT, NULL);
// derive new model off of store
model = GTK_TREE_MODEL(store);
// Create new tree view based off the model
view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(model));
g_object_set(G_OBJECT(view),
"enable-search", false,
"enable-grid-lines", true,
"reorderable", false,
"app-paintable", true,
NULL);
gdk_window_set_back_pixmap(view->window, NULL, FALSE);
// set view and model
gtk_tree_view_set_model(GTK_TREE_VIEW(view), model);
renderer = gtk_cell_renderer_text_new ();
g_object_set(G_OBJECT(renderer),
"foreground", "#045E00",
NULL);
gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (view),
-1,
"Address",
renderer,
"text", DV_HEX_ADDR,
NULL);
renderer = gtk_cell_renderer_text_new ();
g_object_set(G_OBJECT(renderer),
"foreground", "#070098",
"size", 9000,
"family", "Monospace",
NULL);
gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (view),
-1,
"Data",
renderer,
"text", DV_HEX_DATA,
NULL);
renderer = gtk_cell_renderer_text_new ();
g_object_set(G_OBJECT(renderer),
"foreground", "#070098",
"size", 9000,
"family", "Monospace",
NULL);
gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (view),
-1,
"Ascii",
renderer,
"text", DV_HEX_ASCII,
NULL);
// Create hidden pointer collumn for data row pointer (dependent on
// initial data)
renderer = gtk_cell_renderer_text_new ();
gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (view),
-1,
"PTR",
renderer,
"text", DV_HEX_PTR,
NULL);
// Create hidden integer collumn to represent the data type
renderer = gtk_cell_renderer_text_new ();
gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (view),
-1,
"TYPE",
renderer,
"text", DV_HEX_TYPE,
NULL);
// Block size is natively 24 bytes per row
unsigned int blocks = 0;
unsigned int remainder = 0;
// counts blocks in main loop
unsigned int i = 0;
// inner loop vars
unsigned int x = 0, y = 0;
// If the length is greater then 64, set remainder as
if(length < HEX_DISPLAY_COUNT){
// set remainder to length, as length is less then one line
// block.
remainder = length;
length = 0;
} else {
// Set blocks and remainder
blocks = length / HEX_DISPLAY_COUNT;
remainder = length % HEX_DISPLAY_COUNT;
}
// Loop through the data and print available data
// Addr string used to print out the occuring address of the data
char addrStr[16];
memset(addrStr, 0x00, 16);
// Data Str is used to actually append data to the tree store
// it is 84 bytes to represent 64 bytes plus 20 bytes of additional
// padding.
char dataStr[200];
memset(dataStr, 0x00, 200);
// Ascii String (64bytes + 20 for padding)
char asciiStr[200];
memset(dataStr, 0x00, 200);
// Data holder for translations (need to memcpy bytes into this
// variable to get correct translatoins)
unsigned int dwData;
// total offset for entire buffer read
unsigned int totalOffset = 0;
for(i = 0; i < blocks; i++){
sprintf(addrStr, "0x%.08x: ", (unsigned int) base);
// assign data string (+base on loop to move string forward
memset(dataStr, 0x00, 200);
memset(asciiStr, 0x00, 200);
for(x = 0; x < 32; x+=4){
memcpy((void *) &dwData, (void *) &data[totalOffset+x], 4);
sprintf(&dataStr[strnlen(dataStr, 83)], "%.08x ", dwData);
memcpy(&asciiStr[x], &dwData, 4);
}
//DV_HEX_ADDR,
// DV_HEX_DATA,
// DV_HEX_ASCII
// Add strings to store and loop
gtk_tree_store_append (store, &iter, NULL);
gtk_tree_store_set (store, &iter,
DV_HEX_ADDR, addrStr,
DV_HEX_DATA, dataStr,
DV_HEX_ASCII, asciiStr,
DV_HEX_PTR, &data[totalOffset],
DV_HEX_TYPE, DV_TYPE_HEX,
-1);
// Advance offset for total read
totalOffset += HEX_DISPLAY_COUNT;
base += HEX_DISPLAY_COUNT;
}
// Add last row for remainder if exists
if(remainder > 0){
// Set the entire data string to spaces for alignment
// assign data string
memset(dataStr, 0x00, 200);
memset(asciiStr, 0x00, 200);
for(i = 0; i < remainder; i+=4){
memcpy((void *) &dwData, (void *) &data[totalOffset+i], 4);
sprintf(&dataStr[strnlen(dataStr, 83)], "%.08x ", dwData);
memcpy(&asciiStr[i], &dwData, 4);
}
sprintf(addrStr, "0x%.08x: ", (unsigned int) base);
gtk_tree_store_append (store, &iter, NULL);
gtk_tree_store_set (store, &iter,
DV_HEX_ADDR, addrStr,
DV_HEX_DATA, dataStr,
DV_HEX_ASCII, asciiStr,
-1);
}
// ------------------------------------------------------------
// Step two, create scale representing the total number of instructions
// in the instruction list.
// the vScale for our new widget: Blocks plus 1 = 64bytes[x]+64bytes
GtkWidget * vScale = gtk_vscale_new_with_range(0, blocks+1, 1);
// set scale callback
g_signal_connect(G_OBJECT(vScale), "value-changed", G_CALLBACK(DV_MainRangeCallback), NULL);
// ---------------------------------------------------------------
// Step three, create custom hBox and pack the scale and tree
// view.
// Testing, create new hbox
GtkWidget * customHbox = gtk_hbox_new(false, 0);
// create scrolled window to hold the tree widget
GtkWidget * treeScrollWindow = gtk_scrolled_window_new(NULL, NULL);
gtk_container_add((GtkContainer *) treeScrollWindow, view);
// may have to re-add "width-request", 700,
g_object_set(G_OBJECT(customHbox),
"height-request", 400,
"hscrollbar-policy", GTK_POLICY_AUTOMATIC,
NULL);
g_object_set(G_OBJECT(treeScrollWindow),
"vscrollbar-policy", GTK_POLICY_NEVER,
"hscrollbar-policy", GTK_POLICY_ALWAYS,
NULL);
// Pack Data View
gtk_box_pack_start((GtkBox *) customHbox, (GtkWidget *) treeScrollWindow, true, true, 0);
// pack the box with scale next
gtk_box_pack_start((GtkBox *) customHbox, vScale, false, false, 0);
// Return the populated tree view, ready for display
return customHbox;
// Return the populated tree view, ready for display
return view;
}
// ----------------------------------------------------------
// ASM VIEW SPECIFIC FUNCTIONS AND DATA
// Default rows for the disasm tree store
enum {
DV_DISASM_ADDR,
DV_DISASM_INST,
DV_DISASM_OPERANDS,
DV_DISASM_PTR,
DV_DISASM_TYPE,
DV_DISASM_NOTES,
};
// Retrieves ASM Display suitable for a data viewer widget, set as treeview
GtkWidget * DV_AsmCreateDisplay(unsigned char *data, unsigned int length, unsigned int maxDisplayRows, unsigned int base, P_DV_HIGHLIGHT_RANGE initialHighlight){
// -----------------------------------------------------------
// Overall widget creation guidelines:
// -----------------------------------------------------------
// Step one, create tree view
// ------------------------------------------------------------
// Step two, create scale representing the total number of instructions
// in the instruction list.
// ---------------------------------------------------------------
// Step three, create custom hBox and pack the scale and tree
// view.
// ---------------------------------------------------------------
// ---------------------------------------------------
// Step 1) Create Tree View
// New base tree view to create
GtkWidget *view;
// New base tree model
GtkTreeModel *model;
GtkTreeStore * store;
GtkTreeModel *mode;
GtkCellRenderer *renderer;
// Cell iters
GtkTreeIter iter, child;
// set up an new tree store (4 elements)
store = gtk_tree_store_new(6, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_POINTER, G_TYPE_INT, G_TYPE_STRING, -1);
// derive new model off of store
model = GTK_TREE_MODEL(store);
// Create new tree view based off the model
view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(model));
g_object_set(G_OBJECT(view),
"enable-search", false,
"enable-grid-lines", true,
"reorderable", false,
NULL);
// dereference model and set to null (speed hack)
g_object_ref(model);
gtk_tree_view_set_model(GTK_TREE_VIEW(view), NULL);
renderer = gtk_cell_renderer_text_new ();
g_object_set(G_OBJECT(renderer),
"foreground", "#045E00",
NULL);
gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (view),
-1,
"Address",
renderer,
"text", DV_DISASM_ADDR,
NULL);
renderer = gtk_cell_renderer_text_new ();
g_object_set(G_OBJECT(renderer),
"foreground", "#5D5858",
NULL);
gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (view),
-1,
"Data",
renderer,
"text", DV_DISASM_INST,
NULL);
renderer = gtk_cell_renderer_text_new ();
g_object_set(G_OBJECT(renderer),
"foreground", "#000000",
"size", 9000,
"family", "Sans",
NULL);
gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (view),
-1,
"Operands",
renderer,
"text", DV_DISASM_OPERANDS,
NULL);
// Hidden collumn to contain the instruction list pointer
// corresponding to the widget. When the row is moved, the
// whole list will be updated but
GtkWidget * columnPtr = NULL;
renderer = gtk_cell_renderer_text_new ();
gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (view),
-1,
"List Pointer",
renderer,
NULL);
columnPtr = (GtkWidget *) gtk_tree_view_get_column((GtkTreeView *) view, DV_DISASM_PTR);
gtk_tree_view_column_set_visible((GtkTreeViewColumn *) columnPtr, false);
// Second hidden collumnl, represents the data type in the row
renderer = gtk_cell_renderer_text_new ();
gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (view),
-1,
"Data Type",
renderer,
NULL);
columnPtr = (GtkWidget *) gtk_tree_view_get_column((GtkTreeView *) view, DV_DISASM_TYPE);
gtk_tree_view_column_set_visible((GtkTreeViewColumn *) columnPtr, false);
renderer = gtk_cell_renderer_text_new ();
g_object_set(G_OBJECT(renderer),
"foreground", "#070098",
"size", 9000,
"family", "Monospace",
NULL);
// Last row, is notes.. its not hidden. Its placed last because of
// the way that the collums are set up. 3'rd and 4th are always taken
// by ptr and type, so this 5th collumn represents the notes.
gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (view),
-1,
"Notes",
renderer,
"text", DV_DISASM_NOTES,
"width", 20,
NULL);
// columnPtr = (GtkWidget *) gtk_tree_view_get_column((GtkTreeView *) view, DV_DISASM_NOTES);
// gtk_tree_view_column_set_visible((GtkTreeViewColumn *) columnPtr, false);
// Retrieve instruction table for global session debugger if not there
// as it is used for disassembly.
if(globals.session.Debugger.instructionTable == NULL){
// THREAD SAFTEY NEEDED
globals.session.Debugger.instructionTable = X86_32_GetX86InstructionTable();
}
// THREAD SAFTEY NEEDED
P_X86_32_DECODED_INSTRUCTION_LIST decodedList = globals.session.Debugger.DbgDecodeInstructionsNL(data, length, base);
P_X86_32_DECODED_INSTRUCTION_LIST decodedListFirst = decodedList->first;
char *instStr = NULL;
char *operStr = NULL;
char *noteStr = NULL;
char addrStr[20];
unsigned int rows = 0;
// Walk the list and fill the treeview
for(decodedList = decodedList->first; decodedList != NULL; decodedList = decodedList->next){
memset(addrStr, 0x00, 20);
// Check instruction first
if(decodedList->instruction == NULL){
instStr = "[bad]";
noteStr = " ";
} else {
instStr = decodedList->instruction->instructionStr;
noteStr = decodedList->instruction->description;
}
// check operands next
if(decodedList->intelDecode == NULL){
operStr = " ";
} else {
operStr = decodedList->intelDecode;
}
sprintf(addrStr, "0x%p:", decodedList->address);
gtk_tree_store_append (store, &iter, NULL);
gtk_tree_store_set (store, &iter,
DV_DISASM_ADDR, addrStr,
DV_DISASM_INST, instStr,
DV_DISASM_OPERANDS, operStr,
DV_DISASM_PTR, decodedList,
DV_DISASM_TYPE, DV_TYPE_DISASM,
DV_DISASM_NOTES, noteStr,
-1);
// Break if we're on the next element
if(decodedList->next == NULL)
break;
// break to only display maxDisplayRows at a time.
if(rows >= maxDisplayRows)
break;
rows++;
}
columnPtr = (GtkWidget *) gtk_tree_view_get_column((GtkTreeView *) view, DV_DISASM_NOTES);
g_object_set(G_OBJECT(columnPtr), "max-width", 10
,"resizable", true,
NULL);
// set view and model
gtk_tree_view_set_model(GTK_TREE_VIEW(view), model);
// ------------------------------------------------------------
// Step two, create scale representing the total number of instructions
// in the instruction list.
// Get top of the list
unsigned int scaleTopVal = X86_32_GetInstructionCount(decodedList->first);
// the vScale for our new widget
GtkWidget * vScale = gtk_vscale_new_with_range(0, scaleTopVal, 1);
// set scale callback
g_signal_connect(G_OBJECT(vScale), "value-changed", G_CALLBACK(DV_MainRangeCallback), NULL);
// ---------------------------------------------------------------
// Step three, create custom hBox and pack the scale and tree
// view.
// Testing, create new hbox
GtkWidget * customHbox = gtk_hbox_new(false, 0);
// create scrolled window to hold the tree widget
GtkWidget * treeScrollWindow = gtk_scrolled_window_new(NULL, NULL);
gtk_container_add((GtkContainer *) treeScrollWindow, view);
// May need to make a width request
g_object_set(G_OBJECT(customHbox),
"height-request", 400,
"hscrollbar-policy", GTK_POLICY_AUTOMATIC,
NULL);
g_object_set(G_OBJECT(treeScrollWindow),
"vscrollbar-policy", GTK_POLICY_NEVER,
"hscrollbar-policy", GTK_POLICY_AUTOMATIC,
NULL);
// Pack Data View
gtk_box_pack_start((GtkBox *) customHbox, (GtkWidget *) treeScrollWindow, true, true, 0);
// pack the box with scale next
gtk_box_pack_start((GtkBox *) customHbox, vScale, false, false, 0);
printf("\n CONFIRMED SCROLLWINDOW PTR: %p", treeScrollWindow);
printf("\n CONFIRMED HBOX PTR: %p", customHbox);
// Working test call
// DV_UpdateAsmDisplay(view, decodedListFirst, 3, NULL);
// Return the populated tree view, ready for display
return customHbox;
}
// Updates the assembly view to render instructions in unison with the current range value
// as the range value increases or decreases, the contents of the treeview change within a
// respective +- threshold.
void DV_AsmUpdateDisplay(GtkWidget *dataView, unsigned int currentRangeValue, unsigned int maxDisplayRows, P_DV_HIGHLIGHT_RANGE initialHighlight){
if(dataView == NULL)
return;
// -----------------------------------------------------
// Steps to take to create the updated window
// -----------------------------------------------------
// Step 1) Extract the treestore from the packed hbox. Get a
// list pointer from the hidden collumns.
// ------------------------------------------------------
// Step 2) Get total list length. The store will be refilled
// along a max value of baseWidgetStoreHeight. Which
// effectively represents the nuber of rows to have in
// the store, total.
// ------------------------------------------------------
// Step 3) move the top of tree store to the value of the
// current range and fill with the remainder of the list
// with baseWidgetStoreHeight number of instructions.
// -------------------------------------------------------
// Remember that dataView is simply a hBox in disguise.
// Retrieve a widget list from the hbox container
GList * childWidgetList = gtk_container_get_children((GtkContainer *) dataView);
if(childWidgetList == NULL)
return;
// Extract child widgets from the hbox
GtkWidget * packedScrollWindow = (GtkWidget *) childWidgetList->data;
if(packedScrollWindow == NULL)
return;
GtkWidget * treeView = (GtkWidget *) gtk_bin_get_child((GtkBin *) packedScrollWindow);
if(treeView == NULL)
return;
GtkWidget * treeModel = (GtkWidget *) gtk_tree_view_get_model((GtkTreeView *) treeView);
if(treeModel == NULL)
return;
// Get the top iter
GtkTreeIter topIter;
unsigned int success = gtk_tree_model_get_iter_first((GtkTreeModel *) treeModel, &topIter);
// false represents an empty tree
if(success == false)
return;
// Get the model type and list pointer from the top of the list
unsigned int modelType = 0;
P_X86_32_DECODED_INSTRUCTION_LIST topList = NULL;
gtk_tree_model_get((GtkTreeModel *) treeModel, &topIter, 4, &modelType, -1);
gtk_tree_model_get((GtkTreeModel *) treeModel, &topIter, 3, &topList, -1);
// Get the list item that represents the current level
printf("\n Got update range: %i", currentRangeValue);
printf("\n Got type: %i", modelType);
printf("\n Got instruction list current top: %p", topList);
printf("\n Got update range: %p", topList->first);
topList = X86_32_GetInstructionAtListPosition(topList->first, currentRangeValue);
if(topList == NULL){
printf("\n toplist is null?");
return;
}
char *instStr = NULL;
char *operStr = NULL;
char *noteStr = NULL;
char addrStr[20];
gtk_tree_store_clear((GtkTreeStore *) treeModel);
unsigned int rows = 0;
// Walk the list and fill the treeview
for(; topList != NULL; topList = topList->next){
memset(addrStr, 0x00, 20);
// Check instruction first
if(topList->instruction == NULL){
instStr = "[bad]";
noteStr = " ";
} else {
instStr = topList->instruction->instructionStr;
noteStr = topList->instruction->description;
}
// check operands next
if(topList->intelDecode == NULL){
operStr = " ";
} else {
operStr = topList->intelDecode;
}
sprintf(addrStr, "0x%p:", topList->address);
gtk_tree_store_append ((GtkTreeStore *) treeModel, &topIter, NULL);
gtk_tree_store_set ((GtkTreeStore *) treeModel, &topIter,
DV_DISASM_ADDR, addrStr,
DV_DISASM_INST, instStr,
DV_DISASM_OPERANDS, operStr,
DV_DISASM_PTR, topList,
DV_DISASM_TYPE, DV_TYPE_DISASM,
DV_DISASM_NOTES, noteStr,
-1);
// Break if we've displayed the total appropriate number
// of rows.
if(rows == maxDisplayRows)
break;
rows++;
// Break if we're on the next element
if(topList->next == NULL)
break;
}
// Now that we've retrieved all relevant data, clear the model
// to get it ready for a redraw.
}
// Retrieves a total instruction count from a Data viewer assembly type
// widget. 0 for failure or none. The dataviewer widget is not
// the window itself, but the hbox corresponding to the scale and
// tree view.
unsigned int DV_AsmGetInstructionCount(GtkWidget * dataViewer){
if(dataViewer == NULL)
return 0;
// Retrieve a widget list for the widget
GList * childWidgetList = gtk_container_get_children((GtkContainer *) dataViewer);
// Extract child widgets from the hbox
GtkWidget * packedScrollWindow = (GtkWidget *) childWidgetList->data;
GtkWidget * treeView = (GtkWidget *) gtk_bin_get_child((GtkBin *) packedScrollWindow);
GtkWidget * treeModel = (GtkWidget *) gtk_tree_view_get_model((GtkTreeView *) treeView);
// Get the top iter
GtkTreeIter topIter;
gtk_tree_model_get_iter_first((GtkTreeModel *) treeModel, &topIter);
// Get the model type from the model next
unsigned int modelType = 0;
gtk_tree_model_get((GtkTreeModel *) treeModel, &topIter, 4, &modelType, -1);
// Exit if the views type is not assembly
if(modelType != DV_TYPE_DISASM){
return 0;
}
// set first instruction and get total count from first instruction
P_X86_32_DECODED_INSTRUCTION_LIST first = NULL;
gtk_tree_model_get((GtkTreeModel *) treeModel, &topIter, 3, &first, -1);
first = first->first;
// get the total instruction count from first pointer
unsigned int retVal = X86_32_GetInstructionCount(first);
return retVal;
}