]>
git.saurik.com Git - wxWidgets.git/blob - src/html/htmlcell.cpp
1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: wxHtmlCell - basic element of HTML output
4 // Author: Vaclav Slavik
6 // Copyright: (c) 1999 Vaclav Slavik
7 // Licence: wxWindows Licence
8 /////////////////////////////////////////////////////////////////////////////
11 #pragma implementation
14 #include "wx/wxprec.h"
27 #include "wx/html/htmlcell.h"
28 #include "wx/html/htmlwin.h"
32 //-----------------------------------------------------------------------------
34 //-----------------------------------------------------------------------------
36 wxHtmlCell::wxHtmlCell() : wxObject()
40 m_Width
= m_Height
= m_Descent
= 0;
41 m_CanLiveOnPagebreak
= TRUE
;
45 wxHtmlCell::~wxHtmlCell()
47 if (m_Link
) delete m_Link
;
48 if (m_Next
) delete m_Next
;
52 void wxHtmlCell::OnMouseClick(wxWindow
*parent
, int x
, int y
,
53 const wxMouseEvent
& event
)
55 wxHtmlLinkInfo
*lnk
= GetLink(x
, y
);
58 wxHtmlLinkInfo
lnk2(*lnk
);
59 lnk2
.SetEvent(&event
);
60 lnk2
.SetHtmlCell(this);
61 ((wxHtmlWindow
*)parent
) -> OnLinkClicked(lnk2
);
62 // note : this overcasting is legal because parent is *always* wxHtmlWindow
68 bool wxHtmlCell::AdjustPagebreak(int *pagebreak
) const
70 if ((!m_CanLiveOnPagebreak
) &&
71 m_PosY
< *pagebreak
&& m_PosY
+ m_Height
> *pagebreak
) {
73 if (m_Next
!= NULL
) m_Next
-> AdjustPagebreak(pagebreak
);
78 if (m_Next
!= NULL
) return m_Next
-> AdjustPagebreak(pagebreak
);
85 void wxHtmlCell::SetLink(const wxHtmlLinkInfo
& link
)
87 if (m_Link
) delete m_Link
;
89 if (link
.GetHref() != wxEmptyString
)
90 m_Link
= new wxHtmlLinkInfo(link
);
95 //-----------------------------------------------------------------------------
97 //-----------------------------------------------------------------------------
99 wxHtmlWordCell::wxHtmlWordCell(const wxString
& word
, wxDC
& dc
) : wxHtmlCell()
103 if (m_Word
.Find(wxT('&')) != -1)
105 #define ESCSEQ(escape, subst) \
106 { wxT("&"escape";"), wxT("&"escape" "), wxT(subst) }
107 static wxChar
* substitutions
[][3] =
109 ESCSEQ("quot", "\""),
114 ESCSEQ("iexcl", "!"),
118 ESCSEQ("brkbar", " "),
122 ESCSEQ("copy", "(c)"),
124 ESCSEQ("laquo", " "),
127 ESCSEQ("reg", "(r)"),
130 ESCSEQ("plusm", " "),
132 ESCSEQ("acute", " "),
133 ESCSEQ("micro", " "),
137 ESCSEQ("raquo", " "),
139 ESCSEQ("iquest", " "),
140 ESCSEQ("Agrave", "À"),
142 ESCSEQ("Acirc", "Â"),
143 ESCSEQ("Atilde", "Ã"),
145 ESCSEQ("Aring", " "),
146 ESCSEQ("AElig", " "),
147 ESCSEQ("Ccedil", "ç"),
148 ESCSEQ("Egrave", "È"),
149 ESCSEQ("Eacute", "É"),
150 ESCSEQ("Ecirc", "Ê"),
152 ESCSEQ("Igrave", "Ì"),
154 ESCSEQ("Icirc", "Î"),
157 ESCSEQ("Ntilde", "Ñ"),
158 ESCSEQ("Ograve", "Ò"),
160 ESCSEQ("Ocirc", "Ô"),
161 ESCSEQ("Otilde", "Õ"),
164 ESCSEQ("Oslash", " "),
165 ESCSEQ("Ugrave", "Ù"),
167 ESCSEQ("Ucirc", " "),
170 ESCSEQ("szlig", "§"),
171 ESCSEQ("agrave;","à"),
172 ESCSEQ("aacute", "á"),
173 ESCSEQ("acirc", "â"),
174 ESCSEQ("atilde", "ã"),
176 ESCSEQ("aring", "a"),
177 ESCSEQ("aelig", "ae"),
178 ESCSEQ("ccedil", "ç"),
179 ESCSEQ("egrave", "è"),
180 ESCSEQ("eacute", "é"),
181 ESCSEQ("ecirc", "ê"),
183 ESCSEQ("igrave", "ì"),
184 ESCSEQ("iacute", "í"),
185 ESCSEQ("icirc", " "),
188 ESCSEQ("ntilde", "ñ"),
189 ESCSEQ("ograve", "ò"),
190 ESCSEQ("oacute", "ó"),
191 ESCSEQ("ocirc", "ô"),
192 ESCSEQ("otilde", "õ"),
194 ESCSEQ("divide", " "),
195 ESCSEQ("oslash", " "),
196 ESCSEQ("ugrave", "ù"),
197 ESCSEQ("uacute", "ú"),
198 ESCSEQ("ucirc", "û"),
203 /* this one should ALWAYS stay the last one!!! */
209 for (int i
= 0; substitutions
[i
][0] != NULL
; i
++)
211 m_Word
.Replace(substitutions
[i
][0], substitutions
[i
][2], TRUE
);
212 m_Word
.Replace(substitutions
[i
][1], substitutions
[i
][2], TRUE
);
216 dc
.GetTextExtent(m_Word
, &m_Width
, &m_Height
, &m_Descent
);
217 SetCanLiveOnPagebreak(FALSE
);
222 void wxHtmlWordCell::Draw(wxDC
& dc
, int x
, int y
, int view_y1
, int view_y2
)
224 dc
.DrawText(m_Word
, x
+ m_PosX
, y
+ m_PosY
);
225 wxHtmlCell::Draw(dc
, x
, y
, view_y1
, view_y2
);
230 //-----------------------------------------------------------------------------
231 // wxHtmlContainerCell
232 //-----------------------------------------------------------------------------
235 wxHtmlContainerCell::wxHtmlContainerCell(wxHtmlContainerCell
*parent
) : wxHtmlCell()
237 m_Cells
= m_LastCell
= NULL
;
239 if (m_Parent
) m_Parent
-> InsertCell(this);
240 m_AlignHor
= wxHTML_ALIGN_LEFT
;
241 m_AlignVer
= wxHTML_ALIGN_BOTTOM
;
242 m_IndentLeft
= m_IndentRight
= m_IndentTop
= m_IndentBottom
= 0;
243 m_WidthFloat
= 100; m_WidthFloatUnits
= wxHTML_UNITS_PERCENT
;
244 m_UseBkColour
= FALSE
;
247 m_MinHeightAlign
= wxHTML_ALIGN_TOP
;
253 void wxHtmlContainerCell::SetIndent(int i
, int what
, int units
)
255 int val
= (units
== wxHTML_UNITS_PIXELS
) ? i
: -i
;
256 if (what
& wxHTML_INDENT_LEFT
) m_IndentLeft
= val
;
257 if (what
& wxHTML_INDENT_RIGHT
) m_IndentRight
= val
;
258 if (what
& wxHTML_INDENT_TOP
) m_IndentTop
= val
;
259 if (what
& wxHTML_INDENT_BOTTOM
) m_IndentBottom
= val
;
265 int wxHtmlContainerCell::GetIndent(int ind
) const
267 if (ind
& wxHTML_INDENT_LEFT
) return m_IndentLeft
;
268 else if (ind
& wxHTML_INDENT_RIGHT
) return m_IndentRight
;
269 else if (ind
& wxHTML_INDENT_TOP
) return m_IndentTop
;
270 else if (ind
& wxHTML_INDENT_BOTTOM
) return m_IndentBottom
;
271 else return -1; /* BUG! Should not be called... */
277 int wxHtmlContainerCell::GetIndentUnits(int ind
) const
280 if (ind
& wxHTML_INDENT_LEFT
) p
= m_IndentLeft
< 0;
281 else if (ind
& wxHTML_INDENT_RIGHT
) p
= m_IndentRight
< 0;
282 else if (ind
& wxHTML_INDENT_TOP
) p
= m_IndentTop
< 0;
283 else if (ind
& wxHTML_INDENT_BOTTOM
) p
= m_IndentBottom
< 0;
284 if (p
) return wxHTML_UNITS_PERCENT
;
285 else return wxHTML_UNITS_PIXELS
;
290 bool wxHtmlContainerCell::AdjustPagebreak(int *pagebreak
) const
292 if (!m_CanLiveOnPagebreak
)
293 return wxHtmlCell::AdjustPagebreak(pagebreak
);
296 wxHtmlCell
*c
= GetFirstCell();
298 int pbrk
= *pagebreak
- m_PosY
;
301 if (c
-> AdjustPagebreak(&pbrk
)) rt
= TRUE
;
304 if (rt
) *pagebreak
= pbrk
+ m_PosY
;
311 void wxHtmlContainerCell::Layout(int w
)
313 if (m_LastLayout
== w
) {
314 wxHtmlCell::Layout(w
);
318 wxHtmlCell
*cell
= m_Cells
, *line
= m_Cells
;
319 long xpos
= 0, ypos
= m_IndentTop
;
320 int xdelta
= 0, ybasicpos
= 0, ydiff
;
321 int s_width
, s_indent
;
322 int ysizeup
= 0, ysizedown
= 0;
323 int MaxLineWidth
= 0;
333 if (m_WidthFloatUnits
== wxHTML_UNITS_PERCENT
) {
334 if (m_WidthFloat
< 0) m_Width
= (100 + m_WidthFloat
) * w
/ 100;
335 else m_Width
= m_WidthFloat
* w
/ 100;
338 if (m_WidthFloat
< 0) m_Width
= w
+ m_WidthFloat
;
339 else m_Width
= m_WidthFloat
;
343 int l
= (m_IndentLeft
< 0) ? (-m_IndentLeft
* m_Width
/ 100) : m_IndentLeft
;
344 int r
= (m_IndentRight
< 0) ? (-m_IndentRight
* m_Width
/ 100) : m_IndentRight
;
345 m_Cells
-> Layout(m_Width
- (l
+ r
));
354 // adjust indentation:
355 s_indent
= (m_IndentLeft
< 0) ? (-m_IndentLeft
* m_Width
/ 100) : m_IndentLeft
;
356 s_width
= m_Width
- s_indent
- ((m_IndentRight
< 0) ? (-m_IndentRight
* m_Width
/ 100) : m_IndentRight
);
359 while (cell
!= NULL
) {
360 switch (m_AlignVer
) {
361 case wxHTML_ALIGN_TOP
: ybasicpos
= 0; break;
362 case wxHTML_ALIGN_BOTTOM
: ybasicpos
= - cell
-> GetHeight(); break;
363 case wxHTML_ALIGN_CENTER
: ybasicpos
= - cell
-> GetHeight() / 2; break;
365 ydiff
= cell
-> GetHeight() + ybasicpos
;
367 if (cell
-> GetDescent() + ydiff
> ysizedown
) ysizedown
= cell
-> GetDescent() + ydiff
;
368 if (ybasicpos
+ cell
-> GetDescent() < -ysizeup
) ysizeup
= - (ybasicpos
+ cell
-> GetDescent());
370 cell
-> SetPos(xpos
, ybasicpos
+ cell
-> GetDescent());
371 xpos
+= cell
-> GetWidth();
372 cell
= cell
-> GetNext();
375 // force new line if occured:
376 if ((cell
== NULL
) || (xpos
+ cell
-> GetWidth() > s_width
)) {
377 if (xpos
> MaxLineWidth
) MaxLineWidth
= xpos
;
378 if (ysizeup
< 0) ysizeup
= 0;
379 if (ysizedown
< 0) ysizedown
= 0;
380 switch (m_AlignHor
) {
381 case wxHTML_ALIGN_LEFT
:
382 case wxHTML_ALIGN_JUSTIFY
:
385 case wxHTML_ALIGN_RIGHT
:
386 xdelta
= 0 + (s_width
- xpos
);
388 case wxHTML_ALIGN_CENTER
:
389 xdelta
= 0 + (s_width
- xpos
) / 2;
392 if (xdelta
< 0) xdelta
= 0;
397 if (m_AlignHor
!= wxHTML_ALIGN_JUSTIFY
|| cell
== NULL
)
398 while (line
!= cell
) {
399 line
-> SetPos(line
-> GetPosX() + xdelta
,
400 ypos
+ line
-> GetPosY());
401 line
= line
-> GetNext();
406 int step
= (s_width
- xpos
);
407 if (step
< 0) step
= 0;
408 while (line
!= cell
) {
409 line
-> SetPos(line
-> GetPosX() + s_indent
+
410 (counter
++ * step
/ xcnt
),
411 ypos
+ line
-> GetPosY());
412 line
= line
-> GetNext();
418 ysizeup
= ysizedown
= 0;
423 // setup height & width, depending on container layout:
424 m_Height
= ypos
+ (ysizedown
+ ysizeup
) + m_IndentBottom
;
426 if (m_Height
< m_MinHeight
) {
427 if (m_MinHeightAlign
!= wxHTML_ALIGN_TOP
) {
428 int diff
= m_MinHeight
- m_Height
;
429 if (m_MinHeightAlign
== wxHTML_ALIGN_CENTER
) diff
/= 2;
432 cell
-> SetPos(cell
-> GetPosX(), cell
-> GetPosY() + diff
);
433 cell
= cell
-> GetNext();
436 m_Height
= m_MinHeight
;
439 MaxLineWidth
+= s_indent
+ ((m_IndentRight
< 0) ? (-m_IndentRight
* m_Width
/ 100) : m_IndentRight
);
440 if (m_Width
< MaxLineWidth
) m_Width
= MaxLineWidth
;
444 wxHtmlCell::Layout(w
);
448 #define mMin(a, b) (((a) < (b)) ? (a) : (b))
449 #define mMax(a, b) (((a) < (b)) ? (b) : (a))
451 void wxHtmlContainerCell::Draw(wxDC
& dc
, int x
, int y
, int view_y1
, int view_y2
)
453 // container visible, draw it:
454 if ((y
+ m_PosY
< view_y2
) && (y
+ m_PosY
+ m_Height
> view_y1
)) {
457 wxBrush myb
= wxBrush(m_BkColour
, wxSOLID
);
459 int real_y1
= mMax(y
+ m_PosY
, view_y1
);
460 int real_y2
= mMin(y
+ m_PosY
+ m_Height
- 1, view_y2
);
463 dc
.SetPen(*wxTRANSPARENT_PEN
);
464 dc
.DrawRectangle(x
+ m_PosX
, real_y1
, m_Width
, real_y2
- real_y1
+ 1);
468 wxPen
mypen1(m_BorderColour1
, 1, wxSOLID
);
469 wxPen
mypen2(m_BorderColour2
, 1, wxSOLID
);
472 dc
.DrawLine(x
+ m_PosX
, y
+ m_PosY
, x
+ m_PosX
, y
+ m_PosY
+ m_Height
- 1);
473 dc
.DrawLine(x
+ m_PosX
, y
+ m_PosY
, x
+ m_PosX
+ m_Width
- 1, y
+ m_PosY
);
475 dc
.DrawLine(x
+ m_PosX
+ m_Width
- 1, y
+ m_PosY
, x
+ m_PosX
+ m_Width
- 1, y
+ m_PosY
+ m_Height
- 1);
476 dc
.DrawLine(x
+ m_PosX
, y
+ m_PosY
+ m_Height
- 1, x
+ m_PosX
+ m_Width
- 1, y
+ m_PosY
+ m_Height
- 1);
479 if (m_Cells
) m_Cells
-> Draw(dc
, x
+ m_PosX
, y
+ m_PosY
, view_y1
, view_y2
);
481 // container invisible, just proceed font+color changing:
483 if (m_Cells
) m_Cells
-> DrawInvisible(dc
, x
+ m_PosX
, y
+ m_PosY
);
486 wxHtmlCell::Draw(dc
, x
, y
, view_y1
, view_y2
);
491 void wxHtmlContainerCell::DrawInvisible(wxDC
& dc
, int x
, int y
)
493 if (m_Cells
) m_Cells
-> DrawInvisible(dc
, x
+ m_PosX
, y
+ m_PosY
);
494 wxHtmlCell::DrawInvisible(dc
, x
, y
);
499 wxHtmlLinkInfo
*wxHtmlContainerCell::GetLink(int x
, int y
) const
501 wxHtmlCell
*c
= m_Cells
;
505 cx
= c
-> GetPosX(), cy
= c
-> GetPosY();
506 cw
= c
-> GetWidth(), ch
= c
-> GetHeight();
507 if ((x
>= cx
) && (x
< cx
+ cw
) && (y
>= cy
) && (y
< cy
+ ch
))
508 return c
-> GetLink(x
- cx
, y
- cy
);
516 void wxHtmlContainerCell::InsertCell(wxHtmlCell
*f
)
518 if (!m_Cells
) m_Cells
= m_LastCell
= f
;
520 m_LastCell
-> SetNext(f
);
522 if (m_LastCell
) while (m_LastCell
-> GetNext()) m_LastCell
= m_LastCell
-> GetNext();
524 f
-> SetParent(this);
530 void wxHtmlContainerCell::SetAlign(const wxHtmlTag
& tag
)
532 if (tag
.HasParam(wxT("ALIGN"))) {
533 wxString alg
= tag
.GetParam(wxT("ALIGN"));
535 if (alg
== wxT("CENTER"))
536 SetAlignHor(wxHTML_ALIGN_CENTER
);
537 else if (alg
== wxT("LEFT"))
538 SetAlignHor(wxHTML_ALIGN_LEFT
);
539 else if (alg
== wxT("JUSTIFY"))
540 SetAlignHor(wxHTML_ALIGN_JUSTIFY
);
541 else if (alg
== wxT("RIGHT"))
542 SetAlignHor(wxHTML_ALIGN_RIGHT
);
549 void wxHtmlContainerCell::SetWidthFloat(const wxHtmlTag
& tag
, double pixel_scale
)
551 if (tag
.HasParam(wxT("WIDTH"))) {
553 wxString wd
= tag
.GetParam(wxT("WIDTH"));
555 if (wd
[wd
.Length()-1] == wxT('%')) {
556 wxSscanf(wd
.c_str(), wxT("%i%%"), &wdi
);
557 SetWidthFloat(wdi
, wxHTML_UNITS_PERCENT
);
560 wxSscanf(wd
.c_str(), wxT("%i"), &wdi
);
561 SetWidthFloat((int)(pixel_scale
* (double)wdi
), wxHTML_UNITS_PIXELS
);
569 const wxHtmlCell
* wxHtmlContainerCell::Find(int condition
, const void* param
) const
571 const wxHtmlCell
*r
= NULL
;
574 r
= m_Cells
-> Find(condition
, param
);
578 return wxHtmlCell::Find(condition
, param
);
583 void wxHtmlContainerCell::OnMouseClick(wxWindow
*parent
, int x
, int y
, const wxMouseEvent
& event
)
586 wxHtmlCell
*c
= m_Cells
;
588 if ( (c
-> GetPosX() <= x
) &&
589 (c
-> GetPosY() <= y
) &&
590 (c
-> GetPosX() + c
-> GetWidth() > x
) &&
591 (c
-> GetPosY() + c
-> GetHeight() > y
)) {
592 c
-> OnMouseClick(parent
, x
- c
-> GetPosX(), y
- c
-> GetPosY(), event
);
604 //--------------------------------------------------------------------------------
606 //--------------------------------------------------------------------------------
608 void wxHtmlColourCell::Draw(wxDC
& dc
, int x
, int y
, int view_y1
, int view_y2
)
610 if (m_Flags
& wxHTML_CLR_FOREGROUND
)
611 dc
.SetTextForeground(m_Colour
);
612 if (m_Flags
& wxHTML_CLR_BACKGROUND
) {
613 dc
.SetBackground(wxBrush(m_Colour
, wxSOLID
));
614 dc
.SetTextBackground(m_Colour
);
616 wxHtmlCell::Draw(dc
, x
, y
, view_y1
, view_y2
);
619 void wxHtmlColourCell::DrawInvisible(wxDC
& dc
, int x
, int y
)
621 if (m_Flags
& wxHTML_CLR_FOREGROUND
)
622 dc
.SetTextForeground(m_Colour
);
623 if (m_Flags
& wxHTML_CLR_BACKGROUND
) {
624 dc
.SetBackground(wxBrush(m_Colour
, wxSOLID
));
625 dc
.SetTextBackground(m_Colour
);
627 wxHtmlCell::DrawInvisible(dc
, x
, y
);
633 //--------------------------------------------------------------------------------
635 //--------------------------------------------------------------------------------
637 void wxHtmlFontCell::Draw(wxDC
& dc
, int x
, int y
, int view_y1
, int view_y2
)
640 wxHtmlCell::Draw(dc
, x
, y
, view_y1
, view_y2
);
643 void wxHtmlFontCell::DrawInvisible(wxDC
& dc
, int x
, int y
)
646 wxHtmlCell::DrawInvisible(dc
, x
, y
);
656 //--------------------------------------------------------------------------------
658 //--------------------------------------------------------------------------------
660 wxHtmlWidgetCell::wxHtmlWidgetCell(wxWindow
*wnd
, int w
)
664 m_Wnd
-> GetSize(&sx
, &sy
);
665 m_Width
= sx
, m_Height
= sy
;
670 void wxHtmlWidgetCell::Draw(wxDC
& dc
, int x
, int y
, int view_y1
, int view_y2
)
672 int absx
= 0, absy
= 0, stx
, sty
;
673 wxHtmlCell
*c
= this;
676 absx
+= c
-> GetPosX();
677 absy
+= c
-> GetPosY();
678 c
= c
-> GetParent();
681 ((wxScrolledWindow
*)(m_Wnd
-> GetParent())) -> ViewStart(&stx
, &sty
);
682 m_Wnd
-> SetSize(absx
- wxHTML_SCROLL_STEP
* stx
, absy
- wxHTML_SCROLL_STEP
* sty
, m_Width
, m_Height
);
684 wxHtmlCell::Draw(dc
, x
, y
, view_y1
, view_y2
);
689 void wxHtmlWidgetCell::DrawInvisible(wxDC
& dc
, int x
, int y
)
691 int absx
= 0, absy
= 0, stx
, sty
;
692 wxHtmlCell
*c
= this;
695 absx
+= c
-> GetPosX();
696 absy
+= c
-> GetPosY();
697 c
= c
-> GetParent();
700 ((wxScrolledWindow
*)(m_Wnd
-> GetParent())) -> ViewStart(&stx
, &sty
);
701 m_Wnd
-> SetSize(absx
- wxHTML_SCROLL_STEP
* stx
, absy
- wxHTML_SCROLL_STEP
* sty
, m_Width
, m_Height
);
703 wxHtmlCell::DrawInvisible(dc
, x
, y
);
708 void wxHtmlWidgetCell::Layout(int w
)
710 if (m_WidthFloat
!= 0) {
711 m_Width
= (w
* m_WidthFloat
) / 100;
712 m_Wnd
-> SetSize(m_Width
, m_Height
);
715 wxHtmlCell::Layout(w
);