editapp.cpp 48 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840
  1. //////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Editor
  4. //
  5. //////////////////////////////////////////////////////////////////////////////
  6. #include "pch.h"
  7. //////////////////////////////////////////////////////////////////////////////
  8. //
  9. // The main entry point
  10. //
  11. //////////////////////////////////////////////////////////////////////////////
  12. #include "main.h"
  13. //////////////////////////////////////////////////////////////////////////////
  14. //
  15. // Forward Declarations
  16. //
  17. //////////////////////////////////////////////////////////////////////////////
  18. class Item;
  19. //////////////////////////////////////////////////////////////////////////////
  20. //
  21. //
  22. //
  23. //////////////////////////////////////////////////////////////////////////////
  24. class Font : public IObject {
  25. private:
  26. HFONT m_hfont;
  27. WinPoint m_size;
  28. public:
  29. Font(HDC hdc, const ZString& strFace, int height)
  30. {
  31. m_hfont =
  32. ::CreateFont(
  33. 11, //height,
  34. 0,
  35. 0,
  36. 0,
  37. FW_DONTCARE, FALSE, FALSE, FALSE, ANSI_CHARSET,
  38. OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
  39. DEFAULT_QUALITY, DEFAULT_PITCH | FF_MODERN,
  40. strFace
  41. );
  42. //
  43. // , this assumes this is a fixed pitch font
  44. //
  45. HFONT hfontOld;
  46. SIZE size;
  47. ZVerify(hfontOld = (HFONT)::SelectObject(hdc, m_hfont));
  48. ZVerify(::GetTextExtentPoint(hdc, "a", 1, &size));
  49. ZVerify(::SelectObject(hdc, hfontOld));
  50. m_size = WinPoint(size.cx, size.cy);
  51. }
  52. HFONT GetHFONT()
  53. {
  54. return m_hfont;
  55. }
  56. WinPoint GetStringExtent(const ZString& str)
  57. {
  58. return WinPoint(m_size.X() * str.GetLength(), m_size.Y());
  59. }
  60. };
  61. //////////////////////////////////////////////////////////////////////////////
  62. //
  63. //
  64. //
  65. //////////////////////////////////////////////////////////////////////////////
  66. class Context2D : public IObject {
  67. private:
  68. TRef<Font> m_pfont;
  69. HDC m_hdc;
  70. HFONT m_hfontOld;
  71. WinPoint m_pointOrigin;
  72. public:
  73. Context2D(HDC hdc, Font* pfont) :
  74. m_hdc(hdc),
  75. m_pfont(pfont),
  76. m_pointOrigin(0, 0)
  77. {
  78. ZVerify(m_hfontOld = (HFONT)::SelectObject(m_hdc, m_pfont->GetHFONT()));
  79. }
  80. ~Context2D()
  81. {
  82. ZVerify(::SelectObject(m_hdc, m_hfontOld));
  83. }
  84. void SetOrigin(const WinPoint& point)
  85. {
  86. m_pointOrigin = point;
  87. }
  88. void SetBackColor(COLORREF color)
  89. {
  90. ZVerify(::SetBkColor(m_hdc, color) != CLR_INVALID);
  91. }
  92. void SetTextColor(COLORREF color)
  93. {
  94. ZVerify(::SetTextColor(m_hdc, color) != CLR_INVALID);
  95. }
  96. void SetFont(Font* pfont)
  97. {
  98. if (m_pfont != pfont) {
  99. m_pfont = pfont;
  100. ZVerify(::SelectObject(m_hdc, m_pfont->GetHFONT()));
  101. }
  102. }
  103. void DrawString(const ZString& str, const WinPoint& point = WinPoint(0, 0))
  104. {
  105. ZVerify(::TextOut(
  106. m_hdc,
  107. m_pointOrigin.X() + point.X(),
  108. m_pointOrigin.Y() + point.Y(),
  109. str,
  110. str.GetLength()
  111. ));
  112. }
  113. void FillRect(const WinRect& rect, COLORREF color)
  114. {
  115. ::FillSolidRect(
  116. m_hdc,
  117. m_pointOrigin.X() + rect.XMin(),
  118. m_pointOrigin.Y() + rect.YMin(),
  119. rect.XSize(),
  120. rect.YSize(),
  121. color
  122. );
  123. }
  124. };
  125. //////////////////////////////////////////////////////////////////////////////
  126. //
  127. //
  128. //
  129. //////////////////////////////////////////////////////////////////////////////
  130. class Item : public IObject {
  131. private:
  132. ZString m_str;
  133. TRef<Item> m_pnext;
  134. Item* m_pprev;
  135. public:
  136. Item(const ZString& str = ZString()) :
  137. m_pprev(NULL)
  138. {
  139. int index;
  140. index = str.Find(0x0d);
  141. if (index == -1) {
  142. m_str = str;
  143. } else {
  144. m_str = str.Left(index);
  145. SetNext(new Item(str.RightOf(index + 2)));
  146. }
  147. }
  148. TRef<Item> Copy()
  149. {
  150. TRef<Item> pitem = new Item(m_str);
  151. if (m_pnext) {
  152. pitem->SetNext(m_pnext->Copy());
  153. }
  154. return pitem;
  155. }
  156. void SetNext(Item* pnext)
  157. {
  158. TRef<Item> pitemSave = m_pnext;
  159. if (m_pnext != NULL) {
  160. m_pnext->m_pprev = NULL;
  161. }
  162. m_pnext = pnext;
  163. if (pnext != NULL) {
  164. if (pnext->m_pprev != NULL) {
  165. pnext->m_pprev->m_pnext = NULL;
  166. }
  167. pnext->m_pprev = this;
  168. }
  169. }
  170. void SetString(const ZString& str)
  171. {
  172. m_str = str;
  173. }
  174. const ZString& GetString()
  175. {
  176. return m_str;
  177. }
  178. int GetLength()
  179. {
  180. return m_str.GetLength();
  181. }
  182. Item* GetNext()
  183. {
  184. return m_pnext;
  185. }
  186. Item* GetPrev()
  187. {
  188. return m_pprev;
  189. }
  190. };
  191. //////////////////////////////////////////////////////////////////////////////
  192. //
  193. //
  194. //
  195. //////////////////////////////////////////////////////////////////////////////
  196. class Marker : public IObject {
  197. public:
  198. typedef TList<Marker*> List;
  199. private:
  200. TRef<Item> m_pitem;
  201. int m_index;
  202. List* m_plistMarkers;
  203. public:
  204. Marker(List* plistMarkers, Item* pitem, int index) :
  205. m_plistMarkers(plistMarkers),
  206. m_pitem(pitem),
  207. m_index(index)
  208. {
  209. ZAssert(index >= 0);
  210. if (m_plistMarkers != NULL) {
  211. m_plistMarkers->PushFront(this);
  212. }
  213. }
  214. Marker(const Marker& marker) :
  215. m_plistMarkers(marker.m_plistMarkers),
  216. m_pitem(marker.m_pitem),
  217. m_index(marker.m_index)
  218. {
  219. if (m_plistMarkers != NULL) {
  220. m_plistMarkers->PushFront(this);
  221. }
  222. }
  223. ~Marker()
  224. {
  225. if (m_plistMarkers != NULL) {
  226. m_plistMarkers->Remove(this);
  227. }
  228. }
  229. Item* GetItem()
  230. {
  231. return m_pitem;
  232. }
  233. int GetIndex()
  234. {
  235. return m_index;
  236. }
  237. void SetItem(Item* pitem)
  238. {
  239. m_pitem = pitem;
  240. }
  241. void SetIndex(int index)
  242. {
  243. ZAssert(index >= 0);
  244. m_index = index;
  245. }
  246. void Set(Item* pitem, int index)
  247. {
  248. ZAssert(index >= 0);
  249. m_pitem = pitem;
  250. m_index = index;
  251. }
  252. void Set(const Marker& marker)
  253. {
  254. m_pitem = marker.m_pitem;
  255. m_index = marker.m_index;
  256. }
  257. friend bool operator<(const Marker& markerStart, const Marker& markerEnd)
  258. {
  259. Item* pitemStart = markerStart.m_pitem;
  260. Item* pitemEnd = markerEnd.m_pitem;
  261. if (pitemStart == pitemEnd) {
  262. return markerStart.m_index < markerEnd.m_index;
  263. }
  264. while (pitemStart != NULL) {
  265. if (pitemStart == pitemEnd) {
  266. return true;
  267. }
  268. pitemStart = pitemStart->GetNext();
  269. }
  270. return false;
  271. }
  272. friend bool operator>=(const Marker& markerStart, const Marker& markerEnd)
  273. {
  274. return !(markerStart < markerEnd);
  275. }
  276. friend bool operator==(const Marker& marker1, const Marker& marker2)
  277. {
  278. return marker1.m_pitem == marker2.m_pitem && marker1.m_index == marker2.m_index;
  279. }
  280. };
  281. //////////////////////////////////////////////////////////////////////////////
  282. //
  283. //
  284. //
  285. //////////////////////////////////////////////////////////////////////////////
  286. class Document : public IObject {
  287. private:
  288. //
  289. // Replace Undo
  290. //
  291. class ReplaceUndo : public IUndo {
  292. Document* m_pdocument;
  293. TRef<Marker> m_pmarkerStart;
  294. TRef<Marker> m_pmarkerEnd;
  295. TRef<Item> m_pitemReplace;
  296. public:
  297. ReplaceUndo(
  298. Document* pdocument,
  299. Marker* pmarkerStart,
  300. Marker* pmarkerEnd,
  301. Item* pitemReplace
  302. ) :
  303. m_pdocument(pdocument),
  304. m_pmarkerStart(pmarkerStart),
  305. m_pmarkerEnd(pmarkerEnd),
  306. m_pitemReplace(pitemReplace)
  307. {
  308. }
  309. TRef<IUndo> Apply()
  310. {
  311. m_pdocument->SetSelection(m_pmarkerStart, m_pmarkerEnd);
  312. return m_pdocument->ReplaceSelection(m_pitemReplace);
  313. }
  314. void AddCharacter()
  315. {
  316. ZAssert(m_pmarkerStart->GetItem() == m_pmarkerEnd->GetItem());
  317. m_pmarkerEnd->SetIndex(m_pmarkerEnd->GetIndex() + 1);
  318. }
  319. void RemoveCharacter(char ch)
  320. {
  321. ZAssert(m_pmarkerStart->GetItem() == m_pmarkerEnd->GetItem());
  322. if (m_pmarkerEnd->GetIndex() > m_pmarkerStart->GetIndex()) {
  323. m_pmarkerEnd->SetIndex(m_pmarkerEnd->GetIndex() - 1);
  324. } else {
  325. TRef<Item> pitem = new Item(ZString(&ch, 1));
  326. if (m_pitemReplace) {
  327. m_pdocument->InsertAtEnd(pitem, m_pitemReplace);
  328. }
  329. m_pitemReplace = pitem;
  330. m_pmarkerStart->SetIndex(m_pmarkerStart->GetIndex() - 1);
  331. m_pmarkerEnd->SetIndex(m_pmarkerEnd->GetIndex() - 1);
  332. }
  333. }
  334. };
  335. //
  336. // Members
  337. //
  338. Marker::List m_listMarkers;
  339. TRef<Item> m_pitemHead;
  340. TRef<Marker> m_pmarkerStart;
  341. TRef<Marker> m_pmarkerEnd;
  342. TRef<Marker> m_pmarkerCurrent;
  343. TRef<Marker> m_pmarkerTop;
  344. ZString m_strFind;
  345. ZString m_strReplace;
  346. TRef<Item> m_pitemClipboard;
  347. TList<TRef<IUndo> > m_listUndos;
  348. TList<TRef<IUndo> > m_listRedos;
  349. TRef<ReplaceUndo> m_pcharacterUndo;
  350. ZString m_strFilename;
  351. bool m_bInsert;
  352. TRef<Font> m_pfont;
  353. WinPoint m_sizeChar;
  354. int m_pageHeight;
  355. int m_pageWidth;
  356. COLORREF m_colorBack;
  357. COLORREF m_colorText;
  358. COLORREF m_colorInfoBack;
  359. COLORREF m_colorInfoText;
  360. COLORREF m_colorSelectionBack;
  361. COLORREF m_colorSelectionText;
  362. COLORREF m_colorCurrent;
  363. public:
  364. Document(Font* pfont, const ZString strFilename, ZFile* pfile) :
  365. m_pfont(pfont),
  366. m_strFilename(strFilename),
  367. m_colorBack(RGB(192, 192, 192)),
  368. m_colorText(RGB(0, 0, 0)),
  369. m_colorSelectionBack(RGB(0, 0, 128)),
  370. m_colorSelectionText(RGB(255, 255, 255)),
  371. m_colorInfoBack(RGB(0, 0, 128)),
  372. m_colorInfoText(RGB(255, 255, 255)),
  373. m_pageHeight(0),
  374. m_pageWidth(0),
  375. m_bInsert(true)
  376. {
  377. m_sizeChar = m_pfont->GetStringExtent("a");
  378. m_pitemHead = new Item();
  379. if (pfile) {
  380. m_pitemHead->SetNext(
  381. new Item(ZString((PCC)pfile->GetPointer(), pfile->Length()))
  382. );
  383. } else {
  384. m_pitemHead->SetNext(new Item());
  385. }
  386. m_pmarkerStart = CreateMarker(GetFirstItem(), 0);
  387. m_pmarkerEnd = CreateMarker(GetFirstItem(), 0);
  388. m_pmarkerTop = CreateMarker(GetFirstItem(), 0);
  389. m_pmarkerCurrent = m_pmarkerEnd;
  390. }
  391. Item* GetHeadItem()
  392. {
  393. return m_pitemHead;
  394. }
  395. Item* GetFirstItem()
  396. {
  397. return m_pitemHead->GetNext();
  398. }
  399. //////////////////////////////////////////////////////////////////////////////
  400. //
  401. // Page size
  402. //
  403. //////////////////////////////////////////////////////////////////////////////
  404. void SetSize(const WinPoint& size)
  405. {
  406. m_pageWidth = (size.X() + m_sizeChar.X() - 1) / m_sizeChar.X();
  407. m_pageHeight = ((size.Y() + m_sizeChar.Y() - 1) / m_sizeChar.Y()) - 2;
  408. }
  409. //////////////////////////////////////////////////////////////////////////////
  410. //
  411. // Markers
  412. //
  413. //////////////////////////////////////////////////////////////////////////////
  414. TRef<Marker> CreateMarker(Item* pitem, int index)
  415. {
  416. return new Marker(&m_listMarkers, pitem, index);
  417. }
  418. void RemoveMarker(Marker* pmarker)
  419. {
  420. m_listMarkers.Remove(pmarker);
  421. }
  422. //////////////////////////////////////////////////////////////////////////////
  423. //
  424. // Undo
  425. //
  426. //////////////////////////////////////////////////////////////////////////////
  427. void AddUndo(IUndo* pundo)
  428. {
  429. if (pundo != m_pcharacterUndo) {
  430. m_pcharacterUndo = NULL;
  431. }
  432. m_listUndos.PushFront(pundo);
  433. }
  434. //////////////////////////////////////////////////////////////////////////////
  435. //
  436. // Join two items
  437. //
  438. //////////////////////////////////////////////////////////////////////////////
  439. void JoinItems(Item* pitem, int index)
  440. {
  441. Item* pitemNext = pitem->GetNext();
  442. if (pitemNext) {
  443. int lengthOld = pitem->GetLength();
  444. if (index >= lengthOld) {
  445. pitem->SetString(pitem->GetString() + pitemNext->GetString());
  446. } else {
  447. const ZString& str = pitem->GetString();
  448. int indexSearch;
  449. for (indexSearch = lengthOld - 1; indexSearch >= index; indexSearch--) {
  450. if (str[indexSearch] != ' ')
  451. break;
  452. }
  453. pitem->SetString(pitem->GetString().Left(indexSearch + 1) + pitemNext->GetString());
  454. }
  455. pitem->SetNext(pitemNext->GetNext());
  456. //
  457. // Fix up the markers
  458. //
  459. Marker::List::Iterator iter(m_listMarkers);
  460. while (!iter.End()) {
  461. Marker* pmarker = iter.Value();
  462. if (pmarker->GetItem() == pitemNext) {
  463. pmarker->Set(pitem, lengthOld + pmarker->GetIndex());
  464. }
  465. iter.Next();
  466. }
  467. }
  468. }
  469. //////////////////////////////////////////////////////////////////////////////
  470. //
  471. // Split an item
  472. //
  473. //////////////////////////////////////////////////////////////////////////////
  474. void SplitItem(Marker* pmarker)
  475. {
  476. Item* pitem = pmarker->GetItem();
  477. int index = pmarker->GetIndex();
  478. //
  479. // Split the item into two items
  480. //
  481. TRef<Item> pitemNext = new Item(pitem->GetString().RightOf(index));
  482. pitem->SetString(pitem->GetString().Left(index));
  483. pitemNext->SetNext(pitem->GetNext());
  484. pitem->SetNext(pitemNext);
  485. //
  486. // Fix up the markers
  487. //
  488. Marker::List::Iterator iter(m_listMarkers);
  489. while (!iter.End()) {
  490. Marker* pmarker = iter.Value();
  491. if (pmarker->GetItem() == pitem && pmarker->GetIndex() >= index) {
  492. pmarker->Set(pitemNext, pmarker->GetIndex() - index);
  493. }
  494. iter.Next();
  495. }
  496. }
  497. //////////////////////////////////////////////////////////////////////////////
  498. //
  499. // Delete a range of items
  500. //
  501. //////////////////////////////////////////////////////////////////////////////
  502. TRef<Item> Delete(Marker* pmarkerStart, Marker* pmarkerEnd)
  503. {
  504. //
  505. // Don't delete anything if the two markers point to the same place
  506. //
  507. bool bJoin = false;
  508. if (pmarkerStart->GetItem() == pmarkerEnd->GetItem()) {
  509. if (pmarkerStart->GetIndex() == pmarkerEnd->GetIndex()) {
  510. return NULL;
  511. }
  512. bJoin = (pmarkerStart->GetIndex() != 0);
  513. }
  514. //
  515. // Make sure the markers point to the beginning of two items
  516. //
  517. if (pmarkerStart->GetIndex() != 0) {
  518. SplitItem(pmarkerStart);
  519. ZAssert(pmarkerStart->GetIndex() == 0);
  520. }
  521. if (pmarkerEnd->GetIndex() != 0) {
  522. SplitItem(pmarkerEnd);
  523. ZAssert(pmarkerEnd->GetIndex() == 0);
  524. }
  525. //
  526. // Cut out the deleted section
  527. //
  528. TRef<Item> pitemDelete = pmarkerStart->GetItem();
  529. TRef<Item> pitemPrev = pitemDelete->GetPrev();
  530. pitemPrev->SetNext(pmarkerEnd->GetItem());
  531. //
  532. // Fix up markers
  533. //
  534. Marker::List::Iterator iter(m_listMarkers);
  535. while (!iter.End()) {
  536. Marker* pmarker = iter.Value();
  537. Item* pitem = pitemDelete;
  538. while (pitem != NULL) {
  539. if (pmarker->GetItem() == pitem) {
  540. pmarker->Set(pmarkerEnd->GetItem(), 0);
  541. }
  542. pitem = pitem->GetNext();
  543. }
  544. iter.Next();
  545. }
  546. //
  547. // Join the two items that were next to the range together
  548. //
  549. if (bJoin) {
  550. JoinItems(pitemPrev, pitemPrev->GetLength());
  551. }
  552. //
  553. // Return the deleted section
  554. //
  555. return pitemDelete;
  556. }
  557. //////////////////////////////////////////////////////////////////////////////
  558. //
  559. // Insert a range of items at the end
  560. //
  561. //////////////////////////////////////////////////////////////////////////////
  562. void InsertAtEnd(Item* pitem, Item* pitemInsert)
  563. {
  564. if (pitem->GetNext()) {
  565. InsertAtEnd(pitem->GetNext(), pitemInsert);
  566. } else {
  567. //
  568. // Fix up markers
  569. //
  570. Marker::List::Iterator iter(m_listMarkers);
  571. while (!iter.End()) {
  572. Marker* pmarker = iter.Value();
  573. if (
  574. pmarker->GetItem() == pitem
  575. && pmarker->GetIndex() == pitem->GetLength()
  576. ) {
  577. pmarker->Set(pitemInsert, 0);
  578. }
  579. iter.Next();
  580. }
  581. //
  582. // join them together
  583. //
  584. pitem->SetNext(pitemInsert);
  585. JoinItems(pitem, pitem->GetLength());
  586. }
  587. }
  588. //////////////////////////////////////////////////////////////////////////////
  589. //
  590. // Insert a range of items
  591. //
  592. //////////////////////////////////////////////////////////////////////////////
  593. void Insert(Marker* pmarker, Item* pitemInsert)
  594. {
  595. Item* pitem = pmarker->GetItem();
  596. int index = pmarker->GetIndex();
  597. if (index == 0) {
  598. TRef<Item> pprev = pitem->GetPrev();
  599. InsertAtEnd(pitemInsert, pitem);
  600. pprev->SetNext(pitemInsert);
  601. } else {
  602. TRef<Marker> pmarkerTemp = CreateMarker(pitem, pitem->GetLength());
  603. if (index >= pitem->GetLength()) {
  604. pmarker = pmarkerTemp;
  605. }
  606. SplitItem(pmarker);
  607. pitem = pmarker->GetItem();
  608. TRef<Item> pprev = pitem->GetPrev();
  609. InsertAtEnd(pitemInsert, pitem);
  610. InsertAtEnd(pprev, pitemInsert);
  611. }
  612. }
  613. //////////////////////////////////////////////////////////////////////////////
  614. //
  615. // Replace the selection with a range of Items
  616. //
  617. //////////////////////////////////////////////////////////////////////////////
  618. TRef<ReplaceUndo> ReplaceSelection(Item* pitemInsert)
  619. {
  620. TRef<Item> pitemReplace = Delete(m_pmarkerStart, m_pmarkerEnd);
  621. TRef<Marker> pmarkerOld = new Marker(NULL, m_pmarkerStart->GetItem(), m_pmarkerStart->GetIndex());
  622. if (pitemInsert != NULL) {
  623. Insert(m_pmarkerStart, pitemInsert);
  624. }
  625. return
  626. new ReplaceUndo(
  627. this,
  628. pmarkerOld,
  629. new Marker(NULL, m_pmarkerStart->GetItem(), m_pmarkerStart->GetIndex()),
  630. pitemReplace
  631. );
  632. }
  633. //////////////////////////////////////////////////////////////////////////////
  634. //
  635. // Insert a file
  636. //
  637. //////////////////////////////////////////////////////////////////////////////
  638. HRESULT Insert(ZFile* pfile)
  639. {
  640. TRef<Item> pitem =
  641. new Item(ZString((PCC)pfile->GetPointer(), pfile->Length()));
  642. AddUndo(ReplaceSelection(pitem));
  643. return S_OK;
  644. }
  645. //////////////////////////////////////////////////////////////////////////////
  646. //
  647. // Render the document
  648. //
  649. //////////////////////////////////////////////////////////////////////////////
  650. void RenderItem(
  651. Context2D* pcontext,
  652. Item* pitem,
  653. int indexStart,
  654. int indexEnd
  655. ) {
  656. int indexSplit = pitem->GetLength();
  657. if (indexSplit > indexEnd) {
  658. indexSplit = indexEnd;
  659. }
  660. if (indexSplit < indexStart) {
  661. indexSplit = indexStart;
  662. }
  663. if (indexStart < indexSplit) {
  664. pcontext->DrawString(
  665. pitem->GetString().Middle(indexStart, indexSplit - indexStart)
  666. );
  667. }
  668. if (indexSplit < indexEnd) {
  669. pcontext->FillRect(
  670. WinRect(
  671. (indexSplit - indexStart) * m_sizeChar.X(),
  672. 0,
  673. (indexEnd - indexStart) * m_sizeChar.X(),
  674. m_sizeChar.Y()
  675. ),
  676. m_colorCurrent
  677. );
  678. }
  679. }
  680. void Render(HDC hdc, const WinRect& rect)
  681. {
  682. TRef<Context2D> pcontext = new Context2D(hdc, m_pfont);
  683. //
  684. // Draw the text
  685. //
  686. pcontext->SetBackColor(m_colorBack);
  687. pcontext->SetTextColor(m_colorText);
  688. m_colorCurrent = m_colorBack;
  689. Item* pitem = m_pmarkerTop->GetItem();
  690. int indexFirst = m_pmarkerTop->GetIndex();
  691. int yStart = -1;
  692. for (int line = 0; line < m_pageHeight; line++) {
  693. int yLine = line * m_sizeChar.Y();
  694. if (pitem != NULL) {
  695. int indexStart = indexFirst;
  696. if (m_pmarkerStart->GetItem() == pitem) {
  697. yStart = yLine;
  698. indexStart = max(indexStart, m_pmarkerStart->GetIndex());
  699. pcontext->SetOrigin(WinPoint(0, yLine));
  700. RenderItem(pcontext, pitem, indexFirst, indexStart);
  701. pcontext->SetBackColor(m_colorSelectionBack);
  702. pcontext->SetTextColor(m_colorSelectionText);
  703. m_colorCurrent = m_colorSelectionBack;
  704. }
  705. if (m_pmarkerEnd->GetItem() == pitem) {
  706. int indexEnd = min(m_pageWidth + indexFirst, m_pmarkerEnd->GetIndex());
  707. pcontext->SetOrigin(
  708. WinPoint(
  709. (indexStart - indexFirst) * m_sizeChar.X(),
  710. yLine
  711. )
  712. );
  713. RenderItem(pcontext, pitem, indexStart, indexEnd);
  714. indexStart = indexEnd;
  715. pcontext->SetBackColor(m_colorBack);
  716. pcontext->SetTextColor(m_colorText);
  717. m_colorCurrent = m_colorBack;
  718. }
  719. pcontext->SetOrigin(
  720. WinPoint(
  721. (indexStart - indexFirst) * m_sizeChar.X(),
  722. yLine
  723. )
  724. );
  725. RenderItem(pcontext, pitem, indexStart, m_pageWidth + indexFirst);
  726. pitem = pitem->GetNext();
  727. } else {
  728. pcontext->SetOrigin(WinPoint(0, yLine));
  729. pcontext->FillRect(
  730. WinRect(
  731. 0,
  732. 0,
  733. m_pageWidth * m_sizeChar.X(),
  734. m_sizeChar.Y()
  735. ),
  736. m_colorBack
  737. );
  738. }
  739. yLine += m_sizeChar.Y();
  740. }
  741. pcontext->SetOrigin(WinPoint(0, 0));
  742. //
  743. // Calculate the selection line
  744. //
  745. int lines = 0;
  746. int selline = 1;
  747. pitem = GetFirstItem();
  748. while (pitem != m_pmarkerCurrent->GetItem()) {
  749. selline++;
  750. lines++;
  751. pitem = pitem->GetNext();
  752. }
  753. while (pitem != NULL) {
  754. lines++;
  755. pitem = pitem->GetNext();
  756. }
  757. //
  758. // Draw the Information line
  759. //
  760. ZString strInfo = m_strFilename;
  761. if (!m_listUndos.IsEmpty()) {
  762. strInfo += "*";
  763. }
  764. strInfo += " Length=" + ZString(lines);
  765. strInfo += " Cursor=(" + ZString(m_pmarkerCurrent->GetIndex() + 1) + ", " + ZString(selline) + ")";
  766. if (m_bInsert) {
  767. strInfo += " insert";
  768. }
  769. pcontext->SetBackColor(m_colorInfoBack);
  770. pcontext->SetTextColor(m_colorInfoText);
  771. pcontext->DrawString(strInfo, WinPoint(0, m_pageHeight * m_sizeChar.Y()));
  772. pcontext->FillRect(
  773. WinRect(
  774. strInfo.GetLength() * m_sizeChar.X(),
  775. m_pageHeight * m_sizeChar.Y(),
  776. m_pageWidth * m_sizeChar.X(),
  777. (m_pageHeight + 1) * m_sizeChar.Y()
  778. ),
  779. m_colorInfoBack
  780. );
  781. //
  782. // Draw the Cursor
  783. //
  784. if (IsCursor() && yStart != -1) {
  785. int index = m_pmarkerStart->GetIndex();
  786. pcontext->FillRect(
  787. WinRect(
  788. index * m_sizeChar.X(),
  789. yStart,
  790. index * m_sizeChar.X() + 3,
  791. yStart + m_sizeChar.Y()
  792. ),
  793. m_colorSelectionBack
  794. );
  795. }
  796. }
  797. //////////////////////////////////////////////////////////////////////////////
  798. //
  799. // Commands
  800. //
  801. //////////////////////////////////////////////////////////////////////////////
  802. bool IsCursor()
  803. {
  804. return *m_pmarkerStart == *m_pmarkerEnd;
  805. }
  806. void SetSelection(Marker* pmarkerStart, Marker* pmarkerEnd)
  807. {
  808. m_pmarkerStart->Set(pmarkerStart->GetItem(), pmarkerStart->GetIndex());
  809. m_pmarkerEnd->Set(pmarkerEnd->GetItem(), pmarkerEnd->GetIndex());
  810. }
  811. void SetCursorPosition(Item* pitem, int index, bool bSelect)
  812. {
  813. m_pcharacterUndo = NULL;
  814. TRef<Marker> pmarker = CreateMarker(pitem, index);
  815. if (bSelect) {
  816. if (m_pmarkerCurrent == m_pmarkerEnd) {
  817. if (*pmarker < *m_pmarkerStart) {
  818. m_pmarkerEnd->Set(*m_pmarkerStart);
  819. m_pmarkerCurrent = m_pmarkerStart;
  820. }
  821. } else {
  822. if (*pmarker >= *m_pmarkerEnd) {
  823. m_pmarkerStart->Set(*m_pmarkerEnd);
  824. m_pmarkerCurrent = m_pmarkerEnd;
  825. }
  826. }
  827. m_pmarkerCurrent->Set(*pmarker);
  828. } else {
  829. m_pmarkerStart->Set(*pmarker);
  830. m_pmarkerEnd->Set(*pmarker);
  831. }
  832. }
  833. //////////////////////////////////////////////////////////////////////////////
  834. //
  835. // Cursor Commands
  836. //
  837. //////////////////////////////////////////////////////////////////////////////
  838. void ScrollLeft()
  839. {
  840. if (m_pmarkerTop->GetIndex() > 0) {
  841. m_pmarkerTop->SetIndex(m_pmarkerTop->GetIndex() - 1);
  842. }
  843. }
  844. void ScrollRight()
  845. {
  846. m_pmarkerTop->SetIndex(m_pmarkerTop->GetIndex() + 1);
  847. }
  848. void ScrollUp()
  849. {
  850. if (m_pmarkerTop->GetItem() != GetFirstItem()) {
  851. m_pmarkerTop->SetItem(m_pmarkerTop->GetItem()->GetPrev());
  852. }
  853. }
  854. void ScrollDown()
  855. {
  856. if (m_pmarkerTop->GetItem()->GetNext() != NULL) {
  857. m_pmarkerTop->SetItem(m_pmarkerTop->GetItem()->GetNext());
  858. }
  859. }
  860. //////////////////////////////////////////////////////////////////////////////
  861. //
  862. // Cursor Commands
  863. //
  864. //////////////////////////////////////////////////////////////////////////////
  865. void Left(bool bSelect)
  866. {
  867. if (m_pmarkerCurrent->GetIndex() > 0) {
  868. SetCursorPosition(m_pmarkerCurrent->GetItem(), m_pmarkerCurrent->GetIndex() - 1, bSelect);
  869. }
  870. }
  871. void Right(bool bSelect)
  872. {
  873. SetCursorPosition(m_pmarkerCurrent->GetItem(), m_pmarkerCurrent->GetIndex() + 1, bSelect);
  874. }
  875. void Up(bool bSelect)
  876. {
  877. if (m_pmarkerCurrent->GetItem() != GetFirstItem()) {
  878. SetCursorPosition(m_pmarkerCurrent->GetItem()->GetPrev(), m_pmarkerCurrent->GetIndex(), bSelect);
  879. }
  880. }
  881. void Down(bool bSelect)
  882. {
  883. if (m_pmarkerCurrent->GetItem()->GetNext() != NULL) {
  884. SetCursorPosition(m_pmarkerCurrent->GetItem()->GetNext(), m_pmarkerCurrent->GetIndex(), bSelect);
  885. }
  886. }
  887. void PageUp(bool bSelect)
  888. {
  889. for(int index = 0; index < m_pageHeight; index++) {
  890. ScrollUp();
  891. Up(bSelect);
  892. }
  893. }
  894. void PageDown(bool bSelect)
  895. {
  896. for(int index = 0; index < m_pageHeight; index++) {
  897. ScrollDown();
  898. Down(bSelect);
  899. }
  900. }
  901. void GotoBeginingOfDocument(bool bSelect)
  902. {
  903. m_pmarkerTop->Set(GetFirstItem(), 0);
  904. SetCursorPosition(GetFirstItem(), 0, bSelect);
  905. }
  906. void GotoEndOfDocument(bool bSelect)
  907. {
  908. Item* pitem = GetFirstItem();
  909. while (pitem->GetNext() != NULL) {
  910. pitem = pitem->GetNext();
  911. }
  912. m_pmarkerTop->Set(pitem, 0);
  913. SetCursorPosition(pitem, 0, bSelect);
  914. }
  915. void GotoBeginingOfLine(bool bSelect)
  916. {
  917. const ZString& str = m_pmarkerCurrent->GetItem()->GetString();
  918. int length = str.GetLength();
  919. int index = 0;
  920. while (index < length && str[index] == ' ') {
  921. index++;
  922. }
  923. if (m_pmarkerCurrent->GetIndex() == index) {
  924. SetCursorPosition(m_pmarkerCurrent->GetItem(), 0, bSelect);
  925. } else {
  926. SetCursorPosition(m_pmarkerCurrent->GetItem(), index, bSelect);
  927. }
  928. }
  929. void GotoEndOfLine(bool bSelect)
  930. {
  931. SetCursorPosition(
  932. m_pmarkerCurrent->GetItem(),
  933. m_pmarkerCurrent->GetItem()->GetLength(),
  934. bSelect
  935. );
  936. }
  937. void Cancel()
  938. {
  939. if (m_pmarkerCurrent == m_pmarkerEnd) {
  940. SetCursorPosition(
  941. m_pmarkerStart->GetItem(),
  942. m_pmarkerStart->GetIndex(),
  943. false
  944. );
  945. } else {
  946. SetCursorPosition(
  947. m_pmarkerEnd->GetItem(),
  948. m_pmarkerEnd->GetIndex(),
  949. false
  950. );
  951. }
  952. }
  953. //////////////////////////////////////////////////////////////////////////////
  954. //
  955. // Commands
  956. //
  957. //////////////////////////////////////////////////////////////////////////////
  958. void Character(TCHAR ch)
  959. {
  960. TRef<Item> pitem = new Item(ZString(&ch, 1));
  961. if (!m_pcharacterUndo) {
  962. m_pcharacterUndo = ReplaceSelection(pitem);
  963. AddUndo(m_pcharacterUndo);
  964. } else {
  965. ReplaceSelection(pitem);
  966. m_pcharacterUndo->AddCharacter();
  967. }
  968. }
  969. void Split()
  970. {
  971. Delete(m_pmarkerStart, m_pmarkerEnd);
  972. SplitItem(m_pmarkerStart);
  973. }
  974. void Join()
  975. {
  976. JoinItems(m_pmarkerStart->GetItem(), 0);
  977. }
  978. void Tab()
  979. {
  980. if (IsCursor()) {
  981. } else {
  982. }
  983. }
  984. void BackTab()
  985. {
  986. if (IsCursor()) {
  987. } else {
  988. }
  989. }
  990. void Delete()
  991. {
  992. if (IsCursor()) {
  993. Item* pitem = m_pmarkerStart->GetItem();
  994. int index = m_pmarkerStart->GetIndex();
  995. if (index < pitem->GetLength()) {
  996. TRef<Marker> pmarkerStart = CreateMarker(pitem, index);
  997. TRef<Marker> pmarkerEnd = CreateMarker(pitem, index + 1);
  998. Delete(pmarkerStart, pmarkerEnd);
  999. } else {
  1000. JoinItems(pitem, index);
  1001. }
  1002. } else {
  1003. Delete(m_pmarkerStart, m_pmarkerEnd);
  1004. }
  1005. }
  1006. void Backspace()
  1007. {
  1008. if (IsCursor()) {
  1009. Item* pitem = m_pmarkerStart->GetItem();
  1010. int index = m_pmarkerStart->GetIndex();
  1011. if (index == 0) {
  1012. if (pitem != GetFirstItem()) {
  1013. JoinItems(pitem->GetPrev(), 0);
  1014. }
  1015. } else {
  1016. m_pmarkerStart->SetIndex(index - 1);
  1017. if (!m_pcharacterUndo) {
  1018. m_pcharacterUndo = ReplaceSelection(NULL);
  1019. AddUndo(m_pcharacterUndo);
  1020. } else {
  1021. TRef<Item> pitem = Delete(m_pmarkerStart, m_pmarkerEnd);
  1022. m_pcharacterUndo->RemoveCharacter(pitem->GetString()[0]);
  1023. }
  1024. }
  1025. } else {
  1026. Delete();
  1027. }
  1028. }
  1029. void AquireFindString()
  1030. {
  1031. if (m_pmarkerStart->GetItem() == m_pmarkerEnd->GetItem()) {
  1032. m_strFind =
  1033. m_pmarkerStart->GetItem()->GetString().Middle(
  1034. m_pmarkerStart->GetIndex(),
  1035. m_pmarkerEnd->GetIndex() - m_pmarkerStart->GetIndex()
  1036. );
  1037. }
  1038. }
  1039. void FindNext()
  1040. {
  1041. if (!IsCursor()) {
  1042. AquireFindString();
  1043. }
  1044. if (!m_strFind.IsEmpty()) {
  1045. Item* pitem = m_pmarkerEnd->GetItem();
  1046. int index = m_pmarkerEnd->GetIndex();
  1047. while (pitem != NULL) {
  1048. int indexFind = pitem->GetString().RightOf(index).Find(m_strFind);
  1049. if (indexFind != -1) {
  1050. m_pmarkerStart->Set(pitem, index + indexFind);
  1051. m_pmarkerEnd->Set(pitem, index + indexFind + m_strFind.GetLength());
  1052. return;
  1053. }
  1054. index = 0;
  1055. pitem = pitem->GetNext();
  1056. }
  1057. }
  1058. }
  1059. void FindPrevious()
  1060. {
  1061. if (!IsCursor()) {
  1062. AquireFindString();
  1063. }
  1064. if (!m_strFind.IsEmpty()) {
  1065. Item* pitem = m_pmarkerStart->GetItem();
  1066. int index = m_pmarkerStart->GetIndex();
  1067. while (pitem != GetHeadItem()) {
  1068. int indexFind = pitem->GetString().Left(index).ReverseFind(m_strFind);
  1069. if (indexFind != -1) {
  1070. m_pmarkerStart->Set(pitem, indexFind);
  1071. m_pmarkerEnd->Set(pitem, indexFind + m_strFind.GetLength());
  1072. return;
  1073. }
  1074. pitem = pitem->GetPrev();
  1075. index = pitem->GetLength();
  1076. }
  1077. }
  1078. }
  1079. void Undo()
  1080. {
  1081. if (!m_listUndos.IsEmpty()) {
  1082. m_pcharacterUndo = NULL;
  1083. TRef<IUndo> pundo = m_listUndos.PopFront();
  1084. m_listRedos.PushFront(pundo->Apply());
  1085. }
  1086. }
  1087. void Redo()
  1088. {
  1089. if (!m_listRedos.IsEmpty()) {
  1090. TRef<IUndo> pundo = m_listRedos.PopFront();
  1091. m_listUndos.PushFront(pundo->Apply());
  1092. }
  1093. }
  1094. void Cut()
  1095. {
  1096. if (!IsCursor()) {
  1097. m_pitemClipboard = Delete(m_pmarkerStart, m_pmarkerEnd);
  1098. }
  1099. }
  1100. void Copy()
  1101. {
  1102. if (!IsCursor()) {
  1103. TRef<Item> pitem = Delete(m_pmarkerStart, m_pmarkerEnd);
  1104. m_pitemClipboard = pitem->Copy();
  1105. AddUndo(ReplaceSelection(pitem));
  1106. }
  1107. }
  1108. void Paste()
  1109. {
  1110. if (m_pitemClipboard) {
  1111. AddUndo(ReplaceSelection(m_pitemClipboard->Copy()));
  1112. }
  1113. }
  1114. void ToggleInsert()
  1115. {
  1116. m_bInsert = !m_bInsert;
  1117. }
  1118. };
  1119. //////////////////////////////////////////////////////////////////////////////
  1120. //
  1121. // Editor Window
  1122. //
  1123. //////////////////////////////////////////////////////////////////////////////
  1124. class EditorWindow : public Window, public IKeyboardInput {
  1125. protected:
  1126. TList<TRef<Document> > m_listDocuments;
  1127. TRef<Document> m_pdocumentCurrent;
  1128. TRef<Font> m_pfont;
  1129. bool m_bControl;
  1130. bool m_bShift;
  1131. public:
  1132. EditorWindow() :
  1133. Window(NULL, WinRect(0, 0, 640, 480), "Editor"),
  1134. m_bControl(false),
  1135. m_bShift(false)
  1136. {
  1137. SetKeyboardInput(IKeyboardInput::CreateDelegate(this));
  1138. HDC hdc = GetDC();
  1139. m_pfont = new Font(hdc, "Lucida Console", 11);
  1140. ReleaseDC(hdc);
  1141. }
  1142. void RectChanged()
  1143. {
  1144. if (m_pdocumentCurrent != NULL) {
  1145. m_pdocumentCurrent->SetSize(GetClientRect().Size());
  1146. }
  1147. Invalidate();
  1148. }
  1149. void NewDocument(const ZString& str, ZFile* pfile)
  1150. {
  1151. TRef<Document> pdocument = new Document(m_pfont, str, pfile);
  1152. m_listDocuments.PushFront(pdocument);
  1153. SetCurrentDocument(pdocument);
  1154. }
  1155. void SetCurrentDocument(Document* pdocument)
  1156. {
  1157. if (m_pdocumentCurrent != pdocument) {
  1158. m_pdocumentCurrent = pdocument;
  1159. m_pdocumentCurrent->SetSize(GetClientRect().Size());
  1160. Invalidate();
  1161. }
  1162. }
  1163. HRESULT Open(const ZString& str)
  1164. {
  1165. TRef<ZFile> pfile = new ZFile(str);
  1166. if (pfile->IsValid()) {
  1167. NewDocument(str, pfile);
  1168. return S_OK;
  1169. }
  1170. return S_FALSE;
  1171. }
  1172. void Invalidate()
  1173. {
  1174. InvalidateRgn();
  1175. }
  1176. void OnPaint(HDC hdc, const WinRect& rect)
  1177. {
  1178. if (m_pdocumentCurrent) {
  1179. m_pdocumentCurrent->Render(hdc, rect);
  1180. } else {
  1181. Window::OnPaint(hdc, rect);
  1182. }
  1183. }
  1184. bool OnSysKey(IInputProvider* pprovider, int vk, bool bDown)
  1185. {
  1186. if (m_pdocumentCurrent) {
  1187. if (bDown) {
  1188. switch(vk) {
  1189. case VK_LEFT:
  1190. m_pdocumentCurrent->Left(true);
  1191. Invalidate();
  1192. return true;
  1193. case VK_RIGHT:
  1194. m_pdocumentCurrent->Right(true);
  1195. Invalidate();
  1196. return true;
  1197. case VK_UP:
  1198. m_pdocumentCurrent->Up(true);
  1199. Invalidate();
  1200. return true;
  1201. case VK_DOWN:
  1202. m_pdocumentCurrent->Down(true);
  1203. Invalidate();
  1204. return true;
  1205. case VK_PRIOR:
  1206. m_pdocumentCurrent->PageUp(true);
  1207. Invalidate();
  1208. return true;
  1209. case VK_NEXT:
  1210. m_pdocumentCurrent->PageDown(true);
  1211. Invalidate();
  1212. return true;
  1213. case VK_HOME:
  1214. m_pdocumentCurrent->GotoBeginingOfLine(true);
  1215. Invalidate();
  1216. return true;
  1217. case VK_END:
  1218. m_pdocumentCurrent->GotoEndOfLine(true);
  1219. Invalidate();
  1220. return true;
  1221. }
  1222. }
  1223. }
  1224. return false;
  1225. }
  1226. bool OnKey(IInputProvider* pprovider, int vk, bool bDown)
  1227. {
  1228. if (m_pdocumentCurrent) {
  1229. switch (vk) {
  1230. case VK_CONTROL:
  1231. m_bControl = bDown;
  1232. break;
  1233. case VK_SHIFT:
  1234. m_bShift = bDown;
  1235. break;
  1236. }
  1237. if (m_bControl && m_bShift) {
  1238. //
  1239. // bShift && bControl
  1240. //
  1241. if (bDown) {
  1242. switch(vk) {
  1243. case VK_PRIOR:
  1244. m_pdocumentCurrent->GotoBeginingOfDocument(true);
  1245. Invalidate();
  1246. return true;
  1247. case VK_NEXT:
  1248. m_pdocumentCurrent->GotoEndOfDocument(true);
  1249. Invalidate();
  1250. return true;
  1251. }
  1252. }
  1253. } else if (m_bControl) {
  1254. //
  1255. // !bShift && bControl
  1256. //
  1257. if (bDown) {
  1258. switch(vk) {
  1259. case 'Z':
  1260. m_pdocumentCurrent->Undo();
  1261. Invalidate();
  1262. return true;
  1263. case 'Q':
  1264. m_pdocumentCurrent->Redo();
  1265. Invalidate();
  1266. return true;
  1267. case 'X':
  1268. m_pdocumentCurrent->Cut();
  1269. Invalidate();
  1270. return true;
  1271. case 'C':
  1272. m_pdocumentCurrent->Copy();
  1273. Invalidate();
  1274. return true;
  1275. case 'V':
  1276. m_pdocumentCurrent->Paste();
  1277. Invalidate();
  1278. return true;
  1279. case 'J':
  1280. m_pdocumentCurrent->Join();
  1281. Invalidate();
  1282. return true;
  1283. case VK_LEFT:
  1284. m_pdocumentCurrent->ScrollLeft();
  1285. Invalidate();
  1286. return true;
  1287. case VK_RIGHT:
  1288. m_pdocumentCurrent->ScrollRight();
  1289. Invalidate();
  1290. return true;
  1291. case VK_UP:
  1292. m_pdocumentCurrent->ScrollUp();
  1293. Invalidate();
  1294. return true;
  1295. case VK_DOWN:
  1296. m_pdocumentCurrent->ScrollDown();
  1297. Invalidate();
  1298. return true;
  1299. case VK_PRIOR:
  1300. m_pdocumentCurrent->GotoBeginingOfDocument(false);
  1301. Invalidate();
  1302. return true;
  1303. case VK_NEXT:
  1304. m_pdocumentCurrent->GotoEndOfDocument(false);
  1305. Invalidate();
  1306. return true;
  1307. }
  1308. }
  1309. } else if (m_bShift) {
  1310. //
  1311. // bShift && !bControl
  1312. //
  1313. if (bDown) {
  1314. switch(vk) {
  1315. case VK_TAB:
  1316. m_pdocumentCurrent->BackTab();
  1317. Invalidate();
  1318. return true;
  1319. case VK_LEFT:
  1320. m_pdocumentCurrent->Left(true);
  1321. Invalidate();
  1322. return true;
  1323. case VK_RIGHT:
  1324. m_pdocumentCurrent->Right(true);
  1325. Invalidate();
  1326. return true;
  1327. case VK_UP:
  1328. m_pdocumentCurrent->Up(true);
  1329. Invalidate();
  1330. return true;
  1331. case VK_DOWN:
  1332. m_pdocumentCurrent->Down(true);
  1333. Invalidate();
  1334. return true;
  1335. case VK_PRIOR:
  1336. m_pdocumentCurrent->PageUp(true);
  1337. Invalidate();
  1338. return true;
  1339. case VK_NEXT:
  1340. m_pdocumentCurrent->PageDown(true);
  1341. Invalidate();
  1342. return true;
  1343. case VK_HOME:
  1344. m_pdocumentCurrent->GotoBeginingOfLine(true);
  1345. Invalidate();
  1346. return true;
  1347. case VK_END:
  1348. m_pdocumentCurrent->GotoEndOfLine(true);
  1349. Invalidate();
  1350. return true;
  1351. }
  1352. }
  1353. } else {
  1354. //
  1355. // !bShift && !bControl
  1356. //
  1357. if (bDown) {
  1358. switch(vk) {
  1359. case VK_LEFT:
  1360. m_pdocumentCurrent->Left(false);
  1361. Invalidate();
  1362. return true;
  1363. case VK_RIGHT:
  1364. m_pdocumentCurrent->Right(false);
  1365. Invalidate();
  1366. return true;
  1367. case VK_UP:
  1368. m_pdocumentCurrent->Up(false);
  1369. Invalidate();
  1370. return true;
  1371. case VK_DOWN:
  1372. m_pdocumentCurrent->Down(false);
  1373. Invalidate();
  1374. return true;
  1375. case VK_PRIOR:
  1376. m_pdocumentCurrent->PageUp(false);
  1377. Invalidate();
  1378. return true;
  1379. case VK_NEXT:
  1380. m_pdocumentCurrent->PageDown(false);
  1381. Invalidate();
  1382. return true;
  1383. case VK_HOME:
  1384. m_pdocumentCurrent->GotoBeginingOfLine(false);
  1385. Invalidate();
  1386. return true;
  1387. case VK_END:
  1388. m_pdocumentCurrent->GotoEndOfLine(false);
  1389. Invalidate();
  1390. return true;
  1391. case VK_ESCAPE:
  1392. m_pdocumentCurrent->Cancel();
  1393. Invalidate();
  1394. return true;
  1395. case VK_BACK:
  1396. m_pdocumentCurrent->Backspace();
  1397. Invalidate();
  1398. return true;
  1399. case VK_DELETE:
  1400. m_pdocumentCurrent->Delete();
  1401. Invalidate();
  1402. return true;
  1403. case VK_RETURN:
  1404. m_pdocumentCurrent->Split();
  1405. Invalidate();
  1406. return true;
  1407. case VK_TAB:
  1408. m_pdocumentCurrent->Tab();
  1409. Invalidate();
  1410. return true;
  1411. case VK_INSERT:
  1412. m_pdocumentCurrent->ToggleInsert();
  1413. Invalidate();
  1414. return true;
  1415. case VK_F3:
  1416. m_pdocumentCurrent->FindNext();
  1417. Invalidate();
  1418. return true;
  1419. case VK_F4:
  1420. m_pdocumentCurrent->FindPrevious();
  1421. Invalidate();
  1422. return true;
  1423. }
  1424. }
  1425. }
  1426. }
  1427. return false;
  1428. }
  1429. bool OnChar(IInputProvider* pprovider, TCHAR ch)
  1430. {
  1431. if (m_pdocumentCurrent) {
  1432. if (ch >= ' ' && ch <='~') {
  1433. m_pdocumentCurrent->Character(ch);
  1434. Invalidate();
  1435. return true;
  1436. }
  1437. }
  1438. return false;
  1439. }
  1440. };
  1441. //////////////////////////////////////////////////////////////////////////////
  1442. //
  1443. // Editor Application
  1444. //
  1445. //////////////////////////////////////////////////////////////////////////////
  1446. class EditApp : public Win32App {
  1447. protected:
  1448. TRef<EditorWindow> m_pwindow;
  1449. public:
  1450. EditApp()
  1451. {
  1452. }
  1453. void Error(const ZString& str)
  1454. {
  1455. m_pwindow->MessageBox(str, "Error", MB_ICONEXCLAMATION | MB_OK);
  1456. }
  1457. HRESULT Initialize(const ZString& strCommandLine)
  1458. {
  1459. m_pwindow = new EditorWindow();
  1460. //
  1461. // Parse the Command line
  1462. //
  1463. PCC pcc = strCommandLine;
  1464. CommandLineToken token(pcc, strCommandLine.GetLength());
  1465. while (token.MoreTokens()) {
  1466. ZString str;
  1467. if (token.Is(CommandLineToken::Minus, false)) {
  1468. /*
  1469. ZString str;
  1470. if (token.IsSymbol(str, true)) {
  1471. if (str == "reduce") {
  1472. if (token.IsNumber(m_scale, true)) {
  1473. m_mode = ModeReduce;
  1474. continue;
  1475. }
  1476. } else if (str == "flatten") {
  1477. if (token.IsNumber(m_frame, true)) {
  1478. m_mode = ModeFlatten;
  1479. continue;
  1480. }
  1481. }
  1482. }
  1483. */
  1484. } else if (token.IsPath(str, true)) {
  1485. if (FAILED(m_pwindow->Open(str))) {
  1486. Error("Unable to open " + str + ".");
  1487. }
  1488. continue;
  1489. }
  1490. //
  1491. // error occured
  1492. //
  1493. Error("Invalid command line.");
  1494. break;
  1495. }
  1496. return S_OK;
  1497. }
  1498. HRESULT Terminate()
  1499. {
  1500. return S_OK;
  1501. }
  1502. } g_app;