#include "compiler.h"
#include <stdarg.h>
#include "resource.h"
#include "strres.h"
#include "textfile.h"
#include "oemtext.h"
#include "dosio.h"
#include "ini.h"
#include "menu.h"
#ifdef TRACE
#ifdef STRICT
#define SUBCLASSPROC WNDPROC
#else
#define SUBCLASSPROC FARPROC
#endif
#define IDC_VIEW (WM_USER + 100)
#define VIEW_BUFFERSIZE 4096
#define VIEW_FGCOLOR 0x000000
#define VIEW_BGCOLOR 0xffffff
#define VIEW_TEXT "‚l‚r ƒSƒVƒbƒN"
#define VIEW_SIZE 12
typedef struct
{
UINT8 en;
TEXTFILEH tf;
HWND hwnd;
} TRACEWIN;
typedef struct {
int posx;
int posy;
int width;
int height;
} TRACECFG;
extern HINSTANCE g_hInstance;
static const TCHAR ProgTitle[] = _T("console");
static const TCHAR ClassName[] = _T("TRACE-console");
static const TCHAR ClassEdit[] = _T("EDIT");
static const TCHAR viewfont[] = _T(VIEW_TEXT);
static const OEMCHAR crlf[] = OEMTEXT("\r\n");
static TRACEWIN tracewin;
static HWND s_hView = NULL;
static HFONT s_hfView = NULL;
static HBRUSH s_hBrush = NULL;
static int viewpos;
static int viewleng;
static TCHAR viewbuf[VIEW_BUFFERSIZE * 2];
static TRACECFG tracecfg;
static int devpos;
static char devstr[256];
static const OEMCHAR np2trace[] = OEMTEXT("np2trace.ini");
static const OEMCHAR inititle[] = OEMTEXT("TRACE");
static const PFTBL initbl[4] = {
PFVAL("posx", PFTYPE_SINT32, &tracecfg.posx),
PFVAL("posy", PFTYPE_SINT32, &tracecfg.posy),
PFVAL("width", PFTYPE_SINT32, &tracecfg.width),
PFVAL("height", PFTYPE_SINT32, &tracecfg.height)};
static void View_ScrollToBottom(HWND hWnd) {
int MinPos;
int MaxPos;
GetScrollRange(hWnd, SB_VERT, &MinPos, &MaxPos);
PostMessage(hWnd, EM_LINESCROLL, 0, MaxPos);
}
static void View_ClrString(void) {
viewpos = 0;
viewleng = 0;
viewbuf[0] = '\0';
SetWindowText(s_hView, viewbuf);
}
static void View_AddString(const OEMCHAR *string) {
int slen;
int vpos;
int vlen;
TCHAR c;
#if defined(OEMCHAR_SAME_TCHAR)
slen = lstrlen(string);
#else
slen = oemtotchar(NULL, 0, string, (UINT)-1) - 1;
#endif
if ((slen == 0) || ((slen + 3) > VIEW_BUFFERSIZE)) {
return;
}
vpos = viewpos;
vlen = viewleng;
if ((vpos + vlen + slen + 3) > (VIEW_BUFFERSIZE * 2)) {
while(vlen > 0) {
vlen--;
c = viewbuf[vpos++];
if ((c == 0x0a) && ((vlen + slen + 3) <= VIEW_BUFFERSIZE)) {
break;
}
}
if (vpos >= VIEW_BUFFERSIZE) {
if (vlen) {
CopyMemory(viewbuf, viewbuf + vpos, vlen * sizeof(TCHAR));
}
vpos = 0;
viewpos = 0;
}
}
#if defined(OEMCHAR_SAME_TCHAR)
CopyMemory(viewbuf + vpos + vlen, string, slen * sizeof(TCHAR));
#else
oemtotchar(viewbuf + vpos + vlen, slen + 1, string, (UINT)-1);
#endif
vlen += slen;
viewbuf[vpos + vlen + 0] = '\r';
viewbuf[vpos + vlen + 1] = '\n';
viewbuf[vpos + vlen + 2] = '\0';
viewleng = vlen + 2;
SetWindowText(s_hView, viewbuf + vpos);
View_ScrollToBottom(s_hView);
}
// ----
static LRESULT onCreate(HWND hWnd)
{
HMENU hMenu;
RECT rc;
hMenu = GetSystemMenu(hWnd, FALSE);
menu_addmenures(hMenu, 0, IDR_TRACE, FALSE);
CheckMenuItem(hMenu, IDM_TRACE_TRACE,
(tracewin.en & 1)?MF_CHECKED:MF_UNCHECKED);
CheckMenuItem(hMenu, IDM_TRACE_VERBOSE,
(tracewin.en & 2)?MF_CHECKED:MF_UNCHECKED);
CheckMenuItem(hMenu, IDM_TRACE_ENABLE,
(tracewin.en & 4)?MF_CHECKED:MF_UNCHECKED);
GetClientRect(hWnd, &rc);
s_hView = CreateWindowEx(WS_EX_CLIENTEDGE,
ClassEdit, NULL,
WS_CHILD | WS_VISIBLE | ES_READONLY | ES_LEFT |
ES_MULTILINE | WS_VSCROLL | ES_AUTOVSCROLL,
0, 0, rc.right, rc.bottom,
hWnd, (HMENU)IDC_VIEW, g_hInstance, NULL);
SendMessage(s_hView, EM_SETLIMITTEXT, (WPARAM)VIEW_BUFFERSIZE, 0);
s_hfView = CreateFont(VIEW_SIZE, 0, 0, 0, 0, 0, 0, 0,
SHIFTJIS_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
DEFAULT_QUALITY, FIXED_PITCH, viewfont);
if (s_hfView)
{
SendMessage(s_hView, WM_SETFONT, (WPARAM)s_hfView,
MAKELPARAM(TRUE, 0));
}
s_hBrush = CreateSolidBrush(VIEW_BGCOLOR);
SetFocus(s_hView);
return TRUE;
}
static LRESULT onSysCommand(HWND hWnd, WPARAM wParam, LPARAM lParam)
{
HMENU hMenu;
hMenu = GetSystemMenu(hWnd, FALSE);
switch(wParam)
{
case IDM_TRACE_TRACE:
tracewin.en ^= 1;
CheckMenuItem(hMenu, IDM_TRACE_TRACE,
(tracewin.en & 1)?MF_CHECKED:MF_UNCHECKED);
break;
case IDM_TRACE_VERBOSE:
tracewin.en ^= 2;
CheckMenuItem(hMenu, IDM_TRACE_VERBOSE,
(tracewin.en & 2)?MF_CHECKED:MF_UNCHECKED);
break;
case IDM_TRACE_ENABLE:
tracewin.en ^= 4;
CheckMenuItem(hMenu, IDM_TRACE_ENABLE,
(tracewin.en & 4)?MF_CHECKED:MF_UNCHECKED);
break;
case IDM_TRACE_FILEOUT:
if (tracewin.tf != NULL)
{
textfile_close(tracewin.tf);
tracewin.tf = NULL;
}
else
{
tracewin.tf = textfile_create(OEMTEXT("traceout.txt"),
0x800);
}
CheckMenuItem(hMenu, IDM_TRACE_FILEOUT,
(tracewin.tf)?MF_CHECKED:MF_UNCHECKED);
break;
case IDM_TRACE_CLEAR:
View_ClrString();
break;
default:
return DefWindowProc(hWnd, WM_SYSCOMMAND, wParam, lParam);
}
return FALSE;
}
static LRESULT CALLBACK traceproc(HWND hWnd, UINT uMsg,
WPARAM wParam, LPARAM lParam)
{
RECT rc;
switch(uMsg)
{
case WM_CREATE:
return onCreate(hWnd);
case WM_SYSCOMMAND:
return onSysCommand(hWnd, wParam, lParam);
case WM_MOVE:
if (!(GetWindowLong(hWnd, GWL_STYLE) &
(WS_MAXIMIZE | WS_MINIMIZE)))
{
GetWindowRect(hWnd, &rc);
tracecfg.posx = rc.left;
tracecfg.posy = rc.top;
}
break;
case WM_SIZE: // window resize
if (!(GetWindowLong(hWnd, GWL_STYLE) &
(WS_MAXIMIZE | WS_MINIMIZE)))
{
GetWindowRect(hWnd, &rc);
tracecfg.width = rc.right - rc.left;
tracecfg.height = rc.bottom - rc.top;
}
MoveWindow(s_hView, 0, 0, LOWORD(lParam), HIWORD(lParam), TRUE);
View_ScrollToBottom(s_hView);
break;
case WM_SETFOCUS:
SetFocus(s_hView);
return(0L);
case WM_CTLCOLORSTATIC:
case WM_CTLCOLOREDIT:
SetTextColor((HDC)wParam, VIEW_FGCOLOR);
SetBkColor((HDC)wParam, VIEW_BGCOLOR);
return((LRESULT)s_hBrush);
case WM_CLOSE:
break;
case WM_DESTROY:
if (s_hBrush)
{
DeleteObject(s_hBrush);
}
if (s_hfView)
{
DeleteObject(s_hfView);
}
break;
#if 0
case WM_ENTERSIZEMOVE:
winloc_movingstart();
break;
case WM_MOVING:
winloc_movingproc((RECT *)lParam);
break;
case WM_ERASEBKGND:
return FALSE;
#endif
default:
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
return FALSE;
}
// ----
void trace_init(void) {
HWND hwnd;
ZeroMemory(&tracewin, sizeof(tracewin));
WNDCLASS wc;
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = traceproc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = g_hInstance;
wc.hIcon = NULL;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wc.lpszMenuName = NULL;
wc.lpszClassName = ClassName;
if (!RegisterClass(&wc)) {
return;
}
#if 1
tracewin.en = 4;
#else
tracewin.en = 1;
tracewin.tf = textfile_create(OEMTEXT("traceout.txt"), 0x800);
#endif
tracecfg.posx = CW_USEDEFAULT;
tracecfg.posy = CW_USEDEFAULT;
tracecfg.width = CW_USEDEFAULT;
tracecfg.height = CW_USEDEFAULT;
ini_read(file_getcd(np2trace), inititle, initbl, NELEMENTS(initbl));
hwnd = CreateWindowEx(WS_EX_CONTROLPARENT,
ClassName, ProgTitle,
WS_OVERLAPPEDWINDOW,
tracecfg.posx, tracecfg.posy,
tracecfg.width, tracecfg.height,
NULL, NULL, g_hInstance, NULL);
tracewin.hwnd = hwnd;
if (hwnd == NULL) {
return;
}
ShowWindow(hwnd, SW_SHOW);
UpdateWindow(hwnd);
}
void trace_term(void) {
if (tracewin.tf != NULL) {
textfile_close(tracewin.tf);
tracewin.tf = NULL;
}
if (tracewin.hwnd) {
DestroyWindow(tracewin.hwnd);
tracewin.hwnd = NULL;
ini_write(file_getcd(np2trace), inititle, initbl, NELEMENTS(initbl));
}
}
void trace_fmt(const char *fmt, ...) {
BOOL en;
va_list ap;
OEMCHAR buf[0x1000];
en = (tracewin.en & 1) &&
((tracewin.en & 4) || (tracewin.tf != NULL));
if (en) {
va_start(ap, fmt);
#if defined(OSLANG_UCS2)
OEMCHAR cnvfmt[0x800];
MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, fmt, -1,
cnvfmt, NELEMENTS(cnvfmt));
vswprintf(buf, cnvfmt, ap);
#else
vsprintf(buf, fmt, ap);
#endif
va_end(ap);
if ((tracewin.en & 4) && (s_hView)) {
View_AddString(buf);
}
if (tracewin.tf != NULL) {
textfile_write(tracewin.tf, buf);
textfile_write(tracewin.tf, crlf);
}
}
}
void trace_fmt2(const char *fmt, ...) {
BOOL en;
va_list ap;
OEMCHAR buf[0x1000];
en = (tracewin.en & 2) &&
((tracewin.en & 4) || (tracewin.tf != NULL));
if (en) {
va_start(ap, fmt);
#if defined(OSLANG_UCS2)
OEMCHAR cnvfmt[0x800];
MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, fmt, -1,
cnvfmt, NELEMENTS(cnvfmt));
vswprintf(buf, cnvfmt, ap);
#else
vsprintf(buf, fmt, ap);
#endif
va_end(ap);
if ((tracewin.en & 4) && (s_hView)) {
View_AddString(buf);
}
if (tracewin.tf != FILEH_INVALID) {
textfile_write(tracewin.tf, buf);
textfile_write(tracewin.tf, crlf);
}
}
}
void trace_char(char c) {
if ((c == 0x0a) || (c == 0x0d)) {
if (devpos) {
devstr[devpos] = '\0';
#if defined(OSLANG_UCS2)
TCHAR pdevstr[0x800];
MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, devstr, -1,
pdevstr, NELEMENTS(pdevstr));
#else
const OEMCHAR *pdevstr = devstr;
#endif
if ((tracewin.en & 4) && (s_hView))
{
View_AddString(pdevstr);
}
if (tracewin.tf != NULL) {
textfile_write(tracewin.tf, pdevstr);
textfile_write(tracewin.tf, crlf);
}
devpos = 0;
}
}
else {
if (devpos < (sizeof(devstr) - 1)) {
devstr[devpos++] = c;
}
}
}
#endif
RetroPC.NET-CVS <cvs@retropc.net>