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