📄 windiff.c
字号:
/* search the view for this line nr */
total = view_getrowcount(current_view);
for (i = 0; i < total; i++) {
if (bIsLeft) {
if (linenr == view_getlinenr_right(current_view, i)) {
/* found it */
SetSelection(i);
return(TRUE);
}
} else {
if (linenr == view_getlinenr_left(current_view, i)) {
SetSelection(i);
return(TRUE);
}
}
}
return(FALSE);
}
/***************************************************************************
* Function: do_editfile
*
* Purpose:
*
* Launch an editor on the current file (the file we are expanding, or
* in outline mode the selected row. Option allows selection of the
* left file, the right file or the composite view of this item.
* pe points to a packet of parameters that must be freed before returning.
* The return value is meaningless (just to conform to CreateThread).
*/
LONG
do_editfile(PEDITARGS pe)
{
VIEW view = pe->view;
int option = pe->option;
int selection = pe->selection;
COMPITEM item;
LPSTR fname;
char cmdline[256];
int currentline;
char * pOut = cmdline;
char * pIn = editor_cmdline;
STARTUPINFO si;
PROCESS_INFORMATION pi;
item = view_getitem(view, selection);
if (item == NULL) {
return -1;
}
fname = compitem_getfilename(item, option);
if ( 0 == fname )
{
windiff_UI(TRUE);
MessageBox(hwndClient, LoadRcString(IDS_FILE_DOESNT_EXIST),
"Windiff", MB_ICONSTOP|MB_OK);
windiff_UI(FALSE);
goto error;
}
switch ( option )
{
case CI_LEFT:
currentline = view_getlinenr_left( view,
selection > 0 ? selection : 1);
break;
case CI_RIGHT:
currentline = view_getlinenr_right( view,
selection > 0 ? selection : 1);
break;
default:
currentline = 1;
break;
}
while( *pIn )
{
switch( *pIn )
{
case '%':
pIn++;
switch ( *pIn )
{
case 'p':
lstrcpy( (LPTSTR)pOut, fname );
while ( *pOut )
pOut++;
break;
case 'l':
_ltoa( currentline, pOut, 10 );
while ( *pOut )
pOut++;
break;
default:
if (IsDBCSLeadByte(*pIn) && *(pIn+1)) {
*pOut++ = *pIn++;
}
*pOut++ = *pIn;
break;
}
pIn++;
break;
default:
if (IsDBCSLeadByte(*pIn) && *(pIn+1)) {
*pOut++ = *pIn++;
}
*pOut++ = *pIn++;
break;
}
}
/* Launch the process and waits for it to complete */
si.cb = sizeof(STARTUPINFO);
si.lpReserved = NULL;
si.lpReserved2 = NULL;
si.cbReserved2 = 0;
si.lpTitle = (LPSTR)cmdline;
si.lpDesktop = (LPTSTR)NULL;
si.dwFlags = STARTF_FORCEONFEEDBACK;
if (!CreateProcess(NULL,
cmdline,
NULL,
NULL,
FALSE,
NORMAL_PRIORITY_CLASS,
NULL,
(LPTSTR)NULL,
&si,
&pi)) {
windiff_UI(TRUE);
MessageBox(hwndClient, LoadRcString(IDS_FAILED_TO_LAUNCH_EDT),
"Windiff", MB_ICONSTOP|MB_OK);
windiff_UI(FALSE);
goto error;
}
/* wait for completion. */
WaitForSingleObject(pi.hProcess, INFINITE);
/* close process and thread handles */
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
/* finished with the filename. deletes it if it was a temp. */
compitem_freefilename(item, option, fname);
/*
* refresh cached view always . A common trick is to edit the
* composite file and then save it as a new left or right file.
* Equally the user can edit the left and save as a new right.
*/
/* We want to force both files to be re-read, but it's not a terribly
* good idea to throw the lines away on this thread. Someone might
* be reading them on another thread!
*/
/* file_discardlines(compitem_getleftfile(item)) */
/* file_discardlines(compitem_getrightfile(item)) */
/* force the compare to be re-done */
PostMessage(hwndClient, WM_COMMAND, IDM_UPDATE, (LONG)item);
error:
gmem_free(hHeap, (LPSTR) pe, sizeof(EDITARGS));
return 0;
} /* do_editfile */
/***************************************************************************
* Function: do_editthread
*
* Purpose:
*
* Launch an editor on a separate thread. It will actually get a separate
* process, but we want our own thread in this process. This thread will
* wait until it's finished and then order up a refresh of the UI.
* Need to give it its parameters as a gmem allocated packet because
* it IS on a separate thread.
*/
void do_editthread(VIEW view, int option)
{
PEDITARGS pe;
HANDLE thread;
DWORD threadid;
pe = (PEDITARGS) gmem_get(hHeap, sizeof(EDITARGS));
pe->view = view;
pe->option = option;
pe->selection = selection;
thread = CreateThread( NULL
, 0
, (LPTHREAD_START_ROUTINE)do_editfile
, (LPVOID) pe
, 0
, &threadid
);
if (thread == NULL)
{
/* The createthread failed, do without the extra thread - just
* call the function synchronously
*/
do_editfile(pe);
}
else CloseHandle(thread);
} /* do_editthread */
/* status bar and busy flags --------------------------------------------*/
/***************************************************************************
* Function: SetButtonText
*
* Purpose:
*
* Set the Text on the statusbar button to reflect the current state
*/
void
SetButtonText(LPSTR cmd)
{
SendMessage(hwndStatus, SM_SETTEXT, IDM_ABORT, (DWORD) cmd);
}
/***************************************************************************
* Function: SetStatus
*
* Purpose:
*
* Set the status field (left-hand part) of the status bar.
*/
void
SetStatus(LPSTR cmd)
{
SendMessage(hwndStatus, SM_SETTEXT, IDL_STATLAB, (DWORD) cmd);
}
/***************************************************************************
* Function: SetNames
*
* Purpose:
*
* Set the names field - the central box in the status bar
*/
void
SetNames(LPSTR names)
{
SendMessage(hwndStatus, SM_SETTEXT, IDL_NAMES, (DWORD) names);
if (names == NULL) {
AppTitle[0] = '\0';
} else {
strncpy(AppTitle, names, sizeof(AppTitle));
}
}
/***************************************************************************
* Function: SetBusy
*
* Purpose:
*
* If we are not already busy, set the busy flag.
*
* Enter critical section first.
*/
BOOL
SetBusy(void)
{
HMENU hmenu;
WDEnter();
if (fBusy) {
WDLeave();
return(FALSE);
}
fBusy = TRUE;
SetStatus(LoadRcString(IDS_COMPARING));
/* status also on window text, so that you can see even from
* the icon when the scan has finished
*/
SetWindowText(hwndClient, LoadRcString(IDS_SCANNING));
/* disable appropriate parts of menu */
hmenu = GetMenu(hwndClient);
EnableMenuItem(hmenu, IDM_FILE,MF_DISABLED|MF_GRAYED|MF_BYCOMMAND);
EnableMenuItem(hmenu, IDM_DIR,MF_DISABLED|MF_GRAYED|MF_BYCOMMAND);
EnableMenuItem(hmenu, IDM_PRINT,MF_DISABLED|MF_GRAYED|MF_BYCOMMAND);
/* enable abort only when busy */
EnableMenuItem(hmenu, IDM_ABORT,MF_ENABLED|MF_BYCOMMAND);
SetButtonText(LoadRcString(IDS_ABORT)); /* leave DisplayMode unchanged */
WDLeave();
return(TRUE);
} /* SetBusy */
/***************************************************************************
* Function: SetNotBusy
*
* Purpose:
*
* This function can be called from the worker thread.
* Thus we must not cause any SendMessage calls to windows
* owned by the main thread while holding the CritSec or we
* could cause deadlock.
*
* The critsec is only needed to protect the fBusy flag - so
* clear the busy flag last, and only get the crit sec as needed.
*/
void
SetNotBusy(void)
{
HMENU hmenu;
/* reset button and status bar (clearing out busy flags) */
if (current_view == NULL) {
SetButtonText(LoadRcString(IDS_EXIT));
SetStatus(NULL);
DisplayMode = MODE_NULL;
} else if (view_isexpanded(current_view)) {
TCHAR szBuf[10];
lstrcpy(szBuf,LoadRcString(IDS_OUTLINE));
SetButtonText(szBuf);
SetStatus(view_getcurrenttag(current_view) );
DisplayMode = MODE_EXPAND;
} else {
TCHAR szBuf[8];
lstrcpy(szBuf,LoadRcString(IDS_EXPAND));
SetButtonText(szBuf);
SetStatus(NULL);
DisplayMode = MODE_OUTLINE;
}
SetWindowText(hwndClient, "WinDiff");
/* re-enable appropriate parts of menu */
hmenu = GetMenu(hwndClient);
EnableMenuItem(hmenu, IDM_FILE,MF_ENABLED|MF_BYCOMMAND);
EnableMenuItem(hmenu, IDM_DIR,MF_ENABLED|MF_BYCOMMAND);
EnableMenuItem(hmenu, IDM_PRINT,MF_ENABLED|MF_BYCOMMAND);
/* disable abort now no longer busy */
EnableMenuItem(hmenu, IDM_ABORT,MF_DISABLED|MF_GRAYED|MF_BYCOMMAND);
/* clear the busy flag, protected by critical section */
WDEnter();
fBusy = FALSE;
bAbort = FALSE;
if (ghThread!=NULL){
CloseHandle(ghThread);
ghThread = NULL;
}
WDLeave();
} /* SetNotBusy */
/***************************************************************************
* Function: IsBusy
*
* Purpose:
*
* Checks whether or not crit sec is open
*/
BOOL
IsBusy()
{
BOOL bOK;
WDEnter();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -