themes: Workaround for bug where a background color of RGB 0,0,0 in Black color schem...
[ntk.git] / src / Fl_arg.cxx
blob59e3e252b74c5eaec680d63bd6360a5136f6c515
1 //
2 // "$Id: Fl_arg.cxx 7903 2010-11-28 21:06:39Z matt $"
3 //
4 // Optional argument initialization code for the Fast Light Tool Kit (FLTK).
5 //
6 // Copyright 1998-2010 by Bill Spitzak and others.
7 //
8 // This library is free software; you can redistribute it and/or
9 // modify it under the terms of the GNU Library General Public
10 // License as published by the Free Software Foundation; either
11 // version 2 of the License, or (at your option) any later version.
13 // This library is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 // Library General Public License for more details.
18 // You should have received a copy of the GNU Library General Public
19 // License along with this library; if not, write to the Free Software
20 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
21 // USA.
23 // Please report all bugs and problems on the following page:
25 // http://www.fltk.org/str.php
28 // OPTIONAL initialization code for a program using fltk.
29 // You do not need to call this! Feel free to make up your own switches.
31 #include <FL/Fl.H>
32 #include <FL/x.H>
33 #include <FL/Fl_Window.H>
34 #include <FL/Fl_Tooltip.H>
35 #include <FL/filename.H>
36 #include <FL/fl_draw.H>
37 #include <ctype.h>
38 #include "flstring.h"
39 #include <FL/themes.H>
41 #if defined(WIN32) || defined(__APPLE__)
42 int XParseGeometry(const char*, int*, int*, unsigned int*, unsigned int*);
43 # define NoValue 0x0000
44 # define XValue 0x0001
45 # define YValue 0x0002
46 # define WidthValue 0x0004
47 # define HeightValue 0x0008
48 # define AllValues 0x000F
49 # define XNegative 0x0010
50 # define YNegative 0x0020
51 #endif
53 static int fl_match(const char *a, const char *s, int atleast = 1) {
54 const char *b = s;
55 while (*a && (*a == *b || tolower(*a) == *b)) {a++; b++;}
56 return !*a && b >= s+atleast;
59 // flags set by previously parsed arguments:
60 extern char fl_show_iconic; // in Fl_x.cxx
61 static char arg_called;
62 static char return_i;
63 static const char *name;
64 static const char *geometry;
65 static const char *title;
66 // these are in Fl_get_system_colors and are set by the switches:
67 extern const char *fl_fg;
68 extern const char *fl_bg;
69 extern const char *fl_bg2;
71 /**
72 Parse a single switch from \p argv, starting at word \p i.
73 Returns the number of words eaten (1 or 2, or 0 if it is not
74 recognized) and adds the same value to \p i.
76 This is the default argument handler used internally by Fl::args(...),
77 but you can use this function if you prefer to step through the
78 standard FLTK switches yourself.
80 All standard FLTK switches except -bg2 may be abbreviated to just
81 one letter and case is ignored:
83 \li -bg color or -background color
84 <br>
85 Sets the background color using Fl::background().
87 \li -bg2 color or -background2 color
88 <br>
89 Sets the secondary background color using Fl::background2().
91 \li -display host:n.n
92 <br>
93 Sets the X display to use; this option is silently
94 ignored under WIN32 and MacOS.
96 \li -dnd and -nodnd
97 <br>
98 Enables or disables drag and drop text operations
99 using Fl::dnd_text_ops().
101 \li -fg color or -foreground color
102 <br>
103 Sets the foreground color using Fl::foreground().
105 \li -geometry WxH+X+Y
106 <br>
107 Sets the initial window position and size according
108 to the standard X geometry string.
110 \li -iconic
111 <br>
112 Iconifies the window using Fl_Window::iconize().
114 \li -kbd and -nokbd
115 <br>
116 Enables or disables visible keyboard focus for
117 non-text widgets using Fl::visible_focus().
119 \li -name string
120 <br>
121 Sets the window class using Fl_Window::xclass().
123 \li -scheme string
124 <br>
125 Sets the widget scheme using Fl::scheme().
127 \li -title string
128 <br>
129 Sets the window title using Fl_Window::label().
131 \li -tooltips and -notooltips
132 <br>
133 Enables or disables tooltips using Fl_Tooltip::enable().
136 If your program requires other switches in addition to the standard
137 FLTK options, you will need to pass your own argument handler to
138 Fl::args(int,char**,int&,Fl_Args_Handler) explicitly.
140 int Fl::arg(int argc, char **argv, int &i) {
141 arg_called = 1;
142 const char *s = argv[i];
144 if (!s) {i++; return 1;} // something removed by calling program?
146 // a word that does not start with '-', or a word after a '--', or
147 // the word '-' by itself all start the "non-switch arguments" to
148 // a program. Return 0 to indicate that we don't understand the
149 // word, but set a flag (return_i) so that args() will return at
150 // that point:
151 if (s[0] != '-' || s[1] == '-' || !s[1]) {return_i = 1; return 0;}
152 s++; // point after the dash
154 if (fl_match(s, "iconic")) {
155 fl_show_iconic = 1;
156 i++;
157 return 1;
158 } else if (fl_match(s, "kbd")) {
159 Fl::visible_focus(1);
160 i++;
161 return 1;
162 } else if (fl_match(s, "nokbd", 3)) {
163 Fl::visible_focus(0);
164 i++;
165 return 1;
166 } else if (fl_match(s, "dnd", 2)) {
167 Fl::dnd_text_ops(1);
168 i++;
169 return 1;
170 } else if (fl_match(s, "nodnd", 3)) {
171 Fl::dnd_text_ops(0);
172 i++;
173 return 1;
174 } else if (fl_match(s, "tooltips", 2)) {
175 Fl_Tooltip::enable();
176 i++;
177 return 1;
178 } else if (fl_match(s, "notooltips", 3)) {
179 Fl_Tooltip::disable();
180 i++;
181 return 1;
185 #ifdef __APPLE__
186 // The Finder application in MacOS X passes the "-psn_N_NNNNN" option
187 // to all apps...
188 else if (strncmp(s, "psn_", 4) == 0) {
189 i++;
190 return 1;
192 #endif // __APPLE__
194 const char *v = argv[i+1];
195 if (i >= argc-1 || !v)
196 return 0; // all the rest need an argument, so if missing it is an error
198 if (fl_match(s, "geometry")) {
200 int flags, gx, gy; unsigned int gw, gh;
201 flags = XParseGeometry(v, &gx, &gy, &gw, &gh);
202 if (!flags) return 0;
203 geometry = v;
205 #if !defined(WIN32) && !defined(__APPLE__)
206 } else if (fl_match(s, "display", 2)) {
207 Fl::display(v);
208 #endif
210 } else if (fl_match(s, "title", 2)) {
211 title = v;
213 } else if (fl_match(s, "name", 2)) {
214 name = v;
216 } else if (fl_match(s, "bg2", 3) || fl_match(s, "background2", 11)) {
217 fl_bg2 = v;
219 } else if (fl_match(s, "bg", 2) || fl_match(s, "background", 10)) {
220 fl_bg = v;
222 } else if (fl_match(s, "fg", 2) || fl_match(s, "foreground", 10)) {
223 fl_fg = v;
225 } else if (fl_match(s, "scheme", 1)) {
226 Fl::scheme(v);
228 } else return 0; // unrecognized
230 i += 2;
231 return 2;
236 Parse command line switches using the \p cb argument handler.
238 Returns 0 on error, or the number of words processed.
240 FLTK provides this as an <i>entirely optional</i> command line
241 switch parser. You don't have to call it if you don't want to.
242 Everything it can do can be done with other calls to FLTK.
244 To use the switch parser, call Fl::args(...) near the start
245 of your program. This does \b not open the display, instead
246 switches that need the display open are stashed into static
247 variables. Then you \b must display your first window by calling
248 <tt>window->show(argc,argv)</tt>, which will do anything stored
249 in the static variables.
251 Providing an argument handler callback \p cb lets you define
252 your own switches. It is called with the same \p argc and \p argv,
253 and with \p i set to the index of the switch to be processed.
254 The \p cb handler should return zero if the switch is unrecognized,
255 and not change \p i. It should return non-zero to indicate the
256 number of words processed if the switch is recognized, i.e. 1 for
257 just the switch, and more than 1 for the switch plus associated
258 parameters. \p i should be incremented by the same amount.
260 The \p cb handler is called \b before any other tests, so
261 <i>you can also override any standard FLTK switch</i>
262 (this is why FLTK can use very short switches instead of
263 the long ones all other toolkits force you to use).
264 See Fl::arg() for descriptions of the standard switches.
266 On return \p i is set to the index of the first non-switch.
267 This is either:
269 \li The first word that does not start with '-'.
270 \li The word '-' (used by many programs to name stdin as a file)
271 \li The first unrecognized switch (return value is 0).
272 \li \p argc
274 The return value is \p i unless an unrecognized switch is found,
275 in which case it is zero. If your program takes no arguments other
276 than switches you should produce an error if the return value is less
277 than \p argc.
280 A usage string is displayed if Fl::args() detects an invalid argument
281 on the command-line. You can change the message by setting the
282 Fl::help pointer.
284 A very simple command line parser can be found in <tt>examples/howto-parse-args.cxx</tt>
286 The simpler Fl::args(int argc, char **argv) form is useful if your program
287 does not have command line switches of its own.
290 int Fl::args(int argc, char** argv, int& i, Fl_Args_Handler cb) {
291 arg_called = 1;
292 i = 1; // skip argv[0]
293 while (i < argc) {
294 if (cb && cb(argc,argv,i)) continue;
295 if (!arg(argc,argv,i)) return return_i ? i : 0;
297 return i;
300 // show a main window, use any parsed arguments
301 void Fl_Window::show(int argc, char **argv) {
302 if (argc && !arg_called) Fl::args(argc,argv);
304 Fl::get_system_colors();
306 #if !defined(WIN32) && !defined(__APPLE__)
307 // Get defaults for drag-n-drop and focus...
308 const char *key = 0, *val;
310 if (Fl::first_window()) key = Fl::first_window()->xclass();
311 if (!key) key = "fltk";
313 val = XGetDefault(fl_display, key, "dndTextOps");
314 if (val) Fl::dnd_text_ops(strcasecmp(val, "true") == 0 ||
315 strcasecmp(val, "on") == 0 ||
316 strcasecmp(val, "yes") == 0);
318 val = XGetDefault(fl_display, key, "tooltips");
319 if (val) Fl_Tooltip::enable(strcasecmp(val, "true") == 0 ||
320 strcasecmp(val, "on") == 0 ||
321 strcasecmp(val, "yes") == 0);
323 val = XGetDefault(fl_display, key, "visibleFocus");
324 if (val) Fl::visible_focus(strcasecmp(val, "true") == 0 ||
325 strcasecmp(val, "on") == 0 ||
326 strcasecmp(val, "yes") == 0);
327 #endif // !WIN32 && !__APPLE__
329 // set colors first, so background_pixel is correct:
330 static char beenhere;
331 if (!beenhere) {
332 if (geometry) {
333 int fl = 0, gx = x(), gy = y(); unsigned int gw = w(), gh = h();
334 fl = XParseGeometry(geometry, &gx, &gy, &gw, &gh);
335 if (fl & XNegative) gx = Fl::w()-w()+gx;
336 if (fl & YNegative) gy = Fl::h()-h()+gy;
337 // int mw,mh; minsize(mw,mh);
338 // if (mw > gw) gw = mw;
339 // if (mh > gh) gh = mh;
340 Fl_Widget *r = resizable();
341 if (!r) resizable(this);
342 // for WIN32 we assume window is not mapped yet:
343 if (fl & (XValue | YValue))
344 x(-1), resize(gx,gy,gw,gh);
345 else
346 size(gw,gh);
347 resizable(r);
351 // set the class, which is used by X version of get_system_colors:
352 if (name) {xclass(name); name = 0;}
353 else if (!xclass()) xclass(fl_filename_name(argv[0]));
355 if (title) {label(title); title = 0;}
356 else if (!label()) label(xclass());
358 // Show the window AFTER we have set the colors and scheme.
359 show();
361 #if !defined(WIN32) && !defined(__APPLE__)
362 // set the command string, used by state-saving window managers:
363 int j;
364 int n=0; for (j=0; j<argc; j++) n += strlen(argv[j])+1;
365 char *buffer = new char[n];
366 char *p = buffer;
367 for (j=0; j<argc; j++) for (const char *q = argv[j]; (*p++ = *q++););
368 XChangeProperty(fl_display, fl_xid(this), XA_WM_COMMAND, XA_STRING, 8, 0,
369 (unsigned char *)buffer, p-buffer-1);
370 delete[] buffer;
371 #endif // !WIN32 && !__APPLE__
374 // Calls useful for simple demo programs, with automatic help message:
376 static const char * const helpmsg =
377 "options are:\n"
378 " -bg2 color\n"
379 " -bg color\n"
380 " -di[splay] host:n.n\n"
381 " -dn[d]\n"
382 " -fg color\n"
383 " -g[eometry] WxH+X+Y\n"
384 " -i[conic]\n"
385 " -k[bd]\n"
386 " -na[me] classname\n"
387 " -nod[nd]\n"
388 " -nok[bd]\n"
389 " -not[ooltips]\n"
390 " -s[cheme] scheme\n"
391 " -ti[tle] windowtitle\n"
392 " -to[oltips]";
394 const char * const Fl::help = helpmsg+13;
397 Parse all command line switches matching standard FLTK options only.
399 It parses all the switches, and if any are not recognized it calls
400 Fl::abort(Fl::help), i.e. unlike the long form, an unrecognized
401 switch generates an error message and causes the program to exit.
404 void Fl::args(int argc, char **argv) {
405 int i; if (Fl::args(argc,argv,i) < argc) Fl::error(helpmsg);
408 #if defined(WIN32) || defined(__APPLE__)
410 /* the following function was stolen from the X sources as indicated. */
412 /* Copyright Massachusetts Institute of Technology 1985, 1986, 1987 */
413 /* $XConsortium: XParseGeom.c,v 11.18 91/02/21 17:23:05 rws Exp $ */
416 Permission to use, copy, modify, distribute, and sell this software and its
417 documentation for any purpose is hereby granted without fee, provided that
418 the above copyright notice appear in all copies and that both that
419 copyright notice and this permission notice appear in supporting
420 documentation, and that the name of M.I.T. not be used in advertising or
421 publicity pertaining to distribution of the software without specific,
422 written prior permission. M.I.T. makes no representations about the
423 suitability of this software for any purpose. It is provided "as is"
424 without express or implied warranty.
428 * XParseGeometry parses strings of the form
429 * "=<width>x<height>{+-}<xoffset>{+-}<yoffset>", where
430 * width, height, xoffset, and yoffset are unsigned integers.
431 * Example: "=80x24+300-49"
432 * The equal sign is optional.
433 * It returns a bitmask that indicates which of the four values
434 * were actually found in the string. For each value found,
435 * the corresponding argument is updated; for each value
436 * not found, the corresponding argument is left unchanged.
439 static int ReadInteger(char* string, char** NextString)
441 register int Result = 0;
442 int Sign = 1;
444 if (*string == '+')
445 string++;
446 else if (*string == '-') {
447 string++;
448 Sign = -1;
450 for (; (*string >= '0') && (*string <= '9'); string++) {
451 Result = (Result * 10) + (*string - '0');
453 *NextString = string;
454 if (Sign >= 0)
455 return (Result);
456 else
457 return (-Result);
460 int XParseGeometry(const char* string, int* x, int* y,
461 unsigned int* width, unsigned int* height)
463 int mask = NoValue;
464 register char *strind;
465 unsigned int tempWidth = 0, tempHeight = 0;
466 int tempX = 0, tempY = 0;
467 char *nextCharacter;
469 if ( (string == NULL) || (*string == '\0')) return(mask);
470 if (*string == '=')
471 string++; /* ignore possible '=' at beg of geometry spec */
473 strind = (char *)string;
474 if (*strind != '+' && *strind != '-' && *strind != 'x') {
475 tempWidth = ReadInteger(strind, &nextCharacter);
476 if (strind == nextCharacter)
477 return (0);
478 strind = nextCharacter;
479 mask |= WidthValue;
482 if (*strind == 'x' || *strind == 'X') {
483 strind++;
484 tempHeight = ReadInteger(strind, &nextCharacter);
485 if (strind == nextCharacter)
486 return (0);
487 strind = nextCharacter;
488 mask |= HeightValue;
491 if ((*strind == '+') || (*strind == '-')) {
492 if (*strind == '-') {
493 strind++;
494 tempX = -ReadInteger(strind, &nextCharacter);
495 if (strind == nextCharacter)
496 return (0);
497 strind = nextCharacter;
498 mask |= XNegative;
500 } else {
501 strind++;
502 tempX = ReadInteger(strind, &nextCharacter);
503 if (strind == nextCharacter)
504 return(0);
505 strind = nextCharacter;
507 mask |= XValue;
508 if ((*strind == '+') || (*strind == '-')) {
509 if (*strind == '-') {
510 strind++;
511 tempY = -ReadInteger(strind, &nextCharacter);
512 if (strind == nextCharacter)
513 return(0);
514 strind = nextCharacter;
515 mask |= YNegative;
517 } else {
518 strind++;
519 tempY = ReadInteger(strind, &nextCharacter);
520 if (strind == nextCharacter)
521 return(0);
522 strind = nextCharacter;
524 mask |= YValue;
528 /* If strind isn't at the end of the string the it's an invalid
529 geometry specification. */
531 if (*strind != '\0') return (0);
533 if (mask & XValue)
534 *x = tempX;
535 if (mask & YValue)
536 *y = tempY;
537 if (mask & WidthValue)
538 *width = tempWidth;
539 if (mask & HeightValue)
540 *height = tempHeight;
541 return (mask);
544 #endif // ifdef WIN32
547 // End of "$Id: Fl_arg.cxx 7903 2010-11-28 21:06:39Z matt $".