📄 status.c
字号:
SetScrollPos(hWnd, SB_VERT, nVscrollPos, TRUE);
UpdateWindow(hWnd);
}
return 0;
case WM_HSCROLL: /* scroll bar action on list box */
switch (wParam)
{
case SB_TOP:
nHscrollInc = -nHscrollPos;
break;
case SB_BOTTOM:
nHscrollInc = nHscrollMax - nHscrollPos;
break;
case SB_LINEUP:
nHscrollInc = -1;
break;
case SB_LINEDOWN:
nHscrollInc = 1;
break;
case SB_PAGEUP:
nHscrollInc = -8;
break;
case SB_PAGEDOWN:
nHscrollInc = 8;
break;
case SB_THUMBPOSITION:
nHscrollInc = LOWORD(lParam) - nHscrollPos;
break;
default:
return DefWindowProc(hWnd, wMessage, wParam, lParam);
}
if (nHscrollInc = max(-nHscrollPos,
min(nHscrollInc, nHscrollMax - nHscrollPos)))
{
nHscrollPos += nHscrollInc;
ScrollWindow(hWnd, -dxChar * nHscrollInc, 0, NULL, NULL);
SetScrollPos(hWnd, SB_HORZ, nHscrollPos, TRUE);
}
return 0;
case WM_KEYDOWN:
bCntl = (BOOL)(GetKeyState(VK_CONTROL) < 0 ? TRUE : FALSE);
for (i = 0, pKE = KeyTable; i < NUMKEYS; i++, pKE++)
{
if ((wParam == pKE->wVirtKey) && (bCntl == pKE->bCntl))
{
SendMessage(hWnd, pKE->wMessage, pKE->wRequest, 0L);
break;
}
}
break;
case WM_PAINT:
if (!hStatusBuffer) /* if nothing to paint */
{
return DefWindowProc(hWnd, wMessage, wParam, lParam);
}
{
REGISTER LPSTR lpsz; /* current char */
LPSTR lpszNextLF; /* address of next '\n' in buffer */
LPSTR lpszStart; /* paint starting character */
LPSTR lpszLineCur; /* beginning of current line */
HANDLE hNew;
DWORD cchLine; /* length of current line */
short nLinesSinceLastEntry; /* lines since last entry */
DWORD dwSearchLen; /* length for _fmemchr() to search */
lpszStart = NULL; /* paint starting character */
lpStatusBuffer = GlobalLock(hStatusBuffer);
WinAssert(lpStatusBuffer); /* DEBUG */
hDC = BeginPaint(hWnd, &ps);
WinAssert(hDC); /* DEBUG */
hNew = SelectObject( hDC, hFixedFont);
WinAssert(hNew);
nPaintBeg = max(0, nVscrollPos+ps.rcPaint.top/dyChar -1);
nPaintEnd = min(nNumLines, nVscrollPos + ps.rcPaint.bottom/dyChar);
if (nPaintBeg >= nPaintEnd) /* if no painting to do ... */
{
EndPaint(hWnd, &ps);
GlobalUnlock(hStatusBuffer);
return 0;
}
if (!cMsgWinEntries) /* re-index whenever more data is added */
{
/* Round up to make lines_per_entry encompass all
* possible lines in buffer.
*/
nLinesPerEntry = (nNumLines+MAX_INDEX_ENTRIES-1) / MAX_INDEX_ENTRIES;
if (!nLinesPerEntry) /* if zero */
nLinesPerEntry++; /* set to 1 as minimum */
/* Count lines from beginning of buffer to:
* 1) mark beginning of paint sequence (lpszStart) and
* 2) periodically save buffer index in MsgWinIndex[] table.
*/
for (lpsz = lpStatusBuffer, i = 0, nLinesSinceLastEntry = 0;
(DWORD)(lpsz - lpStatusBuffer) < dwStatusSize ; i++)
{
/* We are at the 1st character position in the line */
if (i == nPaintBeg) /* Starting point for paint ? */
lpszStart = lpsz; /* If so, mark starting point */
/* Entry time ? */
if (!nLinesSinceLastEntry++ &&
cMsgWinEntries < MAX_INDEX_ENTRIES)
{
rgidwMsgWin[cMsgWinEntries] =
(DWORD)(lpsz - lpStatusBuffer); /* save index */
cMsgWinEntries++;
}
if (nLinesSinceLastEntry >= nLinesPerEntry)
nLinesSinceLastEntry = 0;
/* Use _fmemchr() to find next LF.
* It's probably optimized for searches.
*/
dwSearchLen = dwStatusSize -
(DWORD)(lpsz - lpStatusBuffer);
if ((lpszNextLF = _fmemchr(lpsz, '\n', (size_t)dwSearchLen)))
lpsz = ++lpszNextLF; /* use next char as beg of line */
else /* use lpsz with incremented value */
lpsz += dwSearchLen;
} /* bottom of still-counting-lines loop */
WinAssert(lpszStart);
lpsz = lpszStart; /* restore starting point */
WinAssert((DWORD)lpsz >= (DWORD)lpStatusBuffer &&
(DWORD)lpsz < (DWORD)&lpStatusBuffer[dwStatusSize]);
} /* bottom of need-to-build-index block */
else /* index is still valid */
{
short nIndexEntry;
/* Find index of line number which is equal to or just
* below the starting line to paint. Work backwards
* thru the table. Here, "i" is the line no. corresponding
* to the current table index.
*/
for (nIndexEntry = cMsgWinEntries - 1,
i = nIndexEntry * nLinesPerEntry;
nIndexEntry >= 0 &&
nPaintBeg < i ;
nIndexEntry--, i -= nLinesPerEntry )
{
;
}
WinAssert(nIndexEntry >= 0);
WinAssert(i <= nPaintBeg);
/* OK, we've got a head start on the search.
* Start checking characters from the position found
* in the index table.
*/
for (lpsz = &lpStatusBuffer[rgidwMsgWin[nIndexEntry]];
i < nPaintBeg &&
(DWORD)(lpsz - lpStatusBuffer) < dwStatusSize;
++i)
{
/* Find length of current line. Use _fmemchr() to
* find next LF.
*/
dwSearchLen = dwStatusSize -
(DWORD)(lpsz - lpStatusBuffer);
if ((lpszNextLF = _fmemchr(lpsz, '\n', (size_t)dwSearchLen)) != NULL)
lpsz = ++lpszNextLF; /* point to next char. past '\n' */
else /* If search fails, pretend LF exists, go past it. */
lpsz += dwSearchLen;
}
} /* bottom of index-is-still-valid block. */
/* At this point we've got the buffer address, lpsz, for the 1st
* line at which we begin painting, nPaintBeg.
*/
for (i = nPaintBeg;
(i < nPaintEnd) &&
((DWORD)(lpsz - lpStatusBuffer) >= 0L) &&
((DWORD)(lpsz - lpStatusBuffer) < dwStatusSize) ;
++i)
{
lpszLineCur = lpsz;
/* Find length of current line. Use _fmemchr() to find next LF.
*/
dwSearchLen = dwStatusSize - (DWORD)(lpsz - lpStatusBuffer);
if ((lpszNextLF = _fmemchr(lpsz, '\n', (size_t)dwSearchLen)) == NULL)
{
/* If search fails, pretend we found LF, we won't
* display it anyway.
*/
lpszNextLF = lpsz + dwSearchLen;
}
WinAssert((DWORD)lpszNextLF >= (DWORD)lpszLineCur); /* should be non-negative */
WinAssert((DWORD)lpszNextLF >= (DWORD)lpStatusBuffer && /* DEBUG */
(DWORD)lpszNextLF <= (DWORD)&lpStatusBuffer[dwStatusSize]);
x = dxChar * (1 - nHscrollPos);
y = dyChar * (1 - nVscrollPos + i);
cchLine = (DWORD)(lpszNextLF - lpszLineCur);/* calc length*/
/* don't display '\r' */
if (cchLine && lpszLineCur[cchLine-1] == '\r')
cchLine--;
/* may be displaying long lines if binary file */
if (cchLine > cchTextOutMax)
cchLine = cchTextOutMax;
TabbedTextOut(hDC, x, y, lpszLineCur, (int)cchLine, 0, NULL, 0);
lpsz = ++lpszNextLF; /* point to char. past '\n' */
}
EndPaint(hWnd, &ps);
GlobalUnlock(hStatusBuffer);
return 0;
}
break;
case WM_CLOSE:
DestroyWindow(hWnd);
break;
case WM_DESTROY:
FreeStatusLog();
break;
default:
return DefWindowProc(hWnd, wMessage, wParam, lParam);
}
return 0L;
}
/* Map CR to CRLF is called by the printf and fprintf clones below
* to guarantee that lines added to the Status window will be
* properly terminated DOS-style in case they are copied
* to the Windows clipboard.
* The converts the buffer in-place, provided it won't
* grow beyond the original buffer allocation.
*/
static void MapCRtoCRLF(PSTR pszOrigBuffer);
static void MapCRtoCRLF(PSTR pszOrigBuffer)
{
PSTR pC, pDest;
UINT cBufLen = 0; /* no. chars in buffer, including final null */
UINT cLFs = 0; /* no. LF's in string. \n is linefeed */
for (pC = pszOrigBuffer; *pC; pC++)
{
cBufLen++;
if (*pC == '\n') /* found a linefeed */
cLFs++;
}
cBufLen++; /* buffer length includes final null */
pC = &pszOrigBuffer[cBufLen-1]; /* point to old end's null char */
if (cBufLen + cLFs > STDIO_BUF_SIZE) /* room to add CR's ? */
return; /* if not, don't bother */
/* copy data back-to-front, effectively inserting CR before LF */
pDest = &pszOrigBuffer[cBufLen+cLFs-1]; /* point to new end */
for (; cBufLen; pC--, cBufLen--)
{
*pDest-- = *pC ; /* copy data byte */
if (*pC == '\n') /* was that a linefeed ? */
*pDest-- = '\r'; /* if so, insert CR */
}
}
/* Printf buffers the current output and counts the number of lines
* within it. It makes sure there is enough space in the global
* buffer, then copies the buffered data to the global buffer.
* It then triggers a repaint of the status buffer.
*/
int __far __cdecl printf(const char *format, ...)
{
va_list argptr;
HANDLE hMemory;
PSTR pszBuffer;
va_start(argptr, format);
hMemory = LocalAlloc(LMEM_MOVEABLE, STDIO_BUF_SIZE);
WinAssert(hMemory);
if (!hMemory)
{
return 0;
}
pszBuffer = (PSTR)LocalLock(hMemory);
WinAssert(pszBuffer);
vsprintf(pszBuffer, format, argptr);
va_end(argptr);
WinAssert(strlen(pszBuffer) < STDIO_BUF_SIZE); /* raise STDIO_BUF_SIZE ? */
MapCRtoCRLF(pszBuffer); /* map CR's to CRLF's */
WriteStringToMsgWin(pszBuffer, bRealTimeMsgUpdate);
LocalUnlock(hMemory);
LocalFree(hMemory);
return 0;
}
/* fprintf clone for code in unzip.c, etc. */
int __far __cdecl fprintf(FILE *file, const char *format, ...)
{
va_list argptr;
HANDLE hMemory;
PSTR pszBuffer;
va_start(argptr, format);
hMemory = LocalAlloc(LMEM_MOVEABLE, STDIO_BUF_SIZE);
WinAssert(hMemory);
if (!hMemory)
{
return 0;
}
pszBuffer = (PSTR)LocalLock(hMemory);
WinAssert(pszBuffer);
vsprintf(pszBuffer, format, argptr);
va_end(argptr);
WinAssert(strlen(pszBuffer) < STDIO_BUF_SIZE); /* raise STDIO_BUF_SIZE ? */
MapCRtoCRLF(pszBuffer); /* map CR's to CRLF's */
WriteStringToMsgWin(pszBuffer, bRealTimeMsgUpdate);
LocalUnlock(hMemory);
LocalFree(hMemory);
}
void __far __cdecl perror(const char *parm1)
{
printf(parm1);
}
/* Copy contents of status window to clipboard. Called on receipt of IDM_COPY message.
*/
void CopyStatusToClipboard(HWND hWnd)
{
HANDLE hGlobalMemory; /* memory handles */
LPSTR lpGlobalMemory, lpStatusBuffer ; /* memory pointers */
DWORD dwTextSize = dwStatusSize;
if (dwTextSize > 0x10000 - 2)
dwTextSize = 0x10000 - 2;
if (!(hGlobalMemory = GlobalAlloc(GHND, dwTextSize+1L)))
{
MessageBox (hWnd, szCantClipboard,
"Error", MB_ICONEXCLAMATION | MB_OK);
}
else /* Got it! */
{
lpGlobalMemory = GlobalLock(hGlobalMemory);
assert(lpGlobalMemory); /* DEBUG */
lpStatusBuffer = GlobalLock(hStatusBuffer);
assert(lpStatusBuffer); /* DEBUG */
_fmemcpy((void __far *)lpGlobalMemory, (void __far *)lpStatusBuffer, (size_t)dwTextSize);
lpGlobalMemory[dwTextSize] = '\0'; /* CF_TEXT requires null */
GlobalUnlock(hStatusBuffer); /* unlock status buffer */
GlobalUnlock(hGlobalMemory);
OpenClipboard(hWnd);
EmptyClipboard();
SetClipboardData(CF_TEXT, hGlobalMemory);
CloseClipboard();
}
}
/* Returns TRUE if Status window has anything in it; i.e. is non-clear.
*/
BOOL StatusInWindow(void)
{
return((BOOL)dwStatusSize);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -