Windows NT 4.0 source code leak
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.

1918 lines
39 KiB

4 years ago
  1. // Class Semantics for TextView windows
  2. // Created 5 August 1992 by Ron Murray
  3. #include "stdafx.h"
  4. #include "FTSrch.h"
  5. #include "TxDBase.h"
  6. #include "TextView.h"
  7. #include "usermsgs.h"
  8. #include "ftslex.h" //rmk
  9. #include "CSHelp.h"
  10. extern HINSTANCE hinstDLL;
  11. BOOL CTextView::RegisterWndClass(HINSTANCE hInstance)
  12. {
  13. PSZ szName = "TextViewer";
  14. WNDCLASS wndcls;
  15. // see if the class already exists
  16. if (::GetClassInfo(hInstance, szName, &wndcls)) return TRUE;
  17. // otherwise we need to register a new class
  18. wndcls.style = CS_DBLCLKS;
  19. wndcls.lpfnWndProc = &CTextView::WindowProc;
  20. wndcls.cbClsExtra = 0;
  21. wndcls.cbWndExtra = 4;
  22. wndcls.hInstance = hInstance;
  23. wndcls.hIcon = NULL;
  24. wndcls.hCursor = hcurArrow;
  25. wndcls.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1);
  26. wndcls.lpszMenuName = NULL;
  27. wndcls.lpszClassName = szName;
  28. return ::RegisterClass(&wndcls);
  29. }
  30. HWND CTextView::OpenWindow(PSZ pszWindowName, RECT *prc, HINSTANCE hinst, HWND hwndParent)
  31. {
  32. ASSERT(!m_hwnd);
  33. HWND hwnd= CreateWindow("TextViewer", pszWindowName, WS_CHILD | WS_TABSTOP | WS_VISIBLE,
  34. prc->left, prc->top, prc->right - prc->left, prc->bottom - prc->top,
  35. hwndParent, NULL, hinst, this
  36. );
  37. ASSERT(hwnd);
  38. m_hwnd= hwnd;
  39. return hwnd;
  40. }
  41. LRESULT CALLBACK CTextView::WindowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
  42. {
  43. CTextView *ptv= (CTextView *) GetWindowLong(hwnd, GWL_USERDATA);
  44. if (!ptv) return ::DefWindowProc(hwnd, msg, wparam, lparam);
  45. switch (msg)
  46. {
  47. case WM_HELP:
  48. case WM_CONTEXTMENU:
  49. return SendMessage(GetParent(hwnd), msg, wparam, lparam);
  50. case WM_GETDLGCODE:
  51. return DLGC_WANTARROWS;
  52. case WM_ERASEBKGND:
  53. return ptv->OnEraseBkgnd(HDC(wparam));
  54. case WM_PAINT:
  55. ptv->OnPaint(); return 0;
  56. case WM_SIZE:
  57. ptv->OnSize(wparam, LOWORD(lparam), HIWORD(lparam)); return 0;
  58. case WM_WINDOWPOSCHANGED:
  59. ptv->OnWindowPosChanged((WINDOWPOS *) lparam); return 0;
  60. case WM_SETFOCUS:
  61. ptv->OnSetFocus((HWND) wparam); return 0;
  62. case WM_KILLFOCUS:
  63. ptv->OnKillFocus((HWND) wparam); return 0;
  64. case WM_LBUTTONDOWN:
  65. ptv->OnLButtonDown(wparam, MAKEPOINTS(lparam)); return 0;
  66. case WM_LBUTTONDBLCLK:
  67. ptv->OnLButtonDblClk(wparam, MAKEPOINTS(lparam)); return 0;
  68. case WM_LBUTTONUP:
  69. ptv->OnLButtonUp(wparam, MAKEPOINTS(lparam)); return 0;
  70. case WM_MOUSEMOVE:
  71. ptv->OnMouseMove(wparam, MAKEPOINTS(lparam)); return 0;
  72. case WM_MOUSEACTIVATE:
  73. return ptv->OnMouseActivate((HWND) wparam, LOWORD(lparam), HIWORD(lparam));
  74. case WM_NCHITTEST:
  75. return ptv->OnNcHitTest(MAKEPOINTS(lparam));
  76. case WM_SETCURSOR:
  77. return ptv->OnSetCursor((HWND) wparam, LOWORD(lparam), HIWORD(lparam));
  78. case WM_TIMER:
  79. ptv->OnTimer(wparam); return 0;
  80. case WM_KEYDOWN:
  81. ptv->OnKeyDown(wparam, LOWORD(lparam), HIWORD(lparam)); return 0;
  82. case WM_KEYUP:
  83. ptv->OnKeyUp(wparam, LOWORD(lparam), HIWORD(lparam)); return 0;
  84. default:
  85. return ::DefWindowProc(hwnd, msg, wparam, lparam);
  86. }
  87. }
  88. // CTextView constructor:
  89. // Create the text view window with the appropriate style, size, menu, etc.
  90. CTextView::CTextView()
  91. {
  92. m_hwnd = NULL;
  93. m_ptdm = NULL;
  94. m_pbText = NULL;
  95. m_cbText = 0;
  96. m_fGotFocus = FALSE;
  97. m_fMouseCaptured = FALSE;
  98. m_fSwallowMouseActivate = FALSE;
  99. m_fMarquee = FALSE;
  100. m_fMarqueeActive = FALSE;
  101. m_fMarqueePhase = FALSE;
  102. m_fMarqueeTimerOn = FALSE;
  103. m_fTimerActive = FALSE;
  104. m_hTimer = 0;
  105. m_idTimer = 0;
  106. m_cImageFullRows = 0;
  107. m_cImageFullCols = 0;
  108. m_cImageRows = 0;
  109. m_cImageCols = 0;
  110. m_lTopLine = 0;
  111. m_iLeftCol = 0;
  112. m_nCxChar = 0;
  113. m_nCyChar = 0;
  114. m_clrfg = 0;
  115. m_clrbg = 0xFFFFFF;
  116. m_iCharsetAlternate = 0xFFFFFF;
  117. m_iCharset = 0;
  118. m_iHeight = 0;
  119. m_rowFocus = 0;
  120. m_colFocus = 0;
  121. m_cRowsFocus = 1;
  122. m_cColsFocus = 1;
  123. m_cHighlightsAllocated = 0;
  124. m_cHighlightsActive = 0;
  125. m_clFileRows = 0;
  126. m_clFileCols = 0;
  127. m_cLinesScrollContext = 0;
  128. m_cCharsets = 0;
  129. m_pHighlights = NULL;
  130. m_fpOldWndProc = NULL;
  131. m_pba = NULL;
  132. m_hFontDefault = NULL;
  133. m_hFontAlternate = NULL;
  134. m_hFont = NULL;
  135. m_pCharsets = NULL;
  136. m_hCheck = NULL;
  137. m_hNoCheck = NULL;
  138. m_iCheckHeight = 0;
  139. m_iCheckWidth = 0;
  140. m_bUseCheck = FALSE;
  141. m_pba = NULL;
  142. }
  143. CTextView *CTextView::NewTextView()
  144. {
  145. CTextView *ptv= NULL;
  146. __try
  147. {
  148. ptv= New CTextView;
  149. ptv->Init();
  150. }
  151. __finally
  152. {
  153. if (_abnormal_termination() && ptv)
  154. {
  155. delete ptv; ptv= NULL;
  156. }
  157. }
  158. return ptv;
  159. }
  160. CTextView *CTextView::NewTextView(PSZ pszWindowName, RECT *prc, HINSTANCE hinst, HWND hwndParent)
  161. {
  162. CTextView *ptv= NULL;
  163. __try
  164. {
  165. ptv= New CTextView;
  166. ptv->Init();
  167. ptv->OpenWindow(pszWindowName, prc, hinst, hwndParent);
  168. }
  169. __finally
  170. {
  171. if (_abnormal_termination() && ptv)
  172. {
  173. delete ptv; ptv= NULL;
  174. }
  175. }
  176. return ptv;
  177. }
  178. static UINT iCharsetDefault = UINT(-1);
  179. UINT DefaultCharacterSet()
  180. {
  181. if (iCharsetDefault != UINT(-1)) return iCharsetDefault;
  182. TEXTMETRIC tm;
  183. HDC hdc;
  184. iCharsetDefault= ANSI_CHARSET;
  185. hdc= GetDC(NULL);
  186. if (!hdc) return iCharsetDefault;
  187. if (GetTextMetrics(hdc, &tm))
  188. iCharsetDefault= tm.tmCharSet;
  189. return iCharsetDefault;
  190. }
  191. void CTextView::Init()
  192. {
  193. AttachRef(m_pba, New CByteVector);
  194. }
  195. // SetFont for drawing the list boxes
  196. void CTextView::SetFont(HFONT hFont)
  197. {
  198. ASSERT( hFont); // Dont call me with a bogus font please
  199. ASSERT(!m_hFont); // Must not have a font installed already
  200. m_hFont = hFont;
  201. HDC hdc= GetDC(m_hwnd);
  202. HGDIOBJ hsavFont= ::SelectObject(hdc, hFont);
  203. ::GetTextMetrics(hdc, &m_FontMetrics);
  204. ::SelectObject(hdc, hsavFont);
  205. m_nCxChar = m_FontMetrics.tmMaxCharWidth;
  206. m_nCyChar = m_FontMetrics.tmHeight + m_FontMetrics.tmExternalLeading;
  207. m_LeftMargin = m_nCxChar >> 1;
  208. RECT rc;
  209. GetWindowRect(m_hwnd, &rc);
  210. OnSize(SIZENORMAL, rc.right - rc.left, rc.bottom - rc.top);
  211. LOGFONT lf;
  212. ::GetObject(hFont, sizeof(lf), &lf);
  213. m_iCharset= lf.lfCharSet;
  214. ::ReleaseDC(m_hwnd, hdc);
  215. Invalidate();
  216. }
  217. // Release the drawing font and go back to the default font
  218. HGDIOBJ CTextView::ReleaseFont()
  219. {
  220. ASSERT(m_hFont); // Don't call me if the font has not be set first!
  221. HGDIOBJ hTemp = m_hFont;
  222. m_hFont = NULL;
  223. return hTemp;
  224. }
  225. CTextView *CTextView::NewTextView(CTextMatrix * ptdm)
  226. {
  227. CTextView *ptv= NULL;
  228. __try
  229. {
  230. ptv= New CTextView;
  231. ptv->Init(ptdm);
  232. }
  233. __finally
  234. {
  235. if (_abnormal_termination() && ptv)
  236. {
  237. delete ptv; ptv= NULL;
  238. }
  239. }
  240. return ptv;
  241. }
  242. void CTextView::Init(CTextMatrix * ptdm)
  243. {
  244. Init();
  245. if (ptdm)
  246. {
  247. AttachRef(m_ptdm, ptdm);
  248. ptdm->Connect(this);
  249. m_clFileRows= ptdm->RowCount();
  250. m_clFileCols= ptdm->ColCount();
  251. }
  252. m_cLinesScrollContext = 0;
  253. }
  254. CTextView *CTextView::NewTextView(CTextMatrix * ptdm, PSZ pszWindowName, RECT *prc, HINSTANCE hinst, HWND hwndParent)
  255. {
  256. CTextView *ptv= NULL;
  257. __try
  258. {
  259. ptv= New CTextView;
  260. ptv->Init(ptdm);
  261. ptv->OpenWindow(pszWindowName, prc, hinst, hwndParent);
  262. }
  263. __finally
  264. {
  265. if (_abnormal_termination() && ptv)
  266. {
  267. delete ptv; ptv= NULL;
  268. }
  269. }
  270. return ptv;
  271. }
  272. void CTextView::SetTextDatabase(CTextMatrix * ptdm)
  273. {
  274. if (m_ptdm)
  275. {
  276. m_ptdm->Disconnect(this);
  277. DetachRef(m_ptdm);
  278. if (m_cHighlightsAllocated)
  279. {
  280. m_cHighlightsAllocated = 0;
  281. m_cHighlightsActive = 0;
  282. delete [] m_pHighlights;
  283. m_pHighlights= NULL;
  284. }
  285. }
  286. if (ptdm)
  287. {
  288. AttachRef(m_ptdm, ptdm);
  289. ptdm->Connect(this);
  290. }
  291. if (ptdm)
  292. {
  293. m_clFileRows= ptdm->RowCount();
  294. m_clFileCols= ptdm->ColCount();
  295. FillBuff();
  296. }
  297. else
  298. {
  299. m_clFileRows= 0;
  300. m_clFileCols= 0;
  301. }
  302. InvalidateRect(m_hwnd, NULL, TRUE);
  303. }
  304. void CTextView::RawDataEvent(UINT uEventType)
  305. {
  306. BOOL fOriginChange = FALSE;
  307. BOOL fMarquee = m_fMarquee;
  308. BOOL fMarqueeActive = m_fMarqueeActive;
  309. switch(uEventType)
  310. {
  311. case CTextMatrix::SelectionChange:
  312. break;
  313. case CTextMatrix::FocusChange:
  314. if (fMarquee) RemoveMarquee();
  315. if (m_ptdm->GetFocusRect(&m_rowFocus , &m_colFocus,
  316. &m_cRowsFocus, &m_cColsFocus
  317. )
  318. )
  319. {
  320. ScrollTo(m_rowFocus, m_colFocus, 1, 1);
  321. if(m_fGotFocus) SetupMarquee();
  322. }
  323. if (m_fGotFocus)
  324. if (m_fMarqueeActive && !fMarqueeActive)
  325. {
  326. m_idTimer= ::SetTimer(m_hwnd, MARQUEE_TIMER_ID, MARQUEE_TIMER_SPAN, NULL);
  327. m_fMarqueeTimerOn= m_idTimer? TRUE : FALSE;
  328. }
  329. else
  330. if (fMarqueeActive && !m_fMarqueeActive) ::KillTimer(m_hwnd, m_idTimer);
  331. ::UpdateWindow(m_hwnd);
  332. break;
  333. case CTextMatrix::ShapeChange:
  334. m_clFileRows= m_ptdm->RowCount();
  335. m_clFileCols= m_ptdm->ColCount();
  336. MatchBuffToWindow();
  337. if (m_lTopLine && m_lTopLine > m_clFileRows - m_cImageFullRows - 1)
  338. {
  339. m_lTopLine = m_clFileRows - m_cImageFullRows - 1;
  340. if (m_lTopLine < 0) m_lTopLine= 0;
  341. fOriginChange= TRUE;
  342. }
  343. if (m_iLeftCol && m_iLeftCol > m_clFileCols - m_cImageFullCols - 1)
  344. {
  345. m_iLeftCol = m_clFileCols - m_cImageFullCols - 1;
  346. if (m_iLeftCol < 0) m_iLeftCol= 0;
  347. fOriginChange= TRUE;
  348. }
  349. m_fMarquee = FALSE;
  350. m_fMarqueeActive = FALSE;
  351. if (m_ptdm->GetFocusRect(&m_rowFocus , &m_colFocus,
  352. &m_cRowsFocus, &m_cColsFocus
  353. )
  354. )
  355. {
  356. ScrollTo(m_rowFocus, m_colFocus, 1, 1);
  357. if (m_fGotFocus) SetupMarquee();
  358. }
  359. if (m_fGotFocus)
  360. if (m_fMarqueeActive && !fMarqueeActive)
  361. {
  362. m_idTimer= ::SetTimer(m_hwnd, MARQUEE_TIMER_ID, MARQUEE_TIMER_SPAN, NULL);
  363. m_fMarqueeTimerOn= m_idTimer? TRUE : FALSE;
  364. }
  365. else
  366. if (fMarqueeActive && !m_fMarqueeActive) ::KillTimer(m_hwnd, m_idTimer);
  367. ::UpdateWindow(m_hwnd);
  368. break;
  369. case CTextMatrix::DataDeath:
  370. break;
  371. }
  372. if (fOriginChange) NotifyInterface(OriginChange);
  373. }
  374. CTextView::~CTextView()
  375. {
  376. if (m_hFontDefault)
  377. {
  378. DeleteObject(m_hFontDefault);
  379. m_hFontDefault = NULL;
  380. }
  381. if (m_hFontAlternate)
  382. {
  383. DeleteObject(m_hFontAlternate);
  384. m_hFontAlternate = NULL;
  385. }
  386. if (m_hCheck)
  387. {
  388. DeleteObject(m_hCheck);
  389. m_hCheck = NULL;
  390. }
  391. if (m_hNoCheck)
  392. {
  393. DeleteObject(m_hNoCheck);
  394. m_hNoCheck = NULL;
  395. }
  396. if (m_ptdm)
  397. {
  398. m_ptdm->Disconnect(this);
  399. DetachRef(m_ptdm);
  400. }
  401. if (m_pHighlights) delete m_pHighlights;
  402. if (m_pba) DetachRef(m_pba);
  403. if (m_pCharsets) delete m_pCharsets;
  404. if (m_pbText) delete m_pbText;
  405. }
  406. BOOL CTextView::SubclassDlgItem(UINT nId, HWND hwndParent)
  407. {
  408. ASSERT(!m_hwnd);
  409. HWND hwndCtrl= ::GetDlgItem(hwndParent, nId);
  410. ASSERT(hwndCtrl);
  411. Attach(hwndCtrl);
  412. m_hwnd= hwndCtrl;
  413. m_fpOldWndProc = (WNDPROC)::GetWindowLong(hwndCtrl, GWL_USERDATA);
  414. ::SetWindowLong(hwndCtrl, GWL_USERDATA, long(this));
  415. InitState();
  416. return(TRUE);
  417. }
  418. void CTextView::InitState()
  419. {
  420. // Assumption: We assume that all member variables are initialed with
  421. // zero!
  422. m_cImageFullRows = 0;
  423. m_cImageFullCols = 0;
  424. m_cImageRows = 0;
  425. m_cImageCols = 0;
  426. m_lTopLine = 0;
  427. m_iLeftCol = 0;
  428. m_clFileRows = 0;
  429. m_clFileCols = 0;
  430. m_iHeight = 0;
  431. m_iCharset = 0;
  432. m_cCharsets = 0;
  433. m_pCharsets = NULL;
  434. m_iCharsetAlternate = 0xFFFFFF;
  435. char acName[128];
  436. ::LoadString(hinstDLL,IDS_LISTBOX_FONT,acName,79);
  437. char *pcPointSize;
  438. char c;
  439. for (pcPointSize= acName; (c= *pcPointSize) && c != ','; ++pcPointSize);
  440. m_iHeight= 8;
  441. if (c == ',')
  442. {
  443. *pcPointSize++ = 0;
  444. int iHeight= atoi(pcPointSize);
  445. if (iHeight) m_iHeight= iHeight;
  446. }
  447. m_iCharset = 0;
  448. m_iFamily = 3;
  449. m_iPitch = 2;
  450. HDC hdc= GetDC(m_hwnd);
  451. // Create a font for the list box for default;
  452. m_iHeight = 72 / ((m_iHeight < 8) ? 8 : (m_iHeight > 37) ? 36 : m_iHeight); // Make sure it is reasonable sized
  453. m_iHeight = (hdc) ? GetDeviceCaps(hdc,LOGPIXELSY) / m_iHeight : 8; // convert to point size
  454. if (strlen(acName))
  455. m_hFontDefault = CreateFont(-m_iHeight,0,0,0,0,0,0,0,m_iCharset,OUT_DEFAULT_PRECIS,
  456. CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,m_iPitch | m_iFamily,
  457. acName);
  458. if (!m_hFontDefault) // Assume this means they gave me a bad name use my own
  459. {
  460. m_iCharset = ANSI_CHARSET;
  461. m_iFamily = FF_MODERN;
  462. m_iPitch = VARIABLE_PITCH;
  463. m_hFontDefault = CreateFont(-m_iHeight,0,0,0,0,0,0,0,m_iCharset,OUT_DEFAULT_PRECIS,
  464. CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,m_iPitch | m_iFamily,
  465. "MS Sans Serif");
  466. }
  467. HGDIOBJ hsavFont= ::SelectObject(hdc, m_hFontDefault);
  468. ::GetTextMetrics(hdc, &m_FontMetrics);
  469. ::SelectObject(hdc, hsavFont);
  470. m_nCxChar = m_FontMetrics.tmMaxCharWidth;
  471. m_nCyChar = m_FontMetrics.tmHeight + m_FontMetrics.tmExternalLeading;
  472. m_LeftMargin = m_nCxChar >> 1;
  473. ::ReleaseDC(m_hwnd, hdc);
  474. m_hCheck = LoadBitmap(hinstDLL,MAKEINTRESOURCE(IDB_CHECK));
  475. m_hNoCheck = LoadBitmap(hinstDLL,MAKEINTRESOURCE(IDB_NOCHECK));
  476. BITMAP bmp;
  477. GetObject(m_hCheck,sizeof(bmp),&bmp);
  478. m_iCheckHeight = bmp.bmHeight;
  479. m_iCheckWidth = bmp.bmWidth;
  480. }
  481. void CTextView::MatchBuffToWindow()
  482. {
  483. if (!m_ptdm) return;
  484. if (IsIconic(m_hwnd)) return;
  485. RECT rectClient;
  486. GetClientRect(m_hwnd, &rectClient);
  487. OnSize(SIZENORMAL, rectClient.right - rectClient.left, rectClient.bottom - rectClient.top);
  488. }
  489. void CTextView::RedrawFocusBar()
  490. {
  491. RECT rc;
  492. ::GetClientRect(m_hwnd, &rc);
  493. ::InvalidateRect(m_hwnd, &rc, TRUE);
  494. ::UpdateWindow(m_hwnd);
  495. }
  496. void CTextView::SetupMarquee()
  497. {
  498. ASSERT(!m_fMarquee);
  499. long rowTop, colLeft, cRows, cCols, rowLimit, colLimit;
  500. long rowLimitImage= m_lTopLine + m_cImageRows;
  501. long colLimitImage= m_iLeftCol + m_cImageCols;
  502. cRows = 1;
  503. rowTop = m_rowFocus;
  504. rowLimit= rowTop+ cRows;
  505. if (m_cColsFocus < 0)
  506. {
  507. colLeft = m_colFocus + 1 + m_cColsFocus;
  508. cCols = -m_cColsFocus;
  509. }
  510. else
  511. {
  512. colLeft = m_colFocus;
  513. cCols = m_cColsFocus;
  514. }
  515. colLimit= colLeft+cCols;
  516. #if 0
  517. if ( rowLimit <= m_lTopLine
  518. || rowTop >= rowLimitImage
  519. || colLimit <= m_iLeftCol
  520. || colLeft >= colLimitImage
  521. )
  522. {
  523. m_rcMarquee.top = 0;
  524. m_rcMarquee.bottom = 0;
  525. m_rcMarquee.left = 0;
  526. m_rcMarquee.right = 0;
  527. return;
  528. }
  529. #endif
  530. if (rowTop < m_lTopLine ) rowTop = m_lTopLine - 2;
  531. if (colLeft < m_iLeftCol ) colLeft = m_iLeftCol - 2;
  532. if (rowLimit > rowLimitImage) rowLimit = rowLimitImage + 2;
  533. if (colLimit > colLimitImage) colLimit = colLimitImage + 2;
  534. RECT rc; // RonM -- To make marquees and focus rectangles
  535. // go across the complete display width.
  536. GetWindowRect(m_hwnd, &rc);
  537. m_rcMarquee.top = TopMargin + (rowTop - m_lTopLine) * m_nCyChar;
  538. m_rcMarquee.left = 0; // (colLeft - m_iLeftCol) * m_nCxChar;
  539. m_rcMarquee.bottom = m_rcMarquee.top + (rowLimit - rowTop )* m_nCyChar;
  540. m_rcMarquee.right = rc.right - rc.left; // m_rcMarquee.left + (colLimit - colLeft)* m_nCxChar;
  541. m_fMarquee= TRUE ;
  542. InvalidateMarquee();
  543. }
  544. void CTextView::StartMarquee(HDC hdc)
  545. {
  546. ASSERT(m_fMarquee);
  547. HDC hdcWnd= hdc;
  548. if (!hdcWnd) hdcWnd= GetDC(m_hwnd);
  549. COLORREF clrTextSave = ::SetTextColor(hdcWnd, RGB( 0, 0, 0));
  550. COLORREF clrBkSave = ::SetBkColor (hdcWnd, RGB(256,256,256));
  551. HBRUSH hbrFrame= CreatePatternBrush(m_fMarqueeActive? hbmCheckered : hbmGray50pc);
  552. long xOffset= (m_iLeftCol * (m_nCxChar % 8)) % 8;
  553. long yOffset= (m_lTopLine * (m_nCyChar % 8)) % 8;
  554. ::SetBrushOrgEx(hdcWnd, m_LeftMargin - int(xOffset), TopMargin - int(yOffset), NULL);
  555. HBRUSH hbrSave= (HBRUSH)::SelectObject(hdcWnd, HGDIOBJ(hbrFrame));
  556. DrawMarquee(hdcWnd, PATCOPY);
  557. ::SetTextColor(hdcWnd, clrTextSave);
  558. ::SetBkColor (hdcWnd, clrBkSave );
  559. m_fMarqueePhase = FALSE;
  560. ::SelectObject(hdcWnd, hbrSave);
  561. DeleteObject(hbrFrame);
  562. if (!hdc) ReleaseDC(m_hwnd, hdcWnd);
  563. }
  564. void CTextView::DrawMarquee(HDC hdcWnd, DWORD dwRop)
  565. {
  566. if ( m_rcMarquee.top >= m_rcMarquee.bottom
  567. || m_rcMarquee.left >= m_rcMarquee.right
  568. ) return;
  569. RECT rcClip;
  570. ::GetClientRect(m_hwnd, &rcClip);
  571. rcClip.top = TopMargin;
  572. rcClip.left = 0;
  573. ::IntersectClipRect(hdcWnd, rcClip.left, rcClip.top, rcClip.right, rcClip.bottom);
  574. int cx= m_rcMarquee.right - m_rcMarquee.left;
  575. int cy= m_rcMarquee.bottom - m_rcMarquee.top;
  576. ::PatBlt(hdcWnd, m_rcMarquee.left, m_rcMarquee.top , cx, 1, dwRop);
  577. ::PatBlt(hdcWnd, m_rcMarquee.left, m_rcMarquee.bottom-1, cx, 1, dwRop);
  578. ::PatBlt(hdcWnd, m_rcMarquee.left , m_rcMarquee.top+1, 1, cy-2, dwRop);
  579. ::PatBlt(hdcWnd, m_rcMarquee.right-1, m_rcMarquee.top+1, 1, cy-2, dwRop);
  580. }
  581. void CTextView::CycleMarquee(HDC hdc)
  582. {
  583. HDC hdcWnd= hdc;
  584. if (!hdcWnd) hdcWnd= GetDC(m_hwnd);
  585. DrawMarquee(hdcWnd, DSTINVERT);
  586. m_fMarqueePhase= !m_fMarqueePhase;
  587. if (!hdc) ReleaseDC(m_hwnd, hdcWnd);
  588. }
  589. void CTextView::RemoveMarquee(HDC hdc)
  590. {
  591. ASSERT(m_fMarquee);
  592. // bugbug: Need to turn off the marquee timer here.
  593. // bugbug: also need an OnTimer message handler.
  594. InvalidateMarquee();
  595. m_fMarquee = FALSE;
  596. m_fMarqueeActive = FALSE;
  597. }
  598. void CTextView::InvalidateMarquee()
  599. {
  600. RECT rc= m_rcMarquee;
  601. rc.bottom= rc.top+1;
  602. ::InvalidateRect(m_hwnd, &rc, TRUE);
  603. rc.bottom= m_rcMarquee.bottom;
  604. rc.top = rc .bottom-1;
  605. InvalidateRect(m_hwnd, &rc, TRUE);
  606. rc.top = m_rcMarquee.top;
  607. rc.right = rc .left+1;
  608. InvalidateRect(m_hwnd, &rc, TRUE);
  609. rc.right = m_rcMarquee.right;
  610. rc.left = rc .right-1;
  611. InvalidateRect(m_hwnd, &rc, TRUE);
  612. }
  613. void CTextView::RepaintMarquee(HDC hdc)
  614. {
  615. ASSERT(m_fMarquee);
  616. BOOL fCycle= m_fMarqueePhase;
  617. StartMarquee(hdc);
  618. if (fCycle) CycleMarquee(hdc);
  619. }
  620. void CTextView::OnSetFocus(HWND hwndOld)
  621. {
  622. m_fGotFocus= TRUE;
  623. SetupMarquee();
  624. RedrawFocusBar();
  625. if (m_fMarqueeActive)
  626. {
  627. m_idTimer= ::SetTimer(m_hwnd, MARQUEE_TIMER_ID, MARQUEE_TIMER_SPAN, NULL);
  628. m_fMarqueeTimerOn= m_idTimer? TRUE : FALSE;
  629. }
  630. }
  631. void CTextView::OnKillFocus(HWND hwndNew)
  632. {
  633. m_fGotFocus= FALSE;
  634. if (m_fMarquee) RemoveMarquee();
  635. RedrawFocusBar();
  636. if (m_fMarqueeActive && m_fMarqueeTimerOn)
  637. {
  638. ::KillTimer(m_hwnd, m_idTimer);
  639. m_idTimer= 0;
  640. m_fMarqueeTimerOn= FALSE;
  641. }
  642. }
  643. void CTextView::OnWindowPosChanged(WINDOWPOS FAR* lpwndpos )
  644. {
  645. OnSize(SIZENORMAL, lpwndpos->cx, lpwndpos->cy);
  646. }
  647. void CTextView::OnSize(UINT nType, int cx, int cy)
  648. {
  649. if (nType != SIZEFULLSCREEN && nType != SIZENORMAL) return;
  650. short cColsFull = (short) m_ptdm->ColCount();
  651. short cRowsFull = (cy- TopMargin)/m_nCyChar;
  652. m_cImageFullCols = (cColsFull > 0)? cColsFull : 0;
  653. m_cImageFullRows = (cRowsFull > 0)? cRowsFull : 0;
  654. int cRowsClient = (cy+m_nCyChar-1- TopMargin)/m_nCyChar;
  655. int cColsClient = m_ptdm->ColCount();
  656. if (cRowsClient < 0) cRowsClient= 0;
  657. if (cColsClient < 0) cColsClient= 0;
  658. if (cRowsClient != m_cImageRows || cColsClient != m_cImageCols)
  659. {
  660. m_cImageRows= cRowsClient;
  661. m_cImageCols= cColsClient;
  662. if (m_cImageRows > m_cCharsets)
  663. {
  664. if (m_pCharsets)
  665. {
  666. delete m_pCharsets;
  667. m_pCharsets = NULL;
  668. m_cCharsets = 0;
  669. }
  670. if (m_pCharsets = New UINT[m_cImageRows])
  671. m_cCharsets = m_cImageRows;
  672. }
  673. m_pba->SetSize(cRowsClient*cColsClient);
  674. }
  675. if (m_ptdm) FillBuff();
  676. InvalidateRect(m_hwnd, NULL, TRUE);
  677. }
  678. void CTextView::OnSizeChar(int cx,int cy)
  679. {
  680. short cColsFull = cx;
  681. short cRowsFull = cy;
  682. m_cImageFullCols = (cColsFull > 0)? cColsFull : 0;
  683. m_cImageFullRows = (cRowsFull > 0)? cRowsFull : 0;
  684. int cColsClient = cx;
  685. int cRowsClient = cy;
  686. if (cColsClient < 0) cColsClient= 0;
  687. if (cRowsClient < 0) cRowsClient= 0;
  688. if (cColsClient != m_cImageCols || cRowsClient != m_cImageRows)
  689. {
  690. m_cImageCols= cColsClient;
  691. m_cImageRows= cRowsClient;
  692. if (m_cImageRows > m_cCharsets)
  693. {
  694. if (m_pCharsets)
  695. {
  696. delete m_pCharsets;
  697. m_pCharsets = NULL;
  698. m_cCharsets = 0;
  699. }
  700. if (m_pCharsets = New UINT[m_cImageRows])
  701. m_cCharsets = m_cImageRows;
  702. }
  703. m_pba->SetSize(m_cImageRows * m_cImageCols);
  704. }
  705. if (m_ptdm) FillBuff();
  706. InvalidateRect(m_hwnd, NULL, TRUE);
  707. }
  708. void CTextView::FillBuff()
  709. {
  710. m_ptdm->GetTextMatrixImage
  711. (m_lTopLine, m_iLeftCol, m_cImageRows, m_cImageCols, m_pba->ElementAt(0), m_pCharsets); //rmk
  712. UINT iCharsetDef= DefaultCharacterSet();
  713. for (int c= m_cImageRows; c--; )
  714. if (m_pCharsets[c] == DEFAULT_CHARSET)
  715. m_pCharsets[c] = iCharsetDef;
  716. UINT cHighlights= m_ptdm->GetHighlights(m_lTopLine, m_iLeftCol,
  717. m_cImageRows, m_cImageCols,
  718. 0, NULL
  719. );
  720. if (cHighlights)
  721. {
  722. if (cHighlights > m_cHighlightsAllocated)
  723. {
  724. if (m_cHighlightsAllocated)
  725. delete [] m_pHighlights;
  726. m_cHighlightsAllocated=cHighlights;
  727. m_pHighlights= New CHighlight[m_cHighlightsAllocated];
  728. }
  729. m_ptdm->GetHighlights(m_lTopLine, m_iLeftCol,
  730. m_cImageRows, m_cImageCols,
  731. cHighlights, m_pHighlights
  732. );
  733. // The highlight data is initially relative to the full data image.
  734. // For convenience during repainting we make it relative to the buffer
  735. // image.
  736. // Bug: C 7.00 won't accept the declaration for phl within the
  737. // init phrase of the for statement!
  738. PCHighlight phl= m_pHighlights;
  739. for (UINT c= cHighlights;
  740. c--;
  741. phl++
  742. )
  743. {
  744. phl->m_row -= m_lTopLine;
  745. phl->m_col -= m_iLeftCol;
  746. }
  747. }
  748. m_cHighlightsActive= cHighlights;
  749. }
  750. BOOL CTextView::OnEraseBkgnd(HDC hdc)
  751. {
  752. RECT rect;
  753. UINT wLM= m_LeftMargin;
  754. ::GetClientRect(m_hwnd, &rect );
  755. #if 0 // #ifndef CHICAGO
  756. HBRUSH hbrushSave;
  757. if (m_fGotFocus)
  758. {
  759. HBRUSH hbrFocus= ::CreateSolidBrush(::GetSysColor(COLOR_ACTIVECAPTION));
  760. hbrushSave= ::SelectObject(hdc, hbrFocus);
  761. ::BitBlt(hdc, rect.left, rect.top, FocusMargin, rect.bottom - rect.top, NULL, 0, 0, PATCOPY);
  762. SelectObject(hdc, hbrushSave);
  763. DeleteObject(hbrFocus);
  764. rect.left += FocusMargin;
  765. wLM -= FocusMargin;
  766. }
  767. #endif // 0
  768. #if 0
  769. HBRUSH hbrTextBG= (HBRUSH) ::SendMessage(GetParent(m_hwnd), WM_CTLCOLORDLG, (WPARAM) hdc, (LPARAM) GetParent(m_hwnd));
  770. hbrushSave= ::SelectObject(hdc, hbrTextBG);
  771. if (m_ptdm)
  772. {
  773. ::BitBlt(hdc, rect.left, rect.top, wLM, rect.bottom - rect.top, NULL, 0, 0, PATCOPY);
  774. ::BitBlt(hdc, rect.left+wLM, rect.top, (rect.right - rect.left)-wLM, TopMargin, NULL, 0, 0, PATCOPY);
  775. }
  776. else ::BitBlt(hdc, rect.left, rect.top, (rect.right - rect.left), rect.bottom - rect.top, NULL, 0, 0, PATCOPY);
  777. ::SelectObject(hdc, hbrushSave);
  778. DeleteObject(hbrTextBG);
  779. #endif // 0
  780. return TRUE;
  781. }
  782. void CTextView::ColorTextOut(HDC hdc, int x, int y,
  783. PWCHAR lpChar, int row, int cChar, //rmk
  784. COLORREF clrfg, COLORREF clrbg
  785. )
  786. {
  787. if (m_clrfg != clrfg) ::SetTextColor(hdc, m_clrfg= clrfg);
  788. if (m_clrbg != clrbg) ::SetBkColor (hdc, m_clrbg= clrbg);
  789. RECT rcClip;
  790. ::GetClientRect(m_hwnd, &rcClip);
  791. rcClip.top = y;
  792. if (rcClip.bottom > y + m_nCyChar)
  793. rcClip.bottom = y + m_nCyChar;
  794. //rmk-->
  795. cChar <<= 1; // each WC can generate two MB characters
  796. if (cChar > m_cbText)
  797. {
  798. m_cbText = 0;
  799. if (m_pbText) { delete m_pbText; m_pbText= NULL; }
  800. m_pbText = New char[cChar];
  801. m_cbText = cChar;
  802. }
  803. if (!m_pbText) return;
  804. int cText = WideCharToMultiByte(GetCPFromCharset(m_pCharsets[row]), 0, lpChar, cChar>>1, m_pbText, m_cbText, NULL, NULL); //rmk
  805. //rmk<--
  806. ExtTextOut(hdc, x, y, ETO_OPAQUE, &rcClip, m_pbText, cText, NULL); //rmk
  807. }
  808. // OnPaint
  809. //
  810. #ifdef _DEBUG
  811. static UINT cRepaints= 0;
  812. #endif // _DEBUG
  813. void CTextView::OnPaint()
  814. {
  815. PAINTSTRUCT ps;
  816. int iLastHilite = -1;
  817. HDC hdc= ::BeginPaint(m_hwnd, &ps);
  818. if (! m_ptdm ) { EndPaint(m_hwnd, &ps); return; }
  819. #ifdef _DEBUG
  820. ++cRepaints;
  821. #endif // _DEBUG
  822. // if we are using the 3d drawing stuff we need to setup the
  823. // background manually
  824. HBRUSH hbrTextBG= (HBRUSH) ::SendMessage(GetParent(m_hwnd), WM_CTLCOLORDLG, (WPARAM) hdc, (LPARAM) GetParent(m_hwnd));
  825. LOGBRUSH lb;
  826. ::GetObject(hbrTextBG, sizeof(LOGBRUSH),&lb);
  827. ::SetBkColor(hdc, lb.lbColor);
  828. ::SetTextAlign(hdc, TA_LEFT);
  829. HFONT hfontDefault= m_hFont? m_hFont : m_hFontDefault;
  830. HGDIOBJ hSaveFont= ::SelectObject(hdc, hfontDefault);
  831. m_clrfg= ::GetTextColor(hdc); // Set up to use ColorTextOut routine...
  832. m_clrbg= ::GetBkColor (hdc);
  833. COLORREF clrfgText = ::GetSysColor(COLOR_WINDOWTEXT );
  834. COLORREF clrbgText = ::GetSysColor(COLOR_WINDOW );// m_clrbg;
  835. COLORREF clrfgTextHighlight = ::GetSysColor(COLOR_HIGHLIGHTTEXT);
  836. COLORREF clrbgTextHighlight = ::GetSysColor(COLOR_HIGHLIGHT );
  837. HBRUSH hbrFrame = ::CreateSolidBrush(clrbgTextHighlight);
  838. HBRUSH hbrDotBox = ::CreatePatternBrush(hbmGray50pc );
  839. HBRUSH hbrDashBox = ::CreatePatternBrush(hbmCheckered);
  840. RECT rcFrame;
  841. HBRUSH hbrSave= (HBRUSH)::SelectObject(hdc, HGDIOBJ(hbrFrame));
  842. UINT cHighlightsLeft = m_cHighlightsActive;
  843. CHighlight *pHighlight = m_pHighlights;
  844. RECT rect, rect2;
  845. int y;
  846. PWCHAR lpb; //rmk
  847. ::GetClientRect(m_hwnd, &rect);
  848. RECT rectUpdate= rect;
  849. int yOff= TopMargin;
  850. int xOff= m_LeftMargin;
  851. if (rectUpdate.top < (int) yOff)
  852. rectUpdate.top = yOff;
  853. int rowFirst= (rectUpdate.top - yOff)/m_nCyChar;
  854. int rowLimit= (rectUpdate.bottom + m_nCyChar - 1 - yOff) / m_nCyChar;
  855. if (rectUpdate.left < (int) xOff)
  856. rectUpdate.left= xOff;
  857. int colFirst= 0;
  858. int colLimit= m_cImageCols;
  859. int cols= colLimit - colFirst;
  860. rect2.left = xOff + colFirst*m_nCxChar;
  861. rect2.right = rect.right;
  862. y = yOff + m_nCyChar * rowFirst;
  863. int row= rowFirst;
  864. for ( lpb= m_pba->ElementAt(colFirst + rowFirst * m_cImageCols);
  865. row < rowLimit; // y < rectUpdate.bottom;
  866. y += m_nCyChar, lpb+= m_cImageCols, ++row
  867. )
  868. {
  869. rect2.top = y;
  870. rect2.bottom = y + m_nCyChar;
  871. for (; cHighlightsLeft && ( pHighlight->m_iType
  872. != CHighlight::HIGHLIGHT_TEXT
  873. || pHighlight->m_row < row
  874. );
  875. cHighlightsLeft--, pHighlight++
  876. );
  877. UINT colsDrawn = 0;
  878. int col = colFirst;
  879. int left = rect2.left;
  880. PWCHAR lpchar = lpb; //rmk
  881. for (int cChar= cols;
  882. cChar;
  883. cChar -= colsDrawn,
  884. col += colsDrawn,
  885. left += colsDrawn*m_nCxChar,
  886. lpchar += colsDrawn
  887. )
  888. {
  889. for (; cHighlightsLeft && ( pHighlight->m_iType
  890. != CHighlight::HIGHLIGHT_TEXT
  891. || ( pHighlight->m_row == row
  892. && (pHighlight->m_col
  893. + pHighlight->m_cChars) <= col
  894. )
  895. );
  896. cHighlightsLeft--, pHighlight++
  897. );
  898. if (m_pCharsets[row] == m_iCharset)
  899. ::SelectObject(hdc, hfontDefault);
  900. else if (m_pCharsets[row] == m_iCharsetAlternate)
  901. ::SelectObject(hdc, m_hFontAlternate);
  902. else
  903. {
  904. if (m_hFontAlternate)
  905. DeleteObject(m_hFontAlternate);
  906. m_hFontAlternate = NULL;
  907. m_iCharsetAlternate = m_pCharsets[row];
  908. LOGFONT lf;
  909. GetObject(hfontDefault, sizeof(lf), &lf);
  910. lf.lfCharSet= m_iCharsetAlternate;
  911. if (m_iCharsetAlternate == SYMBOL_CHARSET)
  912. strcpy(lf.lfFaceName, "SYMBOL");
  913. m_hFontAlternate = CreateFontIndirect(&lf);
  914. // m_hFontAlternate = CreateFont(-m_iHeight,0,0,0,0,0,0,0,m_iCharsetAlternate,OUT_DEFAULT_PRECIS,
  915. // CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,m_iPitch | m_iFamily, NULL);
  916. if (m_hFontAlternate)
  917. {
  918. ::SelectObject(hdc, m_hFontAlternate);
  919. TEXTMETRIC tm;
  920. if (GetTextMetrics(hdc, &tm))
  921. //ASSERT(tm.tmCharSet == m_iCharsetAlternate);
  922. ;
  923. else
  924. {
  925. ::SelectObject(hdc, hfontDefault);
  926. ::DeleteObject(m_hFontAlternate);
  927. m_pCharsets[row] = m_iCharset;
  928. m_iCharsetAlternate = 0xFFFFFF;
  929. m_hFontAlternate = NULL;
  930. }
  931. }
  932. else
  933. {
  934. m_pCharsets[row] = m_iCharset;
  935. m_iCharsetAlternate = 0xFFFFFF;
  936. ::SelectObject(hdc, hfontDefault);
  937. }
  938. }
  939. if (cHighlightsLeft && pHighlight->m_row == row
  940. && pHighlight->m_col < colFirst+cols
  941. )
  942. {
  943. if (pHighlight->m_col > col)
  944. {
  945. colsDrawn= pHighlight->m_col-col;
  946. ColorTextOut(hdc, left, rect2.top, lpchar, row, colsDrawn, clrfgText, clrbgText);
  947. }
  948. cChar -= colsDrawn;
  949. lpchar += colsDrawn;
  950. col += colsDrawn;
  951. left += colsDrawn*m_nCxChar;
  952. int colHL= pHighlight->m_col;
  953. int cbHL= m_cImageCols - colHL; // pHighlight->m_cChars;
  954. if (colHL < col)
  955. {
  956. cbHL -= col-colHL;
  957. colHL = col;
  958. }
  959. if (cbHL > cChar) cbHL= cChar;
  960. ColorTextOut(hdc, left, rect2.top, lpchar, row, colsDrawn= cbHL, clrfgTextHighlight, clrbgTextHighlight);
  961. iLastHilite = row;
  962. ++pHighlight; --cHighlightsLeft;
  963. }
  964. else
  965. {
  966. ColorTextOut(hdc, left, rect2.top, lpchar, row, cChar, clrfgText, clrbgText);
  967. break;
  968. }
  969. }
  970. }
  971. cHighlightsLeft = m_cHighlightsActive;
  972. pHighlight = m_pHighlights;
  973. for (row= rowFirst; row < rowLimit; ++row)
  974. {
  975. for (;
  976. cHighlightsLeft && (pHighlight->m_iType == CHighlight::HIGHLIGHT_TEXT || pHighlight->m_row < row);
  977. cHighlightsLeft--, pHighlight++
  978. );
  979. if (!cHighlightsLeft) break;
  980. int col;
  981. for (row= pHighlight->m_row, col= colFirst; col < colLimit; )
  982. {
  983. for (;
  984. cHighlightsLeft && ( pHighlight->m_iType == CHighlight::HIGHLIGHT_TEXT
  985. || (pHighlight->m_row == row && (pHighlight->m_col + pHighlight->m_cChars)<= col)
  986. );
  987. cHighlightsLeft--, pHighlight++
  988. );
  989. if (!cHighlightsLeft) break;
  990. for (;
  991. cHighlightsLeft && pHighlight->m_iType != CHighlight::HIGHLIGHT_TEXT
  992. && pHighlight->m_row == row
  993. && pHighlight->m_col < colLimit;
  994. col= pHighlight->m_col + pHighlight->m_cChars,
  995. cHighlightsLeft--, pHighlight++
  996. )
  997. {
  998. RECT rcBounds;
  999. rcBounds.top = yOff + pHighlight->m_row * m_nCyChar;
  1000. rcBounds.left = xOff + pHighlight->m_col * m_nCxChar;
  1001. rcBounds.bottom = rcBounds.top + m_nCyChar;
  1002. rcBounds.right = rcBounds.left + pHighlight->m_cChars
  1003. * m_nCxChar;
  1004. switch (pHighlight->m_iType)
  1005. {
  1006. case CHighlight::CHECK_MARK:
  1007. case CHighlight::NOCHECK_MARK:
  1008. {
  1009. if (m_bUseCheck)
  1010. {
  1011. HDC hSrcDC = CreateCompatibleDC(hdc);
  1012. COLORREF crBkg, crText;
  1013. crText = SetTextColor(hdc,(iLastHilite == row) ? clrfgTextHighlight : clrfgText);
  1014. crBkg = SetBkColor(hdc,(iLastHilite == row) ? clrbgTextHighlight : clrbgText);
  1015. HBITMAP hbmpSave = (HBITMAP) SelectObject(hSrcDC,(pHighlight->m_iType == CHighlight::CHECK_MARK) ? m_hCheck : m_hNoCheck);
  1016. RECT rcClip;
  1017. ::GetClientRect(m_hwnd, &rcClip);
  1018. if (rcBounds.bottom <= rcClip.bottom)
  1019. {
  1020. BitBlt(hdc,(m_LeftMargin - m_iCheckWidth) / 2,rcBounds.top + ((m_nCyChar - m_iCheckHeight) / 2),
  1021. m_iCheckWidth,m_iCheckHeight,hSrcDC,0,0,SRCCOPY);
  1022. }
  1023. SetBkColor(hSrcDC,crBkg);
  1024. SetTextColor(hSrcDC,crText);
  1025. SelectObject(hSrcDC,hbmpSave);
  1026. DeleteDC(hSrcDC);
  1027. }
  1028. break;
  1029. }
  1030. case CHighlight::DOT_BOX_TEXT:
  1031. ::FrameRect(hdc, &rcBounds, hbrDotBox);
  1032. break;
  1033. case CHighlight::DASH_BOX_TEXT:
  1034. ::FrameRect(hdc, &rcBounds, hbrDashBox);
  1035. break;
  1036. case CHighlight::UNDERSCORE_TEXT:
  1037. ::PatBlt(hdc, rcBounds.left, rcBounds.bottom-1, rcBounds.right - rcBounds.left, 1, PATCOPY);
  1038. break;
  1039. case CHighlight::OVERSCORE_TEXT:
  1040. ::PatBlt(hdc, rcBounds.left, rcBounds.top, rcBounds.right - rcBounds.left, 1, PATCOPY);
  1041. break;
  1042. case CHighlight::BOX_TEXT:
  1043. FrameRect(hdc, &rcFrame, hbrFrame);
  1044. break;
  1045. }
  1046. }
  1047. }
  1048. }
  1049. ::SelectObject(hdc, hbrSave );
  1050. ::SelectObject(hdc, hSaveFont);
  1051. if (m_fMarquee) RepaintMarquee(hdc);
  1052. ::DeleteObject(hbrFrame );
  1053. ::DeleteObject(hbrDotBox );
  1054. ::DeleteObject(hbrDashBox);
  1055. ::EndPaint(m_hwnd, &ps);
  1056. }
  1057. void CTextView::InvalidateImage(long row, long col, long cRows, long cCols)
  1058. {
  1059. long rowLimit= row+cRows;
  1060. long colLimit= col+cCols;
  1061. // Undone: When row is -1, the data object has changed its shape.
  1062. // In that case cRows and cCols give the new data shape.
  1063. //
  1064. // For that situation we must notify our owner that the
  1065. // scroll bar range must be modified.
  1066. if (row < m_lTopLine ) row= m_lTopLine;
  1067. if (col < long(m_iLeftCol)) col= long(m_iLeftCol);
  1068. long rowLimitImage= m_lTopLine + m_cImageRows;
  1069. long colLimitImage= long(m_iLeftCol) + m_cImageCols;
  1070. if (rowLimit > rowLimitImage) rowLimit= rowLimitImage;
  1071. if (colLimit > colLimitImage) colLimit= colLimitImage;
  1072. // if (row >= rowLimit || col >= colLimit) return;
  1073. FillBuff();
  1074. RECT rc;
  1075. GetClientRect(m_hwnd,&rc);
  1076. rc.top = TopMargin + m_nCyChar * UINT(row - m_lTopLine);
  1077. // This causes the bottom to not be emptied
  1078. // rc.bottom = rc.top + m_nCyChar * UINT(rowLimit - row );
  1079. InvalidateRect(m_hwnd, &rc, TRUE);
  1080. }
  1081. //
  1082. // MoveToRow:
  1083. void CTextView::MoveToRow(long row, BOOL fForceUpdate, BOOL fNotify)
  1084. {
  1085. if ( m_ptdm == NULL ) return;
  1086. LONG oldLine= m_lTopLine;
  1087. if (row > m_clFileRows - long(m_cImageFullRows))
  1088. row = m_clFileRows - long(m_cImageFullRows);
  1089. if (row < 0) row= 0;
  1090. long distance= oldLine - row;
  1091. if (!distance) return;
  1092. BOOL fMarquee= m_fMarquee;
  1093. if (fMarquee) RemoveMarquee();
  1094. m_lTopLine= row;
  1095. FillBuff();
  1096. if (fMarquee) SetupMarquee();
  1097. int udistance= (distance < 0)? - distance : distance;
  1098. if (udistance > m_cImageFullRows) InvalidateRect(m_hwnd, NULL, FALSE);
  1099. else
  1100. {
  1101. HDC hdc= ::GetWindowDC(m_hwnd);
  1102. RECT rectText, rectUpdate,rectClip;
  1103. ::GetClientRect(m_hwnd, &rectText);
  1104. ::GetClientRect(m_hwnd, &rectClip);
  1105. // rectClip.bottom = ((rectText.bottom - rectText.top) / m_nCyChar) * m_nCyChar;
  1106. rectText.top += TopMargin;
  1107. ::ScrollDC(hdc, 0, m_nCyChar * (int) distance, &rectText, &rectClip, NULL, &rectUpdate);
  1108. rectUpdate.top -= (rectUpdate.top >= m_nCyChar) ? m_nCyChar : rectUpdate.top;
  1109. ::InvalidateRect(m_hwnd, &rectUpdate, TRUE);
  1110. ReleaseDC(m_hwnd, hdc);
  1111. }
  1112. if (fForceUpdate) UpdateWindow();
  1113. if (fNotify) NotifyInterface(OriginChange);
  1114. }
  1115. void CTextView::RepaintFrom(long row, long col)
  1116. {
  1117. m_lTopLine= row;
  1118. m_iLeftCol= int(col);
  1119. BOOL fMarquee= m_fMarquee;
  1120. if (fMarquee) RemoveMarquee();
  1121. m_lTopLine= row;
  1122. FillBuff();
  1123. if (fMarquee) SetupMarquee();
  1124. ::InvalidateRect(m_hwnd, NULL, TRUE);
  1125. ::UpdateWindow(m_hwnd);
  1126. }
  1127. // MoveToCol:
  1128. //
  1129. void
  1130. CTextView::MoveToCol(long col, BOOL fForceUpdate, BOOL fNotify)
  1131. {
  1132. if ( m_ptdm == NULL ) return;
  1133. int oldLeftCol = m_iLeftCol;
  1134. if (col > m_clFileCols - long(m_cImageFullCols))
  1135. col = m_clFileCols - long(m_cImageFullCols);
  1136. if (col < 0) col= 0;
  1137. long distance= oldLeftCol - int(col);
  1138. if (!distance) return;
  1139. BOOL fMarquee= m_fMarquee;
  1140. if (fMarquee) RemoveMarquee();
  1141. m_iLeftCol= int(col);
  1142. FillBuff();
  1143. if (fMarquee) SetupMarquee();
  1144. int udistance= (distance < 0)? - distance : distance;
  1145. if (udistance > m_cImageFullCols)
  1146. {
  1147. InvalidateRect(m_hwnd, NULL, FALSE);
  1148. return;
  1149. }
  1150. HDC hdcClient= GetWindowDC(m_hwnd);
  1151. RECT rectText, rectUpdate,rectClip;
  1152. GetClientRect(m_hwnd, &rectText);
  1153. GetClientRect(m_hwnd, &rectClip);
  1154. rectClip.bottom = ((rectText.bottom - rectText.top) / m_nCyChar) * m_nCyChar;
  1155. rectText.top += TopMargin;
  1156. ::ScrollDC(hdcClient, m_nCxChar * int(distance), 0, &rectText, &rectClip, NULL, &rectUpdate);
  1157. ::ReleaseDC(m_hwnd, hdcClient);
  1158. rectUpdate.top -= (rectUpdate.top >= m_nCyChar) ? m_nCyChar : rectUpdate.top;
  1159. ::InvalidateRect(m_hwnd, &rectUpdate, TRUE);
  1160. if (fForceUpdate) ::UpdateWindow(m_hwnd);
  1161. if (fNotify) NotifyInterface(OriginChange);
  1162. }
  1163. void CTextView::MoveTo(long rowTop, long colLeft, BOOL fNotify)
  1164. {
  1165. if (rowTop == m_lTopLine && colLeft == m_iLeftCol) return;
  1166. UpdateWindow();
  1167. MoveToRow(rowTop , FALSE, FALSE);
  1168. MoveToCol(colLeft, FALSE, FALSE);
  1169. if (fNotify) NotifyInterface(OriginChange);
  1170. }
  1171. void CTextView::PaddedScrollTo(long rowTop, long colLeft,
  1172. unsigned short cRows, unsigned short cCols
  1173. )
  1174. {
  1175. if (m_cImageFullRows > cRows)
  1176. {
  1177. int cLinesExtra= m_cImageFullRows - cRows;
  1178. if (cLinesExtra > m_cLinesScrollContext)
  1179. cLinesExtra = m_cLinesScrollContext;
  1180. cRows += cLinesExtra;
  1181. rowTop -= cLinesExtra/2;
  1182. if (rowTop < 0) rowTop= 0;
  1183. }
  1184. ScrollTo(rowTop, colLeft, cRows, cCols);
  1185. }
  1186. void CTextView::ScrollTo(int rowTop, int colLeft,
  1187. int cRows, int cCols
  1188. )
  1189. {
  1190. int rowNew= m_lTopLine;
  1191. if (rowTop <= m_lTopLine) rowNew= rowTop;
  1192. else
  1193. if (rowTop + cRows >= m_lTopLine+m_cImageFullRows)
  1194. {
  1195. rowNew= rowTop + cRows - m_cImageFullRows;
  1196. if (rowNew > rowTop) rowNew= rowTop;
  1197. }
  1198. int colNew= m_iLeftCol;
  1199. if (colLeft <= m_iLeftCol) colNew= colLeft;
  1200. else
  1201. if (colLeft + cCols > m_iLeftCol+m_cImageFullCols)
  1202. {
  1203. colNew= colLeft + cCols - m_cImageFullCols;
  1204. if (colNew > colLeft) colNew= colLeft;
  1205. }
  1206. MoveTo(rowNew, colNew);
  1207. }
  1208. UINT CTextView::OnNcHitTest(POINTS point)
  1209. {
  1210. return HTCLIENT;
  1211. }
  1212. BOOL CTextView::OnSetCursor(HWND hWnd, UINT nHitTest, UINT message)
  1213. {
  1214. SetCursor((HCURSOR)hcurArrow);
  1215. return TRUE;
  1216. }
  1217. void CTextView::CharacterMouseEvent(UINT nFlags, POINTS point,
  1218. long& row, long& col
  1219. )
  1220. {
  1221. long x= point.x - long(m_LeftMargin);
  1222. long y= point.y - long( TopMargin);
  1223. if (y >= 0) row= y/m_nCyChar;
  1224. else row= -((m_nCyChar-1-y)/m_nCyChar);
  1225. if (x >= 0) col= x/m_nCxChar;
  1226. else col= -((m_nCxChar-1-x)/m_nCxChar);
  1227. row+= m_lTopLine;
  1228. col+= m_iLeftCol;
  1229. if (row < 0) row= 0;
  1230. else
  1231. if (row >= m_clFileRows) row= m_clFileRows-1;
  1232. if (col < 0) col= 0;
  1233. else
  1234. if (col >= m_clFileCols) col= m_clFileCols-1;
  1235. if ( row >= m_lTopLine && row < m_lTopLine + m_cImageFullRows
  1236. && col >= m_iLeftCol && col < m_iLeftCol + m_cImageFullCols
  1237. )
  1238. {
  1239. if (m_fTimerActive)
  1240. {
  1241. m_fTimerActive= FALSE;
  1242. ::KillTimer(m_hwnd, m_hTimer);
  1243. }
  1244. return;
  1245. }
  1246. if (row < m_lTopLine) MoveToRow(row);
  1247. else
  1248. if (row >= m_lTopLine+m_cImageFullRows)
  1249. MoveToRow(row+1-m_cImageFullRows);
  1250. if (col < long(m_iLeftCol)) MoveToCol(col);
  1251. else
  1252. if (col >= long(m_iLeftCol)+long(m_cImageFullCols))
  1253. MoveToCol(col+1-long(m_cImageFullCols));
  1254. if (m_fTimerActive) return;
  1255. m_fTimerActive= TRUE;
  1256. m_hTimer= SetTimer(m_hwnd, MOUSE_TIMER_ID, GetProfileInt("Windows", "KeyboardSpeed", 100), NULL);
  1257. }
  1258. void CTextView::OnLButtonDown(UINT nFlags, POINTS point)
  1259. {
  1260. if (::GetFocus() != m_hwnd) ::SetFocus(m_hwnd);
  1261. if (!m_ptdm) return;
  1262. if (GetCapture()) return;
  1263. SetCapture(m_hwnd);
  1264. m_fMouseCaptured = TRUE;
  1265. m_fTimerActive = FALSE;
  1266. long row, col;
  1267. CharacterMouseEvent(nFlags, point, row, col);
  1268. m_ptdm->OnLButtonDown(nFlags, row, col);
  1269. }
  1270. void CTextView::OnLButtonUp(UINT nFlags, POINTS point)
  1271. {
  1272. if (!m_fMouseCaptured) return;
  1273. long row, col;
  1274. CharacterMouseEvent(nFlags, point, row, col);
  1275. int x = (m_LeftMargin - m_iCheckWidth) / 2;
  1276. int y = (TopMargin + (row-m_lTopLine) * m_nCyChar) + ((m_nCyChar - m_iCheckHeight) / 2);
  1277. int w = m_iCheckWidth;
  1278. int h = m_iCheckHeight;
  1279. m_ptdm->OnLButtonUp(nFlags, row, col,
  1280. m_bUseCheck ? (point.x >= x &&
  1281. point.y >= y &&
  1282. point.x <= x+w &&
  1283. point.y <= y+h) : FALSE
  1284. );
  1285. if (m_fTimerActive)
  1286. {
  1287. KillTimer(m_hwnd, m_hTimer);
  1288. m_fTimerActive= FALSE;
  1289. }
  1290. m_fMouseCaptured= FALSE;
  1291. ::ReleaseCapture();
  1292. }
  1293. void CTextView::OnLButtonDblClk(UINT nFlags, POINTS point)
  1294. {
  1295. long row, col;
  1296. CharacterMouseEvent(nFlags, point, row, col);
  1297. int x = (m_LeftMargin - m_iCheckWidth) / 2;
  1298. int y = (TopMargin + (row-m_lTopLine) * m_nCyChar) + ((m_nCyChar - m_iCheckHeight) / 2);
  1299. int w = m_iCheckWidth;
  1300. int h = m_iCheckHeight;
  1301. if (!(m_bUseCheck ? (point.x >= x && point.y >= y &&
  1302. point.x <= x+w && point.y <= y+h) : FALSE))
  1303. m_ptdm->OnLButtonDblClk(nFlags, row, col);
  1304. }
  1305. void CTextView::OnMouseMove(UINT nFlags, POINTS point)
  1306. {
  1307. BOOL fStartedWithTimer= m_fTimerActive;
  1308. long row, col;
  1309. if (!m_fMouseCaptured) return;
  1310. CharacterMouseEvent(nFlags, point, row, col);
  1311. if (fStartedWithTimer && m_fTimerActive) return;
  1312. m_ptdm->OnMouseMove(nFlags, row, col);
  1313. }
  1314. void CTextView::OnTimer(UINT nIDEvent)
  1315. {
  1316. if (m_fMarqueeTimerOn && nIDEvent == m_idTimer)
  1317. {
  1318. return;
  1319. }
  1320. if (nIDEvent != m_hTimer) return;
  1321. long info= ::GetMessagePos();
  1322. POINT point;
  1323. point.x = LOWORD(info),
  1324. point.y = HIWORD(info);
  1325. ScreenToClient(m_hwnd, &point);
  1326. long row, col;
  1327. POINTS points;
  1328. points.x= short(point.x);
  1329. points.y= short(point.y);
  1330. CharacterMouseEvent(0, points, row, col);
  1331. m_ptdm->OnMouseMove(0, row, col);
  1332. }
  1333. void CTextView::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
  1334. {
  1335. if (!m_ptdm) return;
  1336. m_ptdm->OnKeyDown(this, nChar, nRepCnt, nFlags);
  1337. }
  1338. void CTextView::OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags)
  1339. {
  1340. if (!m_ptdm) return;
  1341. m_ptdm->OnKeyUp(this, nChar, nRepCnt, nFlags);
  1342. }