]> git.saurik.com Git - wxWidgets.git/blame - src/html/htmlcell.cpp
compilation fix for non-threaded compilation (threads are still broken
[wxWidgets.git] / src / html / htmlcell.cpp
CommitLineData
5526e819
VS
1/////////////////////////////////////////////////////////////////////////////
2// Name: htmlcell.cpp
3// Purpose: wxHtmlCell - basic element of HTML output
4// Author: Vaclav Slavik
69941f05 5// RCS-ID: $Id$
5526e819
VS
6// Copyright: (c) 1999 Vaclav Slavik
7// Licence: wxWindows Licence
8/////////////////////////////////////////////////////////////////////////////
9
5526e819 10#ifdef __GNUG__
69941f05 11#pragma implementation
5526e819
VS
12#endif
13
4dcaf11a 14#include "wx/wxprec.h"
5526e819 15
314260fb 16#include "wx/defs.h"
5526e819
VS
17#if wxUSE_HTML
18
19#ifdef __BORDLANDC__
20#pragma hdrstop
21#endif
22
23#ifndef WXPRECOMP
4dcaf11a 24#include "wx/wx.h"
5526e819
VS
25#endif
26
4dcaf11a
RR
27#include "wx/html/htmlcell.h"
28#include "wx/html/htmlwin.h"
5526e819
VS
29#include <stdlib.h>
30
31
5526e819
VS
32//-----------------------------------------------------------------------------
33// wxHtmlCell
34//-----------------------------------------------------------------------------
35
846914d1
VS
36wxHtmlCell::wxHtmlCell() : wxObject()
37{
38 m_Next = NULL;
39 m_Parent = NULL;
40 m_Width = m_Height = m_Descent = 0;
41 m_CanLiveOnPagebreak = TRUE;
42 m_Link = NULL;
43}
44
45wxHtmlCell::~wxHtmlCell()
46{
47 if (m_Link) delete m_Link;
48 if (m_Next) delete m_Next;
49}
50
5526e819 51
0b2dadd3
VS
52void wxHtmlCell::OnMouseClick(wxWindow *parent, int x, int y,
53 const wxMouseEvent& event)
5526e819 54{
846914d1
VS
55 wxHtmlLinkInfo *lnk = GetLink(x, y);
56 if (lnk != NULL)
0b2dadd3
VS
57 {
58 wxHtmlLinkInfo lnk2(*lnk);
59 lnk2.SetEvent(&event);
9bc8fded 60 lnk2.SetHtmlCell(this);
0b2dadd3 61 ((wxHtmlWindow*)parent) -> OnLinkClicked(lnk2);
5526e819 62 // note : this overcasting is legal because parent is *always* wxHtmlWindow
0b2dadd3 63 }
5526e819
VS
64}
65
66
67
db98870d
VS
68bool wxHtmlCell::AdjustPagebreak(int *pagebreak)
69{
db98870d 70 if ((!m_CanLiveOnPagebreak) &&
e52d6dbc 71 m_PosY < *pagebreak && m_PosY + m_Height > *pagebreak) {
db98870d
VS
72 *pagebreak = m_PosY;
73 if (m_Next != NULL) m_Next -> AdjustPagebreak(pagebreak);
74 return TRUE;
75 }
76
77 else {
78 if (m_Next != NULL) return m_Next -> AdjustPagebreak(pagebreak);
79 else return FALSE;
80 }
81}
82
83
84
846914d1
VS
85void wxHtmlCell::SetLink(const wxHtmlLinkInfo& link)
86{
87 if (m_Link) delete m_Link;
88 m_Link = new wxHtmlLinkInfo(link);
89}
90
91
db98870d 92
5526e819
VS
93//-----------------------------------------------------------------------------
94// wxHtmlWordCell
95//-----------------------------------------------------------------------------
96
97wxHtmlWordCell::wxHtmlWordCell(const wxString& word, wxDC& dc) : wxHtmlCell()
98{
99 m_Word = word;
c181287c
VS
100
101 if (m_Word.Find(wxT('&')) != -1)
102 {
103 static wxChar* substitutions[][3] =
104 {
105 { wxT("&nbsp;"), wxT("&nbsp "), wxT(" ") },
106 { wxT("&copy;"), wxT("&copy "), wxT("(c)") },
107 { wxT("&quot;"), wxT("&quot "), wxT("\"") },
108 { wxT("&lt;"), wxT("&lt "), wxT("<") },
109 { wxT("&gt;"), wxT("&gt "), wxT(">") },
110 { wxT("&amp;"), wxT("&amp "), wxT("&") /*this one should be last one*/ },
111 { NULL, NULL, NULL }
112 };
113
114 for (int i = 0; substitutions[i][0] != NULL; i++)
115 {
116 m_Word.Replace(substitutions[i][0], substitutions[i][2], TRUE);
117 m_Word.Replace(substitutions[i][1], substitutions[i][2], TRUE);
118 }
119 }
12909796 120
5526e819 121 dc.GetTextExtent(m_Word, &m_Width, &m_Height, &m_Descent);
db98870d 122 SetCanLiveOnPagebreak(FALSE);
5526e819
VS
123}
124
125
126
127void wxHtmlWordCell::Draw(wxDC& dc, int x, int y, int view_y1, int view_y2)
128{
129 dc.DrawText(m_Word, x + m_PosX, y + m_PosY);
130 wxHtmlCell::Draw(dc, x, y, view_y1, view_y2);
131}
132
133
134
5526e819
VS
135//-----------------------------------------------------------------------------
136// wxHtmlContainerCell
137//-----------------------------------------------------------------------------
138
139
140wxHtmlContainerCell::wxHtmlContainerCell(wxHtmlContainerCell *parent) : wxHtmlCell()
141{
142 m_Cells = m_LastCell = NULL;
143 m_Parent = parent;
144 if (m_Parent) m_Parent -> InsertCell(this);
efba2b89
VS
145 m_AlignHor = wxHTML_ALIGN_LEFT;
146 m_AlignVer = wxHTML_ALIGN_BOTTOM;
5526e819 147 m_IndentLeft = m_IndentRight = m_IndentTop = m_IndentBottom = 0;
efba2b89 148 m_WidthFloat = 100; m_WidthFloatUnits = wxHTML_UNITS_PERCENT;
5526e819
VS
149 m_UseBkColour = FALSE;
150 m_UseBorder = FALSE;
151 m_MinHeight = m_MaxLineWidth = 0;
efba2b89 152 m_MinHeightAlign = wxHTML_ALIGN_TOP;
5526e819
VS
153}
154
155
156
157void wxHtmlContainerCell::SetIndent(int i, int what, int units)
158{
efba2b89
VS
159 int val = (units == wxHTML_UNITS_PIXELS) ? i : -i;
160 if (what & wxHTML_INDENT_LEFT) m_IndentLeft = val;
161 if (what & wxHTML_INDENT_RIGHT) m_IndentRight = val;
162 if (what & wxHTML_INDENT_TOP) m_IndentTop = val;
163 if (what & wxHTML_INDENT_BOTTOM) m_IndentBottom = val;
5526e819
VS
164}
165
166
167
168int wxHtmlContainerCell::GetIndent(int ind) const
169{
efba2b89
VS
170 if (ind & wxHTML_INDENT_LEFT) return m_IndentLeft;
171 else if (ind & wxHTML_INDENT_RIGHT) return m_IndentRight;
172 else if (ind & wxHTML_INDENT_TOP) return m_IndentTop;
173 else if (ind & wxHTML_INDENT_BOTTOM) return m_IndentBottom;
5526e819
VS
174 else return -1; /* BUG! Should not be called... */
175}
176
177
178
179
180int wxHtmlContainerCell::GetIndentUnits(int ind) const
181{
182 bool p = FALSE;
efba2b89
VS
183 if (ind & wxHTML_INDENT_LEFT) p = m_IndentLeft < 0;
184 else if (ind & wxHTML_INDENT_RIGHT) p = m_IndentRight < 0;
185 else if (ind & wxHTML_INDENT_TOP) p = m_IndentTop < 0;
186 else if (ind & wxHTML_INDENT_BOTTOM) p = m_IndentBottom < 0;
187 if (p) return wxHTML_UNITS_PERCENT;
188 else return wxHTML_UNITS_PIXELS;
5526e819
VS
189}
190
191
192
db98870d
VS
193bool wxHtmlContainerCell::AdjustPagebreak(int *pagebreak)
194{
195 if (!m_CanLiveOnPagebreak)
196 return wxHtmlCell::AdjustPagebreak(pagebreak);
e52d6dbc 197
db98870d
VS
198 else {
199 wxHtmlCell *c = GetFirstCell();
200 bool rt = FALSE;
e52d6dbc 201 int pbrk = *pagebreak - m_PosY;
db98870d
VS
202
203 while (c) {
e52d6dbc 204 if (c -> AdjustPagebreak(&pbrk)) rt = TRUE;
db98870d
VS
205 c = c -> GetNext();
206 }
e52d6dbc 207 if (rt) *pagebreak = pbrk + m_PosY;
db98870d
VS
208 return rt;
209 }
210}
211
212
213
5526e819
VS
214void wxHtmlContainerCell::Layout(int w)
215{
216 wxHtmlCell *cell = m_Cells, *line = m_Cells;
217 long xpos = 0, ypos = m_IndentTop;
218 int xdelta = 0, ybasicpos = 0, ydiff;
219 int s_width, s_indent;
220 int ysizeup = 0, ysizedown = 0;
221
222 /*
7e941458 223
5526e819 224 WIDTH ADJUSTING :
7e941458 225
5526e819
VS
226 */
227
efba2b89 228 if (m_WidthFloatUnits == wxHTML_UNITS_PERCENT) {
5526e819
VS
229 if (m_WidthFloat < 0) m_Width = (100 + m_WidthFloat) * w / 100;
230 else m_Width = m_WidthFloat * w / 100;
231 }
232 else {
233 if (m_WidthFloat < 0) m_Width = w + m_WidthFloat;
234 else m_Width = m_WidthFloat;
235 }
236
237 if (m_Cells) {
238 int l = (m_IndentLeft < 0) ? (-m_IndentLeft * m_Width / 100) : m_IndentLeft;
239 int r = (m_IndentRight < 0) ? (-m_IndentRight * m_Width / 100) : m_IndentRight;
240 m_Cells -> Layout(m_Width - (l + r));
241 }
242
243 /*
244
245 LAYOUTING :
7e941458 246
5526e819
VS
247 */
248
249 // adjust indentation:
250 s_indent = (m_IndentLeft < 0) ? (-m_IndentLeft * m_Width / 100) : m_IndentLeft;
251 s_width = m_Width - s_indent - ((m_IndentRight < 0) ? (-m_IndentRight * m_Width / 100) : m_IndentRight);
252
253 m_MaxLineWidth = 0;
7e941458 254
5526e819
VS
255 // my own layouting:
256 while (cell != NULL) {
257 switch (m_AlignVer) {
efba2b89
VS
258 case wxHTML_ALIGN_TOP : ybasicpos = 0; break;
259 case wxHTML_ALIGN_BOTTOM : ybasicpos = - cell -> GetHeight(); break;
260 case wxHTML_ALIGN_CENTER : ybasicpos = - cell -> GetHeight() / 2; break;
5526e819
VS
261 }
262 ydiff = cell -> GetHeight() + ybasicpos;
263
264 if (cell -> GetDescent() + ydiff > ysizedown) ysizedown = cell -> GetDescent() + ydiff;
265 if (ybasicpos + cell -> GetDescent() < -ysizeup) ysizeup = - (ybasicpos + cell -> GetDescent());
266
267 cell -> SetPos(xpos, ybasicpos + cell -> GetDescent());
268 xpos += cell -> GetWidth();
269 cell = cell -> GetNext();
270
271 // force new line if occured:
272 if ((cell == NULL) || (xpos + cell -> GetWidth() > s_width)) {
273 if (xpos > m_MaxLineWidth) m_MaxLineWidth = xpos;
274 if (ysizeup < 0) ysizeup = 0;
275 if (ysizedown < 0) ysizedown = 0;
276 switch (m_AlignHor) {
efba2b89
VS
277 case wxHTML_ALIGN_LEFT : xdelta = 0; break;
278 case wxHTML_ALIGN_RIGHT : xdelta = 0 + (s_width - xpos); break;
279 case wxHTML_ALIGN_CENTER : xdelta = 0 + (s_width - xpos) / 2; break;
5526e819
VS
280 }
281 if (xdelta < 0) xdelta = 0;
282 xdelta += s_indent;
283
284 ypos += ysizeup;
285 while (line != cell) {
286 line -> SetPos(line -> GetPosX() + xdelta, ypos + line -> GetPosY());
287 line = line -> GetNext();
288 }
289
290 ypos += ysizedown;
291 xpos = 0;
292 ysizeup = ysizedown = 0;
293 line = cell;
294 }
295 }
296
297 // setup height & width, depending on container layout:
298 m_Height = ypos + (ysizedown + ysizeup) + m_IndentBottom;
299
300 if (m_Height < m_MinHeight) {
efba2b89 301 if (m_MinHeightAlign != wxHTML_ALIGN_TOP) {
5526e819 302 int diff = m_MinHeight - m_Height;
efba2b89 303 if (m_MinHeightAlign == wxHTML_ALIGN_CENTER) diff /= 2;
5526e819
VS
304 cell = m_Cells;
305 while (cell) {
306 cell -> SetPos(cell -> GetPosX(), cell -> GetPosY() + diff);
307 cell = cell -> GetNext();
308 }
309 }
310 m_Height = m_MinHeight;
311 }
312
313 m_MaxLineWidth += s_indent + ((m_IndentRight < 0) ? (-m_IndentRight * m_Width / 100) : m_IndentRight);
314 if (m_Width < m_MaxLineWidth) m_Width = m_MaxLineWidth;
315
316 wxHtmlCell::Layout(w);
317}
318
319
320#define mMin(a, b) (((a) < (b)) ? (a) : (b))
321#define mMax(a, b) (((a) < (b)) ? (b) : (a))
322
323void wxHtmlContainerCell::Draw(wxDC& dc, int x, int y, int view_y1, int view_y2)
324{
325 // container visible, draw it:
326 if ((y + m_PosY < view_y2) && (y + m_PosY + m_Height > view_y1)) {
327
328 if (m_UseBkColour) {
329 wxBrush myb = wxBrush(m_BkColour, wxSOLID);
330
331 int real_y1 = mMax(y + m_PosY, view_y1);
332 int real_y2 = mMin(y + m_PosY + m_Height - 1, view_y2);
333
334 dc.SetBrush(myb);
335 dc.SetPen(*wxTRANSPARENT_PEN);
336 dc.DrawRectangle(x + m_PosX, real_y1, m_Width, real_y2 - real_y1 + 1);
337 }
338
339 if (m_UseBorder) {
340 wxPen mypen1(m_BorderColour1, 1, wxSOLID);
341 wxPen mypen2(m_BorderColour2, 1, wxSOLID);
342
343 dc.SetPen(mypen1);
344 dc.DrawLine(x + m_PosX, y + m_PosY, x + m_PosX, y + m_PosY + m_Height - 1);
345 dc.DrawLine(x + m_PosX, y + m_PosY, x + m_PosX + m_Width - 1, y + m_PosY);
346 dc.SetPen(mypen2);
347 dc.DrawLine(x + m_PosX + m_Width - 1, y + m_PosY, x + m_PosX + m_Width - 1, y + m_PosY + m_Height - 1);
348 dc.DrawLine(x + m_PosX, y + m_PosY + m_Height - 1, x + m_PosX + m_Width - 1, y + m_PosY + m_Height - 1);
349 }
350
351 if (m_Cells) m_Cells -> Draw(dc, x + m_PosX, y + m_PosY, view_y1, view_y2);
352 }
353 // container invisible, just proceed font+color changing:
354 else {
355 if (m_Cells) m_Cells -> DrawInvisible(dc, x + m_PosX, y + m_PosY);
356 }
357
358 wxHtmlCell::Draw(dc, x, y, view_y1, view_y2);
359}
360
361
362
363void wxHtmlContainerCell::DrawInvisible(wxDC& dc, int x, int y)
364{
365 if (m_Cells) m_Cells -> DrawInvisible(dc, x + m_PosX, y + m_PosY);
366 wxHtmlCell::DrawInvisible(dc, x, y);
367}
368
369
370
846914d1 371wxHtmlLinkInfo *wxHtmlContainerCell::GetLink(int x, int y) const
5526e819
VS
372{
373 wxHtmlCell *c = m_Cells;
374 int cx, cy, cw, ch;
375
376 while (c) {
377 cx = c -> GetPosX(), cy = c -> GetPosY();
378 cw = c -> GetWidth(), ch = c -> GetHeight();
379 if ((x >= cx) && (x < cx + cw) && (y >= cy) && (y < cy + ch))
380 return c -> GetLink(x - cx, y - cy);
381 c = c -> GetNext();
382 }
846914d1 383 return NULL;
5526e819
VS
384}
385
386
387
388void wxHtmlContainerCell::InsertCell(wxHtmlCell *f)
389{
390 if (!m_Cells) m_Cells = m_LastCell = f;
391 else {
392 m_LastCell -> SetNext(f);
393 m_LastCell = f;
394 if (m_LastCell) while (m_LastCell -> GetNext()) m_LastCell = m_LastCell -> GetNext();
395 }
396 f -> SetParent(this);
397}
398
399
400
401void wxHtmlContainerCell::SetAlign(const wxHtmlTag& tag)
402{
0413cec5
OK
403 if (tag.HasParam(wxT("ALIGN"))) {
404 wxString alg = tag.GetParam(wxT("ALIGN"));
5526e819 405 alg.MakeUpper();
0413cec5 406 if (alg == wxT("CENTER"))
efba2b89 407 SetAlignHor(wxHTML_ALIGN_CENTER);
0413cec5 408 else if (alg == wxT("LEFT"))
efba2b89 409 SetAlignHor(wxHTML_ALIGN_LEFT);
0413cec5 410 else if (alg == wxT("RIGHT"))
efba2b89 411 SetAlignHor(wxHTML_ALIGN_RIGHT);
5526e819
VS
412 }
413}
414
415
416
edbd0635 417void wxHtmlContainerCell::SetWidthFloat(const wxHtmlTag& tag, double pixel_scale)
5526e819 418{
0413cec5 419 if (tag.HasParam(wxT("WIDTH"))) {
5526e819 420 int wdi;
0413cec5 421 wxString wd = tag.GetParam(wxT("WIDTH"));
5526e819 422
0413cec5 423 if (wd[wd.Length()-1] == wxT('%')) {
66a77a74 424 wxSscanf(wd.c_str(), wxT("%i%%"), &wdi);
efba2b89 425 SetWidthFloat(wdi, wxHTML_UNITS_PERCENT);
5526e819
VS
426 }
427 else {
66a77a74 428 wxSscanf(wd.c_str(), wxT("%i"), &wdi);
edbd0635 429 SetWidthFloat((int)(pixel_scale * (double)wdi), wxHTML_UNITS_PIXELS);
5526e819
VS
430 }
431 }
432}
433
434
435
436const wxHtmlCell* wxHtmlContainerCell::Find(int condition, const void* param) const
437{
438 const wxHtmlCell *r = NULL;
7e941458 439
5526e819
VS
440 if (m_Cells) {
441 r = m_Cells -> Find(condition, param);
442 if (r) return r;
443 }
444
445 return wxHtmlCell::Find(condition, param);
446}
447
448
449
0b2dadd3 450void wxHtmlContainerCell::OnMouseClick(wxWindow *parent, int x, int y, const wxMouseEvent& event)
5526e819
VS
451{
452 if (m_Cells) {
453 wxHtmlCell *c = m_Cells;
454 while (c) {
455 if ( (c -> GetPosX() <= x) &&
456 (c -> GetPosY() <= y) &&
457 (c -> GetPosX() + c -> GetWidth() > x) &&
458 (c -> GetPosY() + c -> GetHeight() > y)) {
0b2dadd3 459 c -> OnMouseClick(parent, x - c -> GetPosX(), y - c -> GetPosY(), event);
5526e819
VS
460 break;
461 }
462 c = c -> GetNext();
463 }
464 }
465}
466
467
468
469
470
471//--------------------------------------------------------------------------------
472// wxHtmlColourCell
473//--------------------------------------------------------------------------------
474
475void wxHtmlColourCell::Draw(wxDC& dc, int x, int y, int view_y1, int view_y2)
476{
efba2b89 477 if (m_Flags & wxHTML_CLR_FOREGROUND)
5526e819 478 dc.SetTextForeground(m_Colour);
efba2b89 479 if (m_Flags & wxHTML_CLR_BACKGROUND) {
5526e819
VS
480 dc.SetBackground(wxBrush(m_Colour, wxSOLID));
481 dc.SetTextBackground(m_Colour);
482 }
483 wxHtmlCell::Draw(dc, x, y, view_y1, view_y2);
484}
485
486void wxHtmlColourCell::DrawInvisible(wxDC& dc, int x, int y)
487{
efba2b89 488 if (m_Flags & wxHTML_CLR_FOREGROUND)
5526e819 489 dc.SetTextForeground(m_Colour);
efba2b89 490 if (m_Flags & wxHTML_CLR_BACKGROUND) {
5526e819
VS
491 dc.SetBackground(wxBrush(m_Colour, wxSOLID));
492 dc.SetTextBackground(m_Colour);
493 }
494 wxHtmlCell::DrawInvisible(dc, x, y);
495}
496
497
498
499
500//--------------------------------------------------------------------------------
501// wxHtmlFontCell
502//--------------------------------------------------------------------------------
503
504void wxHtmlFontCell::Draw(wxDC& dc, int x, int y, int view_y1, int view_y2)
505{
921d0fb1 506 dc.SetFont(m_Font);
5526e819
VS
507 wxHtmlCell::Draw(dc, x, y, view_y1, view_y2);
508}
509
510void wxHtmlFontCell::DrawInvisible(wxDC& dc, int x, int y)
511{
921d0fb1 512 dc.SetFont(m_Font);
5526e819
VS
513 wxHtmlCell::DrawInvisible(dc, x, y);
514}
515
516
517
518
519
520
521
522
523//--------------------------------------------------------------------------------
524// wxHtmlWidgetCell
525//--------------------------------------------------------------------------------
526
527wxHtmlWidgetCell::wxHtmlWidgetCell(wxWindow *wnd, int w)
528{
529 int sx, sy;
530 m_Wnd = wnd;
531 m_Wnd -> GetSize(&sx, &sy);
532 m_Width = sx, m_Height = sy;
533 m_WidthFloat = w;
534}
535
536
537void wxHtmlWidgetCell::Draw(wxDC& dc, int x, int y, int view_y1, int view_y2)
538{
539 int absx = 0, absy = 0, stx, sty;
540 wxHtmlCell *c = this;
541
542 while (c) {
543 absx += c -> GetPosX();
544 absy += c -> GetPosY();
545 c = c -> GetParent();
546 }
547
548 ((wxScrolledWindow*)(m_Wnd -> GetParent())) -> ViewStart(&stx, &sty);
efba2b89 549 m_Wnd -> SetSize(absx - wxHTML_SCROLL_STEP * stx, absy - wxHTML_SCROLL_STEP * sty, m_Width, m_Height);
5526e819
VS
550
551 wxHtmlCell::Draw(dc, x, y, view_y1, view_y2);
552}
553
554
555
556void wxHtmlWidgetCell::DrawInvisible(wxDC& dc, int x, int y)
557{
558 int absx = 0, absy = 0, stx, sty;
559 wxHtmlCell *c = this;
560
561 while (c) {
562 absx += c -> GetPosX();
563 absy += c -> GetPosY();
564 c = c -> GetParent();
565 }
7e941458 566
5526e819 567 ((wxScrolledWindow*)(m_Wnd -> GetParent())) -> ViewStart(&stx, &sty);
efba2b89 568 m_Wnd -> SetSize(absx - wxHTML_SCROLL_STEP * stx, absy - wxHTML_SCROLL_STEP * sty, m_Width, m_Height);
ed673c6a 569
5526e819
VS
570 wxHtmlCell::DrawInvisible(dc, x, y);
571}
572
573
574
575void wxHtmlWidgetCell::Layout(int w)
576{
577 if (m_WidthFloat != 0) {
578 m_Width = (w * m_WidthFloat) / 100;
579 m_Wnd -> SetSize(m_Width, m_Height);
580 }
581
582 wxHtmlCell::Layout(w);
583}
584
585#endif