1 /**
2 * Yudit Unicode Editor Source File
3 *
4 * GNU Copyright (C) 1997-2006 Gaspar Sinai <gaspar@yudit.org>
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, version 2,
8 * dated June 1991. See file COPYYING for details.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19
20 #include "gui/SYudit.h"
21 #include "gui/Main.h"
22 #include "stoolkit/SUtil.h"
23 #include "stoolkit/SEncoder.h"
24 #include "stoolkit/SIO.h"
25 #include "stoolkit/STypes.h"
26 #include "stoolkit/SIOStream.h"
27 #include "swidget/SUniPrint.h"
28 #include "swidget/SIconFactory.h"
29 #include <swindow/SPrinter.h>
30 #include <swindow/SScriptProcessor.h>
31 #include <stdlib.h>
32
33 static SString translateHighlightMode (const SString& hl);
34 static SString getPrintHelp ();
35 static int getLineNumber (const SString& s);
36
37 #define SGC_DOUBLE_BUFFER true
38
39 #define CRYPT_FILE_MATCHER "*.sedy"
40 #define CRYPT_MIN_PASSWORD_SIZE 4
41
42 #define SYUDIT_AUTO_KEYBOARD true
43
44 /**
45 * A caret that redraws itself differently for lr and rl text
46 */
SYudit(const SStringVector & args,const SProperties & props,const SString & sedyLib)47 SYudit::SYudit (const SStringVector& args, const SProperties& props, const SString& sedyLib)
48 {
49 passwordDialog = 0;
50 deferredLoader = 0;
51 sedyLibrary = sedyLib;
52 if (sedyLibrary.size()) {
53 cryptFileMatcher = SString(CRYPT_FILE_MATCHER);
54 }
55 // No use to make this main window double buffered
56 // because it almost only redraws its borders and that's it
57 // This is done in SFrame.
58 // setThisDoubleBuffered (false);
59 SPanel::setAllDoubleBuffered (SGC_DOUBLE_BUFFER);
60 // preparse args
61 unsigned int i;
62 for (i=1; i<args.size(); i++)
63 {
64 // fprintf (stderr, "SGCARG[%i] %*.*s\n", i, SSARGS(args[i]));
65 if (args[i] == SString("--"))
66 {
67 break;
68 }
69 else if (args[i] == SString("-ndb"))
70 {
71 SPanel::setAllDoubleBuffered (false);
72 }
73 else if (args[i] == SString("-db"))
74 {
75 SPanel::setAllDoubleBuffered (true);
76 }
77 }
78
79 freeHandShown = false;
80 encrypted = false;
81 freehand = 0;
82 freeHandHeight = 0;
83 setLayout (SLayout (SLocation (0,0), SLocation (3000,2000)));
84 originalProperties = props;
85
86 /* TODO: move this to config file */
87 helpStrings.put ("hilfe", "de");
88 SEncoder kana("Kana");
89 SEncoder utf8("utf-8-s");
90 helpStrings.put (utf8.encode (kana.decode ("HERUPU", false)), "ja");
91 SEncoder hung("Hungarian");
92 helpStrings.put ("segit", "hu");
93 helpStrings.put (utf8.encode (hung.decode ("segi't", false)), "hu");
94 helpStrings.put (utf8.encode (hung.decode ("segi'tse'g", false)), "hu");
95 SEncoder yidd("Yiddish");
96 SV_UCS4 yi0;
97 yi0.append (SD_CD_RLO);
98 yi0.append (yidd.decode ("gehilF", false));
99 yi0.append (SD_CD_PDF);
100 SV_UCS4 yi1;
101 yi1.append (SD_CD_RLO);
102 yi1.append (yidd.decode ("helF", false));
103 yi1.append (SD_CD_PDF);
104 helpStrings.put (utf8.encode (yi0), "yi");
105 helpStrings.put (utf8.encode (yi1), "yi");
106 helpStrings.put (utf8.encode (yidd.decode ("gehilF", false)), "yi");
107 helpStrings.put (utf8.encode (yidd.decode ("helF", false)), "yi");
108 helpStrings.put ("ayuda", "es");
109
110 configFile = props["yudit.config"];
111
112 char fnc[64];
113 /* get an unused filename */
114 for (unsigned int fn=0; fn<100000; fn++)
115 {
116 if (fn==0)
117 {
118 sprintf (fnc, "untitled.txt");
119 }
120 else
121 {
122 sprintf (fnc, "untitled%d.txt", fn);
123 }
124 currentFileName = SString (fnc);
125
126 SFile cfile (currentFileName);
127 if (cfile.size() < 0) break;
128 }
129 lastprinterOption = props["yudit.default.printer.options"];
130 lastpreviewOption ="-e ";
131 lastpreviewOption.append (props["yudit.default.preview.command"]);
132 lastpreviewOption.replaceAll("\\", "/");
133 lastpreviewOption.replaceAll("//", "/");
134 lastencoding=props["yudit.default.filetype"];
135
136 setFrameListener (this);
137 command = new STextEdit ();
138 SString commandFont ("default");
139 if (props.get("yudit.command.font"))
140 {
141 commandFont = props["yudit.command.font"];
142 }
143 SString commandFontSizeString ("16");
144 if (props.get("yudit.command.fontsize"))
145 {
146 commandFontSizeString = props["yudit.command.fontsize"];
147 }
148 commandFontSizeString.append ((char)0);
149 double commandFontSize=0;
150 sscanf (commandFontSizeString.array(), "%lf", &commandFontSize);
151
152 if (commandFontSize < 2.0) commandFontSize = 2.0;
153 command->setFont (commandFont, commandFontSize);
154 unsigned int commandHeight = command->getPreferredSize().height;
155 command->setMultiline (false);
156 command->setLineEndMark (false);
157
158 messagebar = new SMessageBar (props);
159 unsigned int msgbarHeight = messagebar->getPreferredSize().height;
160
161
162 toolbar = new SToolBar (props);
163 unsigned int toobarHeight = toolbar->getPreferredSize().height;
164
165 toolbar->setLayout (
166 SLayout (
167 SLocation (2,0),
168 SLocation (2998, toobarHeight+0),
169 SLocation (0, 0),
170 SLocation (100, 0)
171 )
172 );
173 toolbar->setListener (this);
174
175
176 messagelabel = new SMessageLabel (props);
177 unsigned int messagelabeHeight = messagelabel->getPreferredSize().height;
178
179 messagelabel->setLayout (
180 SLayout (
181 SLocation (2, 1998-messagelabeHeight),
182 SLocation (2998, 1998),
183 SLocation (0, 100),
184 SLocation (100, 100)
185 )
186 );
187 command->setLayout (
188 SLayout (
189 SLocation (2, 1998-commandHeight-messagelabeHeight),
190 SLocation (2998, 1998-messagelabeHeight),
191 SLocation (0, 100),
192 SLocation (100, 100)
193 )
194 );
195
196 messagebar->setLayout (
197 SLayout (
198 SLocation (2,1998-msgbarHeight-commandHeight-messagelabeHeight),
199 SLocation (2998, 1998-commandHeight-messagelabeHeight),
200 SLocation (0, 100),
201 SLocation (100, 100)
202 )
203 );
204
205 sliderLayout = SLayout (
206 SLocation (2978, toobarHeight+2),
207 SLocation (2998, 1998 - commandHeight - msgbarHeight - messagelabeHeight),
208 SLocation (100, 0),
209 SLocation (100, 100)
210 );
211
212 slider = new SSlider ();
213 slider->setLayout (sliderLayout);
214 /* on mac somehow it did not want to resize - force it */
215 slider->resize (SDimension (10, 200));
216
217 SString currentFont = toolbar->fonts[toolbar->currentFont];
218 SString currentFontSize = toolbar->fontsizes[toolbar->currentFontSize];
219 SString currentInput = toolbar->inputs[toolbar->currentInput];
220 SString currentParagraphSeparator = toolbar->paragraphBreaks[toolbar->currentParagraphSeparator];
221
222
223 editor = new STextEdit ();
224 editor->addSyntaxListener (toolbar);
225
226 currentFontSize.append ((char)0);
227 double df;
228 if (sscanf (currentFontSize.array(), "%lf", &df)==0 || df < 2.0) df = 2.0;
229 editor->setFont (currentFont, df);
230
231 editor->setMultiline (true);
232 editor->setLineEndMark (true);
233 editor->setDocumentEmbedding (toolbar->currentEmbedding);
234
235 editorLayout =
236 SLayout (
237 SLocation (2, toobarHeight+2),
238 SLocation (2978, 1998 - commandHeight - msgbarHeight - messagelabeHeight),
239 SLocation (0, 0),
240 SLocation (100, 100)
241 );
242 editor->setLayout (editorLayout);
243
244 /*SGC */
245 SString inputStyle = originalProperties["yudit.editor.xinputs.style"];
246
247 /* allowed styles */
248 if (inputStyle=="preedit-over-status-under"
249 || inputStyle == "preedit-under-status-under"
250 || inputStyle=="preedit-over-status-over"
251 || inputStyle == "preedit-root-status-root" )
252 {
253 SProperties p;
254 SColor cbg(originalProperties["yudit.background"]);
255 SColor cfg(originalProperties["yudit.label.foreground"]);
256
257 sprintf (fnc, "%lu,%lu", (unsigned long)cbg.getValue(),
258 (unsigned long)cfg.getValue());
259 p.put ("InputClientColor", fnc);
260
261 SColor sbg(originalProperties["yudit.background"]);
262 SColor sfg(originalProperties["yudit.title.foreground"]);
263
264 sprintf (fnc, "%lu,%lu", (unsigned long)sbg.getValue(),
265 (unsigned long)sfg.getValue());
266 p.put ("InputStatusColor", fnc);
267 editor->setXIMProperties (p);
268
269 p.put ("InputStyle", inputStyle);
270 editor->setXIMProperties (p);
271 }
272 else
273 {
274 fprintf (stderr, "Yudit: unknown yudit.editor.xinputs.style=%*.*s\n",
275 SSARGS(inputStyle));
276 }
277
278 /* showInputStatus has set up the xim properties for editor */
279 editor->setInputMethod (currentInput);
280
281 if (currentInput.size() > 2)
282 {
283 if (currentInput != SS_KINPUT2_IM
284 && currentInput != SS_WINDOWS_IM
285 && currentInput[0] != 'x'
286 && currentInput[1] != 'X')
287 {
288 command->setInputMethod (currentInput);
289 }
290 }
291 if (props["yudit.editor.showbreak"]=="true")
292 {
293 editor->setLineEndMark (true);
294 }
295 else
296 {
297 editor->setLineEndMark (false);
298 }
299 if (props["yudit.editor.wordwrap"]=="true")
300 {
301 editor->setWordWrap (true);
302 }
303 else
304 {
305 editor->setWordWrap (false);
306 }
307 SSyntaxColors syn;
308 syn.colors[(unsigned int) SSyntax::SD_NONE] = SColor ("cyan");
309 /*
310 got rid of none. For errors and none we use the default fg.
311 = props.getProperty ("yudit.editor.syntax.none.foreground", "green");
312 */
313
314 syn.colors[(unsigned int) SSyntax::SD_ERROR]
315 = props.getProperty ("yudit.editor.syntax.error.foreground", "OrangeRed3");
316 syn.colors[(unsigned int) SSyntax::SD_NUMBER]
317 = props.getProperty ("yudit.editor.syntax.number.foreground", "orange");
318 syn.colors[(unsigned int) SSyntax::SD_STRING]
319 = props.getProperty ("yudit.editor.syntax.string.foreground", "magenta");
320 syn.colors[(unsigned int) SSyntax::SD_COMMENT]
321 = props.getProperty ("yudit.editor.syntax.comment.foreground", "lightgray");
322 syn.colors[(unsigned int) SSyntax::SD_KEYWORD]
323 = props.getProperty ("yudit.editor.syntax.token.foreground", "yellow");
324 syn.colors[(unsigned int) SSyntax::SD_VARIABLE]
325 = props.getProperty ("yudit.editor.syntax.variable.foreground", "red");
326 syn.colors[(unsigned int) SSyntax::SD_DEFINE]
327 = props.getProperty ("yudit.editor.syntax.define.foreground", "cyan");
328 syn.colors[(unsigned int) SSyntax::SD_CONTROL]
329 = props.getProperty ("yudit.editor.syntax.control.foreground", "CornflowerBlue");
330 syn.colors[(unsigned int) SSyntax::SD_OTHER]
331 = props.getProperty ("yudit.editor.syntax.other.foreground", "gray90");
332
333 editor->setSyntaxColors (syn);
334
335 const SString& hl = props["yudit.editor.syntax"];
336 SString mode = translateHighlightMode (hl);
337 if (mode.size() >= 0)
338 {
339 editor->setSyntax (mode);
340 }
341
342 SEditor e(currentParagraphSeparator);
343 editor->setEditor (e);
344 messagebar->setFontSize(df);
345 command->setEditor(SEditor());
346
347 add (slider);
348 add (editor);
349 add (command);
350 add (toolbar);
351 add (messagebar);
352 add (messagelabel);
353
354 setBackground (props["yudit.background"]);
355 editor->setTextBackground (props["yudit.editor.background"]);
356 editor->setForeground (props["yudit.editor.left.foreground"],
357 props["yudit.editor.right.foreground"]);
358 editor->setCaretForeground (props["yudit.editor.caret.left.foreground"],
359 props["yudit.editor.caret.right.foreground"]);
360 command->setTextBackground (props["yudit.command.background"]);
361 command->setForeground (props["yudit.command.left.foreground"],
362 props["yudit.command.right.foreground"]);
363 command->setCaretForeground (props["yudit.command.caret.left.foreground"],
364 props["yudit.command.caret.right.foreground"]);
365 slider->setSliderBackground (props["yudit.slider.background"]);
366
367 SDimension pw = toolbar->getPreferredSize();
368 /* get the dimension */
369 SDimension ms(props["yudit.default.geometry"]);
370 //if (ms.width < pw.width + 10) ms.width = pw.width + 10;
371 //if (ms.height < pw.height + 10) ms.width = pw.height + 10;
372 if (ms.width < 150) ms.width = 150;
373 if (ms.height < 100) ms.height = 100;
374 resize (ms);
375 setMinimumSize (SDimension (150, 100));
376
377 caretNow = STextIndex (0,0);
378 messagebar->setRow(1);
379 messagebar->setColumn (0);
380 editor->setCursorIndex(SCursorIndex(0,0));
381 editor->addTextEditLS (this);
382 command->addTextEditLS (this);
383 command->setHistorySize(30);
384
385 kmapDialog = 0;
386 fileDialog = 0;
387 highlightDialog = 0;
388 textDialog = 0;
389
390 #ifdef USE_WINAPI
391 SToolBar::SFormatIndex ft=SToolBar::SS_FORMAT_DOS;
392 #else
393 SToolBar::SFormatIndex ft=SToolBar::SS_FORMAT_UNIX;
394 #endif
395 toolbar->setParagraphSeparator (ft, true);
396 int lineNum = -1;
397 isFirstLoad = false;
398 SStringVector v;
399 if (args.size())
400 {
401 SString comm ("open -yes ");
402 SString enc ((lastencoding.size()==0)?SString("utf-8"):lastencoding);
403 SString filename;
404 bool help=false;
405 unsigned int i;
406 for (i=1; i<args.size(); i++)
407 {
408 if (args[i] == SString("--"))
409 {
410 if (i+1 < args.size())
411 {
412 filename = args[i+1];
413 }
414 break;
415 }
416 // +NUMBER
417 else if (getLineNumber (args[i]) > 0)
418 {
419 lineNum = getLineNumber (args[i]);
420 }
421 else if (args[i] == SString("-e") && i+1 < args.size())
422 {
423 i++;
424 enc = args[i];
425 }
426 else if (args[i] == SString("-help") || args[i] == SString("-h"))
427 {
428 help = true;
429 }
430 else if (args[i] == SString("-ndb") || args[i] == SString("-db"))
431 {
432 // already processed
433 }
434 else if (args[i] == SString("-us"))
435 {
436 SScriptProcessor::support(true);
437 }
438 else if (args[i] == SString("-nus"))
439 {
440 SScriptProcessor::support(false);
441 }
442 else if (args[i] == SString("-noinit"))
443 {
444 SScriptProcessor::doInit(false);
445 }
446 else if ((args[i] == SString("-d") || args[i] == SString("-geometry"))
447 && i+1 < args.size()) {
448 i++;
449 ms = SDimension (args[i]);
450 //if (ms.width < pw.width + 10) ms.width = pw.width + 10;
451 //if (ms.height < pw.height + 10) ms.width = pw.height + 10;
452 if (ms.width < 150) ms.width = 150;
453 if (ms.height < 100) ms.width = 100;
454 resize (ms);
455 }
456 else
457 {
458 filename = args[i];
459 break;
460 }
461 }
462 //currentFileName = filename;
463 if (help)
464 {
465 filename = SString("help");
466 command->putHistory (filename);
467 }
468 else
469 {
470 filename = composeFileNameCommand (comm, enc,
471 completeFileName(filename));
472 /* now it comes handy - args starts with 1 */
473 unsigned int j;
474 for (j=args.size(); j>i; j--)
475 {
476 SString ss = composeFileNameCommand (comm, enc,
477 completeFileName (args[j-1]));
478 command->putHistory (ss);
479 }
480 }
481 v.smartSplit (filename);
482 firstLoad = v;
483 }
484
485 isFirstLoad = true;
486 deferredLoader = STimer::newTimer(100, this);
487 editor->setEditable (false);
488
489 toolbar->setFileName(currentFileName, lastencoding);
490 toolbar->setHighlightName (editor->getHighlightName());
491
492 setFileTitle ();
493 SIcon* icon = SIconFactory::getIcon("Yudit");
494 setApplicationImage (icon->getImage ());
495
496 //fprintf (stderr, "SYudit.cpp EDITOR FOCUS REQUEST\n");
497 setDropListener (this, SStringVector ("text/uri-list,text/plain"));
498 showFreeHand (currentInput=="freehand");
499 if (lineNum > 0)
500 {
501 editor->setCursorIndex(SCursorIndex((unsigned int)(lineNum-1), 0, true));
502 }
503
504 }
505
~SYudit()506 SYudit::~SYudit ()
507 {
508 }
509 bool
close(SPanel * comp)510 SYudit::close (SPanel* comp)
511 {
512
513 if (textDialog != 0 && textDialog->isShown())
514 {
515 textDialog->center();
516 return false;
517 }
518 bool ret = false;
519 if (toolbar->modified)
520 {
521 createTextDialog ();
522 ret = textDialog->getInput (
523 "Yudit: Exit", translate ("Unsaved changes.\nExit anyway?\n"),
524 STextDialog::SS_QUESTION);
525 if (ret)
526 {
527 saveProperties();
528 exit (0);
529 }
530 return false;
531 }
532 if (toolbar->printing)
533 {
534 createTextDialog ();
535 ret = textDialog->getInput (
536 "Yudit: Exit", translate ("Pending printing job.\nExit anyway?\n"),
537 SDialog::SS_QUESTION);
538 if (ret)
539 {
540 saveProperties();
541 exit (0);
542 }
543 }
544 saveProperties();
545 exit (0);
546 }
547
548 /**
549 * Listening to toolbar.
550 */
551 void
toolBarButtonPressed(void * src,int which,bool accel)552 SYudit::toolBarButtonPressed (void* src, int which, bool accel)
553 {
554 if (!toolbar->printing) messagelabel->setMessage("");
555 if (textDialog != 0 && textDialog->isShown()) return;
556 SString currentFont = toolbar->fonts[toolbar->currentFont];
557 SString currentFontSize = toolbar->fontsizes[toolbar->currentFontSize];
558 SString currentInput = toolbar->inputs[toolbar->currentInput];
559 SString currentParagraphSeparator = toolbar->paragraphBreaks[toolbar->currentParagraphSeparator];
560 currentFontSize.append ((char)0);
561 double df;
562 SString pstr;
563 SStringVector pstrVector;
564 if (sscanf (currentFontSize.array(), "%lf", &df)==0 || df < 2.0) df = 2.0;
565 bool ok = false;
566 int dire = false;
567 bool wasmodified = toolbar->modified;
568
569 switch (which)
570 {
571 /* FIXME */
572 case SToolBar::SS_OPEN:
573 if (!accel)
574 {
575 createFileDialog();
576 if (toolbar->modified)
577 {
578 createTextDialog();
579 ok = textDialog->getInput (
580 "Yudit: Open", translate ("Unsaved changes.\nOpen anyway?\n"),
581 STextDialog::SS_QUESTION);
582 if (!ok)
583 {
584 return;
585 }
586 }
587 fileDialog->setFileName (currentFileName);
588 fileDialog->setFileType (lastencoding);
589 ok = fileDialog->getInput ("Yudit: Open", false, false);
590 if (!ok)
591 {
592 return;
593 }
594 pstr.clear();
595 pstr.append ("open ");
596 pstr.append ("-yes ");
597 pstr.append ("-e ");
598 pstr.append (fileDialog->getFileType());
599 pstr.append (" ");
600 pstr.append (quoteFileName (fileDialog->getFileName()));
601 command->setText (pstr);
602 command->setCursorIndex (SCursorIndex(0,10000));
603 command->putHistory (pstr);
604 pstrVector.smartSplit(pstr);
605 load (pstrVector, pstr);
606 return;
607 }
608 if (toolbar->modified)
609 {
610 messagelabel->setMessage (translate ("Unsaved changes. Enter discards!"), SMessageLabel::SS_ERR);
611 SString str = composeFileNameCommand ("open -yes ",
612 lastencoding, currentFileName);
613 command->setText(str);
614 command->setCursorIndex (SCursorIndex(0,10000));
615 }
616 else
617 {
618 messagelabel->setMessage (translate ("open -yes -e encoding file"),
619 SMessageLabel::SS_INFO);
620 SString str = composeFileNameCommand (
621 "open ", lastencoding, currentFileName);
622 command->setText(str);
623 command->setCursorIndex (SCursorIndex(0,10000));
624 }
625 command->setFocus();
626 break;
627 case SToolBar::SS_SAVE:
628 if (!accel)
629 {
630 createFileDialog();
631 fileDialog->setFileName (currentFileName);
632 fileDialog->setFileType (lastencoding);
633 pstr = fileDialog->getFileName();
634 ok = fileDialog->getInput ("Yudit: Save", false, false);
635 if (!ok)
636 {
637 return;
638 }
639 if (pstr != fileDialog->getFileName() &&
640 newFileExists (fileDialog->getFileName()))
641 {
642 createTextDialog();
643 ok = textDialog->getInput (
644 "Yudit: Save", translate ("File exists.\nSave anyway?"),
645 STextDialog::SS_QUESTION);
646 if (!ok)
647 {
648 return;
649 }
650 }
651 pstr.clear();
652 pstr.append ("save ");
653 pstr.append ("-yes ");
654 pstr.append ("-e ");
655 pstr.append (fileDialog->getFileType());
656 pstr.append (" ");
657 pstr.append (quoteFileName (fileDialog->getFileName()));
658 command->setText (pstr);
659 command->setCursorIndex (SCursorIndex(0,10000));
660 command->putHistory (pstr);
661 pstrVector.smartSplit(pstr);
662 save (pstrVector, pstr);
663 return;
664 }
665 messagelabel->setMessage (translate ("save -e encoding file"),
666 SMessageLabel::SS_INFO);
667 {
668 SString str = composeFileNameCommand (
669 "save ", lastencoding, currentFileName);;
670 command->setText(str);
671 command->setCursorIndex (SCursorIndex(0,10000));
672 }
673 command->setFocus();
674 break;
675 case SToolBar::SS_FIND:
676 messagelabel->setMessage (translate ("find string"),
677 SMessageLabel::SS_INFO);
678 command->setText("find ");
679 command->setCursorIndex (SCursorIndex(0,10000));
680 command->setFocus();
681 break;
682 case SToolBar::SS_GOTO:
683 messagelabel->setMessage (translate ("go line [column]"),
684 SMessageLabel::SS_INFO);
685 command->setText("go ");
686 command->setCursorIndex (SCursorIndex(0,10000));
687 command->setFocus();
688 break;
689 case SToolBar::SS_PRINT:
690 messagelabel->setMessage (getPrintHelp (), SMessageLabel::SS_INFO);
691 pstr.append ("print ");
692 pstr.append (lastprinterOption);
693 command->setText(pstr);
694 command->setCursorIndex (SCursorIndex(0,10000));
695 command->setFocus();
696 break;
697 case SToolBar::SS_PRINT_PREVIEW:
698 messagelabel->setMessage (translate ("print -e program"),
699 SMessageLabel::SS_INFO);
700 pstr.append ("print ");
701 pstr.append (lastpreviewOption);
702 command->setText(pstr);
703 command->setCursorIndex (SCursorIndex(0,10000));
704 command->setFocus();
705 break;
706 case SToolBar::SS_UNDO:
707 if (!editor->undo())
708 {
709 messagelabel->setMessage (translate ("Nothing to undo."),
710 SMessageLabel::SS_WARN);
711 toolbar->setModified (false);
712 }
713 toolbar->setEmbedding(editor->getDocumentEmbedding(), false);
714 break;
715 case SToolBar::SS_REDO:
716 if (!editor->redo())
717 {
718 messagelabel->setMessage (translate ("Nothing to redo."),
719 SMessageLabel::SS_WARN);
720 }
721 toolbar->setEmbedding(editor->getDocumentEmbedding(), false);
722 break;
723 case SToolBar::SS_DOCUMENT_EMBEDDING:
724 editor->setDocumentEmbedding (toolbar->currentEmbedding);
725 break;
726 case SToolBar::SS_SET_OVERRIDE:
727 /* change it back */
728 dire = editor->changeDirection (toolbar->overrideLR ? SS_DR_LO : SS_DR_RO);
729 if (dire)
730 {
731 messagelabel->setMessage("");
732 }
733 else
734 {
735 /* leave it back */
736 if (!wasmodified) toolbar->setModified (true);
737 messagelabel->setMessage (
738 translate ("Direction of selected text has been set."),
739 SMessageLabel::SS_INFO);
740 }
741 break;
742 case SToolBar::SS_YIELD_EMBEDDING:
743 dire = editor->changeDirection (toolbar->currentLR ? SS_DR_L : SS_DR_R);
744 if (dire)
745 {
746 messagelabel->setMessage("");
747 }
748 else
749 {
750 /* leave it back */
751 if (!wasmodified) toolbar->setModified (true);
752 messagelabel->setMessage (
753 translate ("Direction of selected text has been re-set."),
754 SMessageLabel::SS_INFO);
755 }
756 break;
757
758 case SToolBar::SS_SET_EMBEDDING:
759 /* change it back */
760 dire = editor->changeDirection (toolbar->embedLR ? SS_DR_LE : SS_DR_RE);
761 if (dire)
762 {
763 messagelabel->setMessage("");
764 }
765 else
766 {
767 /* leave it back */
768 if (!wasmodified) toolbar->setModified (true);
769 messagelabel->setMessage (
770 translate ("Direction of selected text has been set."),
771 SMessageLabel::SS_INFO);
772 }
773 break;
774 case SToolBar::SS_MAGNIFY_PLUS:
775 case SToolBar::SS_MAGNIFY_MINUS:
776 messagebar->setFontSize(df);
777 editor->setFontSize (df);
778 if (freehand) freehand->setFontSize (df);
779 break;
780 case SToolBar::SS_FONT:
781 editor->setFont (currentFont, df);
782 if (freehand) freehand->setFont (currentFont, df);
783 break;
784 case SToolBar::SS_INPUT:
785 if (!accel)
786 {
787 createKMapDialog ();
788 ok = kmapDialog->getInput ("Yudit: KMap Setup",
789 toolbar->inputs, toolbar->currentInput);
790 if (!ok || kmapDialog->getSelectedKMap() < 0) break;
791 toolbar->inputChanged(kmapDialog->getKMapList (),
792 kmapDialog->getSelectedKMap());
793 currentInput = toolbar->inputs[toolbar->currentInput];
794 userProps.put ("yudit.editor.inputs", toolbar->inputs.join (","));
795 userProps.put ("yudit.editor.input", currentInput);
796 saveProperties();
797 }
798 editor->setInputMethod (currentInput);
799 showFreeHand (currentInput=="freehand");
800
801 if (currentInput != SS_KINPUT2_IM
802 && currentInput != SS_WINDOWS_IM
803 && currentInput[0] != 'x'
804 && currentInput[1] != 'X')
805 {
806 command->setInputMethod (currentInput);
807 }
808 else
809 {
810 command->setInputMethod ("straight");
811 }
812 /* update glyph info */
813 caretMoved();
814 break;
815 case SToolBar::SS_PARAGRAPH_BREAK:
816 editor->setParagraphSeparator (currentParagraphSeparator, true);
817 break;
818 case SToolBar::SS_HIGHLIGHTING:
819 if (!accel)
820 {
821 createHighlightDialog();
822 SString gotMode = editor->getHighlightName();
823 highlightDialog->setHighlightName (gotMode);
824 ok = highlightDialog->getInput ("Yudit: Highlighting");
825 if (!ok)
826 {
827 return;
828 }
829 SString hlmode = highlightDialog->getHighlightName();
830 pstr.clear();
831 pstr.append ("syntax ");
832 pstr.append (" ");
833 //pstr.append (quoteFileName (hlmode));
834 pstr.append (hlmode);
835 //command->setText (pstr);
836 //command->setCursorIndex (SCursorIndex(0,10000));
837 if (setHighlight (hlmode))
838 {
839 command->putHistory(pstr);
840 }
841 return;
842 }
843 else
844 {
845 SString gotMode = editor->getHighlightName();
846 SString cmd ("syntax");
847 cmd.append (" ");
848 cmd.append (gotMode);
849 command->setText (cmd);
850 command->setCursorIndex (SCursorIndex(0,10000));
851 command->setFocus();
852 }
853 break;
854 default:
855 break;
856 }
857 }
858
859 bool
setHighlight(const SString & syntaxMode)860 SYudit::setHighlight (const SString& syntaxMode)
861 {
862 SString smode;
863 if ((smode = translateHighlightMode (syntaxMode)) == "")
864 {
865 SString err = translate ("usage: ");
866 err.append ("syntax none|simple|simple-dark|hunspell:en_US|...");
867 messagelabel->setMessage (err, SMessageLabel::SS_ERR);
868 return false;
869 }
870 SString oldM = editor->getHighlightName ();
871 editor->setSyntax (smode);
872 SString gotMode = editor->getSyntaxName();
873 if (gotMode != smode && smode != "simple"
874 && smode != "simple-dark" && smode != "none")
875 {
876 SString err = translate ("Can not set syntax: ");
877 err.append (smode);
878 messagelabel->setMessage (err, SMessageLabel::SS_ERR);
879 editor->setSyntax (oldM);
880 return false;
881 }
882 // dont display these
883 toolbar->setHighlightName (editor->getHighlightName());
884
885 userProps.put ("yudit.editor.syntax", smode);
886 return true;
887 }
888
889 void
toolBarButtonLeave(void * src,int which)890 SYudit::toolBarButtonLeave (void* src, int which)
891 {
892 }
893
894 void
toolBarButtonEnter(void * src,int which)895 SYudit::toolBarButtonEnter (void* src, int which)
896 {
897 }
898
899
900 /**
901 * This is the STextEditLS
902 */
903 void
textChanged(void * source)904 SYudit::textChanged (void *source)
905 {
906 if (source == editor)
907 {
908 if (!toolbar->printing) messagelabel->setMessage("");
909 toolbar->setModified (true);
910 return;
911 }
912 }
913
914 void
textEntered(void * source)915 SYudit::textEntered (void *source)
916 {
917 if (!toolbar->printing) messagelabel->setMessage("");
918 if (source != command) return;
919 SString text = command->getText();
920 if (text.size()==0)
921 {
922 editor->setFocus();
923 return;
924 }
925 SStringVector cv;
926 cv.smartSplit (text);
927 if (cv.size()==2 && cv[0]=="quit" && cv[1] == "-yes")
928 {
929 exit (0);
930 }
931 if (cv.size()==1 && cv[0] == "quit")
932 {
933 if (toolbar->modified)
934 {
935 messagelabel->setMessage (translate ("Unsaved changes. Enter quits!"),
936 SMessageLabel::SS_ERR);
937 command->setText("quit -yes");
938 command->setCursorIndex (SCursorIndex(0,10000));
939 command->setFocus();
940 return;
941 }
942 if (toolbar->printing)
943 {
944 messagelabel->setMessage (translate ("Pending printing job. Enter quits!"),
945 SMessageLabel::SS_ERR);
946 command->setText("quit -yes");
947 command->setCursorIndex (SCursorIndex(0,10000));
948 command->setFocus();
949 return;
950 }
951 exit (0);
952 }
953 command->putHistory(text);
954 if (cv.size()>0 && cv[0] == "print")
955 {
956 print (cv, text);
957 return;
958 }
959 if ((cv.size()>0 && (cv[0] == "help" || cv[0] == "test" ||
960 helpStrings.get(cv[0]) != 0))
961 || (cv.size() > 1 && cv[0] == "howto"))
962 {
963 load (cv, text);
964 return;
965 }
966 if (cv.size()>0 && (cv[0] == "open" || cv[0] == "load"))
967 {
968 load (cv, text);
969 return;
970 }
971 if (cv.size()>0 && (cv[0] == "configure" || cv[0] == "config"))
972 {
973 load (cv, text);
974 return;
975 }
976 if (cv.size()>0 && (cv[0] == "save" || cv[0] == "save"))
977 {
978 save (cv, text);
979 return;
980 }
981 if (cv.size()>0 && cv[0] == "go")
982 {
983 goLineRow (cv, text);
984 return;
985 }
986 if (cv.size()>0 && cv[0] == "find")
987 {
988 find (cv, text);
989 return;
990 }
991 if (cv.size()>0 && cv[0] == "replace")
992 {
993 replace (cv, text);
994 return;
995 }
996 if (cv.size()>0 && cv[0] == "sedy")
997 {
998 SString lib = SSedy::getLocation ();
999 if (lib.size()==0) lib = SString ("not-found");
1000 SString message ("Sedy: ");
1001 message.append (lib);
1002 messagelabel->setMessage (message, SMessageLabel::SS_INFO);
1003 return;
1004 }
1005 if (cv.size() > 0 && cv[0] == "syntax")
1006 {
1007 SString smode;
1008 if (cv.size() != 2)
1009 {
1010 SString err = translate ("usage: ");
1011 err.append ("syntax none|simple|simple-dark|hunspell:en_US... ");
1012 messagelabel->setMessage (err, SMessageLabel::SS_ERR);
1013 return;
1014 }
1015 if (setHighlight (cv[1]))
1016 {
1017 editor->setFocus();
1018 command->putHistory(text);
1019 }
1020 return;
1021 }
1022 if (cv.size() > 0 && cv[0] == "wordwrap")
1023 {
1024 if (cv.size() != 2 || (cv[1] != "true" && cv[1] != "false"))
1025 {
1026 SString err = translate ("usage: ");
1027 err.append ("wordwrap true|false");
1028 messagelabel->setMessage (err, SMessageLabel::SS_ERR);
1029 return;
1030 }
1031 if (cv[1]=="true")
1032 {
1033 editor->setWordWrap (true);
1034 }
1035 else
1036 {
1037 editor->setWordWrap (false);
1038 }
1039 userProps.put ("yudit.editor.wordwrap", cv[1]);
1040 editor->setFocus();
1041 command->putHistory(text);
1042 return;
1043 }
1044 SString mess ("syntax error: ");
1045 mess.append (SS_LB_LRE);
1046 mess.append ("'");
1047 mess.append (text);
1048 mess.append ("'");
1049 mess.append (SS_LB_PDF);
1050 messagelabel->setMessage (mess, SMessageLabel::SS_ERR);
1051 command->clear();
1052 command->historyEnd();
1053 //editor->setFocus();
1054 }
1055
1056 void
print(const SStringVector & args,const SString & str)1057 SYudit::print (const SStringVector& args, const SString& str)
1058 {
1059 if (toolbar->printing) return;
1060 SString executable;
1061 SString printer;
1062 SString filename;
1063 SString hsize("10");
1064 unsigned int i;
1065 bool shownl = false;
1066 bool islpr = false;
1067 double fontSize = messagebar->fontSize;
1068
1069 SPrinter::SMedia media = SPrinter::A4;
1070 SPrinter::SOrientation orientation = SPrinter::PORTRAIT;
1071
1072 for (i=1; i<args.size(); i++)
1073 {
1074 if ((args[i] == "-printer" || args[i] =="-p") && i+1 < args.size())
1075 {
1076 i++;
1077 printer = args[i];
1078 }
1079 else if ((args[i] == "-hsize") && i+1 < args.size())
1080 {
1081 i++;
1082 hsize = args[i];
1083 }
1084 else if ((args[i] == "-size") && i+1 < args.size())
1085 {
1086 i++;
1087 SString sarg = args[i];
1088 sarg.append ((char)0);
1089 sscanf (sarg.array(), "%lf", &fontSize);
1090 if (fontSize > 1000.0)
1091 {
1092 fontSize = 1000.0;
1093 }
1094 if (fontSize < 1.0)
1095 {
1096 fontSize = 1.0;
1097 }
1098 }
1099 else if ((args[i] == "-out" || args[i] =="-o") && i+1 < args.size())
1100 {
1101 i++;
1102 filename = completeFileName (args[i]);
1103 }
1104 else if ((args[i] == "-m" || args[i] =="-media") && i+1 < args.size())
1105 {
1106 i++;
1107 if (args[i] == "A3")
1108 {
1109 media = SPrinter::A3;
1110 }
1111 else if (args[i] == "A4")
1112 {
1113 media = SPrinter::A4;
1114 }
1115 else if (args[i] == "A5")
1116 {
1117 media = SPrinter::A5;
1118 }
1119 else if (args[i] == "B4")
1120 {
1121 media = SPrinter::B4;
1122 }
1123 else if (args[i] == "B5")
1124 {
1125 media = SPrinter::B5;
1126 }
1127 else if (args[i] == "Executive")
1128 {
1129 media = SPrinter::Executive;
1130 }
1131 else if (args[i] == "Folio")
1132 {
1133 media = SPrinter::Folio;
1134 }
1135 else if (args[i] == "Ledger")
1136 {
1137 media = SPrinter::Ledger;
1138 }
1139 else if (args[i] == "Legal")
1140 {
1141 media = SPrinter::Legal;
1142 }
1143 else if (args[i] == "Letter")
1144 {
1145 media = SPrinter::Letter;
1146 }
1147 else if (args[i] == "Quarto")
1148 {
1149 media = SPrinter::Quarto;
1150 }
1151 else if (args[i] == "Statement")
1152 {
1153 media = SPrinter::Statement;
1154 }
1155 else if (args[i] == "Tabloid")
1156 {
1157 media = SPrinter::Tabloid;
1158 }
1159 else
1160 {
1161 media = SPrinter::A4;
1162 }
1163 }
1164 else if (args[i] == "-exec" && i+1 < args.size())
1165 {
1166 i++;
1167 executable = args[i];
1168 int ind = str.find("-exec");
1169 if (ind > 0)
1170 {
1171 /* strlen ("-exec")*/
1172 ind += 5;
1173 while (ind < (int) str.size()
1174 && (str[(unsigned int)ind] == ' '
1175 || str[(unsigned int)ind] == '\t')) ind++;
1176 if (ind < (int) str.size())
1177 {
1178 executable = SString (&str.array()[(unsigned int)ind],
1179 str.size()-(unsigned int)ind);
1180 i = args.size();
1181 break;
1182 }
1183 }
1184 }
1185 else if (args[i] =="-e" && i+1 < args.size())
1186 {
1187 /* strlen ("-e")*/
1188 i++;
1189 executable = args[i];
1190 int ind = str.find("-e");
1191 if (ind > 0)
1192 {
1193 ind += 2;
1194 while (ind < (int) str.size()
1195 && (str[(unsigned int)ind] == ' '
1196 || str[(unsigned int)ind] == '\t')) ind++;
1197 if (ind < (int) str.size())
1198 {
1199 executable = SString (&str.array()[(unsigned int)ind],
1200 str.size()-(unsigned int)ind);
1201 i = args.size();
1202 break;
1203 }
1204 }
1205 }
1206 else if (args[i] == "-break" || args[i] =="-b")
1207 {
1208 shownl = true;
1209 }
1210 else if (args[i] == "-L" || args[i] =="-landscape")
1211 {
1212 orientation = SPrinter::LANDSCAPE;
1213 }
1214 else
1215 {
1216 break;
1217 }
1218 }
1219 hsize.append ((char)0);
1220 double hsized=10.0;
1221 sscanf (hsize.array(), "%lf", &hsized);
1222 if (hsized < 2.0) hsized = 1.0;
1223 if (hsized > 100.0) hsized = 100.0;
1224
1225 if (filename.size()==0 && executable.size()==0)
1226 {
1227 islpr = true;
1228
1229 #ifdef USE_WINAPI
1230 executable = originalProperties["yudit.default.preview.command"];
1231 executable.replaceAll("\\", "/");
1232 executable.replaceAll("//", "/");
1233 if (!addMytoolPrefix (&executable)) return;
1234 #else
1235 executable = "lpr";
1236 #endif
1237 }
1238 if (i<args.size() || (filename.size()!=0 && executable.size()!=0)
1239 || (filename.size()!=0 && printer.size() > 0))
1240 {
1241 messagelabel->setMessage (getPrintHelp(), SMessageLabel::SS_ERR);
1242 return;
1243 }
1244 SOutputStream os;
1245 if (executable.size())
1246 {
1247 if (!islpr && !addMytoolPrefix (&executable)) return;
1248 if (printer.size())
1249 {
1250 executable.append (" -P ");
1251 executable.append (printer);
1252 }
1253 //fprintf (stderr, "executable [%*.*s]\n", SSARGS (executable));
1254 SPipe p(executable);
1255 os = p.getOutputStream();
1256 if (!os.isOK())
1257 {
1258 SString ems ("Can not execute: ");
1259 ems.append (SS_LB_LRE);
1260 ems.append ("'");
1261 ems.append (executable);
1262 ems.append ("'");
1263 ems.append (SS_LB_PDF);
1264 messagelabel->setMessage (ems, SMessageLabel::SS_ERR);
1265 return;
1266 }
1267 }
1268 else
1269 {
1270 SFile f(filename);
1271 os = f.getOutputStream();
1272 if (!os.isOK())
1273 {
1274 SString ems ("Can not open: ");
1275 ems.append (SS_LB_LRE);
1276 ems.append ("'");
1277 ems.append (filename);
1278 ems.append ("'");
1279 ems.append (SS_LB_PDF);
1280 messagelabel->setMessage (ems, SMessageLabel::SS_ERR);
1281 }
1282 }
1283 SWriter writer(os);
1284 SString fontName = toolbar->fonts[toolbar->currentFont];
1285
1286 SPrinter p (writer, SPrinter::POSTSCRIPT, media, orientation);
1287 SUniPrint uniPrint(p, fontName, hsized, fontName, fontSize);
1288
1289 SString text = editor->getSelectedText();
1290 SString sel = currentFileName;
1291 if (text.size() == 0)
1292 {
1293 text = editor->getText();
1294 }
1295 else
1296 {
1297 sel.append (" (excerpt)");
1298 }
1299
1300 uniPrint.setDocumentEmbedding (toolbar->currentEmbedding);
1301 uniPrint.setLineEndMark(shownl);
1302 uniPrint.setWordWrap (editor->getWordWrap());
1303 toolbar->setPrinting(true);
1304
1305 command->clear();
1306 command->historyEnd();
1307 editor->setFocus();
1308 messagelabel->setMessage (
1309 translate ("Printing..."),
1310 SMessageLabel::SS_NONE);
1311 if (!uniPrint.print (sel, text, true))
1312 {
1313 toolbar->setPrinting (false);
1314 SString ems ("Printing failed on '");
1315 ems.append (executable);
1316 ems.append (filename);
1317 ems.append ("'");
1318 messagelabel->setMessage (ems, SMessageLabel::SS_ERR);
1319 return;
1320 }
1321 int pagecount = uniPrint.getPageCount();
1322 char a[64];
1323 if (pagecount >= 1)
1324 {
1325 SString tr(translate("Printed %d page(s)."));
1326 tr.append ((char)0);
1327 sprintf (a, tr.array(), pagecount);
1328 if (uniPrint.hasNative())
1329 {
1330 SString ms ("Bitmap font printed (bad printing quality).");
1331 ms.append (a);
1332 messagelabel->setMessage (ms, SMessageLabel::SS_WARN);
1333 }
1334 else
1335 {
1336 SString ms (a);
1337 messagelabel->setMessage (ms, SMessageLabel::SS_INFO);
1338 }
1339 }
1340 command->clear();
1341 command->historyEnd();
1342
1343 SString op;
1344 for (i=strlen ("print "); i<str.size(); i++)
1345 {
1346 op.append ((char)str[i]);
1347 }
1348 if (executable.size() && !islpr && args.size() != 1)
1349 {
1350 lastpreviewOption = op;
1351 }
1352 else
1353 {
1354 lastprinterOption = op;
1355 //fprintf (stderr, "lastprinterOption=[%*.*s] str=[%*.*s]\n",
1356 // SSARGS(lastprinterOption), SSARGS (str));
1357 }
1358 toolbar->setPrinting (false);
1359 }
1360
1361 void
load(const SStringVector & args,const SString & notused)1362 SYudit::load (const SStringVector& args, const SString& notused)
1363 {
1364 caretIndex.put (currentFileName, caretNow);
1365 SString encode="utf-8";
1366 bool hasyes = false;
1367 SString filename;
1368 unsigned int i;
1369 SString internal;
1370 for (i=1; i<args.size(); i++)
1371 {
1372 if (args[i] == "-e" && i+1 < args.size())
1373 {
1374 i++;
1375 encode = args[i];
1376 }
1377 else if (args[i] =="-yes")
1378 {
1379 hasyes = true;
1380 }
1381 else if (i+1 == args.size())
1382 {
1383 filename = completeFileName(args[i]);
1384 }
1385 else
1386 {
1387 break;
1388 }
1389 }
1390 if (args[0] =="help" || helpStrings.get (args[0]) != 0)
1391 {
1392 internal = getPrefix();
1393 internal.append ("/doc/");
1394 SString lang = getLanguage();
1395 if (helpStrings.get (args[0]) != 0)
1396 {
1397 lang = helpStrings[args[0]];
1398 }
1399 if (lang.size())
1400 {
1401 SString nd = internal;
1402 nd.append (lang);
1403 nd.append ("/");
1404 nd.append ("FAQ.TXT");
1405 SFile file (nd);
1406 if (file.size() > 0)
1407 {
1408 internal.append (lang);
1409 internal.append ("/");
1410 }
1411 }
1412
1413 internal.append ("FAQ.TXT");
1414 i = args.size();
1415 encode = "utf-8";
1416 filename = internal;
1417 }
1418
1419 if (args[0] =="howto" && args.size() >1)
1420 {
1421 internal = getPrefix();
1422 internal.append ("/doc/");
1423 SString lang = getLanguage();
1424 if (helpStrings.get (args[0]) != 0)
1425 {
1426 lang = helpStrings[args[0]];
1427 }
1428 if (lang.size())
1429 {
1430 SString nd = internal;
1431 nd.append (lang);
1432 nd.append ("/");
1433 nd.append ("HOWTO-");
1434 nd.append (args[1]);
1435 nd.append (".txt");
1436 SFile file (nd);
1437 if (file.size() > 0)
1438 {
1439 internal.append (lang);
1440 internal.append ("/");
1441 }
1442 }
1443 internal.append ("HOWTO-");
1444 internal.append (args[1]);
1445 internal.append (".txt");
1446 i = args.size();
1447 encode = "utf-8";
1448 filename = internal;
1449 }
1450
1451 if (args[0] =="test")
1452 {
1453 internal = getPrefix();
1454 internal.append ("/doc/");
1455 internal.append ("TestPage.txt");
1456 i = args.size();
1457 encode = "utf-8";
1458 filename = internal;
1459 }
1460 if (args[0] =="configure" || args[0] =="config")
1461 {
1462 SString afile = currentFileName;
1463 currentFileName = "/dev/null";
1464 /* trick to save properties */
1465 saveProperties();
1466 currentFileName = afile;
1467 SString internal = getHome();;
1468 internal.append ("/.yudit/yudit.properties");
1469 i = args.size();
1470 encode = "utf-8";
1471 filename = internal;
1472 }
1473
1474 if (filename.size()==0)
1475 {
1476 if (i<args.size())
1477 {
1478 messagelabel->setMessage (translate ("usage: open -e utf-8 -yes filename"),
1479 SMessageLabel::SS_ERR);
1480 return;
1481 }
1482 filename = currentFileName;
1483 }
1484 if (!hasyes && toolbar->modified)
1485 {
1486 messagelabel->setMessage (translate ("Unsaved changes. Try -yes option"),
1487 SMessageLabel::SS_ERR);
1488 return;
1489 }
1490 if (!hasyes && toolbar->printing)
1491 {
1492 messagelabel->setMessage (translate ("Pending printing job. Try -yes option"),
1493 SMessageLabel::SS_ERR);
1494 return;
1495 }
1496
1497 SEncoder utf8("utf-8-s");
1498 SEncoder enc(encode);
1499 if (!enc.isOK())
1500 {
1501 SString ems = translate ("Unknown encoding: ");
1502
1503 ems.append (SS_LB_LRE);
1504 ems.append ("'");
1505 ems.append (encode);
1506 ems.append ("'");
1507 ems.append (SS_LB_PDF);
1508
1509 messagelabel->setMessage (ems, SMessageLabel::SS_ERR);
1510 return;
1511 }
1512 SFile f(filename);
1513 SFileImage im = f.getFileImage();
1514 //fprintf(stderr, "size=%ld im=%ld array=%lx\n", f.size(), im.size(), (unsigned long) im.array());
1515 if (f.size()<0 || im.size()<0 || im.array()==0)
1516 {
1517 if (hasyes)
1518 {
1519 lastencoding = encode;
1520 command->clear();
1521 currentFileName = filename;
1522 toolbar->setFileName(currentFileName, lastencoding);
1523 setFileTitle ();
1524
1525 editor->clear();
1526 editor->setFocus();
1527 toolbar->setModified(false);
1528 }
1529 SString ems = translate ("Can not read: ");
1530 ems.append (SS_LB_LRE);
1531 ems.append ("'");
1532 ems.append (filename);
1533 ems.append ("'");
1534 ems.append (SS_LB_PDF);
1535 messagelabel->setMessage (ems, SMessageLabel::SS_ERR);
1536 return;
1537 }
1538 SString text (im.array(), f.size());
1539 if (cryptFileMatcher.size()!=0 && filename.match (cryptFileMatcher)) {
1540
1541 //fprintf (stderr, "Sedy currentFileName = %*.*s\n", SSARGS(currentFileName));
1542
1543 SStatus status = decryptText (filename, text, &text);
1544 if (status == Failed) {
1545 SString ems = translate ("Can not read: ");
1546 ems.append (SS_LB_LRE);
1547 ems.append ("'");
1548 ems.append (filename);
1549 ems.append ("'");
1550 ems.append (SS_LB_PDF);
1551 messagelabel->setMessage (ems, SMessageLabel::SS_ERR);
1552 // NO workaround works here for editor focus.
1553 //window->getKeyboardFocus();
1554 editor->setFocus();
1555 return;
1556 }
1557 if (status == Canceled) {
1558 // NO workaround works here for editor focus.
1559 //window->getKeyboardFocus();
1560 editor->setFocus();
1561 return;
1562 }
1563 //workaround to get focus.
1564 window->getKeyboardFocus();
1565 encrypted = true;
1566 } else {
1567 encrypted = false;
1568 }
1569
1570 SV_UCS4 ucs4 = enc.decode (text);
1571 //fprintf (stderr, "BOTTLE - END\n");
1572 bool sft = false;
1573 #ifdef USE_WINAPI
1574 SToolBar::SFormatIndex ft=SToolBar::SS_FORMAT_DOS;
1575 #else
1576 SToolBar::SFormatIndex ft=SToolBar::SS_FORMAT_UNIX;
1577 #endif
1578 bool hadlinebreak = false;
1579 if (ucs4.size() > 1 &&
1580 (ucs4[ucs4.size()-1] == (SS_UCS4) '\r'
1581 || ucs4[ucs4.size()-1] == (SS_UCS4) '\n'
1582 || ucs4[ucs4.size()-1] == (SS_UCS4) 0x2029))
1583 {
1584 switch (ucs4[ucs4.size()-1])
1585 {
1586 case '\n':
1587 ft = (ucs4.size()>1 && ucs4[ucs4.size()-2]=='\r')
1588 ? SToolBar::SS_FORMAT_DOS : SToolBar::SS_FORMAT_UNIX;
1589 hadlinebreak = true;
1590 break;
1591 case '\r': ft = SToolBar::SS_FORMAT_MAC;
1592 hadlinebreak = true;
1593 break;
1594 case 0x2029: ft = SToolBar::SS_FORMAT_PS;
1595 hadlinebreak = true;
1596 break;
1597 }
1598 }
1599 else
1600 {
1601 ft = SToolBar::SS_FORMAT_UNIX;
1602 }
1603 sft = (toolbar->currentParagraphSeparator != (unsigned int) ft);
1604 text = utf8.encode (ucs4);
1605 editor->clear();
1606 editor->setText(text);
1607 editor->setCursorIndex(SCursorIndex(0,0));
1608
1609 SString ems = translate ("Opened: ");
1610 ems.append (SS_LB_LRE);
1611 ems.append ("'");
1612 ems.append (filename);
1613 ems.append ("'");
1614 ems.append (SS_LB_PDF);
1615 ems.append (".");
1616 if (sft)
1617 {
1618 ems.append (translate (" Line Break:"));
1619 ems.append (translate (toolbar->paragraphBreakStrings[ft]));
1620 }
1621 if (!hadlinebreak)
1622 {
1623 ems.append (translate(" Incomplete Last Line..."));
1624 }
1625
1626 if (sft)
1627 {
1628 toolbar->setParagraphSeparator ((int) ft, false);
1629 SString currentParagraphSeparator =
1630 toolbar->paragraphBreaks[toolbar->currentParagraphSeparator];
1631 editor->setParagraphSeparator (currentParagraphSeparator, false);
1632 }
1633
1634 toolbar->setModified (false);
1635 editor->setFocus();
1636
1637 /*FIXME: load and set currentFileName */
1638 lastencoding = encode;
1639 command->clear();
1640 currentFileName = filename;
1641 toolbar->setEncrypted(encrypted);
1642 if (encrypted) {
1643 setHighlight("simple");
1644 } else {
1645 currentPassword = SString("");
1646 }
1647 editor->setAutoClipboard(encrypted ? false : SYUDIT_AUTO_KEYBOARD);
1648
1649 toolbar->setFileName(currentFileName, lastencoding);
1650 setFileTitle ();
1651
1652 messagelabel->setMessage (ems,
1653 sft ? SMessageLabel::SS_WARN : SMessageLabel::SS_INFO);
1654 const STextIndex* sindex = caretIndex.get (filename);
1655 if (sindex)
1656 {
1657 editor->setCursorIndex(SCursorIndex(sindex->line, sindex->index));
1658 }
1659 editor->setFocus();
1660 }
1661
1662 // 0 canceled by user
1663 SYudit::SStatus
decryptText(const SString & fileName,const SString & text,SString * out)1664 SYudit::decryptText (const SString& fileName, const SString& text, SString* out)
1665 {
1666 createPasswordDialog();
1667 passwordDialog->setFileName (fileName);
1668 bool ok = passwordDialog->getInput ("Yudit: Decrypt");
1669 if (ok) {
1670 SString password = passwordDialog->getPassword();
1671 *out = sedy.decrypt (text, password);
1672 //fprintf(stderr, "password %*.*s\n", SSARGS(password));
1673 if (sedy.getLastError().size()) {
1674 *out = SString("");
1675 //fprintf (stderr, "Sedy: %*.*s\n", SSARGS(sedy.getLastError()));
1676 return Failed;
1677 }
1678 currentPassword = password;
1679 return Succeeded;
1680 }
1681 *out = SString("");
1682 return Canceled;
1683 }
1684
1685 void
save(const SStringVector & args,const SString & str)1686 SYudit::save (const SStringVector& args, const SString& str)
1687 {
1688 SString encode="utf-8";
1689 SString filename;
1690 unsigned int i;
1691 bool hasyes = false;
1692 for (i=1; i<args.size(); i++)
1693 {
1694 if (args[i] == "-e" && i+1 < args.size())
1695 {
1696 i++;
1697 encode = args[i];
1698 }
1699 else if (i+1 == args.size())
1700 {
1701 filename = completeFileName (args[i]);
1702 }
1703 else if (args[i] =="-yes")
1704 {
1705 hasyes = true;
1706 }
1707 else
1708 {
1709 break;
1710 }
1711 }
1712 if (filename.size()==0)
1713 {
1714 if (i<args.size())
1715 {
1716 messagelabel->setMessage (translate ("usage: save -e utf-8 -yes filename"),
1717 SMessageLabel::SS_ERR);
1718 return;
1719 }
1720 filename = completeFileName (currentFileName);
1721 }
1722
1723 if (!hasyes && newFileExists (filename))
1724 {
1725 SString ems = translate ("File exists. Use -yes option.");
1726 messagelabel->setMessage (ems, SMessageLabel::SS_ERR);
1727 return;
1728 }
1729
1730
1731 SEncoder utf8("utf-8-s");
1732 SEncoder enc(encode);
1733 if (!enc.isOK())
1734 {
1735 SString ems = translate ("Unknown encoding: ");
1736 ems.append (SS_LB_LRE);
1737 ems.append ("'");
1738 ems.append (encode);
1739 ems.append ("'");
1740 ems.append (SS_LB_PDF);
1741 messagelabel->setMessage (ems, SMessageLabel::SS_ERR);
1742 return;
1743 }
1744 SString text = editor->getText();
1745 SString password = currentPassword;
1746 // Dealing with password changes for sedy files.
1747 //fprintf (stderr, "password size: %u\n", password.size());
1748 if (password.size() > 0 && !filename.match (cryptFileMatcher)) {
1749 SString ems = translate ("Output file is not .sedy file");
1750 messagelabel->setMessage (ems, SMessageLabel::SS_ERR);
1751 return;
1752 }
1753
1754 SFile f(filename);
1755 bool encryptedCandidate = encrypted;
1756
1757 SV_UCS4 ucs4 = utf8.decode (text);
1758 bool completed = false;
1759 if (ucs4.size()
1760 && ucs4[ucs4.size()-1] != (SS_UCS4) '\r'
1761 && ucs4[ucs4.size()-1] != (SS_UCS4) '\n'
1762 && ucs4[ucs4.size()-1] != (SS_UCS4) 0x2029)
1763 {
1764 completed = true;
1765 }
1766 text = enc.encode (ucs4);
1767
1768 //fprintf(stderr, "Encrypted in=%d\n", encrypted);
1769 if (encrypted || (sedyLibrary.size() && filename.match (cryptFileMatcher))) {
1770 SString passwordCandidate = currentPassword;
1771 if (newFileExists (filename)) {
1772 SString ems = translate ("Output sedy file exists.");
1773 messagelabel->setMessage (ems, SMessageLabel::SS_ERR);
1774 return;
1775 }
1776 // Only file changes and new files can change password.
1777 if (filename != currentFileName || f.size()<0) {
1778 createPasswordDialog();
1779 passwordDialog->setFileName (filename);
1780 bool ok = passwordDialog->getInput ("Yudit: Change Password");
1781 if (!ok) {
1782 SString ems = translate ("Canceled by user.");
1783 messagelabel->setMessage (ems, SMessageLabel::SS_ERR);
1784 return;
1785 }
1786 passwordCandidate = passwordDialog->getPassword ();
1787 if (passwordCandidate.size() < CRYPT_MIN_PASSWORD_SIZE) {
1788 SString ems = translate ("New Password is too short.");
1789 messagelabel->setMessage (ems, SMessageLabel::SS_ERR);
1790 return;
1791 }
1792 }
1793 text = sedy.encrypt (text, passwordCandidate);
1794 if (sedy.getLastError().size()) {
1795 text = SString("");
1796 //fprintf(stderr, "Sedy: %*.*s\n", SSARGS(sedy.getLastError()));
1797 SString ems = translate ("Failded to set new password.");
1798 messagelabel->setMessage (ems, SMessageLabel::SS_ERR);
1799 return;
1800 }
1801 password = passwordCandidate;
1802 encryptedCandidate = true;
1803 }
1804 SOutputStream os = f.getOutputStream();
1805 if (!os.isOK())
1806 {
1807 SString ems = translate ("Can not write: ");
1808 ems.append (SS_LB_LRE);
1809 ems.append ("'");
1810 ems.append (filename);
1811 ems.append ("'");
1812 ems.append (SS_LB_PDF);
1813 messagelabel->setMessage (ems, SMessageLabel::SS_ERR);
1814 return;
1815 }
1816 SWriter writer(os);
1817 if ((text.size() > 0 && !writer.write (text)) || !writer.close())
1818 {
1819 SString ems = translate ("Error while writing: ");
1820 ems.append (SS_LB_LRE);
1821 ems.append ("'");
1822 ems.append (filename);
1823 ems.append ("'");
1824 ems.append (SS_LB_PDF);
1825 messagelabel->setMessage (ems, SMessageLabel::SS_ERR);
1826 return;
1827 }
1828 currentPassword = password;
1829 encrypted = encryptedCandidate;
1830
1831 lastencoding = encode;
1832 currentFileName = filename;
1833 toolbar->setFileName(currentFileName, lastencoding);
1834 setFileTitle();
1835
1836 toolbar->setEncrypted(encrypted);
1837 if (encrypted) {
1838 setHighlight("simple");
1839 } else {
1840 currentPassword = SString("");
1841 }
1842 editor->setAutoClipboard(currentPassword.size()
1843 ? false : SYUDIT_AUTO_KEYBOARD);
1844
1845 command->clear();
1846 command->historyEnd();
1847
1848 SString ems = translate ("Wrote: ");
1849 ems.append (SS_LB_LRE);
1850 ems.append ("'");
1851 ems.append (filename);
1852 ems.append ("'");
1853 ems.append (SS_LB_PDF);
1854 ems.append (".");
1855 if (completed) ems.append (translate(" Incomplete Last Line..."));
1856 messagelabel->setMessage (ems,
1857 (completed) ? SMessageLabel::SS_WARN : SMessageLabel::SS_INFO);
1858 toolbar->setModified (false);
1859 editor->setFocus();
1860 caretIndex.put (currentFileName, caretNow);
1861 }
1862
1863 /**
1864 * move the cursor
1865 */
1866 void
goLineRow(const SStringVector & args,const SString & str)1867 SYudit::goLineRow (const SStringVector& args, const SString& str)
1868 {
1869 if (args.size () < 2 || args.size() > 3)
1870 {
1871 SString ems = translate ("usage: go line [column] ");
1872 messagelabel->setMessage (ems, SMessageLabel::SS_ERR);
1873 return;
1874 }
1875 SString l=args[1];
1876 SString c;
1877 if (args.size()==3) c=args[2];
1878 l.append ((char)0);
1879 c.append ((char)0);
1880 int li=0;
1881 int ci=0;
1882 sscanf (l.array(), "%d", &li);
1883 sscanf (c.array(), "%d", &ci);
1884 if (li <= 0)
1885 {
1886 editor->setCursorIndex(SCursorIndex(0, 0, true));
1887 }
1888 else if (ci <= 0)
1889 {
1890 editor->setCursorIndex(SCursorIndex((unsigned int)(li-1), 0, true));
1891 }
1892 else
1893 {
1894 editor->setCursorIndex(SCursorIndex((unsigned int)(li-1),
1895 (unsigned int) (ci-1), false));
1896 }
1897 }
1898
1899 /**
1900 * find text
1901 */
1902 void
find(const SStringVector & args,const SString & str)1903 SYudit::find (const SStringVector& args, const SString& str)
1904 {
1905 if (args.size () != 2)
1906 {
1907 SString ems = translate ("usage: find text");
1908 messagelabel->setMessage (ems, SMessageLabel::SS_ERR);
1909 return;
1910 }
1911 if (!editor->find (args[1]))
1912 {
1913 SString ems = translate ("search string not found.");
1914 ems.append (SS_LB_LRE);
1915 ems.append ("'");
1916 ems.append (args[1]);
1917 ems.append ("'");
1918 ems.append (SS_LB_PDF);
1919 messagelabel->setMessage (ems, SMessageLabel::SS_ERR);
1920 return;
1921 }
1922 }
1923
1924 /**
1925 * replace text
1926 */
1927 void
replace(const SStringVector & args,const SString & str)1928 SYudit::replace (const SStringVector& args, const SString& str)
1929 {
1930 if (args.size () != 3 || args[1].size()==0)
1931 {
1932 SString ems = translate ("usage: replace original new");
1933 messagelabel->setMessage (ems, SMessageLabel::SS_ERR);
1934 return;
1935 }
1936 if (!editor->replace (args[1], args[2]))
1937 {
1938 SString ems = translate ("search string not found.");
1939 ems.append (SS_LB_LRE);
1940 ems.append ("'");
1941 ems.append (args[1]);
1942 ems.append ("'");
1943 ems.append (SS_LB_PDF);
1944 messagelabel->setMessage (ems, SMessageLabel::SS_ERR);
1945 }
1946 return;
1947 }
1948
1949 void
focusOutRequest(void * source)1950 SYudit::focusOutRequest (void *source)
1951 {
1952 if (source == editor)
1953 {
1954 command->setFocus();
1955 }
1956 else
1957 {
1958 editor->setFocus();
1959 }
1960 }
1961 void
focusChanged(void * source,bool in)1962 SYudit::focusChanged (void *source, bool in)
1963 {
1964 }
1965 void
caretMoved(void * source,unsigned int _line,unsigned int _column,bool _before)1966 SYudit::caretMoved (void *source,
1967 unsigned int _line, unsigned int _column, bool _before)
1968 {
1969 if (source != editor) return;
1970 caretMoved();
1971 }
1972
1973 void
caretMoved()1974 SYudit::caretMoved ()
1975 {
1976 STextIndex ti = editor->getCaretArrowFrom ();
1977
1978 if (ti.line != caretNow.line) messagebar->setRow(ti.line+1);
1979 if (ti.index != caretNow.index) messagebar->setColumn (ti.index);
1980
1981 if ((caretNow.line != ti.line || caretNow.index != ti.index)
1982 && !toolbar->printing)
1983 {
1984 messagelabel->setMessage("");
1985 }
1986 caretNow = ti;
1987
1988 toolbar->directionChanged (editor->isEmbedStateLR());
1989
1990 if (ti.index == 0)
1991 {
1992 messagebar->setGlyphInfo (0, SString());
1993 }
1994 else
1995 {
1996 STextIndex tn (ti.line, ti.index-1);
1997 const SGlyph* g = editor->glyphAt(tn);
1998 SV_UCS4 chars;
1999 if (g!=0)
2000 {
2001 chars = g->getChars();
2002 }
2003 messagebar->setGlyphInfo (g, editor->encode (chars));
2004 }
2005 }
2006
2007 /**
2008 * compose an escaped file name.
2009 */
2010 SString
composeFileNameCommand(const SString & prefix,const SString & encoding,const SString & file)2011 SYudit::composeFileNameCommand (const SString& prefix,
2012 const SString &encoding, const SString& file)
2013 {
2014 SString ret (prefix);
2015 ret.append ("-e ");
2016 ret.append (encoding);
2017 ret.append (" ");
2018 ret.append (quoteFileName (file));
2019 return SString(ret);
2020 }
2021
2022 SString
quoteFileName(const SString & file)2023 SYudit::quoteFileName (const SString& file)
2024 {
2025 SString ret;
2026 if (file.find(" ") < 0)
2027 {
2028 ret.append (file);
2029 }
2030 else if (file.find ("\"") < 0)
2031 {
2032 ret.append ("\"");
2033 ret.append (file);
2034 ret.append ("\"");
2035 }
2036 else
2037 {
2038 ret.append ("\'");
2039 ret.append (file);
2040 ret.append ("\'");
2041 }
2042 return SString(ret);
2043 }
2044
2045 SString
completeFileName(const SString & _file)2046 SYudit::completeFileName(const SString& _file)
2047 {
2048 /* home directory substitution ~/ */
2049 SString file(_file);
2050 if (file.size() > 2 && file[0] == '~' && file[1]=='/')
2051 {
2052 file.remove (0, 2);
2053 SString homedir = getHome();
2054 homedir.append ("/");
2055 file.insert (0, homedir);
2056 }
2057 return SString(file);
2058 }
2059
2060 /**
2061 * return false if it is not a new file or the file does not exist.
2062 */
2063 bool
newFileExists(const SString & filename)2064 SYudit::newFileExists (const SString& filename)
2065 {
2066 if (filename == currentFileName) return false;
2067 SFile f (filename);
2068 if (f.size() <0) return false;
2069 return true;
2070 }
2071
2072 void
saveProperties()2073 SYudit::saveProperties ()
2074 {
2075 /* do not save proeprties if it is being edited */
2076 SString cfile = getHome();;
2077 cfile.append ("/.yudit/yudit.properties");
2078 if (currentFileName == cfile) return;
2079
2080 //userProps.put ("yudit.default.printer", lastprinterOption);
2081 //userProps.put ("yudit.default.previewer", lastpreviewOption);
2082
2083 SString s;
2084 s = toolbar->fonts[toolbar->currentFont];
2085 userProps.put ("yudit.editor.font", s);
2086 s = toolbar->inputs[toolbar->currentInput];
2087 userProps.put ("yudit.editor.input", s);
2088 s = toolbar->fontsizes[toolbar->currentFontSize];
2089 userProps.put ("yudit.editor.fontsize", s);
2090 s = "";
2091 s.print ((unsigned int) getSize().width);
2092 s.append ("x");
2093 s.print ((unsigned int) getSize().height);
2094 userProps.put ("yudit.default.geometry", s);
2095 if (freehand)
2096 {
2097 SString s = freehand->getConverter();
2098 if (s.size())
2099 {
2100 userProps.put ("yudit.freehand.converter", s);
2101 }
2102 }
2103
2104 /* create a property file that has the original properties and
2105 * the ones that I changed.
2106 */
2107 /* create a property list that has changes since last save */
2108 SProperties changes;
2109 for (unsigned int i=0; i<userProps.size(); i++)
2110 {
2111 for (unsigned int j=0; j<userProps.size(i); j++)
2112 {
2113 if (userProps.get(i, j) ==0) continue;
2114 const SString& key = userProps.key(i, j);
2115 const SString& vle = *userProps.get(i, j);
2116 if (originalProperties.get (key) == 0)
2117 {
2118 changes.put (key, vle);
2119 }
2120 else if (vle != originalProperties[key])
2121 {
2122 changes.put (key, vle);
2123 }
2124 }
2125 }
2126 SProperties full = originalProperties;
2127 SProperties current;
2128 ::loadProperties (configFile, ¤t);
2129 /* just save back everything - change in yudit 2.5 */
2130 full.merge (current);
2131 /* merge in changes */
2132 full.merge (changes);
2133 full.put ("00HEADER.version.yudit", SD_YUDIT_VERSION);
2134
2135 /* That stupid old properties header comment. */
2136 const SString *pstr = full.get ("yudit.background.#");
2137 /* compatibility. remove this. */
2138 if (pstr!=0)
2139 {
2140 /* Test it */
2141 if (pstr->find ("# Autosave will eliminate all comments and '\\' (line joiner) characters.") > 0)
2142 {
2143 SString a;
2144 a.append ("# From version 2.7.6 Yudit preserves comment lines\n");
2145 a.append ("# that start with a '#' and preceed the property \n");
2146 a.append ("# line they refer to. ");
2147 full.put ("yudit.background.#", a);
2148 }
2149 }
2150
2151 if (!::saveProperties (configFile, full))
2152 {
2153 SString str = translate ("Could not save preferences");
2154 str.append (" ");
2155 str.append (configFile);
2156 messagelabel->setMessage (str, SMessageLabel::SS_ERR);
2157 fprintf (stderr, "Could not save properties into %*.*s.\n",
2158 SSARGS(configFile));
2159 }
2160 }
2161
2162 bool
dropped(void * p,const SString & mimetype,const SString & data)2163 SYudit::dropped (void* p, const SString& mimetype, const SString& data)
2164 {
2165 if (textDialog != 0 && textDialog->isShown()) return false;
2166 //fprintf (stderr, "SYudit::dropped %*.*s [%*.*s]\n", SSARGS(mimetype), SSARGS(data));
2167 SStringVector v (data, "\r\n");
2168 SString file=v[0];
2169 if (mimetype == "text/uri-list")
2170 {
2171 // FIX %XX
2172 SString ret;
2173 char* c = 0;
2174 char buff[3];
2175 for (unsigned i=0; i<file.size(); i++)
2176 {
2177 if (file[i] == '%' && i+2<file.size())
2178 {
2179 buff[0] = file[i+1];
2180 buff[1] = file[i+2];
2181 buff[2] = 0;
2182 c = 0;
2183 ret.append ((char)(unsigned char)strtol (buff, &c, 16));
2184 i=i+2;
2185 } else {
2186 ret.append ((char) file[i]);
2187 }
2188 }
2189 file = ret;
2190 if (file.size() < strlen ("file:")
2191 || strncmp (file.array(), "file:", strlen ("file:"))!=0)
2192 {
2193 SString msg = translate ("unsupported text/uri: ");
2194 msg.append (SS_LB_LRE);
2195 msg.append ("'");
2196 msg.append (file);
2197 msg.append ("'");
2198 msg.append (SS_LB_PDF);
2199 messagelabel->setMessage (msg, SMessageLabel::SS_ERR);
2200 return false;
2201 }
2202 file.remove (0, strlen ("file:"));
2203 }
2204 if (fileDialog != 0 && fileDialog->isShown())
2205 {
2206 fileDialog->center();
2207 fileDialog->setFileName (file);
2208 return true;
2209 }
2210 SString cm ("open -e ");;
2211 cm.append (lastencoding);
2212 cm.append (" ");
2213 if (toolbar->modified)
2214 {
2215 messagelabel->setMessage (translate ("Unsaved changes. Enter discards!"), SMessageLabel::SS_ERR);
2216 cm.append ("-yes ");
2217 cm.append (quoteFileName (file));
2218 command->setText(cm);
2219 command->setCursorIndex (SCursorIndex(0,10000));
2220 command->setFocus();
2221 }
2222 else
2223 {
2224 messagelabel->setMessage (translate ("open -yes -e encoding file"),
2225 SMessageLabel::SS_INFO);
2226 cm.append (quoteFileName (file));
2227 command->setText(cm);
2228 command->setCursorIndex (SCursorIndex(0,10000));
2229 command->putHistory(cm);
2230 SStringVector cv; cv.smartSplit (cm);
2231 load (cv, cm);
2232 }
2233 return true;
2234 }
2235
2236 void
createPasswordDialog()2237 SYudit::createPasswordDialog () // If needed
2238 {
2239 if (passwordDialog) return;
2240
2241 passwordDialog = new SPasswordDialog();
2242 passwordDialog->setModal (this);
2243 passwordDialog->setBackground (originalProperties["yudit.background"]);
2244 passwordDialog->setLabelForeground (originalProperties["yudit.label.foreground"]);
2245 passwordDialog->setTitleForeground (originalProperties["yudit.title.foreground"]);
2246 /* set the filetypes */
2247 SString font = originalProperties["yudit.default.font"];
2248 SString fontSizeString=originalProperties["yudit.default.fontsize"];
2249
2250 double fontSize=0;
2251 fontSizeString.append ((char)0);
2252 sscanf (fontSizeString.array(), "%lf", &fontSize);
2253 if (fontSize < 2.0) fontSize = 2.0;
2254 passwordDialog->setFont (font, fontSize);
2255 SIcon* icon = SIconFactory::getIcon("Yudit");
2256 passwordDialog->setApplicationImage (icon->getImage ());
2257 }
2258
2259 void
createFileDialog()2260 SYudit::createFileDialog () // If needed
2261 {
2262 if (fileDialog) return;
2263
2264 fileDialog = new SFileDialog();
2265 fileDialog->setModal (this);
2266 fileDialog->setBackground (originalProperties["yudit.background"]);
2267 fileDialog->setLabelForeground (originalProperties["yudit.label.foreground"]);
2268 fileDialog->setTitleForeground (originalProperties["yudit.title.foreground"]);
2269 fileDialog->setSliderBackground (originalProperties["yudit.slider.background"]);
2270
2271 SStringVector enc;
2272 if (originalProperties.get("yudit.editor.filetypes"))
2273 {
2274 //SString s = originalProperties["yudit.editor.filetypes"];
2275 //fprintf (stderr, "Specified filetypes: %*.*s\n", SSARGS (s));
2276 enc.append (SStringVector (originalProperties["yudit.editor.filetypes"]));
2277 }
2278 SBinHashtable<bool> ph;
2279 unsigned int ic=0;
2280
2281 for (ic=0; ic<enc.size(); ic++)
2282 {
2283 ph.put (enc[ic], true);
2284 }
2285 SStringVector benc = SEncoder::builtin();
2286
2287 unsigned int ib=0;
2288 for (ib=0; ib<benc.size(); ib++)
2289 {
2290 /* this is an input method and it is misleading. */
2291 if (benc[ib] == "unicode") continue;
2292 ph.put (benc[ib], true);
2293 }
2294 SStringVector bext = SEncoder::external();
2295
2296 for (ib=0; ib<bext.size(); ib++)
2297 {
2298 /* this is an input method and it is misleading. */
2299 if (bext[ib].match("iso-8859*"))
2300 {
2301 ph.put (bext[ib], true);
2302 }
2303 if (bext[ib].match("mik"))
2304 {
2305 ph.put (bext[ib], true);
2306 }
2307 else if (bext[ib] == "viscii")
2308 {
2309 ph.put (bext[ib], true);
2310 }
2311 else if (bext[ib] == "wingreek")
2312 {
2313 ph.put (bext[ib], true);
2314 }
2315 else if (bext[ib] == "tcvn")
2316 {
2317 ph.put (bext[ib], true);
2318 }
2319 else if (bext[ib].match("koi8-*"))
2320 {
2321 ph.put (bext[ib], true);
2322 }
2323 else if (bext[ib] == "rovas")
2324 {
2325 ph.put (bext[ib], true);
2326 }
2327 else if (bext[ib] == "cp-1251")
2328 {
2329 ph.put (bext[ib], true);
2330 }
2331 else if (bext[ib] == "cp-1250")
2332 {
2333 ph.put (bext[ib], true);
2334 }
2335 }
2336
2337 SStringVector addEnc;
2338 for (ic=0; ic<ph.size(); ic++)
2339 {
2340 for (ib=0; ib<ph.size(ic); ib++)
2341 {
2342 bool vle = ph.get (ic, ib);
2343 if (vle)
2344 {
2345 addEnc.append (ph.key (ic, ib));
2346 }
2347 }
2348 }
2349 /* set the filetypes */
2350 SString font = originalProperties["yudit.default.font"];
2351 SString fontSizeString=originalProperties["yudit.default.fontsize"];
2352
2353 double fontSize=0;
2354 fontSizeString.append ((char)0);
2355 sscanf (fontSizeString.array(), "%lf", &fontSize);
2356 if (fontSize < 2.0) fontSize = 2.0;
2357 fileDialog->setFont (font, fontSize);
2358 fileDialog->setFileTypes (addEnc);
2359
2360 SIcon* icon = SIconFactory::getIcon("Yudit");
2361 fileDialog->setApplicationImage (icon->getImage ());
2362 }
2363
2364 void
createHighlightDialog()2365 SYudit::createHighlightDialog () // If needed
2366 {
2367 if (highlightDialog) return;
2368
2369 highlightDialog = new SHighlightD();
2370 highlightDialog->setModal (this);
2371 highlightDialog->setBackground (originalProperties["yudit.background"]);
2372 highlightDialog->setLabelForeground (originalProperties["yudit.label.foreground"]);
2373 highlightDialog->setTitleForeground (originalProperties["yudit.title.foreground"]);
2374 highlightDialog->setSliderBackground (originalProperties["yudit.slider.background"]);
2375
2376 /* set the filetypes */
2377 SString font = originalProperties["yudit.default.font"];
2378 SString fontSizeString=originalProperties["yudit.default.fontsize"];
2379 double fontSize=0;
2380 fontSizeString.append ((char)0);
2381 sscanf (fontSizeString.array(), "%lf", &fontSize);
2382 if (fontSize < 2.0) fontSize = 2.0;
2383 highlightDialog->setFont (font, fontSize);
2384
2385 SIcon* icon = SIconFactory::getIcon("Yudit");
2386 highlightDialog->setApplicationImage (icon->getImage ());
2387 }
2388
2389 void
createKMapDialog()2390 SYudit::createKMapDialog ()
2391 {
2392 if (kmapDialog) return;
2393 kmapDialog = new SKMapDialog ();
2394 kmapDialog->setModal (this);
2395 kmapDialog->setXInputs (originalProperties["yudit.editor.xinputs"]);
2396 kmapDialog->setBackground (originalProperties["yudit.background"]);
2397 kmapDialog->setLabelForeground (originalProperties["yudit.label.foreground"]);
2398 kmapDialog->setTitleForeground (originalProperties["yudit.title.foreground"]);
2399 kmapDialog->setSliderBackground (originalProperties["yudit.slider.background"]);
2400 /* set the filetypes */
2401 SString font = originalProperties["yudit.default.font"];
2402 SString fontSizeString=originalProperties["yudit.default.fontsize"];
2403
2404 double fontSize=0;
2405 fontSizeString.append ((char)0);
2406 sscanf (fontSizeString.array(), "%lf", &fontSize);
2407 if (fontSize < 2.0) fontSize = 2.0;
2408 kmapDialog->setFont (font, fontSize);
2409 /* button size bug workaround */
2410 SDimension dim = kmapDialog->getPreferredSize();
2411 kmapDialog->resize(SDimension(dim.width+2, dim.height+2));
2412
2413 SIcon* icon = SIconFactory::getIcon("Yudit");
2414 kmapDialog->setApplicationImage (icon->getImage ());
2415 }
2416
2417 void
createTextDialog()2418 SYudit::createTextDialog ()
2419 {
2420 if (textDialog) return;
2421
2422 textDialog = new STextDialog();
2423 textDialog->setModal (this);
2424
2425 textDialog->setBackground (originalProperties["yudit.background"]);
2426 textDialog->setLabelForeground (originalProperties["yudit.label.foreground"]);
2427 textDialog->setTitleForeground (originalProperties["yudit.title.foreground"]);
2428
2429 SString font = originalProperties["yudit.default.font"];
2430 SString fontSizeString=originalProperties["yudit.default.fontsize"];
2431
2432 double fontSize=0;
2433 fontSizeString.append ((char)0);
2434 sscanf (fontSizeString.array(), "%lf", &fontSize);
2435 if (fontSize < 2.0) fontSize = 2.0;
2436
2437 textDialog->setFont (font, fontSize);
2438
2439 SIcon* icon = SIconFactory::getIcon("Yudit");
2440 textDialog->setApplicationImage (icon->getImage ());
2441 }
2442
2443 /*
2444 * SFreeHandListener
2445 * FIXME:
2446 */
2447 void
freeHandTextChanged(void * source,const SString & lookup)2448 SYudit::freeHandTextChanged (void* source, const SString& lookup)
2449 {
2450 if (lookup.size()==0) return;
2451 if (editor->isFocused ())
2452 {
2453 editor->insertEditorText (lookup);
2454 }
2455 else if (command->isFocused())
2456 {
2457 command->insertEditorText (lookup);
2458 }
2459 }
2460
2461 void
printl(const SLayout lo)2462 printl (const SLayout lo)
2463 {
2464 SLocation l = lo.getLocation();
2465 SDimension d = lo.getDimension();
2466 fprintf (stderr, "l= (%d,%d) d= (%u,%u) l2 =(%d,%d)\n",
2467 l.x, l.y, d.width, d.height, l.x + (int) d.width, l.y + d.height);
2468 }
2469
2470 bool
timeout(const SEventSource * s)2471 SYudit::timeout (const SEventSource* s)
2472 {
2473 if (s != deferredLoader) {
2474 return SFrame::timeout(s);
2475 }
2476 if (!deferredLoader) {
2477 return false;
2478 }
2479 editor->setEditable (true);
2480 if (isFirstLoad) {
2481 isFirstLoad = false;
2482 if (firstLoad.size()) {
2483 load (firstLoad, "");
2484 }
2485 }
2486 delete deferredLoader;
2487 deferredLoader = 0;
2488 // hacking, for X11 somehow focus is remembered.
2489 window->getKeyboardFocus();
2490 editor->setFocus ();
2491 return false;
2492 }
2493
2494 void
showFreeHand(bool is)2495 SYudit::showFreeHand(bool is)
2496 {
2497 if (!(is ^ freeHandShown)) return;
2498 /* need to create */
2499 bool newhand = (freehand==0);
2500 freeHandShown = is;
2501 if (freehand==0)
2502 {
2503 freehand = new SFreeHand ();
2504 freehand->setBackground (originalProperties["yudit.background"]);
2505 freehand->setLabelForeground (originalProperties["yudit.label.foreground"], originalProperties["yudit.title.foreground"]);
2506 freehand->setForeground (originalProperties["yudit.title.foreground"], originalProperties["yudit.title.foreground"]);
2507 freehand->setDrawingForeground (SColor("green"), SColor("yellow"));
2508 freehand->setDrawingBackground (SColor("black"));
2509 freehand->setConverter (originalProperties["yudit.freehand.converter"]);
2510
2511 freehand->setSliderBackground (
2512 originalProperties["yudit.slider.background"]);
2513 freehand->setFreeHandListener (this);
2514 SString font = originalProperties["yudit.default.font"];
2515 SString fontSize=originalProperties["yudit.default.fontsize"];
2516
2517 double df=0;
2518 fontSize.append ((char)0);
2519 sscanf (fontSize.array(), "%lf", &df);
2520 if (fontSize < 2.0) df = 2.0;
2521 freehand->setButtonFont (font, df);
2522
2523 font = toolbar->fonts[toolbar->currentFont];
2524 fontSize = toolbar->fontsizes[toolbar->currentFontSize];
2525 fontSize.append ((char)0);
2526
2527 if (sscanf (fontSize.array(), "%lf", &df)==0 || df < 2.0) df = 2.0;
2528 freehand->setFont (font, df);
2529 freeHandHeight = freehand->getPreferredSize().height;
2530 }
2531
2532 SLocation l = editorLayout.getLocation ();
2533 SDimension d = editorLayout.getDimension ();
2534 SLocation sl = sliderLayout.getLocation();
2535 SDimension sd = sliderLayout.getDimension();
2536 int hp = l.y + (int) d.height -(int)freeHandHeight;
2537
2538 if (is)
2539 {
2540 editor->setLayout (
2541 SLayout (
2542 SLocation (l.x, l.y),
2543 SLocation (l.x+(int) d.width, hp),
2544 SLocation (0, 0),
2545 SLocation (100, 100)
2546 )
2547 );
2548 slider->setLayout (SLayout (
2549 SLocation (sl.x, sl.y),
2550 SLocation (sl.x+(int)sd.width, hp),
2551 SLocation (100, 0),
2552 SLocation (100, 100)
2553 ));
2554
2555 freehand->setLayout (
2556 SLayout (
2557 SLocation (l.x, hp),
2558 SLocation (sl.x + (int) sd.width,
2559 hp+(int)freeHandHeight),
2560 SLocation (0, 100),
2561 SLocation (100, 100)
2562 )
2563 );
2564 SLocation ml = freehand->getLayout().getLocation (layout, getSize());
2565 SDimension md = freehand->getLayout().getDimension (layout, getSize());
2566 }
2567 else
2568 {
2569 editor->setLayout (editorLayout);
2570 slider->setLayout (sliderLayout);
2571 /* move it away */
2572 freehand->setLayout (
2573 SLayout (
2574 SLocation (l.x, -(int)hp -(int)freeHandHeight-1),
2575 SLocation (sl.x + (int) sd.width, -1),
2576 SLocation (0, 0),
2577 SLocation (0, 0)
2578 )
2579 );
2580 }
2581 if (newhand)
2582 {
2583 add (freehand);
2584 editor->setFocus();
2585 }
2586 _resized ();
2587 }
2588
2589 /**
2590 * Try to prefix executable with mytool -pipecmd.
2591 * @return false if mytool not found.
2592 */
2593 bool
addMytoolPrefix(SString * executable)2594 SYudit::addMytoolPrefix (SString* executable)
2595 {
2596 if (executable->size()==0) return false;
2597 #ifdef USE_WINAPI
2598 SString pr = getPrefix();
2599 pr.append ("/bin/mytool.exe");
2600 SFile f (pr);
2601 if (f.size () <= 0)
2602 {
2603 SString message=translate ("Command not found: ");
2604 message.append (SS_LB_RLE);
2605 message.append ("'");
2606 message.append (pr);
2607 message.append ("'");
2608 message.append (SS_LB_PDF);
2609 messagelabel->setMessage (message, SMessageLabel::SS_ERR);
2610 return false;
2611 }
2612 #else
2613 SString pr = getPrefix();
2614 pr.append ("/bin/mytool");
2615 SFile f0 (pr);
2616 if (f0.size () <= 0)
2617 {
2618 pr = getPrefix();
2619 SStringVector pv(pr, "/");
2620 if (pv.size() > 1)
2621 {
2622 pv.truncate (pv.size()-2);
2623 }
2624 pr = pv.join ("/");
2625 pr.insert (0, "/");
2626 pr.append ("/bin/mytool");
2627 SFile f0 (pr);
2628 if (f0.size () <= 0)
2629 {
2630 SString message=translate ("Command not found: ");
2631 message.append (SS_LB_LRE);
2632 message.append ("'");
2633 message.append (pr);
2634 message.append ("'");
2635 message.append (SS_LB_PDF);
2636 messagelabel->setMessage (message, SMessageLabel::SS_ERR);
2637 return false;
2638 }
2639 }
2640 #endif
2641 SStringVector v;
2642 v.smartSplit (*executable);
2643 if (!commandExists (v[0]))
2644 {
2645 SString message=translate ("Command not found: ");
2646 message.append (SS_LB_LRE);
2647 message.append ("'");
2648 message.append (v[0]);
2649 message.append ("'");
2650 message.append (SS_LB_PDF);
2651 messagelabel->setMessage (message, SMessageLabel::SS_ERR);
2652 return false;
2653 }
2654 pr.insert (0, "\"");
2655 pr.append ("\"");
2656 pr.append (" -pipecmd ");
2657 executable->insert (0, pr);
2658 return true;
2659 }
2660
2661 /**
2662 * Set the title to current filename.
2663 */
2664 void
setFileTitle()2665 SYudit::setFileTitle ()
2666 {
2667 SDir d;
2668 /* this will chop off filename */
2669 d.cd (currentFileName);
2670 SString dn = d.getName ();
2671 SString fn;
2672 SStringVector v(currentFileName, "/");
2673 if (v.size())
2674 {
2675 fn.append (v[v.size()-1]);
2676 }
2677
2678 SString t = fn;
2679 // FIXME: do we need the directory?
2680 dn = "";
2681 if (dn.size () > 0)
2682 {
2683 t.append (" (");
2684 t.append (dn);
2685 t.append (")");
2686 }
2687 t.append (" Yudit-");
2688 t.append (SD_YUDIT_VERSION);
2689 setTitle (t);
2690 }
2691
2692 /**
2693 * Translate our string highlight mode to an integer
2694 * @return -1 if it can not be translated.
2695 */
2696 static SString
translateHighlightMode(const SString & hl)2697 translateHighlightMode (const SString& hl)
2698 {
2699 if (hl == "none" || hl == "simple" || hl == "simple-dark")
2700 {
2701 return SString(hl);
2702 }
2703 if (SSyntax::isSupported (hl)) return SString(hl);
2704 return SString("");
2705 }
2706
2707 /**
2708 * \return negative on fail or the number if it is specified
2709 * as +NUMBER.
2710 */
2711 static int
getLineNumber(const SString & s)2712 getLineNumber (const SString& s)
2713 {
2714 if (s.size() < 2 || s.peek(0) != '+') return -1;
2715 int line = 0;
2716 for (unsigned int i=1; i<s.size(); i++)
2717 {
2718 if (s.peek(i) >= '0' && s.peek(i) <= '9')
2719 {
2720 if (line < 100000000)
2721 {
2722 line = line * 10;
2723 line += (s.peek(i) - '0');
2724 }
2725 }
2726 else
2727 {
2728 return -1;
2729 }
2730 }
2731 return line;
2732 }
2733
getPrintHelp()2734 static SString getPrintHelp ()
2735 {
2736 SString pstr =
2737 translate ("usage: print [-o file] [-p printer] [-e exec] [-break] [-hsize header-font-size]");
2738 pstr.append (" [-m A4] [-L]");
2739 return SString (pstr);
2740 }
2741