1 // -*- mode: c++; c-file-style: "linux"; c-basic-offset: 2; indent-tabs-mode: nil -*-
2 //
3 // Copyright (C) 2004-2015 Andrej Vodopivec <andrej.vodopivec@gmail.com>
4 // (C) 2016-2018 Gunter Königsmann <wxMaxima@physikbuch.de>
5 //
6 // This program is free software; you can redistribute it and/or modify
7 // it under the terms of the GNU General Public License as published by
8 // the Free Software Foundation; either version 2 of the License, or
9 // (at your option) any later version.
10 //
11 // This program is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
15 //
16 //
17 // You should have received a copy of the GNU General Public License
18 // along with this program; if not, write to the Free Software
19 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 //
21 // SPDX-License-Identifier: GPL-2.0+
22
23 /*! \file
24 This file defines the class Configuration which serves as a fast configuration storage.
25 */
26
27 #include "Configuration.h"
28 #include "Dirstructure.h"
29 #include "ErrorRedirector.h"
30 #include <wx/wx.h>
31 #include <wx/string.h>
32 #include <wx/font.h>
33 #include <wx/config.h>
34 #include <wx/wfstream.h>
35 #include <wx/fileconf.h>
36 #include "Cell.h"
37
Configuration(wxDC * dc)38 Configuration::Configuration(wxDC *dc) :
39 m_dc(dc),
40 m_mathJaxURL("https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.6/MathJax.js?config=TeX-AMS_HTML"),
41 m_documentclass("article"),
42 m_documentclassOptions("fleqn"),
43 m_symbolPaneAdditionalChars("Øü§")
44 {
45 SetBackgroundBrush(*wxWHITE_BRUSH);
46 m_hidemultiplicationsign = true;
47 m_autoSaveAsTempFile = false;
48 m_inLispMode = false;
49 m_htmlEquationFormat = mathJaX_TeX;
50 m_autodetectMaxima = true;
51 m_clipToDrawRegion = true;
52 m_fontChanged = true;
53 m_mathJaxURL_UseUser = false;
54 m_TOCshowsSectionNumbers = false;
55 m_invertBackground = false;
56 m_antialiassingDC = NULL;
57 m_parenthesisDrawMode = unknown;
58 m_zoomFactor = 1.0; // affects returned fontsizes
59 m_useSVG = false;
60 m_changeAsterisk = true;
61 m_workSheet = NULL;
62 m_latin2greek = false;
63 m_enterEvaluates = false;
64 m_printScale = 1.0;
65 m_forceUpdate = false;
66 m_outdated = false;
67 m_printing = false;
68 m_TeXFonts = false;
69 m_notifyIfIdle = true;
70 m_fixReorderedIndices = true;
71 m_showBrackets = true;
72 m_printBrackets = false;
73 m_hideBrackets = true;
74 m_language = wxLANGUAGE_DEFAULT;
75 m_lineWidth_em = 88;
76 m_adjustWorksheetSizeNeeded = false;
77 m_showLabelChoice = labels_prefer_user;
78 m_abortOnError = true;
79 m_defaultPort = 49152;
80 m_maxGnuplotMegabytes = 12;
81 m_clientWidth = 1024;
82 m_clientHeight = 768;
83 m_indentMaths=true;
84 if(m_maximaLocation_override != wxEmptyString)
85 m_maximaUserLocation = m_maximaLocation_override;
86 else
87 m_maximaUserLocation = Dirstructure::Get()->MaximaDefaultLocation();
88 m_indent = -1;
89 m_autoSubscript = 1;
90 m_antiAliasLines = true;
91 m_showCodeCells = true;
92 m_greekSidebar_ShowLatinLookalikes = false;
93 m_greekSidebar_Show_mu = false;
94 m_copyBitmap = false; // Otherwise MS Office, OpenOffice and LibreOffice prefer the bitmap
95 // to Mathml and RTF. Also mail programs prefer bitmaps to text - which is counter-productive
96 // for maxima-discuss.
97 m_copyMathML = true;
98 m_copyMathMLHTML = false;
99 m_copyRTF = true;
100 m_copySVG = true;
101 m_copyEMF = false;
102 m_showLength = 2;
103 m_useUnicodeMaths = true;
104 m_offerKnownAnswers = true;
105 m_escCodes["pm"] = wxT("\u00B1");
106 m_escCodes["+/-"] = wxT("\u00B1");
107 m_escCodes["alpha"] = wxT("\u03B1");
108 m_escCodes["beta"] = wxT("\u03B2");
109 m_escCodes["gamma"] = wxT("\u03B3");
110 m_escCodes["delta"] = wxT("\u03B4");
111 m_escCodes["epsilon"] = wxT("\u03B5");
112 m_escCodes["zeta"] = wxT("\u03B6");
113 m_escCodes["eta"] = wxT("\u03B7");
114 m_escCodes["theta"] = wxT("\u03B8");
115 m_escCodes["iota"] = wxT("\u03B9");
116 m_escCodes["kappa"] = wxT("\u03BA");
117 m_escCodes["lambda"] = wxT("\u03BB");
118 m_escCodes["mu"] = wxT("\u03BC");
119 m_escCodes["nu"] = wxT("\u03BD");
120 m_escCodes["xi"] = wxT("\u03BE");
121 m_escCodes["om"] = wxT("\u03BF");
122 m_escCodes["omicron"] = wxT("\u03BF");
123 m_escCodes["nabla"] = wxT("\u2207");
124 m_escCodes["pi"] = wxT("\u03C0");
125 m_escCodes["rho"] = wxT("\u03C1");
126 m_escCodes["sigma"] = wxT("\u03C3");
127 m_escCodes["tau"] = wxT("\u03C4");
128 m_escCodes["upsilon"] = wxT("\u03C5");
129 m_escCodes["phi"] = wxT("\u03C6");
130 m_escCodes["chi"] = wxT("\u03C7");
131 m_escCodes["psi"] = wxT("\u03C8");
132 m_escCodes["omega"] = wxT("\u03C9");
133 m_escCodes["Alpha"] = wxT("\u0391");
134 m_escCodes["Beta"] = wxT("\u0392");
135 m_escCodes["Gamma"] = wxT("\u0393");
136 m_escCodes["Delta"] = wxT("\u0394");
137 m_escCodes["Epsilon"] = wxT("\u0395");
138 m_escCodes["Zeta"] = wxT("\u0396");
139 m_escCodes["Eta"] = wxT("\u0397");
140 m_escCodes["Theta"] = wxT("\u0398");
141 m_escCodes["Iota"] = wxT("\u0399");
142 m_escCodes["Kappa"] = wxT("\u039A");
143 m_escCodes["Lambda"] = wxT("\u039B");
144 m_escCodes["Mu"] = wxT("\u039C");
145 m_escCodes["Nu"] = wxT("\u039D");
146 m_escCodes["Xi"] = wxT("\u039E");
147 m_escCodes["Omicron"] = wxT("\u039F");
148 m_escCodes["Pi"] = wxT("\u03A0");
149 m_escCodes["Rho"] = wxT("\u03A1");
150 m_escCodes["Sigma"] = wxT("\u03A3");
151 m_escCodes["Tau"] = wxT("\u03A4");
152 m_escCodes["Upsilon"] = wxT("\u03A5");
153 m_escCodes["Phi"] = wxT("\u03A6");
154 m_escCodes["Chi"] = wxT("\u03A7");
155 m_escCodes["Psi"] = wxT("\u03A8");
156 m_escCodes["Omega"] = wxT("\u03A9");
157 m_escCodes["Ohm"] = wxT("\u03A9");
158 //////////////////////////
159 m_escCodes["^2"] = wxT("\u00B2");
160 m_escCodes["^3"] = wxT("\u00B3");
161 m_escCodes["/2"] = wxT("\u00BD");
162 m_escCodes["sq"] = wxT("\u221A");
163 m_escCodes["ii"] = wxT("\u2148");
164 m_escCodes["ee"] = wxT("\u2147");
165 m_escCodes["hb"] = wxT("\u210F");
166 m_escCodes["in"] = wxT("\u2208");
167 m_escCodes["impl"] = wxT("\u21D2");
168 m_escCodes["inf"] = wxT("\u221e");
169 m_escCodes["empty"] = wxT("\u2205");
170 m_escCodes["TB"] = wxT("\u25b6");
171 m_escCodes["tb"] = wxT("\u25b8");
172 m_escCodes["and"] = wxT("\u22C0");
173 m_escCodes["or"] = wxT("\u22C1");
174 m_escCodes["xor"] = wxT("\u22BB");
175 m_escCodes["nand"] = wxT("\u22BC");
176 m_escCodes["nor"] = wxT("\u22BD");
177 m_escCodes["implies"] = wxT("\u21D2");
178 m_escCodes["=>"] = wxT("\u21D2");
179 m_escCodes["equiv"] = wxT("\u21D4");
180 m_escCodes["<=>"] = wxT("\u21D4");
181 m_escCodes["not"] = wxT("\u00AC");
182 m_escCodes["union"] = wxT("\u22C3");
183 m_escCodes["inter"] = wxT("\u22C2");
184 m_escCodes["subseteq"] = wxT("\u2286");
185 m_escCodes["subset"] = wxT("\u2282");
186 m_escCodes["notsubseteq"] = wxT("\u2288");
187 m_escCodes["notsubset"] = wxT("\u2284");
188 m_escCodes["hbar"] = wxT("\u0127");
189 m_escCodes["Hbar"] = wxT("\u0126");
190 m_escCodes["partial"] = wxT("\u2202");
191 m_escCodes["integral"] = wxT("\u222b");
192 m_escCodes["approx"] = wxT("\u2245");
193 m_escCodes["prop"] = wxT("\u221d");
194 m_escCodes["propto"] = wxT("\u221d");
195 m_escCodes["neq"] = wxT("\u2260");
196 m_escCodes["!="] = wxT("\u2260");
197 m_escCodes["/="] = wxT("\u2260");
198 m_escCodes["#"] = wxT("\u2260");
199 m_escCodes["<="] = wxT("\u2264");
200 m_escCodes["leq"] = wxT("\u2264");
201 m_escCodes[">="] = wxT("\u2265");
202 m_escCodes["geq"] = wxT("\u2265");
203 m_escCodes["ll"] = wxT("\u226A");
204 m_escCodes["<<"] = wxT("\u226A");
205 m_escCodes["gg"] = wxT("\u226B");
206 m_escCodes[">>"] = wxT("\u226B");
207 m_escCodes["qed"] = wxT("\u220E");
208 m_escCodes["equiv"] = wxT("\u2263");
209 m_escCodes["sum"] = wxT("\u2211");
210 m_escCodes["prod"] = wxT("\u220F");
211 m_escCodes["product"] = wxT("\u220F");
212 m_escCodes["exists"] = wxT("\u2203");
213 m_escCodes["nexists"] = wxT("\u2204");
214 m_escCodes["parallel"] = wxT("\u2225");
215 m_escCodes["perp"] = wxT("\u27C2");
216 m_escCodes["perpendicular"] = wxT("\u27C2");
217 m_escCodes["bot"] = wxT("\u27C2");
218 m_escCodes["leadsto"] = wxT("\u219D");
219 m_escCodes["->"] = wxT("\u2192");
220 m_escCodes["-->"] = wxT("\u27F6");
221 m_escCodes[" --> "] = wxT("\u27F6");
222
223 m_parenthesisDrawMode = unknown;
224
225 #ifdef __WXMSW__
226 wxFont font;
227 font.SetFamily(wxFONTFAMILY_MODERN);
228 font.SetFaceName(wxT("Linux Libertine O"));
229 font.SetStyle(wxFONTSTYLE_NORMAL );
230 if(font.IsOk())
231 m_fontName = wxT("Linux Libertine O");
232 if(font.IsOk())
233 m_mathFontName = wxT("Linux Libertine O");
234 else
235 m_mathFontName = wxEmptyString;
236 #endif
237 m_mathFontSize = 12;
238 m_fontEncoding = wxFONTENCODING_DEFAULT;
239 m_styles[TS_DEFAULT].Set(_("Default"),*wxBLACK, true, true, false, 12);
240 m_styles[TS_TEXT].Set(_("Text cell"),*wxBLACK, false, false, false, 12);
241 m_styles[TS_CODE_VARIABLE].Set(_("Code highlighting: Variables"),wxColor(0,128,0), false, true, false);
242 m_styles[TS_CODE_FUNCTION].Set(_("Code highlighting: Functions"),wxColor(128,0,0), false, true, false);
243 m_styles[TS_CODE_COMMENT].Set(_("Code highlighting: Comments"),wxColor(64,64,64), false, true, false);
244 m_styles[TS_CODE_NUMBER].Set(_("Code highlighting: Numbers"),wxColor(128,64,0), false, true, false);
245 m_styles[TS_CODE_STRING].Set(_("Code highlighting: Strings"),wxColor(0,0,128), false, true, false);
246 m_styles[TS_CODE_OPERATOR].Set(_("Code highlighting: Operators"),*wxBLACK, false, true, false);
247 m_styles[TS_CODE_LISP].Set(_("Code highlighting: Lisp"),wxColor(255,0,128), false, true, false);
248 m_styles[TS_CODE_ENDOFLINE].Set(_("Code highlighting: End of line"),wxColor(128,128,128), false, true, false);
249 m_styles[TS_GREEK_CONSTANT].Set(_("Greek constants"),*wxBLACK, false, true, false);
250 m_styles[TS_HEADING6].Set(_("Heading 6"),*wxBLACK, true, false, false, 14);
251 m_styles[TS_HEADING5].Set(_("Heading 5"),*wxBLACK, true, false, false, 15);
252 m_styles[TS_SUBSUBSECTION].Set(_("Subsubsection cell (Heading 4)"),*wxBLACK, true, false, false, 16);
253 m_styles[TS_SUBSECTION].Set(_("Subsection cell (Heading 3)"),*wxBLACK, true, false, false, 16);
254 m_styles[TS_SECTION].Set(_("Section cell (Heading 2)"),*wxBLACK, true, true, false, 18);
255 m_styles[TS_TITLE].Set(_("Title cell (Heading 1)"),*wxBLACK, true, false, true, 24);
256 m_styles[TS_WARNING].Set(_("Maxima warnings"),wxColor(wxT("orange")), true, false, false, 12);
257 m_styles[TS_ERROR].Set(_("Maxima errors"),*wxRED, false, false, false, 12);
258 m_styles[TS_MAIN_PROMPT].Set(_("Input labels"),wxColor(wxT("rgb(255,128,128)")), false, false, false);
259 m_styles[TS_OTHER_PROMPT].Set(_("Maxima questions"),*wxRED, false, true, false);
260 m_styles[TS_LABEL].Set(_("Output labels"),wxColor(wxT("rgb(255,192,128)")), false, false, false);
261 m_styles[TS_USERLABEL].Set(_("User-defined labels"),wxColor(wxT("rgb(255,64,0)")), false, false, false);
262 m_styles[TS_SPECIAL_CONSTANT].Set(_("Special constants"),*wxBLACK, false, false, false);
263 m_styles[TS_INPUT].Set(_("Maxima input"),*wxBLUE, false, false, false);
264 m_styles[TS_NUMBER].Set(_("Numbers"),*wxBLACK, false, false, false);
265 m_styles[TS_STRING].Set(_("Strings"),*wxBLACK, false, true, false);
266 m_styles[TS_GREEK_CONSTANT].Set(_("Greek Constants"),*wxBLACK, false, false, false);
267 m_styles[TS_VARIABLE].Set(_("Variables"),*wxBLACK, false, true, false);
268 m_styles[TS_FUNCTION].Set(_("Function names"),*wxBLACK);
269 m_styles[TS_HIGHLIGHT].Set(_("Highlight (dpart)"),*wxRED);
270 m_styles[TS_TEXT_BACKGROUND].Set(_("Text cell background"),*wxWHITE);
271 m_styles[TS_DOCUMENT_BACKGROUND].Set(_("Document background"),*wxWHITE);
272 m_styles[TS_CELL_BRACKET].Set(_("Cell bracket"),wxColour(wxT("rgb(0,0,0)")));
273 m_styles[TS_ACTIVE_CELL_BRACKET].Set(_("Active cell bracket"),wxT("rgb(255,0,0)"));
274 m_styles[TS_CURSOR].Set(_("Cursor"),wxT("rgb(0,0,0)"));
275 m_styles[TS_SELECTION].Set(_("Selection"),wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHT));
276 m_styles[TS_EQUALSSELECTION].Set(_("Text equal to selection"),wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHT).ChangeLightness(150));
277 m_styles[TS_OUTDATED].Set(_("Outdated cells"),wxColor(wxT("rgb(153,153,153)")));
278 ReadConfig();
279 }
280
GetPPI(wxWindow * win) const281 wxSize Configuration::GetPPI(wxWindow *win) const
282 {
283 if(win == NULL)
284 return wxSize(96,96);
285
286 wxSize ppi(-1,-1);
287 #if wxCHECK_VERSION(3, 1, 1)
288 wxDisplay display;
289
290 int display_idx = wxDisplay::GetFromWindow(win);
291 if (display_idx < 0)
292 ppi = wxSize(72,72);
293 else
294 ppi = wxDisplay(display_idx).GetPPI();
295 #endif
296
297 if((ppi.x < 10) || (ppi.y < 10))
298 ppi = wxGetDisplayPPI();
299 if((ppi.x <= 10) || (ppi.y <= 10))
300 ppi = wxSize(72,72);
301
302 return ppi;
303 }
304
GetAutosubscript_string() const305 wxString Configuration::GetAutosubscript_string() const
306 {
307 switch (m_autoSubscript)
308 {
309 case 0:
310 return "nil";
311 case 1:
312 return "t";
313 default:
314 return "'all";
315 }
316 }
317
ShowCodeCells(bool show)318 void Configuration::ShowCodeCells(bool show)
319 {
320 m_showCodeCells = show;
321 }
322
SetBackgroundBrush(wxBrush brush)323 void Configuration::SetBackgroundBrush(wxBrush brush)
324 {
325 m_BackgroundBrush = brush;
326 m_tooltipBrush = brush;
327 m_tooltipBrush.SetColour(wxColour(255, 255, 192, 128));
328 }
329
MaximaFound(wxString location)330 bool Configuration::MaximaFound(wxString location)
331 {
332 if(location == wxEmptyString)
333 return false;
334
335 bool maximaFound = false;
336 if (wxFileExists(location))
337 maximaFound = true;
338
339 // Find a maxima within an application package.
340 if (wxFileExists(location + wxT("/Contents/Resources/maxima.sh")))
341 maximaFound = true;
342
343 // Don't complain if PATH doesn't yield a result.
344 SuppressErrorDialogs logNull;
345
346 if(!(location.EndsWith("/") || location.EndsWith("\\")))
347 {
348 wxPathList pathlist;
349 pathlist.AddEnvList(wxT("PATH"));
350 wxString path = pathlist.FindAbsoluteValidPath(location);
351 if (!path.empty())
352 maximaFound = true;
353 }
354 return maximaFound;
355 }
356
ReadConfig()357 void Configuration::ReadConfig()
358 {
359 wxConfigBase *config = wxConfig::Get();
360 m_autoWrap = 3;
361
362 if(!config->Read(wxT("AutoSaveAsTempFile"), &m_autoSaveAsTempFile))
363 {
364 long autoSaveMinutes = 0;
365 config->Read(wxT("autoSaveMinutes"), &autoSaveMinutes);
366 m_autoSaveAsTempFile = (autoSaveMinutes == 0);
367 }
368 config->Read("language", &m_language);
369 if (m_language == wxLANGUAGE_UNKNOWN)
370 m_language = wxLANGUAGE_DEFAULT;
371
372 config->Read("invertBackground", &m_invertBackground);
373 config->Read("maxGnuplotMegabytes", &m_maxGnuplotMegabytes);
374 config->Read("offerKnownAnswers", &m_offerKnownAnswers);
375 config->Read(wxT("documentclass"), &m_documentclass);
376 config->Read(wxT("documentclassoptions"), &m_documentclassOptions);
377 config->Read(wxT("latin2greek"), &m_latin2greek);
378 config->Read(wxT("enterEvaluates"), &m_enterEvaluates);
379 config->Read(wxT("hidemultiplicationsign"), &m_hidemultiplicationsign);
380 config->Read("greekSidebar_ShowLatinLookalikes", &m_greekSidebar_ShowLatinLookalikes);
381 config->Read("greekSidebar_Show_mu", &m_greekSidebar_Show_mu);
382 config->Read("symbolPaneAdditionalChars", &m_symbolPaneAdditionalChars);
383 config->Read("parameters", &m_maximaParameters);
384
385 {
386 int tmp;
387 config->Read("HTMLequationFormat", &tmp);
388 m_htmlEquationFormat = (Configuration::htmlExportFormat)tmp;
389 }
390
391 config->Read(wxT("TOCshowsSectionNumbers"), &m_TOCshowsSectionNumbers);
392 config->Read(wxT("autoWrapMode"), &m_autoWrap);
393 config->Read(wxT("mathJaxURL_UseUser"), &m_mathJaxURL_UseUser);
394 config->Read(wxT("useUnicodeMaths"), &m_useUnicodeMaths);
395 config->Read(wxT("mathJaxURL"), &m_mathJaxURL);
396 config->Read(wxT("autosubscript"), &m_autoSubscript);
397 config->Read(wxT("antiAliasLines"), &m_antiAliasLines);
398 config->Read(wxT("indentMaths"), &m_indentMaths);
399 config->Read(wxT("abortOnError"),&m_abortOnError);
400 config->Read("defaultPort",&m_defaultPort);
401 config->Read(wxT("fixReorderedIndices"), &m_fixReorderedIndices);
402 config->Read(wxT("showLength"), &m_showLength);
403 config->Read(wxT("printScale"), &m_printScale);
404 config->Read(wxT("useSVG"), &m_useSVG);
405 config->Read(wxT("copyBitmap"), &m_copyBitmap);
406 config->Read(wxT("copyMathML"), &m_copyMathML);
407 config->Read(wxT("copyMathMLHTML"), &m_copyMathMLHTML);
408 config->Read(wxT("copyRTF"), &m_copyRTF);
409 config->Read(wxT("copySVG"), &m_copySVG );
410 config->Read(wxT("copyEMF"), &m_copyEMF );
411 config->Read(wxT("autodetectMaxima"), &m_autodetectMaxima);
412 config->Read(wxT("maxima"), &m_maximaUserLocation);
413 // Fix wrong" maxima=1" parameter in ~/.wxMaxima if upgrading from 0.7.0a
414 if (m_maximaUserLocation.IsSameAs(wxT("1")))
415 m_maximaUserLocation = Dirstructure::Get()->MaximaDefaultLocation();
416
417 m_autoIndent = true;
418 config->Read(wxT("autoIndent"), &m_autoIndent);
419
420 int showLabelChoice;
421 config->Read(wxT("showLabelChoice"), &showLabelChoice);
422 m_showLabelChoice = (showLabels) showLabelChoice;
423
424 config->Read(wxT("changeAsterisk"), &m_changeAsterisk);
425
426 config->Read(wxT("notifyIfIdle"), &m_notifyIfIdle);
427
428 config->Read(wxT("hideBrackets"), &m_hideBrackets);
429
430 m_displayedDigits = 100;
431 config->Read(wxT("displayedDigits"), &m_displayedDigits);
432 if (m_displayedDigits <= 20)
433 m_displayedDigits = 20;
434
435 m_restartOnReEvaluation = true;
436 config->Read(wxT("restartOnReEvaluation"), &m_restartOnReEvaluation);
437
438 m_matchParens = true;
439 config->Read(wxT("matchParens"), &m_matchParens);
440
441 m_insertAns = false;
442 config->Read(wxT("insertAns"), &m_insertAns);
443
444 m_openHCaret = false;
445 config->Read(wxT("openHCaret"), &m_openHCaret);
446
447 m_labelWidth = 4;
448 config->Read(wxT("labelWidth"), &m_labelWidth);
449
450 config->Read(wxT("printBrackets"), &m_printBrackets);
451
452 m_zoomFactor = 1.0;
453 config->Read(wxT("ZoomFactor"), &m_zoomFactor);
454
455 if (wxFontEnumerator::IsValidFacename(m_fontCMEX = CMEX10) &&
456 wxFontEnumerator::IsValidFacename(m_fontCMSY = CMSY10) &&
457 wxFontEnumerator::IsValidFacename(m_fontCMRI = CMR10) &&
458 wxFontEnumerator::IsValidFacename(m_fontCMMI = CMMI10) &&
459 wxFontEnumerator::IsValidFacename(m_fontCMTI = CMTI10))
460 {
461 m_TeXFonts = true;
462 config->Read(wxT("usejsmath"), &m_TeXFonts);
463 }
464
465 m_keepPercent = true;
466 wxConfig::Get()->Read(wxT("keepPercent"), &m_keepPercent);
467
468 ReadStyles();
469 }
470
GetFont(TextStyle textStyle,long fontSize) const471 wxFont Configuration::GetFont(TextStyle textStyle, long fontSize) const
472 {
473 wxString fontName;
474 wxFontStyle fontStyle;
475 wxFontWeight fontWeight;
476 wxFontEncoding fontEncoding;
477 bool underlined = IsUnderlined(textStyle);
478
479 if ((textStyle == TS_TITLE) ||
480 (textStyle == TS_SECTION) ||
481 (textStyle == TS_SUBSECTION) ||
482 (textStyle == TS_SUBSUBSECTION) ||
483 (textStyle == TS_HEADING5) ||
484 (textStyle == TS_HEADING6))
485 {
486 // While titles and section names may be underlined the section number
487 // isn't. Else the space between section number and section title
488 // would look weird.
489 underlined = false;
490
491 // Besides that these items have a fixed font size.
492 fontSize = GetFontSize(textStyle);
493 }
494 if (fontSize < 4)
495 fontSize = 4;
496
497 // The font size scales with the worksheet
498 long fontSize1 = Scale_Px(fontSize);
499
500 // Ensure a sane minimum font size
501 if (fontSize1 < 4)
502 fontSize1 = 4;
503
504
505 fontName = GetFontName(textStyle);
506 fontStyle = IsItalic(textStyle);
507 fontWeight = IsBold(textStyle);
508
509 fontEncoding = GetFontEncoding();
510
511 wxFont font;
512 font.SetFamily(wxFONTFAMILY_MODERN);
513 font.SetFaceName(fontName);
514 font.SetEncoding(fontEncoding);
515 font.SetStyle(fontStyle);
516 font.SetWeight(fontWeight);
517 font.SetUnderlined(underlined);
518 font.SetEncoding(fontEncoding);
519 if (!font.IsOk())
520 {
521 font.SetFamily(wxFONTFAMILY_MODERN);
522 font.SetEncoding(fontEncoding);
523 font.SetStyle(fontStyle);
524 font.SetWeight(fontWeight);
525 font.SetUnderlined(underlined);
526 }
527
528 if (!font.IsOk())
529 font = *wxNORMAL_FONT;
530
531 font.SetPointSize(fontSize1);
532
533 return font;
534 }
535
DefaultBackgroundColor()536 wxColor Configuration::DefaultBackgroundColor()
537 {
538 if(InvertBackground())
539 return InvertColour(m_styles[TS_DOCUMENT_BACKGROUND].GetColor());
540 else
541 return m_styles[TS_DOCUMENT_BACKGROUND].GetColor();
542 }
543
EditorBackgroundColor()544 wxColor Configuration::EditorBackgroundColor()
545 {
546 if(InvertBackground())
547 return InvertColour(m_styles[TS_TEXT_BACKGROUND].GetColor());
548 else
549 return m_styles[TS_TEXT_BACKGROUND].GetColor();
550 }
551
SetPrinting(bool printing)552 void Configuration::SetPrinting(bool printing)
553 {
554 m_printing = printing;
555 if(printing)
556 m_invertBackground = false;
557 else
558 wxConfig::Get()->Read("invertBackground", m_invertBackground);
559 if(printing)
560 ClipToDrawRegion(false);
561 }
562
InvertColour(wxColour col)563 wxColour Configuration::InvertColour(wxColour col)
564 {
565 return wxColour(
566 255 - col.Red(),
567 255 - col.Green(),
568 255 - col.Blue(),
569 col.Alpha());
570 }
571
GetLineWidth() const572 long Configuration::GetLineWidth() const
573 {
574 // The default line width is the width of the viewport minus the indentation minus
575 // roughly one char
576 long lineWidth = m_clientWidth - Scale_Px(GetLabelWidth() +
577 GetCellBracketWidth() + GetDefaultFontSize());
578
579 // If that was suspiciously wide we reduce the default line width again.
580 if((lineWidth >= Scale_Px(double(GetDefaultFontSize())) * LineWidth_em()) &&
581 (!m_printing))
582 lineWidth = Scale_Px(double(GetDefaultFontSize())) * LineWidth_em();
583 return lineWidth;
584 }
585
GetParenthesisDrawMode()586 Configuration::drawMode Configuration::GetParenthesisDrawMode()
587 {
588 if(m_parenthesisDrawMode == unknown)
589 {
590 m_parenthesisDrawMode = handdrawn;
591 wxFont font = GetFont(TS_FUNCTION,20);
592 if (CharsExistInFont(font,
593 wxT(PAREN_OPEN_TOP_UNICODE),
594 wxT(PAREN_OPEN_EXTEND_UNICODE),
595 wxT(PAREN_OPEN_BOTTOM_UNICODE))
596 )
597 {
598 m_parenthesisDrawMode = assembled_unicode;
599 return m_parenthesisDrawMode;
600 }
601 font.SetFaceName(wxT("Linux Libertine"));
602 if (CharsExistInFont(font,
603 wxT(PAREN_OPEN_TOP_UNICODE),
604 wxT(PAREN_OPEN_EXTEND_UNICODE),
605 wxT(PAREN_OPEN_BOTTOM_UNICODE))
606 )
607 {
608 m_parenthesisDrawMode = assembled_unicode_fallbackfont;
609 return m_parenthesisDrawMode;
610 }
611
612 font.SetFaceName(wxT("Linux Libertine O"));
613 if (CharsExistInFont(font,
614 wxT(PAREN_OPEN_TOP_UNICODE),
615 wxT(PAREN_OPEN_EXTEND_UNICODE),
616 wxT(PAREN_OPEN_BOTTOM_UNICODE))
617 )
618 {
619 m_parenthesisDrawMode = assembled_unicode_fallbackfont2;
620 return m_parenthesisDrawMode;
621 }
622 }
623 return m_parenthesisDrawMode;
624 }
625
IsEqual(wxBitmap bitmap1,wxBitmap bitmap2)626 bool Configuration::IsEqual(wxBitmap bitmap1, wxBitmap bitmap2)
627 {
628 if (bitmap1.GetSize() != bitmap2.GetSize())
629 return false;
630
631 wxImage img1=bitmap1.ConvertToImage();
632 wxImage img2=bitmap2.ConvertToImage();
633 long bytes = img1.GetWidth()*img1.GetHeight()*3;
634
635 if(bytes < 0)
636 return false;
637
638 bool equal = (memcmp(img1.GetData(),img2.GetData(),bytes) == 0);
639 return equal;
640 }
641
SetZoomFactor(double newzoom)642 void Configuration::SetZoomFactor(double newzoom)
643 {
644 if (newzoom > GetMaxZoomFactor())
645 newzoom = GetMaxZoomFactor();
646 if (newzoom < GetMinZoomFactor())
647 newzoom = GetMinZoomFactor();
648
649 m_zoomFactor = newzoom;
650 wxConfig::Get()->Write(wxT("ZoomFactor"), m_zoomFactor);
651 RecalculationForce(true);
652 }
653
~Configuration()654 Configuration::~Configuration()
655 {
656 WriteStyles();
657 wxConfigBase *config = wxConfig::Get();
658 }
659
CharsExistInFont(wxFont font,wxString char1,wxString char2,wxString char3)660 bool Configuration::CharsExistInFont(wxFont font, wxString char1,wxString char2, wxString char3)
661 {
662 wxString name = char1 + char2 + char3;
663 CharsInFontMap::const_iterator it = m_charsInFontMap.find(name);
664 if(it != m_charsInFontMap.end())
665 return it->second;
666
667 if(!font.IsOk())
668 {
669 m_charsInFontMap[name] = false;
670 return false;
671 }
672 // Seems like Apple didn't hold to their high standards as the maths part of this font
673 // don't form nice big mathematical symbols => Blacklisting this font.
674 if (font.GetFaceName() == wxT("Monaco"))
675 {
676 m_charsInFontMap[name] = false;
677 return false;
678 }
679
680 if(!m_useUnicodeMaths)
681 {
682 m_charsInFontMap[name] = false;
683 return false;
684 }
685
686 // Letters with width or height = 0 don't exist in the current font
687 wxCoord width1,height1,descent1;
688 GetDC()->SetFont(font);
689 GetDC()->GetTextExtent(char1,&width1,&height1,&descent1);
690 if((width1 < 1) || (height1-descent1 < 1))
691 {
692 m_charsInFontMap[name] = false;
693 return false;
694 }
695 wxCoord width2,height2,descent2;
696 GetDC()->GetTextExtent(char2,&width2,&height2,&descent2);
697 if((width2 < 1) || (height2-descent2 < 1))
698 {
699 m_charsInFontMap[name] = false;
700 return false;
701 }
702 wxCoord width3,height3,descent3;
703 GetDC()->GetTextExtent(char3,&width3,&height3,&descent3);
704 if((width3 < 1) || (height3-descent3 < 1))
705 {
706 m_charsInFontMap[name] = false;
707 return false;
708 }
709
710 if(((width1 != width2) &&
711 (width1 != width3) &&
712 (width2 != width3))||
713 ((height1 != height2) &&
714 (height1 != height3) &&
715 (height2 != height3)))
716 {
717 m_charsInFontMap[name] = true;
718 return true;
719 }
720
721 wxBitmap bmp1(width1,height1);
722 wxMemoryDC dc1(bmp1);
723 dc1.SetFont(font);
724 dc1.SelectObject(bmp1);
725 dc1.Clear();
726 dc1.DrawText(char1,wxPoint(0,0));
727
728 wxBitmap bmp2(width2,height2);
729 wxMemoryDC dc2(bmp2);
730 dc2.SetFont(font);
731 dc2.SelectObject(bmp2);
732 dc2.Clear();
733 dc2.DrawText(char2,wxPoint(0,0));
734
735 wxBitmap bmp3(width3,height3);
736 wxMemoryDC dc3(bmp3);
737 dc3.SetFont(font);
738 dc3.SelectObject(bmp3);
739 dc3.Clear();
740 dc3.DrawText(char3,wxPoint(0,0));
741
742 if(IsEqual(bmp1,bmp2) || IsEqual(bmp2,bmp3) || IsEqual(bmp1,bmp3))
743 {
744 m_charsInFontMap[name] = false;
745 return false;
746 }
747 else
748 {
749 m_charsInFontMap[name] = false;
750 return true;
751 }
752 }
753
GetFontName(long type) const754 wxString Configuration::GetFontName(long type) const
755 {
756 wxString retval = FontName();
757 if (type == TS_TITLE || type == TS_SUBSECTION || type == TS_SUBSUBSECTION ||
758 type == TS_HEADING5 || type == TS_HEADING6 || type == TS_SECTION || type == TS_TEXT)
759 retval = m_styles[type].FontName();
760 if(retval == wxEmptyString)
761 retval = m_fontName;
762
763 if (type == TS_NUMBER || type == TS_VARIABLE || type == TS_FUNCTION ||
764 type == TS_SPECIAL_CONSTANT || type == TS_STRING)
765 retval = m_mathFontName;
766 return retval;
767 }
768
MaximaLocation() const769 wxString Configuration::MaximaLocation() const
770 {
771 if(m_autodetectMaxima)
772 return MaximaDefaultLocation();
773 else
774 return m_maximaUserLocation;
775 }
776
MaximaDefaultLocation()777 wxString Configuration::MaximaDefaultLocation()
778 {
779 return Dirstructure::Get()->MaximaDefaultLocation();
780 }
781
ReadStyles(wxString file)782 void Configuration::ReadStyles(wxString file)
783 {
784 wxConfigBase *config = NULL;
785 if (file == wxEmptyString)
786 config = wxConfig::Get();
787 else
788 {
789 wxFileInputStream str(file);
790 config = new wxFileConfig(str);
791 }
792
793 // Font
794 config->Read(wxT("Style/Default/Style/Text/fontname"), &m_fontName);
795 #ifdef __WXOSX_MAC__
796 if (m_fontName.IsEmpty())
797 {
798 m_fontName = "Monaco";
799 }
800 #endif
801
802 config->Read(wxT("mathfontsize"), &m_mathFontSize);
803 long encoding = m_fontEncoding;
804 config->Read(wxT("fontEncoding"), &encoding);
805 m_fontEncoding = (wxFontEncoding) encoding;
806 config->Read(wxT("Style/Math/fontname"), &m_mathFontName);
807 #ifdef __WXOSX_MAC__
808 if (m_mathFontName.IsEmpty())
809 {
810 m_mathFontName = "Monaco";
811 }
812 #endif
813
814 m_styles[TS_DEFAULT].Read(config, "Style/Default/");
815 m_styles[TS_TEXT].Read(config, "Style/Text/");
816 m_styles[TS_CODE_VARIABLE].Read(config, "Style/CodeHighlighting/Variable/");
817 m_styles[TS_CODE_FUNCTION].Read(config, "Style/CodeHighlighting/Function/");
818 m_styles[TS_CODE_COMMENT].Read(config, "Style/CodeHighlighting/Comment/");
819 m_styles[TS_CODE_NUMBER].Read(config, "Style/CodeHighlighting/Number/");
820 m_styles[TS_CODE_STRING].Read(config, "Style/CodeHighlighting/String/");
821 m_styles[TS_CODE_OPERATOR].Read(config, "Style/CodeHighlighting/Operator/");
822 m_styles[TS_CODE_LISP].Read(config, "Style/CodeHighlighting/Lisp/");
823 m_styles[TS_CODE_ENDOFLINE].Read(config, "Style/CodeHighlighting/EndOfLine/");
824 m_styles[TS_HEADING6].Read(config, "Style/Heading6/");
825 m_styles[TS_HEADING5].Read(config, "Style/Heading5/");
826 m_styles[TS_SUBSUBSECTION].Read(config, "Style/Subsubsection/");
827 m_styles[TS_SUBSECTION].Read(config, "Style/Subsection/");
828 m_styles[TS_SECTION].Read(config, "Style/Section/");
829 m_styles[TS_TITLE].Read(config, "Style/Title/");
830 m_styles[TS_WARNING].Read(config, "Style/Warning/");
831 m_styles[TS_MAIN_PROMPT].Read(config, "Style/MainPrompt/");
832 m_styles[TS_OTHER_PROMPT].Read(config, "Style/OtherPrompt/");
833 m_styles[TS_LABEL].Read(config, "Style/Label/");
834 m_styles[TS_USERLABEL].Read(config, "Style/UserDefinedLabel/");
835 m_styles[TS_SPECIAL_CONSTANT].Read(config, "Style/Special/");
836 m_styles[TS_GREEK_CONSTANT].Read(config, "Style/Greek/");
837 m_styles[TS_INPUT].Read(config, "Style/Input/");
838 m_styles[TS_NUMBER].Read(config, "Style/Number/");
839 m_styles[TS_STRING].Read(config, "Style/String/");
840 m_styles[TS_GREEK_CONSTANT].Read(config, "Style/Greek/");
841 m_styles[TS_VARIABLE].Read(config, "Style/Variable/");
842 m_styles[TS_FUNCTION].Read(config, "Style/Function/");
843 m_styles[TS_HIGHLIGHT].Read(config, "Style/Highlight/");
844 m_styles[TS_TEXT_BACKGROUND].Read(config, "Style/Background/");
845 m_styles[TS_DOCUMENT_BACKGROUND].Read(config, "Style/DocumentBackground/");
846 m_styles[TS_ERROR].Read(config, "Style/Error/");
847 m_styles[TS_CELL_BRACKET].Read(config, "Style/CellBracket/");
848 m_styles[TS_ACTIVE_CELL_BRACKET].Read(config,wxT("Style/ActiveCellBracket/"));
849 m_styles[TS_CURSOR].Read(config,wxT("Style/ActiveCellBracket/"));
850 m_styles[TS_SELECTION].Read(config,wxT("Style/Selection/"));
851 m_styles[TS_EQUALSSELECTION].Read(config,wxT("Style/EqualsSelection/"));
852 m_styles[TS_OUTDATED].Read(config,wxT("Style/Outdated/"));
853 m_BackgroundBrush = *wxTheBrushList->FindOrCreateBrush(m_styles[TS_DOCUMENT_BACKGROUND].GetColor(), wxBRUSHSTYLE_SOLID);
854
855 }
856
857 //! Saves the style settings to a file.
WriteStyles(wxString file)858 void Configuration::WriteStyles(wxString file)
859 {
860 wxConfigBase *config = NULL;
861 if (file == wxEmptyString)
862 config = wxConfig::Get();
863 else
864 config = new wxFileConfig(wxT("wxMaxima"), wxEmptyString, file);
865
866 // Font
867 config->Write("Style/Default/Style/Text/fontname", m_fontName);
868 config->Write(wxT("mathfontsize"), m_mathFontSize);
869 config->Write(wxT("fontEncoding"), static_cast<int>(m_fontEncoding));
870 config->Write("Style/Math/fontname", m_mathFontName);
871
872 m_styles[TS_DEFAULT].Write(config, "Style/Default/");
873 m_styles[TS_TEXT].Write(config, "Style/Text/");
874 m_styles[TS_CODE_VARIABLE].Write(config, "Style/CodeHighlighting/Variable/");
875 m_styles[TS_CODE_FUNCTION].Write(config, "Style/CodeHighlighting/Function/");
876 m_styles[TS_CODE_COMMENT].Write(config, "Style/CodeHighlighting/Comment/");
877 m_styles[TS_CODE_NUMBER].Write(config, "Style/CodeHighlighting/Number/");
878 m_styles[TS_CODE_STRING].Write(config, "Style/CodeHighlighting/String/");
879 m_styles[TS_CODE_OPERATOR].Write(config, "Style/CodeHighlighting/Operator/");
880 m_styles[TS_CODE_LISP].Write(config, "Style/CodeHighlighting/Lisp/");
881 m_styles[TS_CODE_ENDOFLINE].Write(config, "Style/CodeHighlighting/EndOfLine/");
882 m_styles[TS_HEADING6].Write(config, "Style/Heading6/");
883 m_styles[TS_HEADING5].Write(config, "Style/Heading5/");
884 m_styles[TS_SUBSUBSECTION].Write(config, "Style/Subsubsection/");
885 m_styles[TS_SUBSECTION].Write(config, "Style/Subsection/");
886 m_styles[TS_SECTION].Write(config, "Style/Section/");
887 m_styles[TS_TITLE].Write(config, "Style/Title/");
888 m_styles[TS_WARNING].Write(config, "Style/Warning/");
889 m_styles[TS_MAIN_PROMPT].Write(config, "Style/MainPrompt/");
890 m_styles[TS_OTHER_PROMPT].Write(config, "Style/OtherPrompt/");
891 m_styles[TS_LABEL].Write(config, "Style/Label/");
892 m_styles[TS_USERLABEL].Write(config, "Style/UserDefinedLabel/");
893 m_styles[TS_SPECIAL_CONSTANT].Write(config, "Style/Special/");
894 m_styles[TS_GREEK_CONSTANT].Write(config, "Style/Greek/");
895 m_styles[TS_INPUT].Write(config, "Style/Input/");
896 m_styles[TS_NUMBER].Write(config, "Style/Number/");
897 m_styles[TS_STRING].Write(config, "Style/String/");
898 m_styles[TS_GREEK_CONSTANT].Write(config, "Style/Greek/");
899 m_styles[TS_VARIABLE].Write(config, "Style/Variable/");
900 m_styles[TS_FUNCTION].Write(config, "Style/Function/");
901 m_styles[TS_HIGHLIGHT].Write(config, "Style/Highlight/");
902 m_styles[TS_TEXT_BACKGROUND].Write(config, "Style/Background/");
903 m_styles[TS_DOCUMENT_BACKGROUND].Write(config, "Style/DocumentBackground/");
904 m_styles[TS_ERROR].Write(config, "Style/Error/");
905 m_styles[TS_CELL_BRACKET].Write(config, "Style/CellBracket/");
906 m_styles[TS_ACTIVE_CELL_BRACKET].Write(config,wxT("Style/ActiveCellBracket/"));
907 m_styles[TS_CURSOR].Write(config,wxT("Style/ActiveCellBracket/"));
908 m_styles[TS_SELECTION].Write(config,wxT("Style/Selection/"));
909 m_styles[TS_EQUALSSELECTION].Write(config,wxT("Style/EqualsSelection/"));
910 m_styles[TS_OUTDATED].Write(config,wxT("Style/Outdated/"));
911 if(file != wxEmptyString)
912 {
913 config->Flush();
914 delete config;
915 }
916 }
917
IsBold(long st) const918 wxFontWeight Configuration::IsBold(long st) const
919 {
920 if (m_styles[st].Bold())
921 return wxFONTWEIGHT_BOLD;
922 return wxFONTWEIGHT_NORMAL;
923 }
924
IsItalic(long st) const925 wxFontStyle Configuration::IsItalic(long st) const
926 {
927 if (m_styles[st].Italic())
928 return wxFONTSTYLE_SLANT;
929 return wxFONTSTYLE_NORMAL;
930 }
931
GetSymbolFontName() const932 wxString Configuration::GetSymbolFontName() const
933 {
934 #if defined __WXMSW__
935 return wxT("Symbol");
936 #else
937 return m_fontName;
938 #endif
939 }
940
GetColor(TextStyle style)941 wxColour Configuration::GetColor(TextStyle style)
942 {
943 wxColour col = m_styles[style].GetColor();
944 if (m_outdated)
945 col = m_styles[TS_OUTDATED].Color();
946
947 if(InvertBackground() &&
948 (style != TS_TEXT_BACKGROUND) &&
949 (style != TS_DOCUMENT_BACKGROUND))
950 col = MakeColorDifferFromBackground(col);
951 return col;
952 }
953
Scale_Px(double px) const954 long Configuration::Scale_Px(double px) const
955 {
956 long retval = round(px * GetZoomFactor());
957 if (retval < 1)
958 retval = 1;
959 return retval;
960 }
961
MakeColorDifferFromBackground(wxColor color)962 wxColor Configuration::MakeColorDifferFromBackground(wxColor color)
963 {
964 int newBrightness = 255 - (color.Red() + color.Green() + color.Blue()) / 3;
965 if(color == DefaultBackgroundColor())
966 {
967 return InvertColour(color);
968 }
969 else
970 {
971 int maxOldCol = wxMax(wxMax(color.Red(), color.Green()), color.Blue());
972 return wxColour(
973 newBrightness * color.Red() / maxOldCol,
974 newBrightness * color.Green() / maxOldCol,
975 newBrightness * color.Blue() / maxOldCol
976 );
977 }
978 }
979
980 wxString Configuration::m_maximaLocation_override;
981 wxString Configuration::m_configfileLocation_override;
982