themes: Workaround for bug where a background color of RGB 0,0,0 in Black color schem...
[ntk.git] / src / glut_compatability.cxx
blob0338675ec131cd471e02120821d07094872deeb3
1 //
2 // "$Id: glut_compatability.cxx 7818 2010-11-11 18:22:43Z engelsman $"
3 //
4 // GLUT emulation routines for the Fast Light Tool Kit (FLTK).
5 //
6 // Copyright 1998-2010 by Bill Spitzak and others.
7 //
8 // This library is free software; you can redistribute it and/or
9 // modify it under the terms of the GNU Library General Public
10 // License as published by the Free Software Foundation; either
11 // version 2 of the License, or (at your option) any later version.
13 // This library 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 GNU
16 // Library General Public License for more details.
18 // You should have received a copy of the GNU Library General Public
19 // License along with this library; if not, write to the Free Software
20 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
21 // USA.
23 // Please report all bugs and problems on the following page:
25 // http://www.fltk.org/str.php
28 // Emulation of Glut using fltk.
30 // GLUT is Copyright (c) Mark J. Kilgard, 1994, 1995, 1996.
31 // "This program is freely distributable without licensing fees and is
32 // provided without guarantee or warrantee expressed or implied. This
33 // program is -not- in the public domain."
35 // Although I have copied the GLUT API, none of my code is based on
36 // any Glut implementation details and is therefore covered by the LGPL.
38 #include "flstring.h"
39 #if HAVE_GL
41 # include <FL/glut.H>
42 # ifdef HAVE_GLXGETPROCADDRESSARB
43 # define GLX_GLXEXT_LEGACY
44 # include <GL/glx.h>
45 # endif // HAVE_GLXGETPROCADDRESSARB
46 # ifdef HAVE_DLFCN_H
47 # include <dlfcn.h>
48 # endif // HAVE_DLFCN_H
49 # define MAXWINDOWS 32
50 static Fl_Glut_Window *windows[MAXWINDOWS+1];
52 static void (*glut_idle_func)() = 0; // global glut idle function
54 Fl_Glut_Window *glut_window;
55 int glut_menu;
56 void (*glut_menustate_function)(int);
57 void (*glut_menustatus_function)(int,int,int);
59 static void default_reshape(int w, int h) {glViewport(0,0,w,h);}
60 static void default_display() {}
62 void Fl_Glut_Window::make_current() {
63 glut_window = this;
64 if (shown()) Fl_Gl_Window::make_current();
67 static int indraw;
68 void Fl_Glut_Window::draw() {
69 glut_window = this;
70 indraw = 1;
71 if (!valid()) {reshape(w(),h()); valid(1);}
72 display();
73 indraw = 0;
76 void glutSwapBuffers() {
77 if (!indraw) glut_window->swap_buffers();
80 void Fl_Glut_Window::draw_overlay() {
81 glut_window = this;
82 if (!valid()) {reshape(w(),h()); valid(1);}
83 overlaydisplay();
86 static void domenu(int, int, int);
88 int Fl_Glut_Window::handle(int event) {
89 make_current();
90 int ex = Fl::event_x();
91 int ey = Fl::event_y();
92 int button;
93 switch (event) {
95 case FL_PUSH:
96 if (keyboard || special) Fl::focus(this);
97 button = Fl::event_button()-1;
98 if (button<0) button = 0;
99 if (button>2) button = 2;
100 if (menu[button]) {domenu(menu[button],ex,ey); return 1;}
101 mouse_down |= 1<<button;
102 if (mouse) {mouse(button,GLUT_DOWN,ex,ey); return 1;}
103 if (motion) return 1;
104 break;
106 case FL_MOUSEWHEEL:
107 button = Fl::event_dy();
108 while (button < 0) {if (mouse) mouse(3,GLUT_DOWN,ex,ey); ++button;}
109 while (button > 0) {if (mouse) mouse(4,GLUT_DOWN,ex,ey); --button;}
110 return 1;
112 case FL_RELEASE:
113 for (button = 0; button < 3; button++) if (mouse_down & (1<<button)) {
114 if (mouse) mouse(button,GLUT_UP,ex,ey);
116 mouse_down = 0;
117 return 1;
119 case FL_ENTER:
120 if (entry) {entry(GLUT_ENTERED); return 1;}
121 if (passivemotion) return 1;
122 break;
124 case FL_LEAVE:
125 if (entry) {entry(GLUT_LEFT); return 1;}
126 if (passivemotion) return 1;
127 break;
129 case FL_DRAG:
130 if (motion) {motion(ex, ey); return 1;}
131 break;
133 case FL_MOVE:
134 if (passivemotion) {passivemotion(ex, ey); return 1;}
135 break;
137 case FL_FOCUS:
138 if (keyboard || special) return 1;
139 break;
141 case FL_SHORTCUT:
142 if (!keyboard && !special) break;
144 case FL_KEYBOARD:
145 if (Fl::event_text()[0]) {
146 if (keyboard) {keyboard(Fl::event_text()[0],ex,ey); return 1;}
147 break;
148 } else {
149 if (special) {
150 int k = Fl::event_key();
151 if (k > FL_F && k <= FL_F_Last) k -= FL_F;
152 special(k,ex,ey);
153 return 1;
155 break;
158 case FL_HIDE:
159 if (visibility) visibility(GLUT_NOT_VISIBLE);
160 break;
162 case FL_SHOW:
163 if (visibility) visibility(GLUT_VISIBLE);
164 break;
167 return Fl_Gl_Window::handle(event);
170 static int glut_mode = GLUT_RGB | GLUT_SINGLE | GLUT_DEPTH;
172 void Fl_Glut_Window::_init() {
173 for (number=1; number<MAXWINDOWS; number++) if (!windows[number]) break;
174 windows[number] = this;
175 menu[0] = menu[1] = menu[2] = 0;
176 reshape = default_reshape;
177 display = default_display;
178 overlaydisplay = default_display;
179 keyboard = 0;
180 mouse = 0;
181 motion = 0;
182 passivemotion = 0;
183 entry = 0;
184 visibility = 0;
185 special = 0;
186 mouse_down = 0;
187 mode(glut_mode);
190 /** Creates a glut window, registers to the glut windows list.*/
191 Fl_Glut_Window::Fl_Glut_Window(int W, int H, const char *t) :
192 Fl_Gl_Window(W,H,t) {_init();}
194 /** Creates a glut window, registers to the glut windows list.*/
195 Fl_Glut_Window::Fl_Glut_Window(int X,int Y,int W,int H, const char *t) :
196 Fl_Gl_Window(X,Y,W,H,t) {_init();}
198 static int initargc;
199 static char **initargv;
201 void glutInit(int *argc, char **argv) {
202 initargc = *argc;
203 initargv = new char*[*argc+1];
204 int i,j;
205 for (i=0; i<=*argc; i++) initargv[i] = argv[i];
206 for (i=j=1; i<*argc; ) {
207 if (Fl::arg(*argc,argv,i));
208 else argv[j++] = argv[i++];
210 argv[j] = 0;
211 *argc = j;
214 void glutInitDisplayMode(unsigned int mode) {
215 glut_mode = mode;
218 void glutMainLoop() {Fl::run();}
220 ////////////////////////////////////////////////////////////////
222 static int initx=0, inity=0, initw=300, inith=300, initpos=0;
224 void glutInitWindowPosition(int x, int y) {
225 initx = x; inity = y; initpos = 1;
228 void glutInitWindowSize(int w, int h) {
229 initw = w; inith = h;
232 int glutCreateWindow(char *title) {
233 return glutCreateWindow((const char*)title);
236 int glutCreateWindow(const char *title) {
237 Fl_Glut_Window *W;
238 if (initpos) {
239 W = new Fl_Glut_Window(initx,inity,initw,inith,title);
240 initpos = 0;
241 } else {
242 W = new Fl_Glut_Window(initw,inith,title);
244 W->resizable(W);
245 if (initargc) {
246 W->show(initargc,initargv);
247 initargc = 0;
248 } else {
249 W->show();
251 W->valid(0);
252 W->context_valid(0);
253 W->make_current();
254 return W->number;
257 int glutCreateSubWindow(int win, int x, int y, int w, int h) {
258 Fl_Glut_Window *W = new Fl_Glut_Window(x,y,w,h,0);
259 windows[win]->add(W);
260 if (windows[win]->shown()) W->show();
261 W->make_current();
262 return W->number;
264 /** Destroys the glut window, first unregister it from the glut windows list */
265 Fl_Glut_Window::~Fl_Glut_Window() {
266 if (glut_window == this) glut_window = 0;
267 windows[number] = 0;
270 void glutDestroyWindow(int win) {
271 // should destroy children!!!
272 delete windows[win];
275 void glutPostWindowRedisplay(int win) {
276 windows[win]->redraw();
279 void glutSetWindow(int win) {
280 windows[win]->make_current();
283 ////////////////////////////////////////////////////////////////
284 #include <FL/Fl_Menu_Item.H>
286 struct menu {
287 void (*cb)(int);
288 Fl_Menu_Item *m;
289 int size;
290 int alloc;
293 #define MAXMENUS 32
294 static menu menus[MAXMENUS+1];
296 static void domenu(int n, int ex, int ey) {
297 glut_menu = n;
298 menu *m = &menus[n];
299 if (glut_menustate_function) glut_menustate_function(1);
300 if (glut_menustatus_function) glut_menustatus_function(1,ex,ey);
301 const Fl_Menu_Item* g = m->m->popup(Fl::event_x(), Fl::event_y(), 0);
302 if (g && g->callback_) ((void (*)(int))(g->callback_))(int(g->argument()));
303 if (glut_menustatus_function) glut_menustatus_function(0,ex,ey);
304 if (glut_menustate_function) glut_menustate_function(0);
307 int glutCreateMenu(void (*cb)(int)) {
308 int i;
309 for (i=1; i<MAXMENUS; i++) if (!menus[i].cb) break;
310 menu *m = &menus[i];
311 m->cb = cb;
312 return glut_menu = i;
315 void glutDestroyMenu(int n) {
316 menu *m = &menus[n];
317 delete[] m->m;
318 m->m = 0;
319 m->cb = 0;
320 m->size = m->alloc = 0;
323 static Fl_Menu_Item* additem(menu *m) {
324 if (m->size+1 >= m->alloc) {
325 m->alloc = m->size*2+10;
326 Fl_Menu_Item* nm = new Fl_Menu_Item[m->alloc];
327 for (int i=0; i<m->size; i++) nm[i] = m->m[i];
328 delete[] m->m;
329 m->m = nm;
331 int n = m->size++;
332 m->m[n+1].text = 0;
333 Fl_Menu_Item* i = &(m->m[n]);
334 i->shortcut_ = 0;
335 i->flags = 0;
336 i->labeltype_ = i->labelfont_ = i->labelsize_ = i->labelcolor_ = 0;
337 return i;
340 void glutAddMenuEntry(char *label, int value) {
341 menu *m = &menus[glut_menu];
342 Fl_Menu_Item* i = additem(m);
343 i->text = label;
344 i->callback_ = (Fl_Callback*)(m->cb);
345 i->user_data_ = (void *)value;
348 void glutAddSubMenu(char *label, int submenu) {
349 menu *m = &menus[glut_menu];
350 Fl_Menu_Item* i = additem(m);
351 i->text = label;
352 i->callback_ = 0;
353 i->user_data_ = (void *)(menus[submenu].m);
354 i->flags = FL_PUP_SUBMENU;
357 void glutChangeToMenuEntry(int item, char *label, int value) {
358 menu *m = &menus[glut_menu];
359 Fl_Menu_Item* i = &m->m[item-1];
360 i->text = label;
361 i->callback_ = (Fl_Callback*)(m->cb);
362 i->user_data_ = (void *)value;
363 i->flags = 0;
366 void glutChangeToSubMenu(int item, char *label, int submenu) {
367 menu *m = &menus[glut_menu];
368 Fl_Menu_Item* i = &m->m[item-1];
369 i->text = label;
370 i->callback_ = 0;
371 i->user_data_ = (void *)(menus[submenu].m);
372 i->flags = FL_PUP_SUBMENU;
375 void glutRemoveMenuItem(int item) {
376 menu *m = &menus[glut_menu];
377 if (item > m->size || item < 1) return;
378 for (int i = item-1; i <= m->size; i++) m->m[i] = m->m[i+1];
379 m->size--;
382 ////////////////////////////////////////////////////////////////
384 int glutGet(GLenum type) {
385 switch (type) {
386 case GLUT_RETURN_ZERO: return 0;
387 case GLUT_WINDOW_X: return glut_window->x();
388 case GLUT_WINDOW_Y: return glut_window->y();
389 case GLUT_WINDOW_WIDTH: return glut_window->w();
390 case GLUT_WINDOW_HEIGHT: return glut_window->h();
391 case GLUT_WINDOW_PARENT:
392 if (glut_window->parent())
393 return ((Fl_Glut_Window *)(glut_window->parent()))->number;
394 else
395 return 0;
396 //case GLUT_WINDOW_NUM_CHILDREN:
397 //case GLUT_WINDOW_CURSOR: return
398 case GLUT_SCREEN_WIDTH: return Fl::w();
399 case GLUT_SCREEN_HEIGHT: return Fl::h();
400 //case GLUT_SCREEN_WIDTH_MM:
401 //case GLUT_SCREEN_HEIGHT_MM:
402 case GLUT_MENU_NUM_ITEMS: return menus[glut_menu].size;
403 case GLUT_DISPLAY_MODE_POSSIBLE: return Fl_Gl_Window::can_do(glut_mode);
404 case GLUT_INIT_WINDOW_X: return initx;
405 case GLUT_INIT_WINDOW_Y: return inity;
406 case GLUT_INIT_WINDOW_WIDTH: return initw;
407 case GLUT_INIT_WINDOW_HEIGHT: return inith;
408 case GLUT_INIT_DISPLAY_MODE: return glut_mode;
409 //case GLUT_ELAPSED_TIME:
410 case GLUT_WINDOW_BUFFER_SIZE:
411 if (glutGet(GLUT_WINDOW_RGBA))
412 return glutGet(GLUT_WINDOW_RED_SIZE)+
413 glutGet(GLUT_WINDOW_GREEN_SIZE)+
414 glutGet(GLUT_WINDOW_BLUE_SIZE)+
415 glutGet(GLUT_WINDOW_ALPHA_SIZE);
416 else
417 return glutGet(GLUT_WINDOW_COLORMAP_SIZE);
418 case GLUT_VERSION: return 20400;
419 default: {GLint p; glGetIntegerv(type, &p); return p;}
423 int glutLayerGet(GLenum type) {
424 switch (type) {
425 case GLUT_OVERLAY_POSSIBLE: return glut_window->can_do_overlay();
426 //case GLUT_LAYER_IN_USE:
427 //case GLUT_HAS_OVERLAY:
428 case GLUT_TRANSPARENT_INDEX: return 0; // true for SGI
429 case GLUT_NORMAL_DAMAGED: return glut_window->damage();
430 case GLUT_OVERLAY_DAMAGED: return 1; // kind of works...
431 default: return 0;
435 int glutDeviceGet(GLenum type) {
436 switch (type) {
437 case GLUT_HAS_KEYBOARD : return 1;
438 case GLUT_HAS_MOUSE : return 1;
439 case GLUT_NUM_MOUSE_BUTTONS : return 3;
440 default : return 0;
444 // Get extension function address...
445 GLUTproc glutGetProcAddress(const char *procName) {
446 # ifdef WIN32
447 return (GLUTproc)wglGetProcAddress((LPCSTR)procName);
449 # elif defined(HAVE_DLSYM) && defined(HAVE_DLFCN_H)
450 char symbol[1024];
452 snprintf(symbol, sizeof(symbol), "_%s", procName);
454 # ifdef RTLD_DEFAULT
455 return (GLUTproc)dlsym(RTLD_DEFAULT, symbol);
457 # else // No RTLD_DEFAULT support, so open the current a.out symbols...
458 static void *rtld_default = 0;
460 if (!rtld_default) rtld_default = dlopen(0, RTLD_LAZY);
462 if (rtld_default) return (GLUTproc)dlsym(rtld_default, symbol);
463 else return 0;
465 # endif // RTLD_DEFAULT
467 # elif defined(HAVE_GLXGETPROCADDRESSARB)
468 return (GLUTproc)glXGetProcAddressARB((const GLubyte *)procName);
470 # else
471 return (GLUTproc)0;
472 # endif // WIN32
475 // Parse the GL_EXTENSIONS string to see if the named extension is
476 // supported.
478 // This code was copied from FreeGLUT 2.4.0 which carries the
479 // following notice:
481 // Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved.
482 int glutExtensionSupported( const char* extension )
484 if (!extension || strchr(extension, ' ')) return 0;
486 const char *extensions, *start;
487 const int len = strlen( extension );
489 start = extensions = (const char *) glGetString(GL_EXTENSIONS);
491 if (!extensions) return 0;
493 for (;;) {
494 const char *p = strstr(extensions, extension);
495 if (!p) return 0; /* not found */
496 /* check that the match isn't a super string */
497 if ((p == start || p[-1] == ' ') &&
498 (p[len] == ' ' || p[len] == 0)) return 1;
499 /* skip the false match and continue */
500 extensions = p + len;
504 // Add a mechanism to handle adding/removing the glut idle function
505 // without depending on the (deprecated) set_idle method.
506 void glutIdleFunc(void (*f)())
508 // no change
509 if(glut_idle_func == f) return;
510 // remove current idle
511 if(glut_idle_func) Fl::remove_idle((void (*)(void *))glut_idle_func);
512 // install new idle func - if one was passed
513 if(f) Fl::add_idle((void (*)(void *))f);
514 // record new idle func - even if it is NULL
515 glut_idle_func = f;
516 } // glutIdleFunc
518 #endif // HAVE_GL
521 // End of "$Id: glut_compatability.cxx 7818 2010-11-11 18:22:43Z engelsman $".