Windows2000/private/windbg64/windbg/paneuser.c
2020-09-30 17:12:32 +02:00

1634 lines
37 KiB
C

/*++
Copyright (c) 1992 Microsoft Corporation
Module Name:
paneuser.c
Abstract:
This module contains the code for handling the keyboard and mouse
for the panel manager windows.
Author:
William J. Heaton (v-willhe) 25-Nov-1992
Griffith Wm. Kadnier (v-griffk) 10-Mar-1993
Environment:
Win32, User Mode
--*/
#include "precomp.h"
#pragma hdrstop
void PaneClearEdit( PPANE p);
void PaneDeleteChar( PPANE p, SHORT Idx);
void PaneEditMode( PPANE p);
void PaneInsertChar( PPANE p, CHAR wParam );
void PaneCopyClipBoard( PPANE p );
void PanePasteClipBoard( PPANE p );
void PaneSetPos( PPANE p, SHORT NewPos);
void PaneSetPosXY( HWND hWnd, int X, int Y, BOOL Select);
void PaneSelectWord( PPANE p );
void PaneCutSelection( PPANE p );
extern LRESULT SendMessageNZ (HWND,UINT,WPARAM,LPARAM);
extern void CheckHorizontalScroll (PPANE p);
BOOL inMouseMove=FALSE;
/*** PaneKeyboardHandler
** Synopsis:
** VOID PaneKeyboardHandler( hWnd, msg, wParam, lParam)
** Entry:
** Standard WNDPROC
** Returns:
** Standard WNDPROC
** Description:
** The Standard Keyboard Handler for all of the Panemanager Panes.
*/
#define PAGE (p->PaneLines-1)
void
PaneKeyboardHandler(
HWND hWnd,
UINT message,
WPARAM wParam,
LPARAM lParam
)
{
PPANE p = (PPANE)GetWindowLongPtr(GetParent(hWnd), GWW_EDIT );
BOOL isShiftDown;
BOOL isCtrlDown;
if (IsIconic(GetParent(hWnd))) {
return;
}
if ((message == WM_KEYDOWN) && ((wParam == VK_CONTROL) || (wParam == VK_SHIFT))) {
return; // don't care if it is just the ctrl/shift key
}
isShiftDown = (GetKeyState(VK_SHIFT) < 0);
isCtrlDown = (GetKeyState(VK_CONTROL) < 0);
switch (message) {
case WM_COPY:
PaneCopyClipBoard( p );
break;
case WM_PASTE:
PanePasteClipBoard( p );
break;
case WM_MOUSEMOVE:
if ( wParam & MK_LBUTTON ) {
inMouseMove = TRUE;
PaneSetPosXY( hWnd, LOWORD(lParam), HIWORD(lParam), TRUE );
inMouseMove = FALSE;
}
break;
case WM_LBUTTONDOWN:
PaneSetPosXY( hWnd, LOWORD(lParam), HIWORD(lParam), FALSE );
break;
case WM_LBUTTONDBLCLK:
if ( p->hWndFocus != p->hWndButton ) {
PaneSelectWord( p );
}
break;
case WM_RBUTTONDOWN:
if (p->SelLen) {
PaneCopyClipBoard( p );
} else {
PanePasteClipBoard( p );
}
return;
case WM_CHAR:
switch(wParam) {
// Handled by WM_KEYDOWN
case TAB:
case CTRL_H:
case CTRL_M:
case ESCAPE:
break;
case CTRL_C:
PostMessage(hwndFrame, WM_COMMAND, MAKEWPARAM(IDM_EDIT_COPY, 1), 0);
break;
case CTRL_V:
PostMessage(hwndFrame, WM_COMMAND, MAKEWPARAM(IDM_EDIT_PASTE, 1), 0);
break;
case CTRL_X:
PostMessage(hwndFrame, WM_COMMAND, MAKEWPARAM(IDM_EDIT_CUT, 1), 0);
break;
default:
if ( p->hWndFocus != p->hWndButton && wParam >= ' ') {
PaneInsertChar(p, (CHAR)wParam );
} else {
MessageBeep(0);
}
}
break;
case WM_KEYDOWN:
if (hWnd != p->hWndButton) {
MSG msg;
// if text has been highlighted, a cut may be necessary
// in preparing for an insert
if (p->SelLen != 0 &&
PeekMessage(&msg, hWnd, WM_KEYDOWN, WM_CHAR, PM_NOREMOVE)) {
if (msg.message == WM_CHAR) {
switch (msg.wParam) {
// there will not be any insert for these four cases
case TAB:
case CTRL_C:
case CTRL_H:
case CTRL_M:
case ESCAPE:
break;
default:
if (msg.wParam >= ' ') {
PaneCutSelection(p);
p->SelLen = 0;
return;
}
}
}
}
// removes any highlighting if necessary
// except the following key combinations:
// DELETE, BACKSPACE
// Ctrl+Insert
// Shift+(Ctrl)+Left/Right Arrow
// Shift+Home/End Key
if (wParam != VK_DELETE &&
wParam != VK_BACK &&
!(isCtrlDown && ('C' == wParam || VK_INSERT == wParam)) &&
!(isShiftDown &&
(wParam == VK_LEFT || wParam == VK_RIGHT ||
(!isCtrlDown && (wParam == VK_HOME || wParam == VK_END)))
)
) {
POINT cPos;
GetCaretPos (&cPos);
PaneSetPosXY( hWnd, (WORD)cPos.x, (WORD)cPos.y, FALSE);
}
}
switch ( wParam ) {
case VK_DELETE:
case VK_BACK:
if (p->SelLen != 0) {
PaneCutSelection(p);
p->SelLen = 0;
} else if (wParam == VK_BACK) {
PaneDeleteChar(p, (SHORT)(p->CurPos-1)); // backspace
} else {
PaneDeleteChar(p, (SHORT)p->CurPos);
}
break;
case VK_LEFT:
case VK_RIGHT:
if (isShiftDown) {
POINT cPos;
if (p->SelLen == 0) {
p->SelPos = p->CurPos;
}
PaneSetPos(p,(SHORT)(p->CurPos+((wParam == VK_LEFT)?-1:1)));
GetCaretPos (&cPos);
PaneSetPosXY( hWnd, (WORD)cPos.x, (WORD)cPos.y, TRUE );
} else {
PaneSetPos(p,(SHORT)(p->CurPos+((wParam == VK_LEFT)?-1:1)));
}
break;
case VK_UP:
case VK_DOWN:
PaneInvalidateCurrent(p->hWndFocus, p, -1);
PaneSetIdx(p,(SHORT)(p->CurIdx + ((wParam == VK_UP) ?-1:1)));
if (isShiftDown) {
POINT cPos;
GetCaretPos (&cPos);
PaneSetPosXY( hWnd, (WORD)cPos.x, (WORD)cPos.y, FALSE);
}
p->SelLen = 0;
p->SelPos = 0;
PaneCaretNum(p);
break;
case VK_PRIOR:
case VK_NEXT:
PaneSetIdx(p,(SHORT)(p->CurIdx+((wParam == VK_PRIOR) ?-PAGE:PAGE)));
if (isShiftDown) {
POINT cPos;
GetCaretPos (&cPos);
PaneSetPosXY( hWnd, (WORD)cPos.x, (WORD)cPos.y, FALSE );
}
p->SelLen = 0;
p->SelPos = 0;
PaneCaretNum(p);
break;
case VK_HOME:
case VK_END:
{
SHORT tmp;
POINT cPos;
tmp = (wParam == VK_HOME) ? 0 : 0x7fff; // first or last
if (isCtrlDown) {
PaneSetIdx(p, (SHORT)tmp);
} else if (isShiftDown) {
if (p->SelLen == 0) {
p->SelPos = p->CurPos;
}
PaneSetPos(p, (SHORT)tmp);
GetCaretPos (&cPos);
PaneSetPosXY( hWnd, (WORD)cPos.x, (WORD)cPos.y, TRUE);
} else {
PaneSetPos(p, (SHORT)tmp);
p->SelLen = p->SelPos = 0; // why?
}
PaneCaretNum(p);
}
break;
case VK_TAB:
PaneSwitchFocus(p, NULL, (BOOL)(((GetKeyState (VK_SHIFT) >= 0)) ? FALSE : TRUE));
break;
case VK_INSERT:
if (isShiftDown) {
PanePasteClipBoard( p );
} else if (isCtrlDown) {
PaneCopyClipBoard( p );
} else {
PaneEditMode(p);
}
break;
case VK_ESCAPE:
PaneClearEdit(p);
break;
case VK_RETURN:
if (p->nCtrlId == ID_PANE_BUTTON) {
(*p->fnEditProc)(p->hWndFocus, WU_EXPANDWATCH, (WPARAM)p->CurIdx, (LPARAM)p);
CheckHorizontalScroll (p);
} else {
PaneCloseEdit(p);
}
break;
default:
break;
}
break;
default:
DAssert(FALSE);
}
} /* PaneKeyboardHandler() */
/*** PaneCopyClipBoard
** Synopsis:
** void PaneCopyClipBoard( PPANE p);
** Entry:
** p - pointer to Pane Information Strucure
** Returns:
** None
** Description:
** Copy the current selection (If any to the clipboard)
*/
void
PaneCopyClipBoard(
PPANE p
)
{
PSTR pBuf = NULL;
int nLen = 0;
PANEINFO Info = {0,0,0,0,NULL};
HANDLE hData;
LPSTR pData;
LPSTR pSrc;
if ( p->SelLen != 0 ) {
if ( p->Edit ) {
pBuf = p->EditBuf;
} else {
Info.CtrlId = p->nCtrlId;
Info.ItemId = p->CurIdx;
(PSTR)(*p->fnEditProc)(p->hWndFocus,WU_INFO,(WPARAM)&Info,(LPARAM)p);
pBuf = Info.pBuffer;
}
if ( p->SelLen > 0 ) {
pSrc = pBuf + p->SelPos;
nLen = p->SelLen;
} else {
pSrc = pBuf + p->SelPos + p->SelLen;
nLen = -(p->SelLen);
}
Dbg(hData = GlobalAlloc (GMEM_MOVEABLE|GMEM_DDESHARE, nLen + 1));
if ( hData ) {
Dbg((pData = (PSTR) GlobalLock( hData )) != NULL);
if ( pData ) {
while ( nLen-- ) {
*pData++ = *pSrc++;
}
*pData = '\0';
DbgX(GlobalUnlock(hData) == 0);
if (OpenClipboard (hwndFrame)) {
EmptyClipboard();
SetClipboardData(CF_TEXT, hData);
CloseClipboard();
p->SelLen = 0;
}
}
}
}
} /* PaneCopyClipBoard() */
/*** PanePasteClipBoard
** Synopsis:
** void PanePasteClipBoard( PPANE p);
** Entry:
** p - pointer to Pane Information Strucure
** Returns:
** None
** Description:
** Copy the clipboard to the current pane item
*/
void
PanePasteClipBoard(
PPANE p
)
{
HANDLE hData;
size_t size;
LPSTR p1;
LPSTR pData;
if ( !p->ReadOnly ) {
if (OpenClipboard(hwndFrame)) {
hData = GetClipboardData(CF_TEXT);
if (hData && (size = GlobalSize (hData))) {
if (size >= MAX_CLIPBOARD_SIZE) {
ErrorBox(ERR_Clipboard_Overflow);
} else if ( pData = (PSTR) GlobalLock(hData) ) {
p1 = pData;
while (size && *p1) {
size--;
if (*p1 == '\r' || *p1 == '\n') {
break;
}
PaneInsertChar(p, (CHAR)*p1 );
p1++;
}
DbgX(GlobalUnlock (hData) == FALSE);
}
CloseClipboard();
}
}
}
} /* PanePasteClipBoard() */
/*** PaneCutSelection
** Synopsis:
** void PaneCutSelection( PPANE p);
** Entry:
** p - pointer to Pane Information Strucure
** Returns:
** None
** Description:
** Cut the current selection (delete)
*/
void
PaneCutSelection(
PPANE p
)
{
PSTR pBuf = NULL;
int nLen = 0;
PANEINFO Info = {0,0,0,0,NULL};
SHORT Indx;
if ( p->SelLen != 0 ) {
if ( p->Edit ) {
pBuf = p->EditBuf;
} else {
Info.CtrlId = p->nCtrlId;
Info.ItemId = p->CurIdx;
(PSTR)(*p->fnEditProc)(p->hWndFocus,WU_INFO,(WPARAM)&Info,(LPARAM)p);
pBuf = Info.pBuffer;
}
if ( p->SelLen > 0 ) {
Indx = p->SelPos;
nLen = p->SelLen;
} else {
Indx = p->CurPos;
nLen = -(p->SelLen);
}
while ( nLen-- ) {
PaneDeleteChar(p, Indx);
}
}
} /* PaneCutSelection() */
/*** PaneSetPos
** Synopsis:
** void PaneSetPos( PPANE p, SHORT NewPos);
** Entry:
** p - pointer to Pane Information Strucure
** NewPos - The index of the position to set on the current pane item
** Returns:
** None
** Description:
** This routine is used to set the x coordinate on a pane item
*/
void
PaneSetPos(
PPANE p,
SHORT NewPosArg
)
{
SIZE Size = { 0, 0 };
PANEINFO Info = {0,0,0,0,NULL};
RECT Rect = {0,0,0,0};
PSTR pBuf = NULL;
int nLen = 0;
HDC hDC = 0;
int NewPos = NewPosArg;
if ( p->nCtrlId == ID_PANE_BUTTON ) {
InvertButton( p );
} else {
// Figure out which buffer we're using and it's max
if ( p->Edit ) {
pBuf = &p->EditBuf[0];
nLen = p->CurLen;
} else {
Info.CtrlId = p->nCtrlId;
Info.ItemId = p->CurIdx;
(PSTR)(*p->fnEditProc)(p->hWndFocus,WU_INFO,(WPARAM)&Info,(LPARAM)p);
pBuf = Info.pBuffer;
if ( pBuf ) {
nLen = strlen(pBuf);
}
}
if(NewPos > p->CurPos) { /* move right */
if(IsDBCSLeadByte((BYTE)*(pBuf + p->CurPos))) {
NewPos++;
}
}
else if(NewPos < p->CurPos) { /* move left */
if(IsDBCSLeadByte((BYTE)(*CharPrev(pBuf, pBuf + p->CurPos)))) {
NewPos--;
}
}
// If the New position is out of range, put it back in range
if ( NewPos < 0 ) {
NewPos = 0;
}
if ( NewPos > nLen ) {
NewPos = nLen;
}
p->CurPos = (WORD) NewPos;
// Figure out the offset to the new caret
if ( NewPos <= 0) {
Size.cx = 0;
} else {
hDC = GetDC(p->hWndFocus);
SelectObject(hDC, p->hFont);
GetTextExtentPoint(hDC, pBuf, NewPos, &Size);
ReleaseDC(p->hWndFocus,hDC);
}
PaneSetCaret(p, Size.cx, TRUE);
}
// Set the Status Bar
SetLineColumn_StatusBar(p->CurIdx+1, p->CurPos+1);
} /* PaneSetPos() */
/*** PaneSetPosXY
** Synopsis:
** void PaneSetPosXY( HWND hWnd, int X, int Y, BOOL Select)
** Entry:
** hWnd - The Window
** x - The X coordinate
** y - The Y coordinate
** Select -
** Returns:
** None
** Description:
*/
void
PaneSetPosXY(
HWND hWnd,
int X,
int Y,
BOOL Select
)
{
PPANE p = (PPANE)GetWindowLongPtr(GetParent(hWnd), GWW_EDIT );
SHORT NewIdx;
SHORT NewPos;
PSTR pBuf = NULL;
int nLen = 0;
int Offset = 0;
PANEINFO Info = {0,0,0,0,NULL};
HDC hDC = 0;
BOOL isShiftDown = (GetKeyState(VK_SHIFT) < 0);
SIZE Size;
POINT point;
// Calculate what index the mouse hit was on, If we're selecting
// we ignore anything off our pane and/or index
if ( hWnd != p->hWndButton) {
HideCaret(hWnd);
}
NewIdx = p->TopIdx + Y/p->LineHeight;
if ( Select ) {
if ( hWnd != p->hWndFocus || NewIdx != p->CurIdx ) {
if ( hWnd != p->hWndButton) {
ShowCaret(hWnd);
}
return;
}
}
// Dialog boxes (quickwatch) can't select
if (( p->Type == QUICKW_WIN) || (!isShiftDown && !inMouseMove)) {
Select = FALSE;
}
// Switch pane if necessary
if ( hWnd != p->hWndFocus ) {
PaneSwitchFocus(p, hWnd, FALSE);
Select = FALSE;
// Buttons are special, Expand/Contract the item and get out
if ( hWnd == p->hWndButton) {
p->CurIdx = NewIdx;
(*p->fnEditProc)(p->hWndFocus, WU_EXPANDWATCH, (WPARAM)NewIdx, (LPARAM)p);
CheckHorizontalScroll (p);
return;
}
}
if ( NewIdx < p->MaxIdx ) {
// Calculate new position
if ( NewIdx == p->CurIdx && p->Edit ) {
pBuf = &p->EditBuf[0];
nLen = p->CurLen;
} else {
Info.CtrlId = p->nCtrlId;
Info.ItemId = NewIdx;
(PSTR)(*p->fnEditProc)( p->hWndFocus,
WU_INFO,
(WPARAM)&Info,
(LPARAM)p);
if ( pBuf = Info.pBuffer ) {
nLen = strlen(pBuf);
}
}
if ( p->nCtrlId == ID_PANE_BUTTON) {
(*p->fnEditProc)(p->hWndFocus,
WU_EXPANDWATCH,
(WPARAM)NewIdx,
(LPARAM)p);
if ( p->ScrollBarUp ) {
SetScrollRange(p->hWndScroll, SB_CTL, 0, p->MaxIdx - 1, FALSE);
SetScrollPos( p->hWndScroll, SB_CTL, (INT)p->CurIdx, FALSE);
}
ShowScrollBar( p->hWndScroll, SB_CTL, p->ScrollBarUp);
if (!p->ScrollBarUp) {
p->TopIdx = 0; //reset top if no scrolling
}
SyncPanes(p,(WORD)-1);
CheckHorizontalScroll (p);
}
if ( pBuf ) {
NewPos = -1;
if (p->nCtrlId == ID_PANE_LEFT) {
Offset = p->nXoffLeft;
} else if (p->nCtrlId == ID_PANE_RIGHT) {
Offset = p->nXoffRight;
}
X += Offset;
hDC = GetDC(p->hWndFocus);
SelectObject(hDC, p->hFont);
GetTextExtentPoint(hDC, pBuf, 1, &Size);
ReleaseDC(p->hWndFocus,hDC);
if (X < Size.cx) {
NewPos = 0;
} else {
hDC = GetDC(p->hWndFocus);
SelectObject(hDC, p->hFont);
do {
if(NewPos >=0 && IsDBCSLeadByte((BYTE)*(pBuf+NewPos)))
NewPos++;
NewPos++;
GetTextExtentPoint(hDC, pBuf, NewPos, &Size);
} while (Size.cx < X);
ReleaseDC(p->hWndFocus,hDC);
}
if ( NewPos > nLen ) {
NewPos = (SHORT) nLen;
}
if ( p->CurIdx != NewIdx ) {
Select = FALSE;
p->SelLen = 0;
PaneInvalidateCurrent( p->hWndFocus, p, -1);
PaneSetIdx( p, NewIdx );
}
if ( Select ) {
p->SelLen = NewPos - p->SelPos;
} else {
p->SelPos = NewPos;
p->SelLen = 0;
}
p->CurPos = NewPos;
PaneSetPos( p, NewPos );
PaneInvalidateCurrent( p->hWndFocus, p, -1);
} else {
NewPos = 0;
PaneInvalidateCurrent( p->hWndFocus, p, -1);
PaneSetPos( p, NewPos );
PaneSetIdx( p, NewIdx );
}
}
if ( hWnd != p->hWndButton) {
GetCaretPos(&point);
p->X = point.x;
p->Y = point.y;
ShowCaret(hWnd);
}
} /* PaneSetPosXY() */
/*** PaneSelectWord
** Synopsis:
** void PaneSelectWord( PPANE p );
** Entry:
** p - pointer to Pane Information Strucure
** Returns:
** None
** Description:
** Selects the word around the current selection point
*/
void
PaneSelectWord(
PPANE p
)
{
WORD Start = p->CurPos;
WORD End = p->CurPos;
PSTR pBuf = NULL;
int nLen = 0;
PANEINFO Info = {0,0,0,0,NULL};
if ( p->Edit ) {
pBuf = p->EditBuf;
nLen = p->CurLen;
} else {
Info.CtrlId = p->nCtrlId;
Info.ItemId = p->CurIdx;
(PSTR)(*p->fnEditProc)(p->hWndFocus,WU_INFO,(WPARAM)&Info,(LPARAM)p);
pBuf = Info.pBuffer;
if ( pBuf ) {
nLen = strlen(pBuf);
}
}
if ( pBuf && pBuf[Start] != ' ' && pBuf[Start] != '\t' ) {
if(!IsDBCSLeadByte((BYTE)pBuf[Start])) {
while ( Start > 0 && pBuf[Start] != ' ' && pBuf[Start] != '\t' ) {
Start--;
}
if ( pBuf[Start] == ' ' || pBuf[Start] == '\t' ) {
Start++;
}
}
while ( End < nLen
&& pBuf[End]
&& pBuf[End] != ' '
&& pBuf[End] != '\t' ) {
if(IsDBCSLeadByte((BYTE)pBuf[End])) {
End++;
break;
}
End++;
}
if ( pBuf[End] == ' ' || pBuf[End] == '\t' || !pBuf[End] ) {
End--;
}
p->SelPos = Start;
p->SelLen = End - Start + 1;
PaneInvalidateCurrent( p->hWndFocus, p, -1);
}
} /* PaneSelectWord */
/*** PaneSetIdx
** Synopsis:
** void PaneSetIdx( PPANE p, SHORT NewIdx);
** Entry:
** p - pointer to Pane Information Strucure
** NewIdx - The index (Line) to set the current pane item to.
** Returns:
** None
** Description:
** This routine is used to set the y coordinate on a pane item
*/
void
PaneSetIdx(
PPANE p,
SHORT NewIdx
)
{
// If we're in edit mode and can't close edit, bail out.
if ( !PaneCloseEdit(p) ) {
PaneClearEdit(p);
}
PaneResetIdx(p, NewIdx);
} /* PaneSetIdx */
/*** PaneResetIdx
** Synopsis:
** void PaneResetIdx( PPANE p, SHORT NewIdx);
** Entry:
** p - pointer to Pane Information Strucure
** NewIdx - The index (Line) to set the current pane item to.
** Returns:
** None
** Description:
** This routine is used to set the y coordinate on a pane item
*/
void
PaneResetIdx(
PPANE p,
SHORT NewIdx
)
{
PANEINFO Info = {0,0,0,0,NULL};
if ( p->nCtrlId == ID_PANE_BUTTON ) {
PaneInvalidateCurrent( p->hWndFocus, p, -1);
}
// If the New index is out of range, put it back in range
if ( NewIdx < 0 ) {
NewIdx = 0;
}
if ( (WORD)NewIdx > p->MaxIdx-1) {
NewIdx = (SHORT)p->MaxIdx-1;
}
p->CurIdx = (WORD)NewIdx;
SyncPanes(p, (WORD)-1);
if ( p->nCtrlId != ID_PANE_BUTTON ) {
PaneSetPos(p, 0);
} else {
InvertButton(p);
}
// Set the Status Bar
Info.CtrlId = p->nCtrlId;
Info.ItemId = p->CurIdx;
(PSTR)(*p->fnEditProc)(p->hWndFocus,WU_INFO,(WPARAM)&Info,(LPARAM)p);
p->ReadOnly = Info.ReadOnly;
SetLineColumn_StatusBar(p->CurIdx+1, p->CurPos+1);
} /* PaneResetIdx */
/*** PaneSetCaret
** Synopsis:
** void PaneSetCaret( PPANE p, LONG cx, BOOL Scroll);
** Entry:
** p - pointer to Pane Information Strucure
** cx - The pixel address of where the caret should be
** Scroll - Scroll the pane to show the insertion point
** Returns:
** None
** Description:
** Set the caret (if in view) on the current pane item
*/
void
PaneSetCaret(
PPANE p,
LONG cx,
BOOL Scroll
)
{
RECT Rect = {0,0,0,0};
RECT cRect = {0,0,0,0};
LONG Offset;
LONG PerCent;
LONG Max;
HWND hFoc;
POINT point;
double dMax, dCx;
if (p->CurIdx > p->MaxIdx) {
return; //window is empty or bad indx
}
if (p->hWndFocus) {
SendMessage( p->hWndFocus, LB_GETITEMRECT, (WPARAM)p->CurIdx, (LPARAM)&Rect);
GetClientRect( p->hWndFocus, &cRect);
Offset = Rect.right - cRect.right;
} else
Offset = 0;
if (p->nCtrlId == ID_PANE_LEFT) {
p->nXoffLeft = Offset;
} else if (p->nCtrlId == ID_PANE_RIGHT) {
p->nXoffRight = Offset;
}
p->nCaretPos = cx;
if ((hFoc = GetFocus ()) == p->hWndFocus) {
HideCaret (p->hWndFocus);
}
if (p->CurPos == 0) {
PaneInvalidateItem( p->hWndFocus, p, p->CurIdx);
}
// Is the caret in range?
if ((p->nCaretPos < Offset || p->nCaretPos > (Rect.right -1))
&& ((hFoc = GetFocus ()) == p->hWndFocus)) {
if (!Scroll) {
ShowCaret(p->hWndFocus);
GetCaretPos(&point);
p->X = point.x;
return;
} else {
// Note: Listbox scrollbars are a percentage 1-100
Max = (long) (SendMessage( p->hWndFocus, LB_GETHORIZONTALEXTENT, 0,0))
- p->CharWidth;
DestroyCaret();
CreateCaret( p->hWndFocus, 0, 3, p->LineHeight);
SetCaretPos(cx - Offset, Rect.top);
GetCaretPos(&point);
p->X = point.x;
ShowCaret(p->hWndFocus);
if (Max != 0) {
dMax = (double) Max;
dCx = (double) cx;
PerCent = ((long)((dCx /dMax) * 100.0));
SendMessage( p->hWndFocus,
WM_HSCROLL,
MAKELONG(SB_THUMBPOSITION,PerCent),
0);
}
SendMessage( p->hWndFocus, LB_GETITEMRECT, (WPARAM)p->CurIdx, (LPARAM)&Rect);
GetClientRect( p->hWndFocus, &cRect);
Offset = Rect.right - cRect.right;
if (p->nCtrlId == ID_PANE_LEFT) {
p->nXoffLeft = Offset;
} else if (p->nCtrlId == ID_PANE_RIGHT) {
p->nXoffRight = Offset;
}
PaneInvalidateItem( p->hWndFocus, p, p->CurIdx);
return;
}
}
if ((hFoc = GetFocus ()) == p->hWndFocus) {
SetCaretPos(cx - Offset, Rect.top);
GetCaretPos(&point);
p->X = point.x;
ShowCaret(p->hWndFocus);
}
}
/* PaneSetCaret() */
/*** PaneCaretNum
** Synopsis:
** int PaneCaretNum( PPANE p);
** Entry:
** p - pointer to Pane Information Strucure
** Returns:
** Number of Items visible
*/
int
PaneCaretNum(
PPANE p
)
{
RECT Rect = {0,0,0,0};
RECT tRect = {0,0,0,0};
RECT cRect = {0,0,0,0};
const RECT zeroRect = {0,0,0,0};
int nNum = 0, nMin, nMax, nScrollPos;
HWND hPane;
BOOL fRedo = TRUE;
LRESULT rst;
GetScrollRange (p->hWndScroll,SB_CTL,&nMin, &nMax);
do {
hPane = (p->hWndFocus != p->hWndButton) ?
p->hWndFocus
:p->hWndLeft;
rst = SendMessageNZ(hPane,
LB_GETITEMRECT,
(WPARAM)p->CurIdx,
(LPARAM)&Rect);
if (rst == LB_ERR) {
return 0;
}
rst = SendMessageNZ(hPane,
LB_GETITEMRECT,
(WPARAM)p->TopIdx,
(LPARAM)&tRect);
if (rst == LB_ERR) {
return 0;
}
nScrollPos = GetScrollPos (p->hWndScroll,SB_CTL);
// Is the caret in range?
if (hPane != NULL) {
int nRct;
GetClientRect(hPane, &cRect);
nRct = (cRect.bottom - cRect.top);
if ((Rect.bottom - Rect.top) > nRct) {
nNum = 0;
} else if ((Rect.bottom - Rect.top) != 0) {
nNum = (nRct / (Rect.bottom - Rect.top));
} else {
nNum = 0;
}
}
if ((Rect.bottom > cRect.bottom)
&& (p->CurIdx < p->MaxIdx)
&& (nNum > 0)) {
ScrollPanes (p,
MAKEWPARAM (SB_THUMBTRACK,(p->CurIdx - PAGE)),
0);
} else if ((Rect.top < tRect.top)
&& (p->CurIdx != 0xFFFF)
&& (nNum > 0)) {
ScrollPanes (p,
MAKEWPARAM (SB_THUMBTRACK,p->CurIdx),
0);
} else {
fRedo = FALSE;
}
} while (fRedo == TRUE);
return(nNum);
}
/* PaneCaretNum() */
/*** PaneDeleteChar
** Synopsis:
** void PaneDeleteChar( PPANE p, SHORT Idx);
** Entry:
** p - pointer to Pane Information Strucure
** Idx - The index of the character to delete
** Returns:
** None
** Description:
** Deletes the character at the specified index from the current
** pane item.
*/
void
PaneDeleteChar(
PPANE p,
SHORT Idx
)
{
RECT Rect = {0,0,0,0};
PANEINFO Info = {0,0,0,0,NULL};
PSTR pBuf = NULL;
int nLen = 0;
// Can't delete on a readonly panel (Catchs Button Pane too!)
if ( p->ReadOnly ) {
MessageBeep(0);
return;
}
// Get the Buffer Information
if ( p->Edit ) {
pBuf = &p->EditBuf[0];
nLen = p->CurLen;
}
else {
Info.CtrlId = p->nCtrlId;
Info.ItemId = p->CurIdx;
(PSTR)(*p->fnEditProc)(p->hWndFocus,WU_INFO,(WPARAM)&Info,(LPARAM)p);
pBuf = Info.pBuffer;
if ( pBuf) {
nLen = strlen(pBuf);
}
}
// If the New position is out of range, we can't delete
if ( nLen == 0 || Idx < 0 || Idx > nLen-1) {
MessageBeep(0);
return;
}
// If no Edit open, Start it up
if ( !p->Edit ) {
strcpy(p->EditBuf,pBuf);
p->CurLen = (WORD) nLen;
p->Edit = TRUE;
}
// Let do the Delete
if ( Idx < p->CurLen ) { // If not at end, shift the string over
memmove( &p->EditBuf[Idx],
&p->EditBuf[Idx+1], p->CurLen - Idx);
}
p->CurLen--; // One Less char to worry about
p->EditBuf[p->CurLen] = 0; // But make sure it goes away
PaneInvalidateCurrent( p->hWndFocus, p, Idx);
} /* PaneDeleteChar() */
/*** PaneInsertChar
** Synopsis:
** void PaneDeleteChar( PPANE p, CHAR c);
** Entry:
** p - pointer to Pane Information Strucure
** c - The character to be inserted.
** Returns:
** None
** Description:
** Insert the character passed into the buffer at the current
** insert point.
*/
void
PaneInsertChar(
PPANE p,
CHAR c
)
{
PANEINFO Info = {0,0,0,0,NULL};
// Can't insert on Readonly Pane (Catches Buttons too!)
// Don't Insert into null at end of buffer
if ( p->ReadOnly || p->CurPos == EDITMAX-1) {
MessageBeep(0);
return;
}
// If no Edit open, Start it up
if ( !p->Edit ) {
Info.CtrlId = p->nCtrlId;
Info.ItemId = p->CurIdx;
(PSTR)(*p->fnEditProc)(p->hWndFocus,WU_INFO,(WPARAM)&Info,(LPARAM)p);
if ( Info.pBuffer) {
strcpy(p->EditBuf,Info.pBuffer);
p->CurLen = strlen(p->EditBuf);
}
p->Edit = TRUE;
}
// OverStrike Mode
if ( p->OverType ) {
if ( p->EditBuf[p->CurPos] == 0) {
p->CurLen++;
}
p->EditBuf[p->CurPos] = c;
}
// Insert Mode
else {
// Insert at end of line is a no brainer
if ( p->EditBuf[p->CurPos] == 0) {
p->CurLen++;
p->EditBuf[p->CurPos] = c;
}
// Insert into the Middle
else {
memmove( &p->EditBuf[p->CurPos+1], &p->EditBuf[p->CurPos], p->CurLen - p->CurPos);
p->EditBuf[p->CurPos] = c;
p->CurLen++;
}
}
// Repaint the Line
PaneInvalidateCurrent( p->hWndFocus, p,(SHORT)(p->CurPos+1));
} /* PaneInsertChar() */
/*** PaneEditMode
** Synopsis:
** void PaneEditMode( PPANE p)
** Entry:
** p - The Pane info for the window
** Returns:
** None
** Description:
** Set insert/overstrike mode.
*/
void
PaneEditMode(
PPANE p
)
{
p->OverType = !p->OverType;
SetOverType_StatusBar(p->OverType);
} /* PaneEditMode */
/*** PaneClearEdit
** Synopsis:
** void PaneClearEdit( PPANE p)
** Entry:
** p - The Pane info for the window
** Returns:
** None
** Description:
** Aborts the current edit and repaints the item
*/
void
PaneClearEdit(
PPANE p
)
{
p->Edit = FALSE;
p->CurLen = 0;
memset(p->EditBuf,0,EDITMAX);
PaneInvalidateCurrent( p->hWndFocus, p, 0);
} /* PaneClearEdit */
/*** PaneCloseEdit
** Synopsis:
** BOOL PaneCloseEdit( PPANE p)
** Entry:
** p - The Pane info for the window
** Returns:
** None
** Description:
** Attempts to close the edit and update the item.
*/
BOOL
PaneCloseEdit(
PPANE p
)
{
// If no Edit open, we're done
if ( !p->Edit ) {
PaneInvalidateCurrent( p->hWndRight, p, -1);
return(TRUE);
}
if ( (*p->fnEditProc)(p->hWndFocus, WU_SETWATCH, 0, (LPARAM)p) ) {
PaneClearEdit(p);
return(TRUE);
}
PaneClearEdit(p);
MessageBeep(0);
return(FALSE);
} /* PaneCloseEdit */
/*** PaneInvalidateRow
** Synopsis:
** void PaneInvalidateRow(PPANE p)
** Entry:
** p - The Pane info for the window
** Returns:
** None
** Description:
** Invalidate all panes on the current index.
*/
void
PaneInvalidateRow(
PPANE p
)
{
PaneInvalidateCurrent( p->hWndButton, p, -1);
PaneInvalidateCurrent( p->hWndLeft, p, -1);
PaneInvalidateCurrent( p->hWndRight, p, -1);
}
/*** PaneInvalidateCurrent
** Synopsis:
** void PaneInvalidateCurrent( HWND hWnd, PPANE p, SHORT pos)
** Entry:
** hWnd - The handle to the current window
** p - The Pane info for the window
** pos - A optional position to set the caret to
** Returns:
** None
** Description:
** Invalidate the current item that has the focus causing it to be
** repainted
*/
void
PaneInvalidateCurrent(
HWND hWnd,
PPANE p,
SHORT pos
)
{
PaneInvalidateItem( hWnd, p, p->CurIdx);
if ( pos >= 0) {
PaneSetPos(p,pos);
}
} /* PaneInvalidateCurrent */
/*** PaneInvalidateItem
** Synopsis:
** void PaneInvalidateItem( HWND hWnd, PPANE p, WORD Item)
** Entry:
** hWnd - The handle to the current window
** p - The Pane info for the window
** pos - Item number to invalidate
** Returns:
** None
** Description:
** Invalidate the a given item and cause it to be repainted
*/
void
PaneInvalidateItem(
HWND hWnd,
PPANE p,
SHORT item
)
{
RECT Rect;
if ( hWnd && p->PaneLines > 0 ) {
SendMessage( hWnd, LB_GETITEMRECT, (WPARAM)item, (LPARAM)&Rect);
InvalidateRect( hWnd, &Rect, TRUE);
}
} /* PaneInvalidateItem */
/*** PaneSwitchFocus
** Synopsis:
** PaneSwitchFocus(PPANE p, HWND hwnd, BOOL fPrev);
** Entry:
** p - Pointer to the Pane structure.
** hWnd - Handle to the New pane (NULL if we get to pick)
** Prev - flag to force a switch to reverse order
** Returns:
** None
** Description:
** Switchs to the next logical pane in the panemanager.
*/
void
PaneSwitchFocus(
PPANE p,
HWND hWnd,
BOOL fPrev
)
{
if ( !PaneCloseEdit(p) ) {
MessageBeep(0);
return;
}
// We're not selecting, need to lose the caret
// and are going to repaint the current item (Caret may
// have left junk on screen.
p->SelPos = 0;
p->SelLen = 0;
PaneInvalidateCurrent( p->hWndFocus, p, -1);
// If we got a hWnd to set use that one
if (hWnd != NULL) {
p->hWndFocus = hWnd;
}
else if (p->hWndFocus == NULL) { // If we don't have one, default to left pane
p->hWndFocus = p->hWndLeft;
}
// Other wise move to the right one
else if ( p->hWndFocus == p->hWndLeft ) {
if (fPrev == FALSE) {
p->hWndFocus = p->hWndRight;
} else {
p->hWndFocus = p->hWndButton;
}
}
else if ( p->hWndFocus == p->hWndRight) {
if (fPrev == FALSE) {
p->hWndFocus = p->hWndButton;
} else {
p->hWndFocus = p->hWndLeft;
}
}
else if ( p->hWndFocus == p->hWndButton) {
if (fPrev == FALSE) {
p->hWndFocus = p->hWndLeft;
} else {
p->hWndFocus = p->hWndRight;
}
}
else {
p->hWndFocus = p->hWndLeft;
}
// Make sure we have the right control number
if ( p->hWndFocus == p->hWndLeft ) {
p->nCtrlId = ID_PANE_LEFT;
} else if ( p->hWndFocus == p->hWndRight ) {
p->nCtrlId = ID_PANE_RIGHT;
} else {
p->nCtrlId = ID_PANE_BUTTON;
}
SetFocus(p->hWndFocus);
PaneResetIdx( p, p->CurIdx);
} /* PaneSwitch */