Commited Gustavo Hime's NT patches/fixes.
git-svn-id: file:///fltk/svn/fltk/trunk@7 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
This commit is contained in:
parent
f9039b2ae2
commit
e7d805a88c
181
FL/Fl_Window.H
181
FL/Fl_Window.H
@ -1,90 +1,91 @@
|
||||
// Fl_Window.H
|
||||
|
||||
// fltk (Fast Light Tool Kit) version 0.99
|
||||
// Copyright (C) 1998 Bill Spitzak
|
||||
|
||||
#ifndef Fl_Window_H
|
||||
#define Fl_Window_H
|
||||
|
||||
#include "Fl_Group.H"
|
||||
|
||||
#define FL_WINDOW 0xF0 // all subclasses have type() >= this
|
||||
|
||||
class Fl_Window : public Fl_Group {
|
||||
|
||||
friend class Fl_X; Fl_X *i; // points at the system-specific stuff
|
||||
|
||||
const char* iconlabel_;
|
||||
const char* xclass_;
|
||||
// size_range stuff:
|
||||
short minw, minh, maxw, maxh;
|
||||
uchar dw, dh, aspect, size_range_set;
|
||||
void size_range_();
|
||||
// values for flags():
|
||||
enum {
|
||||
FL_MODAL = 64,
|
||||
FL_NOBORDER = 8,
|
||||
FL_FORCE_POSITION = 16,
|
||||
FL_NON_MODAL = 32
|
||||
};
|
||||
static Fl_Window *current_;
|
||||
void _Fl_Window(); // constructor innards
|
||||
|
||||
protected:
|
||||
|
||||
virtual void draw();
|
||||
virtual void flush();
|
||||
|
||||
public:
|
||||
|
||||
Fl_Window(int,int,int,int, const char* = 0);
|
||||
Fl_Window(int,int, const char* = 0);
|
||||
virtual ~Fl_Window();
|
||||
|
||||
virtual int handle(int);
|
||||
|
||||
virtual void resize(int,int,int,int);
|
||||
void border(int b);
|
||||
void clear_border() {set_flag(FL_NOBORDER);}
|
||||
int border() const {return !(flags() & FL_NOBORDER);}
|
||||
void set_modal() {set_flag(FL_MODAL);}
|
||||
uchar modal() const {return flags() & FL_MODAL;}
|
||||
void set_non_modal() {set_flag(FL_NON_MODAL);}
|
||||
uchar non_modal() const {return flags() & (FL_NON_MODAL|FL_MODAL);}
|
||||
|
||||
void hotspot(int x, int y, int offscreen = 0);
|
||||
void hotspot(const Fl_Widget*, int offscreen = 0);
|
||||
void hotspot(const Fl_Widget& p, int offscreen = 0) {hotspot(&p,offscreen);}
|
||||
void free_position() {clear_flag(FL_FORCE_POSITION);}
|
||||
void size_range(int a, int b, int c=0, int d=0, int e=0, int f=0, int g=0) {
|
||||
minw=a; minh=b; maxw=c; maxh=d; dw=e; dh=f; aspect=g; size_range_();}
|
||||
|
||||
const char* label() const {return Fl_Widget::label();}
|
||||
const char* iconlabel() const {return iconlabel_;}
|
||||
void label(const char*);
|
||||
void iconlabel(const char*);
|
||||
void label(const char* label, const char* iconlabel);
|
||||
const char* xclass() const {return xclass_;}
|
||||
void xclass(const char* c) {xclass_ = c;}
|
||||
|
||||
int shown() {return i != 0;}
|
||||
virtual void show();
|
||||
virtual void hide();
|
||||
void show(int, char**);
|
||||
void fullscreen();
|
||||
void fullscreen_off(int,int,int,int);
|
||||
void iconize();
|
||||
|
||||
int x_root() const ;
|
||||
int y_root() const ;
|
||||
|
||||
static Fl_Window *current() {return current_;}
|
||||
void make_current();
|
||||
|
||||
// for back-compatability only:
|
||||
void cursor(Fl_Cursor, Fl_Color=FL_BLACK, Fl_Color=FL_WHITE);
|
||||
static void default_callback(Fl_Window*, void* v);
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
// Fl_Window.H
|
||||
|
||||
// fltk (Fast Light Tool Kit) version 0.99
|
||||
// Copyright (C) 1998 Bill Spitzak
|
||||
|
||||
#ifndef Fl_Window_H
|
||||
#define Fl_Window_H
|
||||
|
||||
#include "Fl_Group.H"
|
||||
|
||||
#define FL_WINDOW 0xF0 // all subclasses have type() >= this
|
||||
|
||||
class Fl_Window : public Fl_Group {
|
||||
|
||||
friend class Fl_X; Fl_X *i; // points at the system-specific stuff
|
||||
|
||||
const char* iconlabel_;
|
||||
const char* xclass_;
|
||||
// size_range stuff:
|
||||
short minw, minh, maxw, maxh;
|
||||
uchar dw, dh, aspect, size_range_set;
|
||||
void size_range_();
|
||||
// values for flags():
|
||||
enum {
|
||||
FL_MODAL = 64,
|
||||
FL_NOBORDER = 8,
|
||||
FL_FORCE_POSITION = 16,
|
||||
FL_NON_MODAL = 32
|
||||
};
|
||||
static Fl_Window *current_;
|
||||
void _Fl_Window(); // constructor innards
|
||||
|
||||
protected:
|
||||
|
||||
virtual void draw();
|
||||
virtual void flush();
|
||||
|
||||
public:
|
||||
|
||||
Fl_Window(int,int,int,int, const char* = 0);
|
||||
Fl_Window(int,int, const char* = 0);
|
||||
virtual ~Fl_Window();
|
||||
|
||||
virtual int handle(int);
|
||||
|
||||
virtual void resize(int,int,int,int);
|
||||
void border(int b);
|
||||
void clear_border() {set_flag(FL_NOBORDER);}
|
||||
int border() const {return !(flags() & FL_NOBORDER);}
|
||||
void set_modal() {set_flag(FL_MODAL);}
|
||||
uchar modal() const {return flags() & FL_MODAL;}
|
||||
void set_non_modal() {set_flag(FL_NON_MODAL);}
|
||||
uchar non_modal() const {return flags() & (FL_NON_MODAL|FL_MODAL);}
|
||||
|
||||
void hotspot(int x, int y, int offscreen = 0);
|
||||
void hotspot(const Fl_Widget*, int offscreen = 0);
|
||||
void hotspot(const Fl_Widget& p, int offscreen = 0) {hotspot(&p,offscreen);}
|
||||
void free_position() {clear_flag(FL_FORCE_POSITION);}
|
||||
void size_range(int a, int b, int c=0, int d=0, int e=0, int f=0, int g=0) {
|
||||
minw=a; minh=b; maxw=c; maxh=d; dw=e; dh=f; aspect=g; size_range_();}
|
||||
|
||||
const char* label() const {return Fl_Widget::label();}
|
||||
const char* iconlabel() const {return iconlabel_;}
|
||||
void label(const char*);
|
||||
void iconlabel(const char*);
|
||||
void label(const char* label, const char* iconlabel);
|
||||
const char* xclass() const {return xclass_;}
|
||||
void xclass(const char* c) {xclass_ = c;}
|
||||
|
||||
int shown() {return i != 0;}
|
||||
virtual void show();
|
||||
virtual void hide();
|
||||
void show(int, char**);
|
||||
void fullscreen();
|
||||
void fullscreen_off(int,int,int,int);
|
||||
void iconize();
|
||||
void expose(uchar flags,int X,int Y,int W,int H);
|
||||
|
||||
int x_root() const ;
|
||||
int y_root() const ;
|
||||
|
||||
static Fl_Window *current() {return current_;}
|
||||
void make_current();
|
||||
|
||||
// for back-compatability only:
|
||||
void cursor(Fl_Cursor, Fl_Color=FL_BLACK, Fl_Color=FL_WHITE);
|
||||
static void default_callback(Fl_Window*, void* v);
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
169
FL/win32.H
169
FL/win32.H
@ -1,80 +1,89 @@
|
||||
// win32.H
|
||||
|
||||
// Do not directly include this file, instead use <FL/x.H>. It will
|
||||
// include this file if WIN32 is defined. This is to encourage
|
||||
// portability of even the system-specific code...
|
||||
|
||||
#include <windows.h>
|
||||
#ifndef LPMINMAXINFO
|
||||
// the gcc header files are missing some stuff:
|
||||
#define LPMINMAXINFO MINMAXINFO*
|
||||
#define VK_LWIN 0x5B
|
||||
#define VK_RWIN 0x5C
|
||||
#define VK_APPS 0x5D
|
||||
#endif
|
||||
|
||||
// some random X equivalents
|
||||
#define Window HWND
|
||||
#define XPoint POINT
|
||||
struct XRectangle {int x, y, width, height;};
|
||||
struct Region {int x, y, r, b; void operator=(int x) {r = x;}};
|
||||
inline void XClipBox(Region& i, XRectangle* o) {
|
||||
o->x = i.x; o->y = i.y; o->width = i.r-i.x; o->height = i.b-i.y;}
|
||||
#define fl_clip_region(R) fl_clip((R).x,(R).y,(R).r-(R).x,(R).b-(R).y)
|
||||
#define XDestroyWindow(a,b) DestroyWindow(b)
|
||||
#define XMapWindow(a,b) ShowWindow(b, SW_RESTORE)
|
||||
#define XUnmapWindow(a,b) ShowWindow(b, SW_HIDE)
|
||||
|
||||
#include "Fl_Window.H"
|
||||
// this object contains all win32-specific stuff about a window:
|
||||
// Warning: this object is highly subject to change!
|
||||
class Fl_X {
|
||||
public:
|
||||
Window xid;
|
||||
HBITMAP other_xid; // for double-buffered windows
|
||||
Fl_Window* w;
|
||||
Region region;
|
||||
Fl_X *next;
|
||||
HDC private_dc; // used for OpenGL
|
||||
HCURSOR cursor;
|
||||
static Fl_X* first;
|
||||
static Fl_X* i(const Fl_Window* w) {return w->i;}
|
||||
void setwindow(Fl_Window* wi) {w=wi; wi->i=this;}
|
||||
void flush() {w->flush();}
|
||||
void set_minmax(LPMINMAXINFO minmax);
|
||||
void mapraise();
|
||||
static Fl_X* make(Fl_Window*);
|
||||
};
|
||||
extern HCURSOR fl_default_cursor;
|
||||
inline Window fl_xid(const Fl_Window*w) {return Fl_X::i(w)->xid;}
|
||||
Fl_Window* fl_find(Window xid);
|
||||
extern char fl_override_redirect; // hack into Fl_Window::make_xid()
|
||||
extern int fl_background_pixel; // hack into Fl_Window::make_xid()
|
||||
|
||||
// most recent fl_color() or fl_rgbcolor() points at one of these:
|
||||
extern struct Fl_XMap {
|
||||
COLORREF rgb; // this should be the type the RGB() macro returns
|
||||
HPEN pen; // pen, 0 if none created yet
|
||||
int brush; // ref to solid brush, 0 if none created yet
|
||||
} *fl_current_xmap;
|
||||
inline COLORREF fl_RGB() {return fl_current_xmap->rgb;}
|
||||
inline HPEN fl_pen() {return fl_current_xmap->pen;}
|
||||
HBRUSH fl_brush(); // allocates a brush if necessary
|
||||
|
||||
extern HINSTANCE fl_display;
|
||||
extern Window fl_window;
|
||||
extern HDC fl_gc;
|
||||
extern HPALETTE fl_palette; // non-zero only on 8-bit displays!
|
||||
extern HDC fl_DC(Window);
|
||||
extern MSG fl_msg;
|
||||
|
||||
// off-screen pixmaps: create, destroy, draw into, copy to window
|
||||
#define Fl_Offscreen HBITMAP
|
||||
#define fl_create_offscreen(w, h) CreateCompatibleBitmap(fl_gc, w, h)
|
||||
extern void fl_switch_offscreen(HBITMAP);
|
||||
#define fl_begin_offscreen(b) HDC _sw=fl_gc; fl_switch_offscreen(b)
|
||||
#define fl_end_offscreen() fl_gc = _sw
|
||||
void fl_make_current(HBITMAP bitmap);
|
||||
void fl_copy_offscreen(int x,int y,int w,int h,HBITMAP pixmap,int srcx,int srcy);
|
||||
#define fl_delete_offscreen(bitmap) DeleteObject(bitmap);
|
||||
|
||||
// win32.H
|
||||
|
||||
// Do not directly include this file, instead use <FL/x.H>. It will
|
||||
// include this file if WIN32 is defined. This is to encourage
|
||||
// portability of even the system-specific code...
|
||||
|
||||
#include <windows.h>
|
||||
#ifndef LPMINMAXINFO
|
||||
// the gcc header files are missing some stuff:
|
||||
#define LPMINMAXINFO MINMAXINFO*
|
||||
#define VK_LWIN 0x5B
|
||||
#define VK_RWIN 0x5C
|
||||
#define VK_APPS 0x5D
|
||||
#endif
|
||||
|
||||
// some random X equivalents
|
||||
typedef HWND Window;
|
||||
typedef POINT XPoint;
|
||||
struct XRectangle {int x, y, width, height;};
|
||||
typedef HRGN Region;
|
||||
void fl_clip_region(Region);
|
||||
inline Region XRectangleRegion(int x, int y, int w, int h) {
|
||||
return CreateRectRgn(x,y,x+w,y+h);
|
||||
}
|
||||
inline void XDestroyRegion(Region r) {DeleteObject(r);}
|
||||
|
||||
#define XDestroyWindow(a,b) DestroyWindow(b)
|
||||
#define XMapWindow(a,b) ShowWindow(b, SW_RESTORE)
|
||||
#define XUnmapWindow(a,b) ShowWindow(b, SW_HIDE)
|
||||
|
||||
#include "Fl_Window.H"
|
||||
// this object contains all win32-specific stuff about a window:
|
||||
// Warning: this object is highly subject to change!
|
||||
class Fl_X {
|
||||
public:
|
||||
Window xid;
|
||||
HBITMAP other_xid; // for double-buffered windows
|
||||
Fl_Window* w;
|
||||
Region region;
|
||||
Fl_X *next;
|
||||
HDC private_dc; // used for OpenGL
|
||||
HCURSOR cursor;
|
||||
static Fl_X* first;
|
||||
static Fl_X* i(const Fl_Window* w) {return w->i;}
|
||||
void setwindow(Fl_Window* wi) {w=wi; wi->i=this;}
|
||||
void flush() {w->flush();}
|
||||
void set_minmax(LPMINMAXINFO minmax);
|
||||
void mapraise();
|
||||
static Fl_X* make(Fl_Window*);
|
||||
};
|
||||
extern HCURSOR fl_default_cursor;
|
||||
inline Window fl_xid(const Fl_Window*w) {return Fl_X::i(w)->xid;}
|
||||
Fl_Window* fl_find(Window xid);
|
||||
extern char fl_override_redirect; // hack into Fl_Window::make_xid()
|
||||
extern int fl_background_pixel; // hack into Fl_Window::make_xid()
|
||||
|
||||
// most recent fl_color() or fl_rgbcolor() points at one of these:
|
||||
extern struct Fl_XMap {
|
||||
COLORREF rgb; // this should be the type the RGB() macro returns
|
||||
HPEN pen; // pen, 0 if none created yet
|
||||
int brush; // ref to solid brush, 0 if none created yet
|
||||
} *fl_current_xmap;
|
||||
inline COLORREF fl_RGB() {return fl_current_xmap->rgb;}
|
||||
inline HPEN fl_pen() {return fl_current_xmap->pen;}
|
||||
HBRUSH fl_brush(); // allocates a brush if necessary
|
||||
|
||||
extern HINSTANCE fl_display;
|
||||
extern Window fl_window;
|
||||
extern HDC fl_gc;
|
||||
extern HDC window_dc; // for double-buffered windows
|
||||
extern HPALETTE fl_palette; // non-zero only on 8-bit displays!
|
||||
extern HDC fl_GetDC(Window);
|
||||
extern MSG fl_msg;
|
||||
|
||||
// off-screen pixmaps: create, destroy, draw into, copy to window
|
||||
#define Fl_Offscreen HBITMAP
|
||||
#define fl_create_offscreen(w, h) CreateCompatibleBitmap(fl_gc, w, h)
|
||||
extern void fl_switch_offscreen(HBITMAP);
|
||||
|
||||
inline void fl_begin_offscreen(HBITMAP b) {
|
||||
window_dc = fl_gc; fl_switch_offscreen(b);
|
||||
}
|
||||
inline void fl_end_offscreen() {
|
||||
fl_gc = window_dc;
|
||||
}
|
||||
void fl_make_current(HBITMAP bitmap);
|
||||
void fl_copy_offscreen(int x,int y,int w,int h,HBITMAP pixmap,int srcx,int srcy);
|
||||
#define fl_delete_offscreen(bitmap) DeleteObject(bitmap);
|
||||
|
||||
|
1131
src/Fl.cxx
1131
src/Fl.cxx
File diff suppressed because it is too large
Load Diff
@ -1,157 +1,163 @@
|
||||
// Fl_Double_Window.C
|
||||
|
||||
// A double-buffered window. This is achieved by using the Xdbe extension,
|
||||
// or a pixmap if that is not available.
|
||||
|
||||
// On systems that support double buffering "naturally" the base
|
||||
// Fl_Window class will probably do double-buffer and this subclass
|
||||
// does nothing.
|
||||
|
||||
#include <config.h>
|
||||
#include <FL/Fl.H>
|
||||
#include <FL/Fl_Double_Window.H>
|
||||
#include <FL/x.H>
|
||||
#include <FL/fl_draw.H>
|
||||
|
||||
#if USE_XDBE
|
||||
|
||||
#include <X11/extensions/Xdbe.h>
|
||||
|
||||
static int use_xdbe;
|
||||
|
||||
static int can_xdbe() {
|
||||
static int tried;
|
||||
if (!tried) {
|
||||
tried = 1;
|
||||
int event_base, error_base;
|
||||
if (!XdbeQueryExtension(fl_display, &event_base, &error_base)) return 0;
|
||||
Drawable root = RootWindow(fl_display,fl_screen);
|
||||
int numscreens = 1;
|
||||
XdbeScreenVisualInfo *a = XdbeGetVisualInfo(fl_display,&root,&numscreens);
|
||||
if (!a) return 0;
|
||||
for (int j = 0; j < a->count; j++)
|
||||
if (a->visinfo[j].visual == fl_visual->visualid
|
||||
/*&& a->visinfo[j].perflevel > 0*/) {use_xdbe = 1; break;}
|
||||
XdbeFreeVisualInfo(a);
|
||||
}
|
||||
return use_xdbe;
|
||||
}
|
||||
#endif
|
||||
|
||||
void Fl_Double_Window::show() {
|
||||
#ifndef WIN32
|
||||
if (!shown()) { // don't set the background pixel
|
||||
fl_open_display();
|
||||
Fl_X::make_xid(this);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
Fl_Window::show();
|
||||
}
|
||||
|
||||
#ifdef WIN32
|
||||
|
||||
// Code to switch output to an off-screen window:
|
||||
// this is lame, I allow two to exist...
|
||||
|
||||
static HDC blt_gc[2];
|
||||
|
||||
void fl_switch_offscreen(HBITMAP bitmap) {
|
||||
if (!blt_gc[0]) for (int i = 0; i < 2; i++) {
|
||||
blt_gc[i] = CreateCompatibleDC(fl_gc);
|
||||
SetTextAlign(blt_gc[i], TA_BASELINE|TA_LEFT);
|
||||
SetBkMode(blt_gc[i], TRANSPARENT);
|
||||
#if USE_COLORMAP
|
||||
if (fl_palette) SelectPalette(blt_gc[i], fl_palette, FALSE);
|
||||
#endif
|
||||
}
|
||||
int which = 0; if (fl_gc == blt_gc[0]) which = 1;
|
||||
SelectObject(blt_gc[which], bitmap);
|
||||
fl_gc = blt_gc[which];
|
||||
}
|
||||
|
||||
void fl_copy_offscreen(int x,int y,int w,int h,HBITMAP bitmap,int srcx,int srcy) {
|
||||
int which = 0; if (fl_gc == blt_gc[0]) which = 1;
|
||||
SelectObject(blt_gc[which], bitmap);
|
||||
BitBlt(fl_gc, x, y, w, h, blt_gc[which], srcx, srcy, SRCCOPY);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// protected method used by Fl_Overlay_Window to fake overlay:
|
||||
void Fl_Double_Window::_flush(int eraseoverlay) {
|
||||
make_current(); // make sure fl_gc is non-zero
|
||||
Fl_X *i = Fl_X::i(this);
|
||||
if (!i->other_xid) {
|
||||
#if USE_XDBE
|
||||
if (can_xdbe()) i->other_xid =
|
||||
XdbeAllocateBackBufferName(fl_display, fl_xid(this), XdbeCopied);
|
||||
else
|
||||
#endif
|
||||
i->other_xid = fl_create_offscreen(w(), h());
|
||||
clear_damage(~0);
|
||||
}
|
||||
XRectangle rect = {0,0,w(),h()};
|
||||
if (damage()) {
|
||||
if (i->region && !eraseoverlay) XClipBox(i->region, &rect);
|
||||
if ( // don't draw if back buffer is ok
|
||||
#if USE_XDBE
|
||||
use_xdbe ||
|
||||
#endif
|
||||
damage() != 2) {
|
||||
#ifdef WIN32
|
||||
fl_begin_offscreen(i->other_xid);
|
||||
fl_clip_region(i->region); i->region = 0;
|
||||
draw();
|
||||
fl_end_offscreen();
|
||||
#else
|
||||
fl_window = i->other_xid;
|
||||
fl_clip_region(i->region); i->region = 0;
|
||||
draw();
|
||||
fl_window = i->xid;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
fl_clip_region(0);
|
||||
#if USE_XDBE
|
||||
if (use_xdbe) {
|
||||
XdbeSwapInfo s;
|
||||
s.swap_window = fl_xid(this);
|
||||
s.swap_action = XdbeCopied;
|
||||
XdbeSwapBuffers(fl_display,&s,1);
|
||||
} else
|
||||
#endif
|
||||
fl_copy_offscreen(rect.x, rect.y, rect.width, rect.height,
|
||||
i->other_xid, rect.x, rect.y);
|
||||
}
|
||||
|
||||
void Fl_Double_Window::flush() {_flush(0);}
|
||||
|
||||
void Fl_Double_Window::resize(int X,int Y,int W,int H) {
|
||||
int ow = w();
|
||||
int oh = h();
|
||||
Fl_Window::resize(X,Y,W,H);
|
||||
#if USE_XDBE
|
||||
if (use_xdbe) return;
|
||||
#endif
|
||||
Fl_X* i = Fl_X::i(this);
|
||||
if (i && i->other_xid && (ow != w() || oh != h())) {
|
||||
fl_delete_offscreen(i->other_xid);
|
||||
i->other_xid = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void Fl_Double_Window::hide() {
|
||||
Fl_X* i = Fl_X::i(this);
|
||||
if (i && i->other_xid) {
|
||||
#if USE_XDBE
|
||||
if (!use_xdbe)
|
||||
#endif
|
||||
fl_delete_offscreen(i->other_xid);
|
||||
}
|
||||
Fl_Window::hide();
|
||||
}
|
||||
|
||||
Fl_Double_Window::~Fl_Double_Window() {
|
||||
hide();
|
||||
}
|
||||
// Fl_Double_Window.C
|
||||
|
||||
// A double-buffered window. This is achieved by using the Xdbe extension,
|
||||
// or a pixmap if that is not available.
|
||||
|
||||
// On systems that support double buffering "naturally" the base
|
||||
// Fl_Window class will probably do double-buffer and this subclass
|
||||
// does nothing.
|
||||
|
||||
#include <config.h>
|
||||
#include <FL/Fl.H>
|
||||
#include <FL/Fl_Double_Window.H>
|
||||
#include <FL/x.H>
|
||||
#include <FL/fl_draw.H>
|
||||
|
||||
#if USE_XDBE
|
||||
|
||||
#include <X11/extensions/Xdbe.h>
|
||||
|
||||
static int use_xdbe;
|
||||
|
||||
static int can_xdbe() {
|
||||
static int tried;
|
||||
if (!tried) {
|
||||
tried = 1;
|
||||
int event_base, error_base;
|
||||
if (!XdbeQueryExtension(fl_display, &event_base, &error_base)) return 0;
|
||||
Drawable root = RootWindow(fl_display,fl_screen);
|
||||
int numscreens = 1;
|
||||
XdbeScreenVisualInfo *a = XdbeGetVisualInfo(fl_display,&root,&numscreens);
|
||||
if (!a) return 0;
|
||||
for (int j = 0; j < a->count; j++)
|
||||
if (a->visinfo[j].visual == fl_visual->visualid
|
||||
/*&& a->visinfo[j].perflevel > 0*/) {use_xdbe = 1; break;}
|
||||
XdbeFreeVisualInfo(a);
|
||||
}
|
||||
return use_xdbe;
|
||||
}
|
||||
#endif
|
||||
|
||||
void Fl_Double_Window::show() {
|
||||
#ifndef WIN32
|
||||
if (!shown()) { // don't set the background pixel
|
||||
fl_open_display();
|
||||
Fl_X::make_xid(this);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
Fl_Window::show();
|
||||
}
|
||||
|
||||
#ifdef WIN32
|
||||
|
||||
// I've removed the second one (never understool why
|
||||
// it was there to begin with).
|
||||
|
||||
static HDC blt_gc;
|
||||
|
||||
void fl_switch_offscreen(HBITMAP bitmap) {
|
||||
if (!blt_gc) {
|
||||
blt_gc = CreateCompatibleDC(fl_gc);
|
||||
SetTextAlign(blt_gc, TA_BASELINE|TA_LEFT);
|
||||
SetBkMode(blt_gc, TRANSPARENT);
|
||||
#if USE_COLORMAP
|
||||
if (fl_palette) SelectPalette(blt_gc, fl_palette, FALSE);
|
||||
#endif
|
||||
}
|
||||
SelectObject(blt_gc, bitmap);
|
||||
fl_gc = blt_gc;
|
||||
}
|
||||
|
||||
void fl_copy_offscreen(int x,int y,int w,int h,HBITMAP bitmap,int srcx,int srcy) {
|
||||
SelectObject(blt_gc, bitmap);
|
||||
BitBlt(window_dc, x, y, w, h, blt_gc, srcx, srcy, SRCCOPY);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// protected method used by Fl_Overlay_Window to fake overlay:
|
||||
void Fl_Double_Window::_flush(int eraseoverlay) {
|
||||
make_current(); // make sure fl_gc is non-zero
|
||||
Fl_X *i = Fl_X::i(this);
|
||||
if (!i->other_xid) {
|
||||
#if USE_XDBE
|
||||
if (can_xdbe()) i->other_xid =
|
||||
XdbeAllocateBackBufferName(fl_display, fl_xid(this), XdbeCopied);
|
||||
else
|
||||
#endif
|
||||
i->other_xid = fl_create_offscreen(w(), h());
|
||||
clear_damage(~0);
|
||||
}
|
||||
XRectangle rect = {0,0,w(),h()};
|
||||
if (damage()) {
|
||||
if ( // don't draw if back buffer is ok
|
||||
#if USE_XDBE
|
||||
use_xdbe ||
|
||||
#endif
|
||||
damage() != 2) {
|
||||
/*
|
||||
#ifdef WIN32
|
||||
fl_begin_offscreen(i->other_xid);
|
||||
fl_clip_region(i->region); i->region = 0;
|
||||
draw();
|
||||
fl_end_offscreen();
|
||||
#else
|
||||
*/
|
||||
#ifdef WIN32
|
||||
fl_begin_offscreen(i->other_xid);
|
||||
#endif
|
||||
fl_window = i->other_xid;
|
||||
fl_clip_region(i->region); i->region = 0;
|
||||
draw();
|
||||
fl_window = i->xid;
|
||||
#ifdef WIN32
|
||||
fl_end_offscreen();
|
||||
#endif
|
||||
//#endif
|
||||
}
|
||||
}
|
||||
fl_clip_region(0);
|
||||
#if USE_XDBE
|
||||
if (i->region && !eraseoverlay) XClipBox(i->region, &rect);
|
||||
if (use_xdbe) {
|
||||
XdbeSwapInfo s;
|
||||
s.swap_window = fl_xid(this);
|
||||
s.swap_action = XdbeCopied;
|
||||
XdbeSwapBuffers(fl_display,&s,1);
|
||||
} else
|
||||
#endif
|
||||
fl_copy_offscreen(rect.x, rect.y, rect.width, rect.height,
|
||||
i->other_xid, rect.x, rect.y);
|
||||
}
|
||||
|
||||
void Fl_Double_Window::flush() {_flush(0);}
|
||||
|
||||
void Fl_Double_Window::resize(int X,int Y,int W,int H) {
|
||||
int ow = w();
|
||||
int oh = h();
|
||||
Fl_Window::resize(X,Y,W,H);
|
||||
#if USE_XDBE
|
||||
if (use_xdbe) return;
|
||||
#endif
|
||||
Fl_X* i = Fl_X::i(this);
|
||||
if (i && i->other_xid && (ow != w() || oh != h())) {
|
||||
fl_delete_offscreen(i->other_xid);
|
||||
i->other_xid = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void Fl_Double_Window::hide() {
|
||||
Fl_X* i = Fl_X::i(this);
|
||||
if (i && i->other_xid) {
|
||||
#if USE_XDBE
|
||||
if (!use_xdbe)
|
||||
#endif
|
||||
fl_delete_offscreen(i->other_xid);
|
||||
}
|
||||
Fl_Window::hide();
|
||||
}
|
||||
|
||||
Fl_Double_Window::~Fl_Double_Window() {
|
||||
hide();
|
||||
}
|
||||
|
@ -1,287 +1,293 @@
|
||||
// Fl_Gl_Window.C
|
||||
|
||||
#include <config.h>
|
||||
#if HAVE_GL
|
||||
|
||||
#include <FL/Fl.H>
|
||||
#include <FL/x.H>
|
||||
#include <FL/Fl_Gl_Window.H>
|
||||
#include "Fl_Gl_Choice.H"
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
// The symbol SWAP_TYPE defines what is in the back buffer after doing
|
||||
// a glXSwapBuffers().
|
||||
|
||||
// The OpenGl documentation says that the contents of the backbuffer
|
||||
// are "undefined" after glXSwapBuffers(). However, if we know what
|
||||
// is in the backbuffers then we can save a good deal of time. For
|
||||
// this reason you can define some symbols to describe what is left in
|
||||
// the back buffer.
|
||||
|
||||
// The default of SWAP_SWAP works on an SGI, and will also work (but
|
||||
// is sub-optimal) on machines that should be SWAP_COPY or SWAP_NODAMAGE.
|
||||
// The win32 emulation of OpenGL can use COPY, but some (all?) OpenGL
|
||||
// cards use SWAP.
|
||||
|
||||
// contents of back buffer after glXSwapBuffers():
|
||||
#define UNDEFINED 0 // unknown
|
||||
#define SWAP 1 // former front buffer
|
||||
#define COPY 2 // unchanged
|
||||
#define NODAMAGE 3 // unchanged even by X expose() events
|
||||
|
||||
#ifdef MESA
|
||||
#define SWAP_TYPE NODAMAGE
|
||||
#else
|
||||
#define SWAP_TYPE SWAP
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
int Fl_Gl_Window::can_do(int a, const int *b) {
|
||||
#ifdef WIN32
|
||||
Fl_Gl_Choice *g = Fl_Gl_Choice::find(a,b);
|
||||
HWND w = GetDesktopWindow();
|
||||
HDC dc = GetDC(w);
|
||||
int r = ChoosePixelFormat(dc, &g->pfd);
|
||||
ReleaseDC(w,dc);
|
||||
return r != 0;
|
||||
#else
|
||||
return Fl_Gl_Choice::find(a,b) != 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
void Fl_Gl_Window::show() {
|
||||
#ifndef WIN32
|
||||
if (!shown()) {
|
||||
if (!g) {
|
||||
g = Fl_Gl_Choice::find(mode_,alist);
|
||||
if (!g) {Fl::error("Insufficient GL support"); return;}
|
||||
}
|
||||
Fl_X::make_xid(this, g->vis, g->colormap);
|
||||
if (overlay && overlay != this) ((Fl_Gl_Window*)overlay)->show();
|
||||
}
|
||||
#endif
|
||||
Fl_Window::show();
|
||||
}
|
||||
|
||||
void Fl_Gl_Window::invalidate() {
|
||||
valid(0);
|
||||
#ifndef WIN32
|
||||
if (overlay) ((Fl_Gl_Window*)overlay)->valid(0);
|
||||
#endif
|
||||
}
|
||||
|
||||
extern GLXContext fl_first_context; // in Fl_Gl_Choice.C
|
||||
|
||||
int Fl_Gl_Window::mode(int m, const int *a) {
|
||||
if (m == mode_ && a == alist) return 0;
|
||||
mode_ = m; alist = a;
|
||||
#ifdef WIN32
|
||||
// destroy context and g:
|
||||
if (shown()) {hide(); show();}
|
||||
#else
|
||||
// under X, if the visual changes we must make a new X window (!):
|
||||
if (shown()) {
|
||||
Fl_Gl_Choice *g1 = g;
|
||||
g = Fl_Gl_Choice::find(mode_,alist);
|
||||
if (!g || g->vis->visualid != g1->vis->visualid || g->d != g1->d) {
|
||||
hide(); show();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
||||
#ifdef WIN32
|
||||
extern char fl_direct_paint; // true when responding to WM_PAINT
|
||||
#endif
|
||||
|
||||
void Fl_Gl_Window::make_current() {
|
||||
#ifdef WIN32
|
||||
HDC hdc = fl_private_dc(this, mode_,&g);
|
||||
if (!context) {
|
||||
context = wglCreateContext(hdc);
|
||||
if (fl_first_context) wglShareLists(fl_first_context, (GLXContext)context);
|
||||
else fl_first_context = (GLXContext)context;
|
||||
valid(0);
|
||||
}
|
||||
wglMakeCurrent(hdc, (GLXContext)context);
|
||||
#else
|
||||
if (!context) {
|
||||
context = glXCreateContext(fl_display, g->vis, fl_first_context, 1);
|
||||
if (!fl_first_context) fl_first_context = (GLXContext)context;
|
||||
valid(0);
|
||||
}
|
||||
glXMakeCurrent(fl_display, fl_xid(this), (GLXContext)context);
|
||||
#endif
|
||||
glDrawBuffer(GL_BACK);
|
||||
}
|
||||
|
||||
void Fl_Gl_Window::ortho() {
|
||||
glLoadIdentity();
|
||||
glViewport(0, 0, w(), h());
|
||||
glOrtho(0, w(), 0, h(), -1, 1);
|
||||
}
|
||||
|
||||
void Fl_Gl_Window::swap_buffers() {
|
||||
#ifdef WIN32
|
||||
SwapBuffers(Fl_X::i(this)->private_dc);
|
||||
#else
|
||||
glXSwapBuffers(fl_display, fl_xid(this));
|
||||
#endif
|
||||
}
|
||||
|
||||
#if HAVE_GL_OVERLAY
|
||||
#if WIN32
|
||||
uchar fl_overlay; // changes how fl_color() works
|
||||
#endif
|
||||
#endif
|
||||
|
||||
void Fl_Gl_Window::flush() {
|
||||
make_current();
|
||||
|
||||
#if HAVE_GL_OVERLAY
|
||||
#ifdef WIN32
|
||||
uchar save_valid = valid_;
|
||||
if (overlay && overlay!= this && damage() == 8) goto DRAW_OVERLAY_ONLY;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
if (g->d) {
|
||||
|
||||
#if SWAP_TYPE == NODAMAGE
|
||||
|
||||
// don't draw if only overlay damage or expose events:
|
||||
if ((damage()&~0xA0) || !valid()) draw();
|
||||
swap_buffers();
|
||||
|
||||
#elif SWAP_TYPE == COPY
|
||||
|
||||
// don't draw if only the overlay is damaged:
|
||||
if (damage() != 8 || !valid()) draw();
|
||||
swap_buffers();
|
||||
|
||||
#else // SWAP_TYPE == SWAP || SWAP_TYPE == UNDEFINED
|
||||
|
||||
if (overlay == this) { // Use CopyPixels to act like SWAP_TYPE == COPY
|
||||
|
||||
// don't draw if only the overlay is damaged:
|
||||
if (damage1_ || damage() != 8 || !valid()) draw();
|
||||
// we use a seperate context for the copy because rasterpos must be 0
|
||||
// and depth test needs to be off:
|
||||
static GLXContext ortho_context;
|
||||
int init = !ortho_context;
|
||||
#ifdef WIN32
|
||||
if (init) ortho_context = wglCreateContext(Fl_X::i(this)->private_dc);
|
||||
wglMakeCurrent(Fl_X::i(this)->private_dc, ortho_context);
|
||||
#else
|
||||
if (init)
|
||||
ortho_context = glXCreateContext(fl_display,g->vis,fl_first_context,1);
|
||||
glXMakeCurrent(fl_display, fl_xid(this), ortho_context);
|
||||
#endif
|
||||
if (init) {
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glReadBuffer(GL_BACK);
|
||||
glDrawBuffer(GL_FRONT);
|
||||
}
|
||||
glCopyPixels(0,0,w(),h(),GL_COLOR);
|
||||
make_current(); // set current context back to draw overlay
|
||||
damage1_ = 0;
|
||||
|
||||
} else {
|
||||
|
||||
#if SWAP_TYPE == SWAP
|
||||
uchar old_damage = damage();
|
||||
clear_damage(damage1_|old_damage); draw();
|
||||
swap_buffers();
|
||||
damage1_ = old_damage;
|
||||
#else // SWAP_TYPE == UNDEFINED
|
||||
clear_damage(~0); draw();
|
||||
swap_buffers();
|
||||
damage1_ = ~0;
|
||||
#endif
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
if (overlay==this) { // fake overlay in front buffer
|
||||
glDrawBuffer(GL_FRONT);
|
||||
draw_overlay();
|
||||
glDrawBuffer(GL_BACK);
|
||||
glFlush();
|
||||
}
|
||||
|
||||
} else { // single-buffered context is simpler:
|
||||
|
||||
// this faking of the overlay is incorrect but worked good for
|
||||
// one in-house program:
|
||||
if (overlay != this || damage()!=8 || !Fl::pushed()) draw();
|
||||
if (overlay == this) draw_overlay();
|
||||
glFlush();
|
||||
|
||||
}
|
||||
|
||||
#if HAVE_GL_OVERLAY
|
||||
#ifdef WIN32
|
||||
if (overlay && overlay != this) {
|
||||
DRAW_OVERLAY_ONLY:
|
||||
valid_ = save_valid;
|
||||
wglMakeCurrent(Fl_X::i(this)->private_dc, (GLXContext)overlay);
|
||||
glDisable(GL_SCISSOR_TEST);
|
||||
fl_overlay = 1;
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
draw_overlay();
|
||||
wglSwapLayerBuffers(Fl_X::i(this)->private_dc,WGL_SWAP_OVERLAY1);
|
||||
fl_overlay = 0;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
valid(1);
|
||||
}
|
||||
|
||||
void Fl_Gl_Window::resize(int X,int Y,int W,int H) {
|
||||
if (W != w() || H != h()) valid(0);
|
||||
Fl_Window::resize(X,Y,W,H);
|
||||
}
|
||||
|
||||
void Fl_Gl_Window::hide() {
|
||||
if (context) {
|
||||
#ifdef WIN32
|
||||
wglMakeCurrent(0, 0);
|
||||
if (context && context != fl_first_context)
|
||||
wglDeleteContext((GLXContext)context);
|
||||
g = 0;
|
||||
#else
|
||||
glXMakeCurrent(fl_display, 0, 0);
|
||||
if (context != fl_first_context)
|
||||
glXDestroyContext(fl_display, (GLXContext)context);
|
||||
#ifdef GLX_MESA_release_buffers
|
||||
glXReleaseBuffersMESA(fl_display, fl_xid(this));
|
||||
#endif
|
||||
#endif
|
||||
context = 0;
|
||||
}
|
||||
Fl_Window::hide();
|
||||
}
|
||||
|
||||
Fl_Gl_Window::~Fl_Gl_Window() {
|
||||
hide();
|
||||
// delete overlay; this is done by ~Fl_Group
|
||||
}
|
||||
|
||||
void Fl_Gl_Window::init() {
|
||||
end(); // we probably don't want any children
|
||||
box(FL_NO_BOX);
|
||||
mode_ = FL_RGB | FL_DEPTH | FL_DOUBLE;
|
||||
alist = 0;
|
||||
context = 0;
|
||||
g = 0;
|
||||
overlay = 0;
|
||||
damage1_ = 0;
|
||||
}
|
||||
|
||||
void Fl_Gl_Window::draw_overlay() {}
|
||||
|
||||
#endif
|
||||
// Fl_Gl_Window.C
|
||||
|
||||
#include <config.h>
|
||||
#if HAVE_GL
|
||||
|
||||
#include <FL/Fl.H>
|
||||
#include <FL/x.H>
|
||||
#include <FL/Fl_Gl_Window.H>
|
||||
#include "Fl_Gl_Choice.H"
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
// The symbol SWAP_TYPE defines what is in the back buffer after doing
|
||||
// a glXSwapBuffers().
|
||||
|
||||
// The OpenGl documentation says that the contents of the backbuffer
|
||||
// are "undefined" after glXSwapBuffers(). However, if we know what
|
||||
// is in the backbuffers then we can save a good deal of time. For
|
||||
// this reason you can define some symbols to describe what is left in
|
||||
// the back buffer.
|
||||
|
||||
// The default of SWAP_SWAP works on an SGI, and will also work (but
|
||||
// is sub-optimal) on machines that should be SWAP_COPY or SWAP_NODAMAGE.
|
||||
// The win32 emulation of OpenGL can use COPY, but some (all?) OpenGL
|
||||
// cards use SWAP.
|
||||
|
||||
// contents of back buffer after glXSwapBuffers():
|
||||
#define UNDEFINED 0 // unknown
|
||||
#define SWAP 1 // former front buffer
|
||||
#define COPY 2 // unchanged
|
||||
#define NODAMAGE 3 // unchanged even by X expose() events
|
||||
|
||||
#ifdef MESA
|
||||
#define SWAP_TYPE NODAMAGE
|
||||
#else
|
||||
#define SWAP_TYPE SWAP
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
HDC fl_GetDC(HWND);
|
||||
|
||||
int Fl_Gl_Window::can_do(int a, const int *b) {
|
||||
#ifdef WIN32
|
||||
Fl_Gl_Choice *g = Fl_Gl_Choice::find(a,b);
|
||||
/*
|
||||
Is this necessary? Don't all windows have the same
|
||||
support for pixel formats?
|
||||
HWND w = GetDesktopWindow();
|
||||
HDC dc = GetDC(w);
|
||||
*/
|
||||
if (!fl_gc) fl_GetDC(0);
|
||||
int r = ChoosePixelFormat(fl_gc, &g->pfd);
|
||||
return r != 0;
|
||||
#else
|
||||
return Fl_Gl_Choice::find(a,b) != 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
void Fl_Gl_Window::show() {
|
||||
#ifndef WIN32
|
||||
if (!shown()) {
|
||||
if (!g) {
|
||||
g = Fl_Gl_Choice::find(mode_,alist);
|
||||
if (!g) {Fl::error("Insufficient GL support"); return;}
|
||||
}
|
||||
Fl_X::make_xid(this, g->vis, g->colormap);
|
||||
if (overlay && overlay != this) ((Fl_Gl_Window*)overlay)->show();
|
||||
}
|
||||
#endif
|
||||
Fl_Window::show();
|
||||
}
|
||||
|
||||
void Fl_Gl_Window::invalidate() {
|
||||
valid(0);
|
||||
#ifndef WIN32
|
||||
if (overlay) ((Fl_Gl_Window*)overlay)->valid(0);
|
||||
#endif
|
||||
}
|
||||
|
||||
extern GLXContext fl_first_context; // in Fl_Gl_Choice.C
|
||||
|
||||
int Fl_Gl_Window::mode(int m, const int *a) {
|
||||
if (m == mode_ && a == alist) return 0;
|
||||
mode_ = m; alist = a;
|
||||
#ifdef WIN32
|
||||
// destroy context and g:
|
||||
if (shown()) {hide(); show();}
|
||||
#else
|
||||
// under X, if the visual changes we must make a new X window (!):
|
||||
if (shown()) {
|
||||
Fl_Gl_Choice *g1 = g;
|
||||
g = Fl_Gl_Choice::find(mode_,alist);
|
||||
if (!g || g->vis->visualid != g1->vis->visualid || g->d != g1->d) {
|
||||
hide(); show();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
||||
#ifdef WIN32
|
||||
extern char fl_direct_paint; // true when responding to WM_PAINT
|
||||
#endif
|
||||
|
||||
void Fl_Gl_Window::make_current() {
|
||||
#ifdef WIN32
|
||||
HDC hdc = fl_private_dc(this, mode_,&g);
|
||||
if (!context) {
|
||||
context = wglCreateContext(hdc);
|
||||
if (fl_first_context) wglShareLists(fl_first_context, (GLXContext)context);
|
||||
else fl_first_context = (GLXContext)context;
|
||||
valid(0);
|
||||
}
|
||||
wglMakeCurrent(hdc, (GLXContext)context);
|
||||
#else
|
||||
if (!context) {
|
||||
context = glXCreateContext(fl_display, g->vis, fl_first_context, 1);
|
||||
if (!fl_first_context) fl_first_context = (GLXContext)context;
|
||||
valid(0);
|
||||
}
|
||||
glXMakeCurrent(fl_display, fl_xid(this), (GLXContext)context);
|
||||
#endif
|
||||
glDrawBuffer(GL_BACK);
|
||||
}
|
||||
|
||||
void Fl_Gl_Window::ortho() {
|
||||
glLoadIdentity();
|
||||
glViewport(0, 0, w(), h());
|
||||
glOrtho(0, w(), 0, h(), -1, 1);
|
||||
}
|
||||
|
||||
void Fl_Gl_Window::swap_buffers() {
|
||||
#ifdef WIN32
|
||||
SwapBuffers(Fl_X::i(this)->private_dc);
|
||||
#else
|
||||
glXSwapBuffers(fl_display, fl_xid(this));
|
||||
#endif
|
||||
}
|
||||
|
||||
#if HAVE_GL_OVERLAY
|
||||
#if WIN32
|
||||
uchar fl_overlay; // changes how fl_color() works
|
||||
#endif
|
||||
#endif
|
||||
|
||||
void Fl_Gl_Window::flush() {
|
||||
make_current();
|
||||
|
||||
#if HAVE_GL_OVERLAY
|
||||
#ifdef WIN32
|
||||
uchar save_valid = valid_;
|
||||
if (overlay && overlay!= this && damage() == 8) goto DRAW_OVERLAY_ONLY;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
if (g->d) {
|
||||
|
||||
#if SWAP_TYPE == NODAMAGE
|
||||
|
||||
// don't draw if only overlay damage or expose events:
|
||||
if ((damage()&~0xA0) || !valid()) draw();
|
||||
swap_buffers();
|
||||
|
||||
#elif SWAP_TYPE == COPY
|
||||
|
||||
// don't draw if only the overlay is damaged:
|
||||
if (damage() != 8 || !valid()) draw();
|
||||
swap_buffers();
|
||||
|
||||
#else // SWAP_TYPE == SWAP || SWAP_TYPE == UNDEFINED
|
||||
|
||||
if (overlay == this) { // Use CopyPixels to act like SWAP_TYPE == COPY
|
||||
|
||||
// don't draw if only the overlay is damaged:
|
||||
if (damage1_ || damage() != 8 || !valid()) draw();
|
||||
// we use a seperate context for the copy because rasterpos must be 0
|
||||
// and depth test needs to be off:
|
||||
static GLXContext ortho_context;
|
||||
int init = !ortho_context;
|
||||
#ifdef WIN32
|
||||
if (init) ortho_context = wglCreateContext(Fl_X::i(this)->private_dc);
|
||||
wglMakeCurrent(Fl_X::i(this)->private_dc, ortho_context);
|
||||
#else
|
||||
if (init)
|
||||
ortho_context = glXCreateContext(fl_display,g->vis,fl_first_context,1);
|
||||
glXMakeCurrent(fl_display, fl_xid(this), ortho_context);
|
||||
#endif
|
||||
if (init) {
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glReadBuffer(GL_BACK);
|
||||
glDrawBuffer(GL_FRONT);
|
||||
}
|
||||
glCopyPixels(0,0,w(),h(),GL_COLOR);
|
||||
make_current(); // set current context back to draw overlay
|
||||
damage1_ = 0;
|
||||
|
||||
} else {
|
||||
|
||||
#if SWAP_TYPE == SWAP
|
||||
uchar old_damage = damage();
|
||||
clear_damage(damage1_|old_damage); draw();
|
||||
swap_buffers();
|
||||
damage1_ = old_damage;
|
||||
#else // SWAP_TYPE == UNDEFINED
|
||||
clear_damage(~0); draw();
|
||||
swap_buffers();
|
||||
damage1_ = ~0;
|
||||
#endif
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
if (overlay==this) { // fake overlay in front buffer
|
||||
glDrawBuffer(GL_FRONT);
|
||||
draw_overlay();
|
||||
glDrawBuffer(GL_BACK);
|
||||
glFlush();
|
||||
}
|
||||
|
||||
} else { // single-buffered context is simpler:
|
||||
|
||||
// this faking of the overlay is incorrect but worked good for
|
||||
// one in-house program:
|
||||
if (overlay != this || damage()!=8 || !Fl::pushed()) draw();
|
||||
if (overlay == this) draw_overlay();
|
||||
glFlush();
|
||||
|
||||
}
|
||||
|
||||
#if HAVE_GL_OVERLAY
|
||||
#ifdef WIN32
|
||||
if (overlay && overlay != this) {
|
||||
DRAW_OVERLAY_ONLY:
|
||||
valid_ = save_valid;
|
||||
wglMakeCurrent(Fl_X::i(this)->private_dc, (GLXContext)overlay);
|
||||
glDisable(GL_SCISSOR_TEST);
|
||||
fl_overlay = 1;
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
draw_overlay();
|
||||
wglSwapLayerBuffers(Fl_X::i(this)->private_dc,WGL_SWAP_OVERLAY1);
|
||||
fl_overlay = 0;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
valid(1);
|
||||
}
|
||||
|
||||
void Fl_Gl_Window::resize(int X,int Y,int W,int H) {
|
||||
if (W != w() || H != h()) valid(0);
|
||||
Fl_Window::resize(X,Y,W,H);
|
||||
}
|
||||
|
||||
void Fl_Gl_Window::hide() {
|
||||
if (context) {
|
||||
#ifdef WIN32
|
||||
wglMakeCurrent(0, 0);
|
||||
if (context && context != fl_first_context)
|
||||
wglDeleteContext((GLXContext)context);
|
||||
g = 0;
|
||||
#else
|
||||
glXMakeCurrent(fl_display, 0, 0);
|
||||
if (context != fl_first_context)
|
||||
glXDestroyContext(fl_display, (GLXContext)context);
|
||||
#ifdef GLX_MESA_release_buffers
|
||||
glXReleaseBuffersMESA(fl_display, fl_xid(this));
|
||||
#endif
|
||||
#endif
|
||||
context = 0;
|
||||
}
|
||||
Fl_Window::hide();
|
||||
}
|
||||
|
||||
Fl_Gl_Window::~Fl_Gl_Window() {
|
||||
hide();
|
||||
// delete overlay; this is done by ~Fl_Group
|
||||
}
|
||||
|
||||
void Fl_Gl_Window::init() {
|
||||
end(); // we probably don't want any children
|
||||
box(FL_NO_BOX);
|
||||
mode_ = FL_RGB | FL_DEPTH | FL_DOUBLE;
|
||||
alist = 0;
|
||||
context = 0;
|
||||
g = 0;
|
||||
overlay = 0;
|
||||
damage1_ = 0;
|
||||
}
|
||||
|
||||
void Fl_Gl_Window::draw_overlay() {}
|
||||
|
||||
#endif
|
||||
|
@ -1,78 +1,79 @@
|
||||
// Fl_visual.C
|
||||
//
|
||||
// Set the default visual according to passed switches:
|
||||
|
||||
#include <config.h>
|
||||
#include <FL/Fl.H>
|
||||
#include <FL/x.H>
|
||||
|
||||
#ifdef WIN32
|
||||
int Fl::visual(int flags) {
|
||||
if (flags & FL_DOUBLE) return 0;
|
||||
if (!(flags & FL_INDEX) &&
|
||||
GetDeviceCaps(fl_GetDC(0),BITSPIXEL) <= 8) return 0;
|
||||
if ((flags & FL_RGB8) && GetDeviceCaps(fl_GetDC(0),BITSPIXEL)<24) return 0;
|
||||
return 1;
|
||||
}
|
||||
#else
|
||||
|
||||
#if USE_XDBE
|
||||
#include <X11/extensions/Xdbe.h>
|
||||
#endif
|
||||
|
||||
static int test_visual(XVisualInfo& v, int flags) {
|
||||
if (v.screen != fl_screen) return 0;
|
||||
if (!(flags & FL_INDEX)) {
|
||||
if (!v.red_mask) return 0; // detects static, true, and direct color
|
||||
if (v.depth <= 8) return 0; // fltk will work better in colormap mode
|
||||
}
|
||||
if (flags & FL_RGB8) {
|
||||
if (v.depth < 24) return 0;
|
||||
}
|
||||
// for now, fltk does not like colormaps of more than 8 bits:
|
||||
if (!v.red_mask && v.depth > 8) return 0;
|
||||
#if USE_XDBE
|
||||
if (flags & FL_DOUBLE) {
|
||||
static XdbeScreenVisualInfo *xdbejunk;
|
||||
if (!xdbejunk) {
|
||||
int event_base, error_base;
|
||||
if (!XdbeQueryExtension(fl_display, &event_base, &error_base)) return 0;
|
||||
Drawable root = RootWindow(fl_display,fl_screen);
|
||||
int numscreens = 1;
|
||||
xdbejunk = XdbeGetVisualInfo(fl_display,&root,&numscreens);
|
||||
if (!xdbejunk) return 0;
|
||||
}
|
||||
for (int j = 0; ; j++) {
|
||||
if (j >= xdbejunk->count) return 0;
|
||||
if (xdbejunk->visinfo[j].visual == v.visualid) break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
||||
int Fl::visual(int flags) {
|
||||
#if USE_XDBE == 0
|
||||
if (flags & FL_DOUBLE) return 0;
|
||||
#endif
|
||||
fl_open_display();
|
||||
// always use default if possible:
|
||||
if (test_visual(*fl_visual, flags)) return 1;
|
||||
// get all the visuals:
|
||||
XVisualInfo vTemplate;
|
||||
int num;
|
||||
XVisualInfo *visualList = XGetVisualInfo(fl_display, 0, &vTemplate, &num);
|
||||
// find all matches, use the one with greatest depth:
|
||||
XVisualInfo *found = 0;
|
||||
for (int i=0; i<num; i++) if (test_visual(visualList[i], flags)) {
|
||||
if (!found || found->depth < visualList[i].depth)
|
||||
found = &visualList[i];
|
||||
}
|
||||
if (!found) {XFree((void*)visualList); return 0;}
|
||||
fl_visual = found;
|
||||
fl_colormap = XCreateColormap(fl_display, RootWindow(fl_display,fl_screen),
|
||||
fl_visual->visual, AllocNone);
|
||||
return 1;
|
||||
}
|
||||
|
||||
#endif
|
||||
// Fl_visual.C
|
||||
//
|
||||
// Set the default visual according to passed switches:
|
||||
|
||||
#include <config.h>
|
||||
#include <FL/Fl.H>
|
||||
#include <FL/x.H>
|
||||
|
||||
#ifdef WIN32
|
||||
int Fl::visual(int flags) {
|
||||
fl_GetDC(0);
|
||||
if (flags & FL_DOUBLE) return 0;
|
||||
if (!(flags & FL_INDEX) &&
|
||||
GetDeviceCaps(fl_gc,BITSPIXEL) <= 8) return 0;
|
||||
if ((flags & FL_RGB8) && GetDeviceCaps(fl_gc,BITSPIXEL)<24) return 0;
|
||||
return 1;
|
||||
}
|
||||
#else
|
||||
|
||||
#if USE_XDBE
|
||||
#include <X11/extensions/Xdbe.h>
|
||||
#endif
|
||||
|
||||
static int test_visual(XVisualInfo& v, int flags) {
|
||||
if (v.screen != fl_screen) return 0;
|
||||
if (!(flags & FL_INDEX)) {
|
||||
if (!v.red_mask) return 0; // detects static, true, and direct color
|
||||
if (v.depth <= 8) return 0; // fltk will work better in colormap mode
|
||||
}
|
||||
if (flags & FL_RGB8) {
|
||||
if (v.depth < 24) return 0;
|
||||
}
|
||||
// for now, fltk does not like colormaps of more than 8 bits:
|
||||
if (!v.red_mask && v.depth > 8) return 0;
|
||||
#if USE_XDBE
|
||||
if (flags & FL_DOUBLE) {
|
||||
static XdbeScreenVisualInfo *xdbejunk;
|
||||
if (!xdbejunk) {
|
||||
int event_base, error_base;
|
||||
if (!XdbeQueryExtension(fl_display, &event_base, &error_base)) return 0;
|
||||
Drawable root = RootWindow(fl_display,fl_screen);
|
||||
int numscreens = 1;
|
||||
xdbejunk = XdbeGetVisualInfo(fl_display,&root,&numscreens);
|
||||
if (!xdbejunk) return 0;
|
||||
}
|
||||
for (int j = 0; ; j++) {
|
||||
if (j >= xdbejunk->count) return 0;
|
||||
if (xdbejunk->visinfo[j].visual == v.visualid) break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
||||
int Fl::visual(int flags) {
|
||||
#if USE_XDBE == 0
|
||||
if (flags & FL_DOUBLE) return 0;
|
||||
#endif
|
||||
fl_open_display();
|
||||
// always use default if possible:
|
||||
if (test_visual(*fl_visual, flags)) return 1;
|
||||
// get all the visuals:
|
||||
XVisualInfo vTemplate;
|
||||
int num;
|
||||
XVisualInfo *visualList = XGetVisualInfo(fl_display, 0, &vTemplate, &num);
|
||||
// find all matches, use the one with greatest depth:
|
||||
XVisualInfo *found = 0;
|
||||
for (int i=0; i<num; i++) if (test_visual(visualList[i], flags)) {
|
||||
if (!found || found->depth < visualList[i].depth)
|
||||
found = &visualList[i];
|
||||
}
|
||||
if (!found) {XFree((void*)visualList); return 0;}
|
||||
fl_visual = found;
|
||||
fl_colormap = XCreateColormap(fl_display, RootWindow(fl_display,fl_screen),
|
||||
fl_visual->visual, AllocNone);
|
||||
return 1;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
1463
src/Fl_win32.cxx
1463
src/Fl_win32.cxx
File diff suppressed because it is too large
Load Diff
@ -1,159 +1,159 @@
|
||||
// fl_font_win32.C
|
||||
|
||||
#include <config.h>
|
||||
#include <FL/Fl.H>
|
||||
#include <FL/fl_draw.H>
|
||||
#include <FL/win32.H>
|
||||
#include "Fl_Font.H"
|
||||
|
||||
#include <ctype.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
Fl_XFont::Fl_XFont(const char *name, int size, int num) {
|
||||
int weight = FW_NORMAL;
|
||||
int italic = 0;
|
||||
switch (*name++) {
|
||||
case 'I': italic = 1; break;
|
||||
case 'P': italic = 1;
|
||||
case 'B': weight = FW_BOLD; break;
|
||||
case ' ': break;
|
||||
default: name--;
|
||||
}
|
||||
fid = CreateFont(
|
||||
-size, // negative makes it use "char size"
|
||||
0, // logical average character width
|
||||
0, // angle of escapement
|
||||
0, // base-line orientation angle
|
||||
weight,
|
||||
italic,
|
||||
FALSE, // underline attribute flag
|
||||
FALSE, // strikeout attribute flag
|
||||
DEFAULT_CHARSET, // character set identifier
|
||||
OUT_DEFAULT_PRECIS, // output precision
|
||||
CLIP_DEFAULT_PRECIS,// clipping precision
|
||||
DEFAULT_QUALITY, // output quality
|
||||
DEFAULT_PITCH, // pitch and family
|
||||
name // pointer to typeface name string
|
||||
);
|
||||
if (!fl_gc) fl_gc = fl_GetDC(0);
|
||||
SelectObject(fl_gc, fid);
|
||||
GetTextMetrics(fl_gc, &metr);
|
||||
// BOOL ret = GetCharWidthFloat(fl_gc, metr.tmFirstChar, metr.tmLastChar, font->width+metr.tmFirstChar);
|
||||
// ...would be the right call, but is not implemented into Window95! (WinNT?)
|
||||
GetCharWidth(fl_gc, 0, 255, width);
|
||||
#if HAVE_GL
|
||||
listbase = 0;
|
||||
#endif
|
||||
number = num;
|
||||
minsize = maxsize = size;
|
||||
}
|
||||
|
||||
Fl_XFont *fl_current_xfont;
|
||||
|
||||
Fl_XFont::~Fl_XFont() {
|
||||
#if HAVE_GL
|
||||
// Delete list created by gl_draw(). This is not done by this code
|
||||
// as it will link in GL unnecessarily. There should be some kind
|
||||
// of "free" routine pointer, or a subclass?
|
||||
// if (listbase) {
|
||||
// int base = font->min_char_or_byte2;
|
||||
// int size = font->max_char_or_byte2-base+1;
|
||||
// int base = 0; int size = 256;
|
||||
// glDeleteLists(listbase+base,size);
|
||||
// }
|
||||
#endif
|
||||
if (this == fl_current_xfont) fl_current_xfont = 0;
|
||||
DeleteObject(fid);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
// WARNING: if you add to this table, you must redefine FL_FREE_FONT
|
||||
// in Enumerations.H & recompile!!
|
||||
static Fl_Fontdesc built_in_table[] = {
|
||||
{" Arial"},
|
||||
{"BArial"},
|
||||
{"IArial"},
|
||||
{"PArial"},
|
||||
{" Courier New"},
|
||||
{"BCourier New"},
|
||||
{"ICourier New"},
|
||||
{"PCourier New"},
|
||||
{" Times New Roman"},
|
||||
{"BTimes New Roman"},
|
||||
{"ITimes New Roman"},
|
||||
{"PTimes New Roman"},
|
||||
{" Symbol"},
|
||||
{" Terminal"},
|
||||
{"BTerminal"},
|
||||
{" Wingdings"},
|
||||
};
|
||||
|
||||
Fl_Fontdesc *fl_fonts = built_in_table;
|
||||
|
||||
static Fl_XFont *find(int fnum, int size) {
|
||||
Fl_Fontdesc *s = fl_fonts+fnum;
|
||||
if (!s->name) s = fl_fonts; // use 0 if fnum undefined
|
||||
Fl_XFont *f;
|
||||
for (f = s->first; f; f = f->next)
|
||||
if (f->minsize <= size && f->maxsize >= size) return f;
|
||||
f = new Fl_XFont(s->name, size, fnum);
|
||||
f->next = s->first;
|
||||
s->first = f;
|
||||
return f;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
// Public interface:
|
||||
|
||||
int fl_font_;
|
||||
int fl_size_;
|
||||
static HDC font_gc;
|
||||
|
||||
void fl_font(int fnum, int size) {
|
||||
if (fnum == fl_font_ && size == fl_size_) return;
|
||||
fl_font_ = fnum; fl_size_ = size;
|
||||
fl_current_xfont = find(fnum, size);
|
||||
}
|
||||
|
||||
void fl_font(int fnum, int size, Fl_Font default_font, int default_size) {
|
||||
if (fnum<4) fnum |= default_font;
|
||||
fl_font(fnum, size + default_size);
|
||||
}
|
||||
|
||||
int fl_height() {
|
||||
return (fl_current_xfont->metr.tmAscent + fl_current_xfont->metr.tmDescent);
|
||||
}
|
||||
|
||||
int fl_descent() {
|
||||
return fl_current_xfont->metr.tmDescent;
|
||||
}
|
||||
|
||||
double fl_width(const char *c) {
|
||||
double w = 0.0;
|
||||
while (*c) w += fl_current_xfont->width[uchar(*c++)];
|
||||
return w;
|
||||
}
|
||||
|
||||
double fl_width(const char *c, int n) {
|
||||
double w = 0.0;
|
||||
while (n--) w += fl_current_xfont->width[uchar(*c++)];
|
||||
return w;
|
||||
}
|
||||
|
||||
double fl_width(uchar c) {
|
||||
return fl_current_xfont->width[c];
|
||||
}
|
||||
|
||||
void fl_draw(const char *str, int n, int x, int y) {
|
||||
SetTextColor(fl_gc, fl_RGB());
|
||||
SelectObject(fl_gc, fl_current_xfont->fid);
|
||||
TextOut(fl_gc, x, y, str, n);
|
||||
}
|
||||
|
||||
void fl_draw(const char *str, int x, int y) {
|
||||
fl_draw(str, strlen(str), x, y);
|
||||
}
|
||||
|
||||
// end of fl_font_win32.C
|
||||
// fl_font_win32.C
|
||||
|
||||
#include <config.h>
|
||||
#include <FL/Fl.H>
|
||||
#include <FL/fl_draw.H>
|
||||
#include <FL/win32.H>
|
||||
#include "Fl_Font.H"
|
||||
|
||||
#include <ctype.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
Fl_XFont::Fl_XFont(const char *name, int size, int num) {
|
||||
int weight = FW_NORMAL;
|
||||
int italic = 0;
|
||||
switch (*name++) {
|
||||
case 'I': italic = 1; break;
|
||||
case 'P': italic = 1;
|
||||
case 'B': weight = FW_BOLD; break;
|
||||
case ' ': break;
|
||||
default: name--;
|
||||
}
|
||||
fid = CreateFont(
|
||||
-size, // negative makes it use "char size"
|
||||
0, // logical average character width
|
||||
0, // angle of escapement
|
||||
0, // base-line orientation angle
|
||||
weight,
|
||||
italic,
|
||||
FALSE, // underline attribute flag
|
||||
FALSE, // strikeout attribute flag
|
||||
DEFAULT_CHARSET, // character set identifier
|
||||
OUT_DEFAULT_PRECIS, // output precision
|
||||
CLIP_DEFAULT_PRECIS,// clipping precision
|
||||
DEFAULT_QUALITY, // output quality
|
||||
DEFAULT_PITCH, // pitch and family
|
||||
name // pointer to typeface name string
|
||||
);
|
||||
if (!fl_gc) fl_GetDC(0);
|
||||
SelectObject(fl_gc, fid);
|
||||
GetTextMetrics(fl_gc, &metr);
|
||||
// BOOL ret = GetCharWidthFloat(fl_gc, metr.tmFirstChar, metr.tmLastChar, font->width+metr.tmFirstChar);
|
||||
// ...would be the right call, but is not implemented into Window95! (WinNT?)
|
||||
GetCharWidth(fl_gc, 0, 255, width);
|
||||
#if HAVE_GL
|
||||
listbase = 0;
|
||||
#endif
|
||||
number = num;
|
||||
minsize = maxsize = size;
|
||||
}
|
||||
|
||||
Fl_XFont *fl_current_xfont;
|
||||
|
||||
Fl_XFont::~Fl_XFont() {
|
||||
#if HAVE_GL
|
||||
// Delete list created by gl_draw(). This is not done by this code
|
||||
// as it will link in GL unnecessarily. There should be some kind
|
||||
// of "free" routine pointer, or a subclass?
|
||||
// if (listbase) {
|
||||
// int base = font->min_char_or_byte2;
|
||||
// int size = font->max_char_or_byte2-base+1;
|
||||
// int base = 0; int size = 256;
|
||||
// glDeleteLists(listbase+base,size);
|
||||
// }
|
||||
#endif
|
||||
if (this == fl_current_xfont) fl_current_xfont = 0;
|
||||
DeleteObject(fid);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
// WARNING: if you add to this table, you must redefine FL_FREE_FONT
|
||||
// in Enumerations.H & recompile!!
|
||||
static Fl_Fontdesc built_in_table[] = {
|
||||
{" Arial"},
|
||||
{"BArial"},
|
||||
{"IArial"},
|
||||
{"PArial"},
|
||||
{" Courier New"},
|
||||
{"BCourier New"},
|
||||
{"ICourier New"},
|
||||
{"PCourier New"},
|
||||
{" Times New Roman"},
|
||||
{"BTimes New Roman"},
|
||||
{"ITimes New Roman"},
|
||||
{"PTimes New Roman"},
|
||||
{" Symbol"},
|
||||
{" Terminal"},
|
||||
{"BTerminal"},
|
||||
{" Wingdings"},
|
||||
};
|
||||
|
||||
Fl_Fontdesc *fl_fonts = built_in_table;
|
||||
|
||||
static Fl_XFont *find(int fnum, int size) {
|
||||
Fl_Fontdesc *s = fl_fonts+fnum;
|
||||
if (!s->name) s = fl_fonts; // use 0 if fnum undefined
|
||||
Fl_XFont *f;
|
||||
for (f = s->first; f; f = f->next)
|
||||
if (f->minsize <= size && f->maxsize >= size) return f;
|
||||
f = new Fl_XFont(s->name, size, fnum);
|
||||
f->next = s->first;
|
||||
s->first = f;
|
||||
return f;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
// Public interface:
|
||||
|
||||
int fl_font_;
|
||||
int fl_size_;
|
||||
//static HDC font_gc;
|
||||
|
||||
void fl_font(int fnum, int size) {
|
||||
if (fnum == fl_font_ && size == fl_size_) return;
|
||||
fl_font_ = fnum; fl_size_ = size;
|
||||
fl_current_xfont = find(fnum, size);
|
||||
}
|
||||
|
||||
void fl_font(int fnum, int size, Fl_Font default_font, int default_size) {
|
||||
if (fnum<4) fnum |= default_font;
|
||||
fl_font(fnum, size + default_size);
|
||||
}
|
||||
|
||||
int fl_height() {
|
||||
return (fl_current_xfont->metr.tmAscent + fl_current_xfont->metr.tmDescent);
|
||||
}
|
||||
|
||||
int fl_descent() {
|
||||
return fl_current_xfont->metr.tmDescent;
|
||||
}
|
||||
|
||||
double fl_width(const char *c) {
|
||||
double w = 0.0;
|
||||
while (*c) w += fl_current_xfont->width[uchar(*c++)];
|
||||
return w;
|
||||
}
|
||||
|
||||
double fl_width(const char *c, int n) {
|
||||
double w = 0.0;
|
||||
while (n--) w += fl_current_xfont->width[uchar(*c++)];
|
||||
return w;
|
||||
}
|
||||
|
||||
double fl_width(uchar c) {
|
||||
return fl_current_xfont->width[c];
|
||||
}
|
||||
|
||||
void fl_draw(const char *str, int n, int x, int y) {
|
||||
SetTextColor(fl_gc, fl_RGB());
|
||||
SelectObject(fl_gc, fl_current_xfont->fid);
|
||||
TextOut(fl_gc, x, y, str, n);
|
||||
}
|
||||
|
||||
void fl_draw(const char *str, int x, int y) {
|
||||
fl_draw(str, strlen(str), x, y);
|
||||
}
|
||||
|
||||
// end of fl_font_win32.C
|
||||
|
731
src/fl_rect.cxx
731
src/fl_rect.cxx
@ -1,380 +1,351 @@
|
||||
// fl_rect.C
|
||||
|
||||
// These routines from fl_draw.H are used by the standard boxtypes
|
||||
// and thus are always linked into an fltk program.
|
||||
|
||||
// Also all fl_clip routines, since they are always linked in so
|
||||
// that minimal update works.
|
||||
|
||||
#include <FL/Fl_Widget.H>
|
||||
#include <FL/fl_draw.H>
|
||||
#include <FL/x.H>
|
||||
|
||||
void fl_rect(int x, int y, int w, int h) {
|
||||
if (w<=0 || h<=0) return;
|
||||
#ifdef WIN32
|
||||
MoveToEx(fl_gc, x, y, 0L);
|
||||
LineTo(fl_gc, x+w-1, y);
|
||||
LineTo(fl_gc, x+w-1, y+h-1);
|
||||
LineTo(fl_gc, x, y+h-1);
|
||||
LineTo(fl_gc, x, y);
|
||||
#else
|
||||
XDrawRectangle(fl_display, fl_window, fl_gc, x, y, w-1, h-1);
|
||||
#endif
|
||||
}
|
||||
|
||||
void fl_rectf(int x, int y, int w, int h) {
|
||||
if (w<=0 || h<=0) return;
|
||||
#ifdef WIN32
|
||||
RECT rect;
|
||||
rect.left = x; rect.top = y;
|
||||
rect.right = x + w; rect.bottom = y + h;
|
||||
FillRect(fl_gc, &rect, fl_brush());
|
||||
#else
|
||||
if (w && h) XFillRectangle(fl_display, fl_window, fl_gc, x, y, w, h);
|
||||
#endif
|
||||
}
|
||||
|
||||
void fl_xyline(int x, int y, int x1) {
|
||||
#ifdef WIN32
|
||||
MoveToEx(fl_gc, x, y, 0L); LineTo(fl_gc, x1+1, y);
|
||||
#else
|
||||
XDrawLine(fl_display, fl_window, fl_gc, x, y, x1, y);
|
||||
#endif
|
||||
}
|
||||
|
||||
void fl_xyline(int x, int y, int x1, int y2) {
|
||||
#ifdef WIN32
|
||||
if (y2 < y) y2--;
|
||||
MoveToEx(fl_gc, x, y, 0L);
|
||||
LineTo(fl_gc, x1, y);
|
||||
LineTo(fl_gc, x1, y2);
|
||||
#else
|
||||
XPoint p[3];
|
||||
p[0].x = x; p[0].y = p[1].y = y;
|
||||
p[1].x = p[2].x = x1; p[2].y = y2;
|
||||
XDrawLines(fl_display, fl_window, fl_gc, p, 3, 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
void fl_xyline(int x, int y, int x1, int y2, int x3) {
|
||||
#ifdef WIN32
|
||||
MoveToEx(fl_gc, x, y, 0L);
|
||||
LineTo(fl_gc, x1, y);
|
||||
LineTo(fl_gc, x1, y2);
|
||||
LineTo(fl_gc, x3, y2);
|
||||
#else
|
||||
XPoint p[4];
|
||||
p[0].x = x; p[0].y = p[1].y = y;
|
||||
p[1].x = p[2].x = x1; p[2].y = p[3].y = y2;
|
||||
p[3].x = x3;
|
||||
XDrawLines(fl_display, fl_window, fl_gc, p, 4, 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
void fl_yxline(int x, int y, int y1) {
|
||||
#ifdef WIN32
|
||||
if (y1 < y) y1--;
|
||||
MoveToEx(fl_gc, x, y, 0L); LineTo(fl_gc, x, y1);
|
||||
#else
|
||||
XDrawLine(fl_display, fl_window, fl_gc, x, y, x, y1);
|
||||
#endif
|
||||
}
|
||||
|
||||
void fl_yxline(int x, int y, int y1, int x2) {
|
||||
#ifdef WIN32
|
||||
if (x2 > x) x2++;
|
||||
MoveToEx(fl_gc, x, y, 0L);
|
||||
LineTo(fl_gc, x, y1);
|
||||
LineTo(fl_gc, x2, y1);
|
||||
#else
|
||||
XPoint p[3];
|
||||
p[0].x = p[1].x = x; p[0].y = y;
|
||||
p[1].y = p[2].y = y1; p[2].x = x2;
|
||||
XDrawLines(fl_display, fl_window, fl_gc, p, 3, 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
void fl_yxline(int x, int y, int y1, int x2, int y3) {
|
||||
#ifdef WIN32
|
||||
MoveToEx(fl_gc, x, y, 0L);
|
||||
LineTo(fl_gc, x, y1);
|
||||
LineTo(fl_gc, x2, y1);
|
||||
LineTo(fl_gc, x2, y3);
|
||||
#else
|
||||
XPoint p[4];
|
||||
p[0].x = p[1].x = x; p[0].y = y;
|
||||
p[1].y = p[2].y = y1; p[2].x = p[3].x = x2;
|
||||
p[3].y = y3;
|
||||
XDrawLines(fl_display, fl_window, fl_gc, p, 4, 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
void fl_line(int x, int y, int x1, int y1) {
|
||||
#ifdef WIN32
|
||||
MoveToEx(fl_gc, x, y, 0L);
|
||||
LineTo(fl_gc, x1, y1);
|
||||
#else
|
||||
XDrawLine(fl_display, fl_window, fl_gc, x, y, x1, y1);
|
||||
#endif
|
||||
}
|
||||
|
||||
void fl_line(int x, int y, int x1, int y1, int x2, int y2) {
|
||||
#ifdef WIN32
|
||||
MoveToEx(fl_gc, x, y, 0L);
|
||||
LineTo(fl_gc, x1, y1);
|
||||
LineTo(fl_gc, x2, y2);
|
||||
#else
|
||||
XPoint p[3];
|
||||
p[0].x = x; p[0].y = y;
|
||||
p[1].x = x1; p[1].y = y1;
|
||||
p[2].x = x2; p[2].y = y2;
|
||||
XDrawLines(fl_display, fl_window, fl_gc, p, 3, 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
void fl_loop(int x, int y, int x1, int y1, int x2, int y2) {
|
||||
#ifdef WIN32
|
||||
MoveToEx(fl_gc, x, y, 0L);
|
||||
LineTo(fl_gc, x1, y1);
|
||||
LineTo(fl_gc, x2, y2);
|
||||
LineTo(fl_gc, x, y);
|
||||
#else
|
||||
XPoint p[4];
|
||||
p[0].x = x; p[0].y = y;
|
||||
p[1].x = x1; p[1].y = y1;
|
||||
p[2].x = x2; p[2].y = y2;
|
||||
p[3].x = x; p[3].y = y;
|
||||
XDrawLines(fl_display, fl_window, fl_gc, p, 4, 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
void fl_loop(int x, int y, int x1, int y1, int x2, int y2, int x3, int y3) {
|
||||
#ifdef WIN32
|
||||
MoveToEx(fl_gc, x, y, 0L);
|
||||
LineTo(fl_gc, x1, y1);
|
||||
LineTo(fl_gc, x2, y2);
|
||||
LineTo(fl_gc, x3, y3);
|
||||
LineTo(fl_gc, x, y);
|
||||
#else
|
||||
XPoint p[5];
|
||||
p[0].x = x; p[0].y = y;
|
||||
p[1].x = x1; p[1].y = y1;
|
||||
p[2].x = x2; p[2].y = y2;
|
||||
p[3].x = x3; p[3].y = y3;
|
||||
p[4].x = x; p[4].y = y;
|
||||
XDrawLines(fl_display, fl_window, fl_gc, p, 5, 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
void fl_polygon(int x, int y, int x1, int y1, int x2, int y2) {
|
||||
XPoint p[4];
|
||||
p[0].x = x; p[0].y = y;
|
||||
p[1].x = x1; p[1].y = y1;
|
||||
p[2].x = x2; p[2].y = y2;
|
||||
#ifdef WIN32
|
||||
SelectObject(fl_gc, fl_brush());
|
||||
Polygon(fl_gc, p, 3);
|
||||
#else
|
||||
p[3].x = x; p[3].y = y;
|
||||
XFillPolygon(fl_display, fl_window, fl_gc, p, 3, Convex, 0);
|
||||
XDrawLines(fl_display, fl_window, fl_gc, p, 4, 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
void fl_polygon(int x, int y, int x1, int y1, int x2, int y2, int x3, int y3) {
|
||||
XPoint p[5];
|
||||
p[0].x = x; p[0].y = y;
|
||||
p[1].x = x1; p[1].y = y1;
|
||||
p[2].x = x2; p[2].y = y2;
|
||||
p[3].x = x3; p[3].y = y3;
|
||||
#ifdef WIN32
|
||||
SelectObject(fl_gc, fl_brush());
|
||||
Polygon(fl_gc, p, 4);
|
||||
#else
|
||||
p[4].x = x; p[4].y = y;
|
||||
XFillPolygon(fl_display, fl_window, fl_gc, p, 4, Convex, 0);
|
||||
XDrawLines(fl_display, fl_window, fl_gc, p, 5, 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
void fl_point(int x, int y) {
|
||||
#ifdef WIN32
|
||||
SetPixel(fl_gc, x, y, fl_RGB());
|
||||
#else
|
||||
XDrawPoint(fl_display, fl_window, fl_gc, x, y);
|
||||
#endif
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifdef WIN32
|
||||
|
||||
static struct rect {int notnull, x, y, r, b;} rstack[10];
|
||||
static int rstackptr;
|
||||
int fl_clip_state_number; // used by gl_begin.C to update GL clip
|
||||
extern char fl_direct_paint; // in Fl_win32.C
|
||||
|
||||
void fl_clip(int x, int y, int w, int h) {
|
||||
fl_clip_state_number++;
|
||||
int r = x+w;
|
||||
int b = y+h;
|
||||
rect& current = rstack[rstackptr];
|
||||
if (current.notnull) {
|
||||
if (current.x > x) x = current.x;
|
||||
if (current.y > y) y = current.y;
|
||||
if (current.r < r) r = current.r;
|
||||
if (current.b < b) b = current.b;
|
||||
}
|
||||
rect& newrect = rstack[++rstackptr];
|
||||
newrect.notnull = 1;
|
||||
newrect.x = x;
|
||||
newrect.y = y;
|
||||
newrect.r = r;
|
||||
newrect.b = b;
|
||||
if (rstackptr == 1 && fl_direct_paint) return;
|
||||
HRGN R = CreateRectRgn(x,y,r,b);
|
||||
SelectClipRgn(fl_gc, R);
|
||||
DeleteObject(R);
|
||||
}
|
||||
|
||||
void fl_push_no_clip() {
|
||||
fl_clip_state_number++;
|
||||
if (rstack[rstackptr].notnull) SelectClipRgn(fl_gc, 0);
|
||||
rstack[++rstackptr].notnull = 0;
|
||||
}
|
||||
|
||||
void fl_pop_clip() {
|
||||
fl_clip_state_number++;
|
||||
rect& r = rstack[--rstackptr];
|
||||
if (r.notnull) {
|
||||
HRGN R = CreateRectRgn(r.x, r.y, r.r, r.b);
|
||||
SelectClipRgn(fl_gc, R);
|
||||
DeleteObject(R);
|
||||
} else {
|
||||
SelectClipRgn(fl_gc, 0);
|
||||
}
|
||||
}
|
||||
|
||||
// does this rectangle intersect current clip?
|
||||
int fl_not_clipped(int x, int y, int w, int h) {
|
||||
rect& r = rstack[rstackptr];
|
||||
if (!r.notnull) return 2;
|
||||
return (x < r.r && x+w > r.x && y < r.b && y+h > r.y);
|
||||
}
|
||||
|
||||
// return rectangle surrounding intersection of this rectangle and clip:
|
||||
int fl_clip_box(int x, int y, int w, int h, int& X, int& Y, int& W, int& H){
|
||||
X = x; Y = y; W = w; H = h;
|
||||
rect& r = rstack[rstackptr];
|
||||
if (!r.notnull) return 0;
|
||||
int R = x+w;
|
||||
int B = y+h;
|
||||
int ret = 0;
|
||||
if (r.x > x) {X = r.x; ret = 1;}
|
||||
if (r.y > y) {Y = r.y; ret = 1;}
|
||||
if (r.r < R) {R = r.r; ret = 1;}
|
||||
if (r.b < B) {B = r.b; ret = 1;}
|
||||
if (B <= Y || R <= X) {W = H = 0; return 2;}
|
||||
W = R-X;
|
||||
H = B-Y;
|
||||
return ret;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
// Missing X call: (is this the fastest way to init a 1-rectangle region?)
|
||||
Region XRectangleRegion(int x, int y, int w, int h) {
|
||||
XRectangle R;
|
||||
R.x = x; R.y = y; R.width = w; R.height = h;
|
||||
Region r = XCreateRegion();
|
||||
XUnionRectWithRegion(&R, r, r);
|
||||
return r;
|
||||
}
|
||||
|
||||
static Region rstack[10];
|
||||
static int rstackptr;
|
||||
int fl_clip_state_number; // used by gl_begin.C to update GL clip
|
||||
|
||||
// undo any clobbering of clip done by your program:
|
||||
void fl_restore_clip() {
|
||||
fl_clip_state_number++;
|
||||
Region r = rstack[rstackptr];
|
||||
if (r) XSetRegion(fl_display, fl_gc, r);
|
||||
else XSetClipMask(fl_display, fl_gc, 0);
|
||||
}
|
||||
|
||||
// Replace the top of the clip stack:
|
||||
void fl_clip_region(Region r) {
|
||||
Region oldr = rstack[rstackptr];
|
||||
if (oldr) XDestroyRegion(oldr);
|
||||
rstack[rstackptr] = r;
|
||||
fl_restore_clip();
|
||||
}
|
||||
|
||||
// Intersect & push a new clip rectangle:
|
||||
void fl_clip(int x, int y, int w, int h) {
|
||||
Region r;
|
||||
if (w > 0 && h > 0) {
|
||||
r = XRectangleRegion(x,y,w,h);
|
||||
Region current = rstack[rstackptr];
|
||||
if (current) {
|
||||
Region temp = XCreateRegion();
|
||||
XIntersectRegion(current, r, temp);
|
||||
XDestroyRegion(r);
|
||||
r = temp;
|
||||
}
|
||||
} else { // make empty clip region:
|
||||
r = XCreateRegion();
|
||||
}
|
||||
rstack[++rstackptr] = r;
|
||||
fl_restore_clip();
|
||||
}
|
||||
|
||||
// make there be no clip (used by fl_begin_offscreen() only!)
|
||||
void fl_push_no_clip() {
|
||||
rstack[++rstackptr] = 0;
|
||||
fl_restore_clip();
|
||||
}
|
||||
|
||||
// pop back to previous clip:
|
||||
void fl_pop_clip() {
|
||||
Region oldr = rstack[rstackptr--];
|
||||
if (oldr) XDestroyRegion(oldr);
|
||||
fl_restore_clip();
|
||||
}
|
||||
|
||||
// does this rectangle intersect current clip?
|
||||
int fl_not_clipped(int x, int y, int w, int h) {
|
||||
Region r = rstack[rstackptr];
|
||||
return r ? XRectInRegion(r, x, y, w, h) : 1;
|
||||
}
|
||||
|
||||
// return rectangle surrounding intersection of this rectangle and clip:
|
||||
int fl_clip_box(int x, int y, int w, int h, int& X, int& Y, int& W, int& H){
|
||||
X = x; Y = y; W = w; H = h;
|
||||
Region r = rstack[rstackptr];
|
||||
if (!r) return 0;
|
||||
switch (XRectInRegion(r, x, y, w, h)) {
|
||||
case 0: // completely outside
|
||||
W = H = 0;
|
||||
return 2;
|
||||
case 1: // completely inside:
|
||||
return 0;
|
||||
default: // partial:
|
||||
break;
|
||||
}
|
||||
Region rr = XRectangleRegion(x,y,w,h);
|
||||
Region temp = XCreateRegion();
|
||||
XIntersectRegion(r, rr, temp);
|
||||
XRectangle rect;
|
||||
XClipBox(temp, &rect);
|
||||
X = rect.x; Y = rect.y; W = rect.width; H = rect.height;
|
||||
XDestroyRegion(temp);
|
||||
XDestroyRegion(rr);
|
||||
return 1;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// end of fl_rect.C
|
||||
// fl_rect.C
|
||||
|
||||
// These routines from fl_draw.H are used by the standard boxtypes
|
||||
// and thus are always linked into an fltk program.
|
||||
|
||||
// Also all fl_clip routines, since they are always linked in so
|
||||
// that minimal update works.
|
||||
|
||||
#include <FL/Fl_Widget.H>
|
||||
#include <FL/fl_draw.H>
|
||||
#include <FL/x.H>
|
||||
|
||||
void fl_rect(int x, int y, int w, int h) {
|
||||
if (w<=0 || h<=0) return;
|
||||
#ifdef WIN32
|
||||
MoveToEx(fl_gc, x, y, 0L);
|
||||
LineTo(fl_gc, x+w-1, y);
|
||||
LineTo(fl_gc, x+w-1, y+h-1);
|
||||
LineTo(fl_gc, x, y+h-1);
|
||||
LineTo(fl_gc, x, y);
|
||||
#else
|
||||
XDrawRectangle(fl_display, fl_window, fl_gc, x, y, w-1, h-1);
|
||||
#endif
|
||||
}
|
||||
|
||||
void fl_rectf(int x, int y, int w, int h) {
|
||||
if (w<=0 || h<=0) return;
|
||||
#ifdef WIN32
|
||||
RECT rect;
|
||||
rect.left = x; rect.top = y;
|
||||
rect.right = x + w; rect.bottom = y + h;
|
||||
FillRect(fl_gc, &rect, fl_brush());
|
||||
#else
|
||||
if (w && h) XFillRectangle(fl_display, fl_window, fl_gc, x, y, w, h);
|
||||
#endif
|
||||
}
|
||||
|
||||
void fl_xyline(int x, int y, int x1) {
|
||||
#ifdef WIN32
|
||||
MoveToEx(fl_gc, x, y, 0L); LineTo(fl_gc, x1+1, y);
|
||||
#else
|
||||
XDrawLine(fl_display, fl_window, fl_gc, x, y, x1, y);
|
||||
#endif
|
||||
}
|
||||
|
||||
void fl_xyline(int x, int y, int x1, int y2) {
|
||||
#ifdef WIN32
|
||||
if (y2 < y) y2--;
|
||||
MoveToEx(fl_gc, x, y, 0L);
|
||||
LineTo(fl_gc, x1, y);
|
||||
LineTo(fl_gc, x1, y2);
|
||||
#else
|
||||
XPoint p[3];
|
||||
p[0].x = x; p[0].y = p[1].y = y;
|
||||
p[1].x = p[2].x = x1; p[2].y = y2;
|
||||
XDrawLines(fl_display, fl_window, fl_gc, p, 3, 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
void fl_xyline(int x, int y, int x1, int y2, int x3) {
|
||||
#ifdef WIN32
|
||||
MoveToEx(fl_gc, x, y, 0L);
|
||||
LineTo(fl_gc, x1, y);
|
||||
LineTo(fl_gc, x1, y2);
|
||||
LineTo(fl_gc, x3, y2);
|
||||
#else
|
||||
XPoint p[4];
|
||||
p[0].x = x; p[0].y = p[1].y = y;
|
||||
p[1].x = p[2].x = x1; p[2].y = p[3].y = y2;
|
||||
p[3].x = x3;
|
||||
XDrawLines(fl_display, fl_window, fl_gc, p, 4, 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
void fl_yxline(int x, int y, int y1) {
|
||||
#ifdef WIN32
|
||||
if (y1 < y) y1--;
|
||||
MoveToEx(fl_gc, x, y, 0L); LineTo(fl_gc, x, y1);
|
||||
#else
|
||||
XDrawLine(fl_display, fl_window, fl_gc, x, y, x, y1);
|
||||
#endif
|
||||
}
|
||||
|
||||
void fl_yxline(int x, int y, int y1, int x2) {
|
||||
#ifdef WIN32
|
||||
if (x2 > x) x2++;
|
||||
MoveToEx(fl_gc, x, y, 0L);
|
||||
LineTo(fl_gc, x, y1);
|
||||
LineTo(fl_gc, x2, y1);
|
||||
#else
|
||||
XPoint p[3];
|
||||
p[0].x = p[1].x = x; p[0].y = y;
|
||||
p[1].y = p[2].y = y1; p[2].x = x2;
|
||||
XDrawLines(fl_display, fl_window, fl_gc, p, 3, 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
void fl_yxline(int x, int y, int y1, int x2, int y3) {
|
||||
#ifdef WIN32
|
||||
MoveToEx(fl_gc, x, y, 0L);
|
||||
LineTo(fl_gc, x, y1);
|
||||
LineTo(fl_gc, x2, y1);
|
||||
LineTo(fl_gc, x2, y3);
|
||||
#else
|
||||
XPoint p[4];
|
||||
p[0].x = p[1].x = x; p[0].y = y;
|
||||
p[1].y = p[2].y = y1; p[2].x = p[3].x = x2;
|
||||
p[3].y = y3;
|
||||
XDrawLines(fl_display, fl_window, fl_gc, p, 4, 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
void fl_line(int x, int y, int x1, int y1) {
|
||||
#ifdef WIN32
|
||||
MoveToEx(fl_gc, x, y, 0L);
|
||||
LineTo(fl_gc, x1, y1);
|
||||
#else
|
||||
XDrawLine(fl_display, fl_window, fl_gc, x, y, x1, y1);
|
||||
#endif
|
||||
}
|
||||
|
||||
void fl_line(int x, int y, int x1, int y1, int x2, int y2) {
|
||||
#ifdef WIN32
|
||||
MoveToEx(fl_gc, x, y, 0L);
|
||||
LineTo(fl_gc, x1, y1);
|
||||
LineTo(fl_gc, x2, y2);
|
||||
#else
|
||||
XPoint p[3];
|
||||
p[0].x = x; p[0].y = y;
|
||||
p[1].x = x1; p[1].y = y1;
|
||||
p[2].x = x2; p[2].y = y2;
|
||||
XDrawLines(fl_display, fl_window, fl_gc, p, 3, 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
void fl_loop(int x, int y, int x1, int y1, int x2, int y2) {
|
||||
#ifdef WIN32
|
||||
MoveToEx(fl_gc, x, y, 0L);
|
||||
LineTo(fl_gc, x1, y1);
|
||||
LineTo(fl_gc, x2, y2);
|
||||
LineTo(fl_gc, x, y);
|
||||
#else
|
||||
XPoint p[4];
|
||||
p[0].x = x; p[0].y = y;
|
||||
p[1].x = x1; p[1].y = y1;
|
||||
p[2].x = x2; p[2].y = y2;
|
||||
p[3].x = x; p[3].y = y;
|
||||
XDrawLines(fl_display, fl_window, fl_gc, p, 4, 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
void fl_loop(int x, int y, int x1, int y1, int x2, int y2, int x3, int y3) {
|
||||
#ifdef WIN32
|
||||
MoveToEx(fl_gc, x, y, 0L);
|
||||
LineTo(fl_gc, x1, y1);
|
||||
LineTo(fl_gc, x2, y2);
|
||||
LineTo(fl_gc, x3, y3);
|
||||
LineTo(fl_gc, x, y);
|
||||
#else
|
||||
XPoint p[5];
|
||||
p[0].x = x; p[0].y = y;
|
||||
p[1].x = x1; p[1].y = y1;
|
||||
p[2].x = x2; p[2].y = y2;
|
||||
p[3].x = x3; p[3].y = y3;
|
||||
p[4].x = x; p[4].y = y;
|
||||
XDrawLines(fl_display, fl_window, fl_gc, p, 5, 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
void fl_polygon(int x, int y, int x1, int y1, int x2, int y2) {
|
||||
XPoint p[4];
|
||||
p[0].x = x; p[0].y = y;
|
||||
p[1].x = x1; p[1].y = y1;
|
||||
p[2].x = x2; p[2].y = y2;
|
||||
#ifdef WIN32
|
||||
SelectObject(fl_gc, fl_brush());
|
||||
Polygon(fl_gc, p, 3);
|
||||
#else
|
||||
p[3].x = x; p[3].y = y;
|
||||
XFillPolygon(fl_display, fl_window, fl_gc, p, 3, Convex, 0);
|
||||
XDrawLines(fl_display, fl_window, fl_gc, p, 4, 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
void fl_polygon(int x, int y, int x1, int y1, int x2, int y2, int x3, int y3) {
|
||||
XPoint p[5];
|
||||
p[0].x = x; p[0].y = y;
|
||||
p[1].x = x1; p[1].y = y1;
|
||||
p[2].x = x2; p[2].y = y2;
|
||||
p[3].x = x3; p[3].y = y3;
|
||||
#ifdef WIN32
|
||||
SelectObject(fl_gc, fl_brush());
|
||||
Polygon(fl_gc, p, 4);
|
||||
#else
|
||||
p[4].x = x; p[4].y = y;
|
||||
XFillPolygon(fl_display, fl_window, fl_gc, p, 4, Convex, 0);
|
||||
XDrawLines(fl_display, fl_window, fl_gc, p, 5, 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
void fl_point(int x, int y) {
|
||||
#ifdef WIN32
|
||||
SetPixel(fl_gc, x, y, fl_RGB());
|
||||
#else
|
||||
XDrawPoint(fl_display, fl_window, fl_gc, x, y);
|
||||
#endif
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
static Region rstack[10];
|
||||
static int rstackptr;
|
||||
int fl_clip_state_number=0; // used by gl_begin.C to update GL clip
|
||||
|
||||
#ifndef WIN32
|
||||
// Missing X call: (is this the fastest way to init a 1-rectangle region?)
|
||||
// MSWindows equivalent exists, implemented inline in win32.H
|
||||
Region XRectangleRegion(int x, int y, int w, int h) {
|
||||
XRectangle R;
|
||||
R.x = x; R.y = y; R.width = w; R.height = h;
|
||||
Region r = XCreateRegion();
|
||||
XUnionRectWithRegion(&R, r, r);
|
||||
return r;
|
||||
}
|
||||
#endif
|
||||
|
||||
// undo any clobbering of clip done by your program:
|
||||
void fl_restore_clip() {
|
||||
fl_clip_state_number++;
|
||||
Region r = rstack[rstackptr];
|
||||
#ifdef WIN32
|
||||
SelectClipRgn(fl_gc, r); //if r is NULL, clip is automatically cleared
|
||||
#else
|
||||
if (r) XSetRegion(fl_display, fl_gc, r);
|
||||
else XSetClipMask(fl_display, fl_gc, 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Replace the top of the clip stack:
|
||||
void fl_clip_region(Region r) {
|
||||
Region oldr = rstack[rstackptr];
|
||||
if (oldr) XDestroyRegion(oldr);
|
||||
rstack[rstackptr] = r;
|
||||
fl_restore_clip();
|
||||
}
|
||||
|
||||
// Intersect & push a new clip rectangle:
|
||||
void fl_clip(int x, int y, int w, int h) {
|
||||
Region r;
|
||||
if (w > 0 && h > 0) {
|
||||
r = XRectangleRegion(x,y,w,h);
|
||||
Region current = rstack[rstackptr];
|
||||
if (current) {
|
||||
#ifndef WIN32
|
||||
Region temp = XCreateRegion();
|
||||
XIntersectRegion(current, r, temp);
|
||||
XDestroyRegion(r);
|
||||
r = temp;
|
||||
#else
|
||||
CombineRgn(r,r,current,RGN_AND);
|
||||
#endif
|
||||
}
|
||||
} else { // make empty clip region:
|
||||
#ifndef WIN32
|
||||
r = XCreateRegion();
|
||||
#else
|
||||
r = 0; //whatever, for win32 this is the same as having 0 for HRGN
|
||||
#endif
|
||||
}
|
||||
rstack[++rstackptr] = r;
|
||||
fl_restore_clip();
|
||||
}
|
||||
|
||||
// make there be no clip (used by fl_begin_offscreen() only!)
|
||||
void fl_push_no_clip() {
|
||||
rstack[++rstackptr] = 0;
|
||||
fl_restore_clip();
|
||||
}
|
||||
|
||||
// pop back to previous clip:
|
||||
void fl_pop_clip() {
|
||||
Region oldr = rstack[rstackptr--];
|
||||
if (oldr) XDestroyRegion(oldr);
|
||||
fl_restore_clip();
|
||||
}
|
||||
|
||||
// does this rectangle intersect current clip?
|
||||
int fl_not_clipped(int x, int y, int w, int h) {
|
||||
Region r = rstack[rstackptr];
|
||||
#ifndef WIN32
|
||||
return r ? XRectInRegion(r, x, y, w, h) : 1;
|
||||
#else
|
||||
if (!r) return 1;
|
||||
RECT rect;
|
||||
rect.left = x; rect.top = y; rect.right = x+w; rect.bottom = y+h;
|
||||
return RectInRegion(r,&rect);
|
||||
#endif
|
||||
}
|
||||
|
||||
// return rectangle surrounding intersection of this rectangle and clip:
|
||||
int fl_clip_box(int x, int y, int w, int h, int& X, int& Y, int& W, int& H){
|
||||
X = x; Y = y; W = w; H = h;
|
||||
Region r = rstack[rstackptr];
|
||||
if (!r) return 0;
|
||||
#ifndef WIN32
|
||||
switch (XRectInRegion(r, x, y, w, h)) {
|
||||
case 0: // completely outside
|
||||
W = H = 0;
|
||||
return 2;
|
||||
case 1: // completely inside:
|
||||
return 0;
|
||||
default: // partial:
|
||||
break;
|
||||
}
|
||||
#else
|
||||
// The win32 API makes no distinction between partial and complete
|
||||
// intersection, so we have to check for partial intersection ourselves.
|
||||
RECT rect;
|
||||
rect.left = x; rect.top = y; rect.right = x+w; rect.bottom = y+h;
|
||||
if (!RectInRegion(r,&rect)) {
|
||||
W = H = 0;
|
||||
return 2;
|
||||
} else {
|
||||
if (PtInRegion(r, rect.left, rect.top) &&
|
||||
PtInRegion(r, rect.left, rect.top) &&
|
||||
PtInRegion(r, rect.right, rect.bottom) &&
|
||||
PtInRegion(r, rect.right, rect.bottom))
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef WIN32
|
||||
Region rr = XRectangleRegion(x,y,w,h);
|
||||
Region temp = XCreateRegion();
|
||||
XIntersectRegion(r, rr, temp);
|
||||
XRectangle rect;
|
||||
XClipBox(temp, &rect);
|
||||
X = rect.x; Y = rect.y; W = rect.width; H = rect.height;
|
||||
XDestroyRegion(temp);
|
||||
XDestroyRegion(rr);
|
||||
#else
|
||||
Region rr = XRectangleRegion(x,y,w,h);
|
||||
CombineRgn(rr, rr, r,RGN_AND);
|
||||
GetRgnBox(rr, &rect);
|
||||
X = rect.left; Y = rect.top; W = rect.right - X; H = rect.bottom - Y;
|
||||
DeleteObject(rr);
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
||||
// end of fl_rect.C
|
||||
|
196
src/gl_start.cxx
196
src/gl_start.cxx
@ -1,98 +1,98 @@
|
||||
// Code to switch current fltk drawing context in/out of GL "mode":
|
||||
|
||||
// You MUST use gl_visual() to select the default visual before doing
|
||||
// show() of any windows. Mesa will crash if you try to use a visual
|
||||
// not returned by glxChooseVisual.
|
||||
|
||||
// This does not work with Fl_Double_Window's! It will try to draw
|
||||
// into the front buffer. Depending on the system this will either
|
||||
// crash or do nothing (when pixmaps are being used as back buffer
|
||||
// and GL is being done by hardware), work correctly (when GL is done
|
||||
// with software, such as Mesa), or draw into the front buffer and
|
||||
// be erased when the buffers are swapped (when double buffer hardware
|
||||
// is being used)
|
||||
|
||||
#include <config.h>
|
||||
#if HAVE_GL
|
||||
|
||||
#include <FL/Fl.H>
|
||||
#include <FL/Fl_Window.H>
|
||||
#include <FL/x.H>
|
||||
#include <FL/fl_draw.H>
|
||||
|
||||
#include "Fl_Gl_Choice.H"
|
||||
|
||||
extern GLXContext fl_first_context; // in Fl_Gl_Choice.C
|
||||
extern int fl_clip_state_number; // in fl_rect.C
|
||||
|
||||
static GLXContext context;
|
||||
static int clip_state_number;
|
||||
static int pw, ph;
|
||||
|
||||
#ifdef WIN32
|
||||
static int default_mode;
|
||||
#endif
|
||||
|
||||
Region XRectangleRegion(int x, int y, int w, int h); // in fl_rect.C
|
||||
|
||||
void gl_start() {
|
||||
#ifdef WIN32
|
||||
HDC hdc = fl_private_dc(Fl_Window::current(), default_mode,0);
|
||||
if (!context) {
|
||||
context = wglCreateContext(hdc);
|
||||
if (!fl_first_context) fl_first_context = context;
|
||||
else wglShareLists(fl_first_context, context);
|
||||
}
|
||||
wglMakeCurrent(hdc, context);
|
||||
#else
|
||||
if (!context) {
|
||||
context = glXCreateContext(fl_display, fl_visual, fl_first_context, 1);
|
||||
if (!context) Fl::fatal("OpenGL does not support this visual");
|
||||
if (!fl_first_context) fl_first_context = context;
|
||||
}
|
||||
glXMakeCurrent(fl_display, fl_window, context);
|
||||
glXWaitX();
|
||||
#endif
|
||||
if (pw != Fl_Window::current()->w() || ph != Fl_Window::current()->h()) {
|
||||
pw = Fl_Window::current()->w();
|
||||
ph = Fl_Window::current()->h();
|
||||
glLoadIdentity();
|
||||
glViewport(0, 0, pw, ph);
|
||||
glOrtho(0, pw, 0, ph, -1, 1);
|
||||
glDrawBuffer(GL_FRONT);
|
||||
}
|
||||
if (clip_state_number != fl_clip_state_number) {
|
||||
clip_state_number = fl_clip_state_number;
|
||||
int x, y, w, h;
|
||||
if (fl_clip_box(0, 0, Fl_Window::current()->w(), Fl_Window::current()->h(),
|
||||
x, y, w, h)) {
|
||||
fl_clip_region(XRectangleRegion(x,y,w,h));
|
||||
glScissor(x, Fl_Window::current()->h()-(y+h), w, h);
|
||||
glEnable(GL_SCISSOR_TEST);
|
||||
} else {
|
||||
glDisable(GL_SCISSOR_TEST);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void gl_finish() {
|
||||
#ifdef WIN32
|
||||
glFlush();
|
||||
#else
|
||||
glXWaitGL();
|
||||
#endif
|
||||
}
|
||||
|
||||
int Fl::gl_visual(int mode, int *alist) {
|
||||
#ifdef WIN32
|
||||
default_mode = mode;
|
||||
#else
|
||||
Fl_Gl_Choice *c = Fl_Gl_Choice::find(mode,alist);
|
||||
if (!c) return 0;
|
||||
fl_visual = c->vis;
|
||||
fl_colormap = c->colormap;
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
||||
#endif
|
||||
// Code to switch current fltk drawing context in/out of GL "mode":
|
||||
|
||||
// You MUST use gl_visual() to select the default visual before doing
|
||||
// show() of any windows. Mesa will crash if you try to use a visual
|
||||
// not returned by glxChooseVisual.
|
||||
|
||||
// This does not work with Fl_Double_Window's! It will try to draw
|
||||
// into the front buffer. Depending on the system this will either
|
||||
// crash or do nothing (when pixmaps are being used as back buffer
|
||||
// and GL is being done by hardware), work correctly (when GL is done
|
||||
// with software, such as Mesa), or draw into the front buffer and
|
||||
// be erased when the buffers are swapped (when double buffer hardware
|
||||
// is being used)
|
||||
|
||||
#include <config.h>
|
||||
#if HAVE_GL
|
||||
|
||||
#include <FL/Fl.H>
|
||||
#include <FL/Fl_Window.H>
|
||||
#include <FL/x.H>
|
||||
#include <FL/fl_draw.H>
|
||||
|
||||
#include "Fl_Gl_Choice.H"
|
||||
|
||||
extern GLXContext fl_first_context; // in Fl_Gl_Choice.C
|
||||
extern int fl_clip_state_number; // in fl_rect.C
|
||||
|
||||
static GLXContext context;
|
||||
static int clip_state_number=-1;
|
||||
static int pw, ph;
|
||||
|
||||
#ifdef WIN32
|
||||
static int default_mode;
|
||||
#endif
|
||||
|
||||
Region XRectangleRegion(int x, int y, int w, int h); // in fl_rect.C
|
||||
|
||||
void gl_start() {
|
||||
#ifdef WIN32
|
||||
HDC hdc = fl_private_dc(Fl_Window::current(), default_mode,0);
|
||||
if (!context) {
|
||||
context = wglCreateContext(hdc);
|
||||
if (!fl_first_context) fl_first_context = context;
|
||||
else wglShareLists(fl_first_context, context);
|
||||
}
|
||||
wglMakeCurrent(hdc, context);
|
||||
#else
|
||||
if (!context) {
|
||||
context = glXCreateContext(fl_display, fl_visual, fl_first_context, 1);
|
||||
if (!context) Fl::fatal("OpenGL does not support this visual");
|
||||
if (!fl_first_context) fl_first_context = context;
|
||||
}
|
||||
glXMakeCurrent(fl_display, fl_window, context);
|
||||
glXWaitX();
|
||||
#endif
|
||||
if (pw != Fl_Window::current()->w() || ph != Fl_Window::current()->h()) {
|
||||
pw = Fl_Window::current()->w();
|
||||
ph = Fl_Window::current()->h();
|
||||
glLoadIdentity();
|
||||
glViewport(0, 0, pw, ph);
|
||||
glOrtho(0, pw, 0, ph, -1, 1);
|
||||
glDrawBuffer(GL_FRONT);
|
||||
}
|
||||
if (clip_state_number != fl_clip_state_number) {
|
||||
clip_state_number = fl_clip_state_number;
|
||||
int x, y, w, h;
|
||||
if (fl_clip_box(0, 0, Fl_Window::current()->w(), Fl_Window::current()->h(),
|
||||
x, y, w, h)) {
|
||||
fl_clip_region(XRectangleRegion(x,y,w,h));
|
||||
glScissor(x, Fl_Window::current()->h()-(y+h), w, h);
|
||||
glEnable(GL_SCISSOR_TEST);
|
||||
} else {
|
||||
glDisable(GL_SCISSOR_TEST);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void gl_finish() {
|
||||
#ifdef WIN32
|
||||
glFlush();
|
||||
#else
|
||||
glXWaitGL();
|
||||
#endif
|
||||
}
|
||||
|
||||
int Fl::gl_visual(int mode, int *alist) {
|
||||
#ifdef WIN32
|
||||
default_mode = mode;
|
||||
#else
|
||||
Fl_Gl_Choice *c = Fl_Gl_Choice::find(mode,alist);
|
||||
if (!c) return 0;
|
||||
fl_visual = c->vis;
|
||||
fl_colormap = c->colormap;
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -1,53 +1,56 @@
|
||||
/* My own scandir sorting function, useful for the film industry where
|
||||
we have many files with numbers in their names: */
|
||||
|
||||
#include <config.h>
|
||||
#include <ctype.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#ifdef WIN32
|
||||
#include <FL/filename.H>
|
||||
#else
|
||||
#if HAVE_DIRENT_H
|
||||
# include <dirent.h>
|
||||
#else
|
||||
# define dirent direct
|
||||
# if HAVE_SYS_NDIR_H
|
||||
# include <sys/ndir.h>
|
||||
# endif
|
||||
# if HAVE_SYS_DIR_H
|
||||
# include <sys/dir.h>
|
||||
# endif
|
||||
# if HAVE_NDIR_H
|
||||
# include <ndir.h>
|
||||
# endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
int numericsort(const struct dirent **A, const struct dirent **B) {
|
||||
const char* a = (*A)->d_name;
|
||||
const char* b = (*B)->d_name;
|
||||
int ret = 0;
|
||||
for (;;) {
|
||||
if (isdigit(*a) && isdigit(*b)) {
|
||||
int zdiff,diff,magdiff;
|
||||
zdiff = 0;
|
||||
while (*a == '0') {a++; zdiff++;}
|
||||
while (*b == '0') {b++; zdiff--;}
|
||||
while (isdigit(*a) && *a == *b) {a++; b++;}
|
||||
diff = (isdigit(*a) && isdigit(*b)) ? *a - *b : 0;
|
||||
magdiff = 0;
|
||||
while (isdigit(*a)) {magdiff++; a++;}
|
||||
while (isdigit(*b)) {magdiff--; b++;}
|
||||
if (ret);
|
||||
else if (magdiff) ret = magdiff;
|
||||
else if (diff) ret = diff;
|
||||
else if (zdiff) ret = zdiff;
|
||||
} else if (*a == *b) {
|
||||
if (!*a) return ret;
|
||||
a++; b++;
|
||||
} else
|
||||
return (*a-*b);
|
||||
}
|
||||
}
|
||||
/* My own scandir sorting function, useful for the film industry where
|
||||
we have many files with numbers in their names: */
|
||||
|
||||
#include <config.h>
|
||||
#include <ctype.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#ifdef WIN32
|
||||
#include <FL/filename.H>
|
||||
#else
|
||||
#if HAVE_DIRENT_H
|
||||
# include <dirent.h>
|
||||
#else
|
||||
# define dirent direct
|
||||
# if HAVE_SYS_NDIR_H
|
||||
# include <sys/ndir.h>
|
||||
# endif
|
||||
# if HAVE_SYS_DIR_H
|
||||
# include <sys/dir.h>
|
||||
# endif
|
||||
# if HAVE_NDIR_H
|
||||
# include <ndir.h>
|
||||
# endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
#endif
|
||||
int numericsort(const struct dirent **A, const struct dirent **B) {
|
||||
const char* a = (*A)->d_name;
|
||||
const char* b = (*B)->d_name;
|
||||
int ret = 0;
|
||||
for (;;) {
|
||||
if (isdigit(*a) && isdigit(*b)) {
|
||||
int zdiff,diff,magdiff;
|
||||
zdiff = 0;
|
||||
while (*a == '0') {a++; zdiff++;}
|
||||
while (*b == '0') {b++; zdiff--;}
|
||||
while (isdigit(*a) && *a == *b) {a++; b++;}
|
||||
diff = (isdigit(*a) && isdigit(*b)) ? *a - *b : 0;
|
||||
magdiff = 0;
|
||||
while (isdigit(*a)) {magdiff++; a++;}
|
||||
while (isdigit(*b)) {magdiff--; b++;}
|
||||
if (ret);
|
||||
else if (magdiff) ret = magdiff;
|
||||
else if (diff) ret = diff;
|
||||
else if (zdiff) ret = zdiff;
|
||||
} else if (*a == *b) {
|
||||
if (!*a) return ret;
|
||||
a++; b++;
|
||||
} else
|
||||
return (*a-*b);
|
||||
}
|
||||
}
|
||||
|
@ -1,79 +1,82 @@
|
||||
// scandir_win32.C
|
||||
|
||||
// Emulation of posix scandir() call
|
||||
|
||||
#include <config.h>
|
||||
#include <FL/filename.H>
|
||||
#include <string.h>
|
||||
#include <windows.h>
|
||||
|
||||
int scandir(const char *dirname, struct dirent ***namelist,
|
||||
int (*select)(const struct dirent *),
|
||||
int (*compar)(const struct dirent **, const struct dirent **)) {
|
||||
|
||||
int len = strlen(dirname);
|
||||
char *findIn = new char[len+5]; strcpy(findIn, dirname);
|
||||
for (char *d = findIn; *d; d++) if (*d=='/') *d='\\';
|
||||
if ((len==0)) { strcpy(findIn, ".\\*"); }
|
||||
if ((len==1)&& (d[-1]=='.')) { strcpy(findIn, ".\\*"); }
|
||||
if ((len>0) && (d[-1]=='\\')) { *d++ = '*'; *d = 0; }
|
||||
if ((len>1) && (d[-1]=='.') && (d[-2]=='\\')) { d[-1] = '*'; }
|
||||
|
||||
WIN32_FIND_DATA find;
|
||||
HANDLE h;
|
||||
int nDir = 0, NDir = 0;
|
||||
struct dirent **dir = 0, *selectDir;
|
||||
/*
|
||||
selectDir = (struct dirent*)new char[sizeof(dirent)+1];
|
||||
strcpy(selectDir->d_name, ".");
|
||||
dir[0] = selectDir;
|
||||
selectDir = (struct dirent*)new char[sizeof(dirent)+2];
|
||||
strcpy(selectDir->d_name, "..");
|
||||
dir[1] = selectDir;
|
||||
*/
|
||||
unsigned long ret;
|
||||
|
||||
if ((h=FindFirstFile(findIn, &find))==INVALID_HANDLE_VALUE) {
|
||||
ret = GetLastError();
|
||||
if (ret != ERROR_NO_MORE_FILES) {
|
||||
// TODO: return some error code
|
||||
}
|
||||
*namelist = dir;
|
||||
return nDir;
|
||||
}
|
||||
do {
|
||||
selectDir=(struct dirent*)new char[sizeof(dirent)+strlen(find.cFileName)];
|
||||
strcpy(selectDir->d_name, find.cFileName);
|
||||
if (!select || (*select)(selectDir)) {
|
||||
if (nDir==NDir) {
|
||||
struct dirent **tempDir = new struct dirent*[NDir+33];
|
||||
if (NDir) memcpy(tempDir, dir, sizeof(struct dirent*)*NDir);
|
||||
if (dir) delete dir;
|
||||
dir = tempDir;
|
||||
NDir += 32;
|
||||
}
|
||||
dir[nDir] = selectDir;
|
||||
nDir++;
|
||||
dir[nDir] = 0;
|
||||
} else {
|
||||
delete selectDir;
|
||||
}
|
||||
} while (FindNextFile(h, &find));
|
||||
ret = GetLastError();
|
||||
if (ret != ERROR_NO_MORE_FILES) {
|
||||
// TODO: return some error code
|
||||
}
|
||||
FindClose(h);
|
||||
|
||||
delete findIn;
|
||||
|
||||
if (compar) qsort (dir, nDir, sizeof(*dir),
|
||||
(int(*)(const void*, const void*))compar);
|
||||
|
||||
*namelist = dir;
|
||||
return nDir;
|
||||
}
|
||||
|
||||
int alphasort (const struct dirent **a, const struct dirent **b) {
|
||||
return strcmp ((*a)->d_name, (*b)->d_name);
|
||||
}
|
||||
// scandir_win32.C
|
||||
|
||||
// Emulation of posix scandir() call
|
||||
|
||||
#include <config.h>
|
||||
#include <FL/filename.H>
|
||||
#include <string.h>
|
||||
#include <windows.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
#endif
|
||||
int scandir(const char *dirname, struct dirent ***namelist,
|
||||
int (*select)(const struct dirent *),
|
||||
int (*compar)(const struct dirent **, const struct dirent **)) {
|
||||
|
||||
int len = strlen(dirname);
|
||||
char *findIn = new char[len+5]; strcpy(findIn, dirname);
|
||||
for (char *d = findIn; *d; d++) if (*d=='/') *d='\\';
|
||||
if ((len==0)) { strcpy(findIn, ".\\*"); }
|
||||
if ((len==1)&& (d[-1]=='.')) { strcpy(findIn, ".\\*"); }
|
||||
if ((len>0) && (d[-1]=='\\')) { *d++ = '*'; *d = 0; }
|
||||
if ((len>1) && (d[-1]=='.') && (d[-2]=='\\')) { d[-1] = '*'; }
|
||||
|
||||
WIN32_FIND_DATA find;
|
||||
HANDLE h;
|
||||
int nDir = 0, NDir = 0;
|
||||
struct dirent **dir = 0, *selectDir;
|
||||
/*
|
||||
selectDir = (struct dirent*)new char[sizeof(dirent)+1];
|
||||
strcpy(selectDir->d_name, ".");
|
||||
dir[0] = selectDir;
|
||||
selectDir = (struct dirent*)new char[sizeof(dirent)+2];
|
||||
strcpy(selectDir->d_name, "..");
|
||||
dir[1] = selectDir;
|
||||
*/
|
||||
unsigned long ret;
|
||||
|
||||
if ((h=FindFirstFile(findIn, &find))==INVALID_HANDLE_VALUE) {
|
||||
ret = GetLastError();
|
||||
if (ret != ERROR_NO_MORE_FILES) {
|
||||
// TODO: return some error code
|
||||
}
|
||||
*namelist = dir;
|
||||
return nDir;
|
||||
}
|
||||
do {
|
||||
selectDir=(struct dirent*)new char[sizeof(dirent)+strlen(find.cFileName)];
|
||||
strcpy(selectDir->d_name, find.cFileName);
|
||||
if (!select || (*select)(selectDir)) {
|
||||
if (nDir==NDir) {
|
||||
struct dirent **tempDir = new struct dirent*[NDir+33];
|
||||
if (NDir) memcpy(tempDir, dir, sizeof(struct dirent*)*NDir);
|
||||
if (dir) delete dir;
|
||||
dir = tempDir;
|
||||
NDir += 32;
|
||||
}
|
||||
dir[nDir] = selectDir;
|
||||
nDir++;
|
||||
dir[nDir] = 0;
|
||||
} else {
|
||||
delete selectDir;
|
||||
}
|
||||
} while (FindNextFile(h, &find));
|
||||
ret = GetLastError();
|
||||
if (ret != ERROR_NO_MORE_FILES) {
|
||||
// TODO: return some error code
|
||||
}
|
||||
FindClose(h);
|
||||
|
||||
delete findIn;
|
||||
|
||||
if (compar) qsort (dir, nDir, sizeof(*dir),
|
||||
(int(*)(const void*, const void*))compar);
|
||||
|
||||
*namelist = dir;
|
||||
return nDir;
|
||||
}
|
||||
|
||||
int alphasort (const struct dirent **a, const struct dirent **b) {
|
||||
return strcmp ((*a)->d_name, (*b)->d_name);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user