Mercurial > hg > octave-nkf
comparison libgui/src/qtinfo/parser.cc @ 15196:017f0b2e6933
rename gui directory to libgu
* libgui: Rename from gui.
* .hgsub (libgui/qterminal): Rename from gui/qterminal.
* Makefile.am (GUIDIR): Set to libgui instead of gui if
AMCOND_BUILD_GUI is true.
* configure.ac (AC_CONFIG_FILES): Update list for directory renaming.
* Makefile.am (.NOTPARALLEL): Delete.
List octave.html/index.html as the primary HTML target, not
octave.html.
(octave.html): New target for making the octave.html directory.
(octave.pdf): Depend on octave.dvi.
* images.awk: In generated rules for png files, depend on octave.html,
not octave.html/index.html.
* src/Makefile.am (OCTAVE_GUI_CPPFLAGS, OCTAVE_GUI_LIBS): Update for
directory renaming.
(CLEANFILES): Fix typo.
* fntests.m (src_tree): Use libinterp, not src.
author | John W. Eaton <jwe@octave.org> |
---|---|
date | Sat, 18 Aug 2012 18:10:09 -0400 |
parents | gui/src/qtinfo/parser.cc@48ae6a7c69c1 |
children | ae9079bbc627 |
comparison
equal
deleted
inserted
replaced
15195:2fc554ffbc28 | 15196:017f0b2e6933 |
---|---|
1 /* Copyright (C) 2009 P.L. Lucas | |
2 * Copyright (C) 2012 Jacob Dawid <jacob.dawid@gmail.com> | |
3 * | |
4 * This program is free software; you can redistribute it and/or modify | |
5 * it under the terms of the GNU General Public License as published by | |
6 * the Free Software Foundation; either version 2 of the License, or | |
7 * (at your option) any later version. | |
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 | |
15 * along with this program; if not, write to the Free Software | |
16 * Foundation, Inc., 59 Temple Place, Suite 330, | |
17 * Boston, MA 02111-1307, USA. | |
18 */ | |
19 | |
20 #include "parser.h" | |
21 #include <QFileInfo> | |
22 #include <QDir> | |
23 #include <QFile> | |
24 #include <QUrl> | |
25 #include <QRegExp> | |
26 #include <QProcess> | |
27 #include <QBuffer> | |
28 | |
29 parser::parser(QObject *parent) | |
30 : QObject(parent) | |
31 { | |
32 _compressors_map.insert ("bz2", "bzip2 -dc \"%1\""); | |
33 _compressors_map.insert ("gz", "gzip -dc \"%1\""); | |
34 _compressors_map.insert ("lzma", "lzma -dc \"%1\""); | |
35 _compressors_map.insert ("xz", "xz -dc \"%1\""); | |
36 _compressors_map.insert ("Z", "gunzip -c \"%1\""); | |
37 } | |
38 | |
39 void | |
40 parser::set_info_path (QString infoPath) | |
41 { | |
42 this->_info_path = infoPath; | |
43 | |
44 _info_files.clear (); | |
45 | |
46 QFileInfo info (infoPath); | |
47 | |
48 QString path = info.absolutePath (); | |
49 QString fileName = info.fileName (); | |
50 | |
51 QDir infoDir (path); | |
52 QStringList filter; | |
53 filter.append (fileName + "*"); | |
54 | |
55 _info_files = infoDir.entryInfoList (filter, QDir::Files); | |
56 parse_info_map (); | |
57 } | |
58 | |
59 QString | |
60 parser::get_info_path () | |
61 { | |
62 return _info_path; | |
63 } | |
64 | |
65 QIODevice * | |
66 parser::open_file (QFileInfo & file_info) | |
67 { | |
68 QIODevice *iodevice=NULL; | |
69 if ( _compressors_map.contains(file_info.suffix ())) | |
70 { | |
71 QProcess gzip; | |
72 gzip.start (_compressors_map.value (file_info.suffix ()).arg (file_info.absoluteFilePath ())); | |
73 | |
74 if (!gzip.waitForFinished ()) | |
75 return NULL; | |
76 | |
77 QByteArray result = gzip.readAll (); | |
78 | |
79 QBuffer *io = new QBuffer (this); | |
80 io->setData (result); | |
81 | |
82 if (!io->open (QIODevice::ReadOnly | QIODevice::Text)) | |
83 return NULL; | |
84 | |
85 iodevice = io; | |
86 } | |
87 else | |
88 { | |
89 QFile *io = new QFile (file_info.absoluteFilePath ()); | |
90 if (!io->open (QIODevice::ReadOnly | QIODevice::Text)) | |
91 return NULL; | |
92 iodevice = io; | |
93 } | |
94 | |
95 return iodevice; | |
96 } | |
97 | |
98 int | |
99 parser::is_ref (QString node) | |
100 { | |
101 if (_ref_map.contains (node)) | |
102 { | |
103 node_position ref = _ref_map [node]; | |
104 | |
105 return ref.pos-_node_map [ref._node_name].pos; | |
106 } | |
107 return -1; | |
108 } | |
109 | |
110 QString | |
111 parser::search_node (QString node) | |
112 { | |
113 QFileInfo file_info; | |
114 QString ref; | |
115 | |
116 if (_ref_map.contains (node)) | |
117 { | |
118 ref = node; | |
119 node = _ref_map [ref]._node_name; | |
120 } | |
121 | |
122 if (_node_map.contains (node)) | |
123 { | |
124 int pos = _node_map [node].pos; | |
125 int realPos; | |
126 | |
127 real_position (pos, file_info, realPos); | |
128 | |
129 QIODevice *io = open_file (file_info); | |
130 if (io == NULL) | |
131 { | |
132 return QString (); | |
133 } | |
134 | |
135 seek (io, realPos); | |
136 | |
137 QString text = get_next_node (io); | |
138 if (!text.isEmpty()) | |
139 { | |
140 return text; | |
141 } | |
142 | |
143 io->close (); | |
144 delete io; | |
145 } | |
146 | |
147 return QString (); | |
148 } | |
149 | |
150 QString | |
151 parser::search_node (QString node, QIODevice *io) | |
152 { | |
153 while (!io->atEnd ()) | |
154 { | |
155 QString text = get_next_node (io); | |
156 if(node == get_node_name (text)) | |
157 { | |
158 return text; | |
159 } | |
160 } | |
161 | |
162 return QString (); | |
163 } | |
164 | |
165 QString | |
166 parser::get_next_node (QIODevice *io) | |
167 { | |
168 QString text; | |
169 while (!io->atEnd ()) | |
170 { | |
171 QByteArray line = io->readLine (); | |
172 if (line.at(0) == 31) | |
173 { | |
174 break; | |
175 } | |
176 else | |
177 { | |
178 text.append (line); | |
179 } | |
180 } | |
181 return text; | |
182 } | |
183 | |
184 static QString | |
185 get_first_line (QString text) | |
186 { | |
187 int n = text.indexOf ("\n"); | |
188 | |
189 if (n < 0) | |
190 { | |
191 return QString (); | |
192 } | |
193 | |
194 QString first_line = text.left (n); | |
195 return first_line; | |
196 } | |
197 | |
198 static QString | |
199 parser_node (QString text, QString node_name) | |
200 { | |
201 QString firstLine = get_first_line (text); | |
202 QStringList nodes = firstLine.split (","); | |
203 for (int i = 0;i < nodes.size (); i++) | |
204 { | |
205 QString node = nodes.at (i).trimmed (); | |
206 | |
207 if (node.startsWith (node_name)) | |
208 { | |
209 return node.remove (0, node_name.size ()).trimmed (); | |
210 } | |
211 } | |
212 return QString (); | |
213 } | |
214 | |
215 QString | |
216 parser::get_node_name (QString text) | |
217 { | |
218 return parser_node (text, "Node:"); | |
219 } | |
220 | |
221 QString | |
222 parser::get_node_up (QString text) | |
223 { | |
224 return parser_node (text, "Up:"); | |
225 } | |
226 | |
227 QString | |
228 parser::get_node_next (QString text) | |
229 { | |
230 return parser_node (text, "Next:"); | |
231 } | |
232 | |
233 QString | |
234 parser::get_node_prev (QString text) | |
235 { | |
236 return parser_node (text, "Prev:"); | |
237 } | |
238 | |
239 static void | |
240 replace_links (QString &text) | |
241 { | |
242 QRegExp re ("(\\*[N|n]ote|\n\\*)([ |\n]+)([^:]+):([^:\\.,]*)([:,\\.])"); | |
243 int i = 0, f; | |
244 | |
245 while ( (i = re.indexIn (text,i)) != -1) | |
246 { | |
247 QString type = re.cap (1); | |
248 QString note = re.cap (3); | |
249 QString url_link = re.cap (4); | |
250 QString link = re.cap (4); | |
251 | |
252 if (url_link.isEmpty ()) | |
253 { | |
254 url_link = note; | |
255 } | |
256 | |
257 url_link = url_link.trimmed (); | |
258 url_link.replace ("\n"," "); | |
259 url_link.replace (QRegExp (" +")," "); | |
260 url_link.replace ("<b>",""); | |
261 url_link.replace ("</b>",""); | |
262 url_link = QUrl::toPercentEncoding (url_link, "", "'"); | |
263 | |
264 QString href; | |
265 if (type=="\n*") | |
266 { | |
267 href="\n<img src=':/actions/icons/bookmark.png'/>"; | |
268 } | |
269 else | |
270 { | |
271 href="<img src=':/actions/icons/bookmark.png'/>"; | |
272 } | |
273 href += re.cap (2) + "<a href='" + url_link + "'>" + note + ":" + link + re.cap (5) + "</a>"; | |
274 f = re.matchedLength (); | |
275 text.replace (i,f,href); | |
276 i += href.size (); | |
277 } | |
278 } | |
279 | |
280 static void | |
281 replace_colons (QString &text) | |
282 { | |
283 QRegExp re ("`([^']+)'"); | |
284 int i = 0, f; | |
285 while ( (i = re.indexIn (text, i)) != -1) | |
286 { | |
287 QString t = re.cap (1); | |
288 QString bold = "<b>`" + t + "</b>'"; | |
289 | |
290 f = re.matchedLength (); | |
291 text.replace (i,f,bold); | |
292 i += bold.size (); | |
293 } | |
294 } | |
295 | |
296 static void | |
297 info_to_html (QString &text) | |
298 { | |
299 text.replace ("&", "&"); | |
300 text.replace ("<", "<"); | |
301 text.replace (">", ">"); | |
302 | |
303 text.replace ("\n* Menu:", "\n<b>Menu:</b>"); | |
304 text.replace ("*See also:*", "<b>See also:</b>"); | |
305 replace_colons (text); | |
306 replace_links (text); | |
307 } | |
308 | |
309 QString | |
310 parser::node_text_to_html (QString text, int anchorPos, QString anchor) | |
311 { | |
312 QString nodeName = get_node_name (text); | |
313 QString nodeUp = get_node_up (text); | |
314 QString nodeNext = get_node_next (text); | |
315 QString nodePrev = get_node_prev (text); | |
316 | |
317 if (anchorPos > -1) | |
318 { | |
319 QString text1 = text.left (anchorPos); | |
320 QString text2 = text.mid (anchorPos); | |
321 | |
322 int n = text1.indexOf ("\n"); | |
323 text1.remove (0, n); | |
324 | |
325 info_to_html (text1); | |
326 info_to_html (text2); | |
327 | |
328 text = text1 + "<a name='" + anchor + "' /><img src=':/actions/icons/stop.png'>" + text2; | |
329 } | |
330 else | |
331 { | |
332 int n = text.indexOf ("\n"); | |
333 text.remove (0, n); | |
334 info_to_html (text); | |
335 } | |
336 | |
337 QString navigationLinks = QString ( | |
338 "<img src=':/actions/icons/arrow_right.png'/> <b>Section:</b> %1<br>" | |
339 "<b>Previous Section:</b> <a href='%2'>%3</a><br>" | |
340 "<b>Next Section:</b> <a href='%4'>%5</a><br>" | |
341 "<b>Up:</b> <a href='%6'>%7</a><br>\n" | |
342 ) | |
343 .arg (nodeName) | |
344 .arg (QString (QUrl::toPercentEncoding (nodePrev, "", "'"))) | |
345 .arg (nodePrev) | |
346 .arg (QString (QUrl::toPercentEncoding (nodeNext, "", "'"))) | |
347 .arg (nodeNext) | |
348 .arg (QString (QUrl::toPercentEncoding (nodeUp, "", "'"))) | |
349 .arg (nodeUp); | |
350 | |
351 | |
352 text.prepend ("<hr>\n<pre>"); | |
353 text.append ("</pre>\n<hr><hr>\n"); | |
354 text.prepend (navigationLinks); | |
355 text.append (navigationLinks); | |
356 text.prepend ("<html><body>\n"); | |
357 text.append ("</body></html>\n"); | |
358 return text; | |
359 } | |
360 | |
361 void | |
362 parser::parse_info_map () | |
363 { | |
364 QRegExp re ("(Node|Ref): ([^\\0177]+)\\0177(\\d+)\n"); | |
365 QRegExp re_files ("([^:]+): (\\d+)\n"); | |
366 int foundCount = 0; | |
367 | |
368 for(int i = 0; i < _info_files.size (); i++) | |
369 { | |
370 QFileInfo fileInfo = _info_files.at (i); | |
371 | |
372 QIODevice *io = open_file (fileInfo); | |
373 if (io == NULL) | |
374 { | |
375 continue; | |
376 } | |
377 | |
378 QString nodeText; | |
379 while (! (nodeText=get_next_node (io)).isEmpty () && foundCount < 2) | |
380 { | |
381 QString first_line = get_first_line (nodeText); | |
382 if (first_line.startsWith ("Tag") ) | |
383 { | |
384 foundCount++; | |
385 int pos = 0; | |
386 QString last_node; | |
387 | |
388 while ((pos = re.indexIn (nodeText, pos)) != -1) { | |
389 QString type = re.cap (1); | |
390 QString node = re.cap (2); | |
391 int index = re.cap (3).toInt (); | |
392 | |
393 if (type == "Node") | |
394 { | |
395 node_map_item item; | |
396 item.pos = index; | |
397 _node_map [node] = item; | |
398 last_node = node; | |
399 } | |
400 else if (type == "Ref") | |
401 { | |
402 node_position item; | |
403 item._node_name = last_node; | |
404 item.pos = index; | |
405 _ref_map [node] = item; | |
406 } | |
407 pos += re.matchedLength (); | |
408 } | |
409 break; | |
410 } | |
411 else if (first_line.startsWith ("Indirect:")) | |
412 { | |
413 foundCount++; | |
414 int pos = 0; | |
415 | |
416 while ( (pos = re_files.indexIn (nodeText, pos)) != -1) { | |
417 QString fileCap = re_files.cap (1).trimmed (); | |
418 int index = re_files.cap (2).toInt (); | |
419 | |
420 info_file_item item; | |
421 for (int j = 0;j < _info_files.size (); j++) | |
422 { | |
423 QFileInfo info = _info_files.at (j); | |
424 if (info.fileName ().startsWith (fileCap)) | |
425 { | |
426 item.file_info = info; | |
427 break; | |
428 } | |
429 } | |
430 item.real_size = index; | |
431 _info_file_real_size_list.append (item); | |
432 pos += re_files.matchedLength (); | |
433 } | |
434 | |
435 } | |
436 } | |
437 io->close (); | |
438 delete io; | |
439 } | |
440 } | |
441 | |
442 void | |
443 parser::real_position (int pos, QFileInfo & file_info, int & real_pos) | |
444 { | |
445 int header = -1, sum = 0; | |
446 for (int i = 0; i < _info_file_real_size_list.size (); i++) | |
447 { | |
448 info_file_item item = _info_file_real_size_list.at (i); | |
449 if (header == -1) | |
450 { | |
451 file_info = item.file_info; | |
452 header = item.real_size; | |
453 } | |
454 | |
455 if (pos < item.real_size) | |
456 { | |
457 break; | |
458 } | |
459 | |
460 file_info = item.file_info; | |
461 sum = item.real_size; | |
462 } | |
463 real_pos = pos - sum + header + 2; | |
464 } | |
465 | |
466 void | |
467 parser::seek (QIODevice *io, int pos) | |
468 { | |
469 char ch; | |
470 while (!io->atEnd () && pos > 0) | |
471 { | |
472 io->getChar (&ch); | |
473 pos--; | |
474 } | |
475 } | |
476 | |
477 static void | |
478 replace (QString &text, QRegExp re, QString after) | |
479 { | |
480 int pos = 0; | |
481 | |
482 while ( (pos = re.indexIn (text, pos)) != -1) | |
483 { | |
484 QString cap = text.mid (pos,re.matchedLength ()); | |
485 QString a (after); | |
486 a = a.arg (cap); | |
487 text.remove (pos, re.matchedLength ()); | |
488 text.insert (pos, a); | |
489 pos += a.size (); | |
490 } | |
491 } | |
492 | |
493 QString | |
494 parser::global_search (QString text, int max_founds) | |
495 { | |
496 QString results; | |
497 QStringList words = text.split (" ",QString::SkipEmptyParts); | |
498 | |
499 QString re_program ("(" + words.at (0)); | |
500 for (int i = 1; i < words.size (); i++) | |
501 { | |
502 re_program += "|" + words.at (i); | |
503 } | |
504 re_program += ")"; | |
505 | |
506 QRegExp re (re_program, Qt::CaseInsensitive); | |
507 | |
508 results.append ("<html><body>\n<h1>Search results</h1>\n<b>Results for:</b> "); | |
509 results.append (text); | |
510 results.append ("<br>\n"); | |
511 | |
512 for (int i = 0; i < _info_files.size (); i++) | |
513 { | |
514 QFileInfo file_info = _info_files.at (i); | |
515 QIODevice *io = open_file (file_info); | |
516 if (io == NULL) | |
517 { | |
518 continue; | |
519 } | |
520 | |
521 QString node_text; | |
522 while ( !(node_text = get_next_node (io)).isEmpty ()) | |
523 { | |
524 QString firstLine = get_first_line (node_text); | |
525 QString node = get_node_name (node_text); | |
526 if (node.isEmpty ()) | |
527 { | |
528 continue; | |
529 } | |
530 | |
531 int n = node_text.indexOf ("\n"); | |
532 node_text.remove (0, n); | |
533 | |
534 int pos = 0; | |
535 int founds = 0; | |
536 | |
537 for (; founds < words.size () && node_text.indexOf (words.at (founds)) >= 0; founds++) | |
538 { } | |
539 | |
540 if (founds<words.size ()) | |
541 { | |
542 continue; | |
543 } | |
544 founds = 0; | |
545 | |
546 while ( (pos = re.indexIn (node_text, pos)) != -1 && founds < max_founds) | |
547 { | |
548 int line_start, line_end; | |
549 line_start = node_text.lastIndexOf ("\n", pos); | |
550 line_end = node_text.indexOf ("\n", pos); | |
551 QString line = node_text.mid (line_start, line_end - line_start).trimmed (); | |
552 | |
553 if (founds == 0) | |
554 { | |
555 results.append( | |
556 "<br>\n<img src=':/actions/icons/bookmark.png'> <a href='" | |
557 + QString(QUrl::toPercentEncoding(node,"","'")) + | |
558 "'>"); | |
559 results.append (node); | |
560 results.append ("</a><br>\n"); | |
561 } | |
562 | |
563 replace (line, re, "<i>%1</i>"); | |
564 results.append (line); | |
565 results.append ("<br>\n"); | |
566 | |
567 founds++; | |
568 | |
569 pos += re.matchedLength (); | |
570 } | |
571 } | |
572 io->close (); | |
573 delete io; | |
574 } | |
575 | |
576 results.append ("</body></html>"); | |
577 return results; | |
578 } |