vcpe/dhcp_tools/detail_wnd.c

564 lines
26 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//
// Created by HuangXin on 2023/4/26.
//
#include <ctype.h>
#include "main.h"
#include "misc.h"
#include "zlog_module.h"
#include "dhcp_network.h"
#include "sds/sds.h"
#include "dhcp_options.h"
#include "user_errno.h"
typedef struct {
U8 op_code;
U8 op_size;
U8 op_value[256];
} STR_OPT;
static GtkWidget *g_detailWnd = NULL;
static GtkWidget *g_statusBar = NULL;
static GtkTextBuffer *g_pTxtBuf[4];
static GtkWidget *g_ptvDHcp[4];
static PDHCP_INFO g_preInfo = NULL;
static const char *g_mess_info[] = {"NONE", "DISCOVER", "OFFER", "REQUEST", "DECLINE",
"ACK", "NAK", "RELEASE", "INFORM"};
static gboolean delete_event(GtkWidget *widget, GdkEventAny *UNUSED(event)) {
/* 如果你的 "delete_event" 信号处理函数返回 FALSEGTK 会发出 "destroy" 信号。
* 返回 TRUE你不希望关闭窗口。
* 当你想弹出“你确定要退出吗?”对话框时它很有用。*/
//gtk_widget_hide_all(window_test);
gtk_widget_hide(widget);
return TRUE; //注意必须为TRUE否则子窗口点击关闭按钮后就摧毁了而不是隐藏了。
}
static void add_dhcp_tree_colums(GtkWidget *treeView) {
GList *cols = gtk_tree_view_get_columns(GTK_TREE_VIEW(treeView));
if (g_list_length(cols) == 0) {
GtkCellRenderer *renderer = gtk_cell_renderer_text_new();
GtkTreeViewColumn *column = gtk_tree_view_column_new_with_attributes("协议", renderer, "text", 0, NULL);
gtk_tree_view_append_column(GTK_TREE_VIEW(treeView), column);
renderer = gtk_cell_renderer_text_new();
column = gtk_tree_view_column_new_with_attributes("", renderer, "text", 1, NULL);
gtk_tree_view_append_column(GTK_TREE_VIEW(treeView), column);
}
}
#define ADD_SUB_STRING(name, s) \
do { \
gtk_tree_store_append(store, &iterSub, &iter); \
gtk_tree_store_set(store, &iterSub, 0, (name), 1, (s), -1); \
} while (0)
#define ADD_SUB_INT(name, fmt, v) \
do { \
gtk_tree_store_append(store, &iterSub, &iter); \
s = sdsempty(); \
sprintf(s, (fmt), (v)); \
gtk_tree_store_set(store, &iterSub, 0, (name), 1, s, -1); \
sdsfree(s); \
} while (0)
#define ADD_SUB_OPTION(code, len, val) \
do { \
U8 *pVal; \
int count_flag = 0; \
gtk_tree_store_append(store, &iterOpt, &iterSub); \
s = sdsempty(); \
sprintf(s, "%u", (len)); \
gtk_tree_store_set(store, &iterOpt, 0, "Length", 1, s, -1); \
sdsfree(s); \
\
switch (dhcp_get_opType(code)) { \
case 1: \
gtk_tree_store_append(store, &iterOpt, &iterSub); \
gtk_tree_store_set(store, &iterOpt, 0, dhcp_get_opName(code), 1, (val), -1); \
break; \
case 2: \
pVal = val; \
do { \
sds sv = sdsempty(); \
gtk_tree_store_append(store, &iterOpt, &iterSub); \
s = sdsempty(); \
sprintf(s, "%s", dhcp_get_opName(*pVal)); \
sprintf(sv, "Request (%03d)", *pVal); \
gtk_tree_store_set(store, &iterOpt, 0, sv, 1, s, -1); \
sdsfree(s); \
sdsfree(sv); \
count_flag++; \
pVal++; \
} while (count_flag != (len)); \
break; \
case 3: \
do { \
U32 *pIp = (U32 *)(val); \
gtk_tree_store_append(store, &iterOpt, &iterSub); \
s = sdsempty(); \
sprintf(s, "%s", u32_to_str_ip(*pIp)); \
gtk_tree_store_set(store, &iterOpt, 0, dhcp_get_opName(code), 1, s, -1); \
sdsfree(s); \
count_flag += 4; \
} while (count_flag != (len)); \
break; \
case 4: \
gtk_tree_store_append(store, &iterOpt, &iterSub); \
for (int i = 0; i < (len); i++) \
count_flag = count_flag * 256 + (val)[i]; \
s = sdsempty(); \
sprintf(s, "%d(s)", count_flag); \
gtk_tree_store_set(store, &iterOpt, 0, dhcp_get_opName(code), 1, s, -1); \
sdsfree(s); \
break; \
case 6: \
gtk_tree_store_append(store, &iterOpt, &iterSub); \
s = sdsempty(); \
if ((code) == OPT_MESSAGETYPE) { \
gtk_tree_store_set(store, &iterOpt, 0, dhcp_get_opName(code), 1, g_mess_info[(val)[0]], -1); \
} \
sdsfree(s); \
break; \
default: \
gtk_tree_store_append(store, &iterOpt, &iterSub); \
gtk_tree_store_set(store, &iterOpt, 0, dhcp_get_opName(code), 1, "", -1); \
} \
} while (0)
static void create_dhcp_tree_mode(PDHCP_PACKAGE p, U32 nBytes, GtkWidget *treeView) {
// 填充右上侧 TreeView 协议数据
sds s;
GtkTreeIter iter, iterSub, iterOpt;
GtkTreeStore *store = NULL; //gtk_tree_store_new(2, G_TYPE_STRING, G_TYPE_STRING);
const char *itemTitle[] = {"Ethernet II", "802.1Q Virtual LAN", "IP Version 4", "UDP", "DHCP"};
GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(treeView));
//GtkTreeStore *store = GTK_TREE_STORE();
if (model) {
store = GTK_TREE_STORE(model);
if (gtk_tree_model_get_iter_first(model, &iter)) {
gtk_tree_store_clear(store);
}
} else {
store = gtk_tree_store_new(2, G_TYPE_STRING, G_TYPE_STRING);
gtk_tree_view_set_model(GTK_TREE_VIEW(treeView), GTK_TREE_MODEL(store));
}
gtk_tree_store_append(store, &iter, NULL);
gtk_tree_store_set(store, &iter, 0, itemTitle[0], 1, "", -1);
// 添加 Ethernet II 头相关内容
s = sdsempty();
MAC_TO_STR(p->hdr.eth.h_dest, s);
ADD_SUB_STRING("Destination", s);
sdsfree(s);
s = sdsempty();
MAC_TO_STR(p->hdr.eth.h_source, s);
ADD_SUB_STRING("Source", s);
sdsfree(s);
#if VLAN_SUPPORT
// 添加 VLan 头相关内容
gtk_tree_store_append(store, &iter, NULL);
gtk_tree_store_set(store, &iter, 0, itemTitle[1], 1, "", -1);
ADD_SUB_INT("ID", "%u", VLAN_VNI_ID(p->hdr.vlan.id));
ADD_SUB_INT("Type", "0x%04X", ntohs(p->hdr.vlan.type));
#endif
// 添加 IP 头
gtk_tree_store_append(store, &iter, NULL);
gtk_tree_store_set(store, &iter, 0, itemTitle[2], 1, "", -1);
ADD_SUB_INT("Version", "%u", p->hdr.ip.version);
s = sdsempty();
sprintf(s, "%u %s (%u)", p->hdr.ip.ihl * 4, "bytes", p->hdr.ip.ihl);
ADD_SUB_STRING("Header Length", s);
sdsfree(s);
ADD_SUB_INT("Differentiated Services Field", "0x%02X", p->hdr.ip.tos);
ADD_SUB_INT("Total Length", "%u", ntohs(p->hdr.ip.tot_len));
ADD_SUB_INT("Identification", "0x%04X", ntohs(p->hdr.ip.id));
ADD_SUB_INT("Flags", "0x%04X", ntohs(p->hdr.ip.frag_off));
ADD_SUB_INT("Time to live", "%u", p->hdr.ip.ttl);
ADD_SUB_STRING("Protocol", "UDP");
ADD_SUB_INT("Header Checksum", "0x%04X", ntohs(p->hdr.ip.check));
ADD_SUB_STRING("Source", inet_ntoa(*(struct in_addr *)&p->hdr.ip.saddr));
ADD_SUB_STRING("Destination", inet_ntoa(*(struct in_addr *)&p->hdr.ip.daddr));
// 添加 UDP 头
gtk_tree_store_append(store, &iter, NULL);
gtk_tree_store_set(store, &iter, 0, itemTitle[3], 1, "", -1);
ADD_SUB_INT("Source Port", "%u", ntohs(p->hdr.udp.source));
ADD_SUB_INT("Destination Port", "%u", ntohs(p->hdr.udp.dest));
ADD_SUB_INT("Length", "%u", ntohs(p->hdr.udp.len));
ADD_SUB_INT("Checksum", "0x%04X", ntohs(p->hdr.udp.check));
// 添加 DHCP 内容
gtk_tree_store_append(store, &iter, NULL);
gtk_tree_store_set(store, &iter, 0, itemTitle[4], 1, "", -1);
switch (p->dhcp.op) {
case 1:
ADD_SUB_STRING("Message Type", "Boot Request");
break;
case 2:
ADD_SUB_STRING("Message Type", "Boot Reply");
break;
default:
ADD_SUB_STRING("Message Type", "Unknown");
}
switch (p->dhcp.htype) {
case 1:
ADD_SUB_STRING("Hardware Type", "Ethernet");
break;
default:
ADD_SUB_STRING("Hardware Type", "Unknown");
}
ADD_SUB_INT("Hardware address length", "%u", p->dhcp.hlen);
ADD_SUB_INT("Hops", "%u", p->dhcp.hops);
ADD_SUB_INT("Transaction ID", "0x%08X", p->dhcp.xid);
ADD_SUB_INT("Seconds elapsed", "%u", p->dhcp.secs);
ADD_SUB_INT("Bootp flags", "0x%04X", p->dhcp.flags);
ADD_SUB_STRING("Client IP address", inet_ntoa(*(struct in_addr *)&p->dhcp.ciaddr));
ADD_SUB_STRING("Your(client) IP address", inet_ntoa(*(struct in_addr *)&p->dhcp.yiaddr));
ADD_SUB_STRING("Next server IP address", inet_ntoa(*(struct in_addr *)&p->dhcp.siaddr));
ADD_SUB_STRING("Relay agent IP address", inet_ntoa(*(struct in_addr *)&p->dhcp.giaddr));
s = sdsempty();
MAC_TO_STR(p->dhcp.chaddr, s);
ADD_SUB_STRING("Client MAC address", s);
sdsfree(s);
if (strlen((char *)p->dhcp.sname) > 0) {
ADD_SUB_STRING("Server host name", p->dhcp.sname);
} else {
ADD_SUB_STRING("Server host name", "not given");
}
if (strlen((char *)p->dhcp.file) > 0) {
ADD_SUB_STRING("Boot file name", p->dhcp.file);
} else {
ADD_SUB_STRING("Boot file name", "not given");
}
ADD_SUB_STRING("Magic cookie", "DHCP");
U8 *opPointer, *optEnd = (U8 *)p + nBytes;
opPointer = p->dhcp.options;
while (*opPointer && opPointer < optEnd) {
if (*opPointer == OPT_END) {
ADD_SUB_STRING("Option(255)", "End");
opPointer++;
} else {
STR_OPT opTmp;
sds st = sdsempty();
opTmp.op_code = *opPointer;
opPointer++;
opTmp.op_size = *opPointer;
opPointer++;
memcpy(opTmp.op_value, opPointer, opTmp.op_size);
opPointer += opTmp.op_size;
s = sdsempty();
//sprintf(s, "(%u) %s", opTmp.op_code, dhcp_get_opName(opTmp.op_code));
sprintf(st, "Option(%u)", opTmp.op_code);
ADD_SUB_STRING(st, dhcp_get_opName(opTmp.op_code));
sdsfree(s);
sdsfree(st);
ADD_SUB_OPTION(opTmp.op_code, opTmp.op_size, opTmp.op_value);
}
}
}
static gboolean upgrade_statusbar_proc(gpointer user_data) {
PDHCP_INFO pInfo = (PDHCP_INFO)user_data;
int ret;
DHCP_OPT opt;
char buf[1024] = {0};
S32 tmOffer = 0, tmAck = 0;
const char *pIp = NULL, *pNetmask = NULL, *pGw = NULL, *pDns1 = NULL, *pDns2 = NULL;
if (pInfo) {
tmOffer = MAX(0,
(pInfo->pOfferBuf.tm.tv_sec * 1000000 + pInfo->pOfferBuf.tm.tv_usec) -
(pInfo->pDiscBuf.tm.tv_sec * 1000000 + pInfo->pDiscBuf.tm.tv_usec));
tmAck = MAX(0,
(pInfo->pAckBuf.tm.tv_sec * 1000000 + pInfo->pAckBuf.tm.tv_usec) -
(pInfo->pReqBuf.tm.tv_sec * 1000000 + pInfo->pReqBuf.tm.tv_usec));
if (pInfo->pAckBuf.p) {
PDHCP_PACKAGE pkg = (PDHCP_PACKAGE)pInfo->pAckBuf.p;
U32 optSize = pInfo->pAckBuf.buf_size - sizeof(DHCP_PACKAGE);
pIp = u32_to_str_ip_safe(pkg->dhcp.yiaddr);
ret = dhcp_get_option(OPT_NETMASK, pkg->dhcp.options, optSize, &opt);
if (ret == ERR_SUCCESS && opt.len == sizeof(U32)) {
pNetmask = u32_to_str_ip_safe(*((U32 *)opt.pValue));
}
ret = dhcp_get_option(OPT_ROUTER, pkg->dhcp.options, optSize, &opt);
if (ret == ERR_SUCCESS && opt.len == sizeof(U32)) {
pGw = u32_to_str_ip_safe(*((U32 *)opt.pValue));
}
ret = dhcp_get_option(OPT_DNS, pkg->dhcp.options, optSize, &opt);
if (ret == ERR_SUCCESS && opt.len >= sizeof(U32)) {
U32 *pVal = (U32 *)opt.pValue;
pDns1 = u32_to_str_ip_safe(*pVal);
if (opt.len > sizeof(U32)) {
pVal++;
pDns2 = u32_to_str_ip_safe(*pVal);
}
}
}
}
sprintf(buf, "Offer %d.%03ds | ACK %d.%03ds | ip: %s | netmask: %s | gateway: %s | dns1: %s | dns2: %s |",
tmOffer / 1000000, (tmOffer % 1000000) / 1000, tmAck / 1000000, (tmAck % 1000000) / 1000,
SAFETY_STR_STRING(pIp, ""), SAFETY_STR_STRING(pNetmask, ""), SAFETY_STR_STRING(pGw, ""),
SAFETY_STR_STRING(pDns1, ""), SAFETY_STR_STRING(pDns2, ""));
gtk_statusbar_pop(GTK_STATUSBAR(g_statusBar), 0);
gtk_statusbar_push(GTK_STATUSBAR(g_statusBar), 0, buf);
if (pIp) {
free((void *)pIp);
}
if (pDns1) {
free((void *)pDns1);
}
if (pDns2) {
free((void *)pDns2);
}
if (pGw) {
free((void *)pGw);
}
if (pNetmask) {
free((void *)pNetmask);
}
return FALSE;
}
void details_wnd_show(PDHCP_INFO pInfo) {
int i;
PBUF_INFO hexBuf[4];
GtkTextIter iter, iter1;
if (pInfo) {
if (pInfo != g_preInfo) {
g_preInfo = pInfo;
for (i = 0; i < 4; i++) {
gtk_text_buffer_get_start_iter(g_pTxtBuf[i], &iter);
gtk_text_buffer_get_end_iter(g_pTxtBuf[i], &iter1);
gtk_text_buffer_delete(g_pTxtBuf[i], &iter, &iter1);
}
}
hexBuf[0] = &pInfo->pDiscBuf;
hexBuf[1] = &pInfo->pOfferBuf;
hexBuf[2] = &pInfo->pReqBuf;
hexBuf[3] = &pInfo->pAckBuf;
// 填充HEX 窗口数据
for (i = 0; i < 4; i++) {
char buf[128] = {0};
U32 offset = 0;
if (hexBuf[i]->buf_size == 0) {
continue;
}
gtk_text_buffer_get_start_iter(g_pTxtBuf[i], &iter);
gtk_text_buffer_get_end_iter(g_pTxtBuf[i], &iter1);
if (strlen(gtk_text_buffer_get_text(g_pTxtBuf[i], &iter, &iter1, TRUE)) > 0) {
continue;
}
gtk_text_buffer_get_iter_at_offset(g_pTxtBuf[i], &iter, 0);
sprintf(buf, " Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F ASCII Tables\n");
gtk_text_buffer_insert_with_tags_by_name(g_pTxtBuf[i], &iter, buf, -1, "hex_head", NULL);
int row = hexBuf[i]->buf_size / 16 + ((hexBuf[i]->buf_size % 16) > 0 ? 1 : 0);
for (int k = 0; k < row; k++) {
char bufOffset[24] = {0};
memset(buf, 0, 128);
sprintf(bufOffset, " %08X ", offset);
gtk_text_buffer_insert_with_tags_by_name(g_pTxtBuf[i], &iter, bufOffset, -1, "hex_offset", NULL);
for (int m = 0; m < 16; m++) {
char bufStr[4] = {0};
sprintf(bufStr, "%02X ", hexBuf[i]->p[k * 16 + m]);
strcat(buf, bufStr);
if (m == 7 || m == 15) {
strcat(buf, " ");
}
}
for (int m = 0; m < 16; m++) {
if (isprint(hexBuf[i]->p[k * 16 + m])) {
char bufStr[2] = {0};
bufStr[0] = (char)hexBuf[i]->p[k * 16 + m];
strcat(buf, bufStr);
} else {
strcat(buf, ".");
}
}
strcat(buf, "\n");
gtk_text_buffer_insert_with_tags_by_name(g_pTxtBuf[i], &iter, buf, -1, "bold", NULL);
offset += 16;
}
// 填充 TreeView
add_dhcp_tree_colums(g_ptvDHcp[i]);
create_dhcp_tree_mode((PDHCP_PACKAGE)hexBuf[i]->p, hexBuf[i]->buf_size, g_ptvDHcp[i]);
}
upgrade_statusbar_proc(pInfo);
}
upgrade_statusbar_proc(NULL);
gtk_widget_show_all(g_detailWnd);
}
static gboolean button_release_event(GtkWidget *self, GdkEventButton UNUSED(event), gpointer UNUSED(user_data)) {
GtkTextIter iter, start_sel, end_sel;
GtkTextBuffer *buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(self));
gtk_text_buffer_get_iter_at_mark(buffer, &iter, gtk_text_buffer_get_insert(buffer));
int row = gtk_text_iter_get_line(&iter);
int col = gtk_text_iter_get_line_offset(&iter);
if (col <= 57 && col >= 11) {
if ((col <= 35 && ((col - 11) % 3) == 0) || (col > 35 && (col - 12) % 3 == 0)) {
GtkTextMark *mark = gtk_text_buffer_get_insert(buffer);
gtk_text_buffer_get_iter_at_mark(buffer, &start_sel, mark);
gtk_text_buffer_get_iter_at_line_offset(buffer, &end_sel, row, 59);
//char *text = (char *)gtk_text_buffer_get_text(buffer, &iter, &end_sel, FALSE);
//printf("Select %s(%d, %d)\n", text, row, col);
}
}
return FALSE;
}
void switch_page(GtkNotebook *UNUSED(self),
GtkWidget *UNUSED(page),
guint UNUSED(page_num),
gpointer UNUSED(user_data)) {
if (g_preInfo) {
details_wnd_show(g_preInfo);
upgrade_statusbar_proc(g_preInfo);
}
}
void details_wnd_create(GtkBuilder *builder) {
// 创建主窗口
GtkWidget *window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
//设置窗口大小
gtk_widget_set_size_request(window, 900, 600);
GtkWidget *vBox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 2);
// 笔记本放进窗口
gtk_container_add(GTK_CONTAINER(window), vBox);
// 创建笔记本控件
GtkWidget *notebook = gtk_notebook_new();
// 笔记本放进 VBox
//gtk_container_add(GTK_CONTAINER(vBox), notebook);
gtk_box_pack_start(GTK_BOX(vBox), notebook, TRUE, TRUE, 0);
// 页标签的位置,可以有四种位置:上、下、左或右。
gtk_notebook_set_tab_pos(GTK_NOTEBOOK(notebook), GTK_POS_TOP);
g_signal_connect(notebook, "switch-page", G_CALLBACK(switch_page), NULL);
for (int i = 0; i < 4; i++) {
GtkTreeIter iter;
const char *pTabName[] = {"Discover", "Offer", "Request", "Ack"};
// 第一个页面
GtkWidget *label = gtk_label_new(pTabName[i]);
// 水平分割面板
GtkWidget *boxTab = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 3);
// 左侧 Hex 窗口
GtkWidget *scHex = gtk_scrolled_window_new(NULL, NULL);
GtkWidget *scText = gtk_text_view_new();
gtk_container_add(GTK_CONTAINER(scHex), scText);
gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scHex), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
// 分隔条
GtkWidget *vSepar = gtk_separator_new(GTK_ORIENTATION_VERTICAL);
// 右侧 详细信息窗口
GtkWidget *scMsg = gtk_scrolled_window_new(NULL, NULL);
// 上下分割面板
GtkWidget *vpaned = gtk_paned_new(GTK_ORIENTATION_VERTICAL);
// 上半部分控件
GtkWidget *tvDhcp = gtk_tree_view_new();
gtk_tree_view_set_grid_lines(GTK_TREE_VIEW(tvDhcp), GTK_TREE_VIEW_GRID_LINES_BOTH);
gtk_container_add(GTK_CONTAINER(scMsg), tvDhcp);
gtk_paned_pack1(GTK_PANED(vpaned), scMsg, TRUE, FALSE);
gtk_widget_set_size_request(tvDhcp, -1, 300);
gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scMsg), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
// 下半部分控件
GtkWidget *tvHex = gtk_tree_view_new();
GtkCellRenderer *renderer = gtk_cell_renderer_text_new();
GtkTreeViewColumn *column = gtk_tree_view_column_new_with_attributes("类型", renderer, "text", 0, NULL);
gtk_tree_view_append_column(GTK_TREE_VIEW(tvHex), column);
g_object_set(column, "min-width", 120, NULL);
renderer = gtk_cell_renderer_text_new();
column = gtk_tree_view_column_new_with_attributes("", renderer, "text", 1, NULL);
gtk_tree_view_append_column(GTK_TREE_VIEW(tvHex), column);
GtkListStore *store = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_STRING);
const char *itemTitle[] = {"Binary", "unsigne char", "unsigne short", "unsigne int", "unsigne char long long",
"char", "short", "int", "long long"};
for (int k = 0; k < ARRAY_SIZE(itemTitle); k++) {
gtk_list_store_append(store, &iter);
gtk_list_store_set(store, &iter, 0, itemTitle[k], 1, "", -1);
}
gtk_tree_view_set_model(GTK_TREE_VIEW(tvHex), GTK_TREE_MODEL(store));
gtk_tree_view_set_grid_lines(GTK_TREE_VIEW(tvHex), GTK_TREE_VIEW_GRID_LINES_BOTH);
gtk_paned_pack2(GTK_PANED(vpaned), tvHex, FALSE, FALSE);
// 控件布局
gtk_box_pack_start(GTK_BOX(boxTab), scHex, TRUE, TRUE, 1);
gtk_box_pack_start(GTK_BOX(boxTab), vSepar, FALSE, FALSE, 1);
gtk_box_pack_start(GTK_BOX(boxTab), vpaned, TRUE, TRUE, 1);
gtk_widget_set_size_request(scHex, 580, -1);
gtk_widget_set_size_request(tvDhcp, 300, -1);
gtk_notebook_append_page(GTK_NOTEBOOK(notebook), boxTab, label);
g_pTxtBuf[i] = gtk_text_view_get_buffer(GTK_TEXT_VIEW(scText));
gtk_text_view_set_editable(GTK_TEXT_VIEW(scText), FALSE);
gtk_text_view_set_monospace(GTK_TEXT_VIEW(scText), TRUE);
gtk_text_buffer_create_tag(g_pTxtBuf[i], "blue_foreground", "foreground", "blue", NULL);
gtk_text_buffer_create_tag(g_pTxtBuf[i], "hex_head", "foreground", "red", "pixels_below_lines", 5, NULL);
gtk_text_buffer_create_tag(g_pTxtBuf[i], "hex_offset", "foreground", "red", NULL);
gtk_text_buffer_create_tag(g_pTxtBuf[i], "bold", "weight", PANGO_WEIGHT_BOLD, NULL);
g_signal_connect(G_OBJECT(scText), "button_release_event", G_CALLBACK(button_release_event), builder);
g_ptvDHcp[i] = tvDhcp;
}
g_statusBar = gtk_statusbar_new();
gtk_box_pack_start(GTK_BOX(vBox), g_statusBar, FALSE, FALSE, 0);
//gtk_widget_set_size_request(vBox, -1, 16);
g_signal_connect(G_OBJECT(window), "delete_event", G_CALLBACK(delete_event), builder);
g_detailWnd = window;
}