]>
git.saurik.com Git - wxWidgets.git/blob - src/html/m_layout.cpp
   1 ///////////////////////////////////////////////////////////////////////////// 
   3 // Purpose:     wxHtml module for basic paragraphs/layout handling 
   4 // Author:      Vaclav Slavik 
   6 // Copyright:   (c) 1999 Vaclav Slavik 
   7 // Licence:     wxWindows licence 
   8 ///////////////////////////////////////////////////////////////////////////// 
   9 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) 
  10 #pragma implementation 
  13 #include "wx/wxprec.h" 
  17 #if wxUSE_HTML && wxUSE_STREAMS 
  26 #include "wx/html/forcelnk.h" 
  27 #include "wx/html/m_templ.h" 
  29 #include "wx/html/htmlwin.h" 
  31 FORCE_LINK_ME(m_layout
) 
  34     #include "wx/msw/wince/missing.h"       // for bsearch() 
  36     #include <stdlib.h>                     // bsearch() 
  39 //----------------------------------------------------------------------------- 
  40 // wxHtmlPageBreakCell 
  41 //----------------------------------------------------------------------------- 
  43 // Since html isn't a page-layout language, it doesn't support page 
  44 // page breaks directly--that requires CSS2 support. But a page-break 
  45 // facility is handy, and has been requested more than once on the 
  46 // mailing lists. This wxHtml tag handler implements just enough of 
  47 // CSS2 to support a page break by recognizing only 
  48 //   <div style="page-break-before:always"> 
  50 // wxHtml maintains page breaks in wxHtmlPrintout::m_PageBreaks. The 
  51 // tag handler below adds appropriate offsets to that array member. 
  52 // wxHtmlDCRenderer::Render() accesses that array and makes a new page 
  53 // begin after each page-break tag. 
  55 // The page-break handler does all its work in AdjustPagebreak(). For 
  56 // all tag handlers, that function adjusts the page-break position. 
  57 // For other tags, it determines whether the html element can fit on 
  58 // the remainder of the page; if it cannot fit, but must not be split, 
  59 // then the function moves the page break provided in the argument up, 
  60 // and returns 'true' to inform the caller that the argument was 
  63 // Due to its special purpose, the page-break facility differs from 
  64 // other tags. It takes up no space, but it behaves as though there is 
  65 // never enough room to fit it on the remainder of the page--it always 
  66 // forces a page break. Therefore, unlike other elements that trigger 
  67 // a page break, it would never 'fit' on the following page either. 
  68 // Therefore it's necessary to compare each pagebreak candidate to the 
  69 // array wxHtmlPrintout::m_PageBreaks of pagebreaks already set, and 
  70 // set a new one only if it's not in that array. 
  72 class wxHtmlPageBreakCell 
: public wxHtmlCell
 
  75     wxHtmlPageBreakCell() {} 
  77     bool AdjustPagebreak(int* pagebreak
, 
  78                          int* known_pagebreaks 
= NULL
, 
  79                          int number_of_pages 
= 0) const; 
  80     void Draw(wxDC
& WXUNUSED(dc
), 
  81               int WXUNUSED(x
), int WXUNUSED(y
), 
  82               int WXUNUSED(view_y1
), int WXUNUSED(view_y2
), 
  83               wxHtmlRenderingInfo
& WXUNUSED(info
)) {} 
  86     DECLARE_NO_COPY_CLASS(wxHtmlPageBreakCell
) 
  89 // Comparison routine for bsearch into an int* array of pagebreaks. 
  90 extern "C" int wxCMPFUNC_CONV 
wxInteger_compare(void const* i0
, void const* i1
) 
  92     return *(int*)i0 
- *(int*)i1
; 
  95 bool wxHtmlPageBreakCell::AdjustPagebreak(int* pagebreak
, int* known_pagebreaks
, int number_of_pages
) const 
  97     // When we are counting pages, 'known_pagebreaks' is non-NULL. 
  98     // That's the only time we change 'pagebreak'. Otherwise, pages 
  99     // were already counted, 'known_pagebreaks' is NULL, and we don't 
 100     // do anything except return FALSE. 
 102     // We also simply return FALSE if the 'pagebreak' argument is 
 103     // less than (vertically above) or the same as the current 
 104     // vertical position. Otherwise we'd be setting a pagebreak above 
 105     // the current cell, which is incorrect, or duplicating a 
 106     // pagebreak that has already been set. 
 107     if(NULL 
== known_pagebreaks 
|| *pagebreak 
<= m_PosY
) 
 112     // m_PosY is only the vertical offset from the parent. The pagebreak 
 113     // required here is the total page offset, so m_PosY must be added 
 114     // to the parent's offset and height. 
 115     int total_height 
= m_PosY 
+ GetParent()->GetPosY() + GetParent()->GetHeight(); 
 117     // Search the array of pagebreaks to see whether we've already set 
 118     // a pagebreak here. The standard bsearch() function is appropriate 
 119     // because the array of pagebreaks through known_pagebreaks[number_of_pages] 
 120     // is known to be sorted in strictly increasing order. '1 + number_of_pages' 
 121     // is used as a bsearch() argument because the array contains a leading 
 122     // zero plus one element for each page. 
 123     int* where 
= (int*) bsearch(&total_height
, known_pagebreaks
, 
 124                                 1 + number_of_pages
, sizeof(int), 
 126     // Add a pagebreak only if there isn't one already set here. 
 138 TAG_HANDLER_BEGIN(P
, "P") 
 139     TAG_HANDLER_CONSTR(P
) { } 
 141     TAG_HANDLER_PROC(tag
) 
 143         if (m_WParser
->GetContainer()->GetFirstChild() != NULL
) 
 145             m_WParser
->CloseContainer(); 
 146             m_WParser
->OpenContainer(); 
 148         m_WParser
->GetContainer()->SetIndent(m_WParser
->GetCharHeight(), wxHTML_INDENT_TOP
); 
 149         m_WParser
->GetContainer()->SetAlign(tag
); 
 157 TAG_HANDLER_BEGIN(BR
, "BR") 
 158     TAG_HANDLER_CONSTR(BR
) { } 
 160     TAG_HANDLER_PROC(tag
) 
 162         int al 
= m_WParser
->GetContainer()->GetAlignHor(); 
 163         wxHtmlContainerCell 
*c
; 
 165         m_WParser
->CloseContainer(); 
 166         c 
= m_WParser
->OpenContainer(); 
 169         c
->SetMinHeight(m_WParser
->GetCharHeight()); 
 177 TAG_HANDLER_BEGIN(CENTER
, "CENTER") 
 178     TAG_HANDLER_CONSTR(CENTER
) { } 
 180     TAG_HANDLER_PROC(tag
) 
 182         int old 
= m_WParser
->GetAlign(); 
 183         wxHtmlContainerCell 
*c 
= m_WParser
->GetContainer(); 
 185         m_WParser
->SetAlign(wxHTML_ALIGN_CENTER
); 
 186         if (c
->GetFirstChild() != NULL
) 
 188             m_WParser
->CloseContainer(); 
 189             m_WParser
->OpenContainer(); 
 192             c
->SetAlignHor(wxHTML_ALIGN_CENTER
); 
 198             m_WParser
->SetAlign(old
); 
 199             if (c
->GetFirstChild() != NULL
) 
 201                 m_WParser
->CloseContainer(); 
 202                 m_WParser
->OpenContainer(); 
 212 TAG_HANDLER_END(CENTER
) 
 216 TAG_HANDLER_BEGIN(DIV
, "DIV") 
 217     TAG_HANDLER_CONSTR(DIV
) { } 
 219     TAG_HANDLER_PROC(tag
) 
 221         if(tag
.HasParam(wxT("STYLE"))) 
 223             if(tag
.GetParam(wxT("STYLE")).IsSameAs(wxT("PAGE-BREAK-BEFORE:ALWAYS"), FALSE
)) 
 225                 m_WParser
->CloseContainer(); 
 226                 m_WParser
->OpenContainer()->InsertCell(new wxHtmlPageBreakCell
); 
 227                 m_WParser
->CloseContainer(); 
 228                 m_WParser
->OpenContainer(); 
 233                 // Treat other STYLE parameters here when they're supported. 
 237         else if(tag
.HasParam(wxT("ALIGN"))) 
 239             int old 
= m_WParser
->GetAlign(); 
 240             wxHtmlContainerCell 
*c 
= m_WParser
->GetContainer(); 
 241             if (c
->GetFirstChild() != NULL
) 
 243                 m_WParser
->CloseContainer(); 
 244                 m_WParser
->OpenContainer(); 
 245                 c 
= m_WParser
->GetContainer(); 
 247                 m_WParser
->SetAlign(c
->GetAlignHor()); 
 252                 m_WParser
->SetAlign(c
->GetAlignHor()); 
 257             m_WParser
->SetAlign(old
); 
 258             if (c
->GetFirstChild() != NULL
) 
 260                 m_WParser
->CloseContainer(); 
 261                 m_WParser
->OpenContainer(); 
 271             int al 
= m_WParser
->GetContainer()->GetAlignHor(); 
 272             wxHtmlContainerCell 
*c
; 
 274             m_WParser
->CloseContainer(); 
 275             c 
= m_WParser
->OpenContainer(); 
 278             c
->SetMinHeight(m_WParser
->GetCharHeight()); 
 288 TAG_HANDLER_BEGIN(TITLE
, "TITLE") 
 289     TAG_HANDLER_CONSTR(TITLE
) { } 
 291     TAG_HANDLER_PROC(tag
) 
 293         if (m_WParser
->GetWindow()) 
 295             wxHtmlWindow 
*wfr 
= (wxHtmlWindow
*)(m_WParser
->GetWindow()); 
 298                 wxString title 
= m_WParser
->GetSource()->Mid( 
 300                                         tag
.GetEndPos1()-tag
.GetBeginPos()); 
 302                 wxCSConv 
conv(m_WParser
->GetInputEncoding()); 
 303                 title 
= wxString(title
.wc_str(conv
), wxConvLocal
); 
 305                 title 
= m_WParser
->GetEntitiesParser()->Parse(title
); 
 306                 wfr
->OnSetTitle(title
); 
 312 TAG_HANDLER_END(TITLE
) 
 317 TAG_HANDLER_BEGIN(BODY
, "BODY") 
 318     TAG_HANDLER_CONSTR(BODY
) { } 
 320     TAG_HANDLER_PROC(tag
) 
 324         if (tag
.GetParamAsColour(wxT("TEXT"), &clr
)) 
 326             m_WParser
->SetActualColor(clr
); 
 327             m_WParser
->GetContainer()->InsertCell(new wxHtmlColourCell(clr
)); 
 330         if (tag
.GetParamAsColour(wxT("LINK"), &clr
)) 
 331             m_WParser
->SetLinkColor(clr
); 
 333         if (tag
.GetParamAsColour(wxT("BGCOLOR"), &clr
)) 
 335             m_WParser
->GetContainer()->InsertCell( 
 336                 new wxHtmlColourCell(clr
, wxHTML_CLR_BACKGROUND
)); 
 337             if (m_WParser
->GetWindow() != NULL
) 
 338                 m_WParser
->GetWindow()->SetBackgroundColour(clr
); 
 343 TAG_HANDLER_END(BODY
) 
 347 TAG_HANDLER_BEGIN(BLOCKQUOTE
, "BLOCKQUOTE") 
 348     TAG_HANDLER_CONSTR(BLOCKQUOTE
) { } 
 350     TAG_HANDLER_PROC(tag
) 
 352         wxHtmlContainerCell 
*c
; 
 354         m_WParser
->CloseContainer(); 
 355         c 
= m_WParser
->OpenContainer(); 
 357         if (c
->GetAlignHor() == wxHTML_ALIGN_RIGHT
) 
 358             c
->SetIndent(5 * m_WParser
->GetCharWidth(), wxHTML_INDENT_RIGHT
); 
 360             c
->SetIndent(5 * m_WParser
->GetCharWidth(), wxHTML_INDENT_LEFT
); 
 362         c
->SetIndent(m_WParser
->GetCharHeight(), wxHTML_INDENT_TOP
); 
 363         m_WParser
->OpenContainer(); 
 365         c 
= m_WParser
->CloseContainer(); 
 366         c
->SetIndent(m_WParser
->GetCharHeight(), wxHTML_INDENT_BOTTOM
); 
 367         m_WParser
->CloseContainer(); 
 368         m_WParser
->OpenContainer(); 
 372 TAG_HANDLER_END(BLOCKQUOTE
) 
 376 // Tag handler for tags that we have to ignore, otherwise non-text data 
 377 // would show up as text: 
 378 TAG_HANDLER_BEGIN(DoNothing
, "SCRIPT") 
 379     TAG_HANDLER_CONSTR(DoNothing
) { } 
 381     TAG_HANDLER_PROC(WXUNUSED(tag
)) 
 385 TAG_HANDLER_END(DoNothing
) 
 389 TAGS_MODULE_BEGIN(Layout
) 
 393     TAGS_MODULE_ADD(CENTER
) 
 395     TAGS_MODULE_ADD(TITLE
) 
 396     TAGS_MODULE_ADD(BODY
) 
 397     TAGS_MODULE_ADD(BLOCKQUOTE
) 
 398     TAGS_MODULE_ADD(DoNothing
) 
 400 TAGS_MODULE_END(Layout
)