1 /*
2   widgets.cpp:
3 
4   Copyright (C) 2002 Gabriel Maldonado
5 
6   This file is part of Csound.
7 
8   The Csound Library is free software; you can redistribute it
9   and/or modify it under the terms of the GNU Lesser General Public
10   License as published by the Free Software Foundation; either
11   version 2.1 of the License, or (at your option) any later version.
12 
13   Csound is distributed in the hope that it will be useful,
14   but WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16   GNU Lesser General Public License for more details.
17 
18   You should have received a copy of the GNU Lesser General Public
19   License along with Csound; if not, write to the Free Software
20   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
21   02110-1301 USA
22 */
23 
24 #if defined(WIN32)
25 # include <FL/Fl_Output.H>
26 #endif
27 #ifndef _MSC_VER
28 # include <unistd.h>
29 #endif
30 #if !defined(_MSC_VER)
31 #include <unistd.h>
32 #endif
33 #include <csound.h>
34 #include "widglobals.h"
35 #include <FL/x.H>
36 
37 Fl_Font FONT_TABLE[] = { FL_HELVETICA,                  FL_HELVETICA,
38                          FL_HELVETICA_BOLD,             FL_HELVETICA_ITALIC,
39                          FL_HELVETICA_BOLD_ITALIC,      FL_COURIER,
40                          FL_COURIER_BOLD,               FL_COURIER_ITALIC,
41                          FL_COURIER_BOLD_ITALIC,        FL_TIMES,
42                          FL_TIMES_BOLD,                 FL_TIMES_ITALIC,
43                          FL_TIMES_BOLD_ITALIC,          FL_SYMBOL,
44                          FL_SCREEN,                     FL_SCREEN_BOLD,
45                          FL_ZAPF_DINGBATS };
46 
47 Fl_Align ALIGN_TABLE[] = { FL_ALIGN_BOTTOM,      FL_ALIGN_CENTER,
48                            FL_ALIGN_TOP,         FL_ALIGN_BOTTOM,
49                            FL_ALIGN_LEFT,        FL_ALIGN_RIGHT,
50                            FL_ALIGN_TOP_LEFT,    FL_ALIGN_TOP_RIGHT,
51                            FL_ALIGN_BOTTOM_LEFT, FL_ALIGN_BOTTOM_RIGHT };
52 
53 Fl_Boxtype BOX_TABLE[] = {  FL_FLAT_BOX,         FL_FLAT_BOX,
54                             FL_UP_BOX,           FL_DOWN_BOX,
55                             FL_THIN_UP_BOX,      FL_THIN_DOWN_BOX,
56                             FL_ENGRAVED_BOX,     FL_EMBOSSED_BOX,
57                             FL_BORDER_BOX,      _FL_SHADOW_BOX,
58                             _FL_ROUNDED_BOX,    _FL_RSHADOW_BOX,
59                             _FL_RFLAT_BOX,      _FL_ROUND_UP_BOX,
60                             _FL_ROUND_DOWN_BOX, _FL_DIAMOND_UP_BOX,
61                             _FL_DIAMOND_DOWN_BOX,_FL_OVAL_BOX,
62                             _FL_OSHADOW_BOX,    _FL_OFLAT_BOX};
63 
widget_init(CSOUND * csound)64 void widget_init(CSOUND *csound)
65 {
66     WIDGET_GLOBALS *widgetGlobals =
67       (WIDGET_GLOBALS *) csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS");
68     if (widgetGlobals == NULL) {
69       csound->CreateGlobalVariable(csound, "WIDGET_GLOBALS",
70                                    sizeof(WIDGET_GLOBALS));
71       widgetGlobals =
72         (WIDGET_GLOBALS *) csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS");
73 
74       //csound->widgetGlobals = new WIDGET_GLOBALS;
75       //csound->Calloc(csound, sizeof(WIDGET_GLOBALS));
76       //      widgetGlobals->indrag            = 0;
77       //      widgetGlobals->sldrag            = 0;
78       //      widgetGlobals->stack_count)       = 0;
79 
80       widgetGlobals->FLcontrol_iheight = 15;
81       widgetGlobals->FLroller_iheight  = 18;
82       widgetGlobals->FLcontrol_iwidth  = 400;
83       widgetGlobals->FLroller_iwidth   = 150;
84       widgetGlobals->FLvalue_iwidth    = 100;
85 
86       widgetGlobals->FLcolor           = -1;
87       widgetGlobals->FLcolor2          = -1;
88       // below was commented out, why? VL 24-04-08
89       widgetGlobals->FLtext_size       = 0;
90       widgetGlobals->FLtext_color      = -1;
91       widgetGlobals->FLtext_font       = -1;
92       //  below was commented out, why? VL 24-04-08
93       widgetGlobals->FLtext_align      = 0;
94 
95       widgetGlobals->FL_ix             = 10;
96       widgetGlobals->FL_iy             = 10;
97       widgetGlobals->currentSnapGroup  = 0;
98       widgetGlobals->last_KEY=0;
99       widgetGlobals->isKeyDown=0;
100     }
101 }
102 
103 extern void graphs_reset(CSOUND *csound);
104 
widget_reset(CSOUND * csound,void * pp)105 int widget_reset(CSOUND *csound, void *pp)
106 {
107     (void) pp;
108     WIDGET_GLOBALS *widgetGlobals =
109       (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS");
110     if (widgetGlobals != NULL) {
111       widgetGlobals->AddrSetValue.~vector<ADDR_SET_VALUE>();
112       widgetGlobals->AddrStack.~vector<ADDR_STACK>();
113       widgetGlobals->allocatedStrings.~vector<char*>();
114       widgetGlobals->fl_windows.~vector<PANELS>();
115       csound->DestroyGlobalVariable(csound, "WIDGET_GLOBALS");
116     }
117     graphs_reset(csound);
118     return OK;
119 }
120 
121 #ifndef NO_FLTK_THREADS
122 extern "C" {
123   /* called by sensevents() once in every control period */
evt_callback(CSOUND * csound,widgetsGlobals_t * p)124   static void evt_callback(CSOUND *csound, widgetsGlobals_t *p)
125   {
126       /* flush any pending real time events */
127       if (UNLIKELY(p->eventQueue != NULL)) {
128         csound->LockMutex(p->mutex_);
129         while (p->eventQueue != NULL) {
130           rtEvt_t *ep = p->eventQueue;
131           p->eventQueue = ep->nxt;
132           ep->evt.pinstance = NULL;
133           csound->UnlockMutex(p->mutex_);
134           csound->insert_score_event_at_sample(csound, &(ep->evt),
135                                      csound->GetCurrentTimeSamples(csound));
136           free(ep);
137           csound->LockMutex(p->mutex_);
138         }
139         csound->UnlockMutex(p->mutex_);
140       }
141       /* if all windows have been closed, terminate performance */
142       if (UNLIKELY(p->exit_now)) {
143         EVTBLK  e;
144         memset(&e, 0, sizeof(EVTBLK));
145         e.opcod = 'e';
146         csound->insert_score_event_at_sample(csound, &e,
147                                              csound->GetCurrentTimeSamples(csound));
148       }
149   }
150 }       // extern "C"
151 #endif  // NO_FLTK_THREADS
152 
153 // ---- IV - Aug 23 2002 ---- included file: Fl_linux_stubs.cpp
154 
155 /*
156  * this is a file used in the linux distribution to be able to use
157  * the DirectCsound 5.1 widget code by Gabriel Maldonado on linux
158  * systems.
159  *
160  * This code has been written by Nicola Bernardini (nicb@centrotemporeale.it)
161  * mostly based on ideas by Dave Phillips (dlphip@bright.net)
162  */
163 
164 extern "C" {
ButtonSched(CSOUND * csound,MYFLT * args[],int numargs)165   void ButtonSched(CSOUND *csound, MYFLT *args[], int numargs)
166   { /* based on code by rasmus */
167 #ifndef NO_FLTK_THREADS
168       widgetsGlobals_t  *p;
169       /* this is still not fully thread safe... */
170       /* hope that no global variable is created just while this fn is called */
171       p = (widgetsGlobals_t*) csound->QueryGlobalVariable(csound,
172                                                           "_widgets_globals");
173       if (p != NULL) {
174         rtEvt_t   *evt;
175         int       i;
176 
177         /* Create the new event */
178         evt = (rtEvt_t*) malloc(sizeof(rtEvt_t));
179         evt->nxt = NULL;
180         evt->evt.pinstance = NULL;
181         evt->evt.strarg = NULL; evt->evt.scnt = 0;
182         evt->evt.opcod = (char) *args[0];
183         if (evt->evt.opcod == '\0')
184           evt->evt.opcod = 'i';
185         evt->evt.pcnt = numargs - 1;
186         evt->evt.p[1] = evt->evt.p[2] = evt->evt.p[3] = MYFLT(0.0);
187         for (i = 1; i < numargs; i++)
188           evt->evt.p[i] = *args[i];
189         if (evt->evt.p[2] < MYFLT(0.0))
190           evt->evt.p[2] = MYFLT(0.0);
191         /* queue event for insertion by main Csound thread */
192         csound->LockMutex(p->mutex_);
193         if (p->eventQueue == NULL)
194           p->eventQueue = evt;
195         else {
196           rtEvt_t *ep = p->eventQueue;
197           while (ep->nxt != NULL)
198             ep = ep->nxt;
199           ep->nxt = evt;
200         }
201         csound->UnlockMutex(p->mutex_);
202       }
203       else
204 #endif  // NO_FLTK_THREADS
205         {
206           EVTBLK  e;
207           int     i;
208           /* Create the new event */
209           e.strarg = NULL; e.scnt = 0;
210           e.opcod = (char) *args[0];
211           if (e.opcod == '\0')
212             e.opcod = 'i';
213           e.pcnt = numargs - 1;
214           e.p[1] = e.p[2] = e.p[3] = MYFLT(0.0);
215           for (i = 1; i < numargs; i++)
216             e.p[i] = *args[i];
217           if (e.p[2] < MYFLT(0.0))
218             e.p[2] = MYFLT(0.0);
219           e.pinstance = NULL;
220           csound->insert_score_event_at_sample(csound, &e,
221                                   csound->GetCurrentTimeSamples(csound));
222         }
223   }
224 }
225 
226 // ---- IV - Aug 23 2002 ---- included file: Fl_Knob.cxx
227 
228 // generated by Fast Light User Interface Designer (fluid) version 2.00
229 
Fl_Knob(CSOUND * cs,int xx,int yy,int ww,int hh,const char * l)230 Fl_Knob::Fl_Knob(CSOUND *cs, int xx,int yy,int ww,int hh,const char *l)
231   : Fl_Valuator(xx,yy,ww,hh,l)
232 {
233     csound = cs;
234     a1 = 35;
235     a2 = 325;
236     _type = DOTLIN;
237     _percent = 0.3f;
238     _scaleticks = 10;
239 }
240 
~Fl_Knob(void)241 Fl_Knob::~Fl_Knob(void)
242 {
243 }
244 
draw(void)245 void Fl_Knob::draw(void)
246 {
247     int ox,oy,ww,hh,side;
248     unsigned char rr,gg,bb;
249 
250     ox = x();
251     oy = y();
252     ww = w();
253     hh = h();
254     draw_label();
255     fl_clip(ox,oy,ww,hh);
256     if (ww > hh) {
257       side = hh;
258       ox = ox + (ww - side) / 2;
259     }
260     else {
261       side = ww;
262       oy = oy + (hh - side) / 2;
263     }
264     side = w() > h () ? hh:ww;
265     int dam = damage();
266     if (dam & FL_DAMAGE_ALL) {
267       int col = parent()->color();
268       fl_color(col);
269       fl_rectf(ox,oy,side,side);
270       Fl::get_color((Fl_Color)col,rr,gg,bb);
271       shadow(-60,rr,gg,bb);
272       fl_pie(ox+9,oy+9,side-12,side-12,0,360);
273       draw_scale(ox,oy,side);
274       col = color();
275       Fl::get_color((Fl_Color)col,rr,gg,bb);
276       shadow(15,rr,gg,bb);
277       fl_pie(ox+6,oy+6,side-12,side-12,40,80);
278       shadow(30,rr,gg,bb);
279       fl_pie(ox+6,oy+6,side-12,side-12,80,220);
280       shadow(-15,rr,gg,bb);
281       fl_pie(ox+6,oy+6,side-12,side-12,220,260);
282       shadow(-30,rr,gg,bb);
283       fl_pie(ox+6,oy+6,side-12,side-12,260,400);
284       fl_color(FL_BLACK);
285       fl_arc(ox+6,oy+6,side-11,side-11,0,360);
286       fl_color(col);
287       fl_pie(ox+10,oy+10,side-20,side-20,0,360);
288     }
289     else {
290       fl_color(color());
291       fl_pie(ox+10,oy+10,side-20,side-20,0,360);
292     }
293     Fl::get_color((Fl_Color)color(),rr,gg,bb);
294     shadow(10,rr,gg,bb);
295     fl_pie(ox+10,oy+10,side-20,side-20,110,150);
296     fl_pie(ox+10,oy+10,side-20,side-20,290,330);
297     shadow(17,rr,gg,bb);
298     fl_pie(ox+10,oy+10,side-20,side-20,120,140);
299     fl_pie(ox+10,oy+10,side-20,side-20,300,320);
300     shadow(25,rr,gg,bb);
301     fl_pie(ox+10,oy+10,side-20,side-20,127,133);
302     fl_pie(ox+10,oy+10,side-20,side-20,307,313);
303     draw_cursor(ox,oy,side);
304     fl_pop_clip();
305 }
306 
handle(int event)307 int Fl_Knob::handle(int  event)
308 {
309     int ox,oy,ww,hh;
310 
311     ox = x() + 10; oy = y() + 10;
312     ww = w() - 20;
313     hh = h() - 20;
314     switch (event) {
315     case FL_PUSH:
316       handle_push();
317       return 1;                 // CHECKME ***JPff added this; is that right?***
318     case FL_DRAG:
319       {
320         int mx = Fl::event_x()-ox-ww/2;
321         int my = Fl::event_y()-oy-hh/2;
322         if (!mx && !my) return 1;
323         double angle = 270-atan2((float)-my, (float)mx)*180.0/PI;
324         double oldangle = (a2-a1)*(value()-minimum())/(maximum()-minimum()) + a1;
325         while (angle < oldangle-180) angle += 360.0;
326         while (angle > oldangle+180) angle -= 360.0;
327         double val;
328         if ((a1<a2) ? (angle <= a1) : (angle >= a1)) {
329           val = minimum();
330         }
331         else if ((a1<a2) ? (angle >= a2) : (angle <= a2)) {
332           val = maximum();
333         }
334         else {
335           val = minimum() + (maximum()-minimum())*(angle-a1)/(a2-a1);
336         }
337         handle_drag(clamp(round(val)));
338       }
339       return 1;
340     case FL_RELEASE:
341       handle_release();
342       return 1;
343     default:
344       return 0;
345     }
346     return 0;
347 }
348 
type(int ty)349 void Fl_Knob::type(int ty)
350 {
351     _type = ty;
352 }
353 
shadow(const int offs,const uchar r,uchar g,uchar b)354 void Fl_Knob::shadow(const int offs,const uchar r,uchar g,uchar b)
355 {
356     int rr,gg,bb;
357 
358     rr = r + offs;
359     rr = rr > 255 ? 255 : rr;
360     rr = rr < 0 ? 0:rr;
361     gg = g + offs;
362     gg = gg > 255 ? 255 : gg;
363     gg = gg < 0 ? 0 :gg ;
364     bb = b + offs;
365     bb = bb > 255 ? 255 : bb;
366     bb = bb < 0 ? 0 : bb;
367     fl_color((uchar)rr,(uchar)gg,(uchar)bb);
368 }
369 
draw_scale(const int ox,const int oy,const int side)370 void Fl_Knob::draw_scale(const int ox,const int oy,const int side)
371 {
372     float x1,y1,x2,y2,rds,cx,cy,ca,sa;
373 
374     rds = side * 0.5f;
375     cx = ox + side * 0.5f;
376     cy = oy + side * 0.5f;
377     if (!(_type & DOTLOG_3)) {
378       if (_scaleticks == 0) return;
379       double a_step = (10.0*PI/6.0) / _scaleticks;
380       double a_orig = -(PI/3.0);
381       for (int a = 0; a <= _scaleticks; a++) {
382         double na = a_orig + a * a_step;
383         ca = cos(na);
384         sa = sin(na);
385         x1 = cx + rds * ca;
386         y1 = cy - rds * sa;
387         x2 = cx + (rds-6) * ca;
388         y2 = cy - (rds-6) * sa;
389         fl_color(FL_BLACK);
390         fl_line((int)x1,(int)y1,(int)x2,(int)y2);
391         fl_color(FL_WHITE);
392         if (sa*ca >=0)
393           fl_line((int)x1+1,(int)y1+1,(int)x2+1,(int)y2+1);
394         else
395           fl_line((int)x1+1,(int)y1-1,(int)x2+1,(int)y2-1);
396       }
397     }
398     else {
399       int nb_dec = (_type & DOTLOG_3);
400       for (int k = 0; k < nb_dec; k++) {
401         double a_step = (10.0*PI/6.0) / nb_dec;
402         double a_orig = -(PI/3.0) + k * a_step;
403         for (int a = (k) ? 2:1; a <= 10; ) {
404           double na = a_orig + log10((double)a) * a_step;
405           ca = cos(na);
406           sa = sin(na);
407           x1 = cx - rds * ca;
408           y1 = cy - rds * sa;
409           x2 = cx - (rds-6) * ca;
410           y2 = cy - (rds-6) * sa;
411           fl_color(FL_BLACK);
412           fl_line((int)x1,(int)y1,(int)x2,(int)y2);
413           fl_color(FL_WHITE);
414           if (sa*ca <0)
415             fl_line((int)x1+1,(int)y1+1,(int)x2+1,(int)y2+1);
416           else
417             fl_line((int)x1+1,(int)y1-1,(int)x2+1,(int)y2-1);
418           if ((a == 1) || (nb_dec == 1))
419             a += 1;
420           else
421             a += 2;
422         }
423       }
424     }
425 }
426 
draw_cursor(const int ox,const int oy,const int side)427 void Fl_Knob::draw_cursor(const int ox,const int oy,const int side)
428 {
429     float rds,cur,cx,cy;
430     double angle;
431 
432     rds = (side - 20.0f) * 0.5f;
433     cur = _percent * rds * 0.5f;
434     cx = ox + side * 0.5f;
435     cy = oy + side * 0.5f;
436     angle = (a2-a1)*(value()-minimum())/(maximum()-minimum()) + a1;
437     fl_push_matrix();
438     fl_scale(1,1);
439     fl_translate(cx,cy);
440     fl_rotate(-angle);
441     fl_translate(0,rds-cur-2.0f);
442     if (_type<LINELIN) {
443       fl_begin_polygon();
444       fl_color(selection_color());
445       fl_circle(0.0,0.0,cur);
446       fl_end_polygon();
447       fl_begin_loop();
448       fl_color(FL_BLACK);
449       fl_circle(0.0,0.0,cur);
450       fl_end_loop();
451     }
452     else {
453       fl_begin_polygon();
454       fl_color(selection_color());
455       fl_vertex(-1.5,-cur);
456       fl_vertex(-1.5,cur);
457       fl_vertex(1.5,cur);
458       fl_vertex(1.5,-cur);
459       fl_end_polygon();
460       fl_begin_loop();
461       fl_color(FL_BLACK);
462       fl_vertex(-1.5,-cur);
463       fl_vertex(-1.5,cur);
464       fl_vertex(1.5,cur);
465       fl_vertex(1.5,-cur);
466       fl_end_loop();
467     }
468     fl_pop_matrix();
469 }
470 
cursor(const int pc)471 void Fl_Knob::cursor(const int pc)
472 {
473     _percent = (float)pc*0.01f;
474 
475     if (_percent < 0.05f) _percent = 0.05f;
476     if (_percent > 1.0f) _percent = 1.0f;
477     if (visible()) damage(FL_DAMAGE_CHILD);
478 }
479 
scaleticks(const int tck)480 void Fl_Knob::scaleticks(const int tck)
481 {
482     _scaleticks = tck;
483     if (_scaleticks < 0) _scaleticks = 0;
484     if (_scaleticks > 31) _scaleticks = 31;
485     if (visible()) damage(FL_DAMAGE_ALL);
486 }
487 
488 // ---- IV - Aug 23 2002 ---- included file: Fl_Spin.cpp
489 
draw()490 void Fl_Spin::draw()
491 {
492     int sxx = x(), syy = y(), sww = w(), shh = h();
493     Fl_Boxtype box1 = (Fl_Boxtype)(box());
494     int border_size=Fl::box_dx(box());
495     WIDGET_GLOBALS *widgetGlobals =
496       (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS");
497 
498     if (damage()&~FL_DAMAGE_CHILD) clear_damage(FL_DAMAGE_ALL);
499 
500     if (!box1) box1 = (Fl_Boxtype)(box()&-2);
501 
502     if ((widgetGlobals->indrag || mouseobj) && deltadir!=0) {
503       if (deltadir>0) {
504         draw_box(fl_down(box1),sxx,syy,sww,shh/2,color());
505         draw_box(box1,sxx,syy+shh/2,sww,shh/2,color());
506       }
507       else {
508         draw_box(box1,sxx,syy,sww,shh/2,color());
509         draw_box(fl_down(box1),sxx,syy+shh/2,sww,shh/2,color());
510       }
511     }
512     else {
513       draw_box(box1,sxx,syy,sww,shh/2,color());
514       draw_box(box1,sxx,syy+shh/2,sww,shh/2,color());
515     }
516     sxx+=border_size;
517     syy+=border_size;
518     sww-=border_size*2;
519     shh-=border_size*2;
520     if (active_r()) {
521       fl_color(selection_color());
522     }
523     else {
524       fl_color(selection_color() | 8);
525     }
526     int w1 = (sww-1)|1; // use odd sizes only
527     int X = sxx+w1/2;
528     int W = w1/3;
529     int h1 = shh/2-border_size-2;
530     int Y= syy;
531     fl_polygon(X, Y, X+W,Y+h1 , X-W, Y+h1);
532     Y=syy+shh/2+border_size+1+h1;
533     fl_polygon(X, Y, X-W, Y-h1, X+W, Y-h1);
534     clear_damage();
535 }
536 
repeat_callback(void * v)537 void Fl_Spin::repeat_callback(void* v)
538 {
539     Fl_Spin* b = (Fl_Spin*)v;
540     if (b->mouseobj) {
541       Fl::add_timeout(0.1, repeat_callback, b);
542       b->increment_cb();
543     }
544 }
545 
increment_cb(void)546 void Fl_Spin::increment_cb(void)
547 {
548     if (!mouseobj) return;
549     delta += deltadir;
550     double v;
551     switch (drag) {
552     case 3: v = increment(value(), deltadir*100); break;
553     case 2: v = increment(value(), deltadir*10); break;
554     default:v = increment(value(), deltadir); break;
555     }
556     v = round(v);
557     handle_drag(soft()?softclamp(v):clamp(v));
558 }
559 
handle(int event)560 int Fl_Spin::handle(int event)
561 {
562     double v;
563     int olddelta;
564     int mx = Fl::event_x();
565     int my = Fl::event_y();
566     int sxx = x(), syy = y(), sww = w(), shh = h();
567     WIDGET_GLOBALS *widgetGlobals =
568       (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS");
569 
570     switch (event) {
571     case FL_PUSH:
572       //    if (!step()) goto DEFAULT;
573       iy = my;
574       ix = mx;
575       drag = Fl::event_button();
576       handle_push();
577       widgetGlobals->indrag=1;
578       mouseobj=1;
579       Fl::add_timeout(0.5, repeat_callback, this);
580       delta=0;
581       if (Fl::event_inside(sxx,syy,sww,shh/2)) {
582         deltadir=1;
583       }
584       else if (Fl::event_inside(sxx,syy+shh/2,sww,shh/2)) {
585         deltadir=-1;
586       }
587       else {
588         deltadir=0;
589       }
590       increment_cb();
591       redraw();
592       return 1;
593     case FL_DRAG:
594       if (mouseobj) {
595         mouseobj=0;
596         Fl::remove_timeout(repeat_callback, this);
597       }
598       //    if (!step()) goto DEFAULT;
599       olddelta=delta;
600       delta = - (Fl::event_y()-iy);
601       if ((delta>5) || (delta<-5)) {
602         deltadir=((olddelta-delta)>0)?-1:(((olddelta-delta)<0)?1:0);
603       }
604       else {
605         deltadir=0; delta = olddelta;
606       }
607       switch (drag) {
608       case 3: v = increment(value(), deltadir*100); break;
609       case 2: v = increment(value(), deltadir*10); break;
610       default:v = increment(value(), deltadir); break;
611       }
612       v = round(v);
613       handle_drag(soft()?softclamp(v):clamp(v));
614       widgetGlobals->indrag=1;
615       return 1;
616     case FL_RELEASE:
617       if (mouseobj) {
618         Fl::remove_timeout(repeat_callback, this);
619       }
620       //    if (!step()) goto DEFAULT;
621       widgetGlobals->indrag=0;
622       delta=0;
623       deltadir=0;
624       mouseobj=0;
625       handle_release();
626       redraw();
627       return 1;
628     default:
629       widgetGlobals->indrag=0;
630       return Fl_Valuator::handle(event);
631     }
632 }
633 
~Fl_Spin(void)634 Fl_Spin::~Fl_Spin(void)
635 {
636     Fl::remove_timeout(repeat_callback, this);
637 }
638 
Fl_Spin(CSOUND * cs,int x,int y,int w,int h,const char * l)639 Fl_Spin::Fl_Spin(CSOUND *cs, int x, int y, int w, int h, const char* l)
640   : Fl_Valuator(x,y,w,h,l)
641 {
642 
643     csound = cs;
644     WIDGET_GLOBALS *widgetGlobals =
645       (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS");
646     soft_ = 0;
647     align(FL_ALIGN_LEFT);
648     ix=x;
649     iy=y;
650     drag=0;
651     widgetGlobals->indrag=0;
652     mouseobj = 0;
653     deltadir=0;
654     delta=0;
655     indrag=0;
656 }
657 
658 // ---- IV - Aug 23 2002 ---- included file: Fl_Value_Input_Spin.cpp
659 
input_cb(Fl_Widget *,void * v)660 void Fl_Value_Input_Spin::input_cb(Fl_Widget*, void* v)
661 {
662     Fl_Value_Input_Spin& t = *(Fl_Value_Input_Spin*)v;
663 
664     CSOUND *csound = t.csound;
665     WIDGET_GLOBALS *widgetGlobals =
666       (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS");
667     double nv;
668     if (t.step()>=1.0) nv = strtol(t.input.value(), 0, 0);
669     else nv = csound->strtod((char*)t.input.value(), 0);
670     widgetGlobals->hack_o_rama1 = 1;
671     t.handle_push();
672     t.handle_drag(nv);
673     t.handle_release();
674     widgetGlobals->hack_o_rama1 = 0;
675 }
676 
draw(void)677 void Fl_Value_Input_Spin::draw(void)
678 {
679     int sxx = x(), syy = y(), sww = w(), shh = h();
680     sxx += sww - buttonssize(); sww = buttonssize();
681     Fl_Boxtype box1 = (Fl_Boxtype)(box()&-2);
682     int border_size=Fl::box_dx(box());
683     WIDGET_GLOBALS *widgetGlobals =
684       (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS");
685 
686     if (damage()&~FL_DAMAGE_CHILD) input.clear_damage(FL_DAMAGE_ALL);
687     input.box(box());
688     input.color(FL_WHITE, selection_color());
689     input.redraw();
690     input.clear_damage();
691     sxx+=border_size;
692     syy+=border_size;
693     sww-=border_size*2;
694     shh-=border_size*2;
695 
696     if (!box1) box1 = (Fl_Boxtype)(box()&-2);
697 
698     if ((widgetGlobals->indrag || mouseobj) && deltadir!=0) {
699       if (deltadir>0) {
700         draw_box(fl_down(box1),sxx,syy,sww,shh/2,color());
701         draw_box(box1,sxx,syy+shh/2,sww,shh/2,color());
702       }
703       else {
704         draw_box(box1,sxx,syy,sww,shh/2,color());
705         draw_box(fl_down(box1),sxx,syy+shh/2,sww,shh/2,color());
706       }
707     }
708     else {
709       draw_box(box1,sxx,syy,sww,shh/2,color());
710       draw_box(box1,sxx,syy+shh/2,sww,shh/2,color());
711     }
712     sxx+=border_size;
713     syy+=border_size;
714     sww-=border_size*2;
715     shh-=border_size*2;
716     if (active_r()) {
717       fl_color(labelcolor());
718     }
719     else {
720       fl_color(labelcolor() | 8);
721     }
722     int w1 = (sww-1)|1; // use odd sizes only
723     int X = sxx+w1/2;
724     int W = w1/3;
725     int h1 = shh/2-border_size-2;
726     int Y= syy;
727     fl_polygon(X, Y, X+W,Y+h1 , X-W, Y+h1);
728     Y=syy+shh/2+border_size+1+h1;
729     fl_polygon(X, Y, X-W, Y-h1, X+W, Y-h1);
730     clear_damage();
731 }
732 
resize(int X,int Y,int W,int H)733 void Fl_Value_Input_Spin::resize(int X, int Y, int W, int H)
734 {
735     input.resize(X,Y,W,H);
736     Fl_Valuator::resize(X,Y,W,H);
737 }
738 
value_damage(void)739 void Fl_Value_Input_Spin::value_damage(void)
740 {
741     WIDGET_GLOBALS *widgetGlobals =
742       (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS");
743     if (widgetGlobals->hack_o_rama1) return;
744     char buf[128];
745     format(buf);
746     input.value(buf);
747     input.mark(input.position()); // turn off selection highlight
748 }
749 
repeat_callback(void * v)750 void Fl_Value_Input_Spin::repeat_callback(void* v)
751 {
752     Fl_Value_Input_Spin* b = (Fl_Value_Input_Spin*)v;
753     if (b->mouseobj) {
754       Fl::add_timeout(.1, repeat_callback, b);
755       b->increment_cb();
756     }
757 }
758 
increment_cb(void)759 void Fl_Value_Input_Spin::increment_cb(void)
760 {
761     if (!mouseobj) return;
762     delta+=deltadir;
763     double v;
764     switch (drag) {
765     case 3: v = increment(value(), deltadir*100); break;
766     case 2: v = increment(value(), deltadir*10); break;
767     default:v = increment(value(), deltadir); break;
768     }
769     v = round(v);
770     handle_drag(soft()?softclamp(v):clamp(v));
771 }
772 
handle(int event)773 int Fl_Value_Input_Spin::handle(int event)
774 {
775     double v;
776     int olddelta;
777     int mx = Fl::event_x();
778     int my = Fl::event_y();
779     int sxx = x(), syy = y(), sww = w(), shh = h();
780     sxx += sww - buttonssize(); sww = buttonssize();
781     WIDGET_GLOBALS *widgetGlobals =
782       (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS");
783 
784     if (!widgetGlobals->indrag &&
785         ( !widgetGlobals->sldrag || !((mx>=sxx && mx<=(sxx+sww)) &&
786                                       (my>=syy && my<=(syy+shh))))  ) {
787       widgetGlobals->indrag=0;
788       switch(event) {
789       case FL_PUSH:
790       case FL_DRAG:
791         widgetGlobals->sldrag=1;
792         break;
793       case FL_FOCUS:
794         input.take_focus();
795         break;
796       case FL_UNFOCUS:
797         redraw();
798         break;
799       default:
800         widgetGlobals->sldrag=0;
801       }
802       input.type(step()>=1.0 ? FL_INT_INPUT : FL_FLOAT_INPUT);
803       return input.handle(event);
804     }
805 
806     switch (event) {
807     case FL_PUSH:
808       //    if (!step()) goto DEFAULT;
809       iy = my;
810       ix = mx;
811       drag = Fl::event_button();
812       handle_push();
813       widgetGlobals->indrag=1;
814       mouseobj=1;
815       Fl::add_timeout(.5, repeat_callback, this);
816       delta=0;
817       if (Fl::event_inside(sxx,syy,sww,shh/2)) {
818         deltadir=1;
819       }
820       else if (Fl::event_inside(sxx,syy+shh/2,sww,shh/2)) {
821         deltadir=-1;
822       }
823       else {
824         deltadir=0;
825       }
826       increment_cb();
827       redraw();
828       return 1;
829     case FL_DRAG:
830       if (mouseobj) {
831         mouseobj=0;
832         Fl::remove_timeout(repeat_callback, this);
833       }
834       //    if (!step()) goto DEFAULT;
835       olddelta=delta;
836       delta = - (Fl::event_y()-iy);
837       if ((delta>5) || (delta<-5)  ) {
838         deltadir=((olddelta-delta)>0)?-1:(((olddelta-delta)<0)?1:0);
839       }
840       else {
841         deltadir=0; delta = olddelta;
842       }
843       switch (drag) {
844       case 3: v = increment(value(), deltadir*100); break;
845       case 2: v = increment(value(), deltadir*10); break;
846       default:v = increment(value(), deltadir); break;
847       }
848       v = round(v);
849       handle_drag(soft()?softclamp(v):clamp(v));
850       widgetGlobals->indrag=1;
851       return 1;
852     case FL_RELEASE:
853       if (mouseobj) {
854         Fl::remove_timeout(repeat_callback, this);
855       }
856       //    if (!step()) goto DEFAULT;
857       widgetGlobals->indrag=0;
858       delta=0;
859       deltadir=0;
860       mouseobj=0;
861       handle_release();
862       redraw();
863       return 1;
864     case FL_FOCUS:
865       widgetGlobals->indrag=0;
866       return input.take_focus();
867     default:
868       widgetGlobals->indrag=0;
869       input.type(step()>=1.0 ? FL_INT_INPUT : FL_FLOAT_INPUT);
870       return 1;
871     }
872 }
873 
~Fl_Value_Input_Spin(void)874 Fl_Value_Input_Spin::~Fl_Value_Input_Spin(void)
875 {
876     Fl::remove_timeout(repeat_callback, this);
877 }
878 
Fl_Value_Input_Spin(CSOUND * cs,int x,int y,int w,int h,const char * l)879 Fl_Value_Input_Spin::Fl_Value_Input_Spin(CSOUND * cs, int x, int y,
880                                          int w, int h, const char* l)
881   : Fl_Valuator(x,y,w,h,l), input(x, y, w, h, 0)
882 {
883     csound = cs;
884     WIDGET_GLOBALS *widgetGlobals =
885       (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS");
886     soft_ = 0;
887     //  if (input.parent())  // defeat automatic-add
888     //    ((Fl_Group*)input.parent())->remove(input);
889     //  input.parent(this); // kludge!
890     this->parent()->add(input);
891     input.callback(input_cb, this);
892     input.when(FL_WHEN_CHANGED);
893     selection_color(input.selection_color());
894     align(FL_ALIGN_LEFT);
895     box(input.box());
896     value_damage();
897     buttonssize(15);
898     ix       = x;
899     iy       = y;
900     drag     = 0;
901     widgetGlobals->indrag   = 0;
902     widgetGlobals->sldrag   = 0;
903     mouseobj = 0;
904     deltadir = 0;
905     delta    = 0;
906 }
907 
908 // ---- IV - Aug 23 2002 ---- included file: Fl_Value_Slider_Input.cpp
909 
input_cb(Fl_Widget *,void * v)910 void Fl_Value_Slider_Input::input_cb(Fl_Widget*, void* v) {
911     Fl_Value_Slider_Input& t = *(Fl_Value_Slider_Input*)v;
912     CSOUND *csound = t.csound;
913     WIDGET_GLOBALS *widgetGlobals =
914       (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS");
915     double nv;
916     if (t.step()>=1.0) nv = strtol(t.input.value(), 0, 0);
917     else nv = csound->strtod((char*)t.input.value(), 0);
918     widgetGlobals->hack_o_rama2 = 1;
919     t.handle_push();
920     t.handle_drag(nv);
921     t.handle_release();
922     widgetGlobals->hack_o_rama2 = 0;
923 }
924 
draw(void)925 void Fl_Value_Slider_Input::draw(void)
926 {
927     int sxx = x(), syy = y(), sww = w(), shh = h();
928     //int bww = w();
929     int X = x(), Y = y(), W = w(), H = h();
930 
931     int border_size=Fl::box_dx(box());
932 
933     if (horizontal()) {
934       //bww = textboxsize();
935       sxx += textboxsize(); sww -= textboxsize();
936       input.resize(X,Y,W-sww,shh);
937     }
938     else {
939       fl_font(input.textfont(), input.textsize());
940       syy += fl_height()+(border_size+1)*2; shh -= fl_height()+(border_size+1)*2;
941       input.resize(X,Y,W,H-shh);
942     }
943     if (damage()&~FL_DAMAGE_CHILD)  input.clear_damage(FL_DAMAGE_ALL);
944     input.box(box());
945     input.color(FL_WHITE, selection_color());
946     input.redraw();
947     input.resize(X,Y,W,H);
948     input.clear_damage();
949     //  if (horizontal())   input.draw();
950     clear_damage();
951     draw_box(box(),sxx,syy,sww,shh,color());
952     sxx+=border_size;
953     syy+=border_size;
954     sww-=border_size*2;
955     shh-=border_size*2;
956     if (border_size<2) {
957       sxx++;
958       syy++;
959       sww--;
960       shh--;
961     }
962     Fl_Slider::draw(sxx,syy,sww,shh);
963 }
964 
resize(int X,int Y,int W,int H)965 void Fl_Value_Slider_Input::resize(int X, int Y, int W, int H)
966 {
967     input.resize(X,Y,W,H);
968     Fl_Value_Slider::resize(X,Y,W,H);
969 }
970 
value_damage()971 void Fl_Value_Slider_Input::value_damage()
972 {
973     WIDGET_GLOBALS *widgetGlobals =
974       (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS");
975     if (widgetGlobals->hack_o_rama2) return;
976     char buf[128];
977     format(buf);
978     input.value(buf);
979     input.mark(input.position()); // turn off selection highlight
980 }
981 
handle(int event)982 int Fl_Value_Slider_Input::handle(int event)
983 {
984     int mx = Fl::event_x();
985     int my = Fl::event_y();
986     int sxx = x(), syy = y(), sww = w(), shh = h();
987     int border_size=Fl::box_dx(box());
988     WIDGET_GLOBALS *widgetGlobals =
989       (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS");
990     if (horizontal()) {
991       sxx += textboxsize(); sww -= textboxsize();
992     }
993     else {
994       fl_font(input.textfont(), input.textsize());
995       syy += fl_height()+(border_size+1)*2; shh -= fl_height()+(border_size+1)*2;
996     }
997     if ( !widgetGlobals->indrag &&
998          ( !widgetGlobals->sldrag || !((mx>=sxx && mx<=(sxx+sww)) &&
999                                        (my>=syy && my<=(syy+shh))))  ) {
1000       widgetGlobals->indrag=0;
1001       switch(event) {
1002       case FL_PUSH:
1003       case FL_DRAG:
1004         widgetGlobals->sldrag=1;
1005         break;
1006       case FL_FOCUS:
1007         input.take_focus();
1008         break;
1009       case FL_UNFOCUS:
1010         redraw();
1011         break;
1012       default:
1013         widgetGlobals->sldrag=0;
1014       }
1015       input.type(step()>=1.0 ? FL_INT_INPUT : FL_FLOAT_INPUT);
1016       return input.handle(event);
1017     }
1018     switch (event) {
1019     case FL_PUSH:
1020       widgetGlobals->ix = mx;
1021       widgetGlobals->drag = Fl::event_button();
1022       widgetGlobals->indrag=1;
1023       return Fl_Slider::handle(event,sxx,syy,sww,shh);
1024     case FL_DRAG:
1025       widgetGlobals->indrag=1;
1026       return Fl_Slider::handle(event,sxx,syy,sww,shh);
1027     case FL_RELEASE:
1028       //   if (!step()) goto DEFAULT;
1029       if (value() != previous_value() || !Fl::event_is_click())
1030         handle_release();
1031       else {
1032         input.handle(FL_PUSH);
1033         input.handle(FL_RELEASE);
1034       }
1035       widgetGlobals->indrag=0;
1036       return 1;
1037     case FL_FOCUS:
1038       widgetGlobals->indrag=0;
1039       input.take_focus();
1040       return Fl_Slider::handle(event,sxx,syy,sww,shh);
1041     default:
1042       widgetGlobals->indrag=0;
1043       input.type(step()>=1.0 ? FL_INT_INPUT : FL_FLOAT_INPUT);
1044       input.handle(event);
1045       return Fl_Slider::handle(event,sxx,syy,sww,shh);
1046     }
1047 }
1048 
Fl_Value_Slider_Input(CSOUND * cs,int x,int y,int w,int h,const char * l)1049 Fl_Value_Slider_Input::Fl_Value_Slider_Input(CSOUND *cs, int x, int y,
1050                                              int w, int h, const char* l)
1051   : Fl_Value_Slider(x,y,w,h,l),input(x, y, w, h, 0)
1052 {
1053     csound = cs;
1054     soft_ = 0;
1055     // if (input.parent())  // defeat automatic-add
1056     // ((Fl_Group*)input.parent())->remove(input);
1057     // input.parent(this); // kludge!
1058     // input.callback(input_cb, this);
1059     parent()->add(input);
1060     //  input.when(FL_WHEN_CHANGED | FL_WHEN_ENTER_KEY);
1061     input.when(FL_WHEN_CHANGED );
1062     selection_color(input.selection_color());
1063     input.align(FL_ALIGN_LEFT);
1064     align(FL_ALIGN_LEFT);
1065     textboxsize(35);
1066     value_damage();
1067 }
1068 
1069 // ---- IV - Aug 23 2002 ---- end of included files
1070 
1071 //static char *GetString(CSOUND *csound, MYFLT *pname, int is_string);
1072 
1073 //---------------
1074 
set_butbank_value(Fl_Group * o,MYFLT value)1075 static void set_butbank_value(Fl_Group *o, MYFLT value)
1076 {
1077     int       childr = o->children();
1078     Fl_Button *b;
1079     int       ival = (int) value, j, label;
1080 
1081     if (ival < 0 || ival >= childr || (MYFLT) ival != value)
1082       return;
1083     for (j = 0; j < childr; j++) {
1084       b = (Fl_Button *) o->child(j);
1085       label = atoi(b->label());
1086       if (label == ival) {
1087         b->value(1);
1088         b->do_callback();
1089       }
1090       else
1091         b->value(0);
1092     }
1093 }
1094 
FLlock()1095 inline void FLlock() { //gab
1096     Fl::lock();
1097 }
1098 
FLunlock()1099 inline void FLunlock() { //gab
1100     Fl::unlock();
1101     Fl::awake((void*) 0);
1102 }
1103 
SNAPSHOT(vector<ADDR_SET_VALUE> & valuators,int snapGroup)1104 SNAPSHOT::SNAPSHOT (vector<ADDR_SET_VALUE>& valuators, int snapGroup)
1105 { // the constructor captures current values of all widgets
1106   // by copying all current values from "valuators" vector (AddrSetValue)
1107   // to the "fields" vector
1108     is_empty = 0;
1109     FLlock(); //<=================
1110     int i,k;
1111     int vsize  = valuators.size();
1112     for (i = 0, k = 0; i < vsize && k < vsize; i++, k++) {
1113       while (valuators[k].group != snapGroup ) {
1114         k++;
1115         if (UNLIKELY(k >=vsize)) goto err;
1116       }
1117       ADDR_SET_VALUE& v  = valuators[k];
1118       CSOUND *csound = (CSOUND*) (((OPDS *) (v.opcode))->insdshead->csound);
1119       string  opcode_name, widg_name;
1120       fields.resize(i+1);
1121       if ((int) fields.size() < i+1)
1122         fields.resize(i+1);
1123       VALUATOR_FIELD* fld = &(fields[i]);
1124       float val, min, max;
1125       opcode_name = fld->opcode_name = ((OPDS *) (v.opcode))->optext->t.opcod;
1126       if (UNLIKELY(opcode_name.c_str() == NULL))
1127         {
1128           csound->InitError(csound, "%s",
1129                             Str("Invalid snapshot. Perhaps you modified "
1130                                 "orchestra widget code after you saved "
1131                                 "the snapshot bank."));
1132           goto err;
1133         }
1134       else if (opcode_name == "FLslider") {
1135         FLSLIDER *p = (FLSLIDER *) (v.opcode);
1136         fld->widg_name = p->name->data;
1137         fld->exp = (int) *p->iexp;
1138         min = fld->min = *p->imin; max = fld->max = *p->imax;
1139         switch (fld->exp) {
1140         case LIN_:
1141         case EXP_:
1142           val = *p->kout;
1143           if (min < max) {
1144             if (val < min) val=min;
1145             else if(val>max) val=max;
1146           }
1147           else {
1148             if (val < max) val=max;
1149             else if(val>min) val=min;
1150           }
1151           break;
1152         default: val = ((Fl_Valuator *)v.WidgAddress)->value();
1153         }
1154         fld->value = val;
1155       }
1156       else if (opcode_name == "FLslidBnk" || opcode_name == "FLvslidBnk") {
1157         FLSLIDERBANK *p = (FLSLIDERBANK *) (v.opcode);
1158         fld->widg_name = ((STRINGDAT *)p->names)->data;
1159         int numsliders = (int) *p->inumsliders;
1160         fld->sldbnk = p->slider_data;
1161         //   fld->sldbnkValues = new MYFLT[numsliders];
1162         //   widgetGlobals->allocatedStrings.push_back((char *) fld->sldbnkValues);
1163         fld->exp = numsliders; // EXCEPTIONAL CASE! fld->exp contains the number
1164         // of sliders and not the exponential flag
1165         for (int j =0; j < numsliders; j++) {
1166           switch (fld->sldbnk[j].exp) {
1167           case LIN_: case EXP_:
1168             val = *fld->sldbnk[j].out;
1169             min = fld->sldbnk[j].min; max = fld->sldbnk[j].max;
1170             if (min < max) {
1171               if (val < min) val=min;
1172               else if(val>max) val=max;
1173             }
1174             else {
1175               if (val < max) val=max;
1176               else if(val>min) val=min;
1177             }
1178             break;
1179           default:
1180             val = ((Fl_Valuator *) ((Fl_Group*)v.WidgAddress)->
1181                    child(j))->value();
1182           }
1183           fld->set_sldbnk(j, val);
1184         }
1185       }
1186       else if (opcode_name == "FLslidBnk2" || opcode_name == "FLvslidBnk2") {
1187         FLSLIDERBANK2 *p = (FLSLIDERBANK2 *) (v.opcode);
1188         fld->widg_name = ((STRINGDAT *)p->names)->data;
1189         int numsliders = (int) *p->inumsliders;
1190         fld->sldbnk = p->slider_data;
1191         // EXCEPTIONAL CASE! fld->exp contains the number of sliders
1192         // and not the exponential flag
1193         fld->exp = numsliders;
1194         for (int j =0; j < numsliders; j++) {
1195           switch (fld->sldbnk[j].exp) {
1196           case LIN_: case EXP_:
1197             val = *fld->sldbnk[j].out;
1198             min = fld->sldbnk[j].min; max = fld->sldbnk[j].max;
1199             if (min < max) {
1200               if (val < min) val=min;
1201               else if(val>max) val=max;
1202             }
1203             else {
1204               if (val < max) val=max;
1205               else if(val>min) val=min;
1206             }
1207             break;
1208           default:
1209             val = ((Fl_Valuator *) ((Fl_Group*) v.WidgAddress)->child(j))->value();
1210           }
1211           fld->set_sldbnk(j, val);
1212         }
1213       }
1214       else if (opcode_name == "FLknob") {
1215         FLKNOB *p = (FLKNOB *) (v.opcode);
1216         fld->widg_name = p->name->data;
1217         fld->exp = (int) *p->iexp;
1218         min = fld->min = *p->imin; max = fld->max = *p->imax;
1219         switch (fld->exp) {
1220         case LIN_:
1221         case EXP_:
1222           val = *p->kout;
1223           if (min < max) {
1224             if (val < min) val=min;
1225             else if(val>max) val=max;
1226           }
1227           else {
1228             if (val < max) val=max;
1229             else if(val>min) val=min;
1230           }
1231           break;
1232         default: val = ((Fl_Valuator *)v.WidgAddress)->value();
1233         }
1234         fld->value = val;
1235       }
1236       else if (opcode_name == "FLroller") {
1237         FLROLLER *p = (FLROLLER *) (v.opcode);
1238         fld->widg_name = p->name->data;
1239         fld->exp = (int) *p->iexp;
1240         min = fld->min = *p->imin; max = fld->max = *p->imax;
1241         switch (fld->exp) {
1242         case LIN_:
1243         case EXP_:
1244           val = *p->kout;
1245           if (min < max) {
1246             if (val < min) val=min;
1247             else if(val>max) val=max;
1248           }
1249           else {
1250             if (val < max) val=max;
1251             else if(val>min) val=min;
1252           }
1253           break;
1254         default: val = ((Fl_Valuator *)v.WidgAddress)->value();
1255         }
1256         fld->value = val;
1257       }
1258       else if (opcode_name == "FLtext") {
1259         FLTEXT *p = (FLTEXT *) (v.opcode);
1260         fld->widg_name = p->name->data;
1261         val = *p->kout; min = fld->min = *p->imin; max = fld->max = *p->imax;
1262         if (min < max) {
1263           if (val < min) val=min;
1264           else if(val>max) val=max;
1265         }
1266         else {
1267           if (val < max) val=max;
1268           else if(val>min) val=min;
1269         }
1270         fld->value = val;
1271         fld->exp = LIN_;
1272       }
1273       else if (opcode_name == "FLjoy") {
1274         FLJOYSTICK *p = (FLJOYSTICK *) (v.opcode);
1275         fld->widg_name = p->name->data;
1276         fld->exp  = (int) *p->iexpx;
1277         min = fld->min = *p->iminx; max = fld->max = *p->imaxx;
1278         switch (fld->exp) {
1279         case LIN_:
1280         case EXP_:
1281           val = *p->koutx;
1282           if (min < max) {
1283             if (val < min) val=min;
1284             else if(val>max) val=max;
1285           }
1286           else {
1287             if (val < max) val=max;
1288             else if(val>min) val=min;
1289           }
1290           break;
1291         default:
1292           val = ((Fl_Positioner *)v.WidgAddress)->xvalue();
1293         }
1294         fld->value = val;
1295         fld->exp2 = (int) *p->iexpy;
1296         min = fld->min2 = *p->iminy; max = fld->max2 = *p->imaxy;
1297         switch (fld->exp2) {
1298         case LIN_: case EXP_:
1299           val = *p->kouty;
1300           if (min < max) {
1301             if (val < min) val=min;
1302             else if(val>max) val=max;
1303           }
1304           else {
1305             if (val < max) val=max;
1306             else if(val>min) val=min;
1307           }
1308           break;
1309         default:
1310           val = ((Fl_Positioner *)v.WidgAddress)->yvalue();
1311         }
1312         fld->value2 =val;
1313       }
1314       else if (opcode_name == "FLbutton") {
1315         FLBUTTON *p = (FLBUTTON *) (v.opcode);
1316         fld->widg_name =  p->name->data;
1317         fld->value = *p->kout;
1318         fld->min = 0; fld->max = 1; fld->exp = LIN_;
1319       }
1320       else if (opcode_name == "FLbutBank") {
1321         FLBUTTONBANK *p = (FLBUTTONBANK *) (v.opcode);
1322         fld->widg_name =  Str("No name for FLbutbank");
1323         //fld->widg_name = GetString(csound, p->name, p->XSTRCODE);
1324         fld->value = *p->kout;
1325         fld->min = 0; fld->max = 1; fld->exp = LIN_;
1326       }
1327       else if (opcode_name == "FLcount") {
1328         FLCOUNTER *p = (FLCOUNTER *) (v.opcode);
1329         fld->widg_name = p->name->data;
1330         val = *p->kout; min = *p->imin; max =*p->imax;
1331         if (min != max) {
1332           if (val < min) val=min;
1333           else if (val>max) val=max;
1334         }
1335         fld->value = val;
1336         fld->min = *p->imin; fld->max = *p->imax; fld->exp = LIN_;
1337       }
1338       else if (opcode_name == "FLvalue") {
1339         FLVALUE *p = (FLVALUE *) (v.opcode);
1340         fld->widg_name = p->name->data;
1341       }
1342       else if (opcode_name == "FLbox") {
1343         FL_BOX *p = (FL_BOX *) (v.opcode);
1344         fld->widg_name = p->itext->data;
1345       }
1346     }
1347      FLunlock();
1348      return;
1349  err:
1350     FLunlock(); //<=================
1351     is_empty = 1;
1352 }
1353 
get(vector<ADDR_SET_VALUE> & valuators,int snapGroup)1354 int SNAPSHOT::get(vector<ADDR_SET_VALUE>& valuators, int snapGroup)
1355 {
1356     if (UNLIKELY(is_empty == 1)) {
1357       /*  FIXME: should have CSOUND* pointer here */
1358       /*  return csound->InitError(csound, "%s", Str("empty snapshot")); */
1359       //printf("SNAPSHOT IS EMPTY\n");
1360       return -1;
1361     }
1362     FLlock(); //<=================
1363     int j,k;
1364     int siz =valuators.size();
1365     for (j = 0, k = 0; j< siz && k < siz; j++, k++) {
1366       //     int grp = valuators[k].group; //Not used
1367       while (valuators[k].group != snapGroup) {
1368         k++;
1369         if (k >= (int) valuators.size()) goto end_func;
1370       }
1371       Fl_Widget* o = (Fl_Widget*) (valuators[k].WidgAddress);
1372       void *opcode = valuators[k].opcode;
1373 //CSOUND *csound = (CSOUND*) (((OPDS*) opcode)->insdshead->csound); //Not used
1374       VALUATOR_FIELD* fld = &fields[j];
1375       string opcode_name = fld->opcode_name;
1376 
1377       MYFLT val = fld->value, valtab = fld->value, min=fld->min,
1378         max=fld->max, range,base;
1379       if (min < max) {
1380         if (val < min) val = min;
1381         else if (val >max) val = max;
1382       }
1383       else {
1384         if (val < max) val=max;
1385         else if(val>min) val=min;
1386       }
1387 
1388       if (opcode_name == "FLjoy") {
1389         switch(fld->exp) {
1390         case LIN_:
1391           ((Fl_Positioner*) o)->xvalue(val);
1392           break;
1393         case EXP_:
1394           range  = fld->max - fld->min;
1395           #if defined(sun)
1396             base = ::pow(fld->max / (double)fld->min, 1.0/(double)range);
1397           #else
1398             base = ::pow(fld->max / fld->min, 1.0/(double)range);
1399           #endif
1400           ((Fl_Positioner*) o)->xvalue(log(val/fld->min) / log(base)) ;
1401           break;
1402         default:
1403           ((Fl_Positioner*) o)->xvalue(valtab);
1404           break;
1405         }
1406         val = fld->value2; min = fld->min2; max = fld->max2;
1407         //       if (val < min) val = min;
1408         //       else if (val >max) val = max;
1409         switch(fld->exp2) {
1410         case LIN_:
1411           ((Fl_Positioner*) o)->yvalue(val);
1412           break;
1413         case EXP_:
1414           range  = fld->max2 - fld->min2;
1415           #if defined(sun)
1416             base = ::pow(fld->max2 / (double)fld->min2, 1.0/(double)range);
1417           #else
1418             base = ::pow(fld->max2 / fld->min2, 1.0/(double)range);
1419           #endif
1420           ((Fl_Positioner*) o)->yvalue(log(val/fld->min2) / log(base)) ;
1421           break;
1422         default:
1423           ((Fl_Positioner*) o)->yvalue(valtab);
1424           break;
1425         }
1426         o->do_callback(o, opcode);
1427       }
1428       else if (opcode_name == "FLbutton") {
1429         FLBUTTON *p = (FLBUTTON*) (opcode);
1430         //  don't allow to retreive its value if >= 10 or between 21 and 29
1431         if ((*p->itype < 10) || (*p->itype < 30 && *p->itype > 20)) {
1432           if(fld->value >= *p->ioff - 0.0001 &&
1433              fld->value <= *p->ioff + 0.0001)  // to avoid eventual  math rounding
1434             ((Fl_Button*) o)->value(0);
1435           else
1436             if (fld->value >= *p->ion - 0.0001 &&
1437                 fld->value <= *p->ion + 0.0001) // to avoid eventual math rounding
1438               ((Fl_Button*) o)->value(1);
1439             else
1440               ((Fl_Button*) o)->value((int)fld->value);
1441           o->do_callback(o, opcode);
1442         }
1443       }
1444       else if (opcode_name == "FLbutBank") {
1445         FLBUTTONBANK *p = (FLBUTTONBANK*) (opcode);
1446         if (*p->itype < 10 || (*p->itype < 30 && *p->itype > 20)) {
1447           //  don't allow to retreive its value if >= 10
1448           //((Fl_Group*) o)->value(fld->value);
1449           set_butbank_value((Fl_Group*) o, fld->value);
1450           //o->do_callback(o, opcode);
1451           *p->kout=fld->value;
1452           if (*p->args[0] >= 0) ButtonSched(p->h.insdshead->csound,
1453                                             p->args, p->INOCOUNT-7);
1454         }
1455       }
1456       else if (opcode_name == "FLcount") {
1457         FLCOUNTER *p = (FLCOUNTER*) (opcode);
1458         if (*p->itype < 10 || (*p->itype < 30 && *p->itype > 20)) {
1459           //  don't allow to retreive its value if >= 10
1460           ((Fl_Counter*) o)->value(fld->value);
1461           o->do_callback(o, opcode);
1462         }
1463       }
1464       else if (opcode_name == "FLslidBnk" || opcode_name == "FLvslidBnk") {
1465         FLSLIDERBANK *p = (FLSLIDERBANK*) (opcode);
1466         int numsliders = (int) *p->inumsliders;
1467         Fl_Group * grup = (Fl_Group *) o;
1468         for (int j =0; j < numsliders; j++) {
1469           MYFLT val = fld->get_sldbnk(j);
1470           switch (p->slider_data[j].exp) {
1471           case LIN_:
1472             ((Fl_Valuator *) grup->child(j))->value(val);
1473             break;
1474           case EXP_:
1475             range  = p->slider_data[j].max - p->slider_data[j].min;
1476             #if defined(sun)
1477               base = ::pow(p->slider_data[j].max / (double)p->slider_data[j].min,
1478                            1.0/(double)range);
1479             #else
1480               base = ::pow(p->slider_data[j].max / p->slider_data[j].min,
1481                            1.0/(double)range);
1482             #endif
1483             ((Fl_Valuator*) grup->child(j))->
1484               value(log(val/p->slider_data[j].min) / log(base)) ;
1485             break;
1486           default:// TABLE the value must be in the 0 to 1 range...
1487             val = (val - fld->min ) / (fld->max - fld->min);
1488             ((Fl_Valuator *) grup->child(j))->value(val);
1489             break;
1490           }
1491           grup->child(j)->do_callback( grup->child(j),
1492                                        (void *) &(p->slider_data[j]));
1493         }
1494       }
1495       else if (opcode_name == "FLslidBnk2" || opcode_name == "FLvslidBnk2") {
1496         FLSLIDERBANK2 *p = (FLSLIDERBANK2*) (opcode);
1497         int numsliders = (int) *p->inumsliders;
1498         Fl_Group * grup = (Fl_Group *) o;
1499         for (int j =0; j < numsliders; j++) {
1500           MYFLT val = fld->get_sldbnk(j);
1501           switch (p->slider_data[j].exp) {
1502           case LIN_:
1503             ((Fl_Valuator *) grup->child(j))->value(val);
1504             break;
1505           case EXP_:
1506             range  = p->slider_data[j].max - p->slider_data[j].min;
1507             base = pow(p->slider_data[j].max / p->slider_data[j].min, 1/range);
1508             ((Fl_Valuator*) grup->child(j))->value(log(val/p->slider_data[j].min) /
1509                                                    log(base)) ;
1510             break;
1511           default:// TABLE the value must be in the 0 to 1 range...
1512             val = (val - fld->min ) / (fld->max - fld->min);
1513             ((Fl_Valuator *) grup->child(j))->value(val);
1514             break;
1515           }
1516           grup->child(j)->do_callback( grup->child(j),
1517                                        (void *) &(p->slider_data[j]));
1518         }
1519       }
1520       else {
1521         switch(fld->exp) {
1522         case LIN_:
1523           if (opcode_name == "FLbox" || opcode_name == "FLvalue" ) continue;
1524           else if (opcode_name == "FLtext" &&
1525                    *((FLTEXT *)opcode)->itype == 1) {
1526             ((Fl_Valuator*) o)->value(val);
1527             continue;
1528           }
1529           ((Fl_Valuator*) o)->value(val);
1530           break;
1531         case EXP_:
1532           range  = fld->max - fld->min;
1533           #if defined(sun)
1534             base = ::pow(fld->max / (double)fld->min, 1.0/(double)range);
1535           #else
1536             base = ::pow(fld->max / fld->min, 1.0/(double)range);
1537           #endif
1538           ((Fl_Valuator*) o)->value(log(val/fld->min) / log(base)) ;
1539           break;
1540         default: // TABLE the value must be in the 0 to 1 range...
1541           ((Fl_Valuator*) o)->value(valtab);
1542           break;
1543         }
1544         o->do_callback(o, opcode);
1545       }
1546     }
1547  end_func:
1548     FLunlock(); //<=================
1549     return OK;
1550 }
1551 
1552 extern "C" {
1553 
set_snap(CSOUND * csound,FLSETSNAP * p)1554   static int set_snap(CSOUND *csound, FLSETSNAP *p)
1555   {
1556       WIDGET_GLOBALS *widgetGlobals =
1557         (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS");
1558       SNAPSHOT snap(widgetGlobals->AddrSetValue, (int) *p->group );
1559       int numfields = snap.fields.size();
1560       int index = (int) *p->index;
1561       int group = (int) *p->group;
1562       SNAPVEC snapvec_init;
1563       SNAPSHOT snap_init;
1564 
1565       snap_init.fields.resize(1,VALUATOR_FIELD());
1566       snapvec_init.resize(1,snap_init);
1567       if (group+1 > (int) widgetGlobals->snapshots.size())
1568         widgetGlobals->snapshots.resize(group+1, snapvec_init);
1569       // *p->inum_snap = widgetGlobals->snapshots.size();
1570       *p->inum_val = numfields; // number of snapshots
1571       if (*p->ifn >= 1) { // if the table number is valid
1572         FUNC    *ftp;   // store the snapshot into the table
1573         if (LIKELY((ftp = csound->FTnp2Finde(csound, p->ifn)) != NULL)) {
1574           MYFLT *table = ftp->ftable;
1575           for (int j = 0; j < numfields; j++) {
1576             table[index*numfields+j] = snap.fields[j].value;
1577           }
1578         }
1579         else return csound->InitError(csound,
1580                                       "%s", Str("FLsetsnap: invalid table"));
1581       }
1582       else { // else store it into snapshot bank
1583         if ((int) widgetGlobals->snapshots[group].size() < index+1)
1584           widgetGlobals->snapshots[group].resize(index+1);
1585         csound->Message(csound, "%s", Str("setsnap saving\n"));
1586         widgetGlobals->snapshots[group][index]=snap;
1587         *p->inum_snap = widgetGlobals->snapshots[group].size();
1588       }
1589       return OK;
1590   }
1591 
get_snap(CSOUND * csound,FLGETSNAP * p)1592   static int get_snap(CSOUND *csound, FLGETSNAP *p)
1593   {
1594       int index = (int) *p->index;
1595       int group = (int) *p->group;
1596       SNAPVEC snapvec_init;
1597       SNAPSHOT snap_init;
1598       WIDGET_GLOBALS *widgetGlobals =
1599         (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS");
1600       snap_init.fields.resize(1,VALUATOR_FIELD());
1601       snapvec_init.resize(1,snap_init);
1602       if (group+1 > (int) widgetGlobals->snapshots.size())
1603         widgetGlobals->snapshots.resize(group+1, snapvec_init);
1604       if (!widgetGlobals->snapshots[group].empty()) {
1605         if (index >= (int) widgetGlobals->snapshots[group].size())
1606           index = widgetGlobals->snapshots[group].size()-1;
1607         else if (index < 0) index=0;
1608         if (widgetGlobals->snapshots[group][index].get(widgetGlobals->AddrSetValue,
1609                                                        (int) *p->group)!=OK) {
1610           csound->Warning(csound, "could not get snapshot from group %d index %d \n",
1611                           group, index);
1612           return OK;
1613         }
1614       }
1615       *p->inum_el = widgetGlobals->snapshots[group].size();
1616       return OK;
1617   }
1618 
save_snap(CSOUND * csound,FLSAVESNAPS * p)1619   static int save_snap(CSOUND *csound, FLSAVESNAPS *p)
1620   {
1621       char    s[MAXNAME], *s2;
1622       string  filename;
1623 #ifdef WIN32
1624       int id = MessageBox(NULL, Str("Saving could overwrite the old file.\n"
1625                                     "Are you sure to save ?"), Str("Warning"),
1626                           MB_SYSTEMMODAL | MB_ICONWARNING | MB_OKCANCEL);
1627       if (id != IDOK)
1628         return OK;
1629 #else
1630 #  if !defined(NO_FLTK_THREADS)
1631       if (!((getFLTKFlags(csound) & 260) ^ 4))
1632 #  endif
1633         {
1634           int   n;
1635           Fl_lock(csound);
1636           n = fl_choice("%s", Str("Saving could overwrite the old file.\n"
1637                                   "Are you sure you want to save ?"),
1638                         Str("No"), Str("Yes"), (const char*)""); // used to be NULL
1639           Fl_unlock(csound);
1640           if (!n)
1641             return OK;
1642         }
1643 #endif
1644       csound->strarg2name(csound, s, p->filename->data, "snap.", 1);
1645       s2 = csound->FindOutputFile(csound, s, "SNAPDIR");
1646       if (UNLIKELY(s2 == NULL))
1647         return csound->InitError(csound,"%s",
1648                                  Str("FLsavesnap: cannot open file"));
1649       strncpy(s, s2, MAXNAME-1);
1650       csound->Free(csound, s2);
1651       filename = s;
1652 
1653       fstream file(filename.c_str(), ios::out);
1654       int group = (int) *p->group;
1655       WIDGET_GLOBALS *widgetGlobals =
1656         (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS");
1657       for (int j =0; j < (int) widgetGlobals->snapshots[group].size(); j++) {
1658         file << "----------- "<< j << " -----------\n";
1659         int siz = widgetGlobals->snapshots[group][j].fields.size();
1660         for ( int k = 0; k < siz; k++) {
1661           VALUATOR_FIELD& f = widgetGlobals->snapshots[group][j].fields[k];
1662           //      if (f.group != group) continue;
1663           if (f.opcode_name == "FLjoy") {
1664             file <<f.opcode_name<<" "<< f.value <<" "<< f.value2
1665                  <<" "<< f.min <<" "<< f.max <<" "<< f.min2 <<" "
1666                  << f.max2<<" "<<f.exp<<" "<<f.exp2<<" \"" <<f.widg_name<<"\"\n";
1667           }
1668           else if (f.opcode_name == "FLslidBnk"  ||
1669                    f.opcode_name == "FLvslidBnk" ||
1670                    f.opcode_name == "FLslidBnk2" ||
1671                    f.opcode_name == "FLvslidBnk2") {
1672             file << f.opcode_name << " " << f.exp
1673                  << " "; // EXCEPTIONAL CASE! fld.exp contains the
1674             //number of sliders and not the exponential flag
1675             for (int i=0; i < f.exp; i++) {
1676               file << f.get_sldbnk(i) << " ";
1677             }
1678             file << " \"" << f.widg_name << "\"\n";
1679           }
1680           else {
1681             const char *s = f.opcode_name.c_str();
1682             if (*s != '\0') {
1683               file <<f.opcode_name<<" "<< f.value
1684                    <<" "<< f.min <<" "<< f.max <<" "<<f.exp
1685                    <<" \"" <<f.widg_name<<"\"\n";
1686             }
1687           }
1688         }
1689       }
1690       file << "---------------------------";
1691       file.close();
1692       return OK;
1693   }
1694 
load_snap(CSOUND * csound,FLLOADSNAPS * p)1695   static int load_snap(CSOUND *csound, FLLOADSNAPS* p)
1696   {
1697       char     s[MAXNAME], *s2;
1698       string   filename;
1699       WIDGET_GLOBALS *widgetGlobals =
1700         (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS");
1701       csound->strarg2name(csound, s, p->filename->data, "snap.", 1);
1702       s2 = csound->FindInputFile(csound, s, "SNAPDIR");
1703       if (UNLIKELY(s2 == NULL))
1704         return csound->InitError(csound,
1705                                  "%s", Str("FLloadsnap: cannot open file"));
1706       strncpy(s, s2, MAXNAME-1);
1707       csound->Free(csound, s2);
1708       filename = s;
1709 
1710       fstream file(filename.c_str(), ios::in);
1711       int group = (int) *p->group;
1712       int j=0,k=-1,q=0;
1713       SNAPVEC snapvec_init;
1714       SNAPSHOT snap_init;
1715       snap_init.fields.resize(1,VALUATOR_FIELD());
1716       snapvec_init.resize(1,snap_init);
1717       if (group+1 > (int) widgetGlobals->snapshots.size())
1718         widgetGlobals->snapshots.resize(group+1, snapvec_init);
1719       while (!(file.eof())) {
1720         char buf[MAXNAME];
1721         file.getline(buf,MAXNAME-1);
1722 
1723         stringstream sbuf;
1724         sbuf << buf;
1725 
1726         string opc, opc_orig;
1727         getline(sbuf, opc, ' ');
1728         const char *ss = opc.c_str();
1729         if (*ss == '-') { // if it is a separation line
1730           k++; j=0; q=0;
1731           if ((int) widgetGlobals->snapshots[group].size() < k+1)
1732             widgetGlobals->snapshots[group].resize(k+1);
1733         }
1734         else if (*ss != '\0' && *ss != ' ' && *ss != '\n'){ //ignore blank lines
1735           ADDR_SET_VALUE* v = &(widgetGlobals->AddrSetValue[q]);
1736           while (widgetGlobals->AddrSetValue[q].group != group) {
1737             q++;
1738             if (q >= (int) widgetGlobals->AddrSetValue.size()) continue;
1739             v = &(widgetGlobals->AddrSetValue[q]);
1740           }
1741           if (k<0) return NOTOK;
1742           if ((int) widgetGlobals->snapshots[group][k].fields.size() < j+1)
1743             widgetGlobals->snapshots[group][k].fields.resize(j+1);
1744           widgetGlobals->snapshots[group][k].is_empty = 0;
1745           VALUATOR_FIELD& fld = widgetGlobals->snapshots[group][k].fields[j];
1746           opc_orig = ((OPDS *) (v->opcode))->optext->t.opcod;
1747 
1748           if (UNLIKELY(!(opc_orig == opc))) {
1749             //return csound->InitError(csound,
1750             csound->Message(csound,
1751                             "%s", Str("unmatched widget, probably due to a "
1752                                 "modified orchestra. Modifying an "
1753                                 "orchestra makes it incompatible with "
1754                                 "old snapshot files"));
1755           }
1756           else if (opc == "FLjoy") {
1757             fld.opcode_name = opc;
1758             string s;
1759             getline(sbuf,s, ' ');  fld.value  = atof(s.c_str());
1760             getline(sbuf,s, ' ');  fld.value2 = atof(s.c_str());
1761             getline(sbuf,s, ' ');  fld.min    = atof(s.c_str());
1762             getline(sbuf,s, ' ');  fld.max    = atof(s.c_str());
1763             getline(sbuf,s, ' ');  fld.min2   = atof(s.c_str());
1764             getline(sbuf,s, ' ');  fld.max2   = atof(s.c_str());
1765             getline(sbuf,s, ' ');  fld.exp    = atoi(s.c_str());
1766             getline(sbuf,s, ' ');  fld.exp2   = atoi(s.c_str());
1767             getline(sbuf,s, '\"');
1768             getline(sbuf,s, '\"');  fld.widg_name = s;
1769           }
1770           else if (opc == "FLslidBnk"  || opc == "FLvslidBnk"
1771                    || opc == "FLslidBnk2" || opc == "FLvslidBnk2" ) {
1772             fld.opcode_name = opc;
1773             string s;
1774             getline(sbuf,s, ' ');
1775             // EXCEPTIONAL CASE! fld.exp contains the number of sliders
1776             // and not the exponential flag
1777             fld.exp = atoi(s.c_str());
1778             // fld.sldbnkValues = new MYFLT[fld.exp];
1779             // fld.insert_sldbnk(fld.exp);
1780             // allocatedStrings.push_back((char *) fld.sldbnkValues);
1781             // widgetGlobals->allocatedStrings.push_back((char *) fld.sldbnkValues);
1782 
1783             for (int kk =0; kk < fld.exp; kk++) {
1784               getline(sbuf,s, ' ');
1785               //           fld.sldbnkValues[kk] = atof(s.c_str());
1786               fld.set_sldbnk(kk,atof(s.c_str()));
1787 
1788             }
1789             getline(sbuf,s, '\"');
1790             getline(sbuf,s, '\"');  fld.widg_name = s;
1791           }
1792           else {
1793             fld.opcode_name = opc;
1794             string s;
1795             getline(sbuf,s, ' ');  fld.value = atof(s.c_str());
1796             getline(sbuf,s, ' ');  fld.min = atof(s.c_str());
1797             getline(sbuf,s, ' ');  fld.max = atof(s.c_str());
1798             getline(sbuf,s, ' ');  fld.exp = atoi(s.c_str());
1799             getline(sbuf,s, '\"');
1800             getline(sbuf,s, '\"');  fld.widg_name = s;
1801           }
1802           j++; q++;
1803         }
1804       }
1805 
1806       file.close();
1807       return OK;
1808   }
1809 
1810   static int fltkKeyboardCallback(void *, void *, unsigned int);
1811 
1812 }       // extern "C"
1813 
1814 // -----------
1815 
1816 /* unused
1817 static char *GetString(CSOUND *csound, MYFLT *pname, int is_string)
1818 {
1819     char    *Name = new char[MAXNAME];
1820     WIDGET_GLOBALS *widgetGlobals =
1821       (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS");
1822     widgetGlobals->allocatedStrings.push_back(Name);
1823     return csound->strarg2name(csound, Name, pname, "", is_string);
1824 }
1825 */
1826 
1827 class CsoundFLTKKeyboardBuffer {
1828 private:
1829   CSOUND  *csound;
1830   WIDGET_GLOBALS *widgetGlobals;
1831   void    *mutex_;
1832   char    kbdTextBuf[64];
1833   int     kbdEvtBuf[64];
1834   int     kbdTextBufRPos;
1835   int     kbdTextBufWPos;
1836   int     kbdEvtBufRPos;
1837   int     kbdEvtBufWPos;
1838   std::map<int, unsigned char> keyboardState;
lockMutex()1839   void lockMutex()
1840   {
1841       if (mutex_)
1842         csound->LockMutex(mutex_);
1843   }
unlockMutex()1844   void unlockMutex()
1845   {
1846       if (mutex_)
1847         csound->UnlockMutex(mutex_);
1848   }
1849 public:
CsoundFLTKKeyboardBuffer(CSOUND * csound)1850   CsoundFLTKKeyboardBuffer(CSOUND *csound)
1851   {
1852       this->csound = csound;
1853       widgetGlobals =
1854         (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS");
1855       mutex_ = csound->Create_Mutex(0);
1856       kbdTextBufRPos = 0;
1857       kbdTextBufWPos = 0;
1858       kbdEvtBufRPos = 0;
1859       kbdEvtBufWPos = 0;
1860   }
~CsoundFLTKKeyboardBuffer()1861   ~CsoundFLTKKeyboardBuffer()
1862   {
1863       if (mutex_) {
1864         csound->DestroyMutex(mutex_);
1865         mutex_ = (void*) 0;
1866       }
1867   }
GetCsound()1868   CSOUND *GetCsound()
1869   {
1870       return csound;
1871   }
writeFLEvent(int evt)1872   void writeFLEvent(int evt)
1873   {
1874       const char  *s;
1875       int     keyCode;
1876       keyCode = (int) Fl::event_key() & (int) 0xFFFF;
1877       if (keyCode) {
1878         lockMutex();
1879         if (evt == FL_KEYDOWN) {
1880           s = Fl::event_text();
1881           while (*s != (char) 0) {
1882             kbdTextBuf[kbdTextBufWPos] = *(s++);
1883             kbdTextBufWPos = (kbdTextBufWPos + 1) & 63;
1884           }
1885           if (keyboardState[keyCode] == (unsigned char) 0) {
1886             keyboardState[keyCode] = (unsigned char) 1;
1887             kbdEvtBuf[kbdEvtBufWPos] = keyCode;
1888             kbdEvtBufWPos = (kbdEvtBufWPos + 1) & 63;
1889           }
1890         }
1891         else if (keyboardState[keyCode] != (unsigned char) 0) {
1892           keyboardState[keyCode] = (unsigned char) 0;
1893           kbdEvtBuf[kbdEvtBufWPos] = keyCode | (int) 0x10000;
1894           kbdEvtBufWPos = (kbdEvtBufWPos + 1) & 63;
1895         }
1896         unlockMutex();
1897       }
1898   }
getKeyboardText()1899   int getKeyboardText()
1900   {
1901       int     retval = 0;
1902       lockMutex();
1903       if (kbdTextBufRPos != kbdTextBufWPos) {
1904         retval = (int) ((unsigned char) kbdTextBuf[kbdTextBufRPos]);
1905         kbdTextBufRPos = (kbdTextBufRPos + 1) & 63;
1906       }
1907       unlockMutex();
1908       return retval;
1909   }
getKeyboardEvent()1910   int getKeyboardEvent()
1911   {
1912       int     retval = 0;
1913       lockMutex();
1914       if (kbdEvtBufRPos != kbdEvtBufWPos) {
1915         retval = kbdEvtBuf[kbdEvtBufRPos];
1916         kbdEvtBufRPos = (kbdEvtBufRPos + 1) & 63;
1917       }
1918       unlockMutex();
1919       return retval;
1920   }
1921 };
1922 
1923 class CsoundFLWindow : public Fl_Double_Window {
1924 public:
1925   CSOUND *csound_; //gab
1926   WIDGET_GLOBALS *widgetGlobals;
1927   CsoundFLTKKeyboardBuffer  fltkKeyboardBuffer;
CsoundFLWindow(CSOUND * csound,int w,int h,const char * title=0)1928   CsoundFLWindow(CSOUND *csound, int w, int h, const char *title = 0)
1929     : Fl_Double_Window(w, h, title),
1930       csound_(csound),
1931       fltkKeyboardBuffer(csound)//gab
1932   {
1933       widgetGlobals =
1934         (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS");
1935       csound->Set_KeyCallback(csound, fltkKeyboardCallback, (void*) this,
1936                               CSOUND_CALLBACK_KBD_EVENT | CSOUND_CALLBACK_KBD_TEXT);
1937   }
CsoundFLWindow(CSOUND * csound,int x,int y,int w,int h,const char * title=0)1938   CsoundFLWindow(CSOUND *csound,
1939                  int x, int y, int w, int h, const char *title = 0)
1940     : Fl_Double_Window(x, y, w, h, title),
1941       csound_(csound),
1942       fltkKeyboardBuffer(csound)//gab
1943   {
1944       widgetGlobals =
1945         (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS");
1946       csound->Set_KeyCallback(csound, fltkKeyboardCallback, (void*) this,
1947                               CSOUND_CALLBACK_KBD_EVENT | CSOUND_CALLBACK_KBD_TEXT);
1948   }
~CsoundFLWindow()1949   virtual ~CsoundFLWindow()
1950   {
1951       CSOUND  *csound = fltkKeyboardBuffer.GetCsound();
1952       csound->Remove_KeyCallback(csound, fltkKeyboardCallback);
1953   }
handle(int evt)1954   virtual int handle(int evt)
1955   {
1956       switch (evt) {
1957       case FL_FOCUS:
1958         Fl::focus(this);
1959         /* FALLTHRU */
1960       case FL_UNFOCUS:
1961         return 1;
1962       case FL_KEYDOWN:
1963         widgetGlobals->last_KEY = Fl::event_key(); //gab
1964         widgetGlobals->isKeyDown = true;  //gab
1965         break;
1966       case FL_KEYUP:
1967         widgetGlobals->last_KEY = Fl::event_key(); //gab
1968         widgetGlobals->isKeyDown = false; //gab
1969         if (Fl::focus() == this)
1970           fltkKeyboardBuffer.writeFLEvent(evt);
1971         break;
1972       }
1973       return Fl_Window::handle(evt);
1974   }
1975 };
1976 
1977 extern "C"
1978 {
fltkKeyboardCallback(void * userData,void * p,unsigned int type)1979   static int fltkKeyboardCallback(void *userData, void *p, unsigned int type)
1980   {
1981       switch (type) {
1982       case CSOUND_CALLBACK_KBD_EVENT:
1983         *((int*) p) =
1984           ((CsoundFLWindow*) userData)->fltkKeyboardBuffer.getKeyboardEvent();
1985         break;
1986       case CSOUND_CALLBACK_KBD_TEXT:
1987         *((int*) p) =
1988           ((CsoundFLWindow*) userData)->fltkKeyboardBuffer.getKeyboardText();
1989         break;
1990       default:
1991         return 1;
1992       }
1993       return 0;
1994   }
1995 
csoundModuleDestroy(CSOUND * csound)1996   PUBLIC int csoundModuleDestroy(CSOUND *csound)
1997   {
1998       int j;
1999       WIDGET_GLOBALS *widgetGlobals =
2000         (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS");
2001 #ifndef NO_FLTK_THREADS
2002       int *fltkflags = getFLTKFlagsPtr(csound);
2003       if (fltkflags) {
2004         if ((*fltkflags & 260) ^ 4) {
2005           widgetsGlobals_t *p =
2006             (widgetsGlobals_t*) csound->QueryGlobalVariable(csound,
2007                                                             "_widgets_globals");
2008           if (p) {
2009             if (!(*fltkflags & 256)) {
2010               /* if window(s) still open: */
2011               if (!p->exit_now) {
2012                 /* notify GUI thread... */
2013                 p->end_of_perf = -1;
2014                 Fl_lock(csound);
2015                 Fl_awake(csound);
2016                 Fl_unlock(csound);
2017                 /* ...and wait for it to close */
2018                 csound->JoinThread(p->threadHandle);
2019                 p->threadHandle = NULL;
2020               }
2021             }
2022             /* clean up */
2023             csound->LockMutex(p->mutex_);
2024             while (p->eventQueue != NULL) {
2025               rtEvt_t *nxt = p->eventQueue->nxt;
2026               free(p->eventQueue);
2027               p->eventQueue = nxt;
2028             }
2029             csound->UnlockMutex(p->mutex_);
2030             csound->DestroyMutex(p->mutex_);
2031             csound->DestroyGlobalVariable(csound, "_widgets_globals");
2032           }
2033         }
2034       }
2035 #endif  // NO_FLTK_THREADS
2036       if(widgetGlobals != NULL) {
2037         for (j = widgetGlobals->allocatedStrings.size() - 1; j >= 0; j--)  {
2038           delete[] widgetGlobals->allocatedStrings[j];
2039           widgetGlobals->allocatedStrings.pop_back();
2040         }
2041         j = widgetGlobals->fl_windows.size();
2042         if (j > 0) {
2043           // destroy all opened panels
2044           do {
2045             j--;
2046             if (widgetGlobals->fl_windows[j].is_subwindow == 0)
2047               delete widgetGlobals->fl_windows[j].panel;
2048             // VL: this might leak memory, needs checking.
2049             widgetGlobals->fl_windows.pop_back();
2050           } while (j);
2051           Fl_wait_locked(csound, 0.0);
2052         }
2053         widgetGlobals->AddrStack.~vector<ADDR_STACK>();
2054         widgetGlobals->allocatedStrings.~vector<char*>();
2055         widgetGlobals->fl_windows.~vector<PANELS>();
2056         for (size_t si = 0, sn = widgetGlobals->snapshots.size(); si < sn; ++si) {
2057           SNAPVEC &svec = widgetGlobals->snapshots[si];
2058           int ss = svec.size();
2059           for (j = 0; j < ss; j++) {
2060             svec[j].fields.erase(svec[j].fields.begin(),
2061                                  svec[j].fields.end());
2062             // VL: probably leaks memory, needs checking.
2063             svec.resize(svec.size() + 1);
2064           }
2065         }
2066         widgetGlobals->AddrSetValue.clear();  // VL: leaks memory, needs fixing.
2067         widgetGlobals->stack_count       = 0;
2068         widgetGlobals->FLcontrol_iheight = 15;
2069         widgetGlobals->FLroller_iheight  = 18;
2070         widgetGlobals->FLcontrol_iwidth  = 400;
2071         widgetGlobals->FLroller_iwidth   = 150;
2072         widgetGlobals->FLvalue_iwidth    = 100;
2073         widgetGlobals->FLcolor           = -1;
2074         widgetGlobals->FLcolor2          = -1;
2075         widgetGlobals->FLtext_size       = 0;
2076         widgetGlobals->FLtext_color      = -1;
2077         widgetGlobals->FLtext_font       = -1;
2078         widgetGlobals->FLtext_align      = 0;
2079         widgetGlobals->FL_ix             = 10;
2080         widgetGlobals->FL_iy             = 10;
2081 
2082         //delete (WIDGET_GLOBALS*)csound->widgetGlobals;
2083         csound->DestroyGlobalVariable(csound, "WIDGET_GLOBALS");
2084         //csound->widgetGlobals = NULL;
2085       }
2086       return 0;
2087   }
2088 } // extern "C"
2089 
2090 //-----------
2091 
2092 #ifndef NO_FLTK_THREADS
2093 
2094 extern "C" {
2095 
fltkRun(void * userdata)2096   static uintptr_t fltkRun(void *userdata)
2097   {
2098       volatile widgetsGlobals_t *p;
2099       CSOUND    *csound = (CSOUND*) userdata;
2100       int       j;
2101       WIDGET_GLOBALS *widgetGlobals =
2102         (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS");
2103       p = (widgetsGlobals_t*) csound->QueryGlobalVariable(csound,
2104                                                           "_widgets_globals");
2105 #ifdef LINUX
2106       {
2107         struct sched_param  sp;
2108         // IV - Aug 27 2002: widget thread is always run with normal priority
2109         memset(&sp, 0, sizeof(struct sched_param));
2110         pthread_setschedparam(pthread_self(), SCHED_OTHER, &sp);
2111       }
2112 #endif
2113 
2114       if (!(p->fltkFlags & 8))
2115         Fl::lock();
2116       for (j = 0; j < (int) widgetGlobals->fl_windows.size(); j++) {
2117         widgetGlobals->fl_windows[j].panel->show();
2118       }
2119 // #ifdef CS_VSTHOST
2120 //       for (size_t k=0; k < widgetGlobals->VSTplugEditors.size(); k++) {
2121 //         int panelNum = widgetGlobals->VSTplugEditors[k]->targetFLpanel;
2122 // #ifdef WIN32
2123 //         HWND xid = fl_xid(widgetGlobals->fl_windows[panelNum].panel);
2124 //         widgetGlobals->VSTplugEditors[k]->SetEditWindow(xid);
2125 // #elif defined (LINUX) || defined(MACOSX)
2126 //         // put some appropriate alternative code here
2127 //         Fl_Window * xid =
2128 //           fl_find(fl_xid(widgetGlobals->fl_windows[panelNum].panel));
2129 //         widgetGlobals->VSTplugEditors[k]->SetEditWindow(xid);
2130 // #endif  // WIN32
2131 //       }
2132 // #endif  // CS_VSTHOST
2133       if (!(p->fltkFlags & 16))
2134         Fl::awake();
2135       if (!(p->fltkFlags & 8))
2136         Fl::unlock();
2137       do {
2138         if (!(p->fltkFlags & 8))
2139           Fl::lock();
2140         Fl::wait(0.02);
2141         j = (Fl::first_window() != (Fl_Window*) 0);
2142         if (!(p->fltkFlags & 8))
2143           Fl::unlock();
2144       } while (j && !p->end_of_perf);
2145       csound->Message(csound, "%s", Str("end of widget thread\n"));
2146       // IV - Jun 07 2005: exit if all windows are closed
2147       p->exit_now = -1;
2148       return (uintptr_t) 0;
2149   }
2150 
2151 }   // extern "C"
2152 
2153 #endif  // NO_FLTK_THREADS
2154 
2155 extern "C" {
2156 
2157   int CsoundYield_FLTK(CSOUND *csound);
2158 
FL_run(CSOUND * csound,FLRUN * p)2159   int FL_run(CSOUND *csound, FLRUN *p)
2160   {
2161     IGN(p);
2162       int     *fltkFlags;
2163       WIDGET_GLOBALS *widgetGlobals =
2164         (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS");
2165       fltkFlags = getFLTKFlagsPtr(csound);
2166       (*fltkFlags) |= 32;
2167 #ifndef NO_FLTK_THREADS
2168       if (((*fltkFlags) & 260) ^ 4) {
2169         widgetsGlobals_t  *pp;
2170 
2171         if (UNLIKELY(csound->QueryGlobalVariable(csound,
2172                                                  "_widgets_globals") != NULL))
2173           return csound->InitError(csound, "%s", Str("FLrun was already called"));
2174         if (UNLIKELY(csound->CreateGlobalVariable(csound, "_widgets_globals",
2175                                                   sizeof(widgetsGlobals_t)) != 0))
2176           csound->Die(csound, "%s", Str("FL_run: memory allocation failure"));
2177         pp = (widgetsGlobals_t*) csound->QueryGlobalVariable(csound,
2178                                                              "_widgets_globals");
2179         pp->fltkFlags = *fltkFlags;
2180         /* create thread lock */
2181         pp->mutex_ = csound->Create_Mutex(0);
2182         /* register callback function to be called by sensevents() */
2183         csound->RegisterSenseEventCallback(csound, (void (*)(CSOUND *, void *))
2184                                            evt_callback,
2185                                            (void*) pp);
2186         if (!((*fltkFlags) & 256)) {
2187           pp->threadHandle = csound->CreateThread(fltkRun, (void*) csound);
2188           return OK;
2189         }
2190       }
2191 #endif  // NO_FLTK_THREADS
2192       {
2193         int j;
2194 
2195         Fl_lock(csound);
2196         for (j = 0; j < (int) widgetGlobals->fl_windows.size(); j++) {
2197           widgetGlobals->fl_windows[j].panel->show();
2198         }
2199         Fl_wait(csound, 0.0);
2200         Fl_unlock(csound);
2201 
2202 
2203         if (!((*fltkFlags) & 256))
2204           csound->SetInternalYieldCallback(csound, CsoundYield_FLTK);
2205       }
2206       return OK;
2207   }
2208 
fl_update(CSOUND * csound,FLRUN * p)2209   int fl_update(CSOUND *csound, FLRUN *p)
2210   {
2211      IGN(p);
2212     WIDGET_GLOBALS *widgetGlobals =
2213         (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS");
2214       Fl_lock(csound);
2215       for (int j=0; j< (int) widgetGlobals->AddrSetValue.size()-1; j++) {
2216         ADDR_SET_VALUE v = widgetGlobals->AddrSetValue[j];
2217         Fl_Valuator *o = (Fl_Valuator *) v.WidgAddress;
2218         o->do_callback(o, v.opcode);
2219       }
2220       Fl_unlock(csound);
2221       return OK;
2222   }
2223 }       // extern "C"
2224 
2225 //----------------------------------------------
2226 
displ(MYFLT val,MYFLT index,CSOUND * csound)2227 static inline void displ(MYFLT val, MYFLT index, CSOUND *csound)
2228 {
2229     WIDGET_GLOBALS *widgetGlobals =
2230       (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS");
2231     if (index >= 0) {     // display current value of valuator
2232       char valString[MAXNAME];
2233       sprintf(valString, "%.5g", val);
2234       ((Fl_Output*) (widgetGlobals->AddrSetValue[(long) index]).WidgAddress)->
2235         value(valString);
2236     }
2237 }
2238 
fl_callbackButton1(Fl_Button * w,void * a)2239 static void fl_callbackButton1(Fl_Button* w, void *a)
2240 {
2241     IGN(w);
2242     FLBUTTON *p = (FLBUTTON *) a;
2243     *((FLBUTTON*) a)->kout =  *p->ion;
2244     if (*p->args[0] >= 0) ButtonSched(p->h.insdshead->csound,
2245                                       p->args, p->INOCOUNT-8);
2246 }
2247 
fl_callbackCloseButton(Fl_Button * w,void * a)2248 static void fl_callbackCloseButton(Fl_Button* w, void *a)
2249 {
2250     IGN(w);
2251     Fl_Window *p = (Fl_Window *) a;
2252     p->hide();
2253 }
2254 
fl_callbackExecButton(Fl_Button * w,void * a)2255 static void fl_callbackExecButton(Fl_Button* w, void *a)
2256 {
2257     IGN(w);
2258     FLEXECBUTTON *p = (FLEXECBUTTON *)a;
2259     CSOUND *csound = p->csound;
2260     char *command = (char *)csound->Malloc(csound, strlen(p->commandString) + 1);
2261 
2262 #if defined(LINUX) || defined (MACOSX)
2263 
2264 
2265     pid_t pId = vfork();
2266     if (pId == 0) {
2267       char *th;
2268       char *v[40];
2269       int i = 0;
2270 
2271       strcpy(command, p->commandString);
2272 
2273       char *tok = csound->strtok_r(command,(char *) " ", &th);
2274 
2275       if(tok != NULL) {
2276         v[i++] = tok;
2277         while((tok = csound->strtok_r(NULL,(char *) " ", &th)) != NULL) {
2278           v[i++] = tok;
2279         }
2280         v[i] = NULL;
2281         execvp(v[0], v);
2282       }
2283 
2284       _exit(0);
2285     } else if (UNLIKELY(pId < 0)) {
2286       p->csound->Message(p->csound,
2287                          "%s", Str("Error: Unable to fork process\n"));
2288     }
2289 
2290     csound->Free(csound, command);
2291 #elif defined(WIN32)
2292     {
2293 #undef strtok_r // undefine from pthread.h on Windows
2294       char *th;
2295       char *v[40];
2296       int i = 0;
2297 
2298       strcpy(command, p->commandString);
2299       char *tok = csound->strtok_r(command,(char *) " ", &th);
2300 
2301       if(tok != NULL) {
2302         v[i++] = tok;
2303         while((tok = csound->strtok_r(NULL,(char *) " ", &th)) != NULL) {
2304           v[i++] = tok;
2305         }
2306         v[i] = NULL;
2307         csound->Free(csound, command); // Otherwise will lose space
2308         if (UNLIKELY(csound->RunCommand(v, 1)<0))
2309           p->csound->Message(p->csound, "%s",
2310                              Str("Error: Unable to fork process\n"));
2311       }
2312     }
2313 #endif
2314 }
2315 
fl_callbackButton(Fl_Button * w,void * a)2316 static void fl_callbackButton(Fl_Button* w, void *a)
2317 {
2318     FLBUTTON *p = (FLBUTTON *) a;
2319     *((FLBUTTON*) a)->kout =  (w->value()) ? *p->ion : *p->ioff;
2320     if (*p->args[0] >= 0) ButtonSched(p->h.insdshead->csound,
2321                                       p->args, p->INOCOUNT-8);
2322 }
2323 
fl_callbackButtonBank(Fl_Button * w,void * a)2324 static void fl_callbackButtonBank(Fl_Button* w, void *a)
2325 {
2326     FLBUTTONBANK *p = (FLBUTTONBANK *) a;
2327     *((FLBUTTONBANK*) a)->kout = (MYFLT) atoi(w->label());
2328     if (*p->args[0] >= 0) ButtonSched(p->h.insdshead->csound,
2329                                       p->args, p->INOCOUNT-7);
2330 }
2331 
fl_callbackCounter(Fl_Counter * w,void * a)2332 static void fl_callbackCounter(Fl_Counter* w, void *a)
2333 {
2334     FLCOUNTER *p = (FLCOUNTER *) a;
2335     *((FLCOUNTER*) a)->kout =  w->value();
2336     if (*p->args[0] >= 0) ButtonSched(p->h.insdshead->csound,
2337                                       p->args, p->INOCOUNT-10);
2338 }
2339 
fl_callbackLinearSlider(Fl_Valuator * w,void * a)2340 static void fl_callbackLinearSlider(Fl_Valuator* w, void *a)
2341 {
2342     FLSLIDER *p = ((FLSLIDER*) a);
2343     displ(*p->kout = w->value(), *p->idisp, p->h.insdshead->csound);
2344 }
2345 
fl_callbackExponentialSlider(Fl_Valuator * w,void * a)2346 static void fl_callbackExponentialSlider(Fl_Valuator* w, void *a)
2347 {
2348     FLSLIDER *p = ((FLSLIDER*) a);
2349     #if defined(sun)
2350       displ(*p->kout = p->min * ::pow ((double)p->base, w->value()),
2351             *p->idisp, p->h.insdshead->csound);
2352     #else
2353       displ(*p->kout = p->min * ::pow (p->base, w->value()),
2354             *p->idisp, p->h.insdshead->csound);
2355     #endif
2356 }
2357 
fl_callbackInterpTableSlider(Fl_Valuator * w,void * a)2358 static void fl_callbackInterpTableSlider(Fl_Valuator* w, void *a)
2359 {
2360     FLSLIDER *p = ((FLSLIDER*) a);
2361     MYFLT ndx = w->value() * (p->tablen-1);
2362     int index = (int) ndx;
2363     MYFLT v1 = p->table[index];
2364     displ(*p->kout = p->min+ ( v1 + (p->table[index+1] - v1) *
2365                                (ndx - index)) * (*p->imax - p->min),
2366           *p->idisp, p->h.insdshead->csound);
2367 }
2368 
fl_callbackTableSlider(Fl_Valuator * w,void * a)2369 static void fl_callbackTableSlider(Fl_Valuator* w, void *a)
2370 {
2371     FLSLIDER *p = ((FLSLIDER*) a);
2372     displ(*p->kout = p->min+ p->table[(long) (w->value() * p->tablen)] *
2373           (*p->imax - p->min),
2374           *p->idisp, p->h.insdshead->csound);
2375 }
2376 
fl_callbackLinearSliderBank(Fl_Valuator * w,void * a)2377 static void fl_callbackLinearSliderBank(Fl_Valuator* w, void *a)
2378 {
2379     SLDBK_ELEMENT* p = (SLDBK_ELEMENT*) a;
2380     *p->out = w->value();
2381 }
2382 
fl_callbackExponentialSliderBank(Fl_Valuator * w,void * a)2383 static void fl_callbackExponentialSliderBank(Fl_Valuator* w, void *a)
2384 {
2385     SLDBK_ELEMENT* p = (SLDBK_ELEMENT*) a;
2386     #if defined(sun)
2387       *p->out = p->min * ::pow ((double)p->base, w->value());
2388     #else
2389       *p->out = p->min * ::pow (p->base, w->value());
2390     #endif
2391 }
2392 
fl_callbackInterpTableSliderBank(Fl_Valuator * w,void * a)2393 static void fl_callbackInterpTableSliderBank(Fl_Valuator* w, void *a)
2394 {
2395     SLDBK_ELEMENT *p = ((SLDBK_ELEMENT*) a);
2396 
2397     MYFLT ndx = w->value() * (p->tablen-1);
2398     int index = (int) ndx;
2399     MYFLT v1 = p->table[index];
2400     *p->out = p->min + ( v1 + (p->table[index+1] - v1) * (ndx - index)) *
2401       (p->max - p->min);
2402 }
2403 
fl_callbackTableSliderBank(Fl_Valuator * w,void * a)2404 static void fl_callbackTableSliderBank(Fl_Valuator* w, void *a)
2405 {
2406     SLDBK_ELEMENT *p = ((SLDBK_ELEMENT*) a);
2407     *p->out = p->min + p->table[(long)(w->value() * p->tablen)] *
2408       (p->max - p->min);
2409 }
2410 
fl_callbackJoystick(Fl_Widget * w,void * a)2411 static void fl_callbackJoystick(Fl_Widget* w, void *a)
2412 {
2413     FLJOYSTICK *p = (FLJOYSTICK*) a;
2414     Fl_Positioner *j = (Fl_Positioner*) w;
2415     MYFLT val;
2416     int iexpx = (int) *p->iexpx, iexpy = (int) *p->iexpy;
2417     switch (iexpx) {
2418     case LIN_:
2419       val = j->xvalue();
2420       break;
2421     case EXP_:
2422       #if defined(sun)
2423         val = *p->iminx * ::pow ((double)p->basex, j->xvalue());
2424       #else
2425         val = *p->iminx * ::pow (p->basex, j->xvalue());
2426       #endif
2427       break;
2428     default:
2429       if (iexpx > 0) { //interpolated
2430         MYFLT ndx = j->xvalue() * (p->tablenx-1);
2431         int index = (int) ndx;
2432         MYFLT v1 = p->tablex[index];
2433         val = *p->iminx + ( v1 + (p->tablex[index+1] - v1) *
2434                             (ndx - index)) * (*p->imaxx - *p->iminx);
2435       }
2436       else // non-interpolated
2437         val = *p->iminx+ p->tablex[(long) (j->xvalue() * p->tablenx)] *
2438           (*p->imaxx - *p->iminx);
2439     }
2440     displ(*p->koutx = val,*p->idispx, p->h.insdshead->csound);
2441     switch (iexpy) {
2442     case LIN_:
2443       val = j->yvalue();
2444       break;
2445     case EXP_:
2446       #if defined(sun)
2447         val = *p->iminy * ::pow ((double)p->basey, j->yvalue());
2448       #else
2449         val = *p->iminy * ::pow (p->basey, j->yvalue());
2450       #endif
2451       break;
2452     default:
2453       if (iexpy > 0) { //interpolated
2454         MYFLT ndx = j->yvalue() * (p->tableny-1);
2455         long index = (long) ndx;
2456         MYFLT v1 = p->tabley[index];
2457         val = *p->iminy + ( v1 + (p->tabley[index+1] - v1) * (ndx - index))
2458           * (*p->imaxy - *p->iminy);
2459       }
2460       else { // non-interpolated
2461         long index = (long) (j->yvalue()* p->tableny);
2462         val = *p->iminy+ p->tabley[index] * (*p->imaxy - *p->iminy);
2463 
2464       }
2465     }
2466     displ(*p->kouty = val, *p->idispy, p->h.insdshead->csound);
2467 }
2468 
fl_callbackLinearRoller(Fl_Valuator * w,void * a)2469 static void fl_callbackLinearRoller(Fl_Valuator* w, void *a)
2470 {
2471     FLROLLER *p = ((FLROLLER*) a);
2472     displ(*p->kout =  w->value(),*p->idisp, p->h.insdshead->csound);
2473 }
2474 
fl_callbackExponentialRoller(Fl_Valuator * w,void * a)2475 static void fl_callbackExponentialRoller(Fl_Valuator* w, void *a)
2476 {
2477     FLROLLER *p = ((FLROLLER*) a);
2478     #if defined(sun)
2479       displ(*p->kout = ((FLROLLER*) a)->min * ::pow ((double)p->base, w->value()),
2480             *p->idisp, p->h.insdshead->csound);
2481     #else
2482       displ(*p->kout = ((FLROLLER*) a)->min * ::pow (p->base, w->value()),
2483             *p->idisp, p->h.insdshead->csound);
2484     #endif
2485 }
2486 
fl_callbackInterpTableRoller(Fl_Valuator * w,void * a)2487 static void fl_callbackInterpTableRoller(Fl_Valuator* w, void *a)
2488 {
2489     FLROLLER *p = ((FLROLLER*) a);
2490     MYFLT ndx = w->value() * (p->tablen-1);
2491     int index = (int) ndx;
2492     MYFLT v1 = p->table[index];
2493     displ(*p->kout = p->min+ ( v1 + (p->table[index+1] - v1) * (ndx - index)) *
2494           (*p->imax - p->min), *p->idisp, p->h.insdshead->csound);
2495 }
2496 
fl_callbackTableRoller(Fl_Valuator * w,void * a)2497 static void fl_callbackTableRoller(Fl_Valuator* w, void *a)
2498 {
2499     FLROLLER *p = ((FLROLLER*) a);
2500     displ(*p->kout = p->min+ p->table[(long) (w->value() * p->tablen)] *
2501           (*p->imax - p->min), *p->idisp, p->h.insdshead->csound);
2502 }
2503 
fl_callbackLinearKnob(Fl_Valuator * w,void * a)2504 static void fl_callbackLinearKnob(Fl_Valuator* w, void *a)
2505 {
2506     FLKNOB *p = ((FLKNOB*) a);
2507     displ( *p->kout = w->value(), *p->idisp, p->h.insdshead->csound);
2508 }
2509 
fl_callbackExponentialKnob(Fl_Valuator * w,void * a)2510 static void fl_callbackExponentialKnob(Fl_Valuator* w, void *a)
2511 {
2512     FLKNOB *p = ((FLKNOB*) a);
2513     #if defined(sun)
2514       displ(*p->kout = ((FLKNOB*) a)->min * ::pow ((double)p->base, w->value()),
2515             *p->idisp, p->h.insdshead->csound);
2516     #else
2517       displ(*p->kout = ((FLKNOB*) a)->min * ::pow (p->base, w->value()),
2518             *p->idisp, p->h.insdshead->csound);
2519     #endif
2520 }
2521 
fl_callbackInterpTableKnob(Fl_Valuator * w,void * a)2522 static void fl_callbackInterpTableKnob(Fl_Valuator* w, void *a)
2523 {
2524     FLKNOB *p = ((FLKNOB*) a);
2525     MYFLT ndx = w->value() * (p->tablen-1);
2526     int index = (int) ndx;
2527     MYFLT v1 = p->table[index];
2528     displ(*p->kout = p->min+ ( v1 + (p->table[index+1] - v1) * (ndx - index)) *
2529           (*p->imax - p->min), *p->idisp, p->h.insdshead->csound);
2530 }
2531 
fl_callbackTableKnob(Fl_Valuator * w,void * a)2532 static void fl_callbackTableKnob(Fl_Valuator* w, void *a)
2533 {
2534     FLKNOB *p = ((FLKNOB*) a);
2535     displ(*p->kout = p->min+ p->table[(long) (w->value() * p->tablen)] *
2536           (*p->imax - p->min), *p->idisp, p->h.insdshead->csound);
2537 }
2538 
fl_callbackLinearValueInput(Fl_Valuator * w,void * a)2539 static void fl_callbackLinearValueInput(Fl_Valuator* w, void *a)
2540 {
2541     *((FLTEXT*) a)->kout =  w->value();
2542 }
2543 
2544 //-----------
2545 
rand_31_i(CSOUND * csound,int maxVal)2546 static int rand_31_i(CSOUND *csound, int maxVal)
2547 {
2548     int seed = csound->GetRandSeed(csound,2);
2549     double  x = (double) (csound->Rand31(&seed) - 1);
2550     return (int) (x * (double) (maxVal + 1) / 2147483646.0);
2551 }
2552 
widget_attributes(CSOUND * csound,Fl_Widget * o)2553 static void widget_attributes(CSOUND *csound, Fl_Widget *o)
2554 {
2555     WIDGET_GLOBALS *widgetGlobals =
2556       (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS");
2557     if (widgetGlobals->FLtext_size == -2 ) {
2558       widgetGlobals->FLtext_size = -1;
2559       widgetGlobals->FLtext_color= -1;
2560       widgetGlobals->FLtext_font = -1;
2561       widgetGlobals->FLtext_align= -1;
2562       widgetGlobals->FLcolor = -1;
2563     }
2564     if (widgetGlobals->FLtext_size > 0)
2565       // if > 0 assign it, else skip, leaving default
2566       o->labelsize(widgetGlobals->FLtext_size);
2567     switch ((int) widgetGlobals->FLtext_color) {
2568     case -2: // random color
2569       o->labelcolor(fl_rgb_color(rand_31_i(csound, 255), rand_31_i(csound, 255),
2570                                  rand_31_i(csound, 255)));
2571       break;
2572     case -1:
2573       // if FLtext_color is == -1, color assignment is skipped,
2574       // leaving default color
2575       break;
2576     default:
2577       o->labelcolor(widgetGlobals->FLtext_color);
2578       break;
2579     }
2580     if (widgetGlobals->FLtext_font> 0) {
2581       Fl_Font font;
2582       if (widgetGlobals->FLtext_font<0 ||
2583           widgetGlobals->FLtext_font>16) font = FL_HELVETICA;
2584       else font = FONT_TABLE[widgetGlobals->FLtext_font];
2585       //     switch (FLtext_font) {
2586       //     case 1: font  = FL_HELVETICA; break;
2587       //     case 2: font  = FL_HELVETICA_BOLD; break;
2588       //     case 3: font  = FL_HELVETICA_ITALIC; break;
2589       //     case 4: font  = FL_HELVETICA_BOLD_ITALIC; break;
2590       //     case 5: font  = FL_COURIER; break;
2591       //     case 6: font  = FL_COURIER_BOLD; break;
2592       //     case 7: font  = FL_COURIER_ITALIC; break;
2593       //     case 8: font  = FL_COURIER_BOLD_ITALIC; break;
2594       //     case 9: font  = FL_TIMES; break;
2595       //     case 10: font = FL_TIMES_BOLD; break;
2596       //     case 11: font = FL_TIMES_ITALIC; break;
2597       //     case 12: font = FL_TIMES_BOLD_ITALIC; break;
2598       //     case 13: font = FL_SYMBOL; break;
2599       //     case 14: font = FL_SCREEN; break;
2600       //     case 15: font = FL_SCREEN_BOLD; break;
2601       //     case 16: font = FL_ZAPF_DINGBATS; break;
2602       //     default: font = FL_HELVETICA; break;
2603       //     }
2604       o->labelfont(font);
2605     }
2606     if (widgetGlobals->FLtext_align > 0) {
2607       Fl_Align type;
2608       if (widgetGlobals->FLtext_align<0 ||
2609           widgetGlobals->FLtext_align>9) type = FL_ALIGN_BOTTOM;
2610       else type = ALIGN_TABLE[widgetGlobals->FLtext_align];
2611       //     switch (widgetGlobals->FLtext_align) {
2612       //     case 1: type  = FL_ALIGN_CENTER; break;
2613       //     case 2: type  = FL_ALIGN_TOP; break;
2614       //     case 3: type  = FL_ALIGN_BOTTOM; break;
2615       //     case 4: type  = FL_ALIGN_LEFT; break;
2616       //     case 5: type  = FL_ALIGN_RIGHT; break;
2617       //     case 6: type  = FL_ALIGN_TOP_LEFT; break;
2618       //     case 7: type  = FL_ALIGN_TOP_RIGHT; break;
2619       //     case 8: type  = FL_ALIGN_BOTTOM_LEFT; break;
2620       //     case 9: type  = FL_ALIGN_BOTTOM_RIGHT; break;
2621       //     case -1:                // What type is this?
2622       //     default: type = FL_ALIGN_BOTTOM; break;
2623       //     }
2624       o->align(type);
2625     }
2626     switch ((int) widgetGlobals->FLcolor) {  // random color
2627     case -2:
2628       o->color(FL_GRAY,
2629                fl_rgb_color(rand_31_i(csound, 255), rand_31_i(csound, 255),
2630                             rand_31_i(csound, 255)));
2631       break;
2632     case -1:
2633       // if FLcolor is == -1, color assignment is skipped,
2634       // leaving widget default color
2635       break;
2636     default:
2637       o->color(widgetGlobals->FLcolor, widgetGlobals->FLcolor2);
2638       break;
2639     }
2640 }
2641 
2642 //-----------
2643 
2644 extern "C" {
2645 
2646   // static int FLkeyb(CSOUND *csound, FLKEYB *p)
2647   // {
2648   //     (void) csound;
2649   //     (void) p;
2650   //     return OK;
2651   // }
2652 
2653   //-----------
2654 
flpanel_cb(Fl_Widget *,void *)2655   void flpanel_cb(Fl_Widget *,void *) { //suppresses the close button
2656   }
2657 
StartPanel(CSOUND * csound,FLPANEL * p)2658   static int StartPanel(CSOUND *csound, FLPANEL *p)
2659   {
2660       char    *panelName;
2661       panelName =  p->name->data;
2662       WIDGET_GLOBALS *widgetGlobals =
2663         (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS");
2664 
2665       *(getFLTKFlagsPtr(csound)) |= 32;
2666       int      x = (int) *p->ix, y = (int) *p->iy;
2667       int  width = (int) *p->iwidth, height = (int) *p->iheight;
2668       if (width < 0) width = 400;   // default
2669       if (height < 0) height = 300;
2670 
2671       Fl_Boxtype borderType;
2672       int iborder = (int) *p->border;
2673       if (iborder<0 || iborder>7) borderType = FL_FLAT_BOX;
2674       else borderType = BOX_TABLE[iborder];
2675       //   switch( (int) *p->border ) {
2676       //   case 0: borderType = FL_FLAT_BOX; break;
2677       //   case 1: borderType = FL_DOWN_BOX; break;
2678       //   case 2: borderType = FL_UP_BOX; break;
2679       //   case 3: borderType = FL_ENGRAVED_BOX; break;
2680       //   case 4: borderType = FL_EMBOSSED_BOX; break;
2681       //   case 5: borderType = FL_BORDER_BOX; break;
2682       //   case 6: borderType = FL_THIN_DOWN_BOX; break;
2683       //   case 7: borderType = FL_THIN_UP_BOX; break;
2684       //   default: borderType = FL_FLAT_BOX;
2685       //   }
2686 
2687       Fl_Window *o;
2688       if (*(p->ikbdsense) == MYFLT(0.0)) {
2689         if (x < 0)
2690           o = new Fl_Window(width, height, panelName);
2691         else
2692           o = new Fl_Window(x, y, width, height, panelName);
2693       }
2694       else if (x < 0)
2695         o = new CsoundFLWindow(csound, width, height, panelName);
2696       else
2697         o = new CsoundFLWindow(csound, x, y, width, height, panelName);
2698       widget_attributes(csound, o);
2699       o->box(borderType);
2700       o->resizable(o);
2701       if (*p->iclose != 0)
2702         o->callback(flpanel_cb);
2703       widget_attributes(csound, o);
2704       ADDR_STACK adrstk(&p->h, (void *) o, widgetGlobals->stack_count);
2705       widgetGlobals->AddrStack.push_back(adrstk);
2706       PANELS panel(o, (widgetGlobals->stack_count > 0) ? 1 : 0);
2707       widgetGlobals->fl_windows.push_back(panel);
2708       widgetGlobals->stack_count++;
2709 
2710       return OK;
2711   }
2712 
EndPanel(CSOUND * csound,FLPANELEND * p)2713   static int EndPanel(CSOUND *csound, FLPANELEND *p)
2714   {
2715      IGN(p);
2716       WIDGET_GLOBALS *widgetGlobals =
2717         (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS");
2718       widgetGlobals->stack_count--;
2719       ADDR_STACK adrstk = widgetGlobals->AddrStack.back();
2720       if (UNLIKELY(adrstk.h->optext->t.opcod &&
2721                    strcmp( adrstk.h->optext->t.opcod, "FLpanel")))
2722         return csound->InitError(csound,
2723                                  "%s", Str("FLpanel_end: invalid stack pointer: "
2724                                      "verify its placement"));
2725       if (UNLIKELY(adrstk.count != widgetGlobals->stack_count))
2726         return csound->InitError(csound,
2727                                  "%s", Str("FLpanel_end: invalid stack count: "
2728                                      "verify FLpanel/FLpanel_end count and"
2729                                      " placement"));
2730       ((Fl_Window*) adrstk.WidgAddress)->end();
2731       widgetGlobals->AddrStack.pop_back();
2732       return OK;
2733   }
2734 
2735   //-----------
StartScroll(CSOUND * csound,FLSCROLL * p)2736   static int StartScroll(CSOUND *csound, FLSCROLL *p)
2737   {
2738      WIDGET_GLOBALS *widgetGlobals =
2739        (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS");
2740       Fl_Scroll *o = new Fl_Scroll ((int) *p->ix, (int) *p->iy,
2741                                     (int) *p->iwidth, (int) *p->iheight);
2742       ADDR_STACK adrstk(&p->h,o,widgetGlobals->stack_count);
2743       widgetGlobals->AddrStack.push_back(adrstk);
2744       widgetGlobals->stack_count++;
2745       return OK;
2746   }
2747 
EndScroll(CSOUND * csound,FLSCROLLEND * p)2748   static int EndScroll(CSOUND *csound, FLSCROLLEND *p)
2749   {
2750      IGN(p);
2751      WIDGET_GLOBALS *widgetGlobals =
2752        (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS");
2753      widgetGlobals->stack_count--;
2754      ADDR_STACK adrstk = widgetGlobals->AddrStack.back();
2755       if (UNLIKELY(strcmp( adrstk.h->optext->t.opcod, "FLscroll")))
2756         return
2757           csound->InitError(csound,
2758                             "%s", Str("FLscroll_end: invalid stack pointer: "
2759                                 "verify its placement"));
2760       if (UNLIKELY(adrstk.count != widgetGlobals->stack_count))
2761         return csound->InitError(csound,
2762                             "%s", Str("FLscroll_end: invalid stack count: "
2763                                 "verify FLscroll/FLscroll_end count "
2764                                 "and placement"));
2765       ((Fl_Scroll*) adrstk.WidgAddress)->end();
2766 
2767       widgetGlobals->AddrStack.pop_back();
2768       return OK;
2769   }
2770 
2771   //-----------
StartTabs(CSOUND * csound,FLTABS * p)2772   static int StartTabs(CSOUND *csound, FLTABS *p)
2773   {
2774       WIDGET_GLOBALS *widgetGlobals =
2775         (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS");
2776       Fl_Tabs *o = new Fl_Tabs ((int) *p->ix, (int) *p->iy,
2777                                 (int) *p->iwidth, (int) *p->iheight);
2778       widget_attributes(csound, o);
2779       //   o->box(FL_PLASTIC_UP_BOX);
2780       ADDR_STACK adrstk(&p->h,o,widgetGlobals->stack_count);
2781       widgetGlobals->AddrStack.push_back(adrstk);
2782       widgetGlobals->stack_count++;
2783       return OK;
2784   }
2785 
EndTabs(CSOUND * csound,FLTABSEND * p)2786   static int EndTabs(CSOUND *csound, FLTABSEND *p)
2787   {
2788      IGN(p);
2789      WIDGET_GLOBALS *widgetGlobals =
2790        (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS");
2791      widgetGlobals->stack_count--;
2792      ADDR_STACK adrstk = widgetGlobals->AddrStack.back();
2793       if (UNLIKELY(strcmp( adrstk.h->optext->t.opcod, "FLtabs")))
2794         return
2795           csound->InitError(csound,
2796                             "%s", Str("FLscroll_end: invalid stack pointer: "
2797                                 "verify its placement"));
2798       if (UNLIKELY(adrstk.count != widgetGlobals->stack_count))
2799         return csound->InitError(csound,
2800                                  "%s", Str("FLtabs_end: invalid stack count: "
2801                                      "verify FLtabs/FLtabs_end count and "
2802                                      "placement"));
2803       ((Fl_Scroll*) adrstk.WidgAddress)->end();
2804 
2805       widgetGlobals->AddrStack.pop_back();
2806       return OK;
2807   }
2808 
2809   //-----------
StartGroup(CSOUND * csound,FLGROUP * p)2810   static int StartGroup(CSOUND *csound, FLGROUP *p)
2811   {
2812       WIDGET_GLOBALS *widgetGlobals =
2813         (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS");
2814       char *Name = p->name->data;
2815       Fl_Group *o = new Fl_Group ((int) *p->ix, (int) *p->iy,
2816                                   (int) *p->iwidth, (int) *p->iheight,Name);
2817       widget_attributes(csound, o);
2818       Fl_Boxtype borderType;
2819       int iborder = (int)*p->border;
2820       if (iborder<0 || iborder>7) borderType = FL_FLAT_BOX;
2821       else borderType = BOX_TABLE[iborder];
2822       //   switch((int)*p->border ) {
2823       //   case 0: borderType = FL_FLAT_BOX; break;
2824       //   case 1: borderType = FL_DOWN_BOX; break;
2825       //   case 2: borderType = FL_UP_BOX; break;
2826       //   case 3: borderType = FL_ENGRAVED_BOX; break;
2827       //   case 4: borderType = FL_EMBOSSED_BOX; break;
2828       //   case 5: borderType = FL_BORDER_BOX; break;
2829       //   case 6: borderType = FL_THIN_DOWN_BOX; break;
2830       //   case 7: borderType = FL_THIN_UP_BOX; break;
2831       //   default: borderType = FL_FLAT_BOX;
2832       //   }
2833       o->box(borderType);
2834       widget_attributes(csound, o);
2835       ADDR_STACK adrstk(&p->h,o,widgetGlobals->stack_count);
2836       widgetGlobals->AddrStack.push_back(adrstk);
2837       widgetGlobals->stack_count++;
2838       return OK;
2839   }
2840 
EndGroup(CSOUND * csound,FLGROUPEND * p)2841   static int EndGroup(CSOUND *csound, FLGROUPEND *p)
2842   {
2843      IGN(p);
2844       WIDGET_GLOBALS *widgetGlobals =
2845         (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS");
2846       widgetGlobals->stack_count--;
2847       ADDR_STACK adrstk = widgetGlobals->AddrStack.back();
2848       if (UNLIKELY(strcmp( adrstk.h->optext->t.opcod, "FLgroup")))
2849         return csound->InitError(csound,
2850                                  "%s", Str("FLgroup_end: invalid stack pointer: "
2851                                      "verify its placement"));
2852       if (UNLIKELY(adrstk.count != widgetGlobals->stack_count))
2853         return csound->InitError(csound,
2854                                  "%s", Str("FLgroup_end: invalid stack count: "
2855                                      "verify FLgroup/FLgroup_end count and"
2856                                      " placement"));
2857       ((Fl_Scroll*) adrstk.WidgAddress)->end();
2858 
2859       widgetGlobals->AddrStack.pop_back();
2860       return OK;
2861   }
2862 
2863   //-----------
2864 
StartPack(CSOUND * csound,FLPACK * p)2865   static int StartPack(CSOUND *csound, FLPACK *p)
2866   {
2867      WIDGET_GLOBALS *widgetGlobals =
2868        (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS");
2869       Fl_Pack *o = new Fl_Pack ((int) *p->ix, (int) *p->iy,
2870                                 (int) *p->iwidth, (int) *p->iheight);
2871       Fl_Boxtype borderType = FL_FLAT_BOX;
2872       int iborder = (int)*p->iborder;
2873       // fl_window->resizable(o);
2874       if (!((iborder<0 || iborder>7)))
2875           borderType = BOX_TABLE[iborder];
2876       o->box(borderType);       // JPff added March 2012
2877       o->type((int)*p->itype);
2878       o->spacing((int)*p->ispace);
2879 
2880       ADDR_STACK adrstk(&p->h,o,widgetGlobals->stack_count);
2881       widgetGlobals->AddrStack.push_back(adrstk);
2882       widgetGlobals->stack_count++;
2883       return OK;
2884   }
2885 
EndPack(CSOUND * csound,FLSCROLLEND * p)2886   static int EndPack(CSOUND *csound, FLSCROLLEND *p)
2887   {
2888      IGN(p);
2889       WIDGET_GLOBALS *widgetGlobals =
2890         (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS");
2891       widgetGlobals->stack_count--;
2892       ADDR_STACK adrstk = widgetGlobals->AddrStack.back();
2893       if (UNLIKELY(strcmp( adrstk.h->optext->t.opcod, "FLpack")))
2894         return csound->InitError(csound,
2895                                  "%s", Str("FLpack_end: invalid stack pointer: "
2896                                      "verify its placement"));
2897       if (UNLIKELY(adrstk.count != widgetGlobals->stack_count))
2898         return csound->InitError(csound,
2899                                  "%s", Str("FLpack_end: invalid stack count: "
2900                                      "verify FLpack/FLpack_end count and "
2901                                      "placement"));
2902       ((Fl_Pack*) adrstk.WidgAddress)->end();
2903 
2904       widgetGlobals->AddrStack.pop_back();
2905       return OK;
2906   }
2907 
2908   //-----------
2909 
fl_widget_color(CSOUND * csound,FLWIDGCOL * p)2910   static int fl_widget_color(CSOUND *csound, FLWIDGCOL *p)
2911   {
2912       WIDGET_GLOBALS *widgetGlobals =
2913         (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS");
2914       if (*p->red1 < 0) { // reset colors to default
2915         widgetGlobals->FLcolor = (int) *p->red1; //when called without arguments
2916         widgetGlobals->FLcolor2 =(int) *p->red1;
2917       }
2918       else {
2919         widgetGlobals->FLcolor = fl_rgb_color((int) *p->red1,
2920                                    (int) *p->green1,
2921                                    (int) *p->blue1);
2922         widgetGlobals->FLcolor2 = fl_rgb_color((int) *p->red2,
2923                                     (int) *p->green2,
2924                                     (int) *p->blue2);
2925       }
2926       return OK;
2927   }
2928 
fl_widget_color2(CSOUND * csound,FLWIDGCOL2 * p)2929   static int fl_widget_color2(CSOUND *csound, FLWIDGCOL2 *p)
2930   {
2931       WIDGET_GLOBALS *widgetGlobals =
2932         (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS");
2933       if (*p->red < 0) { // reset colors to default
2934         widgetGlobals->FLcolor2 =(int) *p->red;
2935       }
2936       else {
2937         widgetGlobals->FLcolor2 = fl_rgb_color((int) *p->red,
2938                                     (int) *p->green,
2939                                     (int) *p->blue);
2940       }
2941       return OK;
2942   }
2943 
fl_widget_label(CSOUND * csound,FLWIDGLABEL * p)2944   static int fl_widget_label(CSOUND *csound, FLWIDGLABEL *p)
2945   {
2946       WIDGET_GLOBALS *widgetGlobals =
2947         (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS");
2948       if (*p->size <= 0) { // reset settings to default
2949         widgetGlobals->FLtext_size = 0; //when called without arguments
2950         widgetGlobals->FLtext_font = -1;
2951         widgetGlobals->FLtext_align = 0;
2952         widgetGlobals->FLtext_color = -1;
2953       }
2954       else {
2955         widgetGlobals->FLtext_size = (int) *p->size;
2956 
2957         if (*p->font > -1) widgetGlobals->FLtext_font = (int) *p->font;
2958         if (*p->align > 0)  widgetGlobals->FLtext_align =  (int) *p->align;
2959         if (*p->red > -1 && *p->green > -1 && *p->blue > -1) {
2960           widgetGlobals->FLtext_color = fl_rgb_color((int) *p->red,
2961                                           (int) *p->green,
2962                                           (int) *p->blue);
2963         }
2964       }
2965       return OK;
2966   }
2967 
2968 }       // extern "C"
2969 
2970 // -----------
2971 
fl_getWidgetTypeFromOpcodeName(CSOUND * csound,void * p)2972 static int fl_getWidgetTypeFromOpcodeName(CSOUND *csound, void *p)
2973 {
2974     const char  *opname = csound->GetOpcodeName(p);
2975 
2976     if (strcmp(opname, "FLbutton") == 0)
2977       return 1;
2978     if (strcmp(opname, "FLbutBank") == 0)
2979       return 2;
2980     if (strcmp(opname, "FLjoy") == 0)
2981       return 3;
2982     if (strcmp(opname, "FLvalue") == 0)
2983       return 4;
2984     if (strcmp(opname, "FLbox") != 0)
2985       return 0;
2986     csound->Warning(csound, "%s", Str("System error: value() method called from "
2987                                 "non-valuator object"));
2988     return -1;
2989 }
2990 
fl_setWidgetValue_(CSOUND * csound,ADDR_SET_VALUE & v,int widgetType,MYFLT val,MYFLT log_base)2991 static void fl_setWidgetValue_(CSOUND *csound,
2992                                ADDR_SET_VALUE &v, int widgetType,
2993                                MYFLT val, MYFLT log_base)
2994 {
2995     Fl_Widget   *o = (Fl_Widget *) v.WidgAddress;
2996     void        *p = v.opcode;
2997     bool        fltkLockingIsEnabled;
2998 
2999     if ((!widgetType || widgetType > 2) &&
3000         (v.exponential == LIN_ || v.exponential == EXP_)) {
3001       if (val < v.min)
3002         val = v.min;
3003       else if (val > v.max)
3004         val = v.max;
3005       if (v.exponential == EXP_)
3006         val = (MYFLT) (log(val / v.min) / log_base);
3007     }
3008     fltkLockingIsEnabled = ((getFLTKFlags(csound) & 8) == 0);
3009     if (fltkLockingIsEnabled)
3010       Fl_lock(csound);
3011     switch (widgetType) {
3012     case 0:                                     // valuator
3013       ((Fl_Valuator *) o)->value(val);
3014       break;
3015     case 1:                                     // FLbutton
3016       if (val == *(((FLBUTTON *) v.opcode)->ion))
3017         ((Fl_Button *) o)->value(1);
3018       else if (val == *(((FLBUTTON *) v.opcode)->ioff))
3019         ((Fl_Button *) o)->value(0);
3020       break;
3021     case 2:                                     // FLbutBank
3022       set_butbank_value((Fl_Group *) o, val);
3023       break;
3024     case 3:                                     // FLjoy
3025       {
3026         static int  flag = 0;
3027         // FLsetVal always requires two adjacent calls when setting FLjoy
3028         if (!flag) {
3029           ((Fl_Positioner *) o)->xvalue(val);
3030           flag = 1;
3031         }
3032         else {
3033           ((Fl_Positioner *) o)->yvalue(val);
3034           flag = 0;
3035         }
3036       }
3037       break;
3038     default:                                    // invalid
3039       if (fltkLockingIsEnabled)
3040         Fl_unlock(csound);
3041       return;
3042     }
3043     o->do_callback(o, p);
3044     if (fltkLockingIsEnabled)
3045       Fl_unlock(csound);
3046 }
3047 
3048 extern "C" {
3049 
fl_setWidgetValuei(CSOUND * csound,FL_SET_WIDGET_VALUE_I * p)3050   static int fl_setWidgetValuei(CSOUND *csound, FL_SET_WIDGET_VALUE_I *p)
3051   {
3052      WIDGET_GLOBALS *widgetGlobals =
3053        (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS");
3054       MYFLT           log_base = MYFLT(1.0);
3055       ADDR_SET_VALUE  &v = widgetGlobals->AddrSetValue[(int) *p->ihandle];
3056       int             widgetType;
3057 
3058       widgetType = fl_getWidgetTypeFromOpcodeName(csound, v.opcode);
3059       if (UNLIKELY(widgetType == 4)) {
3060         csound->InitError(csound,
3061                           "%s", Str("FLvalue cannot be set by FLsetVal.\n"));
3062         return NOTOK;
3063       }
3064       if (widgetType < 0)
3065         return OK;
3066       if (!widgetType || widgetType > 2) {
3067         switch (v.exponential) {
3068         case LIN_:        // linear
3069           break;
3070         case EXP_:        // exponential
3071           #if defined(sun)
3072             log_base = (MYFLT) log(::pow(v.max / (double)v.min,
3073                                          1.0 / (v.max - v.min)));
3074           #else
3075             log_base = (MYFLT) log(::pow(v.max / v.min, 1.0 / (v.max - v.min)));
3076           #endif
3077           break;
3078         default:
3079           csound->Warning(csound, Str("(fl_setWidgetValuei): "
3080                                       "not fully implemented yet; exp=%d"),
3081                           v.exponential);
3082         }
3083       }
3084       fl_setWidgetValue_(csound, v, widgetType, *(p->ivalue), log_base);
3085       return OK;
3086   }
3087 
fl_setWidgetValue_set(CSOUND * csound,FL_SET_WIDGET_VALUE * p)3088   static int fl_setWidgetValue_set(CSOUND *csound, FL_SET_WIDGET_VALUE *p)
3089   {
3090       p->handle = (int) *(p->ihandle);
3091       WIDGET_GLOBALS *widgetGlobals =
3092         (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS");
3093       MYFLT           log_base = MYFLT(1.0);
3094       ADDR_SET_VALUE  &v = widgetGlobals->AddrSetValue[p->handle];
3095       int             widgetType;
3096 
3097       widgetType = fl_getWidgetTypeFromOpcodeName(csound, v.opcode);
3098       if (UNLIKELY(widgetType == 4)) {
3099         csound->InitError(csound,
3100                           "%s", Str("FLvalue cannot be set by FLsetVal\n"));
3101         return NOTOK;
3102       }
3103       if (widgetType < 0)
3104         return OK;
3105       if (!widgetType || widgetType > 2) {
3106         switch (v.exponential) {
3107         case LIN_:        // linear
3108           break;
3109         case EXP_:        // exponential
3110           #if defined(sun)
3111             log_base = (MYFLT) log(::pow(v.max / (double)v.min,
3112                                    1.0 / (v.max - v.min)));
3113           #else
3114             log_base = (MYFLT) log(::pow(v.max / v.min, 1.0 / (v.max - v.min)));
3115           #endif
3116           break;
3117         default:
3118           csound->Warning(csound, Str("(fl_setWidgetValue_set): "
3119                                       "not fully implemented yet; exp=%d"),
3120                           v.exponential);
3121         }
3122       }
3123       p->widgetType = widgetType;
3124       p->log_base = log_base;
3125 
3126       return OK;
3127   }
3128 
fl_setWidgetValue(CSOUND * csound,FL_SET_WIDGET_VALUE * p)3129   static int fl_setWidgetValue(CSOUND *csound, FL_SET_WIDGET_VALUE *p)
3130   {
3131       WIDGET_GLOBALS *widgetGlobals =
3132         (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS");
3133       if (*p->ktrig != MYFLT(0.0))
3134         fl_setWidgetValue_(csound,
3135                            widgetGlobals->AddrSetValue[p->handle], p->widgetType,
3136                            *(p->kvalue), p->log_base);
3137       return OK;
3138   }
3139 
3140   //-----------
3141   //-----------
3142 
fl_setColor1(CSOUND * csound,FL_SET_COLOR * p)3143   static int fl_setColor1(CSOUND *csound, FL_SET_COLOR *p)
3144   {
3145      WIDGET_GLOBALS *widgetGlobals =
3146        (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS");
3147      ADDR_SET_VALUE v = widgetGlobals->AddrSetValue[(int) *p->ihandle];
3148       Fl_Widget *o = (Fl_Widget *) v.WidgAddress;
3149       int color = fl_rgb_color((int) *p->red,
3150                                (int) *p->green,
3151                                (int) *p->blue);
3152       o->color(color);
3153       o->redraw();
3154       return OK;
3155   }
3156 
fl_setColor2(CSOUND * csound,FL_SET_COLOR * p)3157   static int fl_setColor2(CSOUND *csound, FL_SET_COLOR *p)
3158   {
3159      WIDGET_GLOBALS *widgetGlobals =
3160        (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS");
3161      ADDR_SET_VALUE v = widgetGlobals->AddrSetValue[(int) *p->ihandle];
3162       Fl_Widget *o = (Fl_Widget *) v.WidgAddress;
3163       int color = fl_rgb_color((int) *p->red, (int) *p->green, (int) *p->blue);
3164       o->selection_color(color);
3165       o->redraw();
3166       return OK;
3167   }
3168 
fl_setTextColor(CSOUND * csound,FL_SET_COLOR * p)3169   static int fl_setTextColor(CSOUND *csound, FL_SET_COLOR *p)
3170   {
3171       WIDGET_GLOBALS *widgetGlobals =
3172         (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS");
3173       ADDR_SET_VALUE v = widgetGlobals->AddrSetValue[(int) *p->ihandle];
3174       Fl_Widget *o = (Fl_Widget *) v.WidgAddress;
3175       int color = fl_rgb_color((int) *p->red, (int) *p->green, (int) *p->blue);
3176       o->labelcolor(color);
3177       o->window()->redraw();
3178       return OK;
3179   }
3180 
fl_setTextSize(CSOUND * csound,FL_SET_TEXTSIZE * p)3181   static int fl_setTextSize(CSOUND *csound, FL_SET_TEXTSIZE *p)
3182   {
3183       WIDGET_GLOBALS *widgetGlobals =
3184         (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS");
3185       ADDR_SET_VALUE v = widgetGlobals->AddrSetValue[(int) *p->ihandle];
3186       Fl_Widget *o = (Fl_Widget *) v.WidgAddress;
3187       o->labelsize((uchar) *p->ivalue);
3188       return OK;
3189   }
3190 
fl_setFont(CSOUND * csound,FL_SET_FONT * p)3191   static int fl_setFont(CSOUND *csound, FL_SET_FONT *p)
3192   {
3193       WIDGET_GLOBALS *widgetGlobals =
3194         (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS");
3195       ADDR_SET_VALUE v = widgetGlobals->AddrSetValue[(int) *p->ihandle];
3196       Fl_Widget *o = (Fl_Widget *) v.WidgAddress;
3197       Fl_Font font;
3198       int ifnt = (int) *p->itype;
3199       if (ifnt<0 || ifnt>16) font = FL_HELVETICA;
3200       else font = FONT_TABLE[ifnt];
3201       //   switch ((int) *p->itype) {
3202       //   case 1: font  = FL_HELVETICA; break;
3203       //   case 2: font  = FL_HELVETICA_BOLD; break;
3204       //   case 3: font  = FL_HELVETICA_ITALIC; break;
3205       //   case 4: font  = FL_HELVETICA_BOLD_ITALIC; break;
3206       //   case 5: font  = FL_COURIER; break;
3207       //   case 6: font  = FL_COURIER_BOLD; break;
3208       //   case 7: font  = FL_COURIER_ITALIC; break;
3209       //   case 8: font  = FL_COURIER_BOLD_ITALIC; break;
3210       //   case 9: font  = FL_TIMES; break;
3211       //   case 10: font = FL_TIMES_BOLD; break;
3212       //   case 11: font = FL_TIMES_ITALIC; break;
3213       //   case 12: font = FL_TIMES_BOLD_ITALIC; break;
3214       //   case 13: font = FL_SYMBOL; break;
3215       //   case 14: font = FL_SCREEN; break;
3216       //   case 15: font = FL_SCREEN_BOLD; break;
3217       //   case 16: font = FL_ZAPF_DINGBATS; break;
3218       //   default: font = FL_SCREEN;
3219       //   }
3220       o->labelfont(font);
3221       return OK;
3222   }
3223 
fl_setTextType(CSOUND * csound,FL_SET_FONT * p)3224   static int fl_setTextType(CSOUND *csound, FL_SET_FONT *p)
3225   {
3226       WIDGET_GLOBALS *widgetGlobals =
3227         (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS");
3228       ADDR_SET_VALUE v = widgetGlobals->AddrSetValue[(int) *p->ihandle];
3229       Fl_Widget *o = (Fl_Widget *) v.WidgAddress;
3230       Fl_Labeltype type;
3231       switch ((int) *p->itype) {
3232       case 0: type  = FL_NORMAL_LABEL; break;
3233       case 1: type  = FL_NO_LABEL; break;
3234       case 2: type  = FL_SYMBOL_LABEL; break;
3235       case 3: type  = FL_SHADOW_LABEL; break;
3236       case 4: type  = FL_ENGRAVED_LABEL; break;
3237       case 5: type  = FL_EMBOSSED_LABEL; break;
3238         /*    case 6: type  = _FL_BITMAP_LABEL; break;
3239               case 7: type  = _FL_PIXMAP_LABEL; break;
3240               case 8: type  = _FL_IMAGE_LABEL; break;
3241               case 9: type  = _FL_MULTI_LABEL; break; */
3242       case 10: type = FL_FREE_LABELTYPE; break;
3243       default: type = FL_NORMAL_LABEL;
3244       }
3245       o->labeltype(type);
3246       o->window()->redraw();
3247       return OK;
3248   }
3249 
fl_box_(CSOUND * csound,FL_BOX * p,char * text)3250   static int fl_box_(CSOUND *csound, FL_BOX *p, char *text)
3251   {
3252       //char *text = p->itext->data;
3253       Fl_Box *o =  new Fl_Box((int)*p->ix, (int)*p->iy,
3254                               (int)*p->iwidth, (int)*p->iheight, strdup(text));
3255       widget_attributes(csound, o);
3256       Fl_Boxtype type;
3257       int itype = (int) *p->itype;
3258       if (itype<0 || itype>19) type = FL_FLAT_BOX;
3259       else type = BOX_TABLE[itype];
3260       //   switch ((int) *p->itype) {
3261       //   case 1: type  = FL_FLAT_BOX; break;
3262       //   case 2: type  = FL_UP_BOX; break;
3263       //   case 3: type  = FL_DOWN_BOX; break;
3264       //   case 4: type  = FL_THIN_UP_BOX; break;
3265       //   case 5: type  = FL_THIN_DOWN_BOX; break;
3266       //   case 6: type  = FL_ENGRAVED_BOX; break;
3267       //   case 7: type  = FL_EMBOSSED_BOX; break;
3268       //   case 8: type  = FL_BORDER_BOX; break;
3269       //   case 9: type  = _FL_SHADOW_BOX; break;
3270       //   case 10: type = _FL_ROUNDED_BOX; break;
3271       //   case 11: type = _FL_RSHADOW_BOX; break;
3272       //   case 12: type = _FL_RFLAT_BOX; break;
3273       //   case 13: type = _FL_ROUND_UP_BOX; break;
3274       //   case 14: type = _FL_ROUND_DOWN_BOX; break;
3275       //   case 15: type = _FL_DIAMOND_UP_BOX; break;
3276       //   case 16: type = _FL_DIAMOND_DOWN_BOX; break;
3277       //   case 17: type = _FL_OVAL_BOX; break;
3278       //   case 18: type = _FL_OSHADOW_BOX; break;
3279       //   case 19: type = _FL_OFLAT_BOX; break;
3280       //   default: type = FL_FLAT_BOX;
3281       //   }
3282       o->box(type);
3283       Fl_Font font;
3284       int ifnt = (int) *p->ifont;
3285       if (ifnt<0 || ifnt>16) font = FL_HELVETICA;
3286       else font = FONT_TABLE[ifnt];
3287       //   switch ((int) *p->ifont) {
3288       //   case 1: font  = FL_HELVETICA; break;
3289       //   case 2: font  = FL_HELVETICA_BOLD; break;
3290       //   case 3: font  = FL_HELVETICA_ITALIC; break;
3291       //   case 4: font  = FL_HELVETICA_BOLD_ITALIC; break;
3292       //   case 5: font  = FL_COURIER; break;
3293       //   case 6: font  = FL_COURIER_BOLD; break;
3294       //   case 7: font  = FL_COURIER_ITALIC; break;
3295       //   case 8: font  = FL_COURIER_BOLD_ITALIC; break;
3296       //   case 9: font  = FL_TIMES; break;
3297       //   case 10: font = FL_TIMES_BOLD; break;
3298       //   case 11: font = FL_TIMES_ITALIC; break;
3299       //   case 12: font = FL_TIMES_BOLD_ITALIC; break;
3300       //   case 13: font = FL_SYMBOL; break;
3301       //   case 14: font = FL_SCREEN; break;
3302       //   case 15: font = FL_SCREEN_BOLD; break;
3303       //   case 16: font = FL_ZAPF_DINGBATS; break;
3304       //   default: font = FL_HELVETICA;
3305       //   }
3306       o->labelfont(font);
3307       o->labelsize((unsigned char)*p->isize);
3308       o->align(FL_ALIGN_WRAP);
3309       WIDGET_GLOBALS *widgetGlobals =
3310         (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS");
3311       widgetGlobals->AddrSetValue.push_back(ADDR_SET_VALUE(0, 0, 0, (void *)o,
3312                                                 (void *)p,
3313                                                 widgetGlobals->currentSnapGroup));
3314       *p->ihandle = widgetGlobals->AddrSetValue.size()-1;
3315       return OK;
3316   }
3317 
fl_box_s(CSOUND * csound,FL_BOX * p)3318   static int fl_box_s(CSOUND *csound, FL_BOX *p)
3319   {
3320     return fl_box_(csound, p, p->itext->data);
3321   }
fl_box_i(CSOUND * csound,FL_BOX * p)3322   static int fl_box_i(CSOUND *csound, FL_BOX *p)
3323   {
3324     int i = (int)*((MYFLT*)p->itext);
3325     char* text;
3326     if (i<0 || i>csound->GetStrsmax(csound)) text = (char *) "???";
3327     else if ((text=csound->GetStrsets(csound,i))==NULL) text = (char *) "???";
3328     return fl_box_(csound, p, text);
3329   }
3330 
fl_setText(CSOUND * csound,FL_SET_TEXT * p)3331   static int fl_setText(CSOUND *csound, FL_SET_TEXT *p)
3332   {
3333       WIDGET_GLOBALS *widgetGlobals =
3334         (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS");
3335       char *text = strdup(p->itext->data);
3336       ADDR_SET_VALUE v = widgetGlobals->AddrSetValue[(int) *p->ihandle];
3337       Fl_Widget *o = (Fl_Widget *) v.WidgAddress;
3338       free((void*)o->label());
3339       o->label(text);
3340       return OK;
3341   }
3342 
fl_setTexti(CSOUND * csound,FL_SET_TEXTi * p)3343   static int fl_setTexti(CSOUND *csound, FL_SET_TEXTi *p)
3344   {
3345       WIDGET_GLOBALS *widgetGlobals =
3346         (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS");
3347       int i = (int)(*p->ndx);
3348       char *text ;
3349       ADDR_SET_VALUE v = widgetGlobals->AddrSetValue[(int) *p->ihandle];
3350       Fl_Widget *o = (Fl_Widget *) v.WidgAddress;
3351       if (i<0 || i>csound->GetStrsmax(csound)) text = (char *) "???";
3352       else if ((text=csound->GetStrsets(csound,i))==NULL) text = (char *) "???";
3353       free((void*)o->label());
3354       o->label(strdup(text));
3355       return OK;
3356   }
3357 
fl_setSize(CSOUND * csound,FL_SET_SIZE * p)3358   static int fl_setSize(CSOUND *csound, FL_SET_SIZE *p)
3359   {
3360       WIDGET_GLOBALS *widgetGlobals =
3361         (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS");
3362       ADDR_SET_VALUE v = widgetGlobals->AddrSetValue[(int) *p->ihandle];
3363       Fl_Widget *o = (Fl_Widget *) v.WidgAddress;
3364       o->size((short)  *p->iwidth, (short) *p->iheight);
3365       return OK;
3366   }
3367 
fl_setPosition(CSOUND * csound,FL_SET_POSITION * p)3368   static int fl_setPosition(CSOUND *csound, FL_SET_POSITION *p)
3369   {
3370       WIDGET_GLOBALS *widgetGlobals =
3371         (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS");
3372       ADDR_SET_VALUE v = widgetGlobals->AddrSetValue[(int) *p->ihandle];
3373       Fl_Widget *o = (Fl_Widget *) v.WidgAddress;
3374       o->position((short)  *p->ix, (short) *p->iy);
3375       return OK;
3376   }
3377 
fl_hide(CSOUND * csound,FL_WIDHIDE * p)3378   static int fl_hide(CSOUND *csound, FL_WIDHIDE *p)
3379   {
3380       WIDGET_GLOBALS *widgetGlobals =
3381         (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS");
3382       Fl_lock(csound);
3383       ADDR_SET_VALUE v = widgetGlobals->AddrSetValue[(int) *p->ihandle];
3384       Fl_Widget *o = (Fl_Widget *) v.WidgAddress;
3385       o->hide();
3386       Fl_unlock(csound);
3387       return OK;
3388   }
3389 
fl_show(CSOUND * csound,FL_WIDSHOW * p)3390   static int fl_show(CSOUND *csound, FL_WIDSHOW *p)
3391   {
3392      WIDGET_GLOBALS *widgetGlobals =
3393        (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS");
3394       Fl_lock(csound);
3395       ADDR_SET_VALUE v = widgetGlobals->AddrSetValue[(int) *p->ihandle];
3396       Fl_Widget *o = (Fl_Widget *) v.WidgAddress;
3397       o->show();
3398       Fl_unlock(csound);
3399       return OK;
3400   }
3401 
fl_setBox(CSOUND * csound,FL_SETBOX * p)3402   static int fl_setBox(CSOUND *csound, FL_SETBOX *p)
3403   {
3404       WIDGET_GLOBALS *widgetGlobals =
3405         (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS");
3406       ADDR_SET_VALUE v = widgetGlobals->AddrSetValue[(int) *p->ihandle];
3407       Fl_Widget *o = (Fl_Widget *) v.WidgAddress;
3408       Fl_Boxtype type;
3409       int itype = (int) *p->itype;
3410       if (itype<0||itype>19) type = FL_FLAT_BOX;
3411       else type = BOX_TABLE[itype];
3412       //   switch ((int) *p->itype) {
3413       //   case 1: type  = FL_FLAT_BOX; break;
3414       //   case 2: type  = FL_UP_BOX; break;
3415       //   case 3: type  = FL_DOWN_BOX; break;
3416       //   case 4: type  = FL_THIN_UP_BOX; break;
3417       //   case 5: type  = FL_THIN_DOWN_BOX; break;
3418       //   case 6: type  = FL_ENGRAVED_BOX; break;
3419       //   case 7: type  = FL_EMBOSSED_BOX; break;
3420       //   case 8: type  = FL_BORDER_BOX; break;
3421       //   case 9: type  = FL_SHADOW_BOX; break;
3422       //   case 10: type = FL_ROUNDED_BOX; break;
3423       //   case 11: type = FL_RSHADOW_BOX; break;
3424       //   case 12: type = FL_RFLAT_BOX; break;
3425       //   case 13: type = FL_ROUND_UP_BOX; break;
3426       //   case 14: type = FL_ROUND_DOWN_BOX; break;
3427       //   case 15: type = FL_DIAMOND_UP_BOX; break;
3428       //   case 16: type = FL_DIAMOND_DOWN_BOX; break;
3429       //   case 17: type = FL_OVAL_BOX; break;
3430       //   case 18: type = FL_OSHADOW_BOX; break;
3431       //   case 19: type = FL_OFLAT_BOX; break;
3432       //   default: type = FL_FLAT_BOX;
3433       //   }
3434       o->box(type);
3435       return OK;
3436   }
3437 
fl_align(CSOUND * csound,FL_TALIGN * p)3438   static int fl_align(CSOUND *csound, FL_TALIGN *p)
3439   {
3440       WIDGET_GLOBALS *widgetGlobals =
3441         (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS");
3442       ADDR_SET_VALUE v = widgetGlobals->AddrSetValue[(int) *p->ihandle];
3443       Fl_Widget *o = (Fl_Widget *) v.WidgAddress;
3444       Fl_Align type;
3445       int itype= (int) *p->itype;
3446       if (itype<0 || itype>9) type = FL_ALIGN_BOTTOM;
3447       else type = ALIGN_TABLE[itype];
3448       //   switch ((int) *p->itype) {
3449       //   case 1: type  = FL_ALIGN_CENTER; break;
3450       //   case 2: type  = FL_ALIGN_TOP; break;
3451       //   case 3: type  = FL_ALIGN_BOTTOM; break;
3452       //   case 4: type  = FL_ALIGN_LEFT; break;
3453       //   case 5: type  = FL_ALIGN_RIGHT; break;
3454       //   case 6: type  = FL_ALIGN_TOP_LEFT; break;
3455       //   case 7: type  = FL_ALIGN_TOP_RIGHT; break;
3456       //   case 8: type  = FL_ALIGN_BOTTOM_LEFT; break;
3457       //   case 9: type  = FL_ALIGN_BOTTOM_RIGHT; break;
3458       //   default: type = FL_ALIGN_BOTTOM;
3459       //   }
3460       o->align(type);
3461       return OK;
3462   }
3463 
3464   //-----------
3465   //-----------
3466 
fl_value(CSOUND * csound,FLVALUE * p)3467   static int fl_value(CSOUND *csound, FLVALUE *p)
3468   {
3469       WIDGET_GLOBALS *widgetGlobals =
3470         (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS");
3471       char *controlName = p->name->data;
3472       int ix, iy, iwidth, iheight;
3473       if (*p->ix<0) ix = widgetGlobals->FL_ix;
3474       else  widgetGlobals->FL_ix = ix = (int) *p->ix;
3475       if (*p->iy<0) iy = widgetGlobals->FL_iy;
3476       else  widgetGlobals->FL_iy = iy = (int) *p->iy;
3477       if (*p->iwidth<0) iwidth = widgetGlobals->FLvalue_iwidth;
3478       else widgetGlobals->FLvalue_iwidth = iwidth = (int) *p->iwidth;
3479       if (*p->iheight<0) iheight = widgetGlobals->FLroller_iheight;
3480       else widgetGlobals->FLroller_iheight = iheight = (int) *p->iheight;
3481 
3482       Fl_Output *o = new Fl_Output(ix, iy, iwidth, iheight,controlName);
3483       o->align(FL_ALIGN_BOTTOM | FL_ALIGN_WRAP);
3484       if (widgetGlobals->FLcolor < 0 )
3485         o->color(FL_GRAY );
3486       else
3487         o->color(widgetGlobals->FLcolor, widgetGlobals->FLcolor2);
3488       widget_attributes(csound, o);
3489       //AddrValue.push_back((void *) o);
3490       widgetGlobals->AddrSetValue.push_back(ADDR_SET_VALUE(0, 0, 0, (void *) o,
3491                                                  (void *) p,
3492                                                  widgetGlobals->currentSnapGroup));
3493       // *p->ihandle = AddrValue.size()-1;
3494       *p->ihandle = widgetGlobals->AddrSetValue.size()-1;
3495       return OK;
3496   }
3497 
3498   //-----------
3499 
fl_slider(CSOUND * csound,FLSLIDER * p)3500   static int fl_slider(CSOUND *csound, FLSLIDER *p)
3501   {
3502       WIDGET_GLOBALS *widgetGlobals =
3503         (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS");
3504       char *controlName = p->name->data;
3505       int ix,iy,iwidth, iheight,itype, iexp;
3506       bool plastic = false;
3507 
3508       if (*p->iy < 0) {
3509         iy = widgetGlobals->FL_iy;
3510         widgetGlobals->FL_iy += widgetGlobals->FLcontrol_iheight + 5;
3511       }
3512       else {
3513         iy = (int) *p->iy;
3514         widgetGlobals->FL_iy = iy + widgetGlobals->FLcontrol_iheight + 5;
3515       }
3516       if (*p->ix < 0)  ix = widgetGlobals->FL_ix; // omitted options: set default
3517       else  widgetGlobals->FL_ix = ix = (int) *p->ix;
3518       if (*p->iwidth < 0) iwidth = widgetGlobals->FLcontrol_iwidth;
3519       else widgetGlobals->FLcontrol_iwidth = iwidth = (int) *p->iwidth;
3520       if (*p->iheight < 0) iheight = widgetGlobals->FLcontrol_iheight;
3521       else widgetGlobals->FLcontrol_iheight = iheight = (int) *p->iheight;
3522       if (*p->itype < 1) itype = 1;
3523       else  itype = (int) *p->itype;
3524 
3525       //if (*p->iexp == LIN_) iexp = LIN_;
3526       //else  iexp = (int) *p->iexp;
3527       switch((int) *p->iexp) {
3528       case -1: iexp = EXP_; break;
3529       case 0: iexp = LIN_; break;
3530       default: iexp = (int) *p->iexp;
3531       }
3532       if (itype > 19) {
3533         plastic = true;
3534         itype = itype - 20;
3535       }
3536       if (UNLIKELY(itype > 10 && iexp == EXP_)) {
3537         csound->Warning(csound,
3538                         "%s", Str("FLslider exponential, using non-labeled slider"));
3539         itype -= 10;
3540       }
3541 
3542       Fl_Slider *o;
3543       if (itype <= 10) o = new Fl_Slider(ix, iy, iwidth, iheight, controlName);
3544       else {
3545         o = new Fl_Value_Slider_Input(csound, ix, iy,
3546                                       iwidth, iheight, controlName);
3547         itype -=10;
3548         //o->labelsize(20);
3549         ((Fl_Value_Slider_Input*) o)->textboxsize(50);
3550         ((Fl_Value_Slider_Input*) o)->textsize(13);
3551         o->align(FL_ALIGN_BOTTOM | FL_ALIGN_WRAP);
3552       }
3553       switch (itype) {
3554       case 1:  o->type(FL_HOR_FILL_SLIDER); break;
3555       case 2:  o->type(FL_VERT_FILL_SLIDER); break;
3556       case 3:  o->type(FL_HOR_SLIDER); break;
3557       case 4:  o->type(FL_VERT_SLIDER); break;
3558       case 5:  o->type(FL_HOR_NICE_SLIDER); o->box(FL_FLAT_BOX); break;
3559       case 6:  o->type(FL_VERT_NICE_SLIDER); o->box(FL_FLAT_BOX); break;
3560       default: return csound->InitError(csound,
3561                                         "%s", Str("FLslider: invalid slider type"));
3562       }
3563       if (plastic) o->box(FL_PLASTIC_DOWN_BOX);
3564       widget_attributes(csound, o);
3565       MYFLT min = p->min = *p->imin, max = *p->imax, range;
3566       switch (iexp) {
3567       case LIN_: //linear
3568         o->range(min,max);
3569         o->callback((Fl_Callback*)fl_callbackLinearSlider,(void *) p);
3570         break;
3571       case EXP_ : //exponential
3572         if (UNLIKELY(min == 0 || max == 0))
3573           return csound->InitError(csound,
3574                                    "%s", Str("FLslider: zero is illegal "
3575                                        "in exponential operations"));
3576         range = max - min;
3577         o->range(0,range);
3578         #if defined(sun)
3579           p->base = ::pow((max / (double)min), 1.0/(double)range);
3580         #else
3581           p->base = ::pow((max / min), 1.0/(double)range);
3582         #endif
3583         o->callback((Fl_Callback*)fl_callbackExponentialSlider,(void *) p);
3584         break;
3585       default:
3586         {
3587           FUNC *ftp;
3588           MYFLT fnum = abs(iexp);
3589           if ((ftp = csound->FTnp2Finde(csound, &fnum)) != NULL) {
3590             p->table = ftp->ftable;
3591             p->tablen = ftp->flen;
3592           }
3593           else return NOTOK;
3594           o->range(0,0.99999999);
3595           if (iexp > 0) //interpolated
3596             o->callback((Fl_Callback*)fl_callbackInterpTableSlider,(void *) p);
3597           else // non-interpolated
3598             o->callback((Fl_Callback*)fl_callbackTableSlider,(void *) p);
3599         }
3600       }
3601       widgetGlobals->AddrSetValue.push_back(ADDR_SET_VALUE(iexp, *p->imin,
3602                                                 *p->imax, (void *) o, (void*) p));
3603       /*widgetGlobals->currentSnapGroup;*/
3604       *p->ihandle = widgetGlobals->AddrSetValue.size()-1;
3605       return OK;
3606   }
3607 
fl_slider_bank_(CSOUND * csound,FLSLIDERBANK * p,int istring)3608   static int fl_slider_bank_(CSOUND *csound, FLSLIDERBANK *p, int istring)
3609   {
3610       WIDGET_GLOBALS *widgetGlobals =
3611         (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS");
3612       char s[MAXNAME];
3613       bool plastic = false;
3614       if (istring)
3615         strncpy(s, ((STRINGDAT*) p->names)->data, MAXNAME-1);
3616       else if ((long) *p->names <= csound->GetStrsmax(csound) &&
3617                csound->GetStrsets(csound,(long) *p->names)) {
3618         strncpy(s, csound->GetStrsets(csound,(long) *p->names), MAXNAME-1);
3619       }
3620       string tempname(s);
3621       stringstream sbuf;
3622       sbuf << tempname;
3623 
3624       int width = (int) *p->iwidth;
3625       if (width <=0) width = 100;
3626 
3627       Fl_Group* w = new Fl_Group((int)*p->ix, (int)*p->iy,
3628                                  width, (int)*p->inumsliders*10);
3629       FUNC *ftp;
3630       MYFLT *minmaxtable = NULL, *typetable = NULL, *outable, *exptable = NULL;
3631 
3632       MYFLT *zkstart;
3633       int zklast = csound->GetZakBounds(csound, &zkstart);
3634       if (*p->ioutable  < 1) {
3635         if (LIKELY(zkstart != NULL &&
3636                    zklast > (long)(*p->inumsliders+*p->ioutablestart_ndx)))
3637           outable = zkstart + (long) *p->ioutablestart_ndx;
3638         else {
3639           return csound->InitError(csound,
3640                                    "%s", Str("invalid ZAK space allocation"));
3641         }
3642       }
3643       else {
3644         if (LIKELY((ftp = csound->FTnp2Finde(csound, p->ioutable)) != NULL))
3645           outable = ftp->ftable + (long) *p->ioutablestart_ndx;
3646         else
3647           return NOTOK;
3648       }
3649       if ((int) *p->iminmaxtable > 0) {
3650         if (LIKELY((ftp = csound->FTnp2Finde(csound, p->iminmaxtable)) != NULL))
3651           minmaxtable = ftp->ftable;
3652         else return NOTOK;
3653       }
3654       if ((int) *p->iexptable > 0) {
3655         if (LIKELY((ftp = csound->FTnp2Finde(csound, p->iexptable)) != NULL))
3656           exptable = ftp->ftable;
3657         else return NOTOK;
3658       }
3659       if ((int) *p->itypetable > 0) {
3660         if (LIKELY((ftp = csound->FTnp2Finde(csound, p->itypetable)) != NULL))
3661           typetable = ftp->ftable;
3662         else return NOTOK;
3663       }
3664 
3665       for (int j =0; j< *p->inumsliders; j++) {
3666         string stemp;
3667         if (tempname == " ") {
3668           char s[40];
3669           sprintf(s, "%d", j);
3670           stemp = s;
3671         }
3672         else
3673           getline(sbuf, stemp, '@');
3674         char *Name =  new char[stemp.size()+2];
3675         strcpy(Name,stemp.c_str());
3676         widgetGlobals->allocatedStrings.push_back(Name);
3677 
3678         int x = (int) *p->ix,  y = (int) *p->iy + j*10;
3679         Fl_Slider *o;
3680         int slider_type;
3681         if ((int) *p->itypetable <= 0) {    // no slider type table
3682           if (*p->itypetable >= -7)         //  all sliders are of the same type
3683             slider_type = -((int) *p->itypetable);
3684           else if (*p->itypetable >= -27 && *p->itypetable < -20) {
3685             slider_type = -((int) *p->itypetable) - 20;
3686             plastic = true;
3687           }
3688           else                              // random type
3689             slider_type = rand_31_i(csound, 7) | 1;
3690         }
3691         else
3692           slider_type = (int) typetable[j];
3693         if (slider_type > 20) {
3694           plastic = true;
3695           slider_type -= 20;
3696         }
3697         if (slider_type < 10)
3698           o = new Fl_Slider(x, y, width, 10, Name);
3699         else {
3700           o = new Fl_Value_Slider_Input(csound, x, y, width, 10, Name);
3701           slider_type -=10;
3702           ((Fl_Value_Slider_Input*) o)->textboxsize(50);
3703           ((Fl_Value_Slider_Input*) o)->textsize(13);
3704         }
3705         switch((int) slider_type) { //type
3706         case 1: o->type(FL_HOR_FILL_SLIDER); break;
3707         case 3: o->type(FL_HOR_SLIDER); break;
3708         case 5: o->type(FL_HOR_NICE_SLIDER); o->box(FL_FLAT_BOX); break;
3709         case 7:  o->type(FL_HOR_NICE_SLIDER); o->box(FL_DOWN_BOX); break;
3710         default: o->type(FL_HOR_NICE_SLIDER); o->box(FL_FLAT_BOX); break;
3711         }
3712         if (plastic) o->box(FL_PLASTIC_DOWN_BOX);
3713         o->align(FL_ALIGN_LEFT);
3714         widget_attributes(csound, o);
3715         MYFLT min, max, range;
3716         if ((int) *p->iminmaxtable > 0) {
3717           min = minmaxtable[j*2];
3718           max = minmaxtable[j*2+1];
3719         }
3720         else {
3721           min = MYFLT(0.0);
3722           max = MYFLT(1.0);
3723         }
3724         int iexp;
3725 
3726         p->slider_data[j].min=min;
3727         p->slider_data[j].max=max;
3728         p->slider_data[j].out=&outable[j];
3729 
3730         if ((int) *p->iexptable <=0)
3731           // no table, all sliders have the same behaviour
3732           iexp = (int) *p->iexptable;
3733         else
3734           iexp = (int) exptable[j];
3735         switch (iexp) {
3736         case -1: iexp = EXP_; break;
3737         case 0: iexp = LIN_; break;
3738         }
3739 
3740         MYFLT val = 0;
3741         p->slider_data[j].exp = iexp;
3742         switch (iexp) {
3743         case LIN_: //linear
3744           o->range(min,max);
3745           o->callback((Fl_Callback*)fl_callbackLinearSliderBank,
3746                       (void *) &(p->slider_data[j]));
3747           val = outable[j];
3748           if (val > max) val = max;
3749           else if (val < min) val = min;
3750           break;
3751         case EXP_ : //exponential
3752           if (UNLIKELY(min == 0 || max == 0))
3753             return
3754               csound->InitError(csound,
3755                                 "%s", Str("FLslidBnk: zero is illegal "
3756                                     "in exponential operations"));
3757           range = max - min;
3758           o->range(0,range);
3759           #if defined(sun)
3760             p->slider_data[j].base = ::pow((max / (double)min), 1.0/(double)range);
3761           #else
3762             p->slider_data[j].base = ::pow((max / min), 1.0/(double)range);
3763           #endif
3764           o->callback((Fl_Callback*)fl_callbackExponentialSliderBank,
3765                       (void *) &(p->slider_data[j]));
3766           {
3767             val = outable[j];
3768             MYFLT range = max-min;
3769             #if defined(sun)
3770               MYFLT base = ::pow(max / (double)min, 1.0/(double)range);
3771             #else
3772               MYFLT base = ::pow(max / min, 1.0/(double)range);
3773             #endif
3774             val = (log(val/min) / log(base)) ;
3775           }
3776           break;
3777         default:
3778           {
3779             FUNC *ftp;
3780             MYFLT fnum = abs(iexp);
3781             if ((ftp = csound->FTnp2Finde(csound, &fnum)) != NULL)
3782               p->slider_data[j].table = ftp->ftable;
3783             else return NOTOK;
3784             p->slider_data[j].tablen = ftp->flen;
3785             o->range(0,0.99999999);
3786             if (iexp > 0) //interpolated
3787               o->callback((Fl_Callback*)fl_callbackInterpTableSliderBank,
3788                           (void *)  &(p->slider_data[j]));
3789             else // non-interpolated
3790               o->callback((Fl_Callback*)fl_callbackTableSliderBank,
3791                           (void *)  &(p->slider_data[j]));
3792           }
3793         }
3794         o->value(val);
3795       }
3796       w->resizable(w);
3797       if (*p->iwidth <=0 || *p->iheight <=0) {// default width and height
3798         int a,b;
3799         w->size( a= w->parent()->w() -50, b= w->parent()->h());
3800         w->position(50, 0);
3801       }
3802       else {
3803         w->size( (int)*p->iwidth, (int)*p->iheight);
3804         w->position((int)*p->ix, (int)*p->iy);
3805       }
3806       w->end();
3807       widgetGlobals->AddrSetValue.push_back(ADDR_SET_VALUE(LIN_, 0, 0, (void *) w,
3808                                                 (void *) p,
3809                                                 widgetGlobals->currentSnapGroup));
3810       // *p->ihandle = widgetGlobals->AddrSetValue.size()-1;
3811       widgetGlobals->last_sldbnk = widgetGlobals->AddrSetValue.size()-1;  //gab
3812       return OK;
3813   }
3814 
fl_slider_bank(CSOUND * csound,FLSLIDERBANK * p)3815   static int fl_slider_bank(CSOUND *csound, FLSLIDERBANK *p){
3816     return fl_slider_bank_(csound,p,0);
3817   }
3818 
fl_slider_bank_S(CSOUND * csound,FLSLIDERBANK * p)3819     static int fl_slider_bank_S(CSOUND *csound, FLSLIDERBANK *p){
3820     return fl_slider_bank_(csound,p,1);
3821   }
3822 
fl_joystick(CSOUND * csound,FLJOYSTICK * p)3823   static int fl_joystick(CSOUND *csound, FLJOYSTICK *p)
3824   {
3825       WIDGET_GLOBALS *widgetGlobals =
3826         (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS");
3827       char *Name = p->name->data;
3828       int ix,iy,iwidth, iheight, iexpx, iexpy;
3829 
3830       if (*p->ix < 0)  ix = 10; // omitted options: set default
3831       else  widgetGlobals->FL_ix = ix = (int) *p->ix;
3832       if (*p->iy < 0)  iy = 10; // omitted options: set default
3833       else  iy = (int) *p->iy;
3834       if (*p->iwidth < 0) iwidth = 130;
3835       else iwidth = (int) *p->iwidth;
3836       if (*p->iheight < 0) iheight = 130;
3837       else iheight = (int) *p->iheight;
3838 
3839       switch((int) *p->iexpx) {
3840       case -1: iexpx = EXP_; break;
3841       case 0: iexpx = LIN_; break;
3842       default: iexpx = (int) *p->iexpx;
3843       }
3844       switch((int) *p->iexpy) {
3845       case -1: iexpy = EXP_; break;
3846       case 0: iexpy = LIN_; break;
3847       default: iexpy = (int) *p->iexpy;
3848       }
3849       /*
3850         if (*p->iexpx == LIN_) iexpx = LIN_;
3851         else  iexpx = (int) *p->iexpx;
3852         if (*p->iexpy == LIN_) iexpy = LIN_;
3853         else  iexpy = (int) *p->iexpy;
3854       */
3855 
3856       Fl_Positioner *o = new Fl_Positioner(ix, iy, iwidth, iheight, Name);
3857       widget_attributes(csound, o);
3858       switch (iexpx) {
3859       case LIN_: //linear
3860         o->xbounds(*p->iminx,*p->imaxx); break;
3861       case EXP_: //exponential
3862         { if (UNLIKELY(*p->iminx == 0 || *p->imaxx == 0))
3863             return csound->InitError(csound,
3864                                      "%s", Str("FLjoy X axe: zero is illegal "
3865                                          "in exponential operations"));
3866           MYFLT range = *p->imaxx - *p->iminx;
3867           o->xbounds(0,range);
3868           #if defined(sun)
3869             p->basex = ::pow((*p->imaxx / (double)*p->iminx), 1.0/(double)range);
3870           #else
3871             p->basex = ::pow((*p->imaxx / *p->iminx), 1.0/(double)range);
3872           #endif
3873         } break;
3874       default:
3875         {
3876           FUNC *ftp;
3877           MYFLT fnum = abs(iexpx);
3878           if ((ftp = csound->FTnp2Finde(csound, &fnum)) != NULL) {
3879             p->tablex = ftp->ftable;
3880             p->tablenx = ftp->flen;
3881           }
3882           else return NOTOK;
3883           o->xbounds(0,0.99999999);
3884           /*
3885             if (iexp > 0) //interpolated
3886             o->callback((Fl_Callback*)fl_callbackInterpTableSlider,(void *) p);
3887             else // non-interpolated
3888             o->callback((Fl_Callback*)fl_callbackTableSlider,(void *) p);
3889           */
3890         }
3891       }
3892       switch (iexpy) {
3893       case LIN_: //linear
3894         o->ybounds(*p->imaxy,*p->iminy); break;
3895       case EXP_ : //exponential
3896         { if (UNLIKELY(*p->iminy == 0 || *p->imaxy == 0))
3897             return csound->InitError(csound,
3898                                      "%s", Str("FLjoy X axe: zero is illegal "
3899                                          "in exponential operations"));
3900           MYFLT range = *p->imaxy - *p->iminy;
3901           o->ybounds(range,0);
3902           #if defined(sun)
3903             p->basey = ::pow((*p->imaxy / (double)*p->iminy), 1.0/(double)range);
3904           #else
3905             p->basey = ::pow((*p->imaxy / *p->iminy), 1.0/(double)range);
3906           #endif
3907         } break;
3908       default:
3909         {
3910           FUNC *ftp;
3911           MYFLT fnum = abs(iexpy);
3912           if (LIKELY((ftp = csound->FTnp2Finde(csound, &fnum)) != NULL)) {
3913             p->tabley = ftp->ftable;
3914             p->tableny = ftp->flen;
3915           }
3916           else return NOTOK;
3917           o->ybounds(0,0.99999999);
3918           /*  if (iexp > 0) //interpolated
3919               o->callback((Fl_Callback*)fl_callbackInterpTableSlider,(void *) p);
3920               else // non-interpolated
3921               o->callback((Fl_Callback*)fl_callbackTableSlider,(void *) p);
3922           */
3923         }
3924       }
3925       o->align(FL_ALIGN_BOTTOM | FL_ALIGN_WRAP);
3926       o->callback((Fl_Callback*)fl_callbackJoystick,(void *) p);
3927       widgetGlobals->AddrSetValue.push_back(ADDR_SET_VALUE(iexpx, *p->iminx,
3928                                                 *p->imaxx, (void *) o, (void *) p,
3929                                                 widgetGlobals->currentSnapGroup));
3930       *p->ihandle1 = widgetGlobals->AddrSetValue.size()-1;
3931       ADDR_SET_VALUE *asv = &widgetGlobals->AddrSetValue[(int) *p->ihandle1];
3932       asv->widg_type = FL_JOY;
3933       asv->joy = JOY_X;
3934       widgetGlobals->AddrSetValue.push_back(ADDR_SET_VALUE(iexpy, *p->iminy,
3935                                                 *p->imaxy, (void *) o, (void *) p,
3936                                                 widgetGlobals->currentSnapGroup));
3937       *p->ihandle2 = widgetGlobals->AddrSetValue.size()-1;
3938       asv = &widgetGlobals->AddrSetValue[(int) *p->ihandle2];
3939       asv->widg_type = FL_JOY;
3940       asv->joy = JOY_Y;
3941       return OK;
3942   }
3943 
fl_knob(CSOUND * csound,FLKNOB * p)3944   static int fl_knob(CSOUND *csound, FLKNOB *p)
3945   {
3946       WIDGET_GLOBALS *widgetGlobals =
3947         (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS");
3948       char    *controlName = p->name->data;
3949       int     ix, iy, iwidth, itype, iexp;
3950 
3951       if (*p->iy < 0) iy = widgetGlobals->FL_iy;
3952       else  widgetGlobals->FL_iy = iy = (int) *p->iy;
3953       if (*p->ix < 0)  ix = widgetGlobals->FL_ix;
3954       else  widgetGlobals->FL_ix = ix = (int) *p->ix;
3955       if (*p->iwidth < 0) iwidth = widgetGlobals->FLcontrol_iwidth;
3956       else widgetGlobals->FLcontrol_iwidth = iwidth = (int) *p->iwidth;
3957       if (*p->itype < 1) itype = 1;
3958       else  itype = (int) *p->itype;
3959       /*
3960         if (*p->iexp < LIN_) iexp = LIN_;
3961         else  iexp = (int) *p->iexp;
3962       */
3963       switch((int) *p->iexp) {
3964       case -1: iexp = EXP_; break;
3965       case 0: iexp = LIN_; break;
3966       default: iexp = (int) *p->iexp;
3967       }
3968 
3969       Fl_Valuator* o;
3970       switch (itype) {
3971       case 1:
3972         o = new Fl_Knob(csound, ix, iy, iwidth, iwidth, controlName);
3973         o->box(FL_NO_BOX);
3974         if (*p->icursorsize > MYFLT(0.5))
3975           ((Fl_Knob*) o)->cursor((int) (*p->icursorsize + MYFLT(0.5)));
3976         break;
3977       case 2:
3978         o = new Fl_Dial(ix, iy, iwidth, iwidth, controlName);
3979         o->type(FL_FILL_DIAL);
3980         o->box(_FL_OSHADOW_BOX);
3981         ((Fl_Dial*) o)->angles(20, 340);
3982         break;
3983       case 3:
3984         o = new Fl_Dial(ix, iy, iwidth, iwidth, controlName);
3985         o->type(FL_LINE_DIAL);
3986         o->box(_FL_OSHADOW_BOX);
3987         break;
3988       case 4:
3989         o = new Fl_Dial(ix, iy, iwidth, iwidth, controlName);
3990         o->type(FL_NORMAL_DIAL);
3991         o->box(_FL_OSHADOW_BOX);
3992         break;
3993       default:
3994         return csound->InitError(csound,
3995                                  "%s", Str("FLknob: invalid knob type"));
3996       }
3997       widget_attributes(csound, o);
3998       o->align(FL_ALIGN_BOTTOM | FL_ALIGN_WRAP);
3999       o->range(*p->imin, *p->imax);
4000       switch (iexp) {
4001       case LIN_: //linear
4002         o->range(*p->imin,*p->imax);
4003         o->callback((Fl_Callback*)fl_callbackLinearKnob,(void *) p);
4004         o->step(0.001);
4005         break;
4006       case EXP_ : //exponential
4007         {
4008           MYFLT min = p->min = *p->imin, max = *p->imax;
4009           if (UNLIKELY(min == 0 || max == 0))
4010             return csound->InitError(csound,
4011                                      "%s", Str("FLknob: zero is illegal "
4012                                          "in exponential operations"));
4013           MYFLT range = max - min;
4014           o->range(0,range);
4015           #if defined(sun)
4016             p->base = ::pow((max / (double)min), 1.0/(double)range);
4017           #else
4018             p->base = ::pow((max / min), 1.0/(double)range);
4019           #endif
4020           o->callback((Fl_Callback*)fl_callbackExponentialKnob,(void *) p);
4021         } break;
4022       default:
4023         {
4024           FUNC *ftp;
4025           p->min = *p->imin;
4026           MYFLT fnum = abs(iexp);
4027           if ((ftp = csound->FTnp2Finde(csound, &fnum)) != NULL) {
4028             p->table = ftp->ftable;
4029             p->tablen = ftp->flen;
4030           }
4031           else return OK;
4032           o->range(0,0.99999999);
4033           if (iexp > 0) //interpolated
4034             o->callback((Fl_Callback*)fl_callbackInterpTableKnob,(void *) p);
4035           else // non-interpolated
4036             o->callback((Fl_Callback*)fl_callbackTableKnob,(void *) p);
4037         }
4038       }
4039       widgetGlobals->AddrSetValue.push_back(ADDR_SET_VALUE(iexp, *p->imin, *p->imax,
4040                                                 (void *) o, (void *) p));
4041       *p->ihandle = widgetGlobals->AddrSetValue.size()-1;
4042       return OK;
4043   }
4044 
fl_text(CSOUND * csound,FLTEXT * p)4045   static int fl_text(CSOUND *csound, FLTEXT *p)
4046   {
4047       WIDGET_GLOBALS *widgetGlobals =
4048         (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS");
4049       char *controlName = p->name->data;
4050       int ix,iy,iwidth,iheight,itype;
4051       MYFLT   istep;
4052 
4053       if (*p->iy < 0) iy = widgetGlobals->FL_iy;
4054       else  widgetGlobals->FL_iy = iy = (int) *p->iy;
4055       if (*p->ix < 0)  ix = widgetGlobals->FL_ix;
4056       else  widgetGlobals->FL_ix = ix = (int) *p->ix;
4057       if (*p->iwidth < 0) iwidth = widgetGlobals->FLcontrol_iwidth;
4058       else widgetGlobals->FLcontrol_iwidth = iwidth = (int) *p->iwidth;
4059       if (*p->iheight < 0) iheight = widgetGlobals->FLcontrol_iheight;
4060       else widgetGlobals->FLcontrol_iheight = iheight = (int) *p->iheight;
4061       if (*p->itype < 1) itype = 1;
4062       else  itype = (int) *p->itype;
4063       if (*p->istep < 0) istep = MYFLT(.1);
4064       else  istep = *p->istep;
4065 
4066       Fl_Valuator* o;
4067       switch(itype) {
4068       case 1:
4069         {
4070           o = new Fl_Value_Input(ix, iy, iwidth, iheight, controlName);
4071           ((Fl_Value_Input *) o)->step(istep);
4072           ((Fl_Value_Input *) o)->range(*p->imin,*p->imax);
4073         }
4074         break;
4075       case 2:
4076         {
4077           o = new Fl_Value_Input_Spin(csound, ix, iy,
4078                                       iwidth, iheight, controlName);
4079           ((Fl_Value_Input *) o)->step(istep);
4080           ((Fl_Value_Input *) o)->range(*p->imin,*p->imax);
4081         }
4082         break;
4083       case 3:
4084         {
4085           o = new Fl_Value_Output(ix, iy, iwidth, iheight, controlName);
4086           ((Fl_Value_Output *) o)->step(istep);
4087           ((Fl_Value_Output *) o)->range(*p->imin,*p->imax);
4088         }
4089         break;
4090       default:
4091         return NOTOK;
4092       }
4093       o->align(FL_ALIGN_BOTTOM | FL_ALIGN_WRAP);
4094       widget_attributes(csound, o);
4095       o->callback((Fl_Callback*)fl_callbackLinearValueInput,(void *) p);
4096       widgetGlobals->AddrSetValue.push_back(ADDR_SET_VALUE(1, *p->imin, *p->imax,
4097                                                 (void *) o, (void *) p,
4098                                                 widgetGlobals->currentSnapGroup));
4099       *p->ihandle = widgetGlobals->AddrSetValue.size()-1;
4100       return OK;
4101   }
4102 
fl_button(CSOUND * csound,FLBUTTON * p)4103   static int fl_button(CSOUND *csound, FLBUTTON *p)
4104   {
4105       WIDGET_GLOBALS *widgetGlobals =
4106         (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS");
4107       char *Name = p->name->data;
4108       int type = (int) *p->itype;
4109       bool plastic = false;
4110       if (type > 19) {
4111         type = type - 20;
4112         plastic = true;
4113       }
4114       if (UNLIKELY(type > 9)) {  // ignored when getting widgetGlobals->snapshots
4115         csound->Warning(csound,
4116                         Str("FLbutton \"%s\" ignoring snapshot capture retrieve"),
4117                         Name);
4118         type = type - 10;
4119       }
4120       Fl_Button *w;
4121       *p->kout = *p->ioff;        // IV - Aug 27 2002
4122 
4123       switch (type) {
4124       case 1:
4125         w = new Fl_Button((int)*p->ix, (int)*p->iy,
4126                           (int)*p->iwidth, (int)*p->iheight, Name);
4127         if (plastic) {
4128           w->box(FL_PLASTIC_UP_BOX);
4129           w->down_box(FL_PLASTIC_DOWN_BOX);
4130         }
4131         break;
4132       case 2:
4133         w = new Fl_Light_Button((int)*p->ix, (int)*p->iy,
4134                                 (int)*p->iwidth, (int)*p->iheight, Name);
4135         if (plastic) {
4136           w->box(FL_PLASTIC_UP_BOX);
4137           //       w->down_box(FL_PLASTIC_DOWN_BOX);  //Doesn't work
4138         }
4139         break;
4140       case 3:
4141         w = new Fl_Check_Button((int)*p->ix, (int)*p->iy,
4142                                 (int)*p->iwidth, (int)*p->iheight, Name);
4143         if (plastic) {
4144           w->box(FL_PLASTIC_UP_BOX);
4145           w->down_box(FL_PLASTIC_DOWN_BOX);
4146         }
4147         break;
4148       case 4:
4149         w = new Fl_Round_Button((int)*p->ix, (int)*p->iy,
4150                                 (int)*p->iwidth, (int)*p->iheight, Name);
4151         if (plastic) {
4152           w->box(FL_PLASTIC_UP_BOX);
4153           w->down_box(FL_PLASTIC_DOWN_BOX);
4154         }
4155         break;
4156       default:
4157         return csound->InitError(csound,
4158                                  "%s", Str("FLbutton: invalid button type"));
4159       }
4160       Fl_Button *o = w;
4161       o->align(FL_ALIGN_WRAP);
4162       widget_attributes(csound, o);
4163       if (type == 1)
4164         o->callback((Fl_Callback*) fl_callbackButton1, (void*) p);
4165       else
4166         o->callback((Fl_Callback*) fl_callbackButton, (void*) p);
4167       widgetGlobals->AddrSetValue.push_back(ADDR_SET_VALUE(0, 0, 0, (void *) o,
4168                                                  (void *) p,
4169                                                  widgetGlobals->currentSnapGroup));
4170       *p->ihandle = widgetGlobals->AddrSetValue.size() - 1;
4171 
4172       return OK;
4173   }
4174 
fl_close_button(CSOUND * csound,FLCLOSEBUTTON * p)4175   static int fl_close_button(CSOUND *csound, FLCLOSEBUTTON *p)
4176   {
4177       WIDGET_GLOBALS *widgetGlobals =
4178         (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS");
4179       char *Name = p->name->data;
4180 
4181       Fl_Button *w;
4182 
4183       w = new Fl_Button((int)*p->ix, (int)*p->iy,
4184                         (int)*p->iwidth, (int)*p->iheight, Name);
4185 
4186       Fl_Button *o = w;
4187 
4188       o->align(FL_ALIGN_WRAP);
4189       widget_attributes(csound, o);
4190 
4191       ADDR_STACK adrstk = widgetGlobals->AddrStack.back();
4192       if (UNLIKELY(strcmp( adrstk.h->optext->t.opcod, "FLpanel")))
4193         return csound->InitError(csound,
4194                                  "%s", Str("FLcloseButton: invalid stack"
4195                                      " pointer: verify its placement"));
4196 
4197       o->callback((Fl_Callback*) fl_callbackCloseButton,
4198                   (void*) adrstk.WidgAddress);
4199 
4200       widgetGlobals->AddrSetValue.push_back(ADDR_SET_VALUE(0, 0, 0, (void *) o,
4201                                                            (void *) p));
4202       *p->ihandle = widgetGlobals->AddrSetValue.size() - 1;
4203 
4204       return OK;
4205   }
4206 
fl_exec_button(CSOUND * csound,FLEXECBUTTON * p)4207   static int fl_exec_button(CSOUND *csound, FLEXECBUTTON *p)
4208   {
4209       WIDGET_GLOBALS *widgetGlobals =
4210         (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS");
4211       p->csound = csound;
4212       Fl_Button *w;
4213 
4214       p->commandString = p->command->data;
4215 
4216       csound->Message(csound, Str("Command Found: %s\n"), p->commandString);
4217 
4218       w = new Fl_Button((int)*p->ix, (int)*p->iy,
4219                         (int)*p->iwidth, (int)*p->iheight, Str("About"));
4220 
4221       Fl_Button *o = w;
4222 
4223       o->align(FL_ALIGN_WRAP);
4224       widget_attributes(csound, o);
4225 
4226       o->callback((Fl_Callback*) fl_callbackExecButton, (void*) p);
4227 
4228       widgetGlobals->AddrSetValue.push_back(ADDR_SET_VALUE(0, 0, 0,
4229                                                  (void *) o, (void *) p,
4230                                                  widgetGlobals->currentSnapGroup));
4231       *p->ihandle = widgetGlobals->AddrSetValue.size() - 1;
4232 
4233       return OK;
4234   }
4235 
fl_button_bank(CSOUND * csound,FLBUTTONBANK * p)4236   static int fl_button_bank(CSOUND *csound, FLBUTTONBANK *p)
4237   {
4238       WIDGET_GLOBALS *widgetGlobals =
4239         (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS");
4240       char *Name = (char*)"/0";
4241       int type = (int) *p->itype;
4242       bool plastic = false;
4243       if (type > 20) {
4244         plastic = true;
4245         type = type - 20;
4246       }
4247       if (UNLIKELY(type > 9)) { // ignored when getting widgetGlobals->snapshots
4248         csound->Warning(csound,
4249                         Str("FLbutton \"%s\" ignoring snapshot capture retrieve"),
4250                         Name);
4251         type = type - 10;
4252       }
4253       Fl_Group* o = new Fl_Group((int)*p->ix, (int)*p->iy,
4254                                  (int)*p->inumx * 10, (int)*p->inumy*10);
4255       int z = 0;
4256       for (int j = 0; j < *p->inumx; j++) {
4257         for (int k = 0; k < *p->inumy; k++) {
4258           int       x = (int) *p->ix + j*10, y = (int) *p->iy + k*10;
4259           Fl_Button *w;
4260           char      *btName = new char[30];
4261           widgetGlobals->allocatedStrings.push_back(btName);
4262           sprintf(btName, "%d", z);
4263           switch (type) {
4264           case 1:
4265             w = new Fl_Button(x, y, 10, 10, btName);
4266             if (plastic) {
4267               w->box(FL_PLASTIC_UP_BOX);
4268               w->down_box(FL_PLASTIC_DOWN_BOX);
4269             }
4270             break;
4271           case 2:
4272             w = new Fl_Light_Button(x, y, 10, 10, btName);
4273             if (plastic) {
4274               w->box(FL_PLASTIC_UP_BOX);
4275             }
4276             break;
4277           case 3:
4278             w = new Fl_Check_Button(x, y, 10, 10, btName);
4279             if (plastic) {
4280               w->box(FL_PLASTIC_UP_BOX);
4281               w->down_box(FL_PLASTIC_DOWN_BOX);
4282             }
4283             break;
4284           case 4:
4285             w = new Fl_Round_Button(x, y, 10, 10, btName);
4286             if (plastic) {
4287               w->box(FL_PLASTIC_UP_BOX);
4288               w->down_box(FL_PLASTIC_DOWN_BOX);
4289             }
4290             break;
4291           default: return csound->InitError(csound,
4292                                             "%s", Str("FLbuttonBank: "
4293                                                 "invalid button type"));
4294           }
4295           widget_attributes(csound, w);
4296           w->type(FL_RADIO_BUTTON);
4297           w->callback((Fl_Callback*) fl_callbackButtonBank, (void *) p);
4298           if (!z)
4299             w->value(1);
4300           z++;
4301         }
4302       }
4303       o->resizable(o);
4304       // *p->ix, *p->iy,
4305       o->size( (int)*p->iwidth, (int)*p->iheight);
4306       o->position((int)*p->ix, (int)*p->iy);
4307       o->align(FL_ALIGN_BOTTOM | FL_ALIGN_WRAP);
4308       o->end();
4309 
4310       widgetGlobals->AddrSetValue.push_back(ADDR_SET_VALUE(0, 0, 0,
4311                                                  (void *) o, (void *) p,
4312                                                  widgetGlobals->currentSnapGroup));
4313       *p->kout = MYFLT(0.0);
4314       *p->ihandle = widgetGlobals->AddrSetValue.size()-1;
4315       return OK;
4316   }
4317 
fl_counter(CSOUND * csound,FLCOUNTER * p)4318   static int fl_counter(CSOUND *csound, FLCOUNTER *p)
4319   {
4320       char *controlName = p->name->data;
4321       //      int ix,iy,iwidth,iheight,itype;
4322       //      MYFLT   istep1, istep2;
4323       WIDGET_GLOBALS *widgetGlobals =
4324         (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS");
4325       Fl_Counter* o = new Fl_Counter((int)*p->ix, (int)*p->iy,
4326                                      (int)*p->iwidth, (int)*p->iheight,
4327                                      controlName);
4328       widget_attributes(csound, o);
4329       int type = (int) *p->itype;
4330       if (UNLIKELY(type >9 )) { // ignored when getting widgetGlobals->snapshots
4331         csound->Warning(csound,
4332                         Str("FLcount \"%s\" ignoring snapshot capture retrieve"),
4333                         controlName);
4334         type = type-10;
4335       }
4336       switch(type) {
4337       case 1: o->type(FL_NORMAL_COUNTER);  break;
4338       case 2: o->type(FL_SIMPLE_COUNTER);  break;
4339       default:o->type(FL_NORMAL_COUNTER);  break;
4340       }
4341 
4342       o->step(*p->istep1);
4343       o->lstep(*p->istep2);
4344       o->align(FL_ALIGN_BOTTOM | FL_ALIGN_WRAP);
4345       // range is accepted only if min and max are different
4346       if (*p->imin != *p->imax)
4347         o->range(*p->imin,*p->imax); //otherwise no-range
4348       widget_attributes(csound, o);
4349       o->callback((Fl_Callback*)fl_callbackCounter,(void *) p);
4350       widgetGlobals->AddrSetValue.push_back(ADDR_SET_VALUE(1, 0, 100000, (void *) o,
4351                                                  (void *) p,
4352                                                  widgetGlobals->currentSnapGroup));
4353       *p->ihandle = widgetGlobals->AddrSetValue.size()-1;
4354       return OK;
4355   }
4356 
fl_roller(CSOUND * csound,FLROLLER * p)4357   static int fl_roller(CSOUND *csound, FLROLLER *p)
4358   {
4359       char *controlName = p->name->data;
4360       int ix,iy,iwidth, iheight,itype, iexp ;
4361       double istep;
4362       WIDGET_GLOBALS *widgetGlobals =
4363         (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS");
4364       if (*p->iy < 0) {
4365         iy = widgetGlobals->FL_iy;
4366         widgetGlobals->FL_iy += widgetGlobals->FLroller_iheight + 15;
4367       }
4368       else {
4369         iy = (int) *p->iy;
4370         widgetGlobals->FL_iy = iy + widgetGlobals->FLroller_iheight + 15;
4371       }
4372       // omitted options: set defaults
4373       if (*p->ix<0) ix = widgetGlobals->FL_ix;
4374       else  widgetGlobals->FL_ix = ix = (int) *p->ix;
4375       if (*p->iy<0) iy = widgetGlobals->FL_iy;
4376       else  widgetGlobals->FL_iy = iy = (int) *p->iy;
4377       if (*p->iwidth<0) iwidth = widgetGlobals->FLroller_iwidth;
4378       else widgetGlobals->FLroller_iwidth = iwidth = (int) *p->iwidth;
4379       if (*p->iheight<0) iheight = widgetGlobals->FLroller_iheight;
4380       else widgetGlobals->FLroller_iheight = iheight = (int) *p->iheight;
4381       if (*p->itype<1) itype = 1;
4382       else  itype = (int) *p->itype;
4383       //if (*p->iexp<LIN_) iexp = LIN_;
4384       //else  iexp = (int) *p->iexp;
4385       switch((int) *p->iexp) {
4386       case -1: iexp = EXP_; break;
4387       case 0: iexp = LIN_; break;
4388       default: iexp = (int) *p->iexp;
4389       }
4390 
4391       if (*p->istep<0) istep = 1;     else  istep =  *p->istep;
4392       p->min = *p->imin;
4393       Fl_Roller *o;
4394       switch (itype) {
4395       case 1:
4396         o = new Fl_Roller(ix, iy, iwidth, iheight, controlName);
4397         o->type(FL_HORIZONTAL);
4398         break;
4399       case 2:
4400         o = new Fl_Roller(ix, iy, iwidth, iheight, controlName);
4401         o->type(FL_VERTICAL);
4402         break;
4403       default:
4404         return csound->InitError(csound,
4405                                  "%s", Str("FLroller: invalid roller type"));
4406       }
4407       widget_attributes(csound, o);
4408       o->step(istep);
4409       switch (iexp) {
4410       case LIN_: //linear
4411         o->range(*p->imin,*p->imax);
4412         o->callback((Fl_Callback*)fl_callbackLinearRoller,(void *) p);
4413         break;
4414       case EXP_ : //exponential
4415         {
4416           MYFLT min = p->min, max = *p->imax;
4417           if (UNLIKELY(min == 0 || max == 0))
4418             return csound->InitError(csound,
4419                                      "%s", Str("FLslider: zero is illegal "
4420                                          "in exponential operations"));
4421           MYFLT range = max - min;
4422           o->range(0,range);
4423           #if defined(sun)
4424             p->base = ::pow((max / (double)min), 1.0/(double)range);
4425           #else
4426             p->base = ::pow((max / min), 1.0/(double)range);
4427           #endif
4428           o->callback((Fl_Callback*)fl_callbackExponentialRoller,(void *) p);
4429         }
4430         break;
4431       default:
4432         {
4433           FUNC *ftp;
4434           MYFLT fnum = abs(iexp);
4435           if ((ftp = csound->FTnp2Finde(csound, &fnum)) != NULL) {
4436             p->table = ftp->ftable;
4437             p->tablen = ftp->flen;
4438           }
4439           else return NOTOK;
4440           o->range(0,0.99999999);
4441           if (iexp > 0) //interpolated
4442             o->callback((Fl_Callback*)fl_callbackInterpTableRoller,(void *) p);
4443           else // non-interpolated
4444             o->callback((Fl_Callback*)fl_callbackTableRoller,(void *) p);
4445         }
4446       }
4447       widgetGlobals->AddrSetValue.push_back(ADDR_SET_VALUE(iexp, *p->imin, *p->imax,
4448                                                 (void *) o, (void *) p,
4449                                                 widgetGlobals->currentSnapGroup));
4450       *p->ihandle = widgetGlobals->AddrSetValue.size()-1;
4451       return OK;
4452   }
4453 
FLprintkset(CSOUND * csound,FLPRINTK * p)4454   static int FLprintkset(CSOUND *csound, FLPRINTK *p)
4455   {
4456     //WIDGET_GLOBALS *widgetGlobals =
4457     //(WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS");
4458     if (*p->ptime < MYFLT(1.0) / CS_EKR)
4459       p->ctime = MYFLT(1.0) / CS_EKR;
4460       else        p->ctime = *p->ptime;
4461 
4462     p->initime = (MYFLT) csound->GetKcounter(csound) * (1.0/CS_EKR);
4463       p->cysofar = -1;
4464       return OK;
4465   }
4466 
FLprintk(CSOUND * csound,FLPRINTK * p)4467   static int FLprintk(CSOUND *csound, FLPRINTK *p)
4468   {
4469       MYFLT   timel;
4470       long    cycles;
4471       WIDGET_GLOBALS *widgetGlobals =
4472         (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS");
4473 
4474       timel = ((MYFLT) csound->GetKcounter(csound) *
4475                (1.0/CS_EKR)) - p->initime;
4476       cycles = (long)(timel / p->ctime);
4477       if (p->cysofar < cycles) {
4478         p->cysofar = cycles;
4479         char valString[MAXNAME];
4480         sprintf(valString,"%.5g", *p->val);
4481         ((Fl_Output*) (widgetGlobals->AddrSetValue[(long) *p->idisp]).WidgAddress)->
4482           value(valString );
4483       }
4484       return OK;
4485   }
4486 
FLprintk2set(CSOUND * csound,FLPRINTK2 * p)4487   static int FLprintk2set(CSOUND *csound, FLPRINTK2 *p)   // IV - Aug 27 2002
4488   {
4489     IGN(csound);
4490       p->oldvalue = MYFLT(-1.12123e35);        // hack to force printing first value
4491       return OK;
4492   }
4493 
FLprintk2(CSOUND * csound,FLPRINTK2 * p)4494   static int FLprintk2(CSOUND *csound, FLPRINTK2 *p)
4495   {
4496       MYFLT   value = *p->val;
4497       WIDGET_GLOBALS *widgetGlobals =
4498         (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS");
4499       if (p->oldvalue != value) {
4500         char valString[MAXNAME];
4501         sprintf(valString,"%.5g", *p->val);
4502         ((Fl_Output*) (widgetGlobals->AddrSetValue[(long) *p->idisp]).WidgAddress)->
4503           value(valString );
4504         p->oldvalue = value;
4505       }
4506       return OK;
4507   }
4508 
4509   // New opcodes for Csound5.06 by Gabriel Maldonado, ported by Andres Cabrera
4510 
skin(CSOUND * csound,Fl_Widget * o,int imgNum,bool isTiled)4511   void skin(CSOUND* csound, Fl_Widget *o, int imgNum, bool isTiled)
4512   {
4513     IGN(csound);  IGN(o); IGN(imgNum); IGN(isTiled);
4514     // WIDGET_GLOBALS *widgetGlobals =
4515     //  (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS");
4516 #ifdef CS_IMAGE
4517       extern void* get_image(CSOUND* csound, int imgNum);
4518       ImageSTRUCT *bmp =  (ImageSTRUCT*) get_image(csound, imgNum);
4519       FLlock();
4520       Fl_RGB_Image *img = new Fl_RGB_Image((BYTE*) (bmp->data),
4521                                            bmp->xsize,bmp->ysize,bmp->csize);
4522       widgetGlobals->allocatedStrings.push_back((char *) img);
4523       if (isTiled) {
4524         Fl_Tiled_Image *t_img = new Fl_Tiled_Image(img);
4525         o->image(t_img);
4526         widgetGlobals->allocatedStrings.push_back((char *) t_img);
4527       }
4528       else {
4529         o->image(img);
4530       }
4531       o->align(FL_ALIGN_INSIDE);
4532       FLunlock();
4533 #endif
4534   }
4535 
4536   class HVS_BOX : public Fl_Box{
4537     int rx,ry,rw,rh;
4538     int red, green, blue;
4539     //      Fl_PNG_Image *img;
4540   public:
4541 
4542     int numLinesX,numLinesY;
4543     MYFLT valueX, valueY;
4544 
HVS_BOX(int numLinesX_,int numLinesY_,int x,int y,int w,int h)4545     HVS_BOX(int numLinesX_, int numLinesY_, int x, int y, int w, int h) :
4546       Fl_Box(x,y,w,h) {
4547         numLinesX = numLinesX_ - 1;
4548         numLinesY = numLinesY_ - 1;
4549         valueX = valueY = .5;
4550         rx = rw = ry = rh = 0;
4551         red = green = blue = 0;
4552         //      if (filename != NULL) {
4553         //       img = new Fl_PNG_Image(filename);
4554         //       this->image(img);
4555         //      }
4556     }
draw()4557     void  draw() {
4558         Fl_Box::draw();
4559 
4560         fl_color(selection_color());
4561         MYFLT Xincr = w()/(MYFLT) numLinesX;
4562         MYFLT Yincr = h()/(MYFLT) numLinesY;
4563         fl_color(FL_RED);
4564         for (int j = 1; j < numLinesX; j++) {
4565           fl_yxline((int) (j*Xincr+x()), y(),    h()+y());
4566         }
4567         for (int k = 1; k <numLinesY; k++) {
4568           fl_xyline(x(), (int) (k*Yincr+y()), w()+x()-2);
4569         }
4570         fl_color(FL_CYAN);
4571         fl_yxline((int) (valueX*w()+x()), y(),    h()+y());
4572         fl_xyline(x(), (int) (valueY*h()+y()), w()+x()-2);
4573         fl_color(FL_BLACK);
4574         fl_rect((int) (valueX*w()+x()-6), (int) (valueY*h()+y()-6), 12, 12);
4575         fl_color(FL_WHITE);
4576         fl_rect((int) (valueX*w()+x()-10), (int) (valueY*h()+y()-10), 20, 20);
4577     }
4578 
handle(int event)4579     virtual int handle(int event) {
4580         switch (event) {
4581         case FL_PUSH:
4582         case FL_DRAG:
4583         case FL_RELEASE:
4584           valueX = (MYFLT) (Fl::event_x() - x()) / (MYFLT) w();
4585           valueY = (MYFLT) (Fl::event_y() - y()) / (MYFLT) h();
4586           redraw();
4587           return 1;
4588         default:
4589           return 0;
4590 
4591         }
4592     }
setXY(MYFLT xx,MYFLT yy)4593     void setXY(MYFLT xx, MYFLT yy) {
4594         valueX = xx;
4595         valueY = yy;
4596         damage(FL_DAMAGE_ALL);
4597         redraw();
4598     }
4599 
4600     /*
4601       void set_rect (int newrx, int newry, int newrw, int newrh) {
4602       rx = newrx; ry=newry; rw=newrw; rh=newrh;
4603       redraw();
4604       }
4605       void set_color (int newred, int newgreen, int newblue){
4606       red=newred; blue=newblue; green=newgreen;
4607       }
4608     */
4609   };
4610 
fl_hvsbox(CSOUND * csound,FL_HVSBOX * p)4611   static int fl_hvsbox(CSOUND *csound,FL_HVSBOX *p)
4612   {
4613       WIDGET_GLOBALS *widgetGlobals =
4614         (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS");
4615       if (UNLIKELY(*p->numlinesX < 2 || *p->numlinesY < 2))
4616         return csound->InitError(csound,
4617                                  "%s", Str("FLhvsBox: a square area must be"
4618                                      " delimited by 2 lines at least"));
4619 
4620       HVS_BOX *o =  new HVS_BOX((int) *p->numlinesX,(int)  *p->numlinesY,
4621                                 (int) *p->ix,(int)  *p->iy,
4622                                 (int)  *p->iwidth, (int) *p->iheight);
4623       widget_attributes(csound,o);
4624       o->box(FL_DOWN_BOX);
4625       if (*p->image >= 0) skin(csound, o, (int) *p->image, false);
4626 
4627       widgetGlobals->AddrSetValue.push_back(ADDR_SET_VALUE(0, 0, 0,
4628                                                  (void *) o, (void *) p,
4629                                                  widgetGlobals->currentSnapGroup));
4630       *p->ihandle = widgetGlobals->AddrSetValue.size()-1;
4631       return OK;
4632 
4633   }
4634 
fl_setHvsValue_set(CSOUND * csound,FL_SET_HVS_VALUE * p)4635   static int fl_setHvsValue_set(CSOUND *csound,FL_SET_HVS_VALUE *p)
4636   {
4637     IGN(csound);
4638       WIDGET_GLOBALS *widgetGlobals =
4639         (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS");
4640       ADDR_SET_VALUE v = widgetGlobals->AddrSetValue[(int) *p->ihandle];
4641       p->WidgAddress = v.WidgAddress;
4642       p->opcode = v.opcode;
4643       return OK;
4644   }
4645 
fl_setHvsValue(CSOUND * csound,FL_SET_HVS_VALUE * p)4646   static int fl_setHvsValue(CSOUND *csound,FL_SET_HVS_VALUE *p)
4647   {
4648     IGN(csound);
4649       if(*p->kx != p->old_x || *p->ky != p->old_y ) {
4650         HVS_BOX *o = (HVS_BOX *) p->WidgAddress;
4651         FLlock();
4652         o->setXY(*p->kx, *p->ky);
4653         FLunlock();
4654         p->old_x = *p->kx;
4655         p->old_y = *p->ky;
4656       }
4657       return OK;
4658   }
4659 
4660 
fl_keyin_set(CSOUND * csound,FLKEYIN * p)4661   static int fl_keyin_set(CSOUND *csound,FLKEYIN *p)
4662   {
4663       FUNC* ftp;
4664       if (*p->ifn > 0) { // mapping values
4665         p->flag = 1;
4666 
4667         if (LIKELY((ftp = csound->FTnp2Finde(csound,p->ifn)) != NULL))
4668           p->table = ftp->ftable;
4669         else {
4670           return csound->InitError(csound,
4671                                    "%s", Str("FLkeyIn: invalid table number"));
4672         }
4673         if (UNLIKELY(ftp->flen < 512)) {
4674           return csound->InitError(csound,
4675                                    "%s", Str("FLkeyIn: table too short!"));
4676         }
4677       }
4678       else p->flag = 0;
4679       return OK;
4680   }
4681 
fl_keyin(CSOUND * csound,FLKEYIN * p)4682   static int fl_keyin(CSOUND *csound,FLKEYIN *p)
4683   {
4684      WIDGET_GLOBALS *widgetGlobals =
4685        (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS");
4686      if (widgetGlobals->last_KEY) {
4687         int key;
4688 
4689         if ( widgetGlobals->last_KEY > 0 && widgetGlobals->last_KEY < 256)
4690           key = widgetGlobals->last_KEY;
4691         else
4692           key = (widgetGlobals->last_KEY & 0xFF) + 256;  // function keys
4693 
4694         if(p->flag) {
4695           if(widgetGlobals->isKeyDown)
4696             p->table[key] = 1;
4697           else
4698             p->table[key] = 0;
4699         }
4700         if (widgetGlobals->isKeyDown) *p->kascii = key;
4701         else *p->kascii = -key;
4702         widgetGlobals->last_KEY = 0;
4703       }
4704       return OK;
4705   }
4706 
fl_setSnapGroup(CSOUND * csound,FLSETSNAPGROUP * p)4707   static int fl_setSnapGroup(CSOUND *csound, FLSETSNAPGROUP *p)
4708   {
4709      IGN(csound);
4710       WIDGET_GLOBALS *widgetGlobals =
4711         (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS");
4712       widgetGlobals->currentSnapGroup = (int) *p->group;
4713       return OK;
4714   }
4715 
fl_mouse_set(CSOUND * csound,FLMOUSE * p)4716   static int fl_mouse_set(CSOUND *csound,FLMOUSE *p)
4717   {
4718      IGN(csound);
4719       p->width= Fl::w();
4720       p->height= Fl::h();
4721       return OK;
4722   }
4723 
fl_mouse(CSOUND * csound,FLMOUSE * p)4724   static int fl_mouse(CSOUND *csound,FLMOUSE *p)
4725   {
4726      IGN(csound);
4727       if (*p->flagRaw == 0) {
4728         *p->x = (MYFLT) Fl::event_x_root()/p->width;
4729         *p->y = 1.0 - ((MYFLT) Fl::event_y_root()/p->height);
4730       }
4731       else if (*p->flagRaw == 1) {
4732         *p->x = (MYFLT) Fl::event_x_root();
4733         *p->y = (MYFLT) Fl::event_y_root();
4734       }
4735       else if (*p->flagRaw == 2) {
4736         *p->x = (MYFLT) Fl::event_x();
4737         *p->y = (MYFLT) Fl::event_y();
4738       }
4739       //   *p->b1 = (MYFLT) (Fl::event_button1() >> 56);
4740       //   *p->b2 = (MYFLT) (Fl::event_button2() >> 57);
4741       //   *p->b3 = (MYFLT) (Fl::event_button3() >> 58);
4742       *p->b1 = (MYFLT) (Fl::event_button1() >> 24);
4743       *p->b2 = (MYFLT) (Fl::event_button2() >> 25);
4744       *p->b3 = (MYFLT) (Fl::event_button3() >> 26);
4745 
4746       return OK;
4747   }
4748 
4749 
fl_vertical_slider_bank_(CSOUND * csound,FLSLIDERBANK * p,int istring)4750   static int fl_vertical_slider_bank_(CSOUND *csound, FLSLIDERBANK *p, int istring)
4751   {
4752      WIDGET_GLOBALS *widgetGlobals =
4753        (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS");
4754       char s[MAXNAME];
4755       bool plastic = false;
4756       if (istring)
4757         strncpy(s, ((STRINGDAT *)p->names)->data, MAXNAME-1);
4758       else if ((long) *p->names <= csound->GetStrsmax(csound) &&
4759                csound->GetStrsets(csound,(long) *p->names)) {
4760         strncpy(s, csound->GetStrsets(csound,(long) *p->names), MAXNAME-1);
4761       }
4762       string tempname(s);
4763       stringstream sbuf;
4764       sbuf << tempname;
4765 
4766       int height = (int) *p->iheight;
4767       if (height <=0) height = 100;
4768       Fl_Group* w = new Fl_Group((int)*p->ix, (int)*p->iy,
4769                                  (int)*p->inumsliders*10, height);
4770       FUNC *ftp;
4771       MYFLT *minmaxtable = NULL, *typetable = NULL, *outable, *exptable = NULL;
4772 
4773       MYFLT *zkstart;
4774       int zklast = csound->GetZakBounds(csound, &zkstart);
4775       if (*p->ioutable  < 1) {
4776         if (LIKELY(zkstart != NULL &&
4777                    zklast > (long)(*p->inumsliders+*p->ioutablestart_ndx)))
4778           outable = zkstart + (long) *p->ioutablestart_ndx;
4779         else {
4780           return csound->InitError(csound,
4781                                    "%s", Str("invalid ZAK space allocation"));
4782         }
4783       }
4784       else {
4785         if (LIKELY((ftp = csound->FTnp2Finde(csound, p->ioutable)) != NULL))
4786           outable = ftp->ftable + (long) *p->ioutablestart_ndx;
4787         else
4788           return NOTOK;
4789       }
4790       if ((int) *p->iminmaxtable > 0) {
4791         if (LIKELY((ftp = csound->FTnp2Finde(csound, p->iminmaxtable)) != NULL))
4792           minmaxtable = ftp->ftable;
4793         else return NOTOK;
4794       }
4795       if ((int) *p->iexptable > 0) {
4796         if (LIKELY((ftp = csound->FTnp2Finde(csound, p->iexptable)) != NULL))
4797           exptable = ftp->ftable;
4798         else return NOTOK;
4799       }
4800       if ((int) *p->itypetable > 0) {
4801         if (LIKELY((ftp = csound->FTnp2Finde(csound, p->itypetable)) != NULL))
4802           typetable = ftp->ftable;
4803         else return NOTOK;
4804       }
4805       p->elements = (long) *p->inumsliders;
4806 
4807       for (int j =0; j< p->elements; j++) {
4808         string stemp;
4809         if (tempname == " ") {
4810           char s[40];
4811           sprintf(s, "%d", j);
4812           stemp = s;
4813         }
4814         else
4815           getline(sbuf, stemp, '@');
4816         char *Name =  new char[stemp.size()+2];
4817         strcpy(Name,stemp.c_str());
4818         widgetGlobals->allocatedStrings.push_back(Name);
4819 
4820         int x = (int) *p->ix+j*10,  y = (int) *p->iy /*+ j*10*/;
4821         Fl_Slider *o;
4822         int slider_type;
4823         if ((int) *p->itypetable <= 0) {    // no slider type table
4824           if (*p->itypetable >= -7)         //  all sliders are of the same type
4825             slider_type = -((int) *p->itypetable);
4826           else if (*p->itypetable >= -27 && *p->itypetable < -20) {
4827             slider_type = -((int) *p->itypetable) - 20;
4828             plastic = true;
4829           }
4830           else  {                      // random type
4831             slider_type = rand_31_i(csound, 7) | 1;
4832             switch(slider_type) {
4833             case 0: slider_type = 1; break;
4834             case 2: slider_type = 3; break;
4835             case 4: slider_type = 5; break;
4836             case 6: slider_type = 7; break;
4837             default: slider_type = 1;
4838             }
4839           }
4840         }
4841         else
4842           slider_type = (int) typetable[j];
4843         if (slider_type > 20) {
4844           plastic = true;
4845           slider_type -= 20;
4846         }
4847         if (slider_type < 10)
4848           o = new Fl_Slider(x, y, 10, height, Name);
4849         else {
4850           o = new Fl_Value_Slider_Input(csound, x, y, 10, height, Name);
4851           slider_type -=10;
4852           ((Fl_Value_Slider_Input*) o)->textboxsize(50);
4853           ((Fl_Value_Slider_Input*) o)->textsize(13);
4854         }
4855         switch((int) slider_type) { //type
4856         case 1: o->type(FL_VERT_FILL_SLIDER); break;
4857         case 3: o->type(FL_VERT_SLIDER); break;
4858         case 5: o->type(FL_VERT_NICE_SLIDER); o->box(FL_FLAT_BOX); break;
4859         case 7:  o->type(FL_VERT_NICE_SLIDER); o->box(FL_DOWN_BOX); break;
4860         default: o->type(FL_VERT_NICE_SLIDER); o->box(FL_FLAT_BOX); break;
4861         }
4862         o->align(FL_ALIGN_BOTTOM);
4863         if (plastic) o->box(FL_PLASTIC_DOWN_BOX);
4864         widget_attributes(csound, o);
4865         MYFLT min, max, range;
4866         if ((int) *p->iminmaxtable > 0) {
4867           min = minmaxtable[j*2];
4868           max = minmaxtable[j*2+1];
4869         }
4870         else {
4871           min = MYFLT(0.0);
4872           max = MYFLT(1.0);
4873         }
4874         int iexp;
4875 
4876         p->slider_data[j].min=min;
4877         p->slider_data[j].max=max;
4878         p->slider_data[j].out=&outable[j];
4879 
4880         if ((int) *p->iexptable <=0)
4881           // no table, all sliders have the same behaviour
4882           iexp = (int) *p->iexptable;
4883         else
4884           iexp = (int) exptable[j];
4885         switch (iexp) {
4886         case -1: iexp = EXP_; break;
4887         case 0: iexp = LIN_; break;
4888         }
4889 
4890         MYFLT val = 0;
4891         p->slider_data[j].exp = iexp;
4892         switch (iexp) {
4893         case LIN_: //linear
4894           o->range(min,max);
4895           o->callback((Fl_Callback*)fl_callbackLinearSliderBank,
4896                       (void *) &(p->slider_data[j]));
4897           val = outable[j];
4898           if (val > max) val = max;
4899           else if (val < min) val = min;
4900           break;
4901         case EXP_ : //exponential
4902           if (UNLIKELY(min == 0 || max == 0))
4903             return
4904               csound->InitError(csound,
4905                                 "%s", Str("FLvslidBnk: zero is illegal "
4906                                     "in exponential operations"));
4907           range = max - min;
4908           o->range(range,0);
4909           #if defined(sun)
4910             p->slider_data[j].base = ::pow((max / (double)min), 1.0/(double)range);
4911           #else
4912             p->slider_data[j].base = ::pow((max / min), 1.0/(double)range);
4913           #endif
4914           o->callback((Fl_Callback*)fl_callbackExponentialSliderBank,
4915                       (void *) &(p->slider_data[j]));
4916           {
4917             val = outable[j];
4918             MYFLT range = max-min;
4919             #if defined(sun)
4920               MYFLT base = ::pow(max / (double)min, 1.0/(double)range);
4921             #else
4922               MYFLT base = ::pow(max / min, 1.0/(double)range);
4923             #endif
4924             val = (log(val/min) / log(base)) ;
4925           }
4926           break;
4927         default:
4928           {
4929             FUNC *ftp;
4930             MYFLT fnum = abs(iexp);
4931             if (LIKELY((ftp = csound->FTnp2Finde(csound, &fnum)) != NULL))
4932               p->slider_data[j].table = ftp->ftable;
4933             else return NOTOK;
4934             p->slider_data[j].tablen = ftp->flen;
4935             o->range(.99999999,0);
4936             if (iexp > 0) //interpolated
4937               o->callback((Fl_Callback*)fl_callbackInterpTableSliderBank,
4938                           (void *)  &(p->slider_data[j]));
4939             else // non-interpolated
4940               o->callback((Fl_Callback*)fl_callbackTableSliderBank,
4941                           (void *)  &(p->slider_data[j]));
4942           }
4943         }
4944         o->value(val);
4945         p->slider_data[j].widget_addr= (void*) o;
4946       }
4947       w->resizable(w);
4948       if (*p->iwidth <=0 || *p->iheight <=0) {// default width and height
4949         int a,b;
4950         w->size( a= w->parent()->w(), b= w->parent()->h()-50);
4951         w->position(0, 0);
4952       }
4953       else {
4954         w->size( (int)*p->iwidth, (int)*p->iheight);
4955         w->position((int)*p->ix, (int)*p->iy);
4956       }
4957       w->end();
4958       widgetGlobals->AddrSetValue.push_back(ADDR_SET_VALUE(LIN_, 0, 0, (void *) w,
4959                                                  (void *) p,
4960                                                  widgetGlobals->currentSnapGroup));
4961       widgetGlobals->last_sldbnk = widgetGlobals->AddrSetValue.size()-1;  //gab
4962 
4963       return OK;
4964   }
4965 
fl_vertical_slider_bank(CSOUND * csound,FLSLIDERBANK * p)4966   static int fl_vertical_slider_bank(CSOUND *csound, FLSLIDERBANK *p){
4967     return fl_vertical_slider_bank_(csound,p,0);
4968   }
4969 
fl_vertical_slider_bank_S(CSOUND * csound,FLSLIDERBANK * p)4970  static int fl_vertical_slider_bank_S(CSOUND *csound, FLSLIDERBANK *p){
4971     return fl_vertical_slider_bank_(csound,p,1);
4972   }
4973 
4974 
fl_slider_bank2_(CSOUND * csound,FLSLIDERBANK2 * p,int istring)4975   static int fl_slider_bank2_(CSOUND *csound, FLSLIDERBANK2 *p, int istring)
4976   {
4977      WIDGET_GLOBALS *widgetGlobals =
4978        (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS");
4979       char s[MAXNAME];
4980       bool plastic = false;
4981       if (istring)
4982         strncpy(s, ((STRINGDAT*) p->names)->data, MAXNAME-1);
4983       else if ((long) *p->names <= csound->GetStrsmax(csound) &&
4984                csound->GetStrsets(csound,(long) *p->names)) {
4985         strncpy(s, csound->GetStrsets(csound,(long) *p->names), MAXNAME-1);
4986       }
4987       string tempname(s);
4988       stringstream sbuf;
4989       sbuf << tempname;
4990 
4991       int width = (int) *p->iwidth;
4992       if (width <=0) width = 100;
4993 
4994       Fl_Group* w = new Fl_Group((int)*p->ix, (int)*p->iy,
4995                                  width, (int)*p->inumsliders*10);
4996       FUNC *ftp;
4997       MYFLT *configtable, *outable;
4998 
4999       MYFLT *zkstart;
5000       int zklast = csound->GetZakBounds(csound, &zkstart);
5001       if (*p->ioutable  < 1) {
5002         if (LIKELY(zkstart != NULL &&
5003                    zklast>(long)(*p->inumsliders + *p->ioutablestart_ndx)))
5004           outable = zkstart + (long) *p->ioutablestart_ndx;
5005         else {
5006           return csound->InitError(csound,
5007                                    "%s", Str("invalid ZAK space allocation"));
5008         }
5009       }
5010       else {
5011         if ((ftp = csound->FTnp2Finde(csound, p->ioutable)) != NULL)
5012           outable = ftp->ftable + (long) *p->ioutablestart_ndx;
5013         else
5014           return NOTOK;
5015       }
5016       if((ftp = csound->FTnp2Finde(csound, p->iconfigtable)) != NULL)
5017         configtable = ftp->ftable;
5018       else return NOTOK;
5019 
5020       p->elements = (long) *p->inumsliders;
5021       for (int j =0; j< p->elements; j++) {
5022         string stemp;
5023         if (tempname == " ") {
5024           char s[40];
5025           sprintf(s, "%d", j);
5026           stemp = s;
5027         }
5028         else
5029           getline(sbuf, stemp, '@');
5030         char *Name =  new char[stemp.size()+2];
5031         strcpy(Name,stemp.c_str());
5032         widgetGlobals->allocatedStrings.push_back(Name);
5033 
5034         int x = (int) *p->ix,  y = (int) *p->iy + j*10;
5035         Fl_Slider *o;
5036         int slider_type = (int) configtable[j*4+3];
5037         int iexp = (int) configtable[j*4+2];
5038 
5039         if (slider_type > 19) {
5040           plastic = true;
5041           slider_type = slider_type - 20;
5042         }
5043         if (UNLIKELY(slider_type > 10 && iexp == EXP_)) {
5044           csound->Warning(csound, "%s",
5045                           Str("FLslider exponential, using non-labeled slider"));
5046           slider_type -= 10;
5047         }
5048         if (slider_type <= 10)
5049           o = new Fl_Slider(x, y, width, 10, Name);
5050         else {
5051           o = new Fl_Value_Slider_Input( csound, x, y, width, 10, Name);
5052           slider_type -=10;
5053           ((Fl_Value_Slider_Input*) o)->textboxsize(20);
5054           ((Fl_Value_Slider_Input*) o)->textsize(13);
5055         }
5056         switch((int) slider_type) { //type
5057         case 1: o->type(FL_HOR_FILL_SLIDER); break;
5058         case 3: o->type(FL_HOR_SLIDER); break;
5059         case 5: o->type(FL_HOR_NICE_SLIDER); o->box(FL_FLAT_BOX); break;
5060         case 7:  o->type(FL_HOR_NICE_SLIDER); o->box(FL_DOWN_BOX); break;
5061         default: o->type(FL_HOR_NICE_SLIDER); o->box(FL_FLAT_BOX); break;
5062         }
5063         o->align(FL_ALIGN_LEFT);
5064         if (plastic) o->box(FL_PLASTIC_DOWN_BOX);
5065         o->step(0.0);
5066         widget_attributes(csound, o);
5067         MYFLT min, max, range;
5068         min = configtable[j*4];
5069         max = configtable[j*4+1];
5070 
5071         p->slider_data[j].min=min;
5072         p->slider_data[j].max=max;
5073         p->slider_data[j].out=&outable[j];
5074 
5075         switch (iexp) {
5076         case -1: iexp = EXP_; break;
5077         case 0: iexp = LIN_; break;
5078         }
5079 
5080         MYFLT val = 0;
5081         p->slider_data[j].exp = iexp;
5082 
5083         switch (iexp) {
5084         case LIN_: //linear
5085           o->range(min,max);
5086           o->callback((Fl_Callback*)fl_callbackLinearSliderBank,
5087                       (void *) &(p->slider_data[j]));
5088           val = outable[j];
5089           if (val > max) val = max;
5090           else if (val < min) val = min;
5091           break;
5092         case EXP_ : //exponential
5093           if (UNLIKELY(min == 0 || max == 0))
5094             return
5095               csound->InitError(csound,
5096                                 "%s", Str("FLsliderBank: zero is illegal "
5097                                     "in exponential operations"));
5098           range = max - min;
5099           o->range(0,range);
5100           #if defined(sun)
5101             p->slider_data[j].base = ::pow((max / (double)min), 1.0/(double)range);
5102           #else
5103             p->slider_data[j].base = ::pow((max / min), 1.0/(double)range);
5104           #endif
5105           o->callback((Fl_Callback*)fl_callbackExponentialSliderBank,
5106                       (void *) &(p->slider_data[j]));
5107           {
5108             val = outable[j];
5109             MYFLT range = max-min;
5110             #if defined(sun)
5111               MYFLT base = ::pow(max / (double)min, 1.0/(double)range);
5112             #else
5113               MYFLT base = ::pow(max / min, 1.0/(double)range);
5114             #endif
5115             val = (log(val/min) / log(base)) ;
5116           }
5117           break;
5118         default:
5119           {
5120             FUNC *ftp;
5121             MYFLT fnum = abs(iexp);
5122             if ((ftp = csound->FTnp2Finde(csound, &fnum)) != NULL)
5123               p->slider_data[j].table = ftp->ftable;
5124             else return NOTOK;
5125             p->slider_data[j].tablen = ftp->flen;
5126             o->range(0,0.99999999);
5127             if (iexp > 0) //interpolated
5128               o->callback((Fl_Callback*)fl_callbackInterpTableSliderBank,
5129                           (void *)  &(p->slider_data[j]));
5130             else // non-interpolated
5131               o->callback((Fl_Callback*)fl_callbackTableSliderBank,
5132                           (void *)  &(p->slider_data[j]));
5133           }
5134         }
5135         o->value(val);
5136         p->slider_data[j].widget_addr= (void*) o;
5137       }
5138       w->resizable(w);
5139       if (*p->iwidth <=0 || *p->iheight <=0) {// default width and height
5140         int a,b;
5141         w->size( a= w->parent()->w() -50, b= w->parent()->h());
5142         w->position(50, 0);
5143       }
5144       else {
5145         w->size( (int)*p->iwidth, (int)*p->iheight);
5146         w->position((int)*p->ix, (int)*p->iy);
5147       }
5148       w->end();
5149       widgetGlobals->AddrSetValue.push_back(ADDR_SET_VALUE(LIN_, 0, 0, (void *) w,
5150                                                  (void *) p,
5151                                                  widgetGlobals->currentSnapGroup));
5152       // *p->ihandle = widgetGlobals->AddrSetValue.size()-1;
5153       widgetGlobals->last_sldbnk = widgetGlobals->AddrSetValue.size()-1;  //gab
5154 
5155       return OK;
5156   }
5157 
fl_slider_bank2(CSOUND * csound,FLSLIDERBANK2 * p)5158   static int fl_slider_bank2(CSOUND *csound, FLSLIDERBANK2 *p){
5159     return fl_slider_bank2_(csound, p,0);
5160   }
5161 
fl_slider_bank2_S(CSOUND * csound,FLSLIDERBANK2 * p)5162  static int fl_slider_bank2_S(CSOUND *csound, FLSLIDERBANK2 *p){
5163     return fl_slider_bank2_(csound, p,1);
5164   }
5165 
fl_vertical_slider_bank2_(CSOUND * csound,FLSLIDERBANK2 * p,int istring)5166   static int fl_vertical_slider_bank2_(CSOUND *csound,
5167                                        FLSLIDERBANK2 *p, int istring)
5168   {
5169       WIDGET_GLOBALS *widgetGlobals =
5170         (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS");
5171       char s[MAXNAME];
5172       bool plastic = false;
5173       if (istring)
5174         strncpy(s, ((STRINGDAT*) p->names)->data, MAXNAME-1);
5175       else if ((long) *p->names <= csound->GetStrsmax(csound) &&
5176                csound->GetStrsets(csound,(long) *p->names)) {
5177         strncpy(s, csound->GetStrsets(csound,(long) *p->names), MAXNAME-1);
5178       }
5179       string tempname(s);
5180       stringstream sbuf;
5181       sbuf << tempname;
5182 
5183       int height = (int) *p->iheight;
5184       if (height <=0) height = 100;
5185 
5186       Fl_Group* w = new Fl_Group((int)*p->ix, (int)*p->iy,
5187                                  (int) *p->inumsliders*10, height);
5188       FUNC *ftp;
5189       MYFLT *configtable, *outable;
5190 
5191       MYFLT *zkstart;
5192       int zklast = csound->GetZakBounds(csound, &zkstart);
5193       if (*p->ioutable  < 1) {
5194         if (LIKELY(zkstart != NULL &&
5195                    zklast>(long)(*p->inumsliders + *p->ioutablestart_ndx)))
5196           outable = zkstart + (long) *p->ioutablestart_ndx;
5197         else {
5198           return csound->InitError(csound,
5199                                    "%s", Str("invalid ZAK space allocation"));
5200         }
5201       }
5202       else {
5203         if ((ftp = csound->FTnp2Finde(csound, p->ioutable)) != NULL)
5204           outable = ftp->ftable + (long) *p->ioutablestart_ndx;
5205         else
5206           return NOTOK;
5207       }
5208       if((ftp = csound->FTnp2Finde(csound, p->iconfigtable)) != NULL)
5209         configtable = ftp->ftable;
5210       else
5211         return NOTOK;
5212 
5213       p->elements = (long) *p->inumsliders;
5214       for (int j =0; j< p->elements; j++) {
5215         string stemp;
5216         if (tempname == " ") {
5217           char s[40];
5218           sprintf(s, "%d", j);
5219           stemp = s;
5220         }
5221         else
5222           getline(sbuf, stemp, '@');
5223         char *Name =  new char[stemp.size()+2];
5224         strcpy(Name,stemp.c_str());
5225         widgetGlobals->allocatedStrings.push_back(Name);
5226 
5227         int x = (int) *p->ix+j*10,  y = (int) *p->iy /*+ j*10*/;
5228         Fl_Slider *o;
5229         int slider_type= (int) configtable[j*4+3];
5230         int iexp = (int) configtable[j*4+2];
5231 
5232         if (slider_type > 19) {
5233           plastic = true;
5234           slider_type -= 20;
5235         }
5236         if (UNLIKELY(slider_type > 10 && iexp == EXP_)) {
5237           csound->Warning(csound,
5238                           "%s", Str("FLslidBnk2: FLslider exponential, "
5239                               "using non-labeled slider"));
5240           slider_type -= 10;
5241         }
5242         if (slider_type <= 10)
5243           o = new Fl_Slider(x, y, 10, height, Name);
5244         else {
5245           o = new Fl_Value_Slider_Input( csound, x, y, 10, height, Name);
5246           slider_type -=10;
5247           ((Fl_Value_Slider_Input*) o)->textboxsize(50);
5248           ((Fl_Value_Slider_Input*) o)->textsize(13);
5249         }
5250         switch((int) slider_type) { //type
5251         case 1: case 2: o->type(FL_VERT_FILL_SLIDER); break;
5252         case 3: case 4: o->type(FL_VERT_SLIDER); break;
5253         case 5: case 6: o->type(FL_VERT_NICE_SLIDER); o->box(FL_FLAT_BOX); break;
5254         case 7: case 8: o->type(FL_VERT_NICE_SLIDER); o->box(FL_DOWN_BOX); break;
5255         default: o->type(FL_VERT_NICE_SLIDER); o->box(FL_FLAT_BOX); break;
5256         }
5257         o->align(FL_ALIGN_BOTTOM);
5258         if (plastic) o->box(FL_PLASTIC_DOWN_BOX);
5259         widget_attributes(csound, o);
5260         MYFLT min, max, range;
5261         min = configtable[j*4];
5262         max = configtable[j*4+1];
5263 
5264         p->slider_data[j].min=min;
5265         p->slider_data[j].max=max;
5266         p->slider_data[j].out=&outable[j];
5267 
5268         switch (iexp) {
5269         case -1: iexp = EXP_; break;
5270         case 0: iexp = LIN_; break;
5271         }
5272 
5273         MYFLT val = 0;
5274         p->slider_data[j].exp = iexp;
5275 
5276         switch (iexp) {
5277         case LIN_: //linear
5278           o->range(min,max);
5279           o->callback((Fl_Callback*)fl_callbackLinearSliderBank,
5280                       (void *) &(p->slider_data[j]));
5281           val = outable[j];
5282           if (val > max) val = max;
5283           else if (val < min) val = min;
5284           break;
5285         case EXP_ : //exponential
5286           if (UNLIKELY(min == 0 || max == 0))
5287             return
5288               csound->InitError(csound,
5289                                 "%s", Str("FLsliderBank: zero is illegal "
5290                                     "in exponential operations"));
5291           range = max - min;
5292           o->range(range,0);
5293           #if defined(sun)
5294             p->slider_data[j].base = ::pow((max / (double)min), 1.0/(double)range);
5295           #else
5296             p->slider_data[j].base = ::pow((max / min), 1.0/(double)range);
5297           #endif
5298           o->callback((Fl_Callback*)fl_callbackExponentialSliderBank,
5299                       (void *) &(p->slider_data[j]));
5300           {
5301             val = outable[j];
5302             MYFLT range = max-min;
5303             #if defined(sun)
5304               MYFLT base = ::pow(max / (double)min, 1.0/(double)range);
5305             #else
5306               MYFLT base = ::pow(max / min, 1.0/(double)range);
5307             #endif
5308             val = (log(val/min) / log(base)) ;
5309           }
5310           break;
5311         default:
5312           {
5313             FUNC *ftp;
5314             MYFLT fnum = abs(iexp);
5315             if ((ftp = csound->FTnp2Finde(csound, &fnum)) != NULL)
5316               p->slider_data[j].table = ftp->ftable;
5317             else return NOTOK;
5318             p->slider_data[j].tablen = ftp->flen;
5319             o->range(.99999999,0);
5320             if (iexp > 0) //interpolated
5321               o->callback((Fl_Callback*)fl_callbackInterpTableSliderBank,
5322                           (void *)  &(p->slider_data[j]));
5323             else // non-interpolated
5324               o->callback((Fl_Callback*)fl_callbackTableSliderBank,
5325                           (void *)  &(p->slider_data[j]));
5326           }
5327         }
5328         o->value(val);
5329         p->slider_data[j].widget_addr= (void*) o;
5330 
5331       }
5332       w->resizable(w);
5333       if (*p->iwidth <=0 || *p->iheight <=0) {// default width and height
5334         int a,b;
5335         w->size( a= w->parent()->w(), b= w->parent()->h()-50);
5336         w->position(0, 0);
5337       }
5338       else {
5339         w->size( (int)*p->iwidth, (int)*p->iheight);
5340         w->position((int)*p->ix, (int)*p->iy);
5341       }
5342       w->end();
5343       widgetGlobals->AddrSetValue.push_back(ADDR_SET_VALUE(LIN_, 0, 0,
5344                                                  (void *) w, (void *) p,
5345                                                  widgetGlobals->currentSnapGroup));
5346       // *p->ihandle = widgetGlobals->AddrSetValue.size()-1;
5347       widgetGlobals->last_sldbnk = widgetGlobals->AddrSetValue.size()-1;  //gab
5348 
5349       return OK;
5350   }
5351 
fl_vertical_slider_bank2(CSOUND * csound,FLSLIDERBANK2 * p)5352  static int fl_vertical_slider_bank2(CSOUND *csound, FLSLIDERBANK2 *p){
5353     return fl_vertical_slider_bank2_(csound,p,0);
5354   }
5355 
fl_vertical_slider_bank2_S(CSOUND * csound,FLSLIDERBANK2 * p)5356  static int fl_vertical_slider_bank2_S(CSOUND *csound, FLSLIDERBANK2 *p){
5357     return fl_vertical_slider_bank2_(csound,p,1);
5358   }
5359 
5360 
5361 
fl_slider_bank_getHandle(CSOUND * csound,FLSLDBNK_GETHANDLE * p)5362   static int fl_slider_bank_getHandle(CSOUND *csound, FLSLDBNK_GETHANDLE *p)
5363   //valid only if called immediately after FLslidBnk
5364   {
5365       WIDGET_GLOBALS *widgetGlobals =
5366         (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS");
5367       *p->ihandle = widgetGlobals->last_sldbnk;
5368       return OK;
5369   }
5370 
fl_slider_bank_setVal(CSOUND * csound,FLSLDBNK_SET * p)5371   static int fl_slider_bank_setVal(CSOUND *csound, FLSLDBNK_SET *p)
5372   {
5373       FUNC* ftp;
5374       MYFLT *table, *outable;
5375       int numslid = (int)*p->numSlid;
5376       int startInd = (int)*p->startInd;
5377       int startSlid = (int)*p->startSlid;
5378       WIDGET_GLOBALS *widgetGlobals =
5379         (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS");
5380 
5381       if (LIKELY((ftp = csound->FTnp2Finde(csound, p->ifn)) != NULL))
5382         table = ftp->ftable;
5383       else {
5384         return csound->InitError(csound,
5385                                  "%s", Str("FLsldBnkSet: invalid table number"));
5386       }
5387       // *startInd, *startSlid, *numSlid
5388       if (UNLIKELY( (int) ftp->flen < startInd + numslid)) {
5389         return csound->InitError(csound,
5390                                  "%s", Str("FLslidBnkSet: table too short!"));
5391       }
5392       FLSLIDERBANK *q =
5393         (FLSLIDERBANK *)widgetGlobals->AddrSetValue[ (int) *p->ihandle].opcode;
5394 
5395       if (LIKELY((ftp = csound->FTnp2Finde(csound, q->ioutable)) != NULL))
5396         outable = ftp->ftable;
5397       else {
5398         return csound->InitError(csound,
5399                                  "%s", Str("FLsldBnkSet: invalid outable number"));
5400       }
5401       if (numslid == 0) numslid = (int)(q->elements - *p->startSlid);
5402       if (UNLIKELY( q->elements > startSlid + numslid)) {
5403         return csound->InitError(csound, "%s",
5404                                  Str("FLslidBnkSet: too many sliders to reset!"));
5405       }
5406       for (int j = startSlid, k = startInd; j< numslid + startSlid; j++, k++) {
5407 
5408         MYFLT val = 0;
5409         //      MYFLT base = q->slider_data[j].base;
5410         int iexp = q->slider_data[j].exp;
5411         MYFLT min = q->slider_data[j].min;
5412         MYFLT max = q->slider_data[j].max;
5413         switch (iexp) {
5414         case LIN_: //linear
5415           val = table[k];
5416           if (val > max) val = max;
5417           else if (val < min) val = min;
5418           break;
5419         case EXP_ : //exponential
5420           {
5421             MYFLT range = max - min;
5422             MYFLT base2 = pow(max / min, 1/range);
5423             val = (log(table[k]/min) / log(base2)) ;
5424           }
5425           break;
5426         default:
5427           return csound->InitError(csound,
5428                                    "%s", Str("FLslidBnkSet: "
5429                                        "function mapping not available"));
5430         }
5431 
5432         FLlock();
5433         ((Fl_Slider*) (q->slider_data[j].widget_addr))->value(val);
5434         FLunlock();
5435         outable[j] = table[k];
5436       }
5437       return OK;
5438   }
5439 
fl_slider_bank2_setVal(CSOUND * csound,FLSLDBNK_SET * p)5440   static int fl_slider_bank2_setVal(CSOUND *csound, FLSLDBNK_SET *p)
5441   {
5442       FUNC* ftp;
5443       MYFLT *table, *outable;
5444       int numslid = (int)*p->numSlid;
5445       int startInd = (int)*p->startInd;
5446       int startSlid = (int)*p->startSlid;
5447       WIDGET_GLOBALS *widgetGlobals =
5448         (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS");
5449 
5450       if (LIKELY((ftp = csound->FTnp2Finde(csound, p->ifn)) != NULL))
5451         table = ftp->ftable;
5452       else {
5453         return csound->InitError(csound,
5454                                  "%s", Str("FLsldBnkSet: invalid table number"));
5455       }
5456       // *startInd, *startSlid, *numSlid
5457       if (UNLIKELY((int) ftp->flen < startInd + numslid)) {
5458         return csound->InitError(csound,
5459                                  "%s", Str("FLslidBnkSet: table too short!"));
5460       }
5461       FLSLIDERBANK2 *q =
5462         (FLSLIDERBANK2 *)widgetGlobals->AddrSetValue[ (int) *p->ihandle].opcode;
5463 
5464       if (LIKELY((ftp = csound->FTnp2Finde(csound, q->ioutable)) != NULL))
5465         outable = ftp->ftable;
5466       else {
5467         return csound->InitError(csound,
5468                                  "%s", Str("FLsldBnkSet: invalid outable number"));
5469       }
5470 
5471       if (numslid == 0) numslid = (int)(q->elements - *p->startSlid);
5472       if (UNLIKELY( q->elements > startSlid + numslid)) {
5473         return csound->InitError(csound, "%s",
5474                                  Str("FLslidBnkSet: too many sliders to reset!"));
5475       }
5476 
5477       for (int j = startSlid, k = startInd; j< numslid + startSlid; j++, k++) {
5478 
5479         MYFLT val = 0;
5480         //      MYFLT base = q->slider_data[j].base;
5481         int iexp = q->slider_data[j].exp;
5482         MYFLT min = q->slider_data[j].min;
5483         MYFLT max = q->slider_data[j].max;
5484         switch (iexp) {
5485         case LIN_: //linear
5486           val = table[k];
5487           if (val > max) val = max;
5488           else if (val < min) val = min;
5489           break;
5490         case EXP_ : //exponential
5491           {
5492             MYFLT range = max - min;
5493             MYFLT base2 = pow(max / min, 1/range);
5494             val = (log(table[k]/min) / log(base2));
5495           }
5496           break;
5497         default:  // table
5498           {
5499             //      val = table[k];
5500             if (UNLIKELY(val < 0 || val > 1)) { // input range must be 0 to 1
5501               csound->PerfError(csound, &p->h,
5502                                 "%s", Str("FLslidBnk2Setk: value out of range: "
5503                                     "function mapping requires a 0 to 1 "
5504                                     "range for input"));
5505             }
5506           }
5507           //{
5508           //      initerror("FLslidBnkSet: function mapping not available");
5509           //      return;
5510           //}
5511         }
5512 
5513         FLlock();
5514         ((Fl_Slider*) (q->slider_data[j].widget_addr))->value(val);
5515         FLunlock();
5516         outable[j] = table[k];
5517       }
5518       return OK;
5519   }
fl_slider_bank2_setVal_k_set(CSOUND * csound,FLSLDBNK2_SETK * p)5520   static int fl_slider_bank2_setVal_k_set(CSOUND *csound, FLSLDBNK2_SETK *p)
5521   {
5522       FUNC* ftp;
5523 
5524       p->numslid = (int)*p->numSlid;
5525       p->startind = (int)*p->startInd;
5526       p->startslid = (int)*p->startSlid;
5527       WIDGET_GLOBALS *widgetGlobals =
5528         (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS");
5529 
5530       if (LIKELY((ftp = csound->FTnp2Finde(csound, p->ifn)) != NULL))
5531         p->table = ftp->ftable;
5532       else {
5533         return csound->InitError(csound,
5534                                   "%s", Str("FLsldBnkSetk: invalid table number"));
5535       }
5536       // *startInd, *startSlid, *numSlid
5537       if (UNLIKELY( (int) ftp->flen < p->startind + p->numslid)) {
5538         return csound->InitError(csound,
5539                                  "%s", Str("FLslidBnkSetk: table too short!"));
5540       }
5541       p->q = (FLSLIDERBANK2 *)
5542         widgetGlobals->AddrSetValue[ (int) *p->ihandle].opcode;
5543 
5544       if (LIKELY((ftp = csound->FTnp2Finde(csound, p->q->ioutable)) != NULL))
5545         p->outable = ftp->ftable;
5546       else {
5547         return csound->InitError(csound, "%s",
5548                                  Str("FLsldBnkSetk: invalid outable number"));
5549       }
5550 
5551       if (p->numslid == 0) p->numslid = p->q->elements - p->startslid;
5552       if (UNLIKELY( p->q->elements < p->startslid + p->numslid)) {
5553         return csound->InitError(csound, "%s",
5554                                 Str("FLslidBnkSetk: too many sliders to reset!"));
5555       }
5556       return OK;
5557   }
5558 
5559 
5560 
fl_slider_bank2_setVal_k(CSOUND * csound,FLSLDBNK2_SETK * p)5561   static int fl_slider_bank2_setVal_k(CSOUND *csound, FLSLDBNK2_SETK *p)
5562   {
5563     //WIDGET_GLOBALS *widgetGlobals =
5564     //    (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS");
5565 
5566       if(*p->kflag) {
5567         FLSLIDERBANK2 *q = p->q;
5568         MYFLT *table=p->table;
5569         for (int j = p->startslid, k = p->startind;
5570              j< p->numslid + p->startslid;
5571              j++, k++) {
5572 
5573           MYFLT val = 0;
5574           //  MYFLT base= q->slider_data[j].base;
5575           int iexp =  q->slider_data[j].exp;
5576           MYFLT min = q->slider_data[j].min;
5577           MYFLT max = q->slider_data[j].max;
5578           switch (iexp) {
5579           case LIN_: //linear
5580             val = table[k];
5581             if (val > max) val = max;
5582             else if (val < min) val = min;
5583             break;
5584           case EXP_ : //exponential
5585             {
5586               MYFLT range = max - min;
5587               MYFLT base2 = pow(max / min, 1/range);
5588               val = (log(table[k]/min) / log(base2));
5589             }
5590             break;
5591           default: // table
5592             {
5593               val = table[k];
5594               if (UNLIKELY(val < 0 || val > 1)) { // input range must be 0 to 1
5595                 csound->PerfError(csound, &p->h,
5596                                   "%s", Str("FLslidBnk2Setk: value out of range:"
5597                                       " function mapping requires a 0 to 1"
5598                                       " range for input"));
5599               }
5600             }
5601           }
5602           if (val != p->oldValues[j]) {
5603             FLlock();
5604             ((Fl_Slider*) (q->slider_data[j].widget_addr))->value(val);
5605             ((Fl_Slider*) (q->slider_data[j].widget_addr))->do_callback();
5606             FLunlock();
5607             p->oldValues[j] = val;
5608           }
5609         }
5610       }
5611       return OK;
5612   }
5613 
fl_slider_bank_setVal_k_set(CSOUND * csound,FLSLDBNK_SETK * p)5614   static int fl_slider_bank_setVal_k_set(CSOUND *csound, FLSLDBNK_SETK *p)
5615   {
5616       FUNC* ftp;
5617       WIDGET_GLOBALS *widgetGlobals =
5618       (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS");
5619       p->numslid = (int)*p->numSlid;
5620       p->startind = (int)*p->startInd;
5621       p->startslid = (int)*p->startSlid;
5622 
5623       if (LIKELY((ftp = csound->FTnp2Finde(csound, p->ifn)) != NULL))
5624         p->table = ftp->ftable;
5625       else {
5626         return csound->InitError(csound,
5627                                  "%s", Str("FLslidBnkSetk: invalid table number"));
5628       }
5629       // *startInd, *startSlid, *numSlid
5630       if (UNLIKELY( (int) ftp->flen < p->startind + p->numslid)) {
5631         return csound->InitError(csound,
5632                                  "%s", Str("FLslidBnkSetk: table too short!"));
5633       }
5634       p->q =
5635         (FLSLIDERBANK *) widgetGlobals->AddrSetValue[ (int) *p->ihandle].opcode;
5636 
5637       if (LIKELY((ftp = csound->FTnp2Finde(csound, p->q->ioutable)) != NULL))
5638         p->outable = ftp->ftable;
5639       else {
5640         return csound->InitError(csound, "%s",
5641                                  Str("FLslidBnkSetk: invalid outable number"));
5642       }
5643 
5644       if (p->numslid == 0) p->numslid = p->q->elements - p->startslid;
5645       if (UNLIKELY( p->q->elements < p->startslid + p->numslid)) {
5646         return csound->InitError(csound, "%s",
5647                                  Str("FLslidBnkSetk: too many sliders to reset!"));
5648       }
5649       return OK;
5650   }
5651 
5652 
5653 
fl_slider_bank_setVal_k(CSOUND * csound,FLSLDBNK_SETK * p)5654   static int fl_slider_bank_setVal_k(CSOUND *csound, FLSLDBNK_SETK *p)
5655   {
5656       if (*p->kflag) {
5657         FLSLIDERBANK *q = p->q;
5658         MYFLT *table=p->table;
5659         for (int j = p->startslid, k = p->startind;
5660              j< p->numslid + p->startslid;
5661              j++, k++) {
5662 
5663           MYFLT val = 0;
5664           //         MYFLT base= q->slider_data[j].base;  //Not used
5665           int iexp =  q->slider_data[j].exp;
5666           MYFLT min = q->slider_data[j].min;
5667           MYFLT max = q->slider_data[j].max;
5668           switch (iexp) {
5669           case LIN_: //linear
5670             val = table[k];
5671             if (val > max) val = max;
5672             else if (val < min) val = min;
5673             break;
5674           case EXP_ : //exponential
5675             {
5676               MYFLT range = max - min;
5677               MYFLT base2 = pow(max / min, 1/range);
5678               val = (log(table[k]/min) / log(base2));
5679             }
5680             break;
5681           default: // table
5682             {
5683               val = table[k];
5684               if (UNLIKELY(val < 0 || val > 1)) { // input range must be 0 to 1
5685                 csound->PerfError(csound, &p->h,
5686                                   "%s", Str("FLslidBnk2Setk: value out of range: "
5687                                       "function mapping requires a 0 to 1 range "
5688                                       "for input"));
5689               }
5690             }
5691           }
5692           if (val != p->oldValues[j]) {
5693             FLlock();
5694             ((Fl_Slider*) (q->slider_data[j].widget_addr))->value(val);
5695             ((Fl_Slider*) (q->slider_data[j].widget_addr))->do_callback();
5696             FLunlock();
5697             p->oldValues[j] = val;
5698           }
5699         }
5700       }
5701       return OK;
5702   }
5703 
FLxyin_set(CSOUND * csound,FLXYIN * p)5704   static int FLxyin_set(CSOUND *csound, FLXYIN *p)
5705   {
5706 
5707       *p->koutx = *p->ioutx; //initial values
5708       *p->kouty = *p->iouty;
5709       p->rangex = *p->ioutx_max - *p->ioutx_min;
5710       p->rangey = *p->iouty_max - *p->iouty_min;
5711 
5712       switch((int) *p->iexpx) {
5713       case 0: // LIN
5714         p->expx = LIN_; break;
5715       case -1: // EXP
5716         p->expx = EXP_;
5717         if (UNLIKELY(*p->ioutx_min == 0 || *p->ioutx_max==0))
5718           return csound->InitError(csound, "%s",
5719                                    Str("FLxyin: none of X limits can be zero in"
5720                                        " exponential mode!"));
5721         p->basex = pow((double) (*p->ioutx_max / *p->ioutx_min),
5722                        (double) (1/p->rangex));
5723 
5724         break;
5725       default: // TABLE
5726         p->expx = (int) *p->iexpx;
5727         {
5728           FUNC *ftp;
5729           MYFLT fnum = abs(p->expx);
5730           if ((ftp = csound->FTnp2Finde(csound, &fnum)) != NULL) {
5731             p->tablex = ftp->ftable;
5732             p->tablenx = ftp->flen;
5733           }
5734           else return NOTOK;
5735         }
5736 
5737       }
5738 
5739       switch((int) *p->iexpy) {
5740       case 0: // LIN
5741         p->expy = LIN_; break;
5742       case -1: // EXP
5743         p->expy = EXP_;
5744         if (UNLIKELY(*p->iouty_min == 0 || *p->iouty_max==0))
5745           return csound->InitError(csound,
5746                                    "%s", Str("FLxyin: none of Y limits can "
5747                                        "be zero in exponential mode!"));
5748         p->basey = pow((double) (*p->iouty_max / *p->iouty_min),
5749                        (double) (1/p->rangey));
5750         break;
5751       default: // TABLE
5752         p->expy = (int) *p->iexpy;
5753         {
5754           FUNC *ftp;
5755           MYFLT fnum = abs(p->expy);
5756           if ((ftp = csound->FTnp2Finde(csound, &fnum)) != NULL) {
5757             p->tabley = ftp->ftable;
5758             p->tableny = ftp->flen;
5759           }
5760           else return NOTOK;
5761         }
5762 
5763       }
5764       return OK;
5765   }
5766 
FLxyin(CSOUND * csound,FLXYIN * p)5767   static int FLxyin(CSOUND *csound, FLXYIN *p)
5768   {
5769     IGN(csound);
5770       int windx_min = (int)*p->iwindx_min, windx_max = (int)*p->iwindx_max;
5771       int windy_min = (int)*p->iwindy_min, windy_max = (int)*p->iwindy_max;
5772       MYFLT outx_min = *p->ioutx_min, outy_min = *p->iouty_min;
5773 
5774       MYFLT x=Fl::event_x();
5775       MYFLT y=Fl::event_y();
5776 
5777       *p->kinside = 1;
5778 
5779       if (x< windx_min) { x = windx_min; *p->kinside = 0; }
5780       else if (x > windx_max) { x = windx_max; *p->kinside = 0; }
5781 
5782       if (y< windy_min) { y = windy_min; *p->kinside = 0; }
5783       else if (y > windy_max) { y = windy_max; *p->kinside = 0; }
5784 
5785       MYFLT xx = x - windx_min;
5786       xx /= windx_max - windx_min;
5787 
5788       MYFLT yy = windy_max - y;
5789       yy /= windy_max - windy_min;
5790 
5791       switch (p->expx) {
5792       case LIN_:
5793         *p->koutx = outx_min + xx * p->rangex;
5794         break;
5795       case EXP_:
5796         *p->koutx  = outx_min * pow (p->basex, xx * p->rangex);
5797         break;
5798       default: // TABLE
5799         if (p->expx > 0) { //interpolated
5800           MYFLT ndx = xx * (p->tablenx-1);
5801           int index = (int) ndx;
5802           MYFLT v1 = p->tablex[index];
5803           *p->koutx = outx_min + ( v1 + (p->tablex[index+1] - v1) *
5804                                    (ndx - index)) * p->rangex;
5805         }
5806         else // non-interpolated
5807           *p->koutx = outx_min + p->tablex[(int) (xx*p->tablenx)] * p->rangex;
5808       }
5809 
5810       switch (p->expy) {
5811       case LIN_:
5812         *p->kouty = outy_min + yy *  p->rangey;
5813         break;
5814       case EXP_:
5815         *p->kouty  = outy_min * pow (p->basey, yy * p->rangey);
5816         break;
5817       default: // TABLE
5818         if (p->expy > 0) { //interpolated
5819           MYFLT ndx = yy * (p->tableny-1);
5820           int index = (int) ndx;
5821           MYFLT v1 = p->tabley[index];
5822           *p->kouty = outy_min + ( v1 + ( p->tabley[index+1] - v1) *
5823                                    (ndx - index)) * p->rangey;
5824         }
5825         else // non-interpolated
5826           *p->kouty = outy_min + p->tabley[(int) (yy*p->tableny)] * p->rangey;
5827       }
5828       return OK;
5829   }
5830 
5831   //   //FIXME: Should this be defined to 0dbfs?
5832   // #define MAXAMPVU 32767
5833   //
5834   //   //TODO: Implement FLTK meter
5835   //   void VuMeter(CSOUND *csound);
5836   //
5837   //   static int VuMeter_set(CSOUND *csound, FLTKMETER *p) {
5838   //      //isVumeterActive = 1;
5839   //     csoundSetVuMeterCallback(csound, VuMeter);
5840   //     //OPARMS    *O = csound->oparms;
5841   //     int nchnls = csound->nchnls;
5842   //     Fl_Window *o;
5843   //     int iw;
5844   //     iw = (csound->oparms->sfread) ? 30 : 15;
5845   //     o = new Fl_Window(0,0, 410,nchnls * iw+35, "Meter");
5846   //     Fl_Box *box = new Fl_Box(10,3,260,10,"Outputs");
5847   //     box->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE);
5848   //      //else  o = new Fl_Panel(x,y,width,height, panelName);
5849   //      //o->box((Fl_Boxtype) borderType);
5850   //     o->resizable(o);
5851   //     o->callback(flpanel_cb);
5852   //      //o->set_modal();
5853   //     widget_attributes(csound,o);
5854   //
5855   //     PANELS panel(o, (widgetGlobals->stack_count>0) ? 1 : 0);
5856   //     widgetGlobals->fl_windows.push_back(panel);
5857   //     int j;
5858   //
5859   //     for ( j = 0; j < nchnls; j++) {
5860   //       string stemp;
5861   //       char s[10];
5862   //       stemp = itoa(j+1,s,10);
5863   //       char *Name =  new char[stemp.size()+2];
5864   //       strcpy(Name,stemp.c_str());
5865   //       widgetGlobals->allocatedStrings.push_back(Name);
5866   //
5867   //       Fl_Slider *w = new Fl_Slider(20, 18+15*j, 380, 10, Name);
5868   //       w->align(FL_ALIGN_LEFT);
5869   //       p->widg_address[j] = (unsigned long) w;
5870   //       w->type(FL_HOR_FILL_SLIDER);
5871   //       w->color(FL_BACKGROUND_COLOR,FL_GREEN);
5872   //       w->box(FL_PLASTIC_DOWN_BOX);
5873   //       w->range(0,MAXAMPVU);
5874   //     }
5875   //
5876   //     if (csound->oparms->sfread) {
5877   //       box = new Fl_Box(10,18 + 15 * nchnls ,260,10,"Inputs");
5878   //       box->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE);
5879   //       for (  ; j < nchnls*2; j++) {
5880   //         string stemp;
5881   //         char s[10];
5882   //         stemp = itoa(j+1- nchnls,s,10);
5883   //         char *Name =  new char[stemp.size()+2];
5884   //         strcpy(Name,stemp.c_str());
5885   //         widgetGlobals->allocatedStrings.push_back(Name);
5886   //         Fl_Slider *w = new Fl_Slider(20, 30+15*j , 380, 10, Name);
5887   //         w->align(FL_ALIGN_LEFT);
5888   //         p->widg_address[j] = (unsigned long) w;
5889   //         w->type(FL_HOR_FILL_SLIDER);
5890   //         w->color(FL_BACKGROUND_COLOR,FL_YELLOW);
5891   //         w->box(FL_PLASTIC_DOWN_BOX);
5892   //         w->range(0,MAXAMPVU);
5893   //       }
5894   //     }
5895   //     o->end();
5896   //     widgetGlobals->p_vumeter = p;
5897   //     p->dummycycles = csound->ekr / 16 ;
5898   //     p->dummycyc = 0;
5899   //     return OK;
5900   //   }
5901   //
5902   // //extern "C" MYFLT *spout,*spin; //GAB
5903   //
5904   //   void VuMeter(CSOUND *csound){
5905   //     FLTKMETER *p = widgetGlobals->p_vumeter;
5906   //     Fl_Slider *w;
5907   //     int nchnls = csound->nchnls;
5908   //     int      n = (csound->oparms->sfread) ? nchnls * 2 : nchnls;
5909   //     MYFLT temp[MAXCHNLS];
5910   //     int smps = csound->GetKsmps(csound);
5911   //     MYFLT max[MAXCHNLS];
5912   //     MYFLT *spo = csound->spout;
5913   //     MYFLT *spi = csound->spin;
5914   //
5915   //     static int overfl[MAXCHNLS];
5916   //     int i;
5917   //     for (i=0;i<n;i++) {
5918   //       max[i]=0;
5919   //       temp[i] = 0;
5920   //     }
5921   //     do       {
5922   //       for ( i=0; i<nchnls; i++) {
5923   //         if ((temp[i]=(MYFLT) fabs(*spo++)) > max[i] )
5924   //           max[i]=    temp[i];
5925   //       }
5926   //       if (csound->oparms->sfread) {
5927   //         for ( ; i<n; i++) {
5928   //
5929   //           if ((temp[i]=(MYFLT) fabs(*spi++)) > max[i] )
5930   //             max[i]=  temp[i];
5931   //         }
5932   //       }
5933   //              //if ((temp= (MYFLT) fabs(*a++)) > max) max = temp;
5934   //     } while (--smps);
5935   //
5936   //     for (i=0; i<n; i++) {
5937   //       if (max[i] > p->max[i])
5938   //         p->max[i] = (overfl[i] = max[i]>MAXAMPVU) ? MAXAMPVU : max[i];
5939   //     }
5940   //     p->dummycyc++;
5941   //     if (!(p->dummycyc % p->dummycycles)) {
5942   //       for (int j=0; j<n; j++) {
5943   //         w = (Fl_Slider *) p->widg_address[j];
5944   //
5945   //         FLlock();
5946   //         if (overfl[j]) {
5947   //           w->selection_color(FL_RED);
5948   //           overfl[j] = 0;
5949   //         }
5950   //         else {
5951   //           if (j < nchnls) w->selection_color(FL_GREEN);
5952   //           else w->selection_color(FL_YELLOW);
5953   //         }
5954   //         w->value( p->max[j]);
5955   //         w->do_callback(w);
5956   //         FLunlock();
5957   //       }
5958   // #ifdef WIN32
5959   // //                   PostMessage(callback_target,0,0,0);
5960   // #endif
5961   //       for (i=0; i<n; i++)
5962   //         p->max[i] = 0;
5963   //     }
5964   //   }
5965   //
5966 
5967 }       // extern "C"
5968 
5969 #define S(x)    sizeof(x)
5970 
5971 const OENTRY widgetOpcodes_[] = {
5972   { (char*)"FLslider",    S(FLSLIDER), 0, 1,  (char*)"ki",   (char*)"Siijjjjjjj",
5973     (SUBR) fl_slider,     (SUBR) NULL,    (SUBR) NULL },
5974   { (char*)"FLslidBnk",   S(FLSLIDERBANK), 0, 1, (char*)"", (char*)"Siooooooooo",
5975     (SUBR) fl_slider_bank_S, (SUBR) NULL,   (SUBR) NULL },
5976   { (char*)"FLslidBnk.i",   S(FLSLIDERBANK), 0, 1, (char*)"", (char*)"iiooooooooo",
5977     (SUBR) fl_slider_bank, (SUBR) NULL,   (SUBR) NULL },
5978   { (char*)"FLknob",      S(FLKNOB), 0, 1,  (char*)"ki",   (char*)"Siijjjjjjo",
5979     (SUBR) fl_knob,       (SUBR) NULL,     (SUBR) NULL },
5980   { (char*)"FLroller",    S(FLROLLER), 0, 1,  (char*)"ki",   (char*)"Siijjjjjjjj",
5981     (SUBR) fl_roller,               (SUBR) NULL,              (SUBR) NULL },
5982   { (char*)"FLtext",      S(FLTEXT), 0, 1,  (char*)"ki",   (char*)"Siijjjjjj",
5983     (SUBR) fl_text,                 (SUBR) NULL,              (SUBR) NULL },
5984   { (char*)"FLjoy",  S(FLJOYSTICK), 0, 1,  (char*)"kkii", (char*)"Siiiijjjjjjjj",
5985     (SUBR) fl_joystick,             (SUBR) NULL,              (SUBR) NULL },
5986   { (char*)"FLcount",     S(FLCOUNTER), 0, 1,  (char*)"ki",   (char*)"Siiiiiiiiiz",
5987     (SUBR) fl_counter,              (SUBR) NULL,              (SUBR) NULL },
5988   { (char*)"FLbutton",    S(FLBUTTON), 0, 1,  (char*)"ki",   (char*)"Siiiiiiiz",
5989     (SUBR) fl_button,               (SUBR) NULL,              (SUBR) NULL },
5990   { (char*)"FLbutBank",   S(FLBUTTONBANK), 0, 1,  (char*)"ki",   (char*)"iiiiiiiz",
5991     (SUBR) fl_button_bank,          (SUBR) NULL,              (SUBR) NULL },
5992   //     { (char*)"FLkeyb", S(FLKEYB),    0, 1,  (char*)"k",    (char*)"z",
5993   //         (SUBR) FLkeyb,         (SUBR) NULL,              (SUBR) NULL },
5994   { (char*)"FLcolor",     S(FLWIDGCOL),    0, 1,  (char*)"",     (char*)"jjjjjj",
5995     (SUBR) fl_widget_color,         (SUBR) NULL,              (SUBR) NULL },
5996   { (char*)"FLcolor2",    S(FLWIDGCOL2),   0, 1,  (char*)"",     (char*)"jjj",
5997     (SUBR) fl_widget_color2,        (SUBR) NULL,              (SUBR) NULL },
5998   { (char*)"FLlabel",     S(FLWIDGLABEL),  0, 1,  (char*)"",     (char*)"ojojjj",
5999     (SUBR) fl_widget_label,         (SUBR) NULL,              (SUBR) NULL },
6000   { (char*)"FLsetVal_i", S(FL_SET_WIDGET_VALUE_I), 0, 1,  (char*)"", (char*)"ii",
6001     (SUBR) fl_setWidgetValuei,      (SUBR) NULL,              (SUBR) NULL },
6002   { (char*)"FLsetVali",  S(FL_SET_WIDGET_VALUE_I), 0, 1,  (char*)"", (char*)"ii",
6003     (SUBR) fl_setWidgetValuei,      (SUBR) NULL,              (SUBR) NULL },
6004   { (char*)"FLsetVal",    S(FL_SET_WIDGET_VALUE),0,  3,  (char*)"", (char*)"kki",
6005     (SUBR) fl_setWidgetValue_set,   (SUBR) fl_setWidgetValue, (SUBR) NULL },
6006   { (char*)"FLsetColor",  S(FL_SET_COLOR), 0, 1,  (char*)"",     (char*)"iiii",
6007     (SUBR) fl_setColor1,            (SUBR) NULL,              (SUBR) NULL },
6008   { (char*)"FLsetColor2", S(FL_SET_COLOR), 0, 1,  (char*)"",     (char*)"iiii",
6009     (SUBR) fl_setColor2,            (SUBR) NULL,              (SUBR) NULL },
6010   { (char*)"FLsetTextSize", S(FL_SET_TEXTSIZE), 0, 1,  (char*)"",  (char*)"ii",
6011     (SUBR) fl_setTextSize,          (SUBR) NULL,              (SUBR) NULL },
6012   { (char*)"FLsetTextColor", S(FL_SET_COLOR), 0, 1,  (char*)"",  (char*)"iiii",
6013     (SUBR) fl_setTextColor,       (SUBR) NULL,              (SUBR) NULL },
6014   { (char*)"FLsetFont",   S(FL_SET_FONT),  0, 1,  (char*)"",     (char*)"ii",
6015     (SUBR) fl_setFont,              (SUBR) NULL,              (SUBR) NULL },
6016   { (char*)"FLsetTextType", S(FL_SET_FONT), 0, 1,  (char*)"",     (char*)"ii",
6017     (SUBR) fl_setTextType,          (SUBR) NULL,              (SUBR) NULL },
6018   { (char*)"FLsetText",   S(FL_SET_TEXT),  0, 1,  (char*)"",     (char*)"Si",
6019     (SUBR) fl_setText,              (SUBR) NULL,              (SUBR) NULL },
6020   { (char*)"FLsetText",   S(FL_SET_TEXTi),  0, 1,  (char*)"",     (char*)"ii",
6021     (SUBR) fl_setTexti,              (SUBR) NULL,              (SUBR) NULL },
6022   { (char*)"FLsetSize",   S(FL_SET_SIZE),  0, 1,  (char*)"",     (char*)"iii",
6023     (SUBR) fl_setSize,              (SUBR) NULL,              (SUBR) NULL },
6024   { (char*)"FLsetPosition", S(FL_SET_POSITION), 0, 1,  (char*)"", (char*)"iii",
6025     (SUBR) fl_setPosition,          (SUBR) NULL,              (SUBR) NULL },
6026   { (char*)"FLhide",      S(FL_WIDHIDE),   0, 1,  (char*)"",     (char*)"i",
6027     (SUBR) fl_hide,                (SUBR) NULL,              (SUBR) NULL },
6028   { (char*)"FLshow",      S(FL_WIDSHOW),   0, 1,  (char*)"",     (char*)"i",
6029     (SUBR) fl_show,                 (SUBR) NULL,              (SUBR) NULL },
6030   { (char*)"FLsetBox",    S(FL_SETBOX),    0, 1,  (char*)"",     (char*)"ii",
6031     (SUBR) fl_setBox,               (SUBR) NULL,              (SUBR) NULL },
6032   { (char*)"FLsetAlign",  S(FL_TALIGN),    0, 1,  (char*)"",     (char*)"ii",
6033     (SUBR) fl_align,                (SUBR) NULL,              (SUBR) NULL },
6034   { (char*)"FLbox",       S(FL_BOX),       0, 1,  (char*)"i", (char*)"Siiiiiii",
6035     (SUBR) fl_box_s,                  (SUBR) NULL,              (SUBR) NULL },
6036   { (char*)"FLbox",       S(FL_BOX),       0, 1,  (char*)"i", (char*)"iiiiiiii",
6037     (SUBR) fl_box_i,                  (SUBR) NULL,              (SUBR) NULL },
6038   { (char*)"FLvalue",     S(FLVALUE),      0, 1,  (char*)"i",    (char*)"Sjjjj",
6039     (SUBR) fl_value,                (SUBR) NULL,              (SUBR) NULL },
6040   { (char*)"FLpanel",     S(FLPANEL),      0, 1,  (char*)"",  (char*)"Sjjjoooo",
6041     (SUBR) StartPanel,              (SUBR) NULL,              (SUBR) NULL },
6042   { (char*)"FLpanelEnd",  S(FLPANELEND),   0, 1,  (char*)"",     (char*)"",
6043     (SUBR) EndPanel,                (SUBR) NULL,              (SUBR) NULL },
6044   { (char*)"FLpanel_end", S(FLPANELEND),   0, 1,  (char*)"",     (char*)"",
6045     (SUBR) EndPanel,                (SUBR) NULL,              (SUBR) NULL },
6046   { (char*)"FLscroll",    S(FLSCROLL),     0, 1,  (char*)"",     (char*)"iiii",
6047     (SUBR) StartScroll,             (SUBR) NULL,              (SUBR) NULL },
6048   { (char*)"FLscrollEnd", S(FLSCROLLEND),  0, 1,  (char*)"",     (char*)"",
6049     (SUBR) EndScroll,               (SUBR) NULL,              (SUBR) NULL },
6050   { (char*)"FLscroll_end",S(FLSCROLLEND),  0, 1,  (char*)"",     (char*)"",
6051     (SUBR) EndScroll,               (SUBR) NULL,              (SUBR) NULL },
6052   { (char*)"FLpack",      S(FLPACK),       0, 1,  (char*)"",  (char*)"iiiiooo",
6053     (SUBR) StartPack,               (SUBR) NULL,              (SUBR) NULL },
6054   { (char*)"FLpackEnd",   S(FLPACKEND),    0, 1,  (char*)"",     (char*)"",
6055     (SUBR) EndPack,                 (SUBR) NULL,              (SUBR) NULL },
6056   { (char*)"FLpack_end",  S(FLPACKEND),    0, 1,  (char*)"",     (char*)"",
6057     (SUBR) EndPack,                 (SUBR) NULL,              (SUBR) NULL },
6058   { (char*)"FLtabs",      S(FLTABS),       0, 1,  (char*)"",     (char*)"iiii",
6059     (SUBR) StartTabs,               (SUBR) NULL,              (SUBR) NULL },
6060   { (char*)"FLtabsEnd",   S(FLTABSEND),    0, 1,  (char*)"",     (char*)"",
6061     (SUBR) EndTabs,                 (SUBR) NULL,              (SUBR) NULL },
6062   { (char*)"FLtabs_end",  S(FLTABSEND),    0, 1,  (char*)"",     (char*)"",
6063     (SUBR) EndTabs,                 (SUBR) NULL,              (SUBR) NULL },
6064   { (char*)"FLgroup",     S(FLGROUP),      0, 1,  (char*)"",     (char*)"Siiiij",
6065     (SUBR) StartGroup,              (SUBR) NULL,              (SUBR) NULL },
6066   { (char*)"FLgroupEnd",  S(FLGROUPEND),   0, 1,  (char*)"",     (char*)"",
6067     (SUBR) EndGroup,                (SUBR) NULL,              (SUBR) NULL },
6068   { (char*)"FLgroup_end", S(FLGROUPEND),   0, 1,  (char*)"",     (char*)"",
6069     (SUBR) EndGroup,                (SUBR) NULL,              (SUBR) NULL },
6070   { (char*)"FLsetsnap",   S(FLSETSNAP),    0, 1,  (char*)"ii",   (char*)"ioo",
6071     (SUBR) set_snap,                (SUBR) NULL,              (SUBR) NULL },
6072   { (char*)"FLsetSnapGroup", S(FLSETSNAPGROUP), 0, 1,   (char*)"", (char*)"i",
6073     (SUBR)fl_setSnapGroup,  (SUBR) NULL,              (SUBR) NULL },
6074   { (char*)"FLgetsnap",   S(FLGETSNAP),    0, 1,  (char*)"i",    (char*)"io",
6075     (SUBR) get_snap,                (SUBR) NULL,              (SUBR) NULL },
6076   { (char*)"FLsavesnap",  S(FLSAVESNAPS),  0, 1,  (char*)"",     (char*)"So",
6077     (SUBR) save_snap,               (SUBR) NULL,              (SUBR) NULL },
6078   { (char*)"FLloadsnap",  S(FLLOADSNAPS),  0, 1,  (char*)"",     (char*)"So",
6079     (SUBR) load_snap,               (SUBR) NULL,              (SUBR) NULL },
6080   { (char*)"FLrun",       S(FLRUN),        0, 1,  (char*)"",     (char*)"",
6081     (SUBR) FL_run,                  (SUBR) NULL,              (SUBR) NULL },
6082   { (char*)"FLupdate",    S(FLRUN),        0, 1,  (char*)"",     (char*)"",
6083     (SUBR) fl_update,               (SUBR) NULL,              (SUBR) NULL },
6084   { (char*)"FLprintk",    S(FLPRINTK),     0, 3,  (char*)"",     (char*)"iki",
6085     (SUBR) FLprintkset,             (SUBR) FLprintk,          (SUBR) NULL },
6086   { (char*)"FLprintk2",   S(FLPRINTK2),    0, 3,  (char*)"",     (char*)"ki",
6087     (SUBR) FLprintk2set,            (SUBR) FLprintk2,         (SUBR) NULL },
6088   { (char*)"FLcloseButton",    S(FLCLOSEBUTTON), 0, 1,  (char*)"i", (char*)"Siiii",
6089     (SUBR) fl_close_button,               (SUBR) NULL,              (SUBR) NULL },
6090   { (char*)"FLexecButton",    S(FLEXECBUTTON), 0, 1,  (char*)"i", (char*)"Siiii",
6091     (SUBR) fl_exec_button,               (SUBR) NULL,              (SUBR) NULL },
6092   { (char*)"FLkeyIn",    S(FLKEYIN),       0, 3,  (char*)"k",    (char*)"o",
6093     (SUBR)fl_keyin_set,             (SUBR)fl_keyin,           (SUBR) NULL  },
6094   { (char*)"FLxyin",      S(FLXYIN), 0, 3,  (char*)"kkk",(char*)"iiiiiiiioooo",
6095     (SUBR)FLxyin_set,               (SUBR)FLxyin,            (SUBR) NULL  },
6096   { (char*)"FLmouse",     S(FLMOUSE),             0, 3,  (char*)"kkkkk",(char*)"o",
6097     (SUBR)fl_mouse_set,             (SUBR)fl_mouse,           (SUBR) NULL  },
6098   { (char*)"FLvslidBnk",  S(FLSLIDERBANK), 0, 1,  (char*)"",  (char*)"Siooooooooo",
6099     (SUBR)fl_vertical_slider_bank_S,   (SUBR) NULL,             (SUBR) NULL  },
6100    { (char*)"FLvslidBnk.i", S(FLSLIDERBANK), 0, 1, (char*)"", (char*)"iiooooooooo",
6101     (SUBR)fl_vertical_slider_bank,   (SUBR) NULL,             (SUBR) NULL  },
6102   { (char*)"FLslidBnk2",  S(FLSLIDERBANK2),0, 1,  (char*)"",  (char*)"Siiiooooo",
6103     (SUBR)fl_slider_bank2_S ,          (SUBR) NULL,             (SUBR) NULL  },
6104     { (char*)"FLslidBnk2.i", S(FLSLIDERBANK2),0, 1, (char*)"", (char*)"iiiiooooo",
6105     (SUBR)fl_slider_bank2 ,          (SUBR) NULL,             (SUBR) NULL  },
6106   { (char*)"FLvslidBnk2", S(FLSLIDERBANK2),0, 1,  (char*)"",  (char*)"Siiiooooo",
6107     (SUBR)fl_vertical_slider_bank2_S,  (SUBR) NULL,             (SUBR) NULL  },
6108     { (char*)"FLvslidBnk2.i", S(FLSLIDERBANK2),0, 1, (char*)"", (char*)"iiiiooooo",
6109     (SUBR)fl_vertical_slider_bank2,  (SUBR) NULL,             (SUBR) NULL  },
6110   { (char*)"FLslidBnkGetHandle",S(FLSLDBNK_GETHANDLE),0, 1, (char*)"i", (char*)"",
6111     (SUBR)fl_slider_bank_getHandle,  (SUBR) NULL,             (SUBR) NULL  },
6112   { (char*)"FLslidBnkSet",S(FLSLDBNK_SET), 0, 1,  (char*)"",  (char*)"iiooo",
6113     (SUBR)fl_slider_bank_setVal,     (SUBR) NULL,             (SUBR) NULL  },
6114   { (char*)"FLslidBnkSetk",  S(FLSLDBNK2_SETK), 0, 3,  (char*)"",  (char*)"kiiooo",
6115     (SUBR)fl_slider_bank_setVal_k_set,(SUBR)fl_slider_bank_setVal_k,(SUBR) NULL },
6116   { (char*)"FLslidBnk2Set",  S(FLSLDBNK_SET), 0, 1,  (char*)"",  (char*)"iiooo",
6117     (SUBR)fl_slider_bank2_setVal,    (SUBR) NULL,             (SUBR) NULL  },
6118   { (char*)"FLslidBnk2Setk", S(FLSLDBNK2_SETK), 0, 3,  (char*)"",  (char*)"kiiooo",
6119     (SUBR)fl_slider_bank2_setVal_k_set, (SUBR)fl_slider_bank2_setVal_k,
6120     (SUBR) NULL },
6121   { (char*)"FLhvsBox",    S(FL_HVSBOX),    0, 1,  (char*)"i",    (char*)"iiiiiio",
6122     (SUBR)fl_hvsbox,                (SUBR) NULL,              (SUBR) NULL  },
6123   { (char*)"FLhvsBoxSetValue",S(FL_SET_HVS_VALUE), 0, 3, (char*)"",  (char*)"kki",
6124     (SUBR)fl_setHvsValue_set,       (SUBR)fl_setHvsValue,     (SUBR) NULL  },
6125   //     { (char*)"FLmeter",   S(FLTKMETER),      0, 1,  (char*)"",  (char*)"",
6126   //         (SUBR)VuMeter_set,  (SUBR) NULL,       (SUBR) NULL  },
6127   { NULL,             0,                      0, 0,  NULL,   NULL,
6128     (SUBR) NULL,                    (SUBR) NULL,              (SUBR) NULL }
6129 };
6130