]> git.lyx.org Git - lyx.git/blob - src/frontends/gnome/FormCitation.C
Fixes to insettabular/text + GNOME patch + KDE patch
[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), u_(0), h_(0), ih_(0), inset_(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;
369       string w, h;
370       path = PACKAGE "/" + LOCAL_CONFIGURE_PREFIX;
371
372       w = path + "/" + CONF_PANE_INFO + CONF_PANE_INFO_DEFAULT;
373       paned_info_->set_position( gnome_config_get_int(w.c_str()) );
374
375       int i, sz;
376       for (i = 0, sz = clist_bib_->columns().size(); i < sz; ++i)
377         {
378           w = path + "/" + CONF_COLUMN + "_" + tostr(i) + CONF_COLUMN_DEFAULT;
379           clist_bib_->column(i).set_width( gnome_config_get_int(w.c_str()) );
380         }
381
382       // connecting signals
383       b_ok->clicked.connect(slot(this, &FormCitation::applySelect));
384       b_cancel->clicked.connect(slot(mainAppWin, &GLyxAppWin::remove_action));
385
386       dialog_->destroy.connect(slot(this, &FormCitation::free));
387
388       clist_bib_->click_column.connect(slot(this, &FormCitation::sortBibList));
389       clist_bib_->select_row.connect(bind(slot(this, &FormCitation::selection_toggled),
390                                           true, false));
391       clist_bib_->unselect_row.connect(bind(slot(this, &FormCitation::selection_toggled),
392                                             false, false));
393       // retrieving data
394       vector<pair<string,string> > blist = lv_->buffer()->getBibkeyList();
395       
396       for ( i = 0, sz = blist.size(); i < sz; ++i )
397         {
398           bibkeys.push_back(blist[i].first);
399           bibkeysInfo.push_back(blist[i].second);
400         }
401       
402       blist.clear();      
403       
404       // updating list
405       search();
406     }
407 }
408
409 /*void FormCitation::show()
410 {
411   if (!dialog_)
412     {
413       GtkWidget * pd = create_DiaInsertCitation();
414
415       dialog_ = Gtk::wrap(pd);
416       clist_selected_ = Gtk::wrap( GTK_CLIST( lookup_widget(pd, "clist_selected") ) );
417       info_ = Gtk::wrap( GNOME_LESS( lookup_widget(pd, "info") ) );
418       text_after_ = Gtk::wrap( GNOME_ENTRY( lookup_widget(pd, "text_after") ) );
419       search_text_ = Gtk::wrap( GNOME_ENTRY( lookup_widget(pd, "search_text") ) );
420         
421       button_select_ = Gtk::wrap( GTK_BUTTON( lookup_widget(pd, "button_select") ) );
422       button_unselect_ = Gtk::wrap( GTK_BUTTON( lookup_widget(pd, "button_unselect") ) );
423       button_up_ = Gtk::wrap( GTK_BUTTON( lookup_widget(pd, "button_up") ) );
424       button_down_ = Gtk::wrap( GTK_BUTTON( lookup_widget(pd, "button_down") ) );
425       button_search_ = Gtk::wrap( GTK_BUTTON( lookup_widget(pd, "button_search") ) );
426
427       button_regexp_ = Gtk::wrap( GTK_CHECK_BUTTON( lookup_widget(pd, "button_regexp") ) );
428
429       paned_info_ = Gtk::wrap( GTK_PANED( lookup_widget(pd, "vpaned_info") ) );
430       paned_key_ = Gtk::wrap( GTK_PANED( lookup_widget(pd, "hpaned_key") ) );
431       box_keys_ =  Gtk::wrap( GTK_BOX( lookup_widget(pd, "vbox_keys") ) );
432
433       b_ok = Gtk::wrap( GTK_BUTTON( lookup_widget(pd, "button_ok") ) );
434       b_cancel = Gtk::wrap( GTK_BUTTON( lookup_widget(pd, "button_cancel") ) );
435
436       // constructing and packing CList
437       vector<string> colnames;
438       colnames.push_back("INVISIBLE");
439       colnames.push_back(N_("Key"));
440       colnames.push_back(N_("Author(s)"));
441       colnames.push_back(N_("Title"));
442       colnames.push_back(N_("Year"));
443       colnames.push_back(N_("Journal"));
444       clist_bib_ = manage( new Gtk::CList(colnames) );
445       clist_bib_->column(0).set_visiblity(false);
446       
447       Gtk::ScrolledWindow * sw_ = Gtk::wrap( GTK_SCROLLED_WINDOW( lookup_widget(pd, "scrolledwindow_bib") ) );
448       sw_->add(*clist_bib_);
449
450       // populating buttons with icons
451       Gnome::Pixmap * p;
452       p = Gtk::wrap( GNOME_PIXMAP( gnome_stock_pixmap_widget(NULL, GNOME_STOCK_PIXMAP_BACK) ) ); 
453       button_select_->add(*p);
454       p = Gtk::wrap( GNOME_PIXMAP( gnome_stock_pixmap_widget(NULL, GNOME_STOCK_PIXMAP_TRASH) ) ); 
455       button_unselect_->add(*p);
456       p = Gtk::wrap( GNOME_PIXMAP( gnome_stock_pixmap_widget(NULL, GNOME_STOCK_PIXMAP_UP) ) ); 
457       button_up_->add(*p);
458       p = Gtk::wrap( GNOME_PIXMAP( gnome_stock_pixmap_widget(NULL, GNOME_STOCK_PIXMAP_DOWN) ) ); 
459       button_down_->add(*p);
460       
461
462       // connecting signals
463       clist_bib_->click_column.connect(slot(this, &FormCitation::sortBibList));
464
465       clist_selected_->select_row.connect(bind(slot(this, &FormCitation::selection_toggled),
466                                                true, true));
467       clist_bib_->select_row.connect(bind(slot(this, &FormCitation::selection_toggled),
468                                           true, false));
469       clist_selected_->unselect_row.connect(bind(slot(this, &FormCitation::selection_toggled),
470                                                  false, true));
471       clist_bib_->unselect_row.connect(bind(slot(this, &FormCitation::selection_toggled),
472                                             false, false));
473       
474       button_select_->clicked.connect(slot(this, &FormCitation::newCitation));
475       button_unselect_->clicked.connect(slot(this, &FormCitation::removeCitation));
476       button_up_->clicked.connect(slot(this, &FormCitation::moveCitationUp));
477       button_down_->clicked.connect(slot(this, &FormCitation::moveCitationDown));
478
479       search_text_->get_entry()->activate.connect(slot(this, &FormCitation::search));
480       button_search_->clicked.connect(slot(this, &FormCitation::search));
481       
482       b_ok->clicked.connect(slot(this, &FormCitation::apply));
483       b_ok->clicked.connect(dialog_->destroy.slot());
484       b_cancel->clicked.connect(dialog_->destroy.slot());
485       dialog_->destroy.connect(slot(this, &FormCitation::free));
486
487       u_ = d_->updateBufferDependent.connect(slot(this, &FormCitation::update));
488       h_ = d_->hideBufferDependent.connect(slot(this, &FormCitation::hide));
489
490       // setting sizes of the widgets
491       string path;
492       string w, h;
493       path  += PACKAGE "/" LOCAL_CONFIGURE_PREFIX;
494       w = path + "/" + CONF_DIALOG_WIDTH + CONF_DIALOG_WIDTH_DEFAULT;
495       h = path + "/" + CONF_DIALOG_HEIGTH + CONF_DIALOG_HEIGTH_DEFAULT;
496       dialog_->set_usize(gnome_config_get_int(w.c_str()),
497                          gnome_config_get_int(h.c_str()));
498
499       w = path + "/" + CONF_PANE_INFO + CONF_PANE_INFO_DEFAULT;
500       paned_info_->set_position( gnome_config_get_int(w.c_str()) );
501
502       w = path + "/" + CONF_PANE_KEY + CONF_PANE_KEY_DEFAULT;
503       paned_key_->set_position( gnome_config_get_int(w.c_str()) );
504
505       int i, sz;
506       for (i = 0, sz = clist_bib_->columns().size(); i < sz; ++i)
507         {
508           w = path + "/" + CONF_COLUMN + "_" + tostr(i) + CONF_COLUMN_DEFAULT;
509           clist_bib_->column(i).set_width( gnome_config_get_int(w.c_str()) );
510         }
511
512       // restoring regexp setting
513       w = path + "/" + CONF_REGEXP + CONF_REGEXP_DEFAULT;
514       button_regexp_->set_active( (gnome_config_get_int(w.c_str()) > 0) );
515       
516       // ready to go...
517       if (!dialog_->is_visible()) dialog_->show_all();
518
519       update();  // make sure its up-to-date
520     }
521   else
522     {
523       Gdk_Window dialog_win(dialog_->get_window());
524       dialog_win.raise();
525     }
526 }
527 */
528
529 void FormCitation::addItemToBibList(int i)
530 {
531   vector<string> r;
532   string key, info;
533   string val;
534
535   key = bibkeys[i];
536   info = bibkeysInfo[i];
537
538   // don't change the order of these first two items:
539   // callback functions depend on the data stored in the first column (its hided)
540   // and in the second column (shown to user)
541   r.push_back( tostr(i) ); 
542   r.push_back( key );
543   
544   // this can be changed (configured by user?)
545   parseBibTeX( info, "author", val);  r.push_back(val);
546   parseBibTeX( info, "title", val);  r.push_back(val);
547   parseBibTeX( info, "year", val);  r.push_back(val);
548   parseBibTeX( info, "journal", val);  r.push_back(val);
549   
550   clist_bib_->rows().push_back(r);
551 }
552
553 void FormCitation::update()
554 {
555   return;
556   
557   bibkeys.clear();
558   bibkeysInfo.clear();
559
560   clist_selected_->rows().clear();
561   clist_bib_->rows().clear();
562
563   // populating clist_bib_
564   clist_bib_->freeze();
565
566   vector<pair<string,string> > blist =
567     lv_->buffer()->getBibkeyList();
568
569   int i, sz;
570   for ( i = 0, sz = blist.size(); i < sz; ++i )
571     {
572       bibkeys.push_back(blist[i].first);
573       bibkeysInfo.push_back(blist[i].second);
574     }
575
576   blist.clear();
577
578   for ( i = 0, sz = bibkeys.size(); i < sz; ++i )
579     addItemToBibList(i);
580
581   clist_bib_->sort();
582   clist_bib_->thaw();
583   // clist_bib_: done
584
585   // populating clist_selected_
586   vector<string> r;
587   string tmp, keys( params.getContents() );
588   keys = frontStrip( split(keys, tmp, ',') );
589   while( !tmp.empty() )
590     {
591       r.clear();
592       r.push_back(tmp);
593       clist_selected_->rows().push_back(r);
594
595       keys = frontStrip( split(keys, tmp, ',') );
596     }
597   // clist_selected_: done
598
599   text_after_->get_entry()->set_text(params.getOptions());
600   
601   updateButtons();
602 }
603
604 void FormCitation::updateButtons()
605 {
606   bool sens;
607
608   sens = (clist_selected_->selection().size()>0);
609   button_unselect_->set_sensitive(sens);
610   button_up_->set_sensitive(sens &&
611                             clist_selected_->selection().operator[](0).get_row_num()>0);
612   button_down_->set_sensitive(sens &&
613                               clist_selected_->selection().operator[](0).get_row_num() <
614                               clist_selected_->rows().size()-1);
615
616   sens = (clist_bib_->selection().size()>0);
617   button_select_->set_sensitive( (clist_bib_->selection().size()>0) );
618 }
619
620 void FormCitation::selection_toggled(gint            row,
621                                      gint            ,//column,
622                                      GdkEvent        * ,//event,
623                                      bool selected,
624                                      bool citeselected)
625 {
626   if (selected)
627     {
628       bool keyfound = false;
629       string info;
630       if (citeselected)
631         {
632           // lookup the record with the same key in bibkeys and show additional Info
633           int i;
634           int sz = bibkeys.size();
635           string key = clist_selected_->cell(row,0).get_text();
636           for (i=0; !keyfound && i<sz; ++i)
637             if (bibkeys[i] == key)
638               {
639                 info = bibkeysInfo[i];
640                 keyfound = true;
641               }   
642         }
643       else
644         {
645           // the first column in clist_bib_ contains the index
646           keyfound = true;
647           info = bibkeysInfo[ strToInt(clist_bib_->cell(row,0).get_text()) ];
648         }
649
650       if (keyfound)
651         info_->show_string(info);
652       else
653         info_->show_string(N_("--- No such key in the database ---"));
654     }
655   else
656     {
657       info_->show_string("");
658     }
659 }
660
661 void FormCitation::removeCitation()
662 {
663   clist_selected_->rows().remove(clist_selected_->selection().operator[](0));
664   updateButtons();
665 }
666
667 void FormCitation::moveCitationUp()
668 {
669   int i = clist_selected_->selection().operator[](0).get_row_num();
670   clist_selected_->swap_rows( i-1, i );
671   clist_selected_->row(i-1).select();
672   updateButtons();
673 }
674
675 void FormCitation::moveCitationDown()
676 {
677   int i = clist_selected_->selection().operator[](0).get_row_num();
678   clist_selected_->swap_rows( i+1, i );
679   clist_selected_->row(i+1).select();
680   updateButtons();
681 }
682
683 void FormCitation::newCitation()
684 {
685   // citation key is in the first column of clist_bib_ list
686   vector<string> r;
687   r.push_back( clist_bib_->selection().operator[](0).operator[](1).get_text() );
688   clist_selected_->rows().push_back(r);
689   clist_selected_->row( clist_selected_->rows().size()-1 ).select();
690   updateButtons();
691 }
692
693 void FormCitation::hide()
694 {
695   if (dialog_!=NULL) mainAppWin->remove_action();
696 }
697
698 void FormCitation::free()
699 {
700   if (dialog_!=NULL)
701     {
702       // storing configuration
703 //        string path;
704 //        string w, h;
705 //        path  = PACKAGE "/" LOCAL_CONFIGURE_PREFIX;
706 //        w = path + "/" + CONF_DIALOG_WIDTH;
707 //        h = path + "/" + CONF_DIALOG_HEIGTH;
708
709 //        gnome_config_set_int(w.c_str(), dialog_->width());
710 //        gnome_config_set_int(h.c_str(), dialog_->height());
711
712 //        w = path + "/" + CONF_PANE_INFO;
713 //        gnome_config_set_int(w.c_str(), paned_key_->height());
714
715 //        w = path + "/" + CONF_PANE_KEY;
716 //        gnome_config_set_int(w.c_str(), box_keys_->width());
717
718 //        int i, sz;
719 //        for (i = 0, sz = clist_bib_->columns().size(); i < sz; ++i)
720 //      {
721 //        w = path + "/" + CONF_COLUMN + "_" + tostr(i);
722 //        gnome_config_set_int(w.c_str(), clist_bib_->get_column_width(i));
723 //      }
724
725 //        w = path + "/" + CONF_REGEXP;
726 //        gnome_config_set_int(w.c_str(), button_regexp_->get_active());
727
728 //        gnome_config_sync();
729
730       // cleaning up
731       dialog_ = NULL;
732       u_.disconnect();
733       h_.disconnect();
734       inset_ = 0;
735       ih_.disconnect();
736     }
737 }
738
739 void FormCitation::applySelect()
740 {
741   if( lv_->buffer()->isReadonly() ) return;
742
743   string contents;
744   int i, sz;
745
746   contents = frontStrip( strip(params.getContents()) );
747   if (!contents.empty()) contents += ", ";
748   
749   sz = clist_bib_->selection().size();
750   for (i=0; i < sz; ++i)
751     {
752       if (i > 0) contents += ", ";
753       contents += clist_bib_->selection().operator[](i).operator[](1).get_text();
754     }
755   
756   params.setContents( contents );
757   params.setOptions( text_after_->get_entry()->get_text() );
758
759   if( inset_ != 0 )
760     {
761       // Only update if contents have changed
762       if( params != inset_->params() )
763         {
764           inset_->setParams( params );
765           lv_->view()->updateInset( inset_, true );
766         }
767     }
768   else
769     {
770       lv_->getLyXFunc()->Dispatch( LFUN_CITATION_INSERT,
771                                    params.getAsString().c_str() );
772     }
773
774   // save config
775   text_after_->save_history();
776
777   string path;
778   string w, h;
779   path  = PACKAGE "/" + LOCAL_CONFIGURE_PREFIX;
780
781   w = path + "/" + CONF_PANE_INFO;
782   gnome_config_set_int(w.c_str(), paned_info_->width() - info_->width());
783   
784   for (i = 0, sz = clist_bib_->columns().size(); i < sz; ++i)
785     {
786       w = path + "/" + CONF_COLUMN + "_" + tostr(i);
787       gnome_config_set_int(w.c_str(), clist_bib_->get_column_width(i));
788     }
789   
790   gnome_config_sync();
791   
792   // close dialog
793   hide();
794 }
795
796 void FormCitation::apply()
797 {
798   if( lv_->buffer()->isReadonly() ) return;
799
800   string contents;
801   for( unsigned int i = 0; i < clist_selected_->rows().size(); ++i )
802     {
803       if (i > 0) contents += ", ";
804       contents += clist_selected_->cell(i, 0).get_text();
805     }
806
807   params.setContents( contents );
808   params.setOptions( text_after_->get_entry()->get_text() );
809
810   if( inset_ != 0 )
811     {
812       // Only update if contents have changed
813       if( params != inset_->params() )
814         {
815           inset_->setParams( params );
816           lv_->view()->updateInset( inset_, true );
817         }
818     }
819   else
820     {
821       lv_->getLyXFunc()->Dispatch( LFUN_CITATION_INSERT,
822                                    params.getAsString().c_str() );
823     }
824 }
825
826 void FormCitation::sortBibList(gint col)
827 {
828   clist_bib_->set_sort_column(col);
829   clist_bib_->sort();
830 }
831
832 void FormCitation::search()
833 {
834   if (use_regexp_) searchReg();
835   else searchSimple();
836 }
837
838 // looking for entries which match regexp
839 void FormCitation::searchReg()
840 {
841   string tmp, rexptxt( search_string_ );
842   rexptxt = frontStrip( strip( rexptxt ) );
843   
844   LRegex reg(rexptxt);
845
846   // populating clist_bib_
847   clist_bib_->rows().clear();
848
849   clist_bib_->freeze();
850
851   int i, sz;
852   bool additem;
853   for ( i = 0, sz = bibkeys.size(); i < sz; ++i )
854     {
855       string data = bibkeys[i] + bibkeysInfo[i];
856
857       if (rexptxt.empty()) additem = true;
858       else additem = (reg.exec(data).size() > 0);
859              
860       if ( additem ) addItemToBibList(i);
861     }
862
863   clist_bib_->sort();
864   clist_bib_->thaw();
865 }
866
867 // looking for entries which contain all the words specified in search_text entry
868 void FormCitation::searchSimple()
869 {
870   vector<string> searchwords;
871   string tmp, stext( search_string_ );
872   stext = frontStrip( strip( stext ) );
873   stext = frontStrip( split(stext, tmp, ' ') );
874   while( !tmp.empty() )
875     {
876       searchwords.push_back(tmp);
877       stext = frontStrip( split(stext, tmp, ' ') );
878     }
879   
880   // populating clist_bib_
881   clist_bib_->rows().clear();
882
883   clist_bib_->freeze();
884
885   int i, sz;
886   bool additem;
887   for ( i = 0, sz = bibkeys.size(); i < sz; ++i )
888     {
889       string data = bibkeys[i] + bibkeysInfo[i];
890
891       additem = true;
892
893       int j, szs;
894       for (j = 0, szs = searchwords.size();
895            additem && j < szs; ++j )
896         if ( data.find(searchwords[j]) == string::npos )
897           additem = false;
898              
899       if ( additem ) addItemToBibList(i);
900     }
901
902   clist_bib_->sort();
903   clist_bib_->thaw();
904 }