editwnd.cpp 18 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001
  1. #include <precomp.h>
  2. #include "editwnd.h"
  3. #include <tataki/canvas/canvas.h>
  4. #include <api/wnd/notifmsg.h>
  5. #include <bfc/assert.h>
  6. #define ID_EDITCHILD 12
  7. enum { IDLETIMER = 8, DELETETIMER = 10 };
  8. #define IDLETIME 350 // comprimises suck ;)
  9. #if UTF8
  10. #ifdef WANT_UTF8_WARNINGS
  11. #pragma CHAT("mig", "all", "UTF8 is enabled in editwnd.cpp -- Things might be screwy till it's all debugged?")
  12. #endif
  13. # include <bfc/string/encodedstr.h>
  14. #endif
  15. #ifdef WIN32
  16. #include <commctrl.h>
  17. #endif
  18. #ifdef WIN32
  19. static LRESULT CALLBACK static_editWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  20. {
  21. EditWnd *editwnd = (EditWnd *)GetWindowLongPtrW(hWnd, GWLP_USERDATA);
  22. if (editwnd == NULL) return DefWindowProcW(hWnd, uMsg, wParam, lParam);
  23. return editwnd->editWndProc(hWnd, uMsg, wParam, lParam);
  24. }
  25. #endif
  26. EditWnd::EditWnd(wchar_t *buffer, int buflen)
  27. {
  28. wantfocus = 1;
  29. nextenterfaked = 0;
  30. idleenabled = 1;
  31. beforefirstresize = 1;
  32. editWnd = NULL;
  33. prevWndProc = NULL;
  34. setBuffer(buffer, buflen);
  35. maxlen = 0;
  36. retcode = EDITWND_RETURN_NOTHING;
  37. modal = 0;
  38. autoenter = 0;
  39. autoselect = 0;
  40. outbuf = NULL;
  41. // bordered = 0;
  42. idletimelen = IDLETIME;
  43. multiline = 0;
  44. readonly = 0;
  45. password = 0;
  46. autohscroll = 1;
  47. autovscroll = 1;
  48. vscroll = 0;
  49. #ifdef WIN32
  50. oldbrush = NULL;
  51. #endif
  52. #ifdef LINUX
  53. selstart = selend = 0;
  54. cursorpos = 0;
  55. selectmode = 0;
  56. viewstart = 0;
  57. #endif
  58. #ifdef WASABI_EDITWND_LISTCOLORS
  59. if (WASABI_API_SKIN->skin_getColorElementRef(L"wasabi.list.text"))
  60. textcolor = L"wasabi.list.text";
  61. else
  62. textcolor = L"wasabi.edit.text";
  63. if (WASABI_API_SKIN->skin_getColorElementRef(L"wasabi.list.background"))
  64. backgroundcolor = L"wasabi.list.background";
  65. else
  66. textcolor.setColor(WASABI_API_SKIN->skin_getBitmapColor(L"wasabi.list.background"));
  67. #else
  68. backgroundcolor = "wasabi.edit.background";
  69. textcolor = "wasabi.edit.text";
  70. #endif
  71. selectioncolor = L"wasabi.edit.selection";
  72. setVirtual(0);
  73. }
  74. EditWnd::~EditWnd()
  75. {
  76. killTimer(IDLETIMER);
  77. #ifdef WIN32
  78. if (oldbrush != NULL)
  79. DeleteObject(oldbrush);
  80. oldbrush = NULL;
  81. if (editWnd != NULL)
  82. {
  83. SetWindowLong(editWnd, GWLP_USERDATA, (LONG_PTR)0);
  84. SetWindowLongPtrW(editWnd, GWLP_WNDPROC, (LONG_PTR)prevWndProc);
  85. DestroyWindow(editWnd);
  86. }
  87. #endif
  88. notifyParent(ChildNotify::RETURN_CODE, retcode);
  89. }
  90. int EditWnd::onInit()
  91. {
  92. EDITWND_PARENT::onInit();
  93. #ifdef WIN32
  94. RECT r = clientRect();
  95. editWnd = CreateWindowW(L"EDIT", NULL,
  96. WS_CHILD
  97. | (autohscroll ? ES_AUTOHSCROLL : 0)
  98. | (readonly ? ES_READONLY : 0)
  99. | (multiline ? ES_MULTILINE : 0)
  100. | (password ? ES_PASSWORD : 0)
  101. | (autovscroll ? ES_AUTOVSCROLL : 0)
  102. | (vscroll ? WS_VSCROLL : 0),
  103. r.left, r.top, r.right - r.left, r.bottom - r.top,
  104. gethWnd(), (HMENU)ID_EDITCHILD,
  105. getOsModuleHandle(), NULL);
  106. ASSERT(editWnd != NULL);
  107. if ((maxlen != 0) && (outbuf != NULL))
  108. {
  109. setBuffer(outbuf, maxlen);
  110. }
  111. // stash a pointer to us
  112. SetWindowLongPtrW(editWnd, GWLP_USERDATA, (LONG_PTR)this);
  113. // subclass the edit control -- either by 8 or by 16
  114. prevWndProc = (WNDPROC)SetWindowLongPtrW(editWnd, GWLP_WNDPROC, (LONG_PTR)static_editWndProc);
  115. SendMessageW(editWnd, WM_SETFONT, (WPARAM)GetStockObject(ANSI_VAR_FONT), FALSE);
  116. ShowWindow(editWnd, !getStartHidden() ? SW_NORMAL : SW_HIDE);
  117. #endif
  118. return 1;
  119. }
  120. void EditWnd::onSetVisible(int show)
  121. {
  122. EDITWND_PARENT::onSetVisible(show);
  123. if (editWnd == NULL) return ;
  124. #ifdef WIN32
  125. ShowWindow(editWnd, show ? SW_NORMAL : SW_HIDE);
  126. #endif
  127. }
  128. int EditWnd::onPaint(Canvas *canvas)
  129. {
  130. // if (!bordered) return EDITWND_PARENT::onPaint(canvas);
  131. PaintCanvas paintcanvas;
  132. if (canvas == NULL)
  133. {
  134. if (!paintcanvas.beginPaint(this)) return 0;
  135. canvas = &paintcanvas;
  136. }
  137. EDITWND_PARENT::onPaint(canvas);
  138. RECT r;
  139. getClientRect(&r);
  140. canvas->fillRect(&r, backgroundcolor); //SKIN
  141. #ifdef LINUX
  142. char *str = STRDUP((const char *)inbuf + viewstart);
  143. canvas->setTextColor(textcolor);
  144. canvas->setTextSize(r.bottom - r.top);
  145. canvas->setTextOpaque(FALSE);
  146. char save;
  147. if (selstart != selend)
  148. {
  149. RECT selrect = r;
  150. int start = MAX(MIN(selstart, selend) - viewstart, 0);
  151. int end = MAX(MAX(selstart, selend) - viewstart, 0);
  152. save = str[ start ];
  153. str[start] = '\0';
  154. selrect.left = r.left + canvas->getTextWidth(str);
  155. str[start] = save;
  156. save = str[ end ];
  157. str[end] = '\0';
  158. selrect.right = r.left + canvas->getTextWidth(str);
  159. str[end] = save;
  160. canvas->fillRect(&selrect, selectioncolor);
  161. }
  162. save = str[cursorpos - viewstart];
  163. str[cursorpos - viewstart] = '\0';
  164. RECT cursor = r;
  165. cursor.left = cursor.right = r.left + canvas->getTextWidth(str);
  166. str[cursorpos - viewstart] = save;
  167. canvas->drawRect(&cursor, TRUE, 0xffffff);
  168. canvas->textOut(r.left, r.top, r.right - r.left, r.bottom - r.top, str);
  169. FREE(str);
  170. #endif
  171. return 1;
  172. }
  173. int EditWnd::onResize()
  174. {
  175. EDITWND_PARENT::onResize();
  176. #ifdef WIN32
  177. RECT r = clientRect();
  178. if (1 /*bordered*/)
  179. {
  180. r.top++;
  181. r.bottom--;
  182. r.left++;
  183. r.right--;
  184. }
  185. MoveWindow(editWnd, r.left, r.top, r.right - r.left, r.bottom - r.top, TRUE);
  186. if (beforefirstresize)
  187. {
  188. ShowWindow(editWnd, SW_NORMAL); beforefirstresize = 0;
  189. if (modal)
  190. {
  191. SetFocus(editWnd);
  192. if (getAutoSelect())
  193. SendMessageW(editWnd, EM_SETSEL, 0, -1);
  194. }
  195. }
  196. #endif
  197. return TRUE;
  198. }
  199. #ifdef WIN32
  200. LRESULT EditWnd::wndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  201. {
  202. switch (uMsg)
  203. {
  204. case WM_CTLCOLOREDIT:
  205. {
  206. HDC hdc = (HDC)wParam;
  207. SetTextColor(hdc, textcolor);
  208. SetBkColor(hdc, backgroundcolor);
  209. if (oldbrush != NULL)
  210. {
  211. DeleteObject(oldbrush);
  212. oldbrush = NULL;
  213. }
  214. oldbrush = CreateSolidBrush(backgroundcolor);
  215. return (LRESULT)oldbrush;
  216. }
  217. case WM_MOUSEACTIVATE:
  218. WASABI_API_WND->popupexit_check(this);
  219. break;
  220. case WM_COMMAND:
  221. {
  222. switch (HIWORD(wParam))
  223. {
  224. case EN_CHANGE:
  225. {
  226. if (maxlen > 0)
  227. {
  228. GetWindowTextW(editWnd, outbuf, maxlen);
  229. onEditUpdate();
  230. }
  231. }
  232. break;
  233. case EN_SETFOCUS:
  234. if (getAutoSelect())
  235. SendMessageW(editWnd, EM_SETSEL, (WPARAM)0, (LPARAM) - 1);
  236. break;
  237. case EN_KILLFOCUS:
  238. onLoseFocus();
  239. break;
  240. }
  241. }
  242. break;
  243. }
  244. return EDITWND_PARENT::wndProc(hWnd, uMsg, wParam, lParam);
  245. }
  246. #endif
  247. void EditWnd::setBuffer(wchar_t *buffer, int len)
  248. {
  249. #ifdef LINUX
  250. if (buffer == NULL || len <= 1)
  251. {
  252. inbuf = "";
  253. return ;
  254. }
  255. #endif
  256. if (buffer == NULL || len <= 1) return ;
  257. ASSERT(len > 1);
  258. ASSERT(len < 0x7ffe);
  259. ASSERT((int)wcslen(buffer) <= len);
  260. #ifdef WIN32
  261. #define USE_INTERNAL_BUFFER 0
  262. #if USE_INTERNAL_BUFFER
  263. buffer8.setSize(len + 1);
  264. outbuf = buffer8.getMemory();
  265. if (len)
  266. {
  267. STRNCPY(outbuf, buffer, len);
  268. }
  269. outbuf[len] = 0;
  270. #else
  271. outbuf = buffer;
  272. #endif
  273. if (editWnd != NULL)
  274. {
  275. SetWindowTextW(editWnd, buffer);
  276. // This is going to be problematic. This is where utf8 sucks.
  277. // Just how many characters CAN we save in our buffer, eh?
  278. // (shrug) Oh well. Can't be helped. At most this many.
  279. SendMessageW(editWnd, EM_LIMITTEXT, (WPARAM)len - 1, (LPARAM)0);
  280. // hooray for halcyon7
  281. /* if (getAutoSelect()) {
  282. SetFocus(editWnd);
  283. SendMessageW(editWnd, EM_SETSEL, (WPARAM)0, (LPARAM)-1);
  284. }*/
  285. }
  286. maxlen = len;
  287. #else
  288. outbuf = buffer;
  289. maxlen = len;
  290. inbuf = buffer;
  291. cursorpos = len;
  292. invalidate();
  293. #endif
  294. }
  295. void EditWnd::selectAll()
  296. {
  297. #ifdef WIN32
  298. PostMessage(editWnd, EM_SETSEL, 0, -1);
  299. #else
  300. selstart = 0; selend = inbuf.len();
  301. #endif
  302. }
  303. void EditWnd::enter()
  304. {
  305. onEnter();
  306. }
  307. void EditWnd::getBuffer(wchar_t *buf, int _len)
  308. {
  309. if (_len > maxlen) _len = maxlen;
  310. // SendMessageW(editWnd, WM_GETTEXT, (WPARAM)_len, (LPARAM)buf);
  311. WCSCPYN(buf, outbuf, _len);
  312. }
  313. void EditWnd::setModal(int _modal)
  314. {
  315. modal = _modal;
  316. }
  317. void setBorder(int border)
  318. {
  319. // bordered = border;
  320. }
  321. int EditWnd::isEditorKey(int vk)
  322. {
  323. if (vk >= VK_F1) return 0;
  324. if ((vk == VK_UP || vk == VK_DOWN) || ((Std::keyDown(VK_CONTROL) || Std::keyDown(VK_MENU)) && (vk == VK_LEFT || vk == VK_RIGHT)))
  325. return 0;
  326. if (vk == VK_RETURN && Std::keyDown(VK_CONTROL)) return 0;
  327. if (vk == VK_CONTROL || vk == VK_MENU) return 0;
  328. return 1;
  329. }
  330. LRESULT EditWnd::editWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  331. {
  332. switch (uMsg)
  333. {
  334. case WM_KEYDOWN:
  335. if (!isEditorKey((int)wParam) && !onKeyDown((int)wParam))
  336. {
  337. #ifdef WASABI_COMPILE_WND
  338. WASABI_API_WND->forwardOnKeyDown(this, (int) wParam, (int)lParam);
  339. #endif
  340. }
  341. break;
  342. case WM_KEYUP:
  343. if (!isEditorKey((int)wParam) && !onKeyUp((int)wParam))
  344. {
  345. #ifdef WASABI_COMPILE_WND
  346. WASABI_API_WND->forwardOnKeyUp(this, (int) wParam, (int)lParam);
  347. #endif
  348. }
  349. break;
  350. case WM_CHAR:
  351. if (!(wParam == VK_RETURN && nextenterfaked && !autoenter))
  352. {
  353. notifyParent(ChildNotify::EDITWND_KEY_PRESSED, wParam);
  354. onChar((TCHAR)wParam);
  355. }
  356. if (wParam == VK_RETURN)
  357. {
  358. if (!(nextenterfaked && !autoenter))
  359. if (onEnter()) return 0;
  360. nextenterfaked = 0;
  361. return 0;
  362. }
  363. else if (wParam == VK_ESCAPE)
  364. {
  365. if (onAbort()) return 0;
  366. }
  367. else if (wParam == VK_TAB && multiline)
  368. {
  369. return 0;
  370. }
  371. break;
  372. case WM_SETFOCUS:
  373. onSetRootFocus(this);
  374. // fall thru
  375. case WM_KILLFOCUS:
  376. invalidate();
  377. break;
  378. }
  379. #ifdef WIN32
  380. return CallWindowProc(prevWndProc, hWnd, uMsg, wParam, lParam);
  381. #else
  382. DebugString("portme -- EditWnd::editWndProc\n");
  383. return 0;
  384. #endif
  385. }
  386. void EditWnd::timerCallback(int id)
  387. {
  388. switch (id)
  389. {
  390. case IDLETIMER:
  391. killTimer(IDLETIMER);
  392. if (idleenabled) onIdleEditUpdate();
  393. break;
  394. case DELETETIMER:
  395. killTimer(DELETETIMER);
  396. delete this;
  397. break;
  398. default:
  399. EDITWND_PARENT::timerCallback(id);
  400. }
  401. }
  402. void EditWnd::onEditUpdate()
  403. {
  404. #ifdef LINUX
  405. STRNCPY(outbuf, inbuf, maxlen);
  406. outbuf[maxlen] = '\0';
  407. RECT r;
  408. getClientRect(&r);
  409. SysCanvas sysc;
  410. sysc.setTextSize(r.bottom - r.top);
  411. sysc.getTextWidth(inbuf);
  412. char *str = STRDUP(inbuf);
  413. if (cursorpos < viewstart)
  414. viewstart = cursorpos;
  415. char save = str[cursorpos];
  416. str[cursorpos] = '\0';
  417. while (sysc.getTextWidth(str + viewstart) > r.right - r.left)
  418. {
  419. viewstart++;
  420. }
  421. str[cursorpos] = save;
  422. invalidate();
  423. #endif
  424. killTimer(IDLETIMER);
  425. setTimer(IDLETIMER, idletimelen);
  426. notifyParent(ChildNotify::EDITWND_DATA_MODIFIED);
  427. }
  428. void EditWnd::onIdleEditUpdate()
  429. {
  430. notifyParent(ChildNotify::EDITWND_DATA_MODIFIED_ONIDLE);
  431. }
  432. int EditWnd::onEnter()
  433. {
  434. notifyParent(ChildNotify::EDITWND_ENTER_PRESSED);
  435. if (modal)
  436. {
  437. retcode = EDITWND_RETURN_OK;
  438. delete this;
  439. //CUT setTimer(DELETETIMER, 1);
  440. return 1;
  441. }
  442. return 0;
  443. }
  444. int EditWnd::onAbort()
  445. {
  446. notifyParent(ChildNotify::EDITWND_CANCEL_PRESSED);
  447. if (modal)
  448. {
  449. retcode = EDITWND_RETURN_CANCEL;
  450. delete this;
  451. //CUT setTimer(DELETETIMER, 1);
  452. return 1;
  453. }
  454. return 0;
  455. }
  456. int EditWnd::onLoseFocus()
  457. { // fake an onEnter()
  458. #ifdef WIN32
  459. if (autoenter)
  460. {
  461. nextenterfaked = 1;
  462. PostMessage(editWnd, WM_CHAR, VK_RETURN, 0);
  463. }
  464. #else
  465. invalidate();
  466. selstart = selend = 0;
  467. #endif
  468. return 0;
  469. }
  470. void EditWnd::setAutoEnter(int a)
  471. {
  472. autoenter = a;
  473. }
  474. void EditWnd::setAutoSelect(int a)
  475. {
  476. autoselect = a;
  477. };
  478. void EditWnd::setIdleTimerLen(int ms)
  479. {
  480. if (ms < 0) ms = 0;
  481. idletimelen = ms;
  482. }
  483. int EditWnd::getTextLength()
  484. { // TOTALLY NONPORTABLE AND TOTALLY DIRTY
  485. #ifdef WIN32
  486. HFONT font = (HFONT)SendMessageW(editWnd, WM_GETFONT, 0, 0);
  487. HDC sdc = GetDC(NULL);
  488. HDC dc = CreateCompatibleDC(sdc);
  489. ReleaseDC(NULL, sdc);
  490. HFONT oldfont = (HFONT)SelectObject(dc, font);
  491. SIZE s;
  492. GetTextExtentPoint32W(dc, outbuf, wcslen(outbuf), &s);
  493. SelectObject(dc, oldfont);
  494. DeleteDC(dc);
  495. return s.cx + SendMessageW(editWnd, EM_GETMARGINS, 0, 0)*2 + 2;
  496. #else
  497. if (inbuf.isempty())
  498. return 0;
  499. RECT r;
  500. getClientRect(&r);
  501. SysCanvas sysc;
  502. sysc.setTextSize(r.bottom - r.top);
  503. return sysc.getTextWidth(inbuf);
  504. #endif
  505. }
  506. HWND EditWnd::getEditWnd()
  507. {
  508. return editWnd;
  509. }
  510. #ifndef WIN32
  511. enum {
  512. ES_MULTILINE,
  513. ES_WANTRETURN,
  514. ES_AUTOHSCROLL,
  515. ES_AUTOVSCROLL,
  516. WS_VSCROLL,
  517. };
  518. #endif
  519. void EditWnd::setMultiline(int ml)
  520. {
  521. multiline = ml;
  522. setStyle(ES_MULTILINE | ES_WANTRETURN, ml);
  523. }
  524. void EditWnd::setReadOnly(int ro)
  525. {
  526. readonly = ro;
  527. setStyle(ES_READONLY, ro);
  528. }
  529. void EditWnd::setPassword(int pw)
  530. {
  531. password = pw;
  532. setStyle(ES_PASSWORD, pw);
  533. }
  534. void EditWnd::setAutoHScroll(int hs)
  535. {
  536. autohscroll = hs;
  537. setStyle(ES_AUTOHSCROLL, hs);
  538. }
  539. void EditWnd::setAutoVScroll(int vs)
  540. {
  541. autovscroll = vs;
  542. setStyle(ES_AUTOVSCROLL, vs);
  543. }
  544. void EditWnd::setVScroll(int vs)
  545. {
  546. vscroll = vs;
  547. setStyle(WS_VSCROLL, vs);
  548. }
  549. void EditWnd::setStyle(LONG style, int set)
  550. {
  551. #ifdef WIN32
  552. if (editWnd)
  553. {
  554. LONG s = GetWindowLong(editWnd, GWL_STYLE);
  555. if (set) s |= style;
  556. else s &= ~style;
  557. SetWindowLong(editWnd, GWL_STYLE, s);
  558. }
  559. #else
  560. DebugString("portme -- EditWnd::setStyle\n");
  561. #endif
  562. }
  563. int EditWnd::onGetFocus()
  564. {
  565. int r = EDITWND_PARENT::onGetFocus();
  566. #ifdef WIN32
  567. if (editWnd != NULL)
  568. SetFocus(editWnd);
  569. #endif
  570. return r;
  571. }
  572. int EditWnd::wantFocus()
  573. {
  574. return wantfocus;
  575. }
  576. int EditWnd::gotFocus()
  577. {
  578. return (GetFocus() == editWnd);
  579. }
  580. void EditWnd::setBackgroundColor(COLORREF c)
  581. {
  582. backgroundcolor.setColor(c);
  583. }
  584. void EditWnd::setTextColor(COLORREF c)
  585. {
  586. textcolor.setColor(c);
  587. }
  588. void EditWnd::invalidate()
  589. {
  590. EDITWND_PARENT::invalidate();
  591. InvalidateRect(editWnd, NULL, TRUE);
  592. }
  593. #ifdef LINUX
  594. int EditWnd::textposFromCoord(int x, int y)
  595. {
  596. RECT r;
  597. getClientRect(&r);
  598. SysCanvas canvas;
  599. canvas.setTextColor(textcolor);
  600. canvas.setTextSize(r.bottom - r.top);
  601. canvas.setTextOpaque(FALSE);
  602. x -= r.left;
  603. int i;
  604. char *str = STRDUP(inbuf);
  605. if (x > canvas.getTextWidth(str + viewstart))
  606. return inbuf.len();
  607. for (i = viewstart + 1; str[i]; i++)
  608. {
  609. char save = str[i];
  610. str[i] = '\0';
  611. if (x < canvas.getTextWidth(str + viewstart))
  612. {
  613. str[i] = save;
  614. break;
  615. }
  616. str[i] = save;
  617. }
  618. FREE(str);
  619. return i - 1;
  620. }
  621. int EditWnd::onLeftButtonDown(int x, int y)
  622. {
  623. EDITWND_PARENT::onLeftButtonDown(x, y);
  624. // Add check for double/triple click...
  625. cursorpos = textposFromCoord(x, y);
  626. selstart = selend = cursorpos;
  627. selectmode = 1;
  628. return 1;
  629. }
  630. int EditWnd::onLeftButtonUp(int x, int y)
  631. {
  632. EDITWND_PARENT::onLeftButtonUp(x, y);
  633. selectmode = 0;
  634. return 1;
  635. }
  636. int EditWnd::onMouseMove(int x, int y)
  637. {
  638. EDITWND_PARENT::onMouseMove(x, y);
  639. switch (selectmode)
  640. {
  641. case 0:
  642. // Do nothing
  643. break;
  644. case 1:
  645. selend = textposFromCoord(x, y);
  646. cursorpos = selend;
  647. onEditUpdate();
  648. break;
  649. default:
  650. DebugString("selectmode %d not available\n", selectmode);
  651. break;
  652. }
  653. return selectmode;
  654. }
  655. int EditWnd::onKeyDown(int key)
  656. {
  657. EDITWND_PARENT::onKeyDown(key);
  658. if (Std::keyDown(VK_CONTROL))
  659. {
  660. switch (key)
  661. {
  662. case 'a':
  663. case 'A':
  664. selectAll();
  665. break;
  666. default:
  667. return 0;
  668. }
  669. }
  670. else
  671. {
  672. switch (key)
  673. {
  674. case XK_Home:
  675. if (Std::keyDown(VK_SHIFT))
  676. {
  677. if (selstart == selend)
  678. {
  679. selstart = selend = cursorpos;
  680. }
  681. selend = 0;
  682. }
  683. else
  684. {
  685. selstart = selend = 0;
  686. }
  687. cursorpos = 0;
  688. break;
  689. case XK_End:
  690. if (Std::keyDown(VK_SHIFT))
  691. {
  692. if (selstart == selend)
  693. {
  694. selstart = selend = cursorpos;
  695. }
  696. selend = inbuf.len();
  697. }
  698. else
  699. {
  700. selstart = selend = 0;
  701. }
  702. cursorpos = inbuf.len();
  703. break;
  704. case XK_Right:
  705. if (Std::keyDown(VK_SHIFT))
  706. {
  707. if (selstart == selend)
  708. {
  709. selstart = selend = cursorpos;
  710. }
  711. selend++;
  712. if (selend > inbuf.len()) selend = inbuf.len();
  713. }
  714. else
  715. {
  716. selstart = selend = 0;
  717. }
  718. cursorpos++;
  719. if (cursorpos > inbuf.len()) cursorpos = inbuf.len();
  720. break;
  721. case XK_Left:
  722. if (Std::keyDown(VK_SHIFT))
  723. {
  724. if (selstart == selend)
  725. {
  726. selstart = selend = cursorpos;
  727. }
  728. selend--;
  729. if (selend < 0) selend = 0;
  730. }
  731. else
  732. {
  733. selstart = selend = 0;
  734. }
  735. cursorpos--;
  736. if (cursorpos < 0) cursorpos = 0;
  737. break;
  738. case XK_Escape:
  739. onAbort();
  740. break;
  741. case XK_Return:
  742. onEnter();
  743. break;
  744. case XK_Delete:
  745. if (selstart != selend)
  746. {
  747. int start = MIN(selstart, selend);
  748. int end = MAX(selstart, selend);
  749. String add;
  750. if (end < inbuf.len())
  751. {
  752. add = (const char *)inbuf + end;
  753. }
  754. else
  755. {
  756. add = "";
  757. }
  758. inbuf.trunc(start);
  759. inbuf += add;
  760. cursorpos = start;
  761. selstart = selend = 0;
  762. }
  763. else
  764. {
  765. if (cursorpos >= 0)
  766. {
  767. if (cursorpos < inbuf.len() - 1)
  768. {
  769. String tmp = inbuf;
  770. tmp.trunc(cursorpos);
  771. inbuf = tmp + ((const char *)inbuf + cursorpos + 1);
  772. }
  773. else if (cursorpos == inbuf.len() - 1)
  774. {
  775. inbuf.trunc(cursorpos);
  776. }
  777. }
  778. }
  779. break;
  780. case VK_BACK:
  781. if (selstart != selend)
  782. {
  783. int start = MIN(selstart, selend);
  784. int end = MAX(selstart, selend);
  785. String add;
  786. if (end < inbuf.len())
  787. {
  788. add = (const char *)inbuf + end;
  789. }
  790. else
  791. {
  792. add = "";
  793. }
  794. inbuf.trunc(start);
  795. inbuf += add;
  796. cursorpos = start;
  797. selstart = selend = 0;
  798. }
  799. else
  800. {
  801. if (cursorpos > 0)
  802. {
  803. if (cursorpos >= inbuf.len())
  804. {
  805. inbuf.trunc(cursorpos - 1);
  806. cursorpos--;
  807. }
  808. else
  809. {
  810. String tmp = inbuf;
  811. tmp.trunc(cursorpos - 1);
  812. inbuf = tmp + ((const char *)inbuf + cursorpos);
  813. cursorpos--;
  814. }
  815. }
  816. }
  817. break;
  818. default:
  819. if (key < 0x20 || key > 0x7e)
  820. return 0;
  821. if (selstart != selend)
  822. {
  823. int start = MIN(selstart, selend);
  824. int end = MAX(selstart, selend);
  825. String add;
  826. if (end < inbuf.len())
  827. {
  828. add = (const char *)inbuf + end;
  829. }
  830. else
  831. {
  832. add = "";
  833. }
  834. inbuf.trunc(start);
  835. inbuf += add;
  836. cursorpos = start;
  837. selstart = selend = 0;
  838. }
  839. String tmp;
  840. if (cursorpos >= inbuf.len())
  841. {
  842. tmp = "";
  843. }
  844. else
  845. {
  846. tmp = (const char *)inbuf + cursorpos;
  847. }
  848. inbuf.trunc(cursorpos);
  849. inbuf += (char)key;
  850. inbuf += tmp;
  851. cursorpos++;
  852. }
  853. }
  854. onEditUpdate();
  855. return 1;
  856. }
  857. #endif