]> git.saurik.com Git - wxWidgets.git/blob - src/html/htmlwin.cpp
zipstrm link fix
[wxWidgets.git] / src / html / htmlwin.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: htmlwin.cpp
3 // Purpose: wxHtmlWindow class for parsing & displaying HTML (implementation)
4 // Author: Vaclav Slavik
5 // Copyright: (c) 1999 Vaclav Slavik
6 // Licence: wxWindows Licence
7 /////////////////////////////////////////////////////////////////////////////
8
9
10 #ifdef __GNUG__
11 #pragma implementation
12 #endif
13
14 #include <wx/wxprec.h>
15
16 #include "wx/defs.h"
17 #if wxUSE_HTML
18
19 #ifdef __BORDLANDC__
20 #pragma hdrstop
21 #endif
22
23 #ifndef WXPRECOMP
24 #include <wx/wx.h>
25 #endif
26
27 #include <wx/html/htmlwin.h>
28
29 #include <wx/html/forcelink.h>
30
31
32
33 //-----------------------------------------------------------------------------
34 // wxHtmlWindow
35 //-----------------------------------------------------------------------------
36
37
38
39 #include <wx/arrimpl.cpp>
40 WX_DEFINE_OBJARRAY(HtmlHistoryArray)
41
42
43 wxHtmlWindow::wxHtmlWindow(wxWindow *parent, wxWindowID id, const wxPoint& pos, const wxSize& size,
44 long style, const wxString& name) : wxScrolledWindow(parent, id, pos, size, wxVSCROLL, name)
45 {
46 m_tmpMouseMoved = FALSE;
47 m_tmpCanDraw = TRUE;
48 m_FS = new wxFileSystem();
49 m_RelatedStatusBar = -1;
50 m_RelatedFrame = NULL;
51 m_TitleFormat = "%s";
52 m_OpenedPage = m_OpenedAnchor = wxEmptyString;
53 m_Cell = NULL;
54 m_Parser = new wxHtmlWinParser(this);
55 m_Parser -> SetFS(m_FS);
56 SetBorders(10);
57 m_HistoryPos = -1;
58 m_HistoryOn = TRUE;
59 m_Style = style;
60 SetPage("<html><body></body></html>");
61 }
62
63
64
65 wxHtmlWindow::~wxHtmlWindow()
66 {
67 HistoryClear();
68
69 if (m_Cell) delete m_Cell;
70
71 wxList *parser_data = m_Parser -> GetTempData();
72 if (parser_data) delete parser_data;
73
74 delete m_Parser;
75 delete m_FS;
76 }
77
78
79
80 void wxHtmlWindow::SetRelatedFrame(wxFrame* frame, const wxString& format)
81 {
82 m_RelatedFrame = frame;
83 m_TitleFormat = format;
84 }
85
86
87
88 void wxHtmlWindow::SetRelatedStatusBar(int bar)
89 {
90 m_RelatedStatusBar = bar;
91 }
92
93
94
95 void wxHtmlWindow::SetFonts(wxString normal_face, int normal_italic_mode, wxString fixed_face, int fixed_italic_mode, int *sizes)
96 {
97 m_Parser -> SetFonts(normal_face, normal_italic_mode, fixed_face, fixed_italic_mode, sizes);
98 if (!m_OpenedPage.IsEmpty()) LoadPage(m_OpenedPage);
99 }
100
101
102
103 bool wxHtmlWindow::SetPage(const wxString& source)
104 {
105 wxClientDC *dc = new wxClientDC(this);
106
107 dc -> SetMapMode(wxMM_TEXT);
108 SetBackgroundColour(wxColour(0xFF, 0xFF, 0xFF));
109 m_OpenedPage = m_OpenedAnchor = wxEmptyString;
110 m_Parser -> SetDC(dc);
111 if (m_Cell) {
112 delete m_Cell;
113 m_Cell = NULL;
114 }
115 m_Cell = (wxHtmlContainerCell*) m_Parser -> Parse(source);
116 delete dc;
117 m_Cell -> SetIndent(m_Borders, HTML_INDENT_ALL, HTML_UNITS_PIXELS);
118 m_Cell -> SetAlignHor(HTML_ALIGN_CENTER);
119 CreateLayout();
120 Refresh();
121 return TRUE;
122 }
123
124
125 bool wxHtmlWindow::LoadPage(const wxString& location)
126 {
127 wxFSFile *f;
128 bool rt_val;
129 wxBusyCursor b;
130
131 m_tmpCanDraw = FALSE;
132 if (m_HistoryOn && (m_HistoryPos != -1)) { // store scroll position into history item
133 int x, y;
134 ViewStart(&x, &y);
135 m_History[m_HistoryPos].SetPos(y);
136 }
137
138 if (location[0] == '#') { // local anchor
139 wxString anch = location.Mid(1) /*1 to end*/;
140 m_tmpCanDraw = TRUE;
141 rt_val = ScrollToAnchor(anch);
142 }
143
144 else {
145 // load&display it:
146 if (m_RelatedStatusBar != -1) {
147 m_RelatedFrame -> SetStatusText(_("Connecting..."), m_RelatedStatusBar);
148 Refresh();
149 }
150
151 f = m_FS -> OpenFile(location);
152 if (f == NULL) {
153 wxString err;
154
155 err.Printf(_("The browser is unable to open requested location :\n\n%s"), WXSTRINGCAST location);
156 m_tmpCanDraw = TRUE;
157 Refresh();
158 wxMessageBox(err, "Error");
159 return FALSE;
160 }
161
162 else {
163 wxNode *node;
164 wxString src = wxEmptyString;
165
166 if (m_RelatedStatusBar != -1) {
167 wxString msg = _("Loading : ") + location;
168 m_RelatedFrame -> SetStatusText(msg, m_RelatedStatusBar);
169 Refresh();
170 }
171
172 node = m_Filters.GetFirst();
173 while (node){
174 wxHtmlFilter *h = (wxHtmlFilter*) node -> GetData();
175 if (h -> CanRead(*f)) {
176 src = h -> ReadFile(*f);
177 break;
178 }
179 node = node -> GetNext();
180 }
181 if (src == wxEmptyString) {
182 if (m_DefaultFilter == NULL) m_DefaultFilter = GetDefaultFilter();
183 src = m_DefaultFilter -> ReadFile(*f);
184 }
185
186 m_FS -> ChangePathTo(f -> GetLocation());
187 rt_val = SetPage(src);
188 m_OpenedPage = f -> GetLocation();
189 if (f -> GetAnchor() != wxEmptyString) {
190 m_tmpCanDraw = TRUE;
191 ScrollToAnchor(f -> GetAnchor());
192 m_tmpCanDraw = FALSE;
193 }
194
195 delete f;
196
197 if (m_RelatedStatusBar != -1) m_RelatedFrame -> SetStatusText(_("Done"), m_RelatedStatusBar);
198 }
199 }
200
201 if (m_HistoryOn) { // add this page to history there:
202 int c = m_History.GetCount() - (m_HistoryPos + 1);
203
204 m_HistoryPos++;
205 for (int i = 0; i < c; i++)
206 m_History.Remove(m_HistoryPos);
207 m_History.Add(new HtmlHistoryItem(m_OpenedPage, m_OpenedAnchor));
208 }
209
210 m_tmpCanDraw = TRUE;
211 Refresh();
212 return rt_val;
213 }
214
215
216
217 bool wxHtmlWindow::ScrollToAnchor(const wxString& anchor)
218 {
219 const wxHtmlCell *c = m_Cell -> Find(HTML_COND_ISANCHOR, &anchor);
220 if (!c) return FALSE;
221 else {
222 int y;
223
224 for (y = 0; c != NULL; c = c -> GetParent()) y += c -> GetPosY();
225 Scroll(-1, y / HTML_SCROLL_STEP);
226 m_OpenedAnchor = anchor;
227 return TRUE;
228 }
229 }
230
231
232 void wxHtmlWindow::SetTitle(const wxString& title)
233 {
234 if (m_RelatedFrame) {
235 wxString tit;
236 tit.Printf(m_TitleFormat, title.c_str());
237 m_RelatedFrame -> SetTitle(tit);
238 }
239 }
240
241
242
243
244
245 void wxHtmlWindow::CreateLayout()
246 {
247 int ClientWidth, ClientHeight;
248
249 if (!m_Cell) return;
250
251 if (m_Style == wxHW_SCROLLBAR_NEVER) {
252 GetClientSize(&ClientWidth, &ClientHeight);
253 m_Cell -> Layout(ClientWidth);
254 }
255
256 else {
257 GetClientSize(&ClientWidth, &ClientHeight);
258 SetScrollbars(1, 1, 0, ClientHeight * 2); // always on
259 GetClientSize(&ClientWidth, &ClientHeight);
260 m_Cell -> Layout(ClientWidth);
261 GetClientSize(&ClientWidth, &ClientHeight);
262 if (ClientHeight < m_Cell -> GetHeight()) {
263 SetScrollbars(HTML_SCROLL_STEP, HTML_SCROLL_STEP,
264 m_Cell -> GetWidth() / HTML_SCROLL_STEP,
265 m_Cell -> GetHeight() / HTML_SCROLL_STEP
266 /*cheat: top-level frag is always container*/);
267 }
268 else { /* we fit into window, no need for scrollbars */
269 SetScrollbars(1, 1, 0, 0); // disable...
270 m_Cell -> Layout(ClientWidth); // ...and relayout
271 }
272 }
273 }
274
275
276
277 void wxHtmlWindow::ReadCustomization(wxConfigBase *cfg, wxString path)
278 {
279 wxString oldpath;
280 wxString tmp;
281
282 if (path != wxEmptyString) {
283 oldpath = cfg -> GetPath();
284 cfg -> SetPath(path);
285 }
286
287 m_Borders = cfg -> Read("wxHtmlWindow/Borders", m_Borders);
288 m_Parser -> m_FontFaceFixed = cfg -> Read("wxHtmlWindow/FontFaceFixed", m_Parser -> m_FontFaceFixed);
289 m_Parser -> m_FontFaceNormal = cfg -> Read("wxHtmlWindow/FontFaceNormal", m_Parser -> m_FontFaceNormal);
290 m_Parser -> m_ItalicModeFixed = cfg -> Read("wxHtmlWindow/ItalicModeFixed", m_Parser -> m_ItalicModeFixed);
291 m_Parser -> m_ItalicModeNormal = cfg -> Read("wxHtmlWindow/ItalicModeNormal", m_Parser -> m_ItalicModeNormal);
292 for (int i = 0; i < 7; i++) {
293 tmp.Printf("wxHtmlWindow/FontsSize%i", i);
294 m_Parser -> m_FontsSizes[i] = cfg -> Read(tmp, m_Parser -> m_FontsSizes[i]);
295 }
296
297 if (path != wxEmptyString)
298 cfg -> SetPath(oldpath);
299 }
300
301
302
303 void wxHtmlWindow::WriteCustomization(wxConfigBase *cfg, wxString path)
304 {
305 wxString oldpath;
306 wxString tmp;
307
308 if (path != wxEmptyString) {
309 oldpath = cfg -> GetPath();
310 cfg -> SetPath(path);
311 }
312
313 cfg -> Write("wxHtmlWindow/Borders", (long) m_Borders);
314 cfg -> Write("wxHtmlWindow/FontFaceFixed", m_Parser -> m_FontFaceFixed);
315 cfg -> Write("wxHtmlWindow/FontFaceNormal", m_Parser -> m_FontFaceNormal);
316 cfg -> Write("wxHtmlWindow/ItalicModeFixed", (long) m_Parser -> m_ItalicModeFixed);
317 cfg -> Write("wxHtmlWindow/ItalicModeNormal", (long) m_Parser -> m_ItalicModeNormal);
318 for (int i = 0; i < 7; i++) {
319 tmp.Printf("wxHtmlWindow/FontsSize%i", i);
320 cfg -> Write(tmp, (long) m_Parser -> m_FontsSizes[i]);
321 }
322
323 if (path != wxEmptyString)
324 cfg -> SetPath(oldpath);
325 }
326
327
328
329 bool wxHtmlWindow::HistoryBack()
330 {
331 wxString a, l;
332
333 if (m_HistoryPos < 1) return FALSE;
334
335 m_HistoryPos--;
336
337 l = m_History[m_HistoryPos].GetPage();
338 a = m_History[m_HistoryPos].GetAnchor();
339 m_HistoryOn = FALSE;
340 if (a == wxEmptyString) LoadPage(l);
341 else LoadPage(l + "#" + a);
342 m_HistoryOn = TRUE;
343 Scroll(0, m_History[m_HistoryPos].GetPos());
344 Refresh();
345 return TRUE;
346 }
347
348
349
350 bool wxHtmlWindow::HistoryForward()
351 {
352 wxString a, l;
353
354 if (m_HistoryPos == -1) return FALSE;
355 if (m_HistoryPos >= (int)m_History.GetCount() - 1)return FALSE;
356
357 m_OpenedPage = wxEmptyString; // this will disable adding new entry into history in LoadPage()
358
359 m_HistoryPos++;
360 l = m_History[m_HistoryPos].GetPage();
361 a = m_History[m_HistoryPos].GetAnchor();
362 m_HistoryOn = FALSE;
363 if (a == wxEmptyString) LoadPage(l);
364 else LoadPage(l + "#" + a);
365 m_HistoryOn = TRUE;
366 Scroll(0, m_History[m_HistoryPos].GetPos());
367 Refresh();
368 return TRUE;
369 }
370
371
372
373 void wxHtmlWindow::HistoryClear()
374 {
375 m_History.Empty();
376 m_HistoryPos = -1;
377 }
378
379
380
381 wxList wxHtmlWindow::m_Filters;
382 wxHtmlFilter *wxHtmlWindow::m_DefaultFilter = NULL;
383
384 void wxHtmlWindow::CleanUpStatics()
385 {
386 if (m_DefaultFilter) delete m_DefaultFilter;
387 m_DefaultFilter = NULL;
388 }
389
390
391
392 void wxHtmlWindow::AddFilter(wxHtmlFilter *filter)
393 {
394 m_Filters.DeleteContents(TRUE);
395 m_Filters.Append(filter);
396 }
397
398
399
400
401 void wxHtmlWindow::OnLinkClicked(const wxString& link)
402 {
403 LoadPage(link);
404 }
405
406
407
408 void wxHtmlWindow::OnDraw(wxDC& dc)
409 {
410 int x, y;
411 wxRegionIterator upd(GetUpdateRegion()); // get the update rect list
412 int v_y, v_h;
413
414 if (!m_tmpCanDraw) return;
415 dc.SetMapMode(wxMM_TEXT);
416 #if defined(_MSC_VER) && (_MSC_VER == 1200)
417 ::SetMapMode((HDC)dc.GetHDC(), MM_TEXT);
418 #endif
419 dc.SetBackgroundMode(wxTRANSPARENT);
420 ViewStart(&x, &y);
421
422 while (upd) {
423 v_y = upd.GetY();
424 v_h = upd.GetH();
425 if (m_Cell) m_Cell -> Draw(dc, 0, 0, y * HTML_SCROLL_STEP + v_y, y * HTML_SCROLL_STEP + v_h + v_y);
426 upd++;
427 }
428 }
429
430
431
432
433 void wxHtmlWindow::OnSize(wxSizeEvent& event)
434 {
435 wxScrolledWindow::OnSize(event);
436 CreateLayout();
437 }
438
439
440
441 void wxHtmlWindow::OnKeyDown(wxKeyEvent& event)
442 {
443 int dummy;
444 int sty, szy, cliy;
445
446 ViewStart(&dummy, &sty);
447 GetClientSize(&dummy, &cliy); cliy /= HTML_SCROLL_STEP;
448 GetVirtualSize(&dummy, &szy); szy /= HTML_SCROLL_STEP;
449
450 switch (event.KeyCode()) {
451 case WXK_PAGEUP :
452 case WXK_PRIOR :
453 Scroll(-1, sty - cliy);
454 break;
455 case WXK_PAGEDOWN :
456 case WXK_NEXT :
457 Scroll(-1, sty + cliy);
458 break;
459 case WXK_HOME :
460 Scroll(-1, 0);
461 break;
462 case WXK_END :
463 Scroll(-1, szy - cliy);
464 break;
465 case WXK_UP :
466 Scroll(-1, sty - 1);
467 break;
468 case WXK_DOWN :
469 Scroll(-1, sty + 1);
470 break;
471 }
472 }
473
474
475
476 void wxHtmlWindow::OnMouseEvent(wxMouseEvent& event)
477 {
478 m_tmpMouseMoved = TRUE;
479
480 if (event.ButtonDown()) {
481 int sx, sy;
482 wxPoint pos;
483 wxString lnk;
484
485 ViewStart(&sx, &sy); sx *= HTML_SCROLL_STEP; sy *= HTML_SCROLL_STEP;
486 pos = event.GetPosition();
487
488 if (m_Cell)
489 m_Cell -> OnMouseClick(this, sx + pos.x, sy + pos.y, event.ButtonDown(1), event.ButtonDown(2), event.ButtonDown(3));
490 }
491 }
492
493
494
495 void wxHtmlWindow::OnIdle(wxIdleEvent& event)
496 {
497 static wxCursor cur_hand(wxCURSOR_HAND), cur_arrow(wxCURSOR_ARROW);
498
499 if (m_tmpMouseMoved && (m_Cell != NULL)) {
500 int sx, sy;
501 int x, y;
502 wxString lnk;
503
504 ViewStart(&sx, &sy); sx *= HTML_SCROLL_STEP; sy *= HTML_SCROLL_STEP;
505 wxGetMousePosition(&x, &y);
506 ScreenToClient(&x, &y);
507 lnk = m_Cell -> GetLink(sx + x, sy + y);
508
509 if (lnk == wxEmptyString) {
510 SetCursor(cur_arrow);
511 if (m_RelatedStatusBar != -1) m_RelatedFrame -> SetStatusText(wxEmptyString, m_RelatedStatusBar);
512 }
513 else {
514 SetCursor(cur_hand);
515 if (m_RelatedStatusBar != -1) m_RelatedFrame -> SetStatusText(lnk, m_RelatedStatusBar);
516 }
517 m_tmpMouseMoved = FALSE;
518 }
519 }
520
521
522
523
524 IMPLEMENT_DYNAMIC_CLASS(wxHtmlWindow,wxScrolledWindow)
525
526 BEGIN_EVENT_TABLE(wxHtmlWindow, wxScrolledWindow)
527 EVT_SIZE(wxHtmlWindow::OnSize)
528 EVT_LEFT_DOWN(wxHtmlWindow::OnMouseEvent)
529 EVT_MOTION(wxHtmlWindow::OnMouseEvent)
530 EVT_IDLE(wxHtmlWindow::OnIdle)
531 EVT_KEY_DOWN(wxHtmlWindow::OnKeyDown)
532 END_EVENT_TABLE()
533
534
535
536
537
538 // A module to allow initialization/cleanup
539 // without calling these functions from app.cpp or from
540 // the user's application.
541
542 class wxHtmlWinModule: public wxModule
543 {
544 DECLARE_DYNAMIC_CLASS(wxHtmlWinModule)
545 public:
546 wxHtmlWinModule() : wxModule() {}
547 bool OnInit() { return TRUE; }
548 void OnExit() { wxHtmlWindow::CleanUpStatics(); }
549 };
550
551 IMPLEMENT_DYNAMIC_CLASS(wxHtmlWinModule, wxModule)
552
553
554
555
556 ///// default mod handlers are forced there:
557
558 FORCE_LINK(mod_layout)
559 FORCE_LINK(mod_fonts)
560 FORCE_LINK(mod_image)
561 FORCE_LINK(mod_list)
562 FORCE_LINK(mod_pre)
563 FORCE_LINK(mod_hline)
564 FORCE_LINK(mod_links)
565 FORCE_LINK(mod_tables)
566
567
568 #endif