1 #include <cstring>
2 #include <cstdlib>
3 #include <FL/Fl.H>
4 #include <FL/fl_draw.H>
5
6 #include "combo.h"
7
8 void popbrwsr_cb (Fl_Widget *v, long d);
9
Fl_PopBrowser(int X,int Y,int W,int H,retvals R)10 Fl_PopBrowser::Fl_PopBrowser (int X, int Y, int W, int H, retvals R)
11 : Fl_Window (X, Y, W, H, "")
12 {
13 Rvals = R;
14 hRow = H;
15 wRow = W;
16 clear_border();
17 box(FL_BORDER_BOX);
18 popbrwsr = new Fl_Select_Browser(0,0,wRow,hRow,0);
19 popbrwsr->callback ( (Fl_Callback*)popbrwsr_cb);
20 parent = 0;
21 end();
22 set_modal();
23 }
24
~Fl_PopBrowser()25 Fl_PopBrowser::~Fl_PopBrowser ()
26 {
27 }
28
handle(int event)29 int Fl_PopBrowser::handle(int event)
30 {
31 if (!Fl::event_inside( child(0) ) && event == FL_PUSH) {
32 pophide();
33 return 1;
34 }
35 return Fl_Group::handle(event);
36 }
37
add(char * s,void * d)38 void Fl_PopBrowser::add(char *s, void *d)
39 {
40 popbrwsr->add(s,d);
41 }
42
clear()43 void Fl_PopBrowser::clear()
44 {
45 popbrwsr->clear();
46 }
47
sort()48 void Fl_PopBrowser::sort()
49 {
50 return;
51 }
52
popshow(int x,int y)53 void Fl_PopBrowser::popshow (int x, int y)
54 {
55 int nRows = parent->numrows();
56 int fh = fl_height();
57 int height = nRows * fh + 4;
58
59 if (popbrwsr->size() == 0) return;
60 if (nRows > parent->lsize()) nRows = parent->lsize();
61
62 // locate first occurance of Output string value in the list
63 // and display that if found
64 int i = parent->index();
65 if (!(i >= 0 && i < parent->listsize)) {
66 for (i = 0; i < parent->listsize; i++)
67 if (!strcmp(parent->Output->value(), parent->datalist[i]->s))
68 break;
69 if (i == parent->listsize)
70 i = 0;
71 }
72
73 // resize and reposition the popup to insure that it is within the bounds
74 // of the uppermost parent widget
75 // preferred position is just below and at the same x position as the
76 // parent widget
77
78 Fl_Widget *gparent = parent;
79 int xp = gparent->x(),
80 yp = gparent->y(),
81 hp = gparent->h();
82 while ((gparent = gparent->parent())) {
83 xp = gparent->x();
84 yp = gparent->y();
85 hp = gparent->h();
86 }
87
88 int nu = nRows, nl = nRows;
89 int hu = nu * fh + 4, hl = nl * fh + 4;
90 int yu = parent->y() - hu;
91 int yl = y;
92
93 while (nl > 1 && (yl + hl > hp)) { nl--; hl -= fh; }
94 while (nu > 1 && yu < 0) { nu--; yu += fh; hu -= fh; }
95
96 if (nl >= nu) { y = yl; height = hl; }
97 else { y = yu; height = hu; }
98
99 x += xp;
100 y += yp;
101
102 popbrwsr->size (wRow, height);
103 resize (x, y, wRow, height);
104
105 popbrwsr->topline (i);
106 show();
107
108 Fl::grab(this);
109 }
110
pophide()111 void Fl_PopBrowser::pophide ()
112 {
113 hide ();
114 Fl::release();
115 }
116
popbrwsr_cb_i(Fl_Widget * v,long d)117 void Fl_PopBrowser::popbrwsr_cb_i (Fl_Widget *v, long d)
118 {
119 Fl_PopBrowser *me = (Fl_PopBrowser *)(v->parent());
120 Fl_Input *tgt = me->Rvals.Inp;
121 // update the return values
122 int row = (me->popbrwsr)->value();
123 if (row == 0) return;
124 me->popbrwsr->deselect();
125
126 if (tgt) {
127 tgt->value ((me->popbrwsr)->text (row));
128 me->Rvals.retval = (me->popbrwsr)->data (row);
129 *(me->Rvals.idx) = row - 1;
130 }
131 me->pophide();
132 // user selected an item from the browser list, so execute the
133 // callback if one is registered.
134 if (me->parent)
135 (me->parent)->do_callback();
136 return;
137 }
138
popbrwsr_cb(Fl_Widget * v,long d)139 void popbrwsr_cb (Fl_Widget *v, long d)
140 {
141 ((Fl_PopBrowser *)(v))->popbrwsr_cb_i (v, d);
142 return;
143 }
144
145
fl_popbrwsr(Fl_Widget * p)146 void Fl_ComboBox::fl_popbrwsr(Fl_Widget *p)
147 {
148 int xpos = p->x(), ypos = p->h() + p->y();
149 if (Brwsr == 0) {
150 Brwsr = new Fl_PopBrowser(xpos, ypos, width, height, R);
151 }
152 // pass the calling widget to the popup browser so that the
153 // correct callback function can be called when the user selects an item
154 // from the browser list
155 Brwsr->parent = (Fl_ComboBox *) p;
156 Brwsr->popshow(xpos, ypos);
157 return;
158 }
159
btnComboBox_cb(Fl_Widget * v,void * d)160 void btnComboBox_cb (Fl_Widget *v, void *d)
161 {
162 Fl_Widget *p = v->parent();
163 ((Fl_ComboBox *)p)->fl_popbrwsr (p);
164 return;
165 }
166
167
Fl_ComboBox(int X,int Y,int W,int H,const char * L)168 Fl_ComboBox::Fl_ComboBox (int X,int Y,int W,int H, const char *L)
169 : Fl_Group (X, Y, W, H, L)
170 {
171 width = W; height = H - 4;
172 Btn = new Fl_Button (X + W - 18, Y + 1, 18, H - 2, "@#-32>");
173 Btn->callback ((Fl_Callback *)btnComboBox_cb, 0);
174 Output = new Fl_Input (X, Y, W-18, H);
175
176 Brwsr = 0;
177 datalist = new datambr *[FL_COMBO_LIST_INCR];
178 maxsize = FL_COMBO_LIST_INCR;
179 for (int i = 0; i < FL_COMBO_LIST_INCR; i++) datalist[i] = 0;
180 listsize = 0;
181 listtype = 0;
182 end();
183 R.Inp = Output;
184 R.retval = retdata;
185 R.idx = &idx;
186 numrows_ = 8;
187 }
188
~Fl_ComboBox()189 Fl_ComboBox::~Fl_ComboBox()
190 {
191 if (Brwsr) delete Brwsr;
192 for (int i = 0; i < listsize; i++) {
193 if (datalist[i]) {
194 if (datalist[i]->s) delete [] datalist[i]->s;
195 delete datalist[i];
196 }
197 }
198 delete [] datalist;
199 }
200
type(int t)201 void Fl_ComboBox::type (int t)
202 {
203 listtype = t;
204 }
205
readonly()206 void Fl_ComboBox::readonly()
207 {
208 Output->type(FL_NORMAL_OUTPUT);
209 }
210
211 // ComboBox value is contained in the Output widget
212
value(const char * s)213 void Fl_ComboBox::value( const char *s )
214 {
215 int i;
216 if ((listtype & FL_COMBO_UNIQUE_NOCASE) == FL_COMBO_UNIQUE_NOCASE) {
217 for (i = 0; i < listsize; i++) {
218 if (strcasecmp (s, datalist[i]->s) == 0)
219 break;
220 }
221 } else {
222 for (i = 0; i < listsize; i++) {
223 if (strcmp (s, datalist[i]->s) == 0)
224 break;
225 }
226 }
227 if ( i < listsize)
228 Output->value(datalist[i]->s);
229 }
230
put_value(const char * s)231 void Fl_ComboBox::put_value(const char *s)
232 {
233 value(s);
234 }
235
index(int i)236 void Fl_ComboBox::index(int i)
237 {
238 if (i >= 0 && i < listsize)
239 Output->value( datalist[idx = i]->s);
240 }
241
242
value()243 const char *Fl_ComboBox::value()
244 {
245 return (Output->value ());
246 }
247
index()248 int Fl_ComboBox::index() {
249 return idx;
250 }
251
data()252 void * Fl_ComboBox::data() {
253 return retdata;
254 }
255
add(const char * s,void * d)256 void Fl_ComboBox::add( const char *s, void * d)
257 {
258 if (Brwsr == 0) {
259 Brwsr = new Fl_PopBrowser(0, 0, width, height, R);
260 }
261 // test for uniqueness of entry if required
262 if ((listtype & FL_COMBO_UNIQUE) == FL_COMBO_UNIQUE) {
263 if ((listtype & FL_COMBO_UNIQUE_NOCASE) == FL_COMBO_UNIQUE_NOCASE) {
264 for (int i = 0; i < listsize; i++) {
265 if (strcasecmp (s, datalist[i]->s) == 0)
266 return;
267 }
268 } else {
269 for (int i = 0; i < listsize; i++) {
270 if (strcmp (s, datalist[i]->s) == 0)
271 return;
272 }
273 }
274 }
275 // not unique or not in list, so add this entry
276 datalist[listsize] = new datambr;
277 datalist[listsize]->s = new char [strlen(s) + 1];
278 datalist[listsize]->s[0] = 0;
279 strcpy (datalist[listsize]->s, s);
280 datalist[listsize]->d = d;
281 Brwsr->add(datalist[listsize]->s,d);
282 listsize++;
283 if (listsize == maxsize) {
284 int nusize = maxsize + FL_COMBO_LIST_INCR;
285 datambr **temparray = new datambr *[nusize];
286 for (int i = 0; i < listsize; i++) temparray[i] = datalist[i];
287 delete [] datalist;
288 datalist = temparray;
289 maxsize = nusize;
290 }
291 }
292
clear()293 void Fl_ComboBox::clear()
294 {
295 if (Brwsr == 0)
296 Brwsr = new Fl_PopBrowser(0, 0, width, height, R);
297 else
298 Brwsr->clear();
299
300 if (listsize == 0) return;
301 for (int i = 0; i < listsize; i++) {
302 delete [] datalist[i]->s;
303 delete datalist[i];
304 }
305 listsize = 0;
306 }
307
DataCompare(const void * x1,const void * x2)308 int DataCompare( const void *x1, const void *x2 )
309 {
310 int cmp;
311 datambr *X1, *X2;
312 X1 = *(datambr **)(x1);
313 X2 = *(datambr **)(x2);
314 cmp = strcasecmp (X1->s, X2->s);
315 if (cmp < 0)
316 return -1;
317 if (cmp > 0)
318 return 1;
319 return 0;
320 }
321
sort()322 void Fl_ComboBox::sort() {
323 Brwsr->clear ();
324 qsort (&datalist[0],
325 listsize,
326 sizeof (datambr *),
327 DataCompare);
328 for (int i = 0; i < listsize; i++)
329 Brwsr->add (datalist[i]->s, datalist[i]->d);
330 }
331
textfont(int fnt)332 void Fl_ComboBox::textfont (int fnt)
333 {
334 Output->textfont (fnt);
335 }
336
textsize(uchar n)337 void Fl_ComboBox::textsize (uchar n)
338 {
339 Output->textsize (n);
340 }
341
textcolor(Fl_Color c)342 void Fl_ComboBox::textcolor( Fl_Color c)
343 {
344 Output->textcolor (c);
345 }
346
color(Fl_Color c)347 void Fl_ComboBox::color(Fl_Color c)
348 {
349 _color = c;
350 Output->color(c);
351 if (Brwsr) Brwsr->color(c);
352 }
353
354
355
356