1 
2 /******************************************************************************
3 * MODULE     : editor.cpp
4 * DESCRIPTION: routines for the editor
5 * COPYRIGHT  : (C) 1999  Joris van der Hoeven
6 *******************************************************************************
7 * This software falls under the GNU general public license version 3 or later.
8 * It comes WITHOUT ANY WARRANTY WHATSOEVER. For details, see the file LICENSE
9 * in the root directory or <http://www.gnu.org/licenses/gpl-3.0.html>.
10 ******************************************************************************/
11 
12 #include "edit_main.hpp"
13 #include "tm_buffer.hpp"
14 #include "file.hpp"
15 #include "sys_utils.hpp"
16 #include "printer.hpp"
17 #include "convert.hpp"
18 #include "connect.hpp"
19 #include "typesetter.hpp"
20 #include "drd_std.hpp"
21 #include "message.hpp"
22 #include <setjmp.h>
23 
24 #ifdef EXPERIMENTAL
25 #include "../../Style/Memorizer/clean_copy.hpp"
26 #endif
27 
28 #ifdef PDF_RENDERER
29 //#include "Pdf/pdf_renderer.hpp"
30 #include "Pdf/pdf_hummus_renderer.hpp"
31 #endif
32 
33 #ifdef USE_GS
34 #include "Ghostscript/gs_utilities.hpp"
35 #endif
36 
37 #ifdef QTTEXMACS
38 #include "Qt/qt_gui.hpp"
39 #include "Qt/qt_utilities.hpp"
40 #endif
41 
42 #if defined (QTTEXMACS) && (defined (__MINGW__) || defined (__MINGW32__))
43 #include "Qt/WINPrint.hpp"
44 #endif
45 /******************************************************************************
46 * Constructors and destructor
47 ******************************************************************************/
48 
editor_rep()49 editor_rep::editor_rep ():
50   simple_widget_rep (), cvw (NULL), mvw (NULL),
51   drd (buf->buf->title, std_drd), et (the_et), rp (buf->rp) {}
52 
editor_rep(server_rep * sv2,tm_buffer buf2)53 editor_rep::editor_rep (server_rep* sv2, tm_buffer buf2):
54   simple_widget_rep (), sv (sv2), cvw (NULL), mvw (NULL), buf (buf2),
55   drd (buf->buf->title, std_drd), et (the_et), rp (buf2->rp) {}
56 
edit_main_rep(server_rep * sv,tm_buffer buf)57 edit_main_rep::edit_main_rep (server_rep* sv, tm_buffer buf):
58   editor_rep (sv, buf), props (UNKNOWN), ed_obs (edit_observer (this))
59 {
60 #ifdef EXPERIMENTAL
61   cct= copy (subtree (et, rp));
62   copy_ip (subtree (et, rp), cct);
63 #endif
64   attach_observer (subtree (et, rp), ed_obs);
65   notify_change (THE_TREE);
66   tp= correct_cursor (et, rp * 0);
67 }
68 
~edit_main_rep()69 edit_main_rep::~edit_main_rep () {
70   detach_observer (subtree (et, rp), ed_obs);
71 #ifdef EXPERIMENTAL
72   mem= memorizer ();
73 #endif
74 }
75 
76 editor
new_editor(server_rep * sv,tm_buffer buf)77 new_editor (server_rep* sv, tm_buffer buf) {
78   return tm_new<edit_main_rep> (sv, buf);
79 }
80 
81 /******************************************************************************
82 * Properties
83 ******************************************************************************/
84 
85 void
set_property(scheme_tree what,scheme_tree val)86 edit_main_rep::set_property (scheme_tree what, scheme_tree val) {
87   props (what)= val;
88 }
89 
90 void
set_bool_property(string what,bool val)91 edit_main_rep::set_bool_property (string what, bool val) {
92   props (what)= (val? string ("true"): string ("false"));
93 }
94 
95 void
set_int_property(string what,int val)96 edit_main_rep::set_int_property (string what, int val) {
97   props (what)= as_tree (val);
98 }
99 
100 void
set_string_property(string what,string val)101 edit_main_rep::set_string_property (string what, string val) {
102   props (what)= val;
103 }
104 
105 scheme_tree
get_property(scheme_tree what)106 edit_main_rep::get_property (scheme_tree what) {
107   return props [what];
108 }
109 
110 bool
get_bool_property(string what)111 edit_main_rep::get_bool_property (string what) {
112   return as_bool (props [what]);
113 }
114 
115 int
get_int_property(string what)116 edit_main_rep::get_int_property (string what) {
117   return as_int (props [what]);
118 }
119 
120 string
get_string_property(string what)121 edit_main_rep::get_string_property (string what) {
122   return as_string (props [what]);
123 }
124 
125 /******************************************************************************
126 * Global routines
127 ******************************************************************************/
128 
129 void
clear_buffer()130 edit_main_rep::clear_buffer () {
131   assign (rp, tree (DOCUMENT, tree ("")));
132 }
133 
134 void
new_window()135 edit_main_rep::new_window () {
136 }
137 
138 void
clone_window()139 edit_main_rep::clone_window () {
140 }
141 
142 void
tex_buffer()143 edit_main_rep::tex_buffer () {
144 }
145 
146 url
get_name()147 edit_main_rep::get_name () {
148   return buf->buf->name;
149 }
150 
151 void
focus_on_this_editor()152 edit_main_rep::focus_on_this_editor () {
153   focus_on_editor (this);
154 }
155 
156 void
notify_page_change()157 edit_main_rep::notify_page_change () {
158   if (is_attached (this)) send_invalidate_all (this);
159 }
160 
161 string
get_metadata(string kind)162 edit_main_rep::get_metadata (string kind) {
163   string var= "global-" * kind;
164   string val= get_init_string (var);
165   if (val != "") return val;
166   val= search_metadata (subtree (et, rp), kind);
167   if (val != "") return val;
168   if (kind == "title") return as_string (tail (get_name ()));
169 #ifndef __MINGW32__
170   if (kind == "author" &&
171       !is_none (resolve_in_path ("finger")) &&
172       !is_none (resolve_in_path ("sed"))) {
173     string val= var_eval_system ("finger `whoami` | sed -e '/Name/!d' -e 's/.*Name: //'");
174     if (N(val) > 1) return utf8_to_cork (val);
175   }
176 #endif
177   return "";
178 }
179 
180 /******************************************************************************
181 * Printing
182 ******************************************************************************/
183 
184 string printing_dpi ("600");
185 string printing_cmd ("lpr");
186 string printing_on ("a4");
187 
188 bool
use_pdf()189 use_pdf () {
190 #ifdef PDF_RENDERER
191   return get_preference ("native pdf", "on") == "on";
192 #else
193   return false;
194 #endif
195 }
196 
197 bool
use_ps()198 use_ps () {
199 #ifdef PDF_RENDERER
200   return get_preference ("native postscript", "on") == "on";
201 #else
202   return true;
203 #endif
204 }
205 
206 void
print(url name,bool conform,int first,int last)207 edit_main_rep::print (url name, bool conform, int first, int last) {
208   bool ps  = (suffix (name) == "ps");
209   bool pdf = (suffix (name) == "pdf");
210   url  orig= resolve (name, "");
211 
212 #ifdef USE_GS
213   if (!use_pdf () && pdf)
214     name= url_temp (".ps");
215   if (!use_ps () && ps)
216     name= url_temp (".pdf");
217 #endif
218 
219   string medium = env->get_string (PAGE_MEDIUM);
220   if (conform && (medium != "paper")) conform= false;
221   // FIXME: better command for conform printing
222 
223   // Set environment variables for printing
224 
225   typeset_prepare ();
226   env->write (DPI, printing_dpi);
227   env->write (PAGE_SHOW_HF, "true");
228   env->write (PAGE_SCREEN_MARGIN, "false");
229   if (!conform) {
230     env->write (PAGE_MEDIUM, "paper");
231     env->write (PAGE_PRINTED, "true");
232   }
233 
234   // Typeset pages for printing
235 
236   box the_box= typeset_as_document (env, subtree (et, rp), reverse (rp));
237 
238   // Determine parameters for printer
239 
240   string page_type = env->get_string (PAGE_TYPE);
241   double w         = env->page_width;
242   double h         = env->page_height;
243   double cm        = env->as_length (string ("1cm"));
244   bool   landsc    = env->page_landscape;
245   int    dpi       = as_int (printing_dpi);
246   int    start     = max (0, first-1);
247   int    end       = min (N(the_box[0]), last);
248   int    pages     = end-start;
249   if (conform) {
250     page_type= "user";
251     SI bw= the_box[0][0]->w();
252     SI bh= the_box[0][0]->h();
253     string bws= as_string (bw) * "tmpt";
254     string bhs= as_string (bh) * "tmpt";
255     w= env->as_length (bws);
256     h= env->as_length (bhs);
257   }
258 
259   // Print pages
260   renderer ren;
261 #ifdef PDF_RENDERER
262   if (use_pdf () && (pdf || !use_ps ()))
263     ren= pdf_hummus_renderer (name, dpi, pages, page_type, landsc, w/cm, h/cm);
264   else
265     ren= printer (name, dpi, pages, page_type, landsc, w/cm, h/cm);
266 #else
267   ren= printer (name, dpi, pages, page_type, landsc, w/cm, h/cm);
268 #endif
269 
270   if (ren->is_started ()) {
271     int i;
272     ren->set_metadata ("title", get_metadata ("title"));
273     ren->set_metadata ("author", get_metadata ("author"));
274     ren->set_metadata ("subject", get_metadata ("subject"));
275     for (i=start; i<end; i++) {
276       tree bg= env->read (BG_COLOR);
277       ren->set_background (bg);
278       if (bg != "white")
279         ren->clear_pattern (0, (SI) -h, (SI) w, 0);
280 
281       rectangles rs;
282       the_box[0]->sx(i)= 0;
283       the_box[0]->sy(i)= 0;
284       the_box[0][i]->redraw (ren, path (0), rs);
285       if (i<end-1) ren->next_page ();
286     }
287   }
288   tm_delete (ren);
289 
290 #ifdef USE_GS
291   if (!use_pdf () && pdf) {
292     gs_to_pdf (name, orig, landsc, h/cm, w/cm);
293     ::remove (name);
294   }
295   if (!use_ps () && ps) {
296     gs_to_ps (name, orig, landsc, h/cm, w/cm);
297     ::remove (name);
298   }
299   if (ps || pdf)
300     if (get_preference ("texmacs->pdf:check", "off") == "on") {
301       system_wait ("Checking exported file for correctness", "please wait");
302       gs_check (orig);
303     }
304 #endif
305 }
306 
307 void
print_to_file(url name,string first,string last)308 edit_main_rep::print_to_file (url name, string first, string last) {
309   print (name, false, as_int (first), as_int (last));
310   set_message ("Done printing", "print to file");
311 }
312 
313 void
print_buffer(string first,string last)314 edit_main_rep::print_buffer (string first, string last) {
315    url target;
316 #if defined (QTTEXMACS) && (defined (__MINGW__) || defined (__MINGW32__))
317    {
318      target= url_temp (".pdf");
319      WINPrint wprt(to_qstring(as_string(target)),env->page_landscape);
320      if(wprt.doit) print (target, false,wprt.first_page,wprt.last_page);
321    }
322 #else
323   target= url_temp (".ps");
324   print (target, false, as_int (first), as_int (last));
325   system (printing_cmd, target);  // Send the document to the printer
326   set_message ("Done printing", "print buffer");
327  #endif
328   ::remove (target);
329 }
330 
331 #ifdef THISISTHEPREVIOUSCODE_IJUSTLEFTITHEREINCASE
332 void
print_buffer(string first,string last)333 edit_main_rep::print_buffer (string first, string last) {
334   // in Qt this is the main entry point to the printing subsystem.
335   // the other routines (print_to_file, ...) are overriden since all fine tuning
336   // is made here via the Qt print dialog
337   bool to_file, landscape;
338   url name = url_none();
339   string printer;
340   string paper_type;
341   if (qt_print (to_file, landscape, printer, name, first, last, paper_type)) {
342       if (!to_file) name = url_temp (".ps");
343       print (name, false, as_int (first), as_int (last));
344       if (!to_file) {
345         string cmd = printing_cmd * " -P" * printer;
346         system (cmd, name);
347         ::remove (name);
348       }
349   }
350 }
351 #endif
352 
353 void
export_ps(url name,string first,string last)354 edit_main_rep::export_ps (url name, string first, string last) {
355   print (name, true, as_int (first), as_int (last));
356 }
357 
358 array<int>
print_snippet(url name,tree t)359 edit_main_rep::print_snippet (url name, tree t) {
360   bool ps= suffix (name) == "ps" || suffix (name) == "eps";
361   typeset_prepare ();
362   int dpi= as_int (printing_dpi);
363   //if (!ps) t= tree (WITH, MAGNIFICATION, "2", PAGE_WIDTH, "40cm", t);
364   if (!ps) t= tree (WITH, MAGNIFICATION, "1.6", PAGE_WIDTH, "40cm", t);
365   box b= typeset_as_box (env, t, path ());
366   if (b->x4 - b->x3 >= 5*PIXEL && b->y4 - b->y3 >= 5*PIXEL) {
367     if (ps) make_eps (name, b, dpi);
368     else {
369       url temp= url_temp (".eps");
370       make_eps (temp, b, dpi);
371       ::remove (name);
372       system ("convert", temp, name);
373       if (!exists (name))
374         cout << "TeXmacs] warning, failed to create image " << name << "\n";
375       ::remove (temp);
376     }
377   }
378   array<int> a;
379   a << b->x3 << b->y3 << b->x4 << b->y4;
380   return a;
381 }
382 
383 bool
graphics_file_to_clipboard(url name)384 edit_main_rep::graphics_file_to_clipboard (url name) {
385 #ifdef QTTEXMACS
386   the_gui->put_graphics_on_clipboard (name);
387   return true;
388 #else
389   return false;
390 #endif
391 }
392 
393 /******************************************************************************
394 * Evaluation of expressions
395 ******************************************************************************/
396 
397 void
footer_eval(string s)398 edit_main_rep::footer_eval (string s) {
399   // s= unslash (s); // FIXME: dirty fix; should not be necessary
400   s= tm_decode (s);
401   string r= object_to_string (eval (s));
402   set_message (verbatim (r), "evaluate expression");
403 }
404 
405 tree
the_line()406 edit_main_rep::the_line () {
407   path p= search_parent_upwards (DOCUMENT);
408   return copy (subtree (et, p));
409 }
410 
411 tree
the_root()412 edit_main_rep::the_root () {
413   return et;
414 }
415 
416 tree
the_buffer()417 edit_main_rep::the_buffer () {
418   return subtree (et, rp);
419 }
420 
421 tree
the_subtree(path p)422 edit_main_rep::the_subtree (path p) {
423   return subtree (et, p);
424 }
425 
426 path
the_buffer_path()427 edit_main_rep::the_buffer_path () {
428   return copy (rp);
429 }
430 
431 path
the_path()432 edit_main_rep::the_path () {
433   return copy (tp);
434 }
435 
436 path
the_shifted_path()437 edit_main_rep::the_shifted_path () {
438   return shift (et, tp, 1);
439 }
440 
441 /******************************************************************************
442 * Miscellaneous
443 ******************************************************************************/
444 
445 void
show_tree()446 edit_main_rep::show_tree () {
447   stretched_print (et, true);
448   // cout << et << "\n";
449 }
450 
451 void
show_env()452 edit_main_rep::show_env () {
453   cout << env << "\n";
454 }
455 
456 void
show_path()457 edit_main_rep::show_path () {
458   cout << tp << "\n";
459 }
460 
461 void
show_cursor()462 edit_main_rep::show_cursor () {
463   cout << "Principal cursor: "
464        << cu->ox << ", " << cu->oy << " [" << cu->delta << "]\n";
465   cout << "Ghost cursor    : "
466        << mv->ox << ", " << mv->oy << " [" << mv->delta << "]\n";
467 }
468 
469 void
show_selection()470 edit_main_rep::show_selection () {
471   selection sel; selection_get (sel);
472   cout << "physical  selection: " << cur_sel << "\n";
473   cout << "logical   selection: " << sel->start << " --- " << sel->end << "\n";
474 }
475 
476 void
show_meminfo()477 edit_main_rep::show_meminfo () {
478   mem_info ();
479 }
480 
481 void
edit_special()482 edit_main_rep::edit_special () {
483 }
484 
485 #ifdef UNCOMMENTED
486 void test_commute ();
487 void test_invert ();
488 #endif
489 
490 void
edit_test()491 edit_main_rep::edit_test () {
492   cout << "Test !\n";
493 #ifdef UNCOMMENTED
494   test_commute();
495   test_invert();
496 #endif
497 }
498