~efargaspro/+junk/codeblocks-16.01-release

« back to all changes in this revision

Viewing changes to src/plugins/contrib/wxSmithSTC/stedit/src/steexprt.cpp

  • Committer: damienlmoore at gmail
  • Date: 2016-02-02 02:43:22 UTC
  • Revision ID: damienlmoore@gmail.com-20160202024322-yql5qmtbwdyamdwd
Code::BlocksĀ 16.01

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
///////////////////////////////////////////////////////////////////////////////
 
2
// Name:        steexprt.cpp
 
3
// Purpose:     wxSTEditorExporter
 
4
// Author:      John Labenski, and others see below
 
5
// Modified by:
 
6
// Created:     11/05/2002
 
7
// RCS-ID:
 
8
// Copyright:   (c) John Labenski, Neil Hodgson, & others see below
 
9
// Licence:     wxWidgets licence
 
10
///////////////////////////////////////////////////////////////////////////////
 
11
 
 
12
/*
 
13
Updated to SciTE 3.0.1, 12/3/2011 - see scite/src/Exporters.cxx
 
14
 
 
15
Code below marked with this copyright is under this license.
 
16
"Copyright 1998-2003 by Neil Hodgson <neilh@scintilla.org>"
 
17
 
 
18
License for Scintilla and SciTE
 
19
 
 
20
Copyright 1998-2011 by Neil Hodgson <neilh@scintilla.org>
 
21
 
 
22
All Rights Reserved
 
23
 
 
24
Permission to use, copy, modify, and distribute this software and its
 
25
documentation for any purpose and without fee is hereby granted,
 
26
provided that the above copyright notice appear in all copies and that
 
27
both that copyright notice and this permission notice appear in
 
28
supporting documentation.
 
29
 
 
30
NEIL HODGSON DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
 
31
SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
 
32
AND FITNESS, IN NO EVENT SHALL NEIL HODGSON BE LIABLE FOR ANY
 
33
SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 
34
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
 
35
WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
 
36
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE
 
37
OR PERFORMANCE OF THIS SOFTWARE.
 
38
*/
 
39
 
 
40
#include "precomp.h"
 
41
 
 
42
#include "wx/stedit/stedit.h"    // for wxSTEEditorPrefs/Styles/Langs
 
43
#include "wx/stedit/steexprt.h"
 
44
#include "wx/stedit/steart.h"
 
45
#include "stedlgs_wdr.h"
 
46
 
 
47
#include <wx/filesys.h>
 
48
 
 
49
// ----------------------------------------------------------------------------
 
50
// The code below is copied to avoid having to include the Scintilla headers
 
51
// which are not copied when installing the wxWidgets library
 
52
 
 
53
// ----------------------------------------------------------------------------
 
54
//#include "../../contrib/src/stc/scintilla/include/Platform.h" // for PRectangle & Point
 
55
 
 
56
// PRectangle used for pageMargin, see below, only uses the variables as is
 
57
//   we just dumb it down to it's simplest form
 
58
class PRRectangle
 
59
{
 
60
public:
 
61
    PRRectangle() : left(0), right(0), top(0), bottom(0) {}
 
62
    int left, right, top, bottom;
 
63
};
 
64
 
 
65
// ----------------------------------------------------------------------------
 
66
//#include "../../contrib/src/stc/scintilla/include/SString.h"  // for SString
 
67
 
 
68
// Turn off warnings generated from MSVC's buggy std:: lib header files.
 
69
#if defined(__VISUALC__)
 
70
    #include <yvals.h>
 
71
    #pragma warning(disable: 4018)  // signed/unsigned mismatch
 
72
    #pragma warning(disable: 4100)  // unreferenced formal parameter
 
73
    #pragma warning(disable: 4146)  // unary minus operator applied to unsigned type,
 
74
                                    // result still unsigned
 
75
    #pragma warning(disable: 4244)  // 'conversion' conversion from 'type1' to 'type2',
 
76
                                    // possible loss of data
 
77
    #pragma warning(disable: 4245)  // conversion from 'type1' to 'type2', signed/unsigned
 
78
                                    // mismatch
 
79
    #pragma warning(disable: 4511)  // 'class' : copy constructor could not be generated
 
80
    #pragma warning(disable: 4512)  // 'class' : assignment operator could not be generated
 
81
    #pragma warning(disable: 4663)  // C++ language change: to explicitly specialize class
 
82
                                    // template 'vector'
 
83
    #pragma warning(disable: 4710)  // 'function' : function not inlined
 
84
    #pragma warning(disable: 4786)  // identifier was truncated to 'number' characters
 
85
#endif // defined(__VISUALC__)
 
86
 
 
87
// We can just typedef SString to std::string
 
88
#include <string>
 
89
//using namespace std;
 
90
typedef std::string SString;
 
91
 
 
92
 
 
93
// These functions in wxWidgets/contrib/src/stc/scintilla/src/PropSet.cxx
 
94
inline char MakeUpperCase_(char ch) {
 
95
        if (ch < 'a' || ch > 'z')
 
96
                return ch;
 
97
        else
 
98
                return static_cast<char>(ch - 'a' + 'A');
 
99
}
 
100
int CompareCaseInsensitive_(const char *a, const char *b) {
 
101
        while (*a && *b) {
 
102
                if (*a != *b) {
 
103
                        char upperA = MakeUpperCase_(*a);
 
104
                        char upperB = MakeUpperCase_(*b);
 
105
                        if (upperA != upperB)
 
106
                                return upperA - upperB;
 
107
                }
 
108
                a++;
 
109
                b++;
 
110
        }
 
111
        // Either *a or *b is nul
 
112
        return *a - *b;
 
113
}
 
114
bool EqualCaseInsensitive_(const char *a, const char *b) {
 
115
    return 0 == CompareCaseInsensitive_(a, b);
 
116
}
 
117
 
 
118
// end copied code from Scintilla
 
119
// ----------------------------------------------------------------------------
 
120
 
 
121
wxSTEditorExporter::wxSTEditorExporter(wxSTEditor* editor)
 
122
{
 
123
    wxCHECK_RET(editor, wxT("Invalid editor"));
 
124
    m_editor    = editor;
 
125
    m_stePrefs  = editor->GetEditorPrefs();
 
126
    m_steStyles = editor->GetEditorStyles();
 
127
    m_steLangs  = editor->GetEditorLangs();
 
128
 
 
129
    // we need something... just create them
 
130
    if (!m_stePrefs.IsOk())  m_stePrefs.Create();
 
131
    if (!m_steStyles.IsOk()) m_steStyles.Create();
 
132
    if (!m_steLangs.IsOk())  m_steLangs.Create();
 
133
}
 
134
 
 
135
bool wxSTEditorExporter::ExportToFile(int file_format, const wxFileName& fileName,
 
136
                                      bool overwrite_prompt, bool msg_on_error)
 
137
{
 
138
    wxCHECK_MSG(m_editor, false, wxT("Invalid editor"));
 
139
 
 
140
    if (overwrite_prompt && fileName.FileExists())
 
141
    {
 
142
        int overw = wxMessageBox(wxString::Format(_("Overwrite file : '%s'?\n"),
 
143
                                    fileName.GetFullPath().wx_str()),
 
144
                           _("Export error"),
 
145
                           wxOK|wxCANCEL|wxCENTRE|wxICON_QUESTION, m_editor);
 
146
 
 
147
        if (overw == wxCANCEL)
 
148
            return false;
 
149
    }
 
150
 
 
151
    bool ret = false;
 
152
 
 
153
    switch (file_format)
 
154
    {
 
155
        case STE_EXPORT_HTML    : ret = SaveToHTML(fileName);    break;
 
156
        case STE_EXPORT_HTMLCSS : ret = SaveToHTMLCSS(fileName); break;
 
157
        case STE_EXPORT_PDF     : ret = SaveToPDF(fileName);     break;
 
158
        case STE_EXPORT_RTF     : ret = SaveToRTF(fileName);     break;
 
159
        case STE_EXPORT_TEX     : ret = SaveToTEX(fileName);     break;
 
160
        case STE_EXPORT_XML     : ret = SaveToXML(fileName);     break;
 
161
        default : break;
 
162
    }
 
163
 
 
164
    if (!ret && msg_on_error)
 
165
    {
 
166
        wxMessageBox(wxString::Format(_("Unable to export to file : '%s'.\n"),
 
167
                           fileName.GetFullPath().wx_str()),
 
168
                     _("Export error"),
 
169
                     wxOK|wxCENTRE|wxICON_ERROR, m_editor);
 
170
    }
 
171
 
 
172
    return ret;
 
173
}
 
174
 
 
175
wxString wxSTEditorExporter::GetExtension(int file_format)
 
176
{
 
177
    switch (file_format)
 
178
    {
 
179
        case STE_EXPORT_HTML    :
 
180
        case STE_EXPORT_HTMLCSS : return wxT("html");
 
181
        case STE_EXPORT_PDF     : return wxT("pdf");
 
182
        case STE_EXPORT_RTF     : return wxT("rtf");
 
183
        case STE_EXPORT_TEX     : return wxT("tex");
 
184
        case STE_EXPORT_XML     : return wxT("xml");
 
185
        default : break;
 
186
    }
 
187
 
 
188
    return wxEmptyString;
 
189
}
 
190
 
 
191
wxString wxSTEditorExporter::GetWildcards(int file_format)
 
192
{
 
193
    switch (file_format)
 
194
    {
 
195
        case STE_EXPORT_HTML    :
 
196
        case STE_EXPORT_HTMLCSS : return wxT("HTML (html,htm)|*.html;*.htm");
 
197
        case STE_EXPORT_PDF     : return wxT("PDF (pdf)|*.pdf");
 
198
        case STE_EXPORT_RTF     : return wxT("RTF (rtf)|*.rtf");
 
199
        case STE_EXPORT_TEX     : return wxT("LaTex (tex)|*.tex");
 
200
        case STE_EXPORT_XML     : return wxT("XML (xml)|*.xml");
 
201
        default : break;
 
202
    }
 
203
 
 
204
    return wxFileSelectorDefaultWildcardStr;
 
205
}
 
206
 
 
207
int wxSTEditorExporter::SciToSTEStyle(int sci_style) const
 
208
{
 
209
    int ste_lang_n = m_editor->GetLanguageId();
 
210
    int ste_style  = m_steLangs.SciToSTEStyle(ste_lang_n, sci_style);
 
211
 
 
212
    return ste_style >= 0 ? ste_style : STE_STYLE_DEFAULT;
 
213
}
 
214
 
 
215
// SciTE - Scintilla based Text Editor
 
216
/** @file Exporters.cxx
 
217
 ** Export the current document to various markup languages.
 
218
 **/
 
219
// Copyright 1998-2011 by Neil Hodgson <neilh@scintilla.org>
 
220
// The License.txt file describes the conditions under which this software may be distributed.
 
221
 
 
222
#include <stdlib.h>
 
223
#include <string.h>
 
224
#include <ctype.h>
 
225
#include <stdio.h>
 
226
#include <fcntl.h>
 
227
#include <time.h>
 
228
 
 
229
// Some compatibility defines to simplify transition
 
230
#define STYLE_DEFAULT           wxSTC_STYLE_DEFAULT
 
231
#define STYLE_MAX               wxSTC_STYLE_MAX
 
232
#define STYLE_LASTPREDEFINED    wxSTC_STYLE_LASTPREDEFINED
 
233
#define SC_FOLDLEVELNUMBERMASK  wxSTC_FOLDLEVELNUMBERMASK
 
234
#define SC_FOLDLEVELBASE        wxSTC_FOLDLEVELBASE
 
235
#define SC_FOLDLEVELHEADERFLAG  wxSTC_FOLDLEVELHEADERFLAG
 
236
 
 
237
// From scite/src/SciTEBase.h/cxx copied here to allow for fewer changes below
 
238
class StyleDefinition {
 
239
public:
 
240
        SString font;
 
241
        int size;
 
242
        SString fore;
 
243
        SString back;
 
244
        bool bold;
 
245
        bool italics;
 
246
        bool eolfilled;
 
247
        bool underlined;
 
248
        int  caseForce;
 
249
        bool visible;
 
250
        bool changeable;
 
251
        enum flags { sdNone = 0, sdFont = 0x1, sdSize = 0x2, sdFore = 0x4, sdBack = 0x8,
 
252
                     sdBold = 0x10, sdItalics = 0x20, sdEOLFilled = 0x40, sdUnderlined = 0x80,
 
253
                     sdCaseForce = 0x100, sdVisible = 0x200, sdChangeable = 0x400} specified;
 
254
        StyleDefinition() {}
 
255
        StyleDefinition(const wxSTEditorStyles& styles, int ste_style)
 
256
            { Create(styles, ste_style); }
 
257
        void Create(const wxSTEditorStyles& styles, int ste_style);
 
258
        //bool ParseStyleDefinition(const char *definition);
 
259
        //long ForeAsLong() const;
 
260
        //long BackAsLong() const;
 
261
};
 
262
 
 
263
void StyleDefinition::Create(const wxSTEditorStyles& styles, int ste_style)
 
264
{
 
265
    wxCHECK_RET(styles.IsOk(), wxT("Invalid styles"));
 
266
    font       = wx2stc(styles.GetFaceName(ste_style));
 
267
    size       = styles.GetSize(ste_style);
 
268
    fore       = wx2stc(wxString::Format(wxT("#%06X"), styles.GetForegroundColourInt(ste_style)));
 
269
    back       = wx2stc(wxString::Format(wxT("#%06X"), styles.GetBackgroundColourInt(ste_style)));
 
270
    bold       = styles.GetBold(ste_style);
 
271
    italics    = styles.GetItalic(ste_style);
 
272
    eolfilled  = styles.GetEOLFilled(ste_style);
 
273
    underlined = styles.GetUnderlined(ste_style);
 
274
    caseForce  = styles.GetCase(ste_style);
 
275
    visible    = !styles.GetHidden(ste_style);
 
276
    changeable = true;
 
277
 
 
278
    int specified_ = sdNone;
 
279
    specified_ |= styles.GetUsesDefault(ste_style, STE_STYLE_USEDEFAULT_FACENAME)   ? 0 : sdFont;
 
280
    specified_ |= styles.GetUsesDefault(ste_style, STE_STYLE_USEDEFAULT_FONTSIZE)   ? 0 : sdSize;
 
281
    specified_ |= styles.GetUsesDefault(ste_style, STE_STYLE_USEDEFAULT_FORECOLOUR) ? 0 : sdFore;
 
282
    specified_ |= styles.GetUsesDefault(ste_style, STE_STYLE_USEDEFAULT_BACKCOLOUR) ? 0 : sdBack;
 
283
    specified_ |= styles.GetUsesDefault(ste_style, STE_STYLE_USEDEFAULT_FONTSTYLE)  ? 0 : sdBold|sdItalics|sdEOLFilled|sdUnderlined|sdCaseForce|sdVisible;
 
284
    specified = flags(specified_);
 
285
}
 
286
 
 
287
int IntFromHexDigit(int ch) {
 
288
        if ((ch >= '0') && (ch <= '9')) {
 
289
                return ch - '0';
 
290
        } else if (ch >= 'A' && ch <= 'F') {
 
291
                return ch - 'A' + 10;
 
292
        } else if (ch >= 'a' && ch <= 'f') {
 
293
                return ch - 'a' + 10;
 
294
        } else {
 
295
                return 0;
 
296
        }
 
297
}
 
298
 
 
299
int IntFromHexByte(const char *hexByte) {
 
300
        return IntFromHexDigit(hexByte[0]) * 16 + IntFromHexDigit(hexByte[1]);
 
301
}
 
302
 
 
303
//---------- Save to RTF ----------
 
304
 
 
305
#define RTF_HEADEROPEN "{\\rtf1\\ansi\\deff0\\deftab720"
 
306
#define RTF_FONTDEFOPEN "{\\fonttbl"
 
307
#define RTF_FONTDEF "{\\f%d\\fnil\\fcharset%u %s;}"
 
308
#define RTF_FONTDEFCLOSE "}"
 
309
#define RTF_COLORDEFOPEN "{\\colortbl"
 
310
#define RTF_COLORDEF "\\red%d\\green%d\\blue%d;"
 
311
#define RTF_COLORDEFCLOSE "}"
 
312
#define RTF_HEADERCLOSE "\n"
 
313
#define RTF_BODYOPEN ""
 
314
#define RTF_BODYCLOSE "}"
 
315
 
 
316
#define RTF_SETFONTFACE "\\f"
 
317
#define RTF_SETFONTSIZE "\\fs"
 
318
#define RTF_SETCOLOR "\\cf"
 
319
#define RTF_SETBACKGROUND "\\highlight"
 
320
#define RTF_BOLD_ON "\\b"
 
321
#define RTF_BOLD_OFF "\\b0"
 
322
#define RTF_ITALIC_ON "\\i"
 
323
#define RTF_ITALIC_OFF "\\i0"
 
324
#define RTF_UNDERLINE_ON "\\ul"
 
325
#define RTF_UNDERLINE_OFF "\\ulnone"
 
326
#define RTF_STRIKE_ON "\\i"
 
327
#define RTF_STRIKE_OFF "\\strike0"
 
328
 
 
329
#define RTF_EOLN "\\par\n"
 
330
#define RTF_TAB "\\tab "
 
331
 
 
332
#define MAX_STYLEDEF 128
 
333
#define MAX_FONTDEF 64
 
334
#define MAX_COLORDEF 8
 
335
#define RTF_FONTFACE "Courier New"
 
336
#define RTF_COLOR "#000000"
 
337
 
 
338
// extract the next RTF control word from *style
 
339
void GetRTFNextControl(char **style, char *control) {
 
340
    ptrdiff_t len;
 
341
    char *pos = *style;
 
342
    *control = '\0';
 
343
    if ('\0' == *pos) return;
 
344
    pos++; // implicit skip over leading '\'
 
345
    while ('\0' != *pos && '\\' != *pos) { pos++; }
 
346
    len = pos - *style;
 
347
    memcpy(control, *style, len);
 
348
    *(control + len) = '\0';
 
349
    *style = pos;
 
350
}
 
351
 
 
352
// extracts control words that are different between two styles
 
353
void GetRTFStyleChange(char *delta, char *last, char *current) { // \f0\fs20\cf0\highlight0\b0\i0
 
354
    char lastControl[MAX_STYLEDEF], currentControl[MAX_STYLEDEF];
 
355
    char *lastPos = last;
 
356
    char *currentPos = current;
 
357
    *delta = '\0';
 
358
    // font face, size, color, background, bold, italic
 
359
    for (int i = 0; i < 6; i++) {
 
360
        GetRTFNextControl(&lastPos, lastControl);
 
361
        GetRTFNextControl(&currentPos, currentControl);
 
362
        if (strcmp(lastControl, currentControl)) {  // changed
 
363
            strcat(delta, currentControl);
 
364
        }
 
365
    }
 
366
    if ('\0' != *delta) { strcat(delta, " "); }
 
367
    strcpy(last, current);
 
368
}
 
369
 
 
370
bool wxSTEditorExporter::SaveToRTF(const wxFileName& saveName, int start, int end)
 
371
{
 
372
    wxCHECK_MSG(m_editor, false, wxT("Invalid editor"));
 
373
    wxBusyCursor busy;
 
374
 
 
375
    int lengthDoc = m_editor->GetLength(); //LengthDocument();
 
376
    if (end < 0)
 
377
        end = lengthDoc;
 
378
 
 
379
    //RemoveFindMarks();
 
380
    m_editor->Colourise(0, -1); // wEditor.Call(SCI_COLOURISE, 0, -1);
 
381
 
 
382
    // Read the default settings
 
383
    //char key[200];
 
384
    //sprintf(key, "style.*.%0d", STYLE_DEFAULT);
 
385
    //char *valdefDefault = StringDup(props.GetExpanded(key).c_str());
 
386
    //sprintf(key, "style.%s.%0d", language.c_str(), STYLE_DEFAULT);
 
387
    //char *valDefault = StringDup(props.GetExpanded(key).c_str());
 
388
 
 
389
    StyleDefinition defaultStyle(m_steStyles, STE_STYLE_DEFAULT);
 
390
    //defaultStyle.ParseStyleDefinition(val);
 
391
 
 
392
    //if (val) delete []valDefault;
 
393
    //if (valdef) delete []valdefDefault;
 
394
 
 
395
    int tabSize = m_editor->GetTabWidth(); //props.GetInt("export.rtf.tabsize", props.GetInt("tabsize"));
 
396
    int wysiwyg = 1;                       //props.GetInt("export.rtf.wysiwyg", 1);
 
397
    SString fontFace = defaultStyle.font;  //props.GetExpanded("export.rtf.font.face");
 
398
    if (fontFace.length()) {
 
399
        defaultStyle.font = fontFace;
 
400
    } else if (defaultStyle.font.length() == 0) {
 
401
        defaultStyle.font = RTF_FONTFACE;
 
402
    }
 
403
    int fontSize = defaultStyle.size;       //props.GetInt("export.rtf.font.size", 0);
 
404
    if (fontSize > 0) {
 
405
        defaultStyle.size = fontSize << 1;
 
406
    } else if (defaultStyle.size == 0) {
 
407
        defaultStyle.size = 10 << 1;
 
408
    } else {
 
409
        defaultStyle.size <<= 1;
 
410
    }
 
411
    unsigned int characterset = wxSTC_CHARSET_DEFAULT; //props.GetInt("character.set", SC_CHARSET_DEFAULT);
 
412
    int tabs = m_editor->GetUseTabs();                 //props.GetInt("export.rtf.tabs", 0);
 
413
    if (tabSize == 0)
 
414
        tabSize = 4;
 
415
 
 
416
    FILE *fp = wxFopen(saveName.GetFullPath(), wxT("wt"));
 
417
    if (fp) {
 
418
        char styles[STYLE_DEFAULT + 1][MAX_STYLEDEF];
 
419
        char fonts[STYLE_DEFAULT + 1][MAX_FONTDEF];
 
420
        char colors[STYLE_DEFAULT + 1][MAX_COLORDEF];
 
421
        char lastStyle[MAX_STYLEDEF], deltaStyle[MAX_STYLEDEF];
 
422
        int fontCount = 1, colorCount = 2, i;
 
423
        fputs(RTF_HEADEROPEN RTF_FONTDEFOPEN, fp);
 
424
        strncpy(fonts[0], defaultStyle.font.c_str(), MAX_FONTDEF);
 
425
        fprintf(fp, RTF_FONTDEF, 0, characterset, defaultStyle.font.c_str());
 
426
        strncpy(colors[0], defaultStyle.fore.c_str(), MAX_COLORDEF);
 
427
        strncpy(colors[1], defaultStyle.back.c_str(), MAX_COLORDEF);
 
428
 
 
429
        for (int istyle = 0; istyle < STYLE_DEFAULT; istyle++) {
 
430
            //sprintf(key, "style.*.%0d", istyle);
 
431
            //char *valdef = StringDup(props.GetExpanded(key).c_str());
 
432
            //sprintf(key, "style.%s.%0d", language.c_str(), istyle);
 
433
            //char *val = StringDup(props.GetExpanded(key).c_str());
 
434
 
 
435
            StyleDefinition sd(m_steStyles, SciToSTEStyle(istyle));
 
436
            //sd.ParseStyleDefinition(val);
 
437
 
 
438
            if (sd.specified != StyleDefinition::sdNone) {
 
439
                if (wysiwyg && sd.font.length()) {
 
440
                    for (i = 0; i < fontCount; i++)
 
441
                        if (EqualCaseInsensitive_(sd.font.c_str(), fonts[i]))
 
442
                            break;
 
443
                    if (i >= fontCount) {
 
444
                        strncpy(fonts[fontCount++], sd.font.c_str(), MAX_FONTDEF);
 
445
                        fprintf(fp, RTF_FONTDEF, i, characterset, sd.font.c_str());
 
446
                    }
 
447
                    sprintf(lastStyle, RTF_SETFONTFACE "%d", i);
 
448
                } else {
 
449
                    strcpy(lastStyle, RTF_SETFONTFACE "0");
 
450
                }
 
451
 
 
452
                sprintf(lastStyle + strlen(lastStyle), RTF_SETFONTSIZE "%d",
 
453
                        wysiwyg && sd.size ? sd.size << 1 : defaultStyle.size);
 
454
 
 
455
                if (sd.specified & StyleDefinition::sdFore) {
 
456
                    for (i = 0; i < colorCount; i++)
 
457
                        if (EqualCaseInsensitive_(sd.fore.c_str(), colors[i]))
 
458
                            break;
 
459
                    if (i >= colorCount)
 
460
                        strncpy(colors[colorCount++], sd.fore.c_str(), MAX_COLORDEF);
 
461
                    sprintf(lastStyle + strlen(lastStyle), RTF_SETCOLOR "%d", i);
 
462
                } else {
 
463
                    strcat(lastStyle, RTF_SETCOLOR "0");    // Default fore
 
464
                }
 
465
 
 
466
                // PL: highlights doesn't seems to follow a distinct table, at least with WordPad and Word 97
 
467
                // Perhaps it is different for Word 6?
 
468
//              sprintf(lastStyle + strlen(lastStyle), RTF_SETBACKGROUND "%d",
 
469
//                      sd.back.length() ? GetRTFHighlight(sd.back.c_str()) : 0);
 
470
                if (sd.specified & StyleDefinition::sdBack) {
 
471
                    for (i = 0; i < colorCount; i++)
 
472
                        if (EqualCaseInsensitive_(sd.back.c_str(), colors[i]))
 
473
                            break;
 
474
                    if (i >= colorCount)
 
475
                        strncpy(colors[colorCount++], sd.back.c_str(), MAX_COLORDEF);
 
476
                    sprintf(lastStyle + strlen(lastStyle), RTF_SETBACKGROUND "%d", i);
 
477
                } else {
 
478
                    strcat(lastStyle, RTF_SETBACKGROUND "1");   // Default back
 
479
                }
 
480
                if (sd.specified & StyleDefinition::sdBold) {
 
481
                    strcat(lastStyle, sd.bold ? RTF_BOLD_ON : RTF_BOLD_OFF);
 
482
                } else {
 
483
                    strcat(lastStyle, defaultStyle.bold ? RTF_BOLD_ON : RTF_BOLD_OFF);
 
484
                }
 
485
                if (sd.specified & StyleDefinition::sdItalics) {
 
486
                    strcat(lastStyle, sd.italics ? RTF_ITALIC_ON : RTF_ITALIC_OFF);
 
487
                } else {
 
488
                    strcat(lastStyle, defaultStyle.italics ? RTF_ITALIC_ON : RTF_ITALIC_OFF);
 
489
                }
 
490
                strncpy(styles[istyle], lastStyle, MAX_STYLEDEF);
 
491
            } else {
 
492
                sprintf(styles[istyle], RTF_SETFONTFACE "0" RTF_SETFONTSIZE "%d"
 
493
                        RTF_SETCOLOR "0" RTF_SETBACKGROUND "1"
 
494
                        RTF_BOLD_OFF RTF_ITALIC_OFF, defaultStyle.size);
 
495
            }
 
496
            // delete []val;
 
497
            // delete []valdef;
 
498
        }
 
499
        fputs(RTF_FONTDEFCLOSE RTF_COLORDEFOPEN, fp);
 
500
        for (i = 0; i < colorCount; i++) {
 
501
            fprintf(fp, RTF_COLORDEF, IntFromHexByte(colors[i] + 1),
 
502
                    IntFromHexByte(colors[i] + 3), IntFromHexByte(colors[i] + 5));
 
503
        }
 
504
        fprintf(fp, RTF_COLORDEFCLOSE RTF_HEADERCLOSE RTF_BODYOPEN RTF_SETFONTFACE "0"
 
505
                RTF_SETFONTSIZE "%d" RTF_SETCOLOR "0 ", defaultStyle.size);
 
506
        sprintf(lastStyle, RTF_SETFONTFACE "0" RTF_SETFONTSIZE "%d"
 
507
                RTF_SETCOLOR "0" RTF_SETBACKGROUND "1"
 
508
                RTF_BOLD_OFF RTF_ITALIC_OFF, defaultStyle.size);
 
509
        bool prevCR = false;
 
510
        int styleCurrent = -1;
 
511
        //WindowAccessor acc(wEditor.GetID(), props);
 
512
        int column = 0;
 
513
        for (i = start; i < end; i++) {
 
514
            char ch = (char)m_editor->GetCharAt(i); //acc[i];
 
515
            int style = m_editor->GetStyleAt(i);    //acc.StyleAt(i);
 
516
            if (style > STYLE_DEFAULT)
 
517
                style = 0;
 
518
            if (style != styleCurrent) {
 
519
                GetRTFStyleChange(deltaStyle, lastStyle, styles[style]);
 
520
                if (*deltaStyle)
 
521
                    fputs(deltaStyle, fp);
 
522
                styleCurrent = style;
 
523
            }
 
524
            if (ch == '{')
 
525
                fputs("\\{", fp);
 
526
            else if (ch == '}')
 
527
                fputs("\\}", fp);
 
528
            else if (ch == '\\')
 
529
                fputs("\\\\", fp);
 
530
            else if (ch == '\t') {
 
531
                if (tabs) {
 
532
                    fputs(RTF_TAB, fp);
 
533
                } else {
 
534
                    int ts = tabSize - (column % tabSize);
 
535
                    for (int itab = 0; itab < ts; itab++) {
 
536
                        fputc(' ', fp);
 
537
                    }
 
538
                    column += ts - 1;
 
539
                }
 
540
            } else if (ch == '\n') {
 
541
                if (!prevCR) {
 
542
                    fputs(RTF_EOLN, fp);
 
543
                    column = -1;
 
544
                }
 
545
            } else if (ch == '\r') {
 
546
                fputs(RTF_EOLN, fp);
 
547
                column = -1;
 
548
            } else
 
549
                fputc(ch, fp);
 
550
            column++;
 
551
            prevCR = ch == '\r';
 
552
        }
 
553
        fputs(RTF_BODYCLOSE, fp);
 
554
        fclose(fp);
 
555
    } else {
 
556
        return false;
 
557
        //FIMXE SString msg = LocaliseMessage("Could not save file '^0'.", filePath.AsFileSystem());
 
558
        //WindowMessageBox(wSciTE, msg, MB_OK | MB_ICONWARNING);
 
559
    }
 
560
    return true;
 
561
}
 
562
 
 
563
 
 
564
//---------- Save to HTML ----------
 
565
 
 
566
bool wxSTEditorExporter::SaveToHTMLCSS(const wxFileName& saveName)
 
567
{
 
568
    wxCHECK_MSG(m_editor, false, wxT("Invalid editor"));
 
569
    wxBusyCursor busy;
 
570
 
 
571
    //RemoveFindMarks();
 
572
    m_editor->Colourise(0, -1);             //SendEditor(SCI_COLOURISE, 0, -1);
 
573
    int tabSize = m_editor->GetTabWidth();  //props.GetInt("tabsize");
 
574
    if (tabSize == 0)
 
575
        tabSize = 4;
 
576
    int wysiwyg = 1;                        //props.GetInt("export.html.wysiwyg", 1);
 
577
    int tabs = m_editor->GetUseTabs();      //props.GetInt("export.html.tabs", 0);
 
578
    int folding = 0;                        //props.GetInt("export.html.folding", 0);
 
579
    int onlyStylesUsed = 0;                 //props.GetInt("export.html.styleused", 0);
 
580
    int titleFullPath = 0;                  //props.GetInt("export.html.title.fullpath", 0);
 
581
 
 
582
    int lengthDoc = m_editor->GetLength();  //LengthDocument();
 
583
    //WindowAccessor acc(wEditor.GetID(), props);
 
584
 
 
585
    bool styleIsUsed[STYLE_MAX + 1];
 
586
    if (onlyStylesUsed) {
 
587
        int i;
 
588
        for (i = 0; i <= STYLE_MAX; i++) {
 
589
            styleIsUsed[i] = false;
 
590
        }
 
591
        // check the used styles
 
592
        for (i = 0; i < lengthDoc; i++) {
 
593
            styleIsUsed[m_editor->GetStyleAt(i) & 0x7F] = true;
 
594
        }
 
595
    } else {
 
596
        for (int i = 0; i <= STYLE_MAX; i++) {
 
597
            styleIsUsed[i] = true;
 
598
        }
 
599
    }
 
600
    styleIsUsed[STYLE_DEFAULT] = true;
 
601
 
 
602
    FILE *fp = wxFopen(saveName.GetFullPath(), wxT("wt"));
 
603
    if (fp) {
 
604
        fputs("<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n", fp);
 
605
        fputs("<html xmlns=\"http://www.w3.org/1999/xhtml\">\n", fp);
 
606
        fputs("<head>\n", fp);
 
607
        if (titleFullPath)
 
608
            fprintf(fp, "<title>%s</title>\n",
 
609
                static_cast<const char *>(wx2stc(wxFileSystem::FileNameToURL(saveName)))); //FIXME filePath.AsFileSystem()));
 
610
        else
 
611
            fprintf(fp, "<title>%s</title>\n",
 
612
                static_cast<const char *>(wx2stc(wxFileSystem::FileNameToURL(wxFileName(saveName).GetFullName())))); //FIXME filePath.Name().AsFileSystem()));
 
613
        // Probably not used by robots, but making a little advertisement for those looking
 
614
        // at the source code doesn't hurt...
 
615
                fputs("<meta name=\"Generator\" content=\"SciTE - www.Scintilla.org\" />\n", fp);
 
616
        if (m_editor->GetCodePage() == wxSTC_CP_UTF8)
 
617
            fputs("<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />\n", fp);
 
618
 
 
619
        if (folding) {
 
620
                        fputs("<script language=\"JavaScript\" type=\"text/javascript\">\n"
 
621
                              "<!--\n"
 
622
                              "function symbol(id, sym) {\n"
 
623
                              " if (id.textContent==undefined) {\n"
 
624
                              " id.innerText=sym; } else {\n"
 
625
                              " id.textContent=sym; }\n"
 
626
                              "}\n"
 
627
                              "function toggle(id) {\n"
 
628
                              "var thislayer=document.getElementById('ln'+id);\n"
 
629
                              "id-=1;\n"
 
630
                              "var togline=document.getElementById('hd'+id);\n"
 
631
                              "var togsym=document.getElementById('bt'+id);\n"
 
632
                              "if (thislayer.style.display == 'none') {\n"
 
633
                              " thislayer.style.display='block';\n"
 
634
                              " togline.style.textDecoration='none';\n"
 
635
                              " symbol(togsym,'- ');\n"
 
636
                              "} else {\n"
 
637
                              " thislayer.style.display='none';\n"
 
638
                              " togline.style.textDecoration='underline';\n"
 
639
                              " symbol(togsym,'+ ');\n"
 
640
                              "}\n"
 
641
                              "}\n"
 
642
                              "//-->\n"
 
643
                              "</script>\n", fp);
 
644
                }
 
645
 
 
646
        fputs("<style type=\"text/css\">\n", fp);
 
647
 
 
648
        SString bgColour;
 
649
        StyleDefinition sddef(m_steStyles, SciToSTEStyle(STE_STYLE_DEFAULT));
 
650
/*
 
651
        char key[200];
 
652
                sprintf(key, "style.*.%0d", STYLE_DEFAULT);
 
653
                char *valdef = StringDup(props.GetExpanded(key).c_str());
 
654
                sprintf(key, "style.%s.%0d", language.c_str(), STYLE_DEFAULT);
 
655
                char *val = StringDup(props.GetExpanded(key).c_str());
 
656
 
 
657
                StyleDefinition sddef(valdef);
 
658
                sddef.ParseStyleDefinition(val);
 
659
                if (sddef.back.length()) {
 
660
                        bgColour = sddef.back;
 
661
                }
 
662
                delete []val;
 
663
                delete []valdef;
 
664
*/
 
665
        for (int istyle = 0; istyle <= STYLE_MAX; istyle++) {
 
666
            if ((istyle > STYLE_DEFAULT) && (istyle <= STYLE_LASTPREDEFINED))
 
667
                continue;
 
668
            if (styleIsUsed[istyle]) {
 
669
                                //sprintf(key, "style.*.%0d", istyle);
 
670
                                //valdef = StringDup(props.GetExpanded(key).c_str());
 
671
                                //sprintf(key, "style.%s.%0d", language.c_str(), istyle);
 
672
                                //val = StringDup(props.GetExpanded(key).c_str());
 
673
 
 
674
                StyleDefinition sd(m_steStyles, SciToSTEStyle(istyle));
 
675
                //sd.ParseStyleDefinition(val);
 
676
 
 
677
                                //if (CurrentBuffer()->useMonoFont && sd.font.length() && sdmono.font.length()) {
 
678
                                //      sd.font = sdmono.font;
 
679
                                //      sd.size = sdmono.size;
 
680
                                //      sd.italics = sdmono.italics;
 
681
                                //      sd.weight = sdmono.weight;
 
682
                                //}
 
683
 
 
684
                if (sd.specified != StyleDefinition::sdNone) {
 
685
                    if (istyle == STYLE_DEFAULT) {
 
686
                        fprintf(fp, "span {\n");
 
687
                    } else {
 
688
                        fprintf(fp, ".S%0d {\n", istyle);
 
689
                    }
 
690
                    if (sd.italics) {
 
691
                        fprintf(fp, "\tfont-style: italic;\n");
 
692
                    }
 
693
                    if (sd.bold) {
 
694
                        fprintf(fp, "\tfont-weight: bold;\n");
 
695
                    }
 
696
                    if (wysiwyg && sd.font.length()) {
 
697
                        fprintf(fp, "\tfont-family: '%s';\n", sd.font.c_str());
 
698
                    }
 
699
                    if (sd.fore.length()) {
 
700
                        fprintf(fp, "\tcolor: %s;\n", sd.fore.c_str());
 
701
                    } else if (istyle == STYLE_DEFAULT) {
 
702
                        fprintf(fp, "\tcolor: #000000;\n");
 
703
                    }
 
704
                    if (sd.back.length()) {
 
705
                                                if (istyle != STYLE_DEFAULT && bgColour != sd.back) {
 
706
                                                        fprintf(fp, "\tbackground: %s;\n", sd.back.c_str());
 
707
                                                        fprintf(fp, "\ttext-decoration: inherit;\n");
 
708
                                                }
 
709
                                        }
 
710
                    if (wysiwyg && sd.size) {
 
711
                        fprintf(fp, "\tfont-size: %0dpt;\n", sd.size);
 
712
                    }
 
713
                    fprintf(fp, "}\n");
 
714
                } else {
 
715
                    styleIsUsed[istyle] = false;    // No definition, it uses default style (32)
 
716
                }
 
717
 
 
718
                // delete []val;
 
719
                // delete []valdef;
 
720
            }
 
721
        }
 
722
        fputs("</style>\n", fp);
 
723
        fputs("</head>\n", fp);
 
724
        if (bgColour.length() > 0)
 
725
            fprintf(fp, "<body bgcolor=\"%s\">\n", bgColour.c_str());
 
726
        else
 
727
            fputs("<body>\n", fp);
 
728
 
 
729
        int line = m_editor->LineFromPosition(0); // acc.GetLine(0);
 
730
        int level = (m_editor->GetFoldLevel(line) & SC_FOLDLEVELNUMBERMASK) - SC_FOLDLEVELBASE;
 
731
        int newLevel;
 
732
        int styleCurrent = m_editor->GetStyleAt(0);
 
733
        bool inStyleSpan = false;
 
734
        bool inFoldSpan = false;
 
735
        // Global span for default attributes
 
736
        if (wysiwyg) {
 
737
            fputs("<span>", fp);
 
738
        } else {
 
739
            fputs("<pre>", fp);
 
740
        }
 
741
 
 
742
        if (folding) {
 
743
            int lvl = m_editor->GetFoldLevel(0);
 
744
            level = (lvl & SC_FOLDLEVELNUMBERMASK) - SC_FOLDLEVELBASE;
 
745
 
 
746
                        if (lvl & SC_FOLDLEVELHEADERFLAG) {
 
747
                                fprintf(fp, "<span id=\"hd%d\" onclick=\"toggle('%d')\">", line, line + 1);
 
748
                                fprintf(fp, "<span id=\"bt%d\">- </span>", line);
 
749
                                inFoldSpan = true;
 
750
                        } else {
 
751
                                fputs("&nbsp; ", fp);
 
752
                        }
 
753
        }
 
754
 
 
755
        if (styleIsUsed[styleCurrent]) {
 
756
            fprintf(fp, "<span class=\"S%0d\">", styleCurrent);
 
757
            inStyleSpan = true;
 
758
        }
 
759
        // Else, this style has no definition (beside default one):
 
760
        // no span for it, except the global one
 
761
 
 
762
        int column = 0;
 
763
        for (int i = 0; i < lengthDoc; i++) {
 
764
            char ch = (char)m_editor->GetCharAt(i); // acc[i];
 
765
            int style = m_editor->GetStyleAt(i);
 
766
 
 
767
            if (style != styleCurrent) {
 
768
                if (inStyleSpan) {
 
769
                    fputs("</span>", fp);
 
770
                    inStyleSpan = false;
 
771
                }
 
772
                if (ch != '\r' && ch != '\n') { // No need of a span for the EOL
 
773
                    if (styleIsUsed[style]) {
 
774
                        fprintf(fp, "<span class=\"S%0d\">", style);
 
775
                        inStyleSpan = true;
 
776
                    }
 
777
                    styleCurrent = style;
 
778
                }
 
779
            }
 
780
            if (ch == ' ') {
 
781
                if (wysiwyg) {
 
782
                    char prevCh = '\0';
 
783
                    if (column == 0) {  // At start of line, must put a &nbsp; because regular space will be collapsed
 
784
                        prevCh = ' ';
 
785
                    }
 
786
                    while (i < lengthDoc && (char)m_editor->GetCharAt(i) == ' ') { //acc[i] == ' ') {
 
787
                        if (prevCh != ' ') {
 
788
                            fputc(' ', fp);
 
789
                        } else {
 
790
                            fputs("&nbsp;", fp);
 
791
                        }
 
792
                        prevCh = (char)m_editor->GetCharAt(i); //acc[i];
 
793
                        i++;
 
794
                        column++;
 
795
                    }
 
796
                    i--; // the last incrementation will be done by the for loop
 
797
                } else {
 
798
                    fputc(' ', fp);
 
799
                    column++;
 
800
                }
 
801
            } else if (ch == '\t') {
 
802
                int ts = tabSize - (column % tabSize);
 
803
                if (wysiwyg) {
 
804
                    for (int itab = 0; itab < ts; itab++) {
 
805
                        if (itab % 2) {
 
806
                            fputc(' ', fp);
 
807
                        } else {
 
808
                            fputs("&nbsp;", fp);
 
809
                        }
 
810
                    }
 
811
                    column += ts;
 
812
                } else {
 
813
                    if (tabs) {
 
814
                        fputc(ch, fp);
 
815
                        column++;
 
816
                    } else {
 
817
                        for (int itab = 0; itab < ts; itab++) {
 
818
                            fputc(' ', fp);
 
819
                        }
 
820
                        column += ts;
 
821
                    }
 
822
                }
 
823
            } else if (ch == '\r' || ch == '\n') {
 
824
                if (inStyleSpan) {
 
825
                    fputs("</span>", fp);
 
826
                    inStyleSpan = false;
 
827
                }
 
828
                                if (inFoldSpan) {
 
829
                                        fputs("</span>", fp);
 
830
                                        inFoldSpan = false;
 
831
                                }
 
832
                if (ch == '\r' && (char)m_editor->GetCharAt(i + 1) == '\n') {
 
833
                    i++;    // CR+LF line ending, skip the "extra" EOL char
 
834
                }
 
835
                column = 0;
 
836
                if (wysiwyg) {
 
837
                    fputs("<br />", fp);
 
838
                }
 
839
 
 
840
                styleCurrent = m_editor->GetStyleAt(i + 1);
 
841
                if (folding) {
 
842
                    line = m_editor->LineFromPosition(i + 1);
 
843
 
 
844
                    int lvl = m_editor->GetFoldLevel(line);
 
845
                    newLevel = (lvl & SC_FOLDLEVELNUMBERMASK) - SC_FOLDLEVELBASE;
 
846
 
 
847
                    if (newLevel < level)
 
848
                        fprintf(fp, "</span>");
 
849
                    fputc('\n', fp); // here to get clean code
 
850
                    if (newLevel > level)
 
851
                        fprintf(fp, "<span id=\"ln%d\">", line);
 
852
 
 
853
                                        if (lvl & SC_FOLDLEVELHEADERFLAG) {
 
854
                                                fprintf(fp, "<span id=\"hd%d\" onclick=\"toggle('%d')\">", line, line + 1);
 
855
                                                fprintf(fp, "<span id=\"bt%d\">- </span>", line);
 
856
                                                inFoldSpan = true;
 
857
                                        } else
 
858
                        fputs("&nbsp; ", fp);
 
859
                    level = newLevel;
 
860
                } else {
 
861
                    fputc('\n', fp);
 
862
                }
 
863
 
 
864
                if (styleIsUsed[styleCurrent] && (char)m_editor->GetCharAt(i + 1) != '\r' && (char)m_editor->GetCharAt(i + 1) != '\n') {
 
865
                    // We know it's the correct next style,
 
866
                    // but no (empty) span for an empty line
 
867
                    fprintf(fp, "<span class=\"S%0d\">", styleCurrent);
 
868
                    inStyleSpan = true;
 
869
                }
 
870
            } else {
 
871
                switch (ch) {
 
872
                case '<':
 
873
                    fputs("&lt;", fp);
 
874
                    break;
 
875
                case '>':
 
876
                    fputs("&gt;", fp);
 
877
                    break;
 
878
                case '&':
 
879
                    fputs("&amp;", fp);
 
880
                    break;
 
881
                default:
 
882
                    fputc(ch, fp);
 
883
                }
 
884
                column++;
 
885
            }
 
886
        }
 
887
 
 
888
        if (inStyleSpan) {
 
889
            fputs("</span>", fp);
 
890
        }
 
891
 
 
892
        if (folding) {
 
893
            while (level > 0) {
 
894
                fprintf(fp, "</span>");
 
895
                level--;
 
896
            }
 
897
        }
 
898
 
 
899
        if (!wysiwyg) {
 
900
            fputs("</pre>", fp);
 
901
        } else {
 
902
            fputs("</span>", fp);
 
903
        }
 
904
 
 
905
        fputs("\n</body>\n</html>\n", fp);
 
906
        fclose(fp);
 
907
    } else {
 
908
        return false;
 
909
        //FIXME SString msg = LocaliseMessage(
 
910
        //                  "Could not save file \"^0\".", filePath.AsFileSystem());
 
911
        //WindowMessageBox(wSciTE, msg, MB_OK | MB_ICONWARNING);
 
912
    }
 
913
    return true;
 
914
}
 
915
 
 
916
 
 
917
//---------- Save to PDF ----------
 
918
 
 
919
/*
 
920
    PDF Exporter. Status: Beta
 
921
    Contributed by Ahmad M. Zawawi <zeus_go64@hotmail.com>
 
922
    Modifications by Darren Schroeder Feb 22, 2003; Philippe Lhoste 2003-10
 
923
    Overhauled by Kein-Hong Man 2003-11
 
924
 
 
925
    This exporter is meant to be small and simple; users are expected to
 
926
    use other methods for heavy-duty formatting. PDF elements marked with
 
927
    "PDF1.4Ref" states where in the PDF 1.4 Reference Spec (the PDF file of
 
928
    which is freely available from Adobe) the particular element can be found.
 
929
 
 
930
    Possible TODOs that will probably not be implemented: full styling,
 
931
    optimization, font substitution, compression, character set encoding.
 
932
*/
 
933
#define PDF_TAB_DEFAULT     8
 
934
#define PDF_FONT_DEFAULT    1   // Helvetica
 
935
#define PDF_FONTSIZE_DEFAULT    10
 
936
#define PDF_SPACING_DEFAULT 1.2
 
937
#define PDF_HEIGHT_DEFAULT  792 // Letter
 
938
#define PDF_WIDTH_DEFAULT   612
 
939
#define PDF_MARGIN_DEFAULT  72  // 1.0"
 
940
#define PDF_ENCODING        "WinAnsiEncoding"
 
941
 
 
942
struct PDFStyle {
 
943
    char fore[24];
 
944
    int font;
 
945
};
 
946
 
 
947
static const char *PDFfontNames[] = {
 
948
    "Courier", "Courier-Bold", "Courier-Oblique", "Courier-BoldOblique",
 
949
    "Helvetica", "Helvetica-Bold", "Helvetica-Oblique", "Helvetica-BoldOblique",
 
950
    "Times-Roman", "Times-Bold", "Times-Italic", "Times-BoldItalic"
 
951
};
 
952
 
 
953
// ascender, descender aligns font origin point with page
 
954
static short PDFfontAscenders[] =  { 629, 718, 699 };
 
955
static short PDFfontDescenders[] = { 157, 207, 217 };
 
956
static short PDFfontWidths[] =     { 600,   0,   0 };
 
957
 
 
958
inline void getPDFRGB(char* pdfcolour, const char* stylecolour) {
 
959
    // grab colour components (max string length produced = 18)
 
960
    for (int i = 1; i < 6; i += 2) {
 
961
        char val[20];
 
962
        // 3 decimal places for enough dynamic range
 
963
        int c = (IntFromHexByte(stylecolour + i) * 1000 + 127) / 255;
 
964
        if (c == 0 || c == 1000) {  // optimise
 
965
            sprintf(val, "%d ", c / 1000);
 
966
        } else {
 
967
            sprintf(val, "0.%03d ", c);
 
968
        }
 
969
        strcat(pdfcolour, val);
 
970
    }
 
971
}
 
972
 
 
973
bool wxSTEditorExporter::SaveToPDF(const wxFileName& saveName)
 
974
{
 
975
    wxCHECK_MSG(m_editor, false, wxT("Invalid editor"));
 
976
    wxBusyCursor busy;
 
977
 
 
978
    // This class conveniently handles the tracking of PDF objects
 
979
    // so that the cross-reference table can be built (PDF1.4Ref(p39))
 
980
    // All writes to fp passes through a PDFObjectTracker object.
 
981
    class PDFObjectTracker {
 
982
    private:
 
983
        FILE *fp;
 
984
        long *offsetList, tableSize;
 
985
    public:
 
986
        int index;
 
987
        PDFObjectTracker(FILE *fp_) {
 
988
            fp = fp_;
 
989
            tableSize = 100;
 
990
            offsetList = new long[tableSize];
 
991
            index = 1;
 
992
        }
 
993
        ~PDFObjectTracker() {
 
994
            delete []offsetList;
 
995
        }
 
996
        void write(const char *objectData) {
 
997
            size_t length = strlen(objectData);
 
998
            // note binary write used, open with "wb"
 
999
            fwrite(objectData, sizeof(char), length, fp);
 
1000
        }
 
1001
        void write(int objectData) {
 
1002
            char val[20];
 
1003
            sprintf(val, "%d", objectData);
 
1004
            write(val);
 
1005
        }
 
1006
        // returns object number assigned to the supplied data
 
1007
        int add(const char *objectData) {
 
1008
            // resize xref offset table if too small
 
1009
            if (index > tableSize) {
 
1010
                long newSize = tableSize * 2;
 
1011
                long *newList = new long[newSize];
 
1012
                for (int i = 0; i < tableSize; i++) {
 
1013
                    newList[i] = offsetList[i];
 
1014
                }
 
1015
                delete []offsetList;
 
1016
                offsetList = newList;
 
1017
                tableSize = newSize;
 
1018
            }
 
1019
            // save offset, then format and write object
 
1020
            offsetList[index - 1] = ftell(fp);
 
1021
            write(index);
 
1022
            write(" 0 obj\n");
 
1023
            write(objectData);
 
1024
            write("endobj\n");
 
1025
            return index++;
 
1026
        }
 
1027
        // builds xref table, returns file offset of xref table
 
1028
        long xref() {
 
1029
            char val[32];
 
1030
            // xref start index and number of entries
 
1031
            long xrefStart = ftell(fp);
 
1032
            write("xref\n0 ");
 
1033
            write(index);
 
1034
            // a xref entry *must* be 20 bytes long (PDF1.4Ref(p64))
 
1035
            // so extra space added; also the first entry is special
 
1036
            write("\n0000000000 65535 f \n");
 
1037
            for (int i = 0; i < index - 1; i++) {
 
1038
                sprintf(val, "%010ld 00000 n \n", offsetList[i]);
 
1039
                write(val);
 
1040
            }
 
1041
            return xrefStart;
 
1042
        }
 
1043
    };
 
1044
 
 
1045
    // Object to manage line and page rendering. Apart from startPDF, endPDF
 
1046
    // everything goes in via add() and nextLine() so that line formatting
 
1047
    // and pagination can be done properly.
 
1048
    class PDFRender {
 
1049
    private:
 
1050
        bool pageStarted;
 
1051
        bool firstLine;
 
1052
        int pageCount;
 
1053
        int pageContentStart;
 
1054
        double xPos, yPos;  // position tracking for line wrapping
 
1055
        SString pageData;   // holds PDF stream contents
 
1056
        SString segment;    // character data
 
1057
        char *segStyle;     // style of segment
 
1058
        bool justWhiteSpace;
 
1059
        int styleCurrent, stylePrev;
 
1060
        double leading;
 
1061
        char *buffer;
 
1062
    public:
 
1063
        PDFObjectTracker *oT;
 
1064
        PDFStyle *style;
 
1065
        int fontSize;       // properties supplied by user
 
1066
        int fontSet;
 
1067
        long pageWidth, pageHeight;
 
1068
        PRRectangle pageMargin;  // see PRRectangle above for compatibility w/ Scintilla's PRectangle
 
1069
        //
 
1070
        PDFRender() {
 
1071
            pageStarted = false;
 
1072
            pageCount = 0;
 
1073
            style = NULL;
 
1074
            buffer = new char[250];
 
1075
            segStyle = new char[100];
 
1076
        }
 
1077
        ~PDFRender() {
 
1078
            delete []style;
 
1079
            delete []buffer;
 
1080
            delete []segStyle;
 
1081
        }
 
1082
        //
 
1083
        double fontToPoints(int thousandths) {
 
1084
            return (double)fontSize * thousandths / 1000.0;
 
1085
        }
 
1086
        void setStyle(char *buff, int style_) {
 
1087
            int styleNext = style_;
 
1088
            if (style_ == -1) { styleNext = styleCurrent; }
 
1089
            *buff = '\0';
 
1090
            if (styleNext != styleCurrent || style_ == -1) {
 
1091
                if (style[styleCurrent].font != style[styleNext].font
 
1092
                    || style_ == -1) {
 
1093
                    sprintf(buff, "/F%d %d Tf ",
 
1094
                        style[styleNext].font + 1, fontSize);
 
1095
                }
 
1096
                if (strcmp(style[styleCurrent].fore, style[styleNext].fore) != 0
 
1097
                    || style_ == -1) {
 
1098
                    strcat(buff, style[styleNext].fore);
 
1099
                    strcat(buff, "rg ");
 
1100
                }
 
1101
            }
 
1102
        }
 
1103
        //
 
1104
        void startPDF() {
 
1105
            if (fontSize <= 0) {
 
1106
                fontSize = PDF_FONTSIZE_DEFAULT;
 
1107
            }
 
1108
            // leading is the term for distance between lines
 
1109
            leading = fontSize * PDF_SPACING_DEFAULT;
 
1110
            // sanity check for page size and margins
 
1111
            int pageWidthMin = (int)leading + pageMargin.left + pageMargin.right;
 
1112
            if (pageWidth < pageWidthMin) {
 
1113
                pageWidth = pageWidthMin;
 
1114
            }
 
1115
            int pageHeightMin = (int)leading + pageMargin.top + pageMargin.bottom;
 
1116
            if (pageHeight < pageHeightMin) {
 
1117
                pageHeight = pageHeightMin;
 
1118
            }
 
1119
            // start to write PDF file here (PDF1.4Ref(p63))
 
1120
            // ASCII>127 characters to indicate binary-possible stream
 
1121
            oT->write("%PDF-1.3\n%ȬĻ¢\n");
 
1122
            styleCurrent = STYLE_DEFAULT;
 
1123
 
 
1124
            // build objects for font resources; note that font objects are
 
1125
            // *expected* to start from index 1 since they are the first objects
 
1126
            // to be inserted (PDF1.4Ref(p317))
 
1127
            for (int i = 0; i < 4; i++) {
 
1128
                sprintf(buffer, "<</Type/Font/Subtype/Type1"
 
1129
                        "/Name/F%d/BaseFont/%s/Encoding/"
 
1130
                        PDF_ENCODING
 
1131
                        ">>\n", i + 1,
 
1132
                        PDFfontNames[fontSet * 4 + i]);
 
1133
                oT->add(buffer);
 
1134
            }
 
1135
            pageContentStart = oT->index;
 
1136
        }
 
1137
        void endPDF() {
 
1138
            if (pageStarted) {  // flush buffers
 
1139
                endPage();
 
1140
            }
 
1141
            // refer to all used or unused fonts for simplicity
 
1142
            int resourceRef = oT->add(
 
1143
                "<</ProcSet[/PDF/Text]\n"
 
1144
                "/Font<</F1 1 0 R/F2 2 0 R/F3 3 0 R"
 
1145
                "/F4 4 0 R>> >>\n");
 
1146
            // create all the page objects (PDF1.4Ref(p88))
 
1147
            // forward reference pages object; calculate its object number
 
1148
            int pageObjectStart = oT->index;
 
1149
            int pagesRef = pageObjectStart + pageCount;
 
1150
            for (int i = 0; i < pageCount; i++) {
 
1151
                sprintf(buffer, "<</Type/Page/Parent %d 0 R\n"
 
1152
                        "/MediaBox[ 0 0 %ld %ld"
 
1153
                        "]\n/Contents %d 0 R\n"
 
1154
                        "/Resources %d 0 R\n>>\n",
 
1155
                        pagesRef, pageWidth, pageHeight,
 
1156
                        pageContentStart + i, resourceRef);
 
1157
                oT->add(buffer);
 
1158
            }
 
1159
            // create page tree object (PDF1.4Ref(p86))
 
1160
            pageData = "<</Type/Pages/Kids[\n";
 
1161
            for (int j = 0; j < pageCount; j++) {
 
1162
                sprintf(buffer, "%d 0 R\n", pageObjectStart + j);
 
1163
                pageData += buffer;
 
1164
            }
 
1165
            sprintf(buffer, "]/Count %d\n>>\n", pageCount);
 
1166
            pageData += buffer;
 
1167
            oT->add(pageData.c_str());
 
1168
            // create catalog object (PDF1.4Ref(p83))
 
1169
            sprintf(buffer, "<</Type/Catalog/Pages %d 0 R >>\n", pagesRef);
 
1170
            int catalogRef = oT->add(buffer);
 
1171
            // append the cross reference table (PDF1.4Ref(p64))
 
1172
            long xref = oT->xref();
 
1173
            // end the file with the trailer (PDF1.4Ref(p67))
 
1174
            sprintf(buffer, "trailer\n<< /Size %d /Root %d 0 R\n>>"
 
1175
                    "\nstartxref\n%ld\n%%%%EOF\n",
 
1176
                    oT->index, catalogRef, xref);
 
1177
            oT->write(buffer);
 
1178
        }
 
1179
        void add(char ch, int style_) {
 
1180
            if (!pageStarted) {
 
1181
                startPage();
 
1182
            }
 
1183
            // get glyph width (TODO future non-monospace handling)
 
1184
            double glyphWidth = fontToPoints(PDFfontWidths[fontSet]);
 
1185
            xPos += glyphWidth;
 
1186
            // if cannot fit into a line, flush, wrap to next line
 
1187
            if (xPos > pageWidth - pageMargin.right) {
 
1188
                nextLine();
 
1189
                xPos += glyphWidth;
 
1190
            }
 
1191
            // if different style, then change to style
 
1192
            if (style_ != styleCurrent) {
 
1193
                flushSegment();
 
1194
                // output code (if needed) for new style
 
1195
                setStyle(segStyle, style_);
 
1196
                stylePrev = styleCurrent;
 
1197
                styleCurrent = style_;
 
1198
            }
 
1199
            // escape these characters
 
1200
            if (ch == ')' || ch == '(' || ch == '\\') {
 
1201
                segment += '\\';
 
1202
            }
 
1203
            if (ch != ' ') { justWhiteSpace = false; }
 
1204
            segment += ch;  // add to segment data
 
1205
        }
 
1206
        void flushSegment() {
 
1207
            if (segment.length() > 0) {
 
1208
                if (justWhiteSpace) {   // optimise
 
1209
                    styleCurrent = stylePrev;
 
1210
                } else {
 
1211
                    pageData += segStyle;
 
1212
                }
 
1213
                pageData += "(";
 
1214
                pageData += segment;
 
1215
                pageData += ")Tj\n";
 
1216
            }
 
1217
            segment.erase(); //clear(); MSVC6 doesn't have clear in their std::string
 
1218
            *segStyle = '\0';
 
1219
            justWhiteSpace = true;
 
1220
        }
 
1221
        void startPage() {
 
1222
            pageStarted = true;
 
1223
            firstLine = true;
 
1224
            pageCount++;
 
1225
            double fontAscender = fontToPoints(PDFfontAscenders[fontSet]);
 
1226
            yPos = pageHeight - pageMargin.top - fontAscender;
 
1227
            // start a new page
 
1228
            sprintf(buffer, "BT 1 0 0 1 %d %d Tm\n",
 
1229
                pageMargin.left, (int)yPos);
 
1230
            // force setting of initial font, colour
 
1231
            setStyle(segStyle, -1);
 
1232
            strcat(buffer, segStyle);
 
1233
            pageData = buffer;
 
1234
            xPos = pageMargin.left;
 
1235
            segment.erase(); //clear(); MSVC6 doesn't have clear in their std::string
 
1236
            flushSegment();
 
1237
        }
 
1238
        void endPage() {
 
1239
            pageStarted = false;
 
1240
            flushSegment();
 
1241
            // build actual text object; +3 is for "ET\n"
 
1242
            // PDF1.4Ref(p38) EOL marker preceding endstream not counted
 
1243
            char *textObj = new char[pageData.length() + 100];
 
1244
            // concatenate stream within the text object
 
1245
            sprintf(textObj, "<</Length %d>>\nstream\n%s"
 
1246
                     "ET\nendstream\n",
 
1247
                     static_cast<int>(pageData.length() - 1 + 3),
 
1248
                     pageData.c_str());
 
1249
            oT->add(textObj);
 
1250
            delete []textObj;
 
1251
        }
 
1252
        void nextLine() {
 
1253
            if (!pageStarted) {
 
1254
                startPage();
 
1255
            }
 
1256
            xPos = pageMargin.left;
 
1257
            flushSegment();
 
1258
            // PDF follows cartesian coords, subtract -> down
 
1259
            yPos -= leading;
 
1260
            double fontDescender = fontToPoints(PDFfontDescenders[fontSet]);
 
1261
            if (yPos < pageMargin.bottom + fontDescender) {
 
1262
                endPage();
 
1263
                startPage();
 
1264
                return;
 
1265
            }
 
1266
            if (firstLine) {
 
1267
                                // avoid breakage due to locale setting
 
1268
                                int f = (int)(leading * 10 + 0.5);
 
1269
                                sprintf(buffer, "0 -%d.%d TD\n", f / 10, f % 10);
 
1270
                firstLine = false;
 
1271
            } else {
 
1272
                sprintf(buffer, "T*\n");
 
1273
            }
 
1274
            pageData += buffer;
 
1275
        }
 
1276
    };
 
1277
    PDFRender pr;
 
1278
 
 
1279
    //RemoveFindMarks();
 
1280
    m_editor->Colourise(0, -1); //SendEditor(SCI_COLOURISE, 0, -1);
 
1281
    // read exporter flags
 
1282
    int tabSize = m_editor->GetTabWidth(); //props.GetInt("tabsize", PDF_TAB_DEFAULT);
 
1283
    if (tabSize < 0) {
 
1284
        tabSize = PDF_TAB_DEFAULT;
 
1285
    }
 
1286
    // read magnification value to add to default screen font size
 
1287
    pr.fontSize = 0; // FIXME props.GetInt("export.pdf.magnification");
 
1288
    // set font family according to face name
 
1289
    SString propItem = "Helvetica"; // FIXME props.GetExpanded("export.pdf.font");
 
1290
    pr.fontSet = PDF_FONT_DEFAULT;
 
1291
    if (propItem.length()) {
 
1292
        if (propItem == "Courier")
 
1293
            pr.fontSet = 0;
 
1294
        else if (propItem == "Helvetica")
 
1295
            pr.fontSet = 1;
 
1296
        else if (propItem == "Times")
 
1297
            pr.fontSet = 2;
 
1298
    }
 
1299
    // page size: width, height
 
1300
    propItem = "595,842"; // FIXME props.GetExpanded("export.pdf.pagesize");
 
1301
    char *buffer = new char[200];
 
1302
    //char *ps = StringDup(propItem.c_str());
 
1303
    //const char *next = GetNextPropItem(ps, buffer, 32);
 
1304
    if (0 >= (pr.pageWidth = 595)) {
 
1305
        pr.pageWidth = PDF_WIDTH_DEFAULT;
 
1306
    }
 
1307
    //next = GetNextPropItem(next, buffer, 32);
 
1308
    if (0 >= (pr.pageHeight = 842)) {
 
1309
        pr.pageHeight = PDF_HEIGHT_DEFAULT;
 
1310
    }
 
1311
    //delete []ps;
 
1312
    // page margins: left, right, top, bottom
 
1313
    //propItem = props.GetExpanded("export.pdf.margins");
 
1314
    //ps = StringDup(propItem.c_str());
 
1315
    //next = GetNextPropItem(ps, buffer, 32);
 
1316
    if (0 >= (pr.pageMargin.left = 72)) {
 
1317
        pr.pageMargin.left = PDF_MARGIN_DEFAULT;
 
1318
    }
 
1319
    //next = GetNextPropItem(next, buffer, 32);
 
1320
    if (0 >= (pr.pageMargin.right = 72)) {
 
1321
        pr.pageMargin.right = PDF_MARGIN_DEFAULT;
 
1322
    }
 
1323
    //next = GetNextPropItem(next, buffer, 32);
 
1324
    if (0 >= (pr.pageMargin.top = 72)) {
 
1325
        pr.pageMargin.top = PDF_MARGIN_DEFAULT;
 
1326
    }
 
1327
    //GetNextPropItem(next, buffer, 32);
 
1328
    if (0 >= (pr.pageMargin.bottom = 72)) {
 
1329
        pr.pageMargin.bottom = PDF_MARGIN_DEFAULT;
 
1330
    }
 
1331
    //delete []ps;
 
1332
 
 
1333
    // collect all styles available for that 'language'
 
1334
    // or the default style if no language is available...
 
1335
    pr.style = new PDFStyle[STYLE_MAX + 1];
 
1336
    for (int i = 0; i <= STYLE_MAX; i++) {  // get keys
 
1337
        pr.style[i].font = 0;
 
1338
        pr.style[i].fore[0] = '\0';
 
1339
 
 
1340
        //sprintf(buffer, "style.*.%0d", i);
 
1341
        //char *valdef = StringDup(props.GetExpanded(buffer).c_str());
 
1342
        //sprintf(buffer, "style.%s.%0d", language.c_str(), i);
 
1343
        //char *val = StringDup(props.GetExpanded(buffer).c_str());
 
1344
 
 
1345
        StyleDefinition sd(m_steStyles, SciToSTEStyle(i));
 
1346
        //sd.ParseStyleDefinition(val);
 
1347
 
 
1348
        if (sd.specified != StyleDefinition::sdNone) {
 
1349
            if (sd.italics) { pr.style[i].font |= 2; }
 
1350
            if (sd.bold) { pr.style[i].font |= 1; }
 
1351
            if (sd.fore.length()) {
 
1352
                getPDFRGB(pr.style[i].fore, sd.fore.c_str());
 
1353
            } else if (i == STYLE_DEFAULT) {
 
1354
                strcpy(pr.style[i].fore, "0 0 0 ");
 
1355
            }
 
1356
            // grab font size from default style
 
1357
            if (i == STYLE_DEFAULT) {
 
1358
                if (sd.size > 0)
 
1359
                    pr.fontSize += sd.size;
 
1360
                else
 
1361
                    pr.fontSize = PDF_FONTSIZE_DEFAULT;
 
1362
            }
 
1363
        }
 
1364
        //delete []val;
 
1365
        //delete []valdef;
 
1366
    }
 
1367
    // patch in default foregrounds
 
1368
    for (int j = 0; j <= STYLE_MAX; j++) {
 
1369
        if (pr.style[j].fore[0] == '\0') {
 
1370
            strcpy(pr.style[j].fore, pr.style[STYLE_DEFAULT].fore);
 
1371
        }
 
1372
    }
 
1373
    delete []buffer;
 
1374
 
 
1375
    FILE *fp = wxFopen(saveName.GetFullPath(), wxT("wb"));
 
1376
    if (!fp)
 
1377
    {
 
1378
        // couldn't open the file for saving, issue an error message
 
1379
        //FIXME SString msg = LocaliseMessage("Could not save file '^0'.", filePath.AsFileSystem());
 
1380
        //WindowMessageBox(wSciTE, msg, MB_OK | MB_ICONWARNING);
 
1381
        return false;
 
1382
    }
 
1383
    // initialise PDF rendering
 
1384
    PDFObjectTracker ot(fp);
 
1385
    pr.oT = &ot;
 
1386
    pr.startPDF();
 
1387
 
 
1388
    // do here all the writing
 
1389
    int lengthDoc = m_editor->GetLength(); //LengthDocument();
 
1390
    //TextReader acc(wEditor);
 
1391
 
 
1392
    if (!lengthDoc) {   // enable zero length docs
 
1393
        pr.nextLine();
 
1394
    } else {
 
1395
                int lineIndex = 0;
 
1396
        for (int i = 0; i < lengthDoc; i++) {
 
1397
            char ch = (char)m_editor->GetCharAt(i); //acc[i];
 
1398
            int style = m_editor->GetStyleAt(i);
 
1399
 
 
1400
            if (ch == '\t') {
 
1401
                // expand tabs
 
1402
                int ts = tabSize - (lineIndex % tabSize);
 
1403
                lineIndex += ts;
 
1404
                for (; ts; ts--) {  // add ts count of spaces
 
1405
                    pr.add(' ', style); // add spaces
 
1406
                }
 
1407
            } else if (ch == '\r' || ch == '\n') {
 
1408
                if (ch == '\r' && (char)m_editor->GetCharAt(i + 1) == '\n') {
 
1409
                    i++;
 
1410
                }
 
1411
                // close and begin a newline...
 
1412
                    pr.nextLine();
 
1413
                    lineIndex = 0;
 
1414
            } else {
 
1415
                // write the character normally...
 
1416
                    pr.add(ch, style);
 
1417
                    lineIndex++;
 
1418
            }
 
1419
        }
 
1420
    }
 
1421
    // write required stuff and close the PDF file
 
1422
    pr.endPDF();
 
1423
    fclose(fp);
 
1424
    return true;
 
1425
}
 
1426
 
 
1427
 
 
1428
//---------- Save to TeX ----------
 
1429
 
 
1430
static char* getTexRGB(char* texcolor, const char* stylecolor) {
 
1431
        //texcolor[rgb]{0,0.5,0}{....}
 
1432
        double rf = IntFromHexByte(stylecolor + 1) / 256.0;
 
1433
        double gf = IntFromHexByte(stylecolor + 3) / 256.0;
 
1434
        double bf = IntFromHexByte(stylecolor + 5) / 256.0;
 
1435
        // avoid breakage due to locale setting
 
1436
        int r = (int)(rf * 10 + 0.5);
 
1437
        int g = (int)(gf * 10 + 0.5);
 
1438
        int b = (int)(bf * 10 + 0.5);
 
1439
        sprintf(texcolor, "%d.%d, %d.%d, %d.%d", r / 10, r % 10, g / 10, g % 10, b / 10, b % 10);
 
1440
        return texcolor;
 
1441
}
 
1442
 
 
1443
#define CHARZ ('z' - 'b')
 
1444
static char* texStyle(int style) {
 
1445
    static char buf[10];
 
1446
    int i = 0;
 
1447
    do {
 
1448
        buf[i++] = static_cast<char>('a' + (style % CHARZ));
 
1449
        style /= CHARZ;
 
1450
    } while ( style > 0 );
 
1451
    buf[i] = 0;
 
1452
    return buf;
 
1453
}
 
1454
 
 
1455
static void defineTexStyle(StyleDefinition &style, FILE* fp, int istyle) {
 
1456
    int closing_brackets = 2;
 
1457
    char rgb[200];
 
1458
    fprintf(fp, "\\newcommand{\\scite%s}[1]{\\noindent{\\ttfamily{", texStyle(istyle));
 
1459
    if (style.italics) {
 
1460
        fputs("\\textit{", fp);
 
1461
        closing_brackets++;
 
1462
    }
 
1463
    if (style.bold) {
 
1464
        fputs("\\textbf{", fp);
 
1465
        closing_brackets++;
 
1466
    }
 
1467
    if (style.fore.length()) {
 
1468
        fprintf(fp, "\\textcolor[rgb]{%s}{", getTexRGB(rgb, style.fore.c_str()) );
 
1469
        closing_brackets++;
 
1470
    }
 
1471
    if (style.back.length()) {
 
1472
        fprintf(fp, "\\colorbox[rgb]{%s}{", getTexRGB( rgb, style.back.c_str()) );
 
1473
        closing_brackets++;
 
1474
    }
 
1475
    fputs("#1", fp);
 
1476
    for (int i = 0; i <= closing_brackets; i++) {
 
1477
        fputc( '}', fp );
 
1478
    }
 
1479
    fputc('\n', fp);
 
1480
}
 
1481
 
 
1482
bool wxSTEditorExporter::SaveToTEX(const wxFileName& saveName)
 
1483
{
 
1484
    wxCHECK_MSG(m_editor, false, wxT("Invalid editor"));
 
1485
    wxBusyCursor busy;
 
1486
 
 
1487
    //RemoveFindMarks();
 
1488
    m_editor->Colourise(0, -1);             //SendEditor(SCI_COLOURISE, 0, -1);
 
1489
    int tabSize = m_editor->GetTabWidth();  //props.GetInt("tabsize");
 
1490
    if (tabSize == 0)
 
1491
        tabSize = 4;
 
1492
 
 
1493
    //char key[200];
 
1494
    int lengthDoc = m_editor->GetLength();  //LengthDocument();
 
1495
    //TextReader acc(wEditor);
 
1496
    bool styleIsUsed[STYLE_MAX + 1];
 
1497
 
 
1498
    //int titleFullPath = 0;                  //props.GetInt("export.tex.title.fullpath", 0);
 
1499
 
 
1500
    int i;
 
1501
    for (i = 0; i <= STYLE_MAX; i++) {
 
1502
        styleIsUsed[i] = false;
 
1503
    }
 
1504
    for (i = 0; i < lengthDoc; i++) {   // check the used styles
 
1505
        styleIsUsed[m_editor->GetStyleAt(i) & 0X7f] = true;
 
1506
    }
 
1507
    styleIsUsed[STYLE_DEFAULT] = true;
 
1508
 
 
1509
    FILE *fp = wxFopen(saveName.GetFullPath(), wxT("wt"));
 
1510
    if (fp) {
 
1511
        fputs("\\documentclass[a4paper]{article}\n"
 
1512
              "\\usepackage[a4paper,margin=2cm]{geometry}\n"
 
1513
              "\\usepackage[T1]{fontenc}\n"
 
1514
              "\\usepackage{color}\n"
 
1515
              "\\usepackage{alltt}\n"
 
1516
                      "\\usepackage{times}\n"
 
1517
                      "\\setlength{\\fboxsep}{0pt}\n", fp);
 
1518
 
 
1519
        for (i = 0; i < STYLE_MAX; i++) {      // get keys
 
1520
            if (styleIsUsed[i]) {
 
1521
                //sprintf(key, "style.*.%0d", i);
 
1522
                //char *valdef = StringDup(props.GetExpanded(key).c_str());
 
1523
                //sprintf(key, "style.%s.%0d", language.c_str(), i);
 
1524
                //char *val = StringDup(props.GetExpanded(key).c_str());
 
1525
 
 
1526
                StyleDefinition sd(m_steStyles, SciToSTEStyle(i)); //check default properties
 
1527
                //sd.ParseStyleDefinition(val); //check language properties
 
1528
 
 
1529
                defineTexStyle(sd, fp, i); // writeout style macroses
 
1530
                //delete []val;
 
1531
                //delete []valdef;
 
1532
            }
 
1533
        }
 
1534
 
 
1535
        fputs("\\begin{document}\n\n", fp);
 
1536
        fprintf(fp, "Source File: %s\n\n\\noindent\n\\small{\n",
 
1537
            (const char*)saveName.GetFullPath().mb_str()); //FIXME titleFullPath ? filePath.AsFileSystem() : filePath.Name().AsFileSystem()));
 
1538
 
 
1539
        int styleCurrent = m_editor->GetStyleAt(0);
 
1540
 
 
1541
        fprintf(fp, "\\scite%s{", texStyle(styleCurrent));
 
1542
 
 
1543
        int lineIdx = 0;
 
1544
 
 
1545
        for (i = 0; i < lengthDoc; i++) { //here process each character of the document
 
1546
            char ch = (char)m_editor->GetCharAt(i); //acc[i];
 
1547
            int style = m_editor->GetStyleAt(i);
 
1548
 
 
1549
            if (style != styleCurrent) { //new style?
 
1550
                                fprintf(fp, "}\\scite%s{", texStyle(style) );
 
1551
                styleCurrent = style;
 
1552
            }
 
1553
 
 
1554
            switch ( ch ) { //write out current character.
 
1555
            case '\t': {
 
1556
                    int ts = tabSize - (lineIdx % tabSize);
 
1557
                    lineIdx += ts - 1;
 
1558
                    fprintf(fp, "\\hspace*{%dem}", ts);
 
1559
                    break;
 
1560
                }
 
1561
            case '\\':
 
1562
                fputs("{\\textbackslash}", fp);
 
1563
                break;
 
1564
            case '>':
 
1565
            case '<':
 
1566
            case '@':
 
1567
                fprintf(fp, "$%c$", ch);
 
1568
                break;
 
1569
            case '{':
 
1570
            case '}':
 
1571
            case '^':
 
1572
            case '_':
 
1573
            case '&':
 
1574
            case '$':
 
1575
            case '#':
 
1576
            case '%':
 
1577
            case '~':
 
1578
                fprintf(fp, "\\%c", ch);
 
1579
                break;
 
1580
            case '\r':
 
1581
            case '\n':
 
1582
                lineIdx = -1;   // Because incremented below
 
1583
                if (ch == '\r' && (char)m_editor->GetCharAt(i + 1) == '\n')
 
1584
                    i++;    // Skip the LF
 
1585
                styleCurrent = m_editor->GetStyleAt(i + 1);
 
1586
                fprintf(fp, "} \\\\\n\\scite%s{", texStyle(styleCurrent) );
 
1587
                break;
 
1588
            case ' ':
 
1589
                if ((char)m_editor->GetCharAt(i + 1) == ' ') {
 
1590
                    fputs("{\\hspace*{1em}}", fp);
 
1591
                } else {
 
1592
                    fputc(' ', fp);
 
1593
                }
 
1594
                break;
 
1595
            default:
 
1596
                fputc(ch, fp);
 
1597
            }
 
1598
            lineIdx++;
 
1599
        }
 
1600
        fputs("}\n} %end small\n\n\\end{document}\n", fp); //close last empty style macros and document too
 
1601
        fclose(fp);
 
1602
    } else {
 
1603
        return false;
 
1604
        //FIXME SString msg = LocaliseMessage(
 
1605
        //                  "Could not save file \"^0\".", filePath.AsFileSystem());
 
1606
        //WindowMessageBox(wSciTE, msg, MB_OK | MB_ICONWARNING);
 
1607
    }
 
1608
    return true;
 
1609
}
 
1610
 
 
1611
 
 
1612
//---------- Save to XML ----------
 
1613
 
 
1614
bool wxSTEditorExporter::SaveToXML(const wxFileName& saveName)
 
1615
{
 
1616
    wxCHECK_MSG(m_editor, false, wxT("Invalid editor"));
 
1617
    wxBusyCursor busy;
 
1618
 
 
1619
    // Author: Hans Hagen / PRAGMA ADE / www.pragma-ade.com
 
1620
    // Version: 1.0 / august 18, 2003
 
1621
    // Remark: for a suitable style, see ConTeXt (future) distributions
 
1622
 
 
1623
    // The idea is that one can use whole files, or ranges of lines in manuals
 
1624
    // and alike. Since ConTeXt can handle XML files, it's quite convenient to
 
1625
    // use this format instead of raw TeX, although the output would not look
 
1626
    // much different in structure.
 
1627
 
 
1628
    // We don't put style definitions in here since the main document will in
 
1629
    // most cases determine the look and feel. This way we have full control over
 
1630
    // the layout. The type attribute will hold the current lexer value.
 
1631
 
 
1632
    // <document>            : the whole thing
 
1633
    // <data>                : reserved for metadata
 
1634
    // <text>                : the main bodyof text
 
1635
    // <line n-'number'>     : a line of text
 
1636
 
 
1637
    // <t n='number'>...<t/> : tag
 
1638
    // <s n='number'/>       : space
 
1639
    // <g/>                  : >
 
1640
    // <l/>                  : <
 
1641
    // <a/>                  : &
 
1642
    // <h/>                  : #
 
1643
 
 
1644
    // We don't use entities, but empty elements for special characters
 
1645
    // but will eventually use utf-8 (once i know how to get them out).
 
1646
 
 
1647
    //RemoveFindMarks();
 
1648
    m_editor->Colourise(0, -1);             //SendEditor(SCI_COLOURISE, 0, -1) ;
 
1649
 
 
1650
    int tabSize = m_editor->GetTabWidth();  //props.GetInt("tabsize") ;
 
1651
    if (tabSize == 0) {
 
1652
        tabSize = 4 ;
 
1653
    }
 
1654
 
 
1655
    int lengthDoc = m_editor->GetLength();  //LengthDocument() ;
 
1656
 
 
1657
    //TextReader acc(wEditor);
 
1658
 
 
1659
    FILE *fp = wxFopen(saveName.GetFullPath(), wxT("wt"));
 
1660
 
 
1661
    if (fp) {
 
1662
 
 
1663
        bool collapseSpaces = 1; //(props.GetInt("export.xml.collapse.spaces", 1) == 1) ;
 
1664
        bool collapseLines  = 1; //(props.GetInt("export.xml.collapse.lines", 1) == 1) ;
 
1665
 
 
1666
                fprintf(fp, "<?xml version='1.0' encoding='%s'?>\n", (m_editor->GetCodePage() == wxSTC_CP_UTF8) ? "utf-8" : "ascii");
 
1667
 
 
1668
        fputs("<document xmlns='http://www.scintila.org/scite.rng'", fp) ;
 
1669
        fprintf(fp, " filename='%s'",
 
1670
 
 
1671
            (const char*)saveName.GetFullPath().mb_str()); //FIXME filePath.Name().AsFileSystem())) ;
 
1672
        fprintf(fp, " type='%s'", "unknown") ;
 
1673
        fprintf(fp, " version='%s'", "1.0") ;
 
1674
        fputs(">\n", fp) ;
 
1675
 
 
1676
        fputs("<data comment='This element is reserved for future usage.'/>\n", fp) ;
 
1677
 
 
1678
        fputs("<text>\n", fp) ;
 
1679
 
 
1680
        int styleCurrent = -1 ; // acc.StyleAt(0) ;
 
1681
        int lineNumber = 1 ;
 
1682
        int lineIndex = 0 ;
 
1683
        bool styleDone = false ;
 
1684
        bool lineDone = false ;
 
1685
        bool charDone = false ;
 
1686
        int styleNew = -1 ;
 
1687
        int spaceLen = 0 ;
 
1688
        int emptyLines = 0 ;
 
1689
 
 
1690
        for (int i = 0; i < lengthDoc; i++) {
 
1691
            char ch = (char)m_editor->GetCharAt(i); //acc[i] ;
 
1692
            int style = m_editor->GetStyleAt(i) ;
 
1693
            if (style != styleCurrent) {
 
1694
                styleCurrent = style ;
 
1695
                styleNew = style ;
 
1696
            }
 
1697
            if (ch == ' ') {
 
1698
                spaceLen++ ;
 
1699
            } else if (ch == '\t') {
 
1700
                int ts = tabSize - (lineIndex % tabSize) ;
 
1701
                lineIndex += ts - 1 ;
 
1702
                spaceLen += ts ;
 
1703
            } else if (ch == '\f') {
 
1704
                // ignore this animal
 
1705
            } else if (ch == '\r' || ch == '\n') {
 
1706
                if (ch == '\r' && (char)m_editor->GetCharAt(i + 1) == '\n') {
 
1707
                    i++;
 
1708
                }
 
1709
                if (styleDone) {
 
1710
                    fputs("</t>", fp) ;
 
1711
                    styleDone = false ;
 
1712
                }
 
1713
                lineIndex = -1 ;
 
1714
                if (lineDone) {
 
1715
                    fputs("</line>\n", fp) ;
 
1716
                    lineDone = false ;
 
1717
                } else if (collapseLines) {
 
1718
                    emptyLines++ ;
 
1719
                } else {
 
1720
                    fprintf(fp, "<line n='%d'/>\n", lineNumber) ;
 
1721
                }
 
1722
                charDone = false ;
 
1723
                lineNumber++ ;
 
1724
                styleCurrent = -1 ; // acc.StyleAt(i + 1) ;
 
1725
            } else {
 
1726
                if (collapseLines && (emptyLines > 0)) {
 
1727
                    fputs("<line/>\n", fp) ;
 
1728
                }
 
1729
                emptyLines = 0 ;
 
1730
                if (! lineDone) {
 
1731
                    fprintf(fp, "<line n='%d'>", lineNumber) ;
 
1732
                    lineDone = true ;
 
1733
                }
 
1734
                if (styleNew >= 0) {
 
1735
                    if (styleDone) { fputs("</t>", fp) ; }
 
1736
                }
 
1737
                if (! collapseSpaces) {
 
1738
                    while (spaceLen > 0) {
 
1739
                        fputs("<s/>", fp) ;
 
1740
                        spaceLen-- ;
 
1741
                    }
 
1742
                } else if (spaceLen == 1) {
 
1743
                    fputs("<s/>", fp) ;
 
1744
                    spaceLen = 0 ;
 
1745
                } else if (spaceLen > 1) {
 
1746
                    fprintf(fp, "<s n='%d'/>", spaceLen) ;
 
1747
                    spaceLen = 0 ;
 
1748
                }
 
1749
                if (styleNew >= 0) {
 
1750
                    fprintf(fp, "<t n='%d'>", style) ;
 
1751
                    styleNew = -1 ;
 
1752
                    styleDone = true ;
 
1753
                }
 
1754
                switch (ch) {
 
1755
                case '>' :
 
1756
                    fputs("<g/>", fp) ;
 
1757
                    break ;
 
1758
                case '<' :
 
1759
                    fputs("<l/>", fp) ;
 
1760
                    break ;
 
1761
                case '&' :
 
1762
                    fputs("<a/>", fp) ;
 
1763
                    break ;
 
1764
                case '#' :
 
1765
                    fputs("<h/>", fp) ;
 
1766
                    break ;
 
1767
                default  :
 
1768
                    fputc(ch, fp) ;
 
1769
                }
 
1770
                charDone = true ;
 
1771
            }
 
1772
            lineIndex++ ;
 
1773
        }
 
1774
        if (styleDone) {
 
1775
            fputs("</t>", fp) ;
 
1776
        }
 
1777
        if (lineDone) {
 
1778
            fputs("</line>\n", fp) ;
 
1779
        }
 
1780
        if (charDone) {
 
1781
            // no last empty line: fprintf(fp, "<line n='%d'/>", lineNumber) ;
 
1782
        }
 
1783
 
 
1784
        fputs("</text>\n", fp) ;
 
1785
        fputs("</document>\n", fp) ;
 
1786
 
 
1787
        fclose(fp) ;
 
1788
    } else {
 
1789
        return false;
 
1790
        //FIXME SString msg = LocaliseMessage("Could not save file \"^0\".", filePath.AsFileSystem()) ;
 
1791
        //WindowMessageBox(wSciTE, msg, MB_OK | MB_ICONWARNING) ;
 
1792
    }
 
1793
    return true;
 
1794
}
 
1795
 
 
1796
bool wxSTEditorExporter::SaveToHTML(const wxFileName& saveName)
 
1797
{
 
1798
    wxCHECK_MSG(m_editor, false, wxT("Invalid editor"));
 
1799
 
 
1800
    FILE *fp = wxFopen(saveName.GetFullPath(), wxT("wt"));
 
1801
    if (fp)
 
1802
    {
 
1803
        fputs(wx2stc(RenderAsHTML(0, m_editor->GetLength())), fp);
 
1804
        fclose(fp);
 
1805
    } else {
 
1806
        return false;
 
1807
        //FIMXE SString msg = LocaliseMessage("Could not save file '^0'.", filePath.AsFileSystem());
 
1808
        //WindowMessageBox(wSciTE, msg, MB_OK | MB_ICONWARNING);
 
1809
    }
 
1810
    return true;
 
1811
}
 
1812
 
 
1813
// helper function to switch styles
 
1814
void STEExporterHTML_Font(int style_n, int old_style_n,
 
1815
                          StyleDefinition* sd, wxString &htmlString)
 
1816
{
 
1817
    // turn off old styles if style_n < 0 or styles differ
 
1818
    if  (old_style_n >= 0)
 
1819
    {
 
1820
        if ((style_n < 0) || (sd[old_style_n].fore != sd[style_n].fore))
 
1821
            htmlString << wxT("</FONT>");
 
1822
 
 
1823
        if (sd[old_style_n].bold       && ((style_n < 0) || !sd[style_n].bold))
 
1824
            htmlString << wxT("</B>");
 
1825
        if (sd[old_style_n].italics    && ((style_n < 0) || !sd[style_n].italics))
 
1826
            htmlString << wxT("</I>");
 
1827
        if (sd[old_style_n].underlined && ((style_n < 0) || !sd[style_n].underlined))
 
1828
            htmlString << wxT("</U>");
 
1829
    }
 
1830
    // turn on new styles, only if changed or set from invalid old style
 
1831
    if (style_n >= 0)
 
1832
    {
 
1833
        // always set new colour
 
1834
        if ((old_style_n < 0) || (sd[old_style_n].fore != sd[style_n].fore))
 
1835
            htmlString += wxString::Format(wxT("<FONT COLOR = \"%s\">"), stc2wx(sd[style_n].fore.c_str()).wx_str());
 
1836
 
 
1837
        if (sd[style_n].bold       && ((old_style_n < 0) || !sd[old_style_n].bold))
 
1838
            htmlString << wxT("<B>");
 
1839
        if (sd[style_n].italics    && ((old_style_n < 0) || !sd[old_style_n].italics))
 
1840
            htmlString << wxT("<I>");
 
1841
        if (sd[style_n].underlined && ((old_style_n < 0) || !sd[old_style_n].underlined))
 
1842
            htmlString << wxT("<U>");
 
1843
    }
 
1844
}
 
1845
 
 
1846
// This modified code is from wxHatch, Copyright Chris Elliott
 
1847
wxString wxSTEditorExporter::RenderAsHTML(int from, int to) const
 
1848
{
 
1849
    wxCHECK_MSG(m_editor, wxEmptyString, wxT("Invalid editor"));
 
1850
    wxBusyCursor busy;
 
1851
 
 
1852
    bool wysiwyg = false; // FIXME
 
1853
    wxFileName fileName = m_editor->GetFileName();
 
1854
 
 
1855
    m_editor->Colourise(0, -1);
 
1856
 
 
1857
    StyleDefinition sd[STYLE_MAX + 1]; // index is scintilla styles
 
1858
 
 
1859
    for (int s = 0; s <= STYLE_MAX; s++)
 
1860
        sd[s].Create(m_steStyles, SciToSTEStyle(s));
 
1861
 
 
1862
    const wxString sOO = wxT("00");
 
1863
    const wxString s8O = wxT("80");
 
1864
    const wxString sFF = wxT("FF");
 
1865
 
 
1866
    wxString htmlString(wxT("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\">\n"));
 
1867
    htmlString << wxT("<HTML>\n");
 
1868
 
 
1869
    // write the header
 
1870
    htmlString << wxT("<HEAD>\n");
 
1871
    htmlString << wxT("  <meta http-equiv=\"Content-Type\" content=\"text/html;charset=iso-8859-1\">\n");
 
1872
    htmlString << wxT("  <TITLE>") + fileName.GetFullPath() + wxT("</TITLE>\n");
 
1873
    htmlString << wxT("</HEAD>\n");
 
1874
 
 
1875
    // write the body
 
1876
    // FIXME: could also use <PRE WIDTH=80> for 80 column line widths
 
1877
    htmlString << wxT("<BODY><TT><PRE>\n");
 
1878
 
 
1879
    int style_n = 0, old_style_n = -1;  // start with invalid style
 
1880
 
 
1881
    // read document letter by letter
 
1882
    for (int n = from; n < to; n++)
 
1883
    {
 
1884
        style_n = m_editor->GetStyleAt(n); // | 31;
 
1885
        if (style_n > STYLE_MAX) style_n = 0;  // should never happen
 
1886
        if (style_n < 0        ) style_n = 0;  // should never happen
 
1887
 
 
1888
        // turn off old style attributes and set new
 
1889
        if (style_n != old_style_n)
 
1890
            STEExporterHTML_Font(style_n, old_style_n, sd, htmlString);
 
1891
 
 
1892
        old_style_n = style_n;
 
1893
 
 
1894
        const wxChar c = m_editor->GetCharAt(n);
 
1895
        //translate < > & \n etc
 
1896
        switch (c)
 
1897
        {
 
1898
            case wxT('\r') :
 
1899
            {
 
1900
                // if CRLF just skip this, it'll get added by our \n
 
1901
                if ((n < (to - 1)) && (m_editor->GetCharAt(n+1) == wxT('\n')))
 
1902
                    break;
 
1903
                // else fall through
 
1904
            }
 
1905
            //case wxT('\n') : htmlString << wxT("\n<BR>"); break; // not if using PRE
 
1906
            case wxT('<')  : htmlString << wxT("&lt;");   break;
 
1907
            case wxT('>')  : htmlString << wxT("&gt;");   break;
 
1908
            case wxT('&')  : htmlString << wxT("&amp;");  break;
 
1909
            case wxT(' ')  :
 
1910
            {
 
1911
                // allow for line breaking by making the first space in a
 
1912
                //   series of spaces or a single space a regular breakable space
 
1913
                if (wysiwyg || (n == 0) || (m_editor->GetCharAt(n-1) == wxT(' ')))
 
1914
                    htmlString << wxT("&nbsp;");
 
1915
                else
 
1916
                    htmlString << c;
 
1917
 
 
1918
                break;
 
1919
            }
 
1920
            default :        htmlString << c;             break;
 
1921
        }
 
1922
    }
 
1923
 
 
1924
    // turn off last set styles (if any)
 
1925
    STEExporterHTML_Font(-1, old_style_n, sd, htmlString);
 
1926
 
 
1927
    htmlString << wxT("\n</PRE></TT></BODY></HTML>");
 
1928
    return htmlString;
 
1929
}
 
1930
 
 
1931
//-----------------------------------------------------------------------------
 
1932
// wxSTEditorExportDialog
 
1933
//-----------------------------------------------------------------------------
 
1934
IMPLEMENT_ABSTRACT_CLASS(wxSTEditorExportDialog, wxDialog);
 
1935
 
 
1936
wxArrayString wxSTEditorExportDialog::sm_fileNames;
 
1937
int           wxSTEditorExportDialog::sm_file_format = 0;
 
1938
 
 
1939
BEGIN_EVENT_TABLE(wxSTEditorExportDialog, wxDialog)
 
1940
    EVT_CHOICE     (wxID_ANY, wxSTEditorExportDialog::OnChoice)
 
1941
    EVT_BUTTON     (wxID_ANY, wxSTEditorExportDialog::OnButton)
 
1942
END_EVENT_TABLE()
 
1943
 
 
1944
wxSTEditorExportDialog::wxSTEditorExportDialog() : wxDialog()
 
1945
{
 
1946
    m_fileFormatChoice = NULL;
 
1947
    m_fileNameCombo    = NULL;
 
1948
}
 
1949
 
 
1950
wxSTEditorExportDialog::wxSTEditorExportDialog(wxWindow* parent, long style) : wxDialog()
 
1951
{
 
1952
    m_fileFormatChoice = NULL;
 
1953
    m_fileNameCombo    = NULL;
 
1954
 
 
1955
    Create(parent, style);
 
1956
}
 
1957
 
 
1958
bool wxSTEditorExportDialog::Create(wxWindow* parent,
 
1959
                                    long style)
 
1960
{
 
1961
    if (!wxDialog::Create(parent, wxID_ANY, _("Export file"), wxDefaultPosition, wxDefaultSize, style))
 
1962
        return false;
 
1963
 
 
1964
    SetIcons(wxSTEditorArtProvider::GetDialogIconBundle());
 
1965
    wxSTEditorExportSizer(this, true, true);
 
1966
    wxSTEditorStdDialogButtonSizer(this, wxOK | wxCANCEL);
 
1967
 
 
1968
    m_fileFormatChoice = wxStaticCast(FindWindow(ID_STEDLG_EXPORT_FORMAT_CHOICE ), wxChoice);
 
1969
    m_fileNameCombo    = wxStaticCast(FindWindow(ID_STEDLG_EXPORT_FILENAME_COMBO), wxComboBox);
 
1970
    m_fileNameCombo->Clear();
 
1971
    wxSTEInitComboBoxStrings(sm_fileNames, m_fileNameCombo);
 
1972
 
 
1973
    m_fileFormatChoice->SetSelection(sm_file_format);
 
1974
 
 
1975
    wxBitmapButton *bmpButton = wxStaticCast(FindWindow(ID_STEDLG_EXPORT_FILENAME_BITMAPBUTTON), wxBitmapButton);
 
1976
    bmpButton->SetBitmapLabel(STE_ARTTOOL(wxART_STEDIT_OPEN));
 
1977
 
 
1978
    Fit();
 
1979
    SetMinSize(GetSize());
 
1980
    Centre();
 
1981
 
 
1982
    return true;
 
1983
}
 
1984
 
 
1985
wxFileName wxSTEditorExportDialog::GetFileName() const
 
1986
{
 
1987
    return m_fileNameCombo->GetValue();
 
1988
}
 
1989
 
 
1990
void wxSTEditorExportDialog::SetFileName(const wxFileName& fileName)
 
1991
{
 
1992
    wxSTEPrependComboBoxString(fileName.GetFullPath(), m_fileNameCombo, 10);
 
1993
    m_fileNameCombo->SetValue(fileName.GetFullPath());
 
1994
    m_fileNameCombo->SetFocus();
 
1995
}
 
1996
STE_Export_Type wxSTEditorExportDialog::GetFileFormat() const
 
1997
{
 
1998
    return (STE_Export_Type)m_fileFormatChoice->GetSelection();
 
1999
}
 
2000
void wxSTEditorExportDialog::SetFileFormat(STE_Export_Type file_format)
 
2001
{
 
2002
    m_fileFormatChoice->SetSelection((int)file_format);
 
2003
}
 
2004
 
 
2005
wxFileName wxSTEditorExportDialog::FileNameExtChange(const wxFileName& fileName, int file_format) const
 
2006
{
 
2007
    wxFileName fName(fileName);
 
2008
 
 
2009
    fName.SetExt(wxSTEditorExporter::GetExtension(file_format));
 
2010
    return fName;
 
2011
}
 
2012
 
 
2013
void wxSTEditorExportDialog::OnChoice(wxCommandEvent& event)
 
2014
{
 
2015
    switch (event.GetId())
 
2016
    {
 
2017
        case ID_STEDLG_EXPORT_FORMAT_CHOICE :
 
2018
        {
 
2019
            if (wxStaticCast(FindWindow(ID_STEDLG_EXPORT_EXTENSION_CHECKBOX), wxCheckBox)->IsChecked())
 
2020
            {
 
2021
                SetFileName(FileNameExtChange(GetFileName(), GetFileFormat()));
 
2022
            }
 
2023
 
 
2024
            break;
 
2025
        }
 
2026
    }
 
2027
}
 
2028
 
 
2029
void wxSTEditorExportDialog::OnButton(wxCommandEvent& event)
 
2030
{
 
2031
    switch (event.GetId())
 
2032
    {
 
2033
        case ID_STEDLG_EXPORT_FILENAME_BITMAPBUTTON :
 
2034
        {
 
2035
            int file_format    = GetFileFormat();
 
2036
            wxFileName fileName  = GetFileName();
 
2037
            wxString path      = wxGetCwd();
 
2038
            wxString extension = wxSTEditorExporter::GetExtension(file_format);
 
2039
            wxString wildcards = wxSTEditorExporter::GetWildcards(file_format) + _("|All files (*)|*");
 
2040
 
 
2041
            if (fileName.GetFullPath().Length())
 
2042
            {
 
2043
                wxFileName fn(fileName);
 
2044
                fileName = wxFileName(wxEmptyString, fn.GetFullName());
 
2045
                wxString fileNamePath = fn.GetPath();
 
2046
                if (fileNamePath.Length())
 
2047
                {
 
2048
                    path = fileNamePath;
 
2049
                }
 
2050
            }
 
2051
 
 
2052
            fileName = wxFileSelector( _("Export to a html, pdf, rtf, tex, or xml file"), path, fileName.GetFullPath(),
 
2053
                                       extension, wildcards,
 
2054
                                       wxFD_SAVE | wxFD_OVERWRITE_PROMPT,
 
2055
                                       this );
 
2056
 
 
2057
            if (fileName.GetFullPath().Length())
 
2058
            {
 
2059
                if (wxStaticCast(FindWindow(ID_STEDLG_EXPORT_EXTENSION_CHECKBOX), wxCheckBox)->IsChecked())
 
2060
                   fileName = wxFileDialogBase::AppendExtension(fileName.GetFullPath(),
 
2061
                                                                 extension);
 
2062
                SetFileName(fileName);
 
2063
            }
 
2064
 
 
2065
            break;
 
2066
        }
 
2067
        case wxID_OK :
 
2068
        {
 
2069
            wxSTEPrependArrayString(GetFileName().GetFullPath(), sm_fileNames, 10);
 
2070
            sm_file_format = GetFileFormat();
 
2071
            break;
 
2072
        }
 
2073
        default : break;
 
2074
    }
 
2075
 
 
2076
    event.Skip();
 
2077
}