2 // "$Id: Fl_arg.cxx 7903 2010-11-28 21:06:39Z matt $"
4 // Optional argument initialization code for the Fast Light Tool Kit (FLTK).
6 // Copyright 1998-2010 by Bill Spitzak and others.
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
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.
33 #include <FL/Fl_Window.H>
34 #include <FL/Fl_Tooltip.H>
35 #include <FL/filename.H>
36 #include <FL/fl_draw.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
53 static int fl_match(const char *a
, const char *s
, int atleast
= 1) {
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
;
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
;
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
85 Sets the background color using Fl::background().
87 \li -bg2 color or -background2 color
89 Sets the secondary background color using Fl::background2().
93 Sets the X display to use; this option is silently
94 ignored under WIN32 and MacOS.
98 Enables or disables drag and drop text operations
99 using Fl::dnd_text_ops().
101 \li -fg color or -foreground color
103 Sets the foreground color using Fl::foreground().
105 \li -geometry WxH+X+Y
107 Sets the initial window position and size according
108 to the standard X geometry string.
112 Iconifies the window using Fl_Window::iconize().
116 Enables or disables visible keyboard focus for
117 non-text widgets using Fl::visible_focus().
121 Sets the window class using Fl_Window::xclass().
125 Sets the widget scheme using Fl::scheme().
129 Sets the window title using Fl_Window::label().
131 \li -tooltips and -notooltips
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
) {
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
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")) {
158 } else if (fl_match(s
, "kbd")) {
159 Fl::visible_focus(1);
162 } else if (fl_match(s
, "nokbd", 3)) {
163 Fl::visible_focus(0);
166 } else if (fl_match(s
, "dnd", 2)) {
170 } else if (fl_match(s
, "nodnd", 3)) {
174 } else if (fl_match(s
, "tooltips", 2)) {
175 Fl_Tooltip::enable();
178 } else if (fl_match(s
, "notooltips", 3)) {
179 Fl_Tooltip::disable();
186 // The Finder application in MacOS X passes the "-psn_N_NNNNN" option
188 else if (strncmp(s
, "psn_", 4) == 0) {
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;
205 #if !defined(WIN32) && !defined(__APPLE__)
206 } else if (fl_match(s
, "display", 2)) {
210 } else if (fl_match(s
, "title", 2)) {
213 } else if (fl_match(s
, "name", 2)) {
216 } else if (fl_match(s
, "bg2", 3) || fl_match(s
, "background2", 11)) {
219 } else if (fl_match(s
, "bg", 2) || fl_match(s
, "background", 10)) {
222 } else if (fl_match(s
, "fg", 2) || fl_match(s
, "foreground", 10)) {
225 } else if (fl_match(s
, "scheme", 1)) {
228 } else return 0; // unrecognized
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.
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).
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
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
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
) {
292 i
= 1; // skip argv[0]
294 if (cb
&& cb(argc
,argv
,i
)) continue;
295 if (!arg(argc
,argv
,i
)) return return_i
? i
: 0;
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
;
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
);
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.
361 #if !defined(WIN32) && !defined(__APPLE__)
362 // set the command string, used by state-saving window managers:
364 int n
=0; for (j
=0; j
<argc
; j
++) n
+= strlen(argv
[j
])+1;
365 char *buffer
= new char[n
];
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);
371 #endif // !WIN32 && !__APPLE__
374 // Calls useful for simple demo programs, with automatic help message:
376 static const char * const helpmsg
=
380 " -di[splay] host:n.n\n"
383 " -g[eometry] WxH+X+Y\n"
386 " -na[me] classname\n"
390 " -s[cheme] scheme\n"
391 " -ti[tle] windowtitle\n"
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;
446 else if (*string
== '-') {
450 for (; (*string
>= '0') && (*string
<= '9'); string
++) {
451 Result
= (Result
* 10) + (*string
- '0');
453 *NextString
= string
;
460 int XParseGeometry(const char* string
, int* x
, int* y
,
461 unsigned int* width
, unsigned int* height
)
464 register char *strind
;
465 unsigned int tempWidth
= 0, tempHeight
= 0;
466 int tempX
= 0, tempY
= 0;
469 if ( (string
== NULL
) || (*string
== '\0')) return(mask
);
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
)
478 strind
= nextCharacter
;
482 if (*strind
== 'x' || *strind
== 'X') {
484 tempHeight
= ReadInteger(strind
, &nextCharacter
);
485 if (strind
== nextCharacter
)
487 strind
= nextCharacter
;
491 if ((*strind
== '+') || (*strind
== '-')) {
492 if (*strind
== '-') {
494 tempX
= -ReadInteger(strind
, &nextCharacter
);
495 if (strind
== nextCharacter
)
497 strind
= nextCharacter
;
502 tempX
= ReadInteger(strind
, &nextCharacter
);
503 if (strind
== nextCharacter
)
505 strind
= nextCharacter
;
508 if ((*strind
== '+') || (*strind
== '-')) {
509 if (*strind
== '-') {
511 tempY
= -ReadInteger(strind
, &nextCharacter
);
512 if (strind
== nextCharacter
)
514 strind
= nextCharacter
;
519 tempY
= ReadInteger(strind
, &nextCharacter
);
520 if (strind
== nextCharacter
)
522 strind
= nextCharacter
;
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);
537 if (mask
& WidthValue
)
539 if (mask
& HeightValue
)
540 *height
= tempHeight
;
544 #endif // ifdef WIN32
547 // End of "$Id: Fl_arg.cxx 7903 2010-11-28 21:06:39Z matt $".