]> git.lyx.org Git - lyx.git/blob - src/insets/insetinclude.C
283eb0a1f14a3fe939c53aa1f4932ca7ac5598f7
[lyx.git] / src / insets / insetinclude.C
1 #include <config.h>
2
3 #include <cstdlib>
4
5 #ifdef __GNUG__
6 #pragma implementation
7 #endif
8
9 #include FORMS_H_LOCATION 
10 #include "filedlg.h" 
11 #include "insetinclude.h"
12 #include "buffer.h"
13 #include "bufferlist.h"
14 #include "debug.h"
15 #include "support/filetools.h"
16 #include "lyxrc.h"
17 #include "LyXView.h"
18 #include "LaTeXFeatures.h"
19 #include "lyx_gui_misc.h" // CancelCloseBoxCB
20 #include "gettext.h"
21 #include "include_form.h"
22 #include "support/FileInfo.h"
23
24 extern BufferView *current_view;
25
26 extern LyXRC *lyxrc;
27 extern BufferList bufferlist;
28 extern void UpdateInset(Inset* inset, bool mark_dirty = true);
29
30
31 FD_include *create_form_include(void)
32 {
33   FL_OBJECT *obj;
34   FD_include *fdui = (FD_include *) fl_calloc(1, sizeof(FD_include));
35
36   fdui->include = fl_bgn_form(FL_NO_BOX, 340, 210);
37   obj = fl_add_box(FL_UP_BOX,0,0,340,210,"");
38   obj = fl_add_frame(FL_ENGRAVED_FRAME,10,70,160,90,"");
39   fdui->browsebt = obj = fl_add_button(FL_NORMAL_BUTTON,230,30,100,30,idex(_("Browse|#B")));
40     fl_set_button_shortcut(obj,scex(_("Browse|#B")),1);
41     fl_set_object_lsize(obj,FL_NORMAL_SIZE);
42     fl_set_object_callback(obj,include_cb,0);
43   fdui->flag1 = obj = fl_add_checkbutton(FL_PUSH_BUTTON,180,70,150,30,idex(_("Don't typeset|#D")));
44     fl_set_button_shortcut(obj,scex(_("Don't typeset|#D")),1);
45     fl_set_object_lsize(obj,FL_NORMAL_SIZE);
46   obj = fl_add_button(FL_RETURN_BUTTON,120,170,100,30,_("OK"));
47     fl_set_object_lsize(obj,FL_NORMAL_SIZE);
48     fl_set_object_callback(obj,include_cb,1);
49   obj = fl_add_button(FL_NORMAL_BUTTON,230,170,100,30,idex(_("Cancel|^[")));
50     fl_set_button_shortcut(obj,scex(_("Cancel|^[")),1);
51     fl_set_object_lsize(obj,FL_NORMAL_SIZE);
52     fl_set_object_callback(obj,include_cb,2);
53   obj = fl_add_button(FL_NORMAL_BUTTON,230,130,100,30,idex(_("Load|#L")));
54     fl_set_button_shortcut(obj,scex(_("Load|#L")),1);
55     fl_set_object_lsize(obj,FL_NORMAL_SIZE);
56     fl_set_object_callback(obj,include_cb,5);
57   fdui->input = obj = fl_add_input(FL_NORMAL_INPUT,10,30,210,30,idex(_("File name:|#F")));
58     fl_set_input_shortcut(obj,scex(_("File name:|#F")),1);
59     fl_set_object_lsize(obj,FL_NORMAL_SIZE);
60     fl_set_object_lalign(obj,FL_ALIGN_TOP_LEFT);
61   fdui->flag41 = obj = fl_add_checkbutton(FL_PUSH_BUTTON,180,100,150,30,idex(_("Visible space|#s")));
62     fl_set_button_shortcut(obj,scex(_("Visible space|#s")),1);
63     fl_set_object_lsize(obj,FL_NORMAL_SIZE);
64
65   fdui->include_grp = fl_bgn_group();
66   fdui->flag4 = obj = fl_add_checkbutton(FL_RADIO_BUTTON,10,130,160,30,idex(_("Verbatim|#V")));
67     fl_set_button_shortcut(obj,scex(_("Verbatim|#V")),1);
68     fl_set_object_lsize(obj,FL_NORMAL_SIZE);
69     fl_set_object_callback(obj,include_cb,10);
70   fdui->flag2 = obj = fl_add_checkbutton(FL_RADIO_BUTTON,10,100,160,30,idex(_("Use input|#i")));
71     fl_set_button_shortcut(obj,scex(_("Use input|#i")),1);
72     fl_set_object_lsize(obj,FL_NORMAL_SIZE);
73     fl_set_object_callback(obj,include_cb,11);
74   fdui->flag3 = obj = fl_add_checkbutton(FL_RADIO_BUTTON,10,70,160,30,idex(_("Use include|#U")));
75     fl_set_button_shortcut(obj,scex(_("Use include|#U")),1);
76     fl_set_object_lsize(obj,FL_NORMAL_SIZE);
77     fl_set_object_callback(obj,include_cb,11);
78   fl_end_group();
79
80   fl_end_form();
81
82   //fdui->include->fdui = fdui;
83
84   return fdui;
85 }
86 /*---------------------------------------*/
87
88
89 FD_include *form = 0;
90
91 extern "C" void include_cb(FL_OBJECT *, long arg)
92 {
93     
94         InsetInclude *inset = (InsetInclude*)form->vdata;
95         switch (arg) {
96         case 0:
97         {
98                 // Should browsing too be disabled in RO-mode?
99                 LyXFileDlg fileDlg;
100                 string mpath = OnlyPath(inset->getMasterFilename());
101                 string ext;
102     
103                 if (fl_get_button(form->flag2)) // Use Input Button
104                         ext = "*.tex";
105                 else if (fl_get_button(form->flag4)) // Verbatim all files
106                         ext = "*";
107                 else
108                         ext = "*.lyx";
109                 // launches dialog
110                 fileDlg.SetButton(0, _("Documents"), lyxrc->document_path);
111     
112                 // Use by default the master's path
113                 string filename = fileDlg.Select(_("Select Child Document"),
114                                                   mpath, ext, 
115                                                   inset->getContents());
116                 XFlush(fl_get_display());
117  
118                 // check selected filename
119                 if (!filename.empty()) {
120                         string filename2 = MakeRelPath(filename,
121                                                         mpath);
122                         if (prefixIs(filename2, ".."))
123                                 fl_set_input(form->input,
124                                              filename.c_str());
125                         else
126                                 fl_set_input(form->input,
127                                              filename2.c_str());
128                 }
129                 break;
130         }
131
132         case 1:
133                 if(!current_view->currentBuffer()->isReadonly()) {
134                         inset->setContents(fl_get_input(form->input));
135                         // don't typeset
136                         inset->setNoLoad(fl_get_button(form->flag1));
137                         if (fl_get_button(form->flag2))
138                                 inset->setInput();
139                         else if (fl_get_button(form->flag3))
140                                 inset->setInclude();
141                         else if (fl_get_button(form->flag4)) {
142                                 inset->setVerb();
143                                 inset->setVisibleSpace(fl_get_button(form->flag41));
144                         }
145                         
146                         fl_hide_form(form->include);
147                         UpdateInset(inset);
148                         break;
149                 } // fall through
150                 
151         case 2:
152                 fl_hide_form(form->include);
153                 break;
154         case 5:
155                 if(!current_view->currentBuffer()->isReadonly()) {
156                         inset->setContents(fl_get_input(form->input));
157                         inset->setNoLoad(fl_get_button(form->flag1));
158                         if (fl_get_button(form->flag2))
159                                 inset->setInput();
160                         else if (fl_get_button(form->flag3))
161                                 inset->setInclude();
162                         else if (fl_get_button(form->flag4)) {
163                                 inset->setVerb();
164                                 inset->setVisibleSpace(fl_get_button(form->flag41));
165                         }
166                         
167                         fl_hide_form(form->include);
168                         UpdateInset(inset);
169                         current_view->getOwner()->getLyXFunc()->Dispatch(LFUN_CHILDOPEN, inset->getContents().c_str());
170                 }
171                 break;
172                 
173         case 10:
174                 fl_activate_object(form->flag41);
175                 fl_set_object_lcol(form->flag41, FL_BLACK); 
176                 break;
177         case 11:
178                 fl_deactivate_object(form->flag41);
179                 fl_set_object_lcol(form->flag41, FL_INACTIVE);
180                 fl_set_button(form->flag41, 0);
181                 break;
182         }
183 }
184
185
186 InsetInclude::InsetInclude(string const & fname, Buffer *bf)
187         : InsetCommand("include") 
188 {
189         master = bf;
190         setContents(fname);
191         flag = InsetInclude::INCLUDE;
192         noload = false;
193 }
194
195
196 InsetInclude::~InsetInclude()
197 {
198         if (form && form->vdata == this) {
199                 // this inset is in the popup so hide the popup 
200                 // and remove the reference to this inset. ARRae
201                 if (form->include) {
202                         if (form->include->visible) {
203                                 fl_hide_form(form->include);
204                         }
205                         fl_free_form(form->include);
206                 }
207                 fl_free(form);
208                 form = 0;
209         }
210 }
211
212 Inset * InsetInclude::Clone() 
213
214         InsetInclude * ii = new InsetInclude (contents, master); 
215         ii->setNoLoad(isNoLoad());
216         // By default, the newly created inset is of `include' type,
217         // so we do not test this case.
218         if (isInput())
219                 ii->setInput();
220         else if (isVerb()) {
221                 ii->setVerb();
222                 ii->setVisibleSpace(isVerbVisibleSpace());
223         }
224         return (Inset*)ii;
225 }
226
227 void InsetInclude::Edit(int, int)
228 {
229         if(current_view->currentBuffer()->isReadonly())
230                 WarnReadonly();
231
232         if (!form) {
233                 form = create_form_include();
234                 fl_set_form_atclose(form->include, IgnoreCloseBoxCB, 0);
235         }
236         form->vdata = this;
237     
238         fl_set_input(form->input, contents.c_str());
239         fl_set_button(form->flag1, int(isNoLoad()));
240         fl_set_button(form->flag2, int(isInput()));
241         fl_set_button(form->flag3, int(isInclude()));
242         fl_set_button(form->flag4, int(isVerb()));
243         if (isVerb()) 
244             fl_set_button(form->flag41, int(isVerbVisibleSpace()));
245         else {
246             fl_set_button(form->flag41, 0);
247             fl_deactivate_object(form->flag41);
248             fl_set_object_lcol(form->flag41, FL_INACTIVE);
249         }
250         
251         if (form->include->visible) {
252                 fl_raise_form(form->include);
253         } else {
254                 fl_show_form(form->include,FL_PLACE_MOUSE, FL_FULLBORDER,
255                              _("Include"));
256         }
257 }
258
259
260 void InsetInclude::Write(FILE *file)
261 {
262         fprintf(file, "Include %s\n", getCommand().c_str());
263 }
264
265
266 void InsetInclude::Read(LyXLex &lex)
267 {
268         InsetCommand::Read(lex);
269     
270         if (getCmdName()=="include")
271                 setInclude();
272         else if (getCmdName() == "input")
273                 setInput();
274         else if (contains(getCmdName(), "verbatim")) {
275                 setVerb();
276                 if (getCmdName() == "verbatiminput*")
277                         setVisibleSpace(true);
278         }
279 }
280
281
282 string InsetInclude::getScreenLabel() const
283 {
284         string temp;
285         if (isInput())
286                 temp += _("Input");
287         else if (isVerb()) {
288                 temp += _("Verbatim Input");
289                 if (isVerbVisibleSpace()) temp += '*';
290         } else temp += _("Include");
291         temp += ": ";
292         
293         if (contents.empty()) {
294                 temp+="???";
295         } else {
296                 temp+=contents;
297         }
298         return temp;
299 }
300
301
302 bool InsetInclude::loadIfNeeded() const
303 {
304         if (isNoLoad() || isVerb()) return false;
305         if (!IsLyXFilename(getFileName())) return false;
306         
307         if (bufferlist.exists(getFileName())) return true;
308         
309         // the readonly flag can/will be wrong, not anymore I think.
310         FileInfo finfo(getFileName());
311         bool ro = !finfo.writable();
312         return ( bufferlist.readFile(getFileName(), ro) != 0 );
313 }
314
315
316 int InsetInclude::Latex(FILE *file, signed char /*fragile*/)
317 {
318         string include_file;
319         signed char dummy = 0;
320         Latex(include_file, dummy);
321         fprintf(file, "%s", include_file.c_str());
322         return 0;
323 }
324
325
326 int InsetInclude::Latex(string &file, signed char /*fragile*/)
327 {
328         string writefile, incfile;
329
330         // Do nothing if no file name has been specified
331         if (contents.empty())
332                 return 0;
333     
334         // Use += to force a copy of contents (JMarc)
335         incfile += contents;
336
337         if (loadIfNeeded()) {
338                 Buffer *tmp = bufferlist.getBuffer(getFileName());
339
340                 if (tmp->params.textclass != master->params.textclass) {
341                         lyxerr << "ERROR: Cannot handle include file `"
342                                << MakeDisplayPath(getFileName())
343                                << "' which has textclass `"
344                                << lyxstyle.NameOfClass(tmp->params.textclass)
345                                << "' instead of `"
346                                << lyxstyle.NameOfClass(master->params.textclass)
347                                << "'." << endl;
348                         return 0;
349                 }
350                 
351                 // write it to a file (so far the complete file)
352                 writefile = ChangeExtension(getFileName(), ".tex", false);
353                 if (!master->tmppath.empty()
354                     && !master->niceFile) {
355                         incfile = subst(incfile, '/','@');
356                         #ifdef __EMX__
357                         incfile = subst(incfile, ':', '$');
358                         #endif
359                         writefile = AddName(master->tmppath, incfile);
360                 } else
361                         writefile = getFileName();
362                 writefile = ChangeExtension(writefile,".tex",false);
363                 lyxerr[Debug::LATEX] << "incfile:" << incfile << endl;
364                 lyxerr[Debug::LATEX] << "writefile:" << writefile << endl;
365                 
366                 tmp->markDepClean(master->tmppath);
367                 
368                 tmp->makeLaTeXFile(writefile,
369                                    OnlyPath(getMasterFilename()), 
370                                    master->niceFile, true);
371         } 
372
373         if (isVerb()) {
374                 file += '\\';
375                 file += command + '{';
376                 file += incfile + '}';
377         } 
378         else if (isInput()) {
379                 // \input wants file with extension (default is .tex)
380                 if (!IsLyXFilename(getFileName())) {
381                         file += '\\';
382                         file += command + '{';
383                         file += incfile + '}';
384                 } else {
385                         file += '\\';
386                         file += command + '{';
387                         file += ChangeExtension(incfile, ".tex", false)
388                                 + '}';
389                 }
390         } else {
391                 // \include don't want extension and demands that the
392                 // file really have .tex
393                 file += '\\';
394                 file += command + '{';
395                 file += ChangeExtension(incfile, string(), false)
396                         + '}';
397         }
398
399         return 0;
400 }
401
402
403 void InsetInclude::Validate(LaTeXFeatures& features) const
404 {
405         if (isVerb())
406                 features.verbatim = true;
407
408         // Here we must do the fun stuff...
409         // Load the file in the include if it needs
410         // to be loaded:
411         if (loadIfNeeded()) {
412                 // a file got loaded
413                 Buffer *tmp = bufferlist.getBuffer(getFileName());
414                 tmp->validate(features);
415         }
416 }
417
418
419 string InsetInclude::getLabel(int) const
420 {
421     string label;
422     string parentname;
423         
424         
425     if (loadIfNeeded()) {
426         Buffer *tmp = bufferlist.getBuffer(getFileName());
427         tmp->setParentName(""); 
428         label =  tmp->getReferenceList('\n');
429         tmp->setParentName(getMasterFilename());
430     }
431
432     return label;
433 }
434
435
436 int InsetInclude::GetNumberOfLabels() const {
437     string label;
438     int nl;
439
440     if (loadIfNeeded()) {
441         Buffer *tmp = bufferlist.getBuffer(getFileName());
442         tmp->setParentName("");    
443         label = tmp->getReferenceList('\n');
444         tmp->setParentName(getMasterFilename());
445     }
446         nl = (label.empty())? 0: 1;
447         
448     return nl;
449 }
450
451
452 string InsetInclude::getKeys() const
453 {
454         string list;
455         
456         if (loadIfNeeded()) {
457                 Buffer *tmp = bufferlist.getBuffer(getFileName());
458                 tmp->setParentName(""); 
459                 list =  tmp->getBibkeyList(',');
460                 tmp->setParentName(getMasterFilename());
461         }
462         
463         return list;
464 }