Panda3D

programBase.cxx

00001 // Filename: programBase.cxx
00002 // Created by:  drose (13Feb00)
00003 //
00004 ////////////////////////////////////////////////////////////////////
00005 //
00006 // PANDA 3D SOFTWARE
00007 // Copyright (c) Carnegie Mellon University.  All rights reserved.
00008 //
00009 // All use of this software is subject to the terms of the revised BSD
00010 // license.  You should have received a copy of this license along
00011 // with this source code in a file named "LICENSE."
00012 //
00013 ////////////////////////////////////////////////////////////////////
00014 
00015 #include "programBase.h"
00016 #include "wordWrapStream.h"
00017 
00018 #include "pnmFileTypeRegistry.h"
00019 #include "indent.h"
00020 #include "dSearchPath.h"
00021 #include "coordinateSystem.h"
00022 #include "dconfig.h"
00023 #include "config_dconfig.h"
00024 #include "string_utils.h"
00025 #include "vector_string.h"
00026 #include "configVariableInt.h"
00027 #include "configVariableBool.h"
00028 
00029 #include <stdlib.h>
00030 #include <algorithm>
00031 #include <ctype.h>
00032 
00033 // If our system getopt() doesn't come with getopt_long_only(), then use
00034 // the GNU flavor that we've got in tool for this purpose.
00035 #ifndef HAVE_GETOPT_LONG_ONLY
00036   #include "gnu_getopt.h"
00037 #else
00038   #include <getopt.h>
00039 #endif
00040 
00041 // This manifest is defined if we are running on a system (e.g. most
00042 // any Unix) that allows us to determine the width of the terminal
00043 // screen via an ioctl() call.  It's just handy to know for formatting
00044 // output nicely for the user.
00045 #ifdef IOCTL_TERMINAL_WIDTH
00046   #include <termios.h>
00047   #ifndef TIOCGWINSZ
00048     #include <sys/ioctl.h>
00049   #elif __APPLE__
00050     #include <sys/ioctl.h>
00051   #endif  // TIOCGWINSZ
00052 #endif  // IOCTL_TERMINAL_WIDTH
00053 
00054 bool ProgramBase::SortOptionsByIndex::
00055 operator () (const Option *a, const Option *b) const {
00056   if (a->_index_group != b->_index_group) {
00057     return a->_index_group < b->_index_group;
00058   }
00059   return a->_sequence < b->_sequence;
00060 }
00061 
00062 // This should be called at program termination just to make sure
00063 // Notify gets properly flushed before we exit, if someone calls
00064 // exit().  It's probably not necessary, but why not be phobic about
00065 // it?
00066 static void flush_nout() {
00067   nout << flush;
00068 }
00069 
00070 static ConfigVariableInt default_terminal_width
00071 ("default-terminal-width", 72,
00072  PRC_DESC("Specify the column at which to wrap output lines "
00073           "from pandatool-based programs, if it cannot be determined "
00074           "automatically."));
00075 
00076 static ConfigVariableBool use_terminal_width
00077 ("use-terminal-width", true,
00078  PRC_DESC("True to try to determine the terminal width automatically from "
00079           "the operating system, if supported; false to use the width "
00080           "specified by default-terminal-width even if the operating system "
00081           "appears to report a valid width."));
00082 
00083 ////////////////////////////////////////////////////////////////////
00084 //     Function: ProgramBase::Constructor
00085 //       Access: Public
00086 //  Description:
00087 ////////////////////////////////////////////////////////////////////
00088 ProgramBase::
00089 ProgramBase() {
00090   // Set up Notify to write output to our own formatted stream.
00091   Notify::ptr()->set_ostream_ptr(new WordWrapStream(this), true);
00092 
00093   // And we'll want to be sure to flush that in all normal exit cases.
00094   atexit(&flush_nout);
00095 
00096   _path_replace = new PathReplace;
00097 
00098   // If a program never adds the path store options, the default path
00099   // store is PS_absolute.  This is the most robust solution for
00100   // programs that read files but do not need to write them.
00101   _path_replace->_path_store = PS_absolute;
00102   _got_path_store = false;
00103   _got_path_directory = false;
00104 
00105   _next_sequence = 0;
00106   _sorted_options = false;
00107   _last_newline = false;
00108   _got_terminal_width = false;
00109   _got_option_indent = false;
00110 
00111   add_option("h", "", 100,
00112              "Display this help page.",
00113              &ProgramBase::handle_help_option, NULL, (void *)this);
00114 
00115   // It's nice to start with a blank line.
00116   nout << "\r";
00117 }
00118 
00119 ////////////////////////////////////////////////////////////////////
00120 //     Function: ProgramBase::Destructor
00121 //       Access: Public, Virtual
00122 //  Description:
00123 ////////////////////////////////////////////////////////////////////
00124 ProgramBase::
00125 ~ProgramBase() {
00126   // Reset Notify in case any messages get sent after our
00127   // destruction--our stream is no longer valid.
00128   Notify::ptr()->set_ostream_ptr(NULL, false);
00129 }
00130 
00131 ////////////////////////////////////////////////////////////////////
00132 //     Function: ProgramBase::show_description
00133 //       Access: Public
00134 //  Description: Writes the program description to stderr.
00135 ////////////////////////////////////////////////////////////////////
00136 void ProgramBase::
00137 show_description() {
00138   nout << _description << "\n";
00139 }
00140 
00141 ////////////////////////////////////////////////////////////////////
00142 //     Function: ProgramBase::show_usage
00143 //       Access: Public
00144 //  Description: Writes the usage line(s) to stderr.
00145 ////////////////////////////////////////////////////////////////////
00146 void ProgramBase::
00147 show_usage() {
00148   nout << "\rUsage:\n";
00149   Runlines::const_iterator ri;
00150   string prog = "  " +_program_name.get_basename_wo_extension();
00151 
00152   for (ri = _runlines.begin(); ri != _runlines.end(); ++ri) {
00153     show_text(prog, prog.length() + 1, *ri);
00154   }
00155   nout << "\r";
00156 }
00157 
00158 ////////////////////////////////////////////////////////////////////
00159 //     Function: ProgramBase::show_options
00160 //       Access: Public
00161 //  Description: Describes each of the available options to stderr.
00162 ////////////////////////////////////////////////////////////////////
00163 void ProgramBase::
00164 show_options() {
00165   sort_options();
00166   if (!_got_option_indent) {
00167     get_terminal_width();
00168     _option_indent = min(15, (int)(_terminal_width * 0.25));
00169     _got_option_indent = true;
00170   }
00171 
00172   nout << "Options:\n";
00173   OptionsByIndex::const_iterator oi;
00174   for (oi = _options_by_index.begin(); oi != _options_by_index.end(); ++oi) {
00175     const Option &opt = *(*oi);
00176     string prefix = "  -" + opt._option + " " + opt._parm_name;
00177     show_text(prefix, _option_indent, opt._description + "\r");
00178   }
00179 }
00180 
00181 ////////////////////////////////////////////////////////////////////
00182 //     Function: ProgramBase::show_text
00183 //       Access: Public
00184 //  Description: Formats the indicated text and its prefix for output
00185 //               to stderr with the known _terminal_width.
00186 ////////////////////////////////////////////////////////////////////
00187 void ProgramBase::
00188 show_text(const string &prefix, int indent_width, string text) {
00189   get_terminal_width();
00190 
00191   // This is correct!  It goes go to cerr, not to nout.  Sending it to
00192   // nout would be cyclic, since nout is redefined to map back through
00193   // this function.
00194   format_text(cerr, _last_newline,
00195               prefix, indent_width, text, _terminal_width);
00196 }
00197 
00198 ////////////////////////////////////////////////////////////////////
00199 //     Function: ProgramBase::parse_command_line
00200 //       Access: Public, Virtual
00201 //  Description: Dispatches on each of the options on the command
00202 //               line, and passes the remaining parameters to
00203 //               handle_args().  If an error on the command line is
00204 //               detected, will automatically call show_usage() and
00205 //               exit(1).
00206 ////////////////////////////////////////////////////////////////////
00207 void ProgramBase::
00208 parse_command_line(int argc, char *argv[]) {
00209 
00210 
00211   // Setting this variable to zero reinitializes the options parser
00212   // This is only necessary for processing multiple command lines in
00213   // the same program (mainly the MaxToEgg converter plugin)
00214   extern int optind;
00215   optind = 0;
00216 
00217 
00218   _program_name = Filename::from_os_specific(argv[0]);
00219   int i;
00220   for (i = 1; i < argc; i++) {
00221     _program_args.push_back(argv[i]);
00222   }
00223 
00224   // Build up the long options list and the short options string for
00225   // getopt_long_only().
00226   pvector<struct option> long_options;
00227   string short_options;
00228 
00229   // We also need to build a temporary map of int index numbers to
00230   // Option pointers.  We'll pass these index numbers to GNU's
00231   // getopt_long() so we can tell one option from another.
00232   typedef pmap<int, const Option *> Options;
00233   Options options;
00234 
00235   OptionsByName::const_iterator oi;
00236   int next_index = 256;
00237 
00238   // Let's prefix the option string with "-" to tell GNU getopt that
00239   // we want it to tell us the post-option arguments, instead of
00240   // trying to meddle with ARGC and ARGV (which we aren't using
00241   // directly).
00242   short_options = "-";
00243 
00244   for (oi = _options_by_name.begin(); oi != _options_by_name.end(); ++oi) {
00245     const Option &opt = (*oi).second;
00246 
00247     int index;
00248     if (opt._option.length() == 1) {
00249       // This is a "short" option; its option string consists of only
00250       // one letter.  Its index is the letter itself.
00251       index = (int)opt._option[0];
00252 
00253       short_options += opt._option;
00254       if (!opt._parm_name.empty()) {
00255         // This option takes an argument.
00256         short_options += ':';
00257       }
00258     } else {
00259       // This is a "long" option; we'll assign it the next available
00260       // index.
00261       index = ++next_index;
00262     }
00263 
00264     // Now add it to the GNU data structures.
00265     struct option gopt;
00266     gopt.name = (char *)opt._option.c_str();
00267     gopt.has_arg = (opt._parm_name.empty()) ?
00268       no_argument : required_argument;
00269     gopt.flag = (int *)NULL;
00270 
00271     // Return an index into the _options_by_index array, offset by 256
00272     // so we don't confuse it with '?'.
00273     gopt.val = index;
00274 
00275     long_options.push_back(gopt);
00276 
00277     options[index] = &opt;
00278   }
00279 
00280   // Finally, add one more structure, all zeroes, to indicate the end
00281   // of the options.
00282   struct option gopt;
00283   memset(&gopt, 0, sizeof(gopt));
00284   long_options.push_back(gopt);
00285 
00286   // We'll use this vector to save the non-option arguments.
00287   // Generally, these will all be at the end, but with the GNU
00288   // extensions, they need not be.
00289   Args remaining_args;
00290 
00291   // Now call getopt_long() to actually parse the arguments.
00292   extern char *optarg;
00293   const struct option *long_opts = &long_options[0];
00294 
00295   int flag =
00296     getopt_long_only(argc, argv, short_options.c_str(), long_opts, NULL);
00297   while (flag != EOF) {
00298     string arg;
00299     if (optarg != NULL) {
00300       arg = optarg;
00301     }
00302 
00303     switch (flag) {
00304     case '?':
00305       // Invalid option or parameter.
00306       show_usage();
00307       exit(1);
00308 
00309     case '\x1':
00310       // A special return value from getopt() indicating a non-option
00311       // argument.
00312       remaining_args.push_back(arg);
00313       break;
00314 
00315     default:
00316       {
00317         // A normal option.  Figure out which one it is.
00318         Options::const_iterator ii;
00319         ii = options.find(flag);
00320         if (ii == options.end()) {
00321           nout << "Internal error!  Invalid option index returned.\n";
00322           abort();
00323         }
00324 
00325         const Option &opt = *(*ii).second;
00326         bool okflag = true;
00327         if (opt._option_function != (OptionDispatchFunction)NULL) {
00328           okflag = (*opt._option_function)(opt._option, arg, opt._option_data);
00329         }
00330         if (opt._option_method != (OptionDispatchMethod)NULL) {
00331           okflag = (*opt._option_method)(this, opt._option, arg, opt._option_data);
00332         }
00333         if (opt._bool_var != (bool *)NULL) {
00334           (*opt._bool_var) = true;
00335         }
00336 
00337         if (!okflag) {
00338           show_usage();
00339           exit(1);
00340         }
00341       }
00342     }
00343 
00344     flag =
00345       getopt_long_only(argc, argv, short_options.c_str(), long_opts, NULL);
00346   }
00347 
00348   if (!handle_args(remaining_args)) {
00349     show_usage();
00350     exit(1);
00351   }
00352 
00353   if (!post_command_line()) {
00354     show_usage();
00355     exit(1);
00356   }
00357 }
00358 
00359 ////////////////////////////////////////////////////////////////////
00360 //     Function: ProgramBase::get_exec_command
00361 //       Access: Public
00362 //  Description: Returns the command that invoked this program, as a
00363 //               shell-friendly string, suitable for pasting into the
00364 //               comments of output files.
00365 ////////////////////////////////////////////////////////////////////
00366 string ProgramBase::
00367 get_exec_command() const {
00368   string command;
00369 
00370   command = _program_name.get_basename_wo_extension();
00371   Args::const_iterator ai;
00372   for (ai = _program_args.begin(); ai != _program_args.end(); ++ai) {
00373     const string &arg = (*ai);
00374 
00375     // First, check to see if the string is shell-acceptable.
00376     bool legal = true;
00377     string::const_iterator si;
00378     for (si = arg.begin(); legal && si != arg.end(); ++si) {
00379       switch (*si) {
00380       case ' ':
00381       case '\n':
00382       case '\t':
00383       case '*':
00384       case '?':
00385       case '\\':
00386       case '(':
00387       case ')':
00388       case '|':
00389       case '&':
00390       case '<':
00391       case '>':
00392       case '"':
00393       case ';':
00394       case '$':
00395         legal = false;
00396       }
00397     }
00398 
00399     if (legal) {
00400       command += " " + arg;
00401     } else {
00402       command += " '" + arg + "'";
00403     }
00404   }
00405 
00406   return command;
00407 }
00408 
00409 
00410 ////////////////////////////////////////////////////////////////////
00411 //     Function: ProgramBase::handle_args
00412 //       Access: Protected, Virtual
00413 //  Description: Does something with the additional arguments on the
00414 //               command line (after all the -options have been
00415 //               parsed).  Returns true if the arguments are good,
00416 //               false otherwise.
00417 ////////////////////////////////////////////////////////////////////
00418 bool ProgramBase::
00419 handle_args(ProgramBase::Args &args) {
00420   if (!args.empty()) {
00421     nout << "Unexpected arguments on command line:\n";
00422     Args::const_iterator ai;
00423     for (ai = args.begin(); ai != args.end(); ++ai) {
00424       nout << (*ai) << " ";
00425     }
00426     nout << "\r";
00427     return false;
00428   }
00429 
00430   return true;
00431 }
00432 
00433 ////////////////////////////////////////////////////////////////////
00434 //     Function: ProgramBase::post_command_line
00435 //       Access: Protected, Virtual
00436 //  Description: This is called after the command line has been
00437 //               completely processed, and it gives the program a
00438 //               chance to do some last-minute processing and
00439 //               validation of the options and arguments.  It should
00440 //               return true if everything is fine, false if there is
00441 //               an error.
00442 ////////////////////////////////////////////////////////////////////
00443 bool ProgramBase::
00444 post_command_line() {
00445   return true;
00446 }
00447 
00448 ////////////////////////////////////////////////////////////////////
00449 //     Function: ProgramBase::set_program_description
00450 //       Access: Protected
00451 //  Description: Sets the description of the program that will be
00452 //               reported by show_usage().  The description should be
00453 //               one long string of text.  Embedded newline characters
00454 //               are interpreted as paragraph breaks and printed as
00455 //               blank lines.
00456 ////////////////////////////////////////////////////////////////////
00457 void ProgramBase::
00458 set_program_description(const string &description) {
00459   _description = description;
00460 }
00461 
00462 ////////////////////////////////////////////////////////////////////
00463 //     Function: ProgramBase::clear_runlines
00464 //       Access: Protected
00465 //  Description: Removes all of the runlines that were previously
00466 //               added, presumably before adding some new ones.
00467 ////////////////////////////////////////////////////////////////////
00468 void ProgramBase::
00469 clear_runlines() {
00470   _runlines.clear();
00471 }
00472 
00473 ////////////////////////////////////////////////////////////////////
00474 //     Function: ProgramBase::add_runline
00475 //       Access: Protected
00476 //  Description: Adds an additional line to the list of lines that
00477 //               will be displayed to describe briefly how the program
00478 //               is to be run.  Each line should be something like
00479 //               "[opts] arg1 arg2", that is, it does *not* include
00480 //               the name of the program, but it includes everything
00481 //               that should be printed after the name of the program.
00482 //
00483 //               Normally there is only one runline for a given
00484 //               program, but it is possible to define more than one.
00485 ////////////////////////////////////////////////////////////////////
00486 void ProgramBase::
00487 add_runline(const string &runline) {
00488   _runlines.push_back(runline);
00489 }
00490 
00491 ////////////////////////////////////////////////////////////////////
00492 //     Function: ProgramBase::clear_options
00493 //       Access: Protected
00494 //  Description: Removes all of the options that were previously
00495 //               added, presumably before adding some new ones.
00496 //               Normally you wouldn't want to do this unless you want
00497 //               to completely replace all of the options defined by
00498 //               base classes.
00499 ////////////////////////////////////////////////////////////////////
00500 void ProgramBase::
00501 clear_options() {
00502   _options_by_name.clear();
00503 }
00504 
00505 ////////////////////////////////////////////////////////////////////
00506 //     Function: ProgramBase::add_option
00507 //       Access: Protected
00508 //  Description: Adds (or redefines) a command line option.  When
00509 //               parse_command_line() is executed it will look for
00510 //               these options (followed by a hyphen) on the command
00511 //               line; when a particular option is found it will call
00512 //               the indicated option_function, supplying the provided
00513 //               option_data.  This allows the user to define a
00514 //               function that does some special behavior for any
00515 //               given option, or to use any of a number of generic
00516 //               pre-defined functions to fill in data for each
00517 //               option.
00518 //
00519 //               Each option may or may not take a parameter.  If
00520 //               parm_name is nonempty, it is assumed that the option
00521 //               does take a parameter (and parm_name contains the
00522 //               name that will be printed by show_options()).  This
00523 //               parameter will be supplied as the second parameter to
00524 //               the dispatch function.  If parm_name is empty, it is
00525 //               assumed that the option does not take a parameter.
00526 //               There is no provision for optional parameters.
00527 //
00528 //               The options are listed first in order by their
00529 //               index_group number, and then in the order that
00530 //               add_option() was called.  This provides a mechanism
00531 //               for listing the options defined in derived classes
00532 //               before those of the base classes.
00533 ////////////////////////////////////////////////////////////////////
00534 void ProgramBase::
00535 add_option(const string &option, const string &parm_name,
00536            int index_group, const string &description,
00537            OptionDispatchFunction option_function,
00538            bool *bool_var, void *option_data) {
00539   Option opt;
00540   opt._option = option;
00541   opt._parm_name = parm_name;
00542   opt._index_group = index_group;
00543   opt._sequence = ++_next_sequence;
00544   opt._description = description;
00545   opt._option_function = option_function;
00546   opt._option_method = (OptionDispatchMethod)NULL;
00547   opt._bool_var = bool_var;
00548   opt._option_data = option_data;
00549 
00550   _options_by_name[option] = opt;
00551   _sorted_options = false;
00552 
00553   if (bool_var != (bool *)NULL) {
00554     (*bool_var) = false;
00555   }
00556 }
00557 
00558 ////////////////////////////////////////////////////////////////////
00559 //     Function: ProgramBase::add_option
00560 //       Access: Protected
00561 //  Description: This is another variant on add_option(), above,
00562 //               except that it receives a pointer to a "method",
00563 //               which is really just another static (or global)
00564 //               function, whose first parameter is a ProgramBase *.
00565 //
00566 //               We can't easily add a variant that accepts a real
00567 //               method, because the C++ syntax for methods requires
00568 //               us to know exactly what class object the method is
00569 //               defined for, and we want to support adding pointers
00570 //               for methods that are defined in other classes.  So we
00571 //               have this hacky thing, which requires the "method" to
00572 //               be declared static, and receive its this pointer
00573 //               explicitly, as the first argument.
00574 ////////////////////////////////////////////////////////////////////
00575 void ProgramBase::
00576 add_option(const string &option, const string &parm_name,
00577            int index_group, const string &description,
00578            OptionDispatchMethod option_method,
00579            bool *bool_var, void *option_data) {
00580   Option opt;
00581   opt._option = option;
00582   opt._parm_name = parm_name;
00583   opt._index_group = index_group;
00584   opt._sequence = ++_next_sequence;
00585   opt._description = description;
00586   opt._option_function = (OptionDispatchFunction)NULL;
00587   opt._option_method = option_method;
00588   opt._bool_var = bool_var;
00589   opt._option_data = option_data;
00590 
00591   _options_by_name[option] = opt;
00592   _sorted_options = false;
00593 
00594   if (bool_var != (bool *)NULL) {
00595     (*bool_var) = false;
00596   }
00597 }
00598 
00599 ////////////////////////////////////////////////////////////////////
00600 //     Function: ProgramBase::redescribe_option
00601 //       Access: Protected
00602 //  Description: Changes the description associated with a
00603 //               previously-defined option.  Returns true if the
00604 //               option was changed, false if it hadn't been defined.
00605 ////////////////////////////////////////////////////////////////////
00606 bool ProgramBase::
00607 redescribe_option(const string &option, const string &description) {
00608   OptionsByName::iterator oi = _options_by_name.find(option);
00609   if (oi == _options_by_name.end()) {
00610     return false;
00611   }
00612   (*oi).second._description = description;
00613   return true;
00614 }
00615 
00616 ////////////////////////////////////////////////////////////////////
00617 //     Function: ProgramBase::remove_option
00618 //       Access: Protected
00619 //  Description: Removes a previously-defined option.  Returns true if
00620 //               the option was removed, false if it hadn't existed.
00621 ////////////////////////////////////////////////////////////////////
00622 bool ProgramBase::
00623 remove_option(const string &option) {
00624   OptionsByName::iterator oi = _options_by_name.find(option);
00625   if (oi == _options_by_name.end()) {
00626     return false;
00627   }
00628   _options_by_name.erase(oi);
00629   _sorted_options = false;
00630   return true;
00631 }
00632 
00633 ////////////////////////////////////////////////////////////////////
00634 //     Function: ProgramBase::add_path_replace_options
00635 //       Access: Public
00636 //  Description: Adds -pr etc. as valid options for this program.
00637 //               These are appropriate for a model converter or model
00638 //               reader type program, and specify how to locate
00639 //               possibly-invalid pathnames in the source model file.
00640 ////////////////////////////////////////////////////////////////////
00641 void ProgramBase::
00642 add_path_replace_options() {
00643   add_option
00644     ("pr", "path_replace", 40,
00645      "Sometimes references to other files (textures, external references) "
00646      "are stored with a full path that is appropriate for some other system, "
00647      "but does not exist here.  This option may be used to specify how "
00648      "those invalid paths map to correct paths.  Generally, this is of "
00649      "the form 'orig_prefix=replacement_prefix', which indicates a "
00650      "particular initial sequence of characters that should be replaced "
00651      "with a new sequence; e.g. '/c/home/models=/beta/fish'.  "
00652      "If the replacement prefix does not begin with a slash, the file "
00653      "will then be searched for along the search path specified by -pp.  "
00654      "You may use standard filename matching characters ('*', '?', etc.) in "
00655      "the original prefix, and '**' as a component by itself stands for "
00656      "any number of components.\n\n"
00657 
00658      "This option may be repeated as necessary; each file will be tried "
00659      "against each specified method, in the order in which they appear in "
00660      "the command line, until the file is found.  If the file is not found, "
00661      "the last matching prefix is used anyway.",
00662      &ProgramBase::dispatch_path_replace, NULL, _path_replace.p());
00663 
00664   add_option
00665     ("pp", "dirname", 40,
00666      "Adds the indicated directory name to the list of directories to "
00667      "search for filenames referenced by the source file.  This is used "
00668      "only for relative paths, or for paths that are made relative by a "
00669      "-pr replacement string that doesn't begin with a leading slash.  "
00670      "The model-path is always implicitly searched anyway.",
00671      &ProgramBase::dispatch_search_path, NULL, &(_path_replace->_path));
00672 }
00673 
00674 ////////////////////////////////////////////////////////////////////
00675 //     Function: ProgramBase::add_path_store_options
00676 //       Access: Public
00677 //  Description: Adds -ps etc. as valid options for this program.
00678 //               These are appropriate for a model converter type
00679 //               program, and specify how to represent filenames in
00680 //               the output file.
00681 ////////////////////////////////////////////////////////////////////
00682 void ProgramBase::
00683 add_path_store_options() {
00684   // If a program has path store options at all, the default path
00685   // store is relative.
00686   _path_replace->_path_store = PS_relative;
00687 
00688   add_option
00689     ("ps", "path_store", 40,
00690      "Specifies the way an externally referenced file is to be "
00691      "represented in the resulting output file.  This "
00692      "assumes the named filename actually exists; "
00693      "see -pr to indicate how to deal with external "
00694      "references that have bad pathnames.  "
00695      "This option will not help you to find a missing file, but simply "
00696      "controls how filenames are represented in the output.\n\n"
00697 
00698      "The option may be one of: rel, abs, rel_abs, strip, or keep.  If "
00699      "either rel or rel_abs is specified, the files are made relative to "
00700      "the directory specified by -pd.  The default is rel.",
00701      &ProgramBase::dispatch_path_store, &_got_path_store, 
00702      &(_path_replace->_path_store));
00703 
00704   add_option
00705     ("pd", "path_directory", 40,
00706      "Specifies the name of a directory to make paths relative to, if "
00707      "'-ps rel' or '-ps rel_abs' is specified.  If this is omitted, the "
00708      "directory name is taken from the name of the output file.",
00709      &ProgramBase::dispatch_filename, &_got_path_directory, 
00710      &(_path_replace->_path_directory));
00711 }
00712 
00713 ////////////////////////////////////////////////////////////////////
00714 //     Function: ProgramBase::dispatch_none
00715 //       Access: Protected, Static
00716 //  Description: Standard dispatch function for an option that takes
00717 //               no parameters, and does nothing special.  Typically
00718 //               this would be used for a boolean flag, whose presence
00719 //               means something and whose absence means something
00720 //               else.  Use the bool_var parameter to add_option() to
00721 //               determine whether the option appears on the command
00722 //               line or not.
00723 ////////////////////////////////////////////////////////////////////
00724 bool ProgramBase::
00725 dispatch_none(const string &, const string &, void *) {
00726   return true;
00727 }
00728 
00729 ////////////////////////////////////////////////////////////////////
00730 //     Function: ProgramBase::dispatch_true
00731 //       Access: Protected, Static
00732 //  Description: Standard dispatch function for an option that takes
00733 //               no parameters, and when it is present sets a bool
00734 //               variable to the 'true' value.  This is another way to
00735 //               handle a boolean flag.  See also dispatch_none() and
00736 //               dispatch_false().
00737 //
00738 //               The data pointer is to a bool variable.
00739 ////////////////////////////////////////////////////////////////////
00740 bool ProgramBase::
00741 dispatch_true(const string &, const string &, void *var) {
00742   bool *bp = (bool *)var;
00743   (*bp) = true;
00744   return true;
00745 }
00746 
00747 ////////////////////////////////////////////////////////////////////
00748 //     Function: ProgramBase::dispatch_false
00749 //       Access: Protected, Static
00750 //  Description: Standard dispatch function for an option that takes
00751 //               no parameters, and when it is present sets a bool
00752 //               variable to the 'false' value.  This is another way to
00753 //               handle a boolean flag.  See also dispatch_none() and
00754 //               dispatch_true().
00755 //
00756 //               The data pointer is to a bool variable.
00757 ////////////////////////////////////////////////////////////////////
00758 bool ProgramBase::
00759 dispatch_false(const string &, const string &, void *var) {
00760   bool *bp = (bool *)var;
00761   (*bp) = false;
00762   return true;
00763 }
00764 
00765 ////////////////////////////////////////////////////////////////////
00766 //     Function: ProgramBase::dispatch_count
00767 //       Access: Protected, Static
00768 //  Description: Standard dispatch function for an option that takes
00769 //               no parameters, but whose presence on the command line
00770 //               increments an integer counter for each time it
00771 //               appears.  -v is often an option that works this way.
00772 //               The data pointer is to an int counter variable.
00773 ////////////////////////////////////////////////////////////////////
00774 bool ProgramBase::
00775 dispatch_count(const string &, const string &, void *var) {
00776   int *ip = (int *)var;
00777   (*ip)++;
00778 
00779   return true;
00780 }
00781 
00782 ////////////////////////////////////////////////////////////////////
00783 //     Function: ProgramBase::dispatch_int
00784 //       Access: Protected, Static
00785 //  Description: Standard dispatch function for an option that takes
00786 //               one parameter, which is to be interpreted as an
00787 //               integer.  The data pointer is to an int variable.
00788 ////////////////////////////////////////////////////////////////////
00789 bool ProgramBase::
00790 dispatch_int(const string &opt, const string &arg, void *var) {
00791   int *ip = (int *)var;
00792 
00793   if (!string_to_int(arg, *ip)) {
00794     nout << "Invalid integer parameter for -" << opt << ": "
00795          << arg << "\n";
00796     return false;
00797   }
00798 
00799   return true;
00800 }
00801 
00802 ////////////////////////////////////////////////////////////////////
00803 //     Function: ProgramBase::dispatch_int_pair
00804 //       Access: Protected, Static
00805 //  Description: Standard dispatch function for an option that takes
00806 //               a pair of integer parameters.  The data pointer is to
00807 //               an array of two integers.
00808 ////////////////////////////////////////////////////////////////////
00809 bool ProgramBase::
00810 dispatch_int_pair(const string &opt, const string &arg, void *var) {
00811   int *ip = (int *)var;
00812 
00813   vector_string words;
00814   tokenize(arg, words, ",");
00815 
00816   bool okflag = false;
00817   if (words.size() == 2) {
00818     okflag =
00819       string_to_int(words[0], ip[0]) &&
00820       string_to_int(words[1], ip[1]);
00821   }
00822 
00823   if (!okflag) {
00824     nout << "-" << opt
00825          << " requires a pair of integers separated by a comma.\n";
00826     return false;
00827   }
00828 
00829   return true;
00830 }
00831 
00832 ////////////////////////////////////////////////////////////////////
00833 //     Function: ProgramBase::dispatch_double
00834 //       Access: Protected, Static
00835 //  Description: Standard dispatch function for an option that takes
00836 //               one parameter, which is to be interpreted as a
00837 //               double.  The data pointer is to an double variable.
00838 ////////////////////////////////////////////////////////////////////
00839 bool ProgramBase::
00840 dispatch_double(const string &opt, const string &arg, void *var) {
00841   double *ip = (double *)var;
00842 
00843   if (!string_to_double(arg, *ip)) {
00844     nout << "Invalid numeric parameter for -" << opt << ": "
00845          << arg << "\n";
00846     return false;
00847   }
00848 
00849   return true;
00850 }
00851 
00852 ////////////////////////////////////////////////////////////////////
00853 //     Function: ProgramBase::dispatch_double_pair
00854 //       Access: Protected, Static
00855 //  Description: Standard dispatch function for an option that takes
00856 //               a pair of double parameters.  The data pointer is to
00857 //               an array of two doubles.
00858 ////////////////////////////////////////////////////////////////////
00859 bool ProgramBase::
00860 dispatch_double_pair(const string &opt, const string &arg, void *var) {
00861   double *ip = (double *)var;
00862 
00863   vector_string words;
00864   tokenize(arg, words, ",");
00865 
00866   bool okflag = false;
00867   if (words.size() == 2) {
00868     okflag =
00869       string_to_double(words[0], ip[0]) &&
00870       string_to_double(words[1], ip[1]);
00871   }
00872 
00873   if (!okflag) {
00874     nout << "-" << opt
00875          << " requires a pair of numbers separated by a comma.\n";
00876     return false;
00877   }
00878 
00879   return true;
00880 }
00881 
00882 ////////////////////////////////////////////////////////////////////
00883 //     Function: ProgramBase::dispatch_double_triple
00884 //       Access: Protected, Static
00885 //  Description: Standard dispatch function for an option that takes
00886 //               a triple of double parameters.  The data pointer is to
00887 //               an array of three doubles.
00888 ////////////////////////////////////////////////////////////////////
00889 bool ProgramBase::
00890 dispatch_double_triple(const string &opt, const string &arg, void *var) {
00891   double *ip = (double *)var;
00892 
00893   vector_string words;
00894   tokenize(arg, words, ",");
00895 
00896   bool okflag = false;
00897   if (words.size() == 3) {
00898     okflag =
00899       string_to_double(words[0], ip[0]) &&
00900       string_to_double(words[1], ip[1]) &&
00901       string_to_double(words[2], ip[2]);
00902   }
00903 
00904   if (!okflag) {
00905     nout << "-" << opt
00906          << " requires three numbers separated by commas.\n";
00907     return false;
00908   }
00909 
00910   return true;
00911 }
00912 
00913 ////////////////////////////////////////////////////////////////////
00914 //     Function: ProgramBase::dispatch_double_quad
00915 //       Access: Protected, Static
00916 //  Description: Standard dispatch function for an option that takes
00917 //               a quad of double parameters.  The data pointer is to
00918 //               an array of four doubles.
00919 ////////////////////////////////////////////////////////////////////
00920 bool ProgramBase::
00921 dispatch_double_quad(const string &opt, const string &arg, void *var) {
00922   double *ip = (double *)var;
00923 
00924   vector_string words;
00925   tokenize(arg, words, ",");
00926 
00927   bool okflag = false;
00928   if (words.size() == 4) {
00929     okflag =
00930       string_to_double(words[0], ip[0]) &&
00931       string_to_double(words[1], ip[1]) &&
00932       string_to_double(words[2], ip[2]) &&
00933       string_to_double(words[3], ip[3]);
00934   }
00935 
00936   if (!okflag) {
00937     nout << "-" << opt
00938          << " requires four numbers separated by commas.\n";
00939     return false;
00940   }
00941 
00942   return true;
00943 }
00944 
00945 ////////////////////////////////////////////////////////////////////
00946 //     Function: ProgramBase::dispatch_color
00947 //       Access: Protected, Static
00948 //  Description: Standard dispatch function for an option that takes a
00949 //               color, as l or l,a or r,g,b or r,g,b,a.  The data
00950 //               pointer is to an array of four floats, e.g. a Colorf.
00951 ////////////////////////////////////////////////////////////////////
00952 bool ProgramBase::
00953 dispatch_color(const string &opt, const string &arg, void *var) {
00954   float *ip = (float *)var;
00955 
00956   vector_string words;
00957   tokenize(arg, words, ",");
00958 
00959   bool okflag = false;
00960   switch (words.size()) {
00961   case 4:
00962     okflag =
00963       string_to_float(words[0], ip[0]) &&
00964       string_to_float(words[1], ip[1]) &&
00965       string_to_float(words[2], ip[2]) &&
00966       string_to_float(words[3], ip[3]);
00967     break;
00968 
00969   case 3:
00970     okflag =
00971       string_to_float(words[0], ip[0]) &&
00972       string_to_float(words[1], ip[1]) &&
00973       string_to_float(words[2], ip[2]);
00974     ip[3] = 1.0;
00975     break;
00976 
00977   case 2:
00978     okflag =
00979       string_to_float(words[0], ip[0]) &&
00980       string_to_float(words[1], ip[3]);
00981     ip[1] = ip[0];
00982     ip[2] = ip[0];
00983     break;
00984 
00985   case 1:
00986     okflag =
00987       string_to_float(words[0], ip[0]);
00988     ip[1] = ip[0];
00989     ip[2] = ip[0];
00990     ip[3] = 1.0;
00991     break;
00992   }
00993 
00994   if (!okflag) {
00995     nout << "-" << opt
00996          << " requires one through four numbers separated by commas.\n";
00997     return false;
00998   }
00999 
01000   return true;
01001 }
01002 
01003 ////////////////////////////////////////////////////////////////////
01004 //     Function: ProgramBase::dispatch_string
01005 //       Access: Protected, Static
01006 //  Description: Standard dispatch function for an option that takes
01007 //               one parameter, which is to be interpreted as a
01008 //               string.  The data pointer is to a string variable.
01009 ////////////////////////////////////////////////////////////////////
01010 bool ProgramBase::
01011 dispatch_string(const string &, const string &arg, void *var) {
01012   string *ip = (string *)var;
01013   (*ip) = arg;
01014 
01015   return true;
01016 }
01017 
01018 ////////////////////////////////////////////////////////////////////
01019 //     Function: ProgramBase::dispatch_vector_string
01020 //       Access: Protected, Static
01021 //  Description: Standard dispatch function for an option that takes
01022 //               one parameter, which is to be interpreted as a
01023 //               string.  This is different from dispatch_string in
01024 //               that the parameter may be repeated multiple times,
01025 //               and each time the string value is appended to a
01026 //               vector.
01027 //
01028 //               The data pointer is to a vector_string variable.
01029 ////////////////////////////////////////////////////////////////////
01030 bool ProgramBase::
01031 dispatch_vector_string(const string &, const string &arg, void *var) {
01032   vector_string *ip = (vector_string *)var;
01033   (*ip).push_back(arg);
01034 
01035   return true;
01036 }
01037 
01038 ////////////////////////////////////////////////////////////////////
01039 //     Function: ProgramBase::dispatch_vector_string_comma
01040 //       Access: Protected, Static
01041 //  Description: Similar to dispatch_vector_string, but a comma is
01042 //               allowed to separate multiple tokens in one argument,
01043 //               without having to repeat the argument for each token.
01044 //
01045 //               The data pointer is to a vector_string variable.
01046 ////////////////////////////////////////////////////////////////////
01047 bool ProgramBase::
01048 dispatch_vector_string_comma(const string &, const string &arg, void *var) {
01049   vector_string *ip = (vector_string *)var;
01050 
01051   vector_string words;
01052   tokenize(arg, words, ",");
01053 
01054   vector_string::const_iterator wi;
01055   for (wi = words.begin(); wi != words.end(); ++wi) {
01056     (*ip).push_back(*wi);
01057   }
01058 
01059   return true;
01060 }
01061 
01062 ////////////////////////////////////////////////////////////////////
01063 //     Function: ProgramBase::dispatch_filename
01064 //       Access: Protected, Static
01065 //  Description: Standard dispatch function for an option that takes
01066 //               one parameter, which is to be interpreted as a
01067 //               filename.  The data pointer is to a Filename variable.
01068 ////////////////////////////////////////////////////////////////////
01069 bool ProgramBase::
01070 dispatch_filename(const string &opt, const string &arg, void *var) {
01071   if (arg.empty()) {
01072     nout << "-" << opt << " requires a filename parameter.\n";
01073     return false;
01074   }
01075 
01076   Filename *ip = (Filename *)var;
01077   (*ip) = Filename::from_os_specific(arg);
01078 
01079   return true;
01080 }
01081 
01082 ////////////////////////////////////////////////////////////////////
01083 //     Function: ProgramBase::dispatch_search_path
01084 //       Access: Protected, Static
01085 //  Description: Standard dispatch function for an option that takes
01086 //               one parameter, which is to be interpreted as a
01087 //               single directory name to add to a search path.  The
01088 //               data pointer is to a DSearchPath variable.  This kind
01089 //               of option may appear multiple times on the command
01090 //               line; each time, the new directory is appended.
01091 ////////////////////////////////////////////////////////////////////
01092 bool ProgramBase::
01093 dispatch_search_path(const string &opt, const string &arg, void *var) {
01094   if (arg.empty()) {
01095     nout << "-" << opt << " requires a search path parameter.\n";
01096     return false;
01097   }
01098 
01099   DSearchPath *ip = (DSearchPath *)var;
01100   ip->append_directory(Filename::from_os_specific(arg));
01101 
01102   return true;
01103 }
01104 
01105 ////////////////////////////////////////////////////////////////////
01106 //     Function: ProgramBase::dispatch_coordinate_system
01107 //       Access: Protected, Static
01108 //  Description: Standard dispatch function for an option that takes
01109 //               one parameter, which is to be interpreted as a
01110 //               coordinate system string.  The data pointer is to a
01111 //               CoordinateSystem variable.
01112 ////////////////////////////////////////////////////////////////////
01113 bool ProgramBase::
01114 dispatch_coordinate_system(const string &opt, const string &arg, void *var) {
01115   CoordinateSystem *ip = (CoordinateSystem *)var;
01116   (*ip) = parse_coordinate_system_string(arg);
01117 
01118   if ((*ip) == CS_invalid) {
01119     nout << "Invalid coordinate system for -" << opt << ": " << arg << "\n"
01120          << "Valid coordinate system strings are any of 'y-up', 'z-up', "
01121       "'y-up-left', or 'z-up-left'.\n";
01122     return false;
01123   }
01124 
01125   return true;
01126 }
01127 
01128 ////////////////////////////////////////////////////////////////////
01129 //     Function: ProgramBase::dispatch_units
01130 //       Access: Protected, Static
01131 //  Description: Standard dispatch function for an option that takes
01132 //               one parameter, which is to be interpreted as a
01133 //               unit of distance measurement.  The data pointer is to
01134 //               a DistanceUnit variable.
01135 ////////////////////////////////////////////////////////////////////
01136 bool ProgramBase::
01137 dispatch_units(const string &opt, const string &arg, void *var) {
01138   DistanceUnit *ip = (DistanceUnit *)var;
01139   (*ip) = string_distance_unit(arg);
01140 
01141   if ((*ip) == DU_invalid) {
01142     nout << "Invalid units for -" << opt << ": " << arg << "\n"
01143          << "Valid units are mm, cm, m, km, yd, ft, in, nmi, and mi.\n";
01144     return false;
01145   }
01146 
01147   return true;
01148 }
01149 
01150 ////////////////////////////////////////////////////////////////////
01151 //     Function: ProgramBase::dispatch_image_type
01152 //       Access: Protected, Static
01153 //  Description: Standard dispatch function for an option that takes
01154 //               one parameter, which is to indicate an image file
01155 //               type, like rgb, bmp, jpg, etc.  The data pointer is
01156 //               to a PNMFileType pointer.
01157 ////////////////////////////////////////////////////////////////////
01158 bool ProgramBase::
01159 dispatch_image_type(const string &opt, const string &arg, void *var) {
01160   PNMFileType **ip = (PNMFileType **)var;
01161 
01162   PNMFileTypeRegistry *reg = PNMFileTypeRegistry::get_global_ptr();
01163 
01164   (*ip) = reg->get_type_from_extension(arg);
01165 
01166   if ((*ip) == (PNMFileType *)NULL) {
01167     nout << "Invalid image type for -" << opt << ": " << arg << "\n"
01168          << "The following image types are known:\n";
01169     reg->write(nout, 2);
01170     return false;
01171   }
01172 
01173   return true;
01174 }
01175 
01176 ////////////////////////////////////////////////////////////////////
01177 //     Function: ProgramBase::dispatch_path_replace
01178 //       Access: Protected, Static
01179 //  Description: Standard dispatch function for an option that takes
01180 //               one parameter, which is to be interpreted as a
01181 //               single component of a path replace request.  The data
01182 //               pointer is to a PathReplace variable.
01183 ////////////////////////////////////////////////////////////////////
01184 bool ProgramBase::
01185 dispatch_path_replace(const string &opt, const string &arg, void *var) {
01186   PathReplace *ip = (PathReplace *)var;
01187   size_t equals = arg.find('=');
01188   if (equals == string::npos) {
01189     nout << "Invalid path replacement string for -" << opt << ": " << arg << "\n"
01190          << "String should be of the form 'old-prefix=new-prefix'.\n";
01191     return false;
01192   }
01193   ip->add_pattern(arg.substr(0, equals), arg.substr(equals + 1));
01194 
01195   return true;
01196 }
01197 
01198 ////////////////////////////////////////////////////////////////////
01199 //     Function: ProgramBase::dispatch_path_store
01200 //       Access: Protected, Static
01201 //  Description: Standard dispatch function for an option that takes
01202 //               one parameter, which is to be interpreted as a
01203 //               path store string.  The data pointer is to a
01204 //               PathStore variable.
01205 ////////////////////////////////////////////////////////////////////
01206 bool ProgramBase::
01207 dispatch_path_store(const string &opt, const string &arg, void *var) {
01208   PathStore *ip = (PathStore *)var;
01209   (*ip) = string_path_store(arg);
01210 
01211   if ((*ip) == PS_invalid) {
01212     nout << "Invalid path store for -" << opt << ": " << arg << "\n"
01213          << "Valid path store strings are any of 'rel', 'abs', "
01214          << "'rel_abs', 'strip', or 'keep'.\n";
01215     return false;
01216   }
01217 
01218   return true;
01219 }
01220 
01221 ////////////////////////////////////////////////////////////////////
01222 //     Function: ProgramBase::handle_help_option
01223 //       Access: Protected, Static
01224 //  Description: Called when the user enters '-h', this describes how
01225 //               to use the program and then exits.
01226 ////////////////////////////////////////////////////////////////////
01227 bool ProgramBase::
01228 handle_help_option(const string &, const string &, void *data) {
01229   ProgramBase *me = (ProgramBase *)data;
01230   me->show_description();
01231   me->show_usage();
01232   me->show_options();
01233   exit(0);
01234 
01235   return false;
01236 }
01237 
01238 
01239 ////////////////////////////////////////////////////////////////////
01240 //     Function: ProgramBase::format_text
01241 //       Access: Protected, Static
01242 //  Description: Word-wraps the indicated text to the indicated output
01243 //               stream.  The first line is prefixed with the
01244 //               indicated prefix, then tabbed over to indent_width
01245 //               where the text actually begins.  A newline is
01246 //               inserted at or before column line_width.  Each
01247 //               subsequent line begins with indent_width spaces.
01248 //
01249 //               An embedded newline character ('\n') forces a line
01250 //               break, while an embedded carriage-return character
01251 //               ('\r'), or two or more consecutive newlines, marks a
01252 //               paragraph break, which is usually printed as a blank
01253 //               line.  Redundant newline and carriage-return
01254 //               characters are generally ignored.
01255 //
01256 //               The flag last_newline should be initialized to false
01257 //               for the first call to format_text, and then preserved
01258 //               for future calls; it tracks the state of trailing
01259 //               newline characters between calls so we can correctly
01260 //               identify doubled newlines.
01261 ////////////////////////////////////////////////////////////////////
01262 void ProgramBase::
01263 format_text(ostream &out, bool &last_newline,
01264             const string &prefix, int indent_width,
01265             const string &text, int line_width) {
01266   indent_width = min(indent_width, line_width - 20);
01267   int indent_amount = indent_width;
01268   bool initial_break = false;
01269 
01270   if (!prefix.empty()) {
01271     out << prefix;
01272     indent_amount = indent_width - prefix.length();
01273     if ((int)prefix.length() + 1 > indent_width) {
01274       out << "\n";
01275       initial_break = true;
01276       indent_amount = indent_width;
01277     }
01278   }
01279 
01280   size_t p = 0;
01281 
01282   // Skip any initial whitespace and newlines.
01283   while (p < text.length() && isspace(text[p])) {
01284     if (text[p] == '\r' ||
01285         (p > 0 && text[p] == '\n' && text[p - 1] == '\n') ||
01286         (p == 0 && text[p] == '\n' && last_newline)) {
01287       if (!initial_break) {
01288         // Here's an initial paragraph break, however.
01289         out << "\n";
01290         initial_break = true;
01291       }
01292       indent_amount = indent_width;
01293 
01294     } else if (text[p] == '\n') {
01295       // Largely ignore an initial newline.
01296       indent_amount = indent_width;
01297 
01298     } else if (text[p] == ' ') {
01299       // Do count up leading spaces.
01300       indent_amount++;
01301     }
01302     p++;
01303   }
01304 
01305   last_newline = (!text.empty() && text[text.length() - 1] == '\n');
01306 
01307   while (p < text.length()) {
01308     // Look for the paragraph or line break--the next newline
01309     // character, if any.
01310     size_t par = text.find_first_of("\n\r", p);
01311     bool is_paragraph_break = false;
01312     if (par == string::npos) {
01313       par = text.length();
01314       /*
01315         This shouldn't be necessary.
01316     } else {
01317       is_paragraph_break = (text[par] == '\r');
01318       */
01319     }
01320 
01321     indent(out, indent_amount);
01322 
01323     size_t eol = p + (line_width - indent_width);
01324     if (eol >= par) {
01325       // The rest of the paragraph fits completely on the line.
01326       eol = par;
01327 
01328     } else {
01329       // The paragraph doesn't fit completely on the line.  Determine
01330       // the best place to break the line.  Look for the last space
01331       // before the ideal eol.
01332       size_t min_eol = max((int)p, (int)eol - 25);
01333       size_t q = eol;
01334       while (q > min_eol && !isspace(text[q])) {
01335         q--;
01336       }
01337       // Now roll back to the last non-space before this one.
01338       while (q > min_eol && isspace(text[q])) {
01339         q--;
01340       }
01341 
01342       if (q != min_eol) {
01343         // Here's a good place to stop!
01344         eol = q + 1;
01345 
01346       } else {
01347         // The line cannot be broken cleanly.  Just let it keep going;
01348         // don't try to wrap it.
01349         eol = par;
01350       }
01351     }
01352     out << text.substr(p, eol - p) << "\n";
01353     p = eol;
01354 
01355     // Skip additional whitespace between the lines.
01356     while (p < text.length() && isspace(text[p])) {
01357       if (text[p] == '\r' ||
01358           (p > 0 && text[p] == '\n' && text[p - 1] == '\n')) {
01359         is_paragraph_break = true;
01360       }
01361       p++;
01362     }
01363 
01364     if (eol == par && is_paragraph_break) {
01365       // Print the paragraph break as a blank line.
01366       out << "\n";
01367       if (p >= text.length()) {
01368         // If we end on a paragraph break, don't try to insert a new
01369         // one in the next pass.
01370         last_newline = false;
01371       }
01372     }
01373 
01374     indent_amount = indent_width;
01375   }
01376 }
01377 
01378 
01379 ////////////////////////////////////////////////////////////////////
01380 //     Function: ProgramBase::sort_options
01381 //       Access: Private
01382 //  Description: Puts all the options in order by index number
01383 //               (e.g. in the order they were added, within
01384 //               index_groups), for output by show_options().
01385 ////////////////////////////////////////////////////////////////////
01386 void ProgramBase::
01387 sort_options() {
01388   if (!_sorted_options) {
01389     _options_by_index.clear();
01390 
01391     OptionsByName::const_iterator oi;
01392     for (oi = _options_by_name.begin(); oi != _options_by_name.end(); ++oi) {
01393       _options_by_index.push_back(&(*oi).second);
01394     }
01395 
01396     sort(_options_by_index.begin(), _options_by_index.end(),
01397          SortOptionsByIndex());
01398     _sorted_options = true;
01399   }
01400 }
01401 
01402 ////////////////////////////////////////////////////////////////////
01403 //     Function: ProgramBase::get_terminal_width
01404 //       Access: Private
01405 //  Description: Attempts to determine the ideal terminal width for
01406 //               formatting output.
01407 ////////////////////////////////////////////////////////////////////
01408 void ProgramBase::
01409 get_terminal_width() {
01410   if (!_got_terminal_width) {
01411     _got_terminal_width = true;
01412     _got_option_indent = false;
01413 
01414 #ifdef IOCTL_TERMINAL_WIDTH
01415     if (use_terminal_width) {
01416       struct winsize size;
01417       int result = ioctl(STDIN_FILENO, TIOCGWINSZ, (char *)&size);
01418       if (result < 0 || size.ws_col < 10) {
01419         // Couldn't determine the width for some reason.  Instead of
01420         // complaining, just punt.
01421         _terminal_width = default_terminal_width;
01422       } else {
01423         
01424         // Subtract 10% for the comfort margin at the edge.
01425         _terminal_width = size.ws_col - min(8, (int)(size.ws_col * 0.1));
01426       }
01427       return;
01428     }
01429 #endif  // IOCTL_TERMINAL_WIDTH
01430     
01431     _terminal_width = default_terminal_width;
01432   }
01433 }
 All Classes Functions Variables Enumerations