]>
git.saurik.com Git - wxWidgets.git/blob - src/html/m_layout.cpp
   1 ///////////////////////////////////////////////////////////////////////////// 
   2 // Name:        src/html/m_layout.cpp 
   3 // Purpose:     wxHtml module for basic paragraphs/layout handling 
   4 // Author:      Vaclav Slavik 
   6 // Copyright:   (c) 1999 Vaclav Slavik 
   7 // Licence:     wxWindows licence 
   8 ///////////////////////////////////////////////////////////////////////////// 
  10 #include "wx/wxprec.h" 
  16 #if wxUSE_HTML && wxUSE_STREAMS 
  22 #include "wx/html/forcelnk.h" 
  23 #include "wx/html/m_templ.h" 
  25 #include "wx/html/htmlwin.h" 
  27 FORCE_LINK_ME(m_layout
) 
  30     #include "wx/msw/wince/missing.h"       // for bsearch() 
  32     #include <stdlib.h>                     // bsearch() 
  35 //----------------------------------------------------------------------------- 
  36 // wxHtmlPageBreakCell 
  37 //----------------------------------------------------------------------------- 
  39 // Since html isn't a page-layout language, it doesn't support page 
  40 // page breaks directly--that requires CSS2 support. But a page-break 
  41 // facility is handy, and has been requested more than once on the 
  42 // mailing lists. This wxHtml tag handler implements just enough of 
  43 // CSS2 to support a page break by recognizing only 
  44 //   <div style="page-break-before:always"> 
  46 // wxHtml maintains page breaks in wxHtmlPrintout::m_PageBreaks. The 
  47 // tag handler below adds appropriate offsets to that array member. 
  48 // wxHtmlDCRenderer::Render() accesses that array and makes a new page 
  49 // begin after each page-break tag. 
  51 // The page-break handler does all its work in AdjustPagebreak(). For 
  52 // all tag handlers, that function adjusts the page-break position. 
  53 // For other tags, it determines whether the html element can fit on 
  54 // the remainder of the page; if it cannot fit, but must not be split, 
  55 // then the function moves the page break provided in the argument up, 
  56 // and returns 'true' to inform the caller that the argument was 
  59 // Due to its special purpose, the page-break facility differs from 
  60 // other tags. It takes up no space, but it behaves as though there is 
  61 // never enough room to fit it on the remainder of the page--it always 
  62 // forces a page break. Therefore, unlike other elements that trigger 
  63 // a page break, it would never 'fit' on the following page either. 
  64 // Therefore it's necessary to compare each pagebreak candidate to the 
  65 // array wxHtmlPrintout::m_PageBreaks of pagebreaks already set, and 
  66 // set a new one only if it's not in that array. 
  68 class wxHtmlPageBreakCell 
: public wxHtmlCell
 
  71     wxHtmlPageBreakCell() {} 
  73     bool AdjustPagebreak(int* pagebreak
, 
  74                          wxArrayInt
& known_pagebreaks
) const; 
  76     void Draw(wxDC
& WXUNUSED(dc
), 
  77               int WXUNUSED(x
), int WXUNUSED(y
), 
  78               int WXUNUSED(view_y1
), int WXUNUSED(view_y2
), 
  79               wxHtmlRenderingInfo
& WXUNUSED(info
)) {} 
  82     wxDECLARE_NO_COPY_CLASS(wxHtmlPageBreakCell
); 
  85 bool wxHtmlPageBreakCell::AdjustPagebreak(int* pagebreak
, wxArrayInt
& known_pagebreaks
) const 
  87     // When we are counting pages, 'known_pagebreaks' is non-NULL. 
  88     // That's the only time we change 'pagebreak'. Otherwise, pages 
  89     // were already counted, 'known_pagebreaks' is NULL, and we don't 
  90     // do anything except return false. 
  92     // We also simply return false if the 'pagebreak' argument is 
  93     // less than (vertically above) or the same as the current 
  94     // vertical position. Otherwise we'd be setting a pagebreak above 
  95     // the current cell, which is incorrect, or duplicating a 
  96     // pagebreak that has already been set. 
  97     if( known_pagebreaks
.GetCount() == 0 || *pagebreak 
<= m_PosY
) 
 102     // m_PosY is only the vertical offset from the parent. The pagebreak 
 103     // required here is the total page offset, so m_PosY must be added 
 104     // to the parent's offset and height. 
 105     int total_height 
= m_PosY
; 
 106     for ( wxHtmlCell 
*parent 
= GetParent(); parent
; parent 
= parent
->GetParent() ) 
 108         total_height 
+= parent
->GetPosY(); 
 112     // Search the array of pagebreaks to see whether we've already set 
 114     int where 
= known_pagebreaks
.Index( total_height
); 
 115     // Add a pagebreak only if there isn't one already set here. 
 116     if( wxNOT_FOUND 
!= where
) 
 129 TAG_HANDLER_BEGIN(P
, "P") 
 130     TAG_HANDLER_CONSTR(P
) { } 
 132     TAG_HANDLER_PROC(tag
) 
 134         if (m_WParser
->GetContainer()->GetFirstChild() != NULL
) 
 136             m_WParser
->CloseContainer(); 
 137             m_WParser
->OpenContainer(); 
 139         m_WParser
->GetContainer()->SetIndent(m_WParser
->GetCharHeight(), wxHTML_INDENT_TOP
); 
 140         m_WParser
->GetContainer()->SetAlign(tag
); 
 148 TAG_HANDLER_BEGIN(BR
, "BR") 
 149     TAG_HANDLER_CONSTR(BR
) { } 
 151     TAG_HANDLER_PROC(tag
) 
 153         int al 
= m_WParser
->GetContainer()->GetAlignHor(); 
 154         wxHtmlContainerCell 
*c
; 
 156         m_WParser
->CloseContainer(); 
 157         c 
= m_WParser
->OpenContainer(); 
 160         c
->SetMinHeight(m_WParser
->GetCharHeight()); 
 168 TAG_HANDLER_BEGIN(CENTER
, "CENTER") 
 169     TAG_HANDLER_CONSTR(CENTER
) { } 
 171     TAG_HANDLER_PROC(tag
) 
 173         int old 
= m_WParser
->GetAlign(); 
 174         wxHtmlContainerCell 
*c 
= m_WParser
->GetContainer(); 
 176         m_WParser
->SetAlign(wxHTML_ALIGN_CENTER
); 
 177         if (c
->GetFirstChild() != NULL
) 
 179             m_WParser
->CloseContainer(); 
 180             m_WParser
->OpenContainer(); 
 183             c
->SetAlignHor(wxHTML_ALIGN_CENTER
); 
 189             m_WParser
->SetAlign(old
); 
 190             if (c
->GetFirstChild() != NULL
) 
 192                 m_WParser
->CloseContainer(); 
 193                 m_WParser
->OpenContainer(); 
 203 TAG_HANDLER_END(CENTER
) 
 207 TAG_HANDLER_BEGIN(DIV
, "DIV") 
 208     TAG_HANDLER_CONSTR(DIV
) { } 
 210     TAG_HANDLER_PROC(tag
) 
 212         if(tag
.HasParam(wxT("STYLE"))) 
 214             if(tag
.GetParam(wxT("STYLE")).IsSameAs(wxT("PAGE-BREAK-BEFORE:ALWAYS"), false)) 
 216                 m_WParser
->CloseContainer(); 
 217                 m_WParser
->OpenContainer()->InsertCell(new wxHtmlPageBreakCell
); 
 218                 m_WParser
->CloseContainer(); 
 219                 m_WParser
->OpenContainer(); 
 224                 // Treat other STYLE parameters here when they're supported. 
 228         else if(tag
.HasParam(wxT("ALIGN"))) 
 230             int old 
= m_WParser
->GetAlign(); 
 231             wxHtmlContainerCell 
*c 
= m_WParser
->GetContainer(); 
 232             if (c
->GetFirstChild() != NULL
) 
 234                 m_WParser
->CloseContainer(); 
 235                 m_WParser
->OpenContainer(); 
 236                 c 
= m_WParser
->GetContainer(); 
 238                 m_WParser
->SetAlign(c
->GetAlignHor()); 
 243                 m_WParser
->SetAlign(c
->GetAlignHor()); 
 248             m_WParser
->SetAlign(old
); 
 249             if (c
->GetFirstChild() != NULL
) 
 251                 m_WParser
->CloseContainer(); 
 252                 m_WParser
->OpenContainer(); 
 262             int al 
= m_WParser
->GetContainer()->GetAlignHor(); 
 263             wxHtmlContainerCell 
*c
; 
 265             m_WParser
->CloseContainer(); 
 266             c 
= m_WParser
->OpenContainer(); 
 269             c
->SetMinHeight(m_WParser
->GetCharHeight()); 
 279 TAG_HANDLER_BEGIN(TITLE
, "TITLE") 
 280     TAG_HANDLER_CONSTR(TITLE
) { } 
 282     TAG_HANDLER_PROC(tag
) 
 284         wxHtmlWindowInterface 
*winIface 
= m_WParser
->GetWindowInterface(); 
 287             wxString 
title(tag
.GetBeginIter(), tag
.GetEndIter1()); 
 288 #if !wxUSE_UNICODE && wxUSE_WCHAR_T 
 289             const wxFontEncoding enc 
= m_WParser
->GetInputEncoding(); 
 290             if ( enc 
!= wxFONTENCODING_DEFAULT 
) 
 292                 // need to convert to the current one 
 293                 title 
= wxString(title
.wc_str(wxCSConv(enc
)), wxConvLocal
); 
 295 #endif // !wxUSE_UNICODE 
 297             title 
= m_WParser
->GetEntitiesParser()->Parse(title
); 
 299             winIface
->SetHTMLWindowTitle(title
); 
 304 TAG_HANDLER_END(TITLE
) 
 309 TAG_HANDLER_BEGIN(BODY
, "BODY") 
 310     TAG_HANDLER_CONSTR(BODY
) { } 
 312     TAG_HANDLER_PROC(tag
) 
 316         if (tag
.GetParamAsColour(wxT("TEXT"), &clr
)) 
 318             m_WParser
->SetActualColor(clr
); 
 319             m_WParser
->GetContainer()->InsertCell(new wxHtmlColourCell(clr
)); 
 322         if (tag
.GetParamAsColour(wxT("LINK"), &clr
)) 
 323             m_WParser
->SetLinkColor(clr
); 
 325         wxHtmlWindowInterface 
*winIface 
= m_WParser
->GetWindowInterface(); 
 326         // the rest of this function requires a window: 
 330         if (tag
.HasParam(wxT("BACKGROUND"))) 
 332             wxFSFile 
*fileBgImage 
= m_WParser
->OpenURL
 
 335                                                 tag
.GetParam(wxT("BACKGROUND")) 
 339                 wxInputStream 
*is 
= fileBgImage
->GetStream(); 
 344                         winIface
->SetHTMLBackgroundImage(image
); 
 351         if (tag
.GetParamAsColour(wxT("BGCOLOR"), &clr
)) 
 353             m_WParser
->GetContainer()->InsertCell( 
 354                 new wxHtmlColourCell(clr
, wxHTML_CLR_BACKGROUND
)); 
 355             winIface
->SetHTMLBackgroundColour(clr
); 
 361 TAG_HANDLER_END(BODY
) 
 365 TAG_HANDLER_BEGIN(BLOCKQUOTE
, "BLOCKQUOTE") 
 366     TAG_HANDLER_CONSTR(BLOCKQUOTE
) { } 
 368     TAG_HANDLER_PROC(tag
) 
 370         wxHtmlContainerCell 
*c
; 
 372         m_WParser
->CloseContainer(); 
 373         c 
= m_WParser
->OpenContainer(); 
 375         if (c
->GetAlignHor() == wxHTML_ALIGN_RIGHT
) 
 376             c
->SetIndent(5 * m_WParser
->GetCharWidth(), wxHTML_INDENT_RIGHT
); 
 378             c
->SetIndent(5 * m_WParser
->GetCharWidth(), wxHTML_INDENT_LEFT
); 
 380         c
->SetIndent(m_WParser
->GetCharHeight(), wxHTML_INDENT_TOP
); 
 381         m_WParser
->OpenContainer(); 
 383         c 
= m_WParser
->CloseContainer(); 
 384         c
->SetIndent(m_WParser
->GetCharHeight(), wxHTML_INDENT_BOTTOM
); 
 385         m_WParser
->CloseContainer(); 
 386         m_WParser
->OpenContainer(); 
 390 TAG_HANDLER_END(BLOCKQUOTE
) 
 394 TAG_HANDLER_BEGIN(SUBSUP
, "SUB,SUP") 
 396     TAG_HANDLER_PROC(tag
) 
 398         bool issub 
= (tag
.GetName() == wxT("SUB")); 
 399         wxHtmlScriptMode oldmode 
= m_WParser
->GetScriptMode(); 
 400         int oldbase 
= m_WParser
->GetScriptBaseline(); 
 401         int oldsize 
= m_WParser
->GetFontSize(); 
 403         wxHtmlContainerCell 
*cont 
= m_WParser
->GetContainer(); 
 404         wxHtmlCell 
*c 
= cont
->GetLastChild(); 
 406         m_WParser
->SetScriptMode(issub 
? wxHTML_SCRIPT_SUB 
: wxHTML_SCRIPT_SUP
); 
 407         m_WParser
->SetScriptBaseline( 
 408                 oldbase 
+ c 
? c
->GetScriptBaseline() : 0); 
 410         // select smaller font 
 411         m_WParser
->SetFontSize(m_WParser
->GetFontSize()-2); 
 412         cont
->InsertCell(new wxHtmlFontCell(m_WParser
->CreateCurrentFont())); 
 417         m_WParser
->SetFontSize(oldsize
); 
 418         m_WParser
->GetContainer()->InsertCell( 
 419             new wxHtmlFontCell(m_WParser
->CreateCurrentFont())); 
 421         // restore base and alignment 
 422         m_WParser
->SetScriptBaseline(oldbase
); 
 423         m_WParser
->SetScriptMode(oldmode
); 
 428 TAG_HANDLER_END(SUBSUP
) 
 431 // Tag handler for tags that we have to ignore, otherwise non-text data 
 432 // would show up as text: 
 433 TAG_HANDLER_BEGIN(DoNothing
, "SCRIPT") 
 434     TAG_HANDLER_CONSTR(DoNothing
) { } 
 436     TAG_HANDLER_PROC(WXUNUSED(tag
)) 
 440 TAG_HANDLER_END(DoNothing
) 
 446 TAGS_MODULE_BEGIN(Layout
) 
 450     TAGS_MODULE_ADD(CENTER
) 
 452     TAGS_MODULE_ADD(TITLE
) 
 453     TAGS_MODULE_ADD(BODY
) 
 454     TAGS_MODULE_ADD(BLOCKQUOTE
) 
 455     TAGS_MODULE_ADD(SUBSUP
) 
 456     TAGS_MODULE_ADD(DoNothing
) 
 458 TAGS_MODULE_END(Layout
)