vlp-10 Using coding style in loghelp.
[vlp.git] / src / help / help.cpp
1 #include <qapp.h>
2 #include <qframe.h>
3 #include <qmlined.h>
4 #include <qmenubar.h>
5 #include <qpopmenu.h>
6 #include <qdialog.h>
7 #include <qbttngrp.h>
8 #include <qlabel.h>
9 #include <qlined.h>
10 #include <qlistbox.h>
11 #include <qpushbt.h>
12 #include <qradiobt.h>
13 #include <qlist.h>
14 #include <qfile.h>
15 #include <qcombo.h>
16 #include <qtooltip.h>
17 #include <qfont.h>
18 #include <qpixmap.h>
19 #include <qmsgbox.h>
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <unistd.h>
23 #include <qfile.h>
24 #include <qtstream.h>
25 #include <qstring.h>
26 #include <qfiledlg.h>
27 #include <qfontmet.h>
28 #include <qpainter.h>
29 #include <qscrbar.h>
30
31
32 #define TAG_TEXT        0
33 #define TAG_OTHER       1
34
35 #define TAG_LINK        2 
36 #define TAG_ANCHOR      3 
37 #define TAG_BOLD_ON     4 
38 #define TAG_BOLD_OFF    5 
39 #define TAG_ITALIC_ON   6 
40 #define TAG_ITALIC_OFF  7 
41 #define TAG_BREAK       8 
42 #define TAG_LINE        9 
43 #define TAG_LINK_END    10 
44 #define TAG_LIST_ON     11
45 #define TAG_LIST_OFF    12
46 #define TAG_LIST_ITEM   13
47
48 #define PIX_HEIGHT      2000
49
50 char names[14][40] = {
51         "text", "other", "link", "anchor", "bold on",
52         "bold off", "italic on", "italic off", "break",
53         "line", "end link", "list on", "list off", "list item"
54 };
55
56 class Tag {
57 public:
58         Tag()
59         {
60                 tag_type=0;
61                 strcpy(tag_label, "");
62                 strcpy(tag_link, "");
63                 strcpy(tag_text, "");
64         };
65         int tag_type;
66         char tag_label[255];
67         char tag_link[255];
68         char tag_text[255]; 
69         int x;
70         int y;
71         int w;
72         int h;
73 };
74
75 class HTMLAnalyzer {
76 public:
77         QList<Tag> tags;
78         bool verbatim;
79
80         HTMLAnalyzer();
81
82         bool LoadFile(char*);
83         void AnalyzeTag(QString*);
84         void PackLinks();
85         void DumpList();
86         Tag *CheckTag(int, int);
87         Tag *FindAnchor(char*);
88 };
89
90 HTMLAnalyzer::HTMLAnalyzer()
91 {
92         tags.clear();
93         verbatim = FALSE;
94 }
95
96
97 bool HTMLAnalyzer::LoadFile(char *fname)
98 {
99         QFile f(fname);
100         QString poms, poms1;
101         int i;
102         Tag *pomt;
103         bool not_ended;
104
105         tags.clear();
106         if (!f.open(IO_ReadOnly))
107                 return(FALSE);
108
109         QTextStream fs(&f);
110
111         while (!fs.eof()) {
112                 poms = fs.readLine();
113                 while (poms.length()>0) {
114                         i = poms.find('<');
115                         if (i != -1) {
116                                 if (i > 1) {
117                                         poms1 = poms.left(i);
118                                         pomt = new Tag;
119                                         pomt->tag_type = TAG_TEXT;
120                                         if (!verbatim) {
121                                                 poms1 = poms1.simplifyWhiteSpace();
122                                         }
123                                                 
124                                         sprintf(pomt->tag_text, " %s",
125                                                                 poms1.data());
126                                         tags.append(pomt);
127                                 }
128                                 poms = poms.right(poms.length() - i);
129
130                                 i = poms.find('>');
131                                 if (i != -1) {
132                                         poms1 = poms.mid(1, i - 1);
133                                         AnalyzeTag(&poms1);
134                                         poms = poms.right(poms.length() - i -1);
135                                 } else {
136                                         not_ended = TRUE;
137                                         break;
138                                 }
139                         } else {
140                                 pomt = new Tag;
141                                 pomt->tag_type = TAG_TEXT;
142                                 if (!verbatim) 
143                                         poms=poms.simplifyWhiteSpace();
144                                 
145                                 sprintf(pomt->tag_text, " %s", poms.data());
146                                 tags.append(pomt);
147                                 break;
148                         }
149                 }/* while length>0 */
150                 if (verbatim) {
151                         pomt = new Tag;
152                         pomt->tag_type = TAG_BREAK;
153                         tags.append(pomt);
154                 }
155         } /* eof */
156         f.close();
157         return TRUE;
158 }
159
160 void HTMLAnalyzer::AnalyzeTag(QString *t)
161 {
162         Tag *pom;
163         int i;
164         QString poms, poms1;
165
166         *t = t->simplifyWhiteSpace();
167         pom = new Tag;
168
169         if ((t->data()[0] != 'A') && (t->data()[0] != 'a')) {
170                 *t = t->upper();
171                 if (strcmp(t->data(), "B") ==0 ) {
172                         pom->tag_type = TAG_BOLD_ON;
173                 }
174                 else if (strcmp(t->data(), "/B") == 0) {
175                         pom->tag_type = TAG_BOLD_OFF;
176                 }
177                 else if (strcmp(t->data(), "I") == 0) {
178                         pom->tag_type = TAG_ITALIC_ON;
179                 }
180                 else if (strcmp(t->data(), "/I") == 0) {
181                         pom->tag_type = TAG_ITALIC_OFF;
182                 }
183                 else if (strcmp(t->data(), "BR") == 0) {
184                         pom->tag_type = TAG_BREAK;
185                 }
186                 else if (strcmp(t->data(), "HR") == 0) {
187                         pom->tag_type = TAG_LINE;
188                 }
189                 else if (strcmp(t->data(), "/A") == 0) {
190                         pom->tag_type = TAG_LINK_END;
191                 }
192                 else if (strcmp(t->data(), "UL") == 0) {
193                         pom->tag_type = TAG_LIST_ON;
194                 }
195                 else if (strcmp(t->data(), "/UL") == 0) {
196                         pom->tag_type = TAG_LIST_OFF;
197                 }
198                 else if (strcmp(t->data(), "LI") == 0) {
199                         pom->tag_type = TAG_LIST_ITEM;
200                 }
201                 else if (strcmp(t->data(), "PRE") == 0) {
202                         verbatim=TRUE;
203                 }
204                 else if (strcmp(t->data(),"/PRE") == 0) {
205                         verbatim=FALSE;
206                 }
207         } else {
208          /*
209         'a' or 'A'
210         links
211         */
212                 i = t->find('=');
213                 if (i != -1) {
214                         poms = t->mid(2, i - 2);
215                         poms = poms.simplifyWhiteSpace();
216                         poms = poms.upper();
217                         poms1 = t->right(t->length() - i - 1);
218                         poms1 = poms1.simplifyWhiteSpace();
219
220                         if (strcmp(poms.data(),"HREF") == 0) {
221                                 pom->tag_type = TAG_LINK;
222                                 strcpy(pom->tag_link,poms1.data());
223                         }
224                         else if (strcmp(poms.data(), "NAME") == 0) {
225                                 pom->tag_type = TAG_ANCHOR;
226                                 if (poms1.data()[0] == '"')
227                                         poms1=poms1.right(poms1.length() - 1);
228                                 if (poms1.data()[poms1.length() - 1] == '"')
229                                         poms1=poms1.left(poms1.length() - 1);
230                                 strcpy(pom->tag_label, poms1.data());
231                         }
232                 }
233         }
234         tags.append(pom);
235 }
236
237 void HTMLAnalyzer::DumpList()
238 {
239         Tag *pom;
240         pom = tags.first();
241         while (pom != NULL) {
242                 fprintf(stderr, "%s:%s,%s,%s\n", names[pom->tag_type],
243                         pom->tag_text, pom->tag_link, pom->tag_label);
244                 pom=tags.next();
245         }
246 }
247
248 void HTMLAnalyzer::PackLinks()
249 {
250         Tag *pom,*pom1;
251         char s[255];
252
253         pom = tags.first();
254         while (pom!=NULL) {
255                 if ((pom->tag_type == TAG_LINK) ||
256                         (pom->tag_type == TAG_ANCHOR)) {
257                         pom1 = tags.next();
258                         strcpy(s, "");
259                         while ((pom1 != NULL) &&
260                                 (pom1->tag_type != TAG_LINK_END)) {
261                                 if (pom1->tag_type == TAG_TEXT)
262                                         strcat(s,pom1->tag_text);
263                                 tags.remove(pom1);
264                                 pom1 = tags.current();
265                         }
266                         strcpy(pom->tag_text,s); 
267                         tags.remove(pom1);
268                         pom = tags.current();
269                 } else {
270                         pom = tags.next();
271                 }
272         }
273 }
274
275
276 Tag *HTMLAnalyzer::CheckTag(int x,int y)
277 {
278         Tag *pom;
279         pom=tags.first();
280         while (pom != NULL) {
281                 if (pom->tag_type==TAG_LINK)
282                         if ((x >= pom->x) && (x <= pom->x + pom->w) &&
283                                 (y >= pom->y) && (y <= pom->y + pom->h)) {
284                                 return pom;
285                         }
286                 pom=tags.next();
287         }
288         return NULL;
289 }
290
291 Tag *HTMLAnalyzer::FindAnchor(char *name)
292 {
293         Tag *pom;
294         pom = tags.first();
295         while (pom != NULL) {
296                 if ((pom->tag_type == TAG_ANCHOR) &&
297                         (strcmp(pom->tag_label, name) == 0)) {
298                                 return(pom);
299                         }
300                 pom=tags.next();
301         }
302         return pom;
303 }
304 /********************************/
305
306 class QHTML: public QFrame {
307         Q_OBJECT
308 public:
309         QScrollBar *vscroll;
310         QMenuBar *bar;  
311         HTMLAnalyzer *analyzer;
312         QPixmap *map;
313         int cx,cy,oy,lstep,pstep;
314         bool Bold,Italic;
315         QFont *normal,*bold,*italic,*bold_italic,*actual_font;
316         char homedir[255];
317
318         QHTML(char*);
319         void DrawList();
320         virtual void paintEvent(QPaintEvent *ev);
321         virtual void resizeEvent(QResizeEvent *ev);
322         virtual void mousePressEvent(QMouseEvent *ev);
323 public slots:
324         void load();
325         void back();
326         void vscrolled(int);
327         void contents();
328         void user_guide();
329         void lang_guide();
330 };
331
332
333 QApplication *app;
334
335 QHTML::QHTML(char *d)
336 {
337         QPopupMenu *pp;
338         char s[255];
339
340         QFont f("Helvetica", 12, QFont::Bold);
341         normal = new QFont("Helvetica", 12, QFont::Normal);
342         bold = new QFont("Helvetica", 12, QFont::Bold);
343         italic = new QFont("Helvetica", 12, QFont::Normal, TRUE);
344         bold_italic = new QFont("Helvetica", 12, QFont::Bold, TRUE);
345         strcpy(homedir, d);
346
347         actual_font = normal;
348         bar = new QMenuBar(this);
349         pp = new QPopupMenu;
350         pp->insertItem("Index", this, SLOT(contents()));
351         pp->insertItem("User Guide", this, SLOT(user_guide()));
352         pp->insertItem("Language reference", this, SLOT(lang_guide()));
353         pp->setFont(f);
354         /*pp->setStyle(WindowsStyle);*/
355         bar->insertItem("File", this, SLOT(load()));
356         bar->insertItem("Contents", pp);
357         bar->insertItem("Quit", app, SLOT(quit()));
358         bar->setFont(f);
359         setCaption("LOGLAN Help");
360         setBackgroundColor(gray);
361         analyzer = new HTMLAnalyzer;
362         map = new QPixmap(500, PIX_HEIGHT);
363         map->fill(backgroundColor());
364         resize(500, height());
365         setFixedSize(width(), height());
366         oy = 0;
367         lstep = 10;
368         pstep = height() - bar->height();
369         vscroll = new QScrollBar(0, PIX_HEIGHT, lstep, pstep, 0, 
370                                                 QScrollBar::Vertical, this);
371         vscroll->setTracking(TRUE);  
372         vscroll->setGeometry(width() - 16, bar->height(), 16, 
373                                                         height()-bar->height());
374         connect(vscroll, SIGNAL(valueChanged(int)), this, SLOT(vscrolled(int)));  
375         sprintf(s, "%s/index.html", homedir);
376         analyzer->LoadFile(s);
377         analyzer->PackLinks();
378         DrawList();
379 }
380
381 void QHTML::vscrolled(int v)
382 {
383         oy = v;
384         repaint();
385 }
386
387 void QHTML::load()
388 {
389         QString s(QFileDialog::getOpenFileName(homedir, "*", this));
390         if (!s.isNull()) {
391                 vscroll->setValue(0); 
392                 analyzer->LoadFile((char*)s.ascii());
393                 analyzer->PackLinks();
394                 DrawList();
395         }
396 }
397
398 void QHTML::contents()
399 {
400         char ss[255];
401         sprintf(ss, "%s/index.html", homedir);
402         analyzer->LoadFile(ss);
403         analyzer->PackLinks();
404         DrawList(); 
405 }
406
407 void QHTML::user_guide()
408 {
409         char ss[255];
410         sprintf(ss, "%s/userg.html", homedir);
411         analyzer->LoadFile(ss);
412         analyzer->PackLinks();
413         DrawList(); 
414 }
415
416 void QHTML::lang_guide()
417 {
418         char ss[255];
419         sprintf(ss, "%s/langg.html", homedir);
420         analyzer->LoadFile(ss);
421         analyzer->PackLinks();
422         DrawList();
423 }
424
425 void QHTML::paintEvent(QPaintEvent *ev)
426 {
427         if (map != NULL) {
428                 bitBlt(this, 0, bar->height(), map, 0, oy,
429                                                 width() - 16, height() - 16);
430         }
431 }
432
433 void QHTML::resizeEvent(QResizeEvent *ev)
434 {
435         DrawList();
436 }
437
438 void QHTML::mousePressEvent(QMouseEvent *ev)
439 {
440         Tag *pom, *pom1;
441         QString poms;
442         char ss[255];
443
444         pom = analyzer->CheckTag(ev->x(), ev->y() + oy);
445         if (pom != NULL) {
446                 poms.sprintf(pom->tag_link);
447                 if (poms.data()[0] == '"') 
448                         poms = poms.right(poms.length() - 1);
449                 if (poms.data()[poms.length() - 1] == '"')
450                         poms=poms.left(poms.length() - 1);
451                 if (poms.data()[0] == '#') {
452                         poms = poms.right(poms.length() - 1);
453                         pom1 = analyzer->FindAnchor((char*)poms.ascii());
454                         if (pom1 != NULL) {
455                                 vscroll->setValue(pom1->y);
456                         }
457                 } else {
458                         sprintf(ss, "%s/%s", homedir, poms.data());
459                         analyzer->LoadFile(ss);
460                         analyzer->PackLinks();
461                         DrawList();
462                 }
463         }
464 }
465
466 void QHTML::back()
467 {
468 }
469
470 void QHTML::DrawList()
471 {
472         Tag *pom;
473         QPainter p;
474
475         if (!analyzer->tags.isEmpty()) {
476                 cx = 5;
477                 cy = 15;
478                 map->fill(backgroundColor());
479                 p.begin(map);
480
481                 pom = analyzer->tags.first();
482                 while (pom != NULL) {
483                         switch(pom->tag_type) {
484                         case TAG_TEXT:
485                                 p.setFont(*actual_font);
486                                 if (cx + p.fontMetrics().width(pom->tag_text) > 
487                                                                 width() - 16) {
488                                         cx = 5;
489                                         cy = cy + p.fontMetrics().height();
490                                 }
491                                 p.drawText(cx, cy, pom->tag_text);
492                                 cx = cx + p.fontMetrics().width(pom->tag_text);
493                                 break;
494                         case TAG_BREAK:
495                                 p.setFont(*actual_font);
496                                 cy = cy + p.fontMetrics().height();
497                                 cx = 5;
498                                 break;
499                         case TAG_ITALIC_ON:
500                                 if (actual_font == bold)
501                                         actual_font = bold_italic;
502                                 else 
503                                         actual_font = italic;
504
505                                 break;
506                         case TAG_ITALIC_OFF:
507                                 if (actual_font == bold_italic)
508                                         actual_font = bold;
509                                 else
510                                         actual_font = normal;
511
512                                 break;
513                         case TAG_BOLD_ON:
514                                 if (actual_font == italic)
515                                         actual_font = bold_italic;
516                                 else 
517                                         actual_font = bold;
518                                         
519                                 break;
520                         case TAG_BOLD_OFF:
521                                 if (actual_font == bold_italic)
522                                         actual_font = italic;
523                                 else 
524                                         actual_font = normal;
525                                         
526                                 break;
527                         case TAG_LINK:
528                                 p.setFont(*actual_font);
529                                 if (cx + p.fontMetrics().width(pom->tag_text) >
530                                                                 width() - 16) {
531                                         cx = 5;
532                                         cy = cy + p.fontMetrics().height();
533                                 }
534                                 p.setPen(QColor(255, 0, 0));
535                                 p.drawText(cx, cy, pom->tag_text);
536                                 pom->x = cx;
537                                 pom->y = cy + p.fontMetrics().height();
538                                 pom->w = p.fontMetrics().width(pom->tag_text);
539                                 pom->h = p.fontMetrics().height();
540                                 p.setPen(QColor(0, 0, 0));
541                                 cx = cx + p.fontMetrics().width(pom->tag_text);
542                                 break;
543                         case TAG_ANCHOR:
544                                 p.setFont(*actual_font);
545                                 if (cx + p.fontMetrics().width(pom->tag_text) >
546                                                                 width() - 16) {
547                                         cx = 5;
548                                         cy = cy + p.fontMetrics().height();
549                                 }
550                                 //p.setPen(QColor(0,255,0));
551                                 p.drawText(cx, cy, pom->tag_text);
552                                 pom->x = cx;
553                                 pom->y = cy - p.fontMetrics().height();
554                                 pom->w = p.fontMetrics().width(pom->tag_text);
555                                 pom->h = p.fontMetrics().height();
556                                 p.setPen(QColor(0, 0, 0));
557                                 cx=cx + p.fontMetrics().width(pom->tag_text);
558                                 break;
559                         case TAG_LIST_OFF:
560                         case TAG_LIST_ON:
561                                 p.setFont(*actual_font);
562                                 cx = 5;
563                                 cy = cy + p.fontMetrics().height();
564                                 break;
565                         case TAG_LIST_ITEM:p.setFont(*actual_font);
566                                 p.setBrush(QBrush(QColor(0, 0, 255)));
567                                 cx = 5;
568                                 cy = cy + p.fontMetrics().height();
569                                 p.drawPie(cx, cy - 5, 5, 5, 0, 5760); 
570                                 cx = cx + 15;
571                                 break;
572                         case TAG_LINE:
573                                 p.setFont(*actual_font);
574                                 cx = 5;
575                                 cy = cy + p.fontMetrics().height();
576                                 p.drawLine(cx, cy - 
577                                         (int)(p.fontMetrics().height() / 2),
578                                         width() - 16 - 5, cy -
579                                         (int)(p.fontMetrics().height() / 2));
580                                 cx = 5;
581                                 cy = cy + p.fontMetrics().height();
582                                 break;
583                         }//switch
584                         pom = analyzer->tags.next();
585                 }
586                 p.end();
587                 repaint();
588         }
589 }
590
591 #include "help.moc"
592
593 int main( int argc, char **argv )
594 {
595         QString ps;
596
597         app = new QApplication(argc, argv);
598         if (argc == 2)
599                 ps.sprintf(argv[1]);
600         else
601                 ps.sprintf(".");
602         QHTML cfg((char*)ps.ascii());
603         //app->setStyle(WindowsStyle);
604         app->setMainWidget(&cfg);
605         cfg.show();
606         return app->exec();
607 }