📄 watchwnd.c
字号:
/*
Copyright 2001-2003 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA.
You may contact the author at:
mailto::camille@bluegrass.net
or by snail mail at:
David Lindauer
850 Washburn Ave Apt 99
Louisville, KY 40222
**********************************************************************
WATCHWND.C holds the functionality for the watch window. This includes
the window itself, a right click menu, and an interface for the editor
to add things to the watch window via its own right-click window.
**********************************************************************
*/
#include <windows.h>
#include <commctrl.h>
#include <stdio.h>
#include <ctype.h>
#include <richedit.h>
#include "header.h"
#include <dir.h>
#include "cvinfo.h"
extern HWND hwndSourceTab;
extern HWND hwndFrame, hwndProject, hwndRegister, hwndClient, hwndError,
hwndTab;
extern HINSTANCE hInstance;
extern THREAD *StoppedThread;
extern PROCESS DebugProcess;
extern unsigned bitmask[];
HWND hwndWatch;
static HWND hwndTree, hwndCtrl;
static char szWatchClassName[] = "xccWatchClass";
static char szWatchTitle[] = "Watch Window";
static HBITMAP valueBitmap, itemBitmap;
static LOGFONT fontdata =
{
14, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, FF_DONTCARE,
"Helvetica"
};
static WATCHINFO *watchinfo_list;
static int watchinfo_max;
static int watchinfo_count;
void AddTypeInfoToName(char *typetab, VARINFO *v)
{
char buf[256], *p;
strcpy(v->screenname, v->membername);
p = v->screenname + strlen(v->screenname);
sprintf(p, "(%s)", SymTypeName(buf, typetab, v));
}
//-------------------------------------------------------------------------
WATCHINFO *MatchItem(VARINFO *var)
{
int i;
for (i = 0; i < watchinfo_count; i++)
if (!strcmp(watchinfo_list[i].info->membername, var->membername))
if (watchinfo_list[i].info->typetab == var->typetab)
return &watchinfo_list[i];
return 0;
}
//-------------------------------------------------------------------------
void FreeTree(VARINFO *info)
{
while (info)
{
FreeTree(info->subtype);
if (info->hTreeItem)
TreeView_DeleteItem(hwndTree, info->hTreeItem);
info = info->link;
}
}
//-------------------------------------------------------------------------
void RefreshAddresses(VARINFO *var, int address, int noscope)
{
while (var)
{
int unscope = noscope;
int val;
if (noscope)
var->outofscope = TRUE;
else
{
var->outofscope = FALSE;
val = var->address = address + var->offset;
if (var->pointer)
unscope = !ReadValue(var->address, &val, 4, var->inreg ? &var
->thread->regs: 0) || !val;
}
RefreshAddresses(var->subtype, val, unscope);
var = var->link;
}
}
//-------------------------------------------------------------------------
void WatchValue(char *typetab, char *buf, VARINFO *info, int onevalue)
{
int i;
if (info->outofscope || info->outofscopereg)
sprintf(buf, "out of scope");
else if (info->structure)
{
sprintf(buf, "STRUCTURE: %p", info->address);
}
else if (info->unionx)
{
sprintf(buf, "UNION: %p", info->address);
}
else if (info->pointer)
{
int val;
if (ReadValue(info->address, &val, 4, info->inreg ? &info->thread->regs
: 0))
{
info->editable = TRUE;
if (onevalue)
sprintf(buf, "0x%p ", val);
else
sprintf(buf, "POINTER: %p ", val);
GetStringValue(info, buf + strlen(buf), 32, val);
}
else
sprintf(buf, "POINTER: <UNKNOWN>");
}
else if (info->enumx)
{
info->editable = TRUE;
HintEnum(typetab, info, buf, FALSE, onevalue);
}
else if (info->bitfield)
{
int signedtype;
int v = HintBf(info, &signedtype);
if (onevalue)
if (signedtype)
sprintf(buf, "0x%x", v);
else
sprintf(buf, "0x%x", v);
else
if (signedtype)
sprintf(buf, "%d(0x%x)", v, v);
else
sprintf(buf, "%u(0x%x)", v, v);
info->editable = TRUE;
}
else if (info->array)
{
sprintf(buf, "ARRAY: %p ", info->address);
GetStringValue(info, buf + strlen(buf), 32, info->address);
}
else
{
int signedtype;
char buf1[20];
LLONG_TYPE v;
info->editable = TRUE;
switch (HintBasicType(info, &signedtype, buf1))
{
case T_INT8:
#ifndef BORLANDC
v = *(LLONG_TYPE*)buf1;
if (onevalue)
if (signedtype)
sprintf(buf, "0x%llx", v);
else
sprintf(buf, "0x%llx", v);
else
if (signedtype)
sprintf(buf, "%lld(0x%llx)", v, v);
else
sprintf(buf, "%lld(0x%llx)", v, v);
break;
#endif
default:
sprintf(buf, "unknown type");
break;
case T_INT4:
v = *(int*)buf1;
if (onevalue)
if (signedtype)
sprintf(buf, "0x%x", (int)v);
else
sprintf(buf, "0x%x", (int)v);
else
if (signedtype)
sprintf(buf, "%d(0x%x)", (int)v, (int)v);
else
sprintf(buf, "%u(0x%x)", (int)v, (int)v);
break;
case T_BOOL08:
if (buf1[0])
sprintf(buf, "True");
else
sprintf(buf, "False");
break;
case T_REAL32:
case T_IMAGINARY32:
sprintf(buf, "%f", (double)*(float*)buf1);
break;
case T_REAL80:
case T_IMAGINARY80:
*(double*)buf1 = *(long double*)buf1;
case T_REAL64:
case T_IMAGINARY64:
sprintf(buf, "%f", *(double*)buf1);
break;
case T_CPLX32:
sprintf(buf, "%f + %f * I", (double)*(float*)buf1, (double)*(float *)(buf1 + 4));
break;
case T_CPLX64:
sprintf(buf, "%f + %f * I", *(double *)buf1, *(double *)(buf1 + 8));
break;
case T_CPLX80:
sprintf(buf, "%f + %f * I", (double)*(long double *)buf1, (double)*(long double *)(buf1 + 10));
break;
}
}
}
//-------------------------------------------------------------------------
void RefreshData(char *typetab, VARINFO *var)
{
while (var)
{
WatchValue(typetab, var->value, var, FALSE);
RefreshData(typetab, var->subtype);
var = var->link;
}
}
//-------------------------------------------------------------------------
void RefreshItem(WATCHINFO *var, int address)
{
RefreshAddresses(var->info, address, var->info->outofscope);
RefreshData(var->typetab, var->info);
}
//-------------------------------------------------------------------------
HTREEITEM InsertItem(HTREEITEM hParent, HTREEITEM after, VARINFO *var)
{
HTREEITEM rv;
TV_INSERTSTRUCT t;
memset(&t, 0, sizeof(t));
t.hParent = hParent;
t.hInsertAfter = after;
#if !defined( _WIN32_IE) && !defined(__CCDL__)
t.item.mask = 0;
t.item.lParam = (int)var;
#else
t.u.item.mask = 0;
t.u.item.lParam = (int)var;
#endif
rv = TreeView_InsertItem(hwndTree, &t);
return rv;
}
//-------------------------------------------------------------------------
void InsertSubTree(HTREEITEM parent, HTREEITEM after, VARINFO *var, int index)
{
while (var)
{
AddTypeInfoToName(watchinfo_list[index].typetab, var);
var->hTreeItem = InsertItem(parent, after, var);
var->watchindex = index;
var->watchhead.col1Text = &var->screenname;
var->watchhead.col2Text = &var->value;
if (var->pointer && !var->subtype)
{
var->hTreeHolder = InsertItem(var->hTreeItem, TVI_LAST, var);
TreeView_Expand(hwndTree, var->hTreeItem, TVE_COLLAPSE);
}
else
InsertSubTree(var->hTreeItem, 0, var->subtype, index);
after = var->hTreeItem;
var = var->link;
}
}
//-------------------------------------------------------------------------
void AddItem(char *typetab, DEBUG_INFO *dbg, char *symtab, VARINFO *var, int
ebp, int cursoreip)
{
WATCHINFO *x = MatchItem(var);
if (x)
{
FreeVarInfo(var);
}
else
{
HTREEITEM previous = 0;
if (watchinfo_count >= watchinfo_max)
{
if (watchinfo_max >= 128)
{
ExtendedMessageBox("Watch Window Full", MB_SETFOREGROUND |
MB_SYSTEMMODAL,
"There are too many items in the watch window\nNot adding the current selection");
return ;
}
watchinfo_max += 64;
watchinfo_list = realloc(watchinfo_list, watchinfo_max *sizeof
(WATCHINFO));
}
if (watchinfo_count)
previous = watchinfo_list[watchinfo_count - 1].info->hTreeItem;
memset(&watchinfo_list[watchinfo_count], 0, sizeof(watchinfo_list[0]));
watchinfo_list[watchinfo_count].info = var;
watchinfo_list[watchinfo_count].dbg_info = dbg;
watchinfo_list[watchinfo_count].symtab = symtab;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -