helpbox.cc 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249
  1. // Copyright (C) 2003 Mooffie <mooffie@typo.co.il>
  2. //
  3. // This program is free software; you can redistribute it and/or modify
  4. // it under the terms of the GNU General Public License as published by
  5. // the Free Software Foundation; either version 2 of the License, or
  6. // (at your option) any later version.
  7. //
  8. // This program is distributed in the hope that it will be useful,
  9. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. // GNU General Public License for more details.
  12. //
  13. // You should have received a copy of the GNU General Public License
  14. // along with this program; if not, write to the Free Software
  15. // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
  16. #include <config.h>
  17. #include "helpbox.h"
  18. #include "editor.h"
  19. #include "io.h"
  20. #include "pathnames.h"
  21. #include "themes.h"
  22. std::vector<HelpBox::Position> HelpBox::positions_stack;
  23. HelpBox::HelpBox(Editor *aApp, const EditBox &settings)
  24. {
  25. app = aApp;
  26. statusmsg.set_text(_("F1 or ALT-X to exit help, ENTER to follow link, 'l' to move back, 't' to TOC"));
  27. statusmsg.highlight();
  28. set_undo_size_limit(0);
  29. set_read_only(true);
  30. scroll_step = settings.get_scroll_step();
  31. rtl_nsm_display = settings.get_rtl_nsm_display();
  32. maqaf_display = settings.get_maqaf_display();
  33. show_explicits = false;
  34. show_paragraph_endings = true;
  35. show_tabs = true;
  36. }
  37. INTERACTIVE void HelpBox::layout_windows()
  38. {
  39. app->layout_windows();
  40. int cols, rows;
  41. getmaxyx(stdscr, rows, cols);
  42. resize(rows - 1, cols, 0, 0);
  43. statusmsg.resize(1, cols, rows - 1, 0);
  44. }
  45. bool HelpBox::load_user_manual()
  46. {
  47. u8string dummy_encoding;
  48. bool dummy_new;
  49. if (!xload_file(this, get_cfg_filename(USER_MANUAL_FILE),
  50. NULL, "UTF-8", dummy_encoding, dummy_new, false)
  51. && !xload_file(this, get_cfg_filename(SYSTEM_MANUAL_FILE),
  52. NULL, "UTF-8", dummy_encoding, dummy_new, false))
  53. {
  54. app->show_file_io_error(_("Cannot open the manual file %s: %s"),
  55. get_cfg_filename(SYSTEM_MANUAL_FILE));
  56. return false;
  57. } else {
  58. scan_toc();
  59. pop_position();
  60. return true;
  61. }
  62. }
  63. void HelpBox::push_position()
  64. {
  65. Position pos;
  66. pos.top_line = top_line;
  67. pos.cursor = cursor;
  68. positions_stack.push_back(pos);
  69. }
  70. INTERACTIVE void HelpBox::pop_position()
  71. {
  72. if (positions_stack.size()) {
  73. Position pos = positions_stack.back();
  74. positions_stack.pop_back();
  75. top_line = pos.top_line;
  76. if ((int)paragraphs[top_line.para]->line_breaks.size()
  77. <= top_line.inner_line)
  78. // window probably resized, so previous
  79. // inner_line lost.
  80. top_line.inner_line = 0;
  81. set_cursor_position(pos.cursor);
  82. request_update(rgnAll);
  83. }
  84. }
  85. INTERACTIVE void HelpBox::move_to_toc()
  86. {
  87. push_position();
  88. top_line = CombinedLine(toc_first_line, 0);
  89. set_cursor_position(Point(toc_first_line, 0));
  90. request_update(rgnAll);
  91. }
  92. INTERACTIVE void HelpBox::refresh_and_center()
  93. {
  94. center_line();
  95. invalidate_view();
  96. statusmsg.invalidate_view();
  97. clearok(curscr, TRUE);
  98. }
  99. INTERACTIVE void HelpBox::jump_to_topic(const char *topic)
  100. {
  101. push_position();
  102. move_beginning_of_buffer();
  103. while (search_forward(unistring(u8string(topic))) && cursor.pos != 0)
  104. ;
  105. top_line = CombinedLine(cursor.para, 0);
  106. request_update(rgnAll);
  107. }
  108. // HelpBox::exec() - reads events and hands them to the help window.
  109. void HelpBox::exec()
  110. {
  111. set_modal();
  112. while (is_modal()) {
  113. Event evt;
  114. statusmsg.update();
  115. update();
  116. doupdate();
  117. get_next_event(evt, wnd);
  118. handle_event(evt);
  119. }
  120. push_position();
  121. }
  122. // scan_toc() - reads the TOC (table of contents) into toc_items
  123. void HelpBox::scan_toc()
  124. {
  125. toc_items.clear();
  126. bool in_toc = false;
  127. for (int i = 0; i < parags_count(); i++) {
  128. const unistring &str = paragraphs[i]->str;
  129. if (!in_toc) {
  130. if (str.len() && str[0] == '-') {
  131. in_toc = true;
  132. toc_first_line = i;
  133. }
  134. }
  135. if (in_toc) {
  136. if (str.len()) {
  137. // add this item to toc_items
  138. unistring item = str;
  139. while (item.len() &&
  140. (item[0] == ' ' || item[0] == '-'))
  141. item.erase_head(1);
  142. toc_items.push_back(item);
  143. } else {
  144. // finished processing TOC
  145. toc_last_line = i - 1;
  146. break;
  147. }
  148. }
  149. }
  150. }
  151. // jump_to_topic() - reads the topic on which the cursor stands,
  152. // then jumps to it. Usually called in reply to the ENTER key.
  153. void HelpBox::jump_to_topic()
  154. {
  155. const unistring &str = curr_para()->str;
  156. if (cursor.para >= toc_first_line && cursor.para <= toc_last_line) {
  157. unistring topic = str;
  158. while (topic.len()
  159. && (topic[0] == ' ' || topic[0] == '-'))
  160. topic.erase_head(1);
  161. jump_to_topic(u8string(topic).c_str());
  162. } else if (cursor.pos < str.len()) {
  163. // read the topic on which the cursor stands
  164. idx_t start = cursor.pos;
  165. while (start >= 0 && str[start] != '"')
  166. start--;
  167. idx_t end = cursor.pos;
  168. while (end < str.len() && str[end] != '"')
  169. end++;
  170. if (str[start] == '"' && str[end] == '"' && (start < end)) {
  171. unistring topic = str.substr(start + 1, end - start - 1);
  172. jump_to_topic(u8string(topic).c_str());
  173. }
  174. }
  175. }
  176. // do_syntax_highlight() - highlight all the topic names in the text.
  177. void HelpBox::do_syntax_highlight(const unistring &str,
  178. AttributeArray &attributes, int para_num)
  179. {
  180. attribute_t links_attr = get_attr(EDIT_LINKS_ATTR);
  181. if (para_num >= toc_first_line && para_num <= toc_last_line) {
  182. // toc
  183. int i = 0;
  184. while (str[i] == ' ' || str[i] == '-')
  185. i++;
  186. while (i < str.len())
  187. attributes[i++] = links_attr;
  188. } else {
  189. // normal text: search for the topic names
  190. for (int i = 0; i < (int)toc_items.size(); i++) {
  191. unistring topic = toc_items[i];
  192. topic.insert(topic.begin(), '"');
  193. topic.push_back('"');
  194. idx_t pos = 0;
  195. while ((pos = str.index(topic, pos + 1)) != -1) {
  196. for (idx_t k = pos + 1; k < pos + topic.len() - 1; k++)
  197. attributes[k] = links_attr;
  198. }
  199. }
  200. }
  201. }
  202. bool HelpBox::handle_event(const Event &evt)
  203. {
  204. if (evt.is_literal()) {
  205. switch (evt.ch) {
  206. case 13:
  207. jump_to_topic();
  208. return true;
  209. case 'l':
  210. pop_position();
  211. return true;
  212. case 't':
  213. case 'd':
  214. move_to_toc();
  215. return true;
  216. case 'q':
  217. end_modal();
  218. return true;
  219. }
  220. }
  221. if (!Dispatcher::handle_event(evt))
  222. return EditBox::handle_event(evt);
  223. return false;
  224. }