edit.cpp 27 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018
  1. ////////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright 2016 RWS Inc, All Rights Reserved
  4. //
  5. // This program is free software; you can redistribute it and/or modify
  6. // it under the terms of version 2 of the GNU General Public License as published by
  7. // the Free Software Foundation
  8. //
  9. // This program is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU General Public License for more details.
  13. //
  14. // You should have received a copy of the GNU General Public License along
  15. // with this program; if not, write to the Free Software Foundation, Inc.,
  16. // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  17. //
  18. //////////////////////////////////////////////////////////////////////////////
  19. //
  20. // EDIT.CPP
  21. //
  22. // History:
  23. // 08/15/96 JMI Started.
  24. //
  25. // 09/24/96 JMI Changed all BLU_MB?_* macros to RSP_MB?_* macros.
  26. //
  27. // 10/02/96 JMI No longer checks ms_szText for NULL before calling
  28. // m_print stuff and updating m_aptTextPos.
  29. //
  30. // 10/27/96 MJR Fixed "unused variable" warnings.
  31. //
  32. // 10/31/96 JMI Changed:
  33. // Old label: New label:
  34. // ========= =========
  35. // CEdit REdit
  36. // CTxt RTxt
  37. // CImage RImage
  38. // CGuiItem RGuiItem
  39. // LEFT RGuiItem::Left
  40. // MULTILINE Multiline
  41. // NUMBERS_ONLY NumbersOnly
  42. // POINT Point
  43. // EDITNOTIFY EditNotify
  44. //
  45. // Moved #include <string.h> to the beginning.
  46. //
  47. // 10/30/96 JMI Changed:
  48. // Old label: New label:
  49. // ========= =========
  50. // Rect RRect
  51. //
  52. // 11/12/96 MJR Added RSP_ prefix to GK keyboard macros.
  53. //
  54. // 11/14/96 JMI DrawText() now attempts to clip the string to the edit
  55. // box.
  56. //
  57. // 11/27/96 JMI Added initialization of m_type to identify this type
  58. // of GUI item.
  59. //
  60. // 12/04/96 JMI Do() can no longer optionally poll for input, does not
  61. // call rspGetKey(), and does not return that key. Instead,
  62. // you pass the a pointer to the rspGetKeys() formatted key
  63. // you want Do() to process. The key will be zeroed if it
  64. // is "absorbed" by the edit box.
  65. //
  66. // 12/19/96 JMI Uses new m_justification (as m_sJustification) and
  67. // upgraded to new RFont/RPrint.
  68. //
  69. // 12/31/96 JMI Do() now calls base implementation in RGuiItem.
  70. //
  71. // 01/01/97 JMI DrawText() now draws a space with transparent back and
  72. // foreground colors so that the positions array will be
  73. // updated so we can use the caret position.
  74. // Also, now clips caret.
  75. //
  76. // 01/04/97 JMI Upgraded HotCall() to new CursorEvent(). This upgrade
  77. // is in response to RGuiItem now using relative RHots.
  78. // Now m_hot.m_sX/Y is parent item relative just like
  79. // m_sX/Y. This should simplify a lot of stuff and even
  80. // fix some odd features like being able to click a GUI
  81. // item that exceeds the boundary of its parent. This fix
  82. // will be essential for the not-yet-existent RListBox since
  83. // it will most likely scroll many children through a small
  84. // client area.
  85. // Now there are two regions associated with cursor events.
  86. // The first is the 'hot' area. This is the area that m_hot
  87. // is set to include. Child items can only receive cursor
  88. // events through this area. The second is the 'event' area.
  89. // This is the area where the item really is actually con-
  90. // cerned with cursor events. Example: For a Dlg, the
  91. // entire window is the 'hot' area and the title bar is the
  92. // 'event' area.
  93. //
  94. // 01/08/97 JMI There were some typos in Draw() involving clipping.
  95. // Fixed.
  96. //
  97. // 01/18/97 JMI Converted Do() to take an RInputEvent* instead of a
  98. // long*.
  99. //
  100. // 01/20/97 JMI Made very few changes for overriding Read/WriteMembers.
  101. // Should not change functionality. Checked in to use at
  102. // home.
  103. //
  104. // 01/21/97 JMI Added ReadMembers() and WriteMembers() overloads to read
  105. // and write members of this class. Note that they call the
  106. // base class version to read/write base class members.
  107. // Support exists for versions 0 and 1. Version 0 did not
  108. // contain other than RGuiItem members.
  109. //
  110. // 01/23/97 JMI Added escape to keys we don't want to process during Do().
  111. //
  112. // 01/23/97 JMI Now sets m_sShowFocus to FALSE in constructor. Focus is
  113. // shown via caret anyhow.
  114. //
  115. // 02/05/97 JMI Changed position of default: case in ReadMembers().
  116. //
  117. // 03/14/97 JMI Added ClipCaret().
  118. //
  119. // 03/19/97 JMI Converted to using the RHot::m_iecUser (was using
  120. // RHot::m_epcUser) so HotCall and CursorEvent now take
  121. // RInputEvent ptrs.
  122. //
  123. // 03/28/97 JMI RSP_MB0_DOUBLECLICK is now treated the same as
  124. // RSP_MB0_PRESSED.
  125. //
  126. // 04/10/97 JMI DrawText() considers new m_sFontCellHeight member.
  127. // Now uses m_sFontCellHeight instead of GetPos() to get
  128. // cell height.
  129. //
  130. // 04/24/97 JMI Added m_u32TextShadowColor.
  131. //
  132. // 07/07/97 JMI Now calls SetTextEffects() before drawing text in
  133. // DrawText() and Draw().
  134. //
  135. // 08/25/97 JMI Added m_sFirstVisibleCharIndex which is the first visible
  136. // character in the field.
  137. // Now automagically scrolls left or right based on caret
  138. // positions.
  139. //
  140. // 08/25/97 JMI Was not handling the case where the text was truncated by
  141. // an outside source. Now handled by calling ClipCaret() in
  142. // DrawText().
  143. //
  144. // 08/25/97 JMI Added macros to define extra space on each side of text
  145. // in the edit field to make sure it doesn't butt up against
  146. // stuff.
  147. // Also, effects, justification, size, and word-wrappage
  148. // were not being set before drawing the caret in Draw().
  149. //
  150. // 08/25/97 JMI Now scrolls half the field to the left if the caret
  151. // passes the left edge (used to only scroll one character).
  152. //
  153. // 08/30/97 JMI Now repaginates if the caret position is less than the
  154. // first visible character.
  155. //
  156. // 09/01/97 JMI Now Do() only functions if this is activated.
  157. //
  158. // 01/15/98 JMI Added numeric keypad support in Do().
  159. //
  160. //////////////////////////////////////////////////////////////////////////////
  161. //
  162. // This a GUI item that is based on the CTxt item.
  163. // This overrides CursorEvent() to get information about where a click it
  164. // occurred.
  165. // This overrides DrawText() to store the postion of each character.
  166. // This overrides Draw() to add a cursor.
  167. //
  168. // Enhancements/Uses:
  169. // To change the look of the text, you may want to override DrawText()
  170. // in a derived class or see CTxt for other overridables
  171. // To change the background of the text item, see CGuiItem.
  172. // To get a callback on a click/release pair in the text item, see CTxt.
  173. //
  174. //////////////////////////////////////////////////////////////////////////////
  175. //////////////////////////////////////////////////////////////////////////////
  176. // Headers.
  177. //////////////////////////////////////////////////////////////////////////////
  178. #include <string.h>
  179. #include "Blue.h"
  180. #ifdef PATHS_IN_INCLUDES
  181. #include "ORANGE/GUI/edit.h"
  182. #else
  183. #include "edit.h"
  184. #endif // PATHS_IN_INCLUDES
  185. //////////////////////////////////////////////////////////////////////////////
  186. // Module specific macros.
  187. //////////////////////////////////////////////////////////////////////////////
  188. // Sets val to def if val is -1.
  189. #define DEF(val, def) ((val == -1) ? def : val)
  190. // Number of pixels to reserve as non-client on each vertical edge.
  191. #define VERT_EDGE_RESERVED 1
  192. #define EXTRA_NONCLIENT_EDGE (m_sShowFocus ? m_sBorderThickness + VERT_EDGE_RESERVED : VERT_EDGE_RESERVED)
  193. //////////////////////////////////////////////////////////////////////////////
  194. // Module specific typedefs.
  195. //////////////////////////////////////////////////////////////////////////////
  196. //////////////////////////////////////////////////////////////////////////////
  197. // Module specific (static) variables.
  198. //////////////////////////////////////////////////////////////////////////////
  199. //////////////////////////////////////////////////////////////////////////////
  200. // Construction/Destruction.
  201. //////////////////////////////////////////////////////////////////////////////
  202. //////////////////////////////////////////////////////////////////////////////
  203. //
  204. // Default constructor.
  205. //
  206. //////////////////////////////////////////////////////////////////////////////
  207. REdit::REdit()
  208. {
  209. ///////////////////////////////////////////////////////////////////////////
  210. // Defaults:
  211. ///////////////////////////////////////////////////////////////////////////
  212. m_cCaretChar = '_'; // Character to use as caret.
  213. m_u32CaretColor = 255; // Color to use for caret.
  214. m_sCaretPos = 0; // Text position of caret.
  215. m_lCaretBlinkRate = 500; // Rate at which character blinks in ms. Can be
  216. // 0 indicating no blinkage.
  217. m_sMaxText = GUI_MAX_STR; // Maximum text to allow. Limited to
  218. // GUI_MAX_STR.
  219. m_sBehavior = 0; // Flags. See enums in header.
  220. m_encCall = NULL; // Callback when a user input notification
  221. // should occur such as too much input or
  222. // invalid character generated (e.g., alphas
  223. // in NUMBERS_ONLY mode). A good place to
  224. // generate a beep or something.
  225. m_lNextCaretUpdate = 0; // Time in ms of next caret update.
  226. m_sCaretState = 0; // Current state the caret is in until
  227. // m_lNextCaretUpdate. (0 == hidden,
  228. // 1 == shown).
  229. m_sInvertedBorder = TRUE; // Override RGuiItem's default.
  230. m_type = Edit; // Indicates type of GUI item.
  231. m_sShowFocus = FALSE; // Focus is shown via the caret.
  232. m_sFirstVisibleCharIndex = 0; // First visible char in field.
  233. }
  234. //////////////////////////////////////////////////////////////////////////////
  235. //
  236. // Destructor.
  237. //
  238. //////////////////////////////////////////////////////////////////////////////
  239. REdit::~REdit()
  240. {
  241. }
  242. ////////////////////////////////////////////////////////////////////////
  243. // Methods.
  244. ////////////////////////////////////////////////////////////////////////
  245. ////////////////////////////////////////////////////////////////////////
  246. //
  247. // Draw this item and all its subitems into the provided RImage.
  248. // This override adds in the caret.
  249. //
  250. ////////////////////////////////////////////////////////////////////////
  251. short REdit::Draw( // Returns 0 on success.
  252. RImage* pimDst, // Destination image.
  253. short sDstX /*= 0*/, // X position in destination.
  254. short sDstY /*= 0*/, // Y position in destination.
  255. short sSrcX /*= 0*/, // X position in source.
  256. short sSrcY /*= 0*/, // Y position in source.
  257. short sW /*= 0*/, // Amount to draw.
  258. short sH /*= 0*/, // Amount to draw.
  259. RRect* prc /*= NULL*/) // Clip to.
  260. {
  261. short sRes = 0; // Assume success.
  262. // If visible . . .
  263. if (m_sVisible != FALSE)
  264. {
  265. // Call the base class.
  266. sRes = RGuiItem::Draw( pimDst, sDstX, sDstY,
  267. sSrcX, sSrcY, sW, sH, prc);
  268. // If the caret is shown . . .
  269. if (m_sCaretState != 0)
  270. {
  271. // Make sure the caret is inside the string.
  272. ClipCaret();
  273. // If the caret is less than the first visible index (this can happen
  274. // if an outside party sets the caret position) . . .
  275. if (m_sCaretPos < m_sFirstVisibleCharIndex)
  276. {
  277. // We'll need to 'repaginate' the field.
  278. Compose();
  279. }
  280. // Setup printer ////////////////////////////////
  281. // Word wrap must be off.
  282. short sWordWrapWas = (m_pprint->m_eModes & RPrint::WORD_WRAP) ? TRUE : FALSE;
  283. m_pprint->SetWordWrap(FALSE);
  284. // Text support is currently 8 bit only.
  285. m_pprint->SetColor((short)m_u32CaretColor, (short)0, (short)m_u32TextShadowColor);
  286. m_pprint->SetFont(m_sFontCellHeight);
  287. SetJustification();
  288. SetTextEffects();
  289. m_pprint->SetDestination(pimDst);
  290. // Done setting up printer //////////////////////
  291. short sClientX, sClientY, sClientW, sClientH;
  292. GetClient(&sClientX, &sClientY, &sClientW, &sClientH);
  293. short sClipW, sClipH;
  294. if (sW == 0)
  295. {
  296. // Use client.
  297. sClipW = sClientW;
  298. }
  299. else
  300. {
  301. // Adjust by blt position.
  302. sClipW = sW - (sClientX + m_sX);
  303. }
  304. if (sH == 0)
  305. {
  306. // Use client.
  307. sClipH = sClientH;
  308. }
  309. else
  310. {
  311. // Adjust by blt position.
  312. sClipH = sH - (sClientY + m_sY);
  313. }
  314. // Clip.
  315. m_pprint->SetColumn(
  316. sDstX + m_sX + sClientX + EXTRA_NONCLIENT_EDGE,
  317. sDstY + m_sY + sClientY,
  318. sClipW - EXTRA_NONCLIENT_EDGE * 2,
  319. sClipH);
  320. ASSERT(m_sCaretPos - m_sFirstVisibleCharIndex >= 0);
  321. m_pprint->print(
  322. sDstX + m_sX + m_aptTextPos[m_sCaretPos - m_sFirstVisibleCharIndex].sX,
  323. sDstY + m_sY + m_aptTextPos[m_sCaretPos - m_sFirstVisibleCharIndex].sY,
  324. "%c", m_cCaretChar);
  325. // Restore printer //////////////////////////////
  326. m_pprint->SetWordWrap(sWordWrapWas);
  327. }
  328. }
  329. return sRes;
  330. }
  331. ////////////////////////////////////////////////////////////////////////
  332. //
  333. // Draw text in m_szText in m_u32TextColor with transparent
  334. // background at sX, sY with sW and m_sJustification.
  335. // The only additional functionality this has over RGuiItem::DrawText is
  336. // that it blts the characters one at a time and tracks the position of
  337. // each character in m_aptTextPos.
  338. // If m_szText is empty, a space is printed with the foreground and
  339. // background colors set to transparent. This way, the array of
  340. // positions is set for the caret.
  341. //
  342. ////////////////////////////////////////////////////////////////////////
  343. short REdit::DrawText( // Returns 0 on success.
  344. short sX, // X position in image.
  345. short sY, // Y position in image.
  346. short sW /*= 0*/, // Width of text area.
  347. short sH /*= 0*/, // Height of test area.
  348. RImage* pim /*= NULL*/) // Destination image. NULL == use m_im.
  349. {
  350. short sRes = 0; // Assume success.
  351. if (pim == NULL)
  352. {
  353. // Use internal image.
  354. pim = &m_im;
  355. }
  356. char* pszText;
  357. U32 u32ForeColor;
  358. if (m_szText[0] != '\0')
  359. {
  360. // Use user supplied text.
  361. pszText = m_szText;
  362. // Use user supplied color.
  363. u32ForeColor = m_u32TextColor;
  364. }
  365. else
  366. {
  367. // Use fake text and colors so that the positions
  368. // array is updated. It would be handy if the
  369. // print command would update the array even for
  370. // printing "". Then this would not be necessary.
  371. static char szSpace[] = " ";
  372. // Display space so that we can guarantee that the
  373. // character positions array will be updated.
  374. pszText = szSpace;
  375. // Use transparent color (just in case actually has
  376. // some pixels).
  377. u32ForeColor = 0;
  378. }
  379. // Text support is currently 8 bit only.
  380. m_pprint->SetColor(u32ForeColor, 0, m_u32TextShadowColor);
  381. // Set size. Hopefully this won't do too much scaling for
  382. // caching purposes but I'm not sure.
  383. m_pprint->SetFont(m_sFontCellHeight);
  384. // Only left justified editting supported . . .
  385. if (m_justification == RGuiItem::Left)
  386. {
  387. // Added in extra space before starting text.
  388. sX += EXTRA_NONCLIENT_EDGE;
  389. // Remove extra space before starting text.
  390. sW -= EXTRA_NONCLIENT_EDGE * 2;
  391. // Keep the caret within bounds.
  392. ClipCaret();
  393. SetJustification();
  394. SetTextEffects();
  395. // Word wrap must be off.
  396. short sWordWrapWas = (m_pprint->m_eModes & RPrint::WORD_WRAP) ? TRUE : FALSE;
  397. m_pprint->SetWordWrap(FALSE);
  398. m_pprint->SetDestination(pim);
  399. m_pprint->SetColumn(sX, sY, sW, sH);
  400. m_pprint->GetWidth(pszText);
  401. long lLen = strlen(pszText);
  402. // Whenever the caret hits or passes the left edge, jump the first visible
  403. // character back.
  404. if (m_sCaretPos < m_sFirstVisibleCharIndex)
  405. {
  406. short sHalfWidth = sW / 2;
  407. // Go backward until we hit the beginning
  408. // or we get within half the field of the caret.
  409. while (m_sFirstVisibleCharIndex > 0)
  410. {
  411. if (m_pprint->ms_sCharPosX[m_sCaretPos] - m_pprint->ms_sCharPosX[m_sFirstVisibleCharIndex] >= sHalfWidth)
  412. {
  413. break;
  414. }
  415. m_sFirstVisibleCharIndex--;
  416. }
  417. }
  418. short sCaretWidth = m_pprint->GetBlitW(m_cCaretChar);
  419. // Whenever the caret hits or passes the right edge, jump the first
  420. // visible character forward.
  421. if (m_pprint->ms_sCharPosX[m_sCaretPos] - m_pprint->ms_sCharPosX[m_sFirstVisibleCharIndex] + sCaretWidth >= sW - EXTRA_NONCLIENT_EDGE)
  422. {
  423. short sHalfWidth = sW / 2;
  424. // Go forward until we hit the end
  425. // or we get within half the field of the caret.
  426. while (m_sFirstVisibleCharIndex < lLen)
  427. {
  428. if (m_pprint->ms_sCharPosX[m_sCaretPos] - m_pprint->ms_sCharPosX[m_sFirstVisibleCharIndex] <= sHalfWidth)
  429. {
  430. break;
  431. }
  432. m_sFirstVisibleCharIndex++;
  433. }
  434. }
  435. ASSERT(m_sFirstVisibleCharIndex <= lLen);
  436. ASSERT(m_sFirstVisibleCharIndex >= 0);
  437. m_pprint->print(sX, sY, "%s", pszText + m_sFirstVisibleCharIndex);
  438. REdit::Point* ppt = m_aptTextPos;
  439. long lIndex;
  440. for (lIndex = 0; lIndex < lLen; lIndex++, ppt++)
  441. {
  442. // Store its position in the pim.
  443. ppt->sX = m_pprint->ms_sCharPosX[lIndex];
  444. ppt->sY = sY; // Eventually will be available as above.
  445. }
  446. // Update last position for cursor.
  447. ppt->sX = m_pprint->ms_sCharPosX[lIndex];
  448. ppt->sY = sY; // Eventually will be available as above.
  449. m_pprint->SetWordWrap(sWordWrapWas);
  450. }
  451. else
  452. {
  453. TRACE("DrawText(): Only left justification supported by REdit "
  454. "currently.\n");
  455. sRes = -1;
  456. }
  457. return sRes;
  458. }
  459. ////////////////////////////////////////////////////////////////////////
  460. //
  461. // Does REdit stuff like check for keys, update caret, and add new
  462. // text.
  463. //
  464. ////////////////////////////////////////////////////////////////////////
  465. void REdit::Do( // Returns nothing.
  466. RInputEvent* pie) // In: Most recent user input event.
  467. // Out: pie->sUsed = TRUE, if used.
  468. {
  469. // Call base.
  470. RTxt::Do(pie);
  471. // Only if currenly active . . .
  472. if (IsActivated() != FALSE)
  473. {
  474. short sRedrawText = FALSE; // Redraw text if TRUE.
  475. short sRedrawItem = FALSE; // Redraw item if TRUE (for event driven
  476. // user).
  477. // If unused key event . . .
  478. if (pie->sUsed == FALSE && pie->type == RInputEvent::Key)
  479. {
  480. // Set the caret state to show.
  481. m_sCaretState = 1;
  482. // Get length of current text. Always handy.
  483. long lStrLen = strlen(m_szText);
  484. // Remember caret position.
  485. short sCaretPosIn = m_sCaretPos;
  486. // Char to add or 0.
  487. long lNewChar = 0;
  488. // Make sure the caret is inside the string.
  489. ClipCaret();
  490. // Switch on extended keys.
  491. switch (pie->lKey & 0x0000FF00)
  492. {
  493. case 0x00000000: // ASCII key.
  494. // Switch on ASCII key.
  495. switch (pie->lKey & 0x000000FF)
  496. {
  497. case '\b':
  498. if (m_sCaretPos > 0)
  499. {
  500. // Remove character at cursor.
  501. memmove( m_szText + m_sCaretPos - 1,
  502. m_szText + m_sCaretPos,
  503. lStrLen - m_sCaretPos + 1);
  504. m_sCaretPos--;
  505. // Need to redraw text.
  506. sRedrawText = TRUE;
  507. }
  508. else
  509. {
  510. NotifyCall();
  511. }
  512. // Absorb key.
  513. pie->sUsed = TRUE;
  514. break;
  515. case '\r':
  516. if (m_sBehavior & REdit::Multiline)
  517. {
  518. TRACE("Do(): REdit::Multiline NYI.\n");
  519. NotifyCall();
  520. // Absorb key.
  521. pie->sUsed = TRUE;
  522. }
  523. break;
  524. // Keys we don't want to process.
  525. case '\t':
  526. case 27:
  527. break;
  528. default:
  529. lNewChar = pie->lKey;
  530. // Absorb key.
  531. pie->sUsed = TRUE;
  532. break;
  533. }
  534. break;
  535. // Numpad numeric keys.
  536. case RSP_GK_NUMPAD_0:
  537. case RSP_GK_NUMPAD_1:
  538. case RSP_GK_NUMPAD_2:
  539. case RSP_GK_NUMPAD_3:
  540. case RSP_GK_NUMPAD_4:
  541. case RSP_GK_NUMPAD_5:
  542. case RSP_GK_NUMPAD_6:
  543. case RSP_GK_NUMPAD_7:
  544. case RSP_GK_NUMPAD_8:
  545. case RSP_GK_NUMPAD_9:
  546. lNewChar = '0' + ( (pie->lKey - RSP_GK_NUMPAD_0) >> 8);
  547. // Absorb key.
  548. pie->sUsed = TRUE;
  549. break;
  550. // Numpad other keys.
  551. // NOTE: This is essentially a table so, if it gets too large, let's use a real table
  552. // instead. Maybe there should be a function.
  553. case RSP_GK_NUMPAD_ASTERISK:
  554. lNewChar = '*';
  555. // Absorb key.
  556. pie->sUsed = TRUE;
  557. break;
  558. case RSP_GK_NUMPAD_PLUS :
  559. lNewChar = '+';
  560. // Absorb key.
  561. pie->sUsed = TRUE;
  562. break;
  563. case RSP_GK_NUMPAD_MINUS :
  564. lNewChar = '-';
  565. // Absorb key.
  566. pie->sUsed = TRUE;
  567. break;
  568. case RSP_GK_NUMPAD_DECIMAL :
  569. lNewChar = '.';
  570. // Absorb key.
  571. pie->sUsed = TRUE;
  572. break;
  573. case RSP_GK_NUMPAD_DIVIDE :
  574. lNewChar = '/';
  575. // Absorb key.
  576. pie->sUsed = TRUE;
  577. break;
  578. // Single line caret movement.
  579. case RSP_GK_LEFT:
  580. if (m_sCaretPos > 0)
  581. {
  582. m_sCaretPos--;
  583. }
  584. else
  585. {
  586. NotifyCall();
  587. }
  588. // Absorb key.
  589. pie->sUsed = TRUE;
  590. break;
  591. case RSP_GK_RIGHT:
  592. if (m_sCaretPos < lStrLen)
  593. {
  594. m_sCaretPos++;
  595. }
  596. else
  597. {
  598. NotifyCall();
  599. }
  600. // Absorb key.
  601. pie->sUsed = TRUE;
  602. break;
  603. case RSP_GK_DELETE:
  604. if (m_sCaretPos < lStrLen)
  605. {
  606. // Remove character at cursor.
  607. memmove( m_szText + m_sCaretPos,
  608. m_szText + m_sCaretPos + 1,
  609. lStrLen - m_sCaretPos);
  610. // Need to redraw text.
  611. sRedrawText = TRUE;
  612. }
  613. else
  614. {
  615. NotifyCall();
  616. }
  617. // Absorb key.
  618. pie->sUsed = TRUE;
  619. break;
  620. case RSP_GK_HOME:
  621. m_sCaretPos = 0;
  622. // Absorb key.
  623. pie->sUsed = TRUE;
  624. break;
  625. case RSP_GK_END:
  626. m_sCaretPos = (short)lStrLen;
  627. // Absorb key.
  628. pie->sUsed = TRUE;
  629. break;
  630. // Multiline caret movement.
  631. case RSP_GK_UP:
  632. if (m_sBehavior & REdit::Multiline)
  633. {
  634. TRACE("Do(): REdit::Multiline NYI.\n");
  635. NotifyCall();
  636. }
  637. // Absorb key.
  638. pie->sUsed = TRUE;
  639. break;
  640. case RSP_GK_DOWN:
  641. if (m_sBehavior & REdit::Multiline)
  642. {
  643. TRACE("Do(): REdit::Multiline NYI.\n");
  644. NotifyCall();
  645. }
  646. // Absorb key.
  647. pie->sUsed = TRUE;
  648. break;
  649. }
  650. // If we should add a key . . .
  651. if (lNewChar)
  652. {
  653. if (lStrLen < m_sMaxText - 1)
  654. {
  655. // Add character to string.
  656. // Move existing characters (perhaps only '\0')
  657. // out of the way.
  658. memmove( m_szText + m_sCaretPos + 1,
  659. m_szText + m_sCaretPos,
  660. lStrLen - m_sCaretPos + 1);
  661. // Place character and advance caret position.
  662. m_szText[m_sCaretPos++] = (char)lNewChar;
  663. // Need to redraw text.
  664. sRedrawText = TRUE;
  665. }
  666. else
  667. {
  668. NotifyCall();
  669. }
  670. }
  671. // If change in caret pos . . .
  672. if (m_sCaretPos != sCaretPosIn)
  673. {
  674. // We must make sure the caret is visible.
  675. Compose();
  676. sRedrawItem = TRUE;
  677. }
  678. }
  679. if (m_lCaretBlinkRate != 0)
  680. {
  681. // If the next blink time has expired . . .
  682. long lCurTime = rspGetMilliseconds();
  683. if (lCurTime >= m_lNextCaretUpdate)
  684. {
  685. // Set next blink time.
  686. m_lNextCaretUpdate = lCurTime + m_lCaretBlinkRate;
  687. // If caret is to be shown . . .
  688. if (m_sCaretState == 1)
  689. {
  690. // Set caret state.
  691. m_sCaretState = 0;
  692. }
  693. else
  694. {
  695. // Set caret state.
  696. m_sCaretState = 1;
  697. }
  698. // Redraw needed.
  699. sRedrawItem = TRUE;
  700. }
  701. }
  702. else
  703. {
  704. m_sCaretState = 1;
  705. }
  706. // If we need to redraw the text . . .
  707. if (sRedrawText != FALSE)
  708. {
  709. // Recompose the item.
  710. Compose();
  711. sRedrawItem = TRUE;
  712. }
  713. // If a redraw is necessary . . .
  714. if (sRedrawItem != FALSE)
  715. {
  716. // Cause a redraw for the event driven user.
  717. Redraw();
  718. }
  719. }
  720. }
  721. ////////////////////////////////////////////////////////////////////////
  722. //
  723. // Cursor event notification.
  724. // Events in event area.
  725. // (virtual).
  726. //
  727. ////////////////////////////////////////////////////////////////////////
  728. void REdit::CursorEvent( // Returns nothing.
  729. RInputEvent* pie) // In: Most recent user input event.
  730. // Out: pie->sUsed = TRUE, if used.
  731. {
  732. RGuiItem::CursorEvent(pie);
  733. switch (pie->sEvent)
  734. {
  735. case RSP_MB0_DOUBLECLICK:
  736. case RSP_MB0_RELEASED:
  737. {
  738. // Set the caret position based on the area clicked.
  739. char* pszText = m_szText;
  740. Point* ppt = m_aptTextPos;
  741. m_sCaretPos = m_sFirstVisibleCharIndex;
  742. short sCellH = m_sFontCellHeight;
  743. // Adjust sPosY to bottom of line.
  744. short sPosY = pie->sPosY + sCellH;
  745. while (*pszText++ != '\0')
  746. {
  747. if (ppt->sX < pie->sPosX && ppt->sY < sPosY)
  748. {
  749. m_sCaretPos++;
  750. ppt++;
  751. }
  752. else
  753. {
  754. break;
  755. }
  756. }
  757. // Make sure it gets shown.
  758. m_lNextCaretUpdate = 0L;
  759. m_sCaretState = 0;
  760. // Note that we used it.
  761. pie->sUsed = TRUE;
  762. break;
  763. }
  764. }
  765. }
  766. ////////////////////////////////////////////////////////////////////////
  767. // Internal.
  768. ////////////////////////////////////////////////////////////////////////
  769. ////////////////////////////////////////////////////////////////////////
  770. //
  771. // Read item's members from file.
  772. // (virtual/protected (overriden here)).
  773. //
  774. ////////////////////////////////////////////////////////////////////////
  775. short REdit::ReadMembers( // Returns 0 on success.
  776. RFile* pfile, // File to read from.
  777. U32 u32Version) // File format version to use.
  778. {
  779. short sRes = 0; // Assume success.
  780. // Invoke base class to read base members.
  781. sRes = RTxt::ReadMembers(pfile, u32Version);
  782. // If okay so far . . .
  783. if (sRes == 0)
  784. {
  785. ASSERT(pfile != NULL);
  786. ASSERT(pfile->IsOpen() != FALSE);
  787. // Switch on version.
  788. switch (u32Version)
  789. {
  790. default:
  791. // Insert additional version numbers here!
  792. // case 4: // Version 4 stuff.
  793. // case 3: // Version 3 stuff.
  794. case 2: // Version 2 stuff.
  795. case 1:
  796. // Read this class's members.
  797. pfile->Read(&m_cCaretChar);
  798. pfile->Read(&m_u32CaretColor);
  799. pfile->Read(&m_lCaretBlinkRate);
  800. pfile->Read(&m_sMaxText);
  801. pfile->Read(&m_sBehavior);
  802. case 0: // In version 0, only base class RGuiItem members were stored.
  803. // If successful . . .
  804. if (pfile->Error() == FALSE)
  805. {
  806. // Success.
  807. }
  808. else
  809. {
  810. TRACE("ReadMembers(): Error reading REdit members.\n");
  811. sRes = -1;
  812. }
  813. break;
  814. }
  815. }
  816. return sRes;
  817. }
  818. ////////////////////////////////////////////////////////////////////////
  819. //
  820. // Write item's members to file.
  821. // (virtual/protected (overriden here)).
  822. //
  823. ////////////////////////////////////////////////////////////////////////
  824. short REdit::WriteMembers( // Returns 0 on success.
  825. RFile* pfile) // File to write to.
  826. {
  827. short sRes = 0; // Assume success.
  828. // Invoke base class to read base members.
  829. sRes = RTxt::WriteMembers(pfile);
  830. // If okay so far . . .
  831. if (sRes == 0)
  832. {
  833. ASSERT(pfile != NULL);
  834. ASSERT(pfile->IsOpen() != FALSE);
  835. // Write this class's members.
  836. pfile->Write(&m_cCaretChar);
  837. pfile->Write(&m_u32CaretColor);
  838. pfile->Write(&m_lCaretBlinkRate);
  839. pfile->Write(&m_sMaxText);
  840. pfile->Write(&m_sBehavior);
  841. // If successful . . .
  842. if (pfile->Error() == FALSE)
  843. {
  844. // Success.
  845. }
  846. else
  847. {
  848. TRACE("WriteMembers(): Error writing REdit members.\n");
  849. sRes = -1;
  850. }
  851. }
  852. return sRes;
  853. }
  854. ////////////////////////////////////////////////////////////////////////
  855. // Clips the caret to within the string length.
  856. ////////////////////////////////////////////////////////////////////////
  857. void REdit::ClipCaret(void) // Returns nothing.
  858. {
  859. long lLen = strlen(m_szText);
  860. if (m_sCaretPos > lLen)
  861. {
  862. // After last char.
  863. m_sCaretPos = (short)lLen;
  864. }
  865. }
  866. ////////////////////////////////////////////////////////////////////////
  867. // Querries.
  868. ////////////////////////////////////////////////////////////////////////
  869. //////////////////////////////////////////////////////////////////////////////
  870. // EOF
  871. //////////////////////////////////////////////////////////////////////////////