Source file: /~heha/hsn/borg.zip/USER_DLG.CPP

/************************************************************************
* dlg_view.cpp								*
* - the functions here are viewers for various lists within Borg, for	*
*   example exports,imports and xrefs Dialog box viewers, along with	*
*   any calling functions which stop/start the secondary thread.	*
* - Extracted from various classes v2.22				*
* - All routines in here when entered from outside should stop the	*
*   secondary thread and restart it on exit.				*
************************************************************************/

#include <windows.h>

//#include "menuids.rh"
#include "resource.h"
#include "dasm.h"
#include "schedule.h"
#include "xref.h"
#include "range.h"
#include "gname.h"
#include "disio.h"
#include "data.h"
#include "disasm.h"
#include "debug.h"

// standard creation for modeless dialog boxes
// wnd must reference to a global-static HWND
void MyCreateDialog(HWND &wnd, UINT id, DLGPROC dlgproc) {
 if (dlgproc) {
  if (wnd) SetActiveWindow(wnd);
  else wnd=CreateDialog(hInst,MAKEINTRESOURCE(id),MainWnd,dlgproc);
 }else if (wnd) DestroyWindow(wnd);
}

// standard processing for modeless dialog boxes
// wnd must reference to a global-static HWND
void MyDefDlgProc(HWND &wnd, HWND w, UINT Msg, WPARAM wParam) {
 switch (Msg) {
  case WM_ACTIVATE: KBHand=wParam?w:0; break;
  case WM_COMMAND: if (LOWORD(wParam)==IDCANCEL) DestroyWindow(w); break;
  case WM_DESTROY: wnd=0;
 }
}

HWND ExportsBox;
/************************************************************************
* exportsbox								*
* - this is the exports viewer dialog box. It is simpler than the names *
*   class dialog box, featuring only a jump to option. As for the names *
*   class a request is added to the scheduler for any jump and the	*
*   dialog box exits. the main code is for filling the initial list box *
*   and for displaying a new address when the selection is changed	*
************************************************************************/
BOOL CALLBACK exportsbox(HWND Wnd,UINT Msg,WPARAM wParam,LPARAM lParam) {
 static gnameitem *t;
 dword st;
 dword i;
 MyDefDlgProc(ExportsBox,Wnd,Msg,wParam);

 switch (Msg) {
  case WM_INITDIALOG: {
   HWND w=GetDlgItem(Wnd,IDC_LISTBOX);
   expt->resetiterator();
   for (i=0;i<expt->numlistitems();i++) {
    t=expt->nextiterator();
    SendMessage(w,LB_ADDSTRING,0,(LPARAM)(LPCTSTR)t->name);
   }
   SendMessage(w,LB_SETCURSEL,0,0);
   SendMessage(Wnd,WM_COMMAND,MAKELONG(IDC_LISTBOX,LBN_SELCHANGE),(LPARAM)w);
  }return TRUE;

  case WM_COMMAND: switch (LOWORD(wParam)) {
   case IDC_LISTBOX: switch (HIWORD(wParam)) {
    case LBN_SELCHANGE: {
     TCHAR s[20];
     i=SendMessage((HWND)lParam,LB_GETCURSEL,0,0)+1;
     expt->resetiterator();
     while (i) {
      t=expt->nextiterator();
      i--;
     }
     st=t->addr.segm;
     wsprintf(s,"0x%lx",st);	      SetDlgItemText(Wnd,EXPORTS_TEXTSTART,s);
     wsprintf(s,"0x%lx",t->addr.offs); SetDlgItemText(Wnd,EXPORTS_TEXTEND,s);
    }break;
    case LBN_DBLCLK: SendMessage(Wnd,WM_COMMAND,IDOK,0);
   }break;
   case IDOK: {
    scheduler.addtask(user_jumptoaddr,priority_userrequest,t->addr,NULL);
   }break;
  }
 }
 return FALSE;
}

/************************************************************************
* exportsviewer								*
* - stops the thread and displays the exports viewer dialog.		*
************************************************************************/
void exportsviewer(bool state) {
// scheduler.stopthread();
 if (state) {
  if (!expt->numlistitems()) {
   MessageBox(MainWnd,"There are no exports in the list","Borg Message",MB_OK);
  }else{
   MyCreateDialog(ExportsBox,Exports_Viewer,exportsbox);
  }
 }else MyCreateDialog(ExportsBox,0,NULL);
// scheduler.continuethread();
}

HWND ImportsBox;
/************************************************************************
* importsbox								*
* - this is the imports viewer dialog box, it is similar to the exports *
*   and names dialog, although simpler since there is only an ok button *
*   Most of the code is for filling the list box and displaying info	*
*   when an item is selected						*
************************************************************************/
BOOL CALLBACK importsbox(HWND Wnd,UINT Msg,WPARAM wParam,LPARAM lParam) {
 static gnameitem *t;
 dword st;
 dword i;
 MyDefDlgProc(ImportsBox,Wnd,Msg,wParam);

 switch (Msg) {
  case WM_INITDIALOG: {
   HWND w=GetDlgItem(Wnd,IDC_LISTBOX);
   import->resetiterator();
   for (i=0;i<import->numlistitems();i++) {
    t=import->nextiterator();
    SendMessage(w,LB_ADDSTRING,0,(LPARAM)(LPCTSTR)t->name);
   }
   SendMessage(w,LB_SETCURSEL,0,0);
   SendMessage(Wnd,WM_COMMAND,MAKELONG(IDC_LISTBOX,LBN_SELCHANGE),(LPARAM)w);
  }return TRUE;

  case WM_COMMAND: switch (LOWORD(wParam)) {
   case IDC_LISTBOX: switch (HIWORD(wParam)) {
    case LBN_SELCHANGE: {
     TCHAR s[20];
     i=SendMessage((HWND)lParam,LB_GETCURSEL,0,0)+1;
     import->resetiterator();
     while (i) {
      t=import->nextiterator();
      i--;
     }
     st=t->addr.segm;
     wsprintf(s,"0x%lx",st);	      SetDlgItemText(Wnd,IMPORTS_TEXTSTART,s);
     wsprintf(s,"0x%lx",t->addr.offs); SetDlgItemText(Wnd,IMPORTS_TEXTEND,s);
    }break;
    case LBN_DBLCLK: SendMessage(Wnd,WM_COMMAND,IDOK,0);
   }break;
   case IDOK:
   case Xrefs_Viewer: {
    xrefsviewer(&t->addr);
   }break;
  }
 }
 return FALSE;
}

/************************************************************************
* importsviewer								*
* - stops the thread and displays the imports viewer dialog.		*
************************************************************************/
void importsviewer(bool state) {
// scheduler.stopthread();
 if (state) {
  if (!import->numlistitems()) {
   MessageBox(MainWnd,"There are no imports in the list","Borg Message",MB_OK);
  }else{
   MyCreateDialog(ImportsBox,Imports_Viewer,importsbox);
  }
 }else MyCreateDialog(ImportsBox,0,NULL); 
// scheduler.continuethread();
}

/************************************************************************
* getnamebox								*
* - this is a small dialog for the input of name for a location. the	*
*   name is stored (pointer) in the extra parameter  from		*
*   DialogBoxParam							*
************************************************************************/
BOOL CALLBACK getnamebox(HWND Wnd,UINT Msg,WPARAM wParam,LPARAM lParam) {

 switch (Msg) {
  case WM_INITDIALOG: {
   SetWindowLong(Wnd,DWL_USER,lParam);
   SetDlgItemText(Wnd,IDC_NAMEEDIT,(LPSTR)lParam);
  } return TRUE;

  case WM_COMMAND: switch (LOWORD(wParam)) {
   case IDOK: {
    lParam=GetWindowLong(Wnd,DWL_USER);
    GetDlgItemText(Wnd,IDC_NAMEEDIT,(LPSTR)lParam,GNAME_MAXLEN);
   }nobreak;
   case IDCANCEL: EndDialog(Wnd,wParam);
  }
 }
 return FALSE;
}

HWND NamesBox;		// modeless dialog, with dynamic changeable list box
/************************************************************************
* namesbox								*
* - the dialog box for the names list.					*
* - the list is a simple location order of names, which is the same as	*
*   the underlying list class ordering					*
************************************************************************/
BOOL CALLBACK namesbox(HWND Wnd,UINT Msg,WPARAM wParam,LPARAM lParam) {
 static gnameitem *t;
 dword st;
 dword i;
 MyDefDlgProc(NamesBox,Wnd,Msg,wParam);

 switch (Msg) {
  case WM_INITDIALOG: {
   HWND w=GetDlgItem(Wnd,IDC_LISTBOX);
   name->resetiterator();
   for (i=0;i<name->numlistitems();i++) {
    t=name->nextiterator();
    WPARAM j=SendMessage(w,LB_ADDSTRING,0,(LPARAM)(LPCTSTR)t->name);
    SendMessage(w,LB_SETITEMDATA,j,(LPARAM)t);
   }
   SendMessage(w,LB_SETCURSEL,0,0);
   SendMessage(Wnd,WM_COMMAND,MAKELONG(IDC_LISTBOX,LBN_SELCHANGE),(LPARAM)w);
  }return TRUE;

  case WM_SETADDR: {
   HWND w=GetDlgItem(Wnd,IDC_LISTBOX);
   WPARAM k=SendMessage(w,LB_GETCOUNT,0,0);
   for (i=0; i<k; i++) {		// focus to the address given
    gnameitem *j=(gnameitem*)SendMessage(w,LB_GETITEMDATA,i,0);
    if (j->addr==*(lptr*)lParam) {
     SendMessage(w,LB_SETCURSEL,i,0);
     SendMessage(Wnd,WM_COMMAND,MAKELONG(IDC_LISTBOX,LBN_SELCHANGE),(LPARAM)w);
     break;
    }
   }
  }break;

  case WM_DELETENAME: {
   HWND w=GetDlgItem(Wnd,IDC_LISTBOX);
   WPARAM k=SendMessage(w,LB_GETCOUNT,0,0);
   for (i=0; i<k; i++) {		// if already present, delete item
    LPARAM j=SendMessage(w,LB_GETITEMDATA,i,0);
    if (j==lParam) {
     SendMessage(w,LB_DELETESTRING,i,0);
     break;
    }
   }
  }break;

  case WM_ADDNAME: {
   HWND w=GetDlgItem(Wnd,IDC_LISTBOX);
   WPARAM j=SendMessage(w,LB_ADDSTRING,0,(LPARAM)(LPCTSTR)((gnameitem*)lParam)->name);
   SendMessage(w,LB_SETITEMDATA,j,(LPARAM)(gnameitem*)lParam);
  }break;

  case WM_COMMAND: switch (LOWORD(wParam)) {
   case IDC_LISTBOX: switch (HIWORD(wParam)) {
    case LBN_SELCHANGE: {
     TCHAR s[20];
     i=SendMessage((HWND)lParam,LB_GETCURSEL,0,0);
     t=(gnameitem*)SendMessage((HWND)lParam,LB_GETITEMDATA,i,0);
     st=t->addr.segm;
     wsprintf(s,"0x%lx",st);	      SetDlgItemText(Wnd,NAMES_TEXTSTART,s);
     wsprintf(s,"0x%lx",t->addr.offs); SetDlgItemText(Wnd,NAMES_TEXTEND,s);
    }break;
    case LBN_DBLCLK: SendMessage(Wnd,WM_COMMAND,IDOK,0);	// make a "jump to"
   }break;
   case NAMES_DELETE: {
    name->delname(t->addr);
//    scheduler.addtask(user_repeatnameview,priority_userrequest,nlptr,NULL);
   }break;
   case NAMES_RENAME: {
    TCHAR s[20];
    lstrcpy(s,t->name);
    if (DialogBoxParam(hInst,MAKEINTRESOURCE(Get_Name),Wnd,getnamebox,
      (LPARAM)s)==IDOK) {
     scheduler.addtask(namecurloc,priority_userrequest,t->addr,s);
    }
//    scheduler.addtask(user_repeatnameview,priority_userrequest,nlptr,NULL);
   }break;
   case Xrefs_Viewer: {
    xrefsviewer(&t->addr);
   }break;
   case IDOK: {
    scheduler.addtask(user_jumptoaddr,priority_userrequest,t->addr,NULL);
   }break;
  }
 }
 return FALSE;
}

/************************************************************************
* namesviewer								*
* - this controls the display of the names viewer dialog box. names are *
*   viewed in the dialog box in location order.				*
************************************************************************/
void namesviewer(const lptr *loc) {
// scheduler.stopthread();
 if (loc) {
  if (!name->numlistitems()) {
   MessageBox(MainWnd,"There are no names in the list","Borg Message",MB_OK);
  }else{
   MyCreateDialog(NamesBox,Names_Viewer,namesbox);
   SendMessage(NamesBox,WM_SETADDR,0,(LPARAM)loc);
  }
 }else MyCreateDialog(NamesBox,0,NULL);
// scheduler.continuethread();
}

/************************************************************************
* namelocation								*
* - this calls the user dialog for a name to be entered for the current *
*   location, and names it						*
************************************************************************/
void namelocation(void) {
 lptr loc;
 TCHAR s[20];

// scheduler.stopthread();
 s[0]=0;
 if (DialogBoxParam(hInst,MAKEINTRESOURCE(Get_Name),MainWnd,getnamebox,
   (LPARAM)s)==IDOK) {
  cvd->findcurrentaddr(&loc);
  scheduler.addtask(namecurloc,priority_userrequest,loc,s);
 }
// scheduler.continuethread();
}

/************************************************************************
* blockbox								*
* - this is the dialog which just shows the extents of the current	*
*   block								*
************************************************************************/
BOOL CALLBACK blockbox(HWND Wnd,UINT Msg,WPARAM wParam,LPARAM) {
 switch (Msg) {
  case WM_INITDIALOG: {
   TCHAR s[30],*sp;
   wsprintf(s,"%04x:%08lxh",blk.top.segm,blk.top.offs);
   SetDlgItemText(Wnd,Text_Top,s);
   wsprintf(s,"%04x:%08lxh",blk.bottom.segm,blk.bottom.offs);
   SetDlgItemText(Wnd,Text_Bottom,s);
   if (blk.top==nlptr)		sp=T("Top not set");
   else if(blk.bottom==nlptr)	sp=T("Bottom not set");
   else if(blk.top>blk.bottom)	sp=T("Range is empty");
   else				sp=T("Range set");
   SetDlgItemText(Wnd,Text_Status,sp);
  }return TRUE;

  case WM_COMMAND: switch (LOWORD(wParam)) {
   case IDOK:
   case IDCANCEL: EndDialog(Wnd,wParam);
  }
 }
 return FALSE;
}

/************************************************************************
* blockview								*
* - this stops the secondary thread and puts up the dialog box for	*
*   viewing the extents of the block					*
************************************************************************/
void blockview(void)
{ //scheduler.stopthread();
  DialogBox(hInst,MAKEINTRESOURCE(Block_Dialog),MainWnd,blockbox);
//  scheduler.continuethread();
}

HWND XrefsBox;
/************************************************************************
* dialog box controls and workings - most message processing is		*
* standardised across Borg (colorchanges, etc)				*
************************************************************************/
BOOL CALLBACK xrefsbox(HWND Wnd,UINT Msg,WPARAM wParam,LPARAM lParam) {
 static xrefitem *currentsel,xtmp,*vt;
 static int numberofitems;
 dword st;
 dword i;
 MyDefDlgProc(XrefsBox,Wnd,Msg,wParam);

 switch (Msg) {
  case WM_INITDIALOG: {
  }return TRUE;

  case WM_SETADDR: {		// build the list from address given
   HWND w=GetDlgItem(Wnd,IDC_LISTBOX);
   TCHAR s[40];
   SendMessage(w,LB_RESETCONTENT,0,0);
//   cvd->findcurrentaddr(&xtmp.addr);
   xtmp.addr=*(lptr*)lParam;
   xtmp.refby=nlptr;
   xrefs->findnext(&xtmp);
   vt=xrefs->nextiterator();
   currentsel=vt;
   numberofitems=0;
   if (vt) {
    while (vt->addr==xtmp.addr) {
     st=vt->refby.segm;
     wsprintf(s,"0x%lx:0x%lx",st,vt->refby.offs);
     numberofitems++;
     SendMessage(w,LB_ADDSTRING,0,(LPARAM)(LPCTSTR)s);
     vt=xrefs->nextiterator();
     if (!vt) break;
    }
   }
   SendMessage(w,LB_SETCURSEL,0,0);
   name->resetiterator();
   for (i=0;i<name->numlistitems();i++) {
    gnameitem *t=name->nextiterator();
    if (t->addr==*(lptr*)lParam) {
     SetDlgItemText(Wnd,102,t->name);
     break;
    }
   }
  }break;

  case WM_COMMAND: switch (LOWORD(wParam)) {
   case IDC_LISTBOX: switch (HIWORD(wParam)) {
    case LBN_SELCHANGE: {
     i=SendMessage((HWND)lParam,LB_GETCURSEL,0,0)+1;
     xrefs->findnext(&xtmp);
     while (i) {
      vt=xrefs->nextiterator();
      i--;
     }
     currentsel=vt;
    }break;
    case LBN_DBLCLK: SendMessage(Wnd,WM_COMMAND,IDOK,0);	// make a "jump to"
   }break;
   case NAMES_DELETE: {
    scheduler.addtask(user_delxref,priority_userrequest,currentsel->refby,NULL);
    scheduler.addtask(windowupdate,priority_window,nlptr,NULL);
//    if (numberofitems>1)
//      scheduler.addtask(user_repeatxrefview,priority_userrequest,nlptr,NULL);
   }break;
   case IDOK: {
    scheduler.addtask(user_jumptoaddr,priority_userrequest,currentsel->refby,NULL);
   }break;
  }
 }
 return FALSE;
}

/************************************************************************
* the xrefs viewer - stops the thread and continues it after		*
* displaying the dialog box						*
************************************************************************/
void xrefsviewer(const lptr *loc) {
 xrefitem *findit,xtmp;

// scheduler.stopthread();
 if (loc) {
  xtmp.addr=*loc;
  xtmp.refby=nlptr;
  findit=xrefs->findnext(&xtmp);
  if (!findit) {
   MessageBox(MainWnd,"Unable to find any xrefs for the location","Borg Message",MB_OK);
  }else if (findit->addr!=xtmp.addr) {
   MessageBox(MainWnd,"There are no xrefs for the current location in the list","Borg Message",MB_OK);
  }else{
   MyCreateDialog(XrefsBox,Xrefs_Viewer,xrefsbox);
   SendMessage(XrefsBox,WM_SETADDR,0,(LPARAM)loc);
  }
 }else MyCreateDialog(XrefsBox,0,NULL);
// scheduler.continuethread();
}

HWND SegBox;
/************************************************************************
* segbox								*
* - this is the segment viewer dialog box which shows the segments, and *
*   details of them as they are clicked on. It allows jumping to the	*
*   segments as well. Background analysis is halted when calling this	*
*   particularly because iterators are used, and they there is only one *
*   iterator for the segment list					*
************************************************************************/
void SetType(HWND Wnd, dsegitem *t) {
 TCHAR s[20];
 dword st;

 wsprintf(s,"0x%lx",t->addr.offs); SetDlgItemText(Wnd,SEG_TEXTSTART,s);
 st=t->addr.offs+t->size-1;
 wsprintf(s,"0x%lx",st);	   SetDlgItemText(Wnd,SEG_TEXTEND,s);
 wsprintf(s,"0x%lx",t->size);	   SetDlgItemText(Wnd,SEG_TEXTSIZE,s);
 SetDlgItemText(Wnd,SEG_TEXTTYPE,typ2name(t->typ));
 SetDlgItemText(Wnd,IDC_SEGNAMETEXT,t->name);
}

BOOL CALLBACK segbox(HWND Wnd,UINT Msg,WPARAM wParam,LPARAM lParam) {
 static string *segt;
 static dsegitem *t;
 dword st;
 dword i;
 MyDefDlgProc(SegBox,Wnd,Msg,wParam);

 switch (Msg) {
  case WM_INITDIALOG: {
   HWND w=GetDlgItem(Wnd,IDC_LISTBOX);
   segt=new string[dta->numlistitems()];
   dta->resetiterator();
   for (i=0;i<dta->numlistitems();i++) {
    segt[i]=new char[20];
    t=dta->nextiterator();
    st=t->addr.segm;
    wsprintf(segt[i],"0x%x",st);
    st=t->addr.offs;
    wsprintf(segt[i]+lstrlen(segt[i]),":0x%04lx",st);
    SendMessage(w,LB_ADDSTRING,0,(LPARAM)(LPCTSTR)segt[i]);
   }
   SendMessage(w,LB_SETCURSEL,0,0);
   SendMessage(Wnd,WM_COMMAND,MAKELONG(IDC_LISTBOX,LBN_SELCHANGE),(LPARAM)w);
  }return TRUE;

  case WM_COMMAND: switch (LOWORD(wParam)) {
   case IDC_LISTBOX: switch (HIWORD(wParam)) {
    case LBN_SELCHANGE: {
     i=SendMessage((HWND)lParam,LB_GETCURSEL,0,0);
     dta->resetiterator();
     t=dta->nextiterator();
     while(i) {
      t=dta->nextiterator();
      i--;
     }
     SetType(Wnd,t);
    }break;
    case LBN_DBLCLK: SendMessage(Wnd,WM_COMMAND,IDOK,0);
   }break;
   case IDOK: {
    scheduler.addtask(user_jumptoaddr,priority_userrequest,t->addr,NULL);
   }break;
  }break;
  
  case WM_DESTROY: {
   for (i=0;i<dta->numlistitems();i++) {
    delete segt[dta->numlistitems()-i-1];
   }
   delete segt;
  }break;
 }
 return FALSE;
}

/************************************************************************
* segviewer								*
* - stops the secondary thread, and calls the dialog box for viewing	*
*   the segments, then restarts the thread when the dialog box is done. *
************************************************************************/
void segviewer(bool state) {

// scheduler.stopthread();
 MyCreateDialog(SegBox,Seg_Viewer,state?segbox:NULL);
// scheduler.continuethread();
}

/************************************************************************
* getcommentbox								*
* - this is the small dialog box for getting a comment from the user.	*
* - it determines the current address, and obtains a comment, adding it *
*   to the database, and deleting any previous comment.			*
************************************************************************/
BOOL CALLBACK getcommentbox(HWND Wnd,UINT Msg,WPARAM wParam,LPARAM) {
 static lptr loc;

 switch (Msg) {
  case WM_INITDIALOG: {
      // need to get any initial comments and stuff into edit box.
   dsmitem titem,*tblock;
   cvd->findcurrentaddr(&loc);
   titem.addr=loc;
   titem.type=dsmnull;
   dsm->findnext(&titem);
   tblock=dsm->nextiterator();
   if (tblock) while(tblock->addr==loc) {
    if(tblock->type==dsmcomment) {
     SetDlgItemText(Wnd,IDC_COMMENTEDIT,(LPSTR)tblock->tptr);
     break;
    }
    tblock=dsm->nextiterator();
    if (!tblock) break;
   }
  }return TRUE;

  case WM_COMMAND: switch (LOWORD(wParam)) {
   case IDOK: {
    char *newcomment;
    newcomment= new char[80];
    GetDlgItemText(Wnd,IDC_COMMENTEDIT,newcomment,80);
    scheduler.addtask(user_delcomment,priority_userrequest,loc,NULL);
    if (lstrlen((char *)newcomment))
      scheduler.addtask(user_addcomment,priority_userrequest,loc,newcomment);
   }nobreak;
   case IDCANCEL:  EndDialog(Wnd,wParam);
  }
 }
 return FALSE;
}

/************************************************************************
* getcomment								*
* - stops the thread and gets a comment from the user to be added to	*
*   the disassembly database, and posts a windowupdate request.		*
************************************************************************/
void getcomment(void) {

// scheduler.stopthread();
 DialogBox(hInst,MAKEINTRESOURCE(Comment_Editor),MainWnd,getcommentbox);
// scheduler.continuethread();
}
Detected encoding: ASCII (7 bit)2