]> git.lyx.org Git - lyx.git/blob - src/frontends/xforms/FormCitation.C
Fix crash on exit (angus)
[lyx.git] / src / frontends / xforms / FormCitation.C
1 // -*- C++ -*-
2 /* This file is part of
3  * ====================================================== 
4  *
5  *           LyX, The Document Processor
6  *
7  *           Copyright 2000 The LyX Team.
8  *
9  * ======================================================
10  */
11
12 #include <config.h>
13
14 #include FORMS_H_LOCATION
15
16 #include <algorithm>
17
18 #ifdef __GNUG__
19 #pragma implementation
20 #endif
21
22
23 #include "gettext.h"
24 #include "Dialogs.h"
25 #include "FormCitation.h"
26 #include "LyXView.h"
27 #include "buffer.h"
28 #include "form_citation.h"
29 #include "lyxfunc.h"
30 #include "support/filetools.h"
31
32 using std::vector;
33 using std::pair;
34 using std::max;
35 using std::min;
36 using std::find;
37
38 static vector<string> citekeys;
39 static vector<string> bibkeys;
40 static vector<string> bibkeysInfo;
41
42 FormCitation::FormCitation(LyXView * lv, Dialogs * d)
43         : FormCommand(lv, d, _("Citation")), dialog_(0)
44 {
45         // let the dialog be shown
46         // These are permanent connections so we won't bother
47         // storing a copy because we won't be disconnecting.
48         d->showCitation.connect(slot(this, &FormCitation::showInset));
49         d->createCitation.connect(slot(this, &FormCitation::createInset));
50 }
51
52
53 FormCitation::~FormCitation()
54 {
55         free();
56         delete dialog_;
57 }
58
59
60 void FormCitation::clearStore()
61 {
62         citekeys.clear();
63         bibkeys.clear();
64         bibkeysInfo.clear();
65 }
66
67
68 void FormCitation::build()
69 {
70         dialog_ = build_citation();
71 }
72
73
74 FL_FORM * const FormCitation::form() const
75 {
76         if( dialog_ && dialog_->form_citation )
77                 return dialog_->form_citation;
78         else
79                 return 0;
80 }
81
82
83 void FormCitation::update()
84 {
85         bibkeys.clear();
86         bibkeysInfo.clear();
87
88         vector<pair<string,string> > blist =
89                 lv_->buffer()->getBibkeyList();
90
91         for( unsigned int i = 0; i < blist.size(); ++i ) {
92                 bibkeys.push_back(blist[i].first);
93                 bibkeysInfo.push_back(blist[i].second);
94         }
95         blist.clear();
96
97         citekeys.clear();
98         string tmp, keys( params.getContents() );
99         keys = frontStrip( split(keys, tmp, ',') );
100         while( !tmp.empty() ) {
101                 citekeys.push_back( tmp );
102                 keys = frontStrip( split(keys, tmp, ',') );
103         }
104
105         fl_freeze_form( dialog_->form_citation );
106
107         updateBrowser( dialog_->bibBrsr,  bibkeys );
108         updateBrowser( dialog_->citeBrsr, citekeys );
109         fl_clear_browser( dialog_->infoBrsr );
110
111         // No keys have been selected yet, so...
112         setBibButtons( OFF );
113         setCiteButtons( OFF );
114
115         int noKeys = max( bibkeys.size(), citekeys.size() );
116
117         // Place bounds, so that 4 <= noKeys <= 15
118         noKeys = max( 4, min(15, noKeys) );
119
120         // Re-size the form to accommodate the new browser size
121         int size = 20 * noKeys;
122         bool bibPresent = ( bibkeys.size() > 0 );
123         setSize( size, bibPresent );
124
125         fl_set_input( dialog_->textAftr, params.getOptions().c_str() );
126
127         fl_unfreeze_form( dialog_->form_citation );
128 }
129
130
131 void FormCitation::updateBrowser( FL_OBJECT * browser,
132                                   vector<string> const & keys ) const
133 {
134         fl_clear_browser( browser );
135
136         for( unsigned int i = 0; i < keys.size(); ++i )
137                 fl_add_browser_line( browser, keys[i].c_str() );
138 }
139
140
141 void FormCitation::setBibButtons( State status ) const
142 {
143         switch (status) {
144         case ON:
145                 fl_activate_object( dialog_->addBtn );
146                 fl_set_object_lcol( dialog_->addBtn, FL_BLACK );
147                 break;
148
149         case OFF:
150                 fl_deactivate_object( dialog_->addBtn );
151                 fl_set_object_lcol( dialog_->addBtn, FL_INACTIVE );
152                 break;
153
154         default:
155                 break;
156         }
157 }
158
159
160 void FormCitation::setCiteButtons( State status ) const
161 {
162         switch( status ) {
163         case ON:
164         {
165                 fl_activate_object( dialog_->delBtn );
166                 fl_set_object_lcol( dialog_->delBtn, FL_BLACK );
167
168                 int sel = fl_get_browser( dialog_->citeBrsr );
169
170                 if( sel != 1 ) {
171                         fl_activate_object( dialog_->upBtn );
172                         fl_set_object_lcol( dialog_->upBtn, FL_BLACK );
173                 } else {
174                         fl_deactivate_object( dialog_->upBtn );
175                         fl_set_object_lcol( dialog_->upBtn, FL_INACTIVE );
176                 }
177
178                 if( sel != fl_get_browser_maxline(dialog_->citeBrsr)) {
179                         fl_activate_object( dialog_->downBtn );
180                         fl_set_object_lcol( dialog_->downBtn, FL_BLACK );
181                 } else {
182                         fl_deactivate_object( dialog_->downBtn );
183                         fl_set_object_lcol( dialog_->downBtn, FL_INACTIVE );
184                 }
185
186                 break;
187         }
188         case OFF:
189         {
190                 fl_deactivate_object( dialog_->delBtn );
191                 fl_set_object_lcol( dialog_->delBtn, FL_INACTIVE );
192
193                 fl_deactivate_object( dialog_->upBtn );
194                 fl_set_object_lcol( dialog_->upBtn, FL_INACTIVE );
195
196                 fl_deactivate_object( dialog_->downBtn );
197                 fl_set_object_lcol( dialog_->downBtn, FL_INACTIVE );
198         }
199         default:
200                 break;
201         }
202 }
203
204
205 void FormCitation::setSize( int hbrsr, bool bibPresent ) const
206 {
207         int const hinfo  = dialog_->infoBrsr->h;
208         int const hother = 140;
209         hbrsr = max( hbrsr, 175 );
210         int wform = dialog_->form_citation->w;
211         int hform = hbrsr + hother;
212
213         if( bibPresent ) hform += hinfo + 30;
214         fl_set_form_size( dialog_->form_citation, wform, hform );
215
216         // No resizing is alowed in the y-direction
217         fl_set_form_minsize( dialog_->form_citation, wform,   hform );
218         fl_set_form_maxsize( dialog_->form_citation, 3*wform, hform );
219
220         int y = 0;
221         fl_set_object_geometry( dialog_->box, 0, y, wform, hform );
222         y += 30;
223         fl_set_object_geometry( dialog_->citeBrsr, 10, y, 180, hbrsr );
224         fl_set_object_geometry( dialog_->bibBrsr, 240, y, 180, hbrsr );
225
226         fl_set_object_position( dialog_->addBtn,  200, y );
227         y += 5 + dialog_->addBtn->h;
228         fl_set_object_position( dialog_->delBtn,  200, y );
229         y += 5 + dialog_->delBtn->h;
230         fl_set_object_position( dialog_->upBtn,   200, y );
231         y += 5 + dialog_->upBtn->h;
232         fl_set_object_position( dialog_->downBtn, 200, y );
233
234         y = dialog_->bibBrsr->y + dialog_->bibBrsr->h;
235
236         // awaiting natbib support
237         fl_hide_object( dialog_->style );
238
239         if( bibPresent ) {
240                 y += 30;
241                 fl_set_object_position( dialog_->infoBrsr, 10, y );
242                 fl_show_object( dialog_->infoBrsr );
243                 y += hinfo;
244         }
245         else
246                 fl_hide_object( dialog_->infoBrsr );
247
248         y += 20;
249         // awaiting natbib support
250         fl_hide_object( dialog_->textBefore );
251
252         fl_set_object_position( dialog_->textAftr, 100, y );
253         fl_set_object_position( dialog_->ok,       230, y+50 );
254         fl_set_object_position( dialog_->cancel,   330, y+50 );
255 }
256
257
258 void FormCitation::input( long data )
259 {
260         State cb = static_cast<FormCitation::State>( data );
261
262         switch( cb ) {
263         case BIBBRSR:
264         {
265                 fl_deselect_browser( dialog_->citeBrsr );
266                 
267                 unsigned int sel = fl_get_browser( dialog_->bibBrsr );
268                 if( sel < 1 || sel > bibkeys.size() ) break;
269
270                 // Put into infoBrsr the additional info associated with
271                 // the selected bibBrsr key
272                 fl_clear_browser( dialog_->infoBrsr );
273                 fl_add_browser_line( dialog_->infoBrsr,
274                                      bibkeysInfo[sel-1].c_str() );
275
276                 // Highlight the selected bibBrsr key in citeBrsr if present
277                 vector<string>::iterator it =
278                         find( citekeys.begin(), citekeys.end(), bibkeys[sel-1] );
279
280                 if( it != citekeys.end() ) {
281                         int n = it - citekeys.begin();
282                         fl_select_browser_line( dialog_->citeBrsr, n+1 );
283                         fl_set_browser_topline( dialog_->citeBrsr, n+1 );
284                 }
285
286                 if( !lv_->buffer()->isReadonly() ) {
287                         if( it != citekeys.end() ) {
288                                 setBibButtons( OFF );
289                                 setCiteButtons( ON );
290                         } else {
291                                 setBibButtons( ON );
292                                 setCiteButtons( OFF );
293                         }
294                 }
295         }
296         break;
297         case CITEBRSR:
298         {
299                 unsigned int sel = fl_get_browser( dialog_->citeBrsr );
300                 if( sel < 1 || sel > citekeys.size() ) break;
301
302                 if( !lv_->buffer()->isReadonly() ) {
303                         setBibButtons( OFF );
304                         setCiteButtons( ON );
305                 }
306
307                 // Highlight the selected citeBrsr key in bibBrsr
308                 vector<string>::iterator it =
309                         find( bibkeys.begin(), bibkeys.end(), citekeys[sel-1] );
310
311                 if (it != bibkeys.end()) {
312                         int n = it - bibkeys.begin();
313                         fl_select_browser_line( dialog_->bibBrsr, n+1 );
314                         fl_set_browser_topline( dialog_->bibBrsr, n+1 );
315
316                         // Put into infoBrsr the additional info associated with
317                         // the selected citeBrsr key
318                         fl_clear_browser( dialog_->infoBrsr );
319                         fl_add_browser_line( dialog_->infoBrsr,
320                                              bibkeysInfo[n].c_str() );
321                 }
322         }
323         break;
324         case ADD:
325         {
326                 if( lv_->buffer()->isReadonly() ) break;
327
328                 unsigned int sel = fl_get_browser( dialog_->bibBrsr );
329                 if( sel < 1 || sel > bibkeys.size() ) break;
330
331                 // Add the selected bibBrsr key to citeBrsr
332                 fl_addto_browser( dialog_->citeBrsr,
333                                   bibkeys[sel-1].c_str() );
334                 citekeys.push_back( bibkeys[sel-1] );
335
336                 int n = citekeys.size();
337                 fl_select_browser_line( dialog_->citeBrsr, n );
338
339                 setBibButtons( OFF );
340                 setCiteButtons( ON );
341         }
342         break;
343         case DELETE:
344         {
345                 if( lv_->buffer()->isReadonly() ) break;
346
347                 unsigned int sel = fl_get_browser( dialog_->citeBrsr );
348                 if( sel < 1 || sel > citekeys.size() ) break;
349
350                 // Remove the selected key from citeBrsr
351                 fl_delete_browser_line( dialog_->citeBrsr, sel ) ;
352                 citekeys.erase( citekeys.begin() + sel-1 );
353
354                 setBibButtons( ON );
355                 setCiteButtons( OFF );
356         }
357         break;
358         case UP:
359         {
360                 if( lv_->buffer()->isReadonly() ) break;
361
362                 unsigned int sel = fl_get_browser( dialog_->citeBrsr );
363                 if( sel < 2 || sel > citekeys.size() ) break;
364
365                 // Move the selected key up one line
366                 vector<string>::iterator it = citekeys.begin() + sel-1;
367                 string tmp = *it;
368
369                 fl_delete_browser_line( dialog_->citeBrsr, sel );
370                 citekeys.erase( it );
371
372                 fl_insert_browser_line( dialog_->citeBrsr, sel-1, tmp.c_str() );
373                 fl_select_browser_line( dialog_->citeBrsr, sel-1 );
374                 citekeys.insert( it-1, tmp );
375                 setCiteButtons( ON );
376         }
377         break;
378         case DOWN:
379         {
380                 if( lv_->buffer()->isReadonly() ) break;
381
382                 unsigned int sel = fl_get_browser( dialog_->citeBrsr );
383                 if( sel < 1 || sel > citekeys.size()-1 ) break;
384
385                 // Move the selected key down one line
386                 vector<string>::iterator it = citekeys.begin() + sel-1;
387                 string tmp = *it;
388
389                 fl_delete_browser_line( dialog_->citeBrsr, sel );
390                 citekeys.erase( it );
391
392                 fl_insert_browser_line( dialog_->citeBrsr, sel+1, tmp.c_str() );
393                 fl_select_browser_line( dialog_->citeBrsr, sel+1 );
394                 citekeys.insert( it+1, tmp );
395                 setCiteButtons( ON );
396         }
397         break;
398         default:
399                 break;
400         }
401 }
402
403
404 void FormCitation::apply()
405 {
406         if( lv_->buffer()->isReadonly() ) return;
407
408         string contents;
409         for( unsigned int i = 0; i < citekeys.size(); ++i ) {
410                 if (i > 0) contents += ", ";
411                 contents += citekeys[i];
412         }
413
414         params.setContents( contents );
415         params.setOptions( fl_get_input(dialog_->textAftr) );
416
417         if( inset_ != 0 )
418         {
419                 // Only update if contents have changed
420                 if( params.getCmdName()  != inset_->getCmdName()  ||
421                     params.getContents() != inset_->getContents() ||
422                     params.getOptions()  != inset_->getOptions() ) {
423                         inset_->setParams( params );
424                         lv_->view()->updateInset( inset_, true );
425                 }
426         } else {
427                 lv_->getLyXFunc()->Dispatch( LFUN_CITATION_INSERT,
428                                              params.getAsString().c_str() );
429         }
430 }