~brian-sidebotham/wxwidgets-cmake/wxpython-2.9.4

« back to all changes in this revision

Viewing changes to src/html/m_layout.cpp

  • Committer: Brian Sidebotham
  • Date: 2013-08-03 14:30:08 UTC
  • Revision ID: brian.sidebotham@gmail.com-20130803143008-c7806tkych1tp6fc
Initial import into Bazaar

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/////////////////////////////////////////////////////////////////////////////
 
2
// Name:        src/html/m_layout.cpp
 
3
// Purpose:     wxHtml module for basic paragraphs/layout handling
 
4
// Author:      Vaclav Slavik
 
5
// RCS-ID:      $Id: m_layout.cpp 70528 2012-02-07 13:02:32Z VZ $
 
6
// Copyright:   (c) 1999 Vaclav Slavik
 
7
// Licence:     wxWindows licence
 
8
/////////////////////////////////////////////////////////////////////////////
 
9
 
 
10
#include "wx/wxprec.h"
 
11
 
 
12
#ifdef __BORLANDC__
 
13
    #pragma hdrstop
 
14
#endif
 
15
 
 
16
#if wxUSE_HTML && wxUSE_STREAMS
 
17
 
 
18
#ifndef WX_PRECOMP
 
19
    #include "wx/image.h"
 
20
#endif
 
21
 
 
22
#include "wx/html/forcelnk.h"
 
23
#include "wx/html/m_templ.h"
 
24
 
 
25
#include "wx/html/htmlwin.h"
 
26
 
 
27
FORCE_LINK_ME(m_layout)
 
28
 
 
29
#ifdef __WXWINCE__
 
30
    #include "wx/msw/wince/missing.h"       // for bsearch()
 
31
#else
 
32
    #include <stdlib.h>                     // bsearch()
 
33
#endif
 
34
 
 
35
//-----------------------------------------------------------------------------
 
36
// wxHtmlPageBreakCell
 
37
//-----------------------------------------------------------------------------
 
38
 
 
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">
 
45
//
 
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.
 
50
 
 
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
 
57
// modified.
 
58
//
 
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.
 
67
 
 
68
class wxHtmlPageBreakCell : public wxHtmlCell
 
69
{
 
70
public:
 
71
    wxHtmlPageBreakCell() {}
 
72
 
 
73
    bool AdjustPagebreak(int* pagebreak,
 
74
                         const wxArrayInt& known_pagebreaks,
 
75
                         int pageHeight) const;
 
76
 
 
77
    void Draw(wxDC& WXUNUSED(dc),
 
78
              int WXUNUSED(x), int WXUNUSED(y),
 
79
              int WXUNUSED(view_y1), int WXUNUSED(view_y2),
 
80
              wxHtmlRenderingInfo& WXUNUSED(info)) {}
 
81
 
 
82
private:
 
83
    wxDECLARE_NO_COPY_CLASS(wxHtmlPageBreakCell);
 
84
};
 
85
 
 
86
bool
 
87
wxHtmlPageBreakCell::AdjustPagebreak(int* pagebreak,
 
88
                                     const wxArrayInt& known_pagebreaks,
 
89
                                     int WXUNUSED(pageHeight)) const
 
90
{
 
91
    // When we are counting pages, 'known_pagebreaks' is non-NULL.
 
92
    // That's the only time we change 'pagebreak'. Otherwise, pages
 
93
    // were already counted, 'known_pagebreaks' is NULL, and we don't
 
94
    // do anything except return false.
 
95
    //
 
96
    // We also simply return false if the 'pagebreak' argument is
 
97
    // less than (vertically above) or the same as the current
 
98
    // vertical position. Otherwise we'd be setting a pagebreak above
 
99
    // the current cell, which is incorrect, or duplicating a
 
100
    // pagebreak that has already been set.
 
101
    if( known_pagebreaks.GetCount() == 0 || *pagebreak <= m_PosY)
 
102
    {
 
103
        return false;
 
104
    }
 
105
 
 
106
    // m_PosY is only the vertical offset from the parent. The pagebreak
 
107
    // required here is the total page offset, so m_PosY must be added
 
108
    // to the parent's offset and height.
 
109
    int total_height = m_PosY;
 
110
    for ( wxHtmlCell *parent = GetParent(); parent; parent = parent->GetParent() )
 
111
    {
 
112
        total_height += parent->GetPosY();
 
113
    }
 
114
 
 
115
 
 
116
    // Search the array of pagebreaks to see whether we've already set
 
117
    // a pagebreak here.
 
118
    int where = known_pagebreaks.Index( total_height);
 
119
    // Add a pagebreak only if there isn't one already set here.
 
120
    if( wxNOT_FOUND != where)
 
121
    {
 
122
        return false;
 
123
    }
 
124
    else
 
125
    {
 
126
        *pagebreak = m_PosY;
 
127
        return true;
 
128
    }
 
129
}
 
130
 
 
131
 
 
132
 
 
133
TAG_HANDLER_BEGIN(P, "P")
 
134
    TAG_HANDLER_CONSTR(P) { }
 
135
 
 
136
    TAG_HANDLER_PROC(tag)
 
137
    {
 
138
        if (m_WParser->GetContainer()->GetFirstChild() != NULL)
 
139
        {
 
140
            m_WParser->CloseContainer();
 
141
            m_WParser->OpenContainer();
 
142
        }
 
143
        m_WParser->GetContainer()->SetIndent(m_WParser->GetCharHeight(), wxHTML_INDENT_TOP);
 
144
        m_WParser->GetContainer()->SetAlign(tag);
 
145
        return false;
 
146
    }
 
147
 
 
148
TAG_HANDLER_END(P)
 
149
 
 
150
 
 
151
 
 
152
TAG_HANDLER_BEGIN(BR, "BR")
 
153
    TAG_HANDLER_CONSTR(BR) { }
 
154
 
 
155
    TAG_HANDLER_PROC(tag)
 
156
    {
 
157
        int al = m_WParser->GetContainer()->GetAlignHor();
 
158
        wxHtmlContainerCell *c;
 
159
 
 
160
        m_WParser->CloseContainer();
 
161
        c = m_WParser->OpenContainer();
 
162
        c->SetAlignHor(al);
 
163
        c->SetAlign(tag);
 
164
        c->SetMinHeight(m_WParser->GetCharHeight());
 
165
        return false;
 
166
    }
 
167
 
 
168
TAG_HANDLER_END(BR)
 
169
 
 
170
 
 
171
 
 
172
TAG_HANDLER_BEGIN(CENTER, "CENTER")
 
173
    TAG_HANDLER_CONSTR(CENTER) { }
 
174
 
 
175
    TAG_HANDLER_PROC(tag)
 
176
    {
 
177
        int old = m_WParser->GetAlign();
 
178
        wxHtmlContainerCell *c = m_WParser->GetContainer();
 
179
 
 
180
        m_WParser->SetAlign(wxHTML_ALIGN_CENTER);
 
181
        if (c->GetFirstChild() != NULL)
 
182
        {
 
183
            m_WParser->CloseContainer();
 
184
            m_WParser->OpenContainer();
 
185
        }
 
186
        else
 
187
            c->SetAlignHor(wxHTML_ALIGN_CENTER);
 
188
 
 
189
        if (tag.HasEnding())
 
190
        {
 
191
            ParseInner(tag);
 
192
 
 
193
            m_WParser->SetAlign(old);
 
194
            if (c->GetFirstChild() != NULL)
 
195
            {
 
196
                m_WParser->CloseContainer();
 
197
                m_WParser->OpenContainer();
 
198
            }
 
199
            else
 
200
                c->SetAlignHor(old);
 
201
 
 
202
            return true;
 
203
        }
 
204
        else return false;
 
205
    }
 
206
 
 
207
TAG_HANDLER_END(CENTER)
 
208
 
 
209
 
 
210
 
 
211
TAG_HANDLER_BEGIN(DIV, "DIV")
 
212
    TAG_HANDLER_CONSTR(DIV) { }
 
213
 
 
214
    TAG_HANDLER_PROC(tag)
 
215
    {
 
216
        if(tag.HasParam(wxT("STYLE")))
 
217
        {
 
218
            if(tag.GetParam(wxT("STYLE")).IsSameAs(wxT("PAGE-BREAK-BEFORE:ALWAYS"), false))
 
219
            {
 
220
                m_WParser->CloseContainer();
 
221
                m_WParser->OpenContainer()->InsertCell(new wxHtmlPageBreakCell);
 
222
                m_WParser->CloseContainer();
 
223
                m_WParser->OpenContainer();
 
224
                return false;
 
225
            }
 
226
            else
 
227
            {
 
228
                // Treat other STYLE parameters here when they're supported.
 
229
                return false;
 
230
            }
 
231
        }
 
232
        else if(tag.HasParam(wxT("ALIGN")))
 
233
        {
 
234
            int old = m_WParser->GetAlign();
 
235
            wxHtmlContainerCell *c = m_WParser->GetContainer();
 
236
            if (c->GetFirstChild() != NULL)
 
237
            {
 
238
                m_WParser->CloseContainer();
 
239
                m_WParser->OpenContainer();
 
240
                c = m_WParser->GetContainer();
 
241
                c->SetAlign(tag);
 
242
                m_WParser->SetAlign(c->GetAlignHor());
 
243
            }
 
244
            else
 
245
            {
 
246
                c->SetAlign(tag);
 
247
                m_WParser->SetAlign(c->GetAlignHor());
 
248
            }
 
249
 
 
250
            ParseInner(tag);
 
251
 
 
252
            m_WParser->SetAlign(old);
 
253
            if (c->GetFirstChild() != NULL)
 
254
            {
 
255
                m_WParser->CloseContainer();
 
256
                m_WParser->OpenContainer();
 
257
            }
 
258
            else
 
259
                c->SetAlignHor(old);
 
260
 
 
261
            return true;
 
262
        }
 
263
        else
 
264
        {
 
265
            // Same as BR
 
266
            int al = m_WParser->GetContainer()->GetAlignHor();
 
267
            wxHtmlContainerCell *c;
 
268
 
 
269
            m_WParser->CloseContainer();
 
270
            c = m_WParser->OpenContainer();
 
271
            c->SetAlignHor(al);
 
272
            c->SetAlign(tag);
 
273
            c->SetMinHeight(m_WParser->GetCharHeight());
 
274
            return false;
 
275
        }
 
276
    }
 
277
 
 
278
TAG_HANDLER_END(DIV)
 
279
 
 
280
 
 
281
 
 
282
 
 
283
TAG_HANDLER_BEGIN(TITLE, "TITLE")
 
284
    TAG_HANDLER_CONSTR(TITLE) { }
 
285
 
 
286
    TAG_HANDLER_PROC(tag)
 
287
    {
 
288
        wxHtmlWindowInterface *winIface = m_WParser->GetWindowInterface();
 
289
        if (winIface)
 
290
        {
 
291
            wxString title(tag.GetBeginIter(), tag.GetEndIter1());
 
292
#if !wxUSE_UNICODE
 
293
            const wxFontEncoding enc = m_WParser->GetInputEncoding();
 
294
            if ( enc != wxFONTENCODING_DEFAULT )
 
295
            {
 
296
                // need to convert to the current one
 
297
                title = wxString(title.wc_str(wxCSConv(enc)), wxConvLocal);
 
298
            }
 
299
#endif // !wxUSE_UNICODE
 
300
 
 
301
            title = m_WParser->GetEntitiesParser()->Parse(title);
 
302
 
 
303
            winIface->SetHTMLWindowTitle(title);
 
304
        }
 
305
        return true;
 
306
    }
 
307
 
 
308
TAG_HANDLER_END(TITLE)
 
309
 
 
310
 
 
311
 
 
312
 
 
313
TAG_HANDLER_BEGIN(BODY, "BODY")
 
314
    TAG_HANDLER_CONSTR(BODY) { }
 
315
 
 
316
    TAG_HANDLER_PROC(tag)
 
317
    {
 
318
        wxColour clr;
 
319
 
 
320
        if (tag.GetParamAsColour(wxT("TEXT"), &clr))
 
321
        {
 
322
            m_WParser->SetActualColor(clr);
 
323
            m_WParser->GetContainer()->InsertCell(new wxHtmlColourCell(clr));
 
324
        }
 
325
 
 
326
        if (tag.GetParamAsColour(wxT("LINK"), &clr))
 
327
            m_WParser->SetLinkColor(clr);
 
328
 
 
329
        wxHtmlWindowInterface *winIface = m_WParser->GetWindowInterface();
 
330
        // the rest of this function requires a window:
 
331
        if ( !winIface )
 
332
            return false;
 
333
 
 
334
        if (tag.HasParam(wxT("BACKGROUND")))
 
335
        {
 
336
            wxFSFile *fileBgImage = m_WParser->OpenURL
 
337
                                               (
 
338
                                                wxHTML_URL_IMAGE,
 
339
                                                tag.GetParam(wxT("BACKGROUND"))
 
340
                                               );
 
341
            if ( fileBgImage )
 
342
            {
 
343
                wxInputStream *is = fileBgImage->GetStream();
 
344
                if ( is )
 
345
                {
 
346
                    wxImage image(*is);
 
347
                    if ( image.IsOk() )
 
348
                        winIface->SetHTMLBackgroundImage(image);
 
349
                }
 
350
 
 
351
                delete fileBgImage;
 
352
            }
 
353
        }
 
354
 
 
355
        if (tag.GetParamAsColour(wxT("BGCOLOR"), &clr))
 
356
        {
 
357
            m_WParser->GetContainer()->InsertCell(
 
358
                new wxHtmlColourCell(clr, wxHTML_CLR_BACKGROUND));
 
359
            winIface->SetHTMLBackgroundColour(clr);
 
360
        }
 
361
 
 
362
        return false;
 
363
    }
 
364
 
 
365
TAG_HANDLER_END(BODY)
 
366
 
 
367
 
 
368
 
 
369
TAG_HANDLER_BEGIN(BLOCKQUOTE, "BLOCKQUOTE")
 
370
    TAG_HANDLER_CONSTR(BLOCKQUOTE) { }
 
371
 
 
372
    TAG_HANDLER_PROC(tag)
 
373
    {
 
374
        wxHtmlContainerCell *c;
 
375
 
 
376
        m_WParser->CloseContainer();
 
377
        c = m_WParser->OpenContainer();
 
378
 
 
379
        if (c->GetAlignHor() == wxHTML_ALIGN_RIGHT)
 
380
            c->SetIndent(5 * m_WParser->GetCharWidth(), wxHTML_INDENT_RIGHT);
 
381
        else
 
382
            c->SetIndent(5 * m_WParser->GetCharWidth(), wxHTML_INDENT_LEFT);
 
383
 
 
384
        c->SetIndent(m_WParser->GetCharHeight(), wxHTML_INDENT_TOP);
 
385
        m_WParser->OpenContainer();
 
386
        ParseInner(tag);
 
387
        c = m_WParser->CloseContainer();
 
388
        c->SetIndent(m_WParser->GetCharHeight(), wxHTML_INDENT_BOTTOM);
 
389
        m_WParser->CloseContainer();
 
390
        m_WParser->OpenContainer();
 
391
        return true;
 
392
    }
 
393
 
 
394
TAG_HANDLER_END(BLOCKQUOTE)
 
395
 
 
396
 
 
397
 
 
398
TAG_HANDLER_BEGIN(SUBSUP, "SUB,SUP")
 
399
 
 
400
    TAG_HANDLER_PROC(tag)
 
401
    {
 
402
        bool issub = (tag.GetName() == wxT("SUB"));
 
403
        wxHtmlScriptMode oldmode = m_WParser->GetScriptMode();
 
404
        int oldbase = m_WParser->GetScriptBaseline();
 
405
        int oldsize = m_WParser->GetFontSize();
 
406
 
 
407
        wxHtmlContainerCell *cont = m_WParser->GetContainer();
 
408
        wxHtmlCell *c = cont->GetLastChild();
 
409
 
 
410
        m_WParser->SetScriptMode(issub ? wxHTML_SCRIPT_SUB : wxHTML_SCRIPT_SUP);
 
411
        m_WParser->SetScriptBaseline(
 
412
                oldbase + c ? c->GetScriptBaseline() : 0);
 
413
 
 
414
        // select smaller font
 
415
        m_WParser->SetFontSize(m_WParser->GetFontSize()-2);
 
416
        cont->InsertCell(new wxHtmlFontCell(m_WParser->CreateCurrentFont()));
 
417
 
 
418
        ParseInner(tag);
 
419
 
 
420
        // restore font size
 
421
        m_WParser->SetFontSize(oldsize);
 
422
        m_WParser->GetContainer()->InsertCell(
 
423
            new wxHtmlFontCell(m_WParser->CreateCurrentFont()));
 
424
 
 
425
        // restore base and alignment
 
426
        m_WParser->SetScriptBaseline(oldbase);
 
427
        m_WParser->SetScriptMode(oldmode);
 
428
 
 
429
        return true;
 
430
    }
 
431
 
 
432
TAG_HANDLER_END(SUBSUP)
 
433
 
 
434
 
 
435
// Tag handler for tags that we have to ignore, otherwise non-text data
 
436
// would show up as text:
 
437
TAG_HANDLER_BEGIN(DoNothing, "SCRIPT")
 
438
    TAG_HANDLER_CONSTR(DoNothing) { }
 
439
 
 
440
    TAG_HANDLER_PROC(WXUNUSED(tag))
 
441
    {
 
442
        return true;
 
443
    }
 
444
TAG_HANDLER_END(DoNothing)
 
445
 
 
446
 
 
447
 
 
448
 
 
449
 
 
450
TAGS_MODULE_BEGIN(Layout)
 
451
 
 
452
    TAGS_MODULE_ADD(P)
 
453
    TAGS_MODULE_ADD(BR)
 
454
    TAGS_MODULE_ADD(CENTER)
 
455
    TAGS_MODULE_ADD(DIV)
 
456
    TAGS_MODULE_ADD(TITLE)
 
457
    TAGS_MODULE_ADD(BODY)
 
458
    TAGS_MODULE_ADD(BLOCKQUOTE)
 
459
    TAGS_MODULE_ADD(SUBSUP)
 
460
    TAGS_MODULE_ADD(DoNothing)
 
461
 
 
462
TAGS_MODULE_END(Layout)
 
463
 
 
464
#endif