fltk 1.3.0rc3
About: FLTK (Fast Light Tool Kit) is a cross-platform C++ GUI toolkit for UNIX/Linux (X11), Microsoft Windows, and MacOS X. Release candidate.
  SfR Fresh Dox: fltk-1.3.0rc3-source.tar.gz ("inofficial" and yet experimental doxygen-generated source code documentation)  

glut_compatability.cxx

Go to the documentation of this file.
00001 //
00002 // "$Id: glut_compatability.cxx 7818 2010-11-11 18:22:43Z engelsman $"
00003 //
00004 // GLUT emulation routines for the Fast Light Tool Kit (FLTK).
00005 //
00006 // Copyright 1998-2010 by Bill Spitzak and others.
00007 //
00008 // This library is free software; you can redistribute it and/or
00009 // modify it under the terms of the GNU Library General Public
00010 // License as published by the Free Software Foundation; either
00011 // version 2 of the License, or (at your option) any later version.
00012 //
00013 // This library is distributed in the hope that it will be useful,
00014 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00015 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00016 // Library General Public License for more details.
00017 //
00018 // You should have received a copy of the GNU Library General Public
00019 // License along with this library; if not, write to the Free Software
00020 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
00021 // USA.
00022 //
00023 // Please report all bugs and problems on the following page:
00024 //
00025 //     http://www.fltk.org/str.php
00026 //
00027 
00028 // Emulation of Glut using fltk.
00029 
00030 // GLUT is Copyright (c) Mark J. Kilgard, 1994, 1995, 1996.
00031 // "This program is freely distributable without licensing fees  and is
00032 // provided without guarantee or warrantee expressed or  implied. This
00033 // program is -not- in the public domain."
00034 
00035 // Although I have copied the GLUT API, none of my code is based on
00036 // any Glut implementation details and is therefore covered by the LGPL.
00037 
00038 #include "flstring.h"
00039 #if HAVE_GL
00040 
00041 #  include <FL/glut.H>
00042 #  ifdef HAVE_GLXGETPROCADDRESSARB
00043 #    define GLX_GLXEXT_LEGACY
00044 #    include <GL/glx.h>
00045 #  endif // HAVE_GLXGETPROCADDRESSARB
00046 #  ifdef HAVE_DLFCN_H
00047 #    include <dlfcn.h>
00048 #  endif // HAVE_DLFCN_H
00049 #  define MAXWINDOWS 32
00050 static Fl_Glut_Window *windows[MAXWINDOWS+1];
00051 
00052 static void (*glut_idle_func)() = 0; // global glut idle function
00053 
00054 Fl_Glut_Window *glut_window;
00055 int glut_menu;
00056 void (*glut_menustate_function)(int);
00057 void (*glut_menustatus_function)(int,int,int);
00058 
00059 static void default_reshape(int w, int h) {glViewport(0,0,w,h);}
00060 static void default_display() {}
00061 
00062 void Fl_Glut_Window::make_current() {
00063   glut_window = this;
00064   if (shown()) Fl_Gl_Window::make_current();
00065 }
00066 
00067 static int indraw;
00068 void Fl_Glut_Window::draw() {
00069   glut_window = this;
00070   indraw = 1;
00071   if (!valid()) {reshape(w(),h()); valid(1);}
00072   display();
00073   indraw = 0;
00074 }
00075 
00076 void glutSwapBuffers() {
00077   if (!indraw) glut_window->swap_buffers();
00078 }
00079 
00080 void Fl_Glut_Window::draw_overlay() {
00081   glut_window = this;
00082   if (!valid()) {reshape(w(),h()); valid(1);}
00083   overlaydisplay();
00084 }
00085 
00086 static void domenu(int, int, int);
00087 
00088 int Fl_Glut_Window::handle(int event) {
00089   make_current();
00090   int ex = Fl::event_x();
00091   int ey = Fl::event_y();
00092   int button;
00093   switch (event) {
00094 
00095   case FL_PUSH:
00096     if (keyboard || special) Fl::focus(this);
00097     button = Fl::event_button()-1;
00098     if (button<0) button = 0;
00099     if (button>2) button = 2;
00100     if (menu[button]) {domenu(menu[button],ex,ey); return 1;}
00101     mouse_down |= 1<<button;
00102     if (mouse) {mouse(button,GLUT_DOWN,ex,ey); return 1;}
00103     if (motion) return 1;
00104     break;
00105 
00106   case FL_MOUSEWHEEL:
00107     button = Fl::event_dy();
00108     while (button < 0) {if (mouse) mouse(3,GLUT_DOWN,ex,ey); ++button;}
00109     while (button > 0) {if (mouse) mouse(4,GLUT_DOWN,ex,ey); --button;}
00110     return 1;
00111 
00112   case FL_RELEASE:
00113     for (button = 0; button < 3; button++) if (mouse_down & (1<<button)) {
00114       if (mouse) mouse(button,GLUT_UP,ex,ey);
00115     }
00116     mouse_down = 0;
00117     return 1;
00118 
00119   case FL_ENTER:
00120     if (entry) {entry(GLUT_ENTERED); return 1;}
00121     if (passivemotion) return 1;
00122     break;
00123 
00124   case FL_LEAVE:
00125     if (entry) {entry(GLUT_LEFT); return 1;}
00126     if (passivemotion) return 1;
00127     break;
00128 
00129   case FL_DRAG:
00130     if (motion) {motion(ex, ey); return 1;}
00131     break;
00132 
00133   case FL_MOVE:
00134     if (passivemotion) {passivemotion(ex, ey); return 1;}
00135     break;
00136 
00137   case FL_FOCUS:
00138     if (keyboard || special) return 1;
00139     break;
00140 
00141   case FL_SHORTCUT:
00142     if (!keyboard && !special) break;
00143 
00144   case FL_KEYBOARD:
00145     if (Fl::event_text()[0]) {
00146       if (keyboard) {keyboard(Fl::event_text()[0],ex,ey); return 1;}
00147       break;
00148     } else {
00149       if (special) {
00150         int k = Fl::event_key();
00151         if (k > FL_F && k <= FL_F_Last) k -= FL_F;
00152         special(k,ex,ey);
00153         return 1;
00154       }
00155       break;
00156     }
00157 
00158   case FL_HIDE:
00159     if (visibility) visibility(GLUT_NOT_VISIBLE);
00160     break;
00161 
00162   case FL_SHOW:
00163     if (visibility) visibility(GLUT_VISIBLE);
00164     break;
00165   }
00166 
00167   return Fl_Gl_Window::handle(event);
00168 }
00169 
00170 static int glut_mode = GLUT_RGB | GLUT_SINGLE | GLUT_DEPTH;
00171 
00172 void Fl_Glut_Window::_init() {
00173   for (number=1; number<MAXWINDOWS; number++) if (!windows[number]) break;
00174   windows[number] = this;
00175   menu[0] = menu[1] = menu[2] = 0;
00176   reshape = default_reshape;
00177   display = default_display;
00178   overlaydisplay = default_display;
00179   keyboard = 0;
00180   mouse = 0;
00181   motion = 0;
00182   passivemotion = 0;
00183   entry = 0;
00184   visibility = 0;
00185   special = 0;
00186   mouse_down = 0;
00187   mode(glut_mode);
00188 }
00189 
00191 Fl_Glut_Window::Fl_Glut_Window(int W, int H, const char *t) :
00192   Fl_Gl_Window(W,H,t) {_init();}
00193 
00195 Fl_Glut_Window::Fl_Glut_Window(int X,int Y,int W,int H, const char *t) :
00196   Fl_Gl_Window(X,Y,W,H,t) {_init();}
00197 
00198 static int initargc;
00199 static char **initargv;
00200 
00201 void glutInit(int *argc, char **argv) {
00202   initargc = *argc;
00203   initargv = new char*[*argc+1];
00204   int i,j;
00205   for (i=0; i<=*argc; i++) initargv[i] = argv[i];
00206   for (i=j=1; i<*argc; ) {
00207     if (Fl::arg(*argc,argv,i));
00208     else argv[j++] = argv[i++];
00209   }
00210   argv[j] = 0;
00211   *argc = j;
00212 }
00213 
00214 void glutInitDisplayMode(unsigned int mode) {
00215   glut_mode = mode;
00216 }
00217 
00218 void glutMainLoop() {Fl::run();}
00219 
00221 
00222 static int initx=0, inity=0, initw=300, inith=300, initpos=0;
00223 
00224 void glutInitWindowPosition(int x, int y) {
00225   initx = x; inity = y; initpos = 1;
00226 }
00227 
00228 void glutInitWindowSize(int w, int h) {
00229   initw = w; inith = h;
00230 }
00231 
00232 int glutCreateWindow(char *title) {
00233   return glutCreateWindow((const char*)title);
00234 }
00235 
00236 int glutCreateWindow(const char *title) {
00237   Fl_Glut_Window *W;
00238   if (initpos) {
00239     W = new Fl_Glut_Window(initx,inity,initw,inith,title);
00240     initpos = 0;
00241   } else {
00242     W = new Fl_Glut_Window(initw,inith,title);
00243   }
00244   W->resizable(W);
00245   if (initargc) {
00246     W->show(initargc,initargv);
00247     initargc = 0;
00248   } else {
00249     W->show();
00250   }
00251   W->valid(0);
00252   W->context_valid(0);
00253   W->make_current();
00254   return W->number;
00255 }
00256 
00257 int glutCreateSubWindow(int win, int x, int y, int w, int h) {
00258   Fl_Glut_Window *W = new Fl_Glut_Window(x,y,w,h,0);
00259   windows[win]->add(W);
00260   if (windows[win]->shown()) W->show();
00261   W->make_current();
00262   return W->number;
00263 }
00265 Fl_Glut_Window::~Fl_Glut_Window() {
00266   if (glut_window == this) glut_window = 0;
00267   windows[number] = 0;
00268 }
00269 
00270 void glutDestroyWindow(int win) {
00271   // should destroy children!!!
00272   delete windows[win];
00273 }
00274 
00275 void glutPostWindowRedisplay(int win) {
00276   windows[win]->redraw();
00277 }
00278 
00279 void glutSetWindow(int win) {
00280   windows[win]->make_current();
00281 }
00282 
00284 #include <FL/Fl_Menu_Item.H>
00285 
00286 struct menu {
00287   void (*cb)(int);
00288   Fl_Menu_Item *m;
00289   int size;
00290   int alloc;
00291 };
00292 
00293 #define MAXMENUS 32
00294 static menu menus[MAXMENUS+1];
00295 
00296 static void domenu(int n, int ex, int ey) {
00297   glut_menu = n;
00298   menu *m = &menus[n];
00299   if (glut_menustate_function) glut_menustate_function(1);
00300   if (glut_menustatus_function) glut_menustatus_function(1,ex,ey);
00301   const Fl_Menu_Item* g = m->m->popup(Fl::event_x(), Fl::event_y(), 0);
00302   if (g && g->callback_) ((void (*)(int))(g->callback_))(int(g->argument()));
00303   if (glut_menustatus_function) glut_menustatus_function(0,ex,ey);
00304   if (glut_menustate_function) glut_menustate_function(0);
00305 }
00306 
00307 int glutCreateMenu(void (*cb)(int)) {
00308   int i;
00309   for (i=1; i<MAXMENUS; i++) if (!menus[i].cb) break;
00310   menu *m = &menus[i];
00311   m->cb = cb;
00312   return glut_menu = i;
00313 }
00314 
00315 void glutDestroyMenu(int n) {
00316   menu *m = &menus[n];
00317   delete[] m->m;
00318   m->m = 0;
00319   m->cb = 0;
00320   m->size = m->alloc = 0;
00321 }
00322 
00323 static Fl_Menu_Item* additem(menu *m) {
00324   if (m->size+1 >= m->alloc) {
00325     m->alloc = m->size*2+10;
00326     Fl_Menu_Item* nm = new Fl_Menu_Item[m->alloc];
00327     for (int i=0; i<m->size; i++) nm[i] = m->m[i];
00328     delete[] m->m;
00329     m->m = nm;
00330   }
00331   int n = m->size++;
00332   m->m[n+1].text = 0;
00333   Fl_Menu_Item* i = &(m->m[n]);
00334   i->shortcut_ = 0;
00335   i->flags = 0;
00336   i->labeltype_ = i->labelfont_ = i->labelsize_ = i->labelcolor_ = 0;
00337   return i;
00338 }
00339 
00340 void glutAddMenuEntry(char *label, int value) {
00341   menu *m = &menus[glut_menu];
00342   Fl_Menu_Item* i = additem(m);
00343   i->text = label;
00344   i->callback_ = (Fl_Callback*)(m->cb);
00345   i->user_data_ = (void *)value;
00346 }
00347 
00348 void glutAddSubMenu(char *label, int submenu) {
00349   menu *m = &menus[glut_menu];
00350   Fl_Menu_Item* i = additem(m);
00351   i->text = label;
00352   i->callback_ = 0;
00353   i->user_data_ = (void *)(menus[submenu].m);
00354   i->flags = FL_PUP_SUBMENU;
00355 }
00356 
00357 void glutChangeToMenuEntry(int item, char *label, int value) {
00358   menu *m = &menus[glut_menu];
00359   Fl_Menu_Item* i = &m->m[item-1];
00360   i->text = label;
00361   i->callback_ = (Fl_Callback*)(m->cb);
00362   i->user_data_ = (void *)value;
00363   i->flags = 0;
00364 }
00365 
00366 void glutChangeToSubMenu(int item, char *label, int submenu) {
00367   menu *m = &menus[glut_menu];
00368   Fl_Menu_Item* i = &m->m[item-1];
00369   i->text = label;
00370   i->callback_ = 0;
00371   i->user_data_ = (void *)(menus[submenu].m);
00372   i->flags = FL_PUP_SUBMENU;
00373 }
00374 
00375 void glutRemoveMenuItem(int item) {
00376   menu *m = &menus[glut_menu];
00377   if (item > m->size || item < 1) return;
00378   for (int i = item-1; i <= m->size; i++) m->m[i] = m->m[i+1];
00379   m->size--;
00380 }
00381 
00383 
00384 int glutGet(GLenum type) {
00385   switch (type) {
00386   case GLUT_RETURN_ZERO: return 0;
00387   case GLUT_WINDOW_X: return glut_window->x();
00388   case GLUT_WINDOW_Y: return glut_window->y();
00389   case GLUT_WINDOW_WIDTH: return glut_window->w();
00390   case GLUT_WINDOW_HEIGHT: return glut_window->h();
00391   case GLUT_WINDOW_PARENT:
00392     if (glut_window->parent())
00393       return ((Fl_Glut_Window *)(glut_window->parent()))->number;
00394     else
00395       return 0;
00396 //case GLUT_WINDOW_NUM_CHILDREN:
00397 //case GLUT_WINDOW_CURSOR: return 
00398   case GLUT_SCREEN_WIDTH: return Fl::w();
00399   case GLUT_SCREEN_HEIGHT: return Fl::h();
00400 //case GLUT_SCREEN_WIDTH_MM:
00401 //case GLUT_SCREEN_HEIGHT_MM:
00402   case GLUT_MENU_NUM_ITEMS: return menus[glut_menu].size;
00403   case GLUT_DISPLAY_MODE_POSSIBLE: return Fl_Gl_Window::can_do(glut_mode);
00404   case GLUT_INIT_WINDOW_X: return initx;
00405   case GLUT_INIT_WINDOW_Y: return inity;
00406   case GLUT_INIT_WINDOW_WIDTH: return initw;
00407   case GLUT_INIT_WINDOW_HEIGHT: return inith;
00408   case GLUT_INIT_DISPLAY_MODE: return glut_mode;
00409 //case GLUT_ELAPSED_TIME:
00410   case GLUT_WINDOW_BUFFER_SIZE:
00411     if (glutGet(GLUT_WINDOW_RGBA))
00412       return glutGet(GLUT_WINDOW_RED_SIZE)+
00413         glutGet(GLUT_WINDOW_GREEN_SIZE)+
00414         glutGet(GLUT_WINDOW_BLUE_SIZE)+
00415         glutGet(GLUT_WINDOW_ALPHA_SIZE);
00416     else
00417       return glutGet(GLUT_WINDOW_COLORMAP_SIZE);
00418   case GLUT_VERSION: return 20400;
00419   default: {GLint p; glGetIntegerv(type, &p); return p;}
00420   }
00421 }
00422 
00423 int glutLayerGet(GLenum type) {
00424   switch (type) {
00425   case GLUT_OVERLAY_POSSIBLE: return glut_window->can_do_overlay();
00426 //case GLUT_LAYER_IN_USE:
00427 //case GLUT_HAS_OVERLAY:
00428   case GLUT_TRANSPARENT_INDEX: return 0; // true for SGI
00429   case GLUT_NORMAL_DAMAGED: return glut_window->damage();
00430   case GLUT_OVERLAY_DAMAGED: return 1; // kind of works...
00431   default: return 0;
00432   }
00433 }
00434 
00435 int glutDeviceGet(GLenum type) {
00436   switch (type) {
00437     case GLUT_HAS_KEYBOARD : return 1;
00438     case GLUT_HAS_MOUSE : return 1;
00439     case GLUT_NUM_MOUSE_BUTTONS : return 3;
00440     default : return 0;
00441   }
00442 }
00443 
00444 // Get extension function address...
00445 GLUTproc glutGetProcAddress(const char *procName) {
00446 #  ifdef WIN32
00447   return (GLUTproc)wglGetProcAddress((LPCSTR)procName);
00448 
00449 #  elif defined(HAVE_DLSYM) && defined(HAVE_DLFCN_H)
00450   char symbol[1024];
00451 
00452   snprintf(symbol, sizeof(symbol), "_%s", procName);
00453 
00454 #    ifdef RTLD_DEFAULT
00455   return (GLUTproc)dlsym(RTLD_DEFAULT, symbol);
00456 
00457 #    else // No RTLD_DEFAULT support, so open the current a.out symbols...
00458   static void *rtld_default = 0;
00459 
00460   if (!rtld_default) rtld_default = dlopen(0, RTLD_LAZY);
00461 
00462   if (rtld_default) return (GLUTproc)dlsym(rtld_default, symbol);
00463   else return 0;
00464 
00465 #    endif // RTLD_DEFAULT
00466 
00467 #  elif defined(HAVE_GLXGETPROCADDRESSARB)
00468   return (GLUTproc)glXGetProcAddressARB((const GLubyte *)procName);
00469 
00470 #  else
00471   return (GLUTproc)0;
00472 #  endif // WIN32
00473 }
00474 
00475 // Parse the GL_EXTENSIONS string to see if the named extension is
00476 // supported.
00477 //
00478 // This code was copied from FreeGLUT 2.4.0 which carries the
00479 // following notice:
00480 //
00481 //     Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved.
00482 int glutExtensionSupported( const char* extension )
00483 {
00484   if (!extension || strchr(extension, ' ')) return 0;
00485 
00486   const char *extensions, *start;
00487   const int len = strlen( extension );
00488   
00489   start = extensions = (const char *) glGetString(GL_EXTENSIONS);
00490 
00491   if (!extensions) return 0;
00492 
00493   for (;;) {
00494     const char *p = strstr(extensions, extension);
00495     if (!p) return 0;  /* not found */
00496     /* check that the match isn't a super string */
00497     if ((p == start || p[-1] == ' ') &&
00498         (p[len] == ' ' || p[len] == 0)) return 1;
00499     /* skip the false match and continue */
00500     extensions = p + len;
00501   }
00502 }
00503 
00504 // Add a mechanism to handle adding/removing the glut idle function
00505 // without depending on the (deprecated) set_idle method.
00506 void glutIdleFunc(void (*f)())
00507 {
00508   // no change
00509   if(glut_idle_func == f) return;
00510   // remove current idle
00511   if(glut_idle_func) Fl::remove_idle((void (*)(void *))glut_idle_func);
00512   // install new idle func - if one was passed
00513   if(f) Fl::add_idle((void (*)(void *))f);
00514   // record new idle func - even if it is NULL
00515   glut_idle_func = f;
00516 } // glutIdleFunc
00517 
00518 #endif // HAVE_GL
00519 
00520 //
00521 // End of "$Id: glut_compatability.cxx 7818 2010-11-11 18:22:43Z engelsman $".
00522 //