1
///////////////////////////////////////////////////////////////////////////////
3
// Purpose: wxSTEditorExporter
4
// Author: John Labenski, and others see below
8
// Copyright: (c) John Labenski, Neil Hodgson, & others see below
9
// Licence: wxWidgets licence
10
///////////////////////////////////////////////////////////////////////////////
13
Updated to SciTE 3.0.1, 12/3/2011 - see scite/src/Exporters.cxx
15
Code below marked with this copyright is under this license.
16
"Copyright 1998-2003 by Neil Hodgson <neilh@scintilla.org>"
18
License for Scintilla and SciTE
20
Copyright 1998-2011 by Neil Hodgson <neilh@scintilla.org>
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.
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.
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"
47
#include <wx/filesys.h>
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
53
// ----------------------------------------------------------------------------
54
//#include "../../contrib/src/stc/scintilla/include/Platform.h" // for PRectangle & Point
56
// PRectangle used for pageMargin, see below, only uses the variables as is
57
// we just dumb it down to it's simplest form
61
PRRectangle() : left(0), right(0), top(0), bottom(0) {}
62
int left, right, top, bottom;
65
// ----------------------------------------------------------------------------
66
//#include "../../contrib/src/stc/scintilla/include/SString.h" // for SString
68
// Turn off warnings generated from MSVC's buggy std:: lib header files.
69
#if defined(__VISUALC__)
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
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
83
#pragma warning(disable: 4710) // 'function' : function not inlined
84
#pragma warning(disable: 4786) // identifier was truncated to 'number' characters
85
#endif // defined(__VISUALC__)
87
// We can just typedef SString to std::string
89
//using namespace std;
90
typedef std::string SString;
93
// These functions in wxWidgets/contrib/src/stc/scintilla/src/PropSet.cxx
94
inline char MakeUpperCase_(char ch) {
95
if (ch < 'a' || ch > 'z')
98
return static_cast<char>(ch - 'a' + 'A');
100
int CompareCaseInsensitive_(const char *a, const char *b) {
103
char upperA = MakeUpperCase_(*a);
104
char upperB = MakeUpperCase_(*b);
105
if (upperA != upperB)
106
return upperA - upperB;
111
// Either *a or *b is nul
114
bool EqualCaseInsensitive_(const char *a, const char *b) {
115
return 0 == CompareCaseInsensitive_(a, b);
118
// end copied code from Scintilla
119
// ----------------------------------------------------------------------------
121
wxSTEditorExporter::wxSTEditorExporter(wxSTEditor* editor)
123
wxCHECK_RET(editor, wxT("Invalid editor"));
125
m_stePrefs = editor->GetEditorPrefs();
126
m_steStyles = editor->GetEditorStyles();
127
m_steLangs = editor->GetEditorLangs();
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();
135
bool wxSTEditorExporter::ExportToFile(int file_format, const wxFileName& fileName,
136
bool overwrite_prompt, bool msg_on_error)
138
wxCHECK_MSG(m_editor, false, wxT("Invalid editor"));
140
if (overwrite_prompt && fileName.FileExists())
142
int overw = wxMessageBox(wxString::Format(_("Overwrite file : '%s'?\n"),
143
fileName.GetFullPath().wx_str()),
145
wxOK|wxCANCEL|wxCENTRE|wxICON_QUESTION, m_editor);
147
if (overw == wxCANCEL)
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;
164
if (!ret && msg_on_error)
166
wxMessageBox(wxString::Format(_("Unable to export to file : '%s'.\n"),
167
fileName.GetFullPath().wx_str()),
169
wxOK|wxCENTRE|wxICON_ERROR, m_editor);
175
wxString wxSTEditorExporter::GetExtension(int file_format)
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");
188
return wxEmptyString;
191
wxString wxSTEditorExporter::GetWildcards(int file_format)
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");
204
return wxFileSelectorDefaultWildcardStr;
207
int wxSTEditorExporter::SciToSTEStyle(int sci_style) const
209
int ste_lang_n = m_editor->GetLanguageId();
210
int ste_style = m_steLangs.SciToSTEStyle(ste_lang_n, sci_style);
212
return ste_style >= 0 ? ste_style : STE_STYLE_DEFAULT;
215
// SciTE - Scintilla based Text Editor
216
/** @file Exporters.cxx
217
** Export the current document to various markup languages.
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.
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
237
// From scite/src/SciTEBase.h/cxx copied here to allow for fewer changes below
238
class StyleDefinition {
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;
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;
263
void StyleDefinition::Create(const wxSTEditorStyles& styles, int ste_style)
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);
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_);
287
int IntFromHexDigit(int ch) {
288
if ((ch >= '0') && (ch <= '9')) {
290
} else if (ch >= 'A' && ch <= 'F') {
291
return ch - 'A' + 10;
292
} else if (ch >= 'a' && ch <= 'f') {
293
return ch - 'a' + 10;
299
int IntFromHexByte(const char *hexByte) {
300
return IntFromHexDigit(hexByte[0]) * 16 + IntFromHexDigit(hexByte[1]);
303
//---------- Save to RTF ----------
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 "}"
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"
329
#define RTF_EOLN "\\par\n"
330
#define RTF_TAB "\\tab "
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"
338
// extract the next RTF control word from *style
339
void GetRTFNextControl(char **style, char *control) {
343
if ('\0' == *pos) return;
344
pos++; // implicit skip over leading '\'
345
while ('\0' != *pos && '\\' != *pos) { pos++; }
347
memcpy(control, *style, len);
348
*(control + len) = '\0';
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;
358
// font face, size, color, background, bold, italic
359
for (int i = 0; i < 6; i++) {
360
GetRTFNextControl(&lastPos, lastControl);
361
GetRTFNextControl(¤tPos, currentControl);
362
if (strcmp(lastControl, currentControl)) { // changed
363
strcat(delta, currentControl);
366
if ('\0' != *delta) { strcat(delta, " "); }
367
strcpy(last, current);
370
bool wxSTEditorExporter::SaveToRTF(const wxFileName& saveName, int start, int end)
372
wxCHECK_MSG(m_editor, false, wxT("Invalid editor"));
375
int lengthDoc = m_editor->GetLength(); //LengthDocument();
380
m_editor->Colourise(0, -1); // wEditor.Call(SCI_COLOURISE, 0, -1);
382
// Read the default settings
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());
389
StyleDefinition defaultStyle(m_steStyles, STE_STYLE_DEFAULT);
390
//defaultStyle.ParseStyleDefinition(val);
392
//if (val) delete []valDefault;
393
//if (valdef) delete []valdefDefault;
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;
403
int fontSize = defaultStyle.size; //props.GetInt("export.rtf.font.size", 0);
405
defaultStyle.size = fontSize << 1;
406
} else if (defaultStyle.size == 0) {
407
defaultStyle.size = 10 << 1;
409
defaultStyle.size <<= 1;
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);
416
FILE *fp = wxFopen(saveName.GetFullPath(), wxT("wt"));
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);
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());
435
StyleDefinition sd(m_steStyles, SciToSTEStyle(istyle));
436
//sd.ParseStyleDefinition(val);
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]))
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());
447
sprintf(lastStyle, RTF_SETFONTFACE "%d", i);
449
strcpy(lastStyle, RTF_SETFONTFACE "0");
452
sprintf(lastStyle + strlen(lastStyle), RTF_SETFONTSIZE "%d",
453
wysiwyg && sd.size ? sd.size << 1 : defaultStyle.size);
455
if (sd.specified & StyleDefinition::sdFore) {
456
for (i = 0; i < colorCount; i++)
457
if (EqualCaseInsensitive_(sd.fore.c_str(), colors[i]))
460
strncpy(colors[colorCount++], sd.fore.c_str(), MAX_COLORDEF);
461
sprintf(lastStyle + strlen(lastStyle), RTF_SETCOLOR "%d", i);
463
strcat(lastStyle, RTF_SETCOLOR "0"); // Default fore
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]))
475
strncpy(colors[colorCount++], sd.back.c_str(), MAX_COLORDEF);
476
sprintf(lastStyle + strlen(lastStyle), RTF_SETBACKGROUND "%d", i);
478
strcat(lastStyle, RTF_SETBACKGROUND "1"); // Default back
480
if (sd.specified & StyleDefinition::sdBold) {
481
strcat(lastStyle, sd.bold ? RTF_BOLD_ON : RTF_BOLD_OFF);
483
strcat(lastStyle, defaultStyle.bold ? RTF_BOLD_ON : RTF_BOLD_OFF);
485
if (sd.specified & StyleDefinition::sdItalics) {
486
strcat(lastStyle, sd.italics ? RTF_ITALIC_ON : RTF_ITALIC_OFF);
488
strcat(lastStyle, defaultStyle.italics ? RTF_ITALIC_ON : RTF_ITALIC_OFF);
490
strncpy(styles[istyle], lastStyle, MAX_STYLEDEF);
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);
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));
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);
510
int styleCurrent = -1;
511
//WindowAccessor acc(wEditor.GetID(), props);
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)
518
if (style != styleCurrent) {
519
GetRTFStyleChange(deltaStyle, lastStyle, styles[style]);
521
fputs(deltaStyle, fp);
522
styleCurrent = style;
530
else if (ch == '\t') {
534
int ts = tabSize - (column % tabSize);
535
for (int itab = 0; itab < ts; itab++) {
540
} else if (ch == '\n') {
545
} else if (ch == '\r') {
553
fputs(RTF_BODYCLOSE, fp);
557
//FIMXE SString msg = LocaliseMessage("Could not save file '^0'.", filePath.AsFileSystem());
558
//WindowMessageBox(wSciTE, msg, MB_OK | MB_ICONWARNING);
564
//---------- Save to HTML ----------
566
bool wxSTEditorExporter::SaveToHTMLCSS(const wxFileName& saveName)
568
wxCHECK_MSG(m_editor, false, wxT("Invalid editor"));
572
m_editor->Colourise(0, -1); //SendEditor(SCI_COLOURISE, 0, -1);
573
int tabSize = m_editor->GetTabWidth(); //props.GetInt("tabsize");
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);
582
int lengthDoc = m_editor->GetLength(); //LengthDocument();
583
//WindowAccessor acc(wEditor.GetID(), props);
585
bool styleIsUsed[STYLE_MAX + 1];
586
if (onlyStylesUsed) {
588
for (i = 0; i <= STYLE_MAX; i++) {
589
styleIsUsed[i] = false;
591
// check the used styles
592
for (i = 0; i < lengthDoc; i++) {
593
styleIsUsed[m_editor->GetStyleAt(i) & 0x7F] = true;
596
for (int i = 0; i <= STYLE_MAX; i++) {
597
styleIsUsed[i] = true;
600
styleIsUsed[STYLE_DEFAULT] = true;
602
FILE *fp = wxFopen(saveName.GetFullPath(), wxT("wt"));
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);
608
fprintf(fp, "<title>%s</title>\n",
609
static_cast<const char *>(wx2stc(wxFileSystem::FileNameToURL(saveName)))); //FIXME filePath.AsFileSystem()));
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);
620
fputs("<script language=\"JavaScript\" type=\"text/javascript\">\n"
622
"function symbol(id, sym) {\n"
623
" if (id.textContent==undefined) {\n"
624
" id.innerText=sym; } else {\n"
625
" id.textContent=sym; }\n"
627
"function toggle(id) {\n"
628
"var thislayer=document.getElementById('ln'+id);\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"
637
" thislayer.style.display='none';\n"
638
" togline.style.textDecoration='underline';\n"
639
" symbol(togsym,'+ ');\n"
646
fputs("<style type=\"text/css\">\n", fp);
649
StyleDefinition sddef(m_steStyles, SciToSTEStyle(STE_STYLE_DEFAULT));
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());
657
StyleDefinition sddef(valdef);
658
sddef.ParseStyleDefinition(val);
659
if (sddef.back.length()) {
660
bgColour = sddef.back;
665
for (int istyle = 0; istyle <= STYLE_MAX; istyle++) {
666
if ((istyle > STYLE_DEFAULT) && (istyle <= STYLE_LASTPREDEFINED))
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());
674
StyleDefinition sd(m_steStyles, SciToSTEStyle(istyle));
675
//sd.ParseStyleDefinition(val);
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;
684
if (sd.specified != StyleDefinition::sdNone) {
685
if (istyle == STYLE_DEFAULT) {
686
fprintf(fp, "span {\n");
688
fprintf(fp, ".S%0d {\n", istyle);
691
fprintf(fp, "\tfont-style: italic;\n");
694
fprintf(fp, "\tfont-weight: bold;\n");
696
if (wysiwyg && sd.font.length()) {
697
fprintf(fp, "\tfont-family: '%s';\n", sd.font.c_str());
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");
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");
710
if (wysiwyg && sd.size) {
711
fprintf(fp, "\tfont-size: %0dpt;\n", sd.size);
715
styleIsUsed[istyle] = false; // No definition, it uses default style (32)
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());
727
fputs("<body>\n", fp);
729
int line = m_editor->LineFromPosition(0); // acc.GetLine(0);
730
int level = (m_editor->GetFoldLevel(line) & SC_FOLDLEVELNUMBERMASK) - SC_FOLDLEVELBASE;
732
int styleCurrent = m_editor->GetStyleAt(0);
733
bool inStyleSpan = false;
734
bool inFoldSpan = false;
735
// Global span for default attributes
743
int lvl = m_editor->GetFoldLevel(0);
744
level = (lvl & SC_FOLDLEVELNUMBERMASK) - SC_FOLDLEVELBASE;
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);
751
fputs(" ", fp);
755
if (styleIsUsed[styleCurrent]) {
756
fprintf(fp, "<span class=\"S%0d\">", styleCurrent);
759
// Else, this style has no definition (beside default one):
760
// no span for it, except the global one
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);
767
if (style != styleCurrent) {
769
fputs("</span>", fp);
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);
777
styleCurrent = style;
783
if (column == 0) { // At start of line, must put a because regular space will be collapsed
786
while (i < lengthDoc && (char)m_editor->GetCharAt(i) == ' ') { //acc[i] == ' ') {
792
prevCh = (char)m_editor->GetCharAt(i); //acc[i];
796
i--; // the last incrementation will be done by the for loop
801
} else if (ch == '\t') {
802
int ts = tabSize - (column % tabSize);
804
for (int itab = 0; itab < ts; itab++) {
817
for (int itab = 0; itab < ts; itab++) {
823
} else if (ch == '\r' || ch == '\n') {
825
fputs("</span>", fp);
829
fputs("</span>", fp);
832
if (ch == '\r' && (char)m_editor->GetCharAt(i + 1) == '\n') {
833
i++; // CR+LF line ending, skip the "extra" EOL char
840
styleCurrent = m_editor->GetStyleAt(i + 1);
842
line = m_editor->LineFromPosition(i + 1);
844
int lvl = m_editor->GetFoldLevel(line);
845
newLevel = (lvl & SC_FOLDLEVELNUMBERMASK) - SC_FOLDLEVELBASE;
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);
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);
858
fputs(" ", fp);
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);
889
fputs("</span>", fp);
894
fprintf(fp, "</span>");
902
fputs("</span>", fp);
905
fputs("\n</body>\n</html>\n", fp);
909
//FIXME SString msg = LocaliseMessage(
910
// "Could not save file \"^0\".", filePath.AsFileSystem());
911
//WindowMessageBox(wSciTE, msg, MB_OK | MB_ICONWARNING);
917
//---------- Save to PDF ----------
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
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.
930
Possible TODOs that will probably not be implemented: full styling,
931
optimization, font substitution, compression, character set encoding.
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"
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"
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 };
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) {
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);
967
sprintf(val, "0.%03d ", c);
969
strcat(pdfcolour, val);
973
bool wxSTEditorExporter::SaveToPDF(const wxFileName& saveName)
975
wxCHECK_MSG(m_editor, false, wxT("Invalid editor"));
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 {
984
long *offsetList, tableSize;
987
PDFObjectTracker(FILE *fp_) {
990
offsetList = new long[tableSize];
993
~PDFObjectTracker() {
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);
1001
void write(int objectData) {
1003
sprintf(val, "%d", objectData);
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];
1015
delete []offsetList;
1016
offsetList = newList;
1017
tableSize = newSize;
1019
// save offset, then format and write object
1020
offsetList[index - 1] = ftell(fp);
1027
// builds xref table, returns file offset of xref table
1030
// xref start index and number of entries
1031
long xrefStart = ftell(fp);
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]);
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.
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;
1063
PDFObjectTracker *oT;
1065
int fontSize; // properties supplied by user
1067
long pageWidth, pageHeight;
1068
PRRectangle pageMargin; // see PRRectangle above for compatibility w/ Scintilla's PRectangle
1071
pageStarted = false;
1074
buffer = new char[250];
1075
segStyle = new char[100];
1083
double fontToPoints(int thousandths) {
1084
return (double)fontSize * thousandths / 1000.0;
1086
void setStyle(char *buff, int style_) {
1087
int styleNext = style_;
1088
if (style_ == -1) { styleNext = styleCurrent; }
1090
if (styleNext != styleCurrent || style_ == -1) {
1091
if (style[styleCurrent].font != style[styleNext].font
1093
sprintf(buff, "/F%d %d Tf ",
1094
style[styleNext].font + 1, fontSize);
1096
if (strcmp(style[styleCurrent].fore, style[styleNext].fore) != 0
1098
strcat(buff, style[styleNext].fore);
1099
strcat(buff, "rg ");
1105
if (fontSize <= 0) {
1106
fontSize = PDF_FONTSIZE_DEFAULT;
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;
1115
int pageHeightMin = (int)leading + pageMargin.top + pageMargin.bottom;
1116
if (pageHeight < pageHeightMin) {
1117
pageHeight = pageHeightMin;
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;
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/"
1132
PDFfontNames[fontSet * 4 + i]);
1135
pageContentStart = oT->index;
1138
if (pageStarted) { // flush buffers
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);
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);
1165
sprintf(buffer, "]/Count %d\n>>\n", pageCount);
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);
1179
void add(char ch, int style_) {
1183
// get glyph width (TODO future non-monospace handling)
1184
double glyphWidth = fontToPoints(PDFfontWidths[fontSet]);
1186
// if cannot fit into a line, flush, wrap to next line
1187
if (xPos > pageWidth - pageMargin.right) {
1191
// if different style, then change to style
1192
if (style_ != styleCurrent) {
1194
// output code (if needed) for new style
1195
setStyle(segStyle, style_);
1196
stylePrev = styleCurrent;
1197
styleCurrent = style_;
1199
// escape these characters
1200
if (ch == ')' || ch == '(' || ch == '\\') {
1203
if (ch != ' ') { justWhiteSpace = false; }
1204
segment += ch; // add to segment data
1206
void flushSegment() {
1207
if (segment.length() > 0) {
1208
if (justWhiteSpace) { // optimise
1209
styleCurrent = stylePrev;
1211
pageData += segStyle;
1214
pageData += segment;
1215
pageData += ")Tj\n";
1217
segment.erase(); //clear(); MSVC6 doesn't have clear in their std::string
1219
justWhiteSpace = true;
1225
double fontAscender = fontToPoints(PDFfontAscenders[fontSet]);
1226
yPos = pageHeight - pageMargin.top - fontAscender;
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);
1234
xPos = pageMargin.left;
1235
segment.erase(); //clear(); MSVC6 doesn't have clear in their std::string
1239
pageStarted = false;
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"
1247
static_cast<int>(pageData.length() - 1 + 3),
1256
xPos = pageMargin.left;
1258
// PDF follows cartesian coords, subtract -> down
1260
double fontDescender = fontToPoints(PDFfontDescenders[fontSet]);
1261
if (yPos < pageMargin.bottom + fontDescender) {
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);
1272
sprintf(buffer, "T*\n");
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);
1284
tabSize = PDF_TAB_DEFAULT;
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")
1294
else if (propItem == "Helvetica")
1296
else if (propItem == "Times")
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;
1307
//next = GetNextPropItem(next, buffer, 32);
1308
if (0 >= (pr.pageHeight = 842)) {
1309
pr.pageHeight = PDF_HEIGHT_DEFAULT;
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;
1319
//next = GetNextPropItem(next, buffer, 32);
1320
if (0 >= (pr.pageMargin.right = 72)) {
1321
pr.pageMargin.right = PDF_MARGIN_DEFAULT;
1323
//next = GetNextPropItem(next, buffer, 32);
1324
if (0 >= (pr.pageMargin.top = 72)) {
1325
pr.pageMargin.top = PDF_MARGIN_DEFAULT;
1327
//GetNextPropItem(next, buffer, 32);
1328
if (0 >= (pr.pageMargin.bottom = 72)) {
1329
pr.pageMargin.bottom = PDF_MARGIN_DEFAULT;
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';
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());
1345
StyleDefinition sd(m_steStyles, SciToSTEStyle(i));
1346
//sd.ParseStyleDefinition(val);
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 ");
1356
// grab font size from default style
1357
if (i == STYLE_DEFAULT) {
1359
pr.fontSize += sd.size;
1361
pr.fontSize = PDF_FONTSIZE_DEFAULT;
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);
1375
FILE *fp = wxFopen(saveName.GetFullPath(), wxT("wb"));
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);
1383
// initialise PDF rendering
1384
PDFObjectTracker ot(fp);
1388
// do here all the writing
1389
int lengthDoc = m_editor->GetLength(); //LengthDocument();
1390
//TextReader acc(wEditor);
1392
if (!lengthDoc) { // enable zero length docs
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);
1402
int ts = tabSize - (lineIndex % tabSize);
1404
for (; ts; ts--) { // add ts count of spaces
1405
pr.add(' ', style); // add spaces
1407
} else if (ch == '\r' || ch == '\n') {
1408
if (ch == '\r' && (char)m_editor->GetCharAt(i + 1) == '\n') {
1411
// close and begin a newline...
1415
// write the character normally...
1421
// write required stuff and close the PDF file
1428
//---------- Save to TeX ----------
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);
1443
#define CHARZ ('z' - 'b')
1444
static char* texStyle(int style) {
1445
static char buf[10];
1448
buf[i++] = static_cast<char>('a' + (style % CHARZ));
1450
} while ( style > 0 );
1455
static void defineTexStyle(StyleDefinition &style, FILE* fp, int istyle) {
1456
int closing_brackets = 2;
1458
fprintf(fp, "\\newcommand{\\scite%s}[1]{\\noindent{\\ttfamily{", texStyle(istyle));
1459
if (style.italics) {
1460
fputs("\\textit{", fp);
1464
fputs("\\textbf{", fp);
1467
if (style.fore.length()) {
1468
fprintf(fp, "\\textcolor[rgb]{%s}{", getTexRGB(rgb, style.fore.c_str()) );
1471
if (style.back.length()) {
1472
fprintf(fp, "\\colorbox[rgb]{%s}{", getTexRGB( rgb, style.back.c_str()) );
1476
for (int i = 0; i <= closing_brackets; i++) {
1482
bool wxSTEditorExporter::SaveToTEX(const wxFileName& saveName)
1484
wxCHECK_MSG(m_editor, false, wxT("Invalid editor"));
1487
//RemoveFindMarks();
1488
m_editor->Colourise(0, -1); //SendEditor(SCI_COLOURISE, 0, -1);
1489
int tabSize = m_editor->GetTabWidth(); //props.GetInt("tabsize");
1494
int lengthDoc = m_editor->GetLength(); //LengthDocument();
1495
//TextReader acc(wEditor);
1496
bool styleIsUsed[STYLE_MAX + 1];
1498
//int titleFullPath = 0; //props.GetInt("export.tex.title.fullpath", 0);
1501
for (i = 0; i <= STYLE_MAX; i++) {
1502
styleIsUsed[i] = false;
1504
for (i = 0; i < lengthDoc; i++) { // check the used styles
1505
styleIsUsed[m_editor->GetStyleAt(i) & 0X7f] = true;
1507
styleIsUsed[STYLE_DEFAULT] = true;
1509
FILE *fp = wxFopen(saveName.GetFullPath(), wxT("wt"));
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);
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());
1526
StyleDefinition sd(m_steStyles, SciToSTEStyle(i)); //check default properties
1527
//sd.ParseStyleDefinition(val); //check language properties
1529
defineTexStyle(sd, fp, i); // writeout style macroses
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()));
1539
int styleCurrent = m_editor->GetStyleAt(0);
1541
fprintf(fp, "\\scite%s{", texStyle(styleCurrent));
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);
1549
if (style != styleCurrent) { //new style?
1550
fprintf(fp, "}\\scite%s{", texStyle(style) );
1551
styleCurrent = style;
1554
switch ( ch ) { //write out current character.
1556
int ts = tabSize - (lineIdx % tabSize);
1558
fprintf(fp, "\\hspace*{%dem}", ts);
1562
fputs("{\\textbackslash}", fp);
1567
fprintf(fp, "$%c$", ch);
1578
fprintf(fp, "\\%c", ch);
1582
lineIdx = -1; // Because incremented below
1583
if (ch == '\r' && (char)m_editor->GetCharAt(i + 1) == '\n')
1585
styleCurrent = m_editor->GetStyleAt(i + 1);
1586
fprintf(fp, "} \\\\\n\\scite%s{", texStyle(styleCurrent) );
1589
if ((char)m_editor->GetCharAt(i + 1) == ' ') {
1590
fputs("{\\hspace*{1em}}", fp);
1600
fputs("}\n} %end small\n\n\\end{document}\n", fp); //close last empty style macros and document too
1604
//FIXME SString msg = LocaliseMessage(
1605
// "Could not save file \"^0\".", filePath.AsFileSystem());
1606
//WindowMessageBox(wSciTE, msg, MB_OK | MB_ICONWARNING);
1612
//---------- Save to XML ----------
1614
bool wxSTEditorExporter::SaveToXML(const wxFileName& saveName)
1616
wxCHECK_MSG(m_editor, false, wxT("Invalid editor"));
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
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.
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.
1632
// <document> : the whole thing
1633
// <data> : reserved for metadata
1634
// <text> : the main bodyof text
1635
// <line n-'number'> : a line of text
1637
// <t n='number'>...<t/> : tag
1638
// <s n='number'/> : space
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).
1647
//RemoveFindMarks();
1648
m_editor->Colourise(0, -1); //SendEditor(SCI_COLOURISE, 0, -1) ;
1650
int tabSize = m_editor->GetTabWidth(); //props.GetInt("tabsize") ;
1655
int lengthDoc = m_editor->GetLength(); //LengthDocument() ;
1657
//TextReader acc(wEditor);
1659
FILE *fp = wxFopen(saveName.GetFullPath(), wxT("wt"));
1663
bool collapseSpaces = 1; //(props.GetInt("export.xml.collapse.spaces", 1) == 1) ;
1664
bool collapseLines = 1; //(props.GetInt("export.xml.collapse.lines", 1) == 1) ;
1666
fprintf(fp, "<?xml version='1.0' encoding='%s'?>\n", (m_editor->GetCodePage() == wxSTC_CP_UTF8) ? "utf-8" : "ascii");
1668
fputs("<document xmlns='http://www.scintila.org/scite.rng'", fp) ;
1669
fprintf(fp, " filename='%s'",
1671
(const char*)saveName.GetFullPath().mb_str()); //FIXME filePath.Name().AsFileSystem())) ;
1672
fprintf(fp, " type='%s'", "unknown") ;
1673
fprintf(fp, " version='%s'", "1.0") ;
1676
fputs("<data comment='This element is reserved for future usage.'/>\n", fp) ;
1678
fputs("<text>\n", fp) ;
1680
int styleCurrent = -1 ; // acc.StyleAt(0) ;
1681
int lineNumber = 1 ;
1683
bool styleDone = false ;
1684
bool lineDone = false ;
1685
bool charDone = false ;
1688
int emptyLines = 0 ;
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 ;
1699
} else if (ch == '\t') {
1700
int ts = tabSize - (lineIndex % tabSize) ;
1701
lineIndex += ts - 1 ;
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') {
1715
fputs("</line>\n", fp) ;
1717
} else if (collapseLines) {
1720
fprintf(fp, "<line n='%d'/>\n", lineNumber) ;
1724
styleCurrent = -1 ; // acc.StyleAt(i + 1) ;
1726
if (collapseLines && (emptyLines > 0)) {
1727
fputs("<line/>\n", fp) ;
1731
fprintf(fp, "<line n='%d'>", lineNumber) ;
1734
if (styleNew >= 0) {
1735
if (styleDone) { fputs("</t>", fp) ; }
1737
if (! collapseSpaces) {
1738
while (spaceLen > 0) {
1742
} else if (spaceLen == 1) {
1745
} else if (spaceLen > 1) {
1746
fprintf(fp, "<s n='%d'/>", spaceLen) ;
1749
if (styleNew >= 0) {
1750
fprintf(fp, "<t n='%d'>", style) ;
1778
fputs("</line>\n", fp) ;
1781
// no last empty line: fprintf(fp, "<line n='%d'/>", lineNumber) ;
1784
fputs("</text>\n", fp) ;
1785
fputs("</document>\n", fp) ;
1790
//FIXME SString msg = LocaliseMessage("Could not save file \"^0\".", filePath.AsFileSystem()) ;
1791
//WindowMessageBox(wSciTE, msg, MB_OK | MB_ICONWARNING) ;
1796
bool wxSTEditorExporter::SaveToHTML(const wxFileName& saveName)
1798
wxCHECK_MSG(m_editor, false, wxT("Invalid editor"));
1800
FILE *fp = wxFopen(saveName.GetFullPath(), wxT("wt"));
1803
fputs(wx2stc(RenderAsHTML(0, m_editor->GetLength())), fp);
1807
//FIMXE SString msg = LocaliseMessage("Could not save file '^0'.", filePath.AsFileSystem());
1808
//WindowMessageBox(wSciTE, msg, MB_OK | MB_ICONWARNING);
1813
// helper function to switch styles
1814
void STEExporterHTML_Font(int style_n, int old_style_n,
1815
StyleDefinition* sd, wxString &htmlString)
1817
// turn off old styles if style_n < 0 or styles differ
1818
if (old_style_n >= 0)
1820
if ((style_n < 0) || (sd[old_style_n].fore != sd[style_n].fore))
1821
htmlString << wxT("</FONT>");
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>");
1830
// turn on new styles, only if changed or set from invalid old style
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());
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>");
1846
// This modified code is from wxHatch, Copyright Chris Elliott
1847
wxString wxSTEditorExporter::RenderAsHTML(int from, int to) const
1849
wxCHECK_MSG(m_editor, wxEmptyString, wxT("Invalid editor"));
1852
bool wysiwyg = false; // FIXME
1853
wxFileName fileName = m_editor->GetFileName();
1855
m_editor->Colourise(0, -1);
1857
StyleDefinition sd[STYLE_MAX + 1]; // index is scintilla styles
1859
for (int s = 0; s <= STYLE_MAX; s++)
1860
sd[s].Create(m_steStyles, SciToSTEStyle(s));
1862
const wxString sOO = wxT("00");
1863
const wxString s8O = wxT("80");
1864
const wxString sFF = wxT("FF");
1866
wxString htmlString(wxT("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\">\n"));
1867
htmlString << wxT("<HTML>\n");
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");
1876
// FIXME: could also use <PRE WIDTH=80> for 80 column line widths
1877
htmlString << wxT("<BODY><TT><PRE>\n");
1879
int style_n = 0, old_style_n = -1; // start with invalid style
1881
// read document letter by letter
1882
for (int n = from; n < to; n++)
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
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);
1892
old_style_n = style_n;
1894
const wxChar c = m_editor->GetCharAt(n);
1895
//translate < > & \n etc
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')))
1903
// else fall through
1905
//case wxT('\n') : htmlString << wxT("\n<BR>"); break; // not if using PRE
1906
case wxT('<') : htmlString << wxT("<"); break;
1907
case wxT('>') : htmlString << wxT(">"); break;
1908
case wxT('&') : htmlString << wxT("&"); break;
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(" ");
1920
default : htmlString << c; break;
1924
// turn off last set styles (if any)
1925
STEExporterHTML_Font(-1, old_style_n, sd, htmlString);
1927
htmlString << wxT("\n</PRE></TT></BODY></HTML>");
1931
//-----------------------------------------------------------------------------
1932
// wxSTEditorExportDialog
1933
//-----------------------------------------------------------------------------
1934
IMPLEMENT_ABSTRACT_CLASS(wxSTEditorExportDialog, wxDialog);
1936
wxArrayString wxSTEditorExportDialog::sm_fileNames;
1937
int wxSTEditorExportDialog::sm_file_format = 0;
1939
BEGIN_EVENT_TABLE(wxSTEditorExportDialog, wxDialog)
1940
EVT_CHOICE (wxID_ANY, wxSTEditorExportDialog::OnChoice)
1941
EVT_BUTTON (wxID_ANY, wxSTEditorExportDialog::OnButton)
1944
wxSTEditorExportDialog::wxSTEditorExportDialog() : wxDialog()
1946
m_fileFormatChoice = NULL;
1947
m_fileNameCombo = NULL;
1950
wxSTEditorExportDialog::wxSTEditorExportDialog(wxWindow* parent, long style) : wxDialog()
1952
m_fileFormatChoice = NULL;
1953
m_fileNameCombo = NULL;
1955
Create(parent, style);
1958
bool wxSTEditorExportDialog::Create(wxWindow* parent,
1961
if (!wxDialog::Create(parent, wxID_ANY, _("Export file"), wxDefaultPosition, wxDefaultSize, style))
1964
SetIcons(wxSTEditorArtProvider::GetDialogIconBundle());
1965
wxSTEditorExportSizer(this, true, true);
1966
wxSTEditorStdDialogButtonSizer(this, wxOK | wxCANCEL);
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);
1973
m_fileFormatChoice->SetSelection(sm_file_format);
1975
wxBitmapButton *bmpButton = wxStaticCast(FindWindow(ID_STEDLG_EXPORT_FILENAME_BITMAPBUTTON), wxBitmapButton);
1976
bmpButton->SetBitmapLabel(STE_ARTTOOL(wxART_STEDIT_OPEN));
1979
SetMinSize(GetSize());
1985
wxFileName wxSTEditorExportDialog::GetFileName() const
1987
return m_fileNameCombo->GetValue();
1990
void wxSTEditorExportDialog::SetFileName(const wxFileName& fileName)
1992
wxSTEPrependComboBoxString(fileName.GetFullPath(), m_fileNameCombo, 10);
1993
m_fileNameCombo->SetValue(fileName.GetFullPath());
1994
m_fileNameCombo->SetFocus();
1996
STE_Export_Type wxSTEditorExportDialog::GetFileFormat() const
1998
return (STE_Export_Type)m_fileFormatChoice->GetSelection();
2000
void wxSTEditorExportDialog::SetFileFormat(STE_Export_Type file_format)
2002
m_fileFormatChoice->SetSelection((int)file_format);
2005
wxFileName wxSTEditorExportDialog::FileNameExtChange(const wxFileName& fileName, int file_format) const
2007
wxFileName fName(fileName);
2009
fName.SetExt(wxSTEditorExporter::GetExtension(file_format));
2013
void wxSTEditorExportDialog::OnChoice(wxCommandEvent& event)
2015
switch (event.GetId())
2017
case ID_STEDLG_EXPORT_FORMAT_CHOICE :
2019
if (wxStaticCast(FindWindow(ID_STEDLG_EXPORT_EXTENSION_CHECKBOX), wxCheckBox)->IsChecked())
2021
SetFileName(FileNameExtChange(GetFileName(), GetFileFormat()));
2029
void wxSTEditorExportDialog::OnButton(wxCommandEvent& event)
2031
switch (event.GetId())
2033
case ID_STEDLG_EXPORT_FILENAME_BITMAPBUTTON :
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 (*)|*");
2041
if (fileName.GetFullPath().Length())
2043
wxFileName fn(fileName);
2044
fileName = wxFileName(wxEmptyString, fn.GetFullName());
2045
wxString fileNamePath = fn.GetPath();
2046
if (fileNamePath.Length())
2048
path = fileNamePath;
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,
2057
if (fileName.GetFullPath().Length())
2059
if (wxStaticCast(FindWindow(ID_STEDLG_EXPORT_EXTENSION_CHECKBOX), wxCheckBox)->IsChecked())
2060
fileName = wxFileDialogBase::AppendExtension(fileName.GetFullPath(),
2062
SetFileName(fileName);
2069
wxSTEPrependArrayString(GetFileName().GetFullPath(), sm_fileNames, 10);
2070
sm_file_format = GetFileFormat();