/************************************************************************
* Dasm.cpp *
* *
* Borg Disassembler *
* v2.24 *
* by Cronos *
* *
* Contributors: *
* Thanks to Mark Ogden for many bugfixes and mods for assembly under *
* VC++, in its early stages (v2 beta builds). Also changes from *
* wvsprintf to wsprintf to allow compilation under VC++. *
* Thanks to Eugen Polukhin for some interesting alternate code and *
* ideas around v2.11 and feedback on fonts, etc. *
* Thanks to Pawe3 Kunio for a lot of coding ideas and advice re C++ *
* usage around v2.22 *
* Thanks to Howard Chu for some coding additions on default names, and *
* more block functions *
************************************************************************/
/************************************************************************
* dasm.cpp *
* - this whole file is a declaration and global routine dumping area *
* - it includes winmain and the main message callback routine, along *
* with initialisation code and the registry read/write code, odd *
* dialog boxes and helper functions for the main routines. The whole *
* file is a bit of a mish-mash of stuff which hasnt found its way *
* elsewhere. *
* - a lot of the code in here has grown, and i mean grown from the *
* ground up, and at some point it will require reorganisation, or *
* maybe that point was long ago.... *
************************************************************************/
#include <windows.h>
#include <commctrl.h>
#include <stdio.h>
//#include "menuids.rh"
#include "resource.h"
#include "exeload.h"
#include "data.h"
#include "schedule.h"
#include "proctab.h"
#include "disasm.h"
#include "dasm.h"
#include "gname.h"
#include "xref.h"
#include "relocs.h"
#include "srch.h"
#include "disio.h"
#include "range.h"
#include "decrypt.h"
#include "registry.h"
#include "help.h"
#include "database.h"
#include "user_fn.h"
#include "debug.h" // for ShowLastError()
//#define _CRTDBG_MAP_ALLOC
//#include <crtdbg.h>
/************************************************************************
* decaration dumping ground........ *
************************************************************************/
//CRITICAL_SECTION cs;
//volatile bool KillThread;
//volatile bool InThread;
globaloptions options;
LOGFONT UserFont;
fileloader floader;
dataseg *dta; // Segmente
schedule scheduler;
disasm *dsm;
//disio dio;
xref *xrefs;
gname *import;
gname *expt;
gname *name; // all other names
relocs *reloc;
range blk;
decrypt decrypter;
char winname[300];
HINSTANCE hInst;
//HANDLE ThreadHandle;
//DWORD ThreadId;
HWND Toolbar; // comctl32.dll's toolbar, most handled like TOOLSTAT.PAS
HWND Status; // comctl32.dll's status bar
HWND MainWnd; // main (frame) window containing Toolbar and Status too
HWND View[2]; // up to two viewer windows on client area of MainWnd
HWND KBHand; // handle of focused modeless dialog box (keyboard handler)
HACCEL Accel; // Accelerator Table
//POINT mainwndsize;
HFONT Font; // disassembly font
bool StockFont; // whether to free the font
POINT CharBox; // font size, for hit testing
HMENU rmenu; // right-click (and Shift+F10) context menu
//bool charinputenabled=false;
char szWinName[]="Dasm";
char program_name[]="Borg Disassembler";
TCHAR current_exe_name[MAX_PATH];
void CalcClientRect(RECT &R) {
// Calculates the client rectangle of MainWnd,
// removing a tool bar and the status line from height
RECT R2;
GetClientRect(MainWnd,&R);
if (Toolbar) {
GetWindowRect(Toolbar,&R2);
ScreenToClient(MainWnd,(LPPOINT)(&R2.right)); // convert the "bottom" member
R.top=R2.bottom;
}
if (Status) {
GetWindowRect(Status,&R2);
ScreenToClient(MainWnd,(LPPOINT)(&R2.left)); // convert the "top" member
R.bottom=R2.top;
}
}
void InitStruct(LPVOID mem, DWORD size) { // initialize most Windows structures
ZeroMemory(mem,size);
*(LPDWORD)mem=size;
}
/************************************************************************
* savefile_text *
* - this is the savefile as text dialog which asks the user to select *
* a file for the save. The filedump is then controlled by disio *
* - this is for text or asm saves *
************************************************************************/
bool savefile_text(HWND,bool printaddrs,bool block) {
TCHAR savefname[MAX_PATH];
UINT FilterIndex;
if (scheduler.sizelist()) {
MessageBox(MainWnd,"There are still items to process yet","Borg Warning",
MB_OK|MB_ICONEXCLAMATION);
return false;
}
savefname[0]=0;
if (!getfiletosave(savefname,elemof(savefname),IDS_FILTERTEXT,FilterIndex))
return false;
StatusMessage("Saving...");
if (block) cvd->dumpblocktofile(savefname,printaddrs);
else cvd->dumptofile(savefname,printaddrs);
StatusMessage("Saved.");
return true;
}
/************************************************************************/
/* Calculates the (global) size of display font, for easier hit-testing */
/************************************************************************/
void SetCharBox(HDC dc) {
TEXTMETRIC tm;
GetTextMetrics(dc,&tm);
CharBox.x=tm.tmAveCharWidth;
CharBox.y=tm.tmHeight+tm.tmExternalLeading;
}
void SetFont(HFONT NewFont, bool NewStockFont) {
if (!NewFont) return; // don't accept non-existing fonts
if (!StockFont && Font) DeleteObject(Font);
Font=NewFont;
StockFont=NewStockFont;
}
/************************************************************************
* setupfont *
* - handles the setting up of a font (like selecting the object for *
* window painting and setting checkmarks on the menu, etc) *
************************************************************************/
void setupfont(byte fontindex) {
static UINT MenuIDs[6]={font_ansi,font_system,font_courier,font_courier10,
font_courier12,font_user};
int i;
HDC hdc;
HFONT ofont;
HMENU hMenu;
LOGFONT lf;
options.font=fontindex;
hdc=GetDC(MainWnd);
hMenu=GetMenu(MainWnd);
ZeroMemory(&lf,sizeof(lf));
lstrcpy(lf.lfFaceName,T("Courier New"));
lf.lfWeight=FW_LIGHT;
for (i=0; i<6; i++) CheckMenuItem(hMenu,MenuIDs[i],
options.font-ansifont==i ? MF_CHECKED : MF_UNCHECKED);
switch (options.font) {
case systemfont: SetFont((HFONT)GetStockObject(SYSTEM_FIXED_FONT),true); break;
case courierfont: {
lf.lfHeight=-MulDiv(8, GetDeviceCaps(hdc,LOGPIXELSY),72);
SetFont(CreateFontIndirect(&lf),false);
}break;
case courierfont10: {
lf.lfHeight=-MulDiv(10, GetDeviceCaps(hdc,LOGPIXELSY),72);
SetFont(CreateFontIndirect(&lf),false);
}break;
case courierfont12: {
lf.lfHeight=-MulDiv(12, GetDeviceCaps(hdc,LOGPIXELSY),72);
SetFont(CreateFontIndirect(&lf),false);
}break;
case userfont: SetFont(CreateFontIndirect(&UserFont),false); break;
default: SetFont((HFONT)GetStockObject(ANSI_FIXED_FONT),true);
}
ofont=(HFONT)SelectObject(hdc,Font);
SetCharBox(hdc);
SelectObject(hdc,ofont);
ReleaseDC(MainWnd,hdc);
if (View[0]) {
SendMessage(View[0],WM_SETFONT,(WPARAM)Font,TRUE); // let the View do the rest
scheduler.addtask(windowupdate,priority_window,nlptr,NULL);
}
}
void FontSel(void) {
CHOOSEFONT cf;
InitStruct(&cf,sizeof(cf));
cf.hwndOwner=MainWnd;
cf.lpLogFont=&UserFont;
cf.Flags=CF_INITTOLOGFONTSTRUCT|CF_FIXEDPITCHONLY|CF_FORCEFONTEXIST
|CF_SCREENFONTS;
if (!ChooseFont(&cf)) return;
setupfont(userfont);
}
/************************************************************************
* changemenus *
* erm..... everytime I added a menu function I just added another line *
* in here :) *
************************************************************************/
void changemenus(bool HaveProject) {
static UINT IDmenu[]={file_save,save_asm,
Seg_Viewer,Names_Viewer,Xrefs_Viewer,Imports_Viewer,Exports_Viewer,
make_code,undefine_line,undefine_lines,undefine_lines_long,
line_jumpto,line_jumptoarg2,
make_dword,make_word,make_string,pascal_string,uc_string,up_string,dos_string,general_string,
Name_Location,Jump_Back,argover_dec,argover_hex,argover_char,argnegate,offset_dseg,
main_search,save_database,get_comment,
block_top,block_bottom,block_view,block_saveasm,block_savetext,block_undefine,
float_single,float_double,float_longdouble,arg_single,
search_again,cm_decrypt,IDM_Close};
static UINT IDrmenu[]={cm_decrypt,
arg_single,float_single,float_double,float_longdouble,block_top,
block_bottom,make_code,get_comment,
undefine_line,undefine_lines,undefine_lines_long,line_jumpto,line_jumptoarg2,
make_dword,make_word,make_string,pascal_string,uc_string,up_string,dos_string,general_string,
Name_Location,Xrefs_Viewer,argover_dec,argover_hex,argover_char,argnegate,offset_dseg};
HMENU hMenu;
int i;
hMenu=GetMenu(MainWnd);
EnableMenuItem(hMenu,file_open,HaveProject?MF_GRAYED:MF_ENABLED);
EnableMenuItem(hMenu,load_database,HaveProject?MF_GRAYED:MF_ENABLED);
for (i=0; i<sizeof(IDmenu)/sizeof(UINT); i++) {
EnableMenuItem(hMenu,IDmenu[i],HaveProject?MF_ENABLED:MF_GRAYED);
}
for (i=0; i<sizeof(IDrmenu)/sizeof(UINT); i++) {
EnableMenuItem(rmenu,IDrmenu[i],HaveProject?MF_ENABLED:MF_GRAYED);
// eigentlich Unsinn, ist Bestandteil des View-Fensters
}
// charinputenabled=HaveProject;
if (View[0]) DestroyWindow(View[0]); View[0]=0;
if (dsm) {
delete dsm; dsm=NULL; // Zeiger für offenes Projekt
delete import;
delete expt;
delete name;
delete dta;
delete reloc;
delete xrefs;
}
if (HaveProject) {
RECT R;
dsm=new disasm;
import=new gname;
expt=new gname;
name=new gname;
dta=new dataseg;
reloc=new relocs;
xrefs=new xref;
CalcClientRect(R);
View[0]=CreateWindow("BorgView",NULL,WS_CHILD|WS_VISIBLE|WS_VSCROLL,
R.left,R.top,R.right-R.left,R.bottom-R.top,
MainWnd,0,hInst,NULL);
SetFocus(View[0]);
}
}
/************************************************************************
* Thread *
* - this is the secondary thread interface. It just keeps calling the *
* scheduler to process any items in the queue, until such time as the *
* main thread wants to quit. *
************************************************************************/
/*
void Thread(PVOID) {
// needs to setup initial schedule list
// continually monitor schedule list for jobs
do {
if (scheduler.process() && !KillThread)
StatusMessage("Processing Completed");
Sleep(1);
}while (!KillThread);
InThread=false;
ExitThread(0);
}
*/
/************************************************************************
* StatusMessage *
* - output a simple message to the status bar *
************************************************************************/
void StatusMessage(char *msg) {
/*EnterCriticalSection(&cs);*/ // was causing locks (possibly)
Status_SetText(Status,0,0,msg);
/*LeaveCriticalSection(&cs); */
}
/************************************************************************
* StatusMessageNItems *
* - shows how many items there are left to process *
************************************************************************/
void StatusMessageNItems(dword nolistitems) {
static char buff[40];
wsprintf(buff,"Items to Process: %lu",nolistitems);
StatusMessage(buff);
}
/************************************************************************
* optionsinit *
* - initialises the global options struct with some default values *
************************************************************************/
void optionsinit(void) {
options.loaddebug=true;
options.mode16=false;
options.mode32=false;
options.loaddata=true;
options.loadresources=false;
options.cfa=true;
options.demangle=true;
options.processor=PROC_PENTIUM;
options.codedetect=CD_PUSHBP|CD_EAXFROMESP|CD_MOVEAX;
options.bgcolor=GetSysColor(COLOR_WINDOW);
options.highcolor=RGB(0,255,0);
options.textcolor=0;
options.font=ansifont;
options.readonly=false;
options.winmax=false;
}
/************************************************************************
* TestThread *
* - this is used on exit to wait for the secondary thread to finish. *
* - I try every possible way of getting the thread to exit normally *
* before we eventually kill it in the MainWnd, WM_DESTROY handler *
************************************************************************/
/*
bool TestThread(void){
HWND sbox;
bool ttest;
sbox=CreateDialog(hInst,MAKEINTRESOURCE(Borg_Shutdown),MainWnd,shutbox);
if (InThread)
SetThreadPriority(ThreadHandle,THREAD_PRIORITY_TIME_CRITICAL);
Sleep(2000);
DestroyWindow(sbox);
Sleep(5000);
//EnterCriticalSection(&cs);
ttest=InThread;
//LeaveCriticalSection(&cs);
return ttest;
}
*/
void RegisterFileTypes(void) {
TCHAR fn[MAX_PATH],s[1024];
static TCHAR proj[]="Compressed Borg Disassembly Project"; // used twice
GetModuleFileName(NULL,fn,elemof(fn));
wsprintf(s,"\"%s\" \"%%1\"",fn);
if(RegSetValue(HKEY_CLASSES_ROOT,T(".dasm"),REG_SZ,proj+11,25)==ERROR_SUCCESS
&& RegSetValue(HKEY_CLASSES_ROOT,T(".dasm\\shell\\open\\command"),REG_SZ,s,
lstrlen(s)+1)==ERROR_SUCCESS
&& RegSetValue(HKEY_CLASSES_ROOT,T(".cdasm"),REG_SZ,proj,36)==ERROR_SUCCESS
&& RegSetValue(HKEY_CLASSES_ROOT,T(".cdasm\\shell\\open\\command"),REG_SZ,s,
lstrlen(s)+1)==ERROR_SUCCESS) {
MessageBox(MainWnd,"Extensions .dasm and .cdasm registered.","Borg Message",MB_OK);
}else ShowLastError();
}
/************************************************************************
* dasm *
* - dasm is the application main window. *
* - everything the main window does is in this routine (for now) and *
* where a response is quick it appears in one of its helper functions *
* later in this file, otherwise it has been substantial enough to *
* warrant its own file and routines........ *
* - this is long *
************************************************************************/
LRESULT CALLBACK dasm(HWND hwnd,UINT Msg,WPARAM wParam,LPARAM lParam) {
// int killcount;
MainWnd=hwnd;
switch (Msg) {
case WM_CREATE: {
TCHAR *cmdline,*filename;
bool inquote,inspace;
optionsinit();
// InitializeCriticalSection(&cs);
Status=CreateStatusWindow(WS_CHILD|WS_VISIBLE|SBS_SIZEGRIP,
"No File Loaded",hwnd,2);
// KillThread=false;
// InThread=false;
rmenu=GetSubMenu(LoadMenu(hInst,MAKEINTRESOURCE(right_click_menu)),0);
load_reg_entries();
setupfont(options.font);
// get one (here: the last) file name from command line
inquote=false;
inspace=false;
filename=NULL;
for (cmdline=GetCommandLine(); *cmdline; cmdline++) {
switch (*cmdline) {
case '"': {
inquote=!inquote;
*cmdline=0;
}break;
case ' ': {
if (!inquote) {
*cmdline=0;
inspace=true;
}
}break;
default: if (inspace) {
inspace=false;
filename=cmdline;
}
}
}
// if a file name is given, open it (as uncompressed)
if (filename) loaddb(filename,0);
}break;
case WM_DROPFILES: {
TCHAR filename[MAX_PATH];
if (DragQueryFile((HDROP)wParam,(UINT)-1,NULL,0)!=1) {
MessageBox(hwnd,"Dropping of multiple files is not supported.\n"
"Borg will take only the first file.","Borg Message",
MB_OK|MB_ICONINFORMATION);
}
DragQueryFile((HDROP)wParam,0,filename,elemof(filename));
DragFinish((HDROP)wParam);
loaddb(filename,0);
}break;
case WM_ACTIVATE: {
if (View[0]) SetFocus(View[0]);
}break;
case WM_COMMAND: switch (LOWORD(wParam)) {
case CM_RegisterFileTypes: RegisterFileTypes(); break;
case IDM_Close: {
/*
KillThread=true;
killcount=0;
Sleep(0);
SetPriorityClass(ThreadHandle,HIGH_PRIORITY_CLASS);
if (InThread) while (TestThread()) {
killcount++;
if (killcount>2) {
// this is a nasty way of getting out.
// sometimes the thread just will not exit nicely when its busy.
if (TerminateThread(ThreadHandle,1)) {
CloseHandle(ThreadHandle);
break;
}
}
}
*/
if (dsm->dirty && MessageBox(hwnd,"Unsaved Data!\nClose file?","Borg",
MB_YESNO|MB_ICONQUESTION)!=IDYES) break;
CloseHandle(floader.efile);
floader.efile=INVALID_HANDLE_VALUE;
SetWindowText(hwnd,winname);
exportsviewer(false);
importsviewer(false);
namesviewer(NULL);
xrefsviewer(NULL);
segviewer(false);
changemenus(false);
}break;
case file_exit: SendMessage(MainWnd,WM_CLOSE,0,0); break;
case file_save: savefile_text(hwnd,true,false); break;
case get_comment: getcomment(); break;
case save_database: savedb(); break;
case load_database: {
TCHAR szFile[MAX_PATH];
UINT FilterIndex;
if (getfiletoload(szFile, elemof(szFile),IDS_FILTERSAVE,FilterIndex))
loaddb(szFile,FilterIndex);
}break;
case save_asm:
if (MessageBox(hwnd,"Sorry, saving text file only",NULL,MB_OKCANCEL)==IDOK)
savefile_text(hwnd,false,false); break;
case block_saveasm:
if (MessageBox(hwnd,"Sorry, saving text file only",NULL,MB_OKCANCEL)==IDOK)
savefile_text(hwnd,false,true); break;
case block_savetext: savefile_text(hwnd,true,true); break;
case cm_decrypt: decrypterdialog(); break;
case file_open: newfile(); break;
case Seg_Viewer: segviewer(true); break;
case Names_Viewer: {
lptr loc;
cvd->findcurrentaddr(&loc);
namesviewer(&loc);
} break;
case Imports_Viewer: importsviewer(true); break;
case Exports_Viewer: exportsviewer(true); break;
case Xrefs_Viewer: {
lptr loc;
cvd->findcurrentaddr(&loc);
xrefsviewer(&loc);
} break;
case make_code:
scheduler.addtask(user_makecode,priority_userrequest,nlptr,NULL); break;
case make_dword:
scheduler.addtask(user_makedword,priority_userrequest,nlptr,NULL); break;
case float_single:
scheduler.addtask(user_makesingle,priority_userrequest,nlptr,NULL); break;
case float_double:
scheduler.addtask(user_makedouble,priority_userrequest,nlptr,NULL); break;
case float_longdouble:
scheduler.addtask(user_makelongdouble,priority_userrequest,nlptr,NULL);break;
case make_word:
scheduler.addtask(user_makeword,priority_userrequest,nlptr,NULL); break;
case make_string:
scheduler.addtask(user_makestring,priority_userrequest,nlptr,NULL); break;
case pascal_string:
scheduler.addtask(user_pascalstring,priority_userrequest,nlptr,NULL);break;
case uc_string:
scheduler.addtask(user_ucstring,priority_userrequest,nlptr,NULL); break;
case up_string:
scheduler.addtask(user_upstring,priority_userrequest,nlptr,NULL); break;
case dos_string:
scheduler.addtask(user_dosstring,priority_userrequest,nlptr,NULL); break;
case general_string:
scheduler.addtask(user_generalstring,priority_userrequest,nlptr,NULL);break;
case argover_dec:
scheduler.addtask(user_argoverdec,priority_userrequest,nlptr,NULL); break;
case arg_single:
scheduler.addtask(user_argsingle,priority_userrequest,nlptr,NULL); break;
case argover_hex:
scheduler.addtask(user_argoverhex,priority_userrequest,nlptr,NULL); break;
case argnegate:
scheduler.addtask(user_argnegate,priority_userrequest,nlptr,NULL); break;
case offset_dseg:
scheduler.addtask(user_argoveroffsetdseg,priority_userrequest,nlptr,NULL);break;
case argover_char:
scheduler.addtask(user_argoverchar,priority_userrequest,nlptr,NULL);break;
case undefine_line:
scheduler.addtask(user_undefineline,priority_userrequest,nlptr,NULL);break;
case undefine_lines:
scheduler.addtask(user_undefinelines,priority_userrequest,nlptr,NULL);break;
case undefine_lines_long:
scheduler.addtask(user_undefinelines_long,priority_userrequest,nlptr,NULL);break;
case block_undefine:
scheduler.addtask(user_undefineblock,priority_userrequest,nlptr,NULL);break;
case block_view: blockview(); break;
case block_top:
scheduler.addtask(user_marktopblock,priority_userrequest,nlptr,NULL);break;
case block_bottom:
scheduler.addtask(user_markbottomblock,priority_userrequest,nlptr,NULL);break;
case line_jumpto:
scheduler.addtask(user_jumpto,priority_userrequest,nlptr,NULL); break;
case line_jumptoarg2:
scheduler.addtask(user_jumptoarg2,priority_userrequest,nlptr,NULL); break;
case Name_Location: namelocation(); break;
case help_short:
if (HelpShortcuts) SetActiveWindow(HelpShortcuts);
else HelpShortcuts=CreateDialog(hInst,MAKEINTRESOURCE(help_shortcuts),hwnd,helpshortcuts);
break;
case help_about:
DialogBox(hInst,MAKEINTRESOURCE(D_help_about),hwnd,habox);
break;
case Jump_Back:
scheduler.addtask(user_jumpback,priority_userrequest,nlptr,NULL);
break;
case main_search: searchengine(); break;
case search_again: searchmore(); break;
case set_bg_color:
if (choosecolour(options.bgcolor) && View[0]) InvalidateRect(View[0],NULL,true);
scheduler.addtask(windowupdate,priority_window,nlptr,NULL);
break;
case set_high_color:
if (choosecolour(options.highcolor) && View[0]) InvalidateRect(View[0],NULL,true);
scheduler.addtask(windowupdate,priority_window,nlptr,NULL);
break;
case set_text_color:
if (choosecolour(options.textcolor) && View[0]) InvalidateRect(View[0],NULL,true);
scheduler.addtask(windowupdate,priority_window,nlptr,NULL);
break;
case font_system: setupfont(systemfont); break;
case font_courier: setupfont(courierfont); break;
case font_courier10: setupfont(courierfont10); break;
case font_courier12: setupfont(courierfont12); break;
case font_ansi: setupfont(ansifont); break;
case font_user: FontSel(); break;
// default:
// return DefWindowProc(hwnd,Msg,wParam,lParam);
}break;
case WM_QUERYENDSESSION:
save_reg_entries();
if (dsm && dsm->dirty && MessageBox(MainWnd,
"Unsaved Data!\n"
"Are you sure that you want to exit Borg?\n"
"Hit Yes To Exit\n"
"Hit No to Stay","Borg Disassembler",
MB_ICONEXCLAMATION|MB_YESNO)==IDNO) return FALSE;
return TRUE;
case WM_CLOSE:
if (!SendMessage(hwnd,WM_QUERYENDSESSION,0,0)) break;
// scheduler.stopthread();
// scheduler.addtask(quitborg,priority_quit,nlptr,NULL);
// KillThread=true;
// if(InThread)
// SetThreadPriority(ThreadHandle,THREAD_PRIORITY_TIME_CRITICAL);
DestroyWindow(MainWnd);
return 0;
case WM_DESTROY: {
// if (View[0]) SendMessage(hwnd,WM_COMMAND,IDM_Close,0);
// DeleteCriticalSection(&cs);
PostQuitMessage(0);
}break;
case WM_SIZE: {
// if(wParam==SIZE_MAXIMIZED)
// options.winmax=true;
// else if (wParam==SIZE_RESTORED)
// options.winmax=false;
// mainwndsize.top=0;
// mainwndsize.left=0;
// GetWindowRect(Status,&StatusWindowSize);
// GetWindowRect(MainWnd,&mainwnd);
// MoveWindow(Status,0,mainwndsize.bottom-StatusWindowSize.bottom+StatusWindowSize.top,
// mainwndsize.right,StatusWindowSize.bottom-StatusWindowSize.top,true);
if (Toolbar) SendMessage(Toolbar,Msg,wParam,lParam); // self-sizing
if (Status) SendMessage(Status,Msg,wParam,lParam); // self-sizing
if (View[0]) { // Yet only one View window, later dividable
RECT R;
CalcClientRect(R);
MoveWindow(View[0],R.left,R.top,R.right-R.left,R.bottom-R.top,TRUE);
}
}break;
// case WM_REPEATNAMEVIEW: namesviewer(); break;
// case WM_REPEATXREFVIEW: xrefsviewer(); break;
// maximises window, used when the reg is read in at the start to maximise
// the main window after initialisation of it
// case WM_MAXITOUT:
// ShowWindow(MainWnd,SW_MAXIMIZE);
// break;
default: return DefWindowProc(hwnd,Msg,wParam,lParam);
}
return 0;
}
int limit(int i, int u, int o) {
// limit i to the both bounds given; if o<u then return=u
return max(min(i,o),u);
}
/****************************************************/
/* Window Procedure of (one of both) View window(s) */
/****************************************************/
LRESULT CALLBACK ViewWndProc(HWND hwnd,UINT Msg,WPARAM wParam,LPARAM lParam) {
// Get (or create) associated ViewData for the window
disio *vd=(disio*)GetWindowLong(hwnd,GWL_USERDATA);
if (!vd) {
vd=new disio(hwnd); //(PVIEWDATA)LocalAlloc(LPTR,sizeof(VIEWDATA));
vd->MainBuff=0;
SetWindowLong(hwnd,GWL_USERDATA,(LPARAM)vd);
}
// distribute the messages
switch (Msg) {
case WM_CREATE: {
SetScrollRange(hwnd,SB_VERT,0,VERTSCROLLRANGE,false);
SetScrollPos(hwnd,SB_VERT,0,false);
}break;
case WM_SETFONT: if (lParam) InvalidateRect(hwnd,NULL,TRUE);
case WM_SIZE: {
RECT R;
SCROLLINFO SI;
GetClientRect(hwnd,&R);
vd->size.x=(R.right +CharBox.x-1)/CharBox.x; // rounding up
vd->size.y=(R.bottom+CharBox.y-1)/CharBox.y;
// (re)allocate space for disassembly lines
UINT alloc=sizeof(dasm_line)*vd->size.y;
vd->MainBuff=(dasm_line*)(
vd->MainBuff ? LocalReAlloc(vd->MainBuff,alloc,LMEM_ZEROINIT) : LocalAlloc(LPTR,alloc));
// correct hpos
vd->hpos=limit(vd->hpos,0,MAX_LENGTH-vd->size.x);
// correct the horizontal scroll bar
SI.cbSize=sizeof(SI);
SI.fMask=SIF_ALL;
SI.nMin=0;
SI.nMax=MAX_LENGTH;
SI.nPage=vd->size.x;
SI.nPos=vd->hpos;
SetScrollInfo(hwnd,SB_HORZ,&SI,TRUE);
}break;
case WM_SETFOCUS: {
cvd=vd; // set global pointer to focused window
}break;
case WM_PAINT: {
vd->DoPaint();
}break;
case WM_VSCROLL: {
lptr scrll;
switch (LOWORD(wParam)) {
case SB_LINEUP:
scrll.assign(0,(dword)-1);
scheduler.addtask(scrolling,priority_userrequest,scrll,NULL);
break;
case SB_LINEDOWN:
scrll.assign(0,1);
scheduler.addtask(scrolling,priority_userrequest,scrll,NULL);
break;
case SB_PAGEUP:
scrll.assign(0,-(vd->size.y-1));
scheduler.addtask(scrolling,priority_userrequest,scrll,NULL);
break;
case SB_PAGEDOWN:
scrll.assign(0,vd->size.y-1);
scheduler.addtask(scrolling,priority_userrequest,scrll,NULL);
break;
case SB_THUMBPOSITION:
scrll.assign(0,HIWORD(wParam));
scheduler.addtask(vthumbposition,priority_userrequest,scrll,NULL);
break;
}
}break;
case WM_HSCROLL: {
lptr scrll;
int amount,x;
switch (LOWORD(wParam)) {
case SB_THUMBTRACK:
case SB_THUMBPOSITION: amount=(int)HIWORD(wParam)-vd->hpos; goto set;
case SB_LINEUP: amount=-1; goto set;
case SB_LINEDOWN: amount= 1; goto set;
case SB_PAGEUP: amount=-8; goto set;
case SB_PAGEDOWN: amount= 8; set:
x=limit(vd->hpos+amount,0,MAX_LENGTH-vd->size.x);
amount=vd->hpos-x; vd->hpos=x;
SetScrollPos(hwnd,SB_HORZ,vd->hpos,TRUE);
ScrollWindow(hwnd,amount*CharBox.x,0,NULL,NULL);
break;
}
}break;
case WM_CONTEXTMENU: {
POINT p={(short)LOWORD(lParam),(short)HIWORD(lParam)};
if (lParam==(LPARAM)-1) { // from keyboard
p.x=35*CharBox.x;
p.y=(vd->sel+1)*CharBox.y;
ClientToScreen(hwnd,&p);
}
TrackPopupMenu(rmenu,0,p.x,p.y,0,MainWnd,NULL);
}break;
case WM_KEYDOWN: switch (wParam) {
case VK_HOME: SendMessage(hwnd,WM_VSCROLL,SB_TOP,0L); break;
case VK_PRIOR: SendMessage(hwnd,WM_VSCROLL,SB_PAGEUP,0L); break;
case VK_NEXT: SendMessage(hwnd,WM_VSCROLL,SB_PAGEDOWN,0L); break;
case VK_DOWN: SendMessage(hwnd,WM_VSCROLL,SB_LINEDOWN,0L); break;
case VK_UP: SendMessage(hwnd,WM_VSCROLL,SB_LINEUP,0L); break;
case VK_LEFT: SendMessage(hwnd,WM_HSCROLL,SB_PAGEUP,0L); break;
case VK_RIGHT: SendMessage(hwnd,WM_HSCROLL,SB_PAGEDOWN,0L); break;
case VK_RETURN:
scheduler.addtask(
GetKeyState(VK_SHIFT)<0 ? user_jumptoarg2 : user_jumpto,
priority_userrequest,nlptr,NULL);
break;
case VK_ESCAPE:
scheduler.addtask(user_jumpback,priority_userrequest,nlptr,NULL);
break;
case VK_F3:
searchmore();
break;
}break;
case WM_LBUTTONDOWN: {
SetFocus(hwnd);
}nobreak;
case WM_RBUTTONDOWN: {
vd->setpos(HIWORD(lParam)/CharBox.y);
}break;
case WM_LBUTTONDBLCLK: {
SendMessage(hwnd,WM_KEYDOWN,VK_RETURN,0);
}break;
case WM_NCDESTROY: {
LocalFree(vd->MainBuff);
delete vd;
}break;
default: return DefWindowProc(hwnd,Msg,wParam,lParam);
}
return 0;
}
/************************************************************************
* WinMain..... it all starts here *
************************************************************************/
int WINAPI WinMain(HINSTANCE,HINSTANCE,LPSTR,int) {
WNDCLASS wc;
MSG msg;
InitCommonControls();
hInst=GetModuleHandle(NULL);
/* Define window class */
ZeroMemory(&wc,sizeof(wc));
wc.style=CS_DBLCLKS;
wc.lpfnWndProc=dasm; // A fürchterlicher Name!!
wc.hInstance=hInst;
wc.hIcon=LoadIcon(hInst,MAKEINTRESOURCE(100));
wc.hCursor=LoadCursor(NULL,IDC_ARROW);
wc.hbrBackground=(HBRUSH)(COLOR_APPWORKSPACE+1);
wc.lpszMenuName=MAKEINTRESOURCE(100);
wc.lpszClassName=szWinName;
/* Register window classes */
RegisterClass(&wc);
wc.lpfnWndProc=ViewWndProc;
wc.hbrBackground=0;
wc.lpszClassName="BorgView";
RegisterClass(&wc);
Accel=LoadAccelerators(hInst,MAKEINTRESOURCE(100));
/* Create window */
wsprintf(winname,"Borg Disassembler v%0d.%2da",(int)BORG_VER/100,BORG_VER%100);
MainWnd=CreateWindowEx(WS_EX_ACCEPTFILES,szWinName,winname,WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,
NULL,NULL,hInst,NULL);
/* Display window */
ShowWindow(MainWnd,SW_SHOWDEFAULT);
/* Message Loop */
for (;;){
if (PeekMessage(&msg,NULL,0,0,PM_REMOVE)) {
if (msg.message==WM_QUIT) break;
if (KBHand && IsDialogMessage(KBHand,&msg)) continue;
if (Accel && TranslateAccelerator(MainWnd,Accel,&msg)) continue;
TranslateMessage(&msg);
DispatchMessage(&msg);
}else{
if (!scheduler.process()) WaitMessage();
}
}
#ifdef _DEBUG
_CrtMemDumpAllObjectsSince(NULL);
#endif
return msg.wParam;
}
Vorgefundene Kodierung: UTF-8 | 0
|