378 lines
9.9 KiB
C++
378 lines
9.9 KiB
C++
|
// Fl_arg.C
|
||
|
|
||
|
// OPTIONAL initialization code for a program using fltk.
|
||
|
// You do not need to call this! Feel free to make up your own switches.
|
||
|
|
||
|
#include <FL/Fl.H>
|
||
|
#include <FL/x.H>
|
||
|
#include <FL/Fl_Window.H>
|
||
|
#include <FL/filename.H>
|
||
|
#include <FL/fl_draw.H>
|
||
|
#include <ctype.h>
|
||
|
#include <string.h>
|
||
|
|
||
|
#ifdef WIN32
|
||
|
int XParseGeometry(const char*, int*, int*, unsigned int*, unsigned int*);
|
||
|
#define NoValue 0x0000
|
||
|
#define XValue 0x0001
|
||
|
#define YValue 0x0002
|
||
|
#define WidthValue 0x0004
|
||
|
#define HeightValue 0x0008
|
||
|
#define AllValues 0x000F
|
||
|
#define XNegative 0x0010
|
||
|
#define YNegative 0x0020
|
||
|
#endif
|
||
|
|
||
|
static int match(const char *a, const char *match, int atleast = 1) {
|
||
|
const char *b = match;
|
||
|
while (*a && (*a == *b || tolower(*a) == *b)) {a++; b++;}
|
||
|
return !*a && b >= match+atleast;
|
||
|
}
|
||
|
|
||
|
// flags set by previously parsed arguments:
|
||
|
extern char fl_show_iconic; // in Fl_x.C
|
||
|
static char arg_called;
|
||
|
static char return_i;
|
||
|
static const char *name;
|
||
|
static const char *fg;
|
||
|
static const char *bg;
|
||
|
static const char *bg2;
|
||
|
static const char *geometry;
|
||
|
static const char *title;
|
||
|
|
||
|
// consume a switch from argv. Returns number of words eaten, 0 on error:
|
||
|
int Fl::arg(int argc, char **argv, int &i) {
|
||
|
arg_called = 1;
|
||
|
const char *s = argv[i];
|
||
|
|
||
|
if (!s) {i++; return 1;} // something removed by calling program?
|
||
|
|
||
|
// a word that does not start with '-', or a word after a '--', or
|
||
|
// the word '-' by itself all start the "non-switch arguments" to
|
||
|
// a program. Return 0 to indicate that we don't understand the
|
||
|
// word, but set a flag (return_i) so that args() will return at
|
||
|
// that point:
|
||
|
if (s[0] != '-' || !s[1]) {return_i = 1; return 0;}
|
||
|
if (s[1] == '-') {
|
||
|
if (!s[2]) {i++; return_i = 1; return 0;}
|
||
|
s++; // make "--word" work the same as "-word" for Gnu compatability
|
||
|
}
|
||
|
s++; // point after the dash
|
||
|
|
||
|
if (match(s, "iconic")) {
|
||
|
fl_show_iconic = 1;
|
||
|
i++;
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
const char *v = argv[i+1];
|
||
|
if (i >= argc-1 || !v)
|
||
|
return 0; // all the rest need an argument, so if missing it is an error
|
||
|
|
||
|
if (match(s, "geometry")) {
|
||
|
|
||
|
int flags, gx, gy; unsigned int gw, gh;
|
||
|
flags = XParseGeometry(v, &gx, &gy, &gw, &gh);
|
||
|
if (!flags) return 0;
|
||
|
geometry = v;
|
||
|
|
||
|
#ifndef WIN32
|
||
|
} else if (match(s, "display")) {
|
||
|
Fl::display(v);
|
||
|
#endif
|
||
|
|
||
|
} else if (match(s, "title")) {
|
||
|
title = v;
|
||
|
|
||
|
} else if (match(s, "name")) {
|
||
|
name = v;
|
||
|
|
||
|
} else if (match(s, "bg2", 3) || match(s, "background2", 11)) {
|
||
|
bg2 = v;
|
||
|
|
||
|
} else if (match(s, "bg") || match(s, "background")) {
|
||
|
bg = v;
|
||
|
|
||
|
} else if (match(s, "fg") || match(s, "foreground")) {
|
||
|
fg = v;
|
||
|
|
||
|
} else return 0; // unrecognized
|
||
|
|
||
|
i += 2;
|
||
|
return 2;
|
||
|
}
|
||
|
|
||
|
// consume all switches from argv. Returns number of words eaten.
|
||
|
// Returns zero on error. 'i' will either point at first word that
|
||
|
// does not start with '-', at the error word, or after a '--', or at
|
||
|
// argc. If your program does not take any word arguments you can
|
||
|
// report an error if i < argc.
|
||
|
|
||
|
int Fl::args(int argc, char** argv, int& i, int (*cb)(int,char**,int&)) {
|
||
|
arg_called = 1;
|
||
|
i = 1; // skip argv[0]
|
||
|
while (i < argc) {
|
||
|
if (cb && cb(argc,argv,i)) continue;
|
||
|
if (!arg(argc,argv,i)) return return_i ? i : 0;
|
||
|
}
|
||
|
return i;
|
||
|
}
|
||
|
|
||
|
#ifdef WIN32
|
||
|
#include <stdio.h>
|
||
|
// simulation of XParseColor:
|
||
|
int fl_parse_color(const char* p, uchar& r, uchar& g, uchar& b) {
|
||
|
if (*p == '#') p++;
|
||
|
int n = strlen(p);
|
||
|
int m = n/3;
|
||
|
const char *pattern = 0;
|
||
|
switch(m) {
|
||
|
case 1: pattern = "%1x%1x%1x"; break;
|
||
|
case 2: pattern = "%2x%2x%2x"; break;
|
||
|
case 3: pattern = "%3x%3x%3x"; break;
|
||
|
case 4: pattern = "%4x%4x%4x"; break;
|
||
|
default: return 0;
|
||
|
}
|
||
|
int R,G,B; if (sscanf(p,pattern,&R,&G,&B) != 3) return 0;
|
||
|
r = R; g = G; b = B;
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
static void parsecolor(const char *name, void (*func)(uchar,uchar,uchar)) {
|
||
|
uchar r,g,b;
|
||
|
if (!name) return;
|
||
|
if (!fl_parse_color(name, r,g,b))
|
||
|
Fl::error("Unknown color: %s", name);
|
||
|
else
|
||
|
func(r,g,b);
|
||
|
}
|
||
|
|
||
|
#else
|
||
|
|
||
|
static void parsecolor(const char *name, void (*func)(uchar,uchar,uchar)) {
|
||
|
XColor x;
|
||
|
if (!name) return;
|
||
|
if (!XParseColor(fl_display, fl_colormap, name, &x))
|
||
|
Fl::error("Unknown color: %s", name);
|
||
|
else
|
||
|
func(x.red>>8, x.green>>8, x.blue>>8);
|
||
|
}
|
||
|
|
||
|
#endif
|
||
|
|
||
|
// show a main window, use any parsed arguments
|
||
|
void Fl_Window::show(int argc, char **argv) {
|
||
|
if (!arg_called) Fl::args(argc,argv);
|
||
|
|
||
|
// set colors first, so background_pixel is correct:
|
||
|
static char beenhere;
|
||
|
if (!beenhere) {
|
||
|
beenhere = 1;
|
||
|
Fl::get_system_colors(); // opens display! May call Fl::fatal()
|
||
|
parsecolor(fg, Fl::foreground);
|
||
|
parsecolor(bg, Fl::background);
|
||
|
parsecolor(bg2,Fl::background2);
|
||
|
if (geometry) {
|
||
|
int flags = 0, gx = x(), gy = y(); unsigned int gw = w(), gh = h();
|
||
|
flags = XParseGeometry(geometry, &gx, &gy, &gw, &gh);
|
||
|
if (flags & XNegative) gx = Fl::w()-w()+gx;
|
||
|
if (flags & YNegative) gy = Fl::h()-h()+gy;
|
||
|
// int mw,mh; minsize(mw,mh);
|
||
|
// if (mw > gw) gw = mw;
|
||
|
// if (mh > gh) gh = mh;
|
||
|
Fl_Widget *r = resizable();
|
||
|
if (!r) resizable(this);
|
||
|
// for WIN32 we assumme window is not mapped yet:
|
||
|
if (flags & (XValue | YValue))
|
||
|
x(-1), resize(gx,gy,gw,gh);
|
||
|
else
|
||
|
size(gw,gh);
|
||
|
resizable(r);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (name) {xclass(name); name = 0;}
|
||
|
else if (!xclass()) xclass(filename_name(argv[0]));
|
||
|
if (title) {label(title); title = 0;}
|
||
|
else if (!label()) label(xclass());
|
||
|
show();
|
||
|
|
||
|
#ifndef WIN32
|
||
|
// set the command string, used by state-saving window managers:
|
||
|
int i;
|
||
|
int n=0; for (i=0; i<argc; i++) n += strlen(argv[i])+1;
|
||
|
#ifdef __GNUC__
|
||
|
char buffer[n];
|
||
|
#else
|
||
|
char *buffer = new char[n];
|
||
|
#endif
|
||
|
char *p = buffer;
|
||
|
for (i=0; i<argc; i++) for (const char *q = argv[i]; (*p++ = *q++););
|
||
|
XChangeProperty(fl_display, fl_xid(this), XA_WM_COMMAND, XA_STRING, 8, 0,
|
||
|
(unsigned char *)buffer, p-buffer-1);
|
||
|
#ifndef __GNUC__
|
||
|
delete[] buffer;
|
||
|
#endif
|
||
|
#endif
|
||
|
|
||
|
}
|
||
|
|
||
|
// Calls useful for simple demo programs, with automatic help message:
|
||
|
|
||
|
static const char * const helpmsg =
|
||
|
"options are:\n"
|
||
|
" -display host:n.n\n"
|
||
|
" -geometry WxH+X+Y\n"
|
||
|
" -title windowtitle\n"
|
||
|
" -name classname\n"
|
||
|
" -iconic\n"
|
||
|
" -fg color\n"
|
||
|
" -bg color\n"
|
||
|
" -bg2 color";
|
||
|
|
||
|
const char * const Fl::help = helpmsg+13;
|
||
|
|
||
|
void Fl::args(int argc, char **argv) {
|
||
|
int i; if (Fl::args(argc,argv,i) < argc) Fl::error(helpmsg);
|
||
|
}
|
||
|
|
||
|
#ifdef WIN32
|
||
|
|
||
|
/* the following function was stolen from the X sources as indicated. */
|
||
|
|
||
|
/* Copyright Massachusetts Institute of Technology 1985, 1986, 1987 */
|
||
|
/* $XConsortium: XParseGeom.c,v 11.18 91/02/21 17:23:05 rws Exp $ */
|
||
|
|
||
|
/*
|
||
|
Permission to use, copy, modify, distribute, and sell this software and its
|
||
|
documentation for any purpose is hereby granted without fee, provided that
|
||
|
the above copyright notice appear in all copies and that both that
|
||
|
copyright notice and this permission notice appear in supporting
|
||
|
documentation, and that the name of M.I.T. not be used in advertising or
|
||
|
publicity pertaining to distribution of the software without specific,
|
||
|
written prior permission. M.I.T. makes no representations about the
|
||
|
suitability of this software for any purpose. It is provided "as is"
|
||
|
without express or implied warranty.
|
||
|
*/
|
||
|
|
||
|
/*
|
||
|
* XParseGeometry parses strings of the form
|
||
|
* "=<width>x<height>{+-}<xoffset>{+-}<yoffset>", where
|
||
|
* width, height, xoffset, and yoffset are unsigned integers.
|
||
|
* Example: "=80x24+300-49"
|
||
|
* The equal sign is optional.
|
||
|
* It returns a bitmask that indicates which of the four values
|
||
|
* were actually found in the string. For each value found,
|
||
|
* the corresponding argument is updated; for each value
|
||
|
* not found, the corresponding argument is left unchanged.
|
||
|
*/
|
||
|
|
||
|
static int ReadInteger(char* string, char** NextString)
|
||
|
{
|
||
|
register int Result = 0;
|
||
|
int Sign = 1;
|
||
|
|
||
|
if (*string == '+')
|
||
|
string++;
|
||
|
else if (*string == '-') {
|
||
|
string++;
|
||
|
Sign = -1;
|
||
|
}
|
||
|
for (; (*string >= '0') && (*string <= '9'); string++) {
|
||
|
Result = (Result * 10) + (*string - '0');
|
||
|
}
|
||
|
*NextString = string;
|
||
|
if (Sign >= 0)
|
||
|
return (Result);
|
||
|
else
|
||
|
return (-Result);
|
||
|
}
|
||
|
|
||
|
int XParseGeometry(const char* string, int* x, int* y,
|
||
|
unsigned int* width, unsigned int* height)
|
||
|
{
|
||
|
int mask = NoValue;
|
||
|
register char *strind;
|
||
|
unsigned int tempWidth, tempHeight;
|
||
|
int tempX, tempY;
|
||
|
char *nextCharacter;
|
||
|
|
||
|
if ( (string == NULL) || (*string == '\0')) return(mask);
|
||
|
if (*string == '=')
|
||
|
string++; /* ignore possible '=' at beg of geometry spec */
|
||
|
|
||
|
strind = (char *)string;
|
||
|
if (*strind != '+' && *strind != '-' && *strind != 'x') {
|
||
|
tempWidth = ReadInteger(strind, &nextCharacter);
|
||
|
if (strind == nextCharacter)
|
||
|
return (0);
|
||
|
strind = nextCharacter;
|
||
|
mask |= WidthValue;
|
||
|
}
|
||
|
|
||
|
if (*strind == 'x' || *strind == 'X') {
|
||
|
strind++;
|
||
|
tempHeight = ReadInteger(strind, &nextCharacter);
|
||
|
if (strind == nextCharacter)
|
||
|
return (0);
|
||
|
strind = nextCharacter;
|
||
|
mask |= HeightValue;
|
||
|
}
|
||
|
|
||
|
if ((*strind == '+') || (*strind == '-')) {
|
||
|
if (*strind == '-') {
|
||
|
strind++;
|
||
|
tempX = -ReadInteger(strind, &nextCharacter);
|
||
|
if (strind == nextCharacter)
|
||
|
return (0);
|
||
|
strind = nextCharacter;
|
||
|
mask |= XNegative;
|
||
|
|
||
|
} else {
|
||
|
strind++;
|
||
|
tempX = ReadInteger(strind, &nextCharacter);
|
||
|
if (strind == nextCharacter)
|
||
|
return(0);
|
||
|
strind = nextCharacter;
|
||
|
}
|
||
|
mask |= XValue;
|
||
|
if ((*strind == '+') || (*strind == '-')) {
|
||
|
if (*strind == '-') {
|
||
|
strind++;
|
||
|
tempY = -ReadInteger(strind, &nextCharacter);
|
||
|
if (strind == nextCharacter)
|
||
|
return(0);
|
||
|
strind = nextCharacter;
|
||
|
mask |= YNegative;
|
||
|
|
||
|
} else {
|
||
|
strind++;
|
||
|
tempY = ReadInteger(strind, &nextCharacter);
|
||
|
if (strind == nextCharacter)
|
||
|
return(0);
|
||
|
strind = nextCharacter;
|
||
|
}
|
||
|
mask |= YValue;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* If strind isn't at the end of the string the it's an invalid
|
||
|
geometry specification. */
|
||
|
|
||
|
if (*strind != '\0') return (0);
|
||
|
|
||
|
if (mask & XValue)
|
||
|
*x = tempX;
|
||
|
if (mask & YValue)
|
||
|
*y = tempY;
|
||
|
if (mask & WidthValue)
|
||
|
*width = tempWidth;
|
||
|
if (mask & HeightValue)
|
||
|
*height = tempHeight;
|
||
|
return (mask);
|
||
|
}
|
||
|
|
||
|
#endif // ifdef WIN32
|
||
|
|
||
|
// end of Fl_Window_arg.C
|