]> git.lyx.org Git - lyx.git/blob - src/frontends/gnome/FormCitation.C
patch from Marko, remove table.Ch from repository
[lyx.git] / src / frontends / gnome / 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 <algorithm>
15
16 #ifdef __GNUG__
17 #pragma implementation
18 #endif
19
20
21 #include "gettext.h"
22 #include "Dialogs.h"
23 #include "FormCitation.h"
24 #include "LyXView.h"
25 #include "buffer.h"
26 #include "lyxfunc.h"
27 #include "support/filetools.h"
28 #include "support/LRegex.h"
29
30 #include <gtk--/scrolledwindow.h>
31 #include <gnome--/pixmap.h>
32 #include <gtk--/label.h>
33 #include <gtk--/box.h>
34 #include <gtk--/buttonbox.h>
35 #include <gnome--/entry.h>
36 #include <gnome--/stock.h>
37 #include <gtk--/separator.h>
38 #include <libgnome/gnome-config.h>
39
40 // temporary solution for LyXView
41 #include "mainapp.h"
42 extern GLyxAppWin * mainAppWin;
43
44 using std::vector;
45 using std::pair;
46 using std::max;
47 using std::min;
48 using std::find;
49
50 #ifdef SIGC_CXX_NAMESPACES
51 using SigC::slot;
52 using SigC::bind;
53 #endif
54
55
56 // configuration keys
57 static string const  LOCAL_CONFIGURE_PREFIX("FormCitation");
58
59 static string const  CONF_DIALOG_WIDTH("width");
60 static string const  CONF_DIALOG_WIDTH_DEFAULT("=550");
61
62 static string const  CONF_DIALOG_HEIGTH("heigth");
63 static string const  CONF_DIALOG_HEIGTH_DEFAULT("=550");
64
65 static string const  CONF_PANE_INFO("paneinfo");
66 static string const  CONF_PANE_INFO_DEFAULT("=300");
67
68 static string const  CONF_PANE_KEY("panekey");
69 static string const  CONF_PANE_KEY_DEFAULT("=225");
70
71 static string const  CONF_COLUMN("column");
72 static string const  CONF_COLUMN_DEFAULT("=50");
73
74 static string const  CONF_REGEXP("regexp");
75 static string const  CONF_REGEXP_DEFAULT("=0");
76
77 static string const CONF_SEARCH("FormCitation_search");
78 static string const CONF_TEXTAFTER("FormCitation_textafter");
79
80 FormCitation::FormCitation(LyXView * lv, Dialogs * d)
81         : lv_(lv), d_(d), inset_(0), u_(0), h_(0), ih_(0), dialog_(NULL)
82 {
83   // let the dialog be shown
84   // These are permanent connections so we won't bother
85   // storing a copy because we won't be disconnecting.
86   d->showCitation.connect(slot(this, &FormCitation::showInset));
87   d->createCitation.connect(slot(this, &FormCitation::createInset));
88 }
89
90
91 FormCitation::~FormCitation()
92 {
93   hide();
94 }
95
96 void FormCitation::showInset( InsetCommand * const inset )
97 {
98   if( dialog_!=NULL || inset == 0 ) return;
99   
100   inset_ = inset;
101   ih_ = inset_->hide.connect(slot(this, &FormCitation::hide));
102
103   u_ = d_->updateBufferDependent.connect(slot(this, &FormCitation::update));
104   h_ = d_->hideBufferDependent.connect(slot(this, &FormCitation::hide));
105   
106   params = inset->params();
107   //showStageEdit();
108 }
109
110
111 void FormCitation::createInset( string const & arg )
112 {
113   if( dialog_!=NULL ) return;
114   
115   u_ = d_->updateBufferDependent.connect(slot(this, &FormCitation::update));
116   h_ = d_->hideBufferDependent.connect(slot(this, &FormCitation::hide));
117   
118   params.setFromString( arg );
119   showStageSearch();
120 }
121
122
123 static
124 void parseBibTeX(string data,
125                  string const & findkey,
126                  string & keyvalue)
127 {
128   unsigned int i;
129
130   keyvalue = "";
131   
132   for (i=0; i<data.length(); ++i)
133     if (data[i]=='\n' || data[i]=='\t')
134       data[i] = ' ';
135   
136   data = frontStrip(data);
137   while (!data.empty()
138          && data[0]!='='
139          && (data.find(' ')!=string::npos ||
140              data.find('=')!=string::npos) )
141     {
142       unsigned int keypos = min(data.find(' '), data.find('='));
143       string key = lowercase( data.substr(0, keypos) );
144       string value, tmp;
145       char enclosing;
146       
147       data = data.substr(keypos, data.length()-1);
148       data = frontStrip(strip(data));
149       if (data.length() > 1 && data[0]=='=')
150         {
151           data = frontStrip(data.substr(1, data.length()-1));
152           if (!data.empty())
153             {
154               keypos = 1;
155               if (data[0]=='{') enclosing = '}';
156               else if (data[0]=='"') enclosing = '"';
157               else { keypos=0; enclosing=' '; }
158
159               if (keypos &&
160                   data.find(enclosing)!=string::npos &&
161                   data.length()>1)
162                 {
163                   tmp = data.substr(keypos, data.length()-1);
164                   while (tmp.find('{')!=string::npos &&
165                          tmp.find('}')!=string::npos &&
166                          tmp.find('{') < tmp.find('}') &&
167                          tmp.find('{') < tmp.find(enclosing))
168                     {
169                       keypos += tmp.find('{')+1;
170                       tmp = data.substr(keypos, data.length()-1);
171                       keypos += tmp.find('}')+1;
172                       tmp = data.substr(keypos, data.length()-1);
173                     }
174
175                   if (tmp.find(enclosing)==string::npos) return;
176                   else
177                     {
178                       keypos += tmp.find(enclosing);
179                       tmp = data.substr(keypos, data.length()-1);
180                     }
181
182                   value = data.substr(1, keypos-1);
183
184                   if (keypos+1<data.length()-1) data = frontStrip(data.substr(keypos+1, data.length()-1));
185                   else data = "";
186                 }
187               else if (!keypos &&
188                        (data.find(' ') ||
189                         data.find(','))
190                        ) // numerical value ?
191                 {
192                   keypos = data.length()-1;
193                   if (data.find(' ')!=string::npos) keypos = data.find(' ');
194                   if (data.find(',')!=string::npos &&
195                       keypos > data.find(','))
196                     keypos = data.find(',');
197
198                   value = data.substr(0, keypos);
199                   
200                   if (keypos+1<data.length()-1) data = frontStrip(data.substr(keypos+1, data.length()-1));
201                   else data = "";
202                 }
203               else return;
204
205               if (findkey == key) { keyvalue = value; return; } 
206
207               data = frontStrip(frontStrip(data,','));
208             }
209         }
210       else return;
211     }
212 }
213
214 void FormCitation::showStageSearch()
215 {
216   if (!dialog_)
217     {
218       using namespace Gtk::Box_Helpers;
219
220       Gtk::Box * mbox = manage( new Gtk::HBox() );
221       Gtk::ButtonBox * bbox = manage( new Gtk::HButtonBox() );
222       Gtk::Separator * sep = manage( new Gtk::VSeparator() );
223       
224       search_text_ = manage( new Gnome::Entry() );
225       
226       button_regexp_ = manage( new Gtk::CheckButton(N_("Use Regular Expression")) );
227
228       b_ok = manage( new Gtk::Button(N_("Search")) );
229       b_cancel = Gtk::wrap( GTK_BUTTON( gnome_stock_button(GNOME_STOCK_BUTTON_CANCEL) ) );
230       
231       // set up spacing
232       mbox->set_spacing(4);
233       bbox->set_spacing(4);
234
235       search_text_->set_history_id(CONF_SEARCH);
236       search_text_->set_max_saved(10);
237       search_text_->load_history();
238       search_text_->set_use_arrows_always(true);
239       
240       // packing
241       bbox->children().push_back(Element(*b_ok, false, false));
242       bbox->children().push_back(Element(*b_cancel, false, false));
243
244       mbox->children().push_back(Element(*search_text_, true, true));
245       mbox->children().push_back(Element(*button_regexp_, false, false));
246       mbox->children().push_back(Element(*sep, false, false));
247       mbox->children().push_back(Element(*bbox, false, false));
248
249       // packing dialog to main window
250       dialog_ = mbox;
251       mainAppWin->add_action(*dialog_, N_(" Insert Citation: Enter keyword(s) or regular expression "));
252
253       // setting focus
254       GTK_WIDGET_SET_FLAGS (GTK_WIDGET(search_text_->get_entry()->gtkobj()), GTK_CAN_DEFAULT);
255       gtk_widget_grab_focus (GTK_WIDGET(search_text_->get_entry()->gtkobj()));
256       gtk_widget_grab_default (GTK_WIDGET(search_text_->get_entry()->gtkobj()));
257
258       // restoring regexp setting
259       string path = PACKAGE "/" + LOCAL_CONFIGURE_PREFIX;
260       string w;
261       w = path + "/" + CONF_REGEXP + CONF_REGEXP_DEFAULT;
262       button_regexp_->set_active( (gnome_config_get_int(w.c_str()) > 0) );
263
264       // connecting signals
265       b_ok->clicked.connect(slot(this, &FormCitation::moveFromSearchToSelect));
266       search_text_->get_entry()->activate.connect(slot(this, &FormCitation::moveFromSearchToSelect));
267
268       b_cancel->clicked.connect(slot(mainAppWin, &GLyxAppWin::remove_action));
269
270       dialog_->destroy.connect(slot(this, &FormCitation::free));
271     }
272 }
273
274 void FormCitation::moveFromSearchToSelect()
275 {
276   search_string_ = search_text_->get_entry()->get_text();
277   use_regexp_ = button_regexp_->get_active();
278   
279   // saving configuration
280   search_text_->save_history();
281
282   string path = PACKAGE "/" + LOCAL_CONFIGURE_PREFIX;
283   string w;
284   w = path + "/" + CONF_REGEXP;
285   gnome_config_set_int(w.c_str(), button_regexp_->get_active());
286   gnome_config_sync();
287   
288   // moves to stage "select"
289   dialog_ = NULL;
290   mainAppWin->remove_action();
291   showStageSelect();
292 }
293
294 void FormCitation::showStageSelect()
295 {
296   if (!dialog_)
297     {
298       using namespace Gtk::Box_Helpers;
299
300       Gtk::Box * mbox = manage( new Gtk::VBox() );
301       Gtk::Box * tbox = manage( new Gtk::HBox() );
302       Gtk::ButtonBox * bbox = manage( new Gtk::HButtonBox() );
303       Gtk::Separator * sep = manage( new Gtk::HSeparator() );
304       Gtk::ScrolledWindow * sw = manage( new Gtk::ScrolledWindow() );
305
306       info_ = manage( new Gnome::Less() );
307       paned_info_ = manage( new Gtk::HPaned() );
308       text_after_ = manage( new Gnome::Entry() );
309       
310       b_ok = Gtk::wrap( GTK_BUTTON( gnome_stock_button(GNOME_STOCK_BUTTON_OK) ) );
311       b_cancel = Gtk::wrap( GTK_BUTTON( gnome_stock_button(GNOME_STOCK_BUTTON_CANCEL) ) );
312
313       // setup text_after_
314       text_after_->set_history_id(CONF_TEXTAFTER);
315       text_after_->set_max_saved(10);
316       text_after_->load_history();
317       text_after_->set_use_arrows_always(true);
318
319       sw->set_policy(GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
320
321       // constructing CList
322       vector<string> colnames;
323       colnames.push_back("INVISIBLE");
324       colnames.push_back(N_("Key"));
325       colnames.push_back(N_("Author(s)"));
326       colnames.push_back(N_("Title"));
327       colnames.push_back(N_("Year"));
328       colnames.push_back(N_("Journal"));
329       clist_bib_ = manage( new Gtk::CList(colnames) );
330       clist_bib_->column(0).set_visiblity(false);
331
332       bbox->set_layout(GTK_BUTTONBOX_END);
333       
334       // set up spacing
335       mbox->set_spacing(4);
336       bbox->set_spacing(4);
337       tbox->set_spacing(4);
338
339       // packing widgets
340       sw->add(*clist_bib_);
341       paned_info_->add1(*sw);
342       paned_info_->add2(*info_);
343
344       bbox->children().push_back(Element(*b_ok, false, false));
345       bbox->children().push_back(Element(*b_cancel, false, false));
346
347       tbox->children().push_back(Element(*manage(new Gtk::Label(N_("Text after"))), false, false));
348       tbox->children().push_back(Element(*text_after_, true, true));
349       tbox->children().push_back(Element(*manage(new Gtk::VSeparator()), false, false));
350       tbox->children().push_back(Element(*bbox, false, false));
351
352       mbox->children().push_back(Element(*paned_info_,true,true));
353       mbox->children().push_back(Element(*sep, false, false));
354       mbox->children().push_back(Element(*tbox, false, false));
355       
356       // packing dialog to main window
357       dialog_ = mbox;
358       mainAppWin->add_action(*dialog_, N_(" Insert Citation: Select citation "), true);
359
360       // setting focus
361       GTK_WIDGET_SET_FLAGS (GTK_WIDGET(b_ok->gtkobj()), GTK_CAN_DEFAULT);
362       GTK_WIDGET_SET_FLAGS (GTK_WIDGET(b_cancel->gtkobj()), GTK_CAN_DEFAULT);
363       GTK_WIDGET_SET_FLAGS (GTK_WIDGET(clist_bib_->gtkobj()), GTK_CAN_DEFAULT);
364       gtk_widget_grab_focus (GTK_WIDGET(clist_bib_->gtkobj()));
365       gtk_widget_grab_default (GTK_WIDGET(b_ok->gtkobj()));
366
367       // setting sizes of the widgets
368       string path = PACKAGE "/" + LOCAL_CONFIGURE_PREFIX;
369       string w = path + "/" + CONF_PANE_INFO + CONF_PANE_INFO_DEFAULT;
370
371       paned_info_->set_position( gnome_config_get_int(w.c_str()) );
372
373       int sz = clist_bib_->columns().size();
374       for (int i = 0; i < sz; ++i)
375         {
376           w = path + "/" + CONF_COLUMN + "_" + tostr(i) + CONF_COLUMN_DEFAULT;
377           clist_bib_->column(i).set_width( gnome_config_get_int(w.c_str()) );
378         }
379
380       // connecting signals
381       b_ok->clicked.connect(slot(this, &FormCitation::applySelect));
382       b_cancel->clicked.connect(slot(mainAppWin, &GLyxAppWin::remove_action));
383
384       dialog_->destroy.connect(slot(this, &FormCitation::free));
385
386       clist_bib_->click_column.connect(slot(this, &FormCitation::sortBibList));
387       clist_bib_->select_row.connect(bind(slot(this, &FormCitation::selection_toggled),
388                                           true, false));
389       clist_bib_->unselect_row.connect(bind(slot(this, &FormCitation::selection_toggled),
390                                             false, false));
391       // retrieving data
392       vector<pair<string,string> > blist = lv_->buffer()->getBibkeyList();
393
394       sz = blist.size();
395       for (int i = 0; i < sz; ++i )
396         {
397           bibkeys.push_back(blist[i].first);
398           bibkeysInfo.push_back(blist[i].second);
399         }
400       
401       blist.clear();      
402       
403       // updating list
404       search();
405     }
406 }
407
408 /*void FormCitation::show()
409 {
410   if (!dialog_)
411     {
412       GtkWidget * pd = create_DiaInsertCitation();
413
414       dialog_ = Gtk::wrap(pd);
415       clist_selected_ = Gtk::wrap( GTK_CLIST( lookup_widget(pd, "clist_selected") ) );
416       info_ = Gtk::wrap( GNOME_LESS( lookup_widget(pd, "info") ) );
417       text_after_ = Gtk::wrap( GNOME_ENTRY( lookup_widget(pd, "text_after") ) );
418       search_text_ = Gtk::wrap( GNOME_ENTRY( lookup_widget(pd, "search_text") ) );
419         
420       button_select_ = Gtk::wrap( GTK_BUTTON( lookup_widget(pd, "button_select") ) );
421       button_unselect_ = Gtk::wrap( GTK_BUTTON( lookup_widget(pd, "button_unselect") ) );
422       button_up_ = Gtk::wrap( GTK_BUTTON( lookup_widget(pd, "button_up") ) );
423       button_down_ = Gtk::wrap( GTK_BUTTON( lookup_widget(pd, "button_down") ) );
424       button_search_ = Gtk::wrap( GTK_BUTTON( lookup_widget(pd, "button_search") ) );
425
426       button_regexp_ = Gtk::wrap( GTK_CHECK_BUTTON( lookup_widget(pd, "button_regexp") ) );
427
428       paned_info_ = Gtk::wrap( GTK_PANED( lookup_widget(pd, "vpaned_info") ) );
429       paned_key_ = Gtk::wrap( GTK_PANED( lookup_widget(pd, "hpaned_key") ) );
430       box_keys_ =  Gtk::wrap( GTK_BOX( lookup_widget(pd, "vbox_keys") ) );
431
432       b_ok = Gtk::wrap( GTK_BUTTON( lookup_widget(pd, "button_ok") ) );
433       b_cancel = Gtk::wrap( GTK_BUTTON( lookup_widget(pd, "button_cancel") ) );
434
435       // constructing and packing CList
436       vector<string> colnames;
437       colnames.push_back("INVISIBLE");
438       colnames.push_back(N_("Key"));
439       colnames.push_back(N_("Author(s)"));
440       colnames.push_back(N_("Title"));
441       colnames.push_back(N_("Year"));
442       colnames.push_back(N_("Journal"));
443       clist_bib_ = manage( new Gtk::CList(colnames) );
444       clist_bib_->column(0).set_visiblity(false);
445       
446       Gtk::ScrolledWindow * sw_ = Gtk::wrap( GTK_SCROLLED_WINDOW( lookup_widget(pd, "scrolledwindow_bib") ) );
447       sw_->add(*clist_bib_);
448
449       // populating buttons with icons
450       Gnome::Pixmap * p;
451       p = Gtk::wrap( GNOME_PIXMAP( gnome_stock_pixmap_widget(NULL, GNOME_STOCK_PIXMAP_BACK) ) ); 
452       button_select_->add(*p);
453       p = Gtk::wrap( GNOME_PIXMAP( gnome_stock_pixmap_widget(NULL, GNOME_STOCK_PIXMAP_TRASH) ) ); 
454       button_unselect_->add(*p);
455       p = Gtk::wrap( GNOME_PIXMAP( gnome_stock_pixmap_widget(NULL, GNOME_STOCK_PIXMAP_UP) ) ); 
456       button_up_->add(*p);
457       p = Gtk::wrap( GNOME_PIXMAP( gnome_stock_pixmap_widget(NULL, GNOME_STOCK_PIXMAP_DOWN) ) ); 
458       button_down_->add(*p);
459       
460
461       // connecting signals
462       clist_bib_->click_column.connect(slot(this, &FormCitation::sortBibList));
463
464       clist_selected_->select_row.connect(bind(slot(this, &FormCitation::selection_toggled),
465                                                true, true));
466       clist_bib_->select_row.connect(bind(slot(this, &FormCitation::selection_toggled),
467                                           true, false));
468       clist_selected_->unselect_row.connect(bind(slot(this, &FormCitation::selection_toggled),
469                                                  false, true));
470       clist_bib_->unselect_row.connect(bind(slot(this, &FormCitation::selection_toggled),
471                                             false, false));
472       
473       button_select_->clicked.connect(slot(this, &FormCitation::newCitation));
474       button_unselect_->clicked.connect(slot(this, &FormCitation::removeCitation));
475       button_up_->clicked.connect(slot(this, &FormCitation::moveCitationUp));
476       button_down_->clicked.connect(slot(this, &FormCitation::moveCitationDown));
477
478       search_text_->get_entry()->activate.connect(slot(this, &FormCitation::search));
479       button_search_->clicked.connect(slot(this, &FormCitation::search));
480       
481       b_ok->clicked.connect(slot(this, &FormCitation::apply));
482       b_ok->clicked.connect(dialog_->destroy.slot());
483       b_cancel->clicked.connect(dialog_->destroy.slot());
484       dialog_->destroy.connect(slot(this, &FormCitation::free));
485
486       u_ = d_->updateBufferDependent.connect(slot(this, &FormCitation::update));
487       h_ = d_->hideBufferDependent.connect(slot(this, &FormCitation::hide));
488
489       // setting sizes of the widgets
490       string path;
491       string w, h;
492       path  += PACKAGE "/" LOCAL_CONFIGURE_PREFIX;
493       w = path + "/" + CONF_DIALOG_WIDTH + CONF_DIALOG_WIDTH_DEFAULT;
494       h = path + "/" + CONF_DIALOG_HEIGTH + CONF_DIALOG_HEIGTH_DEFAULT;
495       dialog_->set_usize(gnome_config_get_int(w.c_str()),
496                          gnome_config_get_int(h.c_str()));
497
498       w = path + "/" + CONF_PANE_INFO + CONF_PANE_INFO_DEFAULT;
499       paned_info_->set_position( gnome_config_get_int(w.c_str()) );
500
501       w = path + "/" + CONF_PANE_KEY + CONF_PANE_KEY_DEFAULT;
502       paned_key_->set_position( gnome_config_get_int(w.c_str()) );
503
504       int i, sz;
505       for (i = 0, sz = clist_bib_->columns().size(); i < sz; ++i)
506         {
507           w = path + "/" + CONF_COLUMN + "_" + tostr(i) + CONF_COLUMN_DEFAULT;
508           clist_bib_->column(i).set_width( gnome_config_get_int(w.c_str()) );
509         }
510
511       // restoring regexp setting
512       w = path + "/" + CONF_REGEXP + CONF_REGEXP_DEFAULT;
513       button_regexp_->set_active( (gnome_config_get_int(w.c_str()) > 0) );
514       
515       // ready to go...
516       if (!dialog_->is_visible()) dialog_->show_all();
517
518       update();  // make sure its up-to-date
519     }
520   else
521     {
522       Gdk_Window dialog_win(dialog_->get_window());
523       dialog_win.raise();
524     }
525 }
526 */
527
528 void FormCitation::addItemToBibList(int i)
529 {
530   vector<string> r;
531   string key, info;
532   string val;
533
534   key = bibkeys[i];
535   info = bibkeysInfo[i];
536
537   // don't change the order of these first two items:
538   // callback functions depend on the data stored in the first column (its hided)
539   // and in the second column (shown to user)
540   r.push_back( tostr(i) ); 
541   r.push_back( key );
542   
543   // this can be changed (configured by user?)
544   parseBibTeX( info, "author", val);  r.push_back(val);
545   parseBibTeX( info, "title", val);  r.push_back(val);
546   parseBibTeX( info, "year", val);  r.push_back(val);
547   parseBibTeX( info, "journal", val);  r.push_back(val);
548   
549   clist_bib_->rows().push_back(r);
550 }
551
552 void FormCitation::update()
553 {
554   return;
555   
556   bibkeys.clear();
557   bibkeysInfo.clear();
558
559   clist_selected_->rows().clear();
560   clist_bib_->rows().clear();
561
562   // populating clist_bib_
563   clist_bib_->freeze();
564
565   vector<pair<string,string> > blist =
566     lv_->buffer()->getBibkeyList();
567
568   int sz = blist.size();
569   for ( int i = 0; i < sz; ++i )
570     {
571       bibkeys.push_back(blist[i].first);
572       bibkeysInfo.push_back(blist[i].second);
573     }
574
575   blist.clear();
576   sz = bibkeys.size();
577   for ( int i = 0; i < sz; ++i )
578     addItemToBibList(i);
579
580   clist_bib_->sort();
581   clist_bib_->thaw();
582   // clist_bib_: done
583
584   // populating clist_selected_
585   vector<string> r;
586   string tmp, keys( params.getContents() );
587   keys = frontStrip( split(keys, tmp, ',') );
588   while( !tmp.empty() )
589     {
590       r.clear();
591       r.push_back(tmp);
592       clist_selected_->rows().push_back(r);
593
594       keys = frontStrip( split(keys, tmp, ',') );
595     }
596   // clist_selected_: done
597
598   text_after_->get_entry()->set_text(params.getOptions());
599   
600   updateButtons();
601 }
602
603 void FormCitation::updateButtons()
604 {
605   bool sens;
606
607   sens = (clist_selected_->selection().size()>0);
608   button_unselect_->set_sensitive(sens);
609   button_up_->set_sensitive(sens &&
610                             clist_selected_->selection()[0].get_row_num()>0);
611   button_down_->set_sensitive(sens &&
612                               clist_selected_->selection()[0].get_row_num() <
613                               clist_selected_->rows().size()-1);
614
615   sens = (clist_bib_->selection().size()>0);
616   button_select_->set_sensitive( (clist_bib_->selection().size()>0) );
617 }
618
619 void FormCitation::selection_toggled(gint            row,
620                                      gint            ,//column,
621                                      GdkEvent        * ,//event,
622                                      bool selected,
623                                      bool citeselected)
624 {
625   if (selected)
626     {
627       bool keyfound = false;
628       string info;
629       if (citeselected)
630         {
631           // lookup the record with the same key in bibkeys and show additional Info
632           int const sz = bibkeys.size();
633           string key = clist_selected_->cell(row,0).get_text();
634           for (int i=0; !keyfound && i<sz; ++i)
635             if (bibkeys[i] == key)
636               {
637                 info = bibkeysInfo[i];
638                 keyfound = true;
639               }   
640         }
641       else
642         {
643           // the first column in clist_bib_ contains the index
644           keyfound = true;
645           info = bibkeysInfo[ strToInt(clist_bib_->cell(row,0).get_text()) ];
646         }
647
648       if (keyfound)
649         info_->show_string(info);
650       else
651         info_->show_string(N_("--- No such key in the database ---"));
652     }
653   else
654     {
655       info_->show_string("");
656     }
657 }
658
659 void FormCitation::removeCitation()
660 {
661   clist_selected_->rows().remove(clist_selected_->selection()[0]);
662   updateButtons();
663 }
664
665 void FormCitation::moveCitationUp()
666 {
667   int i = clist_selected_->selection()[0].get_row_num();
668   clist_selected_->swap_rows( i-1, i );
669   clist_selected_->row(i-1).select();
670   updateButtons();
671 }
672
673 void FormCitation::moveCitationDown()
674 {
675   int i = clist_selected_->selection()[0].get_row_num();
676   clist_selected_->swap_rows( i+1, i );
677   clist_selected_->row(i+1).select();
678   updateButtons();
679 }
680
681 void FormCitation::newCitation()
682 {
683   // citation key is in the first column of clist_bib_ list
684   vector<string> r;
685   r.push_back( clist_bib_->selection()[0][1].get_text() );
686   clist_selected_->rows().push_back(r);
687   clist_selected_->row( clist_selected_->rows().size()-1 ).select();
688   updateButtons();
689 }
690
691 void FormCitation::hide()
692 {
693   if (dialog_!=NULL) mainAppWin->remove_action();
694 }
695
696 void FormCitation::free()
697 {
698   if (dialog_!=NULL)
699     {
700       // storing configuration
701 //        string path;
702 //        string w, h;
703 //        path  = PACKAGE "/" LOCAL_CONFIGURE_PREFIX;
704 //        w = path + "/" + CONF_DIALOG_WIDTH;
705 //        h = path + "/" + CONF_DIALOG_HEIGTH;
706
707 //        gnome_config_set_int(w.c_str(), dialog_->width());
708 //        gnome_config_set_int(h.c_str(), dialog_->height());
709
710 //        w = path + "/" + CONF_PANE_INFO;
711 //        gnome_config_set_int(w.c_str(), paned_key_->height());
712
713 //        w = path + "/" + CONF_PANE_KEY;
714 //        gnome_config_set_int(w.c_str(), box_keys_->width());
715
716 //        int i, sz;
717 //        for (i = 0, sz = clist_bib_->columns().size(); i < sz; ++i)
718 //      {
719 //        w = path + "/" + CONF_COLUMN + "_" + tostr(i);
720 //        gnome_config_set_int(w.c_str(), clist_bib_->get_column_width(i));
721 //      }
722
723 //        w = path + "/" + CONF_REGEXP;
724 //        gnome_config_set_int(w.c_str(), button_regexp_->get_active());
725
726 //        gnome_config_sync();
727
728       // cleaning up
729       dialog_ = NULL;
730       u_.disconnect();
731       h_.disconnect();
732       inset_ = 0;
733       ih_.disconnect();
734     }
735 }
736
737 void FormCitation::applySelect()
738 {
739   if( lv_->buffer()->isReadonly() ) return;
740
741   string contents;
742   int sz;
743
744   contents = frontStrip( strip(params.getContents()) );
745   if (!contents.empty()) contents += ", ";
746   
747   sz = clist_bib_->selection().size();
748   for (int i=0; i < sz; ++i)
749     {
750       if (i > 0) contents += ", ";
751       contents += clist_bib_->selection()[i][1].get_text();
752     }
753   
754   params.setContents( contents );
755   params.setOptions( text_after_->get_entry()->get_text() );
756
757   if( inset_ != 0 )
758     {
759       // Only update if contents have changed
760       if( params != inset_->params() )
761         {
762           inset_->setParams( params );
763           lv_->view()->updateInset( inset_, true );
764         }
765     }
766   else
767     {
768       lv_->getLyXFunc()->Dispatch( LFUN_CITATION_INSERT,
769                                    params.getAsString() );
770     }
771
772   // save config
773   text_after_->save_history();
774
775   string path = PACKAGE "/" + LOCAL_CONFIGURE_PREFIX;
776   string w = path + "/" + CONF_PANE_INFO;
777
778   gnome_config_set_int(w.c_str(), paned_info_->width() - info_->width());
779
780   sz = clist_bib_->columns().size();
781   for (int i = 0; i < sz; ++i)
782     {
783       w = path + "/" + CONF_COLUMN + "_" + tostr(i);
784       gnome_config_set_int(w.c_str(), clist_bib_->get_column_width(i));
785     }
786   
787   gnome_config_sync();
788   
789   // close dialog
790   hide();
791 }
792
793 void FormCitation::apply()
794 {
795   if( lv_->buffer()->isReadonly() ) return;
796
797   string contents;
798   int const sz = clist_selected_->rows().size();
799   for( int i = 0; i < sz; ++i )
800     {
801       if (i > 0) contents += ", ";
802       contents += clist_selected_->cell(i, 0).get_text();
803     }
804
805   params.setContents( contents );
806   params.setOptions( text_after_->get_entry()->get_text() );
807
808   if( inset_ != 0 )
809     {
810       // Only update if contents have changed
811       if( params != inset_->params() )
812         {
813           inset_->setParams( params );
814           lv_->view()->updateInset( inset_, true );
815         }
816     }
817   else
818     {
819       lv_->getLyXFunc()->Dispatch( LFUN_CITATION_INSERT,
820                                    params.getAsString() );
821     }
822 }
823
824 void FormCitation::sortBibList(gint col)
825 {
826   clist_bib_->set_sort_column(col);
827   clist_bib_->sort();
828 }
829
830 void FormCitation::search()
831 {
832   if (use_regexp_) searchReg();
833   else searchSimple();
834 }
835
836 // looking for entries which match regexp
837 void FormCitation::searchReg()
838 {
839   string tmp, rexptxt( search_string_ );
840   rexptxt = frontStrip( strip( rexptxt ) );
841   
842   LRegex reg(rexptxt);
843
844   // populating clist_bib_
845   clist_bib_->rows().clear();
846
847   clist_bib_->freeze();
848
849   int const sz = bibkeys.size();
850   bool additem;
851   for ( int i = 0; i < sz; ++i )
852     {
853       string data = bibkeys[i] + bibkeysInfo[i];
854
855       if (rexptxt.empty()) additem = true;
856       else additem = (reg.exec(data).size() > 0);
857              
858       if ( additem ) addItemToBibList(i);
859     }
860
861   clist_bib_->sort();
862   clist_bib_->thaw();
863 }
864
865 // looking for entries which contain all the words specified in search_text entry
866 void FormCitation::searchSimple()
867 {
868   vector<string> searchwords;
869   string tmp, stext( search_string_ );
870   stext = frontStrip( strip( stext ) );
871   stext = frontStrip( split(stext, tmp, ' ') );
872   while( !tmp.empty() )
873     {
874       searchwords.push_back(tmp);
875       stext = frontStrip( split(stext, tmp, ' ') );
876     }
877   
878   // populating clist_bib_
879   clist_bib_->rows().clear();
880
881   clist_bib_->freeze();
882
883   int const sz = bibkeys.size();
884   bool additem;
885   for ( int i = 0; i < sz; ++i )
886     {
887       string data = bibkeys[i] + bibkeysInfo[i];
888
889       additem = true;
890
891       int j, szs;
892       for (j = 0, szs = searchwords.size();
893            additem && j < szs; ++j )
894         if ( data.find(searchwords[j]) == string::npos )
895           additem = false;
896              
897       if ( additem ) addItemToBibList(i);
898     }
899
900   clist_bib_->sort();
901   clist_bib_->thaw();
902 }