///////////////////////////////////////////////////////////////////////////////////////// // // Copyright (c) 1998 Active Voice Corporation. All Rights Reserved. // // Active Agent(r) and Unified Communications(tm) are trademarks of Active Voice Corporation. // // Other brand and product names used herein are trademarks of their respective owners. // // The entire program and user interface including the structure, sequence, selection, // and arrangement of the dialog, the exclusively "yes" and "no" choices represented // by "1" and "2," and each dialog message are protected by copyrights registered in // the United States and by international treaties. // // Protected by one or more of the following United States patents: 5,070,526, 5,488,650, // 5,434,906, 5,581,604, 5,533,102, 5,568,540, 5,625,676, 5,651,054. // // Active Voice Corporation // Seattle, Washington // USA // ///////////////////////////////////////////////////////////////////////////////////////// //// // roedit.c - read-only edit control functions //// #include "winlocal.h" #include "roedit.h" #include "mem.h" #include "str.h" #include "trace.h" //// // private definitions //// // roedit control struct // typedef struct ROEDIT { WNDPROC lpfnEditWndProc; DWORD dwFlags; } ROEDIT, FAR *LPROEDIT; // helper functions // LRESULT DLLEXPORT CALLBACK ROEditWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); static int ROEditHighlightWord(HWND hwndEdit); //// // public functions //// // ROEditInit - initialize read-only subclass from edit control // (i) edit control to be subclassed // (i) subclass flags // ROEDIT_FOCUS allow control to get focus // ROEDIT_MOUSE allow control to process mouse messages // ROEDIT_COPY allow text to be copied to clipboard // ROEDIT_SELECT allow user to select any text with mouse // ROEDIT_SELECTWORD allow user to select words with mouse // return 0 if success // int DLLEXPORT WINAPI ROEditInit(HWND hwndEdit, DWORD dwFlags) { BOOL fSuccess = TRUE; WNDPROC lpfnROEditWndProc; HGLOBAL hROEdit; LPROEDIT lpROEdit; // copying text to the clipboard requires selecting text // if ((dwFlags & ROEDIT_COPY) && !(dwFlags & ROEDIT_SELECT) && !(dwFlags & ROEDIT_SELECTWORD)) { dwFlags |= ROEDIT_SELECT; } // selecting text requires both getting focus and mouse usage // if ((dwFlags & ROEDIT_SELECT) || (dwFlags & ROEDIT_SELECTWORD)) { dwFlags |= ROEDIT_FOCUS; dwFlags |= ROEDIT_MOUSE; } if (hwndEdit == NULL) fSuccess = TraceFALSE(NULL); // get pointer to read-only subclass window proc // else if ((lpfnROEditWndProc = (WNDPROC) MakeProcInstance((FARPROC) ROEditWndProc, (HINSTANCE) GetWindowWordPtr(GetParent(hwndEdit), GWWP_HINSTANCE))) == NULL) fSuccess = TraceFALSE(NULL); // memory is allocated such that the client app owns it // else if ((hROEdit = GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, sizeof(ROEDIT))) == NULL) fSuccess = TraceFALSE(NULL); else if ((lpROEdit = GlobalLock(hROEdit)) == NULL) fSuccess = TraceFALSE(NULL); // store old window proc address // else if ((lpROEdit->lpfnEditWndProc = (WNDPROC) GetWindowLongPtr(hwndEdit, GWLP_WNDPROC)) == NULL) fSuccess = TraceFALSE(NULL); // store flags // else if ((lpROEdit->dwFlags = dwFlags) != dwFlags) fSuccess = TraceFALSE(NULL); else if (GlobalUnlock(hROEdit), FALSE) ; // store old window proc address as a property of the control window // else if (!SetProp(hwndEdit, TEXT("hROEdit"), hROEdit)) fSuccess = TraceFALSE(NULL); // replace old window proc with new window proc // else if ( !SetWindowLongPtr(hwndEdit, GWLP_WNDPROC, (LONG_PTR) lpfnROEditWndProc) ) fSuccess = TraceFALSE(NULL); return fSuccess ? 0 : -1; } // ROEditTerm - terminate read-only subclass from edit control // (i) subclassed edit control // return 0 if success // int DLLEXPORT WINAPI ROEditTerm(HWND hwndEdit) { BOOL fSuccess = TRUE; WNDPROC lpfnROEditWndProc; HGLOBAL hROEdit; LPROEDIT lpROEdit; if (hwndEdit == NULL) fSuccess = TraceFALSE(NULL); // get pointer to read-only subclass window proc // else if ((lpfnROEditWndProc = (WNDPROC) GetWindowLongPtr(hwndEdit, GWLP_WNDPROC)) == NULL) fSuccess = TraceFALSE(NULL); // retrieve old window proc address from window property // else if ((hROEdit = GetProp(hwndEdit, TEXT("hROEdit"))) == NULL) fSuccess = TraceFALSE(NULL); else if ((lpROEdit = GlobalLock(hROEdit)) == NULL || lpROEdit->lpfnEditWndProc == NULL) fSuccess = TraceFALSE(NULL); // replace new window proc with old window proc // else if ( !SetWindowLongPtr(hwndEdit, GWLP_WNDPROC, (LONG_PTR) lpROEdit->lpfnEditWndProc) ) fSuccess = TraceFALSE(NULL); else if (GlobalUnlock(hROEdit), FALSE) ; // // else if (( hROEdit = RemoveProp(hwndEdit, TEXT("hROEdit"))) == NULL) fSuccess = TraceFALSE(NULL); else if (GlobalFree(hROEdit) != NULL) fSuccess = TraceFALSE(NULL); return fSuccess ? 0 : -1; } //// // helper functions //// // ROEditWndProc - window procedure for read-only edit control // LRESULT CALLBACK EXPORT ROEditWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { BOOL fSuccess = TRUE; LRESULT lResult; HGLOBAL hROEdit; LPROEDIT lpROEdit; // // we should verify the hwnd argument // if( NULL == hwnd ) { return 0L; } // retrieve old window proc address from window property // if ((hROEdit = GetProp(hwnd, TEXT("hROEdit"))) == NULL) fSuccess = TraceFALSE(NULL); else if ((lpROEdit = GlobalLock(hROEdit)) == NULL || lpROEdit->lpfnEditWndProc == NULL) fSuccess = TraceFALSE(NULL); switch (msg) { // ignore all keyboard messages // case WM_KEYUP: case WM_KEYDOWN: case WM_CHAR: lResult = 1L; break; // ignore clipboard messages which modify control text // case WM_CUT: case WM_PASTE: lResult = 1L; break; // ignore clipboard copy command // unless ROEDIT_COPY flag set // case WM_COPY: if (fSuccess && lpROEdit->dwFlags & ROEDIT_COPY) lResult = CallWindowProc(lpROEdit->lpfnEditWndProc, hwnd, msg, wParam, lParam); else lResult = 1L; break; // ignore all mouse messages // unless ROEDIT_MOUSE flag set // case WM_LBUTTONUP: case WM_LBUTTONDOWN: case WM_LBUTTONDBLCLK: if (fSuccess && lpROEdit->dwFlags & ROEDIT_MOUSE) lResult = CallWindowProc(lpROEdit->lpfnEditWndProc, hwnd, msg, wParam, lParam); else lResult = 1L; break; // do not allow the edit control to get the focus // unless ROEDIT_FOCUS flag set // case WM_GETDLGCODE: if (fSuccess && lpROEdit->dwFlags & ROEDIT_FOCUS) lResult = CallWindowProc(lpROEdit->lpfnEditWndProc, hwnd, msg, wParam, lParam); else lResult = 0L; break; default: { // call old window proc // if (fSuccess) lResult = CallWindowProc(lpROEdit->lpfnEditWndProc, hwnd, msg, wParam, lParam); else lResult = 0L; } break; } // highlight current word after mouse button up // if ROEDIT_SELECTWORD flag is set // if (fSuccess && (lpROEdit->dwFlags & ROEDIT_SELECTWORD)) if (msg == WM_LBUTTONUP) ROEditHighlightWord(hwnd); if (fSuccess) GlobalUnlock(hROEdit); return lResult; } // ROEditHighlightWord - select current word within edit control // (i) edit control window handle // return 0 if success // static int ROEditHighlightWord(HWND hwndEdit) { BOOL fSuccess = TRUE; DWORD dwSel = Edit_GetSel(hwndEdit); WORD wStart = LOWORD(dwSel); WORD wStop = HIWORD(dwSel); LPTSTR lpszText = NULL; int sizText; LPTSTR lpsz; if (hwndEdit == NULL) fSuccess = TraceFALSE(NULL); else if ((sizText = Edit_GetTextLength(hwndEdit)) <= 0) fSuccess = TraceFALSE(NULL); else if ((lpszText = (LPTSTR) MemAlloc(NULL, (sizText + 1) * sizeof(TCHAR), 0)) == NULL) fSuccess = TraceFALSE(NULL); else if (Edit_GetText(hwndEdit, lpszText, sizText + 1) != sizText) fSuccess = TraceFALSE(NULL); else { // adjust wStart to point to start of word // lpsz = lpszText + wStart; while (lpsz > lpszText && ChrIsWordDelimiter(*lpsz)) lpsz = StrPrevChr(lpszText, lpsz), --wStart; while (lpsz > lpszText && !ChrIsWordDelimiter(*lpsz)) lpsz = StrPrevChr(lpszText, lpsz), --wStart; if (lpsz > lpszText) lpsz = StrNextChr(lpsz), ++wStart; // adjust wStop to point to end of word // wStop = wStart; lpsz = lpszText + wStop; while (*lpsz != '\0' && !ChrIsWordDelimiter(*lpsz)) lpsz = StrNextChr(lpsz), ++wStop; while (*lpsz != '\0' && ChrIsWordDelimiter(*lpsz)) lpsz = StrNextChr(lpsz), ++wStop; // select the word // Edit_SetSel(hwndEdit, wStart, wStop); } if (lpszText != NULL && (lpszText = MemFree(NULL, lpszText)) != NULL) fSuccess = TraceFALSE(NULL); return fSuccess ? 0 : -1; }