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:
Michael R Sweet 1998-10-06 18:46:47 +00:00
parent f9039b2ae2
commit e7d805a88c
12 changed files with 2793 additions and 2723 deletions

View File

@ -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

View File

@ -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

File diff suppressed because it is too large Load Diff

View File

@ -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();
}

View File

@ -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

View File

@ -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

File diff suppressed because it is too large Load Diff

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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);
}
}

View File

@ -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);
}