PageRenderTime 53ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/boxvivid/uppsrc/RichEdit/Formating.cpp

http://boxvivid.googlecode.com/
C++ | 627 lines | 578 code | 49 blank | 0 comment | 117 complexity | e829d35759849c3e3a48ab85edb1774a MD5 | raw file
Possible License(s): LGPL-2.1, BSD-2-Clause, BSD-3-Clause, LGPL-3.0
  1. #include "RichEdit.h"
  2. NAMESPACE_UPP
  3. void RichEdit::ApplyFormat(dword charvalid, dword paravalid)
  4. {
  5. if(IsReadOnly())
  6. return;
  7. RichText::FormatInfo f = formatinfo;
  8. f.charvalid = charvalid;
  9. f.paravalid = paravalid;
  10. if(objectpos >= 0) {
  11. ModifyFormat(objectpos, f, 1);
  12. Finish();
  13. }
  14. if(IsSelection()) {
  15. if(tablesel) {
  16. NextUndo();
  17. SaveTable(tablesel);
  18. text.ApplyTableFormatInfo(tablesel, cells, f);
  19. }
  20. else {
  21. int l = min(cursor, anchor);
  22. int h = max(cursor, anchor);
  23. RichPos rp = text.GetRichPos(h);
  24. if(rp.posinpara == 0 && h > l) {
  25. RichPos rp1 = text.GetRichPos(h - 1);
  26. if(InSameTxt(rp, rp1))
  27. h--;
  28. }
  29. ModifyFormat(l, f, h - l);
  30. }
  31. Finish();
  32. }
  33. else
  34. if(cursorp.paralen == 0) {
  35. ModifyFormat(cursor, f, 0);
  36. Finish();
  37. }
  38. else
  39. if(f.paravalid) {
  40. ModifyFormat(cursor, f, 0);
  41. Finish();
  42. }
  43. else
  44. RefreshBar();
  45. }
  46. void RichEdit::ApplyFormatInfo(const RichText::FormatInfo& fi)
  47. {
  48. fi.ApplyTo(formatinfo);
  49. formatinfo.charvalid |= fi.charvalid;
  50. formatinfo.paravalid |= fi.paravalid;
  51. ApplyFormat(fi.charvalid, fi.paravalid);
  52. }
  53. void RichEdit::Bold()
  54. {
  55. NextUndo();
  56. formatinfo.Bold(!(formatinfo.IsBold() && (formatinfo.charvalid & RichText::BOLD)));
  57. ApplyFormat(RichText::BOLD);
  58. }
  59. void RichEdit::Italic()
  60. {
  61. NextUndo();
  62. formatinfo.Italic(!(formatinfo.IsItalic() && (formatinfo.charvalid & RichText::ITALIC)));
  63. ApplyFormat(RichText::ITALIC);
  64. }
  65. void RichEdit::Underline()
  66. {
  67. NextUndo();
  68. formatinfo.Underline(!(formatinfo.IsUnderline() && (formatinfo.charvalid & RichText::UNDERLINE)));
  69. ApplyFormat(RichText::UNDERLINE);
  70. }
  71. void RichEdit::Strikeout()
  72. {
  73. NextUndo();
  74. formatinfo.Strikeout(!(formatinfo.IsStrikeout() && (formatinfo.charvalid & RichText::STRIKEOUT)));
  75. ApplyFormat(RichText::STRIKEOUT);
  76. }
  77. void RichEdit::Capitals()
  78. {
  79. NextUndo();
  80. formatinfo.capitals = !formatinfo.capitals && (formatinfo.charvalid & RichText::CAPITALS);
  81. ApplyFormat(RichText::CAPITALS);
  82. }
  83. void RichEdit::SetScript(int i)
  84. {
  85. NextUndo();
  86. formatinfo.sscript = i;
  87. ApplyFormat(RichText::SSCRIPT);
  88. }
  89. void RichEdit::SetFace()
  90. {
  91. NextUndo();
  92. formatinfo.Face(~face);
  93. ApplyFormat(RichText::FACE);
  94. SetFocus();
  95. }
  96. void RichEdit::SetHeight()
  97. {
  98. NextUndo();
  99. formatinfo.Height(PtToDot(~height));
  100. ApplyFormat(RichText::HEIGHT);
  101. SetFocus();
  102. }
  103. void RichEdit::SetInk()
  104. {
  105. NextUndo();
  106. formatinfo.ink = ~ink;
  107. ApplyFormat(RichText::INK);
  108. SetFocus();
  109. }
  110. void RichEdit::SetPaper()
  111. {
  112. NextUndo();
  113. formatinfo.paper = ~paper;
  114. ApplyFormat(RichText::PAPER);
  115. SetFocus();
  116. }
  117. void RichEdit::SetLanguage()
  118. {
  119. NextUndo();
  120. formatinfo.language = (int)~language;
  121. ApplyFormat(RichText::LANGUAGE);
  122. SetFocus();
  123. }
  124. void RichEdit::Language()
  125. {
  126. WithRichLanguageLayout<TopWindow> d;
  127. CtrlLayoutOKCancel(d, t_("Language"));
  128. d.lang <<= ~language;
  129. if(d.Run() != IDOK)
  130. return;
  131. formatinfo.language = (int)~d.lang;
  132. ApplyFormat(RichText::LANGUAGE);
  133. SetFocus();
  134. if(!language.HasKey((int)~d.lang)) {
  135. Vector<int> h;
  136. for(int i = 0; i < language.GetCount(); i++)
  137. h.Add(language.GetKey(i));
  138. h.Add(~d.lang);
  139. SetupLanguage(h);
  140. }
  141. }
  142. void RichEdit::IndentMark()
  143. {
  144. RichRuler::Marker m;
  145. int l = formatinfo.lm;
  146. int r = cursorc.textpage.Width() - formatinfo.rm;
  147. m.pos = l + formatinfo.indent;
  148. m.minpos = max(l, 0);
  149. m.maxpos = max(r - 120, 0);
  150. m.top = true;
  151. m.image = formatinfo.paravalid & RichText::INDENT ? RichEditImg::Indent()
  152. : RichEditImg::IndentMixed();
  153. ruler.Set(2, m);
  154. }
  155. void RichEdit::ReadFormat()
  156. {
  157. if(objectpos >= 0)
  158. formatinfo = text.GetFormatInfo(objectpos, 1);
  159. else
  160. if(IsSelection())
  161. if(tablesel)
  162. formatinfo = text.GetTableFormatInfo(tablesel, cells);
  163. else
  164. formatinfo = text.GetFormatInfo(min(cursor, anchor), abs(cursor - anchor));
  165. else {
  166. RichPos p = cursorp;
  167. if(cursor && p.posinpara)
  168. p = text.GetRichPos(cursor - 1);
  169. formatinfo.Set(p.format);
  170. }
  171. ShowFormat();
  172. }
  173. void RichEdit::ShowFormat()
  174. {
  175. RefreshBar();
  176. if(formatinfo.charvalid & RichText::FACE)
  177. face <<= formatinfo.GetFace();
  178. else
  179. face <<= Null;
  180. if(formatinfo.charvalid & RichText::HEIGHT)
  181. height <<= DotToPt(formatinfo.GetHeight());
  182. else
  183. height <<= Null;
  184. if(formatinfo.charvalid & RichText::LINK)
  185. hyperlink <<= formatinfo.link;
  186. else
  187. hyperlink <<= Null;
  188. if(formatinfo.charvalid & RichText::INDEXENTRY)
  189. indexentry <<= formatinfo.indexentry;
  190. else
  191. indexentry <<= Null;
  192. if(formatinfo.charvalid & RichText::INK)
  193. ink <<= formatinfo.ink;
  194. else
  195. ink <<= Null;
  196. if(formatinfo.charvalid & RichText::PAPER)
  197. paper <<= formatinfo.paper;
  198. else
  199. paper <<= Null;
  200. if(formatinfo.charvalid & RichText::LANG)
  201. language <<= (int)formatinfo.language;
  202. else
  203. language <<= Null;
  204. if(IsSelection())
  205. label <<= Null;
  206. else
  207. label <<= formatinfo.label;
  208. int l = formatinfo.lm;
  209. int r = cursorc.textpage.Width() - formatinfo.rm;
  210. RichRuler::Marker m;
  211. m.pos = l;
  212. m.minpos = 0;
  213. m.maxpos = max(r - formatinfo.indent - 120, 0);
  214. m.image = formatinfo.paravalid & RichText::LM ? RichEditImg::Margin() : RichEditImg::MarginMixed();
  215. ruler.Set(0, m);
  216. m.pos = r;
  217. m.minpos = max(l + formatinfo.indent + 120, 0);
  218. m.maxpos = cursorc.textpage.Width();
  219. m.image = formatinfo.paravalid & RichText::RM ? RichEditImg::Margin() : RichEditImg::MarginMixed();
  220. ruler.Set(1, m);
  221. IndentMark();
  222. int maxpos = 0;
  223. m.minpos = 0;
  224. m.deletable = true;
  225. if(formatinfo.paravalid & RichText::TABS) {
  226. for(int i = 0; i < formatinfo.tab.GetCount(); i++) {
  227. RichPara::Tab tab = formatinfo.tab[i];
  228. m.pos = tab.pos;
  229. if(tab.pos > maxpos)
  230. maxpos = tab.pos;
  231. switch(tab.align) {
  232. case ALIGN_LEFT:
  233. m.image = RichEditImg::LeftTab();
  234. break;
  235. case ALIGN_RIGHT:
  236. m.image = RichEditImg::RightTab();
  237. break;
  238. case ALIGN_CENTER:
  239. m.image = RichEditImg::CenterTab();
  240. break;
  241. }
  242. ruler.Set(i + 3, m);
  243. }
  244. ruler.SetTabs(maxpos, formatinfo.tabsize);
  245. ruler.SetCount(formatinfo.tab.GetCount() + 3);
  246. }
  247. else {
  248. ruler.SetTabs(INT_MAX / 2, 1);
  249. ruler.SetCount(3);
  250. }
  251. if(formatinfo.paravalid & RichText::STYLE)
  252. style <<= formatinfo.styleid;
  253. else
  254. style <<= Null;
  255. setstyle->Enable(!IsSelection());
  256. }
  257. void RichEdit::HighLightTab(int r)
  258. {
  259. RichRuler::Marker m = ruler[r + 3];
  260. RichPara::Tab tab = formatinfo.tab[r];
  261. m.image = tab.align == ALIGN_RIGHT ? RichEditImg::RightTabTrack() :
  262. tab.align == ALIGN_CENTER ? RichEditImg::CenterTabTrack() :
  263. RichEditImg::LeftTabTrack();
  264. ruler.Set(r + 3, m);
  265. }
  266. void RichEdit::Hyperlink()
  267. {
  268. String s = formatinfo.link;
  269. if(!IsSelection() && !IsNull(s) && cursorp.format.link == s && text[cursor] != '\n') {
  270. int l = cursor - 1;
  271. while(l >= 0 && text[l] != '\n' && text.GetRichPos(l).format.link == s)
  272. l--;
  273. l++;
  274. int h = cursor;
  275. while(h < text.GetLength() && text[h] != '\n' && text.GetRichPos(h).format.link == s)
  276. h++;
  277. if(l < h)
  278. Select(l, h - l);
  279. }
  280. WString linktext;
  281. WhenHyperlink(s, linktext);
  282. if(s != formatinfo.link || linktext.GetLength()) {
  283. formatinfo.link = s;
  284. hyperlink <<= s;
  285. NextUndo();
  286. ApplyFormat(RichText::LINK);
  287. if(linktext.GetLength()) {
  288. RemoveSelection();
  289. RichPara p;
  290. p.format = formatinfo;
  291. p.Cat(linktext, formatinfo);
  292. RichText txt;
  293. txt.SetStyles(text.GetStyles());
  294. txt.Cat(p);
  295. Insert(cursor, txt, true);
  296. Move(cursor + linktext.GetCount(), false);
  297. }
  298. }
  299. SetFocus();
  300. }
  301. void RichEdit::Label()
  302. {
  303. if(IsSelection()) return;
  304. String s = formatinfo.label;
  305. WhenLabel(s);
  306. if(s != formatinfo.label) {
  307. formatinfo.label = s;
  308. NextUndo();
  309. ApplyFormat(0, RichText::LABEL);
  310. SetFocus();
  311. }
  312. }
  313. void RichEdit::IndexEntry()
  314. {
  315. if(EditText(formatinfo.indexentry, t_("Index Entry"), t_("Index entry"))) {
  316. indexentry <<= formatinfo.indexentry;
  317. ApplyFormat(RichText::INDEXENTRY);
  318. NextUndo();
  319. SetFocus();
  320. }
  321. }
  322. void RichEdit::BeginRulerTrack()
  323. {
  324. NextUndo();
  325. SaveFormat();
  326. int r = ruler.GetTrack();
  327. if(r < 0) return;
  328. RichRuler::Marker m = ruler[r];
  329. switch(r) {
  330. case 0:
  331. case 1:
  332. m.image = RichEditImg::MarginTrack();
  333. break;
  334. case 2:
  335. m.image = RichEditImg::IndentTrack();
  336. break;
  337. default:
  338. HighLightTab(r - 3);
  339. return;
  340. }
  341. ruler.Set(r, m);
  342. }
  343. void RichEdit::SetParaFormat(dword paravalid)
  344. {
  345. RichText::FormatInfo f = formatinfo;
  346. f.charvalid = 0;
  347. f.paravalid = paravalid;
  348. if(IsSelection())
  349. if(tablesel)
  350. text.ApplyTableFormatInfo(tablesel, cells, f);
  351. else
  352. text.ApplyFormatInfo(min(cursor, anchor), f, abs(cursor - anchor));
  353. else
  354. text.ApplyFormatInfo(cursor, f, 0);
  355. }
  356. void RichEdit::RulerTrack()
  357. {
  358. int r = ruler.GetTrack();
  359. if(r < 0) return;
  360. RichRuler::Marker m = ruler[r];
  361. switch(r) {
  362. case 0:
  363. formatinfo.lm = m.pos;
  364. SetParaFormat(RichText::LM);
  365. IndentMark();
  366. break;
  367. case 1:
  368. formatinfo.rm = cursorc.textpage.Width() - m.pos;
  369. SetParaFormat(RichText::RM);
  370. break;
  371. case 2:
  372. formatinfo.indent = m.pos - formatinfo.lm;
  373. SetParaFormat(RichText::INDENT);
  374. break;
  375. default:
  376. formatinfo.tab[r - 3].pos = m.pos;
  377. SetParaFormat(RichText::TABS);
  378. int maxpos = 0;
  379. for(int i = 0; i < formatinfo.tab.GetCount(); i++) {
  380. RichPara::Tab tab = formatinfo.tab[i];
  381. if(tab.pos > maxpos)
  382. maxpos = tab.pos;
  383. }
  384. ruler.SetTabs(maxpos, formatinfo.tabsize);
  385. break;
  386. }
  387. FinishNF();
  388. }
  389. void RichEdit::TabAdd(int align)
  390. {
  391. RichPara::Tab tab;
  392. tab.pos = ruler.GetPos();
  393. tab.align = align;
  394. if(formatinfo.tab.GetCount() > 30000 || tab.pos < 0 || tab.pos >= cursorc.textpage.Width()) return;
  395. formatinfo.tab.Add(tab);
  396. SetParaFormat(RichText::TABS);
  397. Finish();
  398. }
  399. void RichEdit::AddTab()
  400. {
  401. NextUndo();
  402. SaveFormat();
  403. TabAdd(ruler.GetNewTabAlign());
  404. }
  405. void RichEdit::TabMenu()
  406. {
  407. NextUndo();
  408. int r = ruler.GetTrack() - 3;
  409. if(r >= 0)
  410. HighLightTab(r);
  411. CallbackArgTarget<int> align;
  412. CallbackArgTarget<int> fill;
  413. MenuBar menu;
  414. menu.Add(t_("Left"), RichEditImg::LeftTab(), align[ALIGN_LEFT]);
  415. menu.Add(t_("Right"), RichEditImg::RightTab(), align[ALIGN_RIGHT]);
  416. menu.Add(t_("Center"), RichEditImg::CenterTab(), align[ALIGN_CENTER]);
  417. if(r >= 0) {
  418. int f = formatinfo.tab[r].fillchar;
  419. menu.Separator();
  420. menu.Add(t_("No fill"), fill[0])
  421. .Radio(f == 0);
  422. menu.Add(t_("Fill with ...."), fill[1])
  423. .Radio(f == 1);
  424. menu.Add(t_("Fill with ----"), fill[2])
  425. .Radio(f == 2);
  426. menu.Add(t_("Fill with __"), fill[3])
  427. .Radio(f == 3);
  428. menu.Separator();
  429. menu.Add(t_("Remove"), fill[-1]);
  430. }
  431. menu.Execute();
  432. if(!IsNull(align)) {
  433. SaveFormat();
  434. if(r >= 0) {
  435. formatinfo.tab[r].align = (int)align;
  436. SetParaFormat(RichText::TABS);
  437. }
  438. else
  439. TabAdd(align);
  440. }
  441. if(!IsNull(fill) && r >= 0) {
  442. SaveFormat();
  443. if(r >= 0) {
  444. if(fill == -1)
  445. formatinfo.tab[r].pos = Null;
  446. else
  447. formatinfo.tab[r].fillchar = (int)fill;
  448. SetParaFormat(RichText::TABS);
  449. }
  450. }
  451. Finish();
  452. }
  453. void RichEdit::AlignLeft()
  454. {
  455. NextUndo();
  456. formatinfo.align = ALIGN_LEFT;
  457. ApplyFormat(0, RichText::ALIGN);
  458. }
  459. void RichEdit::AlignRight()
  460. {
  461. NextUndo();
  462. formatinfo.align = ALIGN_RIGHT;
  463. ApplyFormat(0, RichText::ALIGN);
  464. }
  465. void RichEdit::AlignCenter()
  466. {
  467. NextUndo();
  468. formatinfo.align = ALIGN_CENTER;
  469. ApplyFormat(0, RichText::ALIGN);
  470. }
  471. void RichEdit::AlignJustify()
  472. {
  473. NextUndo();
  474. formatinfo.align = ALIGN_JUSTIFY;
  475. ApplyFormat(0, RichText::ALIGN);
  476. }
  477. void RichEdit::SetBullet(int bullet)
  478. {
  479. NextUndo();
  480. if((formatinfo.paravalid & RichText::BULLET) && formatinfo.bullet == bullet) {
  481. formatinfo.bullet = RichPara::BULLET_NONE;
  482. formatinfo.indent = formatinfo.paravalid & RichText::STYLE ?
  483. text.GetStyle(formatinfo.styleid).format.indent : 0;
  484. }
  485. else {
  486. formatinfo.bullet = bullet;
  487. formatinfo.indent = 150;
  488. }
  489. ApplyFormat(0, RichText::INDENT|RichText::BULLET);
  490. }
  491. void RichEdit::Style()
  492. {
  493. NextUndo();
  494. SaveFormat(cursor, 0);
  495. formatinfo.Set(text.GetStyle((Uuid)~style).format);
  496. ApplyFormat(0, RichText::STYLE);
  497. SetFocus();
  498. Finish();
  499. }
  500. void RichEdit::AdjustObjectSize()
  501. {
  502. NextUndo();
  503. RichObject obj = cursorp.object;
  504. if(!obj) return;
  505. WithObjectSizeLayout<TopWindow> d;
  506. CtrlLayoutOKCancel(d, t_("Object position"));
  507. Size sz = obj.GetSize();
  508. Size psz = obj.GetPhysicalSize();
  509. if(psz.cx == 0) psz.cx = 2000;
  510. if(psz.cy == 0) psz.cy = 2000;
  511. d.width.Set(unit, sz.cx);
  512. d.height.Set(unit, sz.cy);
  513. d.widthp.SetInc(5).Pattern("%.1f");
  514. d.widthp <<= 100.0 * sz.cx / psz.cx;
  515. d.heightp.SetInc(5).Pattern("%.1f");
  516. d.heightp <<= 100.0 * sz.cy / psz.cy;
  517. d.keepratio = obj.IsKeepRatio();
  518. d.width <<= d.height <<= d.widthp <<= d.heightp <<= d.Breaker(IDYES);
  519. d.ydelta.WithSgn().Set(unit, obj.GetYDelta());
  520. d.keepratio <<= d.Breaker(IDNO);
  521. for(;;) {
  522. switch(d.Run()) {
  523. case IDCANCEL:
  524. return;
  525. case IDYES:
  526. if(d.width.HasFocus() && !IsNull(d.width)) {
  527. d.widthp <<= 100 * (double)~d.width / psz.cx;
  528. if(d.keepratio) {
  529. d.height <<= psz.cy * (double)~d.width / psz.cx;
  530. d.heightp <<= ~d.widthp;
  531. }
  532. }
  533. if(d.height.HasFocus() && !IsNull(d.height)) {
  534. d.heightp <<= 100 * (double)~d.height / psz.cy;
  535. if(d.keepratio) {
  536. d.width <<= psz.cx * (double)~d.height / psz.cy;
  537. d.widthp <<= ~d.heightp;
  538. }
  539. }
  540. if(d.widthp.HasFocus() && !IsNull(d.widthp)) {
  541. d.width <<= psz.cx * (double)~d.widthp / 100;
  542. if(d.keepratio) {
  543. d.height <<= psz.cy * (double)~d.width / psz.cx;
  544. d.heightp <<= ~d.widthp;
  545. }
  546. }
  547. if(d.heightp.HasFocus() && !IsNull(d.heightp)) {
  548. d.height <<= psz.cy * (double)~d.heightp / 100;
  549. if(d.keepratio) {
  550. d.width <<= psz.cx * (double)~d.height / psz.cy;
  551. d.widthp <<= ~d.heightp;
  552. }
  553. }
  554. break;
  555. case IDNO:
  556. if(d.keepratio && !IsNull(d.width)) {
  557. d.widthp <<= 100 * (double)~d.width / psz.cx;
  558. if(d.keepratio) {
  559. d.height <<= psz.cy * (double)~d.width / psz.cx;
  560. d.heightp <<= ~d.widthp;
  561. }
  562. }
  563. break;
  564. case IDOK:
  565. if(!IsNull(d.width) && (int)~d.width >= 0)
  566. sz.cx = ~d.width;
  567. if(!IsNull(d.height) && (int)~d.height >= 0)
  568. sz.cy = ~d.height;
  569. obj.SetSize(sz);
  570. if(!IsNull(d.ydelta))
  571. obj.SetYDelta(~d.ydelta);
  572. obj.KeepRatio(d.keepratio);
  573. ReplaceObject(obj);
  574. return;
  575. }
  576. }
  577. }
  578. END_UPP_NAMESPACE