Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

347 lines
8.9 KiB

  1. /////////////////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright (c) 1998 Active Voice Corporation. All Rights Reserved.
  4. //
  5. // Active Agent(r) and Unified Communications(tm) are trademarks of Active Voice Corporation.
  6. //
  7. // Other brand and product names used herein are trademarks of their respective owners.
  8. //
  9. // The entire program and user interface including the structure, sequence, selection,
  10. // and arrangement of the dialog, the exclusively "yes" and "no" choices represented
  11. // by "1" and "2," and each dialog message are protected by copyrights registered in
  12. // the United States and by international treaties.
  13. //
  14. // Protected by one or more of the following United States patents: 5,070,526, 5,488,650,
  15. // 5,434,906, 5,581,604, 5,533,102, 5,568,540, 5,625,676, 5,651,054.
  16. //
  17. // Active Voice Corporation
  18. // Seattle, Washington
  19. // USA
  20. //
  21. /////////////////////////////////////////////////////////////////////////////////////////
  22. ////
  23. // roedit.c - read-only edit control functions
  24. ////
  25. #include "winlocal.h"
  26. #include "roedit.h"
  27. #include "mem.h"
  28. #include "str.h"
  29. #include "trace.h"
  30. ////
  31. // private definitions
  32. ////
  33. // roedit control struct
  34. //
  35. typedef struct ROEDIT
  36. {
  37. WNDPROC lpfnEditWndProc;
  38. DWORD dwFlags;
  39. } ROEDIT, FAR *LPROEDIT;
  40. // helper functions
  41. //
  42. LRESULT DLLEXPORT CALLBACK ROEditWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
  43. static int ROEditHighlightWord(HWND hwndEdit);
  44. ////
  45. // public functions
  46. ////
  47. // ROEditInit - initialize read-only subclass from edit control
  48. // <hwndEdit> (i) edit control to be subclassed
  49. // <dwFlags> (i) subclass flags
  50. // ROEDIT_FOCUS allow control to get focus
  51. // ROEDIT_MOUSE allow control to process mouse messages
  52. // ROEDIT_COPY allow text to be copied to clipboard
  53. // ROEDIT_SELECT allow user to select any text with mouse
  54. // ROEDIT_SELECTWORD allow user to select words with mouse
  55. // return 0 if success
  56. //
  57. int DLLEXPORT WINAPI ROEditInit(HWND hwndEdit, DWORD dwFlags)
  58. {
  59. BOOL fSuccess = TRUE;
  60. WNDPROC lpfnROEditWndProc;
  61. HGLOBAL hROEdit;
  62. LPROEDIT lpROEdit;
  63. // copying text to the clipboard requires selecting text
  64. //
  65. if ((dwFlags & ROEDIT_COPY) &&
  66. !(dwFlags & ROEDIT_SELECT) &&
  67. !(dwFlags & ROEDIT_SELECTWORD))
  68. {
  69. dwFlags |= ROEDIT_SELECT;
  70. }
  71. // selecting text requires both getting focus and mouse usage
  72. //
  73. if ((dwFlags & ROEDIT_SELECT) ||
  74. (dwFlags & ROEDIT_SELECTWORD))
  75. {
  76. dwFlags |= ROEDIT_FOCUS;
  77. dwFlags |= ROEDIT_MOUSE;
  78. }
  79. if (hwndEdit == NULL)
  80. fSuccess = TraceFALSE(NULL);
  81. // get pointer to read-only subclass window proc
  82. //
  83. else if ((lpfnROEditWndProc =
  84. (WNDPROC) MakeProcInstance((FARPROC) ROEditWndProc,
  85. (HINSTANCE) GetWindowWordPtr(GetParent(hwndEdit), GWWP_HINSTANCE))) == NULL)
  86. fSuccess = TraceFALSE(NULL);
  87. // memory is allocated such that the client app owns it
  88. //
  89. else if ((hROEdit = GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT,
  90. sizeof(ROEDIT))) == NULL)
  91. fSuccess = TraceFALSE(NULL);
  92. else if ((lpROEdit = GlobalLock(hROEdit)) == NULL)
  93. fSuccess = TraceFALSE(NULL);
  94. // store old window proc address
  95. //
  96. else if ((lpROEdit->lpfnEditWndProc =
  97. (WNDPROC) GetWindowLongPtr(hwndEdit, GWLP_WNDPROC)) == NULL)
  98. fSuccess = TraceFALSE(NULL);
  99. // store flags
  100. //
  101. else if ((lpROEdit->dwFlags = dwFlags) != dwFlags)
  102. fSuccess = TraceFALSE(NULL);
  103. else if (GlobalUnlock(hROEdit), FALSE)
  104. ;
  105. // store old window proc address as a property of the control window
  106. //
  107. else if (!SetProp(hwndEdit, TEXT("hROEdit"), hROEdit))
  108. fSuccess = TraceFALSE(NULL);
  109. // replace old window proc with new window proc
  110. //
  111. else if ( !SetWindowLongPtr(hwndEdit, GWLP_WNDPROC, (LONG_PTR) lpfnROEditWndProc) )
  112. fSuccess = TraceFALSE(NULL);
  113. return fSuccess ? 0 : -1;
  114. }
  115. // ROEditTerm - terminate read-only subclass from edit control
  116. // <hwndEdit> (i) subclassed edit control
  117. // return 0 if success
  118. //
  119. int DLLEXPORT WINAPI ROEditTerm(HWND hwndEdit)
  120. {
  121. BOOL fSuccess = TRUE;
  122. WNDPROC lpfnROEditWndProc;
  123. HGLOBAL hROEdit;
  124. LPROEDIT lpROEdit;
  125. if (hwndEdit == NULL)
  126. fSuccess = TraceFALSE(NULL);
  127. // get pointer to read-only subclass window proc
  128. //
  129. else if ((lpfnROEditWndProc =
  130. (WNDPROC) GetWindowLongPtr(hwndEdit, GWLP_WNDPROC)) == NULL)
  131. fSuccess = TraceFALSE(NULL);
  132. // retrieve old window proc address from window property
  133. //
  134. else if ((hROEdit = GetProp(hwndEdit, TEXT("hROEdit"))) == NULL)
  135. fSuccess = TraceFALSE(NULL);
  136. else if ((lpROEdit = GlobalLock(hROEdit)) == NULL ||
  137. lpROEdit->lpfnEditWndProc == NULL)
  138. fSuccess = TraceFALSE(NULL);
  139. // replace new window proc with old window proc
  140. //
  141. else if ( !SetWindowLongPtr(hwndEdit, GWLP_WNDPROC, (LONG_PTR) lpROEdit->lpfnEditWndProc) )
  142. fSuccess = TraceFALSE(NULL);
  143. else if (GlobalUnlock(hROEdit), FALSE)
  144. ;
  145. //
  146. //
  147. else if (( hROEdit = RemoveProp(hwndEdit, TEXT("hROEdit"))) == NULL)
  148. fSuccess = TraceFALSE(NULL);
  149. else if (GlobalFree(hROEdit) != NULL)
  150. fSuccess = TraceFALSE(NULL);
  151. return fSuccess ? 0 : -1;
  152. }
  153. ////
  154. // helper functions
  155. ////
  156. // ROEditWndProc - window procedure for read-only edit control
  157. //
  158. LRESULT CALLBACK EXPORT ROEditWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
  159. {
  160. BOOL fSuccess = TRUE;
  161. LRESULT lResult;
  162. HGLOBAL hROEdit;
  163. LPROEDIT lpROEdit;
  164. //
  165. // we should verify the hwnd argument
  166. //
  167. if( NULL == hwnd )
  168. {
  169. return 0L;
  170. }
  171. // retrieve old window proc address from window property
  172. //
  173. if ((hROEdit = GetProp(hwnd, TEXT("hROEdit"))) == NULL)
  174. fSuccess = TraceFALSE(NULL);
  175. else if ((lpROEdit = GlobalLock(hROEdit)) == NULL ||
  176. lpROEdit->lpfnEditWndProc == NULL)
  177. fSuccess = TraceFALSE(NULL);
  178. switch (msg)
  179. {
  180. // ignore all keyboard messages
  181. //
  182. case WM_KEYUP:
  183. case WM_KEYDOWN:
  184. case WM_CHAR:
  185. lResult = 1L;
  186. break;
  187. // ignore clipboard messages which modify control text
  188. //
  189. case WM_CUT:
  190. case WM_PASTE:
  191. lResult = 1L;
  192. break;
  193. // ignore clipboard copy command
  194. // unless ROEDIT_COPY flag set
  195. //
  196. case WM_COPY:
  197. if (fSuccess && lpROEdit->dwFlags & ROEDIT_COPY)
  198. lResult = CallWindowProc(lpROEdit->lpfnEditWndProc, hwnd, msg, wParam, lParam);
  199. else
  200. lResult = 1L;
  201. break;
  202. // ignore all mouse messages
  203. // unless ROEDIT_MOUSE flag set
  204. //
  205. case WM_LBUTTONUP:
  206. case WM_LBUTTONDOWN:
  207. case WM_LBUTTONDBLCLK:
  208. if (fSuccess && lpROEdit->dwFlags & ROEDIT_MOUSE)
  209. lResult = CallWindowProc(lpROEdit->lpfnEditWndProc, hwnd, msg, wParam, lParam);
  210. else
  211. lResult = 1L;
  212. break;
  213. // do not allow the edit control to get the focus
  214. // unless ROEDIT_FOCUS flag set
  215. //
  216. case WM_GETDLGCODE:
  217. if (fSuccess && lpROEdit->dwFlags & ROEDIT_FOCUS)
  218. lResult = CallWindowProc(lpROEdit->lpfnEditWndProc, hwnd, msg, wParam, lParam);
  219. else
  220. lResult = 0L;
  221. break;
  222. default:
  223. {
  224. // call old window proc
  225. //
  226. if (fSuccess)
  227. lResult = CallWindowProc(lpROEdit->lpfnEditWndProc, hwnd, msg, wParam, lParam);
  228. else
  229. lResult = 0L;
  230. }
  231. break;
  232. }
  233. // highlight current word after mouse button up
  234. // if ROEDIT_SELECTWORD flag is set
  235. //
  236. if (fSuccess && (lpROEdit->dwFlags & ROEDIT_SELECTWORD))
  237. if (msg == WM_LBUTTONUP)
  238. ROEditHighlightWord(hwnd);
  239. if (fSuccess)
  240. GlobalUnlock(hROEdit);
  241. return lResult;
  242. }
  243. // ROEditHighlightWord - select current word within edit control
  244. // <hwndEdit> (i) edit control window handle
  245. // return 0 if success
  246. //
  247. static int ROEditHighlightWord(HWND hwndEdit)
  248. {
  249. BOOL fSuccess = TRUE;
  250. DWORD dwSel = Edit_GetSel(hwndEdit);
  251. WORD wStart = LOWORD(dwSel);
  252. WORD wStop = HIWORD(dwSel);
  253. LPTSTR lpszText = NULL;
  254. int sizText;
  255. LPTSTR lpsz;
  256. if (hwndEdit == NULL)
  257. fSuccess = TraceFALSE(NULL);
  258. else if ((sizText = Edit_GetTextLength(hwndEdit)) <= 0)
  259. fSuccess = TraceFALSE(NULL);
  260. else if ((lpszText = (LPTSTR) MemAlloc(NULL, (sizText + 1) * sizeof(TCHAR), 0)) == NULL)
  261. fSuccess = TraceFALSE(NULL);
  262. else if (Edit_GetText(hwndEdit, lpszText, sizText + 1) != sizText)
  263. fSuccess = TraceFALSE(NULL);
  264. else
  265. {
  266. // adjust wStart to point to start of word
  267. //
  268. lpsz = lpszText + wStart;
  269. while (lpsz > lpszText && ChrIsWordDelimiter(*lpsz))
  270. lpsz = StrPrevChr(lpszText, lpsz), --wStart;
  271. while (lpsz > lpszText && !ChrIsWordDelimiter(*lpsz))
  272. lpsz = StrPrevChr(lpszText, lpsz), --wStart;
  273. if (lpsz > lpszText)
  274. lpsz = StrNextChr(lpsz), ++wStart;
  275. // adjust wStop to point to end of word
  276. //
  277. wStop = wStart;
  278. lpsz = lpszText + wStop;
  279. while (*lpsz != '\0' && !ChrIsWordDelimiter(*lpsz))
  280. lpsz = StrNextChr(lpsz), ++wStop;
  281. while (*lpsz != '\0' && ChrIsWordDelimiter(*lpsz))
  282. lpsz = StrNextChr(lpsz), ++wStop;
  283. // select the word
  284. //
  285. Edit_SetSel(hwndEdit, wStart, wStop);
  286. }
  287. if (lpszText != NULL &&
  288. (lpszText = MemFree(NULL, lpszText)) != NULL)
  289. fSuccess = TraceFALSE(NULL);
  290. return fSuccess ? 0 : -1;
  291. }