diff options
Diffstat (limited to 'support/highlight/src')
92 files changed, 38566 insertions, 0 deletions
diff --git a/support/highlight/src/cli/arg_parser.cc b/support/highlight/src/cli/arg_parser.cc new file mode 100644 index 0000000000..55e440d94f --- /dev/null +++ b/support/highlight/src/cli/arg_parser.cc @@ -0,0 +1,193 @@ +/* Arg_parser - A POSIX/GNU command line argument parser. + Copyright (C) 2006, 2007, 2008 Antonio Diaz Diaz. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include <cstring> +#include <string> +#include <vector> + +#include "arg_parser.h" + + +bool Arg_parser::parse_long_option( const char * const opt, const char * const arg, + const Option options[], int & argind ) throw() + { + unsigned int len; + int index = -1; + bool exact = false, ambig = false; + + for( len = 0; opt[len+2] && opt[len+2] != '='; ++len ) ; + + // Test all long options for either exact match or abbreviated matches. + for( int i = 0; options[i].code != 0; ++i ) + if( options[i].name && !std::strncmp( options[i].name, &opt[2], len ) ) + { + if( std::strlen( options[i].name ) == len ) // Exact match found + { index = i; exact = true; break; } + else if( index < 0 ) index = i; // First nonexact match found + else if( options[index].code != options[i].code || + options[index].has_arg != options[i].has_arg ) + ambig = true; // Second or later nonexact match found + } + + if( ambig && !exact ) + { + _error = "option `"; _error += opt; _error += "' is ambiguous"; + return false; + } + + if( index < 0 ) // nothing found + { + _error = "unrecognized option `"; _error += opt; _error += '\''; + return false; + } + + ++argind; + data.push_back( Record( options[index].code ) ); + + if( opt[len+2] ) // `--<long_option>=<argument>' syntax + { + if( options[index].has_arg == no ) + { + _error = "option `--"; _error += options[index].name; + _error += "' doesn't allow an argument"; + return false; + } + if( options[index].has_arg == yes && !opt[len+3] ) + { + _error = "option `--"; _error += options[index].name; + _error += "' requires an argument"; + return false; + } + data.back().argument = &opt[len+3]; + return true; + } + + if( options[index].has_arg == yes ) + { + if( !arg ) + { + _error = "option `--"; _error += options[index].name; + _error += "' requires an argument"; + return false; + } + ++argind; data.back().argument = arg; + return true; + } + + return true; + } + + +bool Arg_parser::parse_short_option( const char * const opt, const char * const arg, + const Option options[], int & argind ) throw() + { + int cind = 1; // character index in opt + + while( cind > 0 ) + { + int index = -1; + const unsigned char code = opt[cind]; + + if( code != 0 ) + for( int i = 0; options[i].code; ++i ) + if( code == options[i].code ) + { index = i; break; } + + if( index < 0 ) + { + _error = "invalid option -- "; _error += code; + return false; + } + + data.push_back( Record( code ) ); + if( opt[++cind] == 0 ) { ++argind; cind = 0; } // opt finished + + if( options[index].has_arg != no && cind > 0 && opt[cind] ) + { + data.back().argument = &opt[cind]; ++argind; cind = 0; + } + else if( options[index].has_arg == yes ) + { + if( !arg || !arg[0] ) + { + _error = "option requires an argument -- "; _error += code; + return false; + } + data.back().argument = arg; ++argind; cind = 0; + } + } + return true; + } + + +Arg_parser::Arg_parser( const int argc, const char * const argv[], + const Option options[], const bool in_order ) throw() + { + if( argc < 2 || !argv || !options ) return; + + std::vector< std::string > non_options; // skipped non-options + int argind = 1; // index in argv + + while( argind < argc ) + { + const unsigned char ch1 = argv[argind][0]; + const unsigned char ch2 = ( ch1 ? argv[argind][1] : 0 ); + + if( ch1 == '-' && ch2 ) // we found an option + { + const char * const opt = argv[argind]; + const char * const arg = (argind + 1 < argc) ? argv[argind+1] : 0; + if( ch2 == '-' ) + { + if( !argv[argind][2] ) { ++argind; break; } // we found "--" + else if( !parse_long_option( opt, arg, options, argind ) ) break; + } + else if( !parse_short_option( opt, arg, options, argind ) ) break; + } + else + { + if( !in_order ) non_options.push_back( argv[argind++] ); + else { data.push_back( Record() ); data.back().argument = argv[argind++]; } + } + } + if( _error.size() ) data.clear(); + else + { + for( unsigned int i = 0; i < non_options.size(); ++i ) + { data.push_back( Record() ); data.back().argument.swap( non_options[i] ); } + while( argind < argc ) + { data.push_back( Record() ); data.back().argument = argv[argind++]; } + } + } + + +Arg_parser::Arg_parser( const char * const opt, const char * const arg, + const Option options[] ) throw() + { + if( !opt || !opt[0] || !options ) return; + + if( opt[0] == '-' && opt[1] ) // we found an option + { + int argind = 1; // dummy + if( opt[1] == '-' ) + { if( opt[2] ) parse_long_option( opt, arg, options, argind ); } + else + parse_short_option( opt, arg, options, argind ); + if( _error.size() ) data.clear(); + } + else { data.push_back( Record() ); data.back().argument = opt; } + } diff --git a/support/highlight/src/cli/arg_parser.h b/support/highlight/src/cli/arg_parser.h new file mode 100644 index 0000000000..b0e44a8770 --- /dev/null +++ b/support/highlight/src/cli/arg_parser.h @@ -0,0 +1,95 @@ +/* Arg_parser - A POSIX/GNU command line argument parser. + Copyright (C) 2006, 2007, 2008 Antonio Diaz Diaz. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +/* Arg_parser reads the arguments in `argv' and creates a number of + option codes, option arguments and non-option arguments. + + In case of error, `error' returns a non-empty error message. + + `options' is an array of `struct Option' terminated by an element + containing a code which is zero. A null name means a short-only + option. A code value outside the unsigned char range means a + long-only option. + + Arg_parser normally makes it appear as if all the option arguments + were specified before all the non-option arguments for the purposes + of parsing, even if the user of your program intermixed option and + non-option arguments. If you want the arguments in the exact order + the user typed them, call `Arg_parser' with `in_order' = true. + + The argument `--' terminates all options; any following arguments are + treated as non-option arguments, even if they begin with a hyphen. + + The syntax for optional option arguments is `-<short_option><argument>' + (without whitespace), or `--<long_option>=<argument>'. +*/ + +class Arg_parser +{ + public: + enum Has_arg { no, yes, maybe }; + + struct Option + { + int code; // Short option letter or code ( code != 0 ) + const char * name; // Long option name (maybe null) + Has_arg has_arg; + }; + + private: + struct Record + { + int code; + std::string argument; + Record ( const int c = 0 ) : code ( c ) {} + }; + + std::string _error; + std::vector< Record > data; + + bool parse_long_option ( const char * const opt, const char * const arg, + const Option options[], int & argind ) throw(); + bool parse_short_option ( const char * const opt, const char * const arg, + const Option options[], int & argind ) throw(); + + public: + Arg_parser ( const int argc, const char * const argv[], + const Option options[], const bool in_order = false ) throw(); + + // Restricted constructor. Parses a single token and argument (if any) + Arg_parser ( const char * const opt, const char * const arg, + const Option options[] ) throw(); + + const std::string & error() const throw() { return _error; } + + // The number of arguments parsed (may be different from argc) + int arguments() const throw() { return data.size(); } + + // If code( i ) is 0, argument( i ) is a non-option. + // Else argument( i ) is the option's argument (or empty). + int code ( const int i ) const throw() + { + if ( i >= 0 && i < arguments() ) return data[i].code; + else return 0; + } + + const std::string & argument ( const int i ) const throw() + { + if ( i >= 0 && i < arguments() ) return data[i].argument; + else return _error; + } +}; diff --git a/support/highlight/src/cli/cmdlineoptions.cpp b/support/highlight/src/cli/cmdlineoptions.cpp new file mode 100644 index 0000000000..21c7646bda --- /dev/null +++ b/support/highlight/src/cli/cmdlineoptions.cpp @@ -0,0 +1,1031 @@ +/*************************************************************************** + cmdlineoptions.cpp - description + ------------------- + begin : Sun Nov 25 2001 + copyright : (C) 2001-2008 by Andre Simon + email : andre.simon1@gmx.de + ***************************************************************************/ + + +/* +This file is part of Highlight. + +Highlight is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +Highlight is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Highlight. If not, see <http://www.gnu.org/licenses/>. +*/ + + +#include "cmdlineoptions.h" +#include "platform_fs.h" +#include "configurationreader.h" +#include "datadir.h" +#include <sstream> +#include <cstdio> + +#include "arg_parser.h" + +using namespace std; + + +CmdLineOptions::CmdLineOptions ( const int argc, const char *argv[] ) : + numberSpaces ( 0 ), + lineNrWidth ( 5 ), + lineLength ( 80 ), + lineNrStart ( 1 ), + wrappingStyle ( highlight::WRAP_DISABLED ), + outputType ( highlight::HTML ), + keywordCase ( StringTools::CASE_UNCHANGED ), + className ( "hl" ), + opt_syntax ( false ), + opt_include_style ( false ), + opt_help ( false ), + opt_version ( false ), + opt_verbose ( false ), + opt_print_config ( false ), + opt_linenumbers ( false ), + opt_style ( false ), + opt_batch_mode ( false ), + opt_fragment ( false ) , + opt_attach_line_anchors ( false ), + opt_show_themes ( false ), + opt_show_langdefs ( false ), + opt_printindex ( false ), + opt_quiet ( false ), + opt_replacequotes ( false ), + opt_babel ( false ), + opt_print_progress ( false ), + opt_fill_zeroes ( false ), + opt_stylepath_explicit ( false ), + opt_force_output ( false ), + opt_ordered_list ( false ), + opt_fnames_as_anchors ( false ), + opt_validate ( false ), + opt_inline_css ( false ), + opt_enclose_pre ( false ), + opt_char_styles ( false ), + opt_pretty_symbols ( false ), + opt_delim_CR (false), + opt_print_style(false), + opt_no_trailing_nl(false), + configFileRead ( false ), + anchorPrefix ( "l" ), + helpLang ( "en" ), + encodingName ( "ISO-8859-1" ) +{ + + loadConfigurationFile(); + + enum Optcode + { + S_OPT_ADDCONFDIR = 256, S_OPT_ENCLOSE_PRE, S_OPT_FORCE_OUTPUT, + S_OPT_INLINE_CSS, S_OPT_KW_CASE, + S_OPT_MARK_LINES, S_OPT_PRINT_CONFIG, S_OPT_TEST_INPUT, + S_OPT_SVG_WIDTH, S_OPT_SVG_HEIGHT, S_OPT_CLASSNAME, S_OPT_RTF_CHAR_STYLES, + S_OPT_SKIP_UNKNOWN, + S_OPT_COMPAT_DOC, S_OPT_COMPAT_NODOC, S_OPT_COMPAT_TAB, S_OPT_COMPAT_CSS, + S_OPT_COMPAT_OUTDIR, S_OPT_COMPAT_FAILSAFE, S_OPT_COMPAT_OUTFORMAT, + S_OPT_COMPAT_SRCLANG, S_OPT_COMPAT_LINENUM, S_OPT_COMPAT_LINEREF, + S_OPT_CTAGS_FILE, S_OPT_PRETTY_SYMBOLS, S_OPT_EOL_DELIM_CR, S_OPT_START_NESTED, + S_OPT_PRINT_STYLE, S_OPT_NO_TRAILING_NL + }; + + const Arg_parser::Option options[] = + { + { 'a', OPT_ANCHORS, Arg_parser::no }, + { 'A', OPT_ANSI, Arg_parser::no }, + { 'b', OPT_BABEL, Arg_parser::no }, + { 'B', OPT_BATCHREC, Arg_parser::yes }, + { 'c', OPT_STYLE_OUT, Arg_parser::yes }, + { 'C', OPT_INDEXFILE, Arg_parser::no }, + { 'd', OPT_DOC_TITLE, Arg_parser::yes }, + { 'D', OPT_DATADIR, Arg_parser::yes }, + { 'e', OPT_STYLE_IN, Arg_parser::yes }, + { 'E', OPT_ADDDATADIR, Arg_parser::yes }, + { 'f', OPT_FRAGMENT, Arg_parser::no }, + { 'F', OPT_FORMAT, Arg_parser::yes }, + { S_OPT_CLASSNAME, OPT_CLASSNAME, Arg_parser::yes }, + { 'h', OPT_HELP, Arg_parser::no }, + { 'H', OPT_HTML, Arg_parser::no }, + { 'i', OPT_IN, Arg_parser::yes }, + { 'I', OPT_INC_STYLE, Arg_parser::no }, + { 'j', OPT_LNR_LEN, Arg_parser::yes }, + { 'J', OPT_LINE_LEN, Arg_parser::yes }, + { 'k', OPT_BASE_FONT, Arg_parser::yes }, + { 'K', OPT_BASE_FONT_SIZE, Arg_parser::yes }, + { 'l', OPT_LINENO, Arg_parser::no }, + { 'L', OPT_LATEX, Arg_parser::no }, + { 'm', OPT_LNR_START, Arg_parser::yes }, + { 'M', OPT_XTERM256, Arg_parser::no }, + { 'n', OPT_ORDERED_LIST, Arg_parser::no }, + { 'N', OPT_ANCHOR_FN, Arg_parser::no }, + { 'o', OPT_OUT, Arg_parser::yes }, + { 'O', OPT_OUTDIR, Arg_parser::yes }, + { 'p', OPT_LISTLANGS, Arg_parser::no }, + { 'P', OPT_PROGRESSBAR, Arg_parser::no }, + { 'q', OPT_QUIET, Arg_parser::no }, + { 'Q', OPT_VERSION, Arg_parser::no }, + { 'r', OPT_REPLACE_QUOTES, Arg_parser::no }, + { 'R', OPT_RTF, Arg_parser::no }, + { 's', OPT_STYLE, Arg_parser::yes }, + { 'S', OPT_SYNTAX, Arg_parser::yes }, + { 't', OPT_DELTABS, Arg_parser::yes }, + { 'T', OPT_TEX, Arg_parser::no }, + { 'u', OPT_ENCODING, Arg_parser::yes }, + { 'v', OPT_VERBOSE, Arg_parser::no }, + { 'V', OPT_WRAPSIMPLE, Arg_parser::no }, + { 'w', OPT_LISTTHEMES, Arg_parser::no }, + { 'W', OPT_WRAP, Arg_parser::no }, + { 'x', OPT_RTF_PAGE_SIZE, Arg_parser::yes }, + { 'X', OPT_XHTML, Arg_parser::no }, + { 'y', OPT_ANCHOR_PFX, Arg_parser::yes }, + { 'z', OPT_FILLZEROES, Arg_parser::no }, + { 'Z', OPT_XML, Arg_parser::no }, + { 'G', OPT_SVG, Arg_parser::no }, + { 'Y', OPT_BBCODE, Arg_parser::no }, + { S_OPT_SVG_WIDTH, OPT_SVG_WIDTH, Arg_parser::yes }, + { S_OPT_SVG_HEIGHT, OPT_SVG_HEIGHT, Arg_parser::yes }, + { S_OPT_ADDCONFDIR, OPT_ADDCONFDIR, Arg_parser::yes }, + { S_OPT_ENCLOSE_PRE, OPT_ENCLOSE_PRE, Arg_parser::no }, + { S_OPT_FORCE_OUTPUT, OPT_FORCE_OUTPUT, Arg_parser::no }, + { S_OPT_INLINE_CSS, OPT_INLINE_CSS, Arg_parser::no }, + { S_OPT_KW_CASE, OPT_KW_CASE, Arg_parser::yes }, + { S_OPT_MARK_LINES, OPT_MARK_LINES, Arg_parser::yes }, + { S_OPT_PRINT_CONFIG, OPT_PRINT_CONFIG, Arg_parser::no }, + { S_OPT_TEST_INPUT, OPT_TEST_INPUT, Arg_parser::no }, + { S_OPT_RTF_CHAR_STYLES, OPT_RTF_CHAR_STYLES, Arg_parser::no }, + { S_OPT_SKIP_UNKNOWN, OPT_SKIP_UNKNOWN, Arg_parser::yes }, + { S_OPT_CTAGS_FILE, OPT_CTAGS_FILE, Arg_parser::maybe }, + { S_OPT_START_NESTED, OPT_START_NESTED, Arg_parser::yes }, + { S_OPT_COMPAT_DOC, OPT_COMPAT_DOC, Arg_parser::no }, + { S_OPT_COMPAT_NODOC, OPT_COMPAT_NODOC, Arg_parser::no }, + { S_OPT_COMPAT_TAB, OPT_COMPAT_TAB, Arg_parser::yes }, + { S_OPT_COMPAT_CSS, OPT_COMPAT_CSS, Arg_parser::yes }, + { S_OPT_COMPAT_OUTDIR, OPT_COMPAT_OUTDIR, Arg_parser::yes }, + { S_OPT_COMPAT_FAILSAFE, OPT_COMPAT_FAILSAFE, Arg_parser::no }, + { S_OPT_COMPAT_OUTFORMAT, OPT_COMPAT_OUTFORMAT, Arg_parser::yes }, + { S_OPT_COMPAT_SRCLANG, OPT_COMPAT_SRCLANG, Arg_parser::yes }, + { S_OPT_COMPAT_LINENUM, OPT_COMPAT_LINENUM, Arg_parser::maybe }, + { S_OPT_COMPAT_LINEREF, OPT_COMPAT_LINEREF, Arg_parser::maybe }, + { S_OPT_PRETTY_SYMBOLS, OPT_PRETTY_SYMBOLS, Arg_parser::no }, + { S_OPT_EOL_DELIM_CR, OPT_EOL_DELIM_CR, Arg_parser::no }, + { S_OPT_PRINT_STYLE, OPT_PRINT_STYLE, Arg_parser::no }, + { S_OPT_NO_TRAILING_NL, OPT_NO_TRAILING_NL, Arg_parser::no }, + + { 0, 0, Arg_parser::no } + }; + + + Arg_parser parser ( argc, argv, options ); + if ( parser.error().size() ) // bad option + { + cerr << "highlight: "<< parser.error() <<"\n"; + cerr << "Try `highlight --help' for more information.\n"; + exit ( 1 ); + } + + int argind = 0; + for ( ; argind < parser.arguments(); ++argind ) + { + const int code = parser.code ( argind ); + const std::string & arg = parser.argument ( argind ); + if ( !code ) break; // no more options + switch ( code ) + { + case 'a': + opt_attach_line_anchors = true; + break; + case 'A': + outputType=highlight::ANSI; + break; + case 'b': + opt_babel=true; + break; + case 'B': + opt_batch_mode = true; + readDirectory ( arg ); + break; + case 'c': + case S_OPT_COMPAT_CSS: + styleOutFilename = arg; + opt_stylepath_explicit=true; + break; + case 'C': + opt_printindex=true; + break; + case 'd': + docTitle = arg; + break; + case 'D': + dataDir=validateDirPath ( arg ); + break; + case 'e': + styleInFilename = arg; + break; + case 'E': + additionalDataDir=validateDirPath ( arg ); + break; + case 'f': + case S_OPT_COMPAT_NODOC: + opt_fragment = true; + break; + case 'F': + indentScheme = arg; + break; + case S_OPT_CLASSNAME: + className = arg; + break; + case 'h': + opt_help = true; + break; + case 'H': + outputType=highlight::HTML; + break; + case 'i': + inputFileNames.push_back ( arg ); + break; + case 'I': + opt_include_style = true; + break; + case 'j': + StringTools::str2num<int> ( lineNrWidth, arg, std::dec ); + break; + case 'J': + StringTools::str2num<int> ( lineLength, arg, std::dec ); + break; + case 'k': + baseFont = arg; + break; + case 'K': + baseFontSize = arg; + break; + case S_OPT_COMPAT_LINENUM: + if ( arg=="0" ) opt_fill_zeroes=true; + case 'l': + opt_linenumbers = true; + break; + case 'L': + outputType=highlight::LATEX; + break; + case 'm': + StringTools::str2num<int> ( lineNrStart, arg, std::dec ); + break; + case 'M': + outputType=highlight::XTERM256; + break; + case 'n': + opt_ordered_list = opt_linenumbers = true; + break; + case 'N': + opt_fnames_as_anchors=true; + break; + case 'o': + outFilename = arg; + break; + case 'O': + case S_OPT_COMPAT_OUTDIR: + outDirectory = validateDirPath ( arg ); + break; + case 'p': + opt_show_langdefs = true; + break; + case 'P': + opt_print_progress=true; + break; + case 'q': + opt_quiet = true; + break; + case 'Q': + opt_version = true; + break; + case 'r': + opt_replacequotes=true; + break; + case 'R': + outputType=highlight::RTF; + break; + case 's': + styleName = arg; + opt_style = true; + break; + case 'S': + case S_OPT_COMPAT_SRCLANG: + syntax = arg; + opt_syntax = true; + break; + case 't': + case S_OPT_COMPAT_TAB: + StringTools::str2num<int> ( numberSpaces, arg, std::dec ); + break; + case 'T': + outputType=highlight::TEX; + break; + case 'u': + encodingName = arg; + break; + case 'v': + opt_verbose = true; + break; + case 'V': + wrappingStyle = highlight::WRAP_SIMPLE; + break; + case 'w': + opt_show_themes = true; + break; + case 'W': + wrappingStyle = highlight::WRAP_DEFAULT; + break; + case 'x': + pageSize = arg; + break; + case 'X': + outputType=highlight::XHTML; + break; + case 'y': + anchorPrefix = arg; + break; + case 'z': + opt_fill_zeroes=true; + break; + case 'Z': + outputType=highlight::XML; + break; + case 'G': + outputType=highlight::SVG; + break; + case 'Y': + outputType=highlight::BBCODE; + break; + case S_OPT_SVG_WIDTH: + svg_width = arg; + break; + case S_OPT_SVG_HEIGHT: + svg_height = arg; + break; + case S_OPT_ADDCONFDIR: + additionalConfigDir = validateDirPath ( arg ); + break; + case S_OPT_ENCLOSE_PRE: + opt_enclose_pre=true; + break; + case S_OPT_FORCE_OUTPUT: + case S_OPT_COMPAT_FAILSAFE: + opt_force_output = true; + break; + case S_OPT_INLINE_CSS: + opt_inline_css=true; + break; + case S_OPT_KW_CASE: + { + const string tmp = StringTools::change_case ( arg ); + if ( tmp == "upper" ) + keywordCase = StringTools::CASE_UPPER; + else if ( tmp == "lower" ) + keywordCase = StringTools::CASE_LOWER; + else if ( tmp == "capitalize" ) + keywordCase = StringTools::CASE_CAPITALIZE; + } + break; + case S_OPT_COMPAT_OUTFORMAT: + { + const string tmp = StringTools::change_case ( arg ); + if ( tmp == "xhtml" ) + outputType = highlight::XHTML; + else if ( tmp == "tex" ) + outputType = highlight::TEX; + else if ( tmp == "latex" ) + outputType = highlight::LATEX; + else if ( tmp == "rtf" ) + outputType = highlight::RTF; + else if ( tmp == "xml" ) + outputType = highlight::XML; + else if ( tmp == "ansi" || tmp == "esc" ) // gnu source-highlight esc parameter + outputType = highlight::ANSI; + else if ( tmp == "xterm256" ) + outputType = highlight::XTERM256; + else if ( tmp == "svg" ) + outputType = highlight::SVG; + else if ( tmp == "bbcode" ) + outputType = highlight::BBCODE; + else + outputType = highlight::HTML; + } + break; + case S_OPT_MARK_LINES: + markLinesArg = arg; + break; + case S_OPT_PRINT_CONFIG: + opt_print_config = true; + break; + case S_OPT_TEST_INPUT: + opt_validate=true; + break; + case S_OPT_RTF_CHAR_STYLES: + opt_char_styles=true; + break; + case S_OPT_SKIP_UNKNOWN: + skipArg=arg; + break; + case S_OPT_CTAGS_FILE: + ctagsFile = ( arg.empty() ) ? "tags" :arg; + break; + case S_OPT_PRETTY_SYMBOLS: + opt_pretty_symbols = true; + break; + case S_OPT_COMPAT_DOC: + opt_fragment = false; + break; + case S_OPT_COMPAT_LINEREF: + opt_linenumbers = true; + opt_attach_line_anchors = true; + anchorPrefix = ( arg.empty() ) ? "line":arg; + break; + case S_OPT_EOL_DELIM_CR: + opt_delim_CR = true; + break; + case S_OPT_START_NESTED: + startNestedLang=arg; + break; + case S_OPT_PRINT_STYLE: + opt_print_style = true; + break; + case S_OPT_NO_TRAILING_NL: + opt_no_trailing_nl = true; + break; + default: + cerr << "highlight: option parsing failed" << endl; + } + } + + if ( argind < parser.arguments() ) //still args left + { + if ( inputFileNames.empty() ) + { + while ( argind < parser.arguments() ) + { + inputFileNames.push_back ( parser.argument ( argind++ ) ); + } + } + } + else if ( inputFileNames.empty() ) + { + inputFileNames.push_back ( "" ); + } + if ( printDebugInfo() && configFileRead ) + { + cout << "Configuration file \""<<configFilePath<<"\" was read.\n"; + } + + if ( skipArg.size() ) + { + istringstream valueStream; + string elem; + string wildcard; + valueStream.str ( StringTools::change_case ( skipArg,StringTools::CASE_LOWER ) ); + + while ( getline ( valueStream, elem, ';' ) ) + { + ignoredFileTypes.insert ( elem ); + } + for ( vector<string>::iterator file=inputFileNames.begin();file!=inputFileNames.end();file++ ) + { + for ( set<string>::iterator ext=ignoredFileTypes.begin();ext!=ignoredFileTypes.end();ext++ ) + { + wildcard="*."+*ext; + if ( Platform::wildcmp ( wildcard.c_str(), ( *file ).c_str() ) ) + { + inputFileNames.erase ( file ); + file--; + break; + } + } + } + } +} + +CmdLineOptions::~CmdLineOptions() {} + +const string &CmdLineOptions::getSingleOutFilename() +{ + if ( !inputFileNames.empty() && !outDirectory.empty() ) + { + if ( outFilename.empty() ) + { + outFilename = outDirectory; + int delim = getSingleInFilename().find_last_of ( Platform::pathSeparator ) +1; + outFilename += getSingleInFilename().substr ( ( delim>-1 ) ?delim:0 ) + + getOutFileSuffix(); + } + } + return outFilename; +} + +const string &CmdLineOptions::getSingleInFilename() const +{ + return inputFileNames[0]; +} + +const string &CmdLineOptions::getOutDirectory() +{ + if ( !outFilename.empty() && !enableBatchMode() ) + { + outDirectory=getDirName ( outFilename ); + } + return outDirectory; +} + +const string CmdLineOptions::getStyleOutFilename() const +{ + if ( !styleOutFilename.empty() ) return styleOutFilename; + + if ( outputType==highlight::TEX || outputType==highlight::LATEX ) + { + return "highlight.sty"; + } + else + { + return "highlight.css"; + } +} +const string &CmdLineOptions::getStyleInFilename() const +{ + return styleInFilename; +} +const string& CmdLineOptions::getSVGWidth() const +{ + return svg_width; +} +const string& CmdLineOptions::getSVGHeight() const +{ + return svg_height; +} +int CmdLineOptions::getNumberSpaces() const +{ + return numberSpaces; +} +bool CmdLineOptions::printVersion() const +{ + return opt_version; +} +bool CmdLineOptions::printHelp() const +{ + return opt_help; +} +bool CmdLineOptions::printDebugInfo() const +{ + return opt_verbose; +} +bool CmdLineOptions::printConfigInfo() const +{ + return opt_print_config; +} +bool CmdLineOptions::quietMode() const +{ + return opt_quiet; +} +bool CmdLineOptions::includeStyleDef() const +{ + return opt_include_style; +} +bool CmdLineOptions::useFNamesAsAnchors() const +{ + return opt_fnames_as_anchors; +} + +bool CmdLineOptions::formatSupportsExtStyle() +{ + return outputType==highlight::HTML || + outputType==highlight::XHTML || + outputType==highlight::LATEX || + outputType==highlight::TEX || + outputType==highlight::SVG; +} + +bool CmdLineOptions::printLineNumbers() const +{ + return opt_linenumbers; +} + +string CmdLineOptions::getThemeName() const +{ + return ( ( opt_style ) ? styleName+".style" : "kwrite.style" ); +} +bool CmdLineOptions::enableBatchMode() const +{ + return inputFileNames.size() >1 || opt_batch_mode; +} +bool CmdLineOptions::fragmentOutput() const +{ + return opt_fragment; +} +string CmdLineOptions::getOutFileSuffix() const +{ + switch ( outputType ) + { + case highlight::XHTML: return ".xhtml"; + case highlight::RTF: return ".rtf"; + case highlight::TEX: + case highlight::LATEX: return ".tex"; + case highlight::XML: return ".xml"; + case highlight::SVG: return ".svg"; + case highlight::ANSI: return ".ansi"; + case highlight::XTERM256: return ".xterm"; + case highlight::BBCODE: return ".bbcode"; + default: return ".html"; + } +} +string CmdLineOptions::getDirName ( const string & path ) +{ + size_t dirNameLength=path.rfind ( Platform::pathSeparator ); + return ( dirNameLength==string::npos ) ?string() :path.substr ( 0, dirNameLength+1 ); +} +bool CmdLineOptions::attachLineAnchors() const +{ + return opt_attach_line_anchors; +} +bool CmdLineOptions::showThemes() const +{ + return opt_show_themes; +} +bool CmdLineOptions::showLangdefs() const +{ + return opt_show_langdefs; +} +bool CmdLineOptions::outDirGiven() const +{ + return !outFilename.empty(); +} +bool CmdLineOptions::replaceQuotes() const +{ + return opt_replacequotes; +} +bool CmdLineOptions::disableBabelShorthands() const +{ + return opt_babel; +} +bool CmdLineOptions::prettySymbols() const +{ + return opt_pretty_symbols; +} +bool CmdLineOptions::getFlag ( const string& paramVal ) +{ + return StringTools::change_case ( paramVal ) =="true"; +} +/* +bool CmdLineOptions::formattingEnabled(){ + return !indentScheme.empty(); +} +*/ +bool CmdLineOptions::orderedList() const +{ + return opt_ordered_list; +} +bool CmdLineOptions::useCRDelimiter() const { + return opt_delim_CR; +} +const string &CmdLineOptions::getDataDir() const +{ + return dataDir; +} +bool CmdLineOptions::printOnlyStyle() const { + return opt_print_style; +} + +string CmdLineOptions::getIndentScheme() const +{ + return StringTools::change_case ( indentScheme ); +} + +const string &CmdLineOptions::getAdditionalDataDir() const +{ + return additionalDataDir; +} +const string &CmdLineOptions::getAdditionalConfDir() const +{ + return additionalConfigDir; +} +const string &CmdLineOptions::getLanguage() const +{ + return syntax; +} +const string&CmdLineOptions::getEncoding() const +{ + return encodingName; +} + +const string& CmdLineOptions::getAnchorPrefix() const +{ + return anchorPrefix; +} + +const string &CmdLineOptions::getPageSize() const +{ + return pageSize; +} +bool CmdLineOptions::printIndexFile() const +{ + return opt_printindex && ( outputType==highlight::HTML || + outputType==highlight::XHTML ); +} +bool CmdLineOptions::printProgress() const +{ + return opt_print_progress; +} +bool CmdLineOptions::fillLineNrZeroes() const +{ + return opt_fill_zeroes; +} +bool CmdLineOptions::syntaxGiven() const +{ + return opt_syntax; +} +bool CmdLineOptions::omitEncoding() const +{ + return StringTools::change_case ( encodingName ) =="none"; +} +bool CmdLineOptions::forceOutput() const +{ + return opt_force_output; +} +bool CmdLineOptions::validateInput() const +{ + return opt_validate; +} +bool CmdLineOptions::inlineCSS() const +{ + return opt_inline_css; +} +bool CmdLineOptions::enclosePreTag() const +{ + return opt_enclose_pre; +} +bool CmdLineOptions::includeCharStyles() const +{ + return opt_char_styles; +} +bool CmdLineOptions::disableTrailingNL() const +{ + return opt_no_trailing_nl; +} +const string &CmdLineOptions::getConfigFilePath() const +{ + return configFilePath; +} + +const string& CmdLineOptions::getDocumentTitle() const +{ + return docTitle; +} + +highlight::WrapMode CmdLineOptions::getWrappingStyle() const +{ + return wrappingStyle; +} +const vector <string> & CmdLineOptions::getInputFileNames() const +{ + return inputFileNames; +} + +const map <int,string> & CmdLineOptions::getMarkLines() +{ + markLines.clear(); + istringstream valueStream; + string elem; + size_t delimPos; + int markLineNo; + valueStream.str ( markLinesArg ); + // Format: "1=help line one; 3=help line three; 5 " + while ( getline ( valueStream, elem, ';' ) ) + { + delimPos = elem.find ( '=' ); + markLineNo=0; + StringTools::str2num<int> ( markLineNo, elem.substr ( 0,delimPos ), std::dec ); + if ( markLineNo ) + { + markLines[markLineNo] = + ( delimPos!=string::npos ) ?elem.substr ( delimPos+1 ) :""; + } + } + return markLines; +} +void CmdLineOptions::readDirectory ( const string & wildcard ) +{ + // get matching files, use recursive search + bool directoryOK=Platform::getDirectoryEntries ( inputFileNames, wildcard, true ); + if ( !directoryOK ) + { + cerr << "highlight: No files matched the pattern \"" + << wildcard << "\"."<< endl; + } +} + +string CmdLineOptions::validateDirPath ( const string & path ) +{ + return ( path[path.length()-1] !=Platform::pathSeparator ) ? + path+Platform::pathSeparator : path; +} + +highlight::OutputType CmdLineOptions::getOutputType() const +{ + return outputType; +} + +StringTools::KeywordCase CmdLineOptions::getKeywordCase() const +{ + return keywordCase; +} + +bool CmdLineOptions::hasBaseFont() const +{ + return ( ! baseFont.empty() ) ; +} + +const string& CmdLineOptions::getBaseFont() const +{ + return baseFont ; +} + +bool CmdLineOptions::hasBaseFontSize() const +{ + return ( ! baseFontSize.empty() ) ; +} + +const string& CmdLineOptions::getBaseFontSize() const +{ + return baseFontSize ; +} + +const string& CmdLineOptions::getClassName() const +{ + return className ; +} + +const string& CmdLineOptions::getTagsFile() const +{ + return ctagsFile; +} +const string& CmdLineOptions::getStartNestedLang() const +{ + return startNestedLang; +} +int CmdLineOptions::getNumberWidth() +{ + return lineNrWidth; +} + +int CmdLineOptions::getLineLength() +{ + return lineLength; +} + +int CmdLineOptions::getNumberStart() +{ + return lineNrStart; +} + +void CmdLineOptions::loadConfigurationFile() +{ +#ifndef _WIN32 +#ifdef CONFIG_FILE_PATH + configFilePath=CONFIG_FILE_PATH; +#else + char* homeEnv=getenv ( "HOME" ); + if ( homeEnv==NULL ) return; + configFilePath=string ( homeEnv ) +"/.highlightrc"; +#endif +#else + configFilePath = Platform::getAppPath() + "highlight.conf"; +#endif + ConfigurationReader userConfig ( configFilePath ); + + if ( userConfig.found() ) + { + string paramVal; + configFileRead=true; + + styleOutFilename = userConfig.getParameter ( OPT_STYLE_OUT ); + styleInFilename = userConfig.getParameter ( OPT_STYLE_IN ); + styleName = userConfig.getParameter ( OPT_STYLE ); + opt_style = !styleName.empty(); + syntax = userConfig.getParameter ( OPT_SYNTAX ); + opt_syntax = !syntax.empty(); + StringTools::str2num<int> ( numberSpaces, userConfig.getParameter ( OPT_DELTABS ), std::dec ); + indentScheme = userConfig.getParameter ( OPT_FORMAT ); + baseFontSize = userConfig.getParameter ( OPT_BASE_FONT_SIZE ); + baseFont = userConfig.getParameter ( OPT_BASE_FONT ); + skipArg = userConfig.getParameter ( OPT_SKIP_UNKNOWN ); + + paramVal = userConfig.getParameter ( OPT_DATADIR ); + if ( !paramVal.empty() ) + { + dataDir=validateDirPath ( paramVal ); + } + paramVal = userConfig.getParameter ( OPT_ADDDATADIR ); + if ( !paramVal.empty() ) + { + additionalDataDir=validateDirPath ( paramVal ); + } + paramVal = userConfig.getParameter ( OPT_ADDCONFDIR ); + if ( !paramVal.empty() ) + { + additionalConfigDir=validateDirPath ( paramVal ); + } + paramVal = userConfig.getParameter ( OPT_OUTDIR ); + if ( !paramVal.empty() ) + { + outDirectory=validateDirPath ( paramVal ); + } + paramVal = userConfig.getParameter ( OPT_ENCODING ); + if ( !paramVal.empty() ) + { + encodingName=paramVal; + } + paramVal = userConfig.getParameter ( OPT_LNR_LEN ); + if ( !paramVal.empty() ) + { + StringTools::str2num<int> ( lineNrWidth, string ( paramVal ), std::dec ); + } + paramVal = userConfig.getParameter ( OPT_LNR_START ); + if ( !paramVal.empty() ) + { + StringTools::str2num<int> ( lineNrStart, string ( paramVal ), std::dec ); + } + paramVal = userConfig.getParameter ( OPT_ANCHOR_PFX ); + if ( !paramVal.empty() ) + { + anchorPrefix=paramVal; + } + + opt_include_style=getFlag ( userConfig.getParameter ( OPT_INC_STYLE ) ); + opt_verbose=getFlag ( userConfig.getParameter ( OPT_VERBOSE ) ); + opt_ordered_list=getFlag ( userConfig.getParameter ( OPT_ORDERED_LIST ) ); + opt_linenumbers=opt_ordered_list || getFlag ( userConfig.getParameter ( OPT_LINENO ) ); + opt_fragment=getFlag ( userConfig.getParameter ( OPT_FRAGMENT ) ); + opt_attach_line_anchors=getFlag ( userConfig.getParameter ( OPT_ANCHORS ) ); + opt_printindex=getFlag ( userConfig.getParameter ( OPT_INDEXFILE ) ); + opt_quiet=getFlag ( userConfig.getParameter ( OPT_QUIET ) ); + opt_replacequotes=getFlag ( userConfig.getParameter ( OPT_REPLACE_QUOTES ) ); + opt_print_progress=getFlag ( userConfig.getParameter ( OPT_PROGRESSBAR ) ); + opt_fill_zeroes=getFlag ( userConfig.getParameter ( OPT_FILLZEROES ) ); + opt_fnames_as_anchors=getFlag ( userConfig.getParameter ( OPT_ANCHOR_FN ) ); + opt_validate=getFlag ( userConfig.getParameter ( OPT_TEST_INPUT ) ); + opt_fnames_as_anchors=getFlag ( userConfig.getParameter ( OPT_ANCHOR_FN ) ); + opt_inline_css=getFlag ( userConfig.getParameter ( OPT_INLINE_CSS ) ); + opt_delim_CR=getFlag ( userConfig.getParameter ( OPT_EOL_DELIM_CR) ); + + if ( getFlag ( userConfig.getParameter ( OPT_WRAP ) ) ) + { + wrappingStyle=highlight::WRAP_DEFAULT; + } + if ( getFlag ( userConfig.getParameter ( OPT_WRAPSIMPLE ) ) ) + { + wrappingStyle=highlight::WRAP_SIMPLE; + } + if ( getFlag ( userConfig.getParameter ( OPT_XHTML ) ) ) + { + outputType=highlight::XHTML; + } + else if ( getFlag ( userConfig.getParameter ( OPT_RTF ) ) ) + { + outputType=highlight::RTF; + } + else if ( getFlag ( userConfig.getParameter ( OPT_TEX ) ) ) + { + outputType=highlight::TEX; + } + else if ( getFlag ( userConfig.getParameter ( OPT_LATEX ) ) ) + { + outputType=highlight::LATEX; + } + else if ( getFlag ( userConfig.getParameter ( OPT_ANSI ) ) ) + { + outputType=highlight::ANSI; + } + else if ( getFlag ( userConfig.getParameter ( OPT_XML ) ) ) + { + outputType=highlight::XML; + } + else if ( getFlag ( userConfig.getParameter ( OPT_SVG ) ) ) + { + outputType=highlight::SVG; + } + else if ( getFlag ( userConfig.getParameter ( OPT_XTERM256 ) ) ) + { + outputType=highlight::XTERM256; + } + else if ( getFlag ( userConfig.getParameter ( OPT_BBCODE) ) ) + { + outputType=highlight::BBCODE; + } + } +} + diff --git a/support/highlight/src/cli/cmdlineoptions.h b/support/highlight/src/cli/cmdlineoptions.h new file mode 100644 index 0000000000..c4cbe26b6d --- /dev/null +++ b/support/highlight/src/cli/cmdlineoptions.h @@ -0,0 +1,471 @@ +/*************************************************************************** + cmdlineoptions.h - description + ------------------- + begin : Sun Nov 25 2001 + copyright : (C) 2001-2007 by Andre Simon + email : andre.simon1@gmx.de + ***************************************************************************/ + + +/* +This file is part of Highlight. + +Highlight is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +Highlight is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Highlight. If not, see <http://www.gnu.org/licenses/>. +*/ + + +#ifndef CMDLINEOPTIONS_H +#define CMDLINEOPTIONS_H + +#ifdef _WIN32 +#include <windows.h> +#endif + +#include <string> +#include <map> +#include <set> +#include <cstdlib> +#include <iostream> +#include <fstream> +#include <vector> + +#include "stringtools.h" +#include "enums.h" + + +#define OPT_ADDCONFDIR "add-config-dir" +#define OPT_ADDDATADIR "add-data-dir" +#define OPT_ANCHORS "anchors" +#define OPT_ANCHOR_FN "anchor-filename" +#define OPT_ANCHOR_PFX "anchor-prefix" +#define OPT_ANSI "ansi" +#define OPT_BABEL "babel" +#define OPT_BASE_FONT "font" +#define OPT_BASE_FONT_SIZE "font-size" +#define OPT_BATCHREC "batch-recursive" +#define OPT_CLASSNAME "class-name" +#define OPT_DATADIR "data-dir" +#define OPT_DELTABS "replace-tabs" +#define OPT_DOC_TITLE "doc-title" +#define OPT_ENCLOSE_PRE "enclose-pre" +#define OPT_ENCODING "encoding" +#define OPT_FILLZEROES "zeroes" +#define OPT_FORCE_OUTPUT "force" +#define OPT_FORMAT "reformat" +#define OPT_FRAGMENT "fragment" +#define OPT_HELP "help" +#define OPT_HTML "html" +#define OPT_IN "input" +#define OPT_INC_STYLE "include-style" +#define OPT_INDEXFILE "print-index" +#define OPT_INLINE_CSS "inline-css" +#define OPT_KW_CASE "kw-case" +#define OPT_LATEX "latex" +#define OPT_LINENO "linenumbers" +#define OPT_LINE_LEN "line-length" +#define OPT_LISTLANGS "list-langs" +#define OPT_LISTTHEMES "list-themes" +#define OPT_LNR_LEN "line-number-length" +#define OPT_LNR_START "line-number-start" +#define OPT_MARK_LINES "mark-line" +#define OPT_ORDERED_LIST "ordered-list" +#define OPT_OUT "output" +#define OPT_OUTDIR "outdir" +#define OPT_RTF_PAGE_SIZE "page-size" +#define OPT_RTF_CHAR_STYLES "char-styles" +#define OPT_PRINT_CONFIG "print-config" +#define OPT_PROGRESSBAR "progress" +#define OPT_QUIET "quiet" +#define OPT_REPLACE_QUOTES "replace-quotes" +#define OPT_RTF "rtf" +#define OPT_STYLE "style" +#define OPT_STYLE_IN "style-infile" +#define OPT_STYLE_OUT "style-outfile" +#define OPT_SYNTAX "syntax" +#define OPT_TEST_INPUT "validate-input" +#define OPT_TEX "tex" +#define OPT_VERBOSE "verbose" +#define OPT_VERSION "version" +#define OPT_WRAP "wrap" +#define OPT_WRAPSIMPLE "wrap-simple" +#define OPT_XHTML "xhtml" +#define OPT_XML "xml" +#define OPT_XTERM256 "xterm256" +#define OPT_SVG "svg" +#define OPT_SVG_WIDTH "width" +#define OPT_SVG_HEIGHT "height" +#define OPT_SKIP_UNKNOWN "skip" +#define OPT_CTAGS_FILE "ctags-file" +#define OPT_PRETTY_SYMBOLS "pretty-symbols" +#define OPT_EOL_DELIM_CR "delim-cr" +#define OPT_BBCODE "bbcode" +#define OPT_START_NESTED "start-nested" +#define OPT_PRINT_STYLE "print-style" +#define OPT_NO_TRAILING_NL "no-trailing-nl" + +// Improve CLI option compatibility with GNU source-highlight +#define OPT_COMPAT_DOC "doc" +#define OPT_COMPAT_NODOC "no-doc" +#define OPT_COMPAT_TAB "tab" +#define OPT_COMPAT_CSS "css" +#define OPT_COMPAT_OUTDIR "output-dir" +#define OPT_COMPAT_FAILSAFE "failsafe" +#define OPT_COMPAT_OUTFORMAT "out-format" +#define OPT_COMPAT_SRCLANG "src-lang" +#define OPT_COMPAT_LINENUM "line-number" +#define OPT_COMPAT_LINEREF "line-number-ref" + +using namespace std; + +/// handle command line options + +class CmdLineOptions +{ + public: + + /**Constructor + \param argc Argument count + \param argv Argument strings + */ + CmdLineOptions ( const int argc, const char *argv[] ); + ~CmdLineOptions(); + + /** \return Single output file name*/ + const string &getSingleOutFilename(); + + /** \return Single input file name*/ + const string &getSingleInFilename() const; + + /** \return Output directory*/ + const string& getOutDirectory() ; + + /** \return Style output file name*/ + const string getStyleOutFilename() const; + + /** \return Style input file name*/ + const string& getStyleInFilename() const; + + /** \return Char set*/ + const string& getEncoding() const; + + /** \return SVG width*/ + const string& getSVGWidth() const; + + /** \return SVG height*/ + const string& getSVGHeight() const; + + /** \return Number of spaces to replace a tab*/ + int getNumberSpaces() const; + + /** \return True if version information should be printed*/ + bool printVersion() const; + + /** \return True if help information should be printed*/ + bool printHelp() const; + + /** \return True if debug information should be printed*/ + bool printDebugInfo() const; + + /** \return True if configuration information should be printed*/ + bool printConfigInfo() const; + + /** \return True if Style definition should be included in output*/ + bool includeStyleDef() const; + + /** \return True if line numbers should be printed*/ + bool printLineNumbers() const; + + /** \return True if CR is eol delimiter */ + bool useCRDelimiter() const; + + /** \return colour theme name */ + string getThemeName() const ; + + /** gibt true zurck, falls deutsche Hilfe ausgegeben werden soll */ + int helpLanguage() const; + + /** \return True if batch mode is active*/ + bool enableBatchMode() const; + + /** \return True if output shluld be fragmented*/ + bool fragmentOutput() const; + + /** \return output file suffix */ + string getOutFileSuffix() const; + + /** \return True if anchors should be attached to line numbers*/ + bool attachLineAnchors() const; + + /** \return True if list of installed themes should be printed*/ + bool showThemes() const; + + /** \return True if list of installed language definitions should be printed*/ + bool showLangdefs() const; + + /** \return True if loutput directory is given*/ + bool outDirGiven() const; + + /** \return True if refomatting is enabled*/ +// bool formattingEnabled(); + + /** \return True if a new data directory is given*/ + bool dataDirGiven() const; + + /** \return True if an additional data directory is given*/ + bool additionalDataDirGiven() const; + + /** \return True if index file should be printed*/ + bool printIndexFile() const; + + /** \return True if quotes should be replaced by /dq in LaTeX*/ + bool replaceQuotes() const; + + /** \return True if shorthands of LaTeX Babel package should be disabled*/ + bool disableBabelShorthands() const; + + /** \return True if input file name should be used as anchor name */ + bool useFNamesAsAnchors() const; + + /** \return Data directory*/ + const string &getDataDir() const; + + /** \return Additional data directory*/ + const string &getAdditionalDataDir() const; + + /** \return Additional config data directory*/ + const string &getAdditionalConfDir() const; + + /** \return path of user config file*/ + const string &getConfigFilePath() const; + + /** \return True if language syntax is given*/ + bool syntaxGiven() const; + + /** \return True if quiet mode is active*/ + bool quietMode() const; + + /** \return True if progress bar should be printed in batch mode */ + bool printProgress() const; + + /** \return True if line numbers are filled with leading zeroes */ + bool fillLineNrZeroes() const; + + /** \return programming syntax */ + const string &getLanguage() const ; + + /** \return Wrapping style*/ + highlight::WrapMode getWrappingStyle() const; + + /** \return List of input file names*/ + const vector <string> & getInputFileNames() const; + + /** \return Map of marked lines*/ + const map <int,string> &getMarkLines(); + + /** \return indentation and reformatting scheme*/ + string getIndentScheme() const; + + /** \return RTF page size */ + const string &getPageSize() const; + + /** \return Output file format */ + highlight::OutputType getOutputType() const; + + /** \return True if chosen output format supports referenced style files */ + bool formatSupportsExtStyle(); + + /** \return True if style output path was defined by user*/ + bool styleOutPathDefined() const + { + return opt_stylepath_explicit; + } + + /** \return True if encoding specification should be omitted in output*/ + bool omitEncoding() const; + + /** \return True if output should be generated if languege type is unknown*/ + bool forceOutput() const; + + /** \return True if line numbers should be replaced by ordered list (HTML) */ + bool orderedList() const; + + /** \return True if a base font has been given */ + bool hasBaseFont() const ; + + /** \return True if input should be validated */ + bool validateInput() const ; + + /** \return True if CSS should be outputted within tag elements */ + bool inlineCSS() const ; + + /** \return True if fragmented html output should be enclosed with pre tags */ + bool enclosePreTag() const ; + + /** \return True if RTF output should include character styles */ + bool includeCharStyles() const ; + + /** \return True if LaTeX output should includ fancier symbols */ + bool prettySymbols() const; + + /** \return True if style should be printed */ + bool printOnlyStyle() const; + + /** \return The given base font, empty string by default */ + const string& getBaseFont() const ; + + /** \return Document title */ + const string& getDocumentTitle() const ; + + /** \return anchor prefix */ + const string& getAnchorPrefix() const ; + + /** \return class name */ + const string& getClassName() const ; + + /** \return ctags file name */ + const string& getTagsFile() const ; + + /** \return True if a base font size has been given */ + bool hasBaseFontSize() const ; + + /** \return True if trailing nl should be omitted */ + bool disableTrailingNL() const ; + + /** \return The given base font size, empty string by default */ + const string& getBaseFontSize() const ; + + /** \return name of nested syntax which starts the input */ + const string& getStartNestedLang() const ; + + /** \return line number width */ + int getNumberWidth(); + + /** \return line length */ + int getLineLength(); + + /** \return Line number start count */ + int getNumberStart(); + + /** \return Keyword Case (upper, lower, unchanged) */ + StringTools::KeywordCase getKeywordCase() const; + + bool isSkippedExt ( const string& ext ) + { + return ignoredFileTypes.count ( ext ); + } + + private: + + int numberSpaces; // number of spaces which replace a tab + int lineNrWidth; // width of line number (left padding) + int lineLength; // length of line before wrapping + int lineNrStart; // line number start count + highlight::WrapMode wrappingStyle; // line wrapping mode + highlight::OutputType outputType; + StringTools::KeywordCase keywordCase; + + // name of single output file + string outFilename, + // output directory + outDirectory, + // programming syntax which will be loaded + syntax, + // name of colour theme + styleName, + // name of external style file + styleOutFilename, + // name of file to be included in external style file + styleInFilename, + // used to define data directories at runtime + dataDir, additionalDataDir, additionalConfigDir; + // name of indenation scheme + string indentScheme, + pageSize, startNestedLang; + + string baseFont, baseFontSize; + string docTitle, className; + string markLinesArg; + string skipArg; + string svg_height, svg_width; + string ctagsFile; + + bool opt_syntax; + bool opt_include_style; + bool opt_help; + bool opt_version ; + bool opt_verbose; + bool opt_print_config; + bool opt_linenumbers; + bool opt_style; + bool opt_batch_mode; + bool opt_fragment; + bool opt_attach_line_anchors; + bool opt_show_themes; + bool opt_show_langdefs; + bool opt_asformat_output; + bool opt_printindex; + bool opt_quiet; + bool opt_replacequotes; + bool opt_babel; + bool opt_print_progress; + bool opt_fill_zeroes; + bool opt_stylepath_explicit; + bool opt_force_output; + bool opt_ordered_list; + bool opt_fnames_as_anchors; + bool opt_validate; + bool opt_inline_css; + bool opt_enclose_pre; + bool opt_char_styles; + bool opt_pretty_symbols; + bool opt_delim_CR; + bool opt_print_style; + bool opt_no_trailing_nl; + + bool configFileRead; + + string anchorPrefix; + + string helpLang, encodingName; + string configFilePath; + + /** list of all input file names */ + vector <string> inputFileNames; + + /** list lines which should be marked and supplied with help string */ + map <int, string> markLines; + + /** list of file types which should be ignored */ + set <string> ignoredFileTypes; + + /** load highlight configuration file */ + void loadConfigurationFile(); + + /** \return file suffix */ + string getFileSuffix ( const string & fileName ) const; + + /** \return directory name of path */ + string getDirName ( const string & path ); + + /** get all entries in the directory defined by wildcard */ + void readDirectory ( const string & wildcard ); + + /** \return Boolean value of paramVal */ + bool getFlag ( const string& paramVal ); + + /** \return Valid path name */ + string validateDirPath ( const string & path ); +}; + +#endif diff --git a/support/highlight/src/cli/help.cpp b/support/highlight/src/cli/help.cpp new file mode 100644 index 0000000000..d80312a7a9 --- /dev/null +++ b/support/highlight/src/cli/help.cpp @@ -0,0 +1,185 @@ +/*************************************************************************** + help.cpp - description + ------------------- + begin : Die Apr 23 2002 + copyright : (C) 2002-2007 by Andre Simon + email : andre.simon1@gmx.de + ***************************************************************************/ + + +/* +This file is part of Highlight. + +Highlight is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +Highlight is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Highlight. If not, see <http://www.gnu.org/licenses/>. +*/ + + +#include <iostream> + +#include "help.h" + +using namespace std; + +namespace Help +{ + + void printHelp() + { + cout<<"USAGE: highlight [OPTIONS]... [FILES]...\n"; + cout<<"\n"; + cout<<"General options:\n"; + cout<<"\n"; + cout<<" -B, --batch-recursive=<wc> convert all matching files, searches subdirs\n"; + cout<<" (Example: -B '*.cpp')\n"; + cout<<" -D, --data-dir=<directory> set path to data directory\n"; + cout<<" -E, --add-data-dir=<directory> set path to an additional data directory, which\n"; + cout<<" is searched first\n"; + cout<<" --add-config-dir=<dir> set path to an additional config directory\n"; + cout<<" -h, --help print this help\n"; + cout<<" -i, --input=<file> name of single input file\n"; + cout<<" -o, --output=<file> name of single output file\n"; + cout<<" -O, --outdir=<directory> name of output directory\n"; + cout<<" -p, --list-langs list installed language definitions\n"; + cout<<" -P, --progress print progress bar in batch mode\n"; + cout<<" -q, --quiet supress progress info in batch mode\n"; + cout<<" -S, --syntax=<type> specify type of source code\n"; + cout<<" -v, --verbose print debug info\n"; + cout<<" -w, --list-themes list installed colour themes\n"; + cout<<" --force generate output if language type is unknown\n"; + cout<<" --print-config print path configuration\n"; + cout<<" --print-style print only style (see --style-outfile)\n"; + cout<<" --skip=<list> ignore listed unknown file types\n"; + cout<<" (Example: --skip='bak;c~;h~')\n"; + cout<<" --start-nested=<lang> define nested language which starts input\n"; + cout<<" without opening delimiter\n"; + cout<<" --validate-input test if input is a valid text file\n"; + cout<<" --version print version and copyright information\n"; + cout<<"\n"; + cout<<"\n"; + cout<<"Output formats:\n"; + cout<<"\n"; + cout<<" -H, --html generate HTML (default)\n"; + cout<<" -A, --ansi generate terminal output (16 colours)\n"; + cout<<" -L, --latex generate LaTeX\n"; + cout<<" -M, --xterm256 generate terminal output (256 colours)\n"; + cout<<" -R, --rtf generate RTF\n"; + cout<<" -T, --tex generate TeX\n"; + cout<<" -X, --xhtml generate XHTML 1.1\n"; + cout<<" -Z, --xml generate XML\n"; + cout<<" -G, --svg generate SVG (experimental)\n"; + cout<<" -Y, --bbcode generate BBCode (experimental)\n"; + cout<<" --out-format=<format> output file in given format\n"; + cout<<" <format>: see long options above\n"; + cout<<"\n"; + cout<<"\n"; + cout<<"Output formatting options:\n"; + cout<<"\n"; + cout<<" -c, --style-outfile=<file> name of style file or output to stdout, if\n"; + cout<<" 'stdout' is given as file argument\n"; + cout<<" -d, --doc-title=<title> document title\n"; + cout<<" -e, --style-infile=<file> file to be included in style-outfile\n"; + cout<<" -I, --include-style include style definition\n"; + cout<<" -f, --fragment omit file header and footer\n"; + cout<<" -F, --reformat=<style> reformats and indents output in given style\n"; + cout<<" <style>=['allman', 'banner', 'gnu',\n"; + cout<<" 'horstmann', 'java', 'kr', 'linux', 'otbs',\n"; + cout<<" 'stroustrup', 'whitesmith']\n"; + cout<<" -J, --line-length=<num> line length before wrapping (see -W, -V)\n"; + cout<<" -j, --line-number-length=<num> line number width incl. left padding\n"; + cout<<" -k, --font=<font> set font (specific to output format)\n"; + cout<<" -K, --font-size=<num?> set font size (specific to output format)\n"; + cout<<" -l, --linenumbers print line numbers in output file\n"; + cout<<" -m, --line-number-start=<cnt> start line numbering with cnt (assumes -l)\n"; + cout<<" -s, --style=<style> set colour style (see -w)\n"; + cout<<" -t, --replace-tabs=<num> replace tabs by <num> spaces\n"; + cout<<" -u, --encoding=<enc> set output encoding which matches input file\n"; + cout<<" encoding; omit encoding info if enc=NONE\n"; + cout<<" -V, --wrap-simple wrap long lines without indenting function\n"; + cout<<" parameters and statements\n"; + cout<<" -W, --wrap wrap long lines\n"; + cout<<" -z, --zeroes fill leading space of line numbers with 0's\n"; + cout<<" --kw-case=<case> change case of case insensitive keywords\n"; + cout<<" <case> = ['upper', 'lower', 'capitalize']\n"; + cout<<" --delim-cr set CR as end-of-line delimiter (MacOS 9)\n"; + cout<<" --no-trailing-nl omit trailing newline\n"; + cout<<"\n"; + cout<<"(X)HTML output options:\n"; + cout<<"\n"; + cout<<" -a, --anchors attach anchor to line numbers\n"; + cout<<" -y, --anchor-prefix=<str> set anchor name prefix\n"; + cout<<" -N, --anchor-filename use input file name as anchor name\n"; + cout<<" -C, --print-index print index with hyperlinks to output files\n"; + cout<<" -n, --ordered-list print lines as ordered list items\n"; + cout<<" --class-name=<str> set CSS class name prefix\n"; + cout<<" --inline-css output CSS within each tag (verbose output)\n"; + cout<<" --mark-line='n[=txt]; m' mark given lines n..m and add optional help\n"; + cout<<" texts as tooltips\n"; + cout<<" --enclose-pre enclose fragmented output with pre tag \n"; + cout<<" (assumes -f)\n"; + cout<<" --ctags-file[=<file>] read ctags file to include meta information as\n"; + cout<<" tooltips (default value: tags)\n"; + cout<<"\n"; + cout<<"LaTeX output options:\n"; + cout<<"\n"; + cout<<" -b, --babel disable Babel package shorthands\n"; + cout<<" -r, --replace-quotes replace double quotes by \\dq{}\n"; + cout<<" --pretty-symbols improve appearance of brackets and other symbols\n"; + cout<<"\n"; + cout<<"\n"; + cout<<"RTF output options:\n"; + cout<<"\n"; + cout<<" -x, --page-size=<ps> set page size \n"; + cout<<" <ps> = [a3, a4, a5, b4, b5, b6, letter]\n"; + cout<<" --char-styles include character stylesheets\n"; + cout<<"\n"; + cout<<"\n"; + cout<<"SVG output options:\n"; + cout<<"\n"; + cout<<" --height set image height (units allowed)\n"; + cout<<" --width set image width (see --height)\n"; + cout<<"\n"; + cout<<"\n"; + cout<<"GNU source-highlight compatibility options:\n"; + cout<<"\n"; + cout<<" --doc create stand alone document\n"; + cout<<" --no-doc cancel the --doc option\n"; + cout<<" --css=filename the external style sheet filename\n"; + cout<<" --src-lang=STRING source language\n"; + cout<<" -t, --tab=INT specify tab length\n"; + cout<<" -n, --line-number[=0] number all output lines, optional padding\n"; + cout<<" --line-number-ref[=p] number all output lines and generate an anchor,\n"; + cout<<" made of the specified prefix p + the line\n"; + cout<<" number (default='line')\n"; + cout<<" --output-dir=path output directory\n"; + cout<<" --failsafe if no language definition is found for the\n"; + cout<<" input, it is simply copied to the output\n"; + cout<<"\n"; + cout<<"\n"; + cout<<"-t will be ignored if -F is set.\n"; + cout<<"-i and -o will be ignored if -b or -B is set.\n"; + cout<<"-r will be ignored if -f is not set.\n"; + cout<<"-c will be ignored if the output format does not support referenced styles.\n"; + cout<<"If no in- or output files are specified, stdin and stdout will be used for\n"; + cout<<"in- or output.\n"; + cout<<"HTML will be generated, if no other output format is given. Style definitions\n"; + cout<<"are stored in highlight.css (HTML, XHTML, SVG) or highlight.sty (LaTeX, TeX)\n"; + cout<<"if neither -c nor -I is given.\n"; + cout<<"Reformatting code will only work with C, C++, C# and Java input files.\n"; + cout<<"Wrapping lines with -V or -W will cause faulty highlighting of long single\n"; + cout<<"line comments and directives. Use with caution.\n"; + cout<<"\n"; + cout<<"Updates and information: http://www.andre-simon.de/\n"; + } + +} diff --git a/support/highlight/src/cli/help.h b/support/highlight/src/cli/help.h new file mode 100644 index 0000000000..e4500d679c --- /dev/null +++ b/support/highlight/src/cli/help.h @@ -0,0 +1,42 @@ +/*************************************************************************** + help.h - description + ------------------- + begin : Die Apr 23 2002 + copyright : (C) 2002-2007 by Andre Simon + email : andre.simon1@gmx.de + ***************************************************************************/ + + +/* +This file is part of Highlight. + +Highlight is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +Highlight is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Highlight. If not, see <http://www.gnu.org/licenses/>. +*/ + + +#ifndef HELP_H +#define HELP_H + +#include <string> + +///Contains methods for printing help messages + +namespace Help +{ + /** print help message to stdout + */ + void printHelp(); +} + +#endif diff --git a/support/highlight/src/cli/main.cpp b/support/highlight/src/cli/main.cpp new file mode 100644 index 0000000000..cb2030fdf5 --- /dev/null +++ b/support/highlight/src/cli/main.cpp @@ -0,0 +1,709 @@ +/*************************************************************************** + main.cpp - description + ------------------- + begin : Die Apr 23 22:16:35 CEST 2002 + copyright : (C) 2002-2009 by Andre Simon + email : andre.simon1@gmx.de + + Highlight is a universal source code to HTML converter. Syntax highlighting + is formatted by Cascading Style Sheets. It's possible to easily enhance + highlight's parsing database. + + ***************************************************************************/ + + +/* +This file is part of Highlight. + +Highlight is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +Highlight is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Highlight. If not, see <http://www.gnu.org/licenses/>. +*/ + + +#include <memory> +#include <algorithm> +#include "main.h" +#include "re/Pattern.h" + +#define MAX_LINE__WIDTH 80 + +using namespace std; + +void HLCmdLineApp::printVersionInfo() +{ + cout << "\n highlight version " + << HIGHLIGHT_VERSION + << "\n Copyright (C) 2002-2010 Andre Simon <andre.simon1 at gmx.de>" + << "\n\n Artistic Style Classes (1.24)" + << "\n Copyright (C) 2006-2010 by Jim Pattee <jimp03 at email.com>" + << "\n Copyright (C) 1998-2002 by Tal Davidson" + << "\n\n Regex library (1.09.00)" + << "\n Copyright (C) 2003-2008 Jeffery Stuart <stuart at cs.unr.edu>" + << "\n\n xterm 256 color matching functions" + << "\n Copyright (C) 2006 Wolfgang Frisch <wf at frexx.de>" + << "\n\n Argparser class" + << "\n Copyright (C) 2006-2008 Antonio Diaz Diaz <ant_diaz at teleline.es>" + << "\n\n This software is released under the terms of the GNU General " + << "Public License." + << "\n For more information about these matters, see the file named " + << "COPYING.\n\n"; +} + +void HLCmdLineApp::printBadInstallationInfo() +{ + cerr << "highlight: Data directory not found ("<<DataDir::LSB_DATA_DIR<<")." + " Bad installation or wrong "<< OPT_DATADIR << " parameter." + << "\n\nCopy the highlight files into one of the directories listed " + << "in INSTALL.\nYou may also set the data directory with " + << OPT_DATADIR << " and " << OPT_ADDDATADIR << ".\n"; +} + +bool HLCmdLineApp::printInstalledThemes() +{ + vector <string> filePaths; + string wildcard="*.style"; + string directory= dataDir.getThemePath(); + string searchDir = directory + wildcard; + + bool directoryOK = Platform::getDirectoryEntries ( filePaths, searchDir, true ); + if ( !directoryOK ) + { + cerr << "highlight: Could not access directory " + << searchDir + << ", aborted.\n"; + return false; + } + + cout << "\nInstalled themes" + << " (located in " << directory << "):\n\n"; + + sort ( filePaths.begin(), filePaths.end() ); + string temp; + + for ( unsigned int i=0;i< filePaths.size(); i++ ) + { + temp = ( filePaths[i] ).substr ( directory.length() ); + cout <<temp.substr ( 1, temp.length()- wildcard.length() ) << endl; + } + cout <<"\nUse name of the desired theme" + << " with the --" OPT_STYLE " option.\n" << endl; + return true; +} + + +bool HLCmdLineApp::printInstalledLanguages() +{ + vector <string> filePaths; + string wildcard="*.lang"; + string directory=dataDir.getLangPath(); + string searchDir = directory + wildcard; + + bool directoryOK = Platform::getDirectoryEntries ( filePaths, searchDir, true ); + if ( !directoryOK ) + { + cerr << "highlight: Could not access directory " + << searchDir + << ", aborted.\n"; + return false; + } + + sort ( filePaths.begin(), filePaths.end() ); + string suffix, desc; + cout << "\nInstalled language definitions" + << " (located in " << directory << "):\n\n"; + + for ( unsigned int i=0;i< filePaths.size(); i++ ) + { + ConfigurationReader lang ( filePaths[i] ); + desc = lang.getParameter ( "description" ); + suffix = ( filePaths[i] ).substr ( directory.length() ) ; + suffix = suffix.substr ( 1, suffix.length()- wildcard.length() ); + cout << setw ( 20 ) <<setiosflags ( ios::left ) <<desc<<": "<<suffix; + int extCnt=0; + for (StringMap::iterator it=extensions.begin();it!=extensions.end();it++) { + if (it->second==suffix ) { + + cout << ((++extCnt==1)?" ( ":" ")<<it->first; + } + } + cout << ((extCnt)?" )":"")<<endl; + } + cout <<"\nUse name of the desired language" + << " with the --" OPT_SYNTAX " option.\n" << endl; + return true; +} + +void HLCmdLineApp::printDebugInfo ( const highlight::LanguageDefinition &lang, + const string & langDefPath ) +{ + cerr << "\nLoading language definition:\n" << langDefPath; + cerr << "\n\nDescription: " << lang.getDescription(); + cerr << "\n\nSYMBOLS (followed by states):\n" << lang.getSymbolString(); + cerr << "\n\nREGEX:\n"; + highlight::RegexElement *re=NULL; + for ( unsigned int i=0; i<lang.getRegexElements().size(); i++ ) + { + re = lang.getRegexElements() [i]; + cerr << "State "<<re->open<<":\t"<<re->rePattern->getPattern() <<"\n"; + } + cerr << "\nKEYWORDS:\n"; + highlight::KeywordMap::iterator it; + highlight::KeywordMap keys=lang.getKeywords(); + for ( it=keys.begin(); it!=keys.end(); it++ ) + { + cerr << " "<< it->first << "("<< it->second << ")"; + } + cerr <<"\n\n"; +} + +void HLCmdLineApp::printConfigInfo ( const string& configFile ) +{ + cout << "\nRoot paths (modify with --" OPT_DATADIR " and --" OPT_ADDDATADIR "):\n"; + cout << " Data directory: "<<dataDir.getDir() <<"\n"; + if ( !dataDir.getAdditionalDataDir().empty() ) + cout << " User defined directory: "<<dataDir.getAdditionalDataDir() <<"\n"; + cout << "\nDefault search paths:\n"; + cout << " Language definitions: "<<dataDir.getLangPath ( "", true ) <<"\n"; + cout << " Colour themes: "<<dataDir.getThemePath ( "", true ) <<"\n"; + + if ( !dataDir.getAdditionalDataDir().empty() ) + { + cout << "\nAdditional search paths:\n"; + cout << " Language definitions: "<<dataDir.getAdditionalLangDefDir() <<"\n"; + cout << " Colour themes: "<<dataDir.getAdditionalThemeDir() <<"\n"; +// cout << " Indentation schemes: "<<dataDir.getAdditionalIndentSchemesDir()<<"\n"; + } + + cout << "\nConfiguration paths:\n"; + cout << " Configuration files: "<<dataDir.getConfDir ( true ) <<"\n"; + cout << " User configuration: "<<configFile<<"\n"; + if ( !dataDir.getAdditionalConfDir().empty() ) + { + cout << "\nAdditional search paths:\n"; + cout << " Configuration files: "<<dataDir.getAdditionalConfDir() <<"\n"; + } + cout << endl; +#ifdef HL_DATA_DIR + cout << "Compiler directive HL_DATA_DIR = " <<HL_DATA_DIR<< "\n"; +#endif +#ifdef HL_CONFIG_DIR + cout << "Compiler directive HL_CONFIG_DIR = " <<HL_CONFIG_DIR<< "\n"; +#endif + + cout << endl; +} + +string HLCmdLineApp::getFileSuffix ( const string &fileName ) +{ + size_t ptPos=fileName.rfind ( "." ); + return ( ptPos == string::npos ) ? "" : fileName.substr ( ptPos+1, fileName.length() ); +} + +bool HLCmdLineApp::loadFileTypeConfig ( const string& name, StringMap* extMap, StringMap* shebangMap ) +{ + if ( !extMap || !shebangMap ) return false; + string confPath=dataDir.getConfDir() + name + ".conf"; + ConfigurationReader config ( confPath ); + if ( config.found() ) + { + stringstream values; + string paramName, paramVal; + for ( unsigned int i=0;i<config.getParameterNames().size();i++ ) + { + paramName = config.getParameterNames() [i]; + + if ( paramName.find ( "ext" ) != string::npos ) + { + values.str ( StringTools::change_case ( config.getParameter ( paramName ) ) ); + paramName = StringTools::getParantheseVal ( paramName ); + while ( values >> paramVal ) + { + extMap->insert ( make_pair ( paramVal, paramName ) ); + } + values.clear(); + } + else if ( paramName.find ( "shebang" ) != string::npos ) + { + values.str ( config.getParameter ( paramName ) ) ; + paramName = StringTools::getParantheseVal ( paramName ); + while ( values >> paramVal ) + { + shebangMap->insert ( make_pair ( paramVal, paramName ) ); + } + values.clear(); + } + } + return true; + } + else + { + cerr << "highlight: Configuration file "<< confPath << " not found.\n"; + return false; + } +} + + +int HLCmdLineApp::getNumDigits ( int i ) +{ + int res=0; + while ( i ) + { + i/=10; + ++res; + } + return res; +} + +void HLCmdLineApp::printProgressBar ( int total, int count ) +{ + if ( !total ) return; + int p=100*count / total; + int numProgressItems=p/10; + cout << "\r["; + for ( int i=0;i<10;i++ ) + { + cout << ( ( i<numProgressItems ) ?"#":" " ); + } + cout<< "] " <<setw ( 3 ) <<p<<"%, "<<count << " / " << total << " " <<flush; + if ( p==100 ) + { + cout << endl; + } +} + +void HLCmdLineApp::printCurrentAction ( const string&outfilePath, + int total, int count, int countWidth ) +{ + cout << "Writing file " + << setw ( countWidth ) << count + << " of " + << total + << ": " + << outfilePath + << "\n"; +} + +void HLCmdLineApp::printIOErrorReport ( unsigned int numberErrorFiles, + vector<string> & fileList, + const string &action ) +{ + cerr << "highlight: Could not " + << action + << " file" + << ( ( numberErrorFiles>1 ) ?"s":"" ) <<":\n"; + copy ( fileList.begin(), fileList.end(), ostream_iterator<string> ( cerr, "\n" ) ); + if ( fileList.size() < numberErrorFiles ) + { + cerr << "... [" + << ( numberErrorFiles - fileList.size() ) + << " of " + << numberErrorFiles + << " failures not shown, use --" + << OPT_VERBOSE + << " switch to print all failures]\n"; + } +} + +string HLCmdLineApp::analyzeFile ( const string& file ) +{ + string firstLine; + + if ( !file.empty() ) + { + ifstream inFile ( file.c_str() ); + getline ( inFile, firstLine ); + } + else + { + // This copies all the data to a new buffer, uses the data to get the + // first line, then makes cin use the new buffer that underlies the + // stringstream instance + cin_bufcopy << cin.rdbuf(); + getline ( cin_bufcopy, firstLine ); + cin_bufcopy.seekg ( 0, ios::beg ); + cin.rdbuf ( cin_bufcopy.rdbuf() ); + } + StringMap::iterator it; + for ( it=scriptShebangs.begin(); it!=scriptShebangs.end();it++ ) + { + if ( Pattern::matches ( it->first, firstLine ) ) return it->second; + } + return ""; +} + +string HLCmdLineApp::guessFileType ( const string& suffix, const string &inputFile ) +{ + string lcSuffix = StringTools::change_case ( suffix ); + string fileType = ( extensions.count ( lcSuffix ) ) ? extensions[lcSuffix] : lcSuffix ; + if ( !fileType.empty() ) return fileType; + return analyzeFile ( inputFile ); +} + + +int HLCmdLineApp::run ( const int argc, const char*argv[] ) +{ + + CmdLineOptions options ( argc, argv ); + + // set data directory path, where /langDefs and /themes reside + string dataDirPath = ( options.getDataDir().empty() ) ? Platform::getAppPath() :options.getDataDir(); + + if ( options.printVersion() ) + { + printVersionInfo(); + return EXIT_SUCCESS; + } + + + + + dataDir.setAdditionalDataDir ( options.getAdditionalDataDir() ); + dataDir.setAdditionalConfDir ( options.getAdditionalConfDir() ); + + if ( ! dataDir.searchDataDir ( dataDirPath ) ) + { + printBadInstallationInfo(); + return EXIT_FAILURE; + } + + if ( options.printHelp() ) + { + Help::printHelp(); + return EXIT_SUCCESS; + } + + if ( options.printConfigInfo() ) + { + printConfigInfo ( options.getConfigFilePath() ); + return EXIT_SUCCESS; + } + + if ( options.showThemes() ) + { + return printInstalledThemes() ?EXIT_SUCCESS:EXIT_FAILURE; + } + + //call before printInstalledLanguages! + loadFileTypeConfig ( "filetypes", &extensions, &scriptShebangs ); + + if ( options.showLangdefs() ) + { + return printInstalledLanguages() ?EXIT_SUCCESS:EXIT_FAILURE; + } + + const vector <string> inFileList=options.getInputFileNames(); + + if ( options.enableBatchMode() && inFileList[0].empty() ) + { + return EXIT_FAILURE; + } + + string themePath=dataDir.getThemePath ( options.getThemeName() ); + + auto_ptr<highlight::CodeGenerator> generator ( highlight::CodeGenerator::getInstance ( options.getOutputType() ) ); + + + generator->setHTMLAttachAnchors ( options.attachLineAnchors() ); + generator->setHTMLOrderedList ( options.orderedList() ); + generator->setHTMLInlineCSS ( options.inlineCSS() ); + generator->setHTMLEnclosePreTag ( options.enclosePreTag() ); + generator->setHTMLAnchorPrefix ( options.getAnchorPrefix() ); + generator->setHTMLClassName ( options.getClassName() ); + + generator->setLATEXReplaceQuotes ( options.replaceQuotes() ); + generator->setLATEXNoShorthands ( options.disableBabelShorthands() ); + generator->setLATEXPrettySymbols ( options.prettySymbols() ); + + generator->setRTFPageSize ( options.getPageSize() ); + generator->setRTFCharStyles ( options.includeCharStyles() ); + + generator->setSVGSize ( options.getSVGWidth(), options.getSVGHeight() ); + + if (options.useCRDelimiter()) + generator->setEOLDelimiter('\r'); + + generator->setValidateInput ( options.validateInput() ); + generator->setStyleInputPath ( options.getStyleInFilename() ); + generator->setStyleOutputPath ( options.getStyleOutFilename() ); + generator->setIncludeStyle ( options.includeStyleDef() ); + generator->setPrintLineNumbers ( options.printLineNumbers(), options.getNumberStart() ); + generator->setPrintZeroes ( options.fillLineNrZeroes() ); + generator->setFragmentCode ( options.fragmentOutput() ); + generator->setPreformatting ( options.getWrappingStyle(), + ( generator->getPrintLineNumbers() ) ? + options.getLineLength() - options.getNumberWidth() : options.getLineLength(), + options.getNumberSpaces() ); + + generator->setEncoding ( options.getEncoding() ); + generator->setBaseFont ( options.getBaseFont() ) ; + generator->setBaseFontSize ( options.getBaseFontSize() ) ; + generator->setLineNumberWidth ( options.getNumberWidth() ); + generator->setStartingNestedLang( options.getStartNestedLang()); + generator->disableTrailingNL(options.disableTrailingNL()); + + bool styleFileWanted = !options.fragmentOutput() || options.styleOutPathDefined(); + + if ( !generator->initTheme ( themePath ) ) + { + cerr << "highlight: Could not find style " + << themePath + << ".\n"; + return EXIT_FAILURE; + } + + if ( options.printOnlyStyle() ) + { + if (!options.formatSupportsExtStyle()){ + cerr << "highlight: output format supports no external styles.\n"; + return EXIT_FAILURE; + } + bool useStdout = options.getStyleOutFilename() =="stdout"; + string cssOutFile=options.getOutDirectory() + options.getStyleOutFilename(); + bool success=generator->printExternalStyle ( useStdout?"":cssOutFile ); + if ( !success ) + { + cerr << "highlight: Could not write " << cssOutFile <<".\n"; + return EXIT_FAILURE; + } + return EXIT_SUCCESS; + } + + bool formattingEnabled = generator->initIndentationScheme ( options.getIndentScheme() ); + + if ( !formattingEnabled && !options.getIndentScheme().empty() ) + { + cerr << "highlight: Undefined indentation scheme " + << options.getIndentScheme() + << ".\n"; + return EXIT_FAILURE; + } + + if ( !options.getTagsFile().empty() ) + { + if ( !generator->initTagInformation ( options.getTagsFile() ) ) + { + cerr << "highlight: Could not load ctags file " + << options.getTagsFile() + << ".\n"; + return EXIT_FAILURE; + } + } + + string outDirectory = options.getOutDirectory(); +#ifndef WIN32 + ifstream dirTest ( outDirectory.c_str() ); + if ( !outDirectory.empty() && !options.quietMode() && !dirTest ) + { + cerr << "highlight: Output directory \"" + << outDirectory + << "\" does not exist.\n"; + return EXIT_FAILURE; + } + dirTest.close(); +#endif + + map <int,string> markedLines = options.getMarkLines(); + if ( !markedLines.empty() ) + { + map<int, string>::iterator it; + for ( it=markedLines.begin(); it!=markedLines.end();it++ ) + { + generator->addMarkedLine ( it->first, it->second ); + } + } + + bool initError=false, IOError=false; + unsigned int fileCount=inFileList.size(), + fileCountWidth=getNumDigits ( fileCount ), + i=0, + numBadFormatting=0, + numBadInput=0, + numBadOutput=0; + + vector<string> badFormattedFiles, badInputFiles, badOutputFiles; + string inFileName, outFilePath; + string suffix, lastSuffix; + + if ( options.syntaxGiven() ) // user defined language definition, valid for all files + { + suffix = guessFileType ( options.getLanguage() ); + } + + while ( i < fileCount && !initError ) + { + if ( !options.syntaxGiven() ) // determine file type for each file + { + suffix = guessFileType ( getFileSuffix ( inFileList[i] ), inFileList[i] ); + } + if ( suffix.empty() ) + { + if ( !options.enableBatchMode() ) + cerr << "highlight: Undefined language definition. Use --" + << OPT_SYNTAX << " option.\n"; + if ( !options.forceOutput() ) + { + initError = true; + break; + } + } + + if ( suffix != lastSuffix ) + { + string langDefPath=dataDir.getLangPath ( suffix+".lang" ); + highlight::LoadResult loadRes= generator->loadLanguage ( langDefPath ); + if ( loadRes==highlight::LOAD_FAILED_REGEX ) + { + cerr << "highlight: Regex error ( " + << generator->getLanguage().getFailedRegex() + << " ) in "<<suffix<<".lang\n"; + initError = true; + break; + } + else if ( loadRes==highlight::LOAD_FAILED ) + { + // do also ignore error msg if --syntax parameter should be skipped + if ( ! (options.quietMode() || options.isSkippedExt ( suffix )) ) + { + cerr << "highlight: Unknown source file extension \"" + << suffix + << "\".\n"; + } + if ( !options.forceOutput() ) + { + initError = true; + break; + } + } + if ( options.printDebugInfo() && loadRes==highlight::LOAD_NEW ) + { + printDebugInfo ( generator->getLanguage(), langDefPath ); + } + lastSuffix = suffix; + } + + string::size_type pos= ( inFileList[i] ).find_last_of ( Platform::pathSeparator ); + inFileName = inFileList[i].substr ( pos+1 ); + + if ( options.enableBatchMode() ) + { + outFilePath = outDirectory; + outFilePath += inFileName; + outFilePath += options.getOutFileSuffix(); + + if ( !options.quietMode() ) + { + if ( options.printProgress() ) + { + printProgressBar ( fileCount, i+1 ); + } + else + { + printCurrentAction ( outFilePath, fileCount, i+1, fileCountWidth ); + } + } + } + else + { + outFilePath = options.getSingleOutFilename(); + if ( outFilePath.size() && outFilePath==options.getSingleInFilename() ) + { + cerr << "highlight: Output path equals input path: \"" + << outFilePath << "\".\n"; + initError = true; + break; + } + + } + + if ( options.useFNamesAsAnchors() ) + { + generator->setHTMLAnchorPrefix ( inFileName ); + } + + generator->setTitle ( options.getDocumentTitle().empty() ? + inFileList[i]:options.getDocumentTitle() ); + + generator->setKeyWordCase ( options.getKeywordCase() ); + + highlight::ParseError error = generator->generateFile ( inFileList[i], outFilePath ); + + if ( error==highlight::BAD_INPUT ) + { + if ( numBadInput++ < IO_ERROR_REPORT_LENGTH || options.printDebugInfo() ) + { + badInputFiles.push_back ( inFileList[i] ); + } + } + else if ( error==highlight::BAD_OUTPUT ) + { + if ( numBadOutput++ < IO_ERROR_REPORT_LENGTH || options.printDebugInfo() ) + { + badOutputFiles.push_back ( outFilePath ); + } + } + if ( formattingEnabled && !generator->formattingIsPossible() ) + { + if ( numBadFormatting++ < IO_ERROR_REPORT_LENGTH || options.printDebugInfo() ) + { + badFormattedFiles.push_back ( outFilePath ); + } + } + ++i; + } + + + if ( i && !options.includeStyleDef() + && styleFileWanted + && options.formatSupportsExtStyle() ) + { + string cssOutFile=outDirectory + options.getStyleOutFilename(); + bool success=generator->printExternalStyle ( cssOutFile ); + if ( !success ) + { + cerr << "highlight: Could not write " << cssOutFile <<".\n"; + IOError = true; + } + } + + if ( i && options.printIndexFile() ) + { + bool success=generator -> printIndexFile ( inFileList, outDirectory ); + if ( !success ) + { + cerr << "highlight: Could not write index file.\n"; + IOError = true; + } + } + + if ( numBadInput ) + { + printIOErrorReport ( numBadInput, badInputFiles, "read input" ); + IOError = true; + } + if ( numBadOutput ) + { + printIOErrorReport ( numBadOutput, badOutputFiles, "write output" ); + IOError = true; + } + if ( numBadFormatting ) + { + printIOErrorReport ( numBadFormatting, badFormattedFiles, "reformat" ); + } + return ( initError || IOError ) ? EXIT_FAILURE : EXIT_SUCCESS; +} + +int main ( const int argc, const char *argv[] ) +{ + HLCmdLineApp app; + return app.run ( argc, argv ); +} diff --git a/support/highlight/src/cli/main.h b/support/highlight/src/cli/main.h new file mode 100644 index 0000000000..2839e5c9fd --- /dev/null +++ b/support/highlight/src/cli/main.h @@ -0,0 +1,117 @@ + +/* +This file is part of Highlight. + +Highlight is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +Highlight is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Highlight. If not, see <http://www.gnu.org/licenses/>. +*/ + + +#ifndef HIGHLIGHT_APP +#define HIGHLIGHT_APP + + +#include <iostream> +#include <fstream> +#include <string> +#include <vector> +#include <map> +#include <iomanip> +#include <cassert> + +//#include "./dirstream0.4/dirstream.h" +#include "cmdlineoptions.h" +#include "configurationreader.h" +#include "codegenerator.h" +#include "help.h" +#include "datadir.h" +#include "version.h" +#include "platform_fs.h" + +#define IO_ERROR_REPORT_LENGTH 5 +#define SHEBANG_CNT 12 + +typedef map<string, string> StringMap; + +/// Main application class of the command line interface + +class HLCmdLineApp +{ + + public: + + HLCmdLineApp() {}; + ~HLCmdLineApp() {}; + + /** Start application + \param argc Number of command line arguments + \param argv values of command line arguments + \return EXIT_SUCCESS or EXIT_FAILURE + */ + int run ( const int argc, const char *argv[] ); + + private: + + DataDir dataDir; + StringMap extensions; + StringMap scriptShebangs; + stringstream cin_bufcopy; + + /** print version info*/ + void printVersionInfo(); + + /** print configuration info*/ + void printConfigInfo ( const string& ); + + /** print error message*/ + void printBadInstallationInfo(); + + /** print input and output errors */ + void printIOErrorReport ( unsigned int numberErrorFiles, vector<string> & fileList, const string &action ); + + /** list installed theme files + \return true if theme files were found + */ + bool printInstalledThemes(); + + /** list installed language definition files + \return true if lang files were found + */ + bool printInstalledLanguages(); + + /** print debug information + \param lang language definition + \param langDefPath path to language definition + */ + void printDebugInfo ( const highlight::LanguageDefinition &lang, + const string &langDefPath ); + + string getFileSuffix ( const string &fileName ); + + string guessFileType ( const string &suffix, const string &inputFile="" ); + + int getNumDigits ( int i ); + + void printProgressBar ( int total, int count ); + void printCurrentAction ( const string&outfilePath, + int total, int count, int countWidth ); + + bool readInputFilePaths ( vector<string> &fileList, string wildcard, + bool recursiveSearch ); + + string analyzeFile ( const string& file ); + bool loadFileTypeConfig ( const string& name, StringMap* map, StringMap* shebangMap ); + +}; + +#endif diff --git a/support/highlight/src/core/ansigenerator.cpp b/support/highlight/src/core/ansigenerator.cpp new file mode 100644 index 0000000000..5c3133619a --- /dev/null +++ b/support/highlight/src/core/ansigenerator.cpp @@ -0,0 +1,109 @@ +/*************************************************************************** + ansigenerator.cpp - description + ------------------- + begin : Jul 5 2004 + copyright : (C) 2004-2007 by Andre Simon + email : andre.simon1@gmx.de + ***************************************************************************/ + + +/* +This file is part of Highlight. + +Highlight is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +Highlight is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Highlight. If not, see <http://www.gnu.org/licenses/>. +*/ + + +#include <sstream> + +#include "ansigenerator.h" + +using namespace std; + +namespace highlight +{ + + string AnsiGenerator::getOpenTag ( const string&font, + const string&fgCol, const string&bgCol ) + { + ostringstream s; + s << "\033["<<font; + if ( !fgCol.empty() ) + s<<";"<<fgCol; + if ( !bgCol.empty() ) + s<<";"<<bgCol; + s << "m"; + return s.str(); + } + + + AnsiGenerator::AnsiGenerator() : CodeGenerator ( ANSI ) + { + + newLineTag = "\n"; + spacer = " "; + } + + AnsiGenerator::~AnsiGenerator() {} + + void AnsiGenerator::initOutputTags(){ + openTags.push_back ( "" ); + openTags.push_back ( getOpenTag ( "00", "31" ) ); //str + openTags.push_back ( getOpenTag ( "00", "34" ) );//number + openTags.push_back ( getOpenTag ( "00", "34" ) );//sl comment + openTags.push_back ( getOpenTag ( "00", "34" ) );//ml comment + openTags.push_back ( getOpenTag ( "00", "35" ) );//escapeChar + openTags.push_back ( getOpenTag ( "00", "35" ) );//directive + openTags.push_back ( getOpenTag ( "00", "31" ) );//directive string + openTags.push_back ( getOpenTag ( "00", "30" ) );//linenum + openTags.push_back ( getOpenTag ( "00", "00" ) );//symbol + + closeTags.push_back ( "" ); + for ( int i=1;i<NUMBER_BUILTIN_STATES; i++ ) + { + closeTags.push_back ( "\033[m" ); + } + } + + string AnsiGenerator::getHeader() + { + return string(); + } + + void AnsiGenerator::printBody() + { + processRootState(); + } + + string AnsiGenerator::getFooter() + { + return string(); + } + + string AnsiGenerator::maskCharacter ( unsigned char c ) + { + return string ( 1, c ); + } + + string AnsiGenerator::getKeywordOpenTag ( unsigned int styleID ) + { + return ( styleID ) ?getOpenTag ( "00", "32", "" ) :getOpenTag ( "00", "33" ); + } + + string AnsiGenerator::getKeywordCloseTag ( unsigned int styleID ) + { + return "\033[m"; + } + +} diff --git a/support/highlight/src/core/ansigenerator.h b/support/highlight/src/core/ansigenerator.h new file mode 100644 index 0000000000..51ac965a5c --- /dev/null +++ b/support/highlight/src/core/ansigenerator.h @@ -0,0 +1,89 @@ +/*************************************************************************** + ansicode.h - description + ------------------- + begin : Jul 5 2004 + copyright : (C) 2004-2007 by Andre Simon + email : andre.simon1@gmx.de + ***************************************************************************/ + + +/* +This file is part of Highlight. + +Highlight is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +Highlight is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Highlight. If not, see <http://www.gnu.org/licenses/>. +*/ + + +#ifndef ANSIGENERATOR_H +#define ANSIGENERATOR_H + +#include <string> + +#include "codegenerator.h" +#include "charcodes.h" +#include "version.h" + +namespace highlight +{ + + /** + \brief This class generates ANSI escape sequences. + + It contains information about the resulting document structure (document + header and footer), the colour system, white space handling and text + formatting attributes. + + * @author Andre Simon + */ + + class AnsiGenerator : public highlight::CodeGenerator + { + public: + AnsiGenerator(); + ~AnsiGenerator(); + + /** prints document header + */ + string getHeader(); + + /** Prints document footer*/ + string getFooter(); + + /** Prints document body*/ + void printBody(); + + private: + + /** \return escaped character*/ + virtual string maskCharacter ( unsigned char ); + + + /** gibt ANSI-"Tags" zurueck (Farbindex+bold+kursiv)*/ + string getOpenTag ( const string&font, + const string&fgCol, const string&bgCol="" ); + + /** initialize tags in specific format according to colouring information provided in DucumentStyle */ + void initOutputTags(); + + /** @param styleID current style ID + @return matching sequence to begin a new element formatting*/ + string getKeywordOpenTag ( unsigned int styleID ); + + /** @param styleID current style ID + @return matching sequence to stop element formatting*/ + string getKeywordCloseTag ( unsigned int styleID ); + }; + +} +#endif diff --git a/support/highlight/src/core/astyle/ASBeautifier.cpp b/support/highlight/src/core/astyle/ASBeautifier.cpp new file mode 100644 index 0000000000..899d46d16b --- /dev/null +++ b/support/highlight/src/core/astyle/ASBeautifier.cpp @@ -0,0 +1,2658 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * + * Copyright (C) 2006-2010 by Jim Pattee <jimp03@email.com> + * Copyright (C) 1998-2002 by Tal Davidson + * <http://www.gnu.org/licenses/lgpl-3.0.html> + * + * This file is a part of Artistic Style - an indentation and + * reformatting tool for C, C++, C# and Java source files. + * <http://astyle.sourceforge.net> + * + * Artistic Style is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Artistic Style is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Artistic Style. If not, see <http://www.gnu.org/licenses/>. + * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + */ + +#include "astyle.h" + +#include <algorithm> +#include <iostream> + + +namespace astyle +{ +// static member variables +int ASBeautifier::beautifierFileType = 9; // initialized with an invalid type +vector<const string*>* ASBeautifier::headers = NULL; +vector<const string*>* ASBeautifier::nonParenHeaders = NULL; +vector<const string*>* ASBeautifier::preBlockStatements; +vector<const string*>* ASBeautifier::assignmentOperators = NULL; +vector<const string*>* ASBeautifier::nonAssignmentOperators; +vector<const string*>* ASBeautifier::indentableHeaders; + + +/** + * ASBeautifier's constructor + */ +ASBeautifier::ASBeautifier() +{ + waitingBeautifierStack = NULL; + activeBeautifierStack = NULL; + waitingBeautifierStackLengthStack = NULL; + activeBeautifierStackLengthStack = NULL; + + headerStack = NULL; + tempStacks = NULL; + blockParenDepthStack = NULL; + blockStatementStack = NULL; + parenStatementStack = NULL; + bracketBlockStateStack = NULL; + inStatementIndentStack = NULL; + inStatementIndentStackSizeStack = NULL; + parenIndentStack = NULL; + sourceIterator = NULL; + isIndentManuallySet = false; + isMinConditionalManuallySet = false; + isModeManuallySet = false; + shouldForceTabIndentation = false; + setSpaceIndentation(4); // also sets minConditionalIndent + setMaxInStatementIndentLength(40); + classInitializerTabs = 1; + setClassIndent(false); + setSwitchIndent(false); + setCaseIndent(false); + setBlockIndent(false); + setBracketIndent(false); + setNamespaceIndent(false); + setLabelIndent(false); + setEmptyLineFill(false); + setCStyle(); + setPreprocessorIndent(false); + + // initialize ASBeautifier static member vectors + beautifierFileType = 9; // reset to an invalid type + initVector(headers); + initVector(nonParenHeaders); + initVector(assignmentOperators); + initVector(nonAssignmentOperators); + initVector(preBlockStatements); + initVector(indentableHeaders); +} + +/** + * ASBeautifier's copy constructor + * must explicitly call the base class copy constructor + */ +ASBeautifier::ASBeautifier(const ASBeautifier &other) : ASBase(other) +{ + // these don't need to copy the stack + waitingBeautifierStack = NULL; + activeBeautifierStack = NULL; + waitingBeautifierStackLengthStack = NULL; + activeBeautifierStackLengthStack = NULL; + + // vector '=' operator performs a DEEP copy of all elements in the vector + + headerStack = new vector<const string*>; + *headerStack = *other.headerStack; + + //tempStacks = new vector<vector<const string*>*>; + //vector<vector<const string*>*>::iterator iter; + //for (iter = other.tempStacks->begin(); + // iter != other.tempStacks->end(); + // ++iter) + //{ + // vector<const string*> *newVec = new vector<const string*>; + // *newVec = **iter; + // tempStacks->push_back(newVec); + //} + tempStacks = copyTempStacks(other); + + blockParenDepthStack = new vector<int>; + *blockParenDepthStack = *other.blockParenDepthStack; + + blockStatementStack = new vector<bool>; + *blockStatementStack = *other.blockStatementStack; + + parenStatementStack = new vector<bool>; + *parenStatementStack = *other.parenStatementStack; + + bracketBlockStateStack = new vector<bool>; + *bracketBlockStateStack = *other.bracketBlockStateStack; + + inStatementIndentStack = new vector<int>; + *inStatementIndentStack = *other.inStatementIndentStack; + + inStatementIndentStackSizeStack = new vector<int>; + *inStatementIndentStackSizeStack = *other.inStatementIndentStackSizeStack; + + parenIndentStack = new vector<int>; + *parenIndentStack = *other.parenIndentStack; + + sourceIterator = other.sourceIterator; + + // protected variables + // variables set by ASFormatter + // must also be updated in activeBeautifierStack + inLineNumber = other.inLineNumber; + horstmannIndentInStatement = other.horstmannIndentInStatement; + nonInStatementBracket = other.nonInStatementBracket; + lineCommentNoBeautify = other.lineCommentNoBeautify; + isNonInStatementArray = other.isNonInStatementArray; + isSharpAccessor = other.isSharpAccessor; + isSharpDelegate = other.isSharpDelegate; + isInExtern = other.isInExtern; + isInBeautifySQL = other.isInBeautifySQL; + isInIndentableStruct = other.isInIndentableStruct; + + // private variables + indentString = other.indentString; + currentHeader = other.currentHeader; + previousLastLineHeader = other.previousLastLineHeader; + probationHeader = other.probationHeader; + isInQuote = other.isInQuote; + isInVerbatimQuote = other.isInVerbatimQuote; + haveLineContinuationChar = other.haveLineContinuationChar; + isInAsm = other.isInAsm; + isInAsmOneLine = other.isInAsmOneLine; + isInAsmBlock = other.isInAsmBlock; + isInComment = other.isInComment; + isInHorstmannComment = other.isInHorstmannComment; + isInCase = other.isInCase; + isInQuestion = other.isInQuestion; + isInStatement = other.isInStatement; + isInHeader = other.isInHeader; + isInTemplate = other.isInTemplate; + isInDefine = other.isInDefine; + isInDefineDefinition = other.isInDefineDefinition; + classIndent = other.classIndent; + isInClassInitializer = other.isInClassInitializer; + isInClassHeaderTab = other.isInClassHeaderTab; + isInEnum = other.isInEnum; + switchIndent = other.switchIndent; + caseIndent = other.caseIndent; + namespaceIndent = other.namespaceIndent; + bracketIndent = other.bracketIndent; + blockIndent = other.blockIndent; + labelIndent = other.labelIndent; + preprocessorIndent = other.preprocessorIndent; + isInConditional = other.isInConditional; + isIndentManuallySet = other.isIndentManuallySet; + isMinConditionalManuallySet = other.isMinConditionalManuallySet; + isModeManuallySet = other.isModeManuallySet; + shouldForceTabIndentation = other.shouldForceTabIndentation; + emptyLineFill = other.emptyLineFill; + lineOpensComment = other.lineOpensComment; + backslashEndsPrevLine = other.backslashEndsPrevLine; + blockCommentNoIndent = other.blockCommentNoIndent; + blockCommentNoBeautify = other.blockCommentNoBeautify; + previousLineProbationTab = other.previousLineProbationTab; + fileType = other.fileType; + minConditionalIndent = other.minConditionalIndent; + parenDepth = other.parenDepth; + indentLength = other.indentLength; + blockTabCount = other.blockTabCount; + maxInStatementIndent = other.maxInStatementIndent; + classInitializerTabs = other.classInitializerTabs; + templateDepth = other.templateDepth; + prevFinalLineSpaceTabCount = other.prevFinalLineSpaceTabCount; + prevFinalLineTabCount = other.prevFinalLineTabCount; + defineTabCount = other.defineTabCount; + quoteChar = other.quoteChar; + prevNonSpaceCh = other.prevNonSpaceCh; + currentNonSpaceCh = other.currentNonSpaceCh; + currentNonLegalCh = other.currentNonLegalCh; + prevNonLegalCh = other.prevNonLegalCh; +} + +/** + * ASBeautifier's destructor + */ +ASBeautifier::~ASBeautifier() +{ + deleteContainer(waitingBeautifierStack); + deleteContainer(activeBeautifierStack); + deleteContainer(waitingBeautifierStackLengthStack); + deleteContainer(activeBeautifierStackLengthStack); + deleteContainer(headerStack); + deleteContainer(tempStacks); + deleteContainer(blockParenDepthStack); + deleteContainer(blockStatementStack); + deleteContainer(parenStatementStack); + deleteContainer(bracketBlockStateStack); + deleteContainer(inStatementIndentStack); + deleteContainer(inStatementIndentStackSizeStack); + deleteContainer(parenIndentStack); +} + +/** + * initialize the ASBeautifier. + * + * init() should be called every time a ABeautifier object is to start + * beautifying a NEW source file. + * init() recieves a pointer to a ASSourceIterator object that will be + * used to iterate through the source code. + * + * @param iter a pointer to the ASSourceIterator or ASStreamIterator object. + */ +void ASBeautifier::init(ASSourceIterator *iter) +{ + sourceIterator = iter; + init(); +} + +/** + * initialize the ASBeautifier. + */ +void ASBeautifier::init() +{ + initStatic(); + ASBase::init(getFileType()); + + initContainer(waitingBeautifierStack, new vector<ASBeautifier*>); + initContainer(activeBeautifierStack, new vector<ASBeautifier*>); + + initContainer(waitingBeautifierStackLengthStack, new vector<int>); + initContainer(activeBeautifierStackLengthStack, new vector<int>); + + initContainer(headerStack, new vector<const string*>); + + initContainer(tempStacks, new vector<vector<const string*>*>); + tempStacks->push_back(new vector<const string*>); + + initContainer(blockParenDepthStack, new vector<int>); + initContainer(blockStatementStack, new vector<bool>); + initContainer(parenStatementStack, new vector<bool>); + + initContainer(bracketBlockStateStack, new vector<bool>); + bracketBlockStateStack->push_back(true); + + initContainer(inStatementIndentStack, new vector<int>); + initContainer(inStatementIndentStackSizeStack, new vector<int>); + inStatementIndentStackSizeStack->push_back(0); + initContainer(parenIndentStack, new vector<int>); + + previousLastLineHeader = NULL; + currentHeader = NULL; + + isInQuote = false; + isInVerbatimQuote = false; + haveLineContinuationChar = false; + isInAsm = false; + isInAsmOneLine = false; + isInAsmBlock = false; + isInComment = false; + isInHorstmannComment = false; + isInStatement = false; + isInCase = false; + isInQuestion = false; + isInClassInitializer = false; + isInClassHeaderTab = false; + isInEnum = false; + isInHeader = false; + isInTemplate = false; + isInConditional = false; + + templateDepth = 0; + parenDepth = 0; + blockTabCount = 0; + prevNonSpaceCh = '{'; + currentNonSpaceCh = '{'; + prevNonLegalCh = '{'; + currentNonLegalCh = '{'; + quoteChar = ' '; + prevFinalLineSpaceTabCount = 0; + prevFinalLineTabCount = 0; + probationHeader = NULL; + backslashEndsPrevLine = false; + lineOpensComment = false; + isInDefine = false; + isInDefineDefinition = false; + defineTabCount = 0; + lineCommentNoBeautify = false; + blockCommentNoIndent = false; + blockCommentNoBeautify = false; + previousLineProbationTab = false; + isNonInStatementArray = false; + isSharpAccessor = false; + isSharpDelegate = false; + isInExtern = false; + isInBeautifySQL = false; + isInIndentableStruct = false; + inLineNumber = 0; + horstmannIndentInStatement = 0; + nonInStatementBracket = 0; +} + +/* + * initialize the static vars + */ +void ASBeautifier::initStatic() +{ + if (fileType == beautifierFileType) // don't build unless necessary + return; + + beautifierFileType = fileType; + + headers->clear(); + nonParenHeaders->clear(); + assignmentOperators->clear(); + nonAssignmentOperators->clear(); + preBlockStatements->clear(); + indentableHeaders->clear(); + + ASResource::buildHeaders(headers, fileType, true); + ASResource::buildNonParenHeaders(nonParenHeaders, fileType, true); + ASResource::buildAssignmentOperators(assignmentOperators); + ASResource::buildNonAssignmentOperators(nonAssignmentOperators); + ASResource::buildPreBlockStatements(preBlockStatements, fileType); + ASResource::buildIndentableHeaders(indentableHeaders); +} + +/** + * set indentation style to C/C++. + */ +void ASBeautifier::setCStyle() +{ + fileType = C_TYPE; +} + +/** + * set indentation style to Java. + */ +void ASBeautifier::setJavaStyle() +{ + fileType = JAVA_TYPE; +} + +/** + * set indentation style to C#. + */ +void ASBeautifier::setSharpStyle() +{ + fileType = SHARP_TYPE; +} + +/** + * set mode manually set flag + */ +void ASBeautifier::setModeManuallySet(bool state) +{ + isModeManuallySet = state; +} + +/** + * indent using one tab per indentation + */ +void ASBeautifier::setTabIndentation(int length, bool forceTabs) +{ + indentString = "\t"; + indentLength = length; + shouldForceTabIndentation = forceTabs; + + if (!isMinConditionalManuallySet) + minConditionalIndent = indentLength * 2; +} + +/** + * indent using a number of spaces per indentation. + * + * @param length number of spaces per indent. + */ +void ASBeautifier::setSpaceIndentation(int length) +{ + indentString = string(length, ' '); + indentLength = length; + + if (!isMinConditionalManuallySet) + minConditionalIndent = indentLength * 2; +} + +/** + * set indent manually set flag + */ +void ASBeautifier::setIndentManuallySet(bool state) +{ + isIndentManuallySet = state; +} + +/** + * set the maximum indentation between two lines in a multi-line statement. + * + * @param max maximum indentation length. + */ +void ASBeautifier::setMaxInStatementIndentLength(int max) +{ + maxInStatementIndent = max; +} + +/** + * set the minimum indentation between two lines in a multi-line condition. + * + * @param min minimal indentation length. + */ +void ASBeautifier::setMinConditionalIndentLength(int min) +{ + minConditionalIndent = min; +} + +/** + * set min conditional manually set flag + */ +void ASBeautifier::setMinConditionalManuallySet(bool state) +{ + isMinConditionalManuallySet = state; +} + +/** + * set the state of the bracket indentation option. If true, brackets will + * be indented one additional indent. + * + * @param state state of option. + */ +void ASBeautifier::setBracketIndent(bool state) +{ + bracketIndent = state; +} + +/** + * set the state of the block indentation option. If true, entire blocks + * will be indented one additional indent, similar to the GNU indent style. + * + * @param state state of option. + */ +void ASBeautifier::setBlockIndent(bool state) +{ + blockIndent = state; +} + +/** + * set the state of the class indentation option. If true, C++ class + * definitions will be indented one additional indent. + * + * @param state state of option. + */ +void ASBeautifier::setClassIndent(bool state) +{ + classIndent = state; +} + +/** + * set the state of the switch indentation option. If true, blocks of 'switch' + * statements will be indented one additional indent. + * + * @param state state of option. + */ +void ASBeautifier::setSwitchIndent(bool state) +{ + switchIndent = state; +} + +/** + * set the state of the case indentation option. If true, lines of 'case' + * statements will be indented one additional indent. + * + * @param state state of option. + */ +void ASBeautifier::setCaseIndent(bool state) +{ + caseIndent = state; +} + +/** + * set the state of the namespace indentation option. + * If true, blocks of 'namespace' statements will be indented one + * additional indent. Otherwise, NO indentation will be added. + * + * @param state state of option. + */ +void ASBeautifier::setNamespaceIndent(bool state) +{ + namespaceIndent = state; +} + +/** + * set the state of the label indentation option. + * If true, labels will be indented one indent LESS than the + * current indentation level. + * If false, labels will be flushed to the left with NO + * indent at all. + * + * @param state state of option. + */ +void ASBeautifier::setLabelIndent(bool state) +{ + labelIndent = state; +} + +/** + * set the state of the preprocessor indentation option. + * If true, multiline #define statements will be indented. + * + * @param state state of option. + */ +void ASBeautifier::setPreprocessorIndent(bool state) +{ + preprocessorIndent = state; +} + +/** + * set the state of the empty line fill option. + * If true, empty lines will be filled with the whitespace. + * of their previous lines. + * If false, these lines will remain empty. + * + * @param state state of option. + */ +void ASBeautifier::setEmptyLineFill(bool state) +{ + emptyLineFill = state; +} + +/** + * get the file type. + */ +int ASBeautifier::getFileType() +{ + return fileType; +} + +/** + * get the number of spaces per indent + * + * @return value of indentLength option. + */ +int ASBeautifier::getIndentLength(void) +{ + return indentLength; +} + +/** + * get the char used for indentation, space or tab + * + * @return the char used for indentation. + */ +string ASBeautifier::getIndentString(void) +{ + return indentString; +} + +/** + * get indent manually set flag + */ +bool ASBeautifier::getIndentManuallySet() +{ + return isIndentManuallySet; +} + +/** + * get the state of the isMinConditionalManuallySet flag + * + * @return the state of isMinConditionalManuallySet. + */ +bool ASBeautifier::getMinConditionalManuallySet() +{ + return isMinConditionalManuallySet; +} + +/** + * get mode manually set flag + */ +bool ASBeautifier::getModeManuallySet() +{ + return isModeManuallySet; +} + +/** + * get the state of the force tab indentation option. + * + * @return state of force tab indentation. + */ +bool ASBeautifier::getForceTabIndentation(void) +{ + return shouldForceTabIndentation; +} + +/** + * get the state of the block indentation option. + * + * @return state of blockIndent option. + */ +bool ASBeautifier::getBlockIndent(void) +{ + return blockIndent; +} + +/** + * get the state of the bracket indentation option. + * + * @return state of bracketIndent option. + */ +bool ASBeautifier::getBracketIndent(void) +{ + return bracketIndent; +} + +/** + * get the state of the class indentation option. If true, blocks of + * the 'class' statement will be indented one additional indent. + * + * @return state of classIndent option. + */ +bool ASBeautifier::getClassIndent(void) +{ + return classIndent; +} + +/** + * get the state of the switch indentation option. If true, blocks of + * the 'switch' statement will be indented one additional indent. + * + * @return state of switchIndent option. + */ +bool ASBeautifier::getSwitchIndent(void) +{ + return switchIndent; +} + +/** + * get the state of the case indentation option. If true, lines of 'case' + * statements will be indented one additional indent. + * + * @return state of caseIndent option. + */ +bool ASBeautifier::getCaseIndent(void) +{ + return caseIndent; +} + +/** + * get the state of the empty line fill option. + * If true, empty lines will be filled with the whitespace. + * of their previous lines. + * If false, these lines will remain empty. + * + * @return state of emptyLineFill option. + */ +bool ASBeautifier::getEmptyLineFill(void) +{ + return emptyLineFill; +} + +/** + * check if there are any indented lines ready to be read by nextLine() + * + * @return are there any indented lines ready? + */ +bool ASBeautifier::hasMoreLines() const +{ + return sourceIterator->hasMoreLines(); +} + +/** + * get the next indented line. + * + * @return indented line. + */ +string ASBeautifier::nextLine() +{ + return beautify(sourceIterator->nextLine()); +} + +/** + * beautify a line of source code. + * every line of source code in a source code file should be sent + * one after the other to the beautify method. + * + * @return the indented line. + * @param originalLine the original unindented line. + */ +string ASBeautifier::beautify(const string &originalLine) +{ + string line; + bool isInLineComment = false; + bool lineStartsInComment = false; + bool isInClass = false; + bool isInSwitch = false; + bool isInOperator = false; + bool isSpecialChar = false; + bool haveCaseIndent = false; + bool haveAssignmentThisLine = false; + bool lineBeginsWithBracket = false; + bool closingBracketReached = false; + bool shouldIndentBrackettedLine = true; + bool previousLineProbation = (probationHeader != NULL); + bool isInQuoteContinuation = isInVerbatimQuote | haveLineContinuationChar; + char ch = ' '; + char prevCh; + char tempCh; + int tabCount = 0; + int spaceTabCount = 0; + int lineOpeningBlocksNum = 0; + int lineClosingBlocksNum = 0; + int tabIncrementIn = 0; + int i; + int iPrelim; + string outBuffer; // the newly idented line is buffered here + const string *lastLineHeader = NULL; + + currentHeader = NULL; + lineStartsInComment = isInComment; + blockCommentNoBeautify = blockCommentNoIndent; + isInAsmOneLine = false; + lineOpensComment = false; + previousLineProbationTab = false; + haveLineContinuationChar = false; + + // handle and remove white spaces around the line: + // If not in comment, first find out size of white space before line, + // so that possible comments starting in the line continue in + // relation to the preliminary white-space. + if (isInQuoteContinuation) + { + // trim a single space added by ASFormatter, otherwise leave it alone + if (!(originalLine.length() == 1 && originalLine[0] == ' ')) + line = originalLine; + } + else if (isInComment || isInBeautifySQL) + { + // trim the end of comment and SQL lines + line = originalLine; + size_t trimEnd = line.find_last_not_of(" \t"); + if (trimEnd == string::npos) + trimEnd = 0; + else + trimEnd++; + if (trimEnd < line.length()) + line.erase(trimEnd); + } + else + { + line = trim(originalLine); + if (line.length() > 0 && line[0] == '{') + lineBeginsWithBracket = true; + + isInHorstmannComment = false; + size_t j = line.find_first_not_of(" \t{"); + if (j != string::npos && line.compare(j, 2, "/*") == 0) + { + lineOpensComment = true; + size_t k = line.find_first_not_of(" \t"); + if (k != string::npos && line.compare(k, 1, "{") == 0) + isInHorstmannComment = true; + } + } + + if (line.length() == 0) + { + if (backslashEndsPrevLine) // must continue to clear variables + line = ' '; + else if (emptyLineFill && !isInQuoteContinuation && headerStack->size() > 0) + return preLineWS(prevFinalLineSpaceTabCount, prevFinalLineTabCount); + else + return line; + } + + // handle preprocessor commands + // except C# region and endregion + + if (!isInComment + && (line[0] == '#' || backslashEndsPrevLine) + && line.compare(0, 7, "#region") != 0 + && line.compare(0, 10, "#endregion") != 0) + { + if (line[0] == '#') + { + string preproc = trim(string(line.c_str() + 1)); + + // When finding a multi-lined #define statement, the original beautifier + // 1. sets its isInDefineDefinition flag + // 2. clones a new beautifier that will be used for the actual indentation + // of the #define. This clone is put into the activeBeautifierStack in order + // to be called for the actual indentation. + // The original beautifier will have isInDefineDefinition = true, isInDefine = false + // The cloned beautifier will have isInDefineDefinition = true, isInDefine = true + if (preprocessorIndent && preproc.compare(0, 6, "define") == 0 && line[line.length() - 1] == '\\') + { + if (!isInDefineDefinition) + { + ASBeautifier *defineBeautifier; + + // this is the original beautifier + isInDefineDefinition = true; + + // push a new beautifier into the active stack + // this beautifier will be used for the indentation of this define + defineBeautifier = new ASBeautifier(*this); + activeBeautifierStack->push_back(defineBeautifier); + } + else + { + // the is the cloned beautifier that is in charge of indenting the #define. + isInDefine = true; + } + } + else if (preproc.compare(0, 2, "if") == 0) + { + // push a new beautifier into the stack + waitingBeautifierStackLengthStack->push_back(waitingBeautifierStack->size()); + activeBeautifierStackLengthStack->push_back(activeBeautifierStack->size()); + waitingBeautifierStack->push_back(new ASBeautifier(*this)); + } + else if (preproc.compare(0, 4/*2*/, "else") == 0) + { + if (waitingBeautifierStack && !waitingBeautifierStack->empty()) + { + // MOVE current waiting beautifier to active stack. + activeBeautifierStack->push_back(waitingBeautifierStack->back()); + waitingBeautifierStack->pop_back(); + } + } + else if (preproc.compare(0, 4, "elif") == 0) + { + if (waitingBeautifierStack && !waitingBeautifierStack->empty()) + { + // append a COPY current waiting beautifier to active stack, WITHOUT deleting the original. + activeBeautifierStack->push_back(new ASBeautifier(*(waitingBeautifierStack->back()))); + } + } + else if (preproc.compare(0, 5, "endif") == 0) + { + int stackLength; + ASBeautifier *beautifier; + + if (waitingBeautifierStackLengthStack && !waitingBeautifierStackLengthStack->empty()) + { + stackLength = waitingBeautifierStackLengthStack->back(); + waitingBeautifierStackLengthStack->pop_back(); + while ((int) waitingBeautifierStack->size() > stackLength) + { + beautifier = waitingBeautifierStack->back(); + waitingBeautifierStack->pop_back(); + delete beautifier; + } + } + + if (!activeBeautifierStackLengthStack->empty()) + { + stackLength = activeBeautifierStackLengthStack->back(); + activeBeautifierStackLengthStack->pop_back(); + while ((int) activeBeautifierStack->size() > stackLength) + { + beautifier = activeBeautifierStack->back(); + activeBeautifierStack->pop_back(); + delete beautifier; + } + } + } + } + + // check if the last char is a backslash + if (line.length() > 0) + backslashEndsPrevLine = (line[line.length() - 1] == '\\'); + else + backslashEndsPrevLine = false; + + // check if this line ends a multi-line #define + // if so, use the #define's cloned beautifier for the line's indentation + // and then remove it from the active beautifier stack and delete it. + if (!backslashEndsPrevLine && isInDefineDefinition && !isInDefine) + { + string beautifiedLine; + ASBeautifier *defineBeautifier; + + isInDefineDefinition = false; + defineBeautifier = activeBeautifierStack->back(); + activeBeautifierStack->pop_back(); + + beautifiedLine = defineBeautifier->beautify(line); + delete defineBeautifier; + return beautifiedLine; + } + + // unless this is a multi-line #define, return this precompiler line as is. + if (!isInDefine && !isInDefineDefinition) + return originalLine; + } + + // if there exists any worker beautifier in the activeBeautifierStack, + // then use it instead of me to indent the current line. + // variables set by ASFormatter must be updated. + if (!isInDefine && activeBeautifierStack != NULL && !activeBeautifierStack->empty()) + { + activeBeautifierStack->back()->inLineNumber = inLineNumber; + activeBeautifierStack->back()->horstmannIndentInStatement = horstmannIndentInStatement; + activeBeautifierStack->back()->nonInStatementBracket = nonInStatementBracket; + activeBeautifierStack->back()->lineCommentNoBeautify = lineCommentNoBeautify; + activeBeautifierStack->back()->isNonInStatementArray = isNonInStatementArray; + activeBeautifierStack->back()->isSharpAccessor = isSharpAccessor; + activeBeautifierStack->back()->isSharpDelegate = isSharpDelegate; + activeBeautifierStack->back()->isInExtern = isInExtern; + activeBeautifierStack->back()->isInBeautifySQL = isInBeautifySQL; + activeBeautifierStack->back()->isInIndentableStruct = isInIndentableStruct; + // must return originalLine not the trimmed line + return activeBeautifierStack->back()->beautify(originalLine); + } + + // calculate preliminary indentation based on data from past lines + + if (!inStatementIndentStack->empty()) + spaceTabCount = inStatementIndentStack->back(); + + for (i = 0; i < (int) headerStack->size(); i++) + { + isInClass = false; + + if (blockIndent) + { + // do NOT indent opening block for these headers + if (!((*headerStack)[i] == &AS_NAMESPACE + || (*headerStack)[i] == &AS_CLASS + || (*headerStack)[i] == &AS_STRUCT + || (*headerStack)[i] == &AS_UNION + || (*headerStack)[i] == &AS_CONST + || (*headerStack)[i] == &AS_INTERFACE + || (*headerStack)[i] == &AS_THROWS + || (*headerStack)[i] == &AS_STATIC)) + ++tabCount; + } + else if (!(i > 0 && (*headerStack)[i-1] != &AS_OPEN_BRACKET + && (*headerStack)[i] == &AS_OPEN_BRACKET)) + ++tabCount; + + if (!isJavaStyle() && !namespaceIndent && i >= 1 + && (*headerStack)[i-1] == &AS_NAMESPACE + && (*headerStack)[i] == &AS_OPEN_BRACKET) + --tabCount; + + if (isCStyle() && i >= 1 + && (*headerStack)[i-1] == &AS_CLASS + && (*headerStack)[i] == &AS_OPEN_BRACKET) + { + if (classIndent) + ++tabCount; + isInClass = true; + } + + // is the switchIndent option is on, indent switch statements an additional indent. + else if (switchIndent && i > 1 + && (*headerStack)[i-1] == &AS_SWITCH + && (*headerStack)[i] == &AS_OPEN_BRACKET) + { + ++tabCount; + isInSwitch = true; + } + + } // end of for loop * end of for loop * end of for loop * end of for loop * end of for loop * + + iPrelim = i; + + if (!lineStartsInComment + && isCStyle() + && isInClass + && classIndent + && headerStack->size() >= 2 + && (*headerStack)[headerStack->size()-2] == &AS_CLASS + && (*headerStack)[headerStack->size()-1] == &AS_OPEN_BRACKET + && line[0] == '}' + && bracketBlockStateStack->back() == true) + --tabCount; + + else if (!lineStartsInComment + && isInSwitch + && switchIndent + && headerStack->size() >= 2 + && (*headerStack)[headerStack->size()-2] == &AS_SWITCH + && (*headerStack)[headerStack->size()-1] == &AS_OPEN_BRACKET + && line[0] == '}') + --tabCount; + + if (isInClassInitializer) + { + if (lineStartsInComment || lineOpensComment) + { + if (!lineBeginsWithBracket) + tabCount--; + } + else if (isCStyle() && !isClassAccessModifier(line)) + { + isInClassHeaderTab = true; + tabCount += classInitializerTabs; + } + else if (blockIndent) + { + if (!lineBeginsWithBracket) + tabCount++; + } + } + // handle special case of indented horstmann brackets + else if (lineStartsInComment && isInHorstmannComment && bracketIndent) + tabCount++; + + // handle special case of horstmann comment in an indented class statement + if (isInClass + && classIndent + && isInHorstmannComment + && !lineOpensComment + && headerStack->size() >= 2 + && (*headerStack)[headerStack->size()-2] == &AS_CLASS) + --tabCount; + + if (isInConditional) + { + --tabCount; + } + + + // parse characters in the current line. + + for (i = 0; i < (int) line.length(); i++) + { + outBuffer.append(1, line[i]); + + tempCh = line[i]; + prevCh = ch; + ch = tempCh; + + if (isInBeautifySQL) + continue; + + if (isWhiteSpace(ch)) + { + if (ch == '\t') + tabIncrementIn += convertTabToSpaces(i, tabIncrementIn); + continue; + } + + // handle special characters (i.e. backslash+character such as \n, \t, ...) + + if (isInQuote && !isInVerbatimQuote) + { + if (isSpecialChar) + { + isSpecialChar = false; + continue; + } + if (line.compare(i, 2, "\\\\") == 0) + { + outBuffer.append(1, '\\'); + i++; + continue; + } + if (ch == '\\') + { + if (peekNextChar(line, i) == ' ') // is this '\' at end of line + haveLineContinuationChar = true; + else + isSpecialChar = true; + continue; + } + } + else if (isInDefine && ch == '\\') + continue; + + // handle quotes (such as 'x' and "Hello Dolly") + if (!(isInComment || isInLineComment) && (ch == '"' || ch == '\'')) + { + if (!isInQuote) + { + quoteChar = ch; + isInQuote = true; + if (isSharpStyle() && prevCh == '@') + isInVerbatimQuote = true; + } + else if (isInVerbatimQuote && ch == '"') + { + if (peekNextChar(line, i) == '"') // check consecutive quotes + { + outBuffer.append(1, '"'); + i++; + } + else + { + isInQuote = false; + isInVerbatimQuote = false; + } + } + else if (quoteChar == ch) + { + isInQuote = false; + isInStatement = true; + continue; + } + } + if (isInQuote) + continue; + + // handle comments + + if (!(isInComment || isInLineComment) && line.compare(i, 2, "//") == 0) + { + isInLineComment = true; + outBuffer.append(1, '/'); + i++; + continue; + } + else if (!(isInComment || isInLineComment) && line.compare(i, 2, "/*") == 0) + { + isInComment = true; + outBuffer.append(1, '*'); + i++; + if (!lineOpensComment) // does line start with comment? + blockCommentNoIndent = true; // if no, cannot indent continuation lines + continue; + } + else if ((isInComment || isInLineComment) && line.compare(i, 2, "*/") == 0) + { + isInComment = false; + outBuffer.append(1, '/'); + i++; + blockCommentNoIndent = false; // ok to indent next comment + continue; + } + // treat C# '#region' and '#endregion' statements as a line comment + else if (isSharpStyle() && + (line.compare(i, 7, "#region") == 0 || line.compare(i, 10, "#endregion") == 0)) + { + isInLineComment = true; + } + + if (isInComment || isInLineComment) + { + // append rest of the comment up to the comment end + while (i+1 < (int) line.length() + && line.compare(i+1, 2, "*/") != 0) + outBuffer.append(1, line[++i]); + continue; + } + + // if we have reached this far then we are NOT in a comment or string of special character... + + // SQL if formatted in ASEnhancer + if (isInBeautifySQL) + continue; + + if (probationHeader != NULL) + { + if (((probationHeader == &AS_STATIC || probationHeader == &AS_CONST) && ch == '{') + || (probationHeader == &AS_SYNCHRONIZED && ch == '(')) + { + // insert the probation header as a new header + isInHeader = true; + headerStack->push_back(probationHeader); + + // handle the specific probation header + isInConditional = (probationHeader == &AS_SYNCHRONIZED); + + isInStatement = false; + // if the probation comes from the previous line, then indent by 1 tab count. + if (previousLineProbation + && ch == '{' + && !(blockIndent + && (probationHeader == &AS_CONST || probationHeader == &AS_STATIC))) + { + tabCount++; + previousLineProbationTab = true; + } + previousLineProbation = false; + } + + // dismiss the probation header + probationHeader = NULL; + } + + prevNonSpaceCh = currentNonSpaceCh; + currentNonSpaceCh = ch; + if (!isLegalNameChar(ch) && ch != ',' && ch != ';') + { + prevNonLegalCh = currentNonLegalCh; + currentNonLegalCh = ch; + } + + if (isInHeader) + { + isInHeader = false; + currentHeader = headerStack->back(); + } + else + currentHeader = NULL; + + if (isCStyle() && isInTemplate + && (ch == '<' || ch == '>') + && findOperator(line, i, nonAssignmentOperators) == NULL) + { + if (ch == '<') + { + ++templateDepth; + } + else if (ch == '>') + { + if (--templateDepth <= 0) + { + if (isInTemplate) + ch = ';'; + else + ch = 't'; + isInTemplate = false; + templateDepth = 0; + } + } + } + + // handle parenthesies + if (ch == '(' || ch == '[' || ch == ')' || ch == ']') + { + if (ch == '(' || ch == '[') + { + isInOperator = false; + // if have a struct header, this is a declaration not a definition + if (ch == '(' + && (isInClassInitializer || isInClassHeaderTab) + && headerStack->size() > 0 + && headerStack->back() == &AS_STRUCT) + { + headerStack->pop_back(); + isInClassInitializer = false; + // -1 for isInClassInitializer, -2 for isInClassHeaderTab + if (isInClassHeaderTab) + { + tabCount -= (1 + classInitializerTabs); + isInClassHeaderTab = false; + } + if (tabCount < 0) + tabCount = 0; + } + + if (parenDepth == 0) + { + parenStatementStack->push_back(isInStatement); + isInStatement = true; + } + parenDepth++; + + inStatementIndentStackSizeStack->push_back(inStatementIndentStack->size()); + + if (currentHeader != NULL) + registerInStatementIndent(line, i, spaceTabCount, tabIncrementIn, minConditionalIndent/*indentLength*2*/, true); + else + registerInStatementIndent(line, i, spaceTabCount, tabIncrementIn, 0, true); + } + else if (ch == ')' || ch == ']') + { + parenDepth--; + if (parenDepth == 0) + { + if (!parenStatementStack->empty()) // in case of unmatched closing parens + { + isInStatement = parenStatementStack->back(); + parenStatementStack->pop_back(); + } + ch = ' '; + isInAsm = false; + isInConditional = false; + } + + if (!inStatementIndentStackSizeStack->empty()) + { + int previousIndentStackSize = inStatementIndentStackSizeStack->back(); + inStatementIndentStackSizeStack->pop_back(); + while (previousIndentStackSize < (int) inStatementIndentStack->size()) + inStatementIndentStack->pop_back(); + + if (!parenIndentStack->empty()) + { + int poppedIndent = parenIndentStack->back(); + parenIndentStack->pop_back(); + + if (i == 0) + spaceTabCount = poppedIndent; + } + } + } + + continue; + } + + + if (ch == '{') + { + // first, check if '{' is a block-opener or an static-array opener + bool isBlockOpener = ((prevNonSpaceCh == '{' && bracketBlockStateStack->back()) + || prevNonSpaceCh == '}' + || prevNonSpaceCh == ')' + || prevNonSpaceCh == ';' + || peekNextChar(line, i) == '{' + || isInClassInitializer + || isNonInStatementArray + || isSharpAccessor + || isSharpDelegate + || isInExtern + || (isInDefine && + (prevNonSpaceCh == '(' + || isLegalNameChar(prevNonSpaceCh)))); + + // remove inStatementIndent for C++ class initializer + if (isInClassInitializer) + { + if (inStatementIndentStack->size() > 0) + inStatementIndentStack->pop_back(); + isInStatement = false; + if (lineBeginsWithBracket) + spaceTabCount = 0; + isInClassInitializer = false; + } + + if (!isBlockOpener && currentHeader != NULL) + { + for (size_t n = 0; n < nonParenHeaders->size(); n++) + if (currentHeader == (*nonParenHeaders)[n]) + { + isBlockOpener = true; + break; + } + } + + bracketBlockStateStack->push_back(isBlockOpener); + + if (!isBlockOpener) + { + inStatementIndentStackSizeStack->push_back(inStatementIndentStack->size()); + registerInStatementIndent(line, i, spaceTabCount, tabIncrementIn, 0, true); + parenDepth++; + if (i == 0) + shouldIndentBrackettedLine = false; + + continue; + } + + // this bracket is a block opener... + + ++lineOpeningBlocksNum; + + if (isInClassHeaderTab) + { + isInClassHeaderTab = false; + // decrease tab count if bracket is broken + size_t firstChar = line.find_first_not_of(" \t"); + if (firstChar != string::npos + && line[firstChar] == '{' + && (int) firstChar == i) + { + tabCount -= classInitializerTabs; + // decrease one more if an empty class + if (headerStack->size() > 0 + && (*headerStack).back() == &AS_CLASS) + { + int nextChar = getNextProgramCharDistance(line, i); + if (line[nextChar] == '}') + tabCount--; + } + } + } + + if (bracketIndent && !namespaceIndent && headerStack->size() > 0 + && (*headerStack).back() == &AS_NAMESPACE) + { + shouldIndentBrackettedLine = false; + tabCount--; + } + + // an indentable struct is treated like a class in the header stack + if (headerStack->size() > 0 + && (*headerStack).back() == &AS_STRUCT + && isInIndentableStruct) + (*headerStack).back() = &AS_CLASS; + + blockParenDepthStack->push_back(parenDepth); + blockStatementStack->push_back(isInStatement); + + inStatementIndentStackSizeStack->push_back(inStatementIndentStack->size()); + if (inStatementIndentStack->size() > 0) + { + spaceTabCount = 0; + inStatementIndentStack->back() = 0; + } + + blockTabCount += isInStatement ? 1 : 0; + parenDepth = 0; + isInStatement = false; + + tempStacks->push_back(new vector<const string*>); + headerStack->push_back(&AS_OPEN_BRACKET); + lastLineHeader = &AS_OPEN_BRACKET; + + continue; + } + + //check if a header has been reached + bool isPotentialHeader = isCharPotentialHeader(line, i); + + if (isPotentialHeader) + { + const string *newHeader = findHeader(line, i, headers); + + if (newHeader != NULL) + { + char peekChar = peekNextChar(line, i + newHeader->length() - 1); + + // is not a header if part of a definition + if (peekChar == ',' || peekChar == ')') + newHeader = NULL; + // the following accessor definitions are NOT headers + // goto default; is NOT a header + // default(int) keyword in C# is NOT a header + else if ((newHeader == &AS_GET || newHeader == &AS_SET || newHeader == &AS_DEFAULT) + && (peekChar == ';' || peekChar == '(')) + { + newHeader = NULL; + } + } + + if (newHeader != NULL) + { + // if we reached here, then this is a header... + bool isIndentableHeader = true; + + isInHeader = true; + + vector<const string*> *lastTempStack; + if (tempStacks->empty()) + lastTempStack = NULL; + else + lastTempStack = tempStacks->back(); + + // if a new block is opened, push a new stack into tempStacks to hold the + // future list of headers in the new block. + + // take care of the special case: 'else if (...)' + if (newHeader == &AS_IF && lastLineHeader == &AS_ELSE) + { + headerStack->pop_back(); + } + + // take care of 'else' + else if (newHeader == &AS_ELSE) + { + if (lastTempStack != NULL) + { + int indexOfIf = indexOf(*lastTempStack, &AS_IF); + if (indexOfIf != -1) + { + // recreate the header list in headerStack up to the previous 'if' + // from the temporary snapshot stored in lastTempStack. + int restackSize = lastTempStack->size() - indexOfIf - 1; + for (int r = 0; r < restackSize; r++) + { + headerStack->push_back(lastTempStack->back()); + lastTempStack->pop_back(); + } + if (!closingBracketReached) + tabCount += restackSize; + } + /* + * If the above if is not true, i.e. no 'if' before the 'else', + * then nothing beautiful will come out of this... + * I should think about inserting an Exception here to notify the caller of this... + */ + } + } + + // check if 'while' closes a previous 'do' + else if (newHeader == &AS_WHILE) + { + if (lastTempStack != NULL) + { + int indexOfDo = indexOf(*lastTempStack, &AS_DO); + if (indexOfDo != -1) + { + // recreate the header list in headerStack up to the previous 'do' + // from the temporary snapshot stored in lastTempStack. + int restackSize = lastTempStack->size() - indexOfDo - 1; + for (int r = 0; r < restackSize; r++) + { + headerStack->push_back(lastTempStack->back()); + lastTempStack->pop_back(); + } + if (!closingBracketReached) + tabCount += restackSize; + } + } + } + // check if 'catch' closes a previous 'try' or 'catch' + else if (newHeader == &AS_CATCH || newHeader == &AS_FINALLY) + { + if (lastTempStack != NULL) + { + int indexOfTry = indexOf(*lastTempStack, &AS_TRY); + if (indexOfTry == -1) + indexOfTry = indexOf(*lastTempStack, &AS_CATCH); + if (indexOfTry != -1) + { + // recreate the header list in headerStack up to the previous 'try' + // from the temporary snapshot stored in lastTempStack. + int restackSize = lastTempStack->size() - indexOfTry - 1; + for (int r = 0; r < restackSize; r++) + { + headerStack->push_back(lastTempStack->back()); + lastTempStack->pop_back(); + } + + if (!closingBracketReached) + tabCount += restackSize; + } + } + } + else if (newHeader == &AS_CASE) + { + isInCase = true; + if (!haveCaseIndent) + { + haveCaseIndent = true; + if (!lineBeginsWithBracket) + --tabCount; + } + } + else if (newHeader == &AS_DEFAULT) + { + isInCase = true; + --tabCount; + } + else if (newHeader == &AS_STATIC + || newHeader == &AS_SYNCHRONIZED + || (newHeader == &AS_CONST && isCStyle())) + { + if (!headerStack->empty() && + (headerStack->back() == &AS_STATIC + || headerStack->back() == &AS_SYNCHRONIZED + || headerStack->back() == &AS_CONST)) + { + isIndentableHeader = false; + } + else + { + isIndentableHeader = false; + probationHeader = newHeader; + } + } + else if (newHeader == &AS_CONST) + { + isIndentableHeader = false; + } + else if (newHeader == &AS_TEMPLATE) + { + if (isCStyle()) + isInTemplate = true; + isIndentableHeader = false; + } + + if (isIndentableHeader) + { + headerStack->push_back(newHeader); + isInStatement = false; + if (indexOf(*nonParenHeaders, newHeader) == -1) + { + isInConditional = true; + } + lastLineHeader = newHeader; + } + else + isInHeader = false; + + outBuffer.append(newHeader->substr(1)); + i += newHeader->length() - 1; + + continue; + } // newHeader != NULL + + if (isCStyle() && findKeyword(line, i, AS_ENUM)) + isInEnum = true; + + } // isPotentialHeader + + if (ch == '?') + isInQuestion = true; + + // special handling of 'case' statements + if (ch == ':') + { + if ((int) line.length() > i + 1 && line[i+1] == ':') // look for :: + { + ++i; + outBuffer.append(1, ':'); + ch = ' '; + continue; + } + + else if (isInQuestion) + { + isInQuestion = false; + } + + else if (isCStyle() && isInClassInitializer) + { + // found a 'class A : public B' definition + // so do nothing special + } + + else if (isCStyle() + && (isInAsm || isInAsmOneLine || isInAsmBlock)) + { + // do nothing special + } + + else if (isCStyle() && isdigit(peekNextChar(line, i))) + { + // found a bit field + // so do nothing special + } + + else if (isCStyle() && isInClass && prevNonSpaceCh != ')') + { + // found a 'private:' or 'public:' inside a class definition + --tabCount; + } + + else if (isCStyle() && prevNonSpaceCh == ')' && !isInCase) + { + isInClassInitializer = true; + if (i == 0) + tabCount += classInitializerTabs; + } + + else if (isJavaStyle() && lastLineHeader == &AS_FOR) + { + // found a java for-each statement + // so do nothing special + } + + else + { + currentNonSpaceCh = ';'; // so that brackets after the ':' will appear as block-openers + if (isInCase) + { + isInCase = false; + ch = ';'; // from here on, treat char as ';' + } + else if (isCStyle() || (isSharpStyle() && peekNextChar(line, i) == ';')) // is in a label (e.g. 'label1:') + { + if (labelIndent) + --tabCount; // unindent label by one indent + else if (!lineBeginsWithBracket) + tabCount = 0; // completely flush indent to left + } + } + } + + if ((ch == ';' || (parenDepth > 0 && ch == ',')) && !inStatementIndentStackSizeStack->empty()) + while ((int) inStatementIndentStackSizeStack->back() + (parenDepth > 0 ? 1 : 0) + < (int) inStatementIndentStack->size()) + inStatementIndentStack->pop_back(); + + // handle commas + // previous "isInStatement" will be from an assignment operator + if (ch == ',' && parenDepth == 0 && !isInStatement && !isNonInStatementArray) + { + // is comma at end of line + size_t nextChar = line.find_first_not_of(" \t", i + 1); + if (nextChar != string::npos) + { + if (line.compare(nextChar, 2, "//") == 0 + || line.compare(nextChar, 2, "/*") == 0) + nextChar = string::npos; + } + // register indent + if (nextChar == string::npos) + { + // register indent at first word after the colon of a C++ class initializer + if (isInClassInitializer) + { + size_t firstChar = line.find_first_not_of(" \t"); + if (firstChar != string::npos && line[firstChar] == ':') + { + size_t firstWord = line.find_first_not_of(" \t", firstChar + 1); + if (firstChar != string::npos) + { + int inStatementIndent = firstWord + spaceTabCount + tabIncrementIn; + inStatementIndentStack->push_back(inStatementIndent); + isInStatement = true; + } + } + } + // register indent at previous word + else + { + int prevWord = getInStatementIndentComma(line, i); + int inStatementIndent = prevWord + spaceTabCount + tabIncrementIn; + inStatementIndentStack->push_back(inStatementIndent); + isInStatement = true; + } + } + } + + // handle ends of statements + if ((ch == ';' && parenDepth == 0) || ch == '}') + { + if (ch == '}') + { + // first check if this '}' closes a previous block, or a static array... + if (!bracketBlockStateStack->empty()) + { + bool bracketBlockState = bracketBlockStateStack->back(); + bracketBlockStateStack->pop_back(); + if (!bracketBlockState) + { + if (!inStatementIndentStackSizeStack->empty()) + { + // this bracket is a static array + + int previousIndentStackSize = inStatementIndentStackSizeStack->back(); + inStatementIndentStackSizeStack->pop_back(); + while (previousIndentStackSize < (int) inStatementIndentStack->size()) + inStatementIndentStack->pop_back(); + parenDepth--; + if (i == 0) + shouldIndentBrackettedLine = false; + + if (!parenIndentStack->empty()) + { + int poppedIndent = parenIndentStack->back(); + parenIndentStack->pop_back(); + if (i == 0) + spaceTabCount = poppedIndent; + } + } + continue; + } + } + + // this bracket is block closer... + + ++lineClosingBlocksNum; + + if (!inStatementIndentStackSizeStack->empty()) + inStatementIndentStackSizeStack->pop_back(); + + if (!blockParenDepthStack->empty()) + { + parenDepth = blockParenDepthStack->back(); + blockParenDepthStack->pop_back(); + isInStatement = blockStatementStack->back(); + blockStatementStack->pop_back(); + + if (isInStatement) + blockTabCount--; + } + + closingBracketReached = true; + isInAsmOneLine = false; + + // added for release 1.24 + // TODO: remove at the appropriate time + assert(isInAsm == false); + assert(isInAsmOneLine == false); + assert(isInQuote == false); + isInAsm = isInAsmOneLine = isInQuote = false; + // end remove + + int headerPlace = indexOf(*headerStack, &AS_OPEN_BRACKET); + if (headerPlace != -1) + { + const string *popped = headerStack->back(); + while (popped != &AS_OPEN_BRACKET) + { + headerStack->pop_back(); + popped = headerStack->back(); + } + headerStack->pop_back(); + + // do not indent namespace bracket unless namespaces are indented + if (!namespaceIndent && headerStack->size() > 0 + && (*headerStack).back() == &AS_NAMESPACE) + shouldIndentBrackettedLine = false; + + if (!tempStacks->empty()) + { + vector<const string*> *temp = tempStacks->back(); + tempStacks->pop_back(); + delete temp; + } + } + + + ch = ' '; // needed due to cases such as '}else{', so that headers ('else' tn tih case) will be identified... + } + + /* + * Create a temporary snapshot of the current block's header-list in the + * uppermost inner stack in tempStacks, and clear the headerStack up to + * the begining of the block. + * Thus, the next future statement will think it comes one indent past + * the block's '{' unless it specifically checks for a companion-header + * (such as a previous 'if' for an 'else' header) within the tempStacks, + * and recreates the temporary snapshot by manipulating the tempStacks. + */ + if (!tempStacks->back()->empty()) + while (!tempStacks->back()->empty()) + tempStacks->back()->pop_back(); + while (!headerStack->empty() && headerStack->back() != &AS_OPEN_BRACKET) + { + tempStacks->back()->push_back(headerStack->back()); + headerStack->pop_back(); + } + + if (parenDepth == 0 && ch == ';') + isInStatement = false; + + previousLastLineHeader = NULL; + isInClassInitializer = false; + isInEnum = false; + isInQuestion = false; + + continue; + } + + if (isPotentialHeader) + { + // check for preBlockStatements in C/C++ ONLY if not within parenthesies + // (otherwise 'struct XXX' statements would be wrongly interpreted...) + if (!isInTemplate && !(isCStyle() && parenDepth > 0)) + { + const string *newHeader = findHeader(line, i, preBlockStatements); + if (newHeader != NULL + && !(isCStyle() && newHeader == &AS_CLASS && isInEnum)) // is it 'enum class' + { + isInClassInitializer = true; + + if (!isSharpStyle()) + headerStack->push_back(newHeader); + // do not need 'where' in the headerStack + // do not need second 'class' statement in a row + else if (!(newHeader == &AS_WHERE + || (newHeader == &AS_CLASS + && headerStack->size() > 0 + && headerStack->back() == &AS_CLASS))) + headerStack->push_back(newHeader); + + outBuffer.append(newHeader->substr(1)); + i += newHeader->length() - 1; + continue; + } + } + const string *foundIndentableHeader = findHeader(line, i, indentableHeaders); + + if (foundIndentableHeader != NULL) + { + // must bypass the header before registering the in statement + outBuffer.append(foundIndentableHeader->substr(1)); + i += foundIndentableHeader->length() - 1; + if (!isInOperator && !isInTemplate && !isNonInStatementArray) + { + registerInStatementIndent(line, i, spaceTabCount, tabIncrementIn, 0, false); + isInStatement = true; + } + continue; + } + + if (isCStyle() && findKeyword(line, i, AS_OPERATOR)) + isInOperator = true; + + // "new" operator is a pointer, not a calculation + if (findKeyword(line, i, AS_NEW)) + { + if (prevNonSpaceCh == '=' && isInStatement && !inStatementIndentStack->empty()) + inStatementIndentStack->back() = 0; + } + + if (isCStyle()) + { + if (findKeyword(line, i, AS_ASM) + || findKeyword(line, i, AS__ASM__)) + { + isInAsm = true; + } + else if (findKeyword(line, i, AS_MS_ASM) // microsoft specific + || findKeyword(line, i, AS_MS__ASM)) + { + int index = 4; + if (peekNextChar(line, i) == '_') // check for __asm + index = 5; + + char peekedChar = ASBase::peekNextChar(line, i + index); + if (peekedChar == '{' || peekedChar == ' ') + isInAsmBlock = true; + else + isInAsmOneLine = true; + } + } + + // append the entire name for all others + string name = getCurrentWord(line, i); + outBuffer.append(name.substr(1)); + i += name.length() - 1; + continue; + } + + // Handle operators + + bool isPotentialOperator = isCharPotentialOperator(ch); + + if (isPotentialOperator) + { + // Check if an operator has been reached. + const string *foundAssignmentOp = findOperator(line, i, assignmentOperators); + const string *foundNonAssignmentOp = findOperator(line, i, nonAssignmentOperators); + + // Since findHeader's boundry checking was not used above, it is possible + // that both an assignment op and a non-assignment op where found, + // e.g. '>>' and '>>='. If this is the case, treat the LONGER one as the + // found operator. + if (foundAssignmentOp != NULL && foundNonAssignmentOp != NULL) + { + if (foundAssignmentOp->length() < foundNonAssignmentOp->length()) + foundAssignmentOp = NULL; + else + foundNonAssignmentOp = NULL; + } + + if (foundNonAssignmentOp != NULL) + { + if (foundNonAssignmentOp->length() > 1) + { + outBuffer.append(foundNonAssignmentOp->substr(1)); + i += foundNonAssignmentOp->length() - 1; + } + + // For C++ input/output, operator<< and >> should be + // aligned, if we are not in a statement already and + // also not in the "operator<<(...)" header line + if (!isInOperator + && inStatementIndentStack->empty() + && isCStyle() + && (foundNonAssignmentOp == &AS_GR_GR || + foundNonAssignmentOp == &AS_LS_LS)) + { + // this will be true if the line begins with the operator + if (i < 2 && spaceTabCount == 0) + spaceTabCount += 2 * indentLength; + // align to the beginning column of the operator + registerInStatementIndent(line, i - foundNonAssignmentOp->length(), spaceTabCount, tabIncrementIn, 0, false); + } + } + + else if (foundAssignmentOp != NULL) + { + if (foundAssignmentOp->length() > 1) + { + outBuffer.append(foundAssignmentOp->substr(1)); + i += foundAssignmentOp->length() - 1; + } + + if (!isInOperator && !isInTemplate && !isNonInStatementArray) + { + // if multiple assignments, align on the previous word + if (foundAssignmentOp == &AS_ASSIGN + && prevNonSpaceCh != ']' // an array + && statementEndsWithComma(line, i)) + { + if (!haveAssignmentThisLine) // only one assignment indent per line + { + // register indent at previous word + haveAssignmentThisLine = true; + int prevWordIndex = getInStatementIndentAssign(line, i); + int inStatementIndent = prevWordIndex + spaceTabCount + tabIncrementIn; + inStatementIndentStack->push_back(inStatementIndent); + } + } + else + registerInStatementIndent(line, i, spaceTabCount, tabIncrementIn, 0, false); + + isInStatement = true; + } + } + } + } // end of for loop * end of for loop * end of for loop * end of for loop * end of for loop * + + // handle special cases of unindentation: + + /* + * if '{' doesn't follow an immediately previous '{' in the headerStack + * (but rather another header such as "for" or "if", then unindent it + * by one indentation relative to its block. + */ + + if (!lineStartsInComment + && !blockIndent + && outBuffer.length() > 0 + && outBuffer[0] == '{' + && !(lineOpeningBlocksNum > 0 && lineOpeningBlocksNum == lineClosingBlocksNum) + && !(headerStack->size() > 1 && (*headerStack)[headerStack->size()-2] == &AS_OPEN_BRACKET) + && shouldIndentBrackettedLine) + --tabCount; + + // must check one less in headerStack if more than one header on a line (allow-addins)... + else if (!lineStartsInComment + && (int) headerStack->size() > iPrelim + 1 + && !blockIndent + && outBuffer.length() > 0 + && outBuffer[0] == '{' + && !(lineOpeningBlocksNum > 0 && lineOpeningBlocksNum == lineClosingBlocksNum) + && !(headerStack->size() > 2 && (*headerStack)[headerStack->size()-3] == &AS_OPEN_BRACKET) + && shouldIndentBrackettedLine) + --tabCount; + + // unindent a closing bracket... + else if (!lineStartsInComment + && outBuffer.length() > 0 + && outBuffer[0] == '}' + && shouldIndentBrackettedLine) + --tabCount; + + // correctly indent one-line-blocks... + else if (!lineStartsInComment + && outBuffer.length() > 0 + && lineOpeningBlocksNum > 0 + && lineOpeningBlocksNum == lineClosingBlocksNum + && previousLineProbationTab) + --tabCount; //lineOpeningBlocksNum - (blockIndent ? 1 : 0); + + // correctly indent class continuation lines... + else if (!lineStartsInComment + && !lineOpensComment + && isInClassHeaderTab + && !blockIndent + && outBuffer.length() > 0 + && lineOpeningBlocksNum == 0 + && lineOpeningBlocksNum == lineClosingBlocksNum + && (headerStack->size() > 0 && headerStack->back() == &AS_CLASS)) + --tabCount; + + if (tabCount < 0) + tabCount = 0; + + // take care of extra bracket indentatation option... + if (!lineStartsInComment + && bracketIndent + && shouldIndentBrackettedLine + && outBuffer.length() > 0 + && (outBuffer[0] == '{' || outBuffer[0] == '}')) + tabCount++; + + if (isInDefine) + { + if (outBuffer[0] == '#') + { + string preproc = trim(string(outBuffer.c_str() + 1)); + if (preproc.compare(0, 6, "define") == 0) + { + if (!inStatementIndentStack->empty() + && inStatementIndentStack->back() > 0) + { + defineTabCount = tabCount; + } + else + { + defineTabCount = tabCount - 1; + tabCount--; + } + } + } + + tabCount -= defineTabCount; + } + + if (tabCount < 0) + tabCount = 0; + if (lineCommentNoBeautify || blockCommentNoBeautify || isInQuoteContinuation) + tabCount = spaceTabCount = 0; + + // finally, insert indentations into begining of line + + if (shouldForceTabIndentation) + { + tabCount += spaceTabCount / indentLength; + spaceTabCount = spaceTabCount % indentLength; + } + + outBuffer = preLineWS(spaceTabCount, tabCount) + outBuffer; + + prevFinalLineSpaceTabCount = spaceTabCount; + prevFinalLineTabCount = tabCount; + + if (lastLineHeader != NULL) + previousLastLineHeader = lastLineHeader; + + return outBuffer; +} + + +string ASBeautifier::preLineWS(int spaceTabCount, int tabCount) +{ + string ws; + + for (int i = 0; i < tabCount; i++) + ws += indentString; + + while ((spaceTabCount--) > 0) + ws += string(" "); + + return ws; + +} + +bool ASBeautifier::isClassAccessModifier(string& line) const +{ + size_t firstChar = line.find_first_not_of(" \t"); + if (firstChar == string::npos) + return false; + // bypass a colon + if (line[firstChar] == ':') + { + firstChar = line.find_first_not_of(" \t"); + if (firstChar == string::npos) + return false; + } + if (line.compare(firstChar, 7, "public ") == 0 + || line.compare(firstChar, 8, "private ") == 0 + || line.compare(firstChar, 10, "protected ") == 0) + return true; + return false; +} + +/** + * register an in-statement indent. + */ +void ASBeautifier::registerInStatementIndent(const string &line, int i, int spaceTabCount, + int tabIncrementIn, int minIndent, bool updateParenStack) +{ + int inStatementIndent; + int remainingCharNum = line.length() - i; + int nextNonWSChar = getNextProgramCharDistance(line, i); + + // if indent is around the last char in the line, indent instead one indent from the previous indent + if (nextNonWSChar == remainingCharNum) + { + int previousIndent = spaceTabCount; + if (!inStatementIndentStack->empty()) + previousIndent = inStatementIndentStack->back(); + int currIndent = /*2*/ indentLength + previousIndent; + if (currIndent > maxInStatementIndent + && line[i] != '{') + currIndent = indentLength * 2 + spaceTabCount; + inStatementIndentStack->push_back(currIndent); + if (updateParenStack) + parenIndentStack->push_back(previousIndent); + return; + } + + if (updateParenStack) + parenIndentStack->push_back(i + spaceTabCount - horstmannIndentInStatement); + + int tabIncrement = tabIncrementIn; + + // check for following tabs + for (int j = i + 1; j < (i + nextNonWSChar); j++) + { + if (line[j] == '\t') + tabIncrement += convertTabToSpaces(j, tabIncrement); + } + + inStatementIndent = i + nextNonWSChar + spaceTabCount + tabIncrement; + + // check for run-in statement + if (i > 0 && line[0] == '{') + inStatementIndent -= indentLength; + +// if (i + nextNonWSChar < minIndent) +// inStatementIndent = minIndent + spaceTabCount; + + if (inStatementIndent < minIndent) + inStatementIndent = minIndent + spaceTabCount; + +// if (i + nextNonWSChar > maxInStatementIndent) +// inStatementIndent = indentLength * 2 + spaceTabCount; + + if (inStatementIndent > maxInStatementIndent) + inStatementIndent = indentLength * 2 + spaceTabCount; + + if (!inStatementIndentStack->empty() && + inStatementIndent < inStatementIndentStack->back()) + inStatementIndent = inStatementIndentStack->back(); + + // the block opener is not indented for a NonInStatementArray + if (isNonInStatementArray && !bracketBlockStateStack->empty() && bracketBlockStateStack->back()) + inStatementIndent = 0; + + inStatementIndentStack->push_back(inStatementIndent); +} + +/** + * get distance to the next non-white space, non-comment character in the line. + * if no such character exists, return the length remaining to the end of the line. + */ +int ASBeautifier::getNextProgramCharDistance(const string &line, int i) const +{ + bool inComment = false; + int remainingCharNum = line.length() - i; + int charDistance; + char ch; + + for (charDistance = 1; charDistance < remainingCharNum; charDistance++) + { + ch = line[i + charDistance]; + if (inComment) + { + if (line.compare(i + charDistance, 2, "*/") == 0) + { + charDistance++; + inComment = false; + } + continue; + } + else if (isWhiteSpace(ch)) + continue; + else if (ch == '/') + { + if (line.compare(i + charDistance, 2, "//") == 0) + return remainingCharNum; + else if (line.compare(i + charDistance, 2, "/*") == 0) + { + charDistance++; + inComment = true; + } + } + else + return charDistance; + } + + return charDistance; +} + +// check if a specific line position contains a header. +const string* ASBeautifier::findHeader(const string &line, int i, + const vector<const string*>* possibleHeaders) const +{ + assert(isCharPotentialHeader(line, i)); + // check the word + size_t maxHeaders = possibleHeaders->size(); + for (size_t p = 0; p < maxHeaders; p++) + { + const string* header = (*possibleHeaders)[p]; + const size_t wordEnd = i + header->length(); + if (wordEnd > line.length()) + continue; + int result = (line.compare(i, header->length(), *header)); + if (result > 0) + continue; + if (result < 0) + break; + // check that this is not part of a longer word + if (wordEnd == line.length()) + return header; + if (isLegalNameChar(line[wordEnd])) + continue; + // is not a header if part of a definition + const char peekChar = peekNextChar(line, wordEnd - 1); + if (peekChar == ',' || peekChar == ')') + break; + return header; + } + return NULL; +} + +// check if a specific line position contains an operator. +const string* ASBeautifier::findOperator(const string &line, int i, + const vector<const string*>* possibleOperators) const +{ + assert(isCharPotentialOperator(line[i])); + // find the operator in the vector + // the vector contains the LONGEST operators first + // must loop thru the entire vector + size_t maxOperators = possibleOperators->size(); + for (size_t p = 0; p < maxOperators; p++) + { + const size_t wordEnd = i + (*(*possibleOperators)[p]).length(); + if (wordEnd > line.length()) + continue; + if (line.compare(i, (*(*possibleOperators)[p]).length(), *(*possibleOperators)[p]) == 0) + return (*possibleOperators)[p]; + } + return NULL; +} + +/** + * find the index number of a string element in a container of strings + * + * @return the index number of element in the container. -1 if element not found. + * @param container a vector of strings. + * @param element the element to find . + */ +int ASBeautifier::indexOf(vector<const string*> &container, const string *element) +{ + vector<const string*>::const_iterator where; + + where = find(container.begin(), container.end(), element); + if (where == container.end()) + return -1; + else + return (int) (where - container.begin()); +} + +/** + * convert tabs to spaces. + * i is the position of the character to convert to spaces. + * tabIncrementIn is the increment that must be added for tab indent characters + * to get the correct column for the current tab. + */ +int ASBeautifier::convertTabToSpaces(int i, int tabIncrementIn) const +{ + int tabToSpacesAdjustment = indentLength - 1 - ((tabIncrementIn + i) % indentLength); + return tabToSpacesAdjustment; +} + +/** + * trim removes the white space surrounding a line. + * + * @return the trimmed line. + * @param str the line to trim. + */ +string ASBeautifier::trim(const string &str) +{ + + int start = 0; + int end = str.length() - 1; + + while (start < end && isWhiteSpace(str[start])) + start++; + + while (start <= end && isWhiteSpace(str[end])) + end--; + + string returnStr(str, start, end + 1 - start); + return returnStr; +} + +/** + * Copy tempStacks for the copy constructor. + * The value of the vectors must also be copied. + */ +vector<vector<const string*>*>* ASBeautifier::copyTempStacks(const ASBeautifier &other) const +{ + vector<vector<const string*>*> *tempStacksNew = new vector<vector<const string*>*>; + vector<vector<const string*>*>::iterator iter; + for (iter = other.tempStacks->begin(); + iter != other.tempStacks->end(); + ++iter) + { + vector<const string*> *newVec = new vector<const string*>; + *newVec = **iter; + tempStacksNew->push_back(newVec); + } + return tempStacksNew; +} + +/** + * delete a static member vector to eliminate memory leak reporting for the vector + */ +void ASBeautifier::deleteStaticVectors() +{ + beautifierFileType = 9; // reset to an invalid type + deleteVector(headers); + deleteVector(nonParenHeaders); + deleteVector(preBlockStatements); + deleteVector(assignmentOperators); + deleteVector(nonAssignmentOperators); + deleteVector(indentableHeaders); +} + +/** + * delete a vector object + * T is the type of vector + * used for all vectors except tempStacks + */ +template<typename T> +void ASBeautifier::deleteContainer(T &container) +{ + if (container != NULL) + { + container->clear(); + delete (container); + container = NULL; + } +} + +/** + * Delete the tempStacks vector object. + * The tempStacks is a vector of pointers to strings allocated with + * the 'new' operator. + * Therefore the strings have to be deleted in addition to the + * tempStacks entries. + */ +void ASBeautifier::deleteContainer(vector<vector<const string*>*>* &container) +{ + if (container != NULL) + { + vector<vector<const string*>*>::iterator iter = container->begin(); + for (; iter != container->end(); iter++) + delete *iter; + container->clear(); + delete (container); + container = NULL; + } +} + +/** + * delete a vector<const string*>* object + */ +void ASBeautifier::deleteVector(vector<const string*>*& container) +{ + assert(container != NULL); + delete container; + container = NULL; +} + +/** + * initialize a vector object + * T is the type of vector + * used for all vectors + */ +template<typename T> +void ASBeautifier::initContainer(T &container, T value) +{ + // since the ASFormatter object is never deleted, + // the existing vectors must be deleted before creating new ones + if (container != NULL ) + deleteContainer(container); + container = value; +} + +/** + * initialize a vector<const string*>* object + */ +void ASBeautifier::initVector(vector<const string*>*& container) +{ + assert(container == NULL); + container = new vector<const string*>; +} + +/** + * Determine if an assignment statement ends with a comma + * that is not in a function argument. It ends with a + * comma if a comma is the last char on the line. + * + * @return true if line ends with a comma, otherwise false. + */ +bool ASBeautifier::statementEndsWithComma(string &line, int index) +{ + assert(line[index] == '='); + + bool isInComment = false; + bool isInQuote = false; + int parenCount = 0; + size_t lineLength = line.length(); + size_t i = 0; + char quoteChar = ' '; + + for (i = index + 1; i < lineLength; ++i) + { + char ch = line[i]; + + if (isInComment) + { + if (line.compare(i, 2, "*/") == 0) + { + isInComment = false; + ++i; + } + continue; + } + + if (ch == '\\') + { + ++i; + continue; + } + + if (isInQuote) + { + if (ch == quoteChar) + isInQuote = false; + continue; + } + + if (ch == '"' || ch == '\'') + { + isInQuote = true; + quoteChar = ch; + continue; + } + + if (line.compare(i, 2, "//") == 0) + break; + + if (line.compare(i, 2, "/*") == 0) + { + if (isLineEndComment(line, i)) + break; + else + { + isInComment = true; + ++i; + continue; + } + } + + if (ch == '(') + parenCount++; + if (ch == ')') + parenCount--; + } + if (isInComment + || isInQuote + || parenCount > 0) + return false; + + size_t lastChar = line.find_last_not_of(" \t", i - 1); + + if (lastChar == string::npos || line[lastChar] != ',') + return false; + + return true; +} + +/** + * check if current comment is a line-end comment + * + * @return is before a line-end comment. + */ +bool ASBeautifier::isLineEndComment(string& line, int startPos) const +{ + assert(line.compare(startPos, 2, "/*") == 0); + + // comment must be closed on this line with nothing after it + size_t endNum = line.find("*/", startPos + 2); + if (endNum != string::npos) + { + size_t nextChar = line.find_first_not_of(" \t", endNum + 2); + if (nextChar == string::npos) + return true; + } + return false; +} + +/** + * get the previous word index for an assignment operator + * + * @return is the index to the previous word (the in statement indent). + */ +int ASBeautifier::getInStatementIndentAssign(const string& line, size_t currPos) const +{ + assert(line[currPos] == '='); + + if (currPos == 0) + return 0; + + // get the last legal word (may be a number) + size_t end = line.find_last_not_of(" \t", currPos-1); + if (end == string::npos || !isLegalNameChar(line[end])) + return 0; + + int start; // start of the previous word + for (start = end; start > -1; start--) + { + if (!isLegalNameChar(line[start]) || line[start] == '.') + break; + } + start++; + + return start; +} + +/** + * get the instatement indent for a comma + * + * @return is the indent to the second word on the line (the in statement indent). + */ +int ASBeautifier::getInStatementIndentComma(const string& line, size_t currPos) const +{ + assert(line[currPos] == ','); + + if (currPos == 0) + return 0; + + // get first word on a line + size_t indent = line.find_first_not_of(" \t"); + if (indent == string::npos || !isLegalNameChar(line[indent])) + return 0; + + // bypass first word + for (; indent < currPos; indent++) + { + if (!isLegalNameChar(line[indent])) + break; + } + indent++; + if (indent >= currPos) + return 0; + + // point to second word or assignment operator + indent = line.find_last_not_of(" \t", indent); + if (indent == string::npos || indent >= currPos) + return 0; + + return indent; +} + + +} // end namespace astyle + diff --git a/support/highlight/src/core/astyle/ASEnhancer.cpp b/support/highlight/src/core/astyle/ASEnhancer.cpp new file mode 100644 index 0000000000..7615601431 --- /dev/null +++ b/support/highlight/src/core/astyle/ASEnhancer.cpp @@ -0,0 +1,582 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * + * Copyright (C) 2006-2010 by Jim Pattee <jimp03@email.com> + * Copyright (C) 1998-2002 by Tal Davidson + * <http://www.gnu.org/licenses/lgpl-3.0.html> + * + * This file is a part of Artistic Style - an indentation and + * reformatting tool for C, C++, C# and Java source files. + * <http://astyle.sourceforge.net> + * + * Artistic Style is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Artistic Style is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Artistic Style. If not, see <http://www.gnu.org/licenses/>. + * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + */ + +#include "astyle.h" + + +namespace astyle +{ + +// ---------------------------- functions for ASEnhancer Class ------------------------------------- + +/** + * ASEnhancer constructor + */ +ASEnhancer::ASEnhancer() +{ + // the following prevents warning messages with cppcheck + // it will NOT compile if activated +// init(); +} + +/** + * Destructor of ASEnhancer + */ +ASEnhancer::~ASEnhancer() +{ +} + +/** + * initialize the ASEnhancer. + * + * init() is called each time an ASFormatter object is initialized. + */ +void ASEnhancer::init(int fileType, + int _indentLength, + string _indentString, + bool _caseIndent, + bool _emptyLineFill) +{ + // formatting variables from ASFormatter and ASBeautifier + ASBase::init(fileType); + indentLength = _indentLength; + if (_indentString == "\t") + useTabs = true; + else + useTabs = false; + + caseIndent = _caseIndent; + emptyLineFill = _emptyLineFill; + quoteChar = '\''; + + // unindent variables + lineNumber = 0; + bracketCount = 0; + isInComment = false; + isInQuote = false; + switchDepth = 0; + lookingForCaseBracket = false; + unindentNextLine = false; + + // switch struct and vector + sw.switchBracketCount = 0; + sw.unindentDepth = 0; + sw.unindentCase = false; + swVector.clear(); + + // other variables + nextLineIsEventIndent = false; + isInEventTable = false; + nextLineIsDeclareIndent = false; + isInDeclareSection = false; +} + +/** + * additional formatting for line of source code. + * every line of source code in a source code file should be sent + * one after the other to this function. + * indents event tables + * unindents the case blocks + * + * @param line the original formatted line will be updated if necessary. + */ +void ASEnhancer::enhance(string &line, bool isInSQL) +{ + bool isSpecialChar = false; // is a backslash escape character + + lineNumber++; + + // check for beginning of event table + if (nextLineIsEventIndent) + { + isInEventTable = true; + nextLineIsEventIndent = false; + } + + // check for beginning of SQL declare section + if (nextLineIsDeclareIndent) + { + isInDeclareSection = true; + nextLineIsDeclareIndent = false; + } + + if (line.length() == 0 + && ! isInEventTable + && ! isInDeclareSection + && ! emptyLineFill) + return; + + // test for unindent on attached brackets + if (unindentNextLine) + { + sw.unindentDepth++; + sw.unindentCase = true; + unindentNextLine = false; + } + + // parse characters in the current line. + + for (size_t i = 0; i < line.length(); i++) + { + char ch = line[i]; + + // bypass whitespace + if (isWhiteSpace(ch)) + continue; + + // handle special characters (i.e. backslash+character such as \n, \t, ...) + if (isSpecialChar) + { + isSpecialChar = false; + continue; + } + if (!(isInComment) && line.compare(i, 2, "\\\\") == 0) + { + i++; + continue; + } + if (!(isInComment) && ch == '\\') + { + isSpecialChar = true; + continue; + } + + // handle quotes (such as 'x' and "Hello Dolly") + if (!isInComment && (ch == '"' || ch == '\'')) + { + if (!isInQuote) + { + quoteChar = ch; + isInQuote = true; + } + else if (quoteChar == ch) + { + isInQuote = false; + continue; + } + } + + if (isInQuote) + continue; + + // handle comments + + if (!(isInComment) && line.compare(i, 2, "//") == 0) + { + // check for windows line markers + if (line.compare(i + 2, 1, "\xf0") > 0) + lineNumber--; + break; // finished with the line + } + else if (!(isInComment) && line.compare(i, 2, "/*") == 0) + { + isInComment = true; + i++; + continue; + } + else if ((isInComment) && line.compare(i, 2, "*/") == 0) + { + isInComment = false; + i++; + continue; + } + + if (isInComment) + continue; + + // if we have reached this far then we are NOT in a comment or string of special characters + + if (line[i] == '{') + bracketCount++; + + if (line[i] == '}') + bracketCount--; + + bool isPotentialKeyword = isCharPotentialHeader(line, i); + + // ---------------- process event tables -------------------------------------- + + if (isPotentialKeyword) + { + if (findKeyword(line, i, "BEGIN_EVENT_TABLE") + || findKeyword(line, i, "BEGIN_MESSAGE_MAP")) + { + nextLineIsEventIndent = true; + break; + } + + if (findKeyword(line, i, "END_EVENT_TABLE") + || findKeyword(line, i, "END_MESSAGE_MAP")) + { + isInEventTable = false; + break; + } + } + + // ---------------- process SQL ----------------------------------------------- + + if (isInSQL) + { + if (isBeginDeclareSectionSQL(line, i)) + nextLineIsDeclareIndent = true; + if (isEndDeclareSectionSQL(line, i)) + isInDeclareSection = false; + break; + } + + // ---------------- process switch statements --------------------------------- + + if (isPotentialKeyword && findKeyword(line, i, "switch")) + { + switchDepth++; + swVector.push_back(sw); // save current variables + sw.switchBracketCount = 0; + sw.unindentCase = false; // don't clear case until end of switch + i += 5; // bypass switch statement + continue; + } + + // just want unindented switch statements from this point + + if (caseIndent || switchDepth == 0) + { + // bypass the entire word + if (isPotentialKeyword) + { + string name = getCurrentWord(line, i); + i += name.length() - 1; + } + continue; + } + + i = processSwitchBlock(line, i); + + } // end of for loop * end of for loop * end of for loop * end of for loop + + if (isInEventTable || isInDeclareSection) + { + if (line[0] != '#') + indentLine(line, 1); + } + + if (sw.unindentDepth > 0) + unindentLine(line, sw.unindentDepth); +} + +/** + * find the colon following a 'case' statement + * + * @param line a reference to the line. + * @param i the line index of the case statement. + * @return the line index of the colon. + */ +size_t ASEnhancer::findCaseColon(string &line, size_t caseIndex) const +{ + size_t i = caseIndex; + bool isInQuote = false; + char quoteChar = ' '; + for (; i < line.length(); i++) + { + if (isInQuote) + { + if (line[i] == '\\') + { + i++; + continue; + } + else if (line[i] == quoteChar) // check ending quote + { + isInQuote = false; + quoteChar = ' '; + continue; + } + else + { + continue; // must close quote before continuing + } + } + if (line[i] == '\'' || line[i] == '\"') // check opening quote + { + isInQuote = true; + quoteChar = line[i]; + continue; + } + if (line[i] == ':') + { + if ((i + 1 < line.length()) && (line[i + 1] == ':')) + i++; // bypass scope resolution operator + else + break; // found it + } + } + return i; +} + +/** + * indent a line by a given number of tabsets + * by inserting leading whitespace to the line argument. + * + * @param line a reference to the line to indent. + * @param unindent the number of tabsets to insert. + * @return the number of characters inserted. + */ +int ASEnhancer::indentLine(string &line, int indent) const +{ + if (line.length() == 0 + && ! emptyLineFill) + return 0; + + size_t charsToInsert; // number of chars to insert + + if (useTabs) // if formatted with tabs + { + charsToInsert = indent; // tabs to insert + line.insert((size_t) 0, charsToInsert, '\t'); // insert the tabs + } + else + { + charsToInsert = indent * indentLength; // compute chars to insert + line.insert((size_t)0, charsToInsert, ' '); // insert the spaces + } + + return charsToInsert; +} + +/** + * check for SQL "BEGIN DECLARE SECTION". + * must compare case insensitive and allow any spacing between words. + * + * @param line a reference to the line to indent. + * @param index the current line index. + * @return true if a hit. + */ +bool ASEnhancer::isBeginDeclareSectionSQL(string &line, size_t index) const +{ + string word; + size_t hits = 0; + size_t i; + for (i = index; i < line.length(); i++) + { + i = line.find_first_not_of(" \t", i); + if (i == string::npos) + return false; + if (line[i] == ';') + break; + if (!isCharPotentialHeader(line, i)) + continue; + word = getCurrentWord(line, i); + for (size_t j = 0; j < word.length(); j++) + word[j] = (char) toupper(word[j]); + if (word == "EXEC" || word == "SQL") + { + i += word.length() - 1; + continue; + } + if (word == "DECLARE" || word == "SECTION") + { + hits++; + i += word.length() - 1; + continue; + } + if (word == "BEGIN") + { + hits++; + i += word.length() - 1; + continue; + } + return false; + } + if (hits == 3) + return true; + return false; +} + +/** + * check for SQL "END DECLARE SECTION". + * must compare case insensitive and allow any spacing between words. + * + * @param line a reference to the line to indent. + * @param index the current line index. + * @return true if a hit. + */ +bool ASEnhancer::isEndDeclareSectionSQL(string &line, size_t index) const +{ + string word; + size_t hits = 0; + size_t i; + for (i = index; i < line.length(); i++) + { + i = line.find_first_not_of(" \t", i); + if (i == string::npos) + return false; + if (line[i] == ';') + break; + if (!isCharPotentialHeader(line, i)) + continue; + word = getCurrentWord(line, i); + for (size_t j = 0; j < word.length(); j++) + word[j] = (char) toupper(word[j]); + if (word == "EXEC" || word == "SQL") + { + i += word.length() - 1; + continue; + } + if (word == "DECLARE" || word == "SECTION") + { + hits++; + i += word.length() - 1; + continue; + } + if (word == "END") + { + hits++; + i += word.length() - 1; + continue; + } + return false; + } + if (hits == 3) + return true; + return false; +} + +/** + * process the character at the current index in a switch block. + * + * @param line a reference to the line to indent. + * @param index the current line index. + * @return the new line index. + */ +size_t ASEnhancer::processSwitchBlock(string &line, size_t index) +{ + size_t i = index; + bool isPotentialKeyword = isCharPotentialHeader(line, i); + + if (line[i] == '{') + { + sw.switchBracketCount++; + if (lookingForCaseBracket) // if 1st after case statement + { + sw.unindentCase = true; // unindenting this case + sw.unindentDepth++; + lookingForCaseBracket = false; // not looking now + } + return i; + } + lookingForCaseBracket = false; // no opening bracket, don't indent + + if (line[i] == '}') // if close bracket + { + sw.switchBracketCount--; + if (sw.switchBracketCount == 0) // if end of switch statement + { + switchDepth--; // one less switch + sw = swVector.back(); // restore sw struct + swVector.pop_back(); // remove last entry from stack + } + return i; + } + + if (isPotentialKeyword + && (findKeyword(line, i, "case") || findKeyword(line, i, "default"))) + { + if (sw.unindentCase) // if unindented last case + { + sw.unindentCase = false; // stop unindenting previous case + sw.unindentDepth--; // reduce depth + } + + i = findCaseColon(line, i); + + i++; + for (; i < line.length(); i++) // bypass whitespace + { + if (!isWhiteSpace(line[i])) + break; + } + if (i < line.length()) + { + if (line[i] == '{') + { + sw.switchBracketCount++; + unindentNextLine = true; + return i; + } + } + lookingForCaseBracket = true; // bracket must be on next line + i--; // need to check for comments + return i; + } + if (isPotentialKeyword) + { + string name = getCurrentWord(line, i); // bypass the entire name + i += name.length() - 1; + } + return i; +} + +/** + * unindent a line by a given number of tabsets + * by erasing the leading whitespace from the line argument. + * + * @param line a reference to the line to unindent. + * @param unindent the number of tabsets to erase. + * @return the number of characters erased. + */ +int ASEnhancer::unindentLine(string &line, int unindent) const +{ + size_t whitespace = line.find_first_not_of(" \t"); + + if (whitespace == string::npos) // if line is blank + whitespace = line.length(); // must remove padding, if any + + if (whitespace == 0) + return 0; + + size_t charsToErase; // number of chars to erase + + if (useTabs) // if formatted with tabs + { + charsToErase = unindent; // tabs to erase + if (charsToErase <= whitespace) // if there is enough whitespace + line.erase(0, charsToErase); // erase the tabs + else + charsToErase = 0; + } + else + { + charsToErase = unindent * indentLength; // compute chars to erase + if (charsToErase <= whitespace) // if there is enough whitespace + line.erase(0, charsToErase); // erase the spaces + else + charsToErase = 0; + } + + return charsToErase; +} + + +} // end namespace astyle diff --git a/support/highlight/src/core/astyle/ASFormatter.cpp b/support/highlight/src/core/astyle/ASFormatter.cpp new file mode 100644 index 0000000000..3617c325b0 --- /dev/null +++ b/support/highlight/src/core/astyle/ASFormatter.cpp @@ -0,0 +1,4520 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * + * Copyright (C) 2006-2010 by Jim Pattee <jimp03@email.com> + * Copyright (C) 1998-2002 by Tal Davidson + * <http://www.gnu.org/licenses/lgpl-3.0.html> + * + * This file is a part of Artistic Style - an indentation and + * reformatting tool for C, C++, C# and Java source files. + * <http://astyle.sourceforge.net> + * + * Artistic Style is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Artistic Style is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Artistic Style. If not, see <http://www.gnu.org/licenses/>. + * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + */ + +#include "astyle.h" + +#include <algorithm> +#include <fstream> +#include <iostream> + + +namespace astyle +{ +// static member variables +int ASFormatter::formatterFileType = 9; // initialized with an invalid type +vector<const string*>* ASFormatter::headers = NULL; +vector<const string*>* ASFormatter::nonParenHeaders = NULL; +vector<const string*>* ASFormatter::preDefinitionHeaders = NULL; +vector<const string*>* ASFormatter::preCommandHeaders = NULL; +vector<const string*>* ASFormatter::operators = NULL; +vector<const string*>* ASFormatter::assignmentOperators = NULL; +vector<const string*>* ASFormatter::castOperators = NULL; + +/** + * Constructor of ASFormatter + */ +ASFormatter::ASFormatter() +{ + sourceIterator = NULL; + enhancer = new ASEnhancer; + preBracketHeaderStack = NULL; + bracketTypeStack = NULL; + parenStack = NULL; + structStack = NULL; + lineCommentNoIndent = false; + formattingStyle = STYLE_NONE; + bracketFormatMode = NONE_MODE; + pointerAlignment = ALIGN_NONE; + lineEnd = LINEEND_DEFAULT; + shouldPadOperators = false; + shouldPadParensOutside = false; + shouldPadParensInside = false; + shouldPadHeader = false; + shouldUnPadParens = false; + shouldBreakOneLineBlocks = true; + shouldBreakOneLineStatements = true; + shouldConvertTabs = false; + shouldIndentCol1Comments = false; + shouldBreakBlocks = false; + shouldBreakClosingHeaderBlocks = false; + shouldBreakClosingHeaderBrackets = false; + shouldDeleteEmptyLines = false; + shouldBreakElseIfs = false; + shouldAddBrackets = false; + shouldAddOneLineBrackets = false; + + // initialize ASFormatter static member vectors + formatterFileType = 9; // reset to an invalid type + initVector(headers); + initVector(nonParenHeaders); + initVector(preDefinitionHeaders); + initVector(preCommandHeaders); + initVector(operators); + initVector(assignmentOperators); + initVector(castOperators); + + // the following prevents warning messages with cppcheck + // it will NOT compile if activated +// init(); +} + +/** + * Destructor of ASFormatter + */ +ASFormatter::~ASFormatter() +{ + // delete ASFormatter stack vectors + deleteContainer(preBracketHeaderStack); + deleteContainer(bracketTypeStack); + deleteContainer(parenStack); + deleteContainer(structStack); + + // delete static member vectors using swap to eliminate memory leak reporting + // delete ASFormatter static member vectors + formatterFileType = 9; // reset to an invalid type + deleteVector(headers); + deleteVector(nonParenHeaders); + deleteVector(preDefinitionHeaders); + deleteVector(preCommandHeaders); + deleteVector(operators); + deleteVector(assignmentOperators); + deleteVector(castOperators); + + // delete ASBeautifier static member vectors + // must be done when the ASFormatter object is deleted (not ASBeautifier) + ASBeautifier::deleteStaticVectors(); + + delete enhancer; +} + +/** + * initialize the ASFormatter. + * + * init() should be called every time a ASFormatter object is to start + * formatting a NEW source file. + * init() recieves a pointer to a ASSourceIterator object that will be + * used to iterate through the source code. + * + * @param sourceIterator a pointer to the ASSourceIterator or ASStreamIterator object. + */ +void ASFormatter::init(ASSourceIterator *si) +{ + buildLanguageVectors(); + fixOptionVariableConflicts(); + + ASBeautifier::init(si); + enhancer->init(getFileType(), + getIndentLength(), + getIndentString(), + getCaseIndent(), + getEmptyLineFill()); + sourceIterator = si; + + initContainer(preBracketHeaderStack, new vector<const string*>); + initContainer(parenStack, new vector<int>); + initContainer(structStack, new vector<bool>); + parenStack->push_back(0); // parenStack must contain this default entry + initContainer(bracketTypeStack, new vector<BracketType>); + bracketTypeStack->push_back(NULL_TYPE); + + currentHeader = NULL; + currentLine = ""; + readyFormattedLine = ""; + formattedLine = ""; + currentChar = ' '; + previousChar = ' '; + previousCommandChar = ' '; + previousNonWSChar = ' '; + quoteChar = '"'; + charNum = 0; + leadingSpaces = 0; + formattedLineCommentNum = 0; + preprocBracketTypeStackSize = 0; + spacePadNum = 0; + nextLineSpacePadNum = 0; + currentLineFirstBracketNum = string::npos; + previousReadyFormattedLineLength = string::npos; + templateDepth = 0; + traceLineNumber = 0; + horstmannIndentChars = 0; + tabIncrementIn = 0; + previousBracketType = NULL_TYPE; + previousOperator = NULL; + + isVirgin = true; + isInLineComment = false; + isInComment = false; + noTrimCommentContinuation = false; + isInPreprocessor = false; + doesLineStartComment = false; + lineEndsInCommentOnly = false; + lineIsLineCommentOnly = false; + lineIsEmpty = false; + isImmediatelyPostCommentOnly = false; + isImmediatelyPostEmptyLine = false; + isInQuote = false; + isInVerbatimQuote = false; + haveLineContinuationChar = false; + isInQuoteContinuation = false; + isSpecialChar = false; + isNonParenHeader = false; + foundNamespaceHeader = false; + foundClassHeader = false; + foundStructHeader = false; + foundInterfaceHeader = false; + foundPreDefinitionHeader = false; + foundPreCommandHeader = false; + foundCastOperator = false; + foundQuestionMark = false; + isInLineBreak = false; + endOfCodeReached = false; + isInExecSQL = false; + isInAsm = false; + isInAsmOneLine = false; + isInAsmBlock = false; + isLineReady = false; + isPreviousBracketBlockRelated = false; + isInPotentialCalculation = false; + shouldReparseCurrentChar = false; + needHeaderOpeningBracket = false; + shouldBreakLineAtNextChar = false; + passedSemicolon = false; + passedColon = false; + clearNonInStatement = false; + isInTemplate = false; + isInBlParen = false; + isImmediatelyPostComment = false; + isImmediatelyPostLineComment = false; + isImmediatelyPostEmptyBlock = false; + isImmediatelyPostPreprocessor = false; + isImmediatelyPostReturn = false; + isImmediatelyPostOperator = false; + isCharImmediatelyPostReturn = false; + isCharImmediatelyPostOperator = false; + isCharImmediatelyPostComment = false; + isPreviousCharPostComment = false; + isCharImmediatelyPostLineComment = false; + isCharImmediatelyPostOpenBlock = false; + isCharImmediatelyPostCloseBlock = false; + isCharImmediatelyPostTemplate = false; + breakCurrentOneLineBlock = false; + isInHorstmannRunIn = false; + currentLineBeginsWithBracket = false; + isPrependPostBlockEmptyLineRequested = false; + isAppendPostBlockEmptyLineRequested = false; + prependEmptyLine = false; + appendOpeningBracket = false; + foundClosingHeader = false; + isImmediatelyPostHeader = false; + isInHeader = false; + isInCase = false; + isJavaStaticConstructor = false; +} + +/** + * build vectors for each programing language + * depending on the file extension. + */ +void ASFormatter::buildLanguageVectors() +{ + if (getFileType() == formatterFileType) // don't build unless necessary + return; + + formatterFileType = getFileType(); + + headers->clear(); + nonParenHeaders->clear(); + preDefinitionHeaders->clear(); + preCommandHeaders->clear(); + operators->clear(); + assignmentOperators->clear(); + castOperators->clear(); + + ASResource::buildHeaders(headers, getFileType()); + ASResource::buildNonParenHeaders(nonParenHeaders, getFileType()); + ASResource::buildPreDefinitionHeaders(preDefinitionHeaders, getFileType()); + ASResource::buildPreCommandHeaders(preCommandHeaders, getFileType()); + if (operators->size() == 0) + ASResource::buildOperators(operators); + if (assignmentOperators->size() == 0) + ASResource::buildAssignmentOperators(assignmentOperators); + if (castOperators->size() == 0) + ASResource::buildCastOperators(castOperators); +} + +/** + * set the variables for each preefined style. + * this will override any previous settings. + */ +void ASFormatter::fixOptionVariableConflicts() +{ + if (formattingStyle == STYLE_ALLMAN) + { + setBracketFormatMode(BREAK_MODE); + setBlockIndent(false); + setBracketIndent(false); + } + else if (formattingStyle == STYLE_JAVA) + { + setBracketFormatMode(ATTACH_MODE); + setBlockIndent(false); + setBracketIndent(false); + } + else if (formattingStyle == STYLE_KandR) + { + setBracketFormatMode(LINUX_MODE); + setBlockIndent(false); + setBracketIndent(false); + } + else if (formattingStyle == STYLE_STROUSTRUP) + { + setBracketFormatMode(STROUSTRUP_MODE); + setBlockIndent(false); + setBracketIndent(false); + if (!getIndentManuallySet()) + { + if (getIndentString() == "\t") + setTabIndentation(5, getForceTabIndentation()); + else + setSpaceIndentation(5); + } + } + else if (formattingStyle == STYLE_WHITESMITH) + { + setBracketFormatMode(BREAK_MODE); + setBlockIndent(false); + setBracketIndent(true); + setClassIndent(true); + setSwitchIndent(true); + } + else if (formattingStyle == STYLE_BANNER) + { + setBracketFormatMode(ATTACH_MODE); + setBlockIndent(false); + setBracketIndent(true); + setClassIndent(true); + setSwitchIndent(true); + } + else if (formattingStyle == STYLE_GNU) + { + setBracketFormatMode(BREAK_MODE); + setBlockIndent(true); + setBracketIndent(false); + if (!getIndentManuallySet()) + { + if (getIndentString() == "\t") + setTabIndentation(2, getForceTabIndentation()); + else + setSpaceIndentation(2); + } + } + else if (formattingStyle == STYLE_LINUX) + { + setBracketFormatMode(LINUX_MODE); + setBlockIndent(false); + setBracketIndent(false); + if (!getIndentManuallySet()) + { + if (getIndentString() == "\t") + setTabIndentation(8, getForceTabIndentation()); + else + setSpaceIndentation(8); + } + if (!getMinConditionalManuallySet()) + setMinConditionalIndentLength(getIndentLength() / 2); + } + else if (formattingStyle == STYLE_HORSTMANN) + { + setBracketFormatMode(HORSTMANN_MODE); + setBlockIndent(false); + setBracketIndent(false); + setSwitchIndent(true); + if (!getIndentManuallySet()) + { + if (getIndentString() == "\t") + setTabIndentation(3, getForceTabIndentation()); + else + setSpaceIndentation(3); + } + } + else if (formattingStyle == STYLE_1TBS) + { + setBracketFormatMode(LINUX_MODE); + setBlockIndent(false); + setBracketIndent(false); + setAddBracketsMode(true); + } + + // add-one-line-brackets implies keep-one-line-blocks + if (shouldAddOneLineBrackets) + setBreakOneLineBlocksMode(false); + // cannot have both indent-blocks and indent-brackets, default to indent-blocks + if (getBlockIndent()) + setBracketIndent(false); +} + +/** + * get the next formatted line. + * + * @return formatted line. + */ + +string ASFormatter::nextLine() +{ + const string *newHeader; + bool isInVirginLine = isVirgin; + isCharImmediatelyPostComment = false; + isPreviousCharPostComment = false; + isCharImmediatelyPostLineComment = false; + isCharImmediatelyPostOpenBlock = false; + isCharImmediatelyPostCloseBlock = false; + isCharImmediatelyPostTemplate = false; + traceLineNumber++; + + while (!isLineReady) + { + if (shouldReparseCurrentChar) + shouldReparseCurrentChar = false; + else if (!getNextChar()) + { + breakLine(); + return beautify(readyFormattedLine); + } + else // stuff to do when reading a new character... + { + // make sure that a virgin '{' at the begining of the file will be treated as a block... + if (isInVirginLine && currentChar == '{' + && currentLineBeginsWithBracket // lineBeginsWith('{') + && previousCommandChar == ' ') + previousCommandChar = '{'; + if (clearNonInStatement) + { + isNonInStatementArray = false; + clearNonInStatement = false; + } + if (isInHorstmannRunIn) + isInLineBreak = false; + if (!isWhiteSpace(currentChar)) + isInHorstmannRunIn = false; + isPreviousCharPostComment = isCharImmediatelyPostComment; + isCharImmediatelyPostComment = false; + isCharImmediatelyPostTemplate = false; + isCharImmediatelyPostReturn = false; + isCharImmediatelyPostOperator = false; + isCharImmediatelyPostOpenBlock = false; + isCharImmediatelyPostCloseBlock = false; + } + +// if (inLineNumber >= 7) +// int x = 1; + + if (shouldBreakLineAtNextChar && !isWhiteSpace(currentChar)) + { + isInLineBreak = true; + shouldBreakLineAtNextChar = false; + } + + if (isInExecSQL && !passedSemicolon) + { + if (currentChar == ';') + passedSemicolon = true; + appendCurrentChar(); + continue; + } + + if (isInLineComment) + { + formatLineCommentBody(); + continue; + } + else if (isInComment) + { + formatCommentBody(); + continue; + } + + // not in line comment or comment + + else if (isInQuote) + { + formatQuoteBody(); + continue; + } + + if (isSequenceReached("//")) + { + formatLineCommentOpener(); + continue; + } + else if (isSequenceReached("/*")) + { + formatCommentOpener(); + continue; + } + else if (currentChar == '"' || currentChar == '\'') + { + formatQuoteOpener(); + continue; + } + // treat these preprocessor statements as a line comment + else if (currentChar =='#') + { + if (isSequenceReached("#region") + || isSequenceReached("#endregion") + || isSequenceReached("#error") + || isSequenceReached("#warning")) + { + // check for horstmann run-in + if (formattedLine[0] == '{') + { + isInLineBreak = true; + isInHorstmannRunIn = false; + } + isInLineComment = true; + appendCurrentChar(); + continue; + } + } + + if (isInPreprocessor) + { + appendCurrentChar(); + continue; + } + + // handle white space - needed to simplify the rest. + if (isWhiteSpace(currentChar)) + { + appendCurrentChar(); + continue; + } + + /* not in MIDDLE of quote or comment or SQL or white-space of any type ... */ + + // check if in preprocessor + // ** isInPreprocessor will be automatically reset at the begining + // of a new line in getnextChar() + if (currentChar == '#') + { + isInPreprocessor = true; + // check for horstmann run-in + if (formattedLine[0] == '{') + { + isInLineBreak = true; + isInHorstmannRunIn = false; + } + processPreprocessor(); + // need to fall thru here to reset the variables + } + + /* not in preprocessor ... */ + + if (isImmediatelyPostComment) + { + isImmediatelyPostComment = false; + isCharImmediatelyPostComment = true; + } + + if (isImmediatelyPostLineComment) + { + isImmediatelyPostLineComment = false; + isCharImmediatelyPostLineComment = true; + } + + if (isImmediatelyPostReturn) + { + isImmediatelyPostReturn = false; + isCharImmediatelyPostReturn = true; + } + + if (isImmediatelyPostOperator) + { + isImmediatelyPostOperator = false; + isCharImmediatelyPostOperator = true; + } + + // reset isImmediatelyPostHeader information + if (isImmediatelyPostHeader) + { + // should brackets be added + if (currentChar != '{' && shouldAddBrackets) + { + bool bracketsAdded = addBracketsToStatement(); + if (bracketsAdded && !shouldAddOneLineBrackets) + { + size_t firstText = currentLine.find_first_not_of(" \t"); + assert(firstText != string::npos); + if ((int) firstText == charNum) + breakCurrentOneLineBlock = true; + } + } + + // Make sure headers are broken from their succeeding blocks + // (e.g. + // if (isFoo) DoBar(); + // should become + // if (isFoo) + // DoBar; + // ) + // But treat else if() as a special case which should not be broken! + if (shouldBreakOneLineStatements + && isOkToBreakBlock(bracketTypeStack->back())) + { + // if may break 'else if()'s, then simply break the line + if (shouldBreakElseIfs) + isInLineBreak = true; + } + + isImmediatelyPostHeader = false; + } + + if (passedSemicolon) // need to break the formattedLine + { + passedSemicolon = false; + if (parenStack->back() == 0 && currentChar != ';') // allow ;; + { + // does a one-line statement have ending comments? + if (isBracketType(bracketTypeStack->back(), SINGLE_LINE_TYPE)) + { + size_t blockEnd = currentLine.rfind(AS_CLOSE_BRACKET); + assert(blockEnd != string::npos); + // move ending comments to this formattedLine + if (isBeforeAnyLineEndComment(blockEnd)) + { + size_t commentStart = currentLine.find_first_not_of(" \t", blockEnd + 1); + assert(commentStart != string::npos); + assert((currentLine.compare(commentStart, 2, "//") == 0) + || (currentLine.compare(commentStart, 2, "/*") == 0)); + size_t commentLength = currentLine.length() - commentStart; + formattedLine.append(getIndentLength() - 1, ' '); + formattedLine.append(currentLine, commentStart, commentLength); + currentLine.erase(commentStart, commentLength); + } + } + isInExecSQL = false; + shouldReparseCurrentChar = true; + isInLineBreak = true; + if (needHeaderOpeningBracket) + { + isCharImmediatelyPostCloseBlock = true; + needHeaderOpeningBracket = false; + } + continue; + } + } + + if (passedColon) + { + passedColon = false; + if (parenStack->back() == 0 && !isBeforeAnyComment()) + { + shouldReparseCurrentChar = true; + isInLineBreak = true; + continue; + } + } + + // Check if in template declaration, e.g. foo<bar> or foo<bar,fig> + // If so, set isInTemplate to true + if (!isInTemplate && currentChar == '<') + { + int maxTemplateDepth = 0; + templateDepth = 0; + for (size_t i = charNum; + i < currentLine.length(); + i++) + { + char currentChar = currentLine[i]; + + if (currentChar == '<') + { + templateDepth++; + maxTemplateDepth++; + } + else if (currentChar == '>') + { + templateDepth--; + if (templateDepth == 0) + { + // this is a template! + isInTemplate = true; + templateDepth = maxTemplateDepth; + break; + } + } + else if (currentLine.compare(i, 2, "&&") == 0 + || currentLine.compare(i, 2, "||") == 0) + { + // this is not a template -> leave... + isInTemplate = false; + break; + } + else if (currentChar == ',' // comma, e.g. A<int, char> + || currentChar == '&' // reference, e.g. A<int&> + || currentChar == '*' // pointer, e.g. A<int*> + || currentChar == ':' // ::, e.g. std::string + || currentChar == '[' // [] e.g. string[] + || currentChar == ']' // [] e.g. string[] + || currentChar == '(' // (...) e.g. function definition + || currentChar == ')') // (...) e.g. function definition + { + continue; + } + else if (!isLegalNameChar(currentChar) && !isWhiteSpace(currentChar)) + { + // this is not a template -> leave... + isInTemplate = false; + break; + } + } + } + + // handle parenthesies + if (currentChar == '(' || currentChar == '[' || (isInTemplate && currentChar == '<')) + { + parenStack->back()++; + if (currentChar == '[') + isInBlParen = true; + } + else if (currentChar == ')' || currentChar == ']' || (isInTemplate && currentChar == '>')) + { + parenStack->back()--; + if (isInTemplate && currentChar == '>') + { + templateDepth--; + if (templateDepth == 0) + { + isInTemplate = false; + isCharImmediatelyPostTemplate = true; + } + } + + // check if this parenthesis closes a header, e.g. if (...), while (...) + if (isInHeader && parenStack->back() == 0) + { + isInHeader = false; + isImmediatelyPostHeader = true; + } + if (currentChar == ']') + isInBlParen = false; + if (currentChar == ')') + { + foundCastOperator = false; + if (parenStack->back() == 0) + isInAsm = false; + } + } + + // handle brackets + if (currentChar == '{' || currentChar == '}') + { + // if appendOpeningBracket this was already done for the original bracket + if (currentChar == '{' && !appendOpeningBracket) + { + BracketType newBracketType = getBracketType(); + foundNamespaceHeader = false; + foundClassHeader = false; + foundStructHeader = false; + foundInterfaceHeader = false; + foundPreDefinitionHeader = false; + foundPreCommandHeader = false; + isInPotentialCalculation = false; + isJavaStaticConstructor = false; + needHeaderOpeningBracket = false; + + isPreviousBracketBlockRelated = !isBracketType(newBracketType, ARRAY_TYPE); + bracketTypeStack->push_back(newBracketType); + preBracketHeaderStack->push_back(currentHeader); + currentHeader = NULL; + structStack->push_back(isInIndentableStruct); + if (isBracketType(newBracketType, STRUCT_TYPE) && isCStyle()) + isInIndentableStruct = isStructAccessModified(currentLine, charNum); + else + isInIndentableStruct = false; + } + + // this must be done before the bracketTypeStack is popped + BracketType bracketType = bracketTypeStack->back(); + bool isOpeningArrayBracket = (isBracketType(bracketType, ARRAY_TYPE) + && bracketTypeStack->size() >= 2 + && !isBracketType((*bracketTypeStack)[bracketTypeStack->size()-2], ARRAY_TYPE) + ); + + if (currentChar == '}') + { + // if a request has been made to append a post block empty line, + // but the block exists immediately before a closing bracket, + // then there is no need for the post block empty line. + isAppendPostBlockEmptyLineRequested = false; + breakCurrentOneLineBlock = false; + isInAsmBlock = false; + + // added for release 1.24 + // TODO: remove at the appropriate time + assert(isInAsm == false); + assert(isInAsmOneLine == false); + assert(isInQuote == false); + isInAsm = isInAsmOneLine = isInQuote = false; + // end remove + + if (bracketTypeStack->size() > 1) + { + previousBracketType = bracketTypeStack->back(); + bracketTypeStack->pop_back(); + isPreviousBracketBlockRelated = !isBracketType(bracketType, ARRAY_TYPE); + } + else + { + previousBracketType = NULL_TYPE; + isPreviousBracketBlockRelated = false; + } + + if (!preBracketHeaderStack->empty()) + { + currentHeader = preBracketHeaderStack->back(); + preBracketHeaderStack->pop_back(); + } + else + currentHeader = NULL; + + if (!structStack->empty()) + { + isInIndentableStruct = structStack->back(); + structStack->pop_back(); + } + else + isInIndentableStruct = false; + + if (isBracketType(bracketType, ARRAY_NIS_TYPE) && !isBracketType(bracketType, SINGLE_LINE_TYPE)) + clearNonInStatement = true; + } + + // format brackets + appendOpeningBracket = false; + if (isBracketType(bracketType, ARRAY_TYPE)) + { + formatArrayBrackets(bracketType, isOpeningArrayBracket); + } + else + { + if (currentChar == '{') + formatOpeningBracket(bracketType); + else + formatClosingBracket(bracketType); + } + continue; + } + + if ((((previousCommandChar == '{' && isPreviousBracketBlockRelated) + || ((previousCommandChar == '}' + && !isImmediatelyPostEmptyBlock + && isPreviousBracketBlockRelated + && !isPreviousCharPostComment // Fixes wrongly appended newlines after '}' immediately after comments + && peekNextChar() != ' ' + && !isBracketType(previousBracketType, DEFINITION_TYPE)) + && !isBracketType(bracketTypeStack->back(), DEFINITION_TYPE))) + && isOkToBreakBlock(bracketTypeStack->back())) + // check for array + || (isBracketType(bracketTypeStack->back(), ARRAY_TYPE) + && !isBracketType(bracketTypeStack->back(), SINGLE_LINE_TYPE) + && isNonInStatementArray)) + { + isCharImmediatelyPostOpenBlock = (previousCommandChar == '{'); + isCharImmediatelyPostCloseBlock = (previousCommandChar == '}'); + + if (isCharImmediatelyPostOpenBlock + && !isCharImmediatelyPostComment + && !isCharImmediatelyPostLineComment) + { + previousCommandChar = ' '; + + if (bracketFormatMode == NONE_MODE) + { + if (shouldBreakOneLineBlocks + && isBracketType(bracketTypeStack->back(), SINGLE_LINE_TYPE)) + isInLineBreak = true; + else if (currentLineBeginsWithBracket) + formatRunIn(); + else + breakLine(); + } + else if (bracketFormatMode == HORSTMANN_MODE + && currentChar != '#') + formatRunIn(); + else + isInLineBreak = true; + } + else if (isCharImmediatelyPostCloseBlock + && shouldBreakOneLineStatements + && (isLegalNameChar(currentChar) && currentChar != '.') + && !isCharImmediatelyPostComment) + { + previousCommandChar = ' '; + isInLineBreak = true; + } + } + + // reset block handling flags + isImmediatelyPostEmptyBlock = false; + + // look for headers + bool isPotentialHeader = isCharPotentialHeader(currentLine, charNum); + + if (isPotentialHeader && !isInTemplate) + { + isNonParenHeader = false; + foundClosingHeader = false; + newHeader = findHeader(headers); + + if (newHeader != NULL) + { + char peekChar = ASBase::peekNextChar(currentLine, charNum + newHeader->length() - 1); + + // is not a header if part of a definition + if (peekChar == ',' || peekChar == ')') + newHeader = NULL; + // the following accessor definitions are NOT headers + // goto default; is NOT a header + else if ((newHeader == &AS_GET || newHeader == &AS_SET || newHeader == &AS_DEFAULT) + && peekChar == ';') + { + newHeader = NULL; + } + } + + if (newHeader != NULL) + { + const string *previousHeader; + + // recognize closing headers of do..while, if..else, try..catch..finally + if ((newHeader == &AS_ELSE && currentHeader == &AS_IF) + || (newHeader == &AS_WHILE && currentHeader == &AS_DO) + || (newHeader == &AS_CATCH && currentHeader == &AS_TRY) + || (newHeader == &AS_CATCH && currentHeader == &AS_CATCH) + || (newHeader == &AS_FINALLY && currentHeader == &AS_TRY) + || (newHeader == &AS_FINALLY && currentHeader == &AS_CATCH) + || (newHeader == &AS_SET && currentHeader == &AS_GET) + || (newHeader == &AS_REMOVE && currentHeader == &AS_ADD)) + foundClosingHeader = true; + + previousHeader = currentHeader; + currentHeader = newHeader; + needHeaderOpeningBracket = true; + + if (foundClosingHeader && previousNonWSChar == '}') + { + if (isOkToBreakBlock(bracketTypeStack->back())) + isLineBreakBeforeClosingHeader(); + + // get the adjustment for a comment following the closing header + if (isInLineBreak) + nextLineSpacePadNum = getNextLineCommentAdjustment(); + else + spacePadNum = getCurrentLineCommentAdjustment(); + } + + // check if the found header is non-paren header + isNonParenHeader = findHeader(nonParenHeaders) != NULL; + + // join 'else if' statements + if (currentHeader == &AS_IF && previousHeader == &AS_ELSE && isInLineBreak + && !shouldBreakElseIfs && !isCharImmediatelyPostLineComment) + { + // 'else' must be last thing on the line, but must not be #else + size_t start = formattedLine.length() >= 6 ? formattedLine.length()-6 : 0; + if (formattedLine.find("else", start) != string::npos + && formattedLine.find("#else", start) == string::npos) + { + appendSpacePad(); + isInLineBreak = false; + } + } + + appendSequence(*currentHeader); + goForward(currentHeader->length() - 1); + // if a paren-header is found add a space after it, if needed + // this checks currentLine, appendSpacePad() checks formattedLine + // in C# 'catch' can be either a paren or non-paren header + if (shouldPadHeader + && (!isNonParenHeader || (currentHeader == &AS_CATCH && peekNextChar() == '(')) + && charNum < (int) currentLine.length() && !isWhiteSpace(currentLine[charNum+1])) + appendSpacePad(); + + // Signal that a header has been reached + // *** But treat a closing while() (as in do...while) + // as if it were NOT a header since a closing while() + // should never have a block after it! + if (!(foundClosingHeader && currentHeader == &AS_WHILE)) + { + isInHeader = true; + + // in C# 'catch' and 'delegate' can be a paren or non-paren header + if (isNonParenHeader && !isSharpStyleWithParen(currentHeader)) + { + isImmediatelyPostHeader = true; + isInHeader = false; + } + } + + if (shouldBreakBlocks + && isOkToBreakBlock(bracketTypeStack->back())) + { + if (previousHeader == NULL + && !foundClosingHeader + && !isCharImmediatelyPostOpenBlock + && !isImmediatelyPostCommentOnly) + { + isPrependPostBlockEmptyLineRequested = true; + } + + if (currentHeader == &AS_ELSE + || currentHeader == &AS_CATCH + || currentHeader == &AS_FINALLY + || foundClosingHeader) + { + isPrependPostBlockEmptyLineRequested = false; + } + + if (shouldBreakClosingHeaderBlocks + && isCharImmediatelyPostCloseBlock + && !isImmediatelyPostCommentOnly + && currentHeader != &AS_WHILE) // closing do-while block + { + isPrependPostBlockEmptyLineRequested = true; + } + + } + + continue; + } + else if ((newHeader = findHeader(preDefinitionHeaders)) != NULL + && parenStack->back() == 0) + { + if (newHeader == &AS_NAMESPACE) + foundNamespaceHeader = true; + if (newHeader == &AS_CLASS) + foundClassHeader = true; + if (newHeader == &AS_STRUCT) + foundStructHeader = true; + if (newHeader == &AS_INTERFACE) + foundInterfaceHeader = true; + foundPreDefinitionHeader = true; + appendSequence(*newHeader); + goForward(newHeader->length() - 1); + + continue; + } + else if ((newHeader = findHeader(preCommandHeaders)) != NULL) + { + if (!(*newHeader == AS_CONST && previousCommandChar != ')')) // 'const' member functions is a command bracket + foundPreCommandHeader = true; + appendSequence(*newHeader); + goForward(newHeader->length() - 1); + + continue; + } + else if ((newHeader = findHeader(castOperators)) != NULL) + { + foundCastOperator = true; + appendSequence(*newHeader); + goForward(newHeader->length() - 1); + continue; + } + } // (isPotentialHeader && !isInTemplate) + + if (isInLineBreak) // OK to break line here + { + breakLine(); + if (isInVirginLine) // adjust for the first line + { + lineCommentNoBeautify = lineCommentNoIndent; + lineCommentNoIndent = false; + } + } + + if (previousNonWSChar == '}' || currentChar == ';') + { + if (currentChar == ';') + { + if ((shouldBreakOneLineStatements + || isBracketType(bracketTypeStack->back(), SINGLE_LINE_TYPE)) + && isOkToBreakBlock(bracketTypeStack->back())) + { + passedSemicolon = true; + } + + // append post block empty line for unbracketed header + if (shouldBreakBlocks && currentHeader != NULL && parenStack->back() == 0) + { + isAppendPostBlockEmptyLineRequested = true; + } + } + + // end of block if a closing bracket was found + // or an opening bracket was not found (';' closes) + if (currentChar != ';' + || (needHeaderOpeningBracket && parenStack->back() == 0)) + currentHeader = NULL; + + foundQuestionMark = false; + foundNamespaceHeader = false; + foundClassHeader = false; + foundStructHeader = false; + foundInterfaceHeader = false; + foundPreDefinitionHeader = false; + foundPreCommandHeader = false; + foundCastOperator = false; + isInPotentialCalculation = false; + isSharpAccessor = false; + isSharpDelegate = false; + isInExtern = false; + nonInStatementBracket = 0; + } + + if (currentChar == ':' && shouldBreakOneLineStatements) + { + if (isInCase + && previousChar != ':' // not part of '::' + && peekNextChar() != ':') // not part of '::' + { + isInCase = false; + passedColon = true; + } + else if (isCStyle() // for C/C++ only + && !foundQuestionMark // not in a ... ? ... : ... sequence + && !foundPreDefinitionHeader // not in a definition block (e.g. class foo : public bar + && previousCommandChar != ')' // not immediately after closing paren of a method header, e.g. ASFormatter::ASFormatter(...) : ASBeautifier(...) + && previousChar != ':' // not part of '::' + && peekNextChar() != ':' // not part of '::' + && !isdigit(peekNextChar()) // not a bit field + && !isInAsm // not in extended assembler + && !isInAsmOneLine // not in extended assembler + && !isInAsmBlock) // not in extended assembler + { + passedColon = true; + } + } + + if (currentChar == '?') + foundQuestionMark = true; + + if (isPotentialHeader && !isInTemplate) + { + if (findKeyword(currentLine, charNum, AS_CASE) + || findKeyword(currentLine, charNum, AS_DEFAULT)) + isInCase = true; + + if (findKeyword(currentLine, charNum, AS_NEW)) + isInPotentialCalculation = false; + + if (findKeyword(currentLine, charNum, AS_RETURN)) + { + isInPotentialCalculation = true; // return is the same as an = sign + isImmediatelyPostReturn = true; + } + + if (findKeyword(currentLine, charNum, AS_OPERATOR)) + isImmediatelyPostOperator = true; + + if (isCStyle() && findKeyword(currentLine, charNum, AS_EXTERN)) + isInExtern = true; + + if (isCStyle() && isExecSQL(currentLine, charNum)) + isInExecSQL = true; + + if (isCStyle()) + { + if (findKeyword(currentLine, charNum, AS_ASM) + || findKeyword(currentLine, charNum, AS__ASM__)) + { + isInAsm = true; + } + else if (findKeyword(currentLine, charNum, AS_MS_ASM) // microsoft specific + || findKeyword(currentLine, charNum, AS_MS__ASM)) + { + int index = 4; + if (peekNextChar() == '_') // check for __asm + index = 5; + + char peekedChar = ASBase::peekNextChar(currentLine, charNum + index); + if (peekedChar == '{' || peekedChar == ' ') + isInAsmBlock = true; + else + isInAsmOneLine = true; + } + } + + if (isJavaStyle() + && (findKeyword(currentLine, charNum, AS_STATIC) + && isNextCharOpeningBracket(charNum + 6))) + isJavaStaticConstructor = true; + + if (isSharpStyle() + && (findKeyword(currentLine, charNum, AS_DELEGATE) + || findKeyword(currentLine, charNum, AS_UNCHECKED))) + isSharpDelegate = true; + + // append the entire name + string name = getCurrentWord(currentLine, charNum); + appendSequence(name); + goForward(name.length() - 1); + + continue; + + } // (isPotentialHeader && !isInTemplate) + + // determine if this is a potential calculation + + bool isPotentialOperator = isCharPotentialOperator(currentChar); + newHeader = NULL; + + if (isPotentialOperator) + { + newHeader = findOperator(operators); + + if (newHeader != NULL) + { + // correct mistake of two >> closing a template + if (isInTemplate && (newHeader == &AS_GR_GR || newHeader == &AS_GR_GR_GR)) + newHeader = &AS_GR; + + if (!isInPotentialCalculation) + { + // must determine if newHeader is an assignment operator + // do NOT use findOperator!!! + if (find(assignmentOperators->begin(), assignmentOperators->end(), newHeader) + != assignmentOperators->end()) + { + char peekedChar = peekNextChar(); + isInPotentialCalculation = (!(newHeader == &AS_EQUAL && peekedChar == '*') + && !(newHeader == &AS_EQUAL && peekedChar == '&')); + } + } + } + } + + // process pointers and references + // check new header to elimnate things like '&&' sequence + if (isCStyle() + && (newHeader == &AS_MULT || newHeader == &AS_BIT_AND) + && isPointerOrReference() + && !isDereferenceOrAddressOf()) + { + formatPointerOrReference(); + continue; + } + + if (shouldPadOperators && newHeader != NULL) + { + padOperators(newHeader); + continue; + } + + // pad commas and semi-colons + if (currentChar == ';' + || (currentChar == ',' && shouldPadOperators)) + { + char nextChar = ' '; + if (charNum + 1 < (int) currentLine.length()) + nextChar = currentLine[charNum+1]; + if (!isWhiteSpace(nextChar) + && nextChar != '}' + && nextChar != ')' + && nextChar != ']' + && nextChar != '>' + && nextChar != ';' + && !isBeforeAnyComment() + /* && !(isBracketType(bracketTypeStack->back(), ARRAY_TYPE)) */ + ) + { + appendCurrentChar(); + appendSpaceAfter(); + continue; + } + } + + if ((shouldPadParensOutside || shouldPadParensInside || shouldUnPadParens) + && (currentChar == '(' || currentChar == ')')) + { + padParens(); + continue; + } + + appendCurrentChar(); + } // end of while loop * end of while loop * end of while loop * end of while loop + + // return a beautified (i.e. correctly indented) line. + + string beautifiedLine; + size_t readyFormattedLineLength = trim(readyFormattedLine).length(); + + if (prependEmptyLine // prepend a blank line before this formatted line + && readyFormattedLineLength > 0 + && previousReadyFormattedLineLength > 0) + { + isLineReady = true; // signal a waiting readyFormattedLine + beautifiedLine = beautify(""); + previousReadyFormattedLineLength = 0; + } + else // format the current formatted line + { + isLineReady = false; + horstmannIndentInStatement = horstmannIndentChars; + beautifiedLine = beautify(readyFormattedLine); + previousReadyFormattedLineLength = readyFormattedLineLength; + // the enhancer is not called for new empty lines + // or no-indent line comments + if (!lineCommentNoBeautify) + enhancer->enhance(beautifiedLine, isInBeautifySQL); + horstmannIndentChars = 0; + lineCommentNoBeautify = lineCommentNoIndent; + lineCommentNoIndent = false; + isInBeautifySQL = isInExecSQL; + } + + prependEmptyLine = false; + return beautifiedLine; +} + + +/** + * check if there are any indented lines ready to be read by nextLine() + * + * @return are there any indented lines ready? + */ +bool ASFormatter::hasMoreLines() const +{ + return !endOfCodeReached; +} + +/** + * comparison function for BracketType enum + */ +bool ASFormatter::isBracketType(BracketType a, BracketType b) const +{ + return ((a & b) == b); +} + +/** + * set the formatting style. + * + * @param mode the formatting style. + */ +void ASFormatter::setFormattingStyle(FormatStyle style) +{ + formattingStyle = style; +} + +/** + * set the add brackets mode. + * options: + * true brackets added to headers for single line statements. + * false brackets NOT added to headers for single line statements. + * + * @param mode the bracket formatting mode. + */ +void ASFormatter::setAddBracketsMode(bool state) +{ + shouldAddBrackets = state; +} + +/** + * set the add one line brackets mode. + * options: + * true one line brackets added to headers for single line statements. + * false one line brackets NOT added to headers for single line statements. + * + * @param mode the bracket formatting mode. + */ +void ASFormatter::setAddOneLineBracketsMode(bool state) +{ + shouldAddBrackets = state; + shouldAddOneLineBrackets = state; +} + +/** + * set the bracket formatting mode. + * options: + * + * @param mode the bracket formatting mode. + */ +void ASFormatter::setBracketFormatMode(BracketMode mode) +{ + bracketFormatMode = mode; +} + +/** + * set closing header bracket breaking mode + * options: + * true brackets just before closing headers (e.g. 'else', 'catch') + * will be broken, even if standard brackets are attached. + * false closing header brackets will be treated as standard brackets. + * + * @param state the closing header bracket breaking mode. + */ +void ASFormatter::setBreakClosingHeaderBracketsMode(bool state) +{ + shouldBreakClosingHeaderBrackets = state; +} + +/** + * set 'else if()' breaking mode + * options: + * true 'else' headers will be broken from their succeeding 'if' headers. + * false 'else' headers will be attached to their succeeding 'if' headers. + * + * @param state the 'else if()' breaking mode. + */ +void ASFormatter::setBreakElseIfsMode(bool state) +{ + shouldBreakElseIfs = state; +} + +/** + * set operator padding mode. + * options: + * true statement operators will be padded with spaces around them. + * false statement operators will not be padded. + * + * @param state the padding mode. + */ +void ASFormatter::setOperatorPaddingMode(bool state) +{ + shouldPadOperators = state; +} + +/** + * set parenthesis outside padding mode. + * options: + * true statement parenthesiss will be padded with spaces around them. + * false statement parenthesiss will not be padded. + * + * @param state the padding mode. + */ +void ASFormatter::setParensOutsidePaddingMode(bool state) +{ + shouldPadParensOutside = state; +} + +/** + * set parenthesis inside padding mode. + * options: + * true statement parenthesis will be padded with spaces around them. + * false statement parenthesis will not be padded. + * + * @param state the padding mode. + */ +void ASFormatter::setParensInsidePaddingMode(bool state) +{ + shouldPadParensInside = state; +} + +/** + * set header padding mode. + * options: + * true headers will be padded with spaces around them. + * false headers will not be padded. + * + * @param state the padding mode. + */ +void ASFormatter::setParensHeaderPaddingMode(bool state) +{ + shouldPadHeader = state; +} + +/** + * set parenthesis unpadding mode. + * options: + * true statement parenthesis will be unpadded with spaces removed around them. + * false statement parenthesis will not be unpadded. + * + * @param state the padding mode. + */ +void ASFormatter::setParensUnPaddingMode(bool state) +{ + shouldUnPadParens = state; +} + +/** + * set option to break/not break one-line blocks + * + * @param state true = break, false = don't break. + */ +void ASFormatter::setBreakOneLineBlocksMode(bool state) +{ + shouldBreakOneLineBlocks = state; +} + +/** + * set option to break/not break lines consisting of multiple statements. + * + * @param state true = break, false = don't break. + */ +void ASFormatter::setSingleStatementsMode(bool state) +{ + shouldBreakOneLineStatements = state; +} + +/** + * set option to convert tabs to spaces. + * + * @param state true = convert, false = don't convert. + */ +void ASFormatter::setTabSpaceConversionMode(bool state) +{ + shouldConvertTabs = state; +} + +/** + * set option to indent comments in column 1. + * + * @param state true = indent, false = don't indent. + */ +void ASFormatter::setIndentCol1CommentsMode(bool state) +{ + shouldIndentCol1Comments = state; +} + +/** + * set option to force all line ends to a particular style. + * + * @param fmt format enum value + */ +void ASFormatter::setLineEndFormat(LineEndFormat fmt) +{ + lineEnd = fmt; +} + +/** + * set option to break unrelated blocks of code with empty lines. + * + * @param state true = convert, false = don't convert. + */ +void ASFormatter::setBreakBlocksMode(bool state) +{ + shouldBreakBlocks = state; +} + +/** + * set option to break closing header blocks of code (such as 'else', 'catch', ...) with empty lines. + * + * @param state true = convert, false = don't convert. + */ +void ASFormatter::setBreakClosingHeaderBlocksMode(bool state) +{ + shouldBreakClosingHeaderBlocks = state; +} + +/** + * set option to delete empty lines. + * + * @param state true = delete, false = don't delete. + */ +void ASFormatter::setDeleteEmptyLinesMode(bool state) +{ + shouldDeleteEmptyLines = state; +} + +/** + * set the pointer alignment. + * options: + * + * @param alignment the pointer alignment. + */ +void ASFormatter::setPointerAlignment(PointerAlign alignment) +{ + pointerAlignment = alignment; +} + +/** + * jump over several characters. + * + * @param i the number of characters to jump over. + */ +void ASFormatter::goForward(int i) +{ + while (--i >= 0) + getNextChar(); +} + +/** + * peek at the next unread character. + * + * @return the next unread character. + */ +char ASFormatter::peekNextChar() const +{ + char ch = ' '; + size_t peekNum = currentLine.find_first_not_of(" \t", charNum + 1); + + if (peekNum == string::npos) + return ch; + + ch = currentLine[peekNum]; + + return ch; +} + +/** + * check if current placement is before a comment + * + * @return is before a comment. + */ +bool ASFormatter::isBeforeComment() const +{ + bool foundComment = false; + size_t peekNum = currentLine.find_first_not_of(" \t", charNum + 1); + + if (peekNum == string::npos) + return foundComment; + + foundComment = (currentLine.compare(peekNum, 2, "/*") == 0); + + return foundComment; +} + +/** + * check if current placement is before a comment or line-comment + * + * @return is before a comment or line-comment. + */ +bool ASFormatter::isBeforeAnyComment() const +{ + bool foundComment = false; + size_t peekNum = currentLine.find_first_not_of(" \t", charNum + 1); + + if (peekNum == string::npos) + return foundComment; + + foundComment = (currentLine.compare(peekNum, 2, "/*") == 0 + || currentLine.compare(peekNum, 2, "//") == 0); + + return foundComment; +} + +/** + * check if current placement is before a comment or line-comment + * if a block comment it must be at the end of the line + * + * @return is before a comment or line-comment. + */ +bool ASFormatter::isBeforeAnyLineEndComment(int startPos) const +{ + bool foundLineEndComment = false; + size_t peekNum = currentLine.find_first_not_of(" \t", startPos + 1); + + if (peekNum != string::npos) + { + if (currentLine.compare(peekNum, 2, "//") == 0) + foundLineEndComment = true; + else if (currentLine.compare(peekNum, 2, "/*") == 0) + { + // comment must be closed on this line with nothing after it + size_t endNum = currentLine.find("*/", peekNum + 2); + if (endNum != string::npos) + { + size_t nextChar = currentLine.find_first_not_of(" \t", endNum + 2); + if (nextChar == string::npos) + foundLineEndComment = true; + } + } + } + return foundLineEndComment; +} + +/** + * check if current placement is before a comment followed by a line-comment + * + * @return is before a multiple line-end comment. + */ +bool ASFormatter::isBeforeMultipleLineEndComments(int startPos) const +{ + bool foundMultipleLineEndComment = false; + size_t peekNum = currentLine.find_first_not_of(" \t", startPos + 1); + + if (peekNum != string::npos) + { + if (currentLine.compare(peekNum, 2, "/*") == 0) + { + // comment must be closed on this line with nothing after it + size_t endNum = currentLine.find("*/", peekNum + 2); + if (endNum != string::npos) + { + size_t nextChar = currentLine.find_first_not_of(" \t", endNum + 2); + if (nextChar != string::npos + && currentLine.compare(nextChar, 2, "//") == 0) + foundMultipleLineEndComment = true; + } + } + } + return foundMultipleLineEndComment; +} + + +/** + * get the next character, increasing the current placement in the process. + * the new character is inserted into the variable currentChar. + * + * @return whether succeded to recieve the new character. + */ +bool ASFormatter::getNextChar() +{ + isInLineBreak = false; + previousChar = currentChar; + + if (!isWhiteSpace(currentChar)) + { + previousNonWSChar = currentChar; + if (!isInComment && !isInLineComment && !isInQuote + && !isImmediatelyPostComment + && !isImmediatelyPostLineComment + && !isInPreprocessor + && !isSequenceReached("/*") + && !isSequenceReached("//")) + previousCommandChar = currentChar; + } + + if (charNum + 1 < (int) currentLine.length() + && (!isWhiteSpace(peekNextChar()) || isInComment || isInLineComment)) + { + currentChar = currentLine[++charNum]; + + if (shouldConvertTabs && currentChar == '\t') + convertTabToSpaces(); + + return true; + } + + // end of line has been reached + return getNextLine(); +} + +/** + * get the next line of input, increasing the current placement in the process. + * + * @param sequence the sequence to append. + * @return whether succeded in reading the next line. + */ +bool ASFormatter::getNextLine(bool emptyLineWasDeleted /*false*/) +{ + if (sourceIterator->hasMoreLines()) + { + if (appendOpeningBracket) + currentLine = "{"; // append bracket that was removed from the previous line + else + currentLine = sourceIterator->nextLine(emptyLineWasDeleted); + // reset variables for new line + inLineNumber++; + isInCase = false; + isInAsmOneLine = false; + isInQuoteContinuation = isInVerbatimQuote | haveLineContinuationChar; + haveLineContinuationChar= false; + isImmediatelyPostEmptyLine = lineIsEmpty; + previousChar = ' '; + + if (currentLine.length() == 0) + { + currentLine = string(" "); // a null is inserted if this is not done + } + + // unless reading in the first line of the file, break a new line. + if (!isVirgin) + isInLineBreak = true; + else + isVirgin = false; + + // check if is in preprocessor before line trimming + // a blank line after a \ will remove the flag + isImmediatelyPostPreprocessor = isInPreprocessor; + if (previousNonWSChar != '\\' + || isEmptyLine(currentLine)) + isInPreprocessor = false; + + if (passedSemicolon) + isInExecSQL = false; + initNewLine(); + currentChar = currentLine[charNum]; + if (isInHorstmannRunIn && previousNonWSChar == '{') + isInLineBreak = false; + isInHorstmannRunIn = false; + + if (shouldConvertTabs && currentChar == '\t') + convertTabToSpaces(); + + // check for an empty line inside a command bracket. + // if yes then read the next line (calls getNextLine recursively). + // must be after initNewLine. + if (shouldDeleteEmptyLines + && lineIsEmpty + && isBracketType((*bracketTypeStack)[bracketTypeStack->size()-1], COMMAND_TYPE)) + { + // but do NOT delete an empty line between comments if blocks are being broken + if (!(shouldBreakBlocks || shouldBreakClosingHeaderBlocks) + || !isImmediatelyPostCommentOnly + || !commentAndHeaderFollows()) + { + isInPreprocessor = isImmediatelyPostPreprocessor; // restore + lineIsEmpty = false; + return getNextLine(true); + } + } + + return true; + } + else + { + endOfCodeReached = true; + return false; + } +} + +/** + * jump over the leading white space in the current line, + * IF the line does not begin a comment or is in a preprocessor definition. + */ +void ASFormatter::initNewLine() +{ + size_t len = currentLine.length(); + size_t indent = getIndentLength(); + charNum = 0; + + if (isInPreprocessor || isInQuoteContinuation) + return; + + // SQL continuation lines must be adjusted so the leading spaces + // is equivalent to the opening EXEC SQL + if (isInExecSQL) + { + // replace leading tabs with spaces + // so that continuation indent will be spaces + size_t tabCount = 0; + size_t i; + for (i = 0; i < currentLine.length(); i++) + { + if (!isWhiteSpace(currentLine[i])) // stop at first text + break; + if (currentLine[i] == '\t') + { + size_t numSpaces = indent - ((tabCount + i) % indent); + currentLine.replace(i, 1, numSpaces, ' '); + tabCount++; + i += indent - 1; + } + } + // correct the format if EXEC SQL is not a hanging indent + if (i < leadingSpaces) + currentLine.insert((size_t)0, leadingSpaces - i, ' '); + trimContinuationLine(); + return; + } + + // comment continuation lines must be adjusted so the leading spaces + // is equivalent to the opening comment + if (isInComment) + { + if (noTrimCommentContinuation) + leadingSpaces = tabIncrementIn = 0; + trimContinuationLine(); + return; + } + + // compute leading spaces + isImmediatelyPostCommentOnly = lineIsLineCommentOnly || lineEndsInCommentOnly; + lineIsLineCommentOnly = false; + lineEndsInCommentOnly = false; + doesLineStartComment = false; + currentLineBeginsWithBracket = false; + lineIsEmpty = false; + currentLineFirstBracketNum = string::npos; + tabIncrementIn = 0; + + for (charNum = 0; isWhiteSpace(currentLine[charNum]) && charNum + 1 < (int) len; charNum++) + { + if (currentLine[charNum] == '\t') + tabIncrementIn += indent - 1 - ((tabIncrementIn + charNum) % indent); + } + leadingSpaces = charNum + tabIncrementIn; + + if (isSequenceReached("/*")) + { + doesLineStartComment = true; + } + else if (isSequenceReached("//")) + { + lineIsLineCommentOnly = true; + } + else if (isSequenceReached("{")) + { + currentLineBeginsWithBracket = true; + currentLineFirstBracketNum = charNum; + size_t firstText = currentLine.find_first_not_of(" \t", charNum + 1); + if (firstText != string::npos) + { + if (currentLine.compare(firstText, 2, "//") == 0) + lineIsLineCommentOnly = true; + else if (currentLine.compare(firstText, 2, "/*") == 0 + || isExecSQL(currentLine, firstText)) + { + // get the extra adjustment + size_t j; + for (j = charNum + 1; isWhiteSpace(currentLine[j]) && j < firstText; j++) + { + if (currentLine[j] == '\t') + tabIncrementIn += indent - 1 - ((tabIncrementIn + j) % indent); + } + leadingSpaces = j + tabIncrementIn; + if (currentLine.compare(firstText, 2, "/*") == 0) + doesLineStartComment = true; + } + } + } + else if (isWhiteSpace(currentLine[charNum]) && !(charNum + 1 < (int) currentLine.length())) + { + lineIsEmpty = true; + } +} + +/** + * append a string sequence to the current formatted line. + * Unless disabled (via canBreakLine == false), first check if a + * line-break has been registered, and if so break the + * formatted line, and only then append the sequence into + * the next formatted line. + * + * @param sequence the sequence to append. + * @param canBreakLine if true, a registered line-break + */ +void ASFormatter::appendSequence(const string &sequence, bool canBreakLine) +{ + if (canBreakLine && isInLineBreak) + breakLine(); + formattedLine.append(sequence); +} + +/** + * append a space to the current formattedline, UNLESS the + * last character is already a white-space character. + */ +void ASFormatter::appendSpacePad() +{ + int len = formattedLine.length(); + if (len > 0 && !isWhiteSpace(formattedLine[len-1])) + { + formattedLine.append(1, ' '); + spacePadNum++; + } +} + +/** + * append a space to the current formattedline, UNLESS the + * next character is already a white-space character. + */ +void ASFormatter::appendSpaceAfter() +{ + int len = currentLine.length(); + if (charNum + 1 < len && !isWhiteSpace(currentLine[charNum+1])) + { + formattedLine.append(1, ' '); + spacePadNum++; + } +} + +/** + * register a line break for the formatted line. + */ +void ASFormatter::breakLine() +{ + isLineReady = true; + isInLineBreak = false; + spacePadNum = nextLineSpacePadNum; + nextLineSpacePadNum = 0; + formattedLineCommentNum = string::npos; + + // queue an empty line prepend request if one exists + prependEmptyLine = isPrependPostBlockEmptyLineRequested; + + readyFormattedLine = formattedLine; + if (isAppendPostBlockEmptyLineRequested) + { + isAppendPostBlockEmptyLineRequested = false; + isPrependPostBlockEmptyLineRequested = true; + } + else + { + isPrependPostBlockEmptyLineRequested = false; + } + + formattedLine = ""; +} + +/** + * check if the currently reached open-bracket (i.e. '{') + * opens a: + * - a definition type block (such as a class or namespace), + * - a command block (such as a method block) + * - a static array + * this method takes for granted that the current character + * is an opening bracket. + * + * @return the type of the opened block. + */ +BracketType ASFormatter::getBracketType() +{ + assert(currentChar == '{'); + + BracketType returnVal; + + if ((previousNonWSChar == '=' + || isBracketType(bracketTypeStack->back(), ARRAY_TYPE)) + && previousCommandChar != ')') + returnVal = ARRAY_TYPE; + else if (foundPreDefinitionHeader) + { + returnVal = DEFINITION_TYPE; + if (foundNamespaceHeader) + returnVal = (BracketType)(returnVal | NAMESPACE_TYPE); + else if (foundClassHeader) + returnVal = (BracketType)(returnVal | CLASS_TYPE); + else if (foundStructHeader) + returnVal = (BracketType)(returnVal | STRUCT_TYPE); + else if (foundInterfaceHeader) + returnVal = (BracketType)(returnVal | INTERFACE_TYPE); + } + else + { + bool isCommandType = (foundPreCommandHeader + || (currentHeader != NULL && isNonParenHeader) + || (previousCommandChar == ')') + || (previousCommandChar == ':' && !foundQuestionMark) + || (previousCommandChar == ';') + || ((previousCommandChar == '{' || previousCommandChar == '}') + && isPreviousBracketBlockRelated) + || isJavaStaticConstructor + || isSharpDelegate); + + // C# methods containing 'get', 'set', 'add', and 'remove' do NOT end with parens + if (!isCommandType && isSharpStyle() && isNextWordSharpNonParenHeader(charNum + 1)) + { + isCommandType = true; + isSharpAccessor = true; + } + + if (!isCommandType && isInExtern) + returnVal = EXTERN_TYPE; + else + returnVal = (isCommandType ? COMMAND_TYPE : ARRAY_TYPE); + } + + if (isOneLineBlockReached(currentLine, charNum)) + returnVal = (BracketType)(returnVal | SINGLE_LINE_TYPE); + + if (isBracketType(returnVal, ARRAY_TYPE) && isNonInStatementArrayBracket()) + { + returnVal = (BracketType)(returnVal | ARRAY_NIS_TYPE); + isNonInStatementArray = true; + nonInStatementBracket = formattedLine.length() - 1; + } + + return returnVal; +} + +/** + * check if a line is empty + * + * @return whether line is empty + */ +bool ASFormatter::isEmptyLine(const string &line) const +{ + return line.find_first_not_of(" \t") == string::npos; +} + +/** + * Check if the currently reached '*' or '&' character is + * a pointer-or-reference symbol, or another operator. + * A pointer dereference (*) or an "address of" character (&) + * counts as a pointer or reference because it is not an + * arithmetic operator. + * + * @return whether current character is a reference-or-pointer + */ +bool ASFormatter::isPointerOrReference() const +{ + assert(currentChar == '*' || currentChar == '&'); + + if (!isCStyle()) + return false; + + if (currentChar == '&' && previousChar == '&') + return false; + + if (previousNonWSChar == '=' || isCharImmediatelyPostReturn) + return true; + + if (currentHeader == &AS_CATCH) + return true; + + // get the last legal word (may be a number) + string lastWord = getPreviousWord(currentLine, charNum); + if (lastWord.empty()) + lastWord[0] = ' '; + char nextChar = peekNextChar(); + + // check for preceding or following numeric values + if (isdigit(lastWord[0]) + || isdigit(nextChar)) + return false; + + // checks on other chars + if (isLegalNameChar(lastWord[0]) + && isLegalNameChar(nextChar) + && parenStack->back() > 0) + { + // if followed by an assignment it is a pointer or reference + size_t nextNum = currentLine.find_first_of("=;)", charNum + 1); + if (nextNum != string::npos && currentLine[nextNum] == '=') + return true; + + // if a function definition it is a pointer or reference + // otherwise it is an arithmetic operator + if (!isBracketType(bracketTypeStack->back(), COMMAND_TYPE)) + return true; + else + return false; + } + + if (nextChar == '-' + || nextChar == '+') + { + size_t nextNum = currentLine.find_first_not_of(" \t", charNum + 1); + if (nextNum != string::npos) + { + if (currentLine.compare(nextNum, 2, "++") != 0 + && currentLine.compare(nextNum, 2, "--") != 0) + return false; + } + } + + bool isPR = (!isInPotentialCalculation + || isBracketType(bracketTypeStack->back(), DEFINITION_TYPE) + || (!isLegalNameChar(previousNonWSChar) + && !(previousNonWSChar == ')' && nextChar == '(') + && !(previousNonWSChar == ')' && currentChar == '*') + && previousNonWSChar != ']') + ); + + if (!isPR) + { + isPR |= (!isWhiteSpace(nextChar) + && nextChar != '-' + && nextChar != '(' + && nextChar != '[' + && !isLegalNameChar(nextChar)); + } + + return isPR; +} + +/** + * Check if the currently reached '*' or '&' character is + * a dereferenced pointer or "address of" symbol. + * NOTE: this MUST be a pointer or reference as determined by + * the function isPointerOrReference(). + * + * @return whether current character is a dereference or address of + */ +bool ASFormatter::isDereferenceOrAddressOf() const +{ + assert(isPointerOrReference()); + + if (previousNonWSChar == '=' + || previousNonWSChar == ',' + || previousNonWSChar == '.' + || previousNonWSChar == '>' + || previousNonWSChar == '<' + || isCharImmediatelyPostReturn) + return true; + + // check for ** + if (currentChar == '*' + && (int) currentLine.length() > charNum + && currentLine[charNum+1] == '*') + { + if (previousNonWSChar == '(') + return true; + if ((int) currentLine.length() < charNum + 2) + return true; + return false; + } + + // check first char on the line + if (charNum == (int) currentLine.find_first_not_of(" \t")) + return true; + + size_t nextChar = currentLine.find_first_not_of(" \t", charNum+1); + if (nextChar != string::npos + && (currentLine[nextChar] == ')' + || currentLine[nextChar] == '>' + || currentLine[nextChar] == ',')) + return false; + + string lastWord = getPreviousWord(currentLine, charNum); + if (lastWord == "else" || lastWord == "delete") + return true; + + bool isDA = (!(isLegalNameChar(previousNonWSChar) || previousNonWSChar == '>') + || !isLegalNameChar(peekNextChar()) + || (ispunct(previousNonWSChar) && previousNonWSChar != '.') + || isCharImmediatelyPostReturn); + + return isDA; +} + +/** + * Check if the currently reached '*' or '&' character is + * centered with one space on each side. + * Only spaces are checked, not tabs. + * If true then a space wil be deleted on the output. + * + * @return whether current character is centered. + */ +bool ASFormatter::isPointerOrReferenceCentered() const +{ + assert(currentLine[charNum] == '*' || currentLine[charNum] == '&'); + + int prNum = charNum; + int lineLength = (int) currentLine.length(); + // check space before + if (prNum < 1 + || currentLine[prNum-1] != ' ') + return false; + + // check no space before that + if (prNum < 2 + || currentLine[prNum-2] == ' ') + return false; + + // check for ** + if (prNum + 1 < lineLength + && currentLine[prNum+1] == '*') + prNum++; + + // check space after + if (prNum + 1 < lineLength + && currentLine[prNum+1] != ' ') + return false; + + // check no space after that + if (prNum + 2 < lineLength + && currentLine[prNum+2] == ' ') + return false; + + return true; +} + +/** + * check if the currently reached '+' or '-' character is a unary operator + * this method takes for granted that the current character + * is a '+' or '-'. + * + * @return whether the current '+' or '-' is a unary operator. + */ +bool ASFormatter::isUnaryOperator() const +{ + assert(currentChar == '+' || currentChar == '-'); + + return ((isCharImmediatelyPostReturn || !isLegalNameChar(previousCommandChar)) + && previousCommandChar != '.' + && previousCommandChar != '\"' + && previousCommandChar != '\'' + && previousCommandChar != ')' + && previousCommandChar != ']'); +} + + +/** + * check if the currently reached '+' or '-' character is + * part of an exponent, i.e. 0.2E-5. + * + * this method takes for granted that the current character + * is a '+' or '-'. + * + * @return whether the current '+' or '-' is in an exponent. + */ +bool ASFormatter::isInExponent() const +{ + assert(currentChar == '+' || currentChar == '-'); + + int formattedLineLength = formattedLine.length(); + if (formattedLineLength >= 2) + { + char prevPrevFormattedChar = formattedLine[formattedLineLength - 2]; + char prevFormattedChar = formattedLine[formattedLineLength - 1]; + + return ((prevFormattedChar == 'e' || prevFormattedChar == 'E') + && (prevPrevFormattedChar == '.' || isdigit(prevPrevFormattedChar))); + } + else + return false; +} + +/** + * check if an array bracket should NOT have an in-statement indent + * + * @return the array is non in-statement + */ +bool ASFormatter::isNonInStatementArrayBracket() const +{ + bool returnVal = false; + char nextChar = peekNextChar(); + // if this opening bracket begins the line there will be no inStatement indent + if (currentLineBeginsWithBracket + && charNum == (int) currentLineFirstBracketNum + && nextChar != '}') + returnVal = true; + // if an opening bracket ends the line there will be no inStatement indent + if (isWhiteSpace(nextChar) + || isBeforeAnyLineEndComment(charNum) + || nextChar == '{') + returnVal = true; + + // Java "new Type [] {...}" IS an inStatement indent + if (isJavaStyle() && previousNonWSChar == ']') + returnVal = false; + + // trace + //if (isNonInStatementArray) + // cout << traceLineNumber << " " << 'x' << endl; + //else + // cout << traceLineNumber << " " << ' ' << endl + + return returnVal; +} + +/** + * check if a one-line bracket has been reached, + * i.e. if the currently reached '{' character is closed + * with a complimentry '}' elsewhere on the current line, + *. + * @return has a one-line bracket been reached? + */ +bool ASFormatter::isOneLineBlockReached(string& line, int startChar) const +{ + assert(line[startChar] == '{'); + + bool isInComment = false; + bool isInQuote = false; + int bracketCount = 1; + int lineLength = line.length(); + char quoteChar = ' '; + + for (int i = startChar + 1; i < lineLength; ++i) + { + char ch = line[i]; + + if (isInComment) + { + if (line.compare(i, 2, "*/") == 0) + { + isInComment = false; + ++i; + } + continue; + } + + if (ch == '\\') + { + ++i; + continue; + } + + if (isInQuote) + { + if (ch == quoteChar) + isInQuote = false; + continue; + } + + if (ch == '"' || ch == '\'') + { + isInQuote = true; + quoteChar = ch; + continue; + } + + if (line.compare(i, 2, "//") == 0) + break; + + if (line.compare(i, 2, "/*") == 0) + { + isInComment = true; + ++i; + continue; + } + + if (ch == '{') + ++bracketCount; + else if (ch == '}') + --bracketCount; + + if (bracketCount == 0) + return true; + } + + return false; +} + +/** + * peek at the next word to determine if it is a C# non-paren header. + * will look ahead in the input file if necessary. + * + * @param char position on currentLine to start the search + * @return true if the next word is get or set. + */ +bool ASFormatter::isNextWordSharpNonParenHeader(int startChar) const +{ + // look ahead to find the next non-comment text + string nextText = peekNextText(currentLine.substr(startChar)); + if (nextText.length() == 0) + return false; + if (nextText[0] == '[') + return true; + if (!isCharPotentialHeader(nextText, 0)) + return false; + if (findKeyword(nextText, 0, AS_GET) || findKeyword(nextText, 0, AS_SET) + || findKeyword(nextText, 0, AS_ADD) || findKeyword(nextText, 0, AS_REMOVE)) + return true; + return false; +} + +/** + * peek at the next char to determine if it is an opening bracket. + * will look ahead in the input file if necessary. + * this determines a java static constructor. + * + * @param char position on currentLine to start the search + * @return true if the next word is an opening bracket. + */ +bool ASFormatter::isNextCharOpeningBracket(int startChar) const +{ + bool retVal = false; + string nextText = peekNextText(currentLine.substr(startChar)); + if (nextText.compare(0, 1, "{") == 0) + retVal = true; + return retVal; +} + +/** + * get the next non-whitespace substring on following lines, bypassing all comments. + * + * @param the first line to check + * @return the next non-whitespace substring. + */ +string ASFormatter::peekNextText(const string& firstLine, bool endOnEmptyLine /*false*/) const +{ + bool isFirstLine = true; + bool needReset = false; + string nextLine = firstLine; + size_t firstChar= string::npos; + + // find the first non-blank text, bypassing all comments. + bool isInComment = false; + while (sourceIterator->hasMoreLines()) + { + if (isFirstLine) + isFirstLine = false; + else + { + nextLine = sourceIterator->peekNextLine(); + needReset = true; + } + + firstChar = nextLine.find_first_not_of(" \t"); + if (firstChar == string::npos) + { + if (endOnEmptyLine && !isInComment) + break; + continue; + } + + if (nextLine.compare(firstChar, 2, "/*") == 0) + isInComment = true; + + if (isInComment) + { + firstChar = nextLine.find("*/", firstChar); + if (firstChar == string::npos) + continue; + firstChar += 2; + isInComment = false; + firstChar = nextLine.find_first_not_of(" \t", firstChar); + if (firstChar == string::npos) + continue; + } + + if (nextLine.compare(firstChar, 2, "//") == 0) + continue; + + // found the next text + break; + } + + if (needReset) + sourceIterator->peekReset(); + if (firstChar == string::npos) + nextLine = ""; + else + nextLine = nextLine.substr(firstChar); + return nextLine; +} + +/** + * adjust comment position because of adding or deleting spaces + * the spaces are added or deleted to formattedLine + * spacePadNum contains the adjustment + */ +void ASFormatter::adjustComments(void) +{ + assert(spacePadNum != 0); + assert(currentLine.compare(charNum, 2, "//") == 0 + || currentLine.compare(charNum, 2, "/*") == 0); + + + // block comment must be closed on this line with nothing after it + if (currentLine.compare(charNum, 2, "/*") == 0) + { + size_t endNum = currentLine.find("*/", charNum + 2); + if (endNum == string::npos) + return; + if (currentLine.find_first_not_of(" \t", endNum + 2) != string::npos) + return; + } + + size_t len = formattedLine.length(); + // don't adjust a tab + if (formattedLine[len-1] == '\t') + return; + // if spaces were removed, need to add spaces before the comment + if (spacePadNum < 0) + { + int adjust = -spacePadNum; // make the number positive + formattedLine.append(adjust, ' '); + } + // if spaces were added, need to delete extra spaces before the comment + // if cannot be done put the comment one space after the last text + else if (spacePadNum > 0) + { + int adjust = spacePadNum; + size_t lastText = formattedLine.find_last_not_of(' '); + if (lastText != string::npos + && lastText < len - adjust - 1) + formattedLine.resize(len - adjust); + else if (len > lastText + 2) + formattedLine.resize(lastText + 2); + else if (len < lastText + 2) + formattedLine.append(len - lastText, ' '); + } +} + +/** + * append the current bracket inside the end of line comments + * currentChar contains the bracket, it will be appended to formattedLine + * formattedLineCommentNum is the comment location on formattedLine + * returns true f appended, false if not + */ +void ASFormatter::appendCharInsideComments(void) +{ + if (formattedLineCommentNum == string::npos) // does the comment start on the previous line? + { + appendCurrentChar(); // don't attach + return; // false; + } + assert(formattedLine.compare(formattedLineCommentNum, 2, "//") == 0 + || formattedLine.compare(formattedLineCommentNum, 2, "/*") == 0); + + // find the previous non space char + size_t end = formattedLineCommentNum; + size_t beg = formattedLine.find_last_not_of(" \t", end-1); + if (beg == string::npos) // is the previous line comment only? + { + appendCurrentChar(); // don't attach + return; // false; + } + beg++; + + // insert the bracket + if (end - beg < 3) // is there room to insert? + formattedLine.insert(beg, 3-end+beg, ' '); + if (formattedLine[beg] == '\t') // don't pad with a tab + formattedLine.insert(beg, 1, ' '); + formattedLine[beg+1] = currentChar; + + if (isBeforeComment()) + breakLine(); + else if (isCharImmediatelyPostLineComment) + shouldBreakLineAtNextChar = true; + return; // true; +} + +/** + * add or remove space padding to operators + * currentChar contains the paren + * the operators and necessary padding will be appended to formattedLine + * the calling function should have a continue statement after calling this method + * + * @param *newOperator the operator to be padded + */ +void ASFormatter::padOperators(const string *newOperator) +{ + assert(newOperator != NULL); + + bool shouldPad = (newOperator != &AS_COLON_COLON + && newOperator != &AS_PAREN_PAREN + && newOperator != &AS_BLPAREN_BLPAREN + && newOperator != &AS_PLUS_PLUS + && newOperator != &AS_MINUS_MINUS + && newOperator != &AS_NOT + && newOperator != &AS_BIT_NOT + && newOperator != &AS_ARROW + && !(newOperator == &AS_MINUS && isInExponent()) + && !((newOperator == &AS_PLUS || newOperator == &AS_MINUS) // check for unary plus or minus + && (previousNonWSChar == '(' + || previousNonWSChar == '=' + || previousNonWSChar == ',')) + && !(newOperator == &AS_PLUS && isInExponent()) + && !isCharImmediatelyPostOperator + && !((newOperator == &AS_MULT || newOperator == &AS_BIT_AND) + && isPointerOrReference()) + && !(newOperator == &AS_MULT + && (previousNonWSChar == '.' + || previousNonWSChar == '>')) // check for -> + && !((isInTemplate || isCharImmediatelyPostTemplate) + && (newOperator == &AS_LS || newOperator == &AS_GR)) + && !(newOperator == &AS_GCC_MIN_ASSIGN + && ASBase::peekNextChar(currentLine, charNum+1) == '>') + && !(newOperator == &AS_GR && previousNonWSChar == '?') + && !isInCase + && !isInAsm + && !isInAsmOneLine + && !isInAsmBlock + ); + + // pad before operator + if (shouldPad + && !isInBlParen + && !(newOperator == &AS_COLON && !foundQuestionMark) + && !(newOperator == &AS_QUESTION && isSharpStyle() // check for C# nullable type (e.g. int?) + && currentLine.find(':', charNum+1) == string::npos) + ) + appendSpacePad(); + appendSequence(*newOperator); + goForward(newOperator->length() - 1); + + // since this block handles '()' and '[]', + // the parenStack must be updated here accordingly! + if (newOperator == &AS_PAREN_PAREN + || newOperator == &AS_BLPAREN_BLPAREN) + parenStack->back()--; + + currentChar = (*newOperator)[newOperator->length() - 1]; + // pad after operator + // but do not pad after a '-' that is a unary-minus. + if (shouldPad + && !isInBlParen + && !isBeforeAnyComment() + && !(newOperator == &AS_PLUS && isUnaryOperator()) + && !(newOperator == &AS_MINUS && isUnaryOperator()) + && !(currentLine.compare(charNum + 1, 1, ";") == 0) + && !(currentLine.compare(charNum + 1, 2, "::") == 0) + && !(newOperator == &AS_QUESTION && isSharpStyle() // check for C# nullable type (e.g. int?) + && currentLine[charNum+1] == '[') + ) + appendSpaceAfter(); + + previousOperator = newOperator; + return; +} + +/** + * format pointer or reference + * currentChar contains the pointer or reference + * the symbol and necessary padding will be appended to formattedLine + * the calling function should have a continue statement after calling this method + */ +void ASFormatter::formatPointerOrReference(void) +{ + assert(currentChar == '*' || currentChar == '&'); + assert(isCStyle()); + + // check for cast + char peekedChar = peekNextChar(); + if (currentChar == '*' + && (int) currentLine.length() > charNum + && currentLine[charNum+1] == '*') + { + size_t nextChar = currentLine.find_first_not_of(" \t", charNum+2); + if (nextChar == string::npos) + peekedChar = ' '; + else + peekedChar = currentLine[nextChar]; + } + if (peekedChar == ')' || peekedChar =='>' || peekedChar ==',') + { + formatPointerOrReferenceCast(); + return; + } + + // do this before bumping charNum + bool isOldPRCentered = isPointerOrReferenceCentered(); + + if (pointerAlignment == ALIGN_TYPE) + { + size_t prevCh = formattedLine.find_last_not_of(" \t"); + if (prevCh == string::npos) + prevCh = 0; + if (formattedLine.length() == 0 || prevCh == formattedLine.length() - 1) + appendCurrentChar(); + else + { + // exchange * or & with character following the type + // this may not work every time with a tab character + string charSave = formattedLine.substr(prevCh+1, 1); + formattedLine[prevCh+1] = currentChar; + formattedLine.append(charSave); + } + if (isSequenceReached("**")) + { + formattedLine.insert(prevCh+2, "*"); + goForward(1); + } + // if no space after * then add one + if (charNum < (int) currentLine.length() - 1 + && !isWhiteSpace(currentLine[charNum+1]) + && currentLine[charNum+1] != ')') + appendSpacePad(); + // if old pointer or reference is centered, remove a space + if (isOldPRCentered + && isWhiteSpace(formattedLine[formattedLine.length()-1])) + { + formattedLine.erase(formattedLine.length()-1, 1); + spacePadNum--; + } + } + else if (pointerAlignment == ALIGN_MIDDLE) + { + // compute current whitespace before + size_t wsBefore = currentLine.find_last_not_of(" \t", charNum - 1); + if (wsBefore == string::npos) + wsBefore = 0; + else + wsBefore = charNum - wsBefore - 1; + // adjust for ** + string sequenceToInsert = currentChar == '*' ? "*" : "&"; + if (isSequenceReached("**")) + { + sequenceToInsert = "**"; + goForward(1); + } + size_t charNumSave = charNum; + // goForward() to convert tabs to spaces, if necessary, + // and move following characters to preceding characters + // this may not work every time with tab characters + for (size_t i = charNum+1; i < currentLine.length() && isWhiteSpace(currentLine[i]); i++) + { + goForward(1); + formattedLine.append(1, currentLine[i]); + } + // whitespace should be at least 2 chars + size_t wsAfter = currentLine.find_first_not_of(" \t", charNumSave + 1); + if (wsAfter == string::npos) + wsAfter = 0; + else + wsAfter = wsAfter - charNumSave - 1; + if (wsBefore + wsAfter < 2) + { + size_t charsToAppend = (2 - (wsBefore + wsAfter)); + formattedLine.append(charsToAppend, ' '); + spacePadNum += charsToAppend; + if (wsBefore == 0) wsBefore++; + if (wsAfter == 0) wsAfter++; + } + // insert the pointer or reference char + size_t padAfter = (wsBefore + wsAfter) / 2; + formattedLine.insert(formattedLine.length() - padAfter, sequenceToInsert); + } + else if (pointerAlignment == ALIGN_NAME) + { + size_t startNum = formattedLine.find_last_not_of(" \t"); + string sequenceToInsert = currentChar == '*' ? "*" : "&"; + if (isSequenceReached("**")) + { + sequenceToInsert = "**"; + goForward(1); + } + // goForward() to convert tabs to spaces, if necessary, + // and move following characters to preceding characters + // this may not work every time with tab characters + for (size_t i = charNum+1; i < currentLine.length() && isWhiteSpace(currentLine[i]); i++) + { + goForward(1); + formattedLine.append(1, currentLine[i]); + } + appendSequence(sequenceToInsert, false); + // if no space before * then add one + if (startNum != string::npos + && !isWhiteSpace(formattedLine[startNum+1])) + { + formattedLine.insert(startNum+1 , 1, ' '); + spacePadNum++; + } + // if old pointer or reference is centered, remove a space + if (isOldPRCentered + && formattedLine.length() > startNum+1 + && isWhiteSpace(formattedLine[startNum+1])) + { + formattedLine.erase(startNum+1, 1); + spacePadNum--; + } + } + else // pointerAlignment == ALIGN_NONE + { + appendCurrentChar(); + } + return; +} + +/** + * format pointer or reference cast + * currentChar contains the pointer or reference + * NOTE: the pointers and references in function definitions + * are processed as a cast (e.g. void foo(void*, void*)) + * is processed here. + */ +void ASFormatter::formatPointerOrReferenceCast(void) +{ + assert(currentChar == '*' || currentChar == '&'); + assert(isCStyle()); + + string sequenceToInsert = currentChar == '*' ? "*" : "&"; + if (isSequenceReached("**")) + { + sequenceToInsert = "**"; + goForward(1); + } + if (pointerAlignment == ALIGN_NONE) + { + appendSequence(sequenceToInsert, false); + return; + } + // remove trailing whitespace + size_t prevCh = formattedLine.find_last_not_of(" \t"); + if (prevCh == string::npos) + prevCh = 0; + if (formattedLine.length() > 0 && isWhiteSpace(formattedLine[prevCh+1])) + { + spacePadNum -= (formattedLine.length() - 1 - prevCh); + formattedLine.erase(prevCh+1); + } + if (pointerAlignment == ALIGN_TYPE) + { + appendSequence(sequenceToInsert, false); + } + else if (pointerAlignment == ALIGN_MIDDLE + || pointerAlignment == ALIGN_NAME) + { + appendSpacePad(); + appendSequence(sequenceToInsert, false); + } + else + appendSequence(sequenceToInsert, false); +} + +/** + * add or remove space padding to parens + * currentChar contains the paren + * the parens and necessary padding will be appended to formattedLine + * the calling function should have a continue statement after calling this method + */ +void ASFormatter::padParens(void) +{ + assert(currentChar == '(' || currentChar == ')'); + + int spacesOutsideToDelete = 0; + int spacesInsideToDelete = 0; + + if (currentChar == '(') + { + spacesOutsideToDelete = formattedLine.length() - 1; + spacesInsideToDelete = 0; + + // compute spaces outside the opening paren to delete + if (shouldUnPadParens) + { + char lastChar = ' '; + bool prevIsParenHeader = false; + size_t i = formattedLine.find_last_not_of(" \t"); + if (i != string::npos) + { + // if last char is a bracket the previous whitespace is an indent + if (formattedLine[i] == '{') + spacesOutsideToDelete = 0; + else + { + spacesOutsideToDelete -= i; + lastChar = formattedLine[i]; + // if previous word is a header, it will be a paren header + string prevWord = getPreviousWord(formattedLine, formattedLine.length()); + const string* prevWordH = NULL; + if (shouldPadHeader + && prevWord.length() > 0 + && isCharPotentialHeader(prevWord, 0)) + prevWordH = ASBeautifier::findHeader(prevWord, 0, headers); + if (prevWordH != NULL) + { + prevIsParenHeader = true; + // trace + //cout << traceLineNumber << " " << *prevWordH << endl; + } + else if (prevWord == "return" // don't unpad return statements + || prevWord == "*") // don't unpad multiply or pointer + { + prevIsParenHeader = true; + // trace + //cout << traceLineNumber << " " << prevWord << endl; + } + // don't unpad variables + else if (prevWord == "bool" + || prevWord == "int" + || prevWord == "void" + || prevWord == "void*" + || (prevWord.length() >= 6 // check end of word for _t + && prevWord.compare(prevWord.length()-2, 2, "_t") == 0) + || prevWord == "BOOL" + || prevWord == "DWORD" + || prevWord == "HWND" + || prevWord == "INT" + || prevWord == "LPSTR" + || prevWord == "VOID" + || prevWord == "LPVOID" + ) + { + prevIsParenHeader = true; + // trace + //cout << traceLineNumber << " " << prevWord << endl; + } + } + } + // do not unpad operators, but leave them if already padded + if (shouldPadParensOutside || prevIsParenHeader) + spacesOutsideToDelete--; + else if (lastChar == '|' // check for || + || lastChar == '&' // check for && + || lastChar == ',' + || (lastChar == '>' && !foundCastOperator) + || lastChar == '<' + || lastChar == '?' + || lastChar == ':' + || lastChar == ';' + || lastChar == '=' + || lastChar == '+' + || lastChar == '-' + || (lastChar == '*' && isInPotentialCalculation) + || lastChar == '/' + || lastChar == '%') + spacesOutsideToDelete--; + + if (spacesOutsideToDelete > 0) + { + formattedLine.erase(i + 1, spacesOutsideToDelete); + spacePadNum -= spacesOutsideToDelete; + } + } + + // pad open paren outside + char peekedCharOutside = peekNextChar(); + if (shouldPadParensOutside) + if (!(currentChar == '(' && peekedCharOutside == ')')) + appendSpacePad(); + + appendCurrentChar(); + + // unpad open paren inside + if (shouldUnPadParens) + { + size_t j = currentLine.find_first_not_of(" \t", charNum + 1); + if (j != string::npos) + spacesInsideToDelete = j - charNum - 1; + if (shouldPadParensInside) + spacesInsideToDelete--; + if (spacesInsideToDelete > 0) + { + currentLine.erase(charNum + 1, spacesInsideToDelete); + spacePadNum -= spacesInsideToDelete; + } + // convert tab to space if requested + if (shouldConvertTabs + && (int)currentLine.length() > charNum + && currentLine[charNum+1] == '\t') + currentLine[charNum+1] = ' '; + + } + + // pad open paren inside + char peekedCharInside = peekNextChar(); + if (shouldPadParensInside) + if (!(currentChar == '(' && peekedCharInside == ')')) + appendSpaceAfter(); + // trace + //if(spacesOutsideToDelete > 0 || spacesInsideToDelete > 0) + // cout << traceLineNumber << " " << spacesOutsideToDelete << '(' << spacesInsideToDelete << endl; + } + else if (currentChar == ')' /*|| currentChar == ']'*/) + { + spacesOutsideToDelete = 0; + spacesInsideToDelete = formattedLine.length(); + + // unpad close paren inside + if (shouldUnPadParens) + { + size_t i = formattedLine.find_last_not_of(" \t"); + if (i != string::npos) + spacesInsideToDelete = formattedLine.length() - 1 - i; + if (shouldPadParensInside) + spacesInsideToDelete--; + if (spacesInsideToDelete > 0) + { + formattedLine.erase(i + 1, spacesInsideToDelete); + spacePadNum -= spacesInsideToDelete; + } + } + + // pad close paren inside + if (shouldPadParensInside) + if (!(previousChar == '(' && currentChar == ')')) + appendSpacePad(); + + appendCurrentChar(); + + // unpad close paren outside + if (shouldUnPadParens) + { + // may have end of line comments + size_t j = currentLine.find_first_not_of(" \t", charNum + 1); + if (j != string::npos) + if (currentLine[j] == '[' || currentLine[j] == ']') + spacesOutsideToDelete = j - charNum - 1; + if (shouldPadParensOutside) + spacesOutsideToDelete--; + + if (spacesOutsideToDelete > 0) + { + currentLine.erase(charNum + 1, spacesOutsideToDelete); + spacePadNum -= spacesOutsideToDelete; + } + } + + // pad close paren outside + char peekedCharOutside = peekNextChar(); + if (shouldPadParensOutside) + if (peekedCharOutside != ';' + && peekedCharOutside != ',' + && peekedCharOutside != '.' + && peekedCharOutside != '-') // check for -> + appendSpaceAfter(); + + // trace + //if(spacesInsideToDelete > 0) + // cout << traceLineNumber << " " << spacesInsideToDelete << ')' << 0 << endl; + } + return; +} + +/** + * format opening bracket as attached or broken + * currentChar contains the bracket + * the brackets will be appended to the current formattedLine or a new formattedLine as necessary + * the calling function should have a continue statement after calling this method + * + * @param bracketType the type of bracket to be formatted. + */ +void ASFormatter::formatOpeningBracket(BracketType bracketType) +{ + assert(!isBracketType(bracketType, ARRAY_TYPE)); + assert(currentChar == '{'); + + parenStack->push_back(0); + + bool breakBracket = isCurrentBracketBroken(); + + if (breakBracket) + { + if (isBeforeAnyComment() && isOkToBreakBlock(bracketType)) + { + // if comment is at line end leave the comment on this line + if (isBeforeAnyLineEndComment(charNum) && !currentLineBeginsWithBracket) // lineBeginsWith('{') + { + currentChar = ' '; // remove bracket from current line + currentLine[charNum] = currentChar; + appendOpeningBracket = true; // append bracket to following line + } + // else put comment after the bracket + else if (!isBeforeMultipleLineEndComments(charNum)) + breakLine(); + } + else if (!isBracketType(bracketType, SINGLE_LINE_TYPE)) + breakLine(); + else if (shouldBreakOneLineBlocks && peekNextChar() != '}') + breakLine(); + else if (!isInLineBreak) + appendSpacePad(); + + appendCurrentChar(); + + // should a following comment break from the bracket? + // must break the line AFTER the bracket + if (isBeforeComment() + && formattedLine[0] == '{' + && isOkToBreakBlock(bracketType) + && (bracketFormatMode == BREAK_MODE + || bracketFormatMode == LINUX_MODE + || bracketFormatMode == STROUSTRUP_MODE)) + { + shouldBreakLineAtNextChar = true; + } + + } + else // attach bracket + { + // are there comments before the bracket? + if (isCharImmediatelyPostComment || isCharImmediatelyPostLineComment) + { + if (isOkToBreakBlock(bracketType) + && !(isCharImmediatelyPostComment && isCharImmediatelyPostLineComment) // don't attach if two comments on the line + && peekNextChar() != '}' // don't attach { } + && previousCommandChar != '{' // don't attach { { + && previousCommandChar != '}' // don't attach } { + && previousCommandChar != ';') // don't attach ; { + { + appendCharInsideComments(); + } + else + { + appendCurrentChar(); // don't attach + } + } + else if (previousCommandChar == '{' + || previousCommandChar == '}' + || previousCommandChar == ';') // '}' , ';' chars added for proper handling of '{' immediately after a '}' or ';' + { + appendCurrentChar(); // don't attach + } + else + { + // if a blank line preceeds this don't attach + if (isEmptyLine(formattedLine)) + appendCurrentChar(); // don't attach + else if (isOkToBreakBlock(bracketType) + && !(isImmediatelyPostPreprocessor + && currentLineBeginsWithBracket)) // lineBeginsWith('{') + { + if (peekNextChar() != '}') + { + appendSpacePad(); + appendCurrentChar(false); // OK to attach + // should a following comment attach with the bracket? + // insert spaces to reposition the comment + if (isBeforeComment() + && !isBeforeMultipleLineEndComments(charNum) + && (!isBeforeAnyLineEndComment(charNum) || currentLineBeginsWithBracket)) // lineBeginsWith('{') + { + breakLine(); + currentLine.insert(charNum+1, charNum+1, ' '); + } + } + else + { + appendSpacePad(); + appendCurrentChar(); + } + } + else + { + if (!isInLineBreak) + appendSpacePad(); + appendCurrentChar(); // don't attach + } + } + } +} + +/** + * format closing bracket + * currentChar contains the bracket + * the calling function should have a continue statement after calling this method + * + * @param bracketType the type of bracket to be formatted. + */ +void ASFormatter::formatClosingBracket(BracketType bracketType) +{ + assert(!isBracketType(bracketType, ARRAY_TYPE)); + assert(currentChar == '}'); + + // parenStack must contain one entry + if (parenStack->size() > 1) + parenStack->pop_back(); + + // mark state of immediately after empty block + // this state will be used for locating brackets that appear immedately AFTER an empty block (e.g. '{} \n}'). + if (previousCommandChar == '{') + isImmediatelyPostEmptyBlock = true; + + if ((!(previousCommandChar == '{' && isPreviousBracketBlockRelated)) // this '{' does not close an empty block + && isOkToBreakBlock(bracketType) // astyle is allowed to break on line blocks + && !isImmediatelyPostEmptyBlock) // this '}' does not immediately follow an empty block + { + breakLine(); + appendCurrentChar(); + } + else + { + appendCurrentChar(); + } + + // if a declaration follows a definition, space pad + if (isLegalNameChar(peekNextChar())) + appendSpaceAfter(); + + if (shouldBreakBlocks && currentHeader != NULL && parenStack->back() == 0) + { + isAppendPostBlockEmptyLineRequested = true; + } +} + +/** + * format array brackets as attached or broken + * determine if the brackets can have an inStatement indent + * currentChar contains the bracket + * the brackets will be appended to the current formattedLine or a new formattedLine as necessary + * the calling function should have a continue statement after calling this method + * + * @param bracketType the type of bracket to be formatted, must be an ARRAY_TYPE. + * @param isOpeningArrayBracket indicates if this is the opening bracket for the array block. + */ +void ASFormatter::formatArrayBrackets(BracketType bracketType, bool isOpeningArrayBracket) +{ + assert(isBracketType(bracketType, ARRAY_TYPE)); + assert(currentChar == '{' || currentChar == '}'); + + if (currentChar == '{') + { + // is this the first opening bracket in the array? + if (isOpeningArrayBracket) + { + if (bracketFormatMode == ATTACH_MODE + || bracketFormatMode == LINUX_MODE + || bracketFormatMode == STROUSTRUP_MODE) + { + // don't attach to a preprocessor directive + if (isImmediatelyPostPreprocessor && currentLineBeginsWithBracket) // lineBeginsWith('{') + { + isInLineBreak = true; + appendCurrentChar(); // don't attach + } + else if (isCharImmediatelyPostComment) + { + // TODO: attach bracket to line-end comment + appendCurrentChar(); // don't attach + } + else if (isCharImmediatelyPostLineComment) + { + appendCharInsideComments(); + } + else + { + // if a blank line preceeds this don't attach + if (isEmptyLine(formattedLine)) + appendCurrentChar(); // don't attach + else + { + // if bracket is broken or not an assignment + if (currentLineBeginsWithBracket // lineBeginsWith('{') + && !isBracketType(bracketTypeStack->back(), SINGLE_LINE_TYPE)) + { + appendSpacePad(); + appendCurrentChar(false); // OK to attach + + if (currentLineBeginsWithBracket + && (int)currentLineFirstBracketNum == charNum) + shouldBreakLineAtNextChar = true; + } + else + { + appendSpacePad(); + appendCurrentChar(); + } + } + } + } + else if (bracketFormatMode == BREAK_MODE) + { + if (isWhiteSpace(peekNextChar())) + breakLine(); + else if (isBeforeAnyComment()) + { + // do not break unless comment is at line end + if (isBeforeAnyLineEndComment(charNum) && !currentLineBeginsWithBracket) + { + currentChar = ' '; // remove bracket from current line + appendOpeningBracket = true; // append bracket to following line + } + } + if (!isInLineBreak) + appendSpacePad(); + appendCurrentChar(); + + if (currentLineBeginsWithBracket + && (int)currentLineFirstBracketNum == charNum + && !isBracketType(bracketTypeStack->back(), SINGLE_LINE_TYPE)) + shouldBreakLineAtNextChar = true; + } + else if (bracketFormatMode == HORSTMANN_MODE) + { + if (isWhiteSpace(peekNextChar())) + breakLine(); + else if (isBeforeAnyComment()) + { + // do not break unless comment is at line end + if (isBeforeAnyLineEndComment(charNum) && !currentLineBeginsWithBracket) // lineBeginsWith('{') + { + currentChar = ' '; // remove bracket from current line + appendOpeningBracket = true; // append bracket to following line + } + } + if (!isInLineBreak) + appendSpacePad(); + appendCurrentChar(); + } + else if (bracketFormatMode == NONE_MODE) + { + if (currentLineBeginsWithBracket) // lineBeginsWith('{') + { + appendCurrentChar(); // don't attach + } + else + { + appendSpacePad(); + appendCurrentChar(false); // OK to attach + } + } + } + else // not the first opening bracket + { + if (bracketFormatMode == HORSTMANN_MODE) + { + if (previousNonWSChar == '{' + && bracketTypeStack->size() > 2 + && !isBracketType((*bracketTypeStack)[bracketTypeStack->size()-2], SINGLE_LINE_TYPE)) + formatArrayRunIn(); + } + else if (!isInLineBreak + && !isWhiteSpace(peekNextChar()) + && previousNonWSChar == '{' + && bracketTypeStack->size() > 2 + && !isBracketType((*bracketTypeStack)[bracketTypeStack->size()-2], SINGLE_LINE_TYPE)) + formatArrayRunIn(); + + appendCurrentChar(); + } + } + else if (currentChar == '}') + { + // does this close the first opening bracket in the array? + if (!isBracketType(bracketType, SINGLE_LINE_TYPE) ) + breakLine(); + appendCurrentChar(); + + // if a declaration follows an enum definition, space pad + char peekedChar = peekNextChar(); + if (isLegalNameChar(peekedChar) + || peekedChar == '[') + appendSpaceAfter(); + } +} + +/** + * determine if a run-in can be attached. + * if it can insert the indents in formattedLine and reset the current line break. + */ +void ASFormatter::formatRunIn() +{ + assert(bracketFormatMode == HORSTMANN_MODE || bracketFormatMode == NONE_MODE); + + // keep one line blocks returns true without indenting the run-in + if (!isOkToBreakBlock(bracketTypeStack->back())) + return; // true; + + size_t lastText = formattedLine.find_last_not_of(" \t"); + if (lastText == string::npos || formattedLine[lastText] != '{') + return; // false; + + // make sure the bracket is broken + if (formattedLine.find_first_not_of(" \t{") != string::npos) + return; // false; + + if (isBracketType(bracketTypeStack->back(), NAMESPACE_TYPE)) + return; // false; + + bool extraIndent = false; + isInLineBreak = true; + + // cannot attach a class modifier without indent-classes + if (isCStyle() + && isCharPotentialHeader(currentLine, charNum) + && (isBracketType(bracketTypeStack->back(), CLASS_TYPE) + || (isBracketType(bracketTypeStack->back(), STRUCT_TYPE) + && isInIndentableStruct))) + { + if (findKeyword(currentLine, charNum, AS_PUBLIC) + || findKeyword(currentLine, charNum, AS_PRIVATE) + || findKeyword(currentLine, charNum, AS_PROTECTED)) + { + if (!getClassIndent()) + return; // false; + } + else if (getClassIndent()) + extraIndent = true; + } + + // cannot attach a 'case' statement without indent-switches + if (!getSwitchIndent() + && isCharPotentialHeader(currentLine, charNum) + && (findKeyword(currentLine, charNum, AS_CASE) + || findKeyword(currentLine, charNum, AS_DEFAULT))) + return; // false; + + // extra indent for switch statements + if (getSwitchIndent() + && !preBracketHeaderStack->empty() + && preBracketHeaderStack->back() == &AS_SWITCH + && ((isLegalNameChar(currentChar) + && !findKeyword(currentLine, charNum, AS_CASE)) + || isSequenceReached("//") + || isSequenceReached("/*"))) + extraIndent = true; + + isInLineBreak = false; + // remove for extra whitespace + if (formattedLine.length() > lastText+1 + && formattedLine.find_first_not_of(" \t", lastText+1) == string::npos) + formattedLine.erase(lastText+1); + + if (getIndentString() == "\t") + { + appendChar('\t', false); + horstmannIndentChars = 2; // one for { and one for tab + if (extraIndent) + { + appendChar('\t', false); + horstmannIndentChars++; + } + } + else + { + int indent = getIndentLength(); + formattedLine.append(indent-1, ' '); + horstmannIndentChars = indent; + if (extraIndent) + { + formattedLine.append(indent, ' '); + horstmannIndentChars += indent; + } + } + isInHorstmannRunIn = true; +} + +/** + * remove whitepace and add indentation for an array run-in. + */ +void ASFormatter::formatArrayRunIn() +{ + assert(isBracketType(bracketTypeStack->back(), ARRAY_TYPE)); + + // make sure the bracket is broken + if (formattedLine.find_first_not_of(" \t{") != string::npos) + return; + + size_t lastText = formattedLine.find_last_not_of(" \t"); + if (lastText == string::npos || formattedLine[lastText] != '{') + return; + + // check for extra whitespace + if (formattedLine.length() > lastText+1 + && formattedLine.find_first_not_of(" \t", lastText+1) == string::npos) + formattedLine.erase(lastText+1); + + if (getIndentString() == "\t") + { + appendChar('\t', false); + horstmannIndentChars = 2; // one for { and one for tab + } + else + { + int indent = getIndentLength(); + formattedLine.append(indent-1, ' '); + horstmannIndentChars = indent; + } + isInHorstmannRunIn = true; + isInLineBreak = false; +} + +/** + * delete a bracketTypeStack vector object + * BracketTypeStack did not work with the DeleteContainer template + */ +void ASFormatter::deleteContainer(vector<BracketType>* &container) +{ + if (container != NULL) + { + container->clear(); + delete (container); + container = NULL; + } +} + +/** + * delete a vector object + * T is the type of vector + * used for all vectors except bracketTypeStack + */ +template<typename T> +void ASFormatter::deleteContainer(T &container) +{ + if (container != NULL) + { + container->clear(); + delete (container); + container = NULL; + } +} + +/** + * initialize a BracketType vector object + * BracketType did not work with the DeleteContainer template + */ +void ASFormatter::initContainer(vector<BracketType>* &container, vector<BracketType>* value) +{ + if (container != NULL) + deleteContainer(container); + container = value; +} + +/** + * initialize a vector object + * T is the type of vector + * used for all vectors except bracketTypeStack + */ +template<typename T> +void ASFormatter::initContainer(T &container, T value) +{ + // since the ASFormatter object is never deleted, + // the existing vectors must be deleted before creating new ones + if (container != NULL) + deleteContainer(container); + container = value; +} + +/** + * convert a tab to spaces. + * charNum points to the current character to convert to spaces. + * tabIncrementIn is the increment that must be added for tab indent characters + * to get the correct column for the current tab. + * replaces the tab in currentLine with the required number of spaces. + * replaces the value of currentChar. + */ +void ASFormatter::convertTabToSpaces() +{ + assert(currentLine[charNum] == '\t'); + + // do NOT replace if in quotes + if (isInQuote || isInQuoteContinuation) + return; + + size_t indent = getIndentLength(); + size_t numSpaces = indent - ((tabIncrementIn + charNum) % indent); + currentLine.replace(charNum, 1, numSpaces, ' '); + currentChar = currentLine[charNum]; +} + +/** +* is it ok to break this block? +*/ +bool ASFormatter::isOkToBreakBlock(BracketType bracketType) const +{ + // Actually, there should not be an ARRAY_TYPE bracket here. + // But this will avoid breaking a one line block when there is. + // Otherwise they will be formatted differently on consecutive runs. + if (isBracketType(bracketType, ARRAY_TYPE) + && isBracketType(bracketType, SINGLE_LINE_TYPE)) + return false; + if (!isBracketType(bracketType, SINGLE_LINE_TYPE) + || shouldBreakOneLineBlocks + || breakCurrentOneLineBlock) + return true; + return false; +} + +/** +* check if a sharp header is a paren or nonparen header +*/ +bool ASFormatter::isSharpStyleWithParen(const string* header) const +{ + if (isSharpStyle() && peekNextChar() == '(' + && (header == &AS_CATCH + || header == &AS_DELEGATE)) + return true; + return false; +} + +/** + * check for a following header when a comment is reached. + * if a header follows, the comments are kept as part of the header block. + * firstLine must contain the start of the comment. + */ +void ASFormatter::checkForFollowingHeader(const string& firstLine) +{ + // look ahead to find the next non-comment text + string nextText = peekNextText(firstLine, true); + if (nextText.length() == 0 || !isCharPotentialHeader(nextText, 0)) + return; + + const string* newHeader = ASBeautifier::findHeader(nextText, 0, headers); + + if (newHeader == NULL) + return; + + // may need to break if a header follows + bool isClosingHeader = (newHeader == &AS_ELSE + || newHeader == &AS_CATCH + || newHeader == &AS_FINALLY); + + // if a closing header, reset break unless break is requested + if (isClosingHeader) + { + if (!shouldBreakClosingHeaderBlocks) + isPrependPostBlockEmptyLineRequested = false; + } + // if an opening header, break before the comment + else + { + isPrependPostBlockEmptyLineRequested = true; + } +} + +/** + * process preprocessor statements. + * charNum should be the index of the preprocessor directive. + * + * delete bracketTypeStack entries added by #if if a #else is found. + * prevents double entries in the bracketTypeStack. + */ +void ASFormatter::processPreprocessor() +{ + assert(currentChar == '#'); + + const int preproc = charNum + 1; + + if (currentLine.compare(preproc, 2, "if") == 0) + { + preprocBracketTypeStackSize = bracketTypeStack->size(); + } + else if (currentLine.compare(preproc, 4, "else") == 0) + { + // delete stack entries added in #if + // should be replaced by #else + if (preprocBracketTypeStackSize > 0) + { + int addedPreproc = bracketTypeStack->size() - preprocBracketTypeStackSize; + for (int i=0; i < addedPreproc; i++) + bracketTypeStack->pop_back(); + } + } +} + +/** + * determine if the next line starts a comment + * and a header follows the comment or comments + */ +bool ASFormatter::commentAndHeaderFollows() const +{ + // is the next line a comment + string nextLine = sourceIterator->peekNextLine(); + size_t firstChar = nextLine.find_first_not_of(" \t"); + if (firstChar == string::npos + || !(nextLine.compare(firstChar, 2, "//") == 0 + || nextLine.compare(firstChar, 2, "/*") == 0)) + { + sourceIterator->peekReset(); + return false; + } + + // if next line is a comment, find the next non-comment text + string nextText = peekNextText(nextLine, true); + if (nextText.length() == 0 || !isCharPotentialHeader(nextText, 0)) + return false; + + const string* newHeader = ASBeautifier::findHeader(nextText, 0, headers); + + if (newHeader == NULL) + return false; + + bool isClosingHeader = (newHeader == &AS_ELSE + || newHeader == &AS_CATCH + || newHeader == &AS_FINALLY); + + if (isClosingHeader && !shouldBreakClosingHeaderBlocks) + return false; + + return true; +} + +/** + * determine if a bracket should be attached or broken + * uses brackets in the bracketTypeStack + * the last bracket in the bracketTypeStack is the one being formatted + * returns true if the bracket should be broken + */ +bool ASFormatter::isCurrentBracketBroken() const +{ + assert(bracketTypeStack->size() > 0); + + bool breakBracket = false; + size_t bracketTypeStackEnd = bracketTypeStack->size()-1; + + if (isBracketType((*bracketTypeStack)[bracketTypeStackEnd], EXTERN_TYPE)) + { + if (currentLineBeginsWithBracket + || bracketFormatMode == HORSTMANN_MODE) + breakBracket = true; + } + else if (bracketFormatMode == NONE_MODE) + { + if (currentLineBeginsWithBracket + && (int)currentLineFirstBracketNum == charNum) // lineBeginsWith('{') + breakBracket = true; + } + else if (bracketFormatMode == BREAK_MODE || bracketFormatMode == HORSTMANN_MODE) + { + breakBracket = true; + } + else if (bracketFormatMode == LINUX_MODE || bracketFormatMode == STROUSTRUP_MODE) + { + // break a class if Linux + if (isBracketType((*bracketTypeStack)[bracketTypeStackEnd], CLASS_TYPE)) + { + if (bracketFormatMode == LINUX_MODE) + breakBracket = true; + } + // break a namespace or interface if Linux + else if (isBracketType((*bracketTypeStack)[bracketTypeStackEnd], NAMESPACE_TYPE) + || isBracketType((*bracketTypeStack)[bracketTypeStackEnd], INTERFACE_TYPE)) + { + if (bracketFormatMode == LINUX_MODE) + breakBracket = true; + } + // break the first bracket if a function + else if (bracketTypeStackEnd == 1 + && isBracketType((*bracketTypeStack)[bracketTypeStackEnd], COMMAND_TYPE)) + { + breakBracket = true; + } + else if (bracketTypeStackEnd > 1) + { + // break the first bracket after a namespace or extern if a function + if (isBracketType((*bracketTypeStack)[bracketTypeStackEnd-1], NAMESPACE_TYPE) + || isBracketType((*bracketTypeStack)[bracketTypeStackEnd-1], EXTERN_TYPE)) + { + if (isBracketType((*bracketTypeStack)[bracketTypeStackEnd], COMMAND_TYPE)) + breakBracket = true; + } + // if not C style then break the first bracket after a class if a function + else if (!isCStyle()) + { + if ((isBracketType((*bracketTypeStack)[bracketTypeStackEnd-1], CLASS_TYPE) + || isBracketType((*bracketTypeStack)[bracketTypeStackEnd-1], ARRAY_TYPE) + || isBracketType((*bracketTypeStack)[bracketTypeStackEnd-1], STRUCT_TYPE)) + && isBracketType((*bracketTypeStack)[bracketTypeStackEnd], COMMAND_TYPE)) + breakBracket = true; + } + } + } + return breakBracket; +} + +/** + * format comment body + * the calling function should have a continue statement after calling this method + */ +void ASFormatter::formatCommentBody() +{ + assert(isInComment); + + if (isSequenceReached("*/")) + { + isInComment = false; + noTrimCommentContinuation = false; + isImmediatelyPostComment = true; + appendSequence(AS_CLOSE_COMMENT); + goForward(1); + if (doesLineStartComment + && (currentLine.find_first_not_of(" \t", charNum+1) == string::npos)) + lineEndsInCommentOnly = true; + if (peekNextChar() == '}' + && previousCommandChar != ';' + && !isBracketType(bracketTypeStack->back(), ARRAY_TYPE) + && isOkToBreakBlock(bracketTypeStack->back())) + breakLine(); + } + else + { + appendCurrentChar(); + // append the comment up to the next tab or comment end + // tabs must be checked for convert-tabs before appending + while (charNum + 1 < (int) currentLine.length() + && currentLine[charNum+1] != '\t' + && currentLine.compare(charNum+1, 2, "*/") != 0) + { + currentChar = currentLine[++charNum]; + appendCurrentChar(); + } + } +} + +/** + * format a comment opener + * the comment opener will be appended to the current formattedLine or a new formattedLine as necessary + * the calling function should have a continue statement after calling this method + */ +void ASFormatter::formatCommentOpener() +{ + assert(isSequenceReached("/*")); + + isInComment = true; + isImmediatelyPostLineComment = false; + + if (spacePadNum != 0) + adjustComments(); + formattedLineCommentNum = formattedLine.length(); + + // must be done BEFORE appendSequence + if (previousCommandChar == '{' + && !isImmediatelyPostComment + && !isImmediatelyPostLineComment) + { + if (bracketFormatMode == NONE_MODE) + { + // should a run-in statement be attached? + if (currentLineBeginsWithBracket) + formatRunIn(); + } + else if (bracketFormatMode == ATTACH_MODE) + { + // if the bracket was not attached? + if (formattedLine[0] == '{' + && !isBracketType(bracketTypeStack->back(), SINGLE_LINE_TYPE)) + isInLineBreak = true; + } + else if (bracketFormatMode == HORSTMANN_MODE) + { + // should a run-in statement be attached? + if (formattedLine[0] == '{') + formatRunIn(); + } + } + else if (!doesLineStartComment) + noTrimCommentContinuation = true; + + // appendSequence will write the previous line + appendSequence(AS_OPEN_COMMENT); + goForward(1); + + // must be done AFTER appendSequence + if (shouldBreakBlocks) + { + // break before the comment if a header follows the comment + // for speed, do not check if previous line is empty, + // if previous line is a line comment or if previous line is '{' + if (doesLineStartComment + && !isImmediatelyPostEmptyLine + && !isImmediatelyPostComment + && !isImmediatelyPostLineComment + && previousCommandChar != '{') + { + checkForFollowingHeader(currentLine.substr(charNum-1)); + } + } + + if (previousCommandChar == '}') + currentHeader = NULL; +} + +/** + * format a line comment body + * the calling function should have a continue statement after calling this method + */ +void ASFormatter::formatLineCommentBody() +{ + assert(isInLineComment); + + appendCurrentChar(); + // append the comment up to the next tab + // tabs must be checked for convert-tabs before appending + while (charNum + 1 < (int) currentLine.length() + && currentLine[charNum+1] != '\t') + { + currentChar = currentLine[++charNum]; + appendCurrentChar(); + } + + // explicitely break a line when a line comment's end is found. + if (charNum + 1 == (int) currentLine.length()) + { + isInLineBreak = true; + isInLineComment = false; + isImmediatelyPostLineComment = true; + currentChar = 0; //make sure it is a neutral char. + } +} + +/** + * format a line comment opener + * the line comment opener will be appended to the current formattedLine or a new formattedLine as necessary + * the calling function should have a continue statement after calling this method + */ +void ASFormatter::formatLineCommentOpener() +{ + assert(isSequenceReached("//")); + + if (currentLine[charNum+2] == '\xf2') // check for windows line marker + isAppendPostBlockEmptyLineRequested = false; + + isInLineComment = true; + isCharImmediatelyPostComment = false; + + // do not indent if in column 1 or 2 + if (!shouldIndentCol1Comments && !lineCommentNoIndent) + { + if (charNum == 0) + lineCommentNoIndent = true; + else if (charNum == 1 && currentLine[0] == ' ') + lineCommentNoIndent = true; + } + // move comment if spaces were added or deleted + if (lineCommentNoIndent == false && spacePadNum != 0) + adjustComments(); + formattedLineCommentNum = formattedLine.length(); + + // must be done BEFORE appendSequence + // check for run-in statement + if (previousCommandChar == '{' + && !isImmediatelyPostComment + && !isImmediatelyPostLineComment) + { + if (bracketFormatMode == NONE_MODE) + { + if (currentLineBeginsWithBracket) + formatRunIn(); + } + else if (bracketFormatMode == HORSTMANN_MODE) + { + if (!lineCommentNoIndent) + formatRunIn(); + else + isInLineBreak = true; + } + else if (bracketFormatMode == BREAK_MODE) + { + if (formattedLine[0] == '{') + isInLineBreak = true; + } + else + { + if (currentLineBeginsWithBracket) + isInLineBreak = true; + } + } + + // appendSequence will write the previous line + appendSequence(AS_OPEN_LINE_COMMENT); + goForward(1); + + if (formattedLine.compare(0, 2, "//") == 0) + lineIsLineCommentOnly = true; + + // must be done AFTER appendSequence + if (shouldBreakBlocks) + { + // break before the comment if a header follows the line comment + // for speed, do not check if previous line is empty, + // if previous line is a comment or if previous line is '{' + if (lineIsLineCommentOnly + && previousCommandChar != '{' + && !isImmediatelyPostEmptyLine + && !isImmediatelyPostComment + && !isImmediatelyPostLineComment) + { + checkForFollowingHeader(currentLine.substr(charNum-1)); + } + } + + if (previousCommandChar == '}') + currentHeader = NULL; + + // if tabbed input don't convert the immediately following tabs to spaces + if (getIndentString() == "\t" && lineCommentNoIndent) + { + while (charNum + 1 < (int) currentLine.length() + && currentLine[charNum+1] == '\t') + { + currentChar = currentLine[++charNum]; + appendCurrentChar(); + } + } + + // explicitely break a line when a line comment's end is found. + if (charNum + 1 == (int) currentLine.length()) + { + isInLineBreak = true; + isInLineComment = false; + isImmediatelyPostLineComment = true; + currentChar = 0; //make sure it is a neutral char. + } +} + +/** + * format quote body + * the calling function should have a continue statement after calling this method + */ +void ASFormatter::formatQuoteBody() +{ + assert(isInQuote); + + if (isSpecialChar) + { + isSpecialChar = false; + } + else if (currentChar == '\\' && !isInVerbatimQuote) + { + if (peekNextChar() == ' ') // is this '\' at end of line + haveLineContinuationChar = true; + else + isSpecialChar = true; + } + else if (isInVerbatimQuote && currentChar == '"') + { + if (peekNextChar() == '"') // check consecutive quotes + { + appendSequence("\"\""); + goForward(1); + return; + } + else + { + isInQuote = false; + isInVerbatimQuote = false; + } + } + else if (quoteChar == currentChar) + { + isInQuote = false; + } + + appendCurrentChar(); + + // append the text to the ending quoteChar or an escape sequence + // tabs in quotes are NOT changed by convert-tabs + if (isInQuote && currentChar != '\\') + { + while (charNum + 1 < (int) currentLine.length() + && currentLine[charNum+1] != quoteChar + && currentLine[charNum+1] != '\\') + { + currentChar = currentLine[++charNum]; + appendCurrentChar(); + } + } +} + +/** + * format a quote opener + * the quote opener will be appended to the current formattedLine or a new formattedLine as necessary + * the calling function should have a continue statement after calling this method + */ +void ASFormatter::formatQuoteOpener() +{ + assert(currentChar == '"' || currentChar == '\''); + + isInQuote = true; + quoteChar = currentChar; + if (isSharpStyle() && previousChar == '@') + isInVerbatimQuote = true; + + // a quote following a bracket is an array + if (previousCommandChar == '{' + && !isImmediatelyPostComment + && !isImmediatelyPostLineComment + && isNonInStatementArray + && !isBracketType(bracketTypeStack->back(), SINGLE_LINE_TYPE) + && !isWhiteSpace(peekNextChar())) + { + if (bracketFormatMode == NONE_MODE) + { + if (currentLineBeginsWithBracket) + formatRunIn(); + } + else if (bracketFormatMode == HORSTMANN_MODE) + { + if (!lineCommentNoIndent) + formatRunIn(); + else + isInLineBreak = true; + } + else if (bracketFormatMode == BREAK_MODE) + { + if (formattedLine[0] == '{') + isInLineBreak = true; + } + else + { + if (currentLineBeginsWithBracket) + isInLineBreak = true; + } + } + previousCommandChar = ' '; + appendCurrentChar(); +} + +/** + * get the next line comment adjustment that results from breaking a closing bracket. + * the bracket must be on the same line as the closing header. + * i.e "} else" changed to "} \n else". + */ +int ASFormatter::getNextLineCommentAdjustment() +{ + assert(foundClosingHeader && previousNonWSChar == '}'); + if (charNum < 1) + return 0; + size_t lastBracket = currentLine.rfind('}', charNum - 1); + if (lastBracket != string::npos) + return (lastBracket - charNum); // return a negative number + return 0; +} + +LineEndFormat ASFormatter::getLineEndFormat() const +{ + return lineEnd; +} + +/** + * get the current line comment adjustment that results from attaching + * a closing header to a closing bracket. + * the bracket must be on the line previous to the closing header. + * the adjustment is 2 chars, one for the bracket and one for the space. + * i.e "} \n else" changed to "} else". + */ +int ASFormatter::getCurrentLineCommentAdjustment() +{ + assert(foundClosingHeader && previousNonWSChar == '}'); + if (charNum < 1) + return 2; + size_t lastBracket = currentLine.rfind('}', charNum - 1); + if (lastBracket == string::npos) + return 2; + return 0; +} + +/** + * get the previous word + * the argument 'end' must point to the search start. + * + * @return is the previous word. + */ +string ASFormatter::getPreviousWord(const string& line, int currPos) const +{ + // get the last legal word (may be a number) + if (currPos == 0) + return string(); + + size_t end = line.find_last_not_of(" \t", currPos-1); + if (end == string::npos || !isLegalNameChar(line[end])) + return string(); + + int start; // start of the previous word + for (start = end; start > -1; start--) + { + if (!isLegalNameChar(line[start]) || line[start] == '.') + break; + } + start++; + + return (line.substr(start, end-start+1)); +} + +/** + * check if a line break is needed when a closing bracket + * is followed by a closing header. + * the break depends on the bracketFormatMode and other factors. + */ +void ASFormatter::isLineBreakBeforeClosingHeader() +{ + assert(foundClosingHeader && previousNonWSChar == '}'); + if (bracketFormatMode == BREAK_MODE || bracketFormatMode == HORSTMANN_MODE) + { + isInLineBreak = true; + } + else if (bracketFormatMode == NONE_MODE) + { + if (shouldBreakClosingHeaderBrackets + || getBracketIndent() || getBlockIndent()) + { + isInLineBreak = true; + } + else + { + appendSpacePad(); + // is closing bracket broken? + size_t i = currentLine.find_first_not_of(" \t"); + if (i != string::npos && currentLine[i] == '}') + isInLineBreak = false; + + if (shouldBreakBlocks) + isAppendPostBlockEmptyLineRequested = false; + } + } + // bracketFormatMode == ATTACH_MODE, LINUX_MODE, STROUSTRUP_MODE + else + { + if (shouldBreakClosingHeaderBrackets + || getBracketIndent() || getBlockIndent()) + { + isInLineBreak = true; + } + else + { + // if a blank line does not preceed this + // or last line is not a one line block, attach header + bool previousLineIsEmpty = isEmptyLine(formattedLine); + bool previousLineIsOneLineBlock = false; + size_t firstBracket = findNextChar(formattedLine, '{'); + if (firstBracket != string::npos) + previousLineIsOneLineBlock = isOneLineBlockReached(formattedLine, firstBracket); + if (!previousLineIsEmpty + && !previousLineIsOneLineBlock) + { + isInLineBreak = false; + appendSpacePad(); + spacePadNum = 0; // don't count as comment padding + } + + if (shouldBreakBlocks) + isAppendPostBlockEmptyLineRequested = false; + } + } +} + +/** + * Add brackets to a single line statement following a header. + * Brackets are not added if the proper conditions are not met. + * Brackets are added to the currentLine. + */ +bool ASFormatter::addBracketsToStatement() +{ + assert(isImmediatelyPostHeader); + + if (currentHeader != &AS_IF + && currentHeader != &AS_ELSE + && currentHeader != &AS_FOR + && currentHeader != &AS_WHILE + && currentHeader != &AS_DO + && currentHeader != &AS_FOREACH) + return false; + + // do not add if a header follows (i.e. else if) + if (isCharPotentialHeader(currentLine, charNum)) + if (findHeader(headers) != NULL) + return false; + + // find the next semi-colon + size_t nextSemiColon = findNextChar(currentLine, ';', charNum+1); + if (nextSemiColon == string::npos) + return false; + + // add closing bracket before changing the line length + if (nextSemiColon == currentLine.length() - 1) + currentLine.append(" }"); + else + currentLine.insert(nextSemiColon + 1, " }"); + // add opening bracket + currentLine.insert(charNum, "{ "); + currentChar = '{'; + // remove extra spaces + if (!shouldAddOneLineBrackets) + { + size_t lastText = formattedLine.find_last_not_of(" \t"); + if ((formattedLine.length() - 1) - lastText > 1) + formattedLine.erase(lastText + 1); + } + return true; +} + +/** + * Find the next character that is not in quotes or a comment. + * + * @param line the line to be searched. + * @param searchChar the char to find. + * @param searchStart the char to find. + * @return the position on the line or string::npos if not found. + */ +size_t ASFormatter::findNextChar(string& line, char searchChar, int searchStart /*0*/) +{ + // find the next searchChar + size_t i; + for (i = searchStart; i < line.length(); i++) + { + if (line.compare(i, 2, "//") == 0) + return string::npos; + if (line.compare(i, 2, "/*") == 0) + { + size_t endComment = line.find("*/", i+2); + if (endComment == string::npos) + return string::npos; + i = endComment + 2; + } + if (line[i] == '\'' || line[i] == '\"') + { + char quote = line[i]; + while (i < line.length()) + { + size_t endQuote = line.find(quote, i+1); + if (endQuote == string::npos) + return string::npos; + i = endQuote; + if (line[endQuote-1] != '\\') // check for '\"' + break; + if (line[endQuote-2] == '\\') // check for '\\' + break; + } + } + + if (line[i] == searchChar) + break; + + // for now don't process C# 'delegate' brackets + // do this last in case the search char is a '{' + if (line[i] == '{') + return string::npos; + } + if (i >= line.length()) // didn't find searchChar + return string::npos; + + return i; +} + +/** + * Look ahead in the file to see if a struct has access modifiers. + * + * @param line a reference to the line to indent. + * @param index the current line index. + * @return true if the struct has access modifiers. + */ +bool ASFormatter::isStructAccessModified(string &firstLine, size_t index) const +{ + assert(firstLine[index] == '{'); + assert(isCStyle()); + + bool isFirstLine = true; + bool needReset = false; + size_t bracketCount = 1; + string nextLine = firstLine.substr(index + 1); + + // find the first non-blank text, bypassing all comments. + bool isInComment = false; + while (sourceIterator->hasMoreLines()) + { + if (isFirstLine) + isFirstLine = false; + else + { + nextLine = sourceIterator->peekNextLine(); + needReset = true; + } + // parse the line + for (size_t i = 0; i < nextLine.length(); i++) + { + if (isWhiteSpace(nextLine[i])) + continue; + if (nextLine.compare(i, 2, "/*") == 0) + isInComment = true; + if (isInComment) + { + i = nextLine.find("*/", i); + if (i == string::npos) + { + i = nextLine.length(); + continue; + } + i++; + isInComment = false; + continue; + } + if (nextLine.compare(i, 2, "//") == 0) + { + i = nextLine.length(); + continue; + } + // handle brackets + if (nextLine[i] == '{') + bracketCount++; + if (nextLine[i] == '}') + bracketCount--; + if (bracketCount == 0) + { + if (needReset) + sourceIterator->peekReset(); + return false; + } + // check for access modifiers + if (isCharPotentialHeader(nextLine, i)) + { + if (findKeyword(nextLine, i, AS_PUBLIC) + || findKeyword(nextLine, i, AS_PRIVATE) + || findKeyword(nextLine, i, AS_PROTECTED)) + { + if (needReset) + sourceIterator->peekReset(); + return true; + } + string name = getCurrentWord(nextLine, i); + i += name.length() - 1; + } + } // end of for loop + } // end of while loop + + if (needReset) + sourceIterator->peekReset(); + return false; +} + +/** + * Check to see if this is an EXEC SQL statement. + * + * @param line a reference to the line to indent. + * @param index the current line index. + * @return true if the statement is EXEC SQL. + */ +bool ASFormatter::isExecSQL(string &line, size_t index) const +{ + if (line[index] != 'e' && line[index] != 'E') // quick check to reject most + return false; + string word; + if (isCharPotentialHeader(line, index)) + word = getCurrentWord(line, index); + for (size_t i = 0; i < word.length(); i++) + word[i] = (char) toupper(word[i]); + if (word != "EXEC") + return false; + size_t index2 = index + word.length(); + index2 = line.find_first_not_of(" \t", index2); + if (index2 == string::npos) + return false; + word.erase(); + if (isCharPotentialHeader(line, index2)) + word = getCurrentWord(line, index2); + for (size_t i = 0; i < word.length(); i++) + word[i] = (char) toupper(word[i]); + if (word != "SQL") + return false; + return true; +} + +/** + * The continuation lines must be adjusted so the leading spaces + * is equivalent to the text on the opening line. + * + * Updates currentLine and charNum. + */ +void ASFormatter::trimContinuationLine() +{ + size_t len = currentLine.length(); + size_t indent = getIndentLength(); + charNum = 0; + + if (leadingSpaces > 0 && len > 0) + { + size_t i; + size_t continuationIncrementIn = 0; + for (i = 0; (i < len) && (i + continuationIncrementIn < leadingSpaces); i++) + { + if (!isWhiteSpace(currentLine[i])) // don't delete any text + { + i = 0; + continuationIncrementIn = tabIncrementIn; + break; + } + if (currentLine[i] == '\t') + continuationIncrementIn += indent - 1 - ((continuationIncrementIn + i) % indent); + } + + if ((int) continuationIncrementIn == tabIncrementIn) + charNum = i; + else + { + // build a new line with the equivalent leading chars + string newLine; + int leadingChars = 0; + if ((int) leadingSpaces > tabIncrementIn) + leadingChars = leadingSpaces - tabIncrementIn; + newLine.append(leadingChars, ' '); + newLine.append(currentLine, i, len-i); + currentLine = newLine; + charNum = leadingChars; + } + if (i >= len) + charNum = 0; + } + return; +} + + +} // end namespace astyle diff --git a/support/highlight/src/core/astyle/ASResource.cpp b/support/highlight/src/core/astyle/ASResource.cpp new file mode 100644 index 0000000000..c2781c88a3 --- /dev/null +++ b/support/highlight/src/core/astyle/ASResource.cpp @@ -0,0 +1,547 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * + * Copyright (C) 2006-2010 by Jim Pattee <jimp03@email.com> + * Copyright (C) 1998-2002 by Tal Davidson + * <http://www.gnu.org/licenses/lgpl-3.0.html> + * + * This file is a part of Artistic Style - an indentation and + * reformatting tool for C, C++, C# and Java source files. + * <http://astyle.sourceforge.net> + * + * Artistic Style is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Artistic Style is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Artistic Style. If not, see <http://www.gnu.org/licenses/>. + * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + */ + +#include "astyle.h" +#include <algorithm> + + +namespace astyle +{ +const string ASResource::AS_IF = string("if"); +const string ASResource::AS_ELSE = string("else"); +const string ASResource::AS_FOR = string("for"); +const string ASResource::AS_DO = string("do"); +const string ASResource::AS_WHILE = string("while"); +const string ASResource::AS_SWITCH = string("switch"); +const string ASResource::AS_CASE = string("case"); +const string ASResource::AS_DEFAULT = string("default"); +const string ASResource::AS_CLASS = string("class"); +const string ASResource::AS_STRUCT = string("struct"); +const string ASResource::AS_UNION = string("union"); +const string ASResource::AS_INTERFACE = string("interface"); +const string ASResource::AS_NAMESPACE = string("namespace"); +const string ASResource::AS_EXTERN = string("extern"); +const string ASResource::AS_ENUM = string("enum"); +const string ASResource::AS_PUBLIC = string("public"); +const string ASResource::AS_PROTECTED = string("protected"); +const string ASResource::AS_PRIVATE = string("private"); +const string ASResource::AS_STATIC = string("static"); +const string ASResource::AS_SYNCHRONIZED = string("synchronized"); +const string ASResource::AS_OPERATOR = string("operator"); +const string ASResource::AS_TEMPLATE = string("template"); +const string ASResource::AS_TRY = string("try"); +const string ASResource::AS_CATCH = string("catch"); +const string ASResource::AS_FINALLY = string("finally"); +const string ASResource::AS_THROWS = string("throws"); +const string ASResource::AS_CONST = string("const"); +const string ASResource::AS_WHERE = string("where"); +const string ASResource::AS_NEW = string("new"); + +const string ASResource::AS_ASM = string("asm"); +const string ASResource::AS__ASM__ = string("__asm__"); +const string ASResource::AS_MS_ASM = string("_asm"); +const string ASResource::AS_MS__ASM = string("__asm"); + +const string ASResource::AS_BAR_DEFINE = string("#define"); +const string ASResource::AS_BAR_INCLUDE = string("#include"); +const string ASResource::AS_BAR_IF = string("#if"); +const string ASResource::AS_BAR_EL = string("#el"); +const string ASResource::AS_BAR_ENDIF = string("#endif"); + +const string ASResource::AS_OPEN_BRACKET = string("{"); +const string ASResource::AS_CLOSE_BRACKET = string("}"); +const string ASResource::AS_OPEN_LINE_COMMENT = string("//"); +const string ASResource::AS_OPEN_COMMENT = string("/*"); +const string ASResource::AS_CLOSE_COMMENT = string("*/"); + +const string ASResource::AS_ASSIGN = string("="); +const string ASResource::AS_PLUS_ASSIGN = string("+="); +const string ASResource::AS_MINUS_ASSIGN = string("-="); +const string ASResource::AS_MULT_ASSIGN = string("*="); +const string ASResource::AS_DIV_ASSIGN = string("/="); +const string ASResource::AS_MOD_ASSIGN = string("%="); +const string ASResource::AS_OR_ASSIGN = string("|="); +const string ASResource::AS_AND_ASSIGN = string("&="); +const string ASResource::AS_XOR_ASSIGN = string("^="); +const string ASResource::AS_GR_GR_ASSIGN = string(">>="); +const string ASResource::AS_LS_LS_ASSIGN = string("<<="); +const string ASResource::AS_GR_GR_GR_ASSIGN = string(">>>="); +const string ASResource::AS_LS_LS_LS_ASSIGN = string("<<<="); +const string ASResource::AS_GCC_MIN_ASSIGN = string("<?"); +const string ASResource::AS_GCC_MAX_ASSIGN = string(">?"); + +const string ASResource::AS_RETURN = string("return"); +const string ASResource::AS_CIN = string("cin"); +const string ASResource::AS_COUT = string("cout"); +const string ASResource::AS_CERR = string("cerr"); + +const string ASResource::AS_EQUAL = string("=="); +const string ASResource::AS_PLUS_PLUS = string("++"); +const string ASResource::AS_MINUS_MINUS = string("--"); +const string ASResource::AS_NOT_EQUAL = string("!="); +const string ASResource::AS_GR_EQUAL = string(">="); +const string ASResource::AS_GR_GR = string(">>"); +const string ASResource::AS_GR_GR_GR = string(">>>"); +const string ASResource::AS_LS_EQUAL = string("<="); +const string ASResource::AS_LS_LS = string("<<"); +const string ASResource::AS_LS_LS_LS = string("<<<"); +const string ASResource::AS_QUESTION_QUESTION = string("??"); +const string ASResource::AS_EQUAL_GR = string("=>"); // C# lambda expression arrow +const string ASResource::AS_ARROW = string("->"); +const string ASResource::AS_AND = string("&&"); +const string ASResource::AS_OR = string("||"); +const string ASResource::AS_COLON_COLON = string("::"); +const string ASResource::AS_PAREN_PAREN = string("()"); +const string ASResource::AS_BLPAREN_BLPAREN = string("[]"); + +const string ASResource::AS_PLUS = string("+"); +const string ASResource::AS_MINUS = string("-"); +const string ASResource::AS_MULT = string("*"); +const string ASResource::AS_DIV = string("/"); +const string ASResource::AS_MOD = string("%"); +const string ASResource::AS_GR = string(">"); +const string ASResource::AS_LS = string("<"); +const string ASResource::AS_NOT = string("!"); +const string ASResource::AS_BIT_OR = string("|"); +const string ASResource::AS_BIT_AND = string("&"); +const string ASResource::AS_BIT_NOT = string("~"); +const string ASResource::AS_BIT_XOR = string("^"); +const string ASResource::AS_QUESTION = string("?"); +const string ASResource::AS_COLON = string(":"); +const string ASResource::AS_COMMA = string(","); +const string ASResource::AS_SEMICOLON = string(";"); + +const string ASResource::AS_FOREACH = string("foreach"); +const string ASResource::AS_LOCK = string("lock"); +const string ASResource::AS_UNSAFE = string("unsafe"); +const string ASResource::AS_FIXED = string("fixed"); +const string ASResource::AS_GET = string("get"); +const string ASResource::AS_SET = string("set"); +const string ASResource::AS_ADD = string("add"); +const string ASResource::AS_REMOVE = string("remove"); +const string ASResource::AS_DELEGATE = string("delegate"); +const string ASResource::AS_UNCHECKED = string("unchecked"); + +const string ASResource::AS_CONST_CAST = string("const_cast"); +const string ASResource::AS_DYNAMIC_CAST = string("dynamic_cast"); +const string ASResource::AS_REINTERPRET_CAST = string("reinterpret_cast"); +const string ASResource::AS_STATIC_CAST = string("static_cast"); + + +/** + * Sort comparison function. + * Compares the length of the value of pointers in the vectors. + * The LONGEST strings will be first in the vector. + * + * @params the string pointers to be compared. + */ +bool sortOnLength(const string *a, const string *b) +{ + return (*a).length() > (*b).length(); +} + +/** + * Sort comparison function. + * Compares the value of pointers in the vectors. + * + * @params the string pointers to be compared. + */ +bool sortOnName(const string *a, const string *b) +{ + return *a < *b; +} + +/** + * Build the vector of assignment operators. + * Used by BOTH ASFormatter.cpp and ASBeautifier.cpp + * + * @param assignmentOperators a reference to the vector to be built. + */ +void ASResource::buildAssignmentOperators(vector<const string*>* assignmentOperators) +{ + assignmentOperators->push_back(&AS_ASSIGN); + assignmentOperators->push_back(&AS_PLUS_ASSIGN); + assignmentOperators->push_back(&AS_MINUS_ASSIGN); + assignmentOperators->push_back(&AS_MULT_ASSIGN); + assignmentOperators->push_back(&AS_DIV_ASSIGN); + assignmentOperators->push_back(&AS_MOD_ASSIGN); + assignmentOperators->push_back(&AS_OR_ASSIGN); + assignmentOperators->push_back(&AS_AND_ASSIGN); + assignmentOperators->push_back(&AS_XOR_ASSIGN); + + // Java + assignmentOperators->push_back(&AS_GR_GR_GR_ASSIGN); + assignmentOperators->push_back(&AS_GR_GR_ASSIGN); + assignmentOperators->push_back(&AS_LS_LS_ASSIGN); + + // Unknown + assignmentOperators->push_back(&AS_LS_LS_LS_ASSIGN); + + sort(assignmentOperators->begin(), assignmentOperators->end(), sortOnLength); +} + +/** + * Build the vector of C++ cast operators. + * Used by ONLY ASFormatter.cpp + * + * @param castOperators a reference to the vector to be built. + */ +void ASResource::buildCastOperators(vector<const string*>* castOperators) +{ + castOperators->push_back(&AS_CONST_CAST); + castOperators->push_back(&AS_DYNAMIC_CAST); + castOperators->push_back(&AS_REINTERPRET_CAST); + castOperators->push_back(&AS_STATIC_CAST); +} + +/** + * Build the vector of header words. + * Used by BOTH ASFormatter.cpp and ASBeautifier.cpp + * + * @param headers a reference to the vector to be built. + */ +void ASResource::buildHeaders(vector<const string*>* headers, int fileType, bool beautifier) +{ + headers->push_back(&AS_IF); + headers->push_back(&AS_ELSE); + headers->push_back(&AS_FOR); + headers->push_back(&AS_WHILE); + headers->push_back(&AS_DO); + headers->push_back(&AS_SWITCH); + headers->push_back(&AS_TRY); + headers->push_back(&AS_CATCH); + + if (fileType == JAVA_TYPE) + { + headers->push_back(&AS_FINALLY); + headers->push_back(&AS_SYNCHRONIZED); + } + + if (fileType == SHARP_TYPE) + { + headers->push_back(&AS_FINALLY); + headers->push_back(&AS_FOREACH); + headers->push_back(&AS_LOCK); +// headers->push_back(&AS_UNSAFE); + headers->push_back(&AS_FIXED); + headers->push_back(&AS_GET); + headers->push_back(&AS_SET); + headers->push_back(&AS_ADD); + headers->push_back(&AS_REMOVE); + } + + if (beautifier) + { + headers->push_back(&AS_CASE); + headers->push_back(&AS_DEFAULT); + + if (fileType == C_TYPE) + { + headers->push_back(&AS_CONST); + headers->push_back(&AS_TEMPLATE); + } + + if (fileType == JAVA_TYPE) + { + headers->push_back(&AS_STATIC); // for static constructor + } + } + sort(headers->begin(), headers->end(), sortOnName); +} + +/** + * Build the vector of indentable headers. + * Used by ONLY ASBeautifier.cpp + * + * @param indentableHeaders a reference to the vector to be built. + */ +void ASResource::buildIndentableHeaders(vector<const string*>* indentableHeaders) +{ + indentableHeaders->push_back(&AS_RETURN); +// indentableHeaders->push_back(&AS_COUT); +// indentableHeaders->push_back(&AS_CERR); +// indentableHeaders->push_back(&AS_CIN); + + sort(indentableHeaders->begin(), indentableHeaders->end(), sortOnName); +} + +/** + * Build the vector of non-assignment operators. + * Used by ONLY ASBeautifier.cpp + * + * @param nonAssignmentOperators a reference to the vector to be built. + */ +void ASResource::buildNonAssignmentOperators(vector<const string*>* nonAssignmentOperators) +{ + nonAssignmentOperators->push_back(&AS_EQUAL); + nonAssignmentOperators->push_back(&AS_PLUS_PLUS); + nonAssignmentOperators->push_back(&AS_MINUS_MINUS); + nonAssignmentOperators->push_back(&AS_NOT_EQUAL); + nonAssignmentOperators->push_back(&AS_GR_EQUAL); + nonAssignmentOperators->push_back(&AS_GR_GR_GR); + nonAssignmentOperators->push_back(&AS_GR_GR); + nonAssignmentOperators->push_back(&AS_LS_EQUAL); + nonAssignmentOperators->push_back(&AS_LS_LS_LS); + nonAssignmentOperators->push_back(&AS_LS_LS); + nonAssignmentOperators->push_back(&AS_ARROW); + nonAssignmentOperators->push_back(&AS_AND); + nonAssignmentOperators->push_back(&AS_OR); + + sort(nonAssignmentOperators->begin(), nonAssignmentOperators->end(), sortOnLength); +} + +/** + * Build the vector of header non-paren headers. + * Used by BOTH ASFormatter.cpp and ASBeautifier.cpp + * + * @param nonParenHeaders a reference to the vector to be built. + */ +void ASResource::buildNonParenHeaders(vector<const string*>* nonParenHeaders, int fileType, bool beautifier) +{ + nonParenHeaders->push_back(&AS_ELSE); + nonParenHeaders->push_back(&AS_DO); + nonParenHeaders->push_back(&AS_TRY); + + if (fileType == JAVA_TYPE) + { + nonParenHeaders->push_back(&AS_FINALLY); + } + + if (fileType == SHARP_TYPE) + { + nonParenHeaders->push_back(&AS_CATCH); // can be a paren or non-paren header + nonParenHeaders->push_back(&AS_FINALLY); +// nonParenHeaders->push_back(&AS_UNSAFE); + nonParenHeaders->push_back(&AS_GET); + nonParenHeaders->push_back(&AS_SET); + nonParenHeaders->push_back(&AS_ADD); + nonParenHeaders->push_back(&AS_REMOVE); + } + + if (beautifier) + { + nonParenHeaders->push_back(&AS_CASE); + nonParenHeaders->push_back(&AS_DEFAULT); + if (fileType == C_TYPE) + { + nonParenHeaders->push_back(&AS_CONST); + nonParenHeaders->push_back(&AS_TEMPLATE); + } + if (fileType == JAVA_TYPE) + { + nonParenHeaders->push_back(&AS_STATIC); + } + } + sort(nonParenHeaders->begin(), nonParenHeaders->end(), sortOnName); +} + +/** + * Build the vector of operators. + * Used by ONLY ASFormatter.cpp + * + * @param operators a reference to the vector to be built. + */ +void ASResource::buildOperators(vector<const string*>* operators) +{ + operators->push_back(&AS_PLUS_ASSIGN); + operators->push_back(&AS_MINUS_ASSIGN); + operators->push_back(&AS_MULT_ASSIGN); + operators->push_back(&AS_DIV_ASSIGN); + operators->push_back(&AS_MOD_ASSIGN); + operators->push_back(&AS_OR_ASSIGN); + operators->push_back(&AS_AND_ASSIGN); + operators->push_back(&AS_XOR_ASSIGN); + operators->push_back(&AS_EQUAL); + operators->push_back(&AS_PLUS_PLUS); + operators->push_back(&AS_MINUS_MINUS); + operators->push_back(&AS_NOT_EQUAL); + operators->push_back(&AS_GR_EQUAL); + operators->push_back(&AS_GR_GR_GR_ASSIGN); + operators->push_back(&AS_GR_GR_ASSIGN); + operators->push_back(&AS_GR_GR_GR); + operators->push_back(&AS_GR_GR); + operators->push_back(&AS_LS_EQUAL); + operators->push_back(&AS_LS_LS_LS_ASSIGN); + operators->push_back(&AS_LS_LS_ASSIGN); + operators->push_back(&AS_LS_LS_LS); + operators->push_back(&AS_LS_LS); + operators->push_back(&AS_QUESTION_QUESTION); + operators->push_back(&AS_EQUAL_GR); + operators->push_back(&AS_GCC_MIN_ASSIGN); + operators->push_back(&AS_GCC_MAX_ASSIGN); + operators->push_back(&AS_ARROW); + operators->push_back(&AS_AND); + operators->push_back(&AS_OR); + operators->push_back(&AS_COLON_COLON); + operators->push_back(&AS_PLUS); + operators->push_back(&AS_MINUS); + operators->push_back(&AS_MULT); + operators->push_back(&AS_DIV); + operators->push_back(&AS_MOD); + operators->push_back(&AS_QUESTION); + operators->push_back(&AS_COLON); + operators->push_back(&AS_ASSIGN); + operators->push_back(&AS_LS); + operators->push_back(&AS_GR); + operators->push_back(&AS_NOT); + operators->push_back(&AS_BIT_OR); + operators->push_back(&AS_BIT_AND); + operators->push_back(&AS_BIT_NOT); + operators->push_back(&AS_BIT_XOR); + + sort(operators->begin(), operators->end(), sortOnLength); +} + +/** + * Build the vector of pre-block statements. + * Used by ONLY ASBeautifier.cpp + * NOTE: Cannot be both a header and a preBlockStatement. + * + * @param preBlockStatements a reference to the vector to be built. + */ +void ASResource::buildPreBlockStatements(vector<const string*>* preBlockStatements, int fileType) +{ + preBlockStatements->push_back(&AS_CLASS); + if (fileType == C_TYPE) + { + preBlockStatements->push_back(&AS_STRUCT); + preBlockStatements->push_back(&AS_UNION); + preBlockStatements->push_back(&AS_NAMESPACE); + } + if (fileType == JAVA_TYPE) + { + preBlockStatements->push_back(&AS_INTERFACE); + preBlockStatements->push_back(&AS_THROWS); + } + if (fileType == SHARP_TYPE) + { + preBlockStatements->push_back(&AS_INTERFACE); + preBlockStatements->push_back(&AS_NAMESPACE); + preBlockStatements->push_back(&AS_WHERE); + preBlockStatements->push_back(&AS_STRUCT); + } + sort(preBlockStatements->begin(), preBlockStatements->end(), sortOnName); +} + +/** + * Build the vector of pre-command headers. + * Used by ONLY ASFormatter.cpp + * + * @param preCommandHeaders a reference to the vector to be built. + */ +void ASResource::buildPreCommandHeaders(vector<const string*>* preCommandHeaders, int fileType) +{ + if (fileType == C_TYPE) + { + preCommandHeaders->push_back(&AS_CONST); + } + + if (fileType == JAVA_TYPE) + { + preCommandHeaders->push_back(&AS_THROWS); + } + + if (fileType == SHARP_TYPE) + { + preCommandHeaders->push_back(&AS_WHERE); + } + + sort(preCommandHeaders->begin(), preCommandHeaders->end(), sortOnName); +} + +/** + * Build the vector of pre-definition headers. + * Used by ONLY ASFormatter.cpp + * NOTE: Do NOT add 'enum' here. It is an array type bracket. + * NOTE: Do NOT add 'extern' here. Do not want an extra indent. + * + * @param preDefinitionHeaders a reference to the vector to be built. + */ +void ASResource::buildPreDefinitionHeaders(vector<const string*>* preDefinitionHeaders, int fileType) +{ + preDefinitionHeaders->push_back(&AS_CLASS); + if (fileType == C_TYPE) + { + preDefinitionHeaders->push_back(&AS_STRUCT); + preDefinitionHeaders->push_back(&AS_UNION); + preDefinitionHeaders->push_back(&AS_NAMESPACE); + } + if (fileType == JAVA_TYPE) + { + preDefinitionHeaders->push_back(&AS_INTERFACE); + } + if (fileType == SHARP_TYPE) + { + preDefinitionHeaders->push_back(&AS_STRUCT); + preDefinitionHeaders->push_back(&AS_INTERFACE); + preDefinitionHeaders->push_back(&AS_NAMESPACE); + } + sort(preDefinitionHeaders->begin(), preDefinitionHeaders->end(), sortOnName); +} + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * ASBase Funtions + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +// check if a specific line position contains a keyword. +bool ASBase::findKeyword(const string &line, int i, const string &keyword) const +{ + assert(isCharPotentialHeader(line, i)); + // check the word + const size_t keywordLength = keyword.length(); + const size_t wordEnd = i + keywordLength; + if (wordEnd > line.length()) + return false; + if (line.compare(i, keywordLength, keyword) != 0) + return false; + // check that this is not part of a longer word + if (wordEnd == line.length()) + return true; + if (isLegalNameChar(line[wordEnd])) + return false; + // is not a keyword if part of a definition + const char peekChar = peekNextChar(line, wordEnd - 1); + if (peekChar == ',' || peekChar == ')') + return false; + return true; +} + +// get the current word on a line +// index must point to the beginning of the word +string ASBase::getCurrentWord(const string& line, size_t index) const +{ + assert(isCharPotentialHeader(line, index)); + size_t lineLength = line.length(); + size_t i; + for (i = index; i < lineLength; i++) + { + if (!isLegalNameChar(line[i])) + break; + } + return line.substr(index, i - index); +} + +} // end namespace astyle diff --git a/support/highlight/src/core/astyle/ASStreamIterator.cpp b/support/highlight/src/core/astyle/ASStreamIterator.cpp new file mode 100644 index 0000000000..fe1cbee37c --- /dev/null +++ b/support/highlight/src/core/astyle/ASStreamIterator.cpp @@ -0,0 +1,167 @@ + +#include "ASStreamIterator.h" + +namespace astyle +{ + + +ASStreamIterator::ASStreamIterator(istream *in) +{ + inStream = in; + buffer.reserve(200); + eolWindows = eolLinux = eolMacOld = 0; + peekStart = 0; + prevLineDeleted = false; + checkForEmptyLine = false; +} + + +ASStreamIterator::~ASStreamIterator() +{ +} + +// save the last input line after input has reached EOF + +void ASStreamIterator::saveLastInputLine() +{ + assert(inStream->eof()); + prevBuffer = buffer; +} + +/** + * read the input stream, delete any end of line characters, + * and build a string that contains the input line. + * + * @return string containing the next input line minus any end of line characters + */ +//template<typename T> +string ASStreamIterator::nextLine(bool emptyLineWasDeleted) +{ + // verify that the current position is correct + assert (peekStart == 0); + + // a deleted line may be replaced if break-blocks is requested + // this sets up the compare to check for a replaced empty line + if (prevLineDeleted) + { + prevLineDeleted = false; + checkForEmptyLine = true; + } + if (!emptyLineWasDeleted) + prevBuffer = buffer; + else + prevLineDeleted = true; + + // read the next record + buffer.clear(); + char ch; + inStream->get(ch); + + while (!inStream->eof() && ch != '\n' && ch != '\r') + { + buffer.append(1, ch); + inStream->get(ch); + } + + if (inStream->eof()) + { + return buffer; + } + + int peekCh = inStream->peek(); + + // find input end-of-line characters + if (!inStream->eof()) + { + if (ch == '\r') // CR+LF is windows otherwise Mac OS 9 + { + if (peekCh == '\n') + { + inStream->get(ch); + eolWindows++; + } + else + eolMacOld++; + } + else // LF is Linux, allow for improbable LF/CR + { + if (peekCh == '\r') + { + inStream->get(ch); + eolWindows++; + } + else + eolLinux++; + } + } + else + { + inStream->clear(); + } + + // set output end of line characters + if (eolWindows >= eolLinux) + { + if (eolWindows >= eolMacOld) + strcpy(outputEOL, "\r\n"); // Windows (CR+LF) + else + strcpy(outputEOL, "\r"); // MacOld (CR) + } + else if (eolLinux >= eolMacOld) + strcpy(outputEOL, "\n"); // Linux (LF) + else + strcpy(outputEOL, "\r"); // MacOld (CR) + + return buffer; +} + +// save the current position and get the next line +// this can be called for multiple reads +// when finished peeking you MUST call peekReset() +// call this function from ASFormatter ONLY +//template<typename T> +string ASStreamIterator::peekNextLine() +{ + assert (hasMoreLines()); + string nextLine; + char ch; + + if (peekStart == 0) + peekStart = inStream->tellg(); + + // read the next record + inStream->get(ch); + while (!inStream->eof() && ch != '\n' && ch != '\r') + { + nextLine.append(1, ch); + inStream->get(ch); + } + + if (inStream->eof()) + { + return nextLine; + } + + int peekCh = inStream->peek(); + + // remove end-of-line characters + if (!inStream->eof()) + { + if ((peekCh == '\n' || peekCh == '\r') && peekCh != ch) ///////////// changed ////////// + inStream->get(ch); + } + + return nextLine; +} + +// reset current position and EOF for peekNextLine() +//template<typename T> +void ASStreamIterator::peekReset() +{ + assert(peekStart != 0); + inStream->clear(); + inStream->seekg(peekStart); + peekStart = 0; +} + +} diff --git a/support/highlight/src/core/astyle/ASStreamIterator.h b/support/highlight/src/core/astyle/ASStreamIterator.h new file mode 100644 index 0000000000..3065895d8a --- /dev/null +++ b/support/highlight/src/core/astyle/ASStreamIterator.h @@ -0,0 +1,101 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * + * Copyright (C) 2006-2008 by Jim Pattee <jimp03@email.com> + * Copyright (C) 1998-2002 by Tal Davidson + * <http://www.gnu.org/licenses/lgpl-3.0.html> + * + * This file is a part of Artistic Style - an indentation and + * reformatting tool for C, C++, C# and Java source files. + * <http://astyle.sourceforge.net> + * + * Artistic Style is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Artistic Style is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Artistic Style. If not, see <http://www.gnu.org/licenses/>. + * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + */ + + +#ifndef ASSTREAMITERATOR_H +#define ASSTREAMITERATOR_H + +#include "astyle.h" +#include <iostream> + +namespace astyle +{ + +class ASStreamIterator : public ASSourceIterator +{ + public: + bool checkForEmptyLine; + + // function declarations + ASStreamIterator(istream *in); + virtual ~ASStreamIterator(); + string nextLine(bool emptyLineWasDeleted); + string peekNextLine(); + void peekReset(); + void saveLastInputLine(); + + // inline functions + bool compareToInputBuffer(const string &nextLine) const { return nextLine == prevBuffer; } + const char* getOutputEOL() const { return outputEOL; } + bool hasMoreLines() const { return !inStream->eof(); } + + private: + istream * inStream; // pointer to the input stream + string buffer; // current input line + string prevBuffer; // previous input line + int eolWindows; // number of Windows line endings (CRLF) + int eolLinux; // number of Linux line endings (LF) + int eolMacOld; // number of old Mac line endings (CR) + int peekStart; // starting position for peekNextLine() + char outputEOL[4]; // output end of line char + bool prevLineDeleted; // the previous input line was deleted +}; + +/* + +// typename will be istringstream for GUI and istream otherwise +//template<typename T> +class ASStreamIterator : + public ASSourceIterator +{ + public: + // function declarations + ASStreamIterator(istream *in); + virtual ~ASStreamIterator(); + string nextLine(); + string peekNextLine(); + void peekReset(); + void saveLastInputLine(); + + // inline functions + bool compareToInputBuffer(const string &nextLine) const { return nextLine == prevBuffer; } + const char* getOutputEOL() const { return outputEOL; } + bool hasMoreLines() const { return !inStream->eof(); } + + private: + istream* inStream; // pointer to the input stream + string buffer; // current input line + string prevBuffer; // previous input line + int eolWindows; // number of Windows line endings (CRLF) + int eolLinux; // number of Linux line endings (LF) + int eolMacOld; // number of old Mac line endings (CR) + char outputEOL[4]; // output end of line char + int peekStart; // starting position for peekNextLine() +}; +*/ +} + +#endif diff --git a/support/highlight/src/core/astyle/astyle.h b/support/highlight/src/core/astyle/astyle.h new file mode 100644 index 0000000000..d3a7c3174d --- /dev/null +++ b/support/highlight/src/core/astyle/astyle.h @@ -0,0 +1,802 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * + * Copyright (C) 2006-2010 by Jim Pattee <jimp03@email.com> + * Copyright (C) 1998-2002 by Tal Davidson + * <http://www.gnu.org/licenses/lgpl-3.0.html> + * + * This file is a part of Artistic Style - an indentation and + * reformatting tool for C, C++, C# and Java source files. + * <http://astyle.sourceforge.net> + * + * Artistic Style is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Artistic Style is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Artistic Style. If not, see <http://www.gnu.org/licenses/>. + * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + */ + +#ifndef ASTYLE_H +#define ASTYLE_H + +#ifdef __VMS +#define __USE_STD_IOSTREAM 1 +#include <assert> +#else +#include <cassert> +#endif + +#include <string.h> // need both string and string.h for GCC +#include <string> +#include <vector> +#include <cctype> + +#ifdef _WIN32 +#define STDCALL __stdcall +#define EXPORT __declspec(dllexport) +#else +#define STDCALL +#define EXPORT +#endif + +#ifdef _MSC_VER +#pragma warning(disable: 4996) // secure version deprecation warnings +#pragma warning(disable: 4267) // 64 bit signed/unsigned loss of data +#endif + +#ifdef __BORLANDC__ +#pragma warn -aus // variable is assigned a value that is never used in function. +#endif + +#ifdef __INTEL_COMPILER +#pragma warning(disable: 383) // value copied to temporary, reference to temporary used +#pragma warning(disable: 444) // destructor for base class is not virtual +#pragma warning(disable: 981) // operands are evaluated in unspecified order +#endif + +using namespace std; + +namespace astyle +{ + +enum FileType { C_TYPE=0, JAVA_TYPE=1, SHARP_TYPE=2 }; + +/* The enums below are not recognized by 'vectors' in Microsoft Visual C++ + V5 when they are part of a namespace!!! Use Visual C++ V6 or higher. +*/ +enum FormatStyle { STYLE_NONE, + STYLE_ALLMAN, + STYLE_JAVA, + STYLE_KandR, + STYLE_STROUSTRUP, + STYLE_WHITESMITH, + STYLE_BANNER, + STYLE_GNU, + STYLE_LINUX, + STYLE_HORSTMANN, + STYLE_1TBS + }; + +enum BracketMode { NONE_MODE, + ATTACH_MODE, + BREAK_MODE, + LINUX_MODE, + STROUSTRUP_MODE, + HORSTMANN_MODE, + BDAC_MODE = LINUX_MODE + }; + +enum BracketType { NULL_TYPE = 0, + NAMESPACE_TYPE = 1, // also a DEFINITION_TYPE + CLASS_TYPE = 2, // also a DEFINITION_TYPE + STRUCT_TYPE = 4, // also a DEFINITION_TYPE + INTERFACE_TYPE = 8, // also a DEFINITION_TYPE + DEFINITION_TYPE = 16, + COMMAND_TYPE = 32, + ARRAY_NIS_TYPE = 64, // also an ARRAY_TYPE + ARRAY_TYPE = 128, // arrays and enums + EXTERN_TYPE = 256, // extern "C". not a command type extern + SINGLE_LINE_TYPE = 512 + }; + +enum PointerAlign { ALIGN_NONE, + ALIGN_TYPE, + ALIGN_MIDDLE, + ALIGN_NAME + }; + +enum FileEncoding { ENCODING_OK, + UTF_16BE, + UTF_16LE, + UTF_32BE, + UTF_32LE + }; + +enum LineEndFormat { LINEEND_DEFAULT, // Use line break that matches most of the file + LINEEND_WINDOWS, + LINEEND_LINUX, + LINEEND_MACOLD, + LINEEND_CRLF = LINEEND_WINDOWS, + LINEEND_LF = LINEEND_LINUX, + LINEEND_CR = LINEEND_MACOLD + }; + + +//---------------------------------------------------------------------------- +// Class ASSourceIterator +// A pure virtual class is used by ASFormatter and ASBeautifier instead of +// ASStreamIterator. This allows programs using AStyle as a plugin to define +// their own ASStreamIterator. The ASStreamIterator class must inherit +// this class. +//---------------------------------------------------------------------------- + +class ASSourceIterator +{ + public: + ASSourceIterator() {} + virtual ~ASSourceIterator() {} + virtual bool hasMoreLines() const = 0; + virtual string nextLine(bool emptyLineWasDeleted = false) = 0; + virtual string peekNextLine() = 0; + virtual void peekReset() = 0; +}; + +//---------------------------------------------------------------------------- +// Class ASResource +//---------------------------------------------------------------------------- + +class ASResource +{ + public: + void buildAssignmentOperators(vector<const string*>* assignmentOperators); + void buildCastOperators(vector<const string*>* castOperators); + void buildHeaders(vector<const string*>* headers, int fileType, bool beautifier=false); + void buildIndentableHeaders(vector<const string*>* indentableHeaders); + void buildNonAssignmentOperators(vector<const string*>* nonAssignmentOperators); + void buildNonParenHeaders(vector<const string*>* nonParenHeaders, int fileType, bool beautifier=false); + void buildOperators(vector<const string*>* operators); + void buildPreBlockStatements(vector<const string*>* preBlockStatements, int fileType); + void buildPreCommandHeaders(vector<const string*>* preCommandHeaders, int fileType); + void buildPreDefinitionHeaders(vector<const string*>* preDefinitionHeaders, int fileType); + + public: + static const string AS_IF, AS_ELSE; + static const string AS_DO, AS_WHILE; + static const string AS_FOR; + static const string AS_SWITCH, AS_CASE, AS_DEFAULT; + static const string AS_TRY, AS_CATCH, AS_THROWS, AS_FINALLY; + static const string AS_PUBLIC, AS_PROTECTED, AS_PRIVATE; + static const string AS_CLASS, AS_STRUCT, AS_UNION, AS_INTERFACE, AS_NAMESPACE; + static const string AS_EXTERN, AS_ENUM; + static const string AS_STATIC, AS_CONST, AS_WHERE, AS_NEW; + static const string AS_SYNCHRONIZED; + static const string AS_OPERATOR, AS_TEMPLATE; + static const string AS_OPEN_BRACKET, AS_CLOSE_BRACKET; + static const string AS_OPEN_LINE_COMMENT, AS_OPEN_COMMENT, AS_CLOSE_COMMENT; + static const string AS_BAR_DEFINE, AS_BAR_INCLUDE, AS_BAR_IF, AS_BAR_EL, AS_BAR_ENDIF; + static const string AS_RETURN; + static const string AS_CIN, AS_COUT, AS_CERR; + static const string AS_ASSIGN, AS_PLUS_ASSIGN, AS_MINUS_ASSIGN, AS_MULT_ASSIGN; + static const string AS_DIV_ASSIGN, AS_MOD_ASSIGN, AS_XOR_ASSIGN, AS_OR_ASSIGN, AS_AND_ASSIGN; + static const string AS_GR_GR_ASSIGN, AS_LS_LS_ASSIGN, AS_GR_GR_GR_ASSIGN, AS_LS_LS_LS_ASSIGN; + static const string AS_GCC_MIN_ASSIGN, AS_GCC_MAX_ASSIGN; + static const string AS_EQUAL, AS_PLUS_PLUS, AS_MINUS_MINUS, AS_NOT_EQUAL, AS_GR_EQUAL, AS_GR_GR_GR, AS_GR_GR; + static const string AS_LS_EQUAL, AS_LS_LS_LS, AS_LS_LS; + static const string AS_QUESTION_QUESTION, AS_EQUAL_GR; + static const string AS_ARROW, AS_AND, AS_OR; + static const string AS_COLON_COLON, AS_PAREN_PAREN, AS_BLPAREN_BLPAREN; + static const string AS_PLUS, AS_MINUS, AS_MULT, AS_DIV, AS_MOD, AS_GR, AS_LS; + static const string AS_NOT, AS_BIT_XOR, AS_BIT_OR, AS_BIT_AND, AS_BIT_NOT; + static const string AS_QUESTION, AS_COLON, AS_SEMICOLON, AS_COMMA; + static const string AS_ASM, AS__ASM__, AS_MS_ASM, AS_MS__ASM; + static const string AS_FOREACH, AS_LOCK, AS_UNSAFE, AS_FIXED; + static const string AS_GET, AS_SET, AS_ADD, AS_REMOVE; + static const string AS_DELEGATE, AS_UNCHECKED; + static const string AS_CONST_CAST, AS_DYNAMIC_CAST, AS_REINTERPRET_CAST, AS_STATIC_CAST; +}; // Class ASResource + +//---------------------------------------------------------------------------- +// Class ASBase +//---------------------------------------------------------------------------- + +class ASBase +{ + private: + // all variables should be set by the "init" function + int baseFileType; // a value from enum FileType + + protected: + ASBase() { baseFileType = C_TYPE; } + ~ASBase() {} + + // functions definitions are at the end of ASResource.cpp + bool findKeyword(const string &line, int i, const string &keyword) const; + string getCurrentWord(const string& line, size_t index) const; + + protected: + + void init(int fileTypeArg) { baseFileType = fileTypeArg; } + bool isCStyle() const { return (baseFileType == C_TYPE); } + bool isJavaStyle() const { return (baseFileType == JAVA_TYPE); } + bool isSharpStyle() const { return (baseFileType == SHARP_TYPE); } + + // check if a specific character can be used in a legal variable/method/class name + bool isLegalNameChar(char ch) const { + if (isWhiteSpace(ch)) return false; + if ((unsigned) ch > 127) return false; + return (isalnum(ch) + || ch == '.' || ch == '_' + || (isJavaStyle() && ch == '$') + || (isSharpStyle() && ch == '@')); // may be used as a prefix + } + + // check if a specific character can be part of a header + bool isCharPotentialHeader(const string &line, size_t i) const { + assert(!isWhiteSpace(line[i])); + char prevCh = ' '; + if (i > 0) prevCh = line[i-1]; + if (!isLegalNameChar(prevCh) && isLegalNameChar(line[i])) + return true; + return false; + } + + // check if a specific character can be part of an operator + bool isCharPotentialOperator(char ch) const { + assert(!isWhiteSpace(ch)); + if ((unsigned) ch > 127) return false; + return (ispunct(ch) + && ch != '{' && ch != '}' + && ch != '(' && ch != ')' + && ch != '[' && ch != ']' + && ch != ';' && ch != ',' + && ch != '#' && ch != '\\' + && ch != '\'' && ch != '\"'); + } + + // check if a specific character is a whitespace character + bool isWhiteSpace(char ch) const { return (ch == ' ' || ch == '\t'); } + + // peek at the next unread character. + char peekNextChar(const string &line, int i) const { + char ch = ' '; + size_t peekNum = line.find_first_not_of(" \t", i + 1); + if (peekNum == string::npos) + return ch; + ch = line[peekNum]; + return ch; + } +}; // Class ASBase + +//---------------------------------------------------------------------------- +// Class ASBeautifier +//---------------------------------------------------------------------------- + +class ASBeautifier : protected ASResource, protected ASBase +{ + public: + ASBeautifier(); + virtual ~ASBeautifier(); + virtual void init(ASSourceIterator* iter); + void init(); + virtual bool hasMoreLines() const; + virtual string nextLine(); + virtual string beautify(const string &line); + void deleteVector(vector<const string*>*& container); + void initVector(vector<const string*>*& container); + void setTabIndentation(int length = 4, bool forceTabs = false); + void setSpaceIndentation(int length = 4); + void setMaxInStatementIndentLength(int max); + void setMinConditionalIndentLength(int min); + void setIndentManuallySet(bool state); + void setMinConditionalManuallySet(bool state); + void setModeManuallySet(bool state); + void setClassIndent(bool state); + void setSwitchIndent(bool state); + void setCaseIndent(bool state); + void setBracketIndent(bool state); + void setBlockIndent(bool state); + void setNamespaceIndent(bool state); + void setLabelIndent(bool state); + void setCStyle(); + void setJavaStyle(); + void setSharpStyle(); + void setEmptyLineFill(bool state); + void setPreprocessorIndent(bool state); + int getFileType(); + int getIndentLength(void); + string getIndentString(void); + bool getBracketIndent(void); + bool getBlockIndent(void); + bool getCaseIndent(void); + bool getClassIndent(void); + bool getEmptyLineFill(void); + bool getForceTabIndentation(void); + bool getIndentManuallySet(void); + bool getMinConditionalManuallySet(void); + bool getModeManuallySet(void); + bool getSwitchIndent(void); + + protected: + void deleteStaticVectors(); + const string* findHeader(const string &line, int i, + const vector<const string*>* possibleHeaders) const; + const string* findOperator(const string &line, int i, + const vector<const string*>* possibleOperators) const; + int getNextProgramCharDistance(const string &line, int i) const; + int indexOf(vector<const string*> &container, const string *element); + string trim(const string &str); + + // variables set by ASFormatter - must be updated in activeBeautifierStack + int inLineNumber; + int horstmannIndentInStatement; + int nonInStatementBracket; + bool lineCommentNoBeautify; + bool isNonInStatementArray; + bool isSharpAccessor; + bool isSharpDelegate; + bool isInExtern; + bool isInBeautifySQL; + bool isInIndentableStruct; + + private: + ASBeautifier(const ASBeautifier ©); + ASBeautifier& operator=(ASBeautifier&); // not to be implemented + + void initStatic(); + void registerInStatementIndent(const string &line, int i, int spaceTabCount, + int tabIncrementIn, int minIndent, bool updateParenStack); + string preLineWS(int spaceTabCount, int tabCount); + + static int beautifierFileType; + static vector<const string*>* headers; + static vector<const string*>* nonParenHeaders; + static vector<const string*>* preBlockStatements; + static vector<const string*>* assignmentOperators; + static vector<const string*>* nonAssignmentOperators; + static vector<const string*>* indentableHeaders; + + ASSourceIterator *sourceIterator; + vector<ASBeautifier*> *waitingBeautifierStack; + vector<ASBeautifier*> *activeBeautifierStack; + vector<int> *waitingBeautifierStackLengthStack; + vector<int> *activeBeautifierStackLengthStack; + vector<const string*> *headerStack; + vector< vector<const string*>* > *tempStacks; + vector<int> *blockParenDepthStack; + vector<bool> *blockStatementStack; + vector<bool> *parenStatementStack; + vector<bool> *bracketBlockStateStack; + vector<int> *inStatementIndentStack; + vector<int> *inStatementIndentStackSizeStack; + vector<int> *parenIndentStack; + int convertTabToSpaces(int i, int tabIncrementIn) const; + int getInStatementIndentAssign(const string& line, size_t currPos) const; + int getInStatementIndentComma(const string& line, size_t currPos) const; + bool isClassAccessModifier(string& line) const; + bool isLineEndComment(string& line, int startPos) const; + bool statementEndsWithComma(string &line, int index); + vector<vector<const string*>*>* copyTempStacks(const ASBeautifier &other) const; + template<typename T> void deleteContainer(T &container); + void deleteContainer(vector<vector<const string*>*>* &container); + template<typename T> void initContainer(T &container, T value); + + private: // variables + string indentString; + const string *currentHeader; + const string *previousLastLineHeader; + const string *probationHeader; + bool isInQuote; + bool isInVerbatimQuote; + bool haveLineContinuationChar; + bool isInAsm; + bool isInAsmOneLine; + bool isInAsmBlock; + bool isInComment; + bool isInHorstmannComment; + bool isInCase; + bool isInQuestion; + bool isInStatement; + bool isInHeader; + bool isInTemplate; + bool isInDefine; + bool isInDefineDefinition; + bool classIndent; + bool isInClassInitializer; + bool isInClassHeaderTab; + bool isInEnum; + bool switchIndent; + bool caseIndent; + bool namespaceIndent; + bool bracketIndent; + bool blockIndent; + bool labelIndent; + bool preprocessorIndent; + bool isInConditional; + bool isIndentManuallySet; + bool isMinConditionalManuallySet; + bool isModeManuallySet; + bool shouldForceTabIndentation; + bool emptyLineFill; + bool backslashEndsPrevLine; + bool lineOpensComment; + bool blockCommentNoIndent; + bool blockCommentNoBeautify; + bool previousLineProbationTab; + int fileType; + int minConditionalIndent; + int parenDepth; + int indentLength; + int blockTabCount; + int maxInStatementIndent; + int classInitializerTabs; + int templateDepth; + int prevFinalLineSpaceTabCount; + int prevFinalLineTabCount; + int defineTabCount; + char quoteChar; + char prevNonSpaceCh; + char currentNonSpaceCh; + char currentNonLegalCh; + char prevNonLegalCh; +}; // Class ASBeautifier + +//---------------------------------------------------------------------------- +// Class ASEnhancer +//---------------------------------------------------------------------------- + +class ASEnhancer : protected ASBase +{ + public: // functions + ASEnhancer(); + ~ASEnhancer(); + void init(int, int, string, bool, bool); + void enhance(string &line, bool isInSQL); + + private: + // options from command line or options file + int indentLength; + bool useTabs; + bool caseIndent; + bool emptyLineFill; + + // parsing variables + int lineNumber; + bool isInQuote; + bool isInComment; + char quoteChar; + + // unindent variables + int bracketCount; + int switchDepth; + bool lookingForCaseBracket; + bool unindentNextLine; + + // struct used by ParseFormattedLine function + // contains variables used to unindent the case blocks + struct switchVariables { + int switchBracketCount; + int unindentDepth; + bool unindentCase; + }; + + switchVariables sw; // switch variables struct + vector<switchVariables> swVector; // stack vector of switch variables + + // event table variables + bool nextLineIsEventIndent; // begin event table indent is reached + bool isInEventTable; // need to indent an event table + + // SQL variables + bool nextLineIsDeclareIndent; // begin declare section indent is reached + bool isInDeclareSection; // need to indent a declare section + + + private: // functions + size_t findCaseColon(string &line, size_t caseIndex) const; + int indentLine(string &line, int indent) const; + bool isBeginDeclareSectionSQL(string &line, size_t index) const; + bool isEndDeclareSectionSQL(string &line, size_t index) const; + size_t processSwitchBlock(string &line, size_t index); + int unindentLine(string &line, int unindent) const; +}; // Class ASEnhancer + +//---------------------------------------------------------------------------- +// Class ASFormatter +//---------------------------------------------------------------------------- + +class ASFormatter : public ASBeautifier +{ + public: // functions + ASFormatter(); + virtual ~ASFormatter(); + virtual void init(ASSourceIterator* iter); + virtual bool hasMoreLines() const; + virtual string nextLine(); + LineEndFormat getLineEndFormat() const; + void setFormattingStyle(FormatStyle style); + void setAddBracketsMode(bool state); + void setAddOneLineBracketsMode(bool state); + void setBracketFormatMode(BracketMode mode); + void setBreakClosingHeaderBracketsMode(bool state); + void setBreakBlocksMode(bool state); + void setBreakClosingHeaderBlocksMode(bool state); + void setBreakElseIfsMode(bool state); + void setBreakOneLineBlocksMode(bool state); + void setDeleteEmptyLinesMode(bool state); + void setIndentCol1CommentsMode(bool state); + void setLineEndFormat(LineEndFormat fmt); + void setOperatorPaddingMode(bool mode); + void setParensOutsidePaddingMode(bool mode); + void setParensInsidePaddingMode(bool mode); + void setParensHeaderPaddingMode(bool mode); + void setParensUnPaddingMode(bool state); + void setPointerAlignment(PointerAlign alignment); + void setSingleStatementsMode(bool state); + void setTabSpaceConversionMode(bool state); + + private: // functions + void ASformatter(ASFormatter ©); // not to be imlpemented + ASFormatter& operator=(ASFormatter&); // not to be implemented + template<typename T> void deleteContainer(T &container); + template<typename T> void initContainer(T &container, T value); + char peekNextChar() const; + BracketType getBracketType(); + bool addBracketsToStatement(); + bool commentAndHeaderFollows() const; + bool getNextChar(); + bool getNextLine(bool emptyLineWasDeleted = false); + bool isBeforeComment() const; + bool isBeforeAnyComment() const; + bool isBeforeAnyLineEndComment(int startPos) const; + bool isBeforeMultipleLineEndComments(int startPos) const; + bool isBracketType(BracketType a, BracketType b) const; + bool isCurrentBracketBroken() const; + bool isDereferenceOrAddressOf() const; + bool isExecSQL(string &line, size_t index) const; + bool isEmptyLine(const string &line) const; + bool isNextWordSharpNonParenHeader(int startChar) const; + bool isNonInStatementArrayBracket() const; + bool isPointerOrReference() const; + bool isPointerOrReferenceCentered() const; + bool isSharpStyleWithParen(const string* header) const; + bool isStructAccessModified(string &firstLine, size_t index) const; + bool isUnaryOperator() const; + bool isInExponent() const; + bool isOneLineBlockReached(string& line, int startChar) const; + bool isNextCharOpeningBracket(int startChar) const; + bool isOkToBreakBlock(BracketType bracketType) const; + int getCurrentLineCommentAdjustment(); + int getNextLineCommentAdjustment(); + void appendCharInsideComments(); + void appendSequence(const string &sequence, bool canBreakLine = true); + void appendSpacePad(); + void appendSpaceAfter(); + void breakLine(); + void buildLanguageVectors(); + void checkForFollowingHeader(const string& firstLine); + void convertTabToSpaces(); + void deleteContainer(vector<BracketType>* &container); + void formatArrayRunIn(); + void formatRunIn(); + void goForward(int i); + void initContainer(vector<BracketType>* &container, vector<BracketType>* value); + void initNewLine(); + void padOperators(const string *newOperator); + void padParens(); + void formatArrayBrackets(BracketType bracketType, bool isOpeningArrayBracket); + void formatClosingBracket(BracketType bracketType); + void formatCommentBody(); + void formatCommentOpener(); + void formatLineCommentBody(); + void formatLineCommentOpener(); + void formatOpeningBracket(BracketType bracketType); + void formatQuoteBody(); + void formatQuoteOpener(); + void formatPointerOrReference(); + void formatPointerOrReferenceCast(); + void adjustComments(); + void isLineBreakBeforeClosingHeader(); + void setBreakBlocksVariables(); + void fixOptionVariableConflicts(); + void processPreprocessor(); + void trimContinuationLine(); + size_t findNextChar(string& line, char searchChar, int searchStart = 0); + string getPreviousWord(const string& line, int currPos) const; + string peekNextText(const string& firstLine, bool endOnEmptyLine=false) const; + + private: // variables + static int formatterFileType; + static vector<const string*>* headers; + static vector<const string*>* nonParenHeaders; + static vector<const string*>* preDefinitionHeaders; + static vector<const string*>* preCommandHeaders; + static vector<const string*>* operators; + static vector<const string*>* assignmentOperators; + static vector<const string*>* castOperators; + + ASSourceIterator *sourceIterator; + ASEnhancer *enhancer; + + vector<const string*> *preBracketHeaderStack; + vector<BracketType> *bracketTypeStack; + vector<int> *parenStack; + vector<bool> *structStack; + string readyFormattedLine; + string currentLine; + string formattedLine; + const string *currentHeader; + const string *previousOperator; // used ONLY by pad-oper + char currentChar; + char previousChar; + char previousNonWSChar; + char previousCommandChar; + char quoteChar; + int charNum; + int preprocBracketTypeStackSize; + int tabIncrementIn; + int spacePadNum; + int nextLineSpacePadNum; + int templateDepth; + int traceLineNumber; + int horstmannIndentChars; + size_t leadingSpaces; + size_t formattedLineCommentNum; // comment location on formattedLine + size_t currentLineFirstBracketNum; // first bracket location on currentLine + size_t previousReadyFormattedLineLength; + FormatStyle formattingStyle; + BracketMode bracketFormatMode; + BracketType previousBracketType; + PointerAlign pointerAlignment; + LineEndFormat lineEnd; + bool isVirgin; + bool shouldPadOperators; + bool shouldPadParensOutside; + bool shouldPadParensInside; + bool shouldPadHeader; + bool shouldUnPadParens; + bool shouldConvertTabs; + bool shouldIndentCol1Comments; + bool isInLineComment; + bool isInComment; + bool noTrimCommentContinuation; + bool isInPreprocessor; + bool isInTemplate; + bool doesLineStartComment; + bool lineEndsInCommentOnly; + bool lineIsLineCommentOnly; + bool lineIsEmpty; + bool isImmediatelyPostCommentOnly; + bool isImmediatelyPostEmptyLine; + bool isInQuote; + bool isInVerbatimQuote; + bool haveLineContinuationChar; + bool isInQuoteContinuation; + bool isInBlParen; + bool isSpecialChar; + bool isNonParenHeader; + bool foundQuestionMark; + bool foundPreDefinitionHeader; + bool foundNamespaceHeader; + bool foundClassHeader; + bool foundStructHeader; + bool foundInterfaceHeader; + bool foundPreCommandHeader; + bool foundCastOperator; + bool isInLineBreak; + bool endOfCodeReached; + bool lineCommentNoIndent; + bool isInExecSQL; + bool isInAsm; + bool isInAsmOneLine; + bool isInAsmBlock; + bool isLineReady; + bool isPreviousBracketBlockRelated; + bool isInPotentialCalculation; + bool isCharImmediatelyPostComment; + bool isPreviousCharPostComment; + bool isCharImmediatelyPostLineComment; + bool isCharImmediatelyPostOpenBlock; + bool isCharImmediatelyPostCloseBlock; + bool isCharImmediatelyPostTemplate; + bool isCharImmediatelyPostReturn; + bool isCharImmediatelyPostOperator; + bool breakCurrentOneLineBlock; + bool isInHorstmannRunIn; + bool currentLineBeginsWithBracket; + bool shouldBreakOneLineBlocks; + bool shouldReparseCurrentChar; + bool shouldBreakOneLineStatements; + bool shouldBreakClosingHeaderBrackets; + bool shouldBreakElseIfs; + bool shouldAddBrackets; + bool shouldAddOneLineBrackets; + bool shouldDeleteEmptyLines; + bool needHeaderOpeningBracket; + bool shouldBreakLineAtNextChar; + bool passedSemicolon; + bool passedColon; + bool clearNonInStatement; + bool isImmediatelyPostComment; + bool isImmediatelyPostLineComment; + bool isImmediatelyPostEmptyBlock; + bool isImmediatelyPostPreprocessor; + bool isImmediatelyPostReturn; + bool isImmediatelyPostOperator; + + bool shouldBreakBlocks; + bool shouldBreakClosingHeaderBlocks; + bool isPrependPostBlockEmptyLineRequested; + bool isAppendPostBlockEmptyLineRequested; + + bool prependEmptyLine; + bool appendOpeningBracket; + bool foundClosingHeader; + + bool isInHeader; + bool isImmediatelyPostHeader; + bool isInCase; + bool isJavaStaticConstructor; + + private: // inline functions + // append a character to the current formatted line. + void appendChar(char ch, bool canBreakLine) { + if (canBreakLine && isInLineBreak) + breakLine(); + formattedLine.append(1, ch); + isImmediatelyPostCommentOnly = false; + } + + // append the CURRENT character (curentChar) to the current formatted line. + void appendCurrentChar(bool canBreakLine = true) { + appendChar(currentChar, canBreakLine); + } + + // check if a specific sequence exists in the current placement of the current line + bool isSequenceReached(const char *sequence) const { + return currentLine.compare(charNum, strlen(sequence), sequence) == 0; + } + + // call ASBase::findHeader for the current character + const string *findHeader(const vector<const string*>* headers) { + return ASBeautifier::findHeader(currentLine, charNum, headers); + } + + // call ASBase::findOperator for the current character + const string *findOperator(const vector<const string*>* headers) { + return ASBeautifier::findOperator(currentLine, charNum, headers); + } +}; // Class ASFormatter + + +//---------------------------------------------------------------------------- +// astyle namespace global declarations +//---------------------------------------------------------------------------- +// sort comparison functions for ASResource +bool sortOnLength(const string *a, const string *b); +bool sortOnName(const string *a, const string *b); + +} // end of astyle namespace + +// end of astyle namespace -------------------------------------------------- + + +//---------------------------------------------------------------------------- +// declarations for library build +// global because they are called externally and are NOT part of the namespace +//---------------------------------------------------------------------------- + +typedef void (STDCALL *fpError)(int, char*); // pointer to callback error handler +typedef char* (STDCALL *fpAlloc)(unsigned long); // pointer to callback memory allocation +extern "C" EXPORT char* STDCALL AStyleMain(const char*, const char*, fpError, fpAlloc); +extern "C" EXPORT const char* STDCALL AStyleGetVersion (void); + + +#endif // closes ASTYLE_H diff --git a/support/highlight/src/core/astyle/astyle_main.cpp b/support/highlight/src/core/astyle/astyle_main.cpp new file mode 100644 index 0000000000..5b8a0b7e3a --- /dev/null +++ b/support/highlight/src/core/astyle/astyle_main.cpp @@ -0,0 +1,2535 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * + * Copyright (C) 2006-2010 by Jim Pattee <jimp03@email.com> + * Copyright (C) 1998-2002 by Tal Davidson + * <http://www.gnu.org/licenses/lgpl-3.0.html> + * + * This file is a part of Artistic Style - an indentation and + * reformatting tool for C, C++, C# and Java source files. + * <http://astyle.sourceforge.net> + * + * Artistic Style is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Artistic Style is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Artistic Style. If not, see <http://www.gnu.org/licenses/>. + * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + */ + +#include "astyle_main.h" + +#include <algorithm> +#include <iostream> +#include <fstream> +#include <sstream> +#include <cstdlib> +#include <errno.h> + +// includes for recursive getFileNames() function +#ifdef _WIN32 +#undef UNICODE // use ASCII windows functions +#include <windows.h> +#else +#include <dirent.h> +#include <sys/stat.h> +#ifdef __VMS +#include <unixlib.h> +#include <rms.h> +#include <ssdef.h> +#include <stsdef.h> +#include <lib$routines.h> +#include <starlet.h> +#endif /* __VMS */ +#endif + +// turn off MinGW automatic file globbing +// this CANNOT be in the astyle namespace +int _CRT_glob = 0; + +namespace astyle +{ + +#define IS_OPTION(arg,op) ((arg).compare(op)==0) +#define IS_OPTIONS(arg,a,b) (IS_OPTION((arg),(a)) || IS_OPTION((arg),(b))) + +#define GET_PARAM(arg,op) ((arg).substr(strlen(op))) +#define GET_PARAMS(arg,a,b) (isParamOption((arg),(a)) ? GET_PARAM((arg),(a)) : GET_PARAM((arg),(b))) + +#ifdef _WIN32 +char g_fileSeparator = '\\'; +bool g_isCaseSensitive = false; +#else +char g_fileSeparator = '/'; +bool g_isCaseSensitive = true; +#endif + +#ifdef ASTYLE_LIB +// library build variables +stringstream* _err = NULL; +#else +// console build variables +ostream* _err = &cerr; // direct error messages to cerr +ASConsole* g_console = NULL; // class to encapsulate console variables +#endif + +#ifdef ASTYLE_JNI +// java library build variables +JNIEnv* g_env; +jobject g_obj; +jmethodID g_mid; +#endif + +const char* _version = "1.24"; + + +/** + * parse the options vector + * ITER can be either a fileOptionsVector (options file) or an optionsVector (command line) + * + * @return true if no errors, false if errors + */ +template<typename ITER> +bool parseOptions(ASFormatter &formatter, + const ITER &optionsBegin, + const ITER &optionsEnd, + const string &errorInfo) +{ + ITER option; + bool ok = true; + string arg, subArg; + + for (option = optionsBegin; option != optionsEnd; ++option) + { + arg = *option; + + if (arg.compare(0, 2, "--") == 0) + ok &= parseOption(formatter, arg.substr(2), errorInfo); + else if (arg[0] == '-') + { + size_t i; + + for (i = 1; i < arg.length(); ++i) + { + if (isalpha(arg[i]) && i > 1) + { + ok &= parseOption(formatter, subArg, errorInfo); + subArg = ""; + } + subArg.append(1, arg[i]); + } + ok &= parseOption(formatter, subArg, errorInfo); + subArg = ""; + } + else + { + ok &= parseOption(formatter, arg, errorInfo); + subArg = ""; + } + } + return ok; +} + +void importOptions(istream &in, vector<string> &optionsVector) +{ + char ch; + string currentToken; + + while (in) + { + currentToken = ""; + do + { + in.get(ch); + if (in.eof()) + break; + // treat '#' as line comments + if (ch == '#') + while (in) + { + in.get(ch); + if (ch == '\n') + break; + } + + // break options on spaces, tabs, commas, or new-lines + if (in.eof() || ch == ' ' || ch == '\t' || ch == ',' || ch == '\n') + break; + else + currentToken.append(1, ch); + + } + while (in); + + if (currentToken.length() != 0) + optionsVector.push_back(currentToken); + } +} + +void isOptionError(const string &arg, const string &errorInfo) +{ +#ifdef ASTYLE_LIB + if (_err->str().length() == 0) + { + (*_err) << errorInfo << endl; // need main error message + (*_err) << arg; // output the option in error + } + else + (*_err) << endl << arg; // put endl after previous option +#else + if (errorInfo.length() > 0) // to avoid a compiler warning + g_console->error("Error in param: ", arg.c_str()); +#endif +} + + +bool isParamOption(const string &arg, const char *option) +{ + bool retVal = arg.compare(0, strlen(option), option) == 0; + // if comparing for short option, 2nd char of arg must be numeric + if (retVal && strlen(option) == 1 && arg.length() > 1) + if (!isdigit(arg[1])) + retVal = false; + return retVal; +} + +bool isParamOption(const string &arg, const char *option1, const char *option2) +{ + return isParamOption(arg, option1) || isParamOption(arg, option2); +} + +bool parseOption(ASFormatter &formatter, const string &arg, const string &errorInfo) +{ + if ( IS_OPTION(arg, "style=allman") || IS_OPTION(arg, "style=ansi") || IS_OPTION(arg, "style=bsd") ) + { + formatter.setFormattingStyle(STYLE_ALLMAN); + } + else if ( IS_OPTION(arg, "style=java") ) + { + formatter.setFormattingStyle(STYLE_JAVA); + } + else if ( IS_OPTION(arg, "style=k&r") || IS_OPTION(arg, "style=k/r") ) + { + formatter.setFormattingStyle(STYLE_KandR); + } + else if ( IS_OPTION(arg, "style=stroustrup") ) + { + formatter.setFormattingStyle(STYLE_STROUSTRUP); + } + else if ( IS_OPTION(arg, "style=whitesmith") ) + { + formatter.setFormattingStyle(STYLE_WHITESMITH); + } + else if ( IS_OPTION(arg, "style=banner") ) + { + formatter.setFormattingStyle(STYLE_BANNER); + } + else if ( IS_OPTION(arg, "style=gnu") ) + { + formatter.setFormattingStyle(STYLE_GNU); + } + else if ( IS_OPTION(arg, "style=linux") ) + { + formatter.setFormattingStyle(STYLE_LINUX); + } + else if ( IS_OPTION(arg, "style=horstmann") ) + { + formatter.setFormattingStyle(STYLE_HORSTMANN); + } + else if ( IS_OPTION(arg, "style=1tbs") || IS_OPTION(arg, "style=otbs") ) + { + formatter.setFormattingStyle(STYLE_1TBS); + } + else if ( isParamOption(arg, "A") ) + { + int style = 0; + string styleParam = GET_PARAM(arg, "A"); + if (styleParam.length() > 0) + style = atoi(styleParam.c_str()); + if (style < 1 || style > 10) + isOptionError(arg, errorInfo); + else if (style == 1) + formatter.setFormattingStyle(STYLE_ALLMAN); + else if (style == 2) + formatter.setFormattingStyle(STYLE_JAVA); + else if (style == 3) + formatter.setFormattingStyle(STYLE_KandR); + else if (style == 4) + formatter.setFormattingStyle(STYLE_STROUSTRUP); + else if (style == 5) + formatter.setFormattingStyle(STYLE_WHITESMITH); + else if (style == 6) + formatter.setFormattingStyle(STYLE_BANNER); + else if (style == 7) + formatter.setFormattingStyle(STYLE_GNU); + else if (style == 8) + formatter.setFormattingStyle(STYLE_LINUX); + else if (style == 9) + formatter.setFormattingStyle(STYLE_HORSTMANN); + else if (style == 10) + formatter.setFormattingStyle(STYLE_1TBS); + } + // must check for mode=cs before mode=c !!! + else if ( IS_OPTION(arg, "mode=cs") ) + { + formatter.setSharpStyle(); + formatter.setModeManuallySet(true); + } + else if ( IS_OPTION(arg, "mode=c") ) + { + formatter.setCStyle(); + formatter.setModeManuallySet(true); + } + else if ( IS_OPTION(arg, "mode=java") ) + { + formatter.setJavaStyle(); + formatter.setModeManuallySet(true); + } + else if ( isParamOption(arg, "t", "indent=tab=") ) + { + int spaceNum = 4; + string spaceNumParam = GET_PARAMS(arg, "t", "indent=tab="); + if (spaceNumParam.length() > 0) + spaceNum = atoi(spaceNumParam.c_str()); + if (spaceNum < 2 || spaceNum > 20) + isOptionError(arg, errorInfo); + else + { + formatter.setTabIndentation(spaceNum, false); + formatter.setIndentManuallySet(true); + } + } + else if ( IS_OPTION(arg, "indent=tab") ) + { + formatter.setTabIndentation(4); + // do NOT call setIndentManuallySet(true); + } + else if ( isParamOption(arg, "T", "indent=force-tab=") ) + { + int spaceNum = 4; + string spaceNumParam = GET_PARAMS(arg, "T", "indent=force-tab="); + if (spaceNumParam.length() > 0) + spaceNum = atoi(spaceNumParam.c_str()); + if (spaceNum < 2 || spaceNum > 20) + isOptionError(arg, errorInfo); + else + { + formatter.setTabIndentation(spaceNum, true); + formatter.setIndentManuallySet(true); + } + } + else if ( IS_OPTION(arg, "indent=force-tab") ) + { + formatter.setTabIndentation(4, true); + // do NOT call setIndentManuallySet(true); + } + else if ( isParamOption(arg, "s", "indent=spaces=") ) + { + int spaceNum = 4; + string spaceNumParam = GET_PARAMS(arg, "s", "indent=spaces="); + if (spaceNumParam.length() > 0) + spaceNum = atoi(spaceNumParam.c_str()); + if (spaceNum < 2 || spaceNum > 20) + isOptionError(arg, errorInfo); + else + { + formatter.setSpaceIndentation(spaceNum); + formatter.setIndentManuallySet(true); + } + } + else if ( IS_OPTION(arg, "indent=spaces") ) + { + formatter.setSpaceIndentation(4); + // do NOT call setIndentManuallySet(true); + } + else if ( isParamOption(arg, "m", "min-conditional-indent=") ) + { + int minIndent = 8; + string minIndentParam = GET_PARAMS(arg, "m", "min-conditional-indent="); + if (minIndentParam.length() > 0) + minIndent = atoi(minIndentParam.c_str()); + if (minIndent > 40) + isOptionError(arg, errorInfo); + else + { + formatter.setMinConditionalIndentLength(minIndent); + formatter.setMinConditionalManuallySet(true); + } + } + else if ( isParamOption(arg, "M", "max-instatement-indent=") ) + { + int maxIndent = 40; + string maxIndentParam = GET_PARAMS(arg, "M", "max-instatement-indent="); + if (maxIndentParam.length() > 0) + maxIndent = atoi(maxIndentParam.c_str()); + if (maxIndent > 80) + isOptionError(arg, errorInfo); + else + formatter.setMaxInStatementIndentLength(maxIndent); + } + else if ( IS_OPTIONS(arg, "B", "indent-brackets") ) + { + formatter.setBracketIndent(true); + } + else if ( IS_OPTIONS(arg, "G", "indent-blocks") ) + { + formatter.setBlockIndent(true); + } + else if ( IS_OPTIONS(arg, "N", "indent-namespaces") ) + { + formatter.setNamespaceIndent(true); + } + else if ( IS_OPTIONS(arg, "C", "indent-classes") ) + { + formatter.setClassIndent(true); + } + else if ( IS_OPTIONS(arg, "S", "indent-switches") ) + { + formatter.setSwitchIndent(true); + } + else if ( IS_OPTIONS(arg, "K", "indent-cases") ) + { + formatter.setCaseIndent(true); + } + else if ( IS_OPTIONS(arg, "L", "indent-labels") ) + { + formatter.setLabelIndent(true); + } + else if ( IS_OPTIONS(arg, "y", "break-closing-brackets") ) + { + formatter.setBreakClosingHeaderBracketsMode(true); + } + else if ( IS_OPTIONS(arg, "b", "brackets=break") ) + { + formatter.setBracketFormatMode(BREAK_MODE); + } + else if ( IS_OPTIONS(arg, "a", "brackets=attach") ) + { + formatter.setBracketFormatMode(ATTACH_MODE); + } + else if ( IS_OPTIONS(arg, "l", "brackets=linux") ) + { + formatter.setBracketFormatMode(LINUX_MODE); + } + else if ( IS_OPTIONS(arg, "u", "brackets=stroustrup") ) + { + formatter.setBracketFormatMode(STROUSTRUP_MODE); + } + else if ( IS_OPTIONS(arg, "g", "brackets=horstmann") ) + { + formatter.setBracketFormatMode(HORSTMANN_MODE); + } + else if ( IS_OPTIONS(arg, "O", "keep-one-line-blocks") ) + { + formatter.setBreakOneLineBlocksMode(false); + } + else if ( IS_OPTIONS(arg, "o", "keep-one-line-statements") ) + { + formatter.setSingleStatementsMode(false); + } + else if ( IS_OPTIONS(arg, "P", "pad-paren") ) + { + formatter.setParensOutsidePaddingMode(true); + formatter.setParensInsidePaddingMode(true); + } + else if ( IS_OPTIONS(arg, "d", "pad-paren-out") ) + { + formatter.setParensOutsidePaddingMode(true); + } + else if ( IS_OPTIONS(arg, "D", "pad-paren-in") ) + { + formatter.setParensInsidePaddingMode(true); + } + else if ( IS_OPTIONS(arg, "H", "pad-header") ) + { + formatter.setParensHeaderPaddingMode(true); + } + else if ( IS_OPTIONS(arg, "U", "unpad-paren") ) + { + formatter.setParensUnPaddingMode(true); + } + else if ( IS_OPTIONS(arg, "p", "pad-oper") ) + { + formatter.setOperatorPaddingMode(true); + } + else if ( IS_OPTIONS(arg, "x", "delete-empty-lines") ) + { + formatter.setDeleteEmptyLinesMode(true); + } + else if ( IS_OPTIONS(arg, "E", "fill-empty-lines") ) + { + formatter.setEmptyLineFill(true); + } + else if ( IS_OPTIONS(arg, "w", "indent-preprocessor") ) + { + formatter.setPreprocessorIndent(true); + } + else if ( IS_OPTIONS(arg, "c", "convert-tabs") ) + { + formatter.setTabSpaceConversionMode(true); + } + else if ( IS_OPTIONS(arg, "F", "break-blocks=all") ) + { + formatter.setBreakBlocksMode(true); + formatter.setBreakClosingHeaderBlocksMode(true); + } + else if ( IS_OPTIONS(arg, "f", "break-blocks") ) + { + formatter.setBreakBlocksMode(true); + } + else if ( IS_OPTIONS(arg, "e", "break-elseifs") ) + { + formatter.setBreakElseIfsMode(true); + } + else if ( IS_OPTIONS(arg, "j", "add-brackets") ) + { + formatter.setAddBracketsMode(true); + } + else if ( IS_OPTIONS(arg, "J", "add-one-line-brackets") ) + { + formatter.setAddOneLineBracketsMode(true); + } + else if ( IS_OPTIONS(arg, "Y", "indent-col1-comments") ) + { + formatter.setIndentCol1CommentsMode(true); + } + else if ( IS_OPTION(arg, "align-pointer=type") ) + { + formatter.setPointerAlignment(ALIGN_TYPE); + } + else if ( IS_OPTION(arg, "align-pointer=middle") ) + { + formatter.setPointerAlignment(ALIGN_MIDDLE); + } + else if ( IS_OPTION(arg, "align-pointer=name") ) + { + formatter.setPointerAlignment(ALIGN_NAME); + } + else if ( isParamOption(arg, "k") ) + { + int align = 0; + string styleParam = GET_PARAM(arg, "k"); + if (styleParam.length() > 0) + align = atoi(styleParam.c_str()); + if (align < 1 || align > 3) + isOptionError(arg, errorInfo); + else if (align == 1) + formatter.setPointerAlignment(ALIGN_TYPE); + else if (align == 2) + formatter.setPointerAlignment(ALIGN_MIDDLE); + else if (align == 3) + formatter.setPointerAlignment(ALIGN_NAME); + } + // depreciated options ///////////////////////////////////////////////////////////////////////////////////// + // depreciated in release 1.23 + // removed from documentation in release 1.24 + // may be removed at an appropriate time +// else if ( IS_OPTION(arg, "style=kr") ) +// { +// formatter.setFormattingStyle(STYLE_JAVA); +// } + else if ( isParamOption(arg, "T", "force-indent=tab=") ) + { + // the 'T' option will already have been processed + int spaceNum = 4; + string spaceNumParam = GET_PARAMS(arg, "T", "force-indent=tab="); + if (spaceNumParam.length() > 0) + spaceNum = atoi(spaceNumParam.c_str()); + if (spaceNum < 1 || spaceNum > 20) + isOptionError(arg, errorInfo); + else + formatter.setTabIndentation(spaceNum, true); + } + else if ( IS_OPTION(arg, "brackets=break-closing") ) + { + formatter.setBreakClosingHeaderBracketsMode(true); + } + + else if ( IS_OPTION(arg, "one-line=keep-blocks") ) + { + formatter.setBreakOneLineBlocksMode(false); + } + else if ( IS_OPTION(arg, "one-line=keep-statements") ) + { + formatter.setSingleStatementsMode(false); + } + else if ( IS_OPTION(arg, "pad=paren") ) + { + formatter.setParensOutsidePaddingMode(true); + formatter.setParensInsidePaddingMode(true); + } + else if ( IS_OPTION(arg, "pad=paren-out") ) + { + formatter.setParensOutsidePaddingMode(true); + } + else if ( IS_OPTION(arg, "pad=paren-in") ) + { + formatter.setParensInsidePaddingMode(true); + } + else if ( IS_OPTION(arg, "unpad=paren") ) + { + formatter.setParensUnPaddingMode(true); + } + else if ( IS_OPTION(arg, "pad=oper") ) + { + formatter.setOperatorPaddingMode(true); + } + // end depreciated options ////////////////////////////////////////////////////////////////////////////// +#ifdef ASTYLE_LIB + // End of options used by GUI + else + isOptionError(arg, errorInfo); +#else + // Options used by only console + else if ( IS_OPTIONS(arg, "n", "suffix=none") ) + { + g_console->setNoBackup(true); + } + else if ( isParamOption(arg, "suffix=") ) + { + string suffixParam = GET_PARAM(arg, "suffix="); + if (suffixParam.length() > 0) + { + g_console->setOrigSuffix(suffixParam); + } + } + else if ( isParamOption(arg, "exclude=") ) + { + string suffixParam = GET_PARAM(arg, "exclude="); + if (suffixParam.length() > 0) + g_console->updateExcludeVector(suffixParam); + } + else if ( IS_OPTIONS(arg, "r", "R") || IS_OPTION(arg, "recursive") ) + { + g_console->setIsRecursive(true); + } + else if ( IS_OPTIONS(arg, "Z", "preserve-date") ) + { + g_console->setPreserveDate(true); + } + else if ( IS_OPTIONS(arg, "v", "verbose") ) + { + g_console->setIsVerbose(true); + } + else if ( IS_OPTIONS(arg, "Q", "formatted") ) + { + g_console->setIsFormattedOnly(true); + } + else if ( IS_OPTIONS(arg, "q", "quiet") ) + { + g_console->setIsQuiet(true); + } + else if ( IS_OPTIONS(arg, "X", "errors-to-stdout") ) + { + _err = &cout; + } + else if ( IS_OPTION(arg, "lineend=windows") ) + { + formatter.setLineEndFormat(LINEEND_WINDOWS); + } + else if ( IS_OPTION(arg, "lineend=linux") ) + { + formatter.setLineEndFormat(LINEEND_LINUX); + } + else if ( IS_OPTION(arg, "lineend=macold") ) + { + formatter.setLineEndFormat(LINEEND_MACOLD); + } + else if ( isParamOption(arg, "z") ) + { + int lineendType = 0; + string lineendParam = GET_PARAM(arg, "z"); + if (lineendParam.length() > 0) + lineendType = atoi(lineendParam.c_str()); + if (lineendType < 1 || lineendType > 3) + isOptionError(arg, errorInfo); + else if (lineendType == 1) + formatter.setLineEndFormat(LINEEND_WINDOWS); + else if (lineendType == 2) + formatter.setLineEndFormat(LINEEND_LINUX); + else if (lineendType == 3) + formatter.setLineEndFormat(LINEEND_MACOLD); + } + else + { + (*_err) << errorInfo << arg << endl; + return false; // invalid option + } +#endif +// End of parseOption function + return true; //o.k. +} + +//-------------------------------------------------------------------------------------- +// ASStreamIterator class +// typename will be istringstream for GUI and istream otherwise +//-------------------------------------------------------------------------------------- + +template<typename T> +ASStreamIterator<T>::ASStreamIterator(T *in) +{ + inStream = in; + buffer.reserve(200); + eolWindows = 0; + eolLinux = 0; + eolMacOld = 0; + outputEOL[0] = '\0'; + peekStart = 0; + prevLineDeleted = false; + checkForEmptyLine = false; +} + +template<typename T> +ASStreamIterator<T>::~ASStreamIterator() +{ +} + +/** + * read the input stream, delete any end of line characters, + * and build a string that contains the input line. + * + * @return string containing the next input line minus any end of line characters + */ +template<typename T> +string ASStreamIterator<T>::nextLine(bool emptyLineWasDeleted) +{ + // verify that the current position is correct + assert (peekStart == 0); + + // a deleted line may be replaced if break-blocks is requested + // this sets up the compare to check for a replaced empty line + if (prevLineDeleted) + { + prevLineDeleted = false; + checkForEmptyLine = true; + } + if (!emptyLineWasDeleted) + prevBuffer = buffer; + else + prevLineDeleted = true; + + // read the next record + buffer.clear(); + char ch; + inStream->get(ch); + + while (!inStream->eof() && ch != '\n' && ch != '\r') + { + buffer.append(1, ch); + inStream->get(ch); + } + + if (inStream->eof()) + { + return buffer; + } + + int peekCh = inStream->peek(); + + // find input end-of-line characters + if (!inStream->eof()) + { + if (ch == '\r') // CR+LF is windows otherwise Mac OS 9 + { + if (peekCh == '\n') + { + inStream->get(); + eolWindows++; + } + else + eolMacOld++; + } + else // LF is Linux, allow for improbable LF/CR + { + if (peekCh == '\r') + { + inStream->get(); + eolWindows++; + } + else + eolLinux++; + } + } + else + { + inStream->clear(); + } + + // set output end of line characters + if (eolWindows >= eolLinux) + { + if (eolWindows >= eolMacOld) + strcpy(outputEOL, "\r\n"); // Windows (CR+LF) + else + strcpy(outputEOL, "\r"); // MacOld (CR) + } + else if (eolLinux >= eolMacOld) + strcpy(outputEOL, "\n"); // Linux (LF) + else + strcpy(outputEOL, "\r"); // MacOld (CR) + + return buffer; +} + +// save the current position and get the next line +// this can be called for multiple reads +// when finished peeking you MUST call peekReset() +// call this function from ASFormatter ONLY +template<typename T> +string ASStreamIterator<T>::peekNextLine() +{ + assert (hasMoreLines()); + string nextLine; + char ch; + + if (peekStart == 0) + peekStart = inStream->tellg(); + + // read the next record + inStream->get(ch); + while (!inStream->eof() && ch != '\n' && ch != '\r') + { + nextLine.append(1, ch); + inStream->get(ch); + } + + if (inStream->eof()) + { + return nextLine; + } + + int peekCh = inStream->peek(); + + // remove end-of-line characters + if (!inStream->eof()) + { + if ((peekCh == '\n' || peekCh == '\r') && peekCh != ch) ///////////// changed ////////// + inStream->get(); + } + + return nextLine; +} + +// reset current position and EOF for peekNextLine() +template<typename T> +void ASStreamIterator<T>::peekReset() +{ + assert(peekStart != 0); + inStream->clear(); + inStream->seekg(peekStart); + peekStart = 0; +} + +// save the last input line after input has reached EOF +template<typename T> +void ASStreamIterator<T>::saveLastInputLine() +{ + assert(inStream->eof()); + prevBuffer = buffer; +} + +// check for a change in line ends +template<typename T> +bool ASStreamIterator<T>::getLineEndChange(int lineEndFormat) const +{ + assert(lineEndFormat == LINEEND_DEFAULT + || lineEndFormat == LINEEND_WINDOWS + || lineEndFormat == LINEEND_LINUX + || lineEndFormat == LINEEND_MACOLD); + + bool lineEndChange = false; + if (lineEndFormat == LINEEND_WINDOWS) + lineEndChange = (eolLinux + eolMacOld != 0); + else if (lineEndFormat == LINEEND_LINUX) + lineEndChange = (eolWindows + eolMacOld != 0); + else if (lineEndFormat == LINEEND_MACOLD) + lineEndChange = (eolWindows + eolLinux != 0); + else + { + if (eolWindows > 0) + lineEndChange = (eolLinux + eolMacOld != 0); + else if (eolLinux > 0) + lineEndChange = (eolWindows + eolMacOld != 0); + else if (eolMacOld > 0) + lineEndChange = (eolWindows + eolLinux != 0); + } + return lineEndChange; +} + +#ifndef ASTYLE_LIB +//-------------------------------------------------------------------------------------- +// ASConsole class +// main function will be included only in the console build +//-------------------------------------------------------------------------------------- + +// rewrite a stringstream converting the line ends +void ASConsole::convertLineEnds(ostringstream& out, int lineEnd) +{ + assert(lineEnd == LINEEND_WINDOWS || lineEnd == LINEEND_LINUX || lineEnd == LINEEND_MACOLD); + const string& inStr = out.str(); // avoids strange looking syntax + string outStr; // the converted ouput + int inLength = inStr.length(); + for (int pos = 0; pos < inLength; pos++) + { + if (inStr[pos] == '\r') + { + if (inStr[pos+ 1] == '\n') + { + // CRLF + if (lineEnd == LINEEND_CR) + { + outStr += inStr[pos]; // Delete the LF + pos++; + continue; + } + else if (lineEnd == LINEEND_LF) + { + outStr += inStr[pos+1]; // Delete the CR + pos++; + continue; + } + else + { + outStr += inStr[pos]; // Do not change + outStr += inStr[pos+1]; + pos++; + continue; + } + } + else + { + // CR + if (lineEnd == LINEEND_CRLF) + { + outStr += inStr[pos]; // Insert the CR + outStr += '\n'; // Insert the LF + continue; + } + else if (lineEnd == LINEEND_LF) + { + outStr += '\n'; // Insert the LF + continue; + } + else + { + outStr += inStr[pos]; // Do not change + continue; + } + } + } + else if (inStr[pos] == '\n') + { + // LF + if (lineEnd == LINEEND_CRLF) + { + outStr += '\r'; // Insert the CR + outStr += inStr[pos]; // Insert the LF + continue; + } + else if (lineEnd == LINEEND_CR) + { + outStr += '\r'; // Insert the CR + continue; + } + else + { + outStr += inStr[pos]; // Do not change + continue; + } + } + else + { + outStr += inStr[pos]; // Write the current char + } + } + // replace the stream + out.str(outStr); +} + +void ASConsole::correctMixedLineEnds(ostringstream& out) +{ + LineEndFormat lineEndFormat = LINEEND_DEFAULT; + if (strcmp(outputEOL, "\r\n") == 0) + lineEndFormat = LINEEND_WINDOWS; + if (strcmp(outputEOL, "\n") == 0) + lineEndFormat = LINEEND_LINUX; + if (strcmp(outputEOL, "\r") == 0) + lineEndFormat = LINEEND_MACOLD; + convertLineEnds(out, lineEndFormat); +} + +void ASConsole::error(const char *why, const char* what) const +{ + (*_err) << why << ' ' << what << '\n' << endl; + (*_err) << "Artistic Style has terminated!" << endl; + exit(EXIT_FAILURE); +} + +/** + * If no files have been given, use cin for input and cout for output. + * + * This is used to format text for text editors like TextWrangler (Mac). + * Do NOT display any console messages when this function is used. + */ +void ASConsole::formatCinToCout(ASFormatter& formatter) const +{ + ASStreamIterator<istream> streamIterator(&cin); // create iterator for cin + formatter.init(&streamIterator); + + while (formatter.hasMoreLines()) + { + cout << formatter.nextLine(); + if (formatter.hasMoreLines()) + cout << streamIterator.getOutputEOL(); + } + cout.flush(); +} + +/** + * Open input file, format it, and close the output. + * + * @param fileName The path and name of the file to be processed. + * @param formatter The formatter object. + */ +void ASConsole::formatFile(const string &fileName, ASFormatter &formatter) +{ + bool isFormatted = false; + + // open input file + ifstream in(fileName.c_str(), ios::binary); + if (!in) + error("Could not open input file", fileName.c_str()); + + ostringstream out; + + // Unless a specific language mode has been set, set the language mode + // according to the file's suffix. + if (!formatter.getModeManuallySet()) + { + if (stringEndsWith(fileName, string(".java"))) + formatter.setJavaStyle(); + else if (stringEndsWith(fileName, string(".cs"))) + formatter.setSharpStyle(); + else + formatter.setCStyle(); + } + + ASStreamIterator<istream> streamIterator(&in); + formatter.init(&streamIterator); + + // make sure encoding is 8 bit + // if not set the eofbit so the file is not formatted + FileEncoding encoding = getFileEncoding(in); + if (encoding != ENCODING_OK) + in.setstate(ios::eofbit); + + // set line end format + string nextLine; // next output line + filesAreIdentical = true; // input and output files are identical + LineEndFormat lineEndFormat = formatter.getLineEndFormat(); + initializeOutputEOL(lineEndFormat); + + // format the file + while (formatter.hasMoreLines()) + { + nextLine = formatter.nextLine(); + out << nextLine; + linesOut++; + if (formatter.hasMoreLines()) + { + setOutputEOL(lineEndFormat, streamIterator.getOutputEOL()); + out << outputEOL; + } + else + streamIterator.saveLastInputLine(); // to compare the last input line + + if (filesAreIdentical) + { + if (streamIterator.checkForEmptyLine) + { + if (nextLine.find_first_not_of(" \t") != string::npos) + filesAreIdentical = false; + } + else if (!streamIterator.compareToInputBuffer(nextLine)) + filesAreIdentical = false; + streamIterator.checkForEmptyLine = false; + } + } + // correct for mixed line ends + if (lineEndsMixed) + { + correctMixedLineEnds(out); + filesAreIdentical = false; + } + in.close(); + + // if file has changed, write the new file + if (!filesAreIdentical || streamIterator.getLineEndChange(lineEndFormat)) + { + writeOutputFile(fileName, out); + isFormatted = true; + filesFormatted++; + } + else + filesUnchanged++; + + if (encoding != ENCODING_OK) + printBadEncoding(encoding); + + // remove targetDirectory from filename if required by print + string displayName; + if (hasWildcard) + displayName = fileName.substr(targetDirectory.length() + 1); + else + displayName = fileName; + + if (isFormatted) + printMsg("formatted " + displayName); + else + { + if (!isFormattedOnly || encoding != ENCODING_OK) + printMsg("unchanged* " + displayName); + } +} + +// for unit testing +vector<bool> ASConsole::getExcludeHitsVector() +{ + return excludeHitsVector; +} + +// for unit testing +vector<string> ASConsole::getExcludeVector() +{ return excludeVector; } + +// for unit testing +vector<string> ASConsole::getFileName() +{ return fileName; } + +// for unit testing +vector<string> ASConsole::getFileNameVector() +{ return fileNameVector; } + +// for unit testing +vector<string> ASConsole::getFileOptionsVector() +{ return fileOptionsVector; } + +int ASConsole::getFilesUnchanged() +{ return filesUnchanged; } + +int ASConsole::getFilesFormatted() +{ return filesFormatted; } + +bool ASConsole::getIsFormattedOnly() +{ return isFormattedOnly; } + +bool ASConsole::getIsQuiet() +{ return isQuiet; } + +bool ASConsole::getIsRecursive() +{ return isRecursive; } + +bool ASConsole::getIsVerbose() +{ return isVerbose; } + +bool ASConsole::getLineEndsMixed() +{ return lineEndsMixed; } + +bool ASConsole::getNoBackup() +{ return noBackup; } + +string ASConsole::getOptionsFileName() +{ return optionsFileName; } + +bool ASConsole::getOptionsFileRequired() +{ return optionsFileRequired; } + +// for unit testing +vector<string> ASConsole::getOptionsVector() +{ return optionsVector; } + +string ASConsole::getOrigSuffix() +{ return origSuffix; } + +bool ASConsole::getPreserveDate() +{ return preserveDate; } + +// initialize output end of line +void ASConsole::initializeOutputEOL(LineEndFormat lineEndFormat) +{ + assert(lineEndFormat == LINEEND_DEFAULT + || lineEndFormat == LINEEND_WINDOWS + || lineEndFormat == LINEEND_LINUX + || lineEndFormat == LINEEND_MACOLD); + + outputEOL[0] = '\0'; // current line end + prevEOL[0] = '\0'; // previous line end + lineEndsMixed = false; // output has mixed line ends, LINEEND_DEFAULT only + + if (lineEndFormat == LINEEND_WINDOWS) + strcpy(outputEOL, "\r\n"); + else if (lineEndFormat == LINEEND_LINUX) + strcpy(outputEOL, "\n"); + else if (lineEndFormat == LINEEND_MACOLD) + strcpy(outputEOL, "\r"); + else + outputEOL[0] = '\0'; +} + +void ASConsole::printBadEncoding(FileEncoding encoding) const +{ + string msg = "********** following file unchanged: "; + if (encoding == UTF_16BE) + msg += "UTF-16BE encoding"; + else if (encoding == UTF_16LE) + msg += "UTF-16LE encoding"; + else if (encoding == UTF_32BE) + msg += "UTF-32BE encoding"; + else if (encoding == UTF_32LE) + msg += "UTF-32LE encoding"; + else + msg += "???????? encoding"; + printMsg(msg); +} + +void ASConsole::setIsFormattedOnly(bool state) +{ isFormattedOnly = state; } + +void ASConsole::setIsQuiet(bool state) +{ isQuiet = state; } + +void ASConsole::setIsRecursive(bool state) +{ isRecursive = state; } + +void ASConsole::setIsVerbose(bool state) +{ isVerbose = state; } + +void ASConsole::setNoBackup(bool state) +{ noBackup = state; } + +void ASConsole::setOptionsFileName(string name) +{ optionsFileName = name; } + +void ASConsole::setOptionsFileRequired(bool state) +{ optionsFileRequired = state; } + +void ASConsole::setOrigSuffix(string suffix) +{ origSuffix = suffix; } + +void ASConsole::setPreserveDate(bool state) +{ preserveDate = state; } + +// set outputEOL variable +void ASConsole::setOutputEOL(LineEndFormat lineEndFormat, const char* currentEOL) +{ + if (lineEndFormat == LINEEND_DEFAULT) + { + strcpy(outputEOL, currentEOL); + if (strlen(prevEOL) == 0) + strcpy(prevEOL, outputEOL); + if (strcmp(prevEOL, outputEOL) != 0) + { + lineEndsMixed = true; + filesAreIdentical = false; + strcpy(prevEOL, outputEOL); + } + } + else + { + strcpy(prevEOL, currentEOL); + if (strcmp(prevEOL, outputEOL) != 0) + filesAreIdentical = false; + } +} + +#ifdef _WIN32 // Windows specific + +/** + * WINDOWS function to get the current directory. + * NOTE: getenv("CD") does not work for Windows Vista. + * The Windows function GetCurrentDirectory is used instead. + * + * @return The path of the current directory + */ +string ASConsole::getCurrentDirectory(const string &fileName) const +{ + char currdir[MAX_PATH]; + currdir[0] = '\0'; + if (!GetCurrentDirectory(sizeof(currdir), currdir)) + error("Cannot find file", fileName.c_str()); + return string(currdir); +} + +/** + * WINDOWS function to resolve wildcards and recurse into sub directories. + * The fileName vector is filled with the path and names of files to process. + * + * @param directory The path of the directory to be processed. + * @param wildcard The wildcard to be processed (e.g. *.cpp). + * @param fileName An empty vector which will be filled with the path and names of files to process. + */ +void ASConsole::getFileNames(const string &directory, const string &wildcard) +{ + vector<string> subDirectory; // sub directories of directory + WIN32_FIND_DATA FindFileData; // for FindFirstFile and FindNextFile + + // Find the first file in the directory + string firstFile = directory + "\\*"; + HANDLE hFind = FindFirstFile(firstFile.c_str(), &FindFileData); + + if (hFind == INVALID_HANDLE_VALUE) + error("Cannot open directory", directory.c_str()); + + // save files and sub directories + do + { + // skip hidden or read only + if (FindFileData.cFileName[0] == '.' + || (FindFileData.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) + || (FindFileData.dwFileAttributes & FILE_ATTRIBUTE_READONLY)) + continue; + + // if a sub directory and recursive, save sub directory + if ((FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) && isRecursive) + { + string subDirectoryPath = directory + g_fileSeparator + FindFileData.cFileName; + if (isPathExclued(subDirectoryPath)) + printMsg("exclude " + subDirectoryPath.substr(mainDirectoryLength)); + else + subDirectory.push_back(subDirectoryPath); + continue; + } + + // save the file name + string filePathName = directory + g_fileSeparator + FindFileData.cFileName; + // check exclude before wildcmp to avoid "unmatched exclude" error + bool isExcluded = isPathExclued(filePathName); + // save file name if wildcard match + if (wildcmp(wildcard.c_str(), FindFileData.cFileName)) + { + if (isExcluded) + printMsg("exclude " + filePathName.substr(mainDirectoryLength)); + else + fileName.push_back(filePathName); + } + } + while (FindNextFile(hFind, &FindFileData) != 0); + + // check for processing error + FindClose(hFind); + DWORD dwError = GetLastError(); + if (dwError != ERROR_NO_MORE_FILES) + error("Error processing directory", directory.c_str()); + + // recurse into sub directories + // if not doing recursive subDirectory is empty + for (unsigned i = 0; i < subDirectory.size(); i++) + { + getFileNames(subDirectory[i], wildcard); + } + + return; +} + +#else // not _WIN32 + +/** + * LINUX function to get the current directory. + * This is done if the fileName does not contain a path. + * It is probably from an editor sending a single file. + * + * @param fileName The filename is used only for the error message. + * @return The path of the current directory + */ +string ASConsole::getCurrentDirectory(const string &fileName) const +{ + char *currdir = getenv("PWD"); + if (currdir == NULL) + error("Cannot find file", fileName.c_str()); + return string(currdir); +} + +/** + * LINUX function to resolve wildcards and recurse into sub directories. + * The fileName vector is filled with the path and names of files to process. + * + * @param directory The path of the directory to be processed. + * @param wildcard The wildcard to be processed (e.g. *.cpp). + * @param fileName An empty vector which will be filled with the path and names of files to process. + */ +void ASConsole::getFileNames(const string &directory, const string &wildcard) +{ + struct dirent *entry; // entry from readdir() + struct stat statbuf; // entry from stat() + vector<string> subDirectory; // sub directories of this directory + + // errno is defined in <errno.h> and is set for errors in opendir, readdir, or stat + errno = 0; + + DIR *dp = opendir(directory.c_str()); + if (dp == NULL) + error("Cannot open directory", directory.c_str()); + + // save the first fileName entry for this recursion + const unsigned firstEntry = fileName.size(); + + // save files and sub directories + while ((entry = readdir(dp)) != NULL) + { + // get file status + string entryFilepath = directory + g_fileSeparator + entry->d_name; + if (stat(entryFilepath.c_str(), &statbuf) != 0) + { + if (errno == EOVERFLOW) // file over 2 GB is OK + { + errno = 0; + continue; + } + perror("errno message"); + error("Error getting file status in directory", directory.c_str()); + } + // skip hidden or read only + if (entry->d_name[0] == '.' || !(statbuf.st_mode & S_IWUSR)) + continue; + // if a sub directory and recursive, save sub directory + if (S_ISDIR(statbuf.st_mode) && isRecursive) + { + if (isPathExclued(entryFilepath)) + printMsg("exclude " + entryFilepath.substr(mainDirectoryLength)); + else + subDirectory.push_back(entryFilepath); + continue; + } + + // if a file, save file name + if (S_ISREG(statbuf.st_mode)) + { + // check exclude before wildcmp to avoid "unmatched exclude" error + bool isExcluded = isPathExclued(entryFilepath); + // save file name if wildcard match + if (wildcmp(wildcard.c_str(), entry->d_name)) + { + if (isExcluded) + printMsg("exclude " + entryFilepath.substr(mainDirectoryLength)); + else + fileName.push_back(entryFilepath); + } + } + } + + if (closedir(dp) != 0) + { + perror("errno message"); + error("Error reading directory", directory.c_str()); + } + + // sort the current entries for fileName + if (firstEntry < fileName.size()) + sort(&fileName[firstEntry], &fileName[fileName.size()]); + + // recurse into sub directories + // if not doing recursive, subDirectory is empty + if (subDirectory.size() > 1) + sort(subDirectory.begin(), subDirectory.end()); + for (unsigned i = 0; i < subDirectory.size(); i++) + { + getFileNames(subDirectory[i], wildcard); + } + + return; +} + +#endif // _WIN32 + +// check files for 16 or 32 bit encoding +// the file must have a Byte Order Mark (BOM) +// NOTE: some string functions don't work with NULLs (e.g. length()) +FileEncoding ASConsole::getFileEncoding(ifstream& in) const +{ + // BOM max is 4 bytes + char buff[4] = {'\0'}; + in.read(buff, 4); + in.seekg(0); + + FileEncoding encoding = ENCODING_OK; + + if (memcmp(buff, "\x00\x00\xFE\xFF", 4) == 0) + encoding = UTF_32BE; + else if (memcmp(buff, "\xFF\xFE\x00\x00", 4) == 0) + encoding = UTF_32LE; + else if (memcmp(buff, "\xFE\xFF", 2) == 0) + encoding = UTF_16BE; + else if (memcmp(buff, "\xFF\xFE", 2) == 0) + encoding = UTF_16LE; + + return encoding; +} + +// get individual file names from the command-line file path +void ASConsole::getFilePaths(string &filePath) +{ + fileName.clear(); + targetDirectory = string(); + targetFilename = string(); + + // separate directory and file name + size_t separator = filePath.find_last_of(g_fileSeparator); + if (separator == string::npos) + { + // if no directory is present, use the currently active directory + targetDirectory = getCurrentDirectory(filePath); + targetFilename = filePath; + mainDirectoryLength = targetDirectory.length() + 1; // +1 includes trailing separator + } + else + { + targetDirectory = filePath.substr(0, separator); + targetFilename = filePath.substr(separator+1); + mainDirectoryLength = targetDirectory.length() + 1; // +1 includes trailing separator + } + + if (targetFilename.length() == 0) + error("Missing filename in", filePath.c_str()); + + // check filename for wildcards + hasWildcard = false; + if (targetFilename.find_first_of( "*?") != string::npos) + hasWildcard = true; + + // clear exclude hits vector + for (size_t ix = 0; ix < excludeHitsVector.size(); ix++) + excludeHitsVector[ix] = false; + + // display directory name for wildcard processing + if (hasWildcard) + { + printMsg("--------------------------------------------------"); + printMsg("directory " + targetDirectory + g_fileSeparator + targetFilename); + } + + // create a vector of paths and file names to process + if (hasWildcard || isRecursive) + getFileNames(targetDirectory, targetFilename); + else + fileName.push_back(targetDirectory + g_fileSeparator + targetFilename); + + if (hasWildcard) + printMsg("--------------------------------------------------"); + + // check for unprocessed excludes + bool excludeErr = false; + for (size_t ix = 0; ix < excludeHitsVector.size(); ix++) + { + if (excludeHitsVector[ix] == false) + { + (*_err) << "Unmatched exclude " << excludeVector[ix].c_str() << endl; + excludeErr = true; + } + } +#ifndef ASTYLECON_LIB + // abort if not a test + if (excludeErr) + exit(EXIT_FAILURE); +#endif + // check if files were found (probably an input error if not) + if (fileName.size() == 0) + (*_err) << "No file to process " << filePath.c_str() << endl; +} + +bool ASConsole::fileNameVectorIsEmpty() +{ + return fileNameVector.empty(); +} + +// compare a path to the exclude vector +// used for both directories and filenames +// updates the g_excludeHitsVector +// return true if a match +bool ASConsole::isPathExclued(const string &subPath) +{ + bool retVal = false; + + // read the exclude vector checking for a match + for (size_t i = 0; i < excludeVector.size(); i++) + { + string exclude = excludeVector[i]; + + if (subPath.length() < exclude.length()) + continue; + + size_t compareStart = subPath.length() - exclude.length(); + // subPath compare must start with a directory name + if (compareStart > 0) + { + char lastPathChar = subPath[compareStart - 1]; + if (lastPathChar != g_fileSeparator) + continue; + } + + string compare = subPath.substr(compareStart); + if (!g_isCaseSensitive) + { + // make it case insensitive for Windows + for (size_t j=0; j<compare.length(); j++) + compare[j] = (char)tolower(compare[j]); + for (size_t j=0; j<exclude.length(); j++) + exclude[j] = (char)tolower(exclude[j]); + } + // compare sub directory to exclude data - must check them all + if (compare == exclude) + { + excludeHitsVector[i] = true; + retVal = true; + break; + } + } + return retVal; +} + +void ASConsole::printHelp() const +{ + (*_err) << endl; + (*_err) << " Artistic Style " << _version << endl; + (*_err) << " Maintained by: Jim Pattee\n"; + (*_err) << " Original Author: Tal Davidson\n"; + (*_err) << endl; + (*_err) << "Usage : astyle [options] Source1.cpp Source2.cpp [...]\n"; + (*_err) << " astyle [options] < Original > Beautified\n"; + (*_err) << endl; + (*_err) << "When indenting a specific file, the resulting indented file RETAINS the\n"; + (*_err) << "original file-name. The original pre-indented file is renamed, with a\n"; + (*_err) << "suffix of \".orig\" added to the original filename.\n"; + (*_err) << endl; + (*_err) << "Wildcards (* and ?) may be used in the filename.\n"; + (*_err) << "A \'recursive\' option can process directories recursively.\n"; + (*_err) << endl; + (*_err) << "By default, astyle is set up to indent C/C++/C#/Java files, with four\n"; + (*_err) << "spaces per indent, a maximal indentation of 40 spaces inside continuous\n"; + (*_err) << "statements, a minimum indentation of eight spaces inside conditional\n"; + (*_err) << "statements, and NO formatting options.\n"; + (*_err) << endl; + (*_err) << "Option's Format:\n"; + (*_err) << "----------------\n"; + (*_err) << " Long options (starting with '--') must be written one at a time.\n"; + (*_err) << " Short options (starting with '-') may be appended together.\n"; + (*_err) << " Thus, -bps4 is the same as -b -p -s4.\n"; + (*_err) << endl; + (*_err) << "Predefined Style Options:\n"; + (*_err) << "-------------------------\n"; + (*_err) << " --style=allman OR --style=ansi OR --style=bsd OR -A1\n"; + (*_err) << " Allman style formatting/indenting.\n"; + (*_err) << " Broken brackets.\n"; + (*_err) << endl; + (*_err) << " --style=java OR -A2\n"; + (*_err) << " Java style formatting/indenting.\n"; + (*_err) << " Attached brackets.\n"; + (*_err) << endl; + (*_err) << " --style=k&r OR --style=k/r OR -A3\n"; + (*_err) << " Kernighan & Ritchie style formatting/indenting.\n"; + (*_err) << " Linux brackets.\n"; + (*_err) << endl; + (*_err) << " --style=stroustrup OR -A4\n"; + (*_err) << " Stroustrup style formatting/indenting.\n"; + (*_err) << " Stroustrup brackets.\n"; + (*_err) << endl; + (*_err) << " --style=whitesmith OR -A5\n"; + (*_err) << " Whitesmith style formatting/indenting.\n"; + (*_err) << " Broken, indented brackets.\n"; + (*_err) << " Indented class blocks and switch blocks.\n"; + (*_err) << endl; + (*_err) << " --style=banner OR -A6\n"; + (*_err) << " Banner style formatting/indenting.\n"; + (*_err) << " Attached, indented brackets.\n"; + (*_err) << " Indented class blocks and switch blocks.\n"; + (*_err) << endl; + (*_err) << " --style=gnu OR -A7\n"; + (*_err) << " GNU style formatting/indenting.\n"; + (*_err) << " Broken brackets, indented blocks, indent is 2 spaces.\n"; + (*_err) << endl; + (*_err) << " --style=linux OR -A8\n"; + (*_err) << " GNU style formatting/indenting.\n"; + (*_err) << " Linux brackets, indent is 8 spaces.\n"; + (*_err) << endl; + (*_err) << " --style=horstmann OR -A9\n"; + (*_err) << " Horstmann style formatting/indenting.\n"; + (*_err) << " Horstmann brackets, indented switches, indent is 3 spaces.\n"; + (*_err) << endl; + (*_err) << " --style=1tbs OR --style=otbs OR -A10\n"; + (*_err) << " One True Brace Style formatting/indenting.\n"; + (*_err) << " Linux brackets, add brackets to all conditionals.\n"; + (*_err) << endl; + (*_err) << "Tab and Bracket Options:\n"; + (*_err) << "------------------------\n"; + (*_err) << " default indent option\n"; + (*_err) << " If no indentation option is set,\n"; + (*_err) << " the default option of 4 spaces will be used.\n"; + (*_err) << endl; + (*_err) << " --indent=spaces=# OR -s#\n"; + (*_err) << " Indent using # spaces per indent. Not specifying #\n"; + (*_err) << " will result in a default of 4 spaces per indent.\n"; + (*_err) << endl; + (*_err) << " --indent=tab OR --indent=tab=# OR -t OR -t#\n"; + (*_err) << " Indent using tab characters, assuming that each\n"; + (*_err) << " tab is # spaces long. Not specifying # will result\n"; + (*_err) << " in a default assumption of 4 spaces per tab.\n"; + (*_err) << endl; + (*_err) << " --indent=force-tab=# OR -T#\n"; + (*_err) << " Indent using tab characters, assuming that each\n"; + (*_err) << " tab is # spaces long. Force tabs to be used in areas\n"; + (*_err) << " Astyle would prefer to use spaces.\n"; + (*_err) << endl; + (*_err) << " default brackets option\n"; + (*_err) << " If no brackets option is set,\n"; + (*_err) << " the brackets will not be changed.\n"; + (*_err) << endl; + (*_err) << " --brackets=break OR -b\n"; + (*_err) << " Break brackets from pre-block code (i.e. ANSI C/C++ style).\n"; + (*_err) << endl; + (*_err) << " --brackets=attach OR -a\n"; + (*_err) << " Attach brackets to pre-block code (i.e. Java/K&R style).\n"; + (*_err) << endl; + (*_err) << " --brackets=linux OR -l\n"; + (*_err) << " Break definition-block brackets and attach command-block\n"; + (*_err) << " brackets.\n"; + (*_err) << endl; + (*_err) << " --brackets=stroustrup OR -u\n"; + (*_err) << " Attach all brackets except function definition brackets.\n"; + (*_err) << endl; + (*_err) << " --brackets=horstmann OR -g\n"; + (*_err) << " Break brackets from pre-block code, but allow following\n"; + (*_err) << " run-in statements on the same line as an opening bracket.\n"; + (*_err) << endl; + (*_err) << "Indentation options:\n"; + (*_err) << "--------------------\n"; + (*_err) << " --indent-classes OR -C\n"; + (*_err) << " Indent 'class' blocks, so that the inner 'public:',\n"; + (*_err) << " 'protected:' and 'private: headers are indented in\n"; + (*_err) << " relation to the class block.\n"; + (*_err) << endl; + (*_err) << " --indent-switches OR -S\n"; + (*_err) << " Indent 'switch' blocks, so that the inner 'case XXX:'\n"; + (*_err) << " headers are indented in relation to the switch block.\n"; + (*_err) << endl; + (*_err) << " --indent-cases OR -K\n"; + (*_err) << " Indent case blocks from the 'case XXX:' headers.\n"; + (*_err) << " Case statements not enclosed in blocks are NOT indented.\n"; + (*_err) << endl; + (*_err) << " --indent-brackets OR -B\n"; + (*_err) << " Add extra indentation to '{' and '}' block brackets.\n"; + (*_err) << endl; + (*_err) << " --indent-blocks OR -G\n"; + (*_err) << " Add extra indentation entire blocks (including brackets).\n"; + (*_err) << endl; + (*_err) << " --indent-namespaces OR -N\n"; + (*_err) << " Indent the contents of namespace blocks.\n"; + (*_err) << endl; + (*_err) << " --indent-labels OR -L\n"; + (*_err) << " Indent labels so that they appear one indent less than\n"; + (*_err) << " the current indentation level, rather than being\n"; + (*_err) << " flushed completely to the left (which is the default).\n"; + (*_err) << endl; + (*_err) << " --indent-preprocessor OR -w\n"; + (*_err) << " Indent multi-line #define statements.\n"; + (*_err) << endl; + (*_err) << " --indent-col1-comments OR -Y\n"; + (*_err) << " Indent line comments that start in column one.\n"; + (*_err) << endl; + (*_err) << " --max-instatement-indent=# OR -M#\n"; + (*_err) << " Indent a maximal # spaces in a continuous statement,\n"; + (*_err) << " relative to the previous line.\n"; + (*_err) << endl; + (*_err) << " --min-conditional-indent=# OR -m#\n"; + (*_err) << " Indent a minimal # spaces in a continuous conditional\n"; + (*_err) << " belonging to a conditional header.\n"; + (*_err) << endl; + (*_err) << "Padding options:\n"; + (*_err) << "--------------------\n"; + (*_err) << " --break-blocks OR -f\n"; + (*_err) << " Insert empty lines around unrelated blocks, labels, classes, ...\n"; + (*_err) << endl; + (*_err) << " --break-blocks=all OR -F\n"; + (*_err) << " Like --break-blocks, except also insert empty lines \n"; + (*_err) << " around closing headers (e.g. 'else', 'catch', ...).\n"; + (*_err) << endl; + (*_err) << " --pad-oper OR -p\n"; + (*_err) << " Insert space paddings around operators.\n"; + (*_err) << endl; + (*_err) << " --pad-paren OR -P\n"; + (*_err) << " Insert space padding around parenthesis on both the outside\n"; + (*_err) << " and the inside.\n"; + (*_err) << endl; + (*_err) << " --pad-paren-out OR -d\n"; + (*_err) << " Insert space padding around parenthesis on the outside only.\n"; + (*_err) << endl; + (*_err) << " --pad-paren-in OR -D\n"; + (*_err) << " Insert space padding around parenthesis on the inside only.\n"; + (*_err) << endl; + (*_err) << " --pad-header OR -H\n"; + (*_err) << " Insert space padding after paren headers (e.g. 'if', 'for'...).\n"; + (*_err) << endl; + (*_err) << " --unpad-paren OR -U\n"; + (*_err) << " Remove unnecessary space padding around parenthesis. This\n"; + (*_err) << " can be used in combination with the 'pad' options above.\n"; + (*_err) << endl; + (*_err) << " --delete-empty-lines OR -x\n"; + (*_err) << " Delete empty lines within a function or method.\n"; + (*_err) << " It will NOT delete lines added by the break-blocks options.\n"; + (*_err) << endl; + (*_err) << " --fill-empty-lines OR -E\n"; + (*_err) << " Fill empty lines with the white space of their\n"; + (*_err) << " previous lines.\n"; + (*_err) << endl; + (*_err) << "Formatting options:\n"; + (*_err) << "-------------------\n"; + (*_err) << " --break-closing-brackets OR -y\n"; + (*_err) << " Break brackets before closing headers (e.g. 'else', 'catch', ...).\n"; + (*_err) << " Use with --brackets=attach, --brackets=linux, \n"; + (*_err) << " or --brackets=stroustrup.\n"; + (*_err) << endl; + (*_err) << " --break-elseifs OR -e\n"; + (*_err) << " Break 'else if()' statements into two different lines.\n"; + (*_err) << endl; + (*_err) << " --add-brackets OR -j\n"; + (*_err) << " Add brackets to unbracketed one line conditional statements.\n"; + (*_err) << endl; + (*_err) << " --add-one-line-brackets OR -J\n"; + (*_err) << " Add one line brackets to unbracketed one line conditional\n"; + (*_err) << " statements.\n"; + (*_err) << endl; + (*_err) << " --keep-one-line-blocks OR -O\n"; + (*_err) << " Don't break blocks residing completely on one line.\n"; + (*_err) << endl; + (*_err) << " --keep-one-line-statements OR -o\n"; + (*_err) << " Don't break lines containing multiple statements into\n"; + (*_err) << " multiple single-statement lines.\n"; + (*_err) << endl; + (*_err) << " --convert-tabs OR -c\n"; + (*_err) << " Convert tabs to the appropriate number of spaces.\n"; + (*_err) << endl; + (*_err) << " --align-pointer=type OR -k1\n"; + (*_err) << " --align-pointer=middle OR -k2\n"; + (*_err) << " --align-pointer=name OR -k3\n"; + (*_err) << " Attach a pointer or reference operator (* or &) to either\n"; + (*_err) << " the operator type (left), middle, or operator name (right).\n"; + (*_err) << endl; + (*_err) << " --mode=c\n"; + (*_err) << " Indent a C or C++ source file (this is the default).\n"; + (*_err) << endl; + (*_err) << " --mode=java\n"; + (*_err) << " Indent a Java source file.\n"; + (*_err) << endl; + (*_err) << " --mode=cs\n"; + (*_err) << " Indent a C# source file.\n"; + (*_err) << endl; + (*_err) << "Other options:\n"; + (*_err) << "--------------\n"; + (*_err) << " --suffix=####\n"; + (*_err) << " Append the suffix #### instead of '.orig' to original filename.\n"; + (*_err) << endl; + (*_err) << " --suffix=none OR -n\n"; + (*_err) << " Do not retain a backup of the original file.\n"; + (*_err) << endl; + (*_err) << " --options=####\n"; + (*_err) << " Specify an options file #### to read and use.\n"; + (*_err) << endl; + (*_err) << " --options=none\n"; + (*_err) << " Disable the default options file.\n"; + (*_err) << " Only the command-line parameters will be used.\n"; + (*_err) << endl; + (*_err) << " --recursive OR -r OR -R\n"; + (*_err) << " Process subdirectories recursively.\n"; + (*_err) << endl; + (*_err) << " --exclude=####\n"; + (*_err) << " Specify a file or directory #### to be excluded from processing.\n"; + (*_err) << endl; + (*_err) << " --errors-to-stdout OR -X\n"; + (*_err) << " Print errors and help information to standard-output rather than\n"; + (*_err) << " to standard-error.\n"; + (*_err) << endl; + (*_err) << " --preserve-date OR -Z\n"; + (*_err) << " The date and time modified will not be changed in the formatted file.\n"; + (*_err) << endl; + (*_err) << " --verbose OR -v\n"; + (*_err) << " Verbose mode. Extra informational messages will be displayed.\n"; + (*_err) << endl; + (*_err) << " --formatted OR -Q\n"; + (*_err) << " Formatted display mode. Display only the files that have been formatted.\n"; + (*_err) << endl; + (*_err) << " --quiet OR -q\n"; + (*_err) << " Quiet mode. Suppress all output except error messages.\n"; + (*_err) << endl; + (*_err) << " --lineend=windows OR -z1\n"; + (*_err) << " --lineend=linux OR -z2\n"; + (*_err) << " --lineend=macold OR -z3\n"; + (*_err) << " Force use of the specified line end style. Valid options\n"; + (*_err) << " are windows (CRLF), linux (LF), and macold (CR).\n"; + (*_err) << endl; + (*_err) << " --version OR -V\n"; + (*_err) << " Print version number.\n"; + (*_err) << endl; + (*_err) << " --help OR -h OR -?\n"; + (*_err) << " Print this help message.\n"; + (*_err) << endl; + (*_err) << "Default options file:\n"; + (*_err) << "---------------------\n"; + (*_err) << " Artistic Style looks for a default options file in the\n"; + (*_err) << " following order:\n"; + (*_err) << " 1. The contents of the ARTISTIC_STYLE_OPTIONS environment\n"; + (*_err) << " variable if it exists.\n"; + (*_err) << " 2. The file called .astylerc in the directory pointed to by the\n"; + (*_err) << " HOME environment variable ( i.e. $HOME/.astylerc ).\n"; + (*_err) << " 3. The file called astylerc in the directory pointed to by the\n"; + (*_err) << " USERPROFILE environment variable ( i.e. %USERPROFILE%\\astylerc ).\n"; + (*_err) << " If a default options file is found, the options in this file\n"; + (*_err) << " will be parsed BEFORE the command-line options.\n"; + (*_err) << " Long options within the default option file may be written without\n"; + (*_err) << " the preliminary '--'.\n"; + (*_err) << endl; +} + + +/** + * Process files in the fileNameVector. + * + * @param formatter The formatter object. + */ +void ASConsole::processFiles(ASFormatter &formatter) +{ + if (isVerbose) + printVerboseHeader(); + + clock_t startTime = clock(); // start time of file formatting + + // loop thru input fileNameVector and process the files + for (size_t i = 0; i < fileNameVector.size(); i++) + { + getFilePaths(fileNameVector[i]); + + // loop thru fileName vector formatting the files + for (size_t j = 0; j < fileName.size(); j++) + formatFile(fileName[j], formatter); + } + + // files are processed, display stats + if (isVerbose) + printVerboseStats(startTime); + +} + +// process options from the command line and options file +// build the vectors fileNameVector, excludeVector, optionsVector, and fileOptionsVector +processReturn ASConsole::processOptions(int argc, char** argv, ASFormatter &formatter) +{ + string arg; + bool ok = true; + bool shouldParseOptionsFile = true; + + // get command line options + for (int i = 1; i < argc; i++) + { + arg = string(argv[i]); + + if ( IS_OPTION(arg, "--options=none") ) + { + shouldParseOptionsFile = false; + } + else if ( isParamOption(arg, "--options=") ) + { + optionsFileName = GET_PARAM(arg, "--options="); + optionsFileRequired = true; + if (optionsFileName.compare("") == 0) + setOptionsFileName(" "); + } + else if ( IS_OPTION(arg, "-h") + || IS_OPTION(arg, "--help") + || IS_OPTION(arg, "-?") ) + { + printHelp(); + return(END_SUCCESS); + } + else if ( IS_OPTION(arg, "-V" ) + || IS_OPTION(arg, "--version") ) + { + (*_err) << "Artistic Style Version " << _version << endl; + return(END_SUCCESS); + } + else if (arg[0] == '-') + { + optionsVector.push_back(arg); + } + else // file-name + { + standardizePath(arg); + fileNameVector.push_back(arg); + } + } + + // get options file path and name + if (shouldParseOptionsFile) + { + if (optionsFileName.compare("") == 0) + { + char* env = getenv("ARTISTIC_STYLE_OPTIONS"); + if (env != NULL) + setOptionsFileName(env); + } + if (optionsFileName.compare("") == 0) + { + char* env = getenv("HOME"); + if (env != NULL) + setOptionsFileName(string(env) + "/.astylerc"); + } + if (optionsFileName.compare("") == 0) + { + char* env = getenv("USERPROFILE"); + if (env != NULL) + setOptionsFileName(string(env) + "/astylerc"); + } + if (optionsFileName.compare("") != 0) + standardizePath(optionsFileName); + } + + // create the options file vector and parse the options for errors + if (optionsFileName.compare("") != 0) + { + ifstream optionsIn(optionsFileName.c_str()); + if (optionsIn) + { + importOptions(optionsIn, fileOptionsVector); + ok = parseOptions(formatter, + fileOptionsVector.begin(), + fileOptionsVector.end(), + string("Invalid option in default options file: ")); + } + else + { + if (optionsFileRequired) + { + (*_err) << "Could not open options file: " << optionsFileName.c_str() << endl; + return (END_FAILURE); + } + optionsFileName.clear(); + } + optionsIn.close(); + } + if (!ok) + { + (*_err) << "For help on options, type 'astyle -h' " << endl; + return(END_FAILURE); + } + + // parse the command line options vector for errors + ok = parseOptions(formatter, + optionsVector.begin(), + optionsVector.end(), + string("Invalid command line option: ")); + if (!ok) + { + (*_err) << "For help on options, type 'astyle -h' \n" << endl; + return(END_FAILURE); + } + return(CONTINUE); +} + +// remove a file and check for an error +void ASConsole::removeFile(const char* fileName, const char* errMsg) const +{ + remove(fileName); + if (errno == ENOENT) // no file is OK + errno = 0; + if (errno) + { + perror("errno message"); + error(errMsg, fileName); + } +} + +// rename a file and check for an error +void ASConsole::renameFile(const char* oldFileName, const char* newFileName, const char* errMsg) const +{ + rename(oldFileName, newFileName); + // if file still exists the remove needs more time - retry + if (errno == EEXIST) + { + errno = 0; + waitForRemove(newFileName); + rename(oldFileName, newFileName); + } + if (errno) + { + perror("errno message"); + error(errMsg, oldFileName); + } +} + +// make sure file separators are correct type (Windows or Linux) +// remove ending file separator +// remove beginning file separator if requested and NOT a complete file path +void ASConsole::standardizePath(string &path, bool removeBeginningSeparator /*false*/) const +{ +#ifdef __VMS + struct FAB fab; + struct NAML naml; + char less[NAML$C_MAXRSS]; + char sess[NAM$C_MAXRSS]; + int r0_status; + + // If we are on a VMS system, translate VMS style filenames to unix + // style. + fab = cc$rms_fab; + fab.fab$l_fna = (char *)-1; + fab.fab$b_fns = 0; + fab.fab$l_naml = &naml; + naml = cc$rms_naml; + strcpy (sess, path.c_str()); + naml.naml$l_long_filename = (char *)sess; + naml.naml$l_long_filename_size = path.length(); + naml.naml$l_long_expand = less; + naml.naml$l_long_expand_alloc = sizeof (less); + naml.naml$l_esa = sess; + naml.naml$b_ess = sizeof (sess); + naml.naml$v_no_short_upcase = 1; + r0_status = sys$parse (&fab); + if (r0_status == RMS$_SYN) + { + error("File syntax error", path.c_str()); + } + else + { + if (!$VMS_STATUS_SUCCESS(r0_status)) + { + (void)lib$signal (r0_status); + } + } + less[naml.naml$l_long_expand_size - naml.naml$b_ver] = '\0'; + sess[naml.naml$b_esl - naml.naml$b_ver] = '\0'; + if (naml.naml$l_long_expand_size > naml.naml$b_esl) + { + path = decc$translate_vms (less); + } + else + { + path = decc$translate_vms (sess); + } +#endif /* __VMS */ + + // make sure separators are correct type (Windows or Linux) + for (size_t i = 0; i < path.length(); i++) + { + i = path.find_first_of("/\\", i); + if (i == string::npos) + break; + path[i] = g_fileSeparator; + } + // remove separator from the end + if (path[path.length()-1] == g_fileSeparator) + path.erase(path.length()-1, 1); + // remove beginning separator if requested + if (removeBeginningSeparator && (path[0] == g_fileSeparator)) + path.erase(0, 1); +} + +void ASConsole::printMsg(const string &msg) const +{ + if (isQuiet) + return; + cout << msg << endl; +} + +void ASConsole::printVerboseHeader() const +{ + assert(isVerbose); + if (isQuiet) + return; + cout << "Artistic Style " << _version << endl; + if (optionsFileName.compare("") != 0) + cout << "Using default options file " << optionsFileName << endl; +} + +void ASConsole::printVerboseStats(clock_t startTime) const +{ + assert(isVerbose); + if (isQuiet) + return; + if (hasWildcard) + cout << "--------------------------------------------------" << endl; + cout << filesFormatted << " formatted, "; + cout << filesUnchanged << " unchanged, "; + + // show processing time + clock_t stopTime = clock(); + float secs = float ((stopTime - startTime) / CLOCKS_PER_SEC); + if (secs < 60) + { + // show tenths of a second if time is less than 20 seconds + cout.precision(2); + if (secs >= 10 && secs < 20) + cout.precision(3); + cout << secs << " seconds, "; + cout.precision(0); + } + else + { + // show minutes and seconds if time is greater than one minute + int min = (int) secs / 60; + secs -= min * 60; + int minsec = int (secs + .5); + cout << min << " min " << minsec << " sec, "; + } + + cout << linesOut << " lines" << endl; +} + +bool ASConsole::stringEndsWith(const string &str, const string &suffix) const +{ + int strIndex = (int) str.length() - 1; + int suffixIndex = (int) suffix.length() - 1; + + while (strIndex >= 0 && suffixIndex >= 0) + { + if (tolower(str[strIndex]) != tolower(suffix[suffixIndex])) + return false; + + --strIndex; + --suffixIndex; + } + // suffix longer than string + if (strIndex < 0 && suffixIndex >= 0) + return false; + return true; +} + +void ASConsole::updateExcludeVector(string suffixParam) +{ + excludeVector.push_back(suffixParam); + standardizePath(excludeVector.back(), true); + excludeHitsVector.push_back(false); +} + +void ASConsole::sleep(int seconds) const +{ + clock_t endwait; + endwait = clock_t (clock () + seconds * CLOCKS_PER_SEC); + while (clock() < endwait) {} +} + +int ASConsole::waitForRemove(const char* newFileName) const +{ + struct stat stBuf; + int seconds; + // sleep a max of 20 seconds for the remove + for (seconds = 0; seconds < 20; seconds++) + { + sleep(1); + if (stat(newFileName, &stBuf) != 0) + break; + } + errno = 0; + return seconds; +} + +// From The Code Project http://www.codeproject.com/string/wildcmp.asp +// Written by Jack Handy - jakkhandy@hotmail.com +// Modified to compare case insensitive for Windows +int ASConsole::wildcmp(const char *wild, const char *data) const +{ + const char *cp = NULL, *mp = NULL; + bool cmpval; + + while ((*data) && (*wild != '*')) + { + if (!g_isCaseSensitive) + cmpval = (tolower(*wild) != tolower(*data)) && (*wild != '?'); + else + cmpval = (*wild != *data) && (*wild != '?'); + + if (cmpval) + { + return 0; + } + wild++; + data++; + } + + while (*data) + { + if (*wild == '*') + { + if (!*++wild) + { + return 1; + } + mp = wild; + cp = data+1; + } + else + { + if (!g_isCaseSensitive) + cmpval = (tolower(*wild) == tolower(*data) || (*wild == '?')); + else + cmpval = (*wild == *data) || (*wild == '?'); + + if (cmpval) + { + wild++; + data++; + } + else + { + wild = mp; + data = cp++; + } + } + } + + while (*wild == '*') + { + wild++; + } + return !*wild; +} + +void ASConsole::writeOutputFile(const string &fileName, ostringstream &out) const +{ + // save date accessed and date modified of original file + struct stat stBuf; + bool statErr = false; + if (stat(fileName.c_str(), &stBuf) == -1) + statErr = true; + + // create a backup + if (!noBackup) + { + string origFileName = fileName + origSuffix; + removeFile(origFileName.c_str(), "Could not remove pre-existing backup file"); + renameFile(fileName.c_str(), origFileName.c_str(), "Could not create backup file"); + } + + // write the output file + ofstream fout(fileName.c_str(), ios::binary | ios::trunc); + if (!fout) + error("Could not open output file", fileName.c_str()); + fout << out.str(); + fout.close(); + + // change date modified to original file date + if (preserveDate) + { + if (!statErr) + { + struct utimbuf outBuf; + outBuf.actime = stBuf.st_atime; + // add ticks so 'make' will recoginze a change + // Visual Studio 2008 needs more than 1 + outBuf.modtime = stBuf.st_mtime + 10; + if (utime(fileName.c_str(), &outBuf) == -1) + statErr = true; + } + if (statErr) + (*_err) << "********* could not preserve following file date" << endl; + } +} + +#endif +// ******************* end of console functions *********************************************** + +} // end of namespace astyle + +// ******************* end of astyle namespace *********************************************** + +using namespace astyle; + +#ifdef ASTYLE_JNI +// ************************* JNI functions ***************************************************** +// called by a java program to get the version number +// the function name is constructed from method names in the calling java program +extern "C" EXPORT +jstring STDCALL Java_AStyleInterface_AStyleGetVersion(JNIEnv* env, jclass) +{ + return env->NewStringUTF(_version); +} + +// called by a java program to format the source code +// the function name is constructed from method names in the calling java program +extern "C" EXPORT +jstring STDCALL Java_AStyleInterface_AStyleMain(JNIEnv* env, + jobject obj, + jstring textInJava, + jstring optionsJava) +{ + g_env = env; // make object available globally + g_obj = obj; // make object available globally + + jstring textErr = env->NewStringUTF(""); // zero length text returned if an error occurs + + // get the method ID + jclass cls = env->GetObjectClass(obj); + g_mid = env->GetMethodID(cls, "ErrorHandler","(ILjava/lang/String;)V"); + if (g_mid == 0) + { + cout << "Cannot find java method ErrorHandler" << endl; + return textErr; + } + + // convert jstring to char* + const char* textIn = env->GetStringUTFChars(textInJava, NULL); + const char* options = env->GetStringUTFChars(optionsJava, NULL); + + // call the C++ formatting function + char* textOut = AStyleMain(textIn, options, javaErrorHandler, javaMemoryAlloc); + // if an error message occurred it was displayed by errorHandler + if (textOut == NULL) + return textErr; + + // release memory + jstring textOutJava = env->NewStringUTF(textOut); + delete [] textOut; + env->ReleaseStringUTFChars(textInJava, textIn); + env->ReleaseStringUTFChars(optionsJava, options); + + return textOutJava; +} + +// Call the Java error handler +void STDCALL javaErrorHandler(int errorNumber, char* errorMessage) +{ + jstring errorMessageJava = g_env->NewStringUTF(errorMessage); + g_env->CallVoidMethod(g_obj, g_mid, errorNumber, errorMessageJava); +} + +// Allocate memory for the formatted text +char* STDCALL javaMemoryAlloc(unsigned long memoryNeeded) +{ + // error condition is checked after return from AStyleMain + char* buffer = new(nothrow) char [memoryNeeded]; + return buffer; +} +#endif + +#ifdef ASTYLE_LIB +// ************************* GUI functions **************************************************** +/* + * IMPORTANT VC DLL linker must have the parameter /EXPORT:AStyleMain=_AStyleMain@16 + * /EXPORT:AStyleGetVersion=_AStyleGetVersion@0 + */ +extern "C" EXPORT char* STDCALL +AStyleMain(const char* pSourceIn, // pointer to the source to be formatted + const char* pOptions, // pointer to AStyle options, separated by \n + fpError fpErrorHandler, // pointer to error handler function + fpAlloc fpMemoryAlloc) // pointer to memory allocation function +{ + if (fpErrorHandler == NULL) // cannot display a message if no error handler + return NULL; + + if (pSourceIn == NULL) + { + fpErrorHandler(101, (char*)"No pointer to source input."); + return NULL; + } + if (pOptions == NULL) + { + fpErrorHandler(102, (char*)"No pointer to AStyle options."); + return NULL; + } + if (fpMemoryAlloc == NULL) + { + fpErrorHandler(103, (char*)"No pointer to memory allocation function."); + return NULL; + } + + ASFormatter formatter; + + vector<string> optionsVector; + istringstream opt(pOptions); + _err = new stringstream; + + importOptions(opt, optionsVector); + + parseOptions(formatter, + optionsVector.begin(), + optionsVector.end(), + "Invalid Artistic Style options.\n" + "The following options were not processed:"); + + if (_err->str().length() > 0) + fpErrorHandler(210, (char*) _err->str().c_str()); + + delete _err; + _err = NULL; + + istringstream in(pSourceIn); + ASStreamIterator<istringstream> streamIterator(&in); + ostringstream out; + formatter.init(&streamIterator); + + while (formatter.hasMoreLines()) + { + out << formatter.nextLine(); + if (formatter.hasMoreLines()) + out << streamIterator.getOutputEOL(); + } + + unsigned long textSizeOut = out.str().length(); + char* pTextOut = fpMemoryAlloc(textSizeOut + 1); // call memory allocation function +// pTextOut = NULL; // for testing + if (pTextOut == NULL) + { + fpErrorHandler(110, (char*)"Allocation failure on output."); + return NULL; + } + + strcpy(pTextOut, out.str().c_str()); + + return pTextOut; +} + +extern "C" EXPORT const char* STDCALL AStyleGetVersion (void) +{ + return _version; +} + +// ASTYLECON_LIB is defined to exclude "main" from the test programs +#elif !defined(ASTYLECON_LIB) + +// ************************** main function *************************************************** + +int main(int argc, char** argv) +{ + ASFormatter formatter; + g_console = new ASConsole; + + // process command line and options file + // build the vectors fileNameVector, optionsVector, and fileOptionsVector + processReturn returnValue = g_console->processOptions(argc, argv, formatter); + + // check for end of processing + if (returnValue == END_SUCCESS) + return EXIT_SUCCESS; + if (returnValue == END_FAILURE) + { + (*_err) << "Artistic Style has terminated!" << endl; + return EXIT_FAILURE; + } + + // if no files have been given, use cin for input and cout for output + if (g_console->fileNameVectorIsEmpty()) + { + g_console->formatCinToCout(formatter); + return EXIT_SUCCESS; + } + + // process entries in the fileNameVector + g_console->processFiles(formatter); + + delete g_console; + return EXIT_SUCCESS; +} + +#endif diff --git a/support/highlight/src/core/astyle/astyle_main.h b/support/highlight/src/core/astyle/astyle_main.h new file mode 100644 index 0000000000..1ec7ea57ff --- /dev/null +++ b/support/highlight/src/core/astyle/astyle_main.h @@ -0,0 +1,268 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * + * Copyright (C) 2006-2010 by Jim Pattee <jimp03@email.com> + * Copyright (C) 1998-2002 by Tal Davidson + * <http://www.gnu.org/licenses/lgpl-3.0.html> + * + * This file is a part of Artistic Style - an indentation and + * reformatting tool for C, C++, C# and Java source files. + * <http://astyle.sourceforge.net> + * + * Artistic Style is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Artistic Style is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Artistic Style. If not, see <http://www.gnu.org/licenses/>. + * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + */ + +#ifndef ASTYLE_MAIN_H +#define ASTYLE_MAIN_H + +//---------------------------------------------------------------------------- +// headers +//---------------------------------------------------------------------------- + +#include <ctime> +#include "astyle.h" + +#if defined(_MSC_VER) || defined(__DMC__) +#include <sys/utime.h> +#include <sys/stat.h> +#else +#include <utime.h> +#include <sys/stat.h> +#endif // end compiler checks + +#ifdef ASTYLE_JNI +#include <jni.h> +#ifndef ASTYLE_LIB // ASTYLE_LIB must be defined for ASTYLE_JNI +#define ASTYLE_LIB +#endif +#endif // ASTYLE_JNI + +// for G++ implementation of string.compare: +#if defined(__GNUC__) && __GNUC__ < 3 +#error - Use GNU C compiler release 3 or higher +#endif + +// for namespace problem in version 5.0 +#if defined(_MSC_VER) && _MSC_VER < 1200 // check for V6.0 +#error - Use Microsoft compiler version 6 or higher +#endif + +//using namespace astyle; + +namespace astyle +{ + +// return values for ASConsole +enum processReturn { CONTINUE, END_SUCCESS, END_FAILURE }; + +//---------------------------------------------------------------------------- +// ASStreamIterator class +// typename will be istringstream for GUI and istream otherwise +// ASSourceIterator is an abstract class defined in astyle.h +//---------------------------------------------------------------------------- + +template<typename T> +class ASStreamIterator : public ASSourceIterator +{ + public: + bool checkForEmptyLine; + + // function declarations + ASStreamIterator(T *in); + virtual ~ASStreamIterator(); + bool getLineEndChange(int lineEndFormat) const; + string nextLine(bool emptyLineWasDeleted); + string peekNextLine(); + void peekReset(); + void saveLastInputLine(); + + private: + T * inStream; // pointer to the input stream + string buffer; // current input line + string prevBuffer; // previous input line + int eolWindows; // number of Windows line endings, CRLF + int eolLinux; // number of Linux line endings, LF + int eolMacOld; // number of old Mac line endings. CR + char outputEOL[4]; // next output end of line char + streamoff peekStart; // starting position for peekNextLine + bool prevLineDeleted; // the previous input line was deleted + + public: // inline functions + bool compareToInputBuffer(const string &nextLine) const + { return (nextLine == prevBuffer); } + const char* getOutputEOL() const { return outputEOL; } + bool hasMoreLines() const { return !inStream->eof(); } +}; + +//---------------------------------------------------------------------------- +// ASConsole class for console build +//---------------------------------------------------------------------------- + +class ASConsole +{ + private: // variables + // command line options + bool isRecursive; // recursive option + string origSuffix; // suffix= option + bool noBackup; // suffix=none option + bool preserveDate; // preserve-date option + bool isVerbose; // verbose option + bool isQuiet; // quiet option + bool isFormattedOnly; // formatted lines only option + bool optionsFileRequired; // options= option + // other variables + bool hasWildcard; // file name includes a wildcard + size_t mainDirectoryLength; // directory length to be excluded in displays + bool filesAreIdentical; // input and output files are identical + bool lineEndsMixed; // outputhas mixed line ends + int linesOut; // number of output lines + int filesFormatted; // number of files formatted + int filesUnchanged; // number of files unchanged + char outputEOL[4]; // current line end + char prevEOL[4]; // previous line end + + string optionsFileName; // file path and name of the options file to use + string targetDirectory; // path to the directory being processed + string targetFilename; // file name being processed + + vector<string> excludeVector; // exclude from wildcard hits + vector<bool> excludeHitsVector; // exclude flags for eror reporting + vector<string> fileNameVector; // file paths and names from the command line + vector<string> optionsVector; // options from the command line + vector<string> fileOptionsVector; // options from the options file + vector<string> fileName; // files to be processed including path + + public: + ASConsole() { + // command line options + isRecursive = false; + origSuffix = ".orig"; + noBackup = false; + preserveDate = false; + isVerbose = false; + isQuiet = false; + isFormattedOnly = false; + optionsFileRequired = false; + // other variables + hasWildcard = false; + filesAreIdentical = true; + lineEndsMixed = false; + outputEOL[0] = '\0'; + prevEOL[0] = '\0'; + mainDirectoryLength = 0; + filesFormatted = 0; + filesUnchanged = 0; + linesOut = 0; + } + + // functions + void convertLineEnds(ostringstream& out, int lineEnd); + void error(const char *why, const char* what) const; + void formatCinToCout(ASFormatter& formatter) const; + FileEncoding getFileEncoding(ifstream& in) const; + bool fileNameVectorIsEmpty(); + int getFilesFormatted(); + int getFilesUnchanged(); + bool getIsFormattedOnly(); + bool getIsQuiet(); + bool getIsRecursive(); + bool getIsVerbose(); + bool getLineEndsMixed(); + bool getNoBackup(); + string getOptionsFileName(); + bool getOptionsFileRequired(); + string getOrigSuffix(); + bool getPreserveDate(); + void processFiles(ASFormatter &formatter); + processReturn processOptions(int argc, char** argv, ASFormatter &formatter); + void setIsFormattedOnly(bool state); + void setIsQuiet(bool state); + void setIsRecursive(bool state); + void setIsVerbose(bool state); + void setNoBackup(bool state); + void setOptionsFileName(string name); + void setOptionsFileRequired(bool state); + void setOrigSuffix(string suffix); + void setPreserveDate(bool state); + void standardizePath(string &path, bool removeBeginningSeparator=false) const; + bool stringEndsWith(const string &str, const string &suffix) const; + void updateExcludeVector(string suffixParam); + + // for unit testing + vector<string> getExcludeVector(); + vector<bool> getExcludeHitsVector(); + vector<string> getFileNameVector(); + vector<string> getOptionsVector(); + vector<string> getFileOptionsVector(); + vector<string> getFileName(); + + private: + void correctMixedLineEnds(ostringstream& out); + void formatFile(const string &fileName, ASFormatter &formatter); + string getCurrentDirectory(const string &fileName) const; + void getFileNames(const string &directory, const string &wildcard); + void getFilePaths(string &filePath); + void initializeOutputEOL(LineEndFormat lineEndFormat); + bool isPathExclued(const string &subPath); + void printBadEncoding(FileEncoding encoding) const; + void printHelp() const; + void printMsg(const string &msg) const; + void printVerboseHeader() const; + void printVerboseStats(clock_t startTime) const; + void removeFile(const char* fileName, const char* errMsg) const; + void renameFile(const char* oldFileName, const char* newFileName, const char* errMsg) const; + void setOutputEOL(LineEndFormat lineEndFormat, const char* currentEOL); + void sleep(int seconds) const; + int waitForRemove(const char* oldFileName) const; + int wildcmp(const char *wild, const char *data) const; + void writeOutputFile(const string &fileName, ostringstream &out) const; +}; + + +//---------------------------------------------------------------------------- +// global function declarations +// used by both console and library builds +//---------------------------------------------------------------------------- + +void importOptions(istream &in, vector<string> &optionsVector); +void isOptionError(const string &arg, const string &errorInfo); +bool isParamOption(const string &arg, const char *option); +bool isParamOption(const string &arg, const char *option1, const char *option2); +bool parseOption(astyle::ASFormatter &formatter, const string &arg, const string &errorInfo); + +template<typename ITER> +bool parseOptions(astyle::ASFormatter &formatter, const ITER &optionsBegin, + const ITER &optionsEnd, const string &errorInfo); + +} // end of namespace astyle + +//---------------------------------------------------------------------------- +// declarations for java native interface (JNI) build +// global because they are called externally and are NOT part of the namespace +//---------------------------------------------------------------------------- + +#ifdef ASTYLE_JNI +void STDCALL javaErrorHandler(int errorNumber, char* errorMessage); +char* STDCALL javaMemoryAlloc(unsigned long memoryNeeded); +// the following function names are constructed from method names in the calling java program +extern "C" EXPORT +jstring STDCALL Java_AStyleInterface_AStyleGetVersion(JNIEnv* env, jclass); +extern "C" EXPORT +jstring STDCALL Java_AStyleInterface_AStyleMain +(JNIEnv* env, jobject obj, jstring textInJava, jstring optionsJava); +#endif // ASTYLE_JNI + + +#endif // closes ASTYLE_MAIN_H diff --git a/support/highlight/src/core/bbcodegenerator.cpp b/support/highlight/src/core/bbcodegenerator.cpp new file mode 100644 index 0000000000..deab822660 --- /dev/null +++ b/support/highlight/src/core/bbcodegenerator.cpp @@ -0,0 +1,128 @@ +/*************************************************************************** + bbcodegenarator.cpp - description + ------------------- + begin : Jul 21 2009 + copyright : (C) 2004-2009 by Andre Simon + email : andre.simon1@gmx.de + ***************************************************************************/ + + +/* +This file is part of Highlight. + +Highlight is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +Highlight is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Highlight. If not, see <http://www.gnu.org/licenses/>. +*/ + + +#include <sstream> + +#include "bbcodegenerator.h" + +using namespace std; + +namespace highlight +{ + + BBCodeGenerator::BBCodeGenerator() : CodeGenerator ( BBCODE ) + { + newLineTag = "\n"; + spacer = " "; + } + + BBCodeGenerator::~BBCodeGenerator() {} + + string BBCodeGenerator::getHeader() + { + return string(); + } + + void BBCodeGenerator::printBody() + { + *out << "[size="<<getBaseFontSize()<<"]"; + processRootState(); + *out << "[/size]"; + } + + string BBCodeGenerator::getFooter() + { + return string(); + } + + string BBCodeGenerator::getOpenTag (const ElementStyle & elem ) + { + ostringstream s; + + s << "[color=#"; + s << elem.getColour().getRed ( HTML ) + << elem.getColour().getGreen ( HTML ) + << elem.getColour().getBlue ( HTML ) + << "]"; + + if ( elem.isBold() ) s << "[b]"; + if ( elem.isItalic() ) s << "[i]"; + if ( elem.isUnderline() ) s << "[u]"; + return s.str(); + } + + string BBCodeGenerator::getCloseTag ( const ElementStyle &elem ) + { + ostringstream s; + if ( elem.isBold() ) s << "[/b]"; + if ( elem.isItalic() ) s << "[/i]"; + if ( elem.isUnderline() ) s << "[/u]"; + s << "[/color]"; + return s.str(); + } + + void BBCodeGenerator::initOutputTags () + { + openTags.push_back ( ""); + openTags.push_back ( getOpenTag ( docStyle.getStringStyle() ) ); + openTags.push_back ( getOpenTag ( docStyle.getNumberStyle() ) ); + openTags.push_back ( getOpenTag ( docStyle.getSingleLineCommentStyle() ) ); + openTags.push_back ( getOpenTag ( docStyle.getCommentStyle() ) ); + openTags.push_back ( getOpenTag ( docStyle.getEscapeCharStyle() ) ); + openTags.push_back ( getOpenTag ( docStyle.getDirectiveStyle() ) ); + openTags.push_back ( getOpenTag ( docStyle.getDirectiveStringStyle() ) ); + openTags.push_back ( getOpenTag ( docStyle.getLineStyle() ) ); + openTags.push_back ( getOpenTag ( docStyle.getSymbolStyle() ) ); + + closeTags.push_back ( "" ); + closeTags.push_back ( getCloseTag ( docStyle.getStringStyle() ) ); + closeTags.push_back ( getCloseTag ( docStyle.getNumberStyle() ) ); + closeTags.push_back ( getCloseTag ( docStyle.getSingleLineCommentStyle() ) ); + closeTags.push_back ( getCloseTag ( docStyle.getCommentStyle() ) ); + closeTags.push_back ( getCloseTag ( docStyle.getEscapeCharStyle() ) ); + closeTags.push_back ( getCloseTag ( docStyle.getDirectiveStyle() ) ); + closeTags.push_back ( getCloseTag ( docStyle.getDirectiveStringStyle() ) ); + closeTags.push_back ( getCloseTag ( docStyle.getLineStyle() ) ); + closeTags.push_back ( getCloseTag ( docStyle.getSymbolStyle() ) ); + } + + string BBCodeGenerator::maskCharacter ( unsigned char c ) + { + return string ( 1, c ); + } + + string BBCodeGenerator::getKeywordOpenTag ( unsigned int styleID ) + { + return getOpenTag (docStyle.getKeywordStyle ( langInfo.getKeywordClasses() [styleID] ) ); + } + + string BBCodeGenerator::getKeywordCloseTag ( unsigned int styleID ) + { + return getCloseTag ( docStyle.getKeywordStyle ( langInfo.getKeywordClasses() [styleID] ) ); + } + +} diff --git a/support/highlight/src/core/bbcodegenerator.h b/support/highlight/src/core/bbcodegenerator.h new file mode 100644 index 0000000000..49792984cf --- /dev/null +++ b/support/highlight/src/core/bbcodegenerator.h @@ -0,0 +1,90 @@ +/*************************************************************************** + bbcodegenerator.h - description + ------------------- + begin : Jul 20 2009 + copyright : (C) 2004-2007 by Andre Simon + email : andre.simon1@gmx.de + ***************************************************************************/ + + +/* +This file is part of Highlight. + +Highlight is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +Highlight is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Highlight. If not, see <http://www.gnu.org/licenses/>. +*/ + + +#ifndef BBCODEGENERATOR_H +#define BBCODEGENERATOR_H + +#include <string> + +#include "codegenerator.h" +#include "charcodes.h" +#include "version.h" + +namespace highlight +{ + + /** + \brief This class generates BBCode. + + It contains information about the resulting document structure (document + header and footer), the colour system, white space handling and text + formatting attributes. + + * @author Andre Simon + */ + + class BBCodeGenerator : public highlight::CodeGenerator + { + public: + BBCodeGenerator(); + ~BBCodeGenerator(); + + /** prints document header + */ + string getHeader(); + + /** Prints document footer*/ + string getFooter(); + + /** Prints document body*/ + void printBody(); + + private: + + /** \return escaped character*/ + virtual string maskCharacter ( unsigned char ); + + /** @return BBcode open tags */ + string getOpenTag (const ElementStyle & elem ); + + /** @return BBcode close tags */ + string getCloseTag ( const ElementStyle &elem ); + + /** initialize tags in specific format according to colouring information provided in DucumentStyle */ + void initOutputTags(); + + /** @param styleID current style ID + @return matching sequence to begin a new element formatting*/ + string getKeywordOpenTag ( unsigned int styleID ); + + /** @param styleID current style ID + @return matching sequence to stop element formatting*/ + string getKeywordCloseTag ( unsigned int styleID ); + }; + +} +#endif diff --git a/support/highlight/src/core/charcodes.h b/support/highlight/src/core/charcodes.h new file mode 100644 index 0000000000..d112b7553e --- /dev/null +++ b/support/highlight/src/core/charcodes.h @@ -0,0 +1,99 @@ +/*************************************************************************** + charcodes.cpp - description + ------------------- + begin : Wed Nov 24 2003 + copyright : (C) 2003 by Andre Simon + email : andre.simon1@gmx.de + ***************************************************************************/ + + +/* +This file is part of Highlight. + +Highlight is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +Highlight is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Highlight. If not, see <http://www.gnu.org/licenses/>. +*/ + + +#ifndef CHAR_CODES +#define CHAR_CODES + +#ifdef _WIN32 + +#define AUML_LC 228 +#define OUML_LC 246 +#define UUML_LC 252 + +#define AUML_UC 196 +#define OUML_UC 214 +#define UUML_UC 220 + + +#define AACUTE_LC 225 +#define EACUTE_LC 233 +#define OACUTE_LC 243 +#define UACUTE_LC 250 + +#define AACUTE_UC 193 +#define EACUTE_UC 201 +#define OACUTE_UC 211 +#define UACUTE_UC 218 + +#define AGRAVE_LC 224 +#define EGRAVE_LC 232 +#define OGRAVE_LC 242 +#define UGRAVE_LC 249 + +#define AGRAVE_UC 192 +#define EGRAVE_UC 200 +#define OGRAVE_UC 210 +#define UGRAVE_UC 217 + +#define SZLIG 223 + +#else + +#define AUML_LC 164 +#define OUML_LC 182 +#define UUML_LC 188 + +#define AUML_UC 132 +#define OUML_UC 150 +#define UUML_UC 156 + + +#define AACUTE_LC 161 +#define EACUTE_LC 169 +#define OACUTE_LC 179 +#define UACUTE_LC 186 + +#define AACUTE_UC 129 +#define EACUTE_UC 137 +#define OACUTE_UC 147 +#define UACUTE_UC 154 + +#define AGRAVE_LC 160 +#define EGRAVE_LC 168 +#define OGRAVE_LC 178 +#define UGRAVE_LC 185 + +#define AGRAVE_UC 128 +#define EGRAVE_UC 136 +#define OGRAVE_UC 146 +#define UGRAVE_UC 153 + +#define SZLIG 159 + +#endif + +#endif diff --git a/support/highlight/src/core/codegenerator.cpp b/support/highlight/src/core/codegenerator.cpp new file mode 100644 index 0000000000..dfb63ec48e --- /dev/null +++ b/support/highlight/src/core/codegenerator.cpp @@ -0,0 +1,1804 @@ +/*************************************************************************** + codegenerator.cpp - description + ------------------- + begin : Die Jul 9 2002 + copyright : (C) 2002-2009 by Andre Simon + email : andre.simon1@gmx.de + ***************************************************************************/ + + +/* +This file is part of Highlight. + +Highlight is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +Highlight is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Highlight. If not, see <http://www.gnu.org/licenses/>. +*/ + + +#include <climits> +#include <memory> + +#include "codegenerator.h" + +#include "htmlgenerator.h" +#include "xhtmlgenerator.h" +#include "rtfgenerator.h" +#include "latexgenerator.h" +#include "texgenerator.h" +#include "xmlgenerator.h" +#include "svggenerator.h" +#include "bbcodegenerator.h" +#include "re/Matcher.h" +#include "astyle/astyle.h" +#include "astyle/ASStreamIterator.h" + +#if !defined (QT) +#include "ansigenerator.h" +#include "xterm256generator.h" +#endif + +using namespace std; + +namespace highlight +{ + + const unsigned int CodeGenerator::NUMBER_BUILTIN_STATES = 10; + + const string CodeGenerator::STY_NAME_STD="std"; + const string CodeGenerator::STY_NAME_STR="str"; + const string CodeGenerator::STY_NAME_NUM="num"; + const string CodeGenerator::STY_NAME_SLC="slc"; + const string CodeGenerator::STY_NAME_COM="com" ; + const string CodeGenerator::STY_NAME_ESC="esc" ; + const string CodeGenerator::STY_NAME_DIR="dir" ; + const string CodeGenerator::STY_NAME_DST="dstr"; + const string CodeGenerator::STY_NAME_LIN="line"; + const string CodeGenerator::STY_NAME_SYM="sym" ; + + CodeGenerator * CodeGenerator::getInstance ( OutputType type ) + { + CodeGenerator* generator=NULL; + switch ( type ) + { + case HTML: + generator = new HtmlGenerator(); + break; + case XHTML: + generator = new XHtmlGenerator(); + break; + case TEX: + generator = new TexGenerator (); + break; + case LATEX: + generator = new LatexGenerator(); + break; + case RTF: + generator = new RtfGenerator (); + break; + case XML: + generator = new XmlGenerator(); + break; + case SVG: + generator = new SVGGenerator(); + break; + case BBCODE: + generator = new BBCodeGenerator(); + break; +#if !defined (QT) + case ANSI: + generator = new AnsiGenerator(); + break; + case XTERM256: + generator = new Xterm256Generator(); + break; +#endif + default: + break; + } + return generator; + } + + + CodeGenerator::CodeGenerator ( highlight::OutputType type ) + :in ( NULL ), + out ( NULL ), + encoding ( "none" ), + docTitle ( "Source file" ), + maskWs ( false ), + excludeWs ( false ), + fragmentOutput ( false ), + showLineNumbers ( false ), + lineNumberFillZeroes ( false ), + printNewLines(true), + lineNumber ( 0 ), + lineNumberOffset ( 0 ), + includeStyleDef ( false ), + lineIndex ( 0 ), + lineNumberWidth ( 5 ), + maxLineCnt ( UINT_MAX ), + terminatingChar ( '\0' ), + formatter ( NULL ), + formattingEnabled ( false ), + formattingPossible ( false ), + validateInput ( false ), + tagsEnabled ( false ), + noTrailingNewLine(false), + keywordCase ( StringTools::CASE_UNCHANGED ), + eolDelimiter ('\n'), + outputType ( type ) + { + } + + + CodeGenerator::~CodeGenerator() + { + delete formatter; + } + + + bool CodeGenerator::initTheme ( const string& themePath ) + { + this->themePath=themePath; + bool loadOK = docStyle.load ( themePath ); + //docStyles.insert(docStyles.begin(), docStyle); // main style must be first + initOutputTags(); + return loadOK; + } + + + bool CodeGenerator::hasWhiteBGColour() + { + //Colour bgCol = docStyles.front().getBgColour(); + Colour bgCol = docStyle.getBgColour(); + return bgCol.getRed ( HTML ) == "ff" && bgCol.getGreen ( HTML ) == "ff" && bgCol.getBlue ( HTML ) == "ff"; + } + + + const string& CodeGenerator::getStyleName() + { + return themePath; + } + + + void CodeGenerator::setLineNumberWidth ( int w ) + { + lineNumberWidth=w; + } + + + int CodeGenerator::getLineNumberWidth() + { + return lineNumberWidth; + } + + + void CodeGenerator::setPrintLineNumbers ( bool flag, unsigned int startCnt ) + { + showLineNumbers=flag; + lineNumberOffset = startCnt-1; + } + + + bool CodeGenerator::getPrintLineNumbers() + { + return showLineNumbers; + } + + + void CodeGenerator::setPrintZeroes ( bool flag ) + { + lineNumberFillZeroes=flag; + } + + + bool CodeGenerator::getPrintZeroes() + { + return lineNumberFillZeroes; + } + + + void CodeGenerator::setIncludeStyle ( bool flag ) + { + includeStyleDef = flag; + } + + void CodeGenerator::disableTrailingNL ( bool flag ) + { + noTrailingNewLine = flag; + } + + + void CodeGenerator::setStyleInputPath ( const string& path ) + { + styleInputPath = path; + } + + + void CodeGenerator::setStyleOutputPath ( const string& path ) + { + styleOutputPath = path; + } + + + const string& CodeGenerator::getStyleInputPath() + { + return styleInputPath; + } + + + const string& CodeGenerator::getStyleOutputPath() + { + return styleOutputPath; + } + + + void CodeGenerator::setFragmentCode ( bool flag ) + { + fragmentOutput=flag; + } + + + bool CodeGenerator::getFragmentCode() + { + return fragmentOutput; + } + + + void CodeGenerator::setValidateInput ( bool flag ) + { + validateInput=flag; + } + + + bool CodeGenerator::getValidateInput() + { + return validateInput; + } + + + void CodeGenerator::setBaseFont ( const string& s ) + { + baseFont = s; + } + + + void CodeGenerator::setBaseFontSize ( const string& s ) + { + baseFontSize = s ; + } + + void CodeGenerator::setStartingNestedLang(const string &langName) { + embedLangStart = langName; + } + + + const string CodeGenerator::getBaseFont() const + { + if ( !baseFont.empty() ) return baseFont; + switch ( outputType ) + { + case LATEX: + return "ttfamily"; + break; + case TEX: + return "tt"; + break; + default: + return "Courier New"; + } + } + + + const string CodeGenerator::getBaseFontSize() + { + if ( baseFontSize.empty() && outputType != LATEX && outputType != TEX ) + { + //return docStyles.front().getFontSize(); + return docStyle.getFontSize(); + } + else + { + return baseFontSize; + } + } + + + void CodeGenerator::setTitle ( const string & title ) + { + if ( !title.empty() ) docTitle= title; + } + + + string CodeGenerator::getTitle() + { + return docTitle; + } + + + void CodeGenerator::setEncoding ( const string& encodingName ) + { + encoding = encodingName; + } + + + bool CodeGenerator::formattingDisabled() + { + return !formattingEnabled; + } + + + void CodeGenerator::setMaxInputLineCnt ( unsigned int cnt ) + { + maxLineCnt = cnt; + } + + + bool CodeGenerator::formattingIsPossible() + { + return formattingPossible; + } + + + void CodeGenerator::setPreformatting ( WrapMode lineWrappingStyle, + unsigned int lineLength, + int numberSpaces ) + { + bool enableWrap = lineWrappingStyle!=WRAP_DISABLED; + bool replaceTabs = numberSpaces > 0; + + if ( enableWrap || replaceTabs ) + { + preFormatter.setWrap ( enableWrap ); + preFormatter.setWrapIndentBraces ( lineWrappingStyle==WRAP_DEFAULT ); + preFormatter.setWrapLineLength ( lineLength ); + preFormatter.setReplaceTabs ( replaceTabs ); + preFormatter.setNumberSpaces ( numberSpaces ); + } + } + + + void CodeGenerator::setKeyWordCase ( StringTools::KeywordCase keyCase ) + { + keywordCase = keyCase; + } + + + void CodeGenerator::addMarkedLine ( int lineNo, string& helpTxt ) + { + markLines[lineNo] = helpTxt; + } + + + const LanguageDefinition &CodeGenerator::getLanguage() + { + return langInfo; + } + + + void CodeGenerator::setEOLDelimiter(char delim){ + eolDelimiter = delim; + } + + + void CodeGenerator::reset() + { + lineIndex = 0; + lineNumber = 0; + line.clear(); + preFormatter.reset(); + inFile.clear(); + outFile.clear(); + hostLangDefPath.clear(); + embedLangDefPath.clear(); + printNewLines=true; + } + + + /** sucht vorwaerts ab Position searchPos Ziffer in s und liefert Integerwert + der gefundenen Zahl zurueck. + Im SymbolString stehen die den einzelnen Symbolen zugeordneten Konstanten + immer HINTER diesen Symbolen*/ + State CodeGenerator::getState ( const string &s, unsigned int searchPos ) + { + string::size_type pos = s.find_first_of ( "1234567890", searchPos+1 ); + if ( pos==string::npos ) return _UNKNOWN; + + string::size_type pos2 = s.find ( ' ', pos ); + int result=_UNKNOWN; + StringTools::str2num<int> ( result, s.substr ( pos, pos2-pos ), std::dec ); + return ( State ) result; + } + + + unsigned int CodeGenerator::getLineNumber() + { + return lineNumber; + } + + + bool CodeGenerator::readNewLine ( string &newLine ) + { + + bool eof; + if ( lineIndex ) terminatingChar=newLine[lineIndex-1]; + if ( formattingPossible && formattingEnabled ) + { + eof=!formatter->hasMoreLines(); + if ( !eof ) + { + newLine = formatter->nextLine(); + } + } + // reformatting not enabled + else + { + eof = ! getline ( *in, newLine, eolDelimiter ); + } + + return eof || ( lineNumber == maxLineCnt ); + } + + + void CodeGenerator::matchRegex ( const string &line ) + { + + regexGroups.clear(); + int matchBegin=0; + int matchLen=0; + int groupID=0; + + // cycle through all regex, save the start and ending indices to report them later + for ( unsigned int i=0; i<langInfo.getRegexElements().size(); i++ ) + { + RegexElement *regexElem = langInfo.getRegexElements() [i]; + auto_ptr<Matcher> matcher ( regexElem->rePattern->createMatcher ( line ) ); + + while ( matcher->findNextMatch() ) + { + groupID = ( regexElem->capturingGroup<0 ) ? matcher->getGroupNum()-1 : regexElem->capturingGroup; + matchBegin = matcher->getStartingIndex ( groupID ); + if ( matchBegin<0 ) continue; + + matchLen = matcher->getEndingIndex ( groupID ) - matchBegin; + /* + std::cerr << "\nmatchBegin="<<1+ matchBegin + << " matchLen old" << ( matcher->getGroup(matcher->getGroupNum()-1).size()) + << " matchLen new" << matchLen<<" group: "<<(matcher->getGroup(matcher->getGroupNum()-1)) + << " group id= "<<regexElem->capturingGroup + << " lang= "<<regexElem->langName<<"\n"; + cerr<<"match: "<<(matcher->getGroup(matcher->getGroupNum()-1))<<" id: "<<regexElem->open<<endl; + */ + regexGroups.insert ( + make_pair ( matchBegin+1, ReGroup ( regexElem->open, matchLen, regexElem->kwClass, regexElem->langName ) ) ); + } + } + } + + + unsigned char CodeGenerator::getInputChar() + { + bool eol = lineIndex == line.length(); + + if ( eol ) + { + bool eof=false; + if ( preFormatter.isEnabled() ) + { + if ( !preFormatter.hasMoreLines() ) + { + eof=readNewLine ( line ); + preFormatter.setLine ( line ); + } + line = preFormatter.getNextLine(); + } + else + { + eof=readNewLine ( line ); + } + lineIndex=0; + ++lineNumber; + //line=StringTools::trimRight ( line ); + matchRegex ( line ); + + return ( eof ) ?'\0':'\n'; + } + + return line[lineIndex++]; + } + + + State CodeGenerator::getCurrentState () + { + + unsigned char c='\0'; + + if ( token.length() ==0 ) + { + c=getInputChar(); + } + else + { + lineIndex-= ( token.length()-1 ); + c=token[0]; + } + if ( c=='\n' ) + { + return _EOL; // End of line + } + + if ( c=='\0' ) + { + return _EOF; // End of file + } + + if ( c==' ' || c=='\t' ) + { + token= c; + return _WS; + } + + /** TODO + COMMENT ... END 2 eintraege in langdef (ML_COMMENT_START=regex(), ML_COMMENT_END=regex()) + weil comment sonst als identifier erkannt wird + */ + + // Test if a regular expression was found at the current position + if ( !regexGroups.empty() ) + { + if ( regexGroups.count ( lineIndex ) ) + { + token = line.substr ( lineIndex-1, regexGroups[lineIndex].length ); + unsigned int oldIndex= lineIndex; + if ( regexGroups[oldIndex].length>1 ) lineIndex+= regexGroups[oldIndex].length-1; + + + if ( regexGroups[oldIndex].state==EMBEDDED_CODE_BEGIN) { + embedLangDefPath = langInfo.getNewPath(regexGroups[oldIndex].name); + } + + if ( regexGroups[oldIndex].state==IDENTIFIER_BEGIN || regexGroups[oldIndex].state==KEYWORD ) + { + string reservedWord= ( langInfo.isIgnoreCase() ) ? StringTools::change_case ( token ) :token; + currentKeywordClass=langInfo.isKeyword ( reservedWord ); + if ( !currentKeywordClass && regexGroups[oldIndex].state==KEYWORD ) + currentKeywordClass = regexGroups[oldIndex].kwClass; + return ( currentKeywordClass ) ? KEYWORD : STANDARD; + } + else + { + return regexGroups[oldIndex].state; + } + } + } + + unsigned int symbolLength; + size_t symbolPos; + size_t symbolFind; + string symbols=langInfo.getSymbolString(); + + //TODO this while loop kills performance - adjust search algorithm + + symbolPos = symbols.find ( c ); + // search symbols (comment delimiters, directives etc.) + // before keywords, because alphabetic chars may be part of symbols, too + + while ( symbolPos!= string::npos && ! std::isdigit(c)) // isdigit: fix rexx issue + { + symbolFind = symbols.find ( ' ', symbolPos ); + if ( symbolFind==string::npos ) break; + symbolLength=symbolFind-symbolPos; + token = symbols.substr ( symbolPos, symbolLength ); + // Abfrage nach Leerzeichen in SymbolString verhindert falsches + // Erkennen von Symbolteilen: + if ( lineIndex && token == line.substr ( lineIndex-1, symbolLength ) + && symbols[symbolPos-1]==' ' ) + { + lineIndex += ( symbolLength-1 ); + return getState ( symbols, symbolPos ); + } + else + { + symbolPos = symbols.find_first_not_of ( ' ',symbols.find ( ' ',symbolPos ) ); + } + } + + // Character not referring to any state + token = c; + return STANDARD; + } + + + //it is faster to pass ostream reference + void CodeGenerator::maskString ( ostream& ss, const string & s ) + { + for ( unsigned int i=0;i< s.length();i++ ) + { + ss << maskCharacter ( s[i] ); + } + } + + + void CodeGenerator::printMaskedToken ( bool addMetaInfo, bool flushWhiteSpace, + StringTools::KeywordCase tcase ) + { + if ( flushWhiteSpace ) flushWs(); + + if ( addMetaInfo && tagsEnabled ) + { + bool insertMetaInfo=metaInfo.tagExists ( token ); + if ( insertMetaInfo ) *out<<getMetaInfoOpenTag ( metaInfo.getTagInfo ( token ) ); + maskString ( *out, StringTools::change_case ( token, tcase ) ); + if ( insertMetaInfo ) *out<<getMetaInfoCloseTag(); + } + else + { + maskString ( *out, StringTools::change_case ( token, tcase ) ); + } + token.clear(); + } + + + bool CodeGenerator::styleFound() + { + return docStyle.found(); + //return docStyles.front().found(); + } + + + bool CodeGenerator::printIndexFile ( const vector<string> &fileList, + const string &outPath ) + { + return true; + } + + + bool CodeGenerator::initIndentationScheme ( const string &indentScheme ) + { + + if ( formatter!=NULL ) + { + return true; + } + + if ( !indentScheme.size() ) return false; + + formatter=new astyle::ASFormatter(); + + formatter->setParensHeaderPaddingMode(true); + + if ( indentScheme=="allman" || indentScheme=="bsd" || indentScheme=="ansi" ) + { + formatter->setFormattingStyle ( astyle::STYLE_ALLMAN ); + } + else if ( indentScheme=="kr"||indentScheme=="k&r"||indentScheme=="k/r" ) + { + formatter->setFormattingStyle ( astyle::STYLE_KandR ); + } + else if ( indentScheme=="java" ) + { + formatter->setFormattingStyle ( astyle::STYLE_JAVA ); + } + else if ( indentScheme=="stroustrup" ) + { + formatter->setFormattingStyle ( astyle::STYLE_STROUSTRUP ); + } + else if ( indentScheme=="whitesmith" ) + { + formatter->setFormattingStyle ( astyle::STYLE_WHITESMITH ); + } + else if ( indentScheme=="banner" ) + { + formatter->setFormattingStyle ( astyle::STYLE_BANNER ); + } + else if ( indentScheme=="gnu" ) + { + formatter->setFormattingStyle ( astyle::STYLE_GNU ); + } + else if ( indentScheme=="linux" ) + { + formatter->setFormattingStyle ( astyle::STYLE_LINUX ); + } + else if ( indentScheme=="horstmann" ) + { + formatter->setFormattingStyle ( astyle::STYLE_HORSTMANN ); + } + else if ( indentScheme=="otbs" || indentScheme=="1tbs") + { + formatter->setFormattingStyle ( astyle::STYLE_1TBS ); + } + else + { + return false; + } + + return formattingEnabled=true; + } + + + LoadResult CodeGenerator::loadLanguage ( const string& langDefPath ) + { + bool reloadNecessary= langInfo.needsReload ( langDefPath ); + if ( reloadNecessary ) + { + //cerr<<"LOADING"<<langDefPath<<endl; + if ( !langInfo.load ( langDefPath ) ) + { + return langInfo.getFailedRegex().size() ? LOAD_FAILED_REGEX : LOAD_FAILED; + } + + formattingPossible=langInfo.enableReformatting(); + + if ( openTags.size() >NUMBER_BUILTIN_STATES ) + { + // remove dynamic keyword tag delimiters of the old language definition + vector<string>::iterator keyStyleOpenBegin = + openTags.begin() + NUMBER_BUILTIN_STATES; + vector<string>::iterator keyStyleCloseBegin = + closeTags.begin() + NUMBER_BUILTIN_STATES; + openTags.erase ( keyStyleOpenBegin, openTags.end() ); + closeTags.erase ( keyStyleCloseBegin, closeTags.end() ); + } + // add new keyword tag delimiters + for ( unsigned int i=0;i< langInfo.getKeywordClasses().size(); i++ ) + { + openTags.push_back ( getKeywordOpenTag ( i ) ); + closeTags.push_back ( getKeywordCloseTag ( i ) ); + } + } + return ( reloadNecessary) ? LOAD_NEW : LOAD_NONE; + } + + + bool CodeGenerator::initTagInformation ( const string& ctagsPath ) + { + if ( tagsEnabled ) return true; // load tag info once + tagsEnabled = metaInfo.load ( ctagsPath ); + return tagsEnabled; + } + + + bool CodeGenerator::validateInputStream() + { + if ( !in ) return false; + + // it is not possible to move stream pointer back with stdin + if ( ( int ) in->tellg() == -1 ) // -1 : stdin + return true; + + // Sources: http://en.wikipedia.org/wiki/Magic_number_(programming) + // Magic configuration of "file" + // This is intended for web plugins - only check filetypes often found in the net + char magic_gif[] = {'G','I','F','8', 0}; + char magic_png[] = {0x89,'P','N','G', 0}; + char magic_java[] = {0xCA,0xFE,0xBA,0xBE, 0}; + char magic_jpeg[] = {0xFF,0xD8,0xFF, 0}; + char magic_bmp[] = {'B','M', 0}; + char magic_pdf[] = {'%','P','D','F', 0}; + char magic_utf8[] = {0xEF,0xBB,0xBF,0}; + char magic_rar[] = {'R','a','r','!', 0}; + char magic_zip[] = {'P','K',0x03,0x04, 0}; + char magic_ace[] = {'*','*','A','C','E','*','*', 0}; + char magic_tgz[] = {0x8b,0x1f, 0x00, 0x08, 0}; + char magic_bzip[] = {'B','Z', 0}; + + char* magic_table[] = {magic_utf8, + magic_gif, magic_png, magic_jpeg, magic_bmp, magic_pdf, + magic_java, + magic_rar, magic_zip, magic_ace, magic_tgz, magic_bzip, + 0 + }; + + char buffer [10]={0}; + in->read ( buffer,8 ); //only read the first 8 bytes of input stream + + int magic_index=0; + while ( magic_table[magic_index] ) + { + if ( !strncmp ( buffer, magic_table[magic_index], strlen ( magic_table[magic_index] ) ) ) + { + break; + } + magic_index++; + } + int streamReadPos=0; + if ( magic_table[magic_index] == magic_utf8 ) + { + //setEncoding("utf-8"); + streamReadPos=3; // remove UTF-8 magic number from output + } + + in -> seekg ( streamReadPos, ios::beg ); + in-> clear(); // clear fail bit to continue reading + + return !magic_table[magic_index] // points to 0 if no pattern was found + || magic_table[magic_index] == magic_utf8; + } + + + ParseError CodeGenerator::generateFile ( const string &inFileName, + const string &outFileName ) + { + if ( !docStyle.found() ) + { + return BAD_STYLE; + } + + reset(); + + ParseError error=PARSE_OK; + + inFile=inFileName; + outFile=outFileName; + in = ( inFileName.empty() ? &cin :new ifstream ( inFileName.c_str() ) ); + + if ( validateInput ) + if ( !validateInputStream() ) error= BAD_INPUT; + + if ( !in->fail() && error==PARSE_OK ) + { + out = ( outFileName.empty() ? &cout :new ofstream ( outFileName.c_str() ) ); + if ( out->fail() ) + { + error=BAD_OUTPUT; + } + } + + if ( in->fail() ) + { + error=BAD_INPUT; + } + + if ( error==PARSE_OK ) + { + if ( formatter != NULL ) + { + formatter->init ( new astyle::ASStreamIterator ( in ) ); + } + if ( ! fragmentOutput ) + { + *out << getHeader(); + } + + printBody(); + + if ( ! fragmentOutput ) + { + *out << getFooter(); + } + } + + if ( !outFileName.empty() ) + { + delete out; out=NULL; + } + if ( !inFileName.empty() ) + { + delete in; in=NULL; + } + return error; + } + + + string CodeGenerator::generateString ( const string &input ) + { + + if ( !docStyle.found() ) + { + return ""; + } + + reset(); + + in = new istringstream ( input ); + out = new ostringstream (); + + if ( in->fail() || out->fail() ) + { + return ""; + } + + if ( formatter != NULL ) + { + formatter->init ( new astyle::ASStreamIterator ( in ) ); + } + if ( ! fragmentOutput ) + { + *out << getHeader(); + } + + printBody(); + + if ( ! fragmentOutput ) + { + *out << getFooter(); + } + + string result = static_cast<ostringstream*> ( out )->str(); + + delete out; out=NULL; + delete in; in=NULL; + + return result; + } + + + string CodeGenerator::generateStringFromFile ( const string &inFileName ) + { + + if ( !docStyle.found() ) + { + return ""; + } + + reset(); + + inFile = inFileName; + in = new ifstream ( inFileName.c_str() ); + out = new ostringstream (); + + if ( in->fail() || out->fail() ) + { + return ""; + } + + if ( validateInput && !validateInputStream() ) + { + return "ERROR: detected binary input"; + } + + if ( formatter != NULL ) + { + formatter->init ( new astyle::ASStreamIterator ( in ) ); + } + if ( ! fragmentOutput ) + { + *out << getHeader(); + } + + printBody(); + + if ( ! fragmentOutput ) + { + *out << getFooter(); + } + + string result = static_cast<ostringstream*> ( out )->str(); + + delete out; out=NULL; + delete in; in=NULL; + + return result; + } + + + unsigned int CodeGenerator::getStyleID ( State s, unsigned int kwClassID ) + { + if ( s==KEYWORD && kwClassID ) + { + return NUMBER_BUILTIN_STATES + kwClassID-1; + } + return ( unsigned int ) s ; + } + + + void CodeGenerator::openTag ( State s ) + { + *out << openTags[ ( unsigned int ) s]; + currentState=s; + } + + + void CodeGenerator::closeTag ( State s ) + { + *out << closeTags[ ( unsigned int ) s]; + flushWs(); + currentState=_UNKNOWN; + } + + + void CodeGenerator::openKWTag ( unsigned int kwClassID ) + { + *out << openTags.at(getStyleID ( KEYWORD, kwClassID ) ); + currentState=KEYWORD; + } + + + void CodeGenerator::closeKWTag ( unsigned int kwClassID ) + { + *out << closeTags.at(getStyleID ( KEYWORD, kwClassID ) ); + flushWs(); + currentState=_UNKNOWN; + } + + void CodeGenerator::loadEmbeddedLang(const string&embedLangDefPath){ + //save path of host language + if (hostLangDefPath.empty()) { + hostLangDefPath =langInfo.getCurrentPath(); + } + //load syntax of embedded langage + loadLanguage(embedLangDefPath); + //pass end delimiter regex to syntax description + langInfo.restoreLangEndDelim(embedLangDefPath); + } + +/////////////////////////////////////////////////////////////////////////////// + + void CodeGenerator::processRootState() + { + + bool eof=false, + firstLine=true; // avoid newline before printing the first output line + + if ( langInfo.highlightingDisabled() ) + { + string line; + while ( getline ( *in, line ) ) + { + ++lineNumber; + insertLineNumber ( !firstLine ); + flushWs(); + firstLine=false; + maskString ( *out, line ); + } + *out << flush; + return; + } + + if (!embedLangStart.empty()) loadEmbeddedLang(langInfo.getNewPath(embedLangStart)); + + State state=STANDARD; + + openTag ( STANDARD ); + do + { + // determine next state + state= getCurrentState(); + + // handle current state + switch ( state ) + { + case KEYWORD: + closeTag ( STANDARD ); + eof=processKeywordState ( state ); + openTag ( STANDARD ); + break; + case NUMBER: + closeTag ( STANDARD ); + eof=processNumberState(); + openTag ( STANDARD ); + break; + case ML_COMMENT: + closeTag ( STANDARD ); + eof=processMultiLineCommentState(); + openTag ( STANDARD ); + break; + case SL_COMMENT: + closeTag ( STANDARD ); + eof=processSingleLineCommentState(); + openTag ( STANDARD ); + break; + case STRING: + closeTag ( STANDARD ); + eof=processStringState ( STANDARD ); + openTag ( STANDARD ); + break; + case DIRECTIVE: + closeTag ( STANDARD ); + eof=processDirectiveState(); + openTag ( STANDARD ); + break; + case ESC_CHAR: + if ( langInfo.allowExtEscSeq() ) + { + closeTag ( STANDARD ); + eof=processEscapeCharState(); + openTag ( STANDARD ); + } + else + { + printMaskedToken(); + } + break; + case SYMBOL: + closeTag ( STANDARD ); + eof=processSymbolState(); + openTag ( STANDARD ); + break; + case EMBEDDED_CODE_BEGIN: + case EMBEDDED_CODE_END: + closeTag ( STANDARD ); + eof=processSyntaxChangeState(state); + openTag ( STANDARD ); + break; + case _EOL: + insertLineNumber ( !firstLine ); + firstLine=false; + break; + case _EOF: + eof=true; + break; + case _WS: + processWsState(); + break; + default: + printMaskedToken ( true ); + break; + } + } + while ( !eof ); + closeTag ( STANDARD ); + printNewLines = !noTrailingNewLine; + *out << getNewLine(); + *out << flush; + } + + bool CodeGenerator::processSyntaxChangeState(State myState) + { + State newState=STANDARD; + bool eof=false, + exitState=false; + openTag ( KEYWORD ); + do + { + if (myState==EMBEDDED_CODE_BEGIN) { + loadEmbeddedLang(embedLangDefPath); + + //test current line again to match tokens of the embedded language + matchRegex(line); + + } + else if (myState==EMBEDDED_CODE_END) { + // load host language syntax + loadLanguage(hostLangDefPath); + //test current line again to match tokens of the host language + matchRegex(line); + + } + + printMaskedToken ( false, newState!=_WS ); + newState= getCurrentState(); + switch ( newState ) + { + case _WS: + processWsState(); + break; + case _EOL: + insertLineNumber(); + exitState=true; + break; + case _EOF: + eof = true; + break; + default: + exitState=true; + break; + } + } + while ( ( !exitState ) && ( !eof ) ); + + closeTag ( KEYWORD ); + return eof; + } + + + bool CodeGenerator::processKeywordState ( State myState ) + { + State newState=STANDARD; + unsigned int myClassID=currentKeywordClass; + bool eof=false, + exitState=false; + + openKWTag ( myClassID ); + do + { + printMaskedToken ( true, newState!=_WS, + ( langInfo.isIgnoreCase() ) ? keywordCase : StringTools::CASE_UNCHANGED ); + newState= getCurrentState(); + switch ( newState ) + { + case _WS: + processWsState(); + break; + case _EOL: + insertLineNumber(); + exitState=true; + break; + case _EOF: + eof = true; + break; + case KEYWORD_END: + exitState=true; + break; + default: + exitState= ( myClassID!=currentKeywordClass ) || ( myState!=newState ); + break; + } + } + while ( ( !exitState ) && ( !eof ) ); + + closeKWTag ( myClassID ); + + currentKeywordClass=0; + return eof; + } + + + bool CodeGenerator::processNumberState() + { + State newState=STANDARD; + bool eof=false, + exitState=false; + openTag ( NUMBER ); + do + { + printMaskedToken ( false, newState!=_WS ); + newState= getCurrentState(); + switch ( newState ) + { + case _WS: + processWsState(); + break; + case _EOL: + insertLineNumber(); + exitState=true; + break; + case _EOF: + eof = true; + break; + default: + exitState=newState!=NUMBER; + break; + } + } + while ( ( !exitState ) && ( !eof ) ); + + closeTag ( NUMBER ); + return eof; + } + + + bool CodeGenerator::processMultiLineCommentState() + { + int commentCount=1; + int delimPairID = langInfo.getDelimiterPairID ( token ); + State newState=STANDARD; + bool eof=false, exitState=false; + openTag ( ML_COMMENT ); + do + { + printMaskedToken ( false, newState!=_WS ); + newState= getCurrentState(); + + switch ( newState ) + { + case _WS: + processWsState(); + break; + case _EOL: + wsBuffer += closeTags[ML_COMMENT]; + insertLineNumber(); + wsBuffer += openTags[ML_COMMENT]; + break; + case _EOF: + eof = true; + break; + case ML_COMMENT: + if ( langInfo.allowNestedMLComments() ) + { + ++commentCount; + } + // if delimiters are equal, close the comment by continueing to + // ML_COMMENT_END section + if ( langInfo.delimiterIsDistinct ( ML_COMMENT ) ) break; + + case ML_COMMENT_END: + if ( delimPairID!=langInfo.getDelimiterPairID ( token ) ) break; + commentCount--; + if ( !commentCount ) + { + printMaskedToken(); + exitState=true; + } + break; + default: + break; + } + } + while ( ( !exitState ) && ( !eof ) ); + + closeTag ( ML_COMMENT ); + return eof; + } + + + bool CodeGenerator::processSingleLineCommentState() + { + + if ( checkSpecialCmd() ) + { + return in->bad(); // if input stream is bad, report eof to calling method + } + + State newState=STANDARD; + bool eof=false, exitState=false; + + openTag ( SL_COMMENT ); + do + { + printMaskedToken ( false, newState!=_WS ); + newState= getCurrentState(); + + switch ( newState ) + { + case _WS: + processWsState(); + break; + case _EOL: + printMaskedToken(); + if ( preFormatter.isEnabled() && preFormatter.isWrappedLine ( lineNumber-1 ) ) + { + exitState=false; + } + else + { + exitState=true; + } + if ( !exitState ) wsBuffer += closeTags[SL_COMMENT]; + insertLineNumber(); + if ( !exitState ) wsBuffer += openTags[SL_COMMENT]; + + break; + case _EOF: + eof = true; + break; + default: + break; + } + } + while ( ( !exitState ) && ( !eof ) ); + + closeTag ( SL_COMMENT ); + return eof; + } + + + bool CodeGenerator::processDirectiveState() + { + State newState=STANDARD; + bool eof=false, exitState=false; + + openTag ( DIRECTIVE ); + do + { + printMaskedToken ( false, newState!=_WS ); + newState= getCurrentState(); + switch ( newState ) + { + case _WS: + processWsState(); + break; + case DIRECTIVE_END: + printMaskedToken(); + exitState=true; + break; + case _EOL: + printMaskedToken(); + if ( preFormatter.isEnabled() && preFormatter.isWrappedLine ( lineNumber-1 ) ) + { + exitState=false; + } + else + { + exitState= ( terminatingChar!=langInfo.getContinuationChar() ); + } + if ( !exitState ) wsBuffer += closeTags[DIRECTIVE]; + insertLineNumber(); + if ( !exitState ) wsBuffer += openTags[DIRECTIVE]; + break; + case ML_COMMENT: + closeTag ( DIRECTIVE ); + eof= processMultiLineCommentState(); + openTag ( DIRECTIVE ); + break; + case SL_COMMENT: + closeTag ( DIRECTIVE ); + eof= processSingleLineCommentState(); + openTag ( DIRECTIVE ); + exitState=true; + break; + case STRING: + closeTag ( DIRECTIVE ); + eof=processStringState ( DIRECTIVE ); + openTag ( DIRECTIVE ); + break; + case _EOF: + eof = true; + break; + default: + break; + } + } + while ( ( !exitState ) && ( !eof ) ); + + closeTag ( DIRECTIVE ); + return eof; + } + + + bool CodeGenerator::processStringState ( State oldState ) + { + State newState=STANDARD; + bool eof=false, exitState=false; + bool returnedFromOtherState=false; + // Test if character before string open delimiter token equals to the + // raw string prefix (Example: r" ", r""" """ in Python) + bool isRawString=false; + if ( lineIndex>token.length() ) + { + isRawString = line[lineIndex-token.length()-1]==langInfo.getRawStringPrefix(); + } + int delimPairID = langInfo.getDelimiterPairID ( token ); + State myState= ( oldState==DIRECTIVE ) ? DIRECTIVE_STRING : STRING; + openTag ( myState ); + do + { + // true if last token was an escape char + if ( !returnedFromOtherState ) + { + printMaskedToken ( false, newState!=_WS ); + } + returnedFromOtherState=false; + newState= getCurrentState(); + + switch ( newState ) + { + case _WS: + processWsState(); + break; + case _EOL: + wsBuffer += closeTags[myState]; + insertLineNumber(); + wsBuffer += openTags[myState]; + break; + case STRING_END: + exitState= true; + printMaskedToken(); + break; + case STRING: + // if there exist multiple string delimiters, close string if + // current delimiters is equal to the opening delimiter + exitState = ( delimPairID==langInfo.getDelimiterPairID ( token ) ); + printMaskedToken(); + break; + case ESC_CHAR: + if ( !isRawString ) + { + closeTag ( myState ); + eof=processEscapeCharState(); + openTag ( myState ); + returnedFromOtherState=true; + } + break; + case _EOF: + eof = true; + break; + default: + printMaskedToken(); + break; + } + } + while ( ( !exitState ) && ( !eof ) ); + + closeTag ( myState ); + return eof; + } + + + bool CodeGenerator::processSymbolState() + { + + State newState=STANDARD; + bool eof=false, + exitState=false; + + openTag ( SYMBOL ); + do + { + printMaskedToken ( false, newState!=_WS ); + newState= getCurrentState(); + switch ( newState ) + { + case _WS: + processWsState(); + break; + case _EOL: + insertLineNumber(); + exitState=true; + break; + case _EOF: + eof = true; + break; + default: + exitState=newState!=SYMBOL; + break; + } + } + while ( ( !exitState ) && ( !eof ) ); + + closeTag ( SYMBOL ); + return eof; + } + + + bool CodeGenerator::processEscapeCharState() + { + State newState=STANDARD; + bool eof=false, exitState=false; + openTag ( ESC_CHAR ); + do + { + printMaskedToken ( false, newState!=_WS ); + newState= getCurrentState(); + switch ( newState ) + { + case _EOL: + insertLineNumber(); + exitState=true; + break; + case _WS: + processWsState(); + break; + case _EOF: + eof = true; + break; + default: + exitState=newState!=ESC_CHAR; + break; + } + } + while ( ( !exitState ) && ( !eof ) ); + + closeTag ( ESC_CHAR ); + return eof; + } + + + void CodeGenerator::processWsState() + { + if ( !maskWs ) + { + wsBuffer += token; + token.clear(); + return; + } + flushWs(); + int cntWs=0; + lineIndex--; + + // while (iswspace(line[lineIndex]) ) { + while ( line[lineIndex]==' ' || line[lineIndex]=='\t' ) + { + ++cntWs; + ++lineIndex; + } + + if ( cntWs>1 ) + { + unsigned int styleID=getStyleID ( currentState, currentKeywordClass ); + if ( excludeWs && styleID!=_UNKNOWN ) + { + *out << closeTags[styleID]; + } + *out << maskWsBegin; + for ( int i=0; i<cntWs; i++ ) + { + *out << spacer; + } + *out << maskWsEnd; + if ( excludeWs && styleID!=_UNKNOWN ) + { + *out << openTags[styleID]; + } + } + else + { + *out << spacer; //Bugfix fehlender Space nach Strings + } + token.clear(); + } + + + void CodeGenerator::flushWs() + { + *out<<wsBuffer; + wsBuffer.clear(); + } + + + string CodeGenerator::getNewLine() + { + return (printNewLines) ? newLineTag : ""; + } + + + void CodeGenerator::insertLineNumber ( bool insertNewLine ) + { + + if ( insertNewLine ) + { + wsBuffer += getNewLine(); + } + + if ( showLineNumbers ) + { + ostringstream os; + ostringstream numberPrefix; + if ( lineNumberFillZeroes ) + { + os.fill ( '0' ); + } + os <<setw ( getLineNumberWidth() ) << right << lineNumber+lineNumberOffset; + + numberPrefix << openTags[LINENUMBER]; + maskString ( numberPrefix, os.str() ); + numberPrefix << spacer + << closeTags[LINENUMBER]; + + wsBuffer += numberPrefix.str(); + } + } + + + unsigned int CodeGenerator::getLineIndex() + { + return lineIndex; + } + + + bool CodeGenerator::printExternalStyle ( const string &outFile ) + { + if ( !includeStyleDef && langInfo.highlightingEnabled() ) + { + ostream *cssOutFile = ( outFile.empty() ? &cout :new ofstream ( outFile.c_str() ) ); + if ( !cssOutFile->fail() ) + { + *cssOutFile << styleCommentOpen + <<" Style definition file generated by highlight " + << HIGHLIGHT_VERSION << ", " << HIGHLIGHT_URL + << " " << styleCommentClose << "\n"; + *cssOutFile << "\n" << styleCommentOpen + << " Highlighting theme definition: " + << styleCommentClose << "\n\n" + << getStyleDefinition() + << "\n"; + *cssOutFile << readUserStyleDef(); + if ( !outFile.empty() ) delete cssOutFile; + } + else + { + return false; + } + } + return true; + } + + + string CodeGenerator::readUserStyleDef() + { + ostringstream ostr; + if ( !styleInputPath.empty() ) + { + ifstream userStyleDef ( styleInputPath.c_str() ); + if ( userStyleDef ) + { + ostr << "\n" << styleCommentOpen + << " Content of " << styleInputPath + << ": " <<styleCommentClose << "\n"; + string line; + while ( getline ( userStyleDef, line ) ) + { + ostr << line << "\n"; + } + userStyleDef.close(); + } + else + { + ostr << styleCommentOpen + << " ERROR: Could not include " << styleInputPath + << "." << styleCommentClose << "\n"; + } + } + return ostr.str(); + } + + + bool CodeGenerator::checkSpecialCmd() + { + + //cerr << "token: "<<token<< " index"<< lineIndex << " "<<line [ lineIndex ]<< "sizes: "<<token.size()<<"=="<<line.size()<<endl; + string noParseCmd="@highlight"; + // if single line comment is described with regex, token is equal to line + // otherwise start searching after the token, which then consists of comment identifier + size_t searchStart= ( token.size() ==line.size() ) ? 0 : lineIndex; + size_t cmdPos = line.find ( noParseCmd, searchStart ); + size_t pos=1; + if ( cmdPos!=string::npos ) + { + string res; + string replaceVar; + + auto_ptr<Pattern> reDefPattern ( Pattern::compile ( "\\$[-\\w]+" ) ); + auto_ptr<Matcher> m ( reDefPattern->createMatcher ( line.substr ( noParseCmd.size() +cmdPos ) ) ); + while ( m.get() && m->findNextMatch() ) + { + res+=line.substr ( noParseCmd.size() +cmdPos + pos , + m->getStartingIndex ( 0 )-pos ); + replaceVar = m->getGroup ( 0 ); + if ( replaceVar=="$nl" ) + { + res+="\n"; + } + else if ( replaceVar=="$infile" ) + { + res+= ( inFile.size() ) ? inFile: "stdin"; + } + else if ( replaceVar=="$outfile" ) + { + res+= ( outFile.size() ) ? outFile: "stdout"; + } + else if ( replaceVar=="$title" ) + { + res+= docTitle; + } + else if ( replaceVar=="$theme"||replaceVar=="$style" ) + { + res+= getStyleName(); + } + else if ( replaceVar=="$font-face" ) + { + res+= getBaseFont(); + } + else if ( replaceVar=="$font-size" ) + { + res+= getBaseFontSize(); + } + else if ( replaceVar=="$encoding" ) + { + res+= encoding; + } + else if ( replaceVar=="$linenum" ) + { + char numBuf[10]; + snprintf ( numBuf, sizeof ( numBuf ), "%d", lineNumber ); + res+= string ( numBuf ); + } + pos=m->getEndingIndex ( 0 ); + } + res+=line.substr ( noParseCmd.size() +cmdPos + pos ); + + *out<<res; + + // hide comment line from output + token.clear(); + lineIndex=line.length(); + getInputChar(); + lineNumber--; + // end hide + + return true; // do not parse line as comment + } + + return false; //parse comment as usual + } + +} diff --git a/support/highlight/src/core/codegenerator.h b/support/highlight/src/core/codegenerator.h new file mode 100644 index 0000000000..d5323673a2 --- /dev/null +++ b/support/highlight/src/core/codegenerator.h @@ -0,0 +1,729 @@ +/*************************************************************************** + codegenerator.h - description + ------------------- + begin : Die Jul 9 2002 + copyright : (C) 2002-2009 by Andre Simon + email : andre.simon1@gmx.de + ***************************************************************************/ + + +/* +This file is part of Highlight. + +Highlight is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +Highlight is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Highlight. If not, see <http://www.gnu.org/licenses/>. +*/ + + +#ifndef CODEPARSER_H +#define CODEPARSER_H + +#include <iostream> +#include <sstream> +#include <string> +#include <iomanip> + +#include "languagedefinition.h" +#include "documentstyle.h" +#include "ctagsreader.h" +#include "astyle/astyle.h" +#include "preformatter.h" +#include "enums.h" +#include "stringtools.h" + +/// The highlight namespace contains all classes and data structures needed for parsing input data. + +namespace highlight +{ + /** \brief Regular Expession Information + + This class associates a processing state with a keyword class and the length of the matched token. + + * @author Andre Simon + */ + class ReGroup + { + public: + + /// Constructor + ReGroup() : length ( 0 ), state ( STANDARD ), kwClass ( 0 ), name() + { + } + + /// Constructor + ReGroup ( State s, unsigned int l , unsigned int c, const string&n ) : + length ( l ), state ( s ), kwClass ( c ), name(n) + { + } + + /// Copy Constructor + ReGroup ( const ReGroup& other ) + { + length = other.length; + state = other.state; + kwClass = other.kwClass; + name=other.name; + } + + /// Operator overloading + ReGroup& operator= ( const ReGroup & other ) + { + length = other.length; + state = other.state; + kwClass = other.kwClass; + name=other.name; + return *this; + } + + ~ReGroup() + { + } + + unsigned int length; ///< length of the token + State state; ///< state of the matched token (keyword, string, etc) + unsigned int kwClass; ///< keyword class if state is keyword + string name; ///< language name needed to handle embedded languages + }; + + + /** \brief Base class for parsing. Works like a finite state machine. + + The virtual class provides source code parsing functionality, based on + information stored in language definitions.<br> + The derived classes have to define the output format.<br> + The colour information is stored in a DocumentStyle instance.<br> + Codegenerator is a singleton class.<br> + Use getInstance for a singleton class instance. Then call the init* methods + and loadLanguage to initialize the parser. Init methods have to be called first. + Call generate* methods to get results. + + * @author Andre Simon + */ + + class CodeGenerator + { + + public: + + virtual ~CodeGenerator(); + + /** + Get appropriate Codegenerator instance (should be used with auto_ptr) + \param type Output file type (HTML, XHTML, RTF, LATEX, TEX, ANSI, XTERM256) + \return CodeGenerator + */ + static CodeGenerator* getInstance ( OutputType type ); + + /** + Delete CodeGenerator instance (this is intended for SWIG integration only, + in normal C++ code the result of getInstance() should be saved in an auto_ptr) + \param CodeGenerator* CodeGenerator instance + */ + static void deleteInstance ( CodeGenerator* inst ) {if ( inst ) delete inst;} + + /** + Define colour theme information; needs to be called before using a generate* method. + Call this method before loadLanguage(). + \param themePath Path of style description file + \return true if successfull + */ + bool initTheme ( const string& themePath ); + + /** initialize source code indentation and reformatting scheme; + needs to be called before using a generate* method + \param indentScheme Name of indentation scheme + \return true if successfull + */ + bool initIndentationScheme ( const string&indentScheme ); + + /** + Load ctags meta information; needs to be called before using a generate* method + \param ctagsPath Path of tags file + \return true if successfull + */ + bool initTagInformation ( const string& ctagsPath ); + + /** \param langDefPath Absolute path to language definition, may be used multiple times for a generator instance + \return LOAD_FAILED: failure, + LOAD_NEW: Reload necessary, + LOAD_NONE: no reload necessary + */ + LoadResult loadLanguage ( const string& langDefPath ); + + /** + Generate output file from input file + \param inFileName Path of input file (if empty use stdin) + \param outFileName Path of output file (if empty use stdout) + \return ParseError + */ + ParseError generateFile ( const string &inFileName, const string &outFileName ); + + /** + Generate output string from input string + \param input input code string + \return formatted output code + */ + string generateString ( const string &input ); + + /** + Generate output string from input file + \param inFileName file path + \return formatted output code + */ + string generateStringFromFile ( const string &inFileName ); + + /** Print style definitions to external file or stdout + \param outFile Path of external style definition; print to stdout if empty + \return true if successfull + */ + bool printExternalStyle ( const string &outFile ); + + /** Print index file with all input file names + \param fileList List of output file names + \param outPath Output path + \return true if successfull + */ + virtual bool printIndexFile ( const vector<string> & fileList, + const string &outPath ); + + + /** define the preformatting parameters. Preformatting takes place before + the optional astyle reformatting and indenting is performed (defined by initIndentationScheme) + \param lineWrappingStyle wrapping style (WRAP_DISABLED, WRAP_SIMPLE, WRAP_DEFAULT) + \param lineLength max line length + \param numberSpaces number of spaces which replace a tab + */ + void setPreformatting ( WrapMode lineWrappingStyle, unsigned int lineLength,int numberSpaces ); + + /** \deprecated + \return True if document style was found */ + bool styleFound(); + + /** \return True if reformatting of current input is disabled */ + bool formattingDisabled(); + + /** \return True if reformatting of current input is possible */ + bool formattingIsPossible(); + + /** \deprecated + \param langDefPath Absolute path to language definition; use loadLanguage instead + \return LOAD_FAILED: failure, + LOAD_NEW: Reload necessary, + LOAD_NONE: no reload necessary + */ + LoadResult initLanguage ( const string& langDefPath ) { return loadLanguage ( langDefPath );} + + /** \return Language definition*/ + const LanguageDefinition &getLanguage(); + + /** output line numbers + \param flag true if line numbers should be printed + \param startCnt line number starting count + */ + void setPrintLineNumbers ( bool flag, unsigned int startCnt=1 ); + + /** \return line number flag */ + bool getPrintLineNumbers(); + + /** output line numbers filled with zeroes + \param flag true if zeroes should be printed + */ + void setPrintZeroes ( bool flag ); + + /** \return print zeroes flag */ + bool getPrintZeroes(); + + /** omit document header and footer + \param flag true if output should be fragmented + */ + void setFragmentCode ( bool flag ); + + /** \return fragment flag */ + bool getFragmentCode(); + + /** define line number width + \param w width + */ + void setLineNumberWidth ( int w ); + + /** \return line number width */ + int getLineNumberWidth(); + + /** check if input is binary or text + \param flag true if input should be checked + */ + void setValidateInput ( bool flag ); + + /** \return input validation flag */ + bool getValidateInput(); + + /** \return style path */ + const string& getStyleName(); + + /** use this font as base font + \param s the font name, e.g. "Courier New" + */ + void setBaseFont ( const string& s ); + + /** \return base font */ + const string getBaseFont() const ; + + /** use this size as base font size + \param s the font size, e.g. "12" + */ + void setBaseFontSize ( const string& s ); + + /** \return base font size*/ + const string getBaseFontSize(); + + /** tell parser the include style definition in output + \param flag true if style should be included + */ + void setIncludeStyle ( bool flag ); + + + /** tell parser to omit trailing newline character + \param flag true if no trailing newline should be printed + */ + void disableTrailingNL ( bool flag ); + + /** Set style input path + \param path path to style input file + */ + void setStyleInputPath ( const string& path ); + + /** Set style output path + \param path path to style output file + */ + void setStyleOutputPath ( const string& path ); + + /** Set encoding (output encoding must match input file) + \param encodingName encoding name + */ + void setEncoding ( const string& encodingName ); + + /** \return style input file path */ + const string& getStyleInputPath(); + + /** \return style output file path */ + const string& getStyleOutputPath(); + + /** \param title Document title */ + void setTitle ( const string & title ); + + /** \return Document title */ + string getTitle(); + + /** \param cnt maximum number of input lines to be processed */ + void setMaxInputLineCnt ( unsigned int cnt ); + + /** \return true if chosen document style has white background colour */ + bool hasWhiteBGColour(); + + /** \param keyCase Keyword case */ + void setKeyWordCase ( StringTools::KeywordCase keyCase ); + + /** \param lineNo number of line that should be marked + \param helpTxt additional help text */ + void addMarkedLine ( int lineNo, string &helpTxt ); + + /** \param delim End of line delimiter (default: NL) + */ + void setEOLDelimiter(char delim); + + /** Define the name of a nested langage which is located at the beginning of input. + The opening embedded delimiter is missing, but the closing delimiter must exist. + \param langName name of nested language + */ + void setStartingNestedLang(const string &langName); + + + /** set HTML output anchor flag + */ + virtual void setHTMLAttachAnchors ( bool ) {}; + + /** set HTML output ordered list flag + */ + virtual void setHTMLOrderedList ( bool ) {}; + + /** set HTML output inline CSS flag + */ + virtual void setHTMLInlineCSS ( bool ) {}; + + /** set HTML output enclose pre tag flag + */ + virtual void setHTMLEnclosePreTag ( bool ) {}; + + /** set HTML output anchor prefix + */ + virtual void setHTMLAnchorPrefix ( const string& ) {}; + + /** set HTML output class name + */ + virtual void setHTMLClassName ( const string& ) {}; + + /** set LaTeX replace quotes flag + */ + virtual void setLATEXReplaceQuotes ( bool ) {}; + + /** set LaTeX no Babel shorthands flag + */ + virtual void setLATEXNoShorthands ( bool ) {}; + + /** set LaTeX pretty Symbols flag + */ + virtual void setLATEXPrettySymbols ( bool ) {}; + + /** set RTF page size + */ + virtual void setRTFPageSize ( const string& ) {}; + + /** set RTF output character styles flag + */ + virtual void setRTFCharStyles ( bool ) {}; + + /** set SVG page size + */ + virtual void setSVGSize ( const string&, const string& ) {}; + + + protected: + + static const unsigned int NUMBER_BUILTIN_STATES; ///< number of token states (without keyword group IDs) + + static const string STY_NAME_STD; + static const string STY_NAME_STR; + static const string STY_NAME_NUM; + static const string STY_NAME_SLC; + static const string STY_NAME_COM; + static const string STY_NAME_ESC; + static const string STY_NAME_DIR; + static const string STY_NAME_DST; + static const string STY_NAME_LIN; + static const string STY_NAME_SYM; + + /** \param type Output type */ + CodeGenerator ( highlight::OutputType type ); + CodeGenerator() {}; + + /** \param c Character to be masked + \return Escape sequence of output format */ + virtual string maskCharacter ( unsigned char c ) = 0; + + /** \param ss destination stream + \param s string */ + void maskString ( ostream& ss, const string &s ) ; + + /** \param s Symbol string + \param searchPos Position where search starts + \return Found state (integer value) */ + State getState ( const string &s, unsigned int searchPos ); + + /** Get current line number + \return line number */ + unsigned int getLineNumber(); + + vector <string> openTags, ///< list of format delimiters (open new format descriptions) + closeTags; ///< list of format delimiters (close format descriptions) + + /** Description of document colour style*/ + DocumentStyle docStyle; + + /** Language definition*/ + LanguageDefinition langInfo; + + /** CTags meta information */ + CTagsReader metaInfo; + + /** Tag for inserting line feeds*/ + string newLineTag; + + /** String that represents a white space in output */ + string spacer; + + /** file input*/ + istream *in; + + /** file output*/ + ostream *out; + + string maskWsBegin, ///< open whitespace mask + maskWsEnd; ///< close whitespace mask + + string styleCommentOpen, ///< open comment delimiter + styleCommentClose; ///< close comment delimiter + + string embedBlockOpen, ///< open block delimiter to highlight embedded code + embedBlockClose; ///< close block delimiter + + /** Encoding name */ + string encoding; + + /** document title */ + string docTitle; + + string inFile, ///< input file name + outFile; ///< output file name + + /** Test if maskWsBegin and maskWsEnd should be applied */ + bool maskWs; + + /** Test if whitespace sould always be separated from enclosing tokens */ + bool excludeWs; + + /** Test if header and footer should be omitted */ + bool fragmentOutput; + + /** Test if line numbers should be printed */ + bool showLineNumbers; + + /** Test if leading spyce of line number should be filled with zeroes*/ + bool lineNumberFillZeroes; + + /** Flag to test if newlines should be printed */ + bool printNewLines; + + /** The base font to use */ + string baseFont ; + + /** The base font size to use */ + string baseFontSize ; + + /** Current line of input file*/ + string line; + + /** Current line number */ + unsigned int lineNumber; + + /**output line number count start */ + int lineNumberOffset; + + /** Current state*/ + State currentState; + + /** keyword class id, used to apply the corresponding keyword style*/ + unsigned int currentKeywordClass; + + /** Processes origin state */ + void processRootState(); + + /** \return line break sequence */ + virtual string getNewLine(); + + /** + \param s current state + \param kwClassID keyword class (has to be set when s=KEYWORD) + \return Index of style tag corresponding to the states + */ + unsigned int getStyleID ( State s, unsigned int kwClassID = 0 ); + + /** \return line index */ + unsigned int getLineIndex(); + + /** print all remaining white space*/ + void flushWs(); + + /** \return Content of user defined input style */ + string readUserStyleDef(); + + /** \return Style definition of the chosen output format */ + virtual string getStyleDefinition() {return "";}; + + /** \return true id encoding is defined */ + bool encodingDefined() {return StringTools::change_case ( encoding ) !="none";} + + /** contains white space, which will be printed after a closing tag */ + string wsBuffer; + + /** Flag to test if style definition should be included in output document */ + bool includeStyleDef; + + /** map which saves all lines that should be highlghted */ + map <int, string> markLines; + + /** Class for line wrapping and tab replacement*/ + PreFormatter preFormatter; + + private: + + CodeGenerator ( const CodeGenerator& ) {} + + CodeGenerator& operator= ( CodeGenerator& ) { return *this;} + + /** Insert line number at the beginning of current output line */ + virtual void insertLineNumber ( bool insertNewLine=true ); + + /** Prints document footer + @return footer */ + virtual string getFooter() = 0; + + /** Prints document body*/ + virtual void printBody() = 0; + + /** Prints document header + @return header + */ + virtual string getHeader() = 0; + + /** initialize tags in specific format according to colouring information provided in DucumentStyle */ + virtual void initOutputTags() = 0; + + /** \param keyword group id + \return open tag */ + virtual string getKeywordOpenTag ( unsigned int ) = 0; + + /** \param keyword group id + \return close tag */ + virtual string getKeywordCloseTag ( unsigned int ) = 0; + + /** return open tag to include ctags meta information + \param info tag information of current token + \return opening tag + */ + virtual string getMetaInfoOpenTag ( const TagInfo& info ) {return "";} + + /** return close tag of meta information + \return closing tag + */ + virtual string getMetaInfoCloseTag() {return "";} + + /** open a new tag, set current state to s*/ + void openTag ( State s ); + + /** close opened tag, clear current state */ + void closeTag ( State s ); + + /** close Keyword tag of corresponding style ID */ + void closeKWTag ( unsigned int styleID ); + + /** open Keyword tag of corresponding style ID */ + void openKWTag ( unsigned int styleID ); + + + + /*void closeTag ( unsigned int styleID ); + + void openTag ( unsigned int styleID );*/ + + /// path to style definition file + string themePath; + + /// path to host language definition + string hostLangDefPath; + + /// path to embedded language definition + string embedLangDefPath; + + /// name of nested language which starts the input (ie opening delim missing, but closing delim exists) + string embedLangStart; + + /// contains current position in line + unsigned int lineIndex; + + /// width of line numbering coloumn + unsigned int lineNumberWidth; + + /**maximum count of input lines to be processed*/ + unsigned int maxLineCnt; + + /**last character of the last line*/ + unsigned char terminatingChar; + + /** Class for reformatting */ + astyle::ASFormatter *formatter; + + /** Flag to test if formatting is enabled with current input document*/ + bool formattingEnabled; + + /** Flag to test if formatting is possible with current input document*/ + bool formattingPossible; + + /** Flag to test if input should be validated (binary or text) */ + bool validateInput; + + /** Flag to test if ctags information is available */ + bool tagsEnabled; + + /** Flag to test if trailing newline should be printed */ + bool noTrailingNewLine; + + /** flag which determines keyword output (unchangeed, uppercase, lowercase)*/ + StringTools::KeywordCase keywordCase; + + /** contains the current token*/ + string token; + + string styleInputPath, ///< style input file path + styleOutputPath; ///< style output file path + + /** end-of-line delimiter*/ + char eolDelimiter; + + /** Resets parser to origin state, call this after every file conversion */ + void reset(); + + /** read new line from in stream */ + bool readNewLine ( string &newLine ); + + /** return next character from in stream */ + unsigned char getInputChar(); + + /** output file type */ + OutputType outputType; + + /** return new state */ + State getCurrentState (); + + /* Methods that represent a parsing state */ + bool processKeywordState ( State myState ); ///< process keywords + bool processNumberState() ; ///< process numbers + bool processMultiLineCommentState(); ///< process multi line comments + bool processSingleLineCommentState(); ///< process single line comments + bool processStringState ( State oldState ); ///< process strings + bool processEscapeCharState(); ///< process escape characters + bool processDirectiveState(); ///< process directives + bool processTagState(); ///< process tags + bool processSymbolState(); ///< process symbols + void processWsState(); ///< process whitespace + bool processSyntaxChangeState(State myState ); ///< process syntax change of embedded languages + + /** print escaped token and clears it + \param addMetaInfo set true if token may have meta information + \param flushWhiteSpace set true if white space should be flushed + \param tcase keyword case + */ + void printMaskedToken ( bool addMetaInfo = false, bool flushWhiteSpace = true, + StringTools::KeywordCase tcase = StringTools::CASE_UNCHANGED ); + + /** look for special commands in comments + \return true if command was found + */ + bool checkSpecialCmd(); + + /** association of matched regexes and the corresponding keyword class ids*/ + map <int, ReGroup> regexGroups; + + /** test for regular expressions + \param line current input line*/ + void matchRegex ( const string &line ); + + /** \return true if input is no binary stream */ + bool validateInputStream(); + + void loadEmbeddedLang(const string&embedLangDefPath); + + }; + +} + +#endif diff --git a/support/highlight/src/core/configurationreader.cpp b/support/highlight/src/core/configurationreader.cpp new file mode 100644 index 0000000000..49b3cca2d4 --- /dev/null +++ b/support/highlight/src/core/configurationreader.cpp @@ -0,0 +1,112 @@ +/*************************************************************************** + configurationreader.cpp - description + ------------------- + begin : Son Nov 10 2002 + copyright : (C) 2002 by Andre Simon + email : andre.simon1@gmx.de + ***************************************************************************/ + + +/* +This file is part of Highlight. + +Highlight is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +Highlight is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Highlight. If not, see <http://www.gnu.org/licenses/>. +*/ + + +#include "configurationreader.h" + +#include <string> +#include <sstream> +#include <map> +#include <iostream> +#include <fstream> +#include <vector> + +#include "stringtools.h" + +using namespace std; + +ConfigurationReader::ConfigurationReader ( const string & configuration_path ) +{ + ifstream in ( configuration_path.c_str() ); + fileFound=in; + if ( fileFound ) + { + string line; + line.reserve ( 500 ); + size_t lineBegin; + size_t delimPos; + string paramName; + char suffix[10]; + int i=0; + + while ( getline ( in, line ) ) + { + lineBegin=line.find_first_not_of ( "\t " ); + if ( ( line.size() >2 ) && ( lineBegin!=string::npos ) + && ( line.at ( lineBegin ) !='#' ) ) //comment? + { + if ( line[lineBegin]=='$' ) // new parameter? + { + delimPos=line.find ( "=",lineBegin )-1; + if ( delimPos!=string::npos ) + { + paramName=StringTools::trimRight ( + StringTools::change_case ( line.substr ( lineBegin+1, delimPos ) ) ); + // if parameter already exists, make it unique + if ( parameterMap.count ( paramName ) ) + { + snprintf ( suffix, sizeof ( suffix ), "#%05d", ++i ); + paramName+=suffix; + } + parameterNames.push_back ( paramName ); + parameterMap[paramName] = line.substr ( delimPos+2, line.length() ); + } + } + else + { + parameterMap[paramName]+= ( " "+line ); + } + } + } + in.close(); + } +} + +ConfigurationReader::~ConfigurationReader() +{ +} + +bool ConfigurationReader::found() +{ + return fileFound; +} + +string &ConfigurationReader::getParameter ( const string & paramName ) +{ + return parameterMap[paramName] ; +} + +const char* ConfigurationReader::getCParameter ( const string & paramName ) +{ + return parameterMap[paramName].c_str() ; +} + +vector<string> &ConfigurationReader::getParameterNames() +{ + return parameterNames; +} + + diff --git a/support/highlight/src/core/configurationreader.h b/support/highlight/src/core/configurationreader.h new file mode 100644 index 0000000000..7755081c12 --- /dev/null +++ b/support/highlight/src/core/configurationreader.h @@ -0,0 +1,80 @@ +/*************************************************************************** + configurationreader.h - description + ------------------- + begin : Son Nov 10 2002 + copyright : (C) 2002 by Andre Simon + email : andre.simon1@gmx.de + ***************************************************************************/ + + +/* +This file is part of Highlight. + +Highlight is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +Highlight is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Highlight. If not, see <http://www.gnu.org/licenses/>. +*/ + + +#ifndef CONFIGURATIONREADER_H +#define CONFIGURATIONREADER_H + +#include <string> +#include <map> +#include <vector> + +using namespace std; + +/** Maps parameter keys to values*/ +typedef map<string, string> ParameterMap; + + +/** \brief Class to handle ASCII config files + + Configuration file format:<br> + $ParamName=ParamValue<br> + ParamValue may be splittet over multiple lines<br> + ParamName is not case sensitive<br> + Comments start with # as the first character of a line + + **/ + +class ConfigurationReader +{ + public: + /** Constructor + \param configuration_path Path to configuration file + */ + ConfigurationReader ( const string & configuration_path ); + ~ConfigurationReader(); + + /** \param paramName Name of parameter + \return Value of parameter */ + string &getParameter ( const string & paramName ); + + /** \param paramName Name of parameter + \return Value of parameter */ + const char* getCParameter ( const string & paramName ); + + /** \return True if config file exists */ + bool found(); + + /** \return List of parameter names */ + vector<string> &getParameterNames(); + + private: + ParameterMap parameterMap; + bool fileFound; + vector<string> parameterNames; +}; + +#endif diff --git a/support/highlight/src/core/ctagsreader.cpp b/support/highlight/src/core/ctagsreader.cpp new file mode 100644 index 0000000000..acfa35e649 --- /dev/null +++ b/support/highlight/src/core/ctagsreader.cpp @@ -0,0 +1,99 @@ +/*************************************************************************** + ctagsreader.h - description + ------------------- + begin : Tue Oct 21 2008 + copyright : (C) 2008 by Andre Simon + email : andre.simon1@gmx.de + ***************************************************************************/ + + +/* +This file is part of Highlight. + +Highlight is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +Highlight is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Highlight. If not, see <http://www.gnu.org/licenses/>. +*/ + + +#include "ctagsreader.h" + + +string TagInfo::getKind() const +{ + if ( kind.empty() ) return ""; + switch ( kind[0] ) + { + case 'c': return "class"; + case 'd': return "define"; + case 'e': return "enumerator"; + case 'f': return "function"; + case 'F': return "file"; + case 'g': return "enumeration name"; + case 'm': return "member"; + case 'n': return "namespace"; + case 'p': return "function prototype"; + case 's': return "structure name"; + case 't': return "typedef"; + case 'u': return "union name"; + case 'v': return "variable"; + default: return ""; + } +} + +bool CTagsReader::load ( const string & ctags_path ) +{ + ifstream in ( ctags_path.c_str() ); + if ( in ) + { + string line; + string tagname, + tagfile, + dummy1, + dummy2, + kind, + name_space, + file; + TagInfo info; + line.reserve ( 250 ); + while ( getline ( in, line ) && line.size() ) + { + if ( line[0]=='!' ) + { + continue; + } + + istringstream tagStream ( line ); + if ( !getline ( tagStream, tagname, '\t' ) ) continue; + if ( !getline ( tagStream, tagfile, '\t' ) ) continue; + if ( !getline ( tagStream, dummy1, '\t' ) ) continue; + if ( !getline ( tagStream, dummy2, '\t' ) ) continue; + if (dummy2.empty()) { + while (dummy2.empty()) { + if ( !getline ( tagStream, dummy2, '\t' ) ) continue; + } + } + if ( !getline ( tagStream, kind, '\t' ) ) continue; + name_space.clear(); file.clear(); + getline ( tagStream, name_space, '\t' ); + + info.file=tagfile; + info.kind=kind; + info.name_space=name_space; + //info.tag_exists=true; + tags[tagname] = info; + } + in.close(); + return true; + } + return false; +} diff --git a/support/highlight/src/core/ctagsreader.h b/support/highlight/src/core/ctagsreader.h new file mode 100644 index 0000000000..3686242dda --- /dev/null +++ b/support/highlight/src/core/ctagsreader.h @@ -0,0 +1,104 @@ +/*************************************************************************** + ctagsreader.h - description + ------------------- + begin : Tue Oct 21 2008 + copyright : (C) 2008 by Andre Simon + email : andre.simon1@gmx.de + ***************************************************************************/ + + +/* +This file is part of Highlight. + +Highlight is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +Highlight is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Highlight. If not, see <http://www.gnu.org/licenses/>. +*/ + + +#ifndef CTAGSREADER_H +#define CTAGSREADER_H + +#include <string> +#include <sstream> +#include <map> +#include <iostream> +#include <fstream> + +using namespace std; + +/** TagInfo contains information about a ctags tag */ +class TagInfo +{ + public: + TagInfo() {}; + string getKind() const; + string file, kind, name_space; + +}; + +/** Maps parameter keys to values*/ +typedef map<string, TagInfo> TagsMap; + +class CTagsReader +{ + public: + + CTagsReader() {}; + ~CTagsReader() {}; + + /** load ctags file + \param ctags_path Path to ctags file + \return true if successfull + */ + bool load ( const string & ctags_path ); + + /** test if tag infoation exists + \param tagname tag ot highlight token + \return true if tag information exists + */ + bool tagExists ( const string& tagname ) + { + return tags.count ( tagname ) >0; + } + + /** return tag info, call tagExists first to avoid growing map + \param tagname tag ot highlight token + \return tag info + */ + TagInfo getTagInfo ( const string &tagname ) + { + return tags[tagname]; + } + + private: + + TagsMap tags; +}; + +/* + c class name + d define (from #define XXX) + e enumerator + f function or method name + F file name + g enumeration name + m member (of structure or class data) + p function prototype + s structure name + t typedef + u union name + v variable + +*/ + +#endif diff --git a/support/highlight/src/core/datadir.cpp b/support/highlight/src/core/datadir.cpp new file mode 100644 index 0000000000..faa929301a --- /dev/null +++ b/support/highlight/src/core/datadir.cpp @@ -0,0 +1,181 @@ +/*************************************************************************** + dataDir.cpp - description + ------------------- + begin : Sam March 1 2003 + copyright : (C) 2003 by André Simon + email : andre.simon1@gmx.de + ***************************************************************************/ + + +/* +This file is part of Highlight. + +Highlight is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +Highlight is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Highlight. If not, see <http://www.gnu.org/licenses/>. +*/ + + +#include <string> +#include <fstream> +#include <vector> +#include "platform_fs.h" + +#include "datadir.h" + +using namespace std; + +string DataDir::LSB_DATA_DIR="/usr/share/highlight/"; +string DataDir::LSB_CFG_DIR="/etc/highlight/"; +string DataDir::LSB_DOC_DIR="/usr/share/doc/highlight/"; + + +bool DataDir::searchDataDir ( const string &userDefinedDir ) +{ + +#ifndef _WIN32 + bool found = false; + + vector <string> possibleDirs; + if ( !userDefinedDir.empty() ) possibleDirs.push_back ( userDefinedDir ); +// if (!additionalDataDir.empty()) possibleDirs.push_back(additionalDataDir); +#ifdef HL_DATA_DIR + possibleDirs.push_back ( HL_DATA_DIR ); +#endif + possibleDirs.push_back ( LSB_DATA_DIR ); + + for ( unsigned int i=0;i<possibleDirs.size();i++ ) + { + if ( fileExists ( possibleDirs[i] ) ) + { + dataDir=possibleDirs[i]; + found = true; break; + } + } + return found; +#else + dataDir=userDefinedDir; + return true; +#endif +} + +DataDir::DataDir() +{ +} + +void DataDir::setAdditionalDataDir ( const string& dir ) +{ + additionalDataDir=dir; +} +void DataDir::setAdditionalConfDir ( const string& dir ) +{ + additionalConfDir=dir; +} + +const string & DataDir::getAdditionalDataDir() +{ + return additionalDataDir; +} + +const string & DataDir::getAdditionalConfDir() +{ + return additionalConfDir; +} + +const string &DataDir::getDir() +{ + return dataDir; +} + +const string DataDir::getLangPath ( const string & file, bool forceDefault ) +{ + if ( !forceDefault && !additionalDataDir.empty() ) + { + string path=getAdditionalLangDefDir() +file; + if ( fileExists ( path ) ) + { + return path; + } + } + return dataDir+"langDefs"+Platform::pathSeparator+file; +} + +const string DataDir::getThemePath ( const string & file, bool forceDefault ) +{ + if ( !forceDefault && !additionalDataDir.empty() ) + { + string path=getAdditionalThemeDir() +file; + if ( fileExists ( path ) ) + { + return path; + } + } + return dataDir+"themes"+Platform::pathSeparator+file; +} + +const string DataDir::getConfDir ( bool forceDefault ) +{ + if ( !forceDefault && !additionalConfDir.empty() ) + { + return additionalConfDir; + } +#ifndef _WIN32 +#ifdef HL_CONFIG_DIR + return HL_CONFIG_DIR; +#else + return LSB_CFG_DIR; +#endif +#else + return getDir(); +#endif +} + +const string DataDir::getAdditionalLangDefDir() +{ + return additionalDataDir+"langDefs"+Platform::pathSeparator; +} + +const string DataDir::getAdditionalThemeDir() +{ + return additionalDataDir+"themes"+Platform::pathSeparator; +} + +const string DataDir::getI18nDir() +{ + return dataDir+"gui_files"+Platform::pathSeparator+"i18n"+Platform::pathSeparator; +} + +const string DataDir::getExtDir() +{ + return dataDir+"gui_files"+Platform::pathSeparator+"ext"+Platform::pathSeparator; +} + +const string DataDir::getDocDir() +{ +#ifndef _WIN32 +#ifdef HL_DOC_DIR + return HL_CONFIG_DIR; +#else + return LSB_DOC_DIR; +#endif +#else + return getDir(); +#endif +} + +bool DataDir::fileExists ( const string&f ) +{ + ifstream file ( f.c_str() ); + bool exists=!file.fail(); + file.close(); + return exists; +} diff --git a/support/highlight/src/core/datadir.h b/support/highlight/src/core/datadir.h new file mode 100644 index 0000000000..1c180156e2 --- /dev/null +++ b/support/highlight/src/core/datadir.h @@ -0,0 +1,108 @@ +/*************************************************************************** + datadir.h - description + ------------------- + begin : Sam March 1 2003 + copyright : (C) 2003 by Andre Simon + email : andre.simon1@gmx.de + ***************************************************************************/ + + +/* +This file is part of Highlight. + +Highlight is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +Highlight is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Highlight. If not, see <http://www.gnu.org/licenses/>. +*/ + + +#ifndef DATADIR_H +#define DATADIR_H + +using namespace std; + +/** \brief Manages access to installation directories. + + Apart from the standard installation directory, one can define additional + search paths. If the additonal paths do not exist, the default paths are + returned. + **/ + +class DataDir +{ + string dataDir; + string additionalDataDir; + string additionalConfDir; + bool fileExists ( const string& ); + + public: + + DataDir(); + + static string LSB_DATA_DIR; + static string LSB_CFG_DIR; + static string LSB_DOC_DIR; + + /** search for a valid installation directory + \param userDefinedDir Directory defined by user + \return True if directory was found */ + bool searchDataDir ( const string &userDefinedDir ); + + /** add another installation directory, which is added to search path + \param dir Directory defined by user */ + void setAdditionalDataDir ( const string& dir ); + + /** add another installation directory, which is added to search path + \param dir Directory defined by user */ + void setAdditionalConfDir ( const string& dir ); + + /** \return data Directory defined by user */ + const string & getAdditionalDataDir(); + + /** \return data Directory defined by user */ + const string & getAdditionalConfDir(); + + /** \return Data installation directory */ + const string & getDir() ; + + /** \param file filename + \param forceDefault set tue if additional directory should be ignored + \return Location of languafe definitions */ + const string getLangPath ( const string & file="", bool forceDefault=false ) ; + + /** \param file filename + \param forceDefault set tue if additional directory should be ignored + \return Location of themes */ + const string getThemePath ( const string & file="", bool forceDefault=false ) ; + + /** \return User defined location of languafe definitions */ + const string getAdditionalLangDefDir() ; + + /** \return User defined location of themes */ + const string getAdditionalThemeDir() ; + + /** \param forceDefault set tue if additional directory should be ignored + \return Location of configuration files */ + const string getConfDir ( bool forceDefault=false ) ; + + /** \return Location of GUI menu translation files */ + const string getI18nDir(); + + /** \return Location of GUI file extension filter files */ + const string getExtDir(); + + /** \return Location of documentation (README) files (GUI) */ + const string getDocDir(); + +}; + +#endif diff --git a/support/highlight/src/core/documentstyle.cpp b/support/highlight/src/core/documentstyle.cpp new file mode 100644 index 0000000000..9c5f7307d5 --- /dev/null +++ b/support/highlight/src/core/documentstyle.cpp @@ -0,0 +1,168 @@ +/*************************************************************************** + documentstyle.cpp - description + ------------------- + begin : Son Nov 10 2002 + copyright : (C) 2002 by Andre Simon + email : andre.simon1@gmx.de + ***************************************************************************/ + + +/* +This file is part of Highlight. + +Highlight is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +Highlight is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Highlight. If not, see <http://www.gnu.org/licenses/>. +*/ + + +#include "documentstyle.h" +#include "stringtools.h" + +namespace highlight +{ + + DocumentStyle::DocumentStyle ( const string &styleDefinitionFile ) + { + fileFound=load ( styleDefinitionFile ); + } + DocumentStyle::DocumentStyle() :fileFound ( false ) + {} + + bool DocumentStyle::load ( const string &styleDefinitionPath ) + { + ConfigurationReader styleConfig ( styleDefinitionPath ); + fileFound = false; + if ( styleConfig.found() ) + { + fontsize = styleConfig.getParameter ( "fontsize" ); + bgColour.setRGB ( styleConfig.getParameter ( "bgcolour" ) ); + defaultElem.set ( styleConfig.getParameter ( "defaultcolour" ) ); + comment.set ( styleConfig.getParameter ( "comment" ) ); + directive.set ( styleConfig.getParameter ( "directive" ) ); + str.set ( styleConfig.getParameter ( "string" ) ); + escapeChar.set ( styleConfig.getParameter ( "escapechar" ) ); + number.set ( styleConfig.getParameter ( "number" ) ); + dstr.set ( styleConfig.getParameter ( "string-directive" ) ); + line.set ( styleConfig.getParameter ( "line" ) ); + symbol.set ( styleConfig.getParameter ( "symbol" ) ); + markLineColour.setRGB ( styleConfig.getParameter ( "mark-line" ) ); + + string tmpstr; + // TODO: Remove this check as soon as all themes have a sl-comment attribute + tmpstr=styleConfig.getParameter ( "sl-comment" ); + if ( tmpstr.empty() ) + { + tmpstr=styleConfig.getParameter ( "comment" ); + } + slcomment.set ( tmpstr ); + + string paramVal; + vector<string> paramNames=styleConfig.getParameterNames(); + + //collect keyword groups, save corresponding style definition + for ( unsigned int i=0;i<paramNames.size();i++ ) + { + paramVal=paramNames[i]; + if ( paramVal.find ( "kw-group" ) != string::npos) + { + keywordStyles.insert ( make_pair ( StringTools::getParantheseVal ( paramVal ), + ElementStyle ( styleConfig.getParameter ( paramVal ) ) ) ); + } + } + fileFound = true; + } + return fileFound; + } + + DocumentStyle::~DocumentStyle() + { + } + + string DocumentStyle::getFontSize() const + { + return fontsize; + } + Colour DocumentStyle::getBgColour() const + { + return bgColour; + } + Colour DocumentStyle::getMarkLineColour() const + { + return markLineColour; + } + ElementStyle DocumentStyle::getDefaultStyle() const + { + return defaultElem; + } + ElementStyle DocumentStyle::getCommentStyle() const + { + return comment; + } + ElementStyle DocumentStyle::getSingleLineCommentStyle() const + { + return slcomment; + } + ElementStyle DocumentStyle::getStringStyle() const + { + return str; + } + ElementStyle DocumentStyle::getDirectiveStringStyle() const + { + return dstr; + } + ElementStyle DocumentStyle::getEscapeCharStyle() const + { + return escapeChar; + } + ElementStyle DocumentStyle::getNumberStyle() const + { + return number; + } + ElementStyle DocumentStyle::getDirectiveStyle() const + { + return directive; + } + ElementStyle DocumentStyle::getLineStyle() const + { + return line; + } + ElementStyle DocumentStyle::getSymbolStyle() const + { + return symbol; + } + bool DocumentStyle::found () const + { + return fileFound; + } + ElementStyle DocumentStyle::getKeywordStyle ( const string &className ) + { + if ( !keywordStyles.count ( className ) ) return defaultElem; + return keywordStyles[className]; + } + + vector <string> DocumentStyle::getClassNames() const + { + vector <string> kwClassNames; + for ( KSIterator iter = keywordStyles.begin(); iter != keywordStyles.end(); iter++ ) + { + kwClassNames.push_back ( ( *iter ).first ); + } + return kwClassNames; + } + + KeywordStyles DocumentStyle::getKeywordStyles() const + { + return keywordStyles; + } + +} diff --git a/support/highlight/src/core/documentstyle.h b/support/highlight/src/core/documentstyle.h new file mode 100644 index 0000000000..46d8aa5e7a --- /dev/null +++ b/support/highlight/src/core/documentstyle.h @@ -0,0 +1,138 @@ +/*************************************************************************** + documentstyle.h - description + ------------------- + begin : Son Nov 10 2002 + copyright : (C) 2002-2007 by Andre Simon + email : andre.simon1@gmx.de + ***************************************************************************/ + + +/* +This file is part of Highlight. + +Highlight is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +Highlight is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Highlight. If not, see <http://www.gnu.org/licenses/>. +*/ + + +#ifndef DOCUMENTSTYLE_H +#define DOCUMENTSTYLE_H + +#include <string> +#include "configurationreader.h" +#include "elementstyle.h" +#include "stylecolour.h" + +using namespace std; + +namespace highlight +{ + + /** maps keyword class names and the corresponding formatting information*/ + typedef map <string, ElementStyle> KeywordStyles; + + /** iterator for keyword styles*/ + typedef KeywordStyles::const_iterator KSIterator; + + /** \brief Contains information about document formatting properties. + * @author Andre Simon + */ + + class DocumentStyle + { + private: + ElementStyle comment, slcomment, str, dstr, + escapeChar, number, directive, line, symbol; + ElementStyle defaultElem; + Colour bgColour; + Colour markLineColour; + + string fontsize; + bool fileFound; + + KeywordStyles keywordStyles; + + public: + /** Constructor + \param styleDefinitionPath Style definition path */ + DocumentStyle ( const string & styleDefinitionPath ); + + /** Constructor */ + DocumentStyle(); + ~DocumentStyle(); + + /** load style definition + \param styleDefinitionFile Style definition path + \return True if successfull */ + bool load ( const string & styleDefinitionFile ); + + /** \return class names defined in the theme file */ + vector <string> getClassNames() const; + + /** \return keyword styles */ + KeywordStyles getKeywordStyles() const; + + /** \return Font size */ + string getFontSize() const; + + /** \return Background colour*/ + Colour getBgColour() const; + + /** \return Mark line colour*/ + Colour getMarkLineColour() const; + + /** \return Style of default (unrecognized) strings */ + ElementStyle getDefaultStyle() const; + + /** \return Comment style*/ + ElementStyle getCommentStyle() const; + + /** \return Single line comment style*/ + ElementStyle getSingleLineCommentStyle() const; + + /** \return String style*/ + ElementStyle getStringStyle() const; + + /** \return Directive line string style*/ + ElementStyle getDirectiveStringStyle() const; + + /** \return Escape character style*/ + ElementStyle getEscapeCharStyle() const; + + /** \return Number style*/ + ElementStyle getNumberStyle() const; + + /** \return Directive style*/ + ElementStyle getDirectiveStyle() const; + + /** \return Type style*/ + ElementStyle getTypeStyle() const; + + /** \return Line number style*/ + ElementStyle getLineStyle() const; + + /** \return Bracket style*/ + ElementStyle getSymbolStyle() const; + + /** \param className Name of keyword class (eg kwa, kwb, .., kwd) + \return keyword style of the given className + */ + ElementStyle getKeywordStyle ( const string &className ) ; + + /** \return True if language definition was found */ + bool found() const ; + }; + +} + +#endif diff --git a/support/highlight/src/core/elementstyle.cpp b/support/highlight/src/core/elementstyle.cpp new file mode 100644 index 0000000000..b1a5e408b7 --- /dev/null +++ b/support/highlight/src/core/elementstyle.cpp @@ -0,0 +1,111 @@ +/*************************************************************************** + elementstyle.cpp - description + ------------------- + begin : Son Nov 10 2002 + copyright : (C) 2002-2007 by Andre Simon + email : andre.simon1@gmx.de + ***************************************************************************/ + +/* +This file is part of Highlight. + +Highlight is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +Highlight is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Highlight. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include <sstream> +#include "elementstyle.h" + +namespace highlight +{ + + ElementStyle::ElementStyle (const Colour &col, bool b, bool i, bool u ) + : colour ( col ) , bold ( b ), italic ( i ), underline ( u ) + {} + + ElementStyle:: ElementStyle ( const string & elementStyleString ) + : bold ( false ), italic ( false ), underline ( false ) + { + set ( elementStyleString ); + } + + ElementStyle::ElementStyle() + : bold ( false ), italic ( false ), underline ( false ) + {} + + void ElementStyle::set ( const string & elementStyleString ) + { + istringstream valueStream ( elementStyleString ); + string r, g, b, attr; + + char c='\0'; + valueStream >> c; + + if ( c=='#' ) + { + string htmlNotation; + valueStream >> htmlNotation; + if ( htmlNotation.size() < 6 ) return; + r = htmlNotation.substr ( 0, 2 ); + g = htmlNotation.substr ( 2, 2 ); + b = htmlNotation.substr ( 4, 2 ); + } + else + { + valueStream.putback ( c ); + valueStream >> r; + valueStream >> g; + valueStream >> b; + } + + colour.setRed ( r ); + colour.setGreen ( g ); + colour.setBlue ( b ); + while ( valueStream >> attr ) + { + if ( attr=="italic" ) + { + italic = true; + } + else if ( attr=="bold" ) + { + bold = true; + } + else if ( attr=="underline" ) + { + underline = true; + } + } + } + + ElementStyle::~ElementStyle() + {} + + bool ElementStyle::isItalic() const + { + return italic; + } + bool ElementStyle::isBold() const + { + return bold; + } + bool ElementStyle::isUnderline() const + { + return underline; + } + Colour ElementStyle::getColour() const + { + return colour; + } + +} diff --git a/support/highlight/src/core/elementstyle.h b/support/highlight/src/core/elementstyle.h new file mode 100644 index 0000000000..45a7c5cc44 --- /dev/null +++ b/support/highlight/src/core/elementstyle.h @@ -0,0 +1,121 @@ +/*************************************************************************** + elementstyle.h - description + ------------------- + begin : Son Nov 10 2002 + copyright : (C) 2002-2007 by Andre Simon + email : andre.simon1@gmx.de + ***************************************************************************/ + + +/* +This file is part of Highlight. + +Highlight is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +Highlight is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Highlight. If not, see <http://www.gnu.org/licenses/>. +*/ + + +#ifndef ELEMENTSTYLE_H +#define ELEMENTSTYLE_H + +#include "stylecolour.h" + +using namespace std; + +namespace highlight +{ + + /** \brief The class stores the basic text formatting properties. + + * @author Andre Simon + */ + + class ElementStyle + { + public: + + /** Constructor + \param col Style colour + \param b Bold flag + \param i Italic flag + \param u Underline flag */ + ElementStyle ( const Colour& col, bool b, bool i, bool u ); + + /** Constuctor + \param elementStyleString String with formatting information (eg "00 aa ff bold") */ + ElementStyle ( const string & elementStyleString ); + + /** Constuctor */ + ElementStyle(); + + /**copy constructor */ + ElementStyle ( const ElementStyle &other ) + { + colour = other.getColour(); + bold = other.isBold(); + italic = other.isItalic(); + underline = other.isUnderline(); + } + + /** operator overloading */ + ElementStyle& operator= ( const ElementStyle &other ) + { + colour = other.getColour(); + bold = other.isBold(); + italic = other.isItalic(); + underline = other.isUnderline(); + return *this; + } + + ~ElementStyle(); + + /** initialize object + \param elementStyleString String which contains formatting attributes + (Format: "color attr" where + color can be HTML hex notation or a hex RGB tuple (ie "#2244ff" or "22 44 ff") + attr can be a combination of "italic, "bold" and "underline") + */ + void set ( const string & elementStyleString ); + + /** \return True if italic */ + bool isItalic() const; + + /** \return True if bold */ + bool isBold() const; + + /** \return True if underline */ + bool isUnderline() const; + + /** \param b set italic flag */ + void setItalic ( bool b ) {italic = b;} + + /** \param b set bold flag */ + void setBold ( bool b ) { bold = b; } + + /** \param b set underline flag */ + void setUnderline ( bool b ) {underline = b; } + + /** \return Element colour */ + Colour getColour() const; + + /** \param col colour of this element */ + void setColour (const Colour& col ) {colour = col;} + + private: + Colour colour; + bool bold, italic, underline; + }; + +} + +#endif diff --git a/support/highlight/src/core/enums.h b/support/highlight/src/core/enums.h new file mode 100644 index 0000000000..0b5609dc0d --- /dev/null +++ b/support/highlight/src/core/enums.h @@ -0,0 +1,109 @@ + +/* +This file is part of Highlight. + +Highlight is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +Highlight is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Highlight. If not, see <http://www.gnu.org/licenses/>. +*/ + + +#ifndef ENUMS_H +#define ENUMS_H + +namespace highlight +{ + + /** states which may occour during input file parsing + TODO Clean up! + */ + enum State + { + STANDARD=0, + STRING, + NUMBER, + SL_COMMENT, + ML_COMMENT, + ESC_CHAR, + DIRECTIVE, + DIRECTIVE_STRING, + LINENUMBER, + SYMBOL, + + // don't use constants > 10 as array indices! + KEYWORD, + STRING_END, + NUMBER_END, + SL_COMMENT_END, + ML_COMMENT_END, + ESC_CHAR_END, + DIRECTIVE_END, + SYMBOL_END, + KEYWORD_END, + IDENTIFIER_BEGIN, + IDENTIFIER_END, + EMBEDDED_CODE_BEGIN, + EMBEDDED_CODE_END, + EMBEDDED_PERL_HACK, + + _UNKNOWN=100, + _EOL, + _EOF, + _WS + } ; + + /** Parser return values*/ + enum ParseError + { + PARSE_OK, + BAD_INPUT=1, + BAD_OUTPUT=2, + BAD_STYLE=4, + BAD_BINARY=8 + }; + + /** line wrapping modes*/ + enum WrapMode + { + WRAP_DISABLED, + WRAP_SIMPLE, + WRAP_DEFAULT + }; + + /** language definition loading results*/ + enum LoadResult + { + LOAD_FAILED, + LOAD_FAILED_REGEX, + LOAD_NEW, + LOAD_NONE + }; + + /** output formats */ + enum OutputType + { + HTML, + XHTML, + TEX, + LATEX, + RTF, + XML, + ANSI, + XTERM256, + HTML32, + SVG, + BBCODE + }; + +} + +#endif diff --git a/support/highlight/src/core/htmlgenerator.cpp b/support/highlight/src/core/htmlgenerator.cpp new file mode 100644 index 0000000000..b21421c51c --- /dev/null +++ b/support/highlight/src/core/htmlgenerator.cpp @@ -0,0 +1,477 @@ +/*************************************************************************** + htmlgenerator.cpp - description + ------------------- + begin : Wed Nov 28 2001 + copyright : (C) 2001-2007 by Andre Simon + email : andre.simon1@gmx.de + ***************************************************************************/ + + +/* +This file is part of Highlight. + +Highlight is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +Highlight is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Highlight. If not, see <http://www.gnu.org/licenses/>. +*/ + + +#include <fstream> +#include <iostream> +#include <sstream> + +#include "htmlgenerator.h" +#include "version.h" + +using namespace std; + +namespace highlight +{ + + HtmlGenerator::HtmlGenerator () : + CodeGenerator ( HTML ), + brTag ( "<br>" ), + hrTag ( "<hr>" ), + idAttr ( "name" ), + fileSuffix ( ".html" ), + cssClassName ( "hl" ), + orderedList ( false ), + useInlineCSS ( false ), + enclosePreTag ( false ), + attachAnchors ( false ), + anchorPrefix ( "l" ) + { + spacer = " "; + styleCommentOpen="/*"; + styleCommentClose="*/"; + } + + string HtmlGenerator::getHeader() + { + ostringstream os; + os << getHeaderStart ( docTitle ); + if ( !useInlineCSS ) + { + if ( includeStyleDef ) + { + os << "<style type=\"text/css\">\n<!--\n"; + os << getStyleDefinition(); + os << CodeGenerator::readUserStyleDef(); + os << "//-->\n</style>\n"; + } + else + { + os << "<link rel=\"stylesheet\" type=\"text/css\" href=\"" + << getStyleOutputPath() + << "\">\n"; + } + os << "</head>\n<body class=\"" << cssClassName + << "\">\n"; + } + else + { + os << "</head>\n<body style=\"" + << "background-color:#" + << ( docStyle.getBgColour().getRed ( HTML ) ) + << ( docStyle.getBgColour().getGreen ( HTML ) ) + << ( docStyle.getBgColour().getBlue ( HTML ) ) + << "\">\n"; + } + + return os.str(); + } + + string HtmlGenerator::getFooter() + { + return getGeneratorComment(); + } + + void HtmlGenerator::printBody() + { + if ( !fragmentOutput || enclosePreTag ) + { + if ( !useInlineCSS ) + { + *out << "<pre class=\"" << cssClassName + << "\">"; + } + else + { + *out << "<pre style=\"" + << "color:#" + << ( docStyle.getDefaultStyle().getColour().getRed ( HTML ) ) + << ( docStyle.getDefaultStyle().getColour().getGreen ( HTML ) ) + << ( docStyle.getDefaultStyle().getColour().getBlue ( HTML ) ) + << "; background-color:#" + << ( docStyle.getBgColour().getRed ( HTML ) ) + << ( docStyle.getBgColour().getGreen ( HTML ) ) + << ( docStyle.getBgColour().getBlue ( HTML ) ) + << "; font-size:" << this->getBaseFontSize() + << "pt; font-family:'" << this->getBaseFont() <<"';\">"; + } + } + if ( showLineNumbers && orderedList ) *out << "<ol>"; + + processRootState(); + + if ( showLineNumbers && orderedList ) *out << "\n</ol>"; + + if ( !fragmentOutput || enclosePreTag ) *out << "</pre>"; + } + + + void HtmlGenerator::initOutputTags () + { + openTags.push_back ( "" ); + if ( useInlineCSS ) + { + //embedBlockOpen = "<div style=\"background-color:#efefef;\">"; + openTags.push_back ( getOpenTag ( docStyle.getStringStyle() ) ); + openTags.push_back ( getOpenTag ( docStyle.getNumberStyle() ) ); + openTags.push_back ( getOpenTag ( docStyle.getSingleLineCommentStyle() ) ); + openTags.push_back ( getOpenTag ( docStyle.getCommentStyle() ) ); + openTags.push_back ( getOpenTag ( docStyle.getEscapeCharStyle() ) ); + openTags.push_back ( getOpenTag ( docStyle.getDirectiveStyle() ) ); + openTags.push_back ( getOpenTag ( docStyle.getDirectiveStringStyle() ) ); + openTags.push_back ( getOpenTag ( docStyle.getLineStyle() ) ); + openTags.push_back ( getOpenTag ( docStyle.getSymbolStyle() ) ); + } + else + { + //embedBlockOpen = "<div style=\"background-color:#efefef;\">"; + openTags.push_back ( getOpenTag ( STY_NAME_STR ) ); + openTags.push_back ( getOpenTag ( STY_NAME_NUM ) ); + openTags.push_back ( getOpenTag ( STY_NAME_SLC ) ); + openTags.push_back ( getOpenTag ( STY_NAME_COM ) ); + openTags.push_back ( getOpenTag ( STY_NAME_ESC ) ); + openTags.push_back ( getOpenTag ( STY_NAME_DIR ) ); + openTags.push_back ( getOpenTag ( STY_NAME_DST ) ); + openTags.push_back ( getOpenTag ( STY_NAME_LIN ) ); + openTags.push_back ( getOpenTag ( STY_NAME_SYM ) ); + } + + closeTags.push_back ( "" ); + for ( int i=1;i<NUMBER_BUILTIN_STATES; i++ ) + { + closeTags.push_back ( "</span>" ); + } + //embedBlockClose = "</div>"; + } + + string HtmlGenerator::getAttributes ( const string & elemName, const ElementStyle & elem ) + { + ostringstream s; + if ( !elemName.empty() ) + { + s << "."<<cssClassName<<"."<<elemName<<" { "; + } + s << "color:#" + << ( elem.getColour().getRed ( HTML ) ) + << ( elem.getColour().getGreen ( HTML ) ) + << ( elem.getColour().getBlue ( HTML ) ) + << ( elem.isBold() ? "; font-weight:bold" :"" ) + << ( elem.isItalic() ? "; font-style:italic" :"" ) + << ( elem.isUnderline() ? "; text-decoration:underline" :"" ); + if ( !elemName.empty() ) + { + s << "; }\n" ; + } + return s.str(); + } + + string HtmlGenerator::getOpenTag ( const string& styleName ) + { + return "<span class=\""+cssClassName+ " " + styleName + "\">"; + } + + string HtmlGenerator::getOpenTag ( const ElementStyle & elem ) + { + return "<span style=\""+getAttributes ( "",elem ) + "\">"; + } + + string HtmlGenerator::getGeneratorComment() + { + ostringstream s; + s <<"\n</body>\n</html>\n<!--HTML generated by highlight " + << HIGHLIGHT_VERSION << ", " << HIGHLIGHT_URL <<"-->\n"; + + return s.str(); + } + + string HtmlGenerator::getStyleDefinition() + { + if ( styleDefinitionCache.empty() ) + { + ostringstream os; + os << "body."<<cssClassName<<"\t{ background-color:#" + << ( docStyle.getBgColour().getRed ( HTML ) ) + << ( docStyle.getBgColour().getGreen ( HTML ) ) + << ( docStyle.getBgColour().getBlue ( HTML ) ) + << "; }\n"; + os << "pre."<<cssClassName<<"\t{ color:#" + << ( docStyle.getDefaultStyle().getColour().getRed ( HTML ) ) + << ( docStyle.getDefaultStyle().getColour().getGreen ( HTML ) ) + << ( docStyle.getDefaultStyle().getColour().getBlue ( HTML ) ) + << "; background-color:#" + << ( docStyle.getBgColour().getRed ( HTML ) ) + << ( docStyle.getBgColour().getGreen ( HTML ) ) + << ( docStyle.getBgColour().getBlue ( HTML ) ) + << "; font-size:" << this->getBaseFontSize(); + + os << "pt; font-family:'" << this->getBaseFont() << "';}\n"; + + if ( orderedList ) + { + os << "li."<<cssClassName<<"\t{ margin-bottom:-"<<this->getBaseFontSize() <<"pt; }\n"; + } + + os << getAttributes ( STY_NAME_NUM, docStyle.getNumberStyle() ) + << getAttributes ( STY_NAME_ESC, docStyle.getEscapeCharStyle() ) + << getAttributes ( STY_NAME_STR, docStyle.getStringStyle() ) + << getAttributes ( STY_NAME_DST, docStyle.getDirectiveStringStyle() ) + << getAttributes ( STY_NAME_SLC, docStyle.getSingleLineCommentStyle() ) + << getAttributes ( STY_NAME_COM, docStyle.getCommentStyle() ) + << getAttributes ( STY_NAME_DIR, docStyle.getDirectiveStyle() ) + << getAttributes ( STY_NAME_SYM, docStyle.getSymbolStyle() ) + << getAttributes ( STY_NAME_LIN, docStyle.getLineStyle() ); + + os << "."<<cssClassName<<".mark\t{ background-color:#" + << ( docStyle.getMarkLineColour().getRed ( HTML ) ) + << ( docStyle.getMarkLineColour().getGreen ( HTML ) ) + << ( docStyle.getMarkLineColour().getBlue ( HTML ) ) + << ";}\n"; + + KeywordStyles styles = docStyle.getKeywordStyles(); + for ( KSIterator it=styles.begin(); it!=styles.end(); it++ ) + { + os << getAttributes ( it->first, it->second ); + } + styleDefinitionCache=os.str(); + } + return styleDefinitionCache; + } + + string HtmlGenerator::maskCharacter ( unsigned char c ) + { + switch ( c ) + { + case '<' : + return "<"; + break; + case '>' : + return ">"; + break; + case '&' : + return "&"; + break; + case '\"' : + return """; + break; + + case '@' : + return "@"; + break; + + default : + return string ( 1, c ); + } + } + + string HtmlGenerator::getNewLine() + { + + string nlStr; + + if ( markLines.count ( lineNumber-1 ) ) nlStr +="</span>"; + + if ( showLineNumbers && orderedList ) nlStr +="</li>"; + /// set wrapping arrow if previous line was wrapped + //else if (preFormatter.isWrappedLine(lineNumber-1)) nlStr += "↵"; + + if (printNewLines) nlStr+="\n"; + + return nlStr; + } + + void HtmlGenerator::insertLineNumber ( bool insertNewLine ) + { + if ( insertNewLine ) + { + wsBuffer += getNewLine(); + } + if ( showLineNumbers ) + { + ostringstream numberPrefix; + int lineNo = lineNumber+lineNumberOffset; + if ( orderedList ) + { + if ( useInlineCSS ) + { + numberPrefix<<"<li style=\""<<getAttributes ( "", docStyle.getLineStyle() ) <<"\">"; + } + else + { + numberPrefix<<"<li class=\""<<cssClassName<<"\">"; + } + // Opera 8 ignores empty list items -> add + if ( line.empty() ) numberPrefix<<" "; + } + if ( attachAnchors ) + numberPrefix << "<a " + << idAttr + << "=\"" + << anchorPrefix + << "_" + << lineNo + << "\"></a>"; + + if ( !orderedList ) + { + ostringstream os; + if ( lineNumberFillZeroes ) os.fill ( '0' ); + os <<setw ( getLineNumberWidth() ) <<right<< lineNo; + numberPrefix << openTags[LINENUMBER] + << os.str() + << spacer + << closeTags[LINENUMBER]; + } + wsBuffer += numberPrefix.str(); + } + + if ( markLines.count ( lineNumber ) ) + { + if ( useInlineCSS ) + { + ostringstream markingFmt; + markingFmt <<"<span style=\"" + <<"background-color:#" + << ( docStyle.getMarkLineColour().getRed ( HTML ) ) + << ( docStyle.getMarkLineColour().getGreen ( HTML ) ) + << ( docStyle.getMarkLineColour().getBlue ( HTML ) ) + << ";\""; + wsBuffer+=markingFmt.str(); + } + else + { + wsBuffer +="<span class=\""+cssClassName+" mark\""; + } + if ( !markLines[lineNumber].empty() ) + wsBuffer +=" title=\""+markLines[lineNumber]+"\""; + wsBuffer +=">"; + } + + } + + string HtmlGenerator::getHeaderStart ( const string &title ) + { + ostringstream header; + header<< "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\">" + << "\n<html>\n<head>\n"; + if ( encodingDefined() ) + { + header << "<meta http-equiv=\"content-type\" content=\"text/html; charset=" + << encoding + << "\">\n"; + } + header << "<title>" + << title + << "</title>\n"; + return header.str(); + } + + bool HtmlGenerator::printIndexFile ( const vector<string> &fileList, + const string &outPath ) + { + string suffix = fileSuffix; + string outFilePath = outPath + "index" + suffix; + ofstream indexfile ( outFilePath.c_str() ); + + if ( !indexfile.fail() ) + { + string inFileName; + string inFilePath, newInFilePath; + indexfile << getHeaderStart ( "Source Index" ); + indexfile << "</head>\n<body>\n<h1> Source Index</h1>\n" + << hrTag + << "\n<ul>\n"; + string::size_type pos; + for ( unsigned int i=0; i < fileList.size(); i++ ) + { + pos= ( fileList[i] ).find_last_of ( Platform::pathSeparator ); + if ( pos!=string::npos ) + { + newInFilePath = ( fileList[i] ).substr ( 0, pos+1 ); + } + else + { + newInFilePath=Platform::pathSeparator; + } + if ( newInFilePath!=inFilePath ) + { + indexfile << "</ul>\n<h2>"; + indexfile << newInFilePath; + indexfile << "</h2>\n<ul>\n"; + inFilePath=newInFilePath; + } + inFileName = ( fileList[i] ).substr ( pos+1 ); + indexfile << "<li><a href=\"" << inFileName << suffix << "\">"; + indexfile << inFileName << suffix <<"</a></li>\n"; + } + + indexfile << "</ul>\n" + << hrTag << brTag + << "<small>Generated by highlight " + << HIGHLIGHT_VERSION + << ", <a href=\"" << HIGHLIGHT_URL << "\" target=\"new\">" + << HIGHLIGHT_URL << "</a></small>"; + indexfile << getGeneratorComment(); + } + else + { + return false; + } + return true; + } + + string HtmlGenerator::getKeywordOpenTag ( unsigned int styleID ) + { + if ( useInlineCSS ) + { + return getOpenTag ( docStyle.getKeywordStyle ( langInfo.getKeywordClasses() [styleID] ) ); + } + return getOpenTag ( langInfo.getKeywordClasses() [styleID] ); + } + + string HtmlGenerator::getKeywordCloseTag ( unsigned int styleID ) + { + return "</span>"; + } + + string HtmlGenerator::getMetaInfoOpenTag ( const TagInfo& info ) + { + ostringstream tagStream; + tagStream<<"<span title=\""<<info.getKind() <<" | "; + if ( !info.name_space.empty() ) + { + maskString ( tagStream, info.name_space ); + tagStream<<" | "; + } + maskString ( tagStream, info.file ) ; + tagStream<<"\">"; + return tagStream.str(); + } + string HtmlGenerator::getMetaInfoCloseTag() + { + return "</span>"; + } + +} diff --git a/support/highlight/src/core/htmlgenerator.h b/support/highlight/src/core/htmlgenerator.h new file mode 100644 index 0000000000..29e650839f --- /dev/null +++ b/support/highlight/src/core/htmlgenerator.h @@ -0,0 +1,195 @@ +/*************************************************************************** + htmlgenerator.h - description + ------------------- + begin : Wed Nov 28 2001 + copyright : (C) 2001-2007 by Andre Simon + email : andre.simon1@gmx.de + ***************************************************************************/ + + +/* +This file is part of Highlight. + +Highlight is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +Highlight is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Highlight. If not, see <http://www.gnu.org/licenses/>. +*/ + + + +#ifndef HTMLGENERATOR_H +#define HTMLGENERATOR_H + +#include <string> + +#include "codegenerator.h" + +#include "stylecolour.h" +#include "elementstyle.h" + +namespace highlight +{ + + /** + \brief This class generates HTML. + + It contains information about the resulting document structure (document + header and footer), the colour system, white space handling and text + formatting attributes. + + * @author Andre Simon + */ + + class HtmlGenerator : public highlight::CodeGenerator + { + public: + + HtmlGenerator(); + + /** Destructor, virtual as it is base for xhtmlgenerator*/ + virtual ~HtmlGenerator() {}; + + /** Print style definitions to external file + \param outFile Path of external style definition + */ + bool printExternalStyle ( const string &outFile ); + + /** Print index file with all input file names + \param fileList List of output file names + \param outPath Output path + */ + bool printIndexFile ( const vector<string> & fileList, const string &outPath ); + + /** + \param b set true if anchors should be attached to line numbers + */ + void setHTMLAttachAnchors ( bool b ) { attachAnchors = b; } + + /** + \param prefix anchor prefix + */ + void setHTMLAnchorPrefix ( const string & prefix ) { anchorPrefix = prefix; } + + /** + \param b if true line numbers should be replaced by list items + */ + void setHTMLOrderedList ( bool b ) { orderedList = b; } + + /** + \param b if true CSS formatting will be inserted into each tag + */ + void setHTMLInlineCSS ( bool b ) { useInlineCSS = b; } + + /** + \param b if truefragmented output will be enclosed in pre tag + */ + void setHTMLEnclosePreTag ( bool b ) { enclosePreTag = b; } + + /** + \param name CSS Class name + */ + void setHTMLClassName ( const string& name ) + { + cssClassName = name; + } + + protected: + + string brTag, ///< break tag + hrTag, ///< horizontal ruler tag + idAttr, ///< ID tag + fileSuffix, ///< filename extension + cssClassName; ///< css class name prefix + + /** caches style definition */ + string styleDefinitionCache; + + /** line count should be replaced by ordered list*/ + bool orderedList; + + /** CSS definition should be outputted inline */ + bool useInlineCSS; + + /** pre tag should be outputted in fragment mode*/ + bool enclosePreTag; + + /** \return CSS definition */ + string getStyleDefinition(); + + /** \return Content of user defined style file */ + string readUserStyleDef(); + + /** \param title Dociment title + \return Start of file header */ + virtual string getHeaderStart ( const string &title ); + + /** \return Comment with program information */ + string getGeneratorComment(); + + private: + + /** insert line number in the beginning of the new line + */ + virtual void insertLineNumber ( bool insertNewLine=true ); + + /** Print document header + */ + string getHeader(); + + /** Print document body*/ + void printBody(); + + /** Print document footer*/ + string getFooter(); + + /** initialize tags in specific format according to colouring information provided in DucumentStyle */ + void initOutputTags(); + + /** \param styleName Style name + \return Opening tag of the given style + */ + string getOpenTag ( const string& styleName ); + + string getOpenTag ( const ElementStyle & elem ); + + /** \return escaped character*/ + virtual string maskCharacter ( unsigned char ); + + /** test if anchors should be appied to line numbers*/ + bool attachAnchors; + + /**Optional anchor prefix */ + string anchorPrefix; + + /**\return text formatting attributes in HTML format */ + string getAttributes ( const string & elemName, const ElementStyle & elem ); + + /** \param styleID Style ID + \return Opening tag of the given style + */ + string getKeywordOpenTag ( unsigned int styleID ); + + /** \param styleID Style ID + \return Closing tag of the given style + */ + string getKeywordCloseTag ( unsigned int styleID ); + + /** @return Newline string */ + string getNewLine(); + + string getMetaInfoOpenTag ( const TagInfo& info ); + string getMetaInfoCloseTag(); + }; + +} + +#endif diff --git a/support/highlight/src/core/languagedefinition.cpp b/support/highlight/src/core/languagedefinition.cpp new file mode 100644 index 0000000000..e52688c910 --- /dev/null +++ b/support/highlight/src/core/languagedefinition.cpp @@ -0,0 +1,396 @@ +/*************************************************************************** + languagedefinition.cpp - description + ------------------- + begin : Wed Nov 28 2001 + copyright : (C) 2001-2007 by Andre Simon + email : andre.simon1@gmx.de + ***************************************************************************/ + + +/* +This file is part of Highlight. + +Highlight is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +Highlight is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Highlight. If not, see <http://www.gnu.org/licenses/>. +*/ + + +#include <memory> + +#include "languagedefinition.h" +#include "stringtools.h" + + +using namespace std; + +namespace highlight +{ + + const string LanguageDefinition::REGEX_IDENTIFIER = + "[a-zA-Z_]\\w*"; + + const string LanguageDefinition::REGEX_NUMBER = + "(?:0x|0X)[0-9a-fA-F]+|\\d*[\\.]?\\d+(?:[eE][\\-\\+]\\d+)?[lLuU]*"; + + LanguageDefinition::LanguageDefinition() : + ignoreCase ( false ), + disableHighlighting ( false ), + allowExtEscape ( false ), + allowNestedComments ( true ), + reformatCode ( false ) + { + reDefPattern=Pattern::compile ( "^regex\\((.+?)(,\\s*(\\d+))?\\)$" ); + } + + LanguageDefinition::~LanguageDefinition() + { + for ( vector<RegexElement*>::iterator it=regex.begin(); it!=regex.end();it++ ) + { + delete *it; + } + delete reDefPattern; + } + + int LanguageDefinition::isKeyword ( const string &s ) + { + return ( s.length() && keywords.count ( s ) ) ? keywords[s] : 0; + } + + void LanguageDefinition::addSymbol ( stringstream& symbolStream, + State stateBegin, + State stateEnd, + bool isDelimiter, + const string& paramValue, + unsigned int classID ) + { + RegexDef re = extractRegex ( paramValue ); + if ( !re.reString.empty() ) + { + Pattern* p = Pattern::compile ( re.reString ); + if ( p!=NULL ) { + regex.push_back ( new RegexElement ( stateBegin,stateEnd, p, re.capturingGroup ) ); + } else { + failedRegex = re.reString; + } + return; + } + if ( isDelimiter ) + { + addDelimiterSymbol ( symbolStream, stateBegin, stateEnd, paramValue, classID ); + } + else + { + addSimpleSymbol ( symbolStream, stateBegin,paramValue ); + } + } + + RegexDef LanguageDefinition::extractRegex ( const string ¶mValue ) + { + RegexDef re_def; + auto_ptr<Matcher> m ( reDefPattern->createMatcher ( paramValue ) ); + if ( m.get() && m->matches() ) + { + re_def.reString = m->getGroup ( 1 ); + if ( m->getStartingIndex ( 3 ) !=-1 ) + { + StringTools::str2num<int> ( re_def.capturingGroup, m->getGroup ( 3 ), std::dec ); + //std::cerr << "capturingGroup "<<re_def.capturingGroup<<"\n"; + } + } + return re_def; + } + + void LanguageDefinition::addSimpleSymbol ( stringstream& symbolStream, + State state, + const string& paramValue ) + { + istringstream valueStream ( paramValue ); + bool valExists=false; + string value; + int pairCount =0; + while ( valueStream >> value ) + { + symbolStream << " " << value; + valExists = true; + delimiterPair[value] = ++pairCount; + } + if ( valExists ) + { + symbolStream << " " << state; + } + } + + void LanguageDefinition::addDelimiterSymbol ( stringstream& symbolStream, + State stateBegin, State stateEnd, + const string& paramValue, + unsigned int classID ) + { + istringstream valueStream ( paramValue ); + string delimPrefix, delimSuffix; + int pairCount =0; + while ( valueStream>>delimPrefix ) + { + valueStream >> delimSuffix; + symbolStream << " "<<delimPrefix <<" " << stateBegin; + symbolStream <<" "<< delimSuffix<<" "<< stateEnd; + delimiterPrefixes.insert ( make_pair ( delimPrefix, classID ) ); + // if no closing delimiter exists, open and close delims are equal: + delimiterDistinct[stateBegin] = !delimSuffix.empty(); + ++pairCount; + delimiterPair[delimPrefix] = delimiterPair[delimSuffix] = pairCount; + //std::cout << "pair: "<< delimPrefix<<"->"<<delimiterPair[delimPrefix] + // <<", "<<delimSuffix<<"->"<<delimiterPair[delimSuffix]<<"\n"; + } + } + + void LanguageDefinition::addDelimiterRegex ( stringstream& symbolStream, + State stateBegin, State stateEnd, + const string& paramValue, const string& langName ) + { + istringstream valueStream ( paramValue ); + string delimStart, delimEnd; + valueStream>>delimStart; + valueStream>>delimEnd; + + RegexDef reStart = extractRegex ( delimStart ); + if ( !reStart.reString.empty() ) + { + Pattern* p = Pattern::compile ( reStart.reString ); + if ( p!=NULL ) { + regex.insert (regex.begin(),1, new RegexElement ( stateBegin,stateBegin, p, reStart.capturingGroup, -1, langName ) ); + } + } + // end regex string needs to be saved to pass it back to host language when embedded section is over + //host language definiton needs to know end delimiter to recognize single line embedded sections + RegexDef reEnd = extractRegex ( delimEnd ); + if ( !reEnd.reString.empty() ) + { + exitDelimiters[getNewPath(langName)]=reEnd.reString; + } + } + + void LanguageDefinition::restoreLangEndDelim(const string& langPath){ + if ( !langPath.empty()&& exitDelimiters.count(langPath) ) + { + Pattern* p = Pattern::compile ( exitDelimiters[langPath]); + if ( p!=NULL ) { + regex.insert (regex.begin(),1, new RegexElement ( EMBEDDED_CODE_END,EMBEDDED_CODE_END, p ) ); + } + //else + // cerr<<"Pattern::compile fehler\n"; + } + } + + + void LanguageDefinition::getFlag ( string& paramValue, bool &flag) + { + if (paramValue.size()) flag= StringTools::change_case ( paramValue ) =="true"; + } + + void LanguageDefinition::getSymbol ( const string& paramValue, unsigned char &symbol ) + { + if (paramValue.empty()) return; + symbol=paramValue[0]; + +/* + istringstream valueStream ( paramValue ); + unsigned char symbol; + valueStream >> symbol; + return symbol; +*/ + } + + void LanguageDefinition::addKeywords ( const string &kwList, + State stateBegin, State stateEnd, + int classID ) + { + RegexDef re = extractRegex ( kwList ); + if ( !re.reString.empty() ) + { + Pattern* p = Pattern::compile ( re.reString ); + if ( p!=NULL ) + regex.push_back ( new RegexElement ( stateBegin,stateEnd, p, classID, re.capturingGroup ) ); + else + failedRegex = re.reString; + return; + } + istringstream valueStream ( kwList ); + string keyword; + while ( valueStream >> keyword ) + { + keywords.insert ( make_pair ( keyword, classID ) ); + } + } + + unsigned int LanguageDefinition::generateNewKWClass ( const string& newClassName ) + { + unsigned int newClassID=0; + bool found=false; + while ( newClassID<keywordClasses.size() && !found ) + { + found = ( newClassName==keywordClasses[newClassID++] ); + } + if ( !found ) + { + newClassID++; + keywordClasses.push_back ( newClassName ); + } + return newClassID; + } + + bool LanguageDefinition::load ( const string& langDefPath, bool clear ) + { + if ( clear ) reset(); + + ConfigurationReader langDef ( langDefPath ); + if ( !langDef.found() ) + { + currentPath.clear(); + return false; + } + currentPath=langDefPath; + disableHighlighting=false; + string token; + stringstream symbolStrStream; + + addSymbol ( symbolStrStream, + STRING, + STRING_END, + false, + langDef.getParameter ( "stringdelimiters" ) ); + + addSymbol ( symbolStrStream, + STRING, + STRING_END, + true, + langDef.getParameter ( "string_unequal" ) ); + + addSymbol ( symbolStrStream, + DIRECTIVE, + DIRECTIVE_END, + false, + langDef.getParameter ( "directive" ) ); + + addSymbol ( symbolStrStream, + ESC_CHAR, + ESC_CHAR_END, + false, + langDef.getParameter ( "escchar" ) ); + + addSymbol ( symbolStrStream, + SL_COMMENT, + SL_COMMENT_END, + false, + langDef.getParameter ( "sl_comment" ) ); + + addSymbol ( symbolStrStream, + ML_COMMENT, + ML_COMMENT_END, + true, + langDef.getParameter ( "ml_comment" ) ); + + addSymbol ( symbolStrStream, + ML_COMMENT, + ML_COMMENT_END, + false, + langDef.getParameter ( "ml_comment_equal" ) ); + + addSymbol ( symbolStrStream, + SYMBOL, + SYMBOL_END, + false, + langDef.getParameter ( "symbols" ) ); + + string paramName, className, classValue; + vector<string> paramNames=langDef.getParameterNames(); + for ( unsigned int i=0;i<paramNames.size();i++ ) + { + paramName=paramNames[i]; + className=StringTools::getParantheseVal ( paramName ); + classValue=langDef.getParameter ( paramName ); + if ( paramName.find ( "keywords" ) != string::npos ) + { + addKeywords ( classValue, KEYWORD, KEYWORD_END, generateNewKWClass ( className ) ); + } else if (paramName.find ( "nested" ) != string::npos) { + addDelimiterRegex( symbolStrStream, EMBEDDED_CODE_BEGIN, EMBEDDED_CODE_END, + classValue, className ); + } + } + + // use hardcoded regex if not defined in language definition + // TODO save as members to alloe redefinition in langdefs with include stmt + string user_def_re = extractRegex ( langDef.getParameter ( "digit" ) ).reString; + string re_digit = ( user_def_re.empty() ) ? REGEX_NUMBER : user_def_re; + + user_def_re = extractRegex ( langDef.getParameter ( "identifier" ) ).reString; + string re_identifier= ( user_def_re.empty() ) ? REGEX_IDENTIFIER: user_def_re; + + // insert identifier and number regex after keyword regexes + regex.push_back ( new RegexElement ( IDENTIFIER_BEGIN, IDENTIFIER_END, + Pattern::compile ( re_identifier ) ) ); + regex.push_back ( new RegexElement ( NUMBER, NUMBER_END, + Pattern::compile ( re_digit ) ) ); + + symbolString = symbolStrStream.str(); + + getFlag ( langDef.getParameter ( "ignorecase" ), ignoreCase); + getFlag ( langDef.getParameter ( "allownestedcomments" ), allowNestedComments ); + getFlag ( langDef.getParameter ( "disablehighlighting" ), disableHighlighting ); + getFlag ( langDef.getParameter ( "reformatting" ), reformatCode ); + getSymbol ( langDef.getParameter ( "rawstringprefix" ), rawStringPrefix ); + getSymbol ( langDef.getParameter ( "continuationsymbol" ), continuationChar ); + getFlag ( langDef.getParameter ( "allowextescape" ), allowExtEscape); + + langDesc = langDef.getParameter ( "description" ); + + //load syntax before it is overridden by calling language definition + string fileToInclude=langDef.getParameter ( "include" ); + if ( !fileToInclude.empty() ) + { + //string::size_type Pos = langDefPath.find_last_of ( Platform::pathSeparator ); + //string includeLangDefPath = langDefPath.substr ( 0, Pos+1 ) + fileToInclude; + //load ( includeLangDefPath, false ); + load(getNewPath(fileToInclude), false); + } + + return failedRegex.empty(); + } + + void LanguageDefinition::reset() + { + keywords.clear(); + keywordClasses.clear(); + delimiterPrefixes.clear(); + delimiterDistinct.clear(); + delimiterPair.clear(); + langDesc.clear(); + ignoreCase= false; + allowNestedComments= reformatCode = false; + rawStringPrefix = continuationChar = '\0'; + disableHighlighting=allowExtEscape=false; + + // TODO eigene methode + for ( vector<RegexElement*>::iterator it=regex.begin(); it!=regex.end();it++ ) + { + delete *it; + } + regex.clear(); + failedRegex.clear(); + } + + string LanguageDefinition::getNewPath(const string& lang){ + string::size_type Pos = currentPath.find_last_of ( Platform::pathSeparator ); + return currentPath.substr ( 0, Pos+1 ) + lang + ".lang"; + } + +} diff --git a/support/highlight/src/core/languagedefinition.h b/support/highlight/src/core/languagedefinition.h new file mode 100644 index 0000000000..08caee3fc3 --- /dev/null +++ b/support/highlight/src/core/languagedefinition.h @@ -0,0 +1,325 @@ +/*************************************************************************** + languagedefinition.h - description + ------------------- + begin : Wed Nov 28 2001 + copyright : (C) 2001-2008 by Andre Simon + email : andre.simon1@gmx.de + ***************************************************************************/ + + +/* +This file is part of Highlight. + +Highlight is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +Highlight is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Highlight. If not, see <http://www.gnu.org/licenses/>. +*/ + + +#ifndef LANGUAGEDEFINITION_H +#define LANGUAGEDEFINITION_H + +#include <string> +#include <map> +#include <iostream> +#include <fstream> +#include <iterator> +#include <sstream> + +#include "configurationreader.h" +#include "platform_fs.h" +#include "enums.h" +#include "re/Pattern.h" +#include "re/Matcher.h" + +namespace highlight +{ + + class RegexElement; + + /** maps keywords and the corresponding class IDs*/ + typedef map <string, int> KeywordMap; + + /** maps embedded langiage names to exit delimiter regexes*/ + typedef map <string, string> EmbedLangDelimMap; + + /**\brief Contains specific data of the programming language being processed. + + The load() method will only read a new language definition if the given + file path is not equal to the path of the current language definition. + + * @author Andre Simon + */ + + class LanguageDefinition + { + + public: + + LanguageDefinition(); + + ~LanguageDefinition(); + + /** \return Symbol string, containg all known symbols with the referencing state ids*/ + const string &getSymbolString() const { return symbolString; } + + /** \return Failed regilar expression */ + const string &getFailedRegex() const { return failedRegex; } + + /** \return Prefix of raw strings */ + unsigned char getRawStringPrefix() const { return rawStringPrefix; } + + /** \return Continuation Character */ + unsigned char getContinuationChar() const { return continuationChar; } + + /** \return true if syntax highlighting is enabled*/ + bool highlightingEnabled() const { return !disableHighlighting;} + + /** \return True if language is case sensitive */ + bool isIgnoreCase() const { return ignoreCase;} + + /** \param s String + \return class id of keyword, 0 if s is not a keyword */ + int isKeyword ( const string &s ) ; + + /** Load new language definition + \param langDefPath Path of language definition + \param clear Test if former data should be deleted + \return True if successfull */ + bool load ( const string& langDefPath, bool clear=true ); + + /** \return True if multi line comments may be nested */ + bool allowNestedMLComments() const { return allowNestedComments; } + + /** \return True if highlighting is disabled + TODO remove method */ + bool highlightingDisabled() const { return disableHighlighting; } + + /** \return True if the next load() call would load a new language definition + \param langDefPath Path to language definition */ + bool needsReload ( const string &langDefPath ) const { return currentPath!=langDefPath; } + + /** \return True if current language may be reformatted (c, c++, c#, java) */ + bool enableReformatting() const { return reformatCode;} + + /** \return True if escape sequences are allowed outsde of strings */ + bool allowExtEscSeq() const { return allowExtEscape; } + + /** \return keywords*/ + const KeywordMap& getKeywords() const { return keywords; } + + /** \return keyword classes*/ + const vector<string>& getKeywordClasses() const { return keywordClasses;} + + /** \return regular expressions */ + const vector<RegexElement*>& getRegexElements() const {return regex;}; + + /** \return description of the programming language */ + const string & getDescription () const {return langDesc;} + + /** \param stateID state id + \return true, if no closing delimiter exists (open and close delimiters are equal) + */ + bool delimiterIsDistinct ( int stateID ) + { + return delimiterDistinct[stateID]; + } + + /** Pairs of open/close tokens have a unique ID to test if two tokens act as delimiters + \param token delimiter token + \return token ID + */ + int getDelimiterPairID ( const string& token ) + { + return delimiterPair[token]; + } + + string getDelimRegex(const string & lang){ + return exitDelimiters[lang]; + } + + /** initializes end delimiter regex to switch back to host language + \param langPath path of embedded language definition + */ + void restoreLangEndDelim(const string&langPath); + + /** + \param lang language definition name (no path, no ".lang" extension) + \return absolute path based on the previously loaded definition + */ + string getNewPath(const string& lang); + + string getCurrentPath() { return currentPath;} + + private: + + static const string REGEX_IDENTIFIER; + static const string REGEX_NUMBER; + + // string containing symbols and their IDs of the programming language + string symbolString; + + // path to laoded language definition + string currentPath; + + // Language description + string langDesc; + + string failedRegex; + + KeywordMap keywords; + + vector <string> keywordClasses; + + vector <RegexElement*> regex; + + KeywordMap delimiterPrefixes; + + EmbedLangDelimMap exitDelimiters; + + // saves if delimiter pair consists of the same delimiter symbol + map <int, bool> delimiterDistinct; + + map <string, int> delimiterPair; + + // keywords are not case sensitive if set + bool ignoreCase, + + // highlighting is disabled + disableHighlighting, + + // Escape sequences are allowed outrside of strings + allowExtEscape, + + // allow nested multi line comment blocks + allowNestedComments, + + // single line comments have to start in coloumn 1 if set + fullLineComment, + + // code formatting is enabled if set + reformatCode; + + // character which is prefix of raw string (c#) + unsigned char rawStringPrefix, + + //character which continues curreent style on next line + continuationChar; + + /* reset members */ + void reset(); + + // add a symbol sequence to the symbolStream + void addSimpleSymbol ( stringstream& symbolStream, State state, + const string& paramValue ); + + void addSymbol ( stringstream& symbolStream, + State stateBegin, + State stateEnd, + bool isDelimiter, + const string& paramValue, + unsigned int classID=0 ); + + // add a delimiter symbol sequence to the symbolStream + void addDelimiterSymbol ( stringstream& symbolStream, + State stateBegin, State stateEnd, + const string& paramValue, + unsigned int classID=0 ); + + void addDelimiterRegex ( stringstream& symbolStream, + State stateBegin, State stateEnd, + const string& paramValue, const string& langName); + + + + //set flag if paramValue is defined + void getFlag ( string& paramValue, bool& flag ); + + void getSymbol ( const string& paramValue, unsigned char& symbol ); + + // generate a unique class ID of the class name + unsigned int generateNewKWClass ( const string& newClassName ); + + // add keywords to the given class + void addKeywords ( const string &kwList,State stateBegin, State stateEnd, int classID ); + + struct RegexDef extractRegex ( const string ¶mValue ); + + Pattern * reDefPattern; + + }; + + + /**\brief Association of a regex with a state description + + A RegexElement associates a regular expression with the state information + (opening and closing state, pattern, keyword class, keyword group id, language name) + */ + class RegexElement + { + public: + RegexElement() + :open ( STANDARD ), end ( STANDARD ), rePattern ( NULL ), kwClass ( 0 ),capturingGroup ( -1 ), langName() + { + } + + RegexElement ( State oState, State eState, Pattern *re, unsigned int cID=0, int group=-1, const string& name="" ) : + open ( oState ), end ( eState ), rePattern ( re ), kwClass ( cID ), capturingGroup ( group ), langName(name) + { + // cerr << "new re element "<< rePattern->getPattern() <<" open: "<<open<<" end "<<end<<"\n"; + } + + ~RegexElement() { if ( rePattern ) delete rePattern; } + + State open, ///< opening state + end; ///< closing state + Pattern *rePattern; ///< regex pattern + unsigned int kwClass; ///< keyword class + int capturingGroup; ///< capturing group ID + string langName; ///< language name + + private: + RegexElement (const RegexElement& rhs){ + // does not work because Pattern misses copy constructor + /*open=rhs.open; + end=rhs.end; + kwClass=rhs.kwClass; + capturingGroup=rhs.capturingGroup; + Pattern *pOrig=rePattern; + rePattern=new Pattern(*rhs.rePattern); + delete pOrig;*/ + } + RegexElement& operator=(const RegexElement& rhs){ + // does not work because Pattern misses copy constructor + /*open=rhs.open; + end=rhs.end; + kwClass=rhs.kwClass; + capturingGroup=rhs.capturingGroup; + Pattern *pOrig=rePattern; + rePattern=new Pattern(*rhs.rePattern); + delete pOrig; + */ + return *this; + } + }; + + /**\brief Association of a regex and its relevant capturing group + */ + struct RegexDef + { + RegexDef() :capturingGroup ( -1 ) {} + string reString; ///< regex string + int capturingGroup; ///< capturing group which should be recognized as token + }; + +} +#endif diff --git a/support/highlight/src/core/latexgenerator.cpp b/support/highlight/src/core/latexgenerator.cpp new file mode 100644 index 0000000000..3508d790be --- /dev/null +++ b/support/highlight/src/core/latexgenerator.cpp @@ -0,0 +1,335 @@ +/*************************************************************************** + LatexCode.cpp - description + ------------------- + begin : Mit Jul 24 2002 + copyright : (C) 2002 by Andre Simon + email : andre.simon1@gmx.de + ***************************************************************************/ + + +/* +This file is part of Highlight. + +Highlight is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +Highlight is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Highlight. If not, see <http://www.gnu.org/licenses/>. +*/ + + +#include "latexgenerator.h" + +namespace highlight +{ + + LatexGenerator::LatexGenerator() + : CodeGenerator ( LATEX ), + replaceQuotes ( false ), + disableBabelShortHand ( false ), + prettySymbols ( false ) + { + // avoid "Underfull \hbox (badness 10000)" warnings + newLineTag = "\\\\\n"; + longLineTag = "\\hspace*{\\fill}" + newLineTag; + spacer = "\\ "; + maskWs=true; + maskWsBegin = "\\hlstd{"; + maskWsEnd = "}"; + excludeWs=true; + styleCommentOpen="%"; + } + + LatexGenerator::~LatexGenerator() + {} + + void LatexGenerator::printBody() + { + *out << "\\noindent\n" ; + if ( ! this->getBaseFont().empty() ) + *out << "\\" << this->getBaseFont() << "\n" ; + else + *out << "\\ttfamily\n"; + if ( ! this->getBaseFontSize().empty() ) + *out << "\\" << this->getBaseFontSize() << "\n" ; + if ( disableBabelShortHand ) + *out << "\\shorthandoff{\"}\n"; + + processRootState(); + + *out << "\\mbox{}\n" + << "\\normalfont\n"; + if ( ! this->getBaseFontSize().empty() ) + *out << "\\normalsize\n" ; + if ( disableBabelShortHand ) + *out << "\\shorthandon{\"}\n"; + } + + string LatexGenerator::getHeader() + { + ostringstream os; + + os << "\\documentclass{article}\n" + << "\\usepackage{color}\n" + << "\\usepackage{alltt}\n"; + + if ( StringTools::change_case ( encoding ) =="utf-8" ) + { + os << "\\usepackage{ucs}\n\\usepackage[utf8x]{inputenc}\n"; + } + else if ( encodingDefined() ) + { + os << "\\usepackage[latin1]{inputenc}\n"; + } + + //needed for Righttorque symbol + if ( preFormatter.isEnabled() ) + { + os << "\\usepackage{marvosym}\n"; + } + + if ( langInfo.highlightingEnabled() ) + { + if ( includeStyleDef ) + { + os << "\n"<<getStyleDefinition(); + os << CodeGenerator::readUserStyleDef(); + } + else + { + os << "\n\\input {" + << getStyleOutputPath() + << "}\n"; + } + } + + os << "\n\\title{" << docTitle << "}\n" + << "\\begin{document}\n" + << "\\pagecolor{bgcolor}\n"; + + if ( prettySymbols ) + { + os<<"\\newsavebox{\\hlboxopenbrace}\n" + <<"\\newsavebox{\\hlboxclosebrace}\n" + <<"\\newsavebox{\\hlboxlessthan}\n" + <<"\\newsavebox{\\hlboxgreaterthan}\n" + <<"\\newsavebox{\\hlboxdollar}\n" + <<"\\newsavebox{\\hlboxunderscore}\n" + <<"\\newsavebox{\\hlboxand}\n" + <<"\\newsavebox{\\hlboxhash}\n" + <<"\\newsavebox{\\hlboxat}\n" + <<"\\newsavebox{\\hlboxbackslash}\n" + <<"\\newsavebox{\\hlboxpercent}\n" + <<"\\newsavebox{\\hlboxhat}\n" + + <<"\\setbox\\hlboxopenbrace=\\hbox{\\verb.{.}\n" + <<"\\setbox\\hlboxclosebrace=\\hbox{\\verb.}.}\n" + <<"\\setbox\\hlboxlessthan=\\hbox{\\verb.<.}\n" + <<"\\setbox\\hlboxgreaterthan=\\hbox{\\verb.>.}\n" + + <<"\\setbox\\hlboxdollar=\\hbox{\\verb.$.}\n" + <<"\\setbox\\hlboxunderscore=\\hbox{\\verb._.}\n" + <<"\\setbox\\hlboxand=\\hbox{\\verb.&.}\n" + <<"\\setbox\\hlboxhash=\\hbox{\\verb.#.}\n" + <<"\\setbox\\hlboxat=\\hbox{\\verb.@.}\n" + <<"\\setbox\\hlboxbackslash=\\hbox{\\verb.\\.}\n" + <<"\\setbox\\hlboxpercent=\\hbox{\\verb.\\%.}\n" + <<"\\setbox\\hlboxhat=\\hbox{\\verb.^.}\n" + + <<"\\def\\urltilda{\\kern -.15em\\lower .7ex\\hbox{\\~{}}\\kern .04em}\n"; + } + + return os.str(); + } + + string LatexGenerator::getFooter() + { + ostringstream os; + os << "\\end {document}\n" + << "(* LaTeX generated by highlight " + << HIGHLIGHT_VERSION + << ", " + << HIGHLIGHT_URL + << " *)\n"; + return os.str(); + } + + + void LatexGenerator::initOutputTags(){ + openTags.push_back ( "\\hlstd{" ); + openTags.push_back ( "\\hlstr{" ); + openTags.push_back ( "\\hlnum{" ); + openTags.push_back ( "\\hlslc{" ); + openTags.push_back ( "\\hlcom{" ); + openTags.push_back ( "\\hlesc{" ); + openTags.push_back ( "\\hldir{" ); + openTags.push_back ( "\\hldstr{" ); + openTags.push_back ( "\\hlline{" ); + openTags.push_back ( "\\hlsym{" ); + + for ( int i=0;i<NUMBER_BUILTIN_STATES; i++ ) + { + closeTags.push_back ( "}" ); + } + } + + string LatexGenerator::getAttributes ( const string & elemName, + const ElementStyle &elem ) + { + ostringstream s; + s << "\\newcommand{\\hl" + << elemName + << "}[1]{\\textcolor[rgb]{" + << elem.getColour().getRed ( LATEX ) << "," + << elem.getColour().getGreen ( LATEX ) << "," + << elem.getColour().getBlue ( LATEX ) + << "}{"; + + if ( elem.isBold() ) + s << "\\bf{"; + if ( elem.isItalic() ) + s << "\\it{"; + + s <<"#1"; + + if ( elem.isBold() ) + s << "}"; + if ( elem.isItalic() ) + s << "}"; + + s <<"}}\n"; + return s.str(); + } + + + string LatexGenerator::getNewLine() + { + string nl; + + // set wrapping arrow if previous line was wrapped + if ( preFormatter.isWrappedLine ( lineNumber-1 ) ) + { + nl = "\\Righttorque"; + } + nl += ( showLineNumbers ) ? newLineTag:longLineTag; + return nl; + } + + string LatexGenerator::maskCharacter ( unsigned char c ) + { + switch ( c ) + { + case ' ': + return spacer; + break; + + case '<' : + return prettySymbols ? "\\usebox{\\hlboxlessthan}" : "$<$"; + break; + case '>' : + return prettySymbols ? "\\usebox{\\hlboxgreaterthan}" : "$>$"; + break; + case '{': + return prettySymbols ? "\\usebox{\\hlboxopenbrace}" : "\\{"; + break; + case '}': + return prettySymbols ? "\\usebox{\\hlboxclosebrace}" : "\\}"; + break; + + case '&': + case '$': + case '#': + case '%': + { + string m ( "\\" ); + m += c; + return m; + } + break; + case '\"': + return ( replaceQuotes ) ?"\\dq{}":"\""; + break; + case '_': + return "\\textunderscore "; + break; + case '^': + return "\\textasciicircum "; + break; + case '\\': + return "$\\backslash$"; + break; + case '~': + return prettySymbols ? "\\urltilda " : "$\\sim$"; + break; + case '|': + return "\\textbar "; + break; + // avoid latex compilation failure if [ or * follows a line break (\\) + case '*': + case '[': + case ']': + // avoid "merging" of consecutive '-' chars when included in bold font ( \bf ) + case '-': + { + string m ( 1, '{' ); + m += c; + m += '}'; + return m; + } + break; + default : + return string ( 1, c ); + } + } + + string LatexGenerator::getKeywordOpenTag ( unsigned int styleID ) + { + return "\\hl"+langInfo.getKeywordClasses() [styleID]+"{"; + } + + string LatexGenerator::getKeywordCloseTag ( unsigned int styleID ) + { + return "}"; + } + + string LatexGenerator::getStyleDefinition() + { + if ( styleDefinitionCache.empty() ) + { + ostringstream os; + os << getAttributes ( STY_NAME_STD, docStyle.getDefaultStyle() ); + os << getAttributes ( STY_NAME_NUM, docStyle.getNumberStyle() ); + os << getAttributes ( STY_NAME_ESC, docStyle.getEscapeCharStyle() ); + os << getAttributes ( STY_NAME_STR, docStyle.getStringStyle() ); + os << getAttributes ( STY_NAME_DST, docStyle.getDirectiveStringStyle() ); + os << getAttributes ( STY_NAME_SLC, docStyle.getSingleLineCommentStyle() ); + os << getAttributes ( STY_NAME_COM, docStyle.getCommentStyle() ); + os << getAttributes ( STY_NAME_DIR, docStyle.getDirectiveStyle() ); + os << getAttributes ( STY_NAME_SYM, docStyle.getSymbolStyle() ); + os << getAttributes ( STY_NAME_LIN, docStyle.getLineStyle() ); + + KeywordStyles styles = docStyle.getKeywordStyles(); + for ( KSIterator it=styles.begin(); it!=styles.end(); it++ ) + { + os << getAttributes ( it->first, it->second ); + } + os << "\\definecolor{bgcolor}{rgb}{" + << docStyle.getBgColour().getRed ( LATEX ) << "," + << docStyle.getBgColour().getGreen ( LATEX ) << "," + << docStyle.getBgColour().getBlue ( LATEX ) + << "}\n"; + + styleDefinitionCache=os.str(); + } + return styleDefinitionCache; + } + + +} diff --git a/support/highlight/src/core/latexgenerator.h b/support/highlight/src/core/latexgenerator.h new file mode 100644 index 0000000000..a1e56c55e4 --- /dev/null +++ b/support/highlight/src/core/latexgenerator.h @@ -0,0 +1,118 @@ +/*************************************************************************** + latexgenerator.h - description + ------------------- + begin : Mit Jul 24 2002 + copyright : (C) 2002 by Andre Simon + email : andre.simon1@gmx.de + ***************************************************************************/ + + +/* +This file is part of Highlight. + +Highlight is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +Highlight is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Highlight. If not, see <http://www.gnu.org/licenses/>. +*/ + + +#ifndef LATEXGENERATOR_H +#define LATEXGENERATOR_H + +#include <string> +#include <iostream> +#include <sstream> + +#include "codegenerator.h" +#include "version.h" +#include "charcodes.h" + + +namespace highlight +{ + + /** + \brief This class generates LaTeX. + + It contains information about the resulting document structure (document + header and footer), the colour system, white space handling and text + formatting attributes. + + * @author Andre Simon + */ + + class LatexGenerator : public highlight::CodeGenerator + { + public: + LatexGenerator(); + ~LatexGenerator(); + + /** set replace quotes flag + \param b flag + */ + void setLATEXReplaceQuotes ( bool b ) { replaceQuotes = b;} + + /** set disable babel shorthand flag + \param b flag + */ + void setLATEXNoShorthands ( bool b ) { disableBabelShortHand = b; } + + /** set pretty symbols flag + \param b flag + */ + void setLATEXPrettySymbols ( bool b ) { prettySymbols = b; } + + private: + + /** prints document header + */ + string getHeader(); + + /** Prints document footer*/ + string getFooter(); + + /** Prints document body*/ + void printBody(); + + /** initialize tags in specific format according to colouring information provided in DucumentStyle */ + void initOutputTags(); + + string styleDefinitionCache; + string longLineTag; + + /** \return escaped character*/ + virtual string maskCharacter ( unsigned char ); + + /**\return text formatting attributes in LaTeX format */ + string getAttributes ( const string & elemName, + const ElementStyle & elem ); + + /** test if double quotes should be replaced by \dq{} */ + bool replaceQuotes; + + /** test if Babel shorthand for " should be disabled */ + bool disableBabelShortHand; + + /** test if symbols like <,>,{,},~ should be replaced by nicer definitions */ + bool prettySymbols; + + string getNewLine(); + + string getStyleDefinition(); + + string getKeywordOpenTag ( unsigned int styleID ); + string getKeywordCloseTag ( unsigned int styleID ); + }; + +} + +#endif diff --git a/support/highlight/src/core/platform_fs.cpp b/support/highlight/src/core/platform_fs.cpp new file mode 100644 index 0000000000..2719bf7a69 --- /dev/null +++ b/support/highlight/src/core/platform_fs.cpp @@ -0,0 +1,339 @@ + +/* +This file is part of Highlight. + +Highlight is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +Highlight is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Highlight. If not, see <http://www.gnu.org/licenses/>. +*/ + + +#include "platform_fs.h" + +// includes for recursive getFileNames() function +#ifdef _WIN32 +#include <windows.h> +#else +#include <dirent.h> +#include <errno.h> +#include <sys/stat.h> +#ifdef __VMS +#include <unixlib.h> +#include <rms.h> +#include <ssdef.h> +#include <stsdef.h> +#include <lib$routines.h> +#include <starlet.h> +#endif /* __VMS */ +#endif + +#include <algorithm> +#include <iostream> +#include <errno.h> + +using namespace std; + +namespace Platform +{ + +#ifdef _WIN32 +#include <windows.h> + const char pathSeparator = '\\'; + std::string getAppPath() + { + char pathAndName[MAX_PATH], path[MAX_PATH], drive[3]; + GetModuleFileName ( NULL, ( wchar_t* ) pathAndName, MAX_PATH ); + _splitpath ( pathAndName, drive, path, 0, 0 ); + return std::string ( drive ) +path; + } +#else + const char pathSeparator = '/'; + + std::string getAppPath() + { + return ""; + } +#endif + + bool getDirectoryEntries ( vector<string> &fileList, + string wildcard, + bool recursiveSearch ) + { + if ( !wildcard.empty() ) + { + string directory_path; + string::size_type Pos = wildcard.find_last_of ( pathSeparator ); + if ( Pos == string::npos ) + { + directory_path = "."; + } + else + { + directory_path = wildcard.substr ( 0, Pos + 1 ); + wildcard = wildcard.substr ( Pos + 1 ); + } + + /* old method using dirstream: + dirstr::dirstream str( directory_path.c_str(), + #ifdef USE_FN_MATCH + dirstr::pred_f(FnMatcher(wildcard.c_str(), 0)), + #else + dirstr::pattern_f(wildcard.c_str()), + #endif + (recursiveSearch)?dirstr::recursive_yes:dirstr::recursive_no); + for(string entry; str >> entry;) { + fileList.push_back(dirstr::full_path(entry)); + //cerr << "1: "<<dirstr::full_path(entry)<<"\n"; + } + */ + + // new method using getFileNames: + getFileNames ( directory_path, wildcard, fileList ); + } + return ! ( fileList.empty() ); + } + + +#ifdef _WIN32 // Windows specific + + /** + * WINDOWS function to resolve wildcards and recurse into sub directories. + * The fileName vector is filled with the path and names of files to process. + * + * @param directory The path of the directory to be processed. + * @param wildcard The wildcard to be processed (e.g. *.cpp). + * @param filenam An empty vector which will be filled with the path and names of files to process. + */ + void getFileNames ( const string &directory,const string &wildcard, vector<string> &fileName ) + { + vector<string> subDirectory; // sub directories of directory + WIN32_FIND_DATA FindFileData; // for FindFirstFile and FindNextFile + + // Find the first file in the directory + string firstFile = directory + "\\*"; + HANDLE hFind = FindFirstFile ( firstFile.c_str(), &FindFileData ); + + if ( hFind == INVALID_HANDLE_VALUE ) + return; + //error("Cannot open directory", directory.c_str()); + + // save files and sub directories + do + { + // skip hidden or read only + if ( FindFileData.cFileName[0] == '.' + || ( FindFileData.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN ) + || ( FindFileData.dwFileAttributes & FILE_ATTRIBUTE_READONLY ) ) + continue; + + // if a sub directory and recursive, save sub directory + if ( ( FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) && true /*g_isRecursive*/ ) + { + string subDirectoryPath = directory + pathSeparator + FindFileData.cFileName; + //if (isPathExclued(subDirectoryPath)) + //{ + // if (!g_isQuiet) + // cout << "exclude " << subDirectoryPath.substr(g_mainDirectoryLength) << endl; + //} + //else + subDirectory.push_back ( subDirectoryPath ); + continue; + } + + // save the file name + string filePathName = directory + pathSeparator + FindFileData.cFileName; + // check exclude before wildcmp to avoid "unmatched exclude" error + //bool isExcluded = isPathExclued(filePathName); + // save file name if wildcard match + if ( wildcmp ( wildcard.c_str(), FindFileData.cFileName ) ) + { + //if (isExcluded) + // cout << "exclude " << filePathName.substr(g_mainDirectoryLength) << endl; + //else + fileName.push_back ( filePathName ); + } + } + while ( FindNextFile ( hFind, &FindFileData ) != 0 ); + + // check for processing error + FindClose ( hFind ); + DWORD dwError = GetLastError(); + if ( dwError != ERROR_NO_MORE_FILES ) + return; + //error("Error processing directory", directory.c_str()); + + // recurse into sub directories + // if not doing recursive subDirectory is empty + for ( unsigned i = 0; i < subDirectory.size(); i++ ) + { +// cout << "directory " << subDirectory[i] << endl; + getFileNames ( subDirectory[i], wildcard, fileName ); + continue; + } + + return; + } + +#else // not _WIN32 + + /** + * LINUX function to resolve wildcards and recurse into sub directories. + * The fileName vector is filled with the path and names of files to process. + * + * @param directory The path of the directory to be processed. + * @param wildcard The wildcard to be processed (e.g. *.cpp). + * @param filenam An empty vector which will be filled with the path and names of files to process. + */ + void getFileNames ( const string &directory,const string &wildcard, vector<string> &fileName ) + { + struct dirent *entry; // entry from readdir() + struct stat statbuf; // entry from stat() + vector<string> subDirectory; // sub directories of this directory + + // errno is defined in <errno.h> and is set for errors in opendir, readdir, or stat + errno = 0; + + DIR *dp = opendir ( directory.c_str() ); + if ( errno ) + return; + //error("Cannot open directory", directory.c_str()); + + // save the first fileName entry for this recursion + const unsigned firstEntry = fileName.size(); + + // save files and sub directories + while ( ( entry = readdir ( dp ) ) != NULL ) + { + // get file status + string entryFilepath = directory + pathSeparator + entry->d_name; + stat ( entryFilepath.c_str(), &statbuf ); + if ( errno ) + return; + //error("Error getting file status in directory", directory.c_str()); + + // skip hidden or read only + if ( entry->d_name[0] == '.' || ! ( statbuf.st_mode & S_IWUSR ) ) + continue; + // if a sub directory and recursive, save sub directory + if ( S_ISDIR ( statbuf.st_mode ) && /*g_isRecursive*/ true ) ///TODO + { + // if (isPathExclued(entryFilepath)) + // cout << "exclude " << entryFilepath.substr(g_mainDirectoryLength) << endl; + // else + subDirectory.push_back ( entryFilepath ); + continue; + } + + // if a file, save file name + if ( S_ISREG ( statbuf.st_mode ) ) + { + // check exclude before wildcmp to avoid "unmatched exclude" error + // bool isExcluded = isPathExclued(entryFilepath); + // save file name if wildcard match + if ( wildcmp ( wildcard.c_str(), entry->d_name ) ) + { + // if (isExcluded) + // cout << "exclude " << entryFilepath.substr(g_mainDirectoryLength) << endl; + // else + fileName.push_back ( entryFilepath ); + } + } + } + closedir ( dp ); + + if ( errno ) + return; + //error("Error reading directory", directory.c_str()); + + // sort the current entries for fileName + if ( firstEntry < fileName.size() ) + sort ( &fileName[firstEntry], &fileName[fileName.size() ] ); + + // recurse into sub directories + // if not doing recursive, subDirectory is empty + if ( subDirectory.size() > 1 ) + sort ( subDirectory.begin(), subDirectory.end() ); + for ( unsigned i = 0; i < subDirectory.size(); i++ ) + { + getFileNames ( subDirectory[i], wildcard, fileName ); + continue; + } + + return; + } + +#endif + +// From The Code Project http://www.codeproject.com/string/wildcmp.asp +// Written by Jack Handy - jakkhandy@hotmail.com +// Modified to compare case insensitive for Windows (the LC macro) + int wildcmp ( const char *wild, const char *data ) + { + const char *cp = NULL, *mp = NULL; + bool cmpval; + + while ( ( *data ) && ( *wild != '*' ) ) + { +#ifdef _WIN32 + cmpval = ( tolower ( *wild ) != tolower ( *data ) ) && ( *wild != '?' ); +#else + cmpval = ( *wild != *data ) && ( *wild != '?' ); +#endif + + if ( cmpval ) + { + return 0; + } + wild++; + data++; + } + + while ( *data ) + { + if ( *wild == '*' ) + { + if ( !*++wild ) + { + return 1; + } + mp = wild; + cp = data+1; + } + else + { +#ifdef _WIN32 + cmpval = ( tolower ( *wild ) == tolower ( *data ) || ( *wild == '?' ) ); +#else + cmpval = ( *wild == *data ) || ( *wild == '?' ); +#endif + + if ( cmpval ) + { + wild++; + data++; + } + else + { + wild = mp; + data = cp++; + } + } + } + + while ( *wild == '*' ) + { + wild++; + } + return !*wild; + } + +} diff --git a/support/highlight/src/core/platform_fs.h b/support/highlight/src/core/platform_fs.h new file mode 100644 index 0000000000..63f36a455c --- /dev/null +++ b/support/highlight/src/core/platform_fs.h @@ -0,0 +1,68 @@ + +/* +This file is part of Highlight. + +Highlight is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +Highlight is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Highlight. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef PLATFORM_FS__H__INCLUDED +#define PLATFORM_FS__H__INCLUDED + +#include <string> +#include <iostream> +#include <vector> +/* +#ifdef USE_FN_MATCH + #include <fnmatch.h> +#endif +*/ + +namespace Platform +{ + extern const char pathSeparator; + + std::string getAppPath(); + + /** \param fileList Vector where found entries will be stored + \param wildcard Directory path and wildcard + \param recursiveSearch Test if directory should be searched recursively */ + bool getDirectoryEntries ( std::vector<std::string> &fileList, + std::string wildcard, + bool recursiveSearch=false ); + + void getFileNames ( const std::string &directory,const std::string &wildcard, + std::vector<std::string> &fileName ); + + int wildcmp ( const char *wild, const char *data ); + + /* + #ifdef USE_FN_MATCH + struct FnMatcher + { + FnMatcher(const char* pattern, int flags) + : pattern_(pattern) + , flags_(flags) + {} + bool operator()(const std::string& e) const { + return ! ::fnmatch(pattern_, e.c_str(), flags_); + } + private: + const char* pattern_; + int flags_; + }; + #endif + */ + +} +#endif diff --git a/support/highlight/src/core/preformatter.cpp b/support/highlight/src/core/preformatter.cpp new file mode 100644 index 0000000000..88ef5293f5 --- /dev/null +++ b/support/highlight/src/core/preformatter.cpp @@ -0,0 +1,206 @@ +/*************************************************************************** + PreFormatter.cpp - description + ------------------- + begin : Mo Jan 03 2005 + copyright : (C) 2005-2007 by Andre Simon + email : andre.simon1@gmx.de + ***************************************************************************/ + + +/* +This file is part of Highlight. + +Highlight is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +Highlight is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Highlight. If not, see <http://www.gnu.org/licenses/>. +*/ + + +#include "preformatter.h" + +#include <iostream> +#include "stringtools.h" + +namespace highlight +{ + + const std::string PreFormatter::LB_CHARS = " \t[](){}-+<>.:,;"; + const std::string PreFormatter::WS_CHARS = " \n\r\t"; + const std::string PreFormatter::INDENT_MARKERS = "{(="; + + PreFormatter::PreFormatter() : + maxLineLength ( 80 ), + index ( 0 ), + numberSpaces ( 0 ), + lineNumber ( 0 ), + wsPrefixLength ( string::npos ), + hasMore ( false ), + indentAfterOpenBraces ( true ), + redefineWsPrefix ( false ), + wrapLines ( false ), + replaceTabs ( false ) + { + } + + PreFormatter::~PreFormatter() + { + } + + bool PreFormatter::hasMoreLines() + { + return hasMore; + } + + bool PreFormatter::indentCode() + { + return indentAfterOpenBraces; + } + + void PreFormatter::setLine ( const std::string& newLine ) + { + + line=newLine; + + if ( replaceTabs && numberSpaces ) + { + size_t tabPos=line.find ( '\t' ); + while ( tabPos!=string::npos ) + { + line.replace ( tabPos , 1, numberSpaces - ( tabPos % numberSpaces ) , ' ' ); + tabPos = line.find ( '\t', tabPos+1 ); + } + } + + if ( wrapLines ) + { + wsPrefix.clear(); + index=0; + wsPrefixLength=string::npos; + hasMore=true; + redefineWsPrefix=false; + } + } + + std::string PreFormatter::getNextLine() + { + + if ( !wrapLines ) + { + hasMore = false; + return line; + } + + ++lineNumber; + + if ( !index && line.length() > maxLineLength ) // erster Durchlauf... + { + // wenn moeglich an oeffnender Klammer oder Geichheitszeichen ausrichten + if ( indentAfterOpenBraces ) + { + wsPrefixLength=line.find_first_of ( INDENT_MARKERS ); + } + // sonst die Einrckung der Originalzeile beibehalten + if ( wsPrefixLength==string::npos || wsPrefixLength-index>maxLineLength ) + { + wsPrefixLength=line.find_first_not_of ( WS_CHARS ); + } + else + { + // wsPrefix in allen neu umgebrochenen Zeilen durch Spaces ersetzen + redefineWsPrefix=true; + // Position hinter oeffnende Klammer springen + wsPrefixLength=line.find_first_not_of ( WS_CHARS,wsPrefixLength+1 ); + } + + if ( wsPrefixLength!=string::npos ) + { + index = wsPrefixLength; + // Falls Anzahl der Whitespaces am beginn der ersten zeile groesser + // als Max. Zeilenlaenge, Whitespaces verwerfen + if ( wsPrefixLength>maxLineLength ) + { + wsPrefixLength=0; + return string(); + } + else + { + wsPrefix=line.substr ( 0, wsPrefixLength ); + } + } + // Zeile enthaelt nur Whitespace; verwerfen + else + { + hasMore= false; + return string(); + } + } + else + { + if ( redefineWsPrefix ) + { + wsPrefix.clear(); + wsPrefix.append ( wsPrefixLength, ' ' ); + } + redefineWsPrefix=false; + } + + string resultString; + + // Position, ab der rueckwaerts nach Umbruchmglichkeit gesucht wird + unsigned int searchEndPos = maxLineLength - wsPrefixLength; + + // letztes Teilstueck der Zeile ausgeben; Parsen beenden + if ( line.length()-index < searchEndPos ) + { + hasMore=false; + resultString= ( index>0 ) ? wsPrefix + line.substr ( index ) : line.substr ( index ); + return resultString; + } + + // Umbrechposition suchen + size_t lbPos = line.find_last_of ( LB_CHARS, index+searchEndPos ); + if ( lbPos <= index || lbPos == string::npos ) + { + // nichts gefunden, hart umbrechen + lbPos = index + searchEndPos; + } + // Einrckung der Originalzeile erhalten + resultString+=wsPrefix; + // Neue Zeile erzeugen + resultString += line.substr ( index, lbPos-index+1 ); + + // Whitespace am neuen Zeilenbeginn ignorieren, ausser beim ersten Durchlauf + size_t newIndex=line.find_first_not_of ( WS_CHARS, lbPos+1 ); + index= ( newIndex!=string::npos ) ?newIndex:line.length(); + + hasMore=index!=line.length(); // unnoetigen Leerstring vermeiden + + if ( hasMore ) wrappedLines.insert ( lineNumber ); // diese Zeile wurde umgebrochen + + return resultString; + } + + void PreFormatter::setWrapLineLength ( unsigned int maxLineLength ) + { + this->maxLineLength = maxLineLength; + } + void PreFormatter::setWrapIndentBraces ( bool indentAfterOpenBraces ) + { + this->indentAfterOpenBraces = indentAfterOpenBraces; + } + + void PreFormatter::setNumberSpaces ( unsigned int num ) + { + numberSpaces = num; + } + +} diff --git a/support/highlight/src/core/preformatter.h b/support/highlight/src/core/preformatter.h new file mode 100644 index 0000000000..4afcb28464 --- /dev/null +++ b/support/highlight/src/core/preformatter.h @@ -0,0 +1,150 @@ +/*************************************************************************** + PreFormatter.cpp - description + ------------------- + begin : Mo Jan 03 2005 + copyright : (C) 2005-2008 by Andre Simon + email : andre.simon1@gmx.de + ***************************************************************************/ + + +/* +This file is part of Highlight. + +Highlight is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +Highlight is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Highlight. If not, see <http://www.gnu.org/licenses/>. +*/ + + +#ifndef PreFormatter_H +#define PreFormatter_H + +#include <string> +#include <set> + +namespace highlight +{ + + /** \brief Class which provides intelligent line wrapping. + * @author Andre Simon + */ + + class PreFormatter + { + public: + + PreFormatter(); + + ~PreFormatter(); + + /** + Set wrapping mode + \param wrap set to true if long lines should be wrapped + */ + void setWrap ( bool wrap ) {wrapLines = wrap;} + + /** + Replace tabs by spaces + \param replTabs set to true if tabs should be replaced by spaces + */ + void setReplaceTabs ( bool replTabs ) {replaceTabs = replTabs;} + + /** + \return True if current line can be wrapped again + */ + bool hasMoreLines(); + + /** + Sets new line to be wrapped + \param newline New line + */ + void setLine ( const std::string & newline ); + + /** + The method will indent function calls and statements + \return Next line + */ + std::string getNextLine(); + + /** + \return True if lines following open braces should be indented + */ + bool indentCode(); + + /** + Maximum line length + \param maxlength max. length of output lines + */ + void setWrapLineLength ( unsigned int maxlength ); + + /** + Indentation mode + \param indentAfterOpenBraces set true if lines should be indented after braces + */ + void setWrapIndentBraces ( bool indentAfterOpenBraces=true ); + + /** + Number of spaces + \param num number of spaces which replace a tab + */ + void setNumberSpaces ( unsigned int num ); + + /** + \return true if preformatting is enabled + */ + bool isEnabled() + { + return wrapLines || replaceTabs; + } + + /** + reset preformatting state to use the object with new input data + */ + void reset () + { + lineNumber=0; + wrappedLines.clear(); + } + + /** + \param lineNumber line number + \return true if input line linenumber was wrapped + */ + bool isWrappedLine ( int lineNumber ) + { + return wrappedLines.count ( lineNumber ); + } + + private: + + unsigned int maxLineLength; + + std::string line, wsPrefix; + unsigned int index; + unsigned int numberSpaces; + unsigned int lineNumber; + size_t wsPrefixLength; + bool hasMore, indentAfterOpenBraces; + bool redefineWsPrefix; + bool wrapLines, replaceTabs; + + std::set<int> wrappedLines; + + static const std::string LB_CHARS; + static const std::string WS_CHARS; + static const std::string INDENT_MARKERS; + + }; + +} + +#endif diff --git a/support/highlight/src/core/re/Matcher.cpp b/support/highlight/src/core/re/Matcher.cpp new file mode 100644 index 0000000000..341bfbd105 --- /dev/null +++ b/support/highlight/src/core/re/Matcher.cpp @@ -0,0 +1,178 @@ +#include "Matcher.h" +#include "Pattern.h" + +const int Matcher::MATCH_ENTIRE_STRING = 0x01; + +/* + Detailed documentation is provided in this class' header file + + @author Jeffery Stuart + @since November 2004 + @version 1.05.01 +*/ + +Matcher::Matcher(Pattern * pattern, const std::string & text) +{ + pat = pattern; + str = text; + gc = pattern->groupCount; + ncgc = -pattern->nonCapGroupCount; + flags = 0; + matchedSomething = false; + starts = new int[gc + ncgc]; + ends = new int[gc + ncgc]; + groups = new int[gc + ncgc]; + groupPos = new int[gc + ncgc]; + groupIndeces = new int[gc + ncgc]; + starts = starts + ncgc; + ends = ends + ncgc; + groups = groups + ncgc; + groupPos = groupPos + ncgc; + groupIndeces = groupIndeces + ncgc; + for (int i = 0; i < gc; ++i) starts[i] = ends[i] = 0; +} +Matcher::~Matcher() +{ + delete [] (starts - ncgc); + delete [] (ends - ncgc); + delete [] (groups - ncgc); + delete [] (groupIndeces - ncgc); + delete [] (groupPos - ncgc); +} +void Matcher::clearGroups() +{ + int i; + lm = 0; + for (i = 0; i < gc; ++i) groups[i] = starts[i] = ends[i] = -1; + for (i = 1; i <= ncgc; ++i) groups[0 - i] = -1; +} +std::string Matcher::replaceWithGroups(const std::string & str) +{ + std::string ret = ""; + + std::string t = str; + while (t.size() > 0) + { + if (t[0] == '\\') + { + t = t.substr(1); + if (t.size() == 0) + { + ret += "\\"; + } + else if (t[0] < '0' || t[0] > '9') + { + ret += t.substr(0, 1); + t = t.substr(1); + } + else + { + int gn = 0; + while (t.size() > 0 && t[0] >= '0' && t[0] <= '9') + { + gn = gn * 10 + (t[0] - '0'); + t = t.substr(1); + } + ret += getGroup(gn); + } + } + else + { + ret += t.substr(0, 1); + t = t.substr(1); + } + } + + return ret; +} +unsigned long Matcher::getFlags() const +{ + return flags; +} +std::string Matcher::getText() const +{ + return str; +} + +bool Matcher::matches() +{ + flags = MATCH_ENTIRE_STRING; + matchedSomething = false; + clearGroups(); + lm = 0; + return pat->head->match(str, this, 0) == (int)str.size(); +} +bool Matcher::findFirstMatch() +{ + starts[0] = 0; + flags = 0; + clearGroups(); + start = 0; + lm = 0; + ends[0] = pat->head->match(str, this, 0); + if (ends[0] >= 0) + { + matchedSomething = true; + return 1; + } + return 0; +} +bool Matcher::findNextMatch() +{ + int s = starts[0], e = ends[0]; + + if (!matchedSomething) return findFirstMatch(); + if (s == e) ++e; + flags = 0; + clearGroups(); + + starts[0] = e; + if (e >= (int)str.size()) return 0; + start = e; + lm = e; + ends[0] = pat->head->match(str, this, e); + return ends[0] >= 0; +} +std::vector<std::string> Matcher::findAll() +{ + std::vector<std::string> ret; + reset(); + while (findNextMatch()) + { + ret.push_back(getGroup()); + } + return ret; +} + +void Matcher::reset() +{ + lm = 0; + clearGroups(); + matchedSomething = false; +} + +int Matcher::getStartingIndex(const int groupNum) const +{ + if (groupNum < 0 || groupNum >= gc) return -1; + return starts[groupNum]; +} +int Matcher::getEndingIndex(const int groupNum) const +{ + if (groupNum < 0 || groupNum >= gc) return -1; + return ends[groupNum]; +} +std::string Matcher::getGroup(const int groupNum) const +{ + if (groupNum < 0 || groupNum >= gc) return ""; + if (starts[groupNum] < 0 || ends[groupNum] < 0) return ""; + return str.substr(starts[groupNum], ends[groupNum] - starts[groupNum]); +} +std::vector<std::string> Matcher::getGroups(const bool includeGroupZero) const +{ + int i, start = (includeGroupZero ? 0 : 1); + std::vector<std::string> ret; + + for (i = start; i < gc; ++i) ret.push_back(getGroup(i)); + return ret; +} + diff --git a/support/highlight/src/core/re/Matcher.h b/support/highlight/src/core/re/Matcher.h new file mode 100644 index 0000000000..8affb5053f --- /dev/null +++ b/support/highlight/src/core/re/Matcher.h @@ -0,0 +1,255 @@ +#ifndef __MATCHER_H__ +#define __MATCHER_H__ + +#include <string> +#include <vector> + +class Vector; +class NFANode; +class NFAStartNode; +class NFAEndNode; +class NFAGroupHeadNode; +class NFAGroupLoopNode; +class NFAGroupLoopPrologueNode; +class NFAGroupTailNode; +class NFALookBehindNode; +class NFAStartOfLineNode; +class NFAEndOfLineNode; +class NFAEndOfMatchNode; +class NFAReferenceNode; +class Pattern; + +/** + A matcher is a non thread-safe object used to scan strings using a given + {@link Pattern Pattern} object. Using a <code>Matcher</code> is the preferred + method for scanning strings. Matchers are not thread-safe. Matchers require + very little dynamic memory, hence one is encouraged to create several + instances of a matcher when necessary as opposed to sharing a single instance + of a matcher. + <p> + The most common methods needed by the matcher are <code>matches</code>, + <code>findNextMatch</code>, and <code>getGroup</code>. <code>matches</code> + and <code>findNextMatch</code> both return success or failure, and further + details can be gathered from their documentation. + <p> + Unlike Java's <code>Matcher</code>, this class allows you to change the string + you are matching against. This provides a small optimization, since you no + longer need multiple matchers for a single pattern in a single thread. + <p> + This class also provides an extremely handy method for replacing text with + captured data via the <code>replaceWithGroups</code> method. A typical + invocation looks like: + <pre> + char buf[10000]; + std::string str = "\\5 (user name \\1) uses \\7 for his/her shell and \\6 is their home directory"; + FILE * fp = fopen("/etc/passwd", "r"); + Pattern::registerPattern("entry", "[^:]+"); + Pattern * p = Pattern::compile("^({entry}):({entry}):({entry}):({entry}):({entry}):({entry}):({entry})$", + Pattern::MULTILINE_MATCHING | Pattern::UNIX_LINE_MODE); + Matcher * m = p->createMatcher(""); + while (fgets(buf, 9999, fp)) + { + m->setString(buf); + if (m->matches()) + { + printf("%s\n", m->replaceWithGroups(str).c_str()); + } + } + fclose(fp); + + </pre> + Calling any of the following functions before first calling + <code>matches</code>, <code>findFirstMatch</code>, or + <code>findNextMatch</code> results in undefined behavior and may cause your + program to crash. + <code> + <ul> + <li>replaceWithGroups</code> + <li>getStartingIndex</li> + <li>getEndingIndex</li> + <li>getGroup</li> + <li>getGroups</li> + </ul> + </code> + <p> + The function <code>findFirstMatch</code> will attempt to find the first match + in the input string. The same results can be obtained by first calling + <code>reset</code> followed by <code>findNextMatch</code>. + <p> + To eliminate the necessity of looping through a string to find all the + matching substrings, <code>findAll</code> was created. The function will find + all matching substrings and return them in a <code>vector</code>. If you need + to examine specific capture groups within the substrings, then this method + should not be used. + + @author Jeffery Stuart + @since March 2003, Stable Since November 2004 + @version 1.04 + @memo Mutable object used on instances of a Pattern class + */ +class Matcher +{ + friend class NFANode; + friend class NFAStartNode; + friend class NFAEndNode; + friend class NFAGroupHeadNode; + friend class NFAGroupLoopNode; + friend class NFAGroupLoopPrologueNode; + friend class NFAGroupTailNode; + friend class NFALookBehindNode; + friend class NFAStartOfLineNode; + friend class NFAEndOfLineNode; + friend class NFAEndOfMatchNode; + friend class NFAReferenceNode; + friend class Pattern; + private: + /** + Creates a new matcher object against <code>text</code> using + <code>pattern</code>. + + @param pattern The pattern with which to search + @param text The text in which to search + */ + Matcher(Pattern * pattern, const std::string & text); + protected: + /// The pattern we use to match + Pattern * pat; + /// The string in which we are matching + std::string str; + /// The starting point of our match + int start; + /// An array of the starting positions for each group + int * starts; + /// An array of the ending positions for each group + int * ends; + /// An array of private data used by NFANodes during matching + int * groups; + /// An array of private data used by NFANodes during matching + int * groupIndeces; + /// An array of private data used by NFANodes during matching + int * groupPos; + /// The ending index of the last match + int lm; + /// The number of capturing groups we have + int gc; + /// The number of non-capturing groups we havew + int ncgc; + /// Whether or not we have matched something (used only by findFirstMatch and findNextMatch) + int matchedSomething; + /// The flags with which we were made + unsigned long flags; + /// Called by reset to clear the group arrays + void clearGroups(); + public: + /// Used internally by match to signify we want the entire string matched + const static int MATCH_ENTIRE_STRING; + public: + /// Cleans up the dynamic memory used by this matcher + ~Matcher(); + /** + Replaces the contents of <code>str</code> with the appropriate captured + text. <code>str</code> should have at least one back reference, otherwise + this function does nothing. + @param str The string in which to replace text + @return A string with all backreferences appropriately replaced + */ + std::string replaceWithGroups(const std::string & str); + /** + The flags currently being used by the matcher. + @return Zero + */ + unsigned long getFlags() const; + /** + The text being searched by the matcher. + @return the text being searched by the matcher. + */ + std::string getText() const; + + /** + Scans the string from start to finish for a match. The entire string must + match for this function to return success. Group variables are + appropriately set and can be queried after this function returns. + + @return Success if and only if the entire string matches the pattern + */ + bool matches(); + /** + Scans the string for the first substring matching the pattern. The entire + string does not necessarily have to match for this function to return + success. Group variables are appropriately set and can be queried after + this function returns. + + @return Success if any substring matches the specified pattern + */ + bool findFirstMatch(); + /** + Scans the string for the next substring matching the pattern. If no calls + have been made to findFirstMatch of findNextMatch since the last call to + reset, matches, or setString, then this function's behavior results to + that of findFirstMatch. + + @return Success if another substring can be found that matches the pattern + */ + bool findNextMatch(); + /** + Returns a vector of every substring in order which matches the given + pattern. + + @return Every substring in order which matches the given pattern + */ + std::vector<std::string> findAll(); + /** + Resets the internal state of the matcher + */ + void reset(); + /** + Same as getText. Left n for backwards compatibilty with old source code + @return Returns the string that is currently being used for matching + */ + inline std::string getString() const { return str; } + /** + Sets the string to scan + @param newStr The string to scan for subsequent matches + */ + inline void setString(const std::string & newStr) { str = newStr; reset(); } + + /** + Returns the starting index of the specified group. + @param groupNum The group to query + @return The starting index of the group if it was matched, -1 for an + invalid group or if the group was not matched + */ + int getStartingIndex(const int groupNum = 0) const; + /** + Returns the ending index of the specified group. + @param groupNum The group to query + @return The ending index of the group if it was matched, -1 for an + invalid group or if the group was not matched + */ + int getEndingIndex(const int groupNum = 0) const; + /** + Returns the specified group. An empty string ("") does not necessarily + mean the group was not matched. A group such as (a*b?) could be matched by + a zero length. If an empty string is returned, getStartingIndex can be + called to determine if the group was actually matched. + @param groupNum The group to query + @return The text of the group + */ + std::string getGroup(const int groupNum = 0) const; + /** + Returns every capture group in a vector + + @param includeGroupZero Whether or not include capture group zero + @return Every capture group + */ + std::vector<std::string> getGroups(const bool includeGroupZero = 0) const; + + /** + Number of captured groups + @return number of captured groups. + */ + int getGroupNum() {return gc;} + +}; + +#endif diff --git a/support/highlight/src/core/re/Pattern.cpp b/support/highlight/src/core/re/Pattern.cpp new file mode 100644 index 0000000000..b5fde13354 --- /dev/null +++ b/support/highlight/src/core/re/Pattern.cpp @@ -0,0 +1,1655 @@ +/** + From the author (Jeff Stuart) + " + Let me start by saying this file is pretty big. If you feel up to it, you can + try making changes yourself, but you would be better off to just email me at + stuart@cs.ucdavis.edu if you think there is a bug, or have something useful you + would like added. This project is very "near and dear" to me, so I am fairly + quick to make bug fixes. The header files for Pattern and Matcher are fairly + well documented and the function names are pretty self-explanatory, but if you + are having any trouble, feel free to email me at stuart@cs.ucdavis.edu. + + If you email me, make sure you put something like C++RE in the subject because + I tend to delete email if I don't recognize the name and the subject is + something like "I Need Your Help" or "Got A Second" or "I Found It". + " + */ + +/* + Detailed documentation is provided in this class' header file + + @author Jeffery Stuart + @since November 2004 + @version 1.05.02 +*/ + +#include "Pattern.h" +#include "Matcher.h" +#include <cstring> +#include <cstdio> +#include <algorithm> +#include <cctype> + +std::map<std::string, Pattern *> Pattern::compiledPatterns; +std::map<std::string, std::pair<std::string, unsigned long> > Pattern::registeredPatterns; + +const int Pattern::MIN_QMATCH = 0x00000000; +const int Pattern::MAX_QMATCH = 0x7FFFFFFF; + +const unsigned long Pattern::CASE_INSENSITIVE = 0x01; +const unsigned long Pattern::LITERAL = 0x02; +const unsigned long Pattern::DOT_MATCHES_ALL = 0x04; +const unsigned long Pattern::MULTILINE_MATCHING = 0x08; +const unsigned long Pattern::UNIX_LINE_MODE = 0x10; + +#ifdef _WIN32 + #define str_icmp stricmp +#else + #define str_icmp strcasecmp +#endif + +Pattern::Pattern(const std::string & rhs) +{ + matcher = NULL; + pattern = rhs; + curInd = 0; + groupCount = 0; + nonCapGroupCount = 0; + error = 0; + head = NULL; +} +// convenience function in case we want to add any extra debugging output +void Pattern::raiseError() +{ + switch (pattern[curInd - 1]) + { + case '*': + case ')': + case '+': + case '?': + case ']': + case '}': + fprintf(stderr, "%s\n%*c^\n", pattern.c_str(), curInd - 1, ' '); + fprintf(stderr, "Syntax Error near here. Possible unescaped meta character.\n"); + break; + default: + fprintf(stderr, "%s\n%*c^\n", pattern.c_str(), curInd - 1, ' '); + fprintf(stderr, "Syntax Error near here. \n"); + break; + } + error = 1; +} +NFANode * Pattern::registerNode(NFANode * node) +{ + nodes[node] = 1; + return node; +} + +std::string Pattern::classUnion (std::string s1, std::string s2) const +{ + char out[300]; + std::sort(s1.begin(), s1.end()); + std::sort(s2.begin(), s2.end()); + *std::set_union(s1.begin(), s1.end(), s2.begin(), s2.end(), out) = 0; + return out; +} +std::string Pattern::classIntersect (std::string s1, std::string s2) const +{ + char out[300]; + std::sort(s1.begin(), s1.end()); + std::sort(s2.begin(), s2.end()); + *std::set_intersection(s1.begin(), s1.end(), s2.begin(), s2.end(), out) = 0; + return out; +} +std::string Pattern::classNegate (std::string s1) const +{ + char out[300]; + int i, ind = 0; + std::map<char, bool> m; + + for (i = 0; i < (int)s1.size(); ++i) m[s1[i]] = 1; + for (i = 0xFF; i >= 0; --i) if (m.find((char)i) == m.end()) out[ind++] = (char)i; + out[ind] = 0; + return std::string(out, ind); +} +std::string Pattern::classCreateRange(char low, char hi) const +{ + char out[300]; + int ind = 0; + while (low != hi) out[ind++] = low++; + out[ind++] = low; + return std::string(out, ind); +} + +int Pattern::getInt(int start, int end) +{ + int ret = 0; + for (; start <= end; ++start) ret = ret * 10 + (pattern[start] - '0'); + return ret; +} +bool Pattern::quantifyCurly(int & sNum, int & eNum) +{ + bool good = 1; + int i, ci = curInd + 1; + int commaInd = ci, endInd = ci, len = pattern.size(); + sNum = eNum = 0; + + while (endInd < len && pattern[endInd ] != '}') ++endInd; + while (commaInd < endInd && pattern[commaInd] != ',') ++commaInd; + if (endInd >= len) { raiseError(); return 0; } + for (i = ci; good && i < endInd; ++i) if (i != commaInd && !isdigit(pattern[i])) good = 0; + if (!good && commaInd < endInd) { raiseError(); return 0; } + if (!good) return 0; + /* so now everything in here is either a comma (and there is at most one comma) or a digit */ + if (commaInd == ci) // {,*} + { + if (endInd == commaInd + 1) { sNum = MIN_QMATCH; eNum = MAX_QMATCH; } // {,} = * + else { sNum = MIN_QMATCH; eNum = getInt(commaInd + 1, endInd - 1); } // {,+} + } + else if (commaInd == endInd - 1) { sNum = getInt(ci, commaInd - 1); eNum = MAX_QMATCH; } // {+,} + else if (commaInd == endInd) { sNum = getInt(ci, endInd - 1); eNum = sNum; } // {+} + else { sNum = getInt(ci, commaInd - 1); eNum = getInt(commaInd + 1, endInd - 1); } // {+,+} + curInd = endInd + 1; + return 1; +} +NFANode * Pattern::quantifyGroup(NFANode * start, NFANode * stop, const int gn) +{ + NFANode * newNode = NULL; + int type = 0; + + if (curInd < (int)pattern.size()) + { + char ch = (curInd + 1 >= (int)pattern.size()) ? -1 : pattern[curInd + 1]; + switch (pattern[curInd]) + { + case '*': + ++curInd; + switch (ch) + { + case '?': ++curInd; type = 1; break; + case '+': ++curInd; type = 2; break; + } + newNode = registerNode(new NFAGroupLoopPrologueNode(gn)); + newNode->next = registerNode(new NFAGroupLoopNode(start, MIN_QMATCH, MAX_QMATCH, gn, type)); + stop->next = newNode->next; + return newNode; + case '?': + ++curInd; + switch (ch) + { + case '?': ++curInd; type = 1; break; + case '+': ++curInd; type = 2; break; + } + newNode = registerNode(new NFAGroupLoopPrologueNode(gn)); + newNode->next = registerNode(new NFAGroupLoopNode(start, MIN_QMATCH, 1, gn, type)); + stop->next = newNode->next; + return newNode; + case '+': + ++curInd; + switch (ch) + { + case '?': ++curInd; type = 1; break; + case '+': ++curInd; type = 2; break; + } + newNode = registerNode(new NFAGroupLoopPrologueNode(gn)); + newNode->next = registerNode(new NFAGroupLoopNode(start, 1, MAX_QMATCH, gn, type)); + stop->next = newNode->next; + return newNode; + case '{': + { + int s, e; + if (quantifyCurly(s, e)) + { + ch = (curInd < (int)pattern.size()) ? pattern[curInd] : -1; + switch (ch) + { + case '?': ++curInd; type = 1; break; + case '+': ++curInd; type = 2; break; + } + newNode = registerNode(new NFAGroupLoopPrologueNode(gn)); + newNode->next = registerNode(new NFAGroupLoopNode(start, s, e, gn, type)); + stop->next = newNode->next; + return newNode; + } + } + default: + break; + } + } + return NULL; +} + +NFANode * Pattern::quantify(NFANode * newNode) +{ + if (curInd < (int)pattern.size()) + { + char ch = (curInd + 1 >= (int)pattern.size()) ? -1 : pattern[curInd + 1]; + switch (pattern[curInd]) + { + case '*': + ++curInd; + switch (ch) + { + case '?': ++curInd; newNode = registerNode(new NFALazyQuantifierNode (this, newNode, MIN_QMATCH, MAX_QMATCH)); break; + case '+': ++curInd; newNode = registerNode(new NFAPossessiveQuantifierNode(this, newNode, MIN_QMATCH, MAX_QMATCH)); break; + default: newNode = registerNode(new NFAGreedyQuantifierNode (this, newNode, MIN_QMATCH, MAX_QMATCH)); break; + } + break; + case '?': + ++curInd; + switch (ch) + { + case '?': ++curInd; newNode = registerNode(new NFALazyQuantifierNode (this, newNode, MIN_QMATCH, 1)); break; + case '+': ++curInd; newNode = registerNode(new NFAPossessiveQuantifierNode(this, newNode, MIN_QMATCH, 1)); break; + default: newNode = registerNode(new NFAGreedyQuantifierNode (this, newNode, MIN_QMATCH, 1)); break; + } + break; + case '+': + ++curInd; + switch (ch) + { + case '?': ++curInd; newNode = registerNode(new NFALazyQuantifierNode (this, newNode, 1, MAX_QMATCH)); break; + case '+': ++curInd; newNode = registerNode(new NFAPossessiveQuantifierNode(this, newNode, 1, MAX_QMATCH)); break; + default: newNode = registerNode(new NFAGreedyQuantifierNode (this, newNode, 1, MAX_QMATCH)); break; + } + break; + case '{': + { + int s, e; + if (quantifyCurly(s, e)) + { + ch = (curInd < (int)pattern.size()) ? pattern[curInd] : -1; + switch (ch) + { + case '?': ++curInd; newNode = registerNode(new NFALazyQuantifierNode (this, newNode, s, e)); break; + case '+': ++curInd; newNode = registerNode(new NFAPossessiveQuantifierNode(this, newNode, s, e)); break; + default: newNode = registerNode(new NFAGreedyQuantifierNode (this, newNode, s, e)); break; + } + } + } + break; + default: + break; + } + } + return newNode; +} +std::string Pattern::parseClass() +{ + std::string t, ret = ""; + char ch, c1, c2; + bool inv = 0, neg = 0, quo = 0; + + if (curInd < (int)pattern.size() && pattern[curInd] == '^') + { + ++curInd; + neg = 1; + } + while (curInd < (int)pattern.size() && pattern[curInd] != ']') + { + ch = pattern[curInd++]; + if (ch == '[') + { + t = parseClass(); + ret = classUnion(ret, t); + } + /*else if (ch == '-') + { + raiseError(); + curInd = pattern.size(); + }*/ + else if (ch == '&' && curInd < (int)pattern.size() && pattern[curInd] == '&') + { + if (pattern[++curInd] != '[') + { + raiseError(); + curInd = pattern.size(); + } + else + { + ++curInd; + t = parseClass(); + ret = classIntersect(ret, t); + } + } + else if (ch == '\\') + { + t = parseEscape(inv, quo); + if (quo) + { + raiseError(); + curInd = pattern.size(); + } + else if (inv || t.size() > 1) // cant be part of a range (a-z) + { + if (inv) t = classNegate(t); + ret = classUnion(ret, t); + } + else if (curInd < (int)pattern.size() && pattern[curInd] == '-') // part of a range (a-z) + { + c1 = t[0]; + ++curInd; + if (curInd >= (int)pattern.size()) raiseError(); + else + { + c2 = pattern[curInd++]; + if (c2 == '\\') + { + t = parseEscape(inv, quo); + if (quo) + { + raiseError(); + curInd = pattern.size(); + } + else if (inv || t.size() > 1) raiseError(); + else ret = classUnion(ret, classCreateRange(c1, c2)); + } + else if (c2 == '[' || c2 == ']' || c2 == '-' || c2 == '&') + { + raiseError(); + curInd = pattern.size(); + } + else ret = classUnion(ret, classCreateRange(c1, c2)); + } + } + else + { + ret = classUnion(ret, t); + } + } + else if (curInd < (int)pattern.size() && pattern[curInd] == '-') + { + c1 = ch; + ++curInd; + if (curInd >= (int)pattern.size()) raiseError(); + else + { + c2 = pattern[curInd++]; + if (c2 == '\\') + { + t = parseEscape(inv, quo); + if (quo) + { + raiseError(); + curInd = pattern.size(); + } + else if (inv || t.size() > 1) raiseError(); + else ret = classUnion(ret, classCreateRange(c1, c2)); + } + else if (c2 == '[' || c2 == ']' || c2 == '-' || c2 == '&') + { + raiseError(); + curInd = pattern.size(); + } + else + { + ret = classUnion(ret, classCreateRange(c1, c2)); + } + } + } + else + { + ret += " "; + ret[ret.size() - 1] = ch; + } + } + if (curInd >= (int)pattern.size() || pattern[curInd] != ']') + { + raiseError(); + ret = ""; + } + else + { + ++curInd; + if (neg) ret = classNegate(ret); + } + return ret; +} +std::string Pattern::parsePosix() +{ + std::string s7 = pattern.substr(curInd, 7); + if (s7 == "{Lower}") { curInd += 7; return "abcdefghijklmnopqrstuvwxyz"; } + if (s7 == "{Upper}") { curInd += 7; return "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; } + if (s7 == "{Alpha}") { curInd += 7; return "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; } + if (s7 == "{Digit}") { curInd += 7; return "0123456789"; } + if (s7 == "{Alnum}") { curInd += 7; return "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; } + if (s7 == "{Punct}") { curInd += 7; return "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~"; } + if (s7 == "{Graph}") { curInd += 7; return "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~"; } + if (s7 == "{Print}") { curInd += 7; return "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~"; } + if (s7 == "{Blank}") { curInd += 7; return " \t"; } + if (s7 == "{Space}") { curInd += 7; return " \t\n\x0B\f\r"; } + if (s7 == "{Cntrl}") + { + int i; + std::string s = " "; + + for (i = 0; i < 5; ++i) s += s; + s += " "; + for (i = 0; i <= 0x1F; ++i) s[i] = i; + s[0x20] = 0x7F; + curInd += 7; + return s; + } + if (s7 == "{ASCII}") + { + std::string s(0x80, ' '); + for (int i = 0; i < 0x80; ++i) s[i] = i; + curInd += 7; + return s; + } + if (pattern.substr(curInd, 8) == "{XDigit}") { curInd += 8; return "abcdefABCDEF0123456789"; } + raiseError(); + return ""; +} +NFANode * Pattern::parseBackref() +{ + #define is_dig(x) ((x) >= '0' && (x) <= '9') + #define to_int(x) ((x) - '0') + int ci = curInd; + int oldRef = 0, ref = 0; + + while (ci < (int)pattern.size() && is_dig(pattern[ci]) && (ref < 10 || ref < groupCount)) + { + oldRef = ref; + ref = ref * 10 + to_int(pattern[ci++]); + } + if (ci == (int)pattern.size()) + { + oldRef = ref; + ++ci; + } + if (oldRef < 0 || ci <= curInd) + { + raiseError(); + return registerNode(new NFAReferenceNode(-1)); + } + curInd = ci; + return registerNode(new NFAReferenceNode(ref)); + + #undef is_dig + #undef to_int +} +std::string Pattern::parseOctal() +{ + #define islowoc(x) ((x) >= '0' && (x) <= '3') + #define isoc(x) ((x) >= '0' && (x) <= '7') + #define fromoc(x) ((x) - '0') + int ci = curInd; + char ch1 = (ci + 0 < (int)pattern.size()) ? pattern[ci + 0] : -1; + char ch2 = (ci + 1 < (int)pattern.size()) ? pattern[ci + 1] : -1; + char ch3 = (ci + 2 < (int)pattern.size()) ? pattern[ci + 2] : -1; + std::string s = " "; + + if (islowoc(ch1) && isoc(ch2)) + { + curInd += 2; + s[0] = fromoc(ch1) * 8 + fromoc(ch2); + if (isoc(ch3)) + { + ++curInd; + s[0] = s[0] * 8 + fromoc(ch3); + } + } + else if (isoc(ch1) && isoc(ch2)) + { + curInd += 2; + s[0] = fromoc(ch1) * 8 + fromoc(ch2); + } + else raiseError(); + + return s; + #undef islowoc + #undef isoc + #undef fromoc +} +std::string Pattern::parseHex() +{ + #define to_low(x) (((x) >= 'A' && (x) <= 'Z') ? ((x) - 'A' + 'a') : (x)) + #define is_dig(x) ((x) >= '0' && (x) <= '9') + #define is_hex(x) (is_dig(x) || (to_low(x) >= 'a' && to_low(x) <= 'f')) + #define to_int(x) ((is_dig(x)) ? ((x) - '0') : (to_low(x) - 'a' + 10)) + + int ci = curInd; + char ch1 = (ci + 0 < (int)pattern.size()) ? pattern[ci + 0] : -1; + char ch2 = (ci + 1 < (int)pattern.size()) ? pattern[ci + 1] : -1; + std::string s = " "; + + if (is_hex(ch1) && is_hex(ch2)) + { + curInd += 2; + s[0] = (to_int(ch1) << 4 & 0xF0) | (to_int(ch2) & 0x0F); + } + + return s; + #undef to_low + #undef is_dig + #undef is_hex + #undef to_int +} +std::string Pattern::parseEscape(bool & inv, bool & quo) +{ + char ch = pattern[curInd++]; + std::string classes = ""; + + if (curInd > (int)pattern.size()) + { + raiseError(); + return NULL; + } + + quo = 0; + inv = 0; + switch (ch) + { + case 'p': classes = parsePosix(); break; + case 'P': classes = "!!"; classes += parsePosix(); break; + case 'd': classes = "0123456789"; break; + case 'D': classes = "!!0123456789"; break; + case 's': classes = " \t\r\n\f"; break; + case 'S': classes = "!! \t\r\n\f"; break; + case 'w': classes = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_"; break; + case 'W': classes = "!!abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_"; break; + case '0': classes = parseOctal(); break; + case 'x': classes = parseHex(); break; + + case 'Q': quo = 1; break; + case 't': classes = "\t"; break; + case 'r': classes = "\r"; break; + case 'n': classes = "\n"; break; + case 'f': classes = "\f"; break; + case 'a': classes = "\a"; break; + case 'e': classes = "\r"; break; + default: classes = " "; classes[0] = ch; break; + } + if (classes.substr(0, 2) == "!!") + { + classes = classes.substr(2); + inv = 1; + } + return classes; +} +NFANode * Pattern::parseRegisteredPattern(NFANode ** end) +{ + int i, j; + std::string s; + NFANode * ret = NULL; + for (i = curInd; i < (int)pattern.size() && pattern[i] != '}'; ++i) { } + if (pattern[i] != '}') { raiseError(); return NULL; } + if (i == curInd + 1) { raiseError(); return NULL; } // {} + if ( + !( + (pattern[curInd] >= 'a' && pattern[curInd] <= 'z') || + (pattern[curInd] >= 'A' && pattern[curInd] <= 'Z') || + (pattern[curInd] == '_') + ) + ) + { + raiseError(); + return NULL; + } + for (j = curInd; !error && j < i; ++j) + { + if ( + !( + (pattern[j] >= 'a' && pattern[j] <= 'z') || + (pattern[j] >= 'A' && pattern[j] <= 'Z') || + (pattern[j] >= '0' && pattern[j] <= '9') || + (pattern[j] == '_') + ) + ) + { + raiseError(); + return NULL; + } + } + s = pattern.substr(curInd, i - curInd); + if (registeredPatterns.find(s) == registeredPatterns.end()) raiseError(); + else + { + unsigned long oflags = flags; + std::string op = pattern; + int ci = i + 1; + + pattern = registeredPatterns[s].first; + curInd = 0; + flags = registeredPatterns[s].second; + + --groupCount; + ret = parse(0, 0, end); + + pattern = op; + curInd = ci; + flags = oflags; + } + if (error) { *end = ret = NULL; } + return ret; +} + +// look behind should interpret everything as a literal (except \\) since the +// pattern must have a concrete length +NFANode * Pattern::parseBehind(const bool pos, NFANode ** end) +{ + std::string t = ""; + while (curInd < (int)pattern.size() && pattern[curInd] != ')') + { + char ch = pattern[curInd++]; + t += " "; + if (ch == '\\') + { + if (curInd + 1 >= (int)pattern.size()) + { + raiseError(); + return *end = registerNode(new NFACharNode(' ')); + } + ch = pattern[curInd++]; + } + t[t.size() - 1] = ch; + } + if (curInd >= (int)pattern.size() || pattern[curInd] != ')') raiseError(); + else ++curInd; + return *end = registerNode(new NFALookBehindNode(t, pos)); +} +NFANode * Pattern::parseQuote() +{ + bool done = 0; + std::string s = ""; + + while (!done) + { + if (curInd >= (int)pattern.size()) + { + raiseError(); + done = 1; + } + else if (pattern.substr(curInd, 2) == "\\E") + { + curInd += 2; + done = 1; + } + else if (pattern[curInd] == '\\') + { + s += " "; + s[s.size() - 1] = pattern[++curInd]; + ++curInd; + } + else + { + s += " "; + s[s.size() - 1] = pattern[curInd++]; + } + } + if ((flags & Pattern::CASE_INSENSITIVE) != 0) return registerNode(new NFACIQuoteNode(s)); + return registerNode(new NFAQuoteNode(s)); +} +NFANode * Pattern::parse(const bool inParen, const bool inOr, NFANode ** end) +{ + NFANode * start, * cur, * next = NULL; + std::string t; + int grc = groupCount++; + bool inv, quo; + bool ahead = 0, pos = 0, noncap = 0, indep = 0; + + if (inParen) + { + if (pattern[curInd] == '?') + { + ++curInd; + --groupCount; + if (pattern[curInd] == ':') { noncap = 1; ++curInd; grc = --nonCapGroupCount; } + else if (pattern[curInd] == '=') { ++curInd; ahead = 1; pos = 1; } + else if (pattern[curInd] == '!') { ++curInd; ahead = 1; pos = 0; } + else if (pattern.substr(curInd, 2) == "<=") { curInd += 2; return parseBehind(1, end); } + else if (pattern.substr(curInd, 2) == "<!") { curInd += 2; return parseBehind(0, end); } + else if (pattern[curInd] == '>') { ++curInd; indep = 1; } + else { raiseError(); return NULL; } + if (noncap) cur = start = registerNode(new NFAGroupHeadNode(grc)); + else cur = start = registerNode(new NFASubStartNode); + } + else cur = start = registerNode(new NFAGroupHeadNode(grc)); + } + else cur = start = registerNode(new NFASubStartNode); + while (curInd < (int)pattern.size()) + { + char ch = pattern[curInd++]; + + next = NULL; + if (error) return NULL; + switch (ch) + { + case '^': + if ((flags & Pattern::MULTILINE_MATCHING) != 0) next = registerNode(new NFAStartOfLineNode); + else next = registerNode(new NFAStartOfInputNode); + break; + case '$': + if ((flags & Pattern::MULTILINE_MATCHING) != 0) next = registerNode(new NFAEndOfLineNode); + else next = registerNode(new NFAEndOfInputNode(0)); + break; + case '|': + --groupCount; + cur->next = registerNode(new NFAAcceptNode); + cur = start = registerNode(new NFAOrNode(start, parse(inParen, 1))); + break; + case '\\': + if (curInd < (int)pattern.size()) + { + bool eoi = 0; + switch (pattern[curInd]) + { + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': next = parseBackref(); break; + case 'A': ++curInd; next = registerNode(new NFAStartOfInputNode); break; + case 'B': ++curInd; next = registerNode(new NFAWordBoundaryNode(0)); break; + case 'b': ++curInd; next = registerNode(new NFAWordBoundaryNode(1)); break; + case 'G': ++curInd; next = registerNode(new NFAEndOfMatchNode); break; + case 'Z': eoi = 1; + case 'z': ++curInd; next = registerNode(new NFAEndOfInputNode(eoi)); break; + default: + t = parseEscape(inv, quo); + if (!quo) + { + if (t.size() > 1 || inv) + { + if ((flags & Pattern::CASE_INSENSITIVE) != 0) next = registerNode(new NFACIClassNode(t, inv)); + else next = registerNode(new NFAClassNode(t, inv)); + } + else + { + next = registerNode(new NFACharNode(t[0])); + } + } + else + { + next = parseQuote(); + } + } + } + else raiseError(); + break; + case '[': + if ((flags & Pattern::CASE_INSENSITIVE) == 0) + { + NFAClassNode * clazz = new NFAClassNode(); + std::string s = parseClass(); + for (int i = 0; i < (int)s.size(); ++i) clazz->vals[s[i]] = 1; + next = registerNode(clazz); + } + else + { + NFACIClassNode * clazz = new NFACIClassNode(); + std::string s = parseClass(); + for (int i = 0; i < (int)s.size(); ++i) clazz->vals[tolower(s[i])] = 1; + next = registerNode(clazz); + } + break; + case '.': + { + bool useN = 1, useR = 1; + NFAClassNode * clazz = new NFAClassNode(1); + if ((flags & Pattern::UNIX_LINE_MODE) != 0) useR = 0; + if ((flags & Pattern::DOT_MATCHES_ALL) != 0) useN = useR = 0; + if (useN) clazz->vals['\n'] = 1; + if (useR) clazz->vals['\r'] = 1; + next = registerNode(clazz); + } + break; + case '(': + { + NFANode * end, * t1, * t2; + t1 = parse(1, 0, &end); + if (!t1) raiseError(); + else if (t1->isGroupHeadNode() && (t2 = quantifyGroup(t1, end, grc)) != NULL) + { + cur->next = t2; + cur = t2->next; + } + else + { + cur->next = t1; + cur = end; + } + } + break; + case ')': + if (!inParen) raiseError(); + else if (inOr) + { + --curInd; + cur = cur->next = registerNode(new NFAAcceptNode); + return start; + } + else + { + if (ahead) + { + cur = cur->next = registerNode(new NFAAcceptNode); + return *end = registerNode(new NFALookAheadNode(start, pos)); + } + else if (indep) + { + cur = cur->next = registerNode(new NFAAcceptNode); + return *end = registerNode(new NFAPossessiveQuantifierNode(this, start, 1, 1)); + } + else // capping or noncapping, it doesnt matter + { + *end = cur = cur->next = registerNode(new NFAGroupTailNode(grc)); + next = quantifyGroup(start, *end, grc); + if (next) + { + start = next; + *end = next->next; + } + return start; + } + } + break; + case '{': // registered pattern + cur->next = parseRegisteredPattern(&next); + if (cur->next) cur = next; + break; + case '*': + case '+': + case '?': + case '}': + case ']': + raiseError(); + break; + default: + if ((flags & Pattern::CASE_INSENSITIVE) != 0) next = registerNode(new NFACICharNode(ch)); + else next = registerNode(new NFACharNode(ch)); + break; + } + if (next) + { + cur = cur->next = quantify(next); + } + } + if (inParen) raiseError(); + else + { + if (inOr) cur = cur->next = registerNode(new NFAAcceptNode); + if (end) *end = cur; + } + + if (error) return NULL; + + return start; +} + +Pattern * Pattern::compile(const std::string & pattern, const unsigned long mode) +{ + Pattern * p = new Pattern(pattern); + NFANode * end; + + p->flags = mode; + if ((mode & Pattern::LITERAL) != 0) + { + p->head = p->registerNode(new NFAStartNode); + if ((mode & Pattern::CASE_INSENSITIVE) != 0) p->head->next = p->registerNode(new NFACIQuoteNode(pattern)); + else p->head->next = p->registerNode(new NFAQuoteNode(pattern)); + p->head->next->next = p->registerNode(new NFAEndNode); + } + else + { + p->head = p->parse(0, 0, &end); + if (!p->head) + { + delete p; + p = NULL; + } + else + { + if (!(p->head && p->head->isStartOfInputNode())) + { + NFANode * n = p->registerNode(new NFAStartNode); + n->next = p->head; + p->head = n; + } + end->next = p->registerNode(new NFAEndNode); + } + } + if (p != NULL) + { + p->matcher = new Matcher(p, ""); + } + + return p; +} + +Pattern * Pattern::compileAndKeep(const std::string & pattern, const unsigned long mode) +{ + Pattern * ret = NULL; + std::map<std::string, Pattern*>::iterator it = compiledPatterns.find(pattern); + + if (it != compiledPatterns.end()) + { + ret = it->second; + } + else + { + ret = compile(pattern, mode); + compiledPatterns[pattern] = ret; + } + + return ret; +} +std::string Pattern::replace(const std::string & pattern, const std::string & str, + const std::string & replacementText, const unsigned long mode) +{ + std::string ret; + Pattern * p = Pattern::compile(pattern, mode); + if (p) + { + ret = p->replace(str, replacementText); + delete p; + } + return ret; +} + +std::vector<std::string> Pattern::split(const std::string & pattern, const std::string & str, const bool keepEmptys, + const unsigned long limit, const unsigned long mode) +{ + std::vector<std::string> ret; + Pattern * p = Pattern::compile(pattern, mode); + if (p) + { + ret = p->split(str, keepEmptys, limit); + delete p; + } + return ret; +} + +std::vector<std::string> Pattern::findAll(const std::string & pattern, const std::string & str, const unsigned long mode) +{ + std::vector<std::string> ret; + Pattern * p = Pattern::compile(pattern, mode); + if (p) + { + ret = p->findAll(str); + delete p; + } + return ret; +} + +bool Pattern::matches(const std::string & pattern, const std::string & str, const unsigned long mode) +{ + bool ret = 0; + Pattern * p = compile(pattern, mode); + + if (p) + { + ret = p->matches(str); + delete p; + } + + return ret; +} + +bool Pattern::registerPattern(const std::string & name, const std::string & pattern, const unsigned long mode) +{ + Pattern * p = Pattern::compile(pattern, mode); + if (!p) return 0; + Pattern::registeredPatterns[name] = std::make_pair(pattern, mode); + delete p; + return 1; +} + +void Pattern::unregisterPatterns() +{ + registeredPatterns.clear(); +} +void Pattern::clearPatternCache() +{ + std::map<std::string, Pattern*>::iterator it; + for (it = compiledPatterns.begin(); it != compiledPatterns.end(); ++it) + { + delete it->second; + } + compiledPatterns.clear(); +} + +std::pair<std::string, int> Pattern::findNthMatch(const std::string & pattern, const std::string & str, + const int matchNum, const unsigned long mode) +{ + std::pair<std::string, int> ret; + Pattern * p = Pattern::compile(pattern, mode); + + ret.second = -1; + if (p) + { + int i = -1; + p->matcher->setString(str); + while (i < matchNum && p->matcher->findNextMatch()) { ++i; } + if (i == matchNum && p->matcher->getStartingIndex() >= 0) + { + ret.first = p->matcher->getGroup(0); + ret.second = p->matcher->getStartingIndex(); + } + delete p; + } + + return ret; +} + +Pattern::~Pattern() +{ + /* + nodes.clear(); + if (head) head->findAllNodes(nodes); + */ + if (matcher) delete matcher; + for (std::map<NFANode*, bool>::iterator it = nodes.begin(); it != nodes.end(); ++it) + { + delete it->first; + } +} +std::string Pattern::replace(const std::string & str, const std::string & replacementText) +{ + int li = 0; + std::string ret = ""; + + matcher->setString(str); + while (matcher->findNextMatch()) + { + ret += str.substr(li, matcher->getStartingIndex() - li); + ret += matcher->replaceWithGroups(replacementText); + li = matcher->getEndingIndex(); + } + ret += str.substr(li); + + return ret; +} +std::vector<std::string> Pattern::split(const std::string & str, const bool keepEmptys, const unsigned long limit) +{ + unsigned long lim = (limit == 0 ? MAX_QMATCH : limit); + int li = 0; + std::vector<std::string> ret; + + matcher->setString(str); + + while (matcher->findNextMatch() && ret.size() < lim) + { + if (matcher->getStartingIndex() == 0 && keepEmptys) ret.push_back(""); + if ((matcher->getStartingIndex() != matcher->getEndingIndex()) || keepEmptys) + { + ret.push_back(str.substr(li, matcher->getStartingIndex() - li)); + li = matcher->getEndingIndex(); + } + } + if (li != (int)str.size()) ret.push_back(str.substr(li)); + + return ret; +} +std::vector<std::string> Pattern::findAll(const std::string & str) +{ + matcher->setString(str); + return matcher->findAll(); +} +bool Pattern::matches(const std::string & str) +{ + matcher->setString(str); + return matcher->matches(); +} +unsigned long Pattern::getFlags() const +{ + return flags; +} +std::string Pattern::getPattern() const +{ + return pattern; +} +Matcher * Pattern::createMatcher(const std::string & str) +{ + return new Matcher(this, str); +} + +// NFANode + +NFANode::NFANode() { next = NULL; } +NFANode::~NFANode() { } +void NFANode::findAllNodes(std::map<NFANode*, bool> & soFar) +{ + if (soFar.find(this) == soFar.end()) return; + soFar[this] = 1; + if (next) next->findAllNodes(soFar); +} + +// NFACharNode + +NFACharNode::NFACharNode(const char c) { ch = c; } +int NFACharNode::match(const std::string & str, Matcher * matcher, const int curInd) const +{ + if (curInd < (int)str.size() && str[curInd] == ch) return next->match(str, matcher, curInd + 1); + return -1; +} + +// NFACICharNode + +NFACICharNode::NFACICharNode(const char c) { ch = tolower(c); } +int NFACICharNode::match(const std::string & str, Matcher * matcher, const int curInd) const +{ + if (curInd < (int)str.size() && tolower(str[curInd]) == ch) return next->match(str, matcher, curInd + 1); + return -1; +} + +// NFAStartNode + +NFAStartNode::NFAStartNode() { } +int NFAStartNode::match(const std::string & str, Matcher * matcher, const int curInd) const +{ + int ret = -1, ci = curInd; + + matcher->starts[0] = curInd; + if ((matcher->getFlags() & Matcher::MATCH_ENTIRE_STRING) == (unsigned int)Matcher::MATCH_ENTIRE_STRING) + { + if (curInd != 0) + { + matcher->starts[0] = -1; + return -1; + } + return next->match(str, matcher, 0); + } + while ((ret = next->match(str, matcher, ci)) == -1 && ci < (int)str.size()) + { + matcher->clearGroups(); + matcher->starts[0] = ++ci; + } + if (ret < 0) matcher->starts[0] = -1; + return ret; +} + +// NFAEndNode + +NFAEndNode::NFAEndNode() { } +int NFAEndNode::match(const std::string & str, Matcher * matcher, const int curInd) const +{ + matcher->ends[0] = curInd; + if ((matcher->getFlags() & Matcher::MATCH_ENTIRE_STRING) != 0) + { + if (curInd == (int)str.size()) return curInd; + matcher->ends[0] = -1; + return -1; + } + return curInd; +} + +// NFAQuantifierNode + +void NFAQuantifierNode::findAllNodes(std::map<NFANode*, bool> & soFar) +{ + inner->findAllNodes(soFar); + NFANode::findAllNodes(soFar); +} +NFAQuantifierNode::NFAQuantifierNode(Pattern * pat, NFANode * internal, const int minMatch, const int maxMatch) +{ + inner = internal; + inner->next = pat->registerNode(new NFAAcceptNode); + min = (minMatch < Pattern::MIN_QMATCH) ? Pattern::MIN_QMATCH : minMatch; + max = (maxMatch > Pattern::MAX_QMATCH) ? Pattern::MAX_QMATCH : maxMatch; +} + +int NFAQuantifierNode::match(const std::string & str, Matcher * matcher, const int curInd) const +{ + int i0, i1, i2 = 0; + + i0 = i1 = curInd; + while (i2 < min) + { + + ++i2; + i1 = inner->match(str, matcher, i0); + if (i1 <= i0) return i1; // i1 < i0 means i1 is -1 + i0 = i1; + } + + return i1; +} +// NFAGreedyQuantifierNode + +NFAGreedyQuantifierNode::NFAGreedyQuantifierNode(Pattern * pat, NFANode * internal, const int minMatch, const int maxMatch) + : NFAQuantifierNode(pat, internal, minMatch, maxMatch) { } +int NFAGreedyQuantifierNode::match(const std::string & str, Matcher * matcher, const int curInd) const +{ + int t = NFAQuantifierNode::match(str, matcher, curInd); + if (t != -1) return matchInternal(str, matcher, t, min); + return t; +} +int NFAGreedyQuantifierNode::matchInternal(const std::string & str, Matcher * matcher, const int curInd, const int soFar) const +{ + if (soFar >= max) return next->match(str, matcher, curInd); + + int i, j; + + i = inner->match(str, matcher, curInd); + if (i != -1) + { + j = matchInternal(str, matcher, i, soFar + 1); + if (j != -1) return j; + } + return next->match(str, matcher, curInd); +} + +// NFALazyQuantifierNode + +NFALazyQuantifierNode::NFALazyQuantifierNode(Pattern * pat, NFANode * internal, const int minMatch, const int maxMatch) + : NFAQuantifierNode(pat, internal, minMatch, maxMatch) { } +int NFALazyQuantifierNode::match(const std::string & str, Matcher * matcher, const int curInd) const +{ + int i, j, m = NFAQuantifierNode::match(str, matcher, curInd); + + if (m == -1) return -1; + + for (i = min; i < max; ++i) + { + j = next->match(str, matcher, m); + if (j == -1) + { + j = inner->match(str, matcher, m); + // if j < m, then j is -1, so we bail. + // if j == m, then we would just go and call next->match on the same index, + // but it already failed trying to match right there, so we know we can + // just bail + if (j <= m) return -1; + m = j; + } + else return j; + } + return next->match(str, matcher, m); +} + +// NFAPossessiveQuantifierNode + +NFAPossessiveQuantifierNode::NFAPossessiveQuantifierNode(Pattern * pat, NFANode * internal, const int minMatch, const int maxMatch) + : NFAQuantifierNode(pat, internal, minMatch, maxMatch) { } +int NFAPossessiveQuantifierNode::match(const std::string & str, Matcher * matcher, const int curInd) const +{ + int i, j, m = NFAQuantifierNode::match(str, matcher, curInd); + + if (m == -1) return -1; + for (i = min; i < max; ++i) + { + j = inner->match(str, matcher, m); + if (j <= m) return next->match(str, matcher, m); + m = j; + } + return next->match(str, matcher, m); +} + +// NFAAcceptNode + +NFAAcceptNode::NFAAcceptNode() { } +int NFAAcceptNode::match(const std::string & str, Matcher * matcher, const int curInd) const +{ + if (!next) return curInd; + else return next->match(str, matcher, curInd); +} + +// NFAClassNode + +NFAClassNode::NFAClassNode(const bool invert) +{ + inv = invert; +} +NFAClassNode::NFAClassNode(const std::string & clazz, const bool invert) +{ + inv = invert; + for (int i = 0; i < (int)clazz.size(); ++i) vals[clazz[i]] = 1; +} +int NFAClassNode::match(const std::string & str, Matcher * matcher, const int curInd) const +{ + if (curInd < (int)str.size() && ((vals.find(str[curInd]) != vals.end()) ^ inv)) + { + return next->match(str, matcher, curInd + 1); + } + return -1; +} + +// NFACIClassNode + +NFACIClassNode::NFACIClassNode(const bool invert) +{ + inv = invert; +} +NFACIClassNode::NFACIClassNode(const std::string & clazz, const bool invert) +{ + inv = invert; + for (int i = 0; i < (int)clazz.size(); ++i) vals[tolower(clazz[i])] = 1; +} +int NFACIClassNode::match(const std::string & str, Matcher * matcher, const int curInd) const +{ + if (curInd < (int)str.size() && ((vals.find(tolower(str[curInd])) != vals.end()) ^ inv)) + { + return next->match(str, matcher, curInd + 1); + } + return -1; +} + +#undef to_lower + +// NFASubStartNode + +NFASubStartNode::NFASubStartNode() { } +int NFASubStartNode::match(const std::string & str, Matcher * matcher, const int curInd) const +{ + return next->match(str, matcher, curInd); +} + +// NFAOrNode + +NFAOrNode::NFAOrNode(NFANode * first, NFANode * second) : one(first), two(second) { } +void NFAOrNode::findAllNodes(std::map<NFANode*, bool> & soFar) +{ + if (one) one->findAllNodes(soFar); + if (two) two->findAllNodes(soFar); + NFANode::findAllNodes(soFar); +} +int NFAOrNode::match(const std::string & str, Matcher * matcher, const int curInd) const +{ + int ci = one->match(str, matcher, curInd); + + if (ci != -1) ci = next->match(str, matcher, ci); + if (ci != -1) return ci; + if (ci == -1) ci = two->match(str, matcher, curInd); + if (ci != -1) ci = next->match(str, matcher, ci); + return ci; +} + +// NFAQuoteNode + +NFAQuoteNode::NFAQuoteNode(const std::string & quoted) : qStr(quoted) { } +int NFAQuoteNode::match(const std::string & str, Matcher * matcher, const int curInd) const +{ + if (curInd + qStr.size() > str.size()) return -1; + if (str.substr(curInd, qStr.size()) != qStr) return -1; + return next->match(str, matcher, curInd + qStr.size()); +} + +// NFACIQuoteNode + +NFACIQuoteNode::NFACIQuoteNode(const std::string & quoted) : qStr(quoted) { } +int NFACIQuoteNode::match(const std::string & str, Matcher * matcher, const int curInd) const +{ + if (curInd + qStr.size() > str.size()) return -1; + if (str_icmp(str.substr(curInd, qStr.size()).c_str(), qStr.c_str())) return -1; + return next->match(str, matcher, qStr.size()); +} + +// NFALookAheadNode + +NFALookAheadNode::NFALookAheadNode(NFANode * internal, const bool positive) : NFANode(), pos(positive), inner(internal) { } +void NFALookAheadNode::findAllNodes(std::map<NFANode*, bool> & soFar) +{ + if (inner) inner->findAllNodes(soFar); + NFANode::findAllNodes(soFar); +} +int NFALookAheadNode::match(const std::string & str, Matcher * matcher, const int curInd) const +{ + return ((inner->match(str, matcher, curInd) == -1) ^ pos) ? next->match(str, matcher, curInd) : -1; +} + +// NFALookBehindNode + +NFALookBehindNode::NFALookBehindNode(const std::string & str, const bool positive) : pos(positive), mStr(str) { } +int NFALookBehindNode::match(const std::string & str, Matcher * matcher, const int curInd) const +{ + if (pos) + { + if (curInd < (int)mStr.size()) return -1; + if (str.substr(curInd - mStr.size(), mStr.size()) == mStr) return next->match(str, matcher, curInd); + } + else + { + if (curInd < (int)mStr.size()) return next->match(str, matcher, curInd); + if (str.substr(curInd - mStr.size(), mStr.size()) == mStr) return -1; + return next->match(str, matcher, curInd); + } + return -1; +} + +// NFAStartOfLineNode + +NFAStartOfLineNode::NFAStartOfLineNode() { } +int NFAStartOfLineNode::match(const std::string & str, Matcher * matcher, const int curInd) const +{ + if (curInd == 0 || str[curInd - 1] == '\n' || str[curInd - 1] == '\r') + { + return next->match(str, matcher, curInd); + } + return -1; +} + +// NFAEndOfLineNode + +NFAEndOfLineNode::NFAEndOfLineNode() { } +int NFAEndOfLineNode::match(const std::string & str, Matcher * matcher, const int curInd) const +{ + if (curInd >= (int)str.size() || str[curInd] == '\n' || str[curInd] == '\r') + { + return next->match(str, matcher, curInd); + } + return -1; +} + +// NFAReferenceNode + +NFAReferenceNode::NFAReferenceNode(const int groupIndex) : gi(groupIndex) { } +int NFAReferenceNode::match(const std::string & str, Matcher * matcher, const int curInd) const +{ + int len = matcher->ends[gi] - matcher->starts[gi]; + int ni = -1; + if (gi < 1 || matcher->ends[gi] < matcher->starts[gi] || len == 0) ni = curInd; + else if (curInd + len > (int)str.size()) return -1; + else if (str.substr(curInd, len) != str.substr(matcher->starts[gi], len)) return -1; + else ni = curInd + len; + + return next->match(str, matcher, ni); +} + +// NFAStartOfInputNode + +NFAStartOfInputNode::NFAStartOfInputNode() { } +int NFAStartOfInputNode::match(const std::string & str, Matcher * matcher, const int curInd) const +{ + if (curInd == 0) return next->match(str, matcher, curInd); + return -1; +} + +// NFAEndOfInputNode + +NFAEndOfInputNode::NFAEndOfInputNode(const bool lookForTerm) : term(lookForTerm) { } +int NFAEndOfInputNode::match(const std::string & str, Matcher * matcher, const int curInd) const +{ + int len = (int)str.size(); + if (curInd == len) return next->match(str, matcher, curInd); + else if (term) + { + if (curInd == len - 1 && (str[curInd] == '\r' || str[curInd] == '\n')) + { + return next->match(str, matcher, curInd); + } + else if (curInd == len - 2 && str.substr(curInd, 2) == "\r\n") + { + return next->match(str, matcher, curInd); + } + } + return -1; +} + +// NFAWordBoundaryNode + +NFAWordBoundaryNode::NFAWordBoundaryNode(const bool positive) : pos(positive) { } +int NFAWordBoundaryNode::match(const std::string & str, Matcher * matcher, const int curInd) const +{ + #define is_alpha(x) (((x) >= 'a' && (x) <= 'z') || ((x) >= 'A' && (x) <= 'Z')) + + int len = (int)str.size(); + bool ok = 0; + char c1 = (curInd - 1 < len) ? str[curInd - 1] : -1; + char c2 = (curInd < len) ? str[curInd ] : -1; + + if (curInd == len) return next->match(str, matcher, curInd); + if (is_alpha(c1) ^ is_alpha(c2)) ok = 1; + if (ok && pos) return next->match(str, matcher, curInd); + return -1; + + #undef is_alpha +} + +// NFAEndOfMatchNode + +NFAEndOfMatchNode::NFAEndOfMatchNode() { } +int NFAEndOfMatchNode::match(const std::string & str, Matcher * matcher, const int curInd) const +{ + if (curInd == matcher->lm) return next->match(str, matcher, curInd); + return -1; +} + +// NFAGroupHeadNode + +NFAGroupHeadNode::NFAGroupHeadNode(const int groupIndex) : gi(groupIndex) { } +int NFAGroupHeadNode::match(const std::string & str, Matcher * matcher, const int curInd) const +{ + int ret, o = matcher->starts[gi]; + + matcher->starts[gi] = curInd; + ret = next->match(str, matcher, curInd); + if (ret < 0) matcher->starts[gi] = o; + + return ret; +} + +// NFAGroupTailNode + +NFAGroupTailNode::NFAGroupTailNode(const int groupIndex) : gi(groupIndex) { } +int NFAGroupTailNode::match(const std::string & str, Matcher * matcher, const int curInd) const +{ + int ret, o = matcher->ends[gi]; + + matcher->ends[gi] = curInd; + ret = next->match(str, matcher, curInd); + if (ret < 0) matcher->ends[gi] = o; + + return ret; +} + +// NFAGroupLoopPrologueNode + +NFAGroupLoopPrologueNode::NFAGroupLoopPrologueNode(const int groupIndex) : gi(groupIndex) { } +int NFAGroupLoopPrologueNode::match(const std::string & str, Matcher * matcher, const int curInd) const +{ + int ret, o1 = matcher->groups[gi], o2 = matcher->groupPos[gi], o3 = matcher->groupIndeces[gi]; + + matcher->groups[gi] = 0; + matcher->groupPos[gi] = 0; + matcher->groupIndeces[gi] = -1; + ret = next->match(str, matcher, curInd); + if (ret < 0) + { + matcher->groups[gi] = o1; + matcher->groupPos[gi] = o2; + matcher->groupIndeces[gi] = o3; + } + + return ret; +} + +// NFAGroupLoopNode + +NFAGroupLoopNode::NFAGroupLoopNode(NFANode * internal, const int minMatch, const int maxMatch, + const int groupIndex, const int matchType) +{ + inner = internal; + min = minMatch; + max = maxMatch; + gi = groupIndex; + type = matchType; +} +void NFAGroupLoopNode::findAllNodes(std::map<NFANode*, bool> & soFar) +{ + if (inner) inner->findAllNodes(soFar); + NFANode::findAllNodes(soFar); +} +int NFAGroupLoopNode::match(const std::string & str, Matcher * matcher, const int curInd) const +{ + bool b = (curInd > matcher->groupIndeces[gi]); + + if (b && matcher->groups[gi] < min) + { + ++matcher->groups[gi]; + int o = matcher->groupIndeces[gi]; + matcher->groupIndeces[gi] = curInd; + int ret = inner->match(str, matcher, curInd); + if (ret < 0) + { + matcher->groupIndeces[gi] = o; + --matcher->groups[gi]; + } + return ret; + } + else if (!b || matcher->groups[gi] >= max) + { + return next->match(str, matcher, curInd); + } + else + { + switch (type) + { + case 0: return matchGreedy(str, matcher, curInd); + case 1: return matchLazy(str, matcher, curInd); + case 2: return matchPossessive(str, matcher, curInd); + } + } + return -1; +} +int NFAGroupLoopNode::matchGreedy(const std::string & str, Matcher * matcher, const int curInd) const +{ + int o = matcher->groupIndeces[gi]; // save our info for backtracking + matcher->groupIndeces[gi] = curInd; // move along + ++matcher->groups[gi]; + int ret = inner->match(str, matcher, curInd); // match internally + if (ret < 0) + { // if we failed, then restore info and match next + --matcher->groups[gi]; + matcher->groupIndeces[gi] = o; + ret = next->match(str, matcher, curInd); + } + return ret; +} +int NFAGroupLoopNode::matchLazy(const std::string & str, Matcher * matcher, const int curInd) const +{ + int ret = next->match(str, matcher, curInd); // be lazy, just go on + if (ret < 0) + { + int o = matcher->groupIndeces[gi]; // save info for backtracking + matcher->groupIndeces[gi] = curInd; // advance our position + ++matcher->groups[gi]; + ret = inner->match(str, matcher, curInd); // match our internal stuff + if (ret < 0) // if we failed, then restore the info + { + --matcher->groups[gi]; + matcher->groupIndeces[gi] = o; + } + } + return ret; +} +int NFAGroupLoopNode::matchPossessive(const std::string & str, Matcher * matcher, const int curInd) const +{ + int o = matcher->groupIndeces[gi]; // save info for backtracking + matcher->groupPos[gi] = matcher->groups[gi]; // set a flag stating we have matcher at least this much + matcher->groupIndeces[gi] = curInd; // move along + ++matcher->groups[gi]; + int ret = inner->match(str, matcher, curInd); // try and match again + if (ret < 0) + { // if we fail, back off, but to an extent + --matcher->groups[gi]; + matcher->groupIndeces[gi] = o; + if (matcher->groups[gi] == matcher->groupPos[gi]) ret = next->match(str, matcher, curInd); + } + return ret; +} diff --git a/support/highlight/src/core/re/Pattern.h b/support/highlight/src/core/re/Pattern.h new file mode 100644 index 0000000000..a88974194c --- /dev/null +++ b/support/highlight/src/core/re/Pattern.h @@ -0,0 +1,1658 @@ +#ifndef __PATTERN_H__ +#define __PATTERN_H__ + +#include <vector> +#include <string> +#include <map> + +class Matcher; +class NFANode; +class NFAQuantifierNode; + +/** + This pattern class is very similar in functionality to Java's + java.util.regex.Pattern class. The pattern class represents an immutable + regular expression object. Instead of having a single object contain both the + regular expression object and the matching object, instead the two objects are + split apart. The {@link Matcher Matcher} class represents the maching + object. + + The Pattern class works primarily off of "compiled" patterns. A typical + instantiation of a regular expression looks like: + + <pre> + Pattern * p = Pattern::compile("a*b"); + Matcher * m = p->createMatcher("aaaaaab"); + if (m->matches()) ... + </pre> + + However, if you do not need to use a pattern more than once, it is often times + okay to use the Pattern's static methods insteads. An example looks like this: + + <pre> + if (Pattern::matches("a*b", "aaaab")) { ... } + </pre> + + This class does not currently support unicode. The unicode update for this + class is coming soon. + + This class is partially immutable. It is completely safe to call createMatcher + concurrently in different threads, but the other functions (e.g. split) should + not be called concurrently on the same <code>Pattern</code>. + + <table border="0" cellpadding="1" cellspacing="0"> + <tr align="left" bgcolor="#CCCCFF"> + <td> + <b>Construct</b> + </td> + <td> + <b>Matches</b> + </th> + </tr> + <tr> + <td colspan="2"> + + </td> + </tr> + <tr> + <td colspan="2"> + <b>Characters</b> + </td> + </tr> + <tr> + <td> + <code><i>x</i></code> + </td> + <td> + The character <code><i>x</i></code> + </td> + </tr> + <tr> + <td> + <code>\\</code> + </td> + <td> + The character <code>\</code> + </td> + </tr> + <tr> + <td> + <code>\0<i>nn</i></code> + </td> + <td> + The character with octal ASCII value <code><i>nn</i></code> + </td> + </tr> + <tr> + <td> + <code>\0<i>nnn</i></code> + </td> + <td> + The character with octal ASCII value <code><i>nnn</i></code> + </td> + </tr> + <tr> + <td> + <code>\x<i>hh</i></code> + </td> + <td> + The character with hexadecimal ASCII value <code><i>hh</i></code> + </td> + </tr> + <tr> + <td> + <code>\t</code> + </td> + <td> + A tab character + </td> + </tr> + <tr> + <td> + <code>\r</code> + </td> + <td> + A carriage return character + </td> + </tr> + <tr> + <td> + <code>\n</code> + </td> + <td> + A new-line character + </td> + </tr> + <tr> + <td colspan="2"> + + </td> + </tr> + <tr> + <td> + <b>Character Classes</b> + </td> + </tr> + <tr> + <td> + <code>[abc]</code> + </td> + <td> + Either <code>a</code>, <code>b</code>, or <code>c</code> + </td> + </tr> + <tr> + <td> + <code>[^abc]</code> + </td> + <td> + Any character but <code>a</code>, <code>b</code>, or <code>c</code> + </td> + </tr> + <tr> + <td> + <code>[a-zA-Z]</code> + </td> + <td> + Any character ranging from <code>a</code> thru <code>z</code>, or + <code>A</code> thru <code>Z</code> + </td> + </tr> + <tr> + <td> + <code>[^a-zA-Z]</code> + </td> + <td> + Any character except those ranging from <code>a</code> thru + <code>z</code>, or <code>A</code> thru <code>Z</code> + </td> + </tr> + <tr> + <td> + <code>[a\-z]</code> + </td> + <td> + Either <code>a</code>, <code>-</code>, or <code>z</code> + </td> + </tr> + <tr> + <td> + <code>[a-z[A-Z]]</code> + </td> + <td> + Same as <code>[a-zA-Z]</code> + </td> + </tr> + <tr> + <td> + <code>[a-z&&[g-i]]</code> + </td> + <td> + Any character in the intersection of <code>a-z</code> and + <code>g-i</code> + </td> + </tr> + <tr> + <td> + <code>[a-z&&[^g-i]]</code> + </td> + <td> + Any character in <code>a-z</code> and not in <code>g-i</code> + </td> + </tr> + <tr> + <td colspan="2"> + + </td> + </tr> + <tr> + <td colspan="2"> + <b>Prefefined character classes</b> + </td> + </tr> + <tr> + <td> + <code><b>.</b></code> + </td> + <td> + Any character. Multiline matching must be compiled into the pattern for + <code><b>.</b></code> to match a <code>\r</code> or a <code>\n</code>. + Even if multiline matching is enabled, <code><b>.</b></code> will not + match a <code>\r\n</code>, only a <code>\r</code> or a <code>\n</code>. + </td> + </tr> + <tr> + <td> + <code>\d</code> + </td> + <td> + <code>[0-9]</code> + </td> + </tr> + <tr> + <td> + <code>\D</code> + </td> + <td> + <code>[^\d]</code> + </td> + </tr> + <tr> + <td> + <code>\s</code> + </td> + <td> + <code>[ \t\r\n\x0B]</code> + </td> + </tr> + <tr> + <td> + <code>\S</code> + </td> + <td> + <code>[^\s]</code> + </td> + </tr> + <tr> + <td> + <code>\w</code> + </td> + <td> + <code>[a-zA-Z0-9_]</code> + </td> + </tr> + <tr> + <td> + <code>\W</code> + </td> + <td> + <code>[^\w]</code> + </td> + </tr> + <tr> + <td colspan="2"> + + </td> + </tr> + <tr> + <td colspan="2"> + <b>POSIX character classes + </td> + </tr> + <tr> + <td> + <code>\p{Lower}</code> + </td> + <td> + <code>[a-z]</code> + </td> + </tr> + <tr> + <td> + <code>\p{Upper}</code> + </td> + <td> + <code>[A-Z]</code> + </td> + </tr> + <tr> + <td> + <code>\p{ASCII}</code> + </td> + <td> + <code>[\x00-\x7F]</code> + </td> + </tr> + <tr> + <td> + <code>\p{Alpha}</code> + </td> + <td> + <code>[a-zA-Z]</code> + </td> + </tr> + <tr> + <td> + <code>\p{Digit}</code> + </td> + <td> + <code>[0-9]</code> + </td> + </tr> + <tr> + <td> + <code>\p{Alnum}</code> + </td> + <td> + <code>[\w&&[^_]]</code> + </td> + </tr> + <tr> + <td> + <code>\p{Punct}</code> + </td> + <td> + <code>[!"#$%&'()*+,-./:;<=>?@[\]^_`{|}~]</code> + </td> + </tr> + <tr> + <td> + <code>\p{XDigit}</code> + </td> + <td> + <code>[a-fA-F0-9]</code> + </td> + </tr> + <tr> + <td colspan="2"> + + </td> + </tr> + <tr> + <td colspan="2"> + <b>Boundary Matches</b> + </td> + </tr> + <tr> + <td> + <code>^</code> + </td> + <td> + The beginning of a line. Also matches the beginning of input. + </td> + </tr> + <tr> + <td> + <code>$</code> + </td> + <td> + The end of a line. Also matches the end of input. + </td> + </tr> + <tr> + <td> + <code>\b</code> + </td> + <td> + A word boundary + </td> + </tr> + <tr> + <td> + <code>\B</code> + </td> + <td> + A non word boundary + </td> + </tr> + <tr> + <td> + <code>\A</code> + </td> + <td> + The beginning of input + </td> + </tr> + <tr> + <td> + <code>\G</code> + </td> + <td> + The end of the previous match. Ensures that a "next" match will only + happen if it begins with the character immediately following the end of + the "current" match. + </td> + </tr> + <tr> + <td> + <code>\Z</code> + </td> + <td> + The end of input. Will also match if there is a single trailing + <code>\r\n</code>, a single trailing <code>\r</code>, or a single + trailing <code>\n</code>. + </td> + </tr> + <tr> + <td> + <code>\z</code> + </td> + <td> + The end of input + </td> + </tr> + <tr> + <td> + + </td> + </tr> + <tr> + <td colspan="2"> + <b>Greedy Quantifiers</b> + </td> + </tr> + <tr> + <td> + <code><i>x?</i></code> + </td> + <td> + <i>x</i>, either zero times or one time + </td> + </tr> + <tr> + <td> + <code><i>x*</i></code> + </td> + <td> + <i>x</i>, zero or more times + </td> + </tr> + <tr> + <td> + <code><i>x+</i></code> + </td> + <td> + <i>x</i>, one or more times + </td> + </tr> + <tr> + <td> + <code><i>x{n}</i></code> + </td> + <td> + <i>x</i>, exactly n times + </td> + </tr> + <tr> + <td> + <code><i>x{n,}</i></code> + </td> + <td> + <i>x</i>, at least <code><i>n</i></code> times + </td> + </tr> + <tr> + <td> + <code><i>x{,m}</i></code> + </td> + <td> + <i>x</i>, at most <code><i>m</i></code> times + </td> + </tr> + <tr> + <td> + <code><i>x{n,m}</i></code> + </td> + <td> + <i>x</i>, at least <code><i>n</i></code> times and at most + <code><i>m</i></code> times + </td> + </tr> + <tr> + <td> + + </td> + </tr> + <tr> + <td colspan="2"> + <b>Possessive Quantifiers</b> + </td> + </tr> + <tr> + <td> + <code><i>x?+</i></code> + </td> + <td> + <i>x</i>, either zero times or one time + </td> + </tr> + <tr> + <td> + <code><i>x*+</i></code> + </td> + <td> + <i>x</i>, zero or more times + </td> + </tr> + <tr> + <td> + <code><i>x++</i></code> + </td> + <td> + <i>x</i>, one or more times + </td> + </tr> + <tr> + <td> + <code><i>x{n}+</i></code> + </td> + <td> + <i>x</i>, exactly n times + </td> + </tr> + <tr> + <td> + <code><i>x{n,}+</i></code> + </td> + <td> + <i>x</i>, at least <code><i>n</i></code> times + </td> + </tr> + <tr> + <td> + <code><i>x{,m}+</i></code> + </td> + <td> + <i>x</i>, at most <code><i>m</i></code> times + </td> + </tr> + <tr> + <td> + <code><i>x{n,m}+</i></code> + </td> + <td> + <i>x</i>, at least <code><i>n</i></code> times and at most + <code><i>m</i></code> times + </td> + </tr> + <tr> + <td colspan="2"> + + </td> + </tr> + <tr> + <td colspan="2"> + <b>Reluctant Quantifiers</b> + </td> + </tr> + <tr> + <td> + <code><i>x??</i></code> + </td> + <td> + <i>x</i>, either zero times or one time + </td> + </tr> + <tr> + <td> + <code><i>x*?</i></code> + </td> + <td> + <i>x</i>, zero or more times + </td> + </tr> + <tr> + <td> + <code><i>x+?</i></code> + </td> + <td> + <i>x</i>, one or more times + </td> + </tr> + <tr> + <td> + <code><i>x{n}?</i></code> + </td> + <td> + <i>x</i>, exactly n times + </td> + </tr> + <tr> + <td> + <code><i>x{n,}?</i></code> + </td> + <td> + <i>x</i>, at least <code><i>n</i></code> times + </td> + </tr> + <tr> + <td> + <code><i>x{,m}?</i></code> + </td> + <td> + <i>x</i>, at most <code><i>m</i></code> times + </td> + </tr> + <tr> + <td> + <code><i>x{n,m}?</i></code> + </td> + <td> + <i>x</i>, at least <code><i>n</i></code> times and at most + <code><i>m</i></code> times + </td> + </tr> + <tr> + <td> + + </td> + </tr> + <tr> + <td colspan="2"> + <b>Operators</b> + </td> + </tr> + <tr> + <td> + <code><i>xy</i></code> + </td> + <td> + <code><i>x</i></code> then <code><i>y</i></code> + </td> + </tr> + <tr> + <td> + <code><i>x</i></code>|<code><i>y</i></code> + </td> + <td> + <code><i>x</i></code> or <code><i>y</i></code> + </td> + </tr> + <tr> + <td> + <code>(<i>x</i>)</code> + </td> + <td> + <code><i>x</i></code> as a capturing group + </td> + </tr> + <tr> + <td colspan="2"> + + </td> + </tr> + <tr> + <td colspan="2"> + <b>Quoting</b> + </td> + </tr> + <tr> + <td> + <code>\Q</code> + </td> + <td> + Nothing, but treat every character (including \s) literally until a + matching <code>\E</code> + </td> + </tr> + <tr> + <td> + <code>\E</code> + </td> + <td> + Nothing, but ends its matching <code>\Q</code> + </td> + </tr> + <tr> + <td> + + </td> + </tr> + <tr> + <td colspan="2"> + <b>Special Constructs</b> + </td> + </tr> + <tr> + <td> + <code>(?:<i>x</i>)</code> + </td> + <td> + <code><i>x</i></code>, but not as a capturing group + </td> + </tr> + <tr> + <td> + <code>(?=<i>x</i>)</code> + </td> + <td> + <code><i>x</i></code>, via positive lookahead. This means that the + expression will match only if it is trailed by <code><i>x</i></code>. + It will not "eat" any of the characters matched by + <code><i>x</i></code>. + </td> + </tr> + <tr> + <td> + <code>(?!<i>x</i>)</code> + </td> + <td> + <code><i>x</i></code>, via negative lookahead. This means that the + expression will match only if it is not trailed by + <code><i>x</i></code>. It will not "eat" any of the characters + matched by <code><i>x</i></code>. + </td> + </tr> + <tr> + <td> + <code>(?<=<i>x</i>)</code> + </td> + <td> + <code><i>x</i></code>, via positive lookbehind. <code><i>x</i></code> + cannot contain any quantifiers. + </td> + </tr> + <tr> + <td> + <code>(?<!<i>x</i>)</code> + </td> + <td> + <code><i>x</i></code>, via negative lookbehind. <code><i>x</i></code> + cannot contain any quantifiers. + </td> + </tr> + <tr> + <td> + <code>(?><i>x</i>)</code> + </td> + <td> + <code><i>x</i>{1}+</code> + </td> + </tr> + <tr> + <td colspan="2"> + + </td> + </tr> + <tr> + <td colspan="2"> + <b>Registered Expression Matching</b> + </td> + </tr> + <tr> + <td> + <code>{<i>x</i>}</code> + </td> + <td> + The registered pattern <code><i>x</i></code> + </td> + </tr> + </table> + + <hr> + + <i>Begin Text Extracted And Modified From java.util.regex.Pattern documentation</i> + + <h4> Backslashes, escapes, and quoting </h4> + + <p> The backslash character (<tt>'\'</tt>) serves to introduce escaped + constructs, as defined in the table above, as well as to quote characters + that otherwise would be interpreted as unescaped constructs. Thus the + expression <tt>\\</tt> matches a single backslash and <tt>\{</tt> matches a + left brace. + + <p> It is an error to use a backslash prior to any alphabetic character that + does not denote an escaped construct; these are reserved for future + extensions to the regular-expression language. A backslash may be used + prior to a non-alphabetic character regardless of whether that character is + part of an unescaped construct. + + <p>It is necessary to double backslashes in string literals that represent + regular expressions to protect them from interpretation by a compiler. The + string literal <tt>"\b"</tt>, for example, matches a single backspace + character when interpreted as a regular expression, while + <tt>"\\b"</tt> matches a word boundary. The string litera + <tt>"\(hello\)"</tt> is illegal and leads to a compile-time error; + in order to match the string <tt>(hello)</tt> the string literal + <tt>"\\(hello\\)"</tt> must be used. + + <h4> Character Classes </h4> + + <p> Character classes may appear within other character classes, and + may be composed by the union operator (implicit) and the intersection + operator (<tt>&&</tt>). + The union operator denotes a class that contains every character that is + in at least one of its operand classes. The intersection operator + denotes a class that contains every character that is in both of its + operand classes. + + <p> The precedence of character-class operators is as follows, from + highest to lowest: + + <blockquote><table border="0" cellpadding="1" cellspacing="0" + summary="Precedence of character class operators."> + + <tr><th>1 </th> + <td>Literal escape </td> + <td><tt>\x</tt></td></tr> + <tr><th>2 </th> + <td>Range</td> + <td><tt>a-z</tt></td></tr> + <tr><th>3 </th> + <td>Grouping</td> + <td><tt>[...]</tt></td></tr> + <tr><th>4 </th> + <td>Intersection</td> + <td><tt>[a-z&&[aeiou]]</tt></td></tr> + <tr><th>5 </th> + <td>Union</td> + <td><tt>[a-e][i-u]<tt></td></tr> + </table></blockquote> + + <p> Note that a different set of metacharacters are in effect inside + a character class than outside a character class. For instance, the + regular expression <tt>.</tt> loses its special meaning inside a + character class, while the expression <tt>-</tt> becomes a range + forming metacharacter. + + <a name="lt"> + + <a name="cg"> + <h4> Groups and capturing </h4> + + <p> Capturing groups are numbered by counting their opening parentheses from + left to right. In the expression <tt>((A)(B(C)))</tt>, for example, there + are four such groups: </p> + + <blockquote><table cellpadding=1 cellspacing=0 summary="Capturing group numberings"> + + <tr><th>1 </th> + <td><tt>((A)(B(C)))</tt></td></tr> + <tr><th>2 </th> + <td><tt>(A)</tt></td></tr> + <tr><th>3 </th> + <td><tt>(B(C))</tt></td></tr> + + <tr><th>4 </th> + <td><tt>(C)</tt></td></tr> + </table></blockquote> + + <p> Group zero always stands for the entire expression. + + <p> Capturing groups are so named because, during a match, each subsequence + of the input sequence that matches such a group is saved. The captured + subsequence may be used later in the expression, via a back reference, and + may also be retrieved from the matcher once the match operation is complete. + + <p> The captured input associated with a group is always the subsequence + that the group most recently matched. If a group is evaluated a second time + because of quantification then its previously-captured value, if any, will + be retained if the second evaluation fails. Matching the string + <tt>"aba"</tt> against the expression <tt>(a(b)?)+</tt>, for example, leaves + group two set to <tt>"b"</tt>. All captured input is discarded at the + beginning of each match. + + <p> Groups beginning with <tt>(?</tt> are pure, <i>non-capturing</i> groups + that do not capture text and do not count towards the group total. + + + <h4> Unicode support </h4> + + <p> Coming Soon. + + <h4> Comparison to Perl 5 </h4> + + <p>The <code>Pattern</code> engine performs traditional NFA-based matching + with ordered alternation as occurs in Perl 5. + + <p> Perl constructs not supported by this class: </p> + + <ul> + + <li><p> The conditional constructs <tt>(?{</tt><i>X</i><tt>})</tt> and + <tt>(?(</tt><i>condition</i><tt>)</tt><i>X</i><tt>|</tt><i>Y</i><tt>)</tt>, + </p></li> + + <li><p> The embedded code constructs <tt>(?{</tt><i>code</i><tt>})</tt> + and <tt>(??{</tt><i>code</i><tt>})</tt>,</p></li> + + <li><p> The embedded comment syntax <tt>(?#comment)</tt>, and </p></li> + + <li><p> The preprocessing operations <tt>\l</tt> <tt>\u</tt>, + <tt>\L</tt>, and <tt>\U</tt>. </p></li> + + <li><p> Embedded flags</p></li> + + </ul> + + <p> Constructs supported by this class but not by Perl: </p> + + <ul> + + <li><p> Possessive quantifiers, which greedily match as much as they can + and do not back off, even when doing so would allow the overall match to + succeed. </p></li> + + <li><p> Character-class union and intersection as described + above.</p></li> + + </ul> + + <p> Notable differences from Perl: </p> + + <ul> + + <li><p> In Perl, <tt>\1</tt> through <tt>\9</tt> are always interpreted + as back references; a backslash-escaped number greater than <tt>9</tt> is + treated as a back reference if at least that many subexpressions exist, + otherwise it is interpreted, if possible, as an octal escape. In this + class octal escapes must always begin with a zero. In this class, + <tt>\1</tt> through <tt>\9</tt> are always interpreted as back + references, and a larger number is accepted as a back reference if at + least that many subexpressions exist at that point in the regular + expression, otherwise the parser will drop digits until the number is + smaller or equal to the existing number of groups or it is one digit. + </p></li> + + <li><p> Perl uses the <tt>g</tt> flag to request a match that resumes + where the last match left off. This functionality is provided implicitly + by the <CODE>Matcher</CODE> class: Repeated invocations of the + <code>find</code> method will resume where the last match left off, + unless the matcher is reset. </p></li> + + <li><p> Perl is forgiving about malformed matching constructs, as in the + expression <tt>*a</tt>, as well as dangling brackets, as in the + expression <tt>abc]</tt>, and treats them as literals. This + class also strict and will not compile a pattern when dangling characters + are encountered.</p></li> + + </ul> + + + <p> For a more precise description of the behavior of regular expression + constructs, please see <a href="http://www.oreilly.com/catalog/regex2/"> + <i>Mastering Regular Expressions, 2nd Edition</i>, Jeffrey E. F. Friedl, + O'Reilly and Associates, 2002.</a> + </p> + <P> + + <i>End Text Extracted And Modified From java.util.regex.Pattern documentation</i> + + <hr> + + @author Jeffery Stuart + @since March 2003, Stable Since November 2004 + @version 1.04 + @memo A class used to represent "PERL 5"-ish regular expressions + */ +class Pattern +{ + friend class Matcher; + friend class NFANode; + friend class NFAQuantifierNode; + private: + /** + This constructor should not be called directly. Those wishing to use the + Pattern class should instead use the {@link compile compile} method. + + @param rhs The pattern to compile + @memo Creates a new pattern from the regular expression in <code>rhs</code>. + */ + Pattern(const std::string & rhs); + protected: + /** + This currently is not used, so don't try to do anything with it. + @memo Holds all the compiled patterns for quick access. + */ + static std::map<std::string, Pattern *> compiledPatterns; + /** + Holds all of the registered patterns as strings. Due to certain problems + with compilation of patterns, especially with capturing groups, this seemed + to be the best way to do it. + */ + static std::map<std::string, std::pair<std::string, unsigned long> > registeredPatterns; + protected: + /** + Holds all the NFA nodes used. This makes deletion of a pattern, as well as + clean-up from an unsuccessful compile much easier and faster. + */ + std::map<NFANode*, bool> nodes; + /** + Used when methods like split are called. The matcher class uses a lot of + dynamic memeory, so having an instance increases speedup of certain + operations. + */ + Matcher * matcher; + /** + The front node of the NFA. + */ + NFANode * head; + /** + The actual regular expression we rerpesent + */ + std::string pattern; + /** + Flag used during compilation. Once the pattern is successfully compiled, + <code>error</code> is no longer used. + */ + bool error; + /** + Used during compilation to keep track of the current index into + <code>{@link pattern pattern}<code>. Once the pattern is successfully + compiled, <code>error</code> is no longer used. + */ + int curInd; + /** + The number of capture groups this contains. + */ + int groupCount; + /** + The number of non-capture groups this contains. + */ + int nonCapGroupCount; + /** + The flags specified when this was compiled. + */ + unsigned long flags; + protected: + /** + Raises an error during compilation. Compilation will cease at that point + and compile will return <code>NULL</code>. + */ + void raiseError(); + /** + Convenience function for registering a node in <code>nodes</code>. + @param node The node to register + @return The registered node + */ + NFANode * registerNode(NFANode * node); + + /** + Calculates the union of two strings. This function will first sort the + strings and then use a simple selection algorithm to find the union. + @param s1 The first "class" to union + @param s2 The second "class" to union + @return A new string containing all unique characters. Each character + must have appeared in one or both of <code>s1</code> and + <code>s2</code>. + */ + std::string classUnion (std::string s1, std::string s2) const; + /** + Calculates the intersection of two strings. This function will first sort + the strings and then use a simple selection algorithm to find the + intersection. + @param s1 The first "class" to intersect + @param s2 The second "class" to intersect + @return A new string containing all unique characters. Each character + must have appeared both <code>s1</code> and <code>s2</code>. + */ + std::string classIntersect (std::string s1, std::string s2) const; + /** + Calculates the negation of a string. The negation is the set of all + characters between <code>\x00</code> and <code>\xFF</code> not + contained in <code>s1</code>. + @param s1 The "class" to be negated. + @param s2 The second "class" to intersect + @return A new string containing all unique characters. Each character + must have appeared both <code>s1</code> and <code>s2</code>. + */ + std::string classNegate (std::string s1) const; + /** + Creates a new "class" representing the range from <code>low</code> thru + <code>hi</code>. This function will wrap if <code>low</code> > + <code>hi</code>. This is a feature, not a buf. Sometimes it is useful + to be able to say [\x70-\x10] instead of [\x70-\x7F\x00-\x10]. + @param low The beginning character + @param hi The ending character + @return A new string containing all the characters from low thru hi. + */ + std::string classCreateRange(char low, char hi) const; + + /** + Extracts a decimal number from the substring of member-variable + <code>{@link pattern pattern}<code> starting at <code>start</code> and + ending at <code>end</code>. + @param start The starting index in <code>{@link pattern pattern}<code> + @param end The last index in <code>{@link pattern pattern}<code> + @return The decimal number in <code>{@link pattern pattern}<code> + */ + int getInt(int start, int end); + /** + Parses a <code>{n,m}</code> string out of the member-variable + <code>{@link pattern pattern}<code> stores the result in <code>sNum</code> + and <code>eNum</code>. + @param sNum Output parameter. The minimum number of matches required + by the curly quantifier are stored here. + @param eNum Output parameter. The maximum number of matches allowed + by the curly quantifier are stored here. + @return Success/Failure. Fails when the curly does not have the proper + syntax + */ + bool quantifyCurly(int & sNum, int & eNum); + /** + Tries to quantify the currently parsed group. If the group being parsed + is indeed quantified in the member-variable + <code>{@link pattern pattern}<code>, then the NFA is modified accordingly. + @param start The starting node of the current group being parsed + @param stop The ending node of the current group being parsed + @param gn The group number of the current group being parsed + @return The node representing the starting node of the group. If the + group becomes quantified, then this node is not necessarily + a GroupHead node. + */ + NFANode * quantifyGroup(NFANode * start, NFANode * stop, const int gn); + + /** + Tries to quantify the last parsed expression. If the character was indeed + quantified, then the NFA is modified accordingly. + @param newNode The recently created expression node + @return The node representing the last parsed expression. If the + expression was quantified, <code>return value != newNode</code> + */ + NFANode * quantify(NFANode * newNode); + /** + Parses the current class being examined in + <code>{@link pattern pattern}</code>. + @return A string of unique characters contained in the current class being + parsed + */ + std::string parseClass(); + /** + Parses the current POSIX class being examined in + <code>{@link pattern pattern}</code>. + @return A string of unique characters representing the POSIX class being + parsed + */ + std::string parsePosix(); + /** + Returns a string containing the octal character being parsed + @return The string contained the octal value being parsed + */ + std::string parseOctal(); + /** + Returns a string containing the hex character being parsed + @return The string contained the hex value being parsed + */ + std::string parseHex(); + /** + Returns a new node representing the back reference being parsed + @return The new node representing the back reference being parsed + */ + NFANode * parseBackref(); + /** + Parses the escape sequence currently being examined. Determines if the + escape sequence is a class, a single character, or the beginning of a + quotation sequence. + @param inv Output parameter. Whether or not to invert the returned class + @param quo Output parameter. Whether or not this sequence starts a + quotation. + @return The characters represented by the class + */ + std::string parseEscape(bool & inv, bool & quo); + /** + Parses a supposed registered pattern currently under compilation. If the + sequence of characters does point to a registered pattern, then the + registered pattern is appended to <code>*end<code>. The registered pattern + is parsed with the current compilation flags. + @param end The ending node of the thus-far compiled pattern + @return The new end node of the current pattern + */ + NFANode * parseRegisteredPattern(NFANode ** end); + /** + Parses a lookbehind expression. Appends the necessary nodes + <code>*end</code>. + @param pos Positive or negative look behind + @param end The ending node of the current pattern + @return The new end node of the current pattern + */ + NFANode * parseBehind(const bool pos, NFANode ** end); + /** + Parses the current expression and tacks on nodes until a \E is found. + @return The end of the current pattern + */ + NFANode * parseQuote(); + /** + Parses <code>{@link pattern pattern}</code>. This function is called + recursively when an or (<code>|</code>) or a group is encountered. + @param inParen Are we currently parsing inside a group + @param inOr Are we currently parsing one side of an or (<code>|</code>) + @param end The end of the current expression + @return The starting node of the NFA constructed from this parse + */ + NFANode * parse(const bool inParen = 0, const bool inOr = 0, NFANode ** end = NULL); + public: + /// We should match regardless of case + const static unsigned long CASE_INSENSITIVE; + /// We are implicitly quoted + const static unsigned long LITERAL; + /// @memo We should treat a <code><b>.</b></code> as [\x00-\x7F] + const static unsigned long DOT_MATCHES_ALL; + /** <code>^</code> and <code>$</code> should anchor to the beginning and + ending of lines, not all input + */ + const static unsigned long MULTILINE_MATCHING; + /** When enabled, only instances of <code>\n</codes> are recognized as + line terminators + */ + const static unsigned long UNIX_LINE_MODE; + /// The absolute minimum number of matches a quantifier can match (0) + const static int MIN_QMATCH; + /// The absolute maximum number of matches a quantifier can match (0x7FFFFFFF) + const static int MAX_QMATCH; + public: + /** + Call this function to compile a regular expression into a + <code>Pattern</code> object. Special values can be assigned to + <code>mode</code> when certain non-standard behaviors are expected from + the <code>Pattern</code> object. + @param pattern The regular expression to compile + @param mode A bitwise or of flags signalling what special behaviors are + wanted from this <code>Pattern</code> object + @return If successful, <code>compile</code> returns a <code>Pattern</code> + pointer. Upon failure, <code>compile</code> returns + <code>NULL</code> + */ + static Pattern * compile (const std::string & pattern, + const unsigned long mode = 0); + /** + Dont use this function. This function will compile a pattern, and cache + the result. This will eventually be used as an optimization when people + just want to call static methods using the same pattern over and over + instead of first compiling the pattern and then using the compiled + instance for matching. + @param pattern The regular expression to compile + @param mode A bitwise or of flags signalling what special behaviors are + wanted from this <code>Pattern</code> object + @return If successful, <code>compileAndKeep</code> returns a + <code>Pattern</code> pointer. Upon failure, <code>compile</code> + returns <code>NULL</code>. + */ + static Pattern * compileAndKeep (const std::string & pattern, + const unsigned long mode = 0); + + /** + Searches through <code>replace</code> and replaces all substrings matched + by <code>pattern</code> with <code>str</code>. <code>str</code> may + contain backreferences (e.g. <code>\1</code>) to capture groups. A typical + invocation looks like: + <p> + <code> + Pattern::replace("(a+)b(c+)", "abcccbbabcbabc", "\\2b\\1"); + </code> + <p> + which would replace <code>abcccbbabcbabc</code> with + <code>cccbabbcbabcba</code>. + @param pattern The regular expression + @param str The replacement text + @param replacementText The string in which to perform replacements + @param mode The special mode requested of the <code>Pattern</code> + during the replacement process + @return The text with the replacement string substituted where necessary + */ + static std::string replace (const std::string & pattern, + const std::string & str, + const std::string & replacementText, + const unsigned long mode = 0); + + /** + Splits the specified string over occurrences of the specified pattern. + Empty strings can be optionally ignored. The number of strings returned is + configurable. A typical invocation looks like: + <p> + <code> + std::string str(strSize, '\0');<br> + FILE * fp = fopen(fileName, "r");<br> + fread((char*)str.data(), strSize, 1, fp);<br> + fclose(fp);<br> + <br> + std::vector<std::string> lines = Pattern::split("[\r\n]+", str, true);<br> + <br> + </code> + + @param pattern The regular expression + @param replace The string to split + @param keepEmptys Whether or not to keep empty strings + @param limit The maximum number of splits to make + @param mode The special mode requested of the <code>Pattern</code> + during the split process + @return All substrings of <code>str</code> split across <code>pattern</code>. + */ + static std::vector<std::string> split (const std::string & pattern, + const std::string & str, + const bool keepEmptys = 0, + const unsigned long limit = 0, + const unsigned long mode = 0); + + /** + Finds all the instances of the specified pattern within the string. You + should be careful to only pass patterns with a minimum length of one. For + example, the pattern <code>a*</code> can be matched by an empty string, so + instead you should pass <code>a+</code> since at least one character must + be matched. A typical invocation of <code>findAll</code> looks like: + <p> + <code> + std::vector<td::string> numbers = Pattern::findAll("\\d+", string); + </code> + <p> + + @param pattern The pattern for which to search + @param str The string to search + @param mode The special mode requested of the <code>Pattern</code> + during the find process + @return All instances of <code>pattern</code> in <code>str</code> + */ + static std::vector<std::string> findAll (const std::string & pattern, + const std::string & str, + const unsigned long mode = 0); + + /** + Determines if an entire string matches the specified pattern + + @param pattern The pattern for to match + @param str The string to match + @param mode The special mode requested of the <code>Pattern</code> + during the replacement process + @return True if <code>str</code> is recognized by <code>pattern</code> + */ + static bool matches (const std::string & pattern, + const std::string & str, + const unsigned long mode = 0); + + /** + Registers a pattern under a specific name for use in later compilations. + A typical invocation and later use looks like: + <p> + <code> + Pattern::registerPattern("ip", "(?:\\d{1,3}\\.){3}\\d{1,3}");<br> + Pattern * p1 = Pattern::compile("{ip}:\\d+");<br> + Pattern * p2 = Pattern::compile("Connection from ({ip}) on port \\d+");<br> + </code> + <p> + Multiple calls to <code>registerPattern</code> with the same + <code>name</code> will result in the pattern getting overwritten. + + @param name The name to give to the pattern + @param pattern The pattern to register + @param mode Any special flags to use when compiling pattern + @return Success/Failure. Fails only if <code>pattern</code> has invalid + syntax + */ + static bool registerPattern(const std::string & name, + const std::string & pattern, + const unsigned long mode = 0); + + /** + Clears the pattern registry + */ + static void unregisterPatterns(); + /** + Don't use + */ + static void clearPatternCache(); + + /** + Searches through a string for the <code>n<sup>th</sup></code> match of the + given pattern in the string. Match indeces start at zero, not one. + A typical invocation looks like this: + <p> + <code> + std::pair<std::string, int> match = Pattern::findNthMatch("\\d{1,3}", "192.168.1.101:22", 1);<br> + printf("%s %i\n", match.first.c_str(), match.second);<br> + <br> + Output: 168 4<br> + <br> + + @param pattern The pattern for which to search + @param str The string to search + @param matchNum Which match to find + @param mode Any special flags to use during the matching process + @return A string and an integer. The string is the string matched. The + integer is the starting location of the matched string in + <code>str</code>. You can check for success/failure by making sure + that the integer returned is greater than or equal to zero. + */ + static std::pair<std::string, int> findNthMatch (const std::string & pattern, + const std::string & str, + const int matchNum, + const unsigned long mode = 0); + public: + /** + Deletes all NFA nodes allocated during compilation + */ + ~Pattern(); + + std::string replace (const std::string & str, + const std::string & replacementText); + std::vector<std::string> split (const std::string & str, const bool keepEmptys = 0, + const unsigned long limit = 0); + std::vector<std::string> findAll (const std::string & str); + bool matches (const std::string & str); + /** + Returns the flags used during compilation of this pattern + @return The flags used during compilation of this pattern + */ + unsigned long getFlags () const; + /** + Returns the regular expression this pattern represents + @return The regular expression this pattern represents + */ + std::string getPattern () const; + /** + Creates a matcher object using the specified string and this pattern. + @param str The string to match against + @return A new matcher using object using this pattern and the specified + string + */ + Matcher * createMatcher (const std::string & str); +}; + +class NFANode +{ + friend class Matcher; + public: + NFANode * next; + NFANode(); + virtual ~NFANode(); + virtual void findAllNodes(std::map<NFANode*, bool> & soFar); + virtual int match(const std::string & str, Matcher * matcher, const int curInd = 0) const = 0; + inline virtual bool isGroupHeadNode() const { return false; } + inline virtual bool isStartOfInputNode() const { return false; } +}; +class NFACharNode : public NFANode +{ + protected: + char ch; + public: + NFACharNode(const char c); + virtual int match(const std::string & str, Matcher * matcher, const int curInd = 0) const; +}; +class NFACICharNode : public NFANode +{ + protected: + char ch; + public: + NFACICharNode(const char c); + virtual int match(const std::string & str, Matcher * matcher, const int curInd = 0) const; +}; +class NFAStartNode : public NFANode +{ + public: + NFAStartNode(); + virtual int match(const std::string & str, Matcher * matcher, const int curInd = 0) const; +}; +class NFAEndNode : public NFANode +{ + public: + NFAEndNode(); + virtual int match(const std::string & str, Matcher * matcher, const int curInd = 0) const; +}; +class NFAQuantifierNode : public NFANode +{ + public: + int min, max; + NFANode * inner; + virtual void findAllNodes(std::map<NFANode*, bool> & soFar); + NFAQuantifierNode(Pattern * pat, NFANode * internal, + const int minMatch = Pattern::MIN_QMATCH, + const int maxMatch = Pattern::MAX_QMATCH); + virtual int match(const std::string & str, Matcher * matcher, const int curInd = 0) const; +}; +class NFAGreedyQuantifierNode : public NFAQuantifierNode +{ + public: + NFAGreedyQuantifierNode(Pattern * pat, NFANode * internal, + const int minMatch = Pattern::MIN_QMATCH, + const int maxMatch = Pattern::MAX_QMATCH); + virtual int match(const std::string & str, Matcher * matcher, const int curInd = 0) const; + virtual int matchInternal(const std::string & str, Matcher * matcher, const int curInd, const int soFar) const; +}; +class NFALazyQuantifierNode : public NFAQuantifierNode +{ + public: + NFALazyQuantifierNode(Pattern * pat, NFANode * internal, + const int minMatch = Pattern::MIN_QMATCH, + const int maxMatch = Pattern::MAX_QMATCH); + virtual int match(const std::string & str, Matcher * matcher, const int curInd = 0) const; +}; +class NFAPossessiveQuantifierNode : public NFAQuantifierNode +{ + public: + NFAPossessiveQuantifierNode(Pattern * pat, NFANode * internal, + const int minMatch = Pattern::MIN_QMATCH, + const int maxMatch = Pattern::MAX_QMATCH); + virtual int match(const std::string & str, Matcher * matcher, const int curInd = 0) const; +}; +class NFAAcceptNode : public NFANode +{ + public: + NFAAcceptNode(); + virtual int match(const std::string & str, Matcher * matcher, const int curInd = 0) const; +}; +class NFAClassNode : public NFANode +{ + public: + bool inv; + std::map<char, bool> vals; + NFAClassNode(const bool invert = 0); + NFAClassNode(const std::string & clazz, const bool invert); + virtual int match(const std::string & str, Matcher * matcher, const int curInd = 0) const; +}; +class NFACIClassNode : public NFANode +{ + public: + bool inv; + std::map<char, bool> vals; + NFACIClassNode(const bool invert = 0); + NFACIClassNode(const std::string & clazz, const bool invert); + virtual int match(const std::string & str, Matcher * matcher, const int curInd = 0) const; +}; +class NFASubStartNode : public NFANode +{ + public: + NFASubStartNode(); + virtual int match(const std::string & str, Matcher * matcher, const int curInd = 0) const; +}; +class NFAOrNode : public NFANode +{ + public: + NFANode * one; + NFANode * two; + NFAOrNode(NFANode * first, NFANode * second); + virtual void findAllNodes(std::map<NFANode*, bool> & soFar); + virtual int match(const std::string & str, Matcher * matcher, const int curInd = 0) const; +}; +class NFAQuoteNode : public NFANode +{ + public: + std::string qStr; + NFAQuoteNode(const std::string & quoted); + virtual int match(const std::string & str, Matcher * matcher, const int curInd = 0) const; +}; +class NFACIQuoteNode : public NFANode +{ + public: + std::string qStr; + NFACIQuoteNode(const std::string & quoted); + virtual int match(const std::string & str, Matcher * matcher, const int curInd = 0) const; +}; +class NFALookAheadNode : public NFANode +{ + public: + bool pos; + NFANode * inner; + NFALookAheadNode(NFANode * internal, const bool positive); + virtual void findAllNodes(std::map<NFANode*, bool> & soFar); + virtual int match(const std::string & str, Matcher * matcher, const int curInd = 0) const; +}; +class NFALookBehindNode : public NFANode +{ + public: + bool pos; + std::string mStr; + NFALookBehindNode(const std::string & str, const bool positive); + virtual int match(const std::string & str, Matcher * matcher, const int curInd = 0) const; +}; +class NFAStartOfLineNode : public NFANode +{ + public: + NFAStartOfLineNode(); + virtual int match(const std::string & str, Matcher * matcher, const int curInd = 0) const; +}; +class NFAEndOfLineNode : public NFANode +{ + public: + NFAEndOfLineNode(); + virtual int match(const std::string & str, Matcher * matcher, const int curInd = 0) const; +}; +class NFAReferenceNode : public NFANode +{ + public: + int gi; + NFAReferenceNode(const int groupIndex); + virtual int match(const std::string & str, Matcher * matcher, const int curInd = 0) const; +}; +class NFAStartOfInputNode : public NFANode +{ + public: + NFAStartOfInputNode(); + virtual int match(const std::string & str, Matcher * matcher, const int curInd = 0) const; + inline virtual bool isStartOfInputNode() const { return true; } +}; +class NFAEndOfInputNode : public NFANode +{ + public: + bool term; + NFAEndOfInputNode(const bool lookForTerm); + virtual int match(const std::string & str, Matcher * matcher, const int curInd = 0) const; +}; +class NFAWordBoundaryNode : public NFANode +{ + public: + bool pos; + NFAWordBoundaryNode(const bool positive); + virtual int match(const std::string & str, Matcher * matcher, const int curInd = 0) const; +}; +class NFAEndOfMatchNode : public NFANode +{ + public: + NFAEndOfMatchNode(); + virtual int match(const std::string & str, Matcher * matcher, const int curInd = 0) const; +}; +class NFAGroupHeadNode : public NFANode +{ + public: + int gi; + NFAGroupHeadNode(const int groupIndex); + virtual int match(const std::string & str, Matcher * matcher, const int curInd = 0) const; + inline virtual bool isGroupHeadNode() const { return true; } +}; +class NFAGroupTailNode : public NFANode +{ + public: + int gi; + NFAGroupTailNode(const int groupIndex); + virtual int match(const std::string & str, Matcher * matcher, const int curInd = 0) const; +}; +class NFAGroupLoopPrologueNode : public NFANode +{ + public: + int gi; + NFAGroupLoopPrologueNode(const int groupIndex); + virtual int match(const std::string & str, Matcher * matcher, const int curInd = 0) const; +}; +class NFAGroupLoopNode : public NFANode +{ + public: + int gi, min, max, type; + NFANode * inner; + NFAGroupLoopNode(NFANode * internal, const int minMatch, + const int maxMatch, const int groupIndex, const int matchType); + virtual void findAllNodes(std::map<NFANode*, bool> & soFar); + virtual int match(const std::string & str, Matcher * matcher, const int curInd = 0) const; + int matchGreedy(const std::string & str, Matcher * matcher, const int curInd = 0) const; + int matchLazy(const std::string & str, Matcher * matcher, const int curInd = 0) const; + int matchPossessive(const std::string & str, Matcher * matcher, const int curInd = 0) const; +}; + +#endif + diff --git a/support/highlight/src/core/rtfgenerator.cpp b/support/highlight/src/core/rtfgenerator.cpp new file mode 100644 index 0000000000..dab2c805cc --- /dev/null +++ b/support/highlight/src/core/rtfgenerator.cpp @@ -0,0 +1,363 @@ +/*************************************************************************** + rtfcode.cpp - description + ------------------- + begin : Die Jul 9 2002 + copyright : (C) 2002-2007 by Andre Simon + email : andre.simon1@gmx.de + ***************************************************************************/ + + +/* +This file is part of Highlight. + +Highlight is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +Highlight is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Highlight. If not, see <http://www.gnu.org/licenses/>. +*/ + + +#include <sstream> + +#include "charcodes.h" +#include "version.h" +#include "rtfgenerator.h" + +using namespace std; + +namespace highlight +{ + + string RtfGenerator::getAttributes ( const ElementStyle & col ) + { + stringstream s; + s << "\\red"<< col.getColour().getRed ( RTF ) + << "\\green"<<col.getColour().getGreen ( RTF ) + << "\\blue"<<col.getColour().getBlue ( RTF ) + << ";"; + return s.str(); + } + + string RtfGenerator::getOpenTag ( int styleNumber,const ElementStyle & elem ) + { + ostringstream s; + s << "{"; + if ( addCharStyles ) + { + s<<"\\*\\cs"<< ( styleNumber+2 ); + } + s << "\\cf"<< ( styleNumber+2 ) <<"{"; + + if ( elem.isBold() ) s << "\\b "; + if ( elem.isItalic() ) s << "\\i "; + if ( elem.isUnderline() ) s << "\\ul "; + return s.str(); + } + + + string RtfGenerator::getCharStyle ( int styleNumber,const ElementStyle &elem, + const string&styleName ) + { + ostringstream s; + s << "{\\*\\cs"<< ( styleNumber+2 ) <<"\\additive\\cf"<< ( styleNumber+2 ) + << "\\f1\\fs"; + int fontSize=0; + StringTools::str2num<int> ( fontSize, this->getBaseFontSize(), std::dec ); + s << ( ( fontSize ) ? fontSize*2: 20 ); // RTF needs double amount + if ( elem.isBold() ) s << "\\b"; + if ( elem.isItalic() ) s << "\\i"; + if ( elem.isUnderline() ) s << "\\ul"; + s << "\\sbasedon222\\snext0 "<< styleName << ";}\n"; + return s.str(); + } +// {\*\cs2\additive\cf2\f1\fs20\sbasedon222\snext0 HL Default;} + + string RtfGenerator::getCloseTag ( const ElementStyle &elem ) + { + ostringstream s; + if ( elem.isBold() ) s << "\\b0 "; + if ( elem.isItalic() ) s << "\\i0 "; + if ( elem.isUnderline() ) s << "\\ul0 "; + s << "}}"; + return s.str(); + } + + RtfGenerator::RtfGenerator() + : CodeGenerator ( RTF ), + pageSize ( "a4" ), // Default: DIN A4 + addCharStyles ( false ) + { + newLineTag = "}\\par\\pard\n\\cbpat1{"; + spacer = " "; + + // Page dimensions + psMap["a3"] = PageSize ( 16837,23811 ); + psMap["a4"] = PageSize ( 11905,16837 ); + psMap["a5"] = PageSize ( 8390,11905 ); + + psMap["b4"] = PageSize ( 14173,20012 ); + psMap["b5"] = PageSize ( 9977,14173 ); + psMap["b6"] = PageSize ( 7086,9977 ); + + psMap["letter"] = PageSize ( 12240,15840 ); + psMap["legal"] = PageSize ( 12240,20163 ); + } + + RtfGenerator::~RtfGenerator() + {} + + string RtfGenerator::getHeader() + { + return string(); + } + + void RtfGenerator::printBody() + { + *out << "{\\rtf1\\ansi\\uc0 \\deff1" + << "{\\fonttbl{\\f1\\fmodern\\fprq1\\fcharset0 " ; + *out << this->getBaseFont() ; + *out << ";}}" + << "{\\colortbl;"; + + *out << "\\red" << ( docStyle.getBgColour().getRed ( RTF ) ); + *out << "\\green" << ( docStyle.getBgColour().getGreen ( RTF ) ); + *out << "\\blue" << ( docStyle.getBgColour().getBlue ( RTF ) ); + *out << ";"; + + *out << getAttributes ( docStyle.getDefaultStyle() ); + + *out << getAttributes ( docStyle.getStringStyle() ); + *out << getAttributes ( docStyle.getNumberStyle() ); + *out << getAttributes ( docStyle.getSingleLineCommentStyle() ); + + *out << getAttributes ( docStyle.getCommentStyle() ); + *out << getAttributes ( docStyle.getEscapeCharStyle() ); + *out << getAttributes ( docStyle.getDirectiveStyle() ); + + *out << getAttributes ( docStyle.getDirectiveStringStyle() ); + *out << getAttributes ( docStyle.getLineStyle() ); + *out << getAttributes ( docStyle.getSymbolStyle() ); + + /* For output formats which can refer to external styles it is more safe + to use the colour theme's keyword class names, since the language + definitions (which may change during a batch conversion) do not have to define + all keyword classes, that are needed to highlight all input files correctly. + It is ok for RTF to use the language definition's class names, because RTF + does not refer to external styles. + We cannot use the theme's class names, because KSIterator returns an + alphabetically ordered list, which is not good because RTF is dependent + on the order. We access the keyword style with an ID, which is calculated + ignoring the alphabetic order. + */ + vector<string> keywordClasses = langInfo.getKeywordClasses(); + for ( unsigned int i=0;i<keywordClasses.size();i++ ) + { + *out << getAttributes ( docStyle.getKeywordStyle ( keywordClasses[i] ) ); + } + + *out << "}\n"; + + if ( addCharStyles ) + { + *out << "{\\stylesheet{\n"; + *out << getCharStyle ( STANDARD, docStyle.getDefaultStyle(), "HL Default" ); + *out << getCharStyle ( STRING, docStyle.getStringStyle(), "HL String" ); + *out << getCharStyle ( NUMBER, docStyle.getNumberStyle(), "HL Number" ); + *out << getCharStyle ( SL_COMMENT, docStyle.getSingleLineCommentStyle(), "HL SL Comment" ); + *out << getCharStyle ( ML_COMMENT, docStyle.getCommentStyle(), "HL ML Comment" ); + *out << getCharStyle ( ESC_CHAR, docStyle.getEscapeCharStyle(), "HL Escape Character" ); + *out << getCharStyle ( DIRECTIVE, docStyle.getDirectiveStyle(), "HL Directive" ); + *out << getCharStyle ( DIRECTIVE_STRING, docStyle.getDirectiveStringStyle(), "HL Directive String" ); + *out << getCharStyle ( LINENUMBER, docStyle.getLineStyle(), "HL Line" ); + *out << getCharStyle ( SYMBOL, docStyle.getSymbolStyle(), "HL Symbol" ); + char styleName[20]; + for ( unsigned int i=0;i<keywordClasses.size();i++ ) + { + sprintf ( styleName, "HL Keyword %c", 'A'+i ); //maybe better simple numbering + *out << getCharStyle ( KEYWORD+i, docStyle.getKeywordStyle ( keywordClasses[i] ), string ( styleName ) ); + } + *out << "}}\n"; + } + + *out << "\\paperw"<< psMap[pageSize].width <<"\\paperh"<< psMap[pageSize].height + << "\\margl1134\\margr1134\\margt1134\\margb1134\\sectd" // page margins + << "\\plain\\f1\\fs" ; // Font formatting + int fontSize=0; + StringTools::str2num<int> ( fontSize, this->getBaseFontSize(), std::dec ); + *out << ( ( fontSize ) ? fontSize*2: 20 ); // RTF needs double amount + *out << "\n\\pard \\cbpat1{"; + + processRootState(); + + *out << "}}"<<endl; + } + + string RtfGenerator::getFooter() + { + return string(); + } + + void RtfGenerator::initOutputTags ( ) + { + openTags.push_back ( getOpenTag ( STANDARD, docStyle.getDefaultStyle() ) ); + openTags.push_back ( getOpenTag ( STRING, docStyle.getStringStyle() ) ); + openTags.push_back ( getOpenTag ( NUMBER, docStyle.getNumberStyle() ) ); + openTags.push_back ( getOpenTag ( SL_COMMENT, docStyle.getSingleLineCommentStyle() ) ); + openTags.push_back ( getOpenTag ( ML_COMMENT,docStyle.getCommentStyle() ) ); + openTags.push_back ( getOpenTag ( ESC_CHAR, docStyle.getEscapeCharStyle() ) ); + openTags.push_back ( getOpenTag ( DIRECTIVE, docStyle.getDirectiveStyle() ) ); + openTags.push_back ( getOpenTag ( DIRECTIVE_STRING, docStyle.getDirectiveStringStyle() ) ); + openTags.push_back ( getOpenTag ( LINENUMBER, docStyle.getLineStyle() ) ); + openTags.push_back ( getOpenTag ( SYMBOL, docStyle.getSymbolStyle() ) ); + + closeTags.push_back ( getCloseTag ( docStyle.getDefaultStyle() ) ); + closeTags.push_back ( getCloseTag ( docStyle.getStringStyle() ) ); + closeTags.push_back ( getCloseTag ( docStyle.getNumberStyle() ) ); + closeTags.push_back ( getCloseTag ( docStyle.getSingleLineCommentStyle() ) ); + closeTags.push_back ( getCloseTag ( docStyle.getCommentStyle() ) ); + closeTags.push_back ( getCloseTag ( docStyle.getEscapeCharStyle() ) ); + closeTags.push_back ( getCloseTag ( docStyle.getDirectiveStyle() ) ); + closeTags.push_back ( getCloseTag ( docStyle.getDirectiveStringStyle() ) ); + closeTags.push_back ( getCloseTag ( docStyle.getLineStyle() ) ); + closeTags.push_back ( getCloseTag ( docStyle.getSymbolStyle() ) ); + } + + string RtfGenerator::maskCharacter ( unsigned char c ) + { + switch ( c ) + { + case '}' : + case '{' : + case '\\' : + { + string m ( "\\" ); + return m += c; + } + break; + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + { + string m ( 1, '{' ); + m += c; + m += '}'; + return m; + } + break; + + case AUML_LC: + return "\\'e4"; + break; + case OUML_LC: + return "\\'f6"; + break; + case UUML_LC: + return "\\'fc"; + break; + case AUML_UC: + return "\\'c4"; + break; + case OUML_UC: + return "\\'d6"; + break; + case UUML_UC: + return "\\'dc"; + break; + + case AACUTE_LC: + return "\\'e1"; + break; + case EACUTE_LC: + return "\\'e9"; + break; + case OACUTE_LC: + return "\\'f3"; + break; + case UACUTE_LC: + return "\\'fa"; + break; + + case AGRAVE_LC: + return "\\'e0"; + break; + case EGRAVE_LC: + return "\\'e8"; + break; + case OGRAVE_LC: + return "\\'f2"; + break; + case UGRAVE_LC: + return "\\'f9"; + break; + + case AACUTE_UC: + return "\\'c1"; + break; + case EACUTE_UC: + return "\\'c9"; + break; + case OACUTE_UC: + return "\\'d3"; + break; + case UACUTE_UC: + return "\\'da"; + break; + case AGRAVE_UC: + return "\\'c0"; + break; + case EGRAVE_UC: + return "\\'c8"; + break; + case OGRAVE_UC: + return "\\'d2"; + break; + case UGRAVE_UC: + return "\\'d9"; + break; + + case SZLIG: + return "\\'df"; + break; + + default : + return string ( 1, c ); + } + } + + string RtfGenerator::getKeywordOpenTag ( unsigned int styleID ) + { + return getOpenTag ( KEYWORD+styleID, + docStyle.getKeywordStyle ( langInfo.getKeywordClasses() [styleID] ) ); + } + + string RtfGenerator::getKeywordCloseTag ( unsigned int styleID ) + { + return getCloseTag ( docStyle.getKeywordStyle ( langInfo.getKeywordClasses() [styleID] ) ); + } + + void RtfGenerator::setRTFPageSize ( const string & ps ) + { + if ( psMap.count ( ps ) ) pageSize = ps; + } + + void RtfGenerator::setRTFCharStyles ( bool cs ) + { + addCharStyles = cs; + } + +} diff --git a/support/highlight/src/core/rtfgenerator.h b/support/highlight/src/core/rtfgenerator.h new file mode 100644 index 0000000000..e3d0ca614c --- /dev/null +++ b/support/highlight/src/core/rtfgenerator.h @@ -0,0 +1,146 @@ +/*************************************************************************** + rtfcode.h - description + ------------------- + begin : Die Jul 9 2002 + copyright : (C) 2002-2008 by Andre Simon + email : andre.simon1@gmx.de + ***************************************************************************/ + + +/* +This file is part of Highlight. + +Highlight is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +Highlight is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Highlight. If not, see <http://www.gnu.org/licenses/>. +*/ + + +#ifndef RTFGENERATOR_H +#define RTFGENERATOR_H + +#include <string> + +#include "codegenerator.h" + +namespace highlight +{ + + /** + PageSize contains the RTF page dimensions. + */ + struct PageSize + { + /// RTF page width + int width; + /// RTF page height + int height; + + PageSize() + { + } + + /** Constructor to define page dimensions + @param w width + @param h height*/ + PageSize ( int w, int h ) + { + width=w; + height = h; + } + + }; + + /** mapping of page size names and dimensions */ + typedef map<string, struct PageSize> PagesizeMap; + + /** + \brief This class generates RTF. + + It contains information about the resulting document structure (document + header and footer), the colour system, white space handling and text + formatting attributes. + + * @author Andre Simon + */ + + class RtfGenerator : public highlight::CodeGenerator + { + public: + + RtfGenerator(); + + ~RtfGenerator(); + + /** Define RTF page size + \param ps RTF page size (a3, a4, a5, b4, b5, b6, letter, legal) */ + void setRTFPageSize ( const string & ps ); + + /** \param cs flag to enable character styles*/ + void setRTFCharStyles ( bool cs ); + + private: + + /** prints document header + */ + string getHeader(); + + /** Prints document footer*/ + string getFooter(); + + /** Prints document body*/ + void printBody(); + + /** initialize tags in specific format according to colouring information provided in DucumentStyle */ + void initOutputTags(); + + /** Map of several pagesizes */ + PagesizeMap psMap; + + /** name of page size which is mapped to page dimensions*/ + string pageSize; + + /** flag to add character styles */ + bool addCharStyles; + + /** \return escaped character*/ + virtual string maskCharacter ( unsigned char ); + + /**\return text formatting attributes in RTF format */ + string getAttributes ( const ElementStyle & col ); + + /** @param styleNumber number of current style + @param elem associated element style + @return RTF formatting seqence (colour index + bold + italic)*/ + string getOpenTag ( int styleNumber,const ElementStyle &elem ); + + /** @param styleNumber number of current style + @param elem associated element style + @param styleName style name + @return RTF character style definition */ + string getCharStyle ( int styleNumber,const ElementStyle &elem, const string&styleName ); + + /** @param elem associated element style + @return RTF formatting sequnce to close element formatting */ + string getCloseTag ( const ElementStyle &elem ); + + /** @param styleID current style ID + @return matching sequence to begin a new element formatting*/ + string getKeywordOpenTag ( unsigned int styleID ); + + /** @param styleID current style ID + @return matching sequence to stop element formatting*/ + string getKeywordCloseTag ( unsigned int styleID ); + }; + +} +#endif diff --git a/support/highlight/src/core/stringtools.cpp b/support/highlight/src/core/stringtools.cpp new file mode 100644 index 0000000000..6db9df9900 --- /dev/null +++ b/support/highlight/src/core/stringtools.cpp @@ -0,0 +1,111 @@ +/*************************************************************************** + stringtools.cpp - description + ------------------- + begin : Mon Dec 10 2001 + copyright : (C) 2001 by Andre Simon + email : andre.simon1@gmx.de + ***************************************************************************/ + + +/* +This file is part of Highlight. + +Highlight is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +Highlight is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Highlight. If not, see <http://www.gnu.org/licenses/>. +*/ + + +#include "stringtools.h" + +// Avoid problems with isspace and UTF-8 characters, use iswspace +//#include <wctype.h> + + +using namespace std; + +namespace StringTools +{ + + string change_case ( const string & s, const KeywordCase kcase ) throw() + { + string r ( s ); + switch ( kcase ) + { + case CASE_UNCHANGED: + break; + case CASE_CAPITALIZE: + case CASE_LOWER: + for ( unsigned int i = 0; i < r.size(); ++i ) + r[i] = tolower ( r[i] ); + if ( kcase == CASE_CAPITALIZE && r.size() ) + r[0] = toupper ( r[0] ); + break; + case CASE_UPPER: + for ( unsigned int i = 0; i < r.size(); ++i ) + r[i] = toupper ( r[i] ); + break; + } + return r; + } + + + string trimRight ( const string &value ) + { + string::size_type where = value.find_last_not_of ( " \t\r" ); + + if ( where == string::npos ) + // string has nothing but space + return string(); + + if ( where == ( value.length() - 1 ) ) + // string has no trailing space, don't copy its contents + return value; + + return value.substr ( 0, where + 1 ); + } + + string getParantheseVal ( const string &s ) + { + string::size_type openPos=s.find ( '(' ); + string::size_type closePos=s.rfind ( ')' ); + if ( openPos ==string::npos || closePos==string::npos ) + { + return string(); + } + return s.substr ( openPos+1, closePos-openPos-1 ); + } + + vector<string> splitString ( const string& s, unsigned char delim ) + { + string::size_type pos=s.find ( delim ), oldPos=0; + vector <string> results; + + if ( pos ==string::npos ) + { + if ( !s.empty() ) results.push_back ( s ); + return results; + } + + do + { + if ( oldPos-pos ) results.push_back ( s.substr ( oldPos, pos-oldPos ) ); + oldPos=pos+1; + pos=s.find ( delim, pos+1 ); + } + while ( pos!=string::npos ); + results.push_back ( s.substr ( oldPos ) ); + + return results; + } + +} diff --git a/support/highlight/src/core/stringtools.h b/support/highlight/src/core/stringtools.h new file mode 100644 index 0000000000..861ae85822 --- /dev/null +++ b/support/highlight/src/core/stringtools.h @@ -0,0 +1,90 @@ +/*************************************************************************** + stringtools.h - description + ------------------- + begin : Mon Dec 10 2001 + copyright : (C) 2001 by Andre Simon + email : andre.simon1@gmx.de + ***************************************************************************/ + + +/* +This file is part of Highlight. + +Highlight is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +Highlight is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Highlight. If not, see <http://www.gnu.org/licenses/>. +*/ + + +#ifndef STRINGTOOLS_H +#define STRINGTOOLS_H + +#include <string> +#include <vector> +#include <sstream> + +using namespace std; + +/// Contains methods for string manipulation + +namespace StringTools +{ + + /** Change Keyword case */ + enum KeywordCase + { + CASE_UNCHANGED, ///< do not alter case + CASE_LOWER, ///< convert to lower case + CASE_UPPER, ///< convert to upper case + CASE_CAPITALIZE ///< convert first character to upper case + }; + + /** Change character case of strings + \param s input string + \param kcase case modification indicator + \return modified string + */ + string change_case ( const string & s, + const KeywordCase kcase = CASE_LOWER ) throw(); + + /** Trim string (remove whitespace) + \param value String + \return string trimmed on the left + */ + string trimRight ( const string &value ); + + /** Parse data within parantheses + \param s String, containing a opening and a closing paranthesis + \return value between "(", ")" */ + string getParantheseVal ( const string &s ); + + /** Split string and return items separated by a delimiter + \param s string containing tokens + \param delim Token delimiter + \return vector containing found tokens */ + vector <string> splitString ( const string& s, unsigned char delim ); + + /** Convert string to a numeric value of the given type + \param val variable of specified type which will contain the numeric value + \param s string containing a number + \param f format specifier function (IO manipulator) + \return true if successfull */ + template <class T> + bool str2num ( T &val, const std::string& s, std::ios_base& ( *f ) ( std::ios_base& ) ) + { + std::istringstream iss ( s ); + return ! ( iss >> f >> val ).fail(); + } + +} + +#endif diff --git a/support/highlight/src/core/stylecolour.cpp b/support/highlight/src/core/stylecolour.cpp new file mode 100644 index 0000000000..3cfec3d743 --- /dev/null +++ b/support/highlight/src/core/stylecolour.cpp @@ -0,0 +1,157 @@ +/*************************************************************************** + stylecolour.cpp - description + ------------------- + begin : Die Nov 5 2002 + copyright : (C) 2002 by Andre Simon + email : andre.simon1@gmx.de + ***************************************************************************/ + + +/* +This file is part of Highlight. + +Highlight is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +Highlight is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Highlight. If not, see <http://www.gnu.org/licenses/>. +*/ + + +#include "stylecolour.h" +#include "stringtools.h" + + +#include <iostream> +#include <sstream> +#include <cmath> + +using std::string; + +namespace highlight +{ + + Colour::Colour ( const string & red, const string & green, const string & blue ) + { + ostringstream rgbStream; + rgbStream << red << " " << green << " " << blue; + setRGB ( rgbStream.str() ); + } + + Colour::Colour() + { + rgb.iRed = rgb.iGreen = rgb.iBlue = 0; + } + + Colour::Colour ( const string & colourString ) + { + setRGB ( colourString ); + } + + void Colour::setRGB ( const string & colourString ) + { + if ( colourString.empty() ) return; + + istringstream valueStream ( colourString.c_str() ); + string r, g, b; + char c='\0'; + valueStream >> c; + + if ( c=='#' ) + { + string htmlNotation; + valueStream >> htmlNotation; + if ( htmlNotation.size() < 6 ) return; + r = htmlNotation.substr ( 0, 2 ); + g = htmlNotation.substr ( 2, 2 ); + b = htmlNotation.substr ( 4, 2 ); + } + else + { + valueStream.putback ( c ); + valueStream >> r; + valueStream >> g; + valueStream >> b; + } + + StringTools::str2num<int> ( rgb.iRed, r, std::hex ); + StringTools::str2num<int> ( rgb.iGreen, g, std::hex ); + StringTools::str2num<int> ( rgb.iBlue, b, std::hex ); + } + + void Colour::setRed ( const string & red ) + { + StringTools::str2num<int> ( rgb.iRed, red, std::hex ); + } + + void Colour::setGreen ( const string & green ) + { + StringTools::str2num<int> ( rgb.iGreen, green, std::hex ); + } + + void Colour::setBlue ( const string & blue ) + { + StringTools::str2num<int> ( rgb.iBlue, blue, std::hex ); + } + + string Colour::getRed ( OutputType type ) const + { + switch ( type ) + { + case RTF: return int2str ( rgb.iRed, std::dec ); + case LATEX: return float2str ( ( float ) rgb.iRed / 255 ); + case TEX: return float2str ( 1 - ( float ) rgb.iRed / 255 ); + default: return int2str ( rgb.iRed, std::hex ); + } + } + + string Colour::getGreen ( OutputType type ) const + { + switch ( type ) + { + case RTF: return int2str ( rgb.iGreen, std::dec ); + case LATEX: return float2str ( ( float ) rgb.iGreen / 255 ); + case TEX: return float2str ( 1 - ( float ) rgb.iGreen / 255 ); + default: return int2str ( rgb.iGreen, std::hex ); + } + } + + string Colour::getBlue ( OutputType type ) const + { + switch ( type ) + { + case RTF: return int2str ( rgb.iBlue, std::dec ); + case LATEX: return float2str ( ( float ) rgb.iBlue / 255 ); + case TEX: return float2str ( 1 - ( float ) rgb.iBlue / 255 ); + default: return int2str ( rgb.iBlue, std::hex ); + } + } + + + string Colour::int2str ( const int num, std::ios_base& ( *f ) ( std::ios_base& ) ) const + { + std::ostringstream outStream; + outStream.width ( 2 ); + outStream.fill ( '0' ); + outStream << f << num; + + return outStream.str(); + } + + string Colour::float2str ( const double num ) const + { + std::ostringstream outStream; + outStream << ( floor ( num * 100 + .5 ) / 100 ); + + return outStream.str(); + } + +} + diff --git a/support/highlight/src/core/stylecolour.h b/support/highlight/src/core/stylecolour.h new file mode 100644 index 0000000000..943952d6c2 --- /dev/null +++ b/support/highlight/src/core/stylecolour.h @@ -0,0 +1,106 @@ +/*************************************************************************** + stylecolour.h - description + ------------------- + begin : Die Nov 5 2002 + copyright : (C) 2002 by Andre Simon + email : andre.simon1@gmx.de + ***************************************************************************/ + + +/* +This file is part of Highlight. + +Highlight is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +Highlight is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Highlight. If not, see <http://www.gnu.org/licenses/>. +*/ + + +#ifndef STYLECOLOUR_H +#define STYLECOLOUR_H + +#include "enums.h" + +#include <string> + + +using namespace std; + +namespace highlight +{ + + /**\brief Stores colours and returns red, green and blue values in different formats + * @author Andre Simon + */ + + struct RGBVal + { + int iRed, ///< Red value + iGreen, ///< Green value + iBlue; ///< Blue value + }; + + class Colour + { + public: + /** Constructor + \param red Red value in hex notation + \param green Blue value in hex notation + \param blue Green value in hex notation + */ + Colour ( const string & red, const string & green, const string & blue ); + + /** Constructor + \param ColourString String with rgb values + */ + Colour ( const string & colourString ); + + Colour(); + ~Colour() {}; + + /** Sets red, green and blue values + \param ColourString String containing colour attributes + */ + void setRGB ( const string & colourString ); + + + /** Sets red value + \param red New red value */ + void setRed ( const string & red ); + + /** Sets green value + \param green New green value */ + void setGreen ( const string & green ); + + /** Sets blue value + \param blue New blue value */ + void setBlue ( const string & blue ); + + /** @param type Output type + @return Red value in color representation according to output type */ + string getRed ( OutputType type ) const; + /** @param type Output type + @return Green value in color representation according to output type */ + string getGreen ( OutputType type ) const; + /** @param type Output type + @return Blue value in color representation according to output type */ + string getBlue ( OutputType type ) const; + + private: + RGBVal rgb; + string int2str ( int, std::ios_base& ( *f ) ( std::ios_base& ) ) const; + string float2str ( double ) const; + }; + +} + +#endif diff --git a/support/highlight/src/core/svggenerator.cpp b/support/highlight/src/core/svggenerator.cpp new file mode 100644 index 0000000000..10e41f6c07 --- /dev/null +++ b/support/highlight/src/core/svggenerator.cpp @@ -0,0 +1,248 @@ +/*************************************************************************** + xmlcode.cpp - description + ------------------- + begin : Mo 23.06.2008 + copyright : (C) 2008 by Andre Simon + email : andre.simon1@gmx.de + ***************************************************************************/ + + +/* +This file is part of Highlight. + +Highlight is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +Highlight is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Highlight. If not, see <http://www.gnu.org/licenses/>. +*/ + + +#include <string> +#include <sstream> + +#include "version.h" +#include "svggenerator.h" + +using namespace std; +namespace highlight +{ + + SVGGenerator::SVGGenerator() + : CodeGenerator ( SVG ) + { + spacer = " "; + newLineTag = "\n"; + styleCommentOpen="/*"; + styleCommentClose="*/"; + } + + SVGGenerator::~SVGGenerator() {} + + void SVGGenerator::initOutputTags(){ + openTags.push_back ( "" ); + openTags.push_back ( getOpenTag ( STY_NAME_STR ) ); + openTags.push_back ( getOpenTag ( STY_NAME_NUM ) ); + openTags.push_back ( getOpenTag ( STY_NAME_SLC ) ); + openTags.push_back ( getOpenTag ( STY_NAME_COM ) ); + openTags.push_back ( getOpenTag ( STY_NAME_ESC ) ); + openTags.push_back ( getOpenTag ( STY_NAME_DIR ) ); + openTags.push_back ( getOpenTag ( STY_NAME_DST ) ); + openTags.push_back ( getOpenTag ( STY_NAME_LIN ) ); + openTags.push_back ( getOpenTag ( STY_NAME_SYM ) ); + + closeTags.push_back ( "" ); + for ( int i=1;i<NUMBER_BUILTIN_STATES; i++ ) + { + closeTags.push_back ( "</tspan>" ); + } + } + + string SVGGenerator::getStyleDefinition() + { + if ( styleDefinitionCache.empty() ) + { + ostringstream os; + if ( includeStyleDef ) + { + os << "<style type=\"text/css\">\n" + << "<![CDATA[\n"; + } + os << "rect { fill:#" + << ( docStyle.getBgColour().getRed ( XML ) ) + << ( docStyle.getBgColour().getGreen ( XML ) ) + << ( docStyle.getBgColour().getBlue ( XML ) ) + << "; } \n"; + os << "g { font-size: " << getBaseFontSize(); + os << "; font-family: \"" << getBaseFont() << "\"; }\n"; + os << getAttributes ( "text", docStyle.getDefaultStyle() ) + << getAttributes ( "tspan."+STY_NAME_NUM, docStyle.getNumberStyle() ) + << getAttributes ( "tspan."+STY_NAME_ESC, docStyle.getEscapeCharStyle() ) + << getAttributes ( "tspan."+STY_NAME_STR, docStyle.getStringStyle() ) + << getAttributes ( "tspan."+STY_NAME_DST, docStyle.getDirectiveStringStyle() ) + << getAttributes ( "tspan."+STY_NAME_SLC, docStyle.getSingleLineCommentStyle() ) + << getAttributes ( "tspan."+STY_NAME_COM, docStyle.getCommentStyle() ) + << getAttributes ( "tspan."+STY_NAME_DIR, docStyle.getDirectiveStyle() ) + << getAttributes ( "tspan."+STY_NAME_SYM, docStyle.getSymbolStyle() ) + << getAttributes ( "tspan."+STY_NAME_LIN, docStyle.getLineStyle() ); + + KeywordStyles styles = docStyle.getKeywordStyles(); + for ( KSIterator it=styles.begin(); it!=styles.end(); it++ ) + { + os << getAttributes ( "tspan."+it->first, it->second ); + } + if ( includeStyleDef ) + { + os << "]]>\n" + << "</style>"; + } + styleDefinitionCache=os.str(); + } + return styleDefinitionCache; + } + + + string SVGGenerator::getAttributes ( const string & elemName, + const ElementStyle & elem ) + { + ostringstream s; + if ( !elemName.empty() ) + { + s << /*cssClassName<<"."<<*/ elemName<<" { "; + } + s << "fill:#" + << ( elem.getColour().getRed ( HTML ) ) + << ( elem.getColour().getGreen ( HTML ) ) + << ( elem.getColour().getBlue ( HTML ) ) + << ( elem.isBold() ? "; font-weight:bold" :"" ) + << ( elem.isItalic() ? "; font-style:italic" :"" ) + << ( elem.isUnderline() ? "; text-decoration:underline" :"" ); + if ( !elemName.empty() ) + { + s << "; }\n" ; + } + return s.str(); + } + + string SVGGenerator::getOpenTag ( const string& styleName ) + { + return "<tspan class=\""+styleName+"\">"; + } + + string SVGGenerator::getHeader() + { + ostringstream header; + header << "<?xml version=\"1.0\""; + if ( encodingDefined() ) + { + header << " encoding=\"" << encoding << "\""; + } + header << "?>\n"; + if ( !includeStyleDef ) + { + header << "<?xml-stylesheet type=\"text/css\" href=\"" + << getStyleOutputPath() + << "\"?>\n"; + } + header << "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.2//EN\" " + << "\"http://www.w3.org/Graphics/SVG/1.2/DTD/svg12.dtd\">\n"; + header << "<svg xmlns=\"http://www.w3.org/2000/svg\" version=\"1.2\" " + << "baseProfile=\"full\" xml:space=\"preserve\""; + if ( width.size() ) header << " width=\""<<width<<"\""; + if ( height.size() ) header << " height=\""<<height<<"\""; + //viewBox=\"0 0 800 600\" + header << ">\n<desc>" << docTitle << "</desc>\n"; + if ( includeStyleDef ) + { + header << "<defs>\n"; + header << getStyleDefinition(); + header << "\n</defs>\n"; + } + return header.str(); + } + + void SVGGenerator::printBody() + { + *out << "<g>\n<rect x=\"0\" y=\"0\" width=\"100%\" height=\"100%\"/>"; // rect: background color + int fontSize=0; + StringTools::str2num<int> ( fontSize, getBaseFontSize(), std::dec ); + *out << "\n<text x=\"10\" y=\""<<fontSize*2<<"\">"; + processRootState(); + *out << "</text>\n</g>\n"; + } + + + string SVGGenerator::getFooter() + { + ostringstream os; + os <<"</svg>\n"; + os<< "<!-- SVG generated by Highlight " + << HIGHLIGHT_VERSION + << ", " + << HIGHLIGHT_URL + <<" -->\n"; + return os.str(); + } + + string SVGGenerator::maskCharacter ( unsigned char c ) + { + switch ( c ) + { + case '<' : + return "<"; + break; + case '>' : + return ">"; + break; + case '&' : + return "&"; + break; + case '\"' : + return """; + break; + default: + return string ( 1, c ); + } + } + + string SVGGenerator::getKeywordOpenTag ( unsigned int styleID ) + { + return getOpenTag ( langInfo.getKeywordClasses() [styleID] ); + } + + string SVGGenerator::getKeywordCloseTag ( unsigned int styleID ) + { + return "</tspan>"; + } + + string SVGGenerator::getNewLine() + { + + if ( lineNumber>1 ) + { + ostringstream os; + int fontSize=0; + StringTools::str2num<int> ( fontSize, getBaseFontSize(), std::dec ); + os<< "</text>\n<text x=\"10\" y=\""<< ( lineNumber*fontSize*2 ) <<"\">"; + return os.str(); + } + else + { + return ""; + } + } + + void SVGGenerator::setSVGSize ( const string& w, const string& h ) + { + width=w; + height=h; + } + +} diff --git a/support/highlight/src/core/svggenerator.h b/support/highlight/src/core/svggenerator.h new file mode 100644 index 0000000000..35b8afe57d --- /dev/null +++ b/support/highlight/src/core/svggenerator.h @@ -0,0 +1,95 @@ +/*************************************************************************** + xmlcode.h - description + ------------------- + begin : Mo 23.06.2008 + copyright : (C) 2008 by Andre Simon + email : andre.simon1@gmx.de + ***************************************************************************/ + + +/* +This file is part of Highlight. + +Highlight is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +Highlight is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Highlight. If not, see <http://www.gnu.org/licenses/>. +*/ + + +#ifndef SVGGenerator_H +#define SVGGenerator_H + +#include "codegenerator.h" + +namespace highlight +{ + + /** + \brief This class generates SVG. + + It contains information about the resulting document structure (document + header and footer), the colour system, white space handling and text + formatting attributes. + + * @author Andre Simon + */ + + class SVGGenerator : public highlight::CodeGenerator + { + public: + + SVGGenerator(); + ~SVGGenerator(); + + /** Set SVG dimensions + \param w page width + \param h page height + */ + void setSVGSize ( const string& w, const string& h ); + + private: + + /** prints document header + */ + string getHeader(); + + /** Prints document footer*/ + string getFooter(); + + /** Prints document body*/ + void printBody(); + + /** initialize tags in specific format according to colouring information provided in DucumentStyle */ + void initOutputTags(); + + string styleDefinitionCache; + string width, height; + + string getStyleDefinition(); + + string getAttributes ( const string &, const ElementStyle & ); + + /** \return escaped character*/ + virtual string maskCharacter ( unsigned char ); + + string getOpenTag ( const string& ); + + string getKeywordOpenTag ( unsigned int styleID ); + string getKeywordCloseTag ( unsigned int styleID ); + + /** @return Newline string */ + string getNewLine(); + }; + +} + +#endif diff --git a/support/highlight/src/core/texgenerator.cpp b/support/highlight/src/core/texgenerator.cpp new file mode 100644 index 0000000000..276af5a7c6 --- /dev/null +++ b/support/highlight/src/core/texgenerator.cpp @@ -0,0 +1,303 @@ +/*************************************************************************** + TexGenerator.cpp - description + ------------------- + begin : Mit Jul 24 2002 + copyright : (C) 2002 by Andre Simon + email : andre.simon1@gmx.de + ***************************************************************************/ + + +/* +This file is part of Highlight. + +Highlight is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +Highlight is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Highlight. If not, see <http://www.gnu.org/licenses/>. +*/ + + +#include <sstream> + +#include "charcodes.h" +#include "version.h" +#include "texgenerator.h" + +namespace highlight +{ + + TexGenerator::TexGenerator() + : CodeGenerator ( TEX ) + { + + + /*This makes TeX to use every par it encounters (the \\leavevmode has + no effect when TeX is in horizontal mode and when TeX is in vertical + mode, it switches it to horizontal mode).*/ + newLineTag="\\leavevmode\\par\n"; + + spacer = "\\ "; + maskWs=true; + excludeWs=true; + maskWsBegin = "{\\hlstd"; + maskWsEnd = "}"; + styleCommentOpen="%"; + } + + TexGenerator::~TexGenerator() + {} + + void TexGenerator::initOutputTags(){ + openTags.push_back ( "{\\hl"+STY_NAME_STD+" " ); + openTags.push_back ( "{\\hl"+STY_NAME_STR+" " ); + openTags.push_back ( "{\\hl"+STY_NAME_NUM+" " ); + openTags.push_back ( "{\\hl"+STY_NAME_SLC+" " ); + openTags.push_back ( "{\\hl"+STY_NAME_COM+" " ); + openTags.push_back ( "{\\hl"+STY_NAME_ESC+" " ); + openTags.push_back ( "{\\hl"+STY_NAME_DIR+" " ); + openTags.push_back ( "{\\hl"+STY_NAME_DST+" " ); + openTags.push_back ( "{\\hl"+STY_NAME_LIN+" " ); + openTags.push_back ( "{\\hl"+STY_NAME_SYM+" " ); + + for ( int i=0; i<NUMBER_BUILTIN_STATES; i++ ) + { + closeTags.push_back ( "}" ); + } + } + + string TexGenerator::getAttributes ( const string & elemName,const ElementStyle & elem ) + { + ostringstream s; + s << "\\def\\hl" + << elemName + << "{"; + if ( elem.isBold() ) s << "\\bf"; + if ( elem.isItalic() ) s << "\\it"; + s << "\\textColor{" + << ( elem.getColour().getRed ( TEX ) ) <<" " + << ( elem.getColour().getGreen ( TEX ) ) <<" " + << ( elem.getColour().getBlue ( TEX ) ) <<" 0.0}}\n"; + return s.str(); + } + + string TexGenerator::getHeader() + { + ostringstream os; + os << styleCommentOpen + << " Document title: " << docTitle << "\n\n"; + if ( langInfo.highlightingEnabled() ) + { + if ( includeStyleDef ) + { + os << getStyleDefinition(); + os << CodeGenerator::readUserStyleDef(); + } + else + { + os << "\\input " + << getStyleOutputPath() + << "\n\n"; + } + } + + return os.str(); + } + + void TexGenerator::printBody() + { + *out << "{\n\\"<<getBaseFont() <<"\n"; + + processRootState(); + + *out << "}\n"; + } + + string TexGenerator::getFooter() + { + ostringstream os; + os << "\\bye\n" + << "% TeX generated by Highlight " + << HIGHLIGHT_VERSION + << ", " + << HIGHLIGHT_URL + << endl; + return os.str(); + } + + string TexGenerator:: maskCharacter ( unsigned char c ) + { + switch ( c ) + { + case '{': + case '}': + { + string m ( "$\\" ); + m += c; + m += '$'; + return m; + } + break; + case '^': + return "{\\bf\\^{}}"; + break; + case '_': + return "\\_{}"; + break; + case '&': + case '$': + case '#': + case '%': + { + string m ( "\\" ); + m += c; + return m; + } + break; + case '\\': + return "$\\backslash$"; + break; + case ' ': + return spacer; + break; + case '+': + case '-': + case '<': + case '>': + case '=': + { + string m ( "$\\mathord{" ); + m += c; + m += "}$"; + return m; + } + break; + case AUML_LC: + return "\\\"a"; + break; + case OUML_LC: + return "\\\"o"; + break; + case UUML_LC: + return "\\\"u"; + break; + case AUML_UC: + return "\\\"A"; + break; + case OUML_UC: + return "\\\"O"; + break; + case UUML_UC: + return "\\\"U"; + break; + case AACUTE_LC: + return "\\'a"; + break; + case EACUTE_LC: + return "\\'e"; + break; + case OACUTE_LC: + return "\\'o"; + break; + case UACUTE_LC: + return "\\'u"; + break; + case AGRAVE_LC: + return "\\`a"; + break; + case EGRAVE_LC: + return "\\`e"; + break; + case OGRAVE_LC: + return "\\`o"; + break; + case UGRAVE_LC: + return "\\`u"; + break; + case AACUTE_UC: + return "\\'A"; + break; + case EACUTE_UC: + return "\\'E"; + break; + case OACUTE_UC: + return "\\'O"; + break; + case UACUTE_UC: + return "\\'U"; + break; + case AGRAVE_UC: + return "\\`A"; + break; + case EGRAVE_UC: + return "\\`E"; + break; + case UGRAVE_UC: + return "\\`O"; + break; + case OGRAVE_UC: + return "\\`U"; + break; + case SZLIG: + return "\\ss "; + break; + + default : + return string ( 1, c ); + } + } + + string TexGenerator::getKeywordOpenTag ( unsigned int styleID ) + { + return "{\\hl"+langInfo.getKeywordClasses() [styleID]+" "; + } + + string TexGenerator::getKeywordCloseTag ( unsigned int styleID ) + { + return "}"; + } + + + string TexGenerator::getStyleDefinition() + { + if ( styleDefinitionCache.empty() ) + { + ostringstream os; + os << getAttributes ( STY_NAME_STD, docStyle.getDefaultStyle() ); + os << getAttributes ( STY_NAME_NUM, docStyle.getNumberStyle() ); + os << getAttributes ( STY_NAME_ESC, docStyle.getEscapeCharStyle() ); + os << getAttributes ( STY_NAME_STR, docStyle.getStringStyle() ); + os << getAttributes ( STY_NAME_DST, docStyle.getDirectiveStringStyle() ); + os << getAttributes ( STY_NAME_SLC, docStyle.getSingleLineCommentStyle() ); + os << getAttributes ( STY_NAME_COM, docStyle.getCommentStyle() ); + os << getAttributes ( STY_NAME_DIR, docStyle.getDirectiveStyle() ); + os << getAttributes ( STY_NAME_LIN, docStyle.getLineStyle() ); + os << getAttributes ( STY_NAME_SYM, docStyle.getSymbolStyle() ); + + KeywordStyles styles = docStyle.getKeywordStyles(); + for ( KSIterator it=styles.begin(); it!=styles.end(); it++ ) + { + os << getAttributes ( it->first, it->second ); + } + + os << "% The special option is not supported by all dvi drivers\n" + << "\\special{background rgb " + << docStyle.getBgColour().getRed ( LATEX ) << " " + << docStyle.getBgColour().getGreen ( LATEX ) << " " + << docStyle.getBgColour().getBlue ( LATEX ) << "}"; + os << "\n\\nopagenumbers\n" + << "\\input colordvi\n"; + styleDefinitionCache=os.str(); + } + return styleDefinitionCache; + } + + +} diff --git a/support/highlight/src/core/texgenerator.h b/support/highlight/src/core/texgenerator.h new file mode 100644 index 0000000000..becd31cd57 --- /dev/null +++ b/support/highlight/src/core/texgenerator.h @@ -0,0 +1,93 @@ +/*************************************************************************** + texcode.h - description + ------------------- + begin : Mit Jul 24 2002 + copyright : (C) 2002 by Andr�Simon + email : andre.simon1@gmx.de + ***************************************************************************/ + + +/* +This file is part of Highlight. + +Highlight is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +Highlight is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Highlight. If not, see <http://www.gnu.org/licenses/>. +*/ + + +#ifndef TEXGENERATOR_H +#define TEXGENERATOR_H + +#include <string> + +#include "codegenerator.h" + + +namespace highlight +{ + + /** + \brief This class generates TeX. + + It contains information about the resulting document structure (document + header and footer), the colour system, white space handling and text + formatting attributes. + + * @author Andre Simon + */ + + class TexGenerator : public highlight::CodeGenerator + { + public: + + TexGenerator(); + ~TexGenerator(); + + private: + + /** prints document header + */ + string getHeader(); + + /** Prints document footer*/ + string getFooter(); + + /** Prints document body*/ + void printBody(); + + /** initialize tags in specific format according to colouring information provided in DucumentStyle */ + void initOutputTags(); + + string styleDefinitionCache; + + string getStyleDefinition(); + + /** \return escaped character*/ + virtual string maskCharacter ( unsigned char ); + + /**\return text formatting attributes in RTF format */ + string getAttributes ( const string & elemName, const ElementStyle & elem ); + + /** @param styleID current style ID + @return matching sequence to begin a new element formatting*/ + string getKeywordOpenTag ( unsigned int styleID ); + + /** @param styleID current style ID + @return matching sequence to stop element formatting*/ + string getKeywordCloseTag ( unsigned int styleID ); + + }; + +} + +#endif diff --git a/support/highlight/src/core/version.h b/support/highlight/src/core/version.h new file mode 100644 index 0000000000..a667705b9e --- /dev/null +++ b/support/highlight/src/core/version.h @@ -0,0 +1,36 @@ +/*************************************************************************** + version.h - description + ------------------- + begin : Mon March 3 2003 + copyright : (C) 2003-2010 by Andre Simon + email : andre.simon1@gmx.de + ***************************************************************************/ + + +/* +This file is part of Highlight. + +Highlight is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +Highlight is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Highlight. If not, see <http://www.gnu.org/licenses/>. +*/ + + +#ifndef VERSION_H +#define VERSION_H + +#define HIGHLIGHT_VERSION "2.16" + +#define HIGHLIGHT_URL "http://www.andre-simon.de/" +#define HIGHLIGHT_EMAIL "andre.simon1@gmx.de" + +#endif diff --git a/support/highlight/src/core/xhtmlgenerator.cpp b/support/highlight/src/core/xhtmlgenerator.cpp new file mode 100644 index 0000000000..aed05a2986 --- /dev/null +++ b/support/highlight/src/core/xhtmlgenerator.cpp @@ -0,0 +1,92 @@ +/*************************************************************************** + htmlcode.cpp - description + ------------------- + begin : Wed Nov 28 2001 + copyright : (C) 2001 by Andre Simon + email : andre.simon1@gmx.de + ***************************************************************************/ + + +/* +This file is part of Highlight. + +Highlight is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +Highlight is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Highlight. If not, see <http://www.gnu.org/licenses/>. +*/ + + +#include "xhtmlgenerator.h" + +using namespace std; + +namespace highlight +{ + + XHtmlGenerator::XHtmlGenerator () + { + fileSuffix=".xhtml"; + brTag="<br />"; + hrTag="<hr />"; + idAttr="id"; + cssClassName="hl"; + } + + string XHtmlGenerator::getHeaderStart ( const string &title ) + { + ostringstream header; + header << "<?xml version=\"1.0\""; + if ( encodingDefined() ) + { + header << " encoding=\"" << encoding << "\""; + } + header << "?>\n<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.1//EN\"" + << " \"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd\">\n" + << "<html xmlns=\"http://www.w3.org/1999/xhtml\">\n" + << "<head>\n<title>" << title << "</title>\n"; + + return header.str(); + } + + + string XHtmlGenerator::getHeader() + { + ostringstream os; + os << getHeaderStart ( docTitle ); + + if ( langInfo.highlightingEnabled() ) + { + if ( includeStyleDef ) + { + os << "<style type=\"text/css\">\n"; + os << "<![CDATA[\n"; + os << getStyleDefinition(); + os << CodeGenerator::readUserStyleDef(); + os << "]]>\n"; + os << "</style>\n"; + } + else + { + os << "<link rel=\"stylesheet\" type=\"text/css\" href=\"" + << getStyleOutputPath() + << "\"" + << "/" + << ">\n"; + } + } + os << "</head>\n<body class=\""<<cssClassName<<"\">"; + //if (showLineNumbers && orderedList) os << "<ol>"; + + return os.str(); + } + +} diff --git a/support/highlight/src/core/xhtmlgenerator.h b/support/highlight/src/core/xhtmlgenerator.h new file mode 100644 index 0000000000..7efca1a636 --- /dev/null +++ b/support/highlight/src/core/xhtmlgenerator.h @@ -0,0 +1,68 @@ +/*************************************************************************** + xhtmlgenerator.h - description + ------------------- + begin : Mo Jun 21 2004 + copyright : (C) 2004 by Andre Simon + email : andre.simon1@gmx.de + ***************************************************************************/ + + +/* +This file is part of Highlight. + +Highlight is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +Highlight is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Highlight. If not, see <http://www.gnu.org/licenses/>. +*/ + + + +#ifndef XHTMLGENERATOR_H +#define XHTMLGENERATOR_H + +#include "htmlgenerator.h" + +namespace highlight +{ + + /** + \brief This class generates XHTML. + + It contains information about the resulting document structure (document + header and footer), the colour system, white space handling and text + formatting attributes. + + * @author Andre Simon + */ + + + class XHtmlGenerator : public highlight::HtmlGenerator + { + public: + + XHtmlGenerator(); + + ~XHtmlGenerator() {}; + + private: + + /** prints document header + */ + string getHeader(); + + string getHeaderStart ( const string &title ); + + }; + +} + +#endif diff --git a/support/highlight/src/core/xmlgenerator.cpp b/support/highlight/src/core/xmlgenerator.cpp new file mode 100644 index 0000000000..dd66dd2652 --- /dev/null +++ b/support/highlight/src/core/xmlgenerator.cpp @@ -0,0 +1,202 @@ +/*************************************************************************** + xmlcode.cpp - description + ------------------- + begin : Do 20.01.2005 + copyright : (C) 2005 by Andre Simon + email : andre.simon1@gmx.de + ***************************************************************************/ + + +/* +This file is part of Highlight. + +Highlight is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +Highlight is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Highlight. If not, see <http://www.gnu.org/licenses/>. +*/ + + +#include <string> +#include <sstream> + +#include "version.h" +#include "xmlgenerator.h" + +using namespace std; +namespace highlight +{ + + XmlGenerator::XmlGenerator() + : CodeGenerator ( XML ) + { + spacer = " "; + newLineTag = "<br />\n"; + } + + XmlGenerator::~XmlGenerator() {} + + string XmlGenerator::getHeader() + { + ostringstream header; + header << "<?xml version=\"1.0\""; + if ( encodingDefined() ) + { + header << " encoding=\"" << encoding << "\""; + } + header << "?>\n<document>"; + header << "\n<title>" << docTitle << "</title>"; + header << getStyleDefinition(); + return header.str(); + } + + void XmlGenerator::printBody() + { + *out << "<source>\n"; + processRootState(); + *out << "</source>\n"; + } + + + string XmlGenerator::getFooter() + { + ostringstream os; + os <<"</document>\n"; + os<< "<!-- XML generated by Highlight " + << HIGHLIGHT_VERSION + << ", " + << HIGHLIGHT_URL + <<" -->\n"; + return os.str(); + } + + void XmlGenerator::initOutputTags(){ + openTags.push_back ( getOpenTag ( STY_NAME_STD ) ); + openTags.push_back ( getOpenTag ( STY_NAME_STR ) ); + openTags.push_back ( getOpenTag ( STY_NAME_NUM ) ); + openTags.push_back ( getOpenTag ( STY_NAME_SLC ) ); + openTags.push_back ( getOpenTag ( STY_NAME_COM ) ); + openTags.push_back ( getOpenTag ( STY_NAME_ESC ) ); + openTags.push_back ( getOpenTag ( STY_NAME_DIR ) ); + openTags.push_back ( getOpenTag ( STY_NAME_DST ) ); + openTags.push_back ( getOpenTag ( STY_NAME_LIN ) ); + openTags.push_back ( getOpenTag ( STY_NAME_SYM ) ); + + closeTags.push_back ( getCloseTag ( STY_NAME_STD ) ); + closeTags.push_back ( getCloseTag ( STY_NAME_STR ) ); + closeTags.push_back ( getCloseTag ( STY_NAME_NUM ) ); + closeTags.push_back ( getCloseTag ( STY_NAME_SLC ) ); + closeTags.push_back ( getCloseTag ( STY_NAME_COM ) ); + closeTags.push_back ( getCloseTag ( STY_NAME_ESC ) ); + closeTags.push_back ( getCloseTag ( STY_NAME_DIR ) ); + closeTags.push_back ( getCloseTag ( STY_NAME_DST ) ); + closeTags.push_back ( getCloseTag ( STY_NAME_LIN ) ); + closeTags.push_back ( getCloseTag ( STY_NAME_SYM ) ); + } + + string XmlGenerator::getStyleDefinition() + { + if ( styleDefinitionCache.empty() ) + { + ostringstream os; + os << "\n<style>\n" + << "\t<bgcolor value=\"" + << ( docStyle.getBgColour().getRed ( XML ) ) + << ( docStyle.getBgColour().getGreen ( XML ) ) + << ( docStyle.getBgColour().getBlue ( XML ) ) + << "\" />\n"; + os << "\t<font size=\"" << getBaseFontSize(); + os << "\" family=\"" << getBaseFont() << "\" />\n"; + os << getAttributes ( STY_NAME_STD, docStyle.getDefaultStyle() ) + << getAttributes ( STY_NAME_NUM, docStyle.getNumberStyle() ) + << getAttributes ( STY_NAME_ESC, docStyle.getEscapeCharStyle() ) + << getAttributes ( STY_NAME_STR, docStyle.getStringStyle() ) + << getAttributes ( STY_NAME_DST, docStyle.getDirectiveStringStyle() ) + << getAttributes ( STY_NAME_SLC, docStyle.getSingleLineCommentStyle() ) + << getAttributes ( STY_NAME_COM, docStyle.getCommentStyle() ) + << getAttributes ( STY_NAME_DIR, docStyle.getDirectiveStyle() ) + << getAttributes ( STY_NAME_SYM, docStyle.getSymbolStyle() ) + << getAttributes ( STY_NAME_LIN, docStyle.getLineStyle() ); + + KeywordStyles styles = docStyle.getKeywordStyles(); + for ( KSIterator it=styles.begin(); it!=styles.end(); it++ ) + { + os << getAttributes ( it->first, it->second ); + } + os << "</style>\n"; + styleDefinitionCache=os.str(); + } + return styleDefinitionCache; + } + + + string XmlGenerator::getAttributes ( const string & elemName, + const ElementStyle & elem ) + { + ostringstream s; + s << "\t<class name=\"" + << elemName + <<"\" color=\"" + << ( elem.getColour().getRed ( XML ) ) + << ( elem.getColour().getGreen ( XML ) ) + << ( elem.getColour().getBlue ( XML ) ) + << "\" bold=\"" + << ( elem.isBold() ? "true" :"false" ) + << "\" italic=\"" + << ( elem.isItalic() ? "true" :"false" ) + << "\" underline=\"" + << ( elem.isUnderline() ? "true" :"false" ) + << "\" />\n" ; + return s.str(); + } + + string XmlGenerator::getOpenTag ( const string& styleName ) + { + return "<"+styleName+">"; + } + + string XmlGenerator::getCloseTag ( const string& styleName ) + { + return "</"+styleName+">"; + } + + string XmlGenerator::maskCharacter ( unsigned char c ) + { + switch ( c ) + { + case '<' : + return "<"; + break; + case '>' : + return ">"; + break; + case '&' : + return "&"; + break; + case '\"' : + return """; + break; + default: + return string ( 1, c ); + } + } + + string XmlGenerator::getKeywordOpenTag ( unsigned int styleID ) + { + return getOpenTag ( langInfo.getKeywordClasses() [styleID] ); + } + + string XmlGenerator::getKeywordCloseTag ( unsigned int styleID ) + { + return getCloseTag ( langInfo.getKeywordClasses() [styleID] ); + } + +} diff --git a/support/highlight/src/core/xmlgenerator.h b/support/highlight/src/core/xmlgenerator.h new file mode 100644 index 0000000000..74319fdec7 --- /dev/null +++ b/support/highlight/src/core/xmlgenerator.h @@ -0,0 +1,86 @@ +/*************************************************************************** + xmlcode.h - description + ------------------- + begin : Do 20.01.2005 + copyright : (C) 2005 by Andre Simon + email : andre.simon1@gmx.de + ***************************************************************************/ + + +/* +This file is part of Highlight. + +Highlight is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +Highlight is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Highlight. If not, see <http://www.gnu.org/licenses/>. +*/ + + +#ifndef XMLGENERATOR_H +#define XMLGENERATOR_H + +#include "codegenerator.h" + +namespace highlight +{ + + /** + \brief This class generates XML. + + It contains information about the resulting document structure (document + header and footer), the colour system, white space handling and text + formatting attributes. + + * @author Andre Simon + */ + + class XmlGenerator : public highlight::CodeGenerator + { + public: + + XmlGenerator(); + ~XmlGenerator(); + + private: + + /** prints document header + */ + string getHeader(); + + /** Prints document footer*/ + string getFooter(); + + /** Prints document body*/ + void printBody(); + + /** initialize tags in specific format according to colouring information provided in DucumentStyle */ + void initOutputTags(); + + string styleDefinitionCache; + + string getStyleDefinition(); + + string getAttributes ( const string &, const ElementStyle & ); + + /** \return escaped character*/ + virtual string maskCharacter ( unsigned char ); + + string getOpenTag ( const string& ); + string getCloseTag ( const string& ); + + string getKeywordOpenTag ( unsigned int styleID ); + string getKeywordCloseTag ( unsigned int styleID ); + }; + +} + +#endif diff --git a/support/highlight/src/core/xterm256generator.cpp b/support/highlight/src/core/xterm256generator.cpp new file mode 100644 index 0000000000..d351d19b8d --- /dev/null +++ b/support/highlight/src/core/xterm256generator.cpp @@ -0,0 +1,208 @@ +/*************************************************************************** + xterm256generator.cpp - description + ------------------- + begin : Oct 13 2006 + copyright : (C) 2006 by Andre Simon + email : andre.simon1@gmx.de + ***************************************************************************/ + + +/* +This file is part of Highlight. + +Highlight is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +Highlight is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Highlight. If not, see <http://www.gnu.org/licenses/>. +*/ + + +#include <stdio.h> +#include <math.h> +#include <stdlib.h> +#include <sstream> + +#include "xterm256generator.h" +#include "charcodes.h" +#include "version.h" + +using namespace std; + +namespace highlight +{ + Xterm256Generator::Xterm256Generator() : CodeGenerator ( XTERM256 ) + { + + newLineTag = "\n"; + spacer = " "; + } + + Xterm256Generator::~Xterm256Generator() {} + + string Xterm256Generator::getHeader() + { + return string(); + } + + void Xterm256Generator::printBody() + { + processRootState(); + } + + string Xterm256Generator::getFooter() + { + return string(); + } + + string Xterm256Generator::maskCharacter ( unsigned char c ) + { + return string ( 1, c ); + } + + void Xterm256Generator::initOutputTags ( ) + { + openTags.push_back ( getOpenTag ( docStyle.getDefaultStyle() ) ); + openTags.push_back ( getOpenTag ( docStyle.getStringStyle() ) ); + openTags.push_back ( getOpenTag ( docStyle.getNumberStyle() ) ); + openTags.push_back ( getOpenTag ( docStyle.getSingleLineCommentStyle() ) ); + openTags.push_back ( getOpenTag ( docStyle.getCommentStyle() ) ); + openTags.push_back ( getOpenTag ( docStyle.getEscapeCharStyle() ) ); + openTags.push_back ( getOpenTag ( docStyle.getDirectiveStyle() ) ); + openTags.push_back ( getOpenTag ( docStyle.getDirectiveStringStyle() ) ); + openTags.push_back ( getOpenTag ( docStyle.getLineStyle() ) ); + openTags.push_back ( getOpenTag ( docStyle.getSymbolStyle() ) ); + + for ( int i=0;i<NUMBER_BUILTIN_STATES; i++ ) + { + closeTags.push_back ( "\033[m" ); + } + } + + string Xterm256Generator::getOpenTag ( const ElementStyle &col ) + { + + Colour c= col.getColour(); + unsigned char rgb[3]; + rgb[0] = ( unsigned char ) strtoll ( c.getRed ( HTML ).c_str(), NULL, 16 ); + rgb[1] = ( unsigned char ) strtoll ( c.getGreen ( HTML ).c_str(), NULL, 16 ); + rgb[2] = ( unsigned char ) strtoll ( c.getBlue ( HTML ).c_str(), NULL, 16 ); + + ostringstream s; + s << "\033[38;5;"<< ( int ) rgb2xterm ( rgb ) << "m"; + return s.str(); + } + + string Xterm256Generator::getKeywordOpenTag ( unsigned int styleID ) + { + return getOpenTag ( docStyle.getKeywordStyle ( langInfo.getKeywordClasses() [styleID] ) ); + } + + string Xterm256Generator::getKeywordCloseTag ( unsigned int styleID ) + { + return "\033[m"; + } + + /* the following functions are based on Wolfgang Frischs xterm256 converter utility: + http://frexx.de/xterm-256-notes/ + */ + + void Xterm256Generator::xterm2rgb ( unsigned char color, unsigned char* rgb ) + { + // 16 basic colors + if ( color<16 ) + { + rgb[0] = basic16[color][0]; + rgb[1] = basic16[color][1]; + rgb[2] = basic16[color][2]; + } + + // color cube color + if ( color>=16 && color<=232 ) + { + color-=16; + rgb[0] = valuerange[ ( color/36 ) %6]; + rgb[1] = valuerange[ ( color/6 ) %6]; + rgb[2] = valuerange[color%6]; + } + + // gray tone + if ( color>=233 && color<=253 ) + { + rgb[0]=rgb[1]=rgb[2] = 8+ ( color-232 ) *0x0a; + } + } + + void Xterm256Generator::maketable() + { + unsigned char c, rgb[3]; + for ( c=0;c<=253;c++ ) + { + xterm2rgb ( c,rgb ); + colortable[c][0] = rgb[0]; + colortable[c][1] = rgb[1]; + colortable[c][2] = rgb[2]; + } + } + + unsigned char Xterm256Generator::rgb2xterm ( unsigned char* rgb ) + { + unsigned char c, best_match=0; + double d, smallest_distance; + + if ( !initialized ) + { + maketable(); + initialized = true; + } + + smallest_distance = 10000000000.0; + + for ( c=0;c<=253;c++ ) + { + d = pow ( colortable[c][0]-rgb[0],2.0 ) + + pow ( colortable[c][1]-rgb[1],2.0 ) + + pow ( colortable[c][2]-rgb[2],2.0 ); + if ( d<smallest_distance ) + { + smallest_distance = d; + best_match=c; + } + } + return best_match; + } + + bool Xterm256Generator::initialized=false; + unsigned char Xterm256Generator::colortable[254][3]; + + const unsigned char Xterm256Generator::valuerange[] = { 0x00, 0x5F, 0x87, 0xAF, 0xD7, 0xFF }; + + const unsigned char Xterm256Generator::basic16[16][3] = + { + { 0x00, 0x00, 0x00 }, // 0 + { 0xCD, 0x00, 0x00 }, // 1 + { 0x00, 0xCD, 0x00 }, // 2 + { 0xCD, 0xCD, 0x00 }, // 3 + { 0x00, 0x00, 0xEE }, // 4 + { 0xCD, 0x00, 0xCD }, // 5 + { 0x00, 0xCD, 0xCD }, // 6 + { 0xE5, 0xE5, 0xE5 }, // 7 + { 0x7F, 0x7F, 0x7F }, // 8 + { 0xFF, 0x00, 0x00 }, // 9 + { 0x00, 0xFF, 0x00 }, // 10 + { 0xFF, 0xFF, 0x00 }, // 11 + { 0x5C, 0x5C, 0xFF }, // 12 + { 0xFF, 0x00, 0xFF }, // 13 + { 0x00, 0xFF, 0xFF }, // 14 + { 0xFF, 0xFF, 0xFF } // 15 + }; + + +} diff --git a/support/highlight/src/core/xterm256generator.h b/support/highlight/src/core/xterm256generator.h new file mode 100644 index 0000000000..e68b78c4c6 --- /dev/null +++ b/support/highlight/src/core/xterm256generator.h @@ -0,0 +1,111 @@ +/*************************************************************************** + xterm256generator.h - description + ------------------- + begin : Oct 13 2006 + copyright : (C) 2006-2007 by Andre Simon + email : andre.simon1@gmx.de + ***************************************************************************/ + + +/* +This file is part of Highlight. + +Highlight is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +Highlight is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Highlight. If not, see <http://www.gnu.org/licenses/>. +*/ + + +#ifndef XTERM256GENERATOR_H +#define XTERM256GENERATOR_H + +#include <string> + +#include "codegenerator.h" + + +namespace highlight +{ + + /** + \brief This class generates xterm 256 color escape sequences. + + It contains information about the resulting document structure (document + header and footer), the colour system, white space handling and text + formatting attributes. + + * @author Andre Simon + */ + + class Xterm256Generator : public highlight::CodeGenerator + { + public: + Xterm256Generator(); + ~Xterm256Generator(); + + private: + + /** prints document header + */ + string getHeader(); + + /** Prints document footer*/ + string getFooter(); + + /** Prints document body*/ + void printBody(); + + /** \return escaped character*/ + virtual string maskCharacter ( unsigned char ); + + /** initialize tags in specific format according to colouring information provided in DucumentStyle */ + void initOutputTags(); + + /** @param style associated element style + @return formatting seqence */ + string getOpenTag (const ElementStyle &style ); + + /** @param styleID current style ID + @return matching sequence to begin a new element formatting*/ + string getKeywordOpenTag ( unsigned int styleID ); + + /** @param styleID current style ID + @return matching sequence to close element formatting*/ + string getKeywordCloseTag ( unsigned int styleID ); + + /** convert an xterm color value (0-253) to 3 unsigned chars rgb + @param color xterm color + @param rgb RGB destination string */ + void xterm2rgb ( unsigned char color, unsigned char* rgb ); + + /** fill the colortable for use with rgb2xterm */ + void maketable(); + + /** selects the nearest xterm color for a 3xBYTE rgb value + @param RGB colour string */ + unsigned char rgb2xterm ( unsigned char* rgb ); + + /// Flag to determine if colourtable is calculated + static bool initialized; + + /// color tzable for nearest match calculation + static unsigned char colortable[254][3]; + + /// the 6 value iterations in the xterm color cube + static const unsigned char valuerange[] ; + + /// 16 basic colors + static const unsigned char basic16[16][3]; + }; + +} +#endif diff --git a/support/highlight/src/gui-qt/Makefile b/support/highlight/src/gui-qt/Makefile new file mode 100644 index 0000000000..588c30faec --- /dev/null +++ b/support/highlight/src/gui-qt/Makefile @@ -0,0 +1,277 @@ +############################################################################# +# Makefile for building: ../highlight-gui +# Generated by qmake (2.01a) (Qt 4.6.2) on: Mi. Mrz 31 16:43:25 2010 +# Project: highlight.pro +# Template: app +# Command: /usr/bin/qmake -unix DEFINES+=DATA_DIR=\\\/usr/share/highlight/\\\\ CONFIG_DIR=\\\/etc/highlight/\\\\ DOC_DIR=\\\/usr/share/doc/highlight/\\\ -o Makefile highlight.pro +############################################################################# + +####### Compiler, tools and options + +CC = gcc +CXX = g++ +DEFINES = -DDATA_DIR=\"/usr/share/highlight/\" -DCONFIG_DIR=\"/etc/highlight/\" -DDOC_DIR=\"/usr/share/doc/highlight/\" -DO2 -DQT -DQT_NO_DEBUG -DQT_GUI_LIB -DQT_CORE_LIB -DQT_SHARED +CFLAGS = -pipe -march=i686 -mtune=generic -O2 -pipe -Wall -W -D_REENTRANT $(DEFINES) +CXXFLAGS = -pipe -march=i686 -mtune=generic -O2 -pipe -Wall -W -D_REENTRANT $(DEFINES) +INCPATH = -I/usr/share/qt/mkspecs/linux-g++ -I. -I/usr/include/QtCore -I/usr/include/QtGui -I/usr/include -I. -I../core -I. -I. +LINK = g++ +LFLAGS = -Wl,--hash-style=gnu -Wl,--as-needed -Wl,-O1 +LIBS = $(SUBLIBS) -L/usr/lib -L.. -lhighlight -lQtGui -lQtCore -lpthread +AR = ar cqs +RANLIB = +QMAKE = /usr/bin/qmake +TAR = tar -cf +COMPRESS = gzip -9f +COPY = cp -f +SED = sed +COPY_FILE = $(COPY) +COPY_DIR = $(COPY) -r +STRIP = strip +INSTALL_FILE = install -m 644 -p +INSTALL_DIR = $(COPY_DIR) +INSTALL_PROGRAM = install -m 755 -p +DEL_FILE = rm -f +SYMLINK = ln -f -s +DEL_DIR = rmdir +MOVE = mv -f +CHK_DIR_EXISTS= test -d +MKDIR = mkdir -p + +####### Output directory + +OBJECTS_DIR = ./ + +####### Files + +SOURCES = main.cpp \ + mainwindow.cpp \ + io_report.cpp \ + showtextfile.cpp moc_mainwindow.cpp \ + moc_io_report.cpp \ + moc_showtextfile.cpp \ + qrc_highlight-gui.cpp +OBJECTS = main.o \ + mainwindow.o \ + io_report.o \ + showtextfile.o \ + moc_mainwindow.o \ + moc_io_report.o \ + moc_showtextfile.o \ + qrc_highlight-gui.o +DIST = /usr/share/qt/mkspecs/common/g++.conf \ + /usr/share/qt/mkspecs/common/unix.conf \ + /usr/share/qt/mkspecs/common/linux.conf \ + /usr/share/qt/mkspecs/qconfig.pri \ + /usr/share/qt/mkspecs/features/qt_functions.prf \ + /usr/share/qt/mkspecs/features/qt_config.prf \ + /usr/share/qt/mkspecs/features/exclusive_builds.prf \ + /usr/share/qt/mkspecs/features/default_pre.prf \ + /usr/share/qt/mkspecs/features/release.prf \ + /usr/share/qt/mkspecs/features/default_post.prf \ + /usr/share/qt/mkspecs/features/warn_on.prf \ + /usr/share/qt/mkspecs/features/qt.prf \ + /usr/share/qt/mkspecs/features/unix/thread.prf \ + /usr/share/qt/mkspecs/features/moc.prf \ + /usr/share/qt/mkspecs/features/resources.prf \ + /usr/share/qt/mkspecs/features/uic.prf \ + /usr/share/qt/mkspecs/features/yacc.prf \ + /usr/share/qt/mkspecs/features/lex.prf \ + /usr/share/qt/mkspecs/features/include_source_dir.prf \ + highlight.pro +QMAKE_TARGET = highlight-gui +DESTDIR = ../ +TARGET = ../highlight-gui + +first: all +####### Implicit rules + +.SUFFIXES: .o .c .cpp .cc .cxx .C + +.cpp.o: + $(CXX) -c -include highlight-gui $(CXXFLAGS) $(INCPATH) -o "$@" "$<" + +.cc.o: + $(CXX) -c -include highlight-gui $(CXXFLAGS) $(INCPATH) -o "$@" "$<" + +.cxx.o: + $(CXX) -c -include highlight-gui $(CXXFLAGS) $(INCPATH) -o "$@" "$<" + +.C.o: + $(CXX) -c -include highlight-gui $(CXXFLAGS) $(INCPATH) -o "$@" "$<" + +.c.o: + $(CC) -c -include highlight-gui $(CFLAGS) $(INCPATH) -o "$@" "$<" + +####### Build rules + +all: Makefile $(TARGET) + +$(TARGET): ui_mainwindow.h ui_io_report.h ui_showtextfile.h $(OBJECTS) + @$(CHK_DIR_EXISTS) ../ || $(MKDIR) ../ + $(LINK) $(LFLAGS) -o $(TARGET) $(OBJECTS) $(OBJCOMP) $(LIBS) + +Makefile: highlight.pro /usr/share/qt/mkspecs/linux-g++/qmake.conf /usr/share/qt/mkspecs/common/g++.conf \ + /usr/share/qt/mkspecs/common/unix.conf \ + /usr/share/qt/mkspecs/common/linux.conf \ + /usr/share/qt/mkspecs/qconfig.pri \ + /usr/share/qt/mkspecs/features/qt_functions.prf \ + /usr/share/qt/mkspecs/features/qt_config.prf \ + /usr/share/qt/mkspecs/features/exclusive_builds.prf \ + /usr/share/qt/mkspecs/features/default_pre.prf \ + /usr/share/qt/mkspecs/features/release.prf \ + /usr/share/qt/mkspecs/features/default_post.prf \ + /usr/share/qt/mkspecs/features/warn_on.prf \ + /usr/share/qt/mkspecs/features/qt.prf \ + /usr/share/qt/mkspecs/features/unix/thread.prf \ + /usr/share/qt/mkspecs/features/moc.prf \ + /usr/share/qt/mkspecs/features/resources.prf \ + /usr/share/qt/mkspecs/features/uic.prf \ + /usr/share/qt/mkspecs/features/yacc.prf \ + /usr/share/qt/mkspecs/features/lex.prf \ + /usr/share/qt/mkspecs/features/include_source_dir.prf \ + /usr/lib/libQtGui.prl \ + /usr/lib/libQtCore.prl + $(QMAKE) -unix DEFINES+=DATA_DIR=\\\/usr/share/highlight/\\\\ CONFIG_DIR=\\\/etc/highlight/\\\\ DOC_DIR=\\\/usr/share/doc/highlight/\\\ -o Makefile highlight.pro +/usr/share/qt/mkspecs/common/g++.conf: +/usr/share/qt/mkspecs/common/unix.conf: +/usr/share/qt/mkspecs/common/linux.conf: +/usr/share/qt/mkspecs/qconfig.pri: +/usr/share/qt/mkspecs/features/qt_functions.prf: +/usr/share/qt/mkspecs/features/qt_config.prf: +/usr/share/qt/mkspecs/features/exclusive_builds.prf: +/usr/share/qt/mkspecs/features/default_pre.prf: +/usr/share/qt/mkspecs/features/release.prf: +/usr/share/qt/mkspecs/features/default_post.prf: +/usr/share/qt/mkspecs/features/warn_on.prf: +/usr/share/qt/mkspecs/features/qt.prf: +/usr/share/qt/mkspecs/features/unix/thread.prf: +/usr/share/qt/mkspecs/features/moc.prf: +/usr/share/qt/mkspecs/features/resources.prf: +/usr/share/qt/mkspecs/features/uic.prf: +/usr/share/qt/mkspecs/features/yacc.prf: +/usr/share/qt/mkspecs/features/lex.prf: +/usr/share/qt/mkspecs/features/include_source_dir.prf: +/usr/lib/libQtGui.prl: +/usr/lib/libQtCore.prl: +qmake: FORCE + @$(QMAKE) -unix DEFINES+=DATA_DIR=\\\/usr/share/highlight/\\\\ CONFIG_DIR=\\\/etc/highlight/\\\\ DOC_DIR=\\\/usr/share/doc/highlight/\\\ -o Makefile highlight.pro + +dist: + @$(CHK_DIR_EXISTS) .tmp/highlight-gui1.0.0 || $(MKDIR) .tmp/highlight-gui1.0.0 + $(COPY_FILE) --parents $(SOURCES) $(DIST) .tmp/highlight-gui1.0.0/ && $(COPY_FILE) --parents mainwindow.h ../core/ansigenerator.h ../core/bbcodegenerator.h ../core/charcodes.h ../core/codegenerator.h ../core/configurationreader.h ../core/ctagsreader.h ../core/datadir.h ../core/documentstyle.h ../core/elementstyle.h ../core/enums.h ../core/htmlgenerator.h ../core/languagedefinition.h ../core/latexgenerator.h ../core/platform_fs.h ../core/preformatter.h ../core/rtfgenerator.h ../core/stringtools.h ../core/stylecolour.h ../core/svggenerator.h ../core/texgenerator.h ../core/version.h ../core/xhtmlgenerator.h ../core/xmlgenerator.h ../core/xterm256generator.h precomp.h io_report.h showtextfile.h .tmp/highlight-gui1.0.0/ && $(COPY_FILE) --parents highlight-gui.qrc .tmp/highlight-gui1.0.0/ && $(COPY_FILE) --parents main.cpp mainwindow.cpp io_report.cpp showtextfile.cpp .tmp/highlight-gui1.0.0/ && $(COPY_FILE) --parents mainwindow.ui io_report.ui showtextfile.ui .tmp/highlight-gui1.0.0/ && $(COPY_FILE) --parents highlight_de_DE.ts highlight_es_ES.ts .tmp/highlight-gui1.0.0/ && (cd `dirname .tmp/highlight-gui1.0.0` && $(TAR) highlight-gui1.0.0.tar highlight-gui1.0.0 && $(COMPRESS) highlight-gui1.0.0.tar) && $(MOVE) `dirname .tmp/highlight-gui1.0.0`/highlight-gui1.0.0.tar.gz . && $(DEL_FILE) -r .tmp/highlight-gui1.0.0 + + +clean:compiler_clean + -$(DEL_FILE) $(OBJECTS) + -$(DEL_FILE) highlight-gui.gch/c highlight-gui.gch/c++ + -$(DEL_FILE) *~ core *.core + + +####### Sub-libraries + +distclean: clean + -$(DEL_FILE) $(TARGET) + -$(DEL_FILE) Makefile + + +###### Prefix headers +highlight-gui.gch/c: precomp.h + @$(CHK_DIR_EXISTS) highlight-gui.gch/ || $(MKDIR) highlight-gui.gch/ + $(CC) $(CFLAGS) $(INCPATH) -x c-header -c precomp.h -o highlight-gui.gch/c + +highlight-gui.gch/c++: precomp.h + @$(CHK_DIR_EXISTS) highlight-gui.gch/ || $(MKDIR) highlight-gui.gch/ + $(CXX) $(CXXFLAGS) $(INCPATH) -x c++-header -c precomp.h -o highlight-gui.gch/c++ + +mocclean: compiler_moc_header_clean compiler_moc_source_clean + +mocables: compiler_moc_header_make_all compiler_moc_source_make_all + +compiler_moc_header_make_all: moc_mainwindow.cpp moc_io_report.cpp moc_showtextfile.cpp +compiler_moc_header_clean: + -$(DEL_FILE) moc_mainwindow.cpp moc_io_report.cpp moc_showtextfile.cpp +moc_mainwindow.cpp: mainwindow.h + /usr/bin/moc $(DEFINES) $(INCPATH) mainwindow.h -o moc_mainwindow.cpp + +moc_io_report.cpp: io_report.h + /usr/bin/moc $(DEFINES) $(INCPATH) io_report.h -o moc_io_report.cpp + +moc_showtextfile.cpp: showtextfile.h + /usr/bin/moc $(DEFINES) $(INCPATH) showtextfile.h -o moc_showtextfile.cpp + +compiler_rcc_make_all: qrc_highlight-gui.cpp +compiler_rcc_clean: + -$(DEL_FILE) qrc_highlight-gui.cpp +qrc_highlight-gui.cpp: highlight-gui.qrc \ + highlight.xpm \ + hl_icon2.png + /usr/bin/rcc -name highlight-gui highlight-gui.qrc -o qrc_highlight-gui.cpp + +compiler_image_collection_make_all: qmake_image_collection.cpp +compiler_image_collection_clean: + -$(DEL_FILE) qmake_image_collection.cpp +compiler_moc_source_make_all: +compiler_moc_source_clean: +compiler_uic_make_all: ui_mainwindow.h ui_io_report.h ui_showtextfile.h +compiler_uic_clean: + -$(DEL_FILE) ui_mainwindow.h ui_io_report.h ui_showtextfile.h +ui_mainwindow.h: mainwindow.ui + /usr/bin/uic mainwindow.ui -o ui_mainwindow.h + +ui_io_report.h: io_report.ui + /usr/bin/uic io_report.ui -o ui_io_report.h + +ui_showtextfile.h: showtextfile.ui + /usr/bin/uic showtextfile.ui -o ui_showtextfile.h + +compiler_yacc_decl_make_all: +compiler_yacc_decl_clean: +compiler_yacc_impl_make_all: +compiler_yacc_impl_clean: +compiler_lex_make_all: +compiler_lex_clean: +compiler_clean: compiler_moc_header_clean compiler_rcc_clean compiler_uic_clean + +####### Compile + +main.o: main.cpp mainwindow.h \ + highlight-gui.gch/c++ + $(CXX) -c -include highlight-gui $(CXXFLAGS) $(INCPATH) -o main.o main.cpp + +mainwindow.o: mainwindow.cpp mainwindow.h \ + ui_mainwindow.h \ + showtextfile.h \ + io_report.h \ + highlight-gui.gch/c++ + $(CXX) -c -include highlight-gui $(CXXFLAGS) $(INCPATH) -o mainwindow.o mainwindow.cpp + +io_report.o: io_report.cpp io_report.h \ + ui_io_report.h \ + highlight-gui.gch/c++ + $(CXX) -c -include highlight-gui $(CXXFLAGS) $(INCPATH) -o io_report.o io_report.cpp + +showtextfile.o: showtextfile.cpp showtextfile.h \ + ui_showtextfile.h \ + highlight-gui.gch/c++ + $(CXX) -c -include highlight-gui $(CXXFLAGS) $(INCPATH) -o showtextfile.o showtextfile.cpp + +moc_mainwindow.o: moc_mainwindow.cpp highlight-gui.gch/c++ + $(CXX) -c -include highlight-gui $(CXXFLAGS) $(INCPATH) -o moc_mainwindow.o moc_mainwindow.cpp + +moc_io_report.o: moc_io_report.cpp highlight-gui.gch/c++ + $(CXX) -c -include highlight-gui $(CXXFLAGS) $(INCPATH) -o moc_io_report.o moc_io_report.cpp + +moc_showtextfile.o: moc_showtextfile.cpp highlight-gui.gch/c++ + $(CXX) -c -include highlight-gui $(CXXFLAGS) $(INCPATH) -o moc_showtextfile.o moc_showtextfile.cpp + +qrc_highlight-gui.o: qrc_highlight-gui.cpp highlight-gui.gch/c++ + $(CXX) -c -include highlight-gui $(CXXFLAGS) $(INCPATH) -o qrc_highlight-gui.o qrc_highlight-gui.cpp + +####### Install + +install: FORCE + +uninstall: FORCE + +FORCE: + diff --git a/support/highlight/src/gui-qt/highlight-gui.qrc b/support/highlight/src/gui-qt/highlight-gui.qrc new file mode 100644 index 0000000000..cf5f269528 --- /dev/null +++ b/support/highlight/src/gui-qt/highlight-gui.qrc @@ -0,0 +1,6 @@ +<RCC> + <qresource prefix="/" > + <file>highlight.xpm</file> + <file>hl_icon2.png</file> + </qresource> +</RCC> diff --git a/support/highlight/src/gui-qt/highlight.pro b/support/highlight/src/gui-qt/highlight.pro new file mode 100644 index 0000000000..88676f021f --- /dev/null +++ b/support/highlight/src/gui-qt/highlight.pro @@ -0,0 +1,39 @@ +# -------------------------------------------------
+# Project created by QtCreator 2009-03-03T22:45:06
+# -------------------------------------------------
+TARGET = highlight-gui
+TEMPLATE = app
+INCLUDEPATH += . \
+ ../core/
+win32:CONFIG += static
+CONFIG += precompile_header
+PRECOMPILED_HEADER = precomp.h
+DEFINES += O2 QT
+win32:DESTDIR = ../../
+unix:DESTDIR = ../
+SOURCES += main.cpp \
+ mainwindow.cpp \
+ io_report.cpp \
+ showtextfile.cpp
+HEADERS += mainwindow.h \
+ ../core/*.h \
+ precomp.h \
+ io_report.h \
+ showtextfile.h
+FORMS += mainwindow.ui \
+ io_report.ui \
+ showtextfile.ui
+RESOURCES = highlight-gui.qrc
+TRANSLATIONS = highlight_de_DE.ts highlight_es_ES.ts
+
+win32:RC_FILE = highlight-gui.rc
+win32:LIBS += -L../.. -lhighlight
+unix:LIBS += -L.. -lhighlight
+
+win32:QMAKE_POST_LINK = f:/upx/upx.exe --best ../../highlight-gui.exe
+#unix {
+#DEFINES += DATA_DIR=\\\"/usr/share/highlight\\\" \
+# CONFIG_DIR=\\\"/etc/highlight\\\" \
+# DOC_DIR=\\\"/usr/share/doc/highlight\\\"
+# message("setting unix default paths")
+#}
diff --git a/support/highlight/src/gui-qt/highlight.xpm b/support/highlight/src/gui-qt/highlight.xpm new file mode 100644 index 0000000000..bc3e73097f --- /dev/null +++ b/support/highlight/src/gui-qt/highlight.xpm @@ -0,0 +1,1173 @@ +/* XPM */ +static char * highlight_xpm[] = { +"48 48 1122 2", +" c None", +". c #0C5C92", +"+ c #0D5C92", +"@ c #0F5F94", +"# c #0F5E94", +"$ c #126196", +"% c #156398", +"& c #156498", +"* c #18669A", +"= c #32728E", +"- c #588D93", +"; c #62857B", +"> c #739482", +", c #748D79", +"' c #6B7E6D", +") c #5F847D", +"! c #37616E", +"~ c #2A607B", +"{ c #196699", +"] c #1B689C", +"^ c #307799", +"/ c #549192", +"( c #609C90", +"_ c #6AA593", +": c #68A696", +"< c #629785", +"[ c #64937D", +"} c #547967", +"| c #546B5C", +"1 c #53584A", +"2 c #515549", +"3 c #3E4747", +"4 c #2C5F7B", +"5 c #1B689B", +"6 c #1E6493", +"7 c #215E87", +"8 c #22547C", +"9 c #275276", +"0 c #3B5A6F", +"a c #3E5770", +"b c #3D5568", +"c c #365D6D", +"d c #1C689A", +"e c #1E6B9E", +"f c #1E6A9E", +"g c #3D8091", +"h c #56A29C", +"i c #499B92", +"j c #5FA290", +"k c #609789", +"l c #558C7A", +"m c #598E79", +"n c #546857", +"o c #485343", +"p c #374A3F", +"q c #4C4231", +"r c #885229", +"s c #A5602A", +"t c #452C1C", +"u c #2C4156", +"v c #395373", +"w c #3F526F", +"x c #465067", +"y c #4E4E5C", +"z c #5A5760", +"A c #675F5F", +"B c #655B59", +"C c #5A5751", +"D c #406071", +"E c #22648B", +"F c #216DA0", +"G c #448E98", +"H c #399EA1", +"I c #3C928D", +"J c #548378", +"K c #54887E", +"L c #3F7872", +"M c #3E6B63", +"N c #404F47", +"O c #41363C", +"P c #221B20", +"Q c #392923", +"R c #BD9C6E", +"S c #5A321F", +"T c #2D1716", +"U c #382B30", +"V c #504550", +"W c #65626C", +"X c #726767", +"Y c #78655E", +"Z c #69574F", +"` c #665D54", +" . c #3F545E", +".. c #285D7D", +"+. c #216D9D", +"@. c #206DA0", +"#. c #246FA2", +"$. c #236FA2", +"%. c #2470A2", +"&. c #2370A2", +"*. c #307797", +"=. c #498F86", +"-. c #3C7777", +";. c #497170", +">. c #437072", +",. c #435559", +"'. c #555E59", +"). c #58665C", +"!. c #736852", +"~. c #7A5334", +"{. c #472815", +"]. c #331D17", +"^. c #674229", +"/. c #5F3528", +"(. c #513B44", +"_. c #463B48", +":. c #503A3F", +"<. c #604137", +"[. c #594133", +"}. c #616661", +"|. c #38667E", +"1. c #256D9A", +"2. c #2772A4", +"3. c #2672A4", +"4. c #2E769D", +"5. c #469FA3", +"6. c #477B78", +"7. c #457073", +"8. c #326471", +"9. c #4D5156", +"0. c #946141", +"a. c #AC5D2A", +"b. c #CD6F27", +"c. c #C36924", +"d. c #945C2E", +"e. c #574936", +"f. c #3C3630", +"g. c #3B3933", +"h. c #322523", +"i. c #746358", +"j. c #A99E85", +"k. c #C3B997", +"l. c #9F967C", +"m. c #2C729D", +"n. c #2672A3", +"o. c #2974A6", +"p. c #2974A5", +"q. c #2975A6", +"r. c #478F95", +"s. c #4A7B7C", +"t. c #3C6267", +"u. c #3F545F", +"v. c #737779", +"w. c #CABFA8", +"x. c #F4CF92", +"y. c #C5682A", +"z. c #9F4E21", +"A. c #52584D", +"B. c #254749", +"C. c #223F43", +"D. c #253A3C", +"E. c #3A3B39", +"F. c #ADA589", +"G. c #DED7AD", +"H. c #C5B890", +"I. c #877C68", +"J. c #4C7386", +"K. c #2A74A6", +"L. c #2975A5", +"M. c #2C77A8", +"N. c #2C77A7", +"O. c #2E78A7", +"P. c #548D85", +"Q. c #485657", +"R. c #9D9891", +"S. c #E0DFD6", +"T. c #FCFDF4", +"U. c #FAFDF0", +"V. c #E8E7D4", +"W. c #78715E", +"X. c #1F3E48", +"Y. c #1B373E", +"Z. c #1D363C", +"`. c #233437", +" + c #343431", +".+ c #B0A88B", +"++ c #E6E3B9", +"@+ c #AF9D7C", +"#+ c #594E48", +"$+ c #3A6478", +"%+ c #2F79A9", +"&+ c #2F79AA", +"*+ c #44899D", +"=+ c #65877E", +"-+ c #D4D3C3", +";+ c #F4F3DF", +">+ c #CFC4A7", +",+ c #A59174", +"'+ c #8F7A5E", +")+ c #3A3839", +"!+ c #1C2023", +"~+ c #1A2023", +"{+ c #161617", +"]+ c #212120", +"^+ c #372924", +"/+ c #69422C", +"(+ c #BCA88B", +"_+ c #C1B192", +":+ c #6C605C", +"<+ c #455E69", +"[+ c #327CAB", +"}+ c #327CAC", +"|+ c #5B9EAC", +"1+ c #94B49B", +"2+ c #8A8F73", +"3+ c #6E7061", +"4+ c #474A45", +"5+ c #353433", +"6+ c #2C3431", +"7+ c #32332F", +"8+ c #303835", +"9+ c #2A2F2C", +"0+ c #263535", +"a+ c #263739", +"b+ c #3E322A", +"c+ c #622915", +"d+ c #632A18", +"e+ c #653B2D", +"f+ c #4A3735", +"g+ c #426780", +"h+ c #367FAE", +"i+ c #55A0B6", +"j+ c #69A59B", +"k+ c #527E6F", +"l+ c #446055", +"m+ c #384741", +"n+ c #344A43", +"o+ c #2D3C39", +"p+ c #333A35", +"q+ c #293B3A", +"r+ c #283B3B", +"s+ c #1D4142", +"t+ c #22383A", +"u+ c #274040", +"v+ c #513122", +"w+ c #692912", +"x+ c #5C2715", +"y+ c #623D2D", +"z+ c #4C4241", +"A+ c #387AA2", +"B+ c #4389B6", +"C+ c #438AB6", +"D+ c #4389B7", +"E+ c #438AB7", +"F+ c #60A8BE", +"G+ c #68A49A", +"H+ c #538373", +"I+ c #446154", +"J+ c #416458", +"K+ c #2F625B", +"L+ c #265855", +"M+ c #204E4E", +"N+ c #21413E", +"O+ c #405647", +"P+ c #364238", +"Q+ c #2D3D37", +"R+ c #253838", +"S+ c #283534", +"T+ c #2C3C3B", +"U+ c #4A3224", +"V+ c #672810", +"W+ c #652B13", +"X+ c #583022", +"Y+ c #473129", +"Z+ c #486D7D", +"`+ c #5196C0", +" @ c #5195C0", +".@ c #6AADC3", +"+@ c #68B7AE", +"@@ c #4C8070", +"#@ c #477666", +"$@ c #427167", +"%@ c #306D66", +"&@ c #255E5D", +"*@ c #1F5657", +"=@ c #205559", +"-@ c #23504E", +";@ c #477560", +">@ c #4C6754", +",@ c #464235", +"'@ c #303A35", +")@ c #323C36", +"!@ c #493E32", +"~@ c #673219", +"{@ c #692A10", +"]@ c #733211", +"^@ c #633421", +"/@ c #483129", +"(@ c #4A6B7C", +"_@ c #60A1C9", +":@ c #68ACC9", +"<@ c #6EB8B4", +"[@ c #5B9986", +"}@ c #528374", +"|@ c #41726C", +"1@ c #396B65", +"2@ c #286764", +"3@ c #226060", +"4@ c #215E61", +"5@ c #225356", +"6@ c #2B5451", +"7@ c #3E635C", +"8@ c #466A6A", +"9@ c #50615A", +"0@ c #604830", +"a@ c #5E3821", +"b@ c #6A3216", +"c@ c #76300E", +"d@ c #79320D", +"e@ c #823B12", +"f@ c #683318", +"g@ c #462E24", +"h@ c #4E6978", +"i@ c #5FA0C8", +"j@ c #6DA9CE", +"k@ c #6DA9CD", +"l@ c #6FABCC", +"m@ c #80C5C6", +"n@ c #5C9480", +"o@ c #588D7C", +"p@ c #467970", +"q@ c #3B726A", +"r@ c #317570", +"s@ c #2B6F6C", +"t@ c #336461", +"u@ c #2F6C6C", +"v@ c #396966", +"w@ c #386B6D", +"x@ c #3F6A6E", +"y@ c #49848B", +"z@ c #605949", +"A@ c #994B18", +"B@ c #9A3906", +"C@ c #843910", +"D@ c #792D0A", +"E@ c #93420E", +"F@ c #8D4213", +"G@ c #6F3619", +"H@ c #4E342A", +"I@ c #54676D", +"J@ c #6DA8CD", +"K@ c #7BB0D2", +"L@ c #75B5B3", +"M@ c #5C9885", +"N@ c #5B907C", +"O@ c #448074", +"P@ c #548074", +"Q@ c #3B7971", +"R@ c #397F7C", +"S@ c #3D7D79", +"T@ c #3A736F", +"U@ c #297172", +"V@ c #376363", +"W@ c #477378", +"X@ c #48767B", +"Y@ c #586E6B", +"Z@ c #7C6A4F", +"`@ c #B6520E", +" # c #A63E05", +".# c #8A3206", +"+# c #873A0C", +"@# c #984D18", +"## c #A14F18", +"$# c #88461E", +"%# c #4E3327", +"&# c #5E7177", +"*# c #7AB0D2", +"=# c #7BB1D2", +"-# c #88B8D6", +";# c #80BACA", +"># c #5AA58D", +",# c #5A9D8A", +"'# c #609484", +")# c #508077", +"!# c #599086", +"~# c #528C82", +"{# c #4E8980", +"]# c #3A7875", +"^# c #266365", +"/# c #3B797E", +"(# c #517979", +"_# c #5F8887", +":# c #657369", +"<# c #938462", +"[# c #C98240", +"}# c #D26714", +"|# c #B94B06", +"1# c #953F0C", +"2# c #8B3D0F", +"3# c #AF6427", +"4# c #AE5D20", +"5# c #884A23", +"6# c #4B3227", +"7# c #7393A0", +"8# c #96C0DA", +"9# c #95C0D9", +"0# c #69B8AF", +"a# c #4E9B88", +"b# c #53978A", +"c# c #59988D", +"d# c #56827A", +"e# c #5B8B82", +"f# c #4D8C83", +"g# c #357E81", +"h# c #235F65", +"i# c #3B7A7B", +"j# c #5C8580", +"k# c #5D7D7A", +"l# c #6B7769", +"m# c #A99263", +"n# c #D99E4B", +"o# c #E68D2A", +"p# c #DA6D0F", +"q# c #B95108", +"r# c #9E4307", +"s# c #A65115", +"t# c #A8591D", +"u# c #AE5E20", +"v# c #93532A", +"w# c #503F31", +"x# c #8EB6CD", +"y# c #96BFDA", +"z# c #A3C7DE", +"A# c #A3C7DF", +"B# c #8BC7CA", +"C# c #3EA196", +"D# c #4B9D92", +"E# c #499189", +"F# c #568D86", +"G# c #4D9189", +"H# c #478B83", +"I# c #3A807B", +"J# c #2D8485", +"K# c #36797C", +"L# c #588283", +"M# c #637F78", +"N# c #727664", +"O# c #9C8B60", +"P# c #DBAE5A", +"Q# c #EDA53C", +"R# c #E6811B", +"S# c #D66609", +"T# c #B85109", +"U# c #B3530D", +"V# c #A54F0F", +"W# c #A05921", +"X# c #AA5C1D", +"Y# c #844D23", +"Z# c #676861", +"`# c #A2C6DE", +" $ c #A4C7DE", +".$ c #B4D1E4", +"+$ c #B4D0E4", +"@$ c #B4D1E3", +"#$ c #ADCDDB", +"$$ c #68C3C4", +"%$ c #329B95", +"&$ c #35918E", +"*$ c #298585", +"=$ c #4B8D85", +"-$ c #338E8D", +";$ c #348583", +">$ c #2B8486", +",$ c #37949B", +"'$ c #4B7E7A", +")$ c #5B7D74", +"!$ c #647C6F", +"~$ c #837D5D", +"{$ c #B9985C", +"]$ c #EAA53C", +"^$ c #EE9223", +"/$ c #E8790F", +"($ c #D66308", +"_$ c #B74F07", +":$ c #A84707", +"<$ c #98490F", +"[$ c #9E5F27", +"}$ c #7F4B22", +"|$ c #614731", +"1$ c #9FB5BF", +"2$ c #B4D0E3", +"3$ c #CEDFEC", +"4$ c #CDDFEC", +"5$ c #9FD4D5", +"6$ c #2DA5AA", +"7$ c #169DA1", +"8$ c #257073", +"9$ c #2D878A", +"0$ c #2F8085", +"a$ c #338A8C", +"b$ c #3099A1", +"c$ c #48847F", +"d$ c #597E78", +"e$ c #447A7B", +"f$ c #388692", +"g$ c #5C7E77", +"h$ c #9B9871", +"i$ c #DDA246", +"j$ c #F19C2A", +"k$ c #EB7B0E", +"l$ c #E06B07", +"m$ c #BF4F03", +"n$ c #AA4A0A", +"o$ c #91430E", +"p$ c #A66122", +"q$ c #975D29", +"r$ c #5A3B25", +"s$ c #7B7B6C", +"t$ c #C9DCE9", +"u$ c #CEDFEB", +"v$ c #E9EEF4", +"w$ c #E8EEF4", +"x$ c #E9EFF4", +"y$ c #82C8CB", +"z$ c #0B9BAA", +"A$ c #1C7E89", +"B$ c #55898A", +"C$ c #1B96A7", +"D$ c #4099A1", +"E$ c #3E8088", +"F$ c #49797D", +"G$ c #3D848A", +"H$ c #2B8193", +"I$ c #3B838C", +"J$ c #3F7980", +"K$ c #828467", +"L$ c #CA974D", +"M$ c #E99B32", +"N$ c #F1901E", +"O$ c #E16D0C", +"P$ c #CD5C09", +"Q$ c #B44D07", +"R$ c #9A4D19", +"S$ c #A0632E", +"T$ c #996A40", +"U$ c #855F3B", +"V$ c #675B4B", +"W$ c #D1D9DB", +"X$ c #8C96A6", +"Y$ c #99B9C0", +"Z$ c #5ECAE5", +"`$ c #5A99A4", +" % c #5D9C9F", +".% c #508188", +"+% c #448C96", +"@% c #528A8F", +"#% c #3D8F9F", +"$% c #418998", +"%% c #498B90", +"&% c #3E7C81", +"*% c #4F7879", +"=% c #597B77", +"-% c #9C8660", +";% c #D9983E", +">% c #F39D29", +",% c #E7760E", +"'% c #C75307", +")% c #C0580F", +"!% c #A34C10", +"~% c #A26333", +"{% c #9A6B3D", +"]% c #A3733E", +"^% c #715332", +"/% c #707882", +"(% c #8B95A5", +"_% c #284B6C", +":% c #5BB4C7", +"<% c #3CB3D7", +"[% c #61999E", +"}% c #568588", +"|% c #4D9298", +"1% c #368496", +"2% c #3A8092", +"3% c #457B82", +"4% c #467C85", +"5% c #407E89", +"6% c #3A7882", +"7% c #43747B", +"8% c #4E5951", +"9% c #AF8444", +"0% c #F8D25D", +"a% c #F6961B", +"b% c #DA6409", +"c% c #B04A0A", +"d% c #A1470B", +"e% c #9D5928", +"f% c #AB8155", +"g% c #9A6C3C", +"h% c #855C2F", +"i% c #4D5B5B", +"j% c #284B6B", +"k% c #6AACCC", +"l% c #6AABCC", +"m% c #6AAFC8", +"n% c #5DCBE8", +"o% c #3BA5CB", +"p% c #3F7681", +"q% c #579CA3", +"r% c #3F8A9C", +"s% c #2D879E", +"t% c #3B8597", +"u% c #488591", +"v% c #4A808C", +"w% c #4A858D", +"x% c #387B87", +"y% c #3E6569", +"z% c #826539", +"A% c #F4DD72", +"B% c #FBC342", +"C% c #EB7A11", +"D% c #C75C0F", +"E% c #9F470F", +"F% c #A3571C", +"G% c #9D6534", +"H% c #B1854C", +"I% c #78522D", +"J% c #586D6F", +"K% c #68A9C9", +"L% c #81CBEB", +"M% c #80CBEC", +"N% c #7ED0E1", +"O% c #56C9ED", +"P% c #3491B4", +"Q% c #2696A7", +"R% c #569CA5", +"S% c #518A94", +"T% c #5297A3", +"U% c #53909D", +"V% c #538B95", +"W% c #45838E", +"X% c #367C87", +"Y% c #476D6F", +"Z% c #9B7B40", +"`% c #F9D14A", +" & c #FCCD49", +".& c #F99E20", +"+& c #E17113", +"@& c #AA5113", +"#& c #954C16", +"$& c #7B441B", +"%& c #996E3E", +"&& c #916C40", +"*& c #67746D", +"=& c #7BC1DF", +"-& c #80CBEB", +";& c #81CBEC", +">& c #8D948C", +",& c #87A8AA", +"'& c #85BFCD", +")& c #83CEEF", +"!& c #82DBEA", +"~& c #44C6EE", +"{& c #2990B4", +"]& c #238799", +"^& c #3A7D8C", +"/& c #4F9DAA", +"(& c #4D97A3", +"_& c #478E9A", +":& c #3E808D", +"<& c #38808A", +"[& c #4C706B", +"}& c #C2923D", +"|& c #FBD656", +"1& c #FBBC2D", +"2& c #FCB52D", +"3& c #F38914", +"4& c #D26613", +"5& c #7F3E18", +"6& c #714627", +"7& c #553722", +"8& c #6E5439", +"9& c #789FA8", +"0& c #81CAE9", +"a& c #83CEEE", +"b& c #9D8880", +"c& c #9A877C", +"d& c #94887E", +"e& c #8B9189", +"f& c #7CCAD3", +"g& c #37B1E1", +"h& c #2A809B", +"i& c #1F7D90", +"j& c #348D9E", +"k& c #2791A2", +"l& c #2E8D9C", +"m& c #2F8190", +"n& c #397E85", +"o& c #4E6964", +"p& c #AB651D", +"q& c #FACC3F", +"r& c #FBBB2E", +"s& c #FCAF20", +"t& c #F68C10", +"u& c #E06D0E", +"v& c #B3520D", +"w& c #5A2B19", +"x& c #463025", +"y& c #58635F", +"z& c #71A2B1", +"A& c #7BC2E2", +"B& c #A59184", +"C& c #AC9D91", +"D& c #AE9D96", +"E& c #A39088", +"F& c #81CCDF", +"G& c #48B1DD", +"H& c #2181A1", +"I& c #286877", +"J& c #238697", +"K& c #2A8290", +"L& c #36747C", +"M& c #3C686B", +"N& c #54453A", +"O& c #A8500E", +"P& c #F6AE23", +"Q& c #FBC333", +"R& c #FBA718", +"S& c #F99610", +"T& c #EA780B", +"U& c #CB600D", +"V& c #843A0C", +"W& c #473021", +"X& c #5D7C84", +"Y& c #73B4D3", +"Z& c #73B5D5", +"`& c #C1B398", +" * c #C4B9A6", +".* c #BEB29E", +"+* c #BBB0A1", +"@* c #A3BEC1", +"#* c #51BFE7", +"$* c #287FAD", +"%* c #2F596B", +"&* c #3E5150", +"** c #4C4640", +"=* c #564338", +"-* c #572D1B", +";* c #AE540B", +">* c #F3970F", +",* c #FCAE16", +"'* c #FCAF1E", +")* c #FAA119", +"!* c #F1860E", +"~* c #DC7617", +"{* c #AC5C19", +"]* c #6E6758", +"^* c #6593A4", +"/* c #6BA8C7", +"(* c #6BA8C8", +"_* c #6BA9C8", +":* c #D4C7A0", +"<* c #D1CAAC", +"[* c #CCC5A9", +"}* c #CBC4AD", +"|* c #BEC9BE", +"1* c #57C0E6", +"2* c #215384", +"3* c #30262D", +"4* c #53352B", +"5* c #663C2B", +"6* c #5F2A16", +"7* c #85400E", +"8* c #DA8518", +"9* c #F6A51B", +"0* c #F9A317", +"a* c #F8A01A", +"b* c #EE9320", +"c* c #E18826", +"d* c #B35916", +"e* c #884729", +"f* c #4E565A", +"g* c #6298B4", +"h* c #639BBB", +"i* c #639CBB", +"j* c #D4C290", +"k* c #D3C59A", +"l* c #D2C8A4", +"m* c #D2C8A8", +"n* c #BDCBB9", +"o* c #2B82BB", +"p* c #3D414F", +"q* c #432924", +"r* c #733C1F", +"s* c #7A360F", +"t* c #95490F", +"u* c #713511", +"v* c #A26022", +"w* c #CE8E31", +"x* c #E49224", +"y* c #CD7C20", +"z* c #B46922", +"A* c #93501C", +"B* c #87411B", +"C* c #EBAF57", +"D* c #C17641", +"E* c #975A3B", +"F* c #7F6050", +"G* c #607481", +"H* c #5B8FAE", +"I* c #BA9D6E", +"J* c #C4A673", +"K* c #C6AE7E", +"L* c #CBB98C", +"M* c #8DB2BB", +"N* c #3076A0", +"O* c #CAAC63", +"P* c #CA832D", +"Q* c #A2510F", +"R* c #9F4E0D", +"S* c #854111", +"T* c #472F34", +"U* c #4D332A", +"V* c #663F26", +"W* c #89552D", +"X* c #A17142", +"Y* c #8C5A33", +"Z* c #B17648", +"`* c #D68D50", +" = c #C08C5B", +".= c #BA875F", +"+= c #B08765", +"@= c #9F7354", +"#= c #996F59", +"$= c #605E61", +"%= c #567E99", +"&= c #5382A2", +"*= c #5382A1", +"== c #906D51", +"-= c #906E4E", +";= c #B09066", +">= c #B49467", +",= c #61A9C9", +"'= c #8A9E91", +")= c #E8A840", +"!= c #C07424", +"~= c #7A3D11", +"{= c #8A4F24", +"]= c #4E383A", +"^= c #524249", +"/= c #64473D", +"(= c #74513C", +"_= c #BB9A66", +":= c #CFB17A", +"<= c #D0AD76", +"[= c #CFAF7E", +"}= c #CCAE85", +"|= c #88624A", +"1= c #A9704F", +"2= c #AC6E4C", +"3= c #B17858", +"4= c #B78968", +"5= c #AE927D", +"6= c #937A70", +"7= c #75767A", +"8= c #55748B", +"9= c #4C7796", +"0= c #516A74", +"a= c #516C7D", +"b= c #5E7682", +"c= c #678580", +"d= c #59A1C1", +"e= c #C18B44", +"f= c #B67029", +"g= c #693B1D", +"h= c #80583A", +"i= c #907051", +"j= c #4A3A3B", +"k= c #5F4840", +"l= c #725644", +"m= c #BA9A67", +"n= c #D5BB7E", +"o= c #D9C289", +"p= c #D3B986", +"q= c #CFB487", +"r= c #B0916F", +"s= c #AE7C5A", +"t= c #BD8A6C", +"u= c #B37D63", +"v= c #B48A73", +"w= c #B9A692", +"x= c #BAA590", +"y= c #B29A88", +"z= c #A39082", +"A= c #877876", +"B= c #797C82", +"C= c #617889", +"D= c #4F738E", +"E= c #48708F", +"F= c #47708F", +"G= c #436887", +"H= c #518BA4", +"I= c #4D4B47", +"J= c #834B1E", +"K= c #54473A", +"L= c #4B626F", +"M= c #50616B", +"N= c #5B5E5C", +"O= c #58504A", +"P= c #47352C", +"Q= c #654E3B", +"R= c #C29C60", +"S= c #CEB074", +"T= c #D1BB84", +"U= c #D5C28F", +"V= c #D8C79A", +"W= c #C9AF8E", +"X= c #CAB195", +"Y= c #C49779", +"Z= c #BE8C72", +"`= c #CBBEA9", +" - c #C3B29F", +".- c #C1AC94", +"+- c #C3B4A4", +"@- c #B6A79B", +"#- c #A8968C", +"$- c #A28E85", +"%- c #9B887F", +"&- c #988A83", +"*- c #858783", +"=- c #6E7C83", +"-- c #607685", +";- c #567284", +">- c #476C86", +",- c #436888", +"'- c #436987", +")- c #3E6180", +"!- c #41667F", +"~- c #49656F", +"{- c #4A3121", +"]- c #484A4D", +"^- c #41627A", +"/- c #415666", +"(- c #5C5F5A", +"_- c #8F7857", +":- c #AD895A", +"<- c #BB9D6D", +"[- c #CEBB8A", +"}- c #D4C198", +"|- c #D8CBA6", +"1- c #D4C8A9", +"2- c #D1C7AC", +"3- c #D0C4A9", +"4- c #CDC2A9", +"5- c #D5C6AC", +"6- c #CFC3AC", +"7- c #CBC6B7", +"8- c #C4BAAC", +"9- c #B7A595", +"0- c #B7A291", +"a- c #AF9585", +"b- c #A8937C", +"c- c #A28E7E", +"d- c #A6958B", +"e- c #9B8D88", +"f- c #87817E", +"g- c #6F777A", +"h- c #586E7C", +"i- c #43637F", +"j- c #406280", +"k- c #3B5B78", +"l- c #3A5979", +"m- c #3A5977", +"n- c #3C5872", +"o- c #3A5A79", +"p- c #3A5A78", +"q- c #3A5978", +"r- c #395A78", +"s- c #3B5B79", +"t- c #4A6478", +"u- c #54626D", +"v- c #6D665B", +"w- c #937654", +"x- c #BCA67B", +"y- c #C9B689", +"z- c #CBBC91", +"A- c #CEC19C", +"B- c #D1C7A8", +"C- c #D3CAAD", +"D- c #D2C3A1", +"E- c #CBB89A", +"F- c #D0C6AE", +"G- c #CBC1AB", +"H- c #CBC1AF", +"I- c #C6B7A3", +"J- c #C1AC96", +"K- c #C3B399", +"L- c #BDAB96", +"M- c #B3A296", +"N- c #AE9A8E", +"O- c #A58D81", +"P- c #A58E82", +"Q- c #A38E82", +"R- c #9A8C84", +"S- c #928D87", +"T- c #7F8180", +"U- c #6A7780", +"V- c #5F707B", +"W- c #566B78", +"X- c #506878", +"Y- c #3C5B78", +"Z- c #355271", +"`- c #365371", +" ; c #4C6271", +".; c #858679", +"+; c #AC956D", +"@; c #A3845D", +"#; c #A48864", +"$; c #C4B48F", +"%; c #D6C9A0", +"&; c #D6CBA3", +"*; c #DAD1AE", +"=; c #D3C6A6", +"-; c #D7D0B3", +";; c #D7D2B7", +">; c #D4CFB8", +",; c #CFC2A7", +"'; c #D6CEB3", +"); c #D0C4AD", +"!; c #C6BDAC", +"~; c #C4BDB2", +"{; c #C0B3A8", +"]; c #C0B09F", +"^; c #C4B49F", +"/; c #BBAA9A", +"(; c #B39A88", +"_; c #B19E90", +":; c #AD9B90", +"<; c #AD9D90", +"[; c #AB9A8D", +"}; c #AA9A8B", +"|; c #9E9386", +"1; c #8E8475", +"2; c #897B6D", +"3; c #304B6A", +"4; c #304B69", +"5; c #3A536D", +"6; c #5A6A6D", +"7; c #787567", +"8; c #9F8C6D", +"9; c #A28061", +"0; c #C6A673", +"a; c #CBB080", +"b; c #D1BD8C", +"c; c #D7C89D", +"d; c #D9CEA8", +"e; c #DDD8B5", +"f; c #E1DAB7", +"g; c #E0DAB7", +"h; c #DBD5B8", +"i; c #D9D4B8", +"j; c #D8D1B7", +"k; c #CFC1A6", +"l; c #D2CAB5", +"m; c #D1C5AB", +"n; c #CBBEA6", +"o; c #C2AC94", +"p; c #B8A18E", +"q; c #C2B3A0", +"r; c #BCAD9C", +"s; c #B4A295", +"t; c #AF9D8F", +"u; c #AC998B", +"v; c #2C4362", +"w; c #2C4462", +"x; c #2E4563", +"y; c #4B5E69", +"z; c #917962", +"A; c #9C7758", +"B; c #956B4A", +"C; c #B28B5E", +"D; c #BB9E71", +"E; c #C7AD7E", +"F; c #D6C494", +"G; c #DFD3A9", +"H; c #D9CFA6", +"I; c #DCD5B2", +"J; c #E1DCB7", +"K; c #DBD1AB", +"L; c #DFD8B5", +"M; c #DACDA6", +"N; c #D9D0B2", +"O; c #D4C8AA", +"P; c #D2C7A9", +"Q; c #D1CAB3", +"R; c #CAC1AC", +"S; c #C0B09E", +"T; c #273C5B", +"U; c #334761", +"V; c #293D5B", +"W; c #887862", +"X; c #696453", +"Y; c #494E4D", +"Z; c #48494F", +"`; c #5E544F", +" > c #866D51", +".> c #A38560", +"+> c #C7AE7D", +"@> c #CFAF78", +"#> c #D0B784", +"$> c #D6C595", +"%> c #D7C99D", +"&> c #D2C293", +"*> c #D8CA9B", +"=> c #D9C99B", +"-> c #D7C89F", +";> c #D9CEA9", +">> c #DED5AE", +",> c #D7CEAE", +"'> c #D7D1B5", +")> c #D1C7AD", +"!> c #B5A398", +"~> c #A69388", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . + + . + . + + + + + . + . + + + . + . . . . . . + . . . . + + + . + . . + . + . + . . . ", +"@ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ # @ @ @ @ @ @ # @ @ ", +"@ @ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ ", +"% % % % % & % % % & % % % % % % % % % % % % % % % % % & & % % % % & % % % % % % % % % % % % % & ", +"* * * * * * * * * * * * * * * * * * * * * = - ; > , ' ) ! ~ { * * * * * * * * * * * * * * * * * ", +"] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ^ / ( _ : < [ } | 1 2 3 4 5 ] ] ] 6 7 8 9 0 a b c d ] ] ] ", +"e e e e e e e e e e e e e e f e e e g h i j k l m n o p q r s t u v w x y z A B C D E e e e e e ", +"F F F F F F F F F F F F F F F F F G H I J K L M N O P Q R S T U V W X Y Z ` ...+.F F F F F F @.", +"#.$.%.#.$.%.%.&.%.%.%.%.&.#.$.#.*.=.-.;.>.,.'.).!.~.{.].^./.(._.:.<.[.}.|.1.&.%.$.%.%.#.&.%.&.&.", +"2.3.2.3.3.3.2.3.3.3.2.3.3.3.3.4.5.6.7.8.9.0.a.b.c.d.e.f.g.h.i.j.k.l.m.3.3.2.n.3.3.3.3.3.n.3.3.n.", +"o.o.o.p.o.o.o.o.o.o.o.o.p.o.q.r.s.t.u.v.w.x.y.z.A.B.C.D.E.F.G.H.I.J.o.p.o.o.o.o.o.K.L.o.o.o.o.o.", +"M.M.M.M.N.N.N.M.M.N.N.N.M.M.O.P.Q.R.S.T.U.V.W.X.Y.Z.`. +.+++@+#+$+N.N.M.M.M.M.M.M.M.N.M.N.N.N.N.", +"%+%+%+%+&+%+%+%+&+%+&+%+%+%+*+=+-+;+>+,+'+)+!+~+{+]+^+/+(+_+:+<+%+&+&+%+&+%+&+%+%+&+%+%+%+%+%+%+", +"[+[+}+}+[+[+[+[+[+[+[+[+[+[+|+1+2+3+4+5+6+7+8+9+0+a+b+c+d+e+f+g+[+[+[+[+[+[+[+[+[+[+[+[+[+[+[+[+", +"h+h+h+h+h+h+h+h+h+h+h+h+h+i+j+k+l+m+n+o+9+p+q+r+s+t+u+v+w+x+y+z+A+h+h+h+h+h+h+h+h+h+h+h+h+h+h+h+", +"B+C+B+D+B+E+D+D+C+B+B+B+F+G+H+I+J+K+L+M+N+O+P+Q+R+S+T+U+V+W+X+Y+Z+B+B+B+D+B+D+B+B+B+D+B+D+B+B+C+", +"`+`+ @`+`+`+`+`+ @ @ @.@+@@@#@$@%@&@*@=@-@;@>@,@'@)@!@~@{@]@^@/@(@ @ @`+`+ @`+`+`+`+ @`+ @ @`+`+", +"_@_@_@_@_@_@_@_@_@_@:@<@[@}@|@1@2@3@4@5@6@7@8@9@0@a@b@c@d@e@f@g@h@i@_@_@_@_@_@_@_@_@_@_@_@_@_@_@", +"j@j@j@j@k@k@j@k@k@l@m@n@o@p@q@r@s@t@u@v@w@x@y@z@A@B@C@D@E@F@G@H@I@J@j@j@j@k@k@k@k@k@j@k@k@j@k@k@", +"K@K@K@K@K@K@K@K@K@L@M@N@O@P@Q@R@S@T@U@V@W@X@Y@Z@`@ #.#+#@###$#%#&#*#K@K@K@K@K@=#=#K@K@K@K@K@K@K@", +"-#-#-#-#-#-#-#-#;#>#,#'#)#!#~#{#]#^#/#(#_#:#<#[#}#|#1#2#3#4#5#6#7#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#", +"8#8#8#8#8#8#8#9#0#a#b#c#d#e#f#g#h#i#j#k#l#m#n#o#p#q#r#s#t#u#v#w#x#8#8#8#8#8#y#8#8#8#8#8#8#8#8#8#", +"z#z#z#A#z#z#A#B#C#D#E#F#G#H#I#J#K#L#M#N#O#P#Q#R#S#T#U#V#W#X#Y#Z#`#z#z#z#z#z# $z#z#z#z#z#A#A#z#A#", +".$+$@$.$@$.$#$$$%$&$*$=$-$;$>$,$'$)$!$~${$]$^$/$($_$:$<$[$}$|$1$2$.$@$.$.$.$.$.$@$.$@$.$.$2$.$.$", +"3$3$4$3$3$3$5$6$7$8$9$0$a$b$c$d$e$f$g$h$i$j$k$l$m$n$o$p$q$r$s$t$3$3$3$3$3$3$3$3$3$3$u$3$3$3$3$3$", +"v$v$v$v$w$x$y$z$A$B$C$D$E$F$G$H$I$J$K$L$M$N$O$P$Q$R$S$T$U$V$W$w$v$v$v$w$v$v$v$v$v$w$v$v$v$v$v$v$", +"X$X$X$X$X$Y$Z$`$ %.%+%@%#%$%%%&%*%=%-%;%>%,%'%)%!%~%{%]%^%/%(%X$X$X$X$X$X$X$X$X$X$X$X$X$X$X$X$X$", +"_%_%_%_%_%:%<%[%}%|%1%2%3%4%5%6%7%8%9%0%a%b%c%d%e%f%g%h%i%j%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%", +"k%l%k%k%m%n%o%p%q%r%s%t%u%v%w%x%y%z%A%B%C%D%E%F%G%H%I%J%K%l%k%l%k%k%k%l%k%k%l%k%k%k%k%k%k%k%l%k%", +"L%M%M%M%N%O%P%Q%R%S%T%U%V%W%X%Y%Z%`% &.&+&@&#&$&%&&&*&=&-&L%L%-&-&-&L%-&-&;&L%M%L%;&M%-&M%;&-&M%", +">&,&'&)&!&~&{&]&^&/&(&_&:&<&[&}&|&1&2&3&4&5&6&7&8&9&0&)&)&a&)&a&a&a&)&)&a&)&a&)&a&)&a&)&)&a&a&a&", +"b&c&d&e&f&g&h&i&j&k&l&m&n&o&p&q&r&s&t&u&v&w&x&y&z&A&A&A&A&A&A&A&A&A&A&A&A&A&A&A&A&A&A&A&A&A&A&A&", +"B&C&D&E&F&G&H&I&J&K&L&M&N&O&P&Q&R&S&T&U&V&W&X&Y&Z&Z&Z&Z&Z&Z&Z&Z&Z&Z&Z&Z&Z&Z&Z&Z&Z&Z&Z&Z&Z&Z&Z&Z&", +"`& *.*+*@*#*$*%*&***=*-*;*>*,*'*)*!*~*{*]*^*/*(*_*(*(*(*(*(*_*(*(*(*(*_*(*_*(*(*(*_*(*(*(*_*(*(*", +":*<*[*}*|*1*2*3*4*5*6*7*8*9*0*a*b*c*d*e*f*g*h*h*i*h*i*i*i*i*i*i*i*i*i*i*i*h*i*h*i*i*i*i*i*i*i*i*", +"j*k*l*m*n*o*p*q*r*s*t*u*v*w*x*y*z*A*B*C*D*E*F*G*H*H*H*H*H*H*H*H*H*H*H*H*H*H*H*H*H*H*H*H*H*H*H*H*", +"I*J*K*L*M*N*O*P*Q*R*S*T*U*V*W*X*Y*Z*`* =.=+=@=#=$=%=&=&=*=*=*=*=*=&=*=&=&=&=&=*=*=&=*=&=*=*=&=*=", +"==-=;=>=,='=)=!=~={=]=^=/=(=_=:=<=[=}=|=1=2=3=4=5=6=7=8=9=9=9=9=9=9=9=9=9=9=9=9=9=9=9=9=9=9=9=9=", +"0=a=b=c=d=e=f=g=h=i=j=k=l=m=n=o=p=q=r=s=t=u=v=w=x=y=z=A=B=C=D=E=E=E=E=E=E=E=F=F=E=F=E=F=E=F=F=E=", +"G=G=G=H=I=J=K=L=M=N=O=P=Q=R=S=T=U=V=W=X=Y=Z=`= -.-+-@-#-$-%-&-*-=---;->-G=G=G=G=G=G=,-,-,-G=G='-", +")-)-!-~-{-]-)-)-)-)-)-^-/-(-_-:-<-[-}-|-1-2-3-4-5-6-7-8-9-0-a-b-c-d-e-f-g-h-i-j-)-)-)-)-)-)-)-)-", +"k-l-k-m-n-o-p-q-o-o-o-p-r-s-t-u-v-w-x-y-z-A-B-C-D-E-F-G-H-I-J-K-L-M-N-O-P-Q-R-S-T-U-V-W-X-Y-l-Y-", +"Z-Z-Z-Z-Z-Z-Z-Z-Z-Z-Z-Z-Z-Z-Z-Z-`- ;.;+;@;#;$;%;&;*;=;-;;;>;,;';);!;~;{;];^;/;(;_;:;<;[;};|;1;2;", +"3;3;3;3;4;3;3;3;3;3;3;3;3;3;4;3;3;3;3;5;6;7;8;9;0;a;b;c;d;e;f;g;h;i;j;k;l;m;n;o;p;q;r;s;t;u;|;|;", +"v;v;v;v;v;v;v;v;v;v;v;v;v;v;v;v;v;v;v;v;w;x;y;z;A;B;C;D;E;F;c;G;H;I;J;K;L;M;N;O;P;Q;R;S;|;|;u;|;", +"T;T;T;T;T;T;T;T;T;T;T;T;T;T;T;T;U;T;T;T;T;T;V;W;X;Y;Z;`; >.>+>@>#>$>%>&>*>=>->;>>>,>'>)>'>!>~>|;"}; diff --git a/support/highlight/src/gui-qt/highlight_de_DE.ts b/support/highlight/src/gui-qt/highlight_de_DE.ts new file mode 100644 index 0000000000..11f6722383 --- /dev/null +++ b/support/highlight/src/gui-qt/highlight_de_DE.ts @@ -0,0 +1,1159 @@ +<?xml version="1.0" encoding="utf-8"?> +<!DOCTYPE TS> +<TS version="2.0" language="de_DE" sourcelanguage="en_US"> +<context> + <name>MainWindow</name> + <message> + <source>Themes or indent schemes not found. +Check installation.</source> + <translation type="obsolete">Farb- oder Formatierungsvorlagen nicht gefunden. +Installation prüfen.</translation> + </message> + <message> + <location filename="mainwindow.cpp" line="82"/> + <source>Initialization error</source> + <translation>Initialisierungsfehler</translation> + </message> + <message> + <location filename="mainwindow.cpp" line="83"/> + <source>Could not find syntax definitions. Check installation.</source> + <translation>Syntaxdefinitionen nicht gefunden. +Installation prüfen.</translation> + </message> + <message> + <location filename="mainwindow.cpp" line="610"/> + <source>Tags file error</source> + <translation>Tags Dateifehler</translation> + </message> + <message> + <location filename="mainwindow.cpp" line="611"/> + <source>Could not read tags information in "%1"</source> + <translation>Konnte Tags-Informationen in %1 nicht lesen</translation> + </message> + <message> + <location filename="mainwindow.cpp" line="628"/> + <location filename="mainwindow.cpp" line="659"/> + <source>Output error</source> + <translation>Ausgabefehler</translation> + </message> + <message> + <location filename="mainwindow.cpp" line="628"/> + <source>Output directory does not exist!</source> + <translation>Zielverzeichnis existert nicht!</translation> + </message> + <message> + <location filename="mainwindow.cpp" line="659"/> + <source>You must define a style output file!</source> + <translation>Sie müssen ein Stylesheet zur Ausgabe angeben!</translation> + </message> + <message> + <location filename="mainwindow.cpp" line="694"/> + <source>Language definition error</source> + <translation>Fehler in Sprachdefinition</translation> + </message> + <message> + <location filename="mainwindow.cpp" line="695"/> + <source>Invalid regular expression in %1: +%2</source> + <translation>Ungültiger regulärer Ausdruck in %1: %2</translation> + </message> + <message> + <location filename="mainwindow.cpp" line="699"/> + <source>Unknown syntax</source> + <translation>Unbekannte Syntax</translation> + </message> + <message> + <location filename="mainwindow.cpp" line="699"/> + <source>Could not convert %1</source> + <translation>Konnte %1 nicht konvertieren</translation> + </message> + <message> + <location filename="mainwindow.cpp" line="759"/> + <source>Converted %1 files in %2 ms</source> + <translation>%1 Dateien in %2 ms konvertiert</translation> + </message> + <message> + <location filename="mainwindow.cpp" line="851"/> + <source>Conversion of "%1" not possible.</source> + <translation>Konnte "%1" nicht konvertieren.</translation> + </message> + <message> + <location filename="mainwindow.cpp" line="851"/> + <location filename="mainwindow.cpp" line="951"/> + <location filename="mainwindow.cpp" line="962"/> + <source>clipboard data</source> + <translation>Daten der Zwischenablage</translation> + </message> + <message> + <location filename="mainwindow.cpp" line="950"/> + <source>Preview (%1):</source> + <translation>Vorschau (%1):</translation> + </message> + <message> + <location filename="mainwindow.cpp" line="953"/> + <source>Current syntax: %1</source> + <translation>Aktuelle Syntax: %1</translation> + </message> + <message> + <location filename="mainwindow.cpp" line="962"/> + <source>Preview of "%1" not possible.</source> + <translation>Vorschau von "%1" nicht möglich.</translation> + </message> + <message> + <location filename="mainwindow.cpp" line="973"/> + <source>Choose a ctags file</source> + <translation>Wählen Sie eine ctags Datei</translation> + </message> + <message> + <location filename="mainwindow.cpp" line="999"/> + <location filename="mainwindow.cpp" line="1003"/> + <location filename="mainwindow.cpp" line="1007"/> + <location filename="mainwindow.cpp" line="1012"/> + <source>Choose a style include file</source> + <translation>Wählen Sie ein Eingabe-Stylesheet</translation> + </message> + <message> + <location filename="mainwindow.cpp" line="1018"/> + <source>About providing translations</source> + <translation>Ãœbersetzungen bereitstellen</translation> + </message> + <message> + <location filename="mainwindow.cpp" line="1019"/> + <source>The GUI was developed using the Qt toolkit, and translations may be provided using the tools Qt Linguist and lrelease. +The highlight.ts file for Linguist resides in the src/gui-qt subdirectory. +The qm file generated by lrelease has to be saved in gui-files/l10n. + +Please send a note to as (at) andre-simon (dot) de if you have issues during translating or if you have finished or updated a translation.</source> + <translation>Diese GUI wurde mit dem Qt Toolkit entwickelt, daher werden Ãœbersetzungsdateien mit den Werkzeugen Qt Linguist und lrelease erstellt. +Die highlight.ts Datei für Linguist befindet sich im src/gui-qt Unterverzeichnis. +Die von lrelease ausgegebene qm-Datei wird in gui-files/l10n gespeichert. + +Bitte senden Sie eine Nachricht an as (at) andre-simon (dot) de, wenn Sie Probleme bei der Ãœbersetzung haben oder wenn Sie eine Ãœbersetzung fertiggestellt bzw. aktualisiert haben.</translation> + </message> +</context> +<context> + <name>MainWindowClass</name> + <message> + <location filename="mainwindow.ui" line="55"/> + <source>Choose the source code files you want to convert.</source> + <translation>Wähle Sourcecode-Dateien zur Konvertierung aus.</translation> + </message> + <message> + <location filename="mainwindow.ui" line="61"/> + <source>Choose input files</source> + <translation>Dateien wählen</translation> + </message> + <message> + <location filename="mainwindow.ui" line="83"/> + <source>List of input files.</source> + <translation>Liste der Eingabedateien.</translation> + </message> + <message> + <location filename="mainwindow.ui" line="104"/> + <source>Remove the selected input files.</source> + <translation>Lösche die markierten Dateien aus der Eingabeliste.</translation> + </message> + <message> + <location filename="mainwindow.ui" line="107"/> + <source>Clear selection</source> + <translation>Auswahl entfernen</translation> + </message> + <message> + <location filename="mainwindow.ui" line="114"/> + <source>Remove all input files.</source> + <translation>Lösche die Eingabeliste.</translation> + </message> + <message> + <location filename="mainwindow.ui" line="117"/> + <source>Clear all</source> + <translation>Alle entfernen</translation> + </message> + <message> + <source>Output destination</source> + <translation type="obsolete">Zielverzeichnis</translation> + </message> + <message> + <location filename="mainwindow.ui" line="156"/> + <source>Output directory</source> + <translation>Zielverzeichnis</translation> + </message> + <message> + <location filename="mainwindow.ui" line="175"/> + <source>Select the output directory.</source> + <translation>Wähle das Ausgabeverzeichnis.</translation> + </message> + <message> + <location filename="mainwindow.ui" line="178"/> + <location filename="mainwindow.ui" line="808"/> + <location filename="mainwindow.ui" line="919"/> + <location filename="mainwindow.ui" line="1158"/> + <location filename="mainwindow.ui" line="1280"/> + <location filename="mainwindow.ui" line="1562"/> + <source>...</source> + <translation>...</translation> + </message> + <message> + <location filename="mainwindow.ui" line="187"/> + <source>Save output in the input file directories.</source> + <translation>Speichere Ausgabe in den Verzeichnissen der Eingabedateien.</translation> + </message> + <message> + <location filename="mainwindow.ui" line="190"/> + <source>Write to source directories</source> + <translation>In Quellverzeichnisse schreiben</translation> + </message> + <message> + <source>Output options</source> + <translation type="obsolete">Ausgabeoptionen</translation> + </message> + <message> + <location filename="mainwindow.ui" line="356"/> + <source>General</source> + <translation>Allgemein</translation> + </message> + <message> + <location filename="mainwindow.ui" line="376"/> + <source>Output format:</source> + <translation>Ausgabeformat:</translation> + </message> + <message> + <location filename="mainwindow.ui" line="398"/> + <source>Choose an output format.</source> + <translation>Wähle ein Ausgabeformat.</translation> + </message> + <message> + <location filename="mainwindow.ui" line="402"/> + <source>HTML</source> + <translation></translation> + </message> + <message> + <location filename="mainwindow.ui" line="407"/> + <source>XHTML</source> + <translation></translation> + </message> + <message> + <location filename="mainwindow.ui" line="412"/> + <source>LaTeX</source> + <translation></translation> + </message> + <message> + <location filename="mainwindow.ui" line="417"/> + <source>TeX</source> + <translation></translation> + </message> + <message> + <location filename="mainwindow.ui" line="422"/> + <source>RTF</source> + <translation></translation> + </message> + <message> + <location filename="mainwindow.ui" line="427"/> + <source>SVG</source> + <translation></translation> + </message> + <message> + <location filename="mainwindow.ui" line="432"/> + <source>XML</source> + <translation></translation> + </message> + <message> + <location filename="mainwindow.ui" line="456"/> + <source>Add line numbers to the output.</source> + <translation>Füge Zeilennummern zur Ausgabe hinzu.</translation> + </message> + <message> + <location filename="mainwindow.ui" line="459"/> + <source>Add line numbers</source> + <translation>Zeilennummerierung</translation> + </message> + <message> + <location filename="mainwindow.ui" line="479"/> + <source>Select the line number width.</source> + <translation>Wähle die Stellenanzahl der Nummerierung.</translation> + </message> + <message> + <location filename="mainwindow.ui" line="500"/> + <source>Fill leading space of line numbers with zeroes.</source> + <translation>Fülle Zeilennummerierung mit Nullen auf.</translation> + </message> + <message> + <location filename="mainwindow.ui" line="503"/> + <source>Pad with zeroes</source> + <translation>Zeige führende Nullen</translation> + </message> + <message> + <location filename="mainwindow.ui" line="516"/> + <source>Generate output without document header and footer.</source> + <translation>Erzeuge Ausgabe ohne Dokumentenkopf und -fußteil.</translation> + </message> + <message> + <location filename="mainwindow.ui" line="519"/> + <source>Omit header and footer</source> + <translation>Kopf- und Fußteil auslassen</translation> + </message> + <message> + <location filename="mainwindow.ui" line="526"/> + <source>Test if input data is not binary. +Removes Unicode BOM mark.</source> + <translation>Stellt sicher, daß die Eingabe nicht binär ist. +Entfernt den Unicode BOM.</translation> + </message> + <message> + <location filename="mainwindow.ui" line="530"/> + <source>Validate input data</source> + <translation>Prüfe Eingabedaten</translation> + </message> + <message> + <location filename="mainwindow.ui" line="539"/> + <source>Set the output file ancoding.</source> + <translation>Setzt das Encoding.</translation> + </message> + <message> + <source>Encoding:</source> + <translation type="obsolete">Encoding:</translation> + </message> + <message> + <location filename="mainwindow.ui" line="549"/> + <source>Select or define the encoding. +The result has to match the input file encoding.</source> + <translation>Wähle oder definiere das Ausgabe-Encoding. +Das Encoding muss mit den Eingabedateien übereinstimmen.</translation> + </message> + <message> + <location filename="mainwindow.ui" line="560"/> + <source>ISO-8859-1</source> + <translation></translation> + </message> + <message> + <location filename="mainwindow.ui" line="565"/> + <source>ISO-8859-2</source> + <translation></translation> + </message> + <message> + <location filename="mainwindow.ui" line="570"/> + <source>ISO-8859-3</source> + <translation></translation> + </message> + <message> + <location filename="mainwindow.ui" line="575"/> + <source>ISO-8859-4</source> + <translation></translation> + </message> + <message> + <location filename="mainwindow.ui" line="580"/> + <source>ISO-8859-5</source> + <translation></translation> + </message> + <message> + <location filename="mainwindow.ui" line="585"/> + <source>ISO-8859-6</source> + <translation></translation> + </message> + <message> + <location filename="mainwindow.ui" line="590"/> + <source>ISO-8859-7</source> + <translation></translation> + </message> + <message> + <location filename="mainwindow.ui" line="595"/> + <source>ISO-8859-8</source> + <translation></translation> + </message> + <message> + <location filename="mainwindow.ui" line="600"/> + <source>ISO-8859-9</source> + <translation></translation> + </message> + <message> + <location filename="mainwindow.ui" line="605"/> + <source>ISO-8859-10</source> + <translation></translation> + </message> + <message> + <location filename="mainwindow.ui" line="610"/> + <source>ISO-8859-11</source> + <translation></translation> + </message> + <message> + <location filename="mainwindow.ui" line="615"/> + <source>ISO-8859-12</source> + <translation></translation> + </message> + <message> + <location filename="mainwindow.ui" line="620"/> + <source>ISO-8859-13</source> + <translation></translation> + </message> + <message> + <location filename="mainwindow.ui" line="625"/> + <source>ISO-8859-14</source> + <translation></translation> + </message> + <message> + <location filename="mainwindow.ui" line="630"/> + <source>ISO-8859-15</source> + <translation></translation> + </message> + <message> + <location filename="mainwindow.ui" line="635"/> + <source>UTF-8</source> + <translation></translation> + </message> + <message> + <location filename="mainwindow.ui" line="659"/> + <source>Output specific</source> + <translation>Format-Optionen</translation> + </message> + <message> + <location filename="mainwindow.ui" line="696"/> + <source>HTML options</source> + <translation>HTML Optionen</translation> + </message> + <message> + <source>Style</source> + <translation type="obsolete">Stylesheets</translation> + </message> + <message> + <location filename="mainwindow.ui" line="734"/> + <location filename="mainwindow.ui" line="1088"/> + <location filename="mainwindow.ui" line="1210"/> + <location filename="mainwindow.ui" line="1492"/> + <source>Include the style information in each output file.</source> + <translation>Füge die Stylesheets in jede Ausgabedatei ein.</translation> + </message> + <message> + <location filename="mainwindow.ui" line="737"/> + <location filename="mainwindow.ui" line="1495"/> + <source>Embed style (CSS)</source> + <translation>CSS einbetten</translation> + </message> + <message> + <location filename="mainwindow.ui" line="747"/> + <source>Add CSS information to each tag (do not use CSS class definitions).</source> + <translation>Füge Stylesheets in jeden Tag ein (benutze keine CSS Klassen).</translation> + </message> + <message> + <location filename="mainwindow.ui" line="750"/> + <source>Inline CSS</source> + <translation></translation> + </message> + <message> + <source>Style file:</source> + <translation type="obsolete">Stylesheet-Datei:</translation> + </message> + <message> + <location filename="mainwindow.ui" line="777"/> + <location filename="mainwindow.ui" line="1232"/> + <location filename="mainwindow.ui" line="1514"/> + <source>Name of the referenced style file.</source> + <translation>Name des referenzierten Stylesheets.</translation> + </message> + <message> + <location filename="mainwindow.ui" line="780"/> + <location filename="mainwindow.ui" line="1517"/> + <source>highlight.css</source> + <translation></translation> + </message> + <message> + <source>Style include file:</source> + <translation type="obsolete">Eingabe-Stylesheet:</translation> + </message> + <message> + <location filename="mainwindow.ui" line="798"/> + <location filename="mainwindow.ui" line="1552"/> + <source>Path of the CSS include file.</source> + <translation>Pfad zur CSS-Datei, die ins Stylesheet eingefügt werden soll.</translation> + </message> + <message> + <location filename="mainwindow.ui" line="805"/> + <source>Select a CSS include file.</source> + <translation>Wähle eine Stylesheet-Eingabedatei.</translation> + </message> + <message> + <location filename="mainwindow.ui" line="819"/> + <source>CSS class prefix:</source> + <translation>CSS Präfix:</translation> + </message> + <message> + <location filename="mainwindow.ui" line="826"/> + <source>Add a CSS class name prefix to avoid namespace clashes.</source> + <translation>Definiere einen CSS-Klassennamen, um Kollisionen mit anderen Stylesheets zu vermeiden.</translation> + </message> + <message> + <source>Tags and index files</source> + <translation type="obsolete">Tags- und Indexdateien</translation> + </message> + <message> + <location filename="mainwindow.ui" line="861"/> + <source>Generate an index file with hyperlinks to all outputted files.</source> + <translation>Erzeuge eine Indexdatei mit Links zu allen Ausgabedateien.</translation> + </message> + <message> + <location filename="mainwindow.ui" line="864"/> + <source>Generate index file</source> + <translation>Indexdatei erzeugen</translation> + </message> + <message> + <location filename="mainwindow.ui" line="884"/> + <source>Read a ctags file and add the included metainformation as tooltips. +See ctags.sf.net for details.</source> + <translation>Lese eine ctags-Datei und füge die Metainformationen als Tooltips hinzu. +Siehe ctags.sf.net um mehr darüber zu erfahren.</translation> + </message> + <message> + <source>Ctags file:</source> + <translation type="obsolete">Ctags Datei:</translation> + </message> + <message> + <location filename="mainwindow.ui" line="903"/> + <source>Path of the ctags file.</source> + <translation>Pfad der ctags-Datei.</translation> + </message> + <message> + <location filename="mainwindow.ui" line="916"/> + <source>Choose a ctags file.</source> + <translation>Wähle eine ctags Datei.</translation> + </message> + <message> + <location filename="mainwindow.ui" line="945"/> + <source>Misc</source> + <translation>Verschiedenes</translation> + </message> + <message> + <location filename="mainwindow.ui" line="964"/> + <source>Add an achor to each line.</source> + <translation>Füge Anker zu jeder Zeile hinzu.</translation> + </message> + <message> + <location filename="mainwindow.ui" line="967"/> + <source>Add line anchors</source> + <translation>Anker einfügen</translation> + </message> + <message> + <location filename="mainwindow.ui" line="974"/> + <source>Add the filename as prefix to the anchors.</source> + <translation>Füge Dateinamen als Präfix zum Anker hinzu.</translation> + </message> + <message> + <location filename="mainwindow.ui" line="977"/> + <source>Include file name in anchor</source> + <translation>Dateiname im Anker</translation> + </message> + <message> + <location filename="mainwindow.ui" line="984"/> + <source>Output the lines within an ordered list.</source> + <translation>Gib die Zeilen als sortierte Liste aus.</translation> + </message> + <message> + <source>Ordered list</source> + <translation type="obsolete">Sortierte Liste</translation> + </message> + <message> + <location filename="mainwindow.ui" line="1001"/> + <source>Add &lt;pre&gt; tags to the output, if the flag "No document header and footer" is selected.</source> + <translation>Schließe die Ausgabe in &lt;pre&gt;-Tags ein, wenn die Option "Kopf- und Fußteil auslassen" gewählt ist.</translation> + </message> + <message> + <source>Enclose in <pre></source> + <translation type="obsolete">Schließe in &lt;pre&gt; ein</translation> + </message> + <message> + <location filename="mainwindow.ui" line="1044"/> + <source>LaTeX options</source> + <translation>LaTeX Optionen</translation> + </message> + <message> + <location filename="mainwindow.ui" line="1058"/> + <source>Replace quotes by dq sequences.</source> + <translation>Ersetze Anführungszeichen mit \dq-Sequenzen.</translation> + </message> + <message> + <location filename="mainwindow.ui" line="1061"/> + <source>Escape quotes</source> + <translation>Ersetze Anführungszeichen</translation> + </message> + <message> + <location filename="mainwindow.ui" line="1068"/> + <source>Make output Babel compatible.</source> + <translation>Erzeuge Code, der mit Babel verträglich ist.</translation> + </message> + <message> + <source>Babel compatibility</source> + <translation type="obsolete">Babel Kompatibilität</translation> + </message> + <message> + <location filename="mainwindow.ui" line="1078"/> + <source>Replace default symbols (brackets, tilde) by nice redefinitions.</source> + <translation>Ersetze Standard-Darstellung verschiedener Symbole (Klammern, Tilde) durch schönere Definitionen.</translation> + </message> + <message> + <source>Pretty symbols</source> + <translation type="obsolete">Schönere Symbole</translation> + </message> + <message> + <location filename="mainwindow.ui" line="1091"/> + <source>Embed style (defs)</source> + <translation>Stylesheet einbetten</translation> + </message> + <message> + <location filename="mainwindow.ui" line="1110"/> + <source>Name of the referenced style file.</source> + <translation>Name des referenzierten Stylesheets.</translation> + </message> + <message> + <location filename="mainwindow.ui" line="1113"/> + <location filename="mainwindow.ui" line="1235"/> + <source>highlight.sty</source> + <translation></translation> + </message> + <message> + <source>Style include:</source> + <translation type="obsolete">Eingabe-Stylesheet:</translation> + </message> + <message> + <location filename="mainwindow.ui" line="542"/> + <source>Set encoding:</source> + <translation>Encoding:</translation> + </message> + <message> + <location filename="mainwindow.ui" line="888"/> + <source>Read ctags file:</source> + <translation>Lese ctags-Datei:</translation> + </message> + <message> + <location filename="mainwindow.ui" line="987"/> + <source>Output as ordered list</source> + <translation>Sortierte Liste</translation> + </message> + <message> + <location filename="mainwindow.ui" line="1004"/> + <source>Enclose in pre tags</source> + <translation>Schließe in pre-Tags ein</translation> + </message> + <message> + <location filename="mainwindow.ui" line="1071"/> + <source>Add Babel compatibility</source> + <translation>Babel Kompatibilität</translation> + </message> + <message> + <location filename="mainwindow.ui" line="1081"/> + <source>Add pretty symbols</source> + <translation>Symbole anpassen</translation> + </message> + <message> + <location filename="mainwindow.ui" line="764"/> + <location filename="mainwindow.ui" line="1100"/> + <location filename="mainwindow.ui" line="1222"/> + <location filename="mainwindow.ui" line="1504"/> + <source>Stylesheet file:</source> + <translation>Stylesheet-Datei:</translation> + </message> + <message> + <location filename="mainwindow.ui" line="141"/> + <source>Output destination:</source> + <translation>Zielverzeichnis:</translation> + </message> + <message> + <location filename="mainwindow.ui" line="1124"/> + <location filename="mainwindow.ui" line="1246"/> + <location filename="mainwindow.ui" line="1528"/> + <source>Stylesheet include file:</source> + <translation>Eingabe-Stylesheet:</translation> + </message> + <message> + <location filename="mainwindow.ui" line="957"/> + <source>Line numbering options:</source> + <translation>Optionen der Zeilennummerierung:</translation> + </message> + <message> + <location filename="mainwindow.ui" line="20"/> + <source>Highlight</source> + <translation>Highlight</translation> + </message> + <message> + <location filename="mainwindow.ui" line="49"/> + <source>Files</source> + <translation>Dateien</translation> + </message> + <message> + <location filename="mainwindow.ui" line="256"/> + <source>Paste clipboard content into the preview window.</source> + <translation>Füge Inhalt der Zwischenablage in die Vorschau ein.</translation> + </message> + <message> + <location filename="mainwindow.ui" line="259"/> + <source>Paste from clipboard</source> + <translation>Aus Zwischenablage einfügen</translation> + </message> + <message> + <location filename="mainwindow.ui" line="297"/> + <source>Copy highlighted code into the clipboard.</source> + <translation>Kopiere formatierte Ausgabe in die Zwischenablage.</translation> + </message> + <message> + <location filename="mainwindow.ui" line="300"/> + <source>Copy preview to clipboard</source> + <translation>In Zwischenablage kopieren</translation> + </message> + <message> + <location filename="mainwindow.ui" line="268"/> + <source>Select syntax:</source> + <translation>Syntax wählen:</translation> + </message> + <message> + <location filename="mainwindow.ui" line="275"/> + <source>Select the correct syntax of the code snippet.</source> + <translation>Wähle die zum Text passende Syntax.</translation> + </message> + <message> + <location filename="mainwindow.ui" line="437"/> + <source>BBCode</source> + <translation>BBCode</translation> + </message> + <message> + <location filename="mainwindow.ui" line="726"/> + <source>Stylesheets</source> + <translation>Stylesheets</translation> + </message> + <message> + <location filename="mainwindow.ui" line="791"/> + <source>Include:</source> + <translation>Eingabedatei:</translation> + </message> + <message> + <location filename="mainwindow.ui" line="855"/> + <source>Index/ctags</source> + <translation>Index/ctags</translation> + </message> + <message> + <location filename="mainwindow.ui" line="1148"/> + <location filename="mainwindow.ui" line="1270"/> + <source>Path of the style include file.</source> + <translation>Pfad zur sty-Datei, die ins Stylesheet eingefügt werden soll.</translation> + </message> + <message> + <location filename="mainwindow.ui" line="1155"/> + <location filename="mainwindow.ui" line="1277"/> + <location filename="mainwindow.ui" line="1559"/> + <source>Select a style include file.</source> + <translation>Wähle eine Stylesheet-Eingabedatei.</translation> + </message> + <message> + <location filename="mainwindow.ui" line="1196"/> + <source>TeX options</source> + <translation>TeX Optionen</translation> + </message> + <message> + <location filename="mainwindow.ui" line="1213"/> + <source>Embed style (macros)</source> + <translation>Stylesheet einbetten</translation> + </message> + <message> + <location filename="mainwindow.ui" line="1318"/> + <source>RTF options</source> + <translation>RTF Optionen</translation> + </message> + <message> + <location filename="mainwindow.ui" line="1332"/> + <source>Add character stylesheets with formatting information. +You can select the stylesheets in your word processor to reformat additional text.</source> + <translation>Füge Zeichenvorlagen mit Formatierungsinformationen hinzu. +Diese können in der Textverarbeitung gewählt werden, um zusätzlichen Text zu formatieren.</translation> + </message> + <message> + <location filename="mainwindow.ui" line="1336"/> + <source>Add character styles</source> + <translation>Zeichenvorlagen</translation> + </message> + <message> + <location filename="mainwindow.ui" line="1345"/> + <source>Page size:</source> + <translation>Papierformat:</translation> + </message> + <message> + <location filename="mainwindow.ui" line="1352"/> + <source>Select a page size.</source> + <translation>Wähle eine Seitengröße aus.</translation> + </message> + <message> + <location filename="mainwindow.ui" line="1359"/> + <source>A3</source> + <translation></translation> + </message> + <message> + <location filename="mainwindow.ui" line="1364"/> + <source>A4</source> + <translation></translation> + </message> + <message> + <location filename="mainwindow.ui" line="1369"/> + <source>A5</source> + <translation></translation> + </message> + <message> + <location filename="mainwindow.ui" line="1374"/> + <source>B4</source> + <translation></translation> + </message> + <message> + <location filename="mainwindow.ui" line="1379"/> + <source>B5</source> + <translation></translation> + </message> + <message> + <location filename="mainwindow.ui" line="1384"/> + <source>B6</source> + <translation></translation> + </message> + <message> + <location filename="mainwindow.ui" line="1389"/> + <source>Letter</source> + <translation></translation> + </message> + <message> + <location filename="mainwindow.ui" line="1394"/> + <source>Legal</source> + <translation></translation> + </message> + <message> + <location filename="mainwindow.ui" line="1433"/> + <source>SVG options</source> + <translation>SVG Optionen</translation> + </message> + <message> + <location filename="mainwindow.ui" line="1447"/> + <source>Image size:</source> + <translation>Bildgröße:</translation> + </message> + <message> + <location filename="mainwindow.ui" line="1456"/> + <source>Width:</source> + <translation>Breite:</translation> + </message> + <message> + <location filename="mainwindow.ui" line="1466"/> + <source>Enter the SVG width (may contain units).</source> + <translation>Gib die Bildbreite ein (kann Größeneinheiten enthalten).</translation> + </message> + <message> + <location filename="mainwindow.ui" line="1473"/> + <source>Height:</source> + <translation>Höhe:</translation> + </message> + <message> + <location filename="mainwindow.ui" line="1483"/> + <source>Enter the SVG height (may contain units).</source> + <translation>Gib die Bildhöhe ein (kann Größeneinheiten enthalten).</translation> + </message> + <message> + <location filename="mainwindow.ui" line="1588"/> + <source>No options defined.</source> + <translation>Keine Optionen vorhanden.</translation> + </message> + <message> + <location filename="mainwindow.ui" line="1613"/> + <source>Formatting</source> + <translation>Formatierung</translation> + </message> + <message> + <location filename="mainwindow.ui" line="1627"/> + <source>Color theme:</source> + <translation>Farbschema:</translation> + </message> + <message> + <location filename="mainwindow.ui" line="1643"/> + <source>Select a colour theme.</source> + <translation>Wähle ein Farbschema.</translation> + </message> + <message> + <location filename="mainwindow.ui" line="1654"/> + <source>Reformat and indent your code. +This feature is enabled tor C, C++, C# and Java code.</source> + <translation>Formatiere den Eingabecode. +Diese Funktion kann auf C, C++, C# und Java-Code angewandt werden.</translation> + </message> + <message> + <location filename="mainwindow.ui" line="1658"/> + <source>Reformat:</source> + <translation>Formatieren:</translation> + </message> + <message> + <location filename="mainwindow.ui" line="1671"/> + <source>Choose a formatting scheme.</source> + <translation>Wähle ein Formatierungs-Schema.</translation> + </message> + <message> + <location filename="mainwindow.ui" line="1675"/> + <source>Allman</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="mainwindow.ui" line="1680"/> + <source>Banner</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="mainwindow.ui" line="1685"/> + <source>GNU</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="mainwindow.ui" line="1690"/> + <source>Java</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="mainwindow.ui" line="1695"/> + <source>K&R</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="mainwindow.ui" line="1700"/> + <source>Linux</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="mainwindow.ui" line="1705"/> + <source>Stroustrup</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="mainwindow.ui" line="1710"/> + <source>Whitesmith</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="mainwindow.ui" line="1722"/> + <source>Change the keyword case.</source> + <translation>Ändere die Groß- und Kleinschreibung, wenn die Eingabesyntax nicht case-sensitive ist.</translation> + </message> + <message> + <location filename="mainwindow.ui" line="1725"/> + <source>Keyword case:</source> + <translation>Schlüsselwort Case:</translation> + </message> + <message> + <location filename="mainwindow.ui" line="1738"/> + <source>Select a keyword case.</source> + <translation>Wähle einen Typ der Groß- und Kleinschreibung.</translation> + </message> + <message> + <location filename="mainwindow.ui" line="1742"/> + <source>UPPER</source> + <translation></translation> + </message> + <message> + <location filename="mainwindow.ui" line="1747"/> + <source>lower</source> + <translation></translation> + </message> + <message> + <location filename="mainwindow.ui" line="1752"/> + <source>Capitalize</source> + <translation></translation> + </message> + <message> + <location filename="mainwindow.ui" line="1770"/> + <source>Tab width:</source> + <translation>Tabulatorbreite:</translation> + </message> + <message> + <location filename="mainwindow.ui" line="1780"/> + <source>Enter the number of spaces which replace a tab. +Set the width to 0 to keep tabs.</source> + <translation>Gib die Anzahl der Leerzeichen an, die ein Tab ersetzen. +Setze die Anzahl auf Null, um Tabs auszugeben.</translation> + </message> + <message> + <location filename="mainwindow.ui" line="1795"/> + <source>Enable line wrapping.</source> + <translation>Aktiviere den automatischen Zeilenumbruch.</translation> + </message> + <message> + <location filename="mainwindow.ui" line="1798"/> + <source>Line wrapping</source> + <translation>Zeilenumbruch</translation> + </message> + <message> + <location filename="mainwindow.ui" line="1805"/> + <source>Enter the maximum line length.</source> + <translation>Gib die maximale Zeilenlänge ein.</translation> + </message> + <message> + <location filename="mainwindow.ui" line="1824"/> + <source>Indent statements and function parameters after wrapping.</source> + <translation>Rücke Kommandos und Funktionsparameter nach dem Umbruch ein.</translation> + </message> + <message> + <location filename="mainwindow.ui" line="1827"/> + <source>Intelligent wrapping</source> + <translation>Intelligenter Umbruch</translation> + </message> + <message> + <location filename="mainwindow.ui" line="1861"/> + <source>Font name:</source> + <translation>Schriftart:</translation> + </message> + <message> + <location filename="mainwindow.ui" line="1871"/> + <source>Select or enter the font name.</source> + <translation>Wähle oder gib die Schriftart an.</translation> + </message> + <message> + <location filename="mainwindow.ui" line="1878"/> + <source>Font size:</source> + <translation>Schriftgröße:</translation> + </message> + <message> + <location filename="mainwindow.ui" line="1894"/> + <source>Enter the font size.</source> + <translation>Gib die Schriftgröße ein.</translation> + </message> + <message> + <location filename="mainwindow.ui" line="1918"/> + <source>Preview</source> + <translation>Vorschau</translation> + </message> + <message> + <location filename="mainwindow.ui" line="226"/> + <source>Start the conversion of your input files.</source> + <translation>Starte die Konvertierung der Eingabedateien.</translation> + </message> + <message> + <location filename="mainwindow.ui" line="229"/> + <source>Convert files</source> + <translation>Konvertieren</translation> + </message> + <message> + <location filename="mainwindow.ui" line="239"/> + <source>Copy highlighted code of the seleted file into the clipboard.</source> + <translation>Kopiere den Inhalt der ausgewählten Datei mit Highlighting in die Zwischenablage.</translation> + </message> + <message> + <location filename="mainwindow.ui" line="250"/> + <source>Clipboard</source> + <translation>Zwischenablage</translation> + </message> + <message> + <location filename="mainwindow.ui" line="242"/> + <source>Copy file to clipboard</source> + <translation>Datei in Zwischenablage</translation> + </message> + <message> + <location filename="mainwindow.ui" line="1943"/> + <source>Output progress:</source> + <translation>Ausgabefortschritt:</translation> + </message> + <message> + <location filename="mainwindow.ui" line="1971"/> + <source>&File</source> + <translation>&Datei</translation> + </message> + <message> + <location filename="mainwindow.ui" line="1979"/> + <source>&Help</source> + <translation>&Hilfe</translation> + </message> + <message> + <location filename="mainwindow.ui" line="1996"/> + <source>&Open files</source> + <translation>Öffne &Dateien</translation> + </message> + <message> + <location filename="mainwindow.ui" line="2001"/> + <source>&Exit</source> + <translation>&Beenden</translation> + </message> + <message> + <location filename="mainwindow.ui" line="2006"/> + <source>&Load</source> + <translation></translation> + </message> + <message> + <location filename="mainwindow.ui" line="2011"/> + <source>&Save</source> + <translation></translation> + </message> + <message> + <location filename="mainwindow.ui" line="2016"/> + <source>Load &default project</source> + <translation></translation> + </message> + <message> + <location filename="mainwindow.ui" line="2021"/> + <source>Readme</source> + <translation>Handbuch</translation> + </message> + <message> + <location filename="mainwindow.ui" line="2026"/> + <source>&Tips</source> + <translation></translation> + </message> + <message> + <location filename="mainwindow.ui" line="2034"/> + <source>&Changelog</source> + <translation></translation> + </message> + <message> + <location filename="mainwindow.ui" line="2039"/> + <source>&License</source> + <translation>&Lizenz</translation> + </message> + <message> + <location filename="mainwindow.ui" line="2044"/> + <source>&About Highlight</source> + <translation>&Ãœber Highlight</translation> + </message> + <message> + <location filename="mainwindow.ui" line="2049"/> + <source>About &translations</source> + <translation>&Infos zu Ãœbersetzungen</translation> + </message> +</context> +<context> + <name>ShowTextFile</name> + <message> + <location filename="showtextfile.ui" line="17"/> + <source>Show text</source> + <translation>Textanzeige</translation> + </message> + <message> + <location filename="showtextfile.ui" line="37"/> + <source>TextLabel</source> + <translation></translation> + </message> + <message> + <location filename="showtextfile.ui" line="69"/> + <source>OK</source> + <translation>OK</translation> + </message> +</context> +<context> + <name>io_report</name> + <message> + <location filename="io_report.ui" line="14"/> + <source>Error summary</source> + <translation>Fehlerübersicht</translation> + </message> + <message> + <location filename="io_report.ui" line="24"/> + <source>Input errors:</source> + <translation>Eingabefehler:</translation> + </message> + <message> + <location filename="io_report.ui" line="34"/> + <source>Remove files above from input file list</source> + <translation>Obige Dateien aus der Eingabeliste löschen</translation> + </message> + <message> + <location filename="io_report.ui" line="48"/> + <source>Output errors:</source> + <translation>Ausgabefehler:</translation> + </message> + <message> + <location filename="io_report.ui" line="65"/> + <source>Reformatting not possible:</source> + <translation>Neuformatierung nicht möglich:</translation> + </message> +</context> +</TS> diff --git a/support/highlight/src/gui-qt/highlight_es_ES.ts b/support/highlight/src/gui-qt/highlight_es_ES.ts new file mode 100644 index 0000000000..6349f0590a --- /dev/null +++ b/support/highlight/src/gui-qt/highlight_es_ES.ts @@ -0,0 +1,1156 @@ +<?xml version="1.0" encoding="utf-8"?> +<!DOCTYPE TS> +<TS version="2.0" language="es_MX"> +<context> + <name>MainWindow</name> + <message> + <source>Themes or indent schemes not found. +Check installation.</source> + <translation type="obsolete">Temas o esquemas de indentación no encontrados +Revise su instalación.</translation> + </message> + <message> + <location filename="mainwindow.cpp" line="82"/> + <source>Initialization error</source> + <translation>Error de inicialización</translation> + </message> + <message> + <location filename="mainwindow.cpp" line="83"/> + <source>Could not find syntax definitions. Check installation.</source> + <translation>Definiciones de sintaxis no encontradas. +Revise su instalacion.</translation> + </message> + <message> + <location filename="mainwindow.cpp" line="610"/> + <source>Tags file error</source> + <translation>Error de archivo de etiquetas</translation> + </message> + <message> + <location filename="mainwindow.cpp" line="611"/> + <source>Could not read tags information in "%1"</source> + <translation>No se pudieron leer las etiquetas de "%1"</translation> + </message> + <message> + <location filename="mainwindow.cpp" line="628"/> + <location filename="mainwindow.cpp" line="659"/> + <source>Output error</source> + <translation>Error de salida</translation> + </message> + <message> + <location filename="mainwindow.cpp" line="628"/> + <source>Output directory does not exist!</source> + <translation>¡Directorio de salida no existe!</translation> + </message> + <message> + <location filename="mainwindow.cpp" line="659"/> + <source>You must define a style output file!</source> + <translation>¡Debe especificar un archivo de estilo de salida!</translation> + </message> + <message> + <location filename="mainwindow.cpp" line="694"/> + <source>Language definition error</source> + <translation>Error de definición de lenguaje</translation> + </message> + <message> + <location filename="mainwindow.cpp" line="695"/> + <source>Invalid regular expression in %1: +%2</source> + <translation>Expresión regular inválida en %1: +%2</translation> + </message> + <message> + <location filename="mainwindow.cpp" line="699"/> + <source>Unknown syntax</source> + <translation>Sintaxis desconocida</translation> + </message> + <message> + <location filename="mainwindow.cpp" line="699"/> + <source>Could not convert %1</source> + <translation>No se pudo convertir %1</translation> + </message> + <message> + <location filename="mainwindow.cpp" line="759"/> + <source>Converted %1 files in %2 ms</source> + <translation>Se convirtieron%1 archivos en %2 ms</translation> + </message> + <message> + <location filename="mainwindow.cpp" line="851"/> + <source>Conversion of "%1" not possible.</source> + <translation>No es posible la conversión de "%1".</translation> + </message> + <message> + <location filename="mainwindow.cpp" line="851"/> + <location filename="mainwindow.cpp" line="951"/> + <location filename="mainwindow.cpp" line="962"/> + <source>clipboard data</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="mainwindow.cpp" line="950"/> + <source>Preview (%1):</source> + <translation>Previsualización (%1):</translation> + </message> + <message> + <location filename="mainwindow.cpp" line="953"/> + <source>Current syntax: %1</source> + <translation>Sintaxis actual: %1</translation> + </message> + <message> + <location filename="mainwindow.cpp" line="962"/> + <source>Preview of "%1" not possible.</source> + <translation>No es posible previsualizar "%1".</translation> + </message> + <message> + <location filename="mainwindow.cpp" line="973"/> + <source>Choose a ctags file</source> + <translation>Elija un archivo de ctags</translation> + </message> + <message> + <location filename="mainwindow.cpp" line="999"/> + <location filename="mainwindow.cpp" line="1003"/> + <location filename="mainwindow.cpp" line="1007"/> + <location filename="mainwindow.cpp" line="1012"/> + <source>Choose a style include file</source> + <translation>Elija un archivo de inclusión de estilo</translation> + </message> + <message> + <location filename="mainwindow.cpp" line="1018"/> + <source>About providing translations</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="mainwindow.cpp" line="1019"/> + <source>The GUI was developed using the Qt toolkit, and translations may be provided using the tools Qt Linguist and lrelease. +The highlight.ts file for Linguist resides in the src/gui-qt subdirectory. +The qm file generated by lrelease has to be saved in gui-files/l10n. + +Please send a note to as (at) andre-simon (dot) de if you have issues during translating or if you have finished or updated a translation.</source> + <translation type="unfinished"></translation> + </message> +</context> +<context> + <name>MainWindowClass</name> + <message> + <location filename="mainwindow.ui" line="55"/> + <source>Choose the source code files you want to convert.</source> + <translation>Elijir los archivos fuente que desea convertir.</translation> + </message> + <message> + <location filename="mainwindow.ui" line="61"/> + <source>Choose input files</source> + <translation>Elijir archivos de entrada</translation> + </message> + <message> + <location filename="mainwindow.ui" line="83"/> + <source>List of input files.</source> + <translation>Lista de archivos de entrada.</translation> + </message> + <message> + <location filename="mainwindow.ui" line="104"/> + <source>Remove the selected input files.</source> + <translation>Remover los archivos de entrada seleccionados.</translation> + </message> + <message> + <location filename="mainwindow.ui" line="107"/> + <source>Clear selection</source> + <translation>Remover seleccionados</translation> + </message> + <message> + <location filename="mainwindow.ui" line="114"/> + <source>Remove all input files.</source> + <translation>Remover todos los archivos de entrada.</translation> + </message> + <message> + <location filename="mainwindow.ui" line="117"/> + <source>Clear all</source> + <translation>Remover todos</translation> + </message> + <message> + <source>Output destination</source> + <translation type="obsolete">Destino de salida</translation> + </message> + <message> + <location filename="mainwindow.ui" line="156"/> + <source>Output directory</source> + <translation>Directorio de salida</translation> + </message> + <message> + <location filename="mainwindow.ui" line="175"/> + <source>Select the output directory.</source> + <translation>Elijir el directorio de salida.</translation> + </message> + <message> + <location filename="mainwindow.ui" line="178"/> + <location filename="mainwindow.ui" line="808"/> + <location filename="mainwindow.ui" line="919"/> + <location filename="mainwindow.ui" line="1158"/> + <location filename="mainwindow.ui" line="1280"/> + <location filename="mainwindow.ui" line="1562"/> + <source>...</source> + <translation>...</translation> + </message> + <message> + <location filename="mainwindow.ui" line="187"/> + <source>Save output in the input file directories.</source> + <translation>Guardar salida en los directorios de entrada de cada archivo.</translation> + </message> + <message> + <location filename="mainwindow.ui" line="190"/> + <source>Write to source directories</source> + <translation>Guardar a los directorios de origen</translation> + </message> + <message> + <source>Output options</source> + <translation type="obsolete">Opciones de salida</translation> + </message> + <message> + <location filename="mainwindow.ui" line="356"/> + <source>General</source> + <translation>General</translation> + </message> + <message> + <location filename="mainwindow.ui" line="376"/> + <source>Output format:</source> + <translation>Formato de salida:</translation> + </message> + <message> + <location filename="mainwindow.ui" line="398"/> + <source>Choose an output format.</source> + <translation>Elija un formato de salida.</translation> + </message> + <message> + <location filename="mainwindow.ui" line="402"/> + <source>HTML</source> + <translation></translation> + </message> + <message> + <location filename="mainwindow.ui" line="407"/> + <source>XHTML</source> + <translation></translation> + </message> + <message> + <location filename="mainwindow.ui" line="412"/> + <source>LaTeX</source> + <translation></translation> + </message> + <message> + <location filename="mainwindow.ui" line="417"/> + <source>TeX</source> + <translation></translation> + </message> + <message> + <location filename="mainwindow.ui" line="422"/> + <source>RTF</source> + <translation></translation> + </message> + <message> + <location filename="mainwindow.ui" line="427"/> + <source>SVG</source> + <translation></translation> + </message> + <message> + <location filename="mainwindow.ui" line="432"/> + <source>XML</source> + <translation></translation> + </message> + <message> + <location filename="mainwindow.ui" line="456"/> + <source>Add line numbers to the output.</source> + <translation>Agregar números de linea a la salida.</translation> + </message> + <message> + <location filename="mainwindow.ui" line="459"/> + <source>Add line numbers</source> + <translation>Agregar números de linea</translation> + </message> + <message> + <location filename="mainwindow.ui" line="479"/> + <source>Select the line number width.</source> + <translation>Seleccione el ancho de número de linea.</translation> + </message> + <message> + <location filename="mainwindow.ui" line="500"/> + <source>Fill leading space of line numbers with zeroes.</source> + <translation>Llenar espacio antes de los números de lineas con ceros.</translation> + </message> + <message> + <location filename="mainwindow.ui" line="503"/> + <source>Pad with zeroes</source> + <translation>Rellenar con ceros</translation> + </message> + <message> + <location filename="mainwindow.ui" line="516"/> + <source>Generate output without document header and footer.</source> + <translation>Generar documento de salida con cabecera y pie de página.</translation> + </message> + <message> + <location filename="mainwindow.ui" line="519"/> + <source>Omit header and footer</source> + <translation>Omitir cabecera y pie de página</translation> + </message> + <message> + <location filename="mainwindow.ui" line="526"/> + <source>Test if input data is not binary. +Removes Unicode BOM mark.</source> + <translation>Probar si los datos de entrada no son binarios. +Remueve marca BOM de Unicode.</translation> + </message> + <message> + <location filename="mainwindow.ui" line="530"/> + <source>Validate input data</source> + <translation>Validar datos de entrada</translation> + </message> + <message> + <location filename="mainwindow.ui" line="539"/> + <source>Set the output file ancoding.</source> + <translation>Ajuste la codificación del archivo de salida.</translation> + </message> + <message> + <source>Encoding:</source> + <translation type="obsolete">Codificación:</translation> + </message> + <message> + <location filename="mainwindow.ui" line="549"/> + <source>Select or define the encoding. +The result has to match the input file encoding.</source> + <translation>Elija o defina la codificación. +El resultado tiene que corresponder a la codificación del archivo de entrada.</translation> + </message> + <message> + <location filename="mainwindow.ui" line="560"/> + <source>ISO-8859-1</source> + <translation></translation> + </message> + <message> + <location filename="mainwindow.ui" line="565"/> + <source>ISO-8859-2</source> + <translation></translation> + </message> + <message> + <location filename="mainwindow.ui" line="570"/> + <source>ISO-8859-3</source> + <translation></translation> + </message> + <message> + <location filename="mainwindow.ui" line="575"/> + <source>ISO-8859-4</source> + <translation></translation> + </message> + <message> + <location filename="mainwindow.ui" line="580"/> + <source>ISO-8859-5</source> + <translation></translation> + </message> + <message> + <location filename="mainwindow.ui" line="585"/> + <source>ISO-8859-6</source> + <translation></translation> + </message> + <message> + <location filename="mainwindow.ui" line="590"/> + <source>ISO-8859-7</source> + <translation></translation> + </message> + <message> + <location filename="mainwindow.ui" line="595"/> + <source>ISO-8859-8</source> + <translation></translation> + </message> + <message> + <location filename="mainwindow.ui" line="600"/> + <source>ISO-8859-9</source> + <translation></translation> + </message> + <message> + <location filename="mainwindow.ui" line="605"/> + <source>ISO-8859-10</source> + <translation></translation> + </message> + <message> + <location filename="mainwindow.ui" line="610"/> + <source>ISO-8859-11</source> + <translation></translation> + </message> + <message> + <location filename="mainwindow.ui" line="615"/> + <source>ISO-8859-12</source> + <translation></translation> + </message> + <message> + <location filename="mainwindow.ui" line="620"/> + <source>ISO-8859-13</source> + <translation></translation> + </message> + <message> + <location filename="mainwindow.ui" line="625"/> + <source>ISO-8859-14</source> + <translation></translation> + </message> + <message> + <location filename="mainwindow.ui" line="630"/> + <source>ISO-8859-15</source> + <translation></translation> + </message> + <message> + <location filename="mainwindow.ui" line="635"/> + <source>UTF-8</source> + <translation></translation> + </message> + <message> + <location filename="mainwindow.ui" line="659"/> + <source>Output specific</source> + <translation>Esoecificas de salida</translation> + </message> + <message> + <location filename="mainwindow.ui" line="696"/> + <source>HTML options</source> + <translation>Opciones de HTML</translation> + </message> + <message> + <source>Style</source> + <translation type="obsolete">Hoja de estilo</translation> + </message> + <message> + <location filename="mainwindow.ui" line="734"/> + <location filename="mainwindow.ui" line="1088"/> + <location filename="mainwindow.ui" line="1210"/> + <location filename="mainwindow.ui" line="1492"/> + <source>Include the style information in each output file.</source> + <translation>Incluir la información de estilo en cada archivo de salida.</translation> + </message> + <message> + <location filename="mainwindow.ui" line="737"/> + <location filename="mainwindow.ui" line="1495"/> + <source>Embed style (CSS)</source> + <translation>Incrustar estilo (CSS)</translation> + </message> + <message> + <location filename="mainwindow.ui" line="747"/> + <source>Add CSS information to each tag (do not use CSS class definitions).</source> + <translation>Agregar información de CSS a cada etiqueta (no utilizar definiciones de clase de CSS).</translation> + </message> + <message> + <location filename="mainwindow.ui" line="750"/> + <source>Inline CSS</source> + <translation></translation> + </message> + <message> + <source>Style file:</source> + <translation type="obsolete">Archivo de estilo:</translation> + </message> + <message> + <location filename="mainwindow.ui" line="777"/> + <location filename="mainwindow.ui" line="1232"/> + <location filename="mainwindow.ui" line="1514"/> + <source>Name of the referenced style file.</source> + <translation>Nombre del archivo de estilo citado.</translation> + </message> + <message> + <location filename="mainwindow.ui" line="780"/> + <location filename="mainwindow.ui" line="1517"/> + <source>highlight.css</source> + <translation></translation> + </message> + <message> + <source>Style include file:</source> + <translation type="obsolete">Archivo de estilo a incluir:</translation> + </message> + <message> + <location filename="mainwindow.ui" line="798"/> + <location filename="mainwindow.ui" line="1552"/> + <source>Path of the CSS include file.</source> + <translation>Ruta del archivo CSS a incluir.</translation> + </message> + <message> + <location filename="mainwindow.ui" line="805"/> + <source>Select a CSS include file.</source> + <translation>Seleccionar un archivo CSS a incluir.</translation> + </message> + <message> + <location filename="mainwindow.ui" line="819"/> + <source>CSS class prefix:</source> + <translation>Prefijo de clase de CSS:</translation> + </message> + <message> + <location filename="mainwindow.ui" line="826"/> + <source>Add a CSS class name prefix to avoid namespace clashes.</source> + <translation>Agregue un prefijo de nombre de clase de CSS para evitar conflictos.</translation> + </message> + <message> + <source>Tags and index files</source> + <translation type="obsolete">Archivos de etiquetas e Ãndice</translation> + </message> + <message> + <location filename="mainwindow.ui" line="861"/> + <source>Generate an index file with hyperlinks to all outputted files.</source> + <translation>Generar un archivo de indice con enlaces a todos los archivos de salida.</translation> + </message> + <message> + <location filename="mainwindow.ui" line="864"/> + <source>Generate index file</source> + <translation>Generar archivo de Ãndice</translation> + </message> + <message> + <location filename="mainwindow.ui" line="884"/> + <source>Read a ctags file and add the included metainformation as tooltips. +See ctags.sf.net for details.</source> + <translation>Leer un archivo de ctags y agregar la metainformación incluida como aviso emergente. +Vea ctags.sf.net para más detalles.</translation> + </message> + <message> + <source>Ctags file:</source> + <translation type="obsolete">Archivo de ctags:</translation> + </message> + <message> + <location filename="mainwindow.ui" line="903"/> + <source>Path of the ctags file.</source> + <translation>Ruta del archivo de ctags.</translation> + </message> + <message> + <location filename="mainwindow.ui" line="916"/> + <source>Choose a ctags file.</source> + <translation>Elijir un archivo de ctags.</translation> + </message> + <message> + <location filename="mainwindow.ui" line="945"/> + <source>Misc</source> + <translation>Miscelaneo</translation> + </message> + <message> + <location filename="mainwindow.ui" line="964"/> + <source>Add an achor to each line.</source> + <translation>Agregar una ancla a cada linea.</translation> + </message> + <message> + <location filename="mainwindow.ui" line="967"/> + <source>Add line anchors</source> + <translation>Agregar ancla por linea</translation> + </message> + <message> + <location filename="mainwindow.ui" line="974"/> + <source>Add the filename as prefix to the anchors.</source> + <translation>Agregar el nombre de archivo como prefijo a las anclas.</translation> + </message> + <message> + <location filename="mainwindow.ui" line="977"/> + <source>Include file name in anchor</source> + <translation>Incluir el nombre de archivo en el ancla</translation> + </message> + <message> + <location filename="mainwindow.ui" line="984"/> + <source>Output the lines within an ordered list.</source> + <translation>Producir las lineas de salida dentro de una lista ordenada.</translation> + </message> + <message> + <source>Ordered list</source> + <translation type="obsolete">Lista ordenada</translation> + </message> + <message> + <location filename="mainwindow.ui" line="1001"/> + <source>Add &lt;pre&gt; tags to the output, if the flag "No document header and footer" is selected.</source> + <translation>Agregar etiquetas &lt;pre&gt; a la salida, si la opción "Sin cabecera ni pie de página" está seleccionada.</translation> + </message> + <message> + <source>Enclose in <pre></source> + <translation type="obsolete">Meter entre &lt;pre&gt;</translation> + </message> + <message> + <location filename="mainwindow.ui" line="1044"/> + <source>LaTeX options</source> + <translation>Opciones de LaTeX</translation> + </message> + <message> + <location filename="mainwindow.ui" line="1058"/> + <source>Replace quotes by dq sequences.</source> + <translation>Reemplazar comillas por sucesiones de dobles comillas.</translation> + </message> + <message> + <location filename="mainwindow.ui" line="1061"/> + <source>Escape quotes</source> + <translation>Sobrepasar comillas</translation> + </message> + <message> + <location filename="mainwindow.ui" line="1068"/> + <source>Make output Babel compatible.</source> + <translation>Hacer que la salida se compatible con Babel.</translation> + </message> + <message> + <source>Babel compatibility</source> + <translation type="obsolete">Compatibilidad con Babel</translation> + </message> + <message> + <location filename="mainwindow.ui" line="1078"/> + <source>Replace default symbols (brackets, tilde) by nice redefinitions.</source> + <translation>Reemplazar sÃmbolos por defecto (llaves, corchetes, tildes) por redefiniciones apropiadas.</translation> + </message> + <message> + <source>Pretty symbols</source> + <translation type="obsolete">SÃmbolos lindos</translation> + </message> + <message> + <location filename="mainwindow.ui" line="1091"/> + <source>Embed style (defs)</source> + <translation>Incrustar estilo</translation> + </message> + <message> + <location filename="mainwindow.ui" line="1110"/> + <source>Name of the referenced style file.</source> + <translation>Nombre del archivo de estilo citado.</translation> + </message> + <message> + <location filename="mainwindow.ui" line="1113"/> + <location filename="mainwindow.ui" line="1235"/> + <source>highlight.sty</source> + <translation></translation> + </message> + <message> + <source>Style include:</source> + <translation type="obsolete">Incluir estilo:</translation> + </message> + <message> + <location filename="mainwindow.ui" line="542"/> + <source>Set encoding:</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="mainwindow.ui" line="141"/> + <source>Output destination:</source> + <translation>Destino de salida</translation> + </message> + <message> + <location filename="mainwindow.ui" line="764"/> + <location filename="mainwindow.ui" line="1100"/> + <location filename="mainwindow.ui" line="1222"/> + <location filename="mainwindow.ui" line="1504"/> + <source>Stylesheet file:</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="mainwindow.ui" line="1124"/> + <location filename="mainwindow.ui" line="1246"/> + <location filename="mainwindow.ui" line="1528"/> + <source>Stylesheet include file:</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="mainwindow.ui" line="888"/> + <source>Read ctags file:</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="mainwindow.ui" line="20"/> + <source>Highlight</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="mainwindow.ui" line="49"/> + <source>Files</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="mainwindow.ui" line="256"/> + <source>Paste clipboard content into the preview window.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="mainwindow.ui" line="259"/> + <source>Paste from clipboard</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="mainwindow.ui" line="297"/> + <source>Copy highlighted code into the clipboard.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="mainwindow.ui" line="300"/> + <source>Copy preview to clipboard</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="mainwindow.ui" line="268"/> + <source>Select syntax:</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="mainwindow.ui" line="275"/> + <source>Select the correct syntax of the code snippet.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="mainwindow.ui" line="437"/> + <source>BBCode</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="mainwindow.ui" line="726"/> + <source>Stylesheets</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="mainwindow.ui" line="791"/> + <source>Include:</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="mainwindow.ui" line="855"/> + <source>Index/ctags</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="mainwindow.ui" line="957"/> + <source>Line numbering options:</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="mainwindow.ui" line="987"/> + <source>Output as ordered list</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="mainwindow.ui" line="1004"/> + <source>Enclose in pre tags</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="mainwindow.ui" line="1071"/> + <source>Add Babel compatibility</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="mainwindow.ui" line="1081"/> + <source>Add pretty symbols</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="mainwindow.ui" line="1148"/> + <location filename="mainwindow.ui" line="1270"/> + <source>Path of the style include file.</source> + <translation>Ruta del archivo de estilo a incluir.</translation> + </message> + <message> + <location filename="mainwindow.ui" line="1155"/> + <location filename="mainwindow.ui" line="1277"/> + <location filename="mainwindow.ui" line="1559"/> + <source>Select a style include file.</source> + <translation>Seleccione un archivo de estilo a incluir.</translation> + </message> + <message> + <location filename="mainwindow.ui" line="1196"/> + <source>TeX options</source> + <translation>Opciones de TeX</translation> + </message> + <message> + <location filename="mainwindow.ui" line="1213"/> + <source>Embed style (macros)</source> + <translation>Estilo de incrustación (macros)</translation> + </message> + <message> + <location filename="mainwindow.ui" line="1318"/> + <source>RTF options</source> + <translation>Opciones de RTF</translation> + </message> + <message> + <location filename="mainwindow.ui" line="1332"/> + <source>Add character stylesheets with formatting information. +You can select the stylesheets in your word processor to reformat additional text.</source> + <translation>Agregar hojas de estilo de caracteres con informacion de formato. +Puede selecionar la hoja de estilo en su procesador de textos para dar formato nuevamente a texto adicional.</translation> + </message> + <message> + <location filename="mainwindow.ui" line="1336"/> + <source>Add character styles</source> + <translation>Agregar estilos de caracteres</translation> + </message> + <message> + <location filename="mainwindow.ui" line="1345"/> + <source>Page size:</source> + <translation>Tamaño de paǵina:</translation> + </message> + <message> + <location filename="mainwindow.ui" line="1352"/> + <source>Select a page size.</source> + <translation>Seleccionar un tamaño de página.</translation> + </message> + <message> + <location filename="mainwindow.ui" line="1359"/> + <source>A3</source> + <translation></translation> + </message> + <message> + <location filename="mainwindow.ui" line="1364"/> + <source>A4</source> + <translation></translation> + </message> + <message> + <location filename="mainwindow.ui" line="1369"/> + <source>A5</source> + <translation></translation> + </message> + <message> + <location filename="mainwindow.ui" line="1374"/> + <source>B4</source> + <translation></translation> + </message> + <message> + <location filename="mainwindow.ui" line="1379"/> + <source>B5</source> + <translation></translation> + </message> + <message> + <location filename="mainwindow.ui" line="1384"/> + <source>B6</source> + <translation></translation> + </message> + <message> + <location filename="mainwindow.ui" line="1389"/> + <source>Letter</source> + <translation>Carta</translation> + </message> + <message> + <location filename="mainwindow.ui" line="1394"/> + <source>Legal</source> + <translation>Oficio</translation> + </message> + <message> + <location filename="mainwindow.ui" line="1433"/> + <source>SVG options</source> + <translation>Opciones de SVG</translation> + </message> + <message> + <location filename="mainwindow.ui" line="1447"/> + <source>Image size:</source> + <translation>Tamaño de la imagen:</translation> + </message> + <message> + <location filename="mainwindow.ui" line="1456"/> + <source>Width:</source> + <translation>Ancho:</translation> + </message> + <message> + <location filename="mainwindow.ui" line="1466"/> + <source>Enter the SVG width (may contain units).</source> + <translation>Introducir el ancho de SVG (puede incluir unidades).</translation> + </message> + <message> + <location filename="mainwindow.ui" line="1473"/> + <source>Height:</source> + <translation>Alto:</translation> + </message> + <message> + <location filename="mainwindow.ui" line="1483"/> + <source>Enter the SVG height (may contain units).</source> + <translation>Introducir el alto de SVG (puede incluir unidades).</translation> + </message> + <message> + <location filename="mainwindow.ui" line="1588"/> + <source>No options defined.</source> + <translation>No hay opciones definidas.</translation> + </message> + <message> + <location filename="mainwindow.ui" line="1613"/> + <source>Formatting</source> + <translation>Formato</translation> + </message> + <message> + <location filename="mainwindow.ui" line="1627"/> + <source>Color theme:</source> + <translation>Tema de color:</translation> + </message> + <message> + <location filename="mainwindow.ui" line="1643"/> + <source>Select a colour theme.</source> + <translation>Seleccionar un tema de color.</translation> + </message> + <message> + <location filename="mainwindow.ui" line="1654"/> + <source>Reformat and indent your code. +This feature is enabled tor C, C++, C# and Java code.</source> + <translation>Dar formato nuevamente e indentar su código. +Esta propiedad esta habilitada para código en C, C++, C# y Java.</translation> + </message> + <message> + <location filename="mainwindow.ui" line="1658"/> + <source>Reformat:</source> + <translation>Dar formato nuevamente:</translation> + </message> + <message> + <location filename="mainwindow.ui" line="1671"/> + <source>Choose a formatting scheme.</source> + <translation>Elija un esquema de formato.</translation> + </message> + <message> + <location filename="mainwindow.ui" line="1675"/> + <source>Allman</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="mainwindow.ui" line="1680"/> + <source>Banner</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="mainwindow.ui" line="1685"/> + <source>GNU</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="mainwindow.ui" line="1690"/> + <source>Java</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="mainwindow.ui" line="1695"/> + <source>K&R</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="mainwindow.ui" line="1700"/> + <source>Linux</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="mainwindow.ui" line="1705"/> + <source>Stroustrup</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="mainwindow.ui" line="1710"/> + <source>Whitesmith</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="mainwindow.ui" line="1722"/> + <source>Change the keyword case.</source> + <translation>Cambiar mayúsculas/minúsculas en palabras reservadas.</translation> + </message> + <message> + <location filename="mainwindow.ui" line="1725"/> + <source>Keyword case:</source> + <translation>Mayúsculas/minúsculas de palabras reservadas:</translation> + </message> + <message> + <location filename="mainwindow.ui" line="1738"/> + <source>Select a keyword case.</source> + <translation>Seleccione un estilo de mayúsculas/minúsculas.</translation> + </message> + <message> + <location filename="mainwindow.ui" line="1742"/> + <source>UPPER</source> + <translation>MAYÚSCULAS</translation> + </message> + <message> + <location filename="mainwindow.ui" line="1747"/> + <source>lower</source> + <translation>minúsculas</translation> + </message> + <message> + <location filename="mainwindow.ui" line="1752"/> + <source>Capitalize</source> + <translation>Primera Letra Mayúscula</translation> + </message> + <message> + <location filename="mainwindow.ui" line="1770"/> + <source>Tab width:</source> + <translation>Ancho de tabulador:</translation> + </message> + <message> + <location filename="mainwindow.ui" line="1780"/> + <source>Enter the number of spaces which replace a tab. +Set the width to 0 to keep tabs.</source> + <translation>Introducir el número de espacios que reemplazaran un tabulador. +En caso de ser 0 se mantendrán los tabuladores.</translation> + </message> + <message> + <location filename="mainwindow.ui" line="1795"/> + <source>Enable line wrapping.</source> + <translation>Habilitar romper lineas.</translation> + </message> + <message> + <location filename="mainwindow.ui" line="1798"/> + <source>Line wrapping</source> + <translation>Romper lineas</translation> + </message> + <message> + <location filename="mainwindow.ui" line="1805"/> + <source>Enter the maximum line length.</source> + <translation>Introducir longitud máxima de linea.</translation> + </message> + <message> + <location filename="mainwindow.ui" line="1824"/> + <source>Indent statements and function parameters after wrapping.</source> + <translation>Indentar instrucciones y parámetros de funciones después de romper la linea.</translation> + </message> + <message> + <location filename="mainwindow.ui" line="1827"/> + <source>Intelligent wrapping</source> + <translation>Rompido inteligente</translation> + </message> + <message> + <location filename="mainwindow.ui" line="1861"/> + <source>Font name:</source> + <translation>Nombre de la fuente:</translation> + </message> + <message> + <location filename="mainwindow.ui" line="1871"/> + <source>Select or enter the font name.</source> + <translation>Seleccionar o introduzcir el nombre de la fuente.</translation> + </message> + <message> + <location filename="mainwindow.ui" line="1878"/> + <source>Font size:</source> + <translation>Tamaño de la fuente:</translation> + </message> + <message> + <location filename="mainwindow.ui" line="1894"/> + <source>Enter the font size.</source> + <translation>Introducir el tamaño de la fuente.</translation> + </message> + <message> + <location filename="mainwindow.ui" line="1918"/> + <source>Preview</source> + <translation>Previsualización</translation> + </message> + <message> + <location filename="mainwindow.ui" line="226"/> + <source>Start the conversion of your input files.</source> + <translation>Comenzar la conversión de los archivos de entrada.</translation> + </message> + <message> + <location filename="mainwindow.ui" line="229"/> + <source>Convert files</source> + <translation>Convertir archivos</translation> + </message> + <message> + <location filename="mainwindow.ui" line="239"/> + <source>Copy highlighted code of the seleted file into the clipboard.</source> + <translation>Copiar codigo resaltado del archivo seleccionado al portapapeles.</translation> + </message> + <message> + <location filename="mainwindow.ui" line="250"/> + <source>Clipboard</source> + <translation>Portapapeles</translation> + </message> + <message> + <location filename="mainwindow.ui" line="242"/> + <source>Copy file to clipboard</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="mainwindow.ui" line="1943"/> + <source>Output progress:</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="mainwindow.ui" line="1971"/> + <source>&File</source> + <translation>&Archivo</translation> + </message> + <message> + <location filename="mainwindow.ui" line="1979"/> + <source>&Help</source> + <translation>Ay&uda</translation> + </message> + <message> + <location filename="mainwindow.ui" line="1996"/> + <source>&Open files</source> + <translation>Ab&rir archivos</translation> + </message> + <message> + <location filename="mainwindow.ui" line="2001"/> + <source>&Exit</source> + <translation>&Salir</translation> + </message> + <message> + <location filename="mainwindow.ui" line="2006"/> + <source>&Load</source> + <translation>&Cargar</translation> + </message> + <message> + <location filename="mainwindow.ui" line="2011"/> + <source>&Save</source> + <translation>&Guardar</translation> + </message> + <message> + <location filename="mainwindow.ui" line="2016"/> + <source>Load &default project</source> + <translation>Cargar proyecto por &defecto</translation> + </message> + <message> + <location filename="mainwindow.ui" line="2021"/> + <source>Readme</source> + <translation>Leeme</translation> + </message> + <message> + <location filename="mainwindow.ui" line="2026"/> + <source>&Tips</source> + <translation>A&visos</translation> + </message> + <message> + <location filename="mainwindow.ui" line="2034"/> + <source>&Changelog</source> + <translation>&Bitácora de cambios</translation> + </message> + <message> + <location filename="mainwindow.ui" line="2039"/> + <source>&License</source> + <translation>&Licencia</translation> + </message> + <message> + <location filename="mainwindow.ui" line="2044"/> + <source>&About Highlight</source> + <translation>&Acerca de Highlight</translation> + </message> + <message> + <location filename="mainwindow.ui" line="2049"/> + <source>About &translations</source> + <translation type="unfinished"></translation> + </message> +</context> +<context> + <name>ShowTextFile</name> + <message> + <location filename="showtextfile.ui" line="17"/> + <source>Show text</source> + <translation>Mostrar texto</translation> + </message> + <message> + <location filename="showtextfile.ui" line="37"/> + <source>TextLabel</source> + <translation>EtiquetaDeTexto</translation> + </message> + <message> + <location filename="showtextfile.ui" line="69"/> + <source>OK</source> + <translation>OK</translation> + </message> +</context> +<context> + <name>io_report</name> + <message> + <location filename="io_report.ui" line="14"/> + <source>Error summary</source> + <translation>Resumen de Error</translation> + </message> + <message> + <location filename="io_report.ui" line="24"/> + <source>Input errors:</source> + <translation>Errores de entrada:</translation> + </message> + <message> + <location filename="io_report.ui" line="34"/> + <source>Remove files above from input file list</source> + <translation>Remover archivos mencionados de la lista de archivos de entrada</translation> + </message> + <message> + <location filename="io_report.ui" line="48"/> + <source>Output errors:</source> + <translation>Errores de salida:</translation> + </message> + <message> + <location filename="io_report.ui" line="65"/> + <source>Reformatting not possible:</source> + <translation>No es posible dar formato nuevamente:</translation> + </message> +</context> +</TS> diff --git a/support/highlight/src/gui-qt/hl_icon2.png b/support/highlight/src/gui-qt/hl_icon2.png Binary files differnew file mode 100644 index 0000000000..dd182616ff --- /dev/null +++ b/support/highlight/src/gui-qt/hl_icon2.png diff --git a/support/highlight/src/gui-qt/hl_icon_exe.ico b/support/highlight/src/gui-qt/hl_icon_exe.ico Binary files differnew file mode 100644 index 0000000000..9b11e75a07 --- /dev/null +++ b/support/highlight/src/gui-qt/hl_icon_exe.ico diff --git a/support/highlight/src/gui-qt/io_report.cpp b/support/highlight/src/gui-qt/io_report.cpp new file mode 100644 index 0000000000..a534cb916a --- /dev/null +++ b/support/highlight/src/gui-qt/io_report.cpp @@ -0,0 +1,68 @@ +/***************************************************************************
+ io_report.cpp
+ -------------------
+ begin : Mo 16.03.2009
+ copyright : (C) 2009 by Andre Simon
+ email : andre.simon1@gmx.de
+ ***************************************************************************/
+
+/*
+This file is part of Highlight.
+
+Highlight is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+Highlight is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Highlight. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "io_report.h"
+#include "ui_io_report.h"
+
+io_report::io_report(QWidget *parent) :
+ QDialog(parent),
+ m_ui(new Ui::io_report)
+{
+ m_ui->setupUi(this);
+}
+
+io_report::~io_report()
+{
+ delete m_ui;
+}
+
+void io_report::changeEvent(QEvent *e)
+{
+ switch (e->type()) {
+ case QEvent::LanguageChange:
+ m_ui->retranslateUi(this);
+ break;
+ default:
+ break;
+ }
+}
+
+void io_report::addInputErrors(QStringList & list){
+ m_ui->listInputErrors->clear();
+ m_ui->listInputErrors->addItems(list);
+}
+
+ void io_report::addOutputErrors(QStringList & list){
+ m_ui->listOutputErrors->clear();
+ m_ui->listOutputErrors->addItems(list);
+ }
+ void io_report::addReformatErrors(QStringList & list){
+ m_ui->listReformatErrors->clear();
+ m_ui->listReformatErrors->addItems(list);
+ }
+
+bool io_report::removeInputErrorFiles() {
+ return m_ui->cbRemoveFiles->isChecked();
+}
diff --git a/support/highlight/src/gui-qt/io_report.h b/support/highlight/src/gui-qt/io_report.h new file mode 100644 index 0000000000..369d8fc5cc --- /dev/null +++ b/support/highlight/src/gui-qt/io_report.h @@ -0,0 +1,56 @@ +/***************************************************************************
+ io_report.h
+ -------------------
+ begin : Mo 16.03.2009
+ copyright : (C) 2009 by Andre Simon
+ email : andre.simon1@gmx.de
+ ***************************************************************************/
+
+/*
+This file is part of Highlight.
+
+Highlight is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+Highlight is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Highlight. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef IO_REPORT_H
+#define IO_REPORT_H
+
+#include <QtGui/QDialog>
+
+namespace Ui {
+ class io_report;
+}
+
+class io_report : public QDialog {
+ Q_OBJECT
+ Q_DISABLE_COPY(io_report)
+public:
+ explicit io_report(QWidget *parent = 0);
+ virtual ~io_report();
+
+ void addInputErrors(QStringList & list);
+ void addOutputErrors(QStringList & list);
+ void addReformatErrors(QStringList & list);
+
+ bool removeInputErrorFiles();
+
+
+protected:
+ virtual void changeEvent(QEvent *e);
+
+private:
+ Ui::io_report *m_ui;
+};
+
+#endif // IO_REPORT_H
diff --git a/support/highlight/src/gui-qt/io_report.ui b/support/highlight/src/gui-qt/io_report.ui new file mode 100644 index 0000000000..6b4d96159c --- /dev/null +++ b/support/highlight/src/gui-qt/io_report.ui @@ -0,0 +1,121 @@ +<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>io_report</class>
+ <widget class="QDialog" name="io_report">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>436</width>
+ <height>372</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Error summary</string>
+ </property>
+ <property name="windowIcon">
+ <iconset resource="highlight-gui.qrc">
+ <normaloff>:/hl_icon2.png</normaloff>:/hl_icon2.png</iconset>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <widget class="QLabel" name="label_2">
+ <property name="text">
+ <string>Input errors:</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QListWidget" name="listInputErrors"/>
+ </item>
+ <item>
+ <widget class="QCheckBox" name="cbRemoveFiles">
+ <property name="text">
+ <string>Remove files above from input file list</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="Line" name="line">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="label">
+ <property name="text">
+ <string>Output errors:</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QListWidget" name="listOutputErrors"/>
+ </item>
+ <item>
+ <widget class="Line" name="line_2">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="label_3">
+ <property name="text">
+ <string>Reformatting not possible:</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QListWidget" name="listReformatErrors"/>
+ </item>
+ <item>
+ <widget class="QDialogButtonBox" name="buttonBox">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="standardButtons">
+ <set>QDialogButtonBox::Ok</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <resources>
+ <include location="highlight-gui.qrc"/>
+ </resources>
+ <connections>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>accepted()</signal>
+ <receiver>io_report</receiver>
+ <slot>accept()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>248</x>
+ <y>254</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>157</x>
+ <y>274</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>rejected()</signal>
+ <receiver>io_report</receiver>
+ <slot>reject()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>316</x>
+ <y>260</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>286</x>
+ <y>274</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
diff --git a/support/highlight/src/gui-qt/main.cpp b/support/highlight/src/gui-qt/main.cpp new file mode 100644 index 0000000000..027f87a2c6 --- /dev/null +++ b/support/highlight/src/gui-qt/main.cpp @@ -0,0 +1,54 @@ +/***************************************************************************
+ main.cpp
+ -------------------
+ begin : Mo 16.03.2009
+ copyright : (C) 2009 by Andre Simon
+ email : andre.simon1@gmx.de
+ ***************************************************************************/
+
+
+/*
+This file is part of Highlight.
+
+Highlight is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+Highlight is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Highlight. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+
+#include <QtGui/QApplication>
+#include <QTranslator>
+#include <QLocale>
+#include "mainwindow.h"
+
+int main(int argc, char *argv[])
+{
+ QApplication app(argc, argv);
+ QTranslator translator;
+ #ifdef DATA_DIR
+ translator.load(QString("%1/gui_files/l10n/highlight_%2").arg(DATA_DIR).arg(QLocale::system().name()));
+ #else
+ translator.load(QString("%1/gui_files/l10n/highlight_%2").arg(QDir::currentPath()).arg(QLocale::system().name()));
+ #endif
+ app.installTranslator(&translator);
+
+ MainWindow w;
+
+ QStringList args=QCoreApplication::arguments();
+ if (args.count()>1){
+ args.removeFirst(); // drop highlight-gui.exe path
+ w.addInputFiles(args);
+ }
+
+ w.show();
+ return app.exec();
+}
diff --git a/support/highlight/src/gui-qt/mainwindow.cpp b/support/highlight/src/gui-qt/mainwindow.cpp new file mode 100644 index 0000000000..06abcd29dd --- /dev/null +++ b/support/highlight/src/gui-qt/mainwindow.cpp @@ -0,0 +1,1080 @@ +/***************************************************************************
+ mainwindow.cpp
+ -------------------
+ begin : Mo 16.03.2009
+ copyright : (C) 2009 by Andre Simon
+ email : andre.simon1@gmx.de
+ ***************************************************************************/
+
+/*
+This file is part of Highlight.
+
+Highlight is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+Highlight is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Highlight. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <memory>
+#include <algorithm>
+
+#include "mainwindow.h"
+#include "ui_mainwindow.h"
+#include "version.h"
+#include "showtextfile.h"
+#include "io_report.h"
+
+
+MainWindow::MainWindow(QWidget *parent)
+ : QMainWindow(parent), ui(new Ui::MainWindowClass)
+{
+ ui->setupUi(this);
+ this->setWindowTitle(QString("Highlight %1").arg( HIGHLIGHT_VERSION));
+
+ // Read file open filter
+#ifdef DATA_DIR
+ QFile filterDef(QString(DATA_DIR) + "/gui_files/ext/fileopenfilter.conf");
+#else
+ QFile filterDef(QDir::currentPath()+"/gui_files/ext/fileopenfilter.conf");
+#endif
+
+ QRegExp rx("(\\S+)\\s?\\(\\*\\.([\\w\\d]+)");
+
+ if (filterDef.open(QIODevice::ReadOnly | QIODevice::Text)){
+ QTextStream in(&filterDef);
+ QString line;
+
+ QStringList syntaxPair;
+ while (!in.atEnd()) {
+ line = in.readLine();
+ fileOpenFilter+=line;
+ fileOpenFilter+=";;";
+ if( rx.indexIn(line)!=-1){
+ syntaxPair = rx.capturedTexts();
+ ui->comboSelectSyntax->addItem(syntaxPair[1], syntaxPair[2]);
+ }
+ }
+ } else {
+ fileOpenFilter="All files (*)";
+ }
+ // fill themes combo
+#ifdef DATA_DIR
+ QDir themesDir(QString(DATA_DIR) + "/themes");
+#else
+ QDir themesDir(QDir::currentPath()+"/themes");
+#endif
+ QStringList themes = themesDir.entryList(QStringList("*.style"), QDir::Files, QDir::Name);
+ for (QStringList::const_iterator constIterator = themes.constBegin();
+ constIterator != themes.constEnd(); ++constIterator) {
+ ui->comboTheme->addItem(QString(*constIterator).section('.',0, 0));
+ }
+
+ // load syntax mappings
+ if (!loadFileTypeConfig(&extensions, &shebangs)){
+ QMessageBox::warning(this, tr("Initialization error"),
+ tr("Could not find syntax definitions. Check installation."));
+ }
+
+ QObject::connect(ui->pbOpenFiles, SIGNAL(clicked()), this, SLOT(openFiles()));
+ QObject::connect(ui->action_Open_files, SIGNAL(triggered()), this, SLOT(openFiles()));
+
+ QObject::connect(ui->cbWrite2Src, SIGNAL(clicked()), this, SLOT(plausibility()));
+ QObject::connect(ui->cbIncLineNo, SIGNAL(clicked()), this, SLOT(plausibility()));
+ QObject::connect(ui->cbWrapping, SIGNAL(clicked()), this, SLOT(plausibility()));
+ QObject::connect(ui->cbEncoding, SIGNAL(clicked()), this, SLOT(plausibility()));
+
+ QObject::connect(ui->comboFormat, SIGNAL(currentIndexChanged(int)), this, SLOT(plausibility()));
+ QObject::connect(ui->cbReformat, SIGNAL(clicked()), this, SLOT(plausibility()));
+ QObject::connect(ui->cbKwCase, SIGNAL(clicked()), this, SLOT(plausibility()));
+ QObject::connect(ui->cbHTMLEmbedStyle, SIGNAL(clicked()), this, SLOT(plausibility()));
+ QObject::connect(ui->cbHTMLAnchors, SIGNAL(clicked()), this, SLOT(plausibility()));
+ QObject::connect(ui->cbHTMLEmbedStyle, SIGNAL(clicked()), this, SLOT(plausibility()));
+ QObject::connect(ui->cbHTMLInlineCSS, SIGNAL(clicked()), this, SLOT(plausibility()));
+ QObject::connect(ui->cbHTMLCtags, SIGNAL(clicked()), this, SLOT(plausibility()));
+ QObject::connect(ui->cbLATEXEmbedStyle, SIGNAL(clicked()), this, SLOT(plausibility()));
+ QObject::connect(ui->cbTEXEmbedStyle, SIGNAL(clicked()), this, SLOT(plausibility()));
+ QObject::connect(ui->cbSVGEmbedStyle, SIGNAL(clicked()), this, SLOT(plausibility()));
+ QObject::connect(ui->cbFragment, SIGNAL(clicked()), this, SLOT(plausibility()));
+ QObject::connect(ui->tabIOSelection, SIGNAL(currentChanged(int)), this, SLOT(plausibility()));
+
+ QObject::connect(ui->lvInputFiles, SIGNAL(itemSelectionChanged()), this, SLOT(updatePreview()));
+ QObject::connect(ui->cbIncLineNo, SIGNAL(clicked()), this, SLOT(updatePreview()));
+ QObject::connect(ui->cbKwCase, SIGNAL(clicked()), this, SLOT(updatePreview()));
+ QObject::connect(ui->cbPadZeroes, SIGNAL(clicked()), this, SLOT(updatePreview()));
+ QObject::connect(ui->cbReformat, SIGNAL(clicked()), this, SLOT(updatePreview()));
+ QObject::connect(ui->cbWrapping, SIGNAL(clicked()), this, SLOT(updatePreview()));
+ QObject::connect(ui->cbAdvWrapping, SIGNAL(clicked()), this, SLOT(updatePreview()));
+ QObject::connect(ui->cbValidateInput, SIGNAL(clicked()), this, SLOT(updatePreview()));
+ QObject::connect(ui->cbEncoding, SIGNAL(clicked()), this, SLOT(updatePreview()));
+ QObject::connect(ui->comboEncoding, SIGNAL(currentIndexChanged(int)), this, SLOT(updatePreview()));
+
+ QObject::connect(ui->comboFontName, SIGNAL(currentIndexChanged(int)), this, SLOT(updatePreview()));
+ QObject::connect(ui->comboKwCase, SIGNAL(currentIndexChanged(int)), this, SLOT(updatePreview()));
+ QObject::connect(ui->comboReformat, SIGNAL(currentIndexChanged(int)), this, SLOT(updatePreview()));
+ QObject::connect(ui->comboTheme, SIGNAL(currentIndexChanged(int)), this, SLOT(updatePreview()));
+ QObject::connect(ui->comboSelectSyntax, SIGNAL(currentIndexChanged(int)), this, SLOT(updatePreview()));
+
+ QObject::connect(ui->sbLineNoWidth, SIGNAL(valueChanged(int)), this, SLOT(updatePreview()));
+ QObject::connect(ui->leFontSize, SIGNAL(textChanged(QString)), this, SLOT(updatePreview()));
+
+ setAcceptDrops(true);
+
+ readSettings();
+ plausibility();
+}
+
+MainWindow::~MainWindow()
+{
+ writeSettings();
+ delete ui;
+}
+
+void MainWindow::openFiles(){
+ QFileDialog dialog(this, "Select one or more files to open",
+ "",
+ fileOpenFilter);
+ dialog.setFileMode(QFileDialog::ExistingFiles);
+ dialog.setViewMode(QFileDialog::Detail);
+
+ if (dialog.exec()) {
+ addInputFiles(dialog.selectedFiles());
+ }
+}
+
+void MainWindow::selectSingleFile(QLineEdit* edit, const QString& title, const QString& filter){
+ QFileDialog dialog(this, title,
+ "",
+ filter);
+ dialog.setFileMode(QFileDialog::ExistingFile);
+ dialog.setViewMode(QFileDialog::Detail);
+
+ if (dialog.exec()) {
+ edit->setText(dialog.selectedFiles().first());
+ }
+}
+
+void MainWindow::addInputFiles(const QStringList& list){
+ for (QStringList::const_iterator constIterator = list.constBegin();
+ constIterator != list.constEnd(); ++constIterator) {
+ if (ui->lvInputFiles->findItems ( *constIterator, Qt::MatchExactly ).empty()) {
+ ui->lvInputFiles->addItem(*constIterator);
+ }
+ }
+}
+
+void MainWindow::on_pbClearSelection_clicked(){
+ QList<QListWidgetItem *> selectedItems = ui->lvInputFiles->selectedItems();
+ for (int i = 0; i < selectedItems.size(); ++i) {
+ delete selectedItems.at(i);
+ }
+}
+
+void MainWindow::on_pbOutputDest_clicked(){
+ QFileDialog dialog(this, "Select destination directory", "");
+ dialog.setFileMode(QFileDialog::Directory);
+ if (dialog.exec() && !dialog.selectedFiles().empty()) {
+ ui->leOutputDest->setText(dialog.selectedFiles().at(0));
+ }
+}
+
+ void MainWindow::writeSettings()
+ {
+ QSettings settings(QSettings::IniFormat, QSettings::UserScope,
+ "andre-simon.de", "highlight-gui");
+
+ settings.beginGroup("MainWindow");
+ settings.setValue("size", size());
+ settings.setValue("pos", pos());
+ settings.endGroup();
+
+ settings.beginGroup("input");
+ QStringList inFiles;
+ for (int i=0;i<ui->lvInputFiles->count();i++){
+ inFiles<<ui->lvInputFiles->item(i)->text();
+ }
+ const char* name="objectName";
+ settings.setValue(ui->lvInputFiles->property(name).toString(),
+ inFiles);
+ settings.setValue(ui->leOutputDest->property(name).toString(),
+ ui->leOutputDest->text());
+ settings.setValue(ui->cbWrite2Src->property(name).toString(),
+ ui->cbWrite2Src->isChecked());
+ settings.setValue(ui->cbAdvWrapping->property(name).toString(),
+ ui->cbAdvWrapping->isChecked());
+ settings.setValue(ui->cbEncoding->property(name).toString(),
+ ui->cbEncoding->isChecked());
+ settings.setValue(ui->cbFragment->property(name).toString(),
+ ui->cbFragment->isChecked());
+ settings.setValue(ui->cbHTMLAnchors->property(name).toString(),
+ ui->cbHTMLAnchors->isChecked());
+ settings.setValue(ui->cbHTMLCtags->property(name).toString(),
+ ui->cbHTMLCtags->isChecked());
+ settings.setValue(ui->cbHTMLEmbedStyle->property(name).toString(),
+ ui->cbHTMLEmbedStyle->isChecked());
+ settings.setValue(ui->cbHTMLEnclosePreTags->property(name).toString(),
+ ui->cbHTMLEnclosePreTags->isChecked());
+ settings.setValue(ui->cbHTMLFileNameAnchor->property(name).toString(),
+ ui->cbHTMLFileNameAnchor->isChecked());
+ settings.setValue(ui->cbHTMLIndex->property(name).toString(),
+ ui->cbHTMLIndex->isChecked());
+ settings.setValue(ui->cbHTMLInlineCSS->property(name).toString(),
+ ui->cbHTMLInlineCSS->isChecked());
+ settings.setValue(ui->cbHTMLOrderedList->property(name).toString(),
+ ui->cbHTMLOrderedList->isChecked());
+ settings.setValue(ui->cbIncLineNo->property(name).toString(),
+ ui->cbIncLineNo->isChecked());
+ settings.setValue(ui->cbKwCase->property(name).toString(),
+ ui->cbKwCase->isChecked());
+ settings.setValue(ui->cbLATEXBabel->property(name).toString(),
+ ui->cbLATEXBabel->isChecked());
+ settings.setValue(ui->cbLATEXEscQuotes->property(name).toString(),
+ ui->cbLATEXEscQuotes->isChecked());
+ settings.setValue(ui->cbLATEXPrettySymbols->property(name).toString(),
+ ui->cbLATEXPrettySymbols->isChecked());
+ settings.setValue(ui->cbPadZeroes->property(name).toString(),
+ ui->cbPadZeroes->isChecked());
+ settings.setValue(ui->cbReformat->property(name).toString(),
+ ui->cbReformat->isChecked());
+ settings.setValue(ui->cbRTFCharStyles->property(name).toString(),
+ ui->cbRTFCharStyles->isChecked());
+ settings.setValue(ui->cbWrapping->property(name).toString(),
+ ui->cbWrapping->isChecked());
+ settings.setValue(ui->cbValidateInput->property(name).toString(),
+ ui->cbValidateInput->isChecked());
+
+ settings.setValue(ui->comboFormat->property(name).toString(),
+ ui->comboFormat->currentIndex());
+ settings.setValue(ui->comboKwCase->property(name).toString(),
+ ui->comboKwCase->currentIndex());
+ settings.setValue(ui->comboReformat->property(name).toString(),
+ ui->comboReformat->currentIndex());
+ settings.setValue(ui->comboRTFPageSize->property(name).toString(),
+ ui->comboRTFPageSize->currentIndex());
+ settings.setValue(ui->comboTheme->property(name).toString(),
+ ui->comboTheme->currentIndex());
+ settings.setValue(ui->comboEncoding->property(name).toString(),
+ ui->comboEncoding->currentText());
+ settings.setValue(ui->comboFontName->property(name).toString(),
+ ui->comboFontName->currentText());
+ settings.setValue(ui->comboSelectSyntax->property(name).toString(),
+ ui->comboSelectSyntax->currentIndex());
+
+ settings.setValue(ui->leHTMLCtagsFile->property(name).toString(),
+ ui->leHTMLCtagsFile->text());
+ settings.setValue(ui->leHTMLStyleFile->property(name).toString(),
+ ui->leHTMLStyleFile->text());
+ settings.setValue(ui->leHTMLStyleIncFile->property(name).toString(),
+ ui->leHTMLStyleIncFile->text());
+ settings.setValue(ui->leLATEXStyleFile->property(name).toString(),
+ ui->leLATEXStyleFile->text());
+ settings.setValue(ui->leLATEXStyleIncFile->property(name).toString(),
+ ui->leLATEXStyleIncFile->text());
+ settings.setValue(ui->leTEXStyleFile->property(name).toString(),
+ ui->leTEXStyleFile->text());
+ settings.setValue(ui->leTEXStyleIncFile->property(name).toString(),
+ ui->leTEXStyleIncFile->text());
+ settings.setValue(ui->leSVGStyleFile->property(name).toString(),
+ ui->leSVGStyleFile->text());
+ settings.setValue(ui->leSVGStyleIncFile->property(name).toString(),
+ ui->leSVGStyleIncFile->text());
+ settings.setValue(ui->cbSVGEmbedStyle->property(name).toString(),
+ ui->cbSVGEmbedStyle->isChecked());
+ settings.setValue(ui->cbLATEXEmbedStyle->property(name).toString(),
+ ui->cbLATEXEmbedStyle->isChecked());
+ settings.setValue(ui->cbTEXEmbedStyle->property(name).toString(),
+ ui->cbTEXEmbedStyle->isChecked());
+ settings.setValue(ui->leSVGHeight->property(name).toString(),
+ ui->leSVGHeight->text());
+ settings.setValue(ui->leSVGWidth->property(name).toString(),
+ ui->leSVGWidth->text());
+ settings.setValue(ui->leFontSize->property(name).toString(),
+ ui->leFontSize->text());
+ settings.setValue(ui->sbLineLength->property(name).toString(),
+ ui->sbLineLength->value());
+ settings.setValue(ui->sbTabWidth->property(name).toString(),
+ ui->sbTabWidth->value());
+ settings.setValue(ui->tabWidget->property(name).toString(),
+ ui->tabWidget->currentIndex());
+ settings.setValue(ui->leHTMLCssPrefix->property(name).toString(),
+ ui->leHTMLCssPrefix->text());
+ settings.setValue(ui->tabIOSelection->property(name).toString(),
+ ui->tabIOSelection->currentIndex());
+
+
+ settings.endGroup();
+ }
+
+ void MainWindow::readSettings()
+ {
+ QSettings settings(QSettings::IniFormat, QSettings::UserScope,
+ "andre-simon.de", "highlight-gui");
+
+ settings.beginGroup("MainWindow");
+ resize(settings.value("size", QSize(400, 400)).toSize());
+ move(settings.value("pos", QPoint(200, 200)).toPoint());
+ settings.endGroup();
+
+ settings.beginGroup("input");
+ const char* name="objectName";
+ ui->lvInputFiles->addItems( settings.value(ui->lvInputFiles->property(name).toString()).toStringList() );
+ ui->leOutputDest->setText(settings.value(ui->leOutputDest->property(name).toString()).toString());
+ ui->cbWrite2Src->setChecked(settings.value(ui->cbWrite2Src->property(name).toString()).toBool());
+ ui->cbAdvWrapping->setChecked(settings.value(ui->cbAdvWrapping->property(name).toString()).toBool());
+ ui->cbEncoding->setChecked(settings.value(ui->cbEncoding->property(name).toString()).toBool());
+ ui->cbFragment->setChecked(settings.value(ui->cbFragment->property(name).toString()).toBool());
+ ui->cbHTMLAnchors->setChecked(settings.value(ui->cbHTMLAnchors->property(name).toString()).toBool());
+ ui->cbHTMLCtags->setChecked(settings.value(ui->cbHTMLCtags->property(name).toString()).toBool());
+ ui->cbHTMLEmbedStyle->setChecked(settings.value(ui->cbHTMLEmbedStyle->property(name).toString()).toBool());
+ ui->cbHTMLEnclosePreTags->setChecked(settings.value(ui->cbHTMLEnclosePreTags->property(name).toString()).toBool());
+ ui->cbHTMLFileNameAnchor->setChecked(settings.value(ui->cbHTMLFileNameAnchor->property(name).toString()).toBool());
+ ui->cbHTMLIndex->setChecked(settings.value(ui->cbHTMLIndex->property(name).toString()).toBool());
+ ui->cbHTMLInlineCSS->setChecked(settings.value(ui->cbHTMLInlineCSS->property(name).toString()).toBool());
+ ui->cbHTMLOrderedList->setChecked(settings.value(ui->cbHTMLOrderedList->property(name).toString()).toBool());
+ ui->cbIncLineNo->setChecked(settings.value(ui->cbIncLineNo->property(name).toString()).toBool());
+ ui->cbKwCase->setChecked(settings.value(ui->cbKwCase->property(name).toString()).toBool());
+ ui->cbLATEXBabel->setChecked(settings.value(ui->cbLATEXBabel->property(name).toString()).toBool());
+ ui->cbLATEXEscQuotes->setChecked(settings.value(ui->cbLATEXEscQuotes->property(name).toString()).toBool());
+ ui->cbLATEXPrettySymbols->setChecked(settings.value(ui->cbLATEXPrettySymbols->property(name).toString()).toBool());
+
+ ui->cbPadZeroes->setChecked(settings.value(ui->cbPadZeroes->property(name).toString()).toBool());
+ ui->cbReformat->setChecked(settings.value(ui->cbReformat->property(name).toString()).toBool());
+ ui->cbRTFCharStyles->setChecked(settings.value(ui->cbRTFCharStyles->property(name).toString()).toBool());
+ ui->cbWrapping->setChecked(settings.value(ui->cbWrapping->property(name).toString()).toBool());
+ ui->cbValidateInput->setChecked(settings.value(ui->cbValidateInput->property(name).toString()).toBool());
+
+ ui->comboEncoding->insertItem(0, settings.value(ui->comboEncoding->property(name).toString()).toString());
+ ui->comboEncoding->setCurrentIndex(0);
+ ui->comboFontName->insertItem(0, settings.value(ui->comboFontName->property(name).toString()).toString());
+ ui->comboFontName->setCurrentIndex(0);
+ ui->comboFormat->setCurrentIndex(settings.value(ui->comboFormat->property(name).toString()).toInt());
+ ui->comboKwCase->setCurrentIndex(settings.value(ui->comboKwCase->property(name).toString()).toInt());
+ ui->comboReformat->setCurrentIndex(settings.value(ui->comboReformat->property(name).toString()).toInt());
+ ui->comboRTFPageSize->setCurrentIndex(settings.value(ui->comboRTFPageSize->property(name).toString()).toInt());
+ ui->comboTheme->setCurrentIndex(settings.value(ui->comboTheme->property(name).toString()).toInt());
+ ui->comboSelectSyntax->setCurrentIndex(settings.value(ui->comboSelectSyntax->property(name).toString()).toInt());
+
+ ui->leHTMLCtagsFile->setText(settings.value(ui->leHTMLCtagsFile->property(name).toString()).toString());
+ ui->leHTMLStyleFile->setText(settings.value(ui->leHTMLStyleFile->property(name).toString()).toString());
+ ui->leHTMLStyleIncFile->setText(settings.value(ui->leHTMLStyleIncFile->property(name).toString()).toString());
+ ui->leLATEXStyleFile->setText(settings.value(ui->leLATEXStyleFile->property(name).toString()).toString());
+ ui->leTEXStyleFile->setText(settings.value(ui->leTEXStyleFile->property(name).toString()).toString());
+ ui->leLATEXStyleIncFile->setText(settings.value(ui->leLATEXStyleIncFile->property(name).toString()).toString());
+ ui->leTEXStyleIncFile->setText(settings.value(ui->leTEXStyleIncFile->property(name).toString()).toString());
+ ui->leSVGHeight->setText(settings.value(ui->leSVGHeight->property(name).toString()).toString());
+ ui->leSVGWidth->setText(settings.value(ui->leSVGWidth->property(name).toString()).toString());
+ ui->leFontSize->setText(settings.value(ui->leFontSize->property(name).toString()).toString());
+ ui->leHTMLCssPrefix->setText(settings.value(ui->leHTMLCssPrefix->property(name).toString()).toString());
+ ui->sbLineLength->setValue(settings.value(ui->sbLineLength->property(name).toString()).toInt());
+ ui->sbTabWidth->setValue(settings.value(ui->sbTabWidth->property(name).toString()).toInt());
+ ui->cbTEXEmbedStyle->setChecked(settings.value(ui->cbTEXEmbedStyle->property(name).toString()).toBool());
+ ui->cbLATEXEmbedStyle->setChecked(settings.value(ui->cbLATEXEmbedStyle->property(name).toString()).toBool());
+ ui->cbSVGEmbedStyle->setChecked(settings.value(ui->cbSVGEmbedStyle->property(name).toString()).toBool());
+ ui->tabWidget->setCurrentIndex(settings.value(ui->tabWidget->property(name).toString()).toInt());
+ ui->tabIOSelection->setCurrentIndex(settings.value(ui->tabIOSelection->property(name).toString()).toInt());
+
+ settings.endGroup();
+ }
+
+bool MainWindow::loadFileTypeConfig(StringMap* extMap, StringMap* shebangMap) {
+ if (!extMap || !shebangMap) return false;
+
+#ifdef CONFIG_DIR
+ QString filetypesPath = QDir::toNativeSeparators(QString("%1/filetypes.conf").arg(CONFIG_DIR));
+#else
+ QString filetypesPath = QDir::toNativeSeparators(QString("%1/filetypes.conf").arg(QDir::currentPath()));
+#endif
+
+ ConfigurationReader config(filetypesPath.toStdString());
+ if (config.found())
+ {
+ stringstream values;
+ string paramName, paramVal;
+ for (unsigned int i=0;i<config.getParameterNames().size();i++){
+ paramName = config.getParameterNames()[i];
+ if (paramName.find("ext") != string::npos){
+ values.str(StringTools::change_case(config.getParameter(paramName)));
+ paramName = StringTools::getParantheseVal(paramName);
+ while (values >> paramVal) {
+ extMap->insert(make_pair( paramVal, paramName));
+ }
+ values.clear();
+ } else if (paramName.find("shebang") != string::npos){
+ values.str(config.getParameter(paramName)) ;
+ paramName = StringTools::getParantheseVal(paramName);
+ while (values >> paramVal) {
+ shebangMap->insert(make_pair( paramVal, paramName));
+ }
+ values.clear();
+ }
+ }
+ return true;
+ }
+ return false;
+}
+
+ string MainWindow::analyzeFile(const string& file){
+ ifstream inFile(file.c_str());
+ string firstLine;
+ getline (inFile, firstLine);
+ StringMap::iterator it;
+ for (it=shebangs.begin(); it!=shebangs.end();it++){
+ if (Pattern::matches(it->first, firstLine)) return it->second;
+ }
+ return "";
+}
+
+string MainWindow::getFileType(const string& suffix, const string &inputFile)
+{
+ string lcSuffix = StringTools::change_case(suffix);
+ string fileType = (extensions.count(lcSuffix)) ? extensions[lcSuffix] : lcSuffix ;
+ if (!fileType.empty()) return fileType;
+ return analyzeFile(inputFile);
+}
+
+string MainWindow::getFileSuffix(const string& fileName)
+{
+ unsigned int ptPos=fileName.rfind(".");
+ return (ptPos == string::npos) ? "" : fileName.substr(ptPos+1,
+ fileName.length());
+}
+
+void MainWindow::on_action_Exit_triggered()
+{
+ this->close();
+}
+
+void MainWindow::on_action_About_Highlight_triggered()
+{
+ QMessageBox::about( this, "About Highlight",
+ QString("Highlight is a code to formatted text converter.\n\n"
+ "Highlight GUI %1\n"
+ "(C) 2002-2010 Andre Simon <andre.simon1 at gmx.de>\n\n"
+ "Artistic Style Classes\n(C) 1998-2002 Tal Davidson\n"
+ "(C) 2006-2009 Jim Pattee <jimp03 at email.com>\n\n"
+ "Regex library\n(C) 2003-2008 Jeffery Stuart <stuart at cs.unr.edu>\n\n"
+ "Built with Qt version %2\n\n"
+ "Released under the terms of the GNU GPL license.\n\n"
+ "The highlight logo is based on the image \"Alcedo Atthis\" by Lukasz Lukasik.\n"
+ "The original was published under the terms of the GNU FDL in the Wikimedia Commons database.\n\n"
+ "Updates: http://www.andre-simon.de/\n").arg(HIGHLIGHT_VERSION).arg(QString(qVersion ())) );
+}
+
+ highlight::OutputType MainWindow::getOutputType(){
+
+ switch (ui->comboFormat->currentIndex()){
+ case 0: return highlight::HTML;
+ case 1: return highlight::XHTML;
+ case 2: return highlight::LATEX;
+ case 3: return highlight::TEX;
+ case 4: return highlight::RTF;
+ case 5: return highlight::SVG;
+ case 6: return highlight::XML;
+ case 7: return highlight::BBCODE;
+ }
+ return highlight::HTML;
+}
+
+ QString MainWindow::getOutFileSuffix(){
+ switch (ui->comboFormat->currentIndex()) {
+ case 0: return ".html";
+ case 1: return ".xhtml";
+ case 2:
+ case 3: return ".tex";
+ case 4: return ".rtf";
+ case 5: return ".svg";
+ case 6: return ".xml";
+ case 7: return ".bbcode";
+ }
+ return ".html";
+}
+
+
+void MainWindow::applyCtrlValues(highlight::CodeGenerator* generator, bool previewMode){
+ if (!generator) return;
+
+ highlight::OutputType outType=getOutputType();
+
+ if (!previewMode){
+ QLineEdit * styleIncFile=NULL;
+ QLineEdit * styleOutFile=NULL;
+ QCheckBox * embedStyle=NULL;
+
+ switch(outType) {
+ case highlight::HTML:
+ case highlight::XHTML: styleIncFile = ui->leHTMLStyleIncFile;
+ styleOutFile = ui->leHTMLStyleFile;
+ embedStyle = ui->cbHTMLEmbedStyle;
+ break;
+ case highlight::LATEX:
+ styleIncFile = ui->leLATEXStyleIncFile;
+ styleOutFile = ui->leLATEXStyleFile;
+ embedStyle = ui->cbLATEXEmbedStyle;
+ break;
+ case highlight::TEX: styleIncFile = ui->leTEXStyleIncFile;
+ styleOutFile = ui->leTEXStyleFile;
+ embedStyle = ui->cbTEXEmbedStyle;
+ break;
+ case highlight::SVG: styleIncFile = ui->leSVGStyleIncFile;
+ styleOutFile = ui->leSVGStyleFile;
+ embedStyle = ui->cbSVGEmbedStyle;
+ break;
+ default: break;
+ }
+ if (styleIncFile)
+ generator->setStyleInputPath(QDir::toNativeSeparators(styleIncFile->text()).toStdString());
+ if (styleOutFile)
+ generator->setStyleOutputPath(styleOutFile->text().toStdString());
+ if (embedStyle)
+ generator->setIncludeStyle(embedStyle->isChecked());
+
+ generator->setFragmentCode(ui->cbFragment->isChecked());
+
+ generator->setHTMLAttachAnchors(ui->cbHTMLAnchors->isChecked());
+ generator->setHTMLOrderedList(ui->cbHTMLOrderedList->isChecked());
+ generator->setHTMLInlineCSS(ui->cbHTMLInlineCSS->isChecked() && ui->cbHTMLInlineCSS->isEnabled());
+ generator->setHTMLEnclosePreTag(ui->cbHTMLEnclosePreTags->isChecked());
+ if (ui->leHTMLCssPrefix->text().size())
+ generator->setHTMLClassName(ui->leHTMLCssPrefix->text().toStdString());
+
+ generator->setLATEXReplaceQuotes(ui->cbLATEXEscQuotes->isChecked());
+ generator->setLATEXNoShorthands(ui->cbLATEXBabel->isChecked());
+ generator->setLATEXPrettySymbols(ui->cbLATEXPrettySymbols->isChecked());
+
+ generator->setRTFPageSize(ui->comboRTFPageSize->currentText().toLower().toStdString());
+ generator->setRTFCharStyles(ui->cbRTFCharStyles->isChecked());
+
+ generator->setSVGSize(ui->leSVGWidth->text().toStdString(), ui->leSVGHeight->text().toStdString());
+ }
+
+ generator->setPrintLineNumbers( ui->cbIncLineNo->isChecked());
+ generator->setPrintZeroes(ui->cbPadZeroes->isEnabled() && ui->cbPadZeroes->isChecked());
+
+#ifdef DATA_DIR
+ QString themePath = QString("%1/themes/%2.style").arg(
+ DATA_DIR).arg(ui->comboTheme->currentText());
+#else
+ QString themePath = QString("%1/themes/%2.style").arg(
+ QDir::currentPath()).arg(ui->comboTheme->currentText());
+#endif
+
+ generator->initTheme(themePath.toStdString());
+
+ if (ui->cbEncoding->isChecked()) {
+ generator->setEncoding(ui->comboEncoding->currentText().toStdString());
+ } else {
+ generator->setEncoding("none");
+ }
+ generator->setValidateInput(ui->cbValidateInput->isChecked());
+ generator->setLineNumberWidth(ui->sbLineNoWidth->value());
+
+ if (getOutputType()!=highlight::LATEX && getOutputType()!=highlight::TEX){
+ string fntName=ui->comboFontName->currentText().toStdString();
+ if(fntName.size()) generator->setBaseFont(fntName);
+ string fntSize=ui->leFontSize->text().toStdString();
+ if(fntSize.size()) generator->setBaseFontSize(fntSize);
+ }
+
+ int lineLength = 0;
+ if (ui->cbWrapping->isChecked()){
+ lineLength = ( ui->cbIncLineNo->isChecked()
+ && ui->sbLineNoWidth->value() > ui->sbLineLength->value())?
+ ui->sbLineLength->value() - ui->sbLineNoWidth->value()
+ : ui->sbLineLength->value();
+ }
+ generator->setPreformatting(getWrappingStyle(), lineLength, ui->sbTabWidth->value());
+
+ if(ui->cbKwCase->isChecked()){
+ StringTools::KeywordCase kwCase=StringTools::CASE_UNCHANGED;
+ switch (ui->comboKwCase->currentIndex()){
+ case 0: kwCase=StringTools::CASE_UPPER; break;
+ case 1: kwCase=StringTools::CASE_LOWER; break;
+ case 2: kwCase=StringTools::CASE_CAPITALIZE; break;
+ }
+ generator->setKeyWordCase(kwCase);
+ }
+
+ if (ui->cbReformat->isChecked()){
+ generator->initIndentationScheme(ui->comboReformat->currentText().toLower().toStdString());
+
+ }
+
+ if ( ui->cbHTMLCtags->isChecked() && !ui->leHTMLCtagsFile->text().isEmpty()
+ && (outType==highlight::HTML || outType==highlight::XHTML)){
+ if (!generator->initTagInformation(ui->leHTMLCtagsFile->text().toStdString())){
+ QMessageBox::warning(this, tr("Tags file error"),
+ tr("Could not read tags information in \"%1\"").arg(ui->leHTMLCtagsFile->text()));
+ }
+ }
+}
+
+highlight::WrapMode MainWindow::getWrappingStyle(){
+ if (!ui->cbAdvWrapping->isChecked() && ui->cbAdvWrapping->isEnabled())
+ return highlight::WRAP_SIMPLE;
+ return (ui->cbWrapping->isChecked())?highlight::WRAP_DEFAULT:highlight::WRAP_DISABLED;
+}
+
+
+void MainWindow::on_pbStartConversion_clicked(){
+
+ if (!ui->lvInputFiles->count()) return;
+
+ if (!ui->cbWrite2Src->isChecked() && !QDir(ui->leOutputDest->text()).exists()){
+ QMessageBox::warning(this, tr("Output error"), tr("Output directory does not exist!"));
+ ui->leOutputDest->setFocus();
+ return;
+ }
+ highlight::OutputType outType = getOutputType();
+ QCheckBox* cbEmbed=NULL;
+ QLineEdit* leStyleFile=NULL;
+
+ if ( outType==highlight::HTML || outType==highlight::XHTML) {
+ cbEmbed = ui->cbHTMLEmbedStyle;
+ leStyleFile = ui->leHTMLStyleFile;
+ }
+ else if ( outType==highlight::LATEX ) {
+ cbEmbed = ui->cbLATEXEmbedStyle;
+ leStyleFile = ui->leLATEXStyleFile;
+ }
+ else if (outType==highlight::TEX ) {
+ cbEmbed = ui->cbTEXEmbedStyle;
+ leStyleFile = ui->leTEXStyleFile;
+ } else if (outType==highlight::SVG ) {
+ cbEmbed = ui->cbSVGEmbedStyle;
+ leStyleFile = ui->leSVGStyleFile;
+ }
+
+ if (cbEmbed && leStyleFile ) {
+ if ( !cbEmbed->isChecked() && leStyleFile->text().isEmpty()){
+ ui->tabWidget->setCurrentIndex(1);
+ if ( outType==highlight::HTML || outType==highlight::XHTML){
+ ui->tabWidget->setCurrentIndex(0);
+ }
+ leStyleFile->setFocus();
+ QMessageBox::warning(this, tr("Output error"), tr("You must define a style output file!"));
+ return;
+ }
+ }
+ ui->pbStartConversion->setDisabled(true);
+ ui->pbCopyFile2CP->setDisabled(true);
+ this->setCursor(Qt::WaitCursor);
+
+ QTime t;
+ t.start();
+
+ auto_ptr<highlight::CodeGenerator> generator(highlight::CodeGenerator::getInstance(outType));
+
+ applyCtrlValues(generator.get(), false);
+ string currentFile, suffix;
+ string outfileName;
+ string outfileSuffix = getOutFileSuffix().toStdString();
+ QString langDefPath;
+ QString inFileName, inFilePath;
+ highlight::ParseError error;
+ highlight::LoadResult loadRes;
+ QStringList inputErrors, outputErrors, reformatErrors;
+
+ for (int i=0; i<ui->lvInputFiles->count(); i++){
+ inFilePath = ui->lvInputFiles->item(i)->text();
+ currentFile = inFilePath.toStdString();
+ suffix = getFileType(getFileSuffix(currentFile), currentFile);
+#ifdef DATA_DIR
+ langDefPath = QDir::toNativeSeparators(QString("%1/langDefs/%2.lang").arg(DATA_DIR).arg(QString::fromStdString(suffix)));
+#else
+ langDefPath = QDir::toNativeSeparators(QString("%1/langDefs/%2.lang").arg(QDir::currentPath()).arg(QString::fromStdString(suffix)));
+#endif
+
+ loadRes=generator->initLanguage(langDefPath.toStdString());
+ if (loadRes==highlight::LOAD_FAILED_REGEX){
+ QMessageBox::warning(this, tr("Language definition error"),
+ tr("Invalid regular expression in %1:\n%2").arg(langDefPath).arg(
+ QString::fromStdString( generator->getLanguage().getFailedRegex())));
+ break;
+ } else if (loadRes==highlight::LOAD_FAILED) {
+ QMessageBox::warning(this, tr("Unknown syntax"), tr("Could not convert %1").arg(QString::fromStdString(currentFile)));
+ inputErrors.append(inFilePath);
+ } else {
+
+ if (ui->cbReformat->isChecked()&& !generator->formattingIsPossible()){
+ reformatErrors.append(inFilePath);
+ }
+
+ if (ui->cbWrite2Src->isChecked()) {
+ outfileName = currentFile;
+ } else {
+ QFileInfo outFileInfo;
+ outFileInfo.setFile(ui->leOutputDest->text(), QFileInfo(inFilePath).fileName());
+ outfileName = outFileInfo.absoluteFilePath().toStdString();
+ }
+ outfileName += outfileSuffix;
+
+ inFileName = QFileInfo(inFilePath).fileName();
+ if (ui->cbHTMLFileNameAnchor->isChecked()){
+ generator->setHTMLAnchorPrefix(inFileName.toStdString());
+ }
+ generator->setTitle(inFileName.toStdString());
+ error = generator->generateFile(currentFile,
+ outfileName );
+ if (error != highlight::PARSE_OK){
+ if (error == highlight::BAD_INPUT) {
+ inputErrors.append(inFilePath);
+ }
+ else {
+ outputErrors.append(inFilePath);
+ }
+ }
+ ui->progressBar->setValue(100*i / ui->lvInputFiles->count());
+ }
+ }
+
+ // write external Stylesheet
+ if (cbEmbed && leStyleFile && !cbEmbed->isChecked()) {
+ QString stylePath=QFileInfo(ui->leOutputDest->text(), leStyleFile->text()).absoluteFilePath();
+ bool styleFileOK=generator -> printExternalStyle(QDir::toNativeSeparators(stylePath).toStdString());
+ if (!styleFileOK) {
+ outputErrors.append(stylePath);
+ }
+ }
+
+ // write HTML index file
+ if ( (outType==highlight::HTML || outType==highlight::XHTML)
+ && ui->cbHTMLIndex->isChecked() && !ui->cbWrite2Src->isChecked()) {
+ vector <string> fileList;
+ for (int i=0;i<ui->lvInputFiles->count();i++){
+ fileList.push_back(QDir::toNativeSeparators(ui->lvInputFiles->item(i)->text()).toStdString());
+ }
+ QString outPath = QDir::toNativeSeparators(ui->leOutputDest->text());
+ if (!outPath.endsWith(QDir::separator())) outPath.append(QDir::separator());
+ bool indexFileOK=generator->printIndexFile(fileList, outPath.toStdString());
+ if (!indexFileOK) {
+ outputErrors.append(outPath+ ((outType==highlight::HTML)?"index.html":"index.xhtml"));
+ }
+ }
+
+ statusBar()->showMessage(tr("Converted %1 files in %2 ms").arg(ui->lvInputFiles->count()).arg(t.elapsed()));
+ ui->progressBar->reset();
+ this->setCursor(Qt::ArrowCursor);
+ ui->pbStartConversion->setEnabled(true);
+ ui->pbCopyFile2CP->setEnabled(true);
+
+ if (!inputErrors.isEmpty() || !outputErrors.isEmpty() || !reformatErrors.isEmpty()){
+ io_report report;
+ report.addInputErrors(inputErrors);
+ report.addOutputErrors(outputErrors);
+ report.addReformatErrors(reformatErrors);
+ report.exec();
+ if (report.removeInputErrorFiles()){
+ QList<QListWidgetItem*> items;
+ for (int i=0;i<inputErrors.count();i++){
+ items=ui->lvInputFiles->findItems(inputErrors.at(i),Qt::MatchExactly);
+ for (int j=0;j<items.count();j++){
+ delete items.at(j);
+ }
+ }
+ }
+ }
+}
+
+void MainWindow::on_pbCopyFile2CP_clicked(){
+
+ highlight2Clipboard(false);
+}
+
+void MainWindow::highlight2Clipboard(bool getDataFromCP){
+
+ if ((!getDataFromCP &&NULL==ui->lvInputFiles->currentItem())
+ || (getDataFromCP && savedClipboardContent.isEmpty())) return;
+
+ this->setCursor(Qt::WaitCursor);
+
+ auto_ptr<highlight::CodeGenerator> generator(
+ highlight::CodeGenerator::getInstance(getOutputType()));
+
+ applyCtrlValues(generator.get(), false);
+
+ string suffix;
+ if (getDataFromCP){
+ suffix= getFileType((ui->comboSelectSyntax->itemData(ui->comboSelectSyntax->currentIndex())).toString().toStdString(),"");
+ }else {
+ string currentFile = ui->lvInputFiles->currentItem()->text().toStdString();
+ suffix = getFileType(getFileSuffix(currentFile), currentFile);
+
+ QString inFileName = QFileInfo(ui->lvInputFiles->currentItem()->text()).fileName();
+ generator->setTitle(inFileName.toStdString());
+ }
+
+#ifdef DATA_DIR
+ QString langPath = QDir::toNativeSeparators(QString("%1/langDefs/%2.lang").arg(
+ DATA_DIR).arg(QString::fromStdString(suffix)));
+#else
+ QString langPath = QDir::toNativeSeparators(QString("%1/langDefs/%2.lang").arg(
+ QDir::currentPath()).arg(QString::fromStdString(suffix)));
+#endif
+
+ if ( generator->initLanguage(langPath.toStdString()) != highlight::LOAD_FAILED){
+ QString clipBoardData;
+ if (getDataFromCP){
+ clipBoardData= QString::fromStdString( generator->generateString(savedClipboardContent.toStdString()));
+ } else {
+ clipBoardData= QString::fromStdString( generator->generateStringFromFile(ui->lvInputFiles->currentItem()->text().toStdString()));
+ }
+
+ QClipboard *clipboard = QApplication::clipboard();
+ if (clipboard) {
+ highlight::OutputType outputType = getOutputType();
+ if ( outputType==highlight::RTF){
+ QMimeData *mimeData = new QMimeData();
+#ifdef WIN32
+ mimeData->setData("Rich Text Format", clipBoardData.toAscii());
+#else
+ mimeData->setData("text/rtf", clipBoardData.toAscii());
+#endif
+ clipboard->setMimeData(mimeData);
+ } else {
+ clipboard->setText(clipBoardData);
+ }
+ }
+ } else {
+ statusBar()->showMessage(
+ tr("Conversion of \"%1\" not possible.").arg((getDataFromCP)?tr("clipboard data"):ui->lvInputFiles->currentItem()->text()));
+ }
+ this->setCursor(Qt::ArrowCursor);
+}
+
+ void MainWindow::plausibility(){
+ ui->leOutputDest->setEnabled(!ui->cbWrite2Src->isChecked());
+ ui->pbOutputDest->setEnabled(!ui->cbWrite2Src->isChecked());
+ ui->pbOutputDest->setEnabled(!ui->cbWrite2Src->isChecked());
+ ui->leOutputDest->setEnabled(!ui->cbWrite2Src->isChecked());
+ ui->cbPadZeroes->setEnabled(ui->cbIncLineNo->isChecked());
+ ui->cbAdvWrapping->setEnabled(ui->cbWrapping->isChecked());
+ ui->comboEncoding->setEnabled(ui->cbEncoding->isChecked());
+
+ ui->comboReformat->setEnabled(ui->cbReformat->isChecked());
+ ui->comboKwCase->setEnabled(ui->cbKwCase->isChecked());
+ ui->cbHTMLInlineCSS->setEnabled(ui->cbHTMLEmbedStyle->isChecked());
+ ui->cbHTMLFileNameAnchor->setEnabled(ui->cbHTMLAnchors->isChecked());
+ ui->leHTMLStyleFile->setEnabled(!ui->cbHTMLEmbedStyle->isChecked());
+ ui->leHTMLStyleIncFile->setEnabled(ui->cbHTMLEmbedStyle->isChecked() && !ui->cbHTMLInlineCSS->isChecked());
+ ui->pbHTMLChooseStyleIncFile->setEnabled(ui->cbHTMLEmbedStyle->isChecked() &&!ui->cbHTMLInlineCSS->isChecked());
+ ui->leHTMLCssPrefix->setEnabled(!ui->cbHTMLInlineCSS->isChecked());
+ ui->leHTMLCtagsFile->setEnabled(ui->cbHTMLCtags->isChecked());
+ ui->pbHTMLChooseTagsFile->setEnabled(ui->cbHTMLCtags->isChecked());
+ ui->leLATEXStyleFile->setEnabled(!ui->cbLATEXEmbedStyle->isChecked());
+ ui->leTEXStyleFile->setEnabled(!ui->cbTEXEmbedStyle->isChecked());
+ ui->leSVGStyleFile->setEnabled(!ui->cbSVGEmbedStyle->isChecked());
+ ui->cbFragment->setEnabled( getOutputType()!=highlight::RTF && getOutputType()!=highlight::SVG );
+ ui->sbLineNoWidth->setEnabled(ui->cbIncLineNo->isChecked());
+ ui->cbHTMLIndex->setEnabled(!ui->cbWrite2Src->isChecked());
+ ui->cbHTMLEnclosePreTags->setEnabled(ui->cbFragment->isChecked());
+ ui->cbHTMLAnchors->setEnabled(ui->cbIncLineNo->isChecked());
+ ui->cbHTMLFileNameAnchor->setEnabled(ui->cbIncLineNo->isChecked());
+ ui->cbHTMLOrderedList->setEnabled(ui->cbIncLineNo->isChecked());
+
+ ui->pbCopyToCP->setEnabled(!savedClipboardContent.isEmpty());
+
+ switch (ui->comboFormat->currentIndex()) {
+ case 0:
+ case 1:
+ ui->stackedSpecificOptions->setCurrentIndex(0);
+ break;
+ case 2:
+ ui->stackedSpecificOptions->setCurrentIndex(1);
+ break;
+ case 3:
+ ui->stackedSpecificOptions->setCurrentIndex(2);
+ break;
+ case 4:
+ ui->stackedSpecificOptions->setCurrentIndex(3);
+ break;
+ case 5:
+ ui->stackedSpecificOptions->setCurrentIndex(4);
+ break;
+ default:
+ ui->stackedSpecificOptions->setCurrentIndex(5);
+ break;
+ }
+ }
+
+ void MainWindow::updatePreview() {
+
+ // is clipboard tab chosen?
+ bool getDataFromCP = ui->tabIOSelection->currentIndex()==1;
+
+ if ((!getDataFromCP && NULL==ui->lvInputFiles->currentItem())
+ || (getDataFromCP && savedClipboardContent.isEmpty())) return;
+
+ int vScroll = ui->browserPreview->verticalScrollBar()->value();
+ int hScroll = ui->browserPreview->horizontalScrollBar()->value();
+ this->setCursor(Qt::WaitCursor);
+ highlight::HtmlGenerator pwgenerator;
+ pwgenerator.setIncludeStyle(true);
+ pwgenerator.setHTMLInlineCSS(true);
+ if (!getDataFromCP){
+ pwgenerator.setMaxInputLineCnt(500);
+ }
+
+ applyCtrlValues(&pwgenerator, true);
+
+ string suffix;
+
+ if (getDataFromCP){
+ suffix= getFileType((ui->comboSelectSyntax->itemData(ui->comboSelectSyntax->currentIndex())).toString().toStdString(),"");
+ } else {
+ string currentFile = ui->lvInputFiles->currentItem()->text().toStdString();
+ suffix = getFileType(getFileSuffix(currentFile), currentFile);
+ }
+#ifdef DATA_DIR
+ QString langPath = QDir::toNativeSeparators(QString("%1/langDefs/%2.lang").arg(
+ DATA_DIR).arg(QString::fromStdString(suffix)));
+#else
+ QString langPath = QDir::toNativeSeparators(QString("%1/langDefs/%2.lang").arg(
+ QDir::currentPath()).arg(QString::fromStdString(suffix)));
+#endif
+
+
+ if ( pwgenerator.initLanguage(langPath.toStdString()) != highlight::LOAD_FAILED){
+
+ ui->lbPreview->setText(tr("Preview (%1):").arg(
+ (getDataFromCP)?tr("clipboard data"):ui->lvInputFiles->currentItem()->text()) );
+
+ statusBar()->showMessage(tr("Current syntax: %1").arg( QString::fromStdString(pwgenerator.getLanguage().getDescription())));
+ QString previewData;
+
+ // fix utf-8 data preview - to be improved (other encodings??)
+ if (ui->cbEncoding->isChecked() && ui->comboEncoding->currentText().toLower()=="utf-8"){
+ if (getDataFromCP){
+ previewData= QString::fromUtf8( pwgenerator.generateString(savedClipboardContent.toStdString()).c_str());
+ } else {
+ previewData= QString::fromUtf8( pwgenerator.generateStringFromFile(ui->lvInputFiles->currentItem()->text().toStdString()).c_str());
+ }
+ }
+ else {
+ if (getDataFromCP){
+ previewData= QString::fromStdString( pwgenerator.generateString(savedClipboardContent.toStdString()));
+ } else {
+ previewData= QString::fromStdString( pwgenerator.generateStringFromFile(ui->lvInputFiles->currentItem()->text().toStdString()));
+ }
+ }
+
+ ui->browserPreview->setHtml(previewData);
+ } else {
+ statusBar()->showMessage(tr("Preview of \"%1\" not possible.").arg((getDataFromCP)?tr("clipboard data"):ui->lvInputFiles->currentItem()->text()));
+ }
+ ui->browserPreview->verticalScrollBar()->setValue(vScroll);
+ ui->browserPreview->horizontalScrollBar()->setValue(hScroll);
+ this->setCursor(Qt::ArrowCursor);
+ }
+
+
+
+void MainWindow::on_pbHTMLChooseTagsFile_clicked()
+{
+ selectSingleFile(ui->leHTMLCtagsFile, tr("Choose a ctags file"), "*");
+}
+
+void MainWindow::on_action_Manual_triggered()
+{
+ ShowTextFile show;
+ show.setFileName("README");
+ show.exec();
+}
+
+void MainWindow::on_action_Changelog_triggered()
+{
+ ShowTextFile show;
+ show.setFileName("ChangeLog");
+ show.exec();
+}
+
+void MainWindow::on_action_License_triggered()
+{
+ ShowTextFile show;
+ show.setFileName("COPYING");
+ show.exec();
+}
+
+void MainWindow::on_pbHTMLChooseStyleIncFile_clicked()
+{
+ selectSingleFile(ui->leHTMLStyleIncFile, tr("Choose a style include file"), "*.css");
+}
+void MainWindow::on_pbSVGChooseStyleIncFile_clicked()
+{
+ selectSingleFile(ui->leSVGStyleIncFile, tr("Choose a style include file"), "*.css");
+}
+void MainWindow::on_pbLATEXChooseStyleIncFile_clicked()
+{
+ selectSingleFile(ui->leLATEXStyleIncFile, tr("Choose a style include file"), "*.sty");
+}
+
+void MainWindow::on_pbTEXChooseStyleIncFile_clicked()
+{
+ selectSingleFile(ui->leTEXStyleIncFile, tr("Choose a style include file"), "*.sty");
+}
+
+
+void MainWindow::on_actionAbout_translations_triggered()
+{
+ QMessageBox::information(this, tr("About providing translations"),
+ tr("The GUI was developed using the Qt toolkit, and "
+ "translations may be provided using the tools Qt Linguist and lrelease.\n"
+ "The highlight.ts file for Linguist resides in the src/gui-qt subdirectory.\n"
+ "The qm file generated by lrelease has to be saved in gui-files/l10n.\n\n"
+ "Please send a note to as (at) andre-simon (dot) de if you have issues during translating "
+ "or if you have finished or updated a translation."));
+}
+
+ void MainWindow::dropEvent(QDropEvent *event)
+ {
+ const QMimeData *mimeData = event->mimeData();
+
+ if (mimeData && mimeData->hasUrls()) {
+ QList<QUrl> urlList = mimeData->urls();
+ QString url;
+ for (int i = 0; i < urlList.size(); ++i) {
+ url=urlList.at(i).toLocalFile();
+ if (ui->lvInputFiles->findItems ( url, Qt::MatchExactly ).empty()) {
+ ui->lvInputFiles->addItem(url);
+ }
+ }
+ }
+ event->acceptProposedAction();
+ }
+
+ void MainWindow::dragEnterEvent(QDragEnterEvent *event)
+ {
+ event->acceptProposedAction();
+ }
+
+ void MainWindow::dragMoveEvent(QDragMoveEvent *event)
+ {
+ event->acceptProposedAction();
+ }
+
+ void MainWindow::dragLeaveEvent(QDragLeaveEvent *event)
+ {
+ event->accept();
+ }
+
+void MainWindow::on_pbPasteFromCB_clicked()
+{
+ QClipboard *clipboard = QApplication::clipboard();
+ if (clipboard) {
+ savedClipboardContent = clipboard->text();
+ updatePreview();
+ ui->pbCopyToCP->setEnabled(!savedClipboardContent.isEmpty());
+ }
+
+}
+
+void MainWindow::on_pbCopyToCP_clicked()
+{
+ highlight2Clipboard(true);
+}
diff --git a/support/highlight/src/gui-qt/mainwindow.h b/support/highlight/src/gui-qt/mainwindow.h new file mode 100644 index 0000000000..89c181168a --- /dev/null +++ b/support/highlight/src/gui-qt/mainwindow.h @@ -0,0 +1,123 @@ +/***************************************************************************
+ mainwindow.h
+ -------------------
+ begin : Mo 16.03.2009
+ copyright : (C) 2009 by Andre Simon
+ email : andre.simon1@gmx.de
+ ***************************************************************************/
+
+/*
+This file is part of Highlight.
+
+Highlight is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+Highlight is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Highlight. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef MAINWINDOW_H
+#define MAINWINDOW_H
+
+#include <QtGui/QMainWindow>
+#include <QtGui/QMessageBox>
+#include <QtGui/QFileDialog>
+#include <QSettings>
+#include <QDir>
+#include <QClipboard>
+#include <QMimeData>
+#include <QTime>
+#include <QLineEdit>
+#include <QString>
+#include <QTextStream>
+#include <QScrollBar>
+#include <QDropEvent>
+
+#include "version.h"
+#include "codegenerator.h"
+#include "htmlgenerator.h"
+#include "configurationreader.h"
+
+#include "enums.h"
+
+typedef map<string, string> StringMap;
+
+namespace Ui
+{
+ class MainWindowClass;
+}
+
+class MainWindow : public QMainWindow
+{
+ Q_OBJECT
+
+public:
+ MainWindow(QWidget *parent = 0);
+ ~MainWindow();
+
+ void addInputFiles(const QStringList& list);
+
+private:
+ Ui::MainWindowClass *ui;
+ StringMap extensions, shebangs;
+ QString fileOpenFilter;
+ QString savedClipboardContent;
+
+ void readSettings();
+ void writeSettings();
+ highlight::OutputType getOutputType();
+ highlight::WrapMode getWrappingStyle();
+ QString getOutFileSuffix();
+ void applyCtrlValues(highlight::CodeGenerator* generator, bool previewMode);
+ void selectSingleFile(QLineEdit*, const QString&, const QString&);
+ bool loadFileTypeConfig(StringMap* extMap, StringMap* shebangMap);
+ void highlight2Clipboard(bool getDataFromCP);
+
+ string analyzeFile(const string& file);
+ string getFileType(const string& suffix, const string &inputFile);
+ string getFileSuffix(const string& fileName);
+
+ void dragEnterEvent(QDragEnterEvent *event);
+ void dragMoveEvent(QDragMoveEvent *event);
+ void dragLeaveEvent(QDragLeaveEvent *event);
+ void dropEvent(QDropEvent *event);
+
+public slots:
+ //This is a slot like the ones we used in our last tutorial
+ // The difference here that it gets automatically connect
+ // If you use on_objectname_signalname it's like connect(pushButton,SIGNAL(clicked()),this,SLOT(on_pushButton_clicked()))
+
+ void on_pbClearSelection_clicked();
+ void on_pbOutputDest_clicked();
+ void on_pbStartConversion_clicked();
+ void on_pbCopyFile2CP_clicked();
+
+private slots:
+
+ void on_pbCopyToCP_clicked();
+ void on_pbPasteFromCB_clicked();
+ void on_actionAbout_translations_triggered();
+ void on_pbTEXChooseStyleIncFile_clicked();
+ void on_pbLATEXChooseStyleIncFile_clicked();
+ void on_pbHTMLChooseStyleIncFile_clicked();
+ void on_pbSVGChooseStyleIncFile_clicked();
+ void on_action_License_triggered();
+ void on_action_Changelog_triggered();
+ void on_action_Manual_triggered();
+ void on_pbHTMLChooseTagsFile_clicked();
+ void on_action_About_Highlight_triggered();
+ void on_action_Exit_triggered();
+ void plausibility();
+ void updatePreview();
+ void openFiles();
+
+};
+
+#endif // MAINWINDOW_H
diff --git a/support/highlight/src/gui-qt/mainwindow.ui b/support/highlight/src/gui-qt/mainwindow.ui new file mode 100644 index 0000000000..0bb46f6216 --- /dev/null +++ b/support/highlight/src/gui-qt/mainwindow.ui @@ -0,0 +1,2147 @@ +<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>MainWindowClass</class>
+ <widget class="QMainWindow" name="MainWindowClass">
+ <property name="windowModality">
+ <enum>Qt::ApplicationModal</enum>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>600</width>
+ <height>645</height>
+ </rect>
+ </property>
+ <property name="acceptDrops">
+ <bool>false</bool>
+ </property>
+ <property name="windowTitle">
+ <string>Highlight</string>
+ </property>
+ <property name="windowIcon">
+ <iconset resource="highlight-gui.qrc">
+ <normaloff>:/hl_icon2.png</normaloff>:/hl_icon2.png</iconset>
+ </property>
+ <widget class="QWidget" name="centralWidget">
+ <layout class="QHBoxLayout" name="horizontalLayout_24">
+ <item>
+ <layout class="QVBoxLayout" name="verticalLayout_7">
+ <item>
+ <widget class="QTabWidget" name="tabIOSelection">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Minimum" vsizetype="Expanding">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="currentIndex">
+ <number>1</number>
+ </property>
+ <widget class="QWidget" name="tab_file_io">
+ <attribute name="title">
+ <string>Files</string>
+ </attribute>
+ <layout class="QVBoxLayout" name="verticalLayout_3">
+ <item>
+ <widget class="QPushButton" name="pbOpenFiles">
+ <property name="toolTip">
+ <string>Choose the source code files you want to convert.</string>
+ </property>
+ <property name="whatsThis">
+ <string/>
+ </property>
+ <property name="text">
+ <string>Choose input files</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QListWidget" name="lvInputFiles">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="MinimumExpanding">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>50</height>
+ </size>
+ </property>
+ <property name="acceptDrops">
+ <bool>false</bool>
+ </property>
+ <property name="toolTip">
+ <string>List of input files.</string>
+ </property>
+ <property name="dragDropMode">
+ <enum>QAbstractItemView::DropOnly</enum>
+ </property>
+ <property name="alternatingRowColors">
+ <bool>true</bool>
+ </property>
+ <property name="selectionMode">
+ <enum>QAbstractItemView::ExtendedSelection</enum>
+ </property>
+ <property name="selectionBehavior">
+ <enum>QAbstractItemView::SelectRows</enum>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <item>
+ <widget class="QPushButton" name="pbClearSelection">
+ <property name="toolTip">
+ <string>Remove the selected input files.</string>
+ </property>
+ <property name="text">
+ <string>Clear selection</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="pbClearAll">
+ <property name="toolTip">
+ <string>Remove all input files.</string>
+ </property>
+ <property name="text">
+ <string>Clear all</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <widget class="Line" name="line_11">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <widget class="QLabel" name="label_11">
+ <property name="font">
+ <font>
+ <weight>75</weight>
+ <bold>true</bold>
+ </font>
+ </property>
+ <property name="text">
+ <string>Output destination:</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_22">
+ <item>
+ <widget class="QLineEdit" name="leOutputDest">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Minimum" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="toolTip">
+ <string>Output directory</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="pbOutputDest">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>20</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="toolTip">
+ <string>Select the output directory.</string>
+ </property>
+ <property name="text">
+ <string>...</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <widget class="QCheckBox" name="cbWrite2Src">
+ <property name="toolTip">
+ <string>Save output in the input file directories.</string>
+ </property>
+ <property name="text">
+ <string>Write to source directories</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <widget class="Line" name="line_2">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="pbStartConversion">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>120</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="font">
+ <font>
+ <family>MS Shell Dlg 2</family>
+ <pointsize>10</pointsize>
+ <weight>75</weight>
+ <bold>true</bold>
+ </font>
+ </property>
+ <property name="toolTip">
+ <string>Start the conversion of your input files.</string>
+ </property>
+ <property name="text">
+ <string>Convert files</string>
+ </property>
+ <property name="default">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="pbCopyFile2CP">
+ <property name="toolTip">
+ <string>Copy highlighted code of the seleted file into the clipboard.</string>
+ </property>
+ <property name="text">
+ <string>Copy file to clipboard</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QWidget" name="tab_clipboard">
+ <attribute name="title">
+ <string>Clipboard</string>
+ </attribute>
+ <layout class="QVBoxLayout" name="verticalLayout_15">
+ <item>
+ <widget class="QPushButton" name="pbPasteFromCB">
+ <property name="toolTip">
+ <string>Paste clipboard content into the preview window.</string>
+ </property>
+ <property name="text">
+ <string>Paste from clipboard</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_23">
+ <item>
+ <widget class="QLabel" name="label_13">
+ <property name="text">
+ <string>Select syntax:</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QComboBox" name="comboSelectSyntax">
+ <property name="toolTip">
+ <string>Select the correct syntax of the code snippet.</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <widget class="Line" name="line_14">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="pbCopyToCP">
+ <property name="font">
+ <font>
+ <weight>75</weight>
+ <bold>true</bold>
+ </font>
+ </property>
+ <property name="toolTip">
+ <string>Copy highlighted code into the clipboard.</string>
+ </property>
+ <property name="text">
+ <string>Copy preview to clipboard</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="verticalSpacer_12">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>106</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </widget>
+ </widget>
+ </item>
+ <item>
+ <widget class="Line" name="line_7">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QTabWidget" name="tabWidget">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Minimum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="layoutDirection">
+ <enum>Qt::LeftToRight</enum>
+ </property>
+ <property name="tabPosition">
+ <enum>QTabWidget::North</enum>
+ </property>
+ <property name="tabShape">
+ <enum>QTabWidget::Rounded</enum>
+ </property>
+ <property name="currentIndex">
+ <number>2</number>
+ </property>
+ <widget class="QWidget" name="page_general">
+ <attribute name="title">
+ <string>General</string>
+ </attribute>
+ <layout class="QVBoxLayout" name="verticalLayout_2">
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_8">
+ <item>
+ <widget class="QLabel" name="label_2">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="font">
+ <font>
+ <weight>75</weight>
+ <bold>true</bold>
+ </font>
+ </property>
+ <property name="text">
+ <string>Output format:</string>
+ </property>
+ <property name="buddy">
+ <cstring>comboFormat</cstring>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QComboBox" name="comboFormat">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="font">
+ <font>
+ <weight>75</weight>
+ <bold>true</bold>
+ </font>
+ </property>
+ <property name="toolTip">
+ <string>Choose an output format.</string>
+ </property>
+ <item>
+ <property name="text">
+ <string>HTML</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>XHTML</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>LaTeX</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>TeX</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>RTF</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>SVG</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>XML</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>BBCode</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <widget class="Line" name="line_9">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_21">
+ <item>
+ <widget class="QCheckBox" name="cbIncLineNo">
+ <property name="toolTip">
+ <string>Add line numbers to the output.</string>
+ </property>
+ <property name="text">
+ <string>Add line numbers</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer_4">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>10</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QSpinBox" name="sbLineNoWidth">
+ <property name="toolTip">
+ <string>Select the line number width.</string>
+ </property>
+ <property name="minimum">
+ <number>1</number>
+ </property>
+ <property name="maximum">
+ <number>6</number>
+ </property>
+ <property name="value">
+ <number>2</number>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <widget class="QCheckBox" name="cbPadZeroes">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="toolTip">
+ <string>Fill leading space of line numbers with zeroes.</string>
+ </property>
+ <property name="text">
+ <string>Pad with zeroes</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QCheckBox" name="cbFragment">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="toolTip">
+ <string>Generate output without document header and footer.</string>
+ </property>
+ <property name="text">
+ <string>Omit header and footer</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QCheckBox" name="cbValidateInput">
+ <property name="toolTip">
+ <string>Test if input data is not binary.
+Removes Unicode BOM mark.</string>
+ </property>
+ <property name="text">
+ <string>Validate input data</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_2">
+ <item>
+ <widget class="QCheckBox" name="cbEncoding">
+ <property name="toolTip">
+ <string>Set the output file ancoding.</string>
+ </property>
+ <property name="text">
+ <string>Set encoding:</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QComboBox" name="comboEncoding">
+ <property name="toolTip">
+ <string>Select or define the encoding.
+The result has to match the input file encoding.</string>
+ </property>
+ <property name="editable">
+ <bool>true</bool>
+ </property>
+ <property name="insertPolicy">
+ <enum>QComboBox::InsertAtBottom</enum>
+ </property>
+ <item>
+ <property name="text">
+ <string>ISO-8859-1</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>ISO-8859-2</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>ISO-8859-3</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>ISO-8859-4</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>ISO-8859-5</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>ISO-8859-6</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>ISO-8859-7</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>ISO-8859-8</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>ISO-8859-9</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>ISO-8859-10</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>ISO-8859-11</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>ISO-8859-12</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>ISO-8859-13</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>ISO-8859-14</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>ISO-8859-15</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>UTF-8</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <spacer name="verticalSpacer_2">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QWidget" name="page_output_spec">
+ <attribute name="title">
+ <string>Output specific</string>
+ </attribute>
+ <layout class="QGridLayout" name="gridLayout">
+ <item row="0" column="0">
+ <widget class="QStackedWidget" name="stackedSpecificOptions">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Ignored">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="currentIndex">
+ <number>0</number>
+ </property>
+ <widget class="QWidget" name="HTMLOptions">
+ <layout class="QVBoxLayout" name="verticalLayout_5">
+ <item>
+ <widget class="QLabel" name="label_17">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="font">
+ <font>
+ <weight>75</weight>
+ <bold>true</bold>
+ </font>
+ </property>
+ <property name="text">
+ <string>HTML options</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="Line" name="line_12">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QTabWidget" name="tabWidget">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>250</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="currentIndex">
+ <number>0</number>
+ </property>
+ <widget class="QWidget" name="tabWidgetPage1">
+ <attribute name="title">
+ <string>Stylesheets</string>
+ </attribute>
+ <layout class="QGridLayout" name="gridLayout_4">
+ <item row="0" column="0">
+ <layout class="QHBoxLayout" name="horizontalLayout_10">
+ <item>
+ <widget class="QCheckBox" name="cbHTMLEmbedStyle">
+ <property name="toolTip">
+ <string>Include the style information in each output file.</string>
+ </property>
+ <property name="text">
+ <string>Embed style (CSS)</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QCheckBox" name="cbHTMLInlineCSS">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="toolTip">
+ <string>Add CSS information to each tag (do not use CSS class definitions).</string>
+ </property>
+ <property name="text">
+ <string>Inline CSS</string>
+ </property>
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item row="1" column="0">
+ <layout class="QHBoxLayout" name="horizontalLayout_14">
+ <item>
+ <widget class="QLabel" name="label_19">
+ <property name="text">
+ <string>Stylesheet file:</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLineEdit" name="leHTMLStyleFile">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="toolTip">
+ <string>Name of the referenced style file.</string>
+ </property>
+ <property name="text">
+ <string>highlight.css</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item row="2" column="0">
+ <layout class="QHBoxLayout" name="horizontalLayout_9">
+ <item>
+ <widget class="QLabel" name="label_20">
+ <property name="text">
+ <string>Include:</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLineEdit" name="leHTMLStyleIncFile">
+ <property name="toolTip">
+ <string>Path of the CSS include file.</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="pbHTMLChooseStyleIncFile">
+ <property name="toolTip">
+ <string>Select a CSS include file.</string>
+ </property>
+ <property name="text">
+ <string>...</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item row="3" column="0">
+ <layout class="QHBoxLayout" name="horizontalLayout_7">
+ <item>
+ <widget class="QLabel" name="label">
+ <property name="text">
+ <string>CSS class prefix:</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLineEdit" name="leHTMLCssPrefix">
+ <property name="toolTip">
+ <string>Add a CSS class name prefix to avoid namespace clashes.</string>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item row="4" column="0">
+ <spacer name="verticalSpacer_9">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>QSizePolicy::MinimumExpanding</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QWidget" name="tabWidgetPage2">
+ <attribute name="title">
+ <string>Index/ctags</string>
+ </attribute>
+ <layout class="QVBoxLayout" name="verticalLayout_6">
+ <item>
+ <widget class="QCheckBox" name="cbHTMLIndex">
+ <property name="toolTip">
+ <string>Generate an index file with hyperlinks to all outputted files.</string>
+ </property>
+ <property name="text">
+ <string>Generate index file</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="Line" name="line_13">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QCheckBox" name="cbHTMLCtags">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="toolTip">
+ <string>Read a ctags file and add the included metainformation as tooltips.
+See ctags.sf.net for details.</string>
+ </property>
+ <property name="text">
+ <string>Read ctags file:</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_12">
+ <item>
+ <widget class="QLineEdit" name="leHTMLCtagsFile">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="toolTip">
+ <string>Path of the ctags file.</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="pbHTMLChooseTagsFile">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="toolTip">
+ <string>Choose a ctags file.</string>
+ </property>
+ <property name="text">
+ <string>...</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <spacer name="verticalSpacer_8">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>QSizePolicy::Expanding</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>72</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QWidget" name="tabWidgetPage3">
+ <attribute name="title">
+ <string>Misc</string>
+ </attribute>
+ <layout class="QVBoxLayout" name="verticalLayout_4">
+ <item>
+ <widget class="QLabel" name="label_8">
+ <property name="font">
+ <font>
+ <weight>50</weight>
+ <bold>false</bold>
+ </font>
+ </property>
+ <property name="text">
+ <string>Line numbering options:</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QCheckBox" name="cbHTMLAnchors">
+ <property name="toolTip">
+ <string>Add an achor to each line.</string>
+ </property>
+ <property name="text">
+ <string>Add line anchors</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QCheckBox" name="cbHTMLFileNameAnchor">
+ <property name="toolTip">
+ <string>Add the filename as prefix to the anchors.</string>
+ </property>
+ <property name="text">
+ <string>Include file name in anchor</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QCheckBox" name="cbHTMLOrderedList">
+ <property name="toolTip">
+ <string>Output the lines within an ordered list.</string>
+ </property>
+ <property name="text">
+ <string>Output as ordered list</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="Line" name="line_4">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QCheckBox" name="cbHTMLEnclosePreTags">
+ <property name="toolTip">
+ <string>Add &lt;pre&gt; tags to the output, if the flag "No document header and footer" is selected.</string>
+ </property>
+ <property name="text">
+ <string>Enclose in pre tags</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="verticalSpacer">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>24</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </widget>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QWidget" name="LATEXOptions">
+ <layout class="QVBoxLayout" name="verticalLayout_12">
+ <item>
+ <widget class="QLabel" name="label_18">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Maximum" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="font">
+ <font>
+ <weight>75</weight>
+ <bold>true</bold>
+ </font>
+ </property>
+ <property name="text">
+ <string>LaTeX options</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="Line" name="line_8">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QCheckBox" name="cbLATEXEscQuotes">
+ <property name="toolTip">
+ <string>Replace quotes by dq sequences.</string>
+ </property>
+ <property name="text">
+ <string>Escape quotes</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QCheckBox" name="cbLATEXBabel">
+ <property name="toolTip">
+ <string>Make output Babel compatible.</string>
+ </property>
+ <property name="text">
+ <string>Add Babel compatibility</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QCheckBox" name="cbLATEXPrettySymbols">
+ <property name="toolTip">
+ <string>Replace default symbols (brackets, tilde) by nice redefinitions.</string>
+ </property>
+ <property name="text">
+ <string>Add pretty symbols</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QCheckBox" name="cbLATEXEmbedStyle">
+ <property name="toolTip">
+ <string>Include the style information in each output file.</string>
+ </property>
+ <property name="text">
+ <string>Embed style (defs)</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_17">
+ <item>
+ <widget class="QLabel" name="label_21">
+ <property name="text">
+ <string>Stylesheet file:</string>
+ </property>
+ <property name="buddy">
+ <cstring>leLATEXStyleFile</cstring>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLineEdit" name="leLATEXStyleFile">
+ <property name="toolTip">
+ <string>Name of the referenced style file.</string>
+ </property>
+ <property name="text">
+ <string>highlight.sty</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_15">
+ <item>
+ <widget class="QLabel" name="label_22">
+ <property name="text">
+ <string>Stylesheet include file:</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer_2">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_16">
+ <item>
+ <widget class="QLineEdit" name="leLATEXStyleIncFile">
+ <property name="toolTip">
+ <string>Path of the style include file.</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="pbLATEXChooseStyleIncFile">
+ <property name="toolTip">
+ <string>Select a style include file.</string>
+ </property>
+ <property name="text">
+ <string>...</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <spacer name="verticalSpacer_4">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QWidget" name="TEXOptions">
+ <layout class="QVBoxLayout" name="verticalLayout_14">
+ <item>
+ <widget class="QLabel" name="label_26">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="font">
+ <font>
+ <weight>75</weight>
+ <bold>true</bold>
+ </font>
+ </property>
+ <property name="text">
+ <string>TeX options</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="Line" name="line_10">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QCheckBox" name="cbTEXEmbedStyle">
+ <property name="toolTip">
+ <string>Include the style information in each output file.</string>
+ </property>
+ <property name="text">
+ <string>Embed style (macros)</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_18">
+ <item>
+ <widget class="QLabel" name="label_24">
+ <property name="text">
+ <string>Stylesheet file:</string>
+ </property>
+ <property name="buddy">
+ <cstring>leTEXStyleFile</cstring>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLineEdit" name="leTEXStyleFile">
+ <property name="toolTip">
+ <string>Name of the referenced style file.</string>
+ </property>
+ <property name="text">
+ <string>highlight.sty</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_19">
+ <item>
+ <widget class="QLabel" name="label_25">
+ <property name="text">
+ <string>Stylesheet include file:</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer_3">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_20">
+ <item>
+ <widget class="QLineEdit" name="leTEXStyleIncFile">
+ <property name="toolTip">
+ <string>Path of the style include file.</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="pbTEXChooseStyleIncFile">
+ <property name="toolTip">
+ <string>Select a style include file.</string>
+ </property>
+ <property name="text">
+ <string>...</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <spacer name="verticalSpacer_5">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QWidget" name="RTFOptions">
+ <layout class="QVBoxLayout" name="verticalLayout_9">
+ <item>
+ <widget class="QLabel" name="label_15">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="font">
+ <font>
+ <weight>75</weight>
+ <bold>true</bold>
+ </font>
+ </property>
+ <property name="text">
+ <string>RTF options</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="Line" name="line_5">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QCheckBox" name="cbRTFCharStyles">
+ <property name="toolTip">
+ <string>Add character stylesheets with formatting information.
+You can select the stylesheets in your word processor to reformat additional text.</string>
+ </property>
+ <property name="text">
+ <string>Add character styles</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_11">
+ <item>
+ <widget class="QLabel" name="label_9">
+ <property name="text">
+ <string>Page size:</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QComboBox" name="comboRTFPageSize">
+ <property name="toolTip">
+ <string>Select a page size.</string>
+ </property>
+ <property name="currentIndex">
+ <number>1</number>
+ </property>
+ <item>
+ <property name="text">
+ <string>A3</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>A4</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>A5</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>B4</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>B5</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>B6</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Letter</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Legal</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <spacer name="verticalSpacer_6">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QWidget" name="SVGOptions">
+ <layout class="QVBoxLayout" name="verticalLayout_10">
+ <item>
+ <widget class="QLabel" name="label_16">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="font">
+ <font>
+ <weight>75</weight>
+ <bold>true</bold>
+ </font>
+ </property>
+ <property name="text">
+ <string>SVG options</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="Line" name="line_6">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="label_10">
+ <property name="text">
+ <string>Image size:</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <layout class="QGridLayout" name="gridLayout_8">
+ <item row="0" column="0">
+ <widget class="QLabel" name="label_3">
+ <property name="text">
+ <string>Width:</string>
+ </property>
+ <property name="buddy">
+ <cstring>leSVGWidth</cstring>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QLineEdit" name="leSVGWidth">
+ <property name="toolTip">
+ <string>Enter the SVG width (may contain units).</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="label_12">
+ <property name="text">
+ <string>Height:</string>
+ </property>
+ <property name="buddy">
+ <cstring>leSVGHeight</cstring>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QLineEdit" name="leSVGHeight">
+ <property name="toolTip">
+ <string>Enter the SVG height (may contain units).</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <widget class="QCheckBox" name="cbSVGEmbedStyle">
+ <property name="toolTip">
+ <string>Include the style information in each output file.</string>
+ </property>
+ <property name="text">
+ <string>Embed style (CSS)</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_26">
+ <item>
+ <widget class="QLabel" name="label_29">
+ <property name="text">
+ <string>Stylesheet file:</string>
+ </property>
+ <property name="buddy">
+ <cstring>leSVGStyleFile</cstring>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLineEdit" name="leSVGStyleFile">
+ <property name="toolTip">
+ <string>Name of the referenced style file.</string>
+ </property>
+ <property name="text">
+ <string>highlight.css</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_27">
+ <item>
+ <widget class="QLabel" name="label_30">
+ <property name="text">
+ <string>Stylesheet include file:</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer_6">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_28">
+ <item>
+ <widget class="QLineEdit" name="leSVGStyleIncFile">
+ <property name="toolTip">
+ <string>Path of the CSS include file.</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="pbSVGChooseStyleIncFile">
+ <property name="toolTip">
+ <string>Select a style include file.</string>
+ </property>
+ <property name="text">
+ <string>...</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <spacer name="verticalSpacer_10">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QWidget" name="EmptyPage">
+ <layout class="QVBoxLayout" name="verticalLayout_11">
+ <item>
+ <widget class="QLabel" name="label_7">
+ <property name="text">
+ <string>No options defined.</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="verticalSpacer_3">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </widget>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QWidget" name="page_formatting">
+ <attribute name="title">
+ <string>Formatting</string>
+ </attribute>
+ <layout class="QVBoxLayout" name="verticalLayout_8">
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_3">
+ <item>
+ <widget class="QLabel" name="label_5">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Color theme:</string>
+ </property>
+ <property name="buddy">
+ <cstring>comboTheme</cstring>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QComboBox" name="comboTheme">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="toolTip">
+ <string>Select a colour theme.</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_4">
+ <item>
+ <widget class="QCheckBox" name="cbReformat">
+ <property name="toolTip">
+ <string>Reformat and indent your code.
+This feature is enabled tor C, C++, C# and Java code.</string>
+ </property>
+ <property name="text">
+ <string>Reformat:</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QComboBox" name="comboReformat">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="toolTip">
+ <string>Choose a formatting scheme.</string>
+ </property>
+ <item>
+ <property name="text">
+ <string>Allman</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Banner</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>GNU</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Horstmann</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Java</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>K&R</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Linux</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>OTBS</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Stroustrup</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Whitesmith</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_5">
+ <item>
+ <widget class="QCheckBox" name="cbKwCase">
+ <property name="toolTip">
+ <string>Change the keyword case.</string>
+ </property>
+ <property name="text">
+ <string>Keyword case:</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QComboBox" name="comboKwCase">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="toolTip">
+ <string>Select a keyword case.</string>
+ </property>
+ <item>
+ <property name="text">
+ <string>UPPER</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>lower</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Capitalize</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_6">
+ <item>
+ <widget class="QLabel" name="label_6">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Tab width:</string>
+ </property>
+ <property name="buddy">
+ <cstring>sbTabWidth</cstring>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QSpinBox" name="sbTabWidth">
+ <property name="toolTip">
+ <string>Enter the number of spaces which replace a tab.
+Set the width to 0 to keep tabs.</string>
+ </property>
+ <property name="maximum">
+ <number>10</number>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <layout class="QGridLayout" name="gridLayout_2">
+ <item row="0" column="0">
+ <widget class="QCheckBox" name="cbWrapping">
+ <property name="toolTip">
+ <string>Enable line wrapping.</string>
+ </property>
+ <property name="text">
+ <string>Line wrapping</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QSpinBox" name="sbLineLength">
+ <property name="toolTip">
+ <string>Enter the maximum line length.</string>
+ </property>
+ <property name="minimum">
+ <number>60</number>
+ </property>
+ <property name="maximum">
+ <number>120</number>
+ </property>
+ <property name="singleStep">
+ <number>2</number>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QCheckBox" name="cbAdvWrapping">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="toolTip">
+ <string>Indent statements and function parameters after wrapping.</string>
+ </property>
+ <property name="text">
+ <string>Intelligent wrapping</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <spacer name="verticalSpacer_11">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>QSizePolicy::Minimum</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>13</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <widget class="Line" name="line_3">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <layout class="QGridLayout" name="gridLayout_9">
+ <item row="0" column="0">
+ <widget class="QLabel" name="label_23">
+ <property name="text">
+ <string>Font name:</string>
+ </property>
+ <property name="buddy">
+ <cstring>comboFontName</cstring>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QFontComboBox" name="comboFontName">
+ <property name="toolTip">
+ <string>Select or enter the font name.</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="label_4">
+ <property name="text">
+ <string>Font size:</string>
+ </property>
+ <property name="buddy">
+ <cstring>leFontSize</cstring>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QLineEdit" name="leFontSize">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="toolTip">
+ <string>Enter the font size.</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <widget class="Line" name="line">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <layout class="QVBoxLayout" name="verticalLayout_13">
+ <item>
+ <widget class="QLabel" name="lbPreview">
+ <property name="text">
+ <string>Preview</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QTextBrowser" name="browserPreview">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="toolTip">
+ <string/>
+ </property>
+ <property name="whatsThis">
+ <string/>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_13">
+ <item>
+ <widget class="QLabel" name="label_14">
+ <property name="text">
+ <string>Output progress:</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QProgressBar" name="progressBar">
+ <property name="value">
+ <number>0</number>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QMenuBar" name="menuBar">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>600</width>
+ <height>20</height>
+ </rect>
+ </property>
+ <widget class="QMenu" name="menu_File">
+ <property name="title">
+ <string>&File</string>
+ </property>
+ <addaction name="action_Open_files"/>
+ <addaction name="separator"/>
+ <addaction name="action_Exit"/>
+ </widget>
+ <widget class="QMenu" name="menu_Help">
+ <property name="title">
+ <string>&Help</string>
+ </property>
+ <addaction name="action_Tips"/>
+ <addaction name="action_Manual"/>
+ <addaction name="action_Changelog"/>
+ <addaction name="action_License"/>
+ <addaction name="separator"/>
+ <addaction name="actionAbout_translations"/>
+ <addaction name="separator"/>
+ <addaction name="action_About_Highlight"/>
+ </widget>
+ <addaction name="menu_File"/>
+ <addaction name="menu_Help"/>
+ </widget>
+ <widget class="QStatusBar" name="statusBar"/>
+ <action name="action_Open_files">
+ <property name="text">
+ <string>&Open files</string>
+ </property>
+ </action>
+ <action name="action_Exit">
+ <property name="text">
+ <string>&Exit</string>
+ </property>
+ </action>
+ <action name="action_Load">
+ <property name="text">
+ <string>&Load</string>
+ </property>
+ </action>
+ <action name="action_Save">
+ <property name="text">
+ <string>&Save</string>
+ </property>
+ </action>
+ <action name="actionLoad_default_project">
+ <property name="text">
+ <string>Load &default project</string>
+ </property>
+ </action>
+ <action name="action_Manual">
+ <property name="text">
+ <string>Readme</string>
+ </property>
+ </action>
+ <action name="action_Tips">
+ <property name="text">
+ <string>&Tips</string>
+ </property>
+ <property name="visible">
+ <bool>false</bool>
+ </property>
+ </action>
+ <action name="action_Changelog">
+ <property name="text">
+ <string>&Changelog</string>
+ </property>
+ </action>
+ <action name="action_License">
+ <property name="text">
+ <string>&License</string>
+ </property>
+ </action>
+ <action name="action_About_Highlight">
+ <property name="text">
+ <string>&About Highlight</string>
+ </property>
+ </action>
+ <action name="actionAbout_translations">
+ <property name="text">
+ <string>About &translations</string>
+ </property>
+ </action>
+ </widget>
+ <layoutdefault spacing="6" margin="11"/>
+ <tabstops>
+ <tabstop>pbOpenFiles</tabstop>
+ <tabstop>lvInputFiles</tabstop>
+ <tabstop>pbClearSelection</tabstop>
+ <tabstop>pbClearAll</tabstop>
+ <tabstop>tabWidget</tabstop>
+ <tabstop>comboFormat</tabstop>
+ <tabstop>cbIncLineNo</tabstop>
+ <tabstop>sbLineNoWidth</tabstop>
+ <tabstop>cbPadZeroes</tabstop>
+ <tabstop>cbFragment</tabstop>
+ <tabstop>cbValidateInput</tabstop>
+ <tabstop>cbEncoding</tabstop>
+ <tabstop>comboEncoding</tabstop>
+ <tabstop>cbHTMLEmbedStyle</tabstop>
+ <tabstop>cbHTMLInlineCSS</tabstop>
+ <tabstop>leHTMLStyleFile</tabstop>
+ <tabstop>leHTMLStyleIncFile</tabstop>
+ <tabstop>pbHTMLChooseStyleIncFile</tabstop>
+ <tabstop>leHTMLCssPrefix</tabstop>
+ <tabstop>cbHTMLIndex</tabstop>
+ <tabstop>cbHTMLCtags</tabstop>
+ <tabstop>leHTMLCtagsFile</tabstop>
+ <tabstop>pbHTMLChooseTagsFile</tabstop>
+ <tabstop>cbHTMLAnchors</tabstop>
+ <tabstop>cbHTMLFileNameAnchor</tabstop>
+ <tabstop>cbHTMLOrderedList</tabstop>
+ <tabstop>cbHTMLEnclosePreTags</tabstop>
+ <tabstop>cbLATEXEscQuotes</tabstop>
+ <tabstop>cbLATEXBabel</tabstop>
+ <tabstop>cbLATEXPrettySymbols</tabstop>
+ <tabstop>cbLATEXEmbedStyle</tabstop>
+ <tabstop>leLATEXStyleFile</tabstop>
+ <tabstop>leLATEXStyleIncFile</tabstop>
+ <tabstop>pbLATEXChooseStyleIncFile</tabstop>
+ <tabstop>cbTEXEmbedStyle</tabstop>
+ <tabstop>leTEXStyleFile</tabstop>
+ <tabstop>leTEXStyleIncFile</tabstop>
+ <tabstop>pbTEXChooseStyleIncFile</tabstop>
+ <tabstop>cbRTFCharStyles</tabstop>
+ <tabstop>comboRTFPageSize</tabstop>
+ <tabstop>leSVGWidth</tabstop>
+ <tabstop>leSVGHeight</tabstop>
+ <tabstop>cbSVGEmbedStyle</tabstop>
+ <tabstop>leSVGStyleFile</tabstop>
+ <tabstop>leSVGStyleIncFile</tabstop>
+ <tabstop>pbSVGChooseStyleIncFile</tabstop>
+ <tabstop>comboTheme</tabstop>
+ <tabstop>cbReformat</tabstop>
+ <tabstop>comboReformat</tabstop>
+ <tabstop>cbKwCase</tabstop>
+ <tabstop>comboKwCase</tabstop>
+ <tabstop>sbTabWidth</tabstop>
+ <tabstop>cbWrapping</tabstop>
+ <tabstop>sbLineLength</tabstop>
+ <tabstop>cbAdvWrapping</tabstop>
+ <tabstop>comboFontName</tabstop>
+ <tabstop>leFontSize</tabstop>
+ <tabstop>browserPreview</tabstop>
+ <tabstop>pbStartConversion</tabstop>
+ <tabstop>pbCopyFile2CP</tabstop>
+ </tabstops>
+ <resources>
+ <include location="highlight-gui.qrc"/>
+ </resources>
+ <connections>
+ <connection>
+ <sender>pbClearAll</sender>
+ <signal>clicked()</signal>
+ <receiver>lvInputFiles</receiver>
+ <slot>clear()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>285</x>
+ <y>420</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>218</x>
+ <y>228</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
diff --git a/support/highlight/src/gui-qt/moc_io_report.cpp b/support/highlight/src/gui-qt/moc_io_report.cpp new file mode 100644 index 0000000000..1b6ef11f60 --- /dev/null +++ b/support/highlight/src/gui-qt/moc_io_report.cpp @@ -0,0 +1,69 @@ +/**************************************************************************** +** Meta object code from reading C++ file 'io_report.h' +** +** Created: Wed Mar 31 16:43:41 2010 +** by: The Qt Meta Object Compiler version 62 (Qt 4.6.2) +** +** WARNING! All changes made in this file will be lost! +*****************************************************************************/ + +#include "io_report.h" +#if !defined(Q_MOC_OUTPUT_REVISION) +#error "The header file 'io_report.h' doesn't include <QObject>." +#elif Q_MOC_OUTPUT_REVISION != 62 +#error "This file was generated using the moc from 4.6.2. It" +#error "cannot be used with the include files from this version of Qt." +#error "(The moc has changed too much.)" +#endif + +QT_BEGIN_MOC_NAMESPACE +static const uint qt_meta_data_io_report[] = { + + // content: + 4, // revision + 0, // classname + 0, 0, // classinfo + 0, 0, // methods + 0, 0, // properties + 0, 0, // enums/sets + 0, 0, // constructors + 0, // flags + 0, // signalCount + + 0 // eod +}; + +static const char qt_meta_stringdata_io_report[] = { + "io_report\0" +}; + +const QMetaObject io_report::staticMetaObject = { + { &QDialog::staticMetaObject, qt_meta_stringdata_io_report, + qt_meta_data_io_report, 0 } +}; + +#ifdef Q_NO_DATA_RELOCATION +const QMetaObject &io_report::getStaticMetaObject() { return staticMetaObject; } +#endif //Q_NO_DATA_RELOCATION + +const QMetaObject *io_report::metaObject() const +{ + return QObject::d_ptr->metaObject ? QObject::d_ptr->metaObject : &staticMetaObject; +} + +void *io_report::qt_metacast(const char *_clname) +{ + if (!_clname) return 0; + if (!strcmp(_clname, qt_meta_stringdata_io_report)) + return static_cast<void*>(const_cast< io_report*>(this)); + return QDialog::qt_metacast(_clname); +} + +int io_report::qt_metacall(QMetaObject::Call _c, int _id, void **_a) +{ + _id = QDialog::qt_metacall(_c, _id, _a); + if (_id < 0) + return _id; + return _id; +} +QT_END_MOC_NAMESPACE diff --git a/support/highlight/src/gui-qt/moc_mainwindow.cpp b/support/highlight/src/gui-qt/moc_mainwindow.cpp new file mode 100644 index 0000000000..2182a76b07 --- /dev/null +++ b/support/highlight/src/gui-qt/moc_mainwindow.cpp @@ -0,0 +1,134 @@ +/**************************************************************************** +** Meta object code from reading C++ file 'mainwindow.h' +** +** Created: Wed Mar 31 16:43:41 2010 +** by: The Qt Meta Object Compiler version 62 (Qt 4.6.2) +** +** WARNING! All changes made in this file will be lost! +*****************************************************************************/ + +#include "mainwindow.h" +#if !defined(Q_MOC_OUTPUT_REVISION) +#error "The header file 'mainwindow.h' doesn't include <QObject>." +#elif Q_MOC_OUTPUT_REVISION != 62 +#error "This file was generated using the moc from 4.6.2. It" +#error "cannot be used with the include files from this version of Qt." +#error "(The moc has changed too much.)" +#endif + +QT_BEGIN_MOC_NAMESPACE +static const uint qt_meta_data_MainWindow[] = { + + // content: + 4, // revision + 0, // classname + 0, 0, // classinfo + 20, 14, // methods + 0, 0, // properties + 0, 0, // enums/sets + 0, 0, // constructors + 0, // flags + 0, // signalCount + + // slots: signature, parameters, type, tag, flags + 12, 11, 11, 11, 0x0a, + 42, 11, 11, 11, 0x0a, + 68, 11, 11, 11, 0x0a, + 99, 11, 11, 11, 0x0a, + 126, 11, 11, 11, 0x08, + 150, 11, 11, 11, 0x08, + 177, 11, 11, 11, 0x08, + 217, 11, 11, 11, 0x08, + 254, 11, 11, 11, 0x08, + 293, 11, 11, 11, 0x08, + 331, 11, 11, 11, 0x08, + 368, 11, 11, 11, 0x08, + 398, 11, 11, 11, 0x08, + 430, 11, 11, 11, 0x08, + 459, 11, 11, 11, 0x08, + 493, 11, 11, 11, 0x08, + 531, 11, 11, 11, 0x08, + 558, 11, 11, 11, 0x08, + 573, 11, 11, 11, 0x08, + 589, 11, 11, 11, 0x08, + + 0 // eod +}; + +static const char qt_meta_stringdata_MainWindow[] = { + "MainWindow\0\0on_pbClearSelection_clicked()\0" + "on_pbOutputDest_clicked()\0" + "on_pbStartConversion_clicked()\0" + "on_pbCopyFile2CP_clicked()\0" + "on_pbCopyToCP_clicked()\0" + "on_pbPasteFromCB_clicked()\0" + "on_actionAbout_translations_triggered()\0" + "on_pbTEXChooseStyleIncFile_clicked()\0" + "on_pbLATEXChooseStyleIncFile_clicked()\0" + "on_pbHTMLChooseStyleIncFile_clicked()\0" + "on_pbSVGChooseStyleIncFile_clicked()\0" + "on_action_License_triggered()\0" + "on_action_Changelog_triggered()\0" + "on_action_Manual_triggered()\0" + "on_pbHTMLChooseTagsFile_clicked()\0" + "on_action_About_Highlight_triggered()\0" + "on_action_Exit_triggered()\0plausibility()\0" + "updatePreview()\0openFiles()\0" +}; + +const QMetaObject MainWindow::staticMetaObject = { + { &QMainWindow::staticMetaObject, qt_meta_stringdata_MainWindow, + qt_meta_data_MainWindow, 0 } +}; + +#ifdef Q_NO_DATA_RELOCATION +const QMetaObject &MainWindow::getStaticMetaObject() { return staticMetaObject; } +#endif //Q_NO_DATA_RELOCATION + +const QMetaObject *MainWindow::metaObject() const +{ + return QObject::d_ptr->metaObject ? QObject::d_ptr->metaObject : &staticMetaObject; +} + +void *MainWindow::qt_metacast(const char *_clname) +{ + if (!_clname) return 0; + if (!strcmp(_clname, qt_meta_stringdata_MainWindow)) + return static_cast<void*>(const_cast< MainWindow*>(this)); + return QMainWindow::qt_metacast(_clname); +} + +int MainWindow::qt_metacall(QMetaObject::Call _c, int _id, void **_a) +{ + _id = QMainWindow::qt_metacall(_c, _id, _a); + if (_id < 0) + return _id; + if (_c == QMetaObject::InvokeMetaMethod) { + switch (_id) { + case 0: on_pbClearSelection_clicked(); break; + case 1: on_pbOutputDest_clicked(); break; + case 2: on_pbStartConversion_clicked(); break; + case 3: on_pbCopyFile2CP_clicked(); break; + case 4: on_pbCopyToCP_clicked(); break; + case 5: on_pbPasteFromCB_clicked(); break; + case 6: on_actionAbout_translations_triggered(); break; + case 7: on_pbTEXChooseStyleIncFile_clicked(); break; + case 8: on_pbLATEXChooseStyleIncFile_clicked(); break; + case 9: on_pbHTMLChooseStyleIncFile_clicked(); break; + case 10: on_pbSVGChooseStyleIncFile_clicked(); break; + case 11: on_action_License_triggered(); break; + case 12: on_action_Changelog_triggered(); break; + case 13: on_action_Manual_triggered(); break; + case 14: on_pbHTMLChooseTagsFile_clicked(); break; + case 15: on_action_About_Highlight_triggered(); break; + case 16: on_action_Exit_triggered(); break; + case 17: plausibility(); break; + case 18: updatePreview(); break; + case 19: openFiles(); break; + default: ; + } + _id -= 20; + } + return _id; +} +QT_END_MOC_NAMESPACE diff --git a/support/highlight/src/gui-qt/moc_showtextfile.cpp b/support/highlight/src/gui-qt/moc_showtextfile.cpp new file mode 100644 index 0000000000..dfd8aa34f6 --- /dev/null +++ b/support/highlight/src/gui-qt/moc_showtextfile.cpp @@ -0,0 +1,79 @@ +/**************************************************************************** +** Meta object code from reading C++ file 'showtextfile.h' +** +** Created: Wed Mar 31 16:43:42 2010 +** by: The Qt Meta Object Compiler version 62 (Qt 4.6.2) +** +** WARNING! All changes made in this file will be lost! +*****************************************************************************/ + +#include "showtextfile.h" +#if !defined(Q_MOC_OUTPUT_REVISION) +#error "The header file 'showtextfile.h' doesn't include <QObject>." +#elif Q_MOC_OUTPUT_REVISION != 62 +#error "This file was generated using the moc from 4.6.2. It" +#error "cannot be used with the include files from this version of Qt." +#error "(The moc has changed too much.)" +#endif + +QT_BEGIN_MOC_NAMESPACE +static const uint qt_meta_data_ShowTextFile[] = { + + // content: + 4, // revision + 0, // classname + 0, 0, // classinfo + 1, 14, // methods + 0, 0, // properties + 0, 0, // enums/sets + 0, 0, // constructors + 0, // flags + 0, // signalCount + + // slots: signature, parameters, type, tag, flags + 14, 13, 13, 13, 0x08, + + 0 // eod +}; + +static const char qt_meta_stringdata_ShowTextFile[] = { + "ShowTextFile\0\0on_pushButton_clicked()\0" +}; + +const QMetaObject ShowTextFile::staticMetaObject = { + { &QDialog::staticMetaObject, qt_meta_stringdata_ShowTextFile, + qt_meta_data_ShowTextFile, 0 } +}; + +#ifdef Q_NO_DATA_RELOCATION +const QMetaObject &ShowTextFile::getStaticMetaObject() { return staticMetaObject; } +#endif //Q_NO_DATA_RELOCATION + +const QMetaObject *ShowTextFile::metaObject() const +{ + return QObject::d_ptr->metaObject ? QObject::d_ptr->metaObject : &staticMetaObject; +} + +void *ShowTextFile::qt_metacast(const char *_clname) +{ + if (!_clname) return 0; + if (!strcmp(_clname, qt_meta_stringdata_ShowTextFile)) + return static_cast<void*>(const_cast< ShowTextFile*>(this)); + return QDialog::qt_metacast(_clname); +} + +int ShowTextFile::qt_metacall(QMetaObject::Call _c, int _id, void **_a) +{ + _id = QDialog::qt_metacall(_c, _id, _a); + if (_id < 0) + return _id; + if (_c == QMetaObject::InvokeMetaMethod) { + switch (_id) { + case 0: on_pushButton_clicked(); break; + default: ; + } + _id -= 1; + } + return _id; +} +QT_END_MOC_NAMESPACE diff --git a/support/highlight/src/gui-qt/precomp.h b/support/highlight/src/gui-qt/precomp.h new file mode 100644 index 0000000000..28d089ae02 --- /dev/null +++ b/support/highlight/src/gui-qt/precomp.h @@ -0,0 +1,26 @@ +#ifndef PRECOMP_H
+#define PRECOMP_H
+
+#if defined __cplusplus
+#include <QtGui/QMainWindow>
+#include <QtGui/QMessageBox>
+#include <QtGui/QFileDialog>
+#include <QSettings>
+#include <QDir>
+#include <QClipboard>
+#include <QMimeData>
+#include <QTime>
+#include <QLineEdit>
+#include <QString>
+#include <QTextStream>
+#include <QDropEvent>
+
+#include "version.h"
+#include "codegenerator.h"
+#include "htmlgenerator.h"
+#include "configurationreader.h"
+
+#include "enums.h"
+#endif
+
+#endif // PRECOMP_H
diff --git a/support/highlight/src/gui-qt/showtextfile.cpp b/support/highlight/src/gui-qt/showtextfile.cpp new file mode 100644 index 0000000000..dffdd131e8 --- /dev/null +++ b/support/highlight/src/gui-qt/showtextfile.cpp @@ -0,0 +1,72 @@ +
+/***************************************************************************
+ showtestfile.cpp
+ -------------------
+ begin : Mo 16.03.2009
+ copyright : (C) 2009 by Andre Simon
+ email : andre.simon1@gmx.de
+ ***************************************************************************/
+
+/*
+This file is part of Highlight.
+
+Highlight is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+Highlight is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Highlight. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "showtextfile.h"
+#include "ui_showtextfile.h"
+#include <QTextStream>
+
+ShowTextFile::ShowTextFile(QWidget *parent) :
+ QDialog(parent),
+ m_ui(new Ui::ShowTextFile)
+{
+ m_ui->setupUi(this);
+}
+
+ShowTextFile::~ShowTextFile()
+{
+ delete m_ui;
+}
+
+void ShowTextFile::changeEvent(QEvent *e)
+{
+ switch (e->type()) {
+ case QEvent::LanguageChange:
+ m_ui->retranslateUi(this);
+ break;
+ default:
+ break;
+ }
+}
+
+
+bool ShowTextFile::setFileName(const QString& fileName){
+#ifndef HL_DOC_DIR
+ QFile file( QString("%1/%2").arg(QDir::currentPath()).arg( fileName ));
+#else
+ QFile file( QString("%1/%2").arg(HL_DOC_DIR).arg(fileName ));
+#endif
+ if ( file.open( QIODevice::ReadOnly) ) {
+ QTextStream stream( &file );
+ m_ui->textEdit->setText( stream.readAll() );
+ m_ui->lbTitle->setText(fileName);
+ }
+ return file.exists();
+}
+
+void ShowTextFile::on_pushButton_clicked()
+{
+ this->close();
+}
diff --git a/support/highlight/src/gui-qt/showtextfile.h b/support/highlight/src/gui-qt/showtextfile.h new file mode 100644 index 0000000000..8840633ec6 --- /dev/null +++ b/support/highlight/src/gui-qt/showtextfile.h @@ -0,0 +1,54 @@ +/***************************************************************************
+ showtextfile.h
+ -------------------
+ begin : Mo 16.03.2009
+ copyright : (C) 2009 by Andre Simon
+ email : andre.simon1@gmx.de
+ ***************************************************************************/
+
+/*
+This file is part of Highlight.
+
+Highlight is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+Highlight is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Highlight. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef SHOWTEXTFILE_H
+#define SHOWTEXTFILE_H
+
+#include <QtGui/QDialog>
+
+
+namespace Ui {
+ class ShowTextFile;
+}
+
+class ShowTextFile : public QDialog {
+ Q_OBJECT
+ Q_DISABLE_COPY(ShowTextFile)
+public:
+ explicit ShowTextFile(QWidget *parent = 0);
+ virtual ~ShowTextFile();
+ bool setFileName(const QString& fileName);
+
+protected:
+ virtual void changeEvent(QEvent *e);
+
+private:
+ Ui::ShowTextFile *m_ui;
+
+private slots:
+ void on_pushButton_clicked();
+};
+
+#endif // SHOWTEXTFILE_H
diff --git a/support/highlight/src/gui-qt/showtextfile.ui b/support/highlight/src/gui-qt/showtextfile.ui new file mode 100644 index 0000000000..095ff23729 --- /dev/null +++ b/support/highlight/src/gui-qt/showtextfile.ui @@ -0,0 +1,84 @@ +<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>ShowTextFile</class>
+ <widget class="QDialog" name="ShowTextFile">
+ <property name="windowModality">
+ <enum>Qt::WindowModal</enum>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>711</width>
+ <height>442</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Show text</string>
+ </property>
+ <property name="windowIcon">
+ <iconset resource="highlight-gui.qrc">
+ <normaloff>:/hl_icon2.png</normaloff>:/hl_icon2.png</iconset>
+ </property>
+ <property name="modal">
+ <bool>true</bool>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <widget class="QLabel" name="lbTitle">
+ <property name="font">
+ <font>
+ <pointsize>10</pointsize>
+ <weight>75</weight>
+ <bold>true</bold>
+ </font>
+ </property>
+ <property name="text">
+ <string>TextLabel</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QTextEdit" name="textEdit">
+ <property name="font">
+ <font>
+ <family>Courier New</family>
+ <pointsize>8</pointsize>
+ </font>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <item>
+ <spacer name="horizontalSpacer">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QPushButton" name="pushButton">
+ <property name="text">
+ <string>OK</string>
+ </property>
+ <property name="default">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ <resources>
+ <include location="highlight-gui.qrc"/>
+ </resources>
+ <connections/>
+</ui>
diff --git a/support/highlight/src/gui-qt/ui_io_report.h b/support/highlight/src/gui-qt/ui_io_report.h new file mode 100644 index 0000000000..e9eaad349e --- /dev/null +++ b/support/highlight/src/gui-qt/ui_io_report.h @@ -0,0 +1,134 @@ +/******************************************************************************** +** Form generated from reading UI file 'io_report.ui' +** +** Created: Wed Mar 31 16:43:25 2010 +** by: Qt User Interface Compiler version 4.6.2 +** +** WARNING! All changes made in this file will be lost when recompiling UI file! +********************************************************************************/ + +#ifndef UI_IO_REPORT_H +#define UI_IO_REPORT_H + +#include <QtCore/QVariant> +#include <QtGui/QAction> +#include <QtGui/QApplication> +#include <QtGui/QButtonGroup> +#include <QtGui/QCheckBox> +#include <QtGui/QDialog> +#include <QtGui/QDialogButtonBox> +#include <QtGui/QFrame> +#include <QtGui/QHeaderView> +#include <QtGui/QLabel> +#include <QtGui/QListWidget> +#include <QtGui/QVBoxLayout> + +QT_BEGIN_NAMESPACE + +class Ui_io_report +{ +public: + QVBoxLayout *verticalLayout; + QLabel *label_2; + QListWidget *listInputErrors; + QCheckBox *cbRemoveFiles; + QFrame *line; + QLabel *label; + QListWidget *listOutputErrors; + QFrame *line_2; + QLabel *label_3; + QListWidget *listReformatErrors; + QDialogButtonBox *buttonBox; + + void setupUi(QDialog *io_report) + { + if (io_report->objectName().isEmpty()) + io_report->setObjectName(QString::fromUtf8("io_report")); + io_report->resize(436, 372); + QIcon icon; + icon.addFile(QString::fromUtf8(":/hl_icon2.png"), QSize(), QIcon::Normal, QIcon::Off); + io_report->setWindowIcon(icon); + verticalLayout = new QVBoxLayout(io_report); + verticalLayout->setObjectName(QString::fromUtf8("verticalLayout")); + label_2 = new QLabel(io_report); + label_2->setObjectName(QString::fromUtf8("label_2")); + + verticalLayout->addWidget(label_2); + + listInputErrors = new QListWidget(io_report); + listInputErrors->setObjectName(QString::fromUtf8("listInputErrors")); + + verticalLayout->addWidget(listInputErrors); + + cbRemoveFiles = new QCheckBox(io_report); + cbRemoveFiles->setObjectName(QString::fromUtf8("cbRemoveFiles")); + + verticalLayout->addWidget(cbRemoveFiles); + + line = new QFrame(io_report); + line->setObjectName(QString::fromUtf8("line")); + line->setFrameShape(QFrame::HLine); + line->setFrameShadow(QFrame::Sunken); + + verticalLayout->addWidget(line); + + label = new QLabel(io_report); + label->setObjectName(QString::fromUtf8("label")); + + verticalLayout->addWidget(label); + + listOutputErrors = new QListWidget(io_report); + listOutputErrors->setObjectName(QString::fromUtf8("listOutputErrors")); + + verticalLayout->addWidget(listOutputErrors); + + line_2 = new QFrame(io_report); + line_2->setObjectName(QString::fromUtf8("line_2")); + line_2->setFrameShape(QFrame::HLine); + line_2->setFrameShadow(QFrame::Sunken); + + verticalLayout->addWidget(line_2); + + label_3 = new QLabel(io_report); + label_3->setObjectName(QString::fromUtf8("label_3")); + + verticalLayout->addWidget(label_3); + + listReformatErrors = new QListWidget(io_report); + listReformatErrors->setObjectName(QString::fromUtf8("listReformatErrors")); + + verticalLayout->addWidget(listReformatErrors); + + buttonBox = new QDialogButtonBox(io_report); + buttonBox->setObjectName(QString::fromUtf8("buttonBox")); + buttonBox->setOrientation(Qt::Horizontal); + buttonBox->setStandardButtons(QDialogButtonBox::Ok); + + verticalLayout->addWidget(buttonBox); + + + retranslateUi(io_report); + QObject::connect(buttonBox, SIGNAL(accepted()), io_report, SLOT(accept())); + QObject::connect(buttonBox, SIGNAL(rejected()), io_report, SLOT(reject())); + + QMetaObject::connectSlotsByName(io_report); + } // setupUi + + void retranslateUi(QDialog *io_report) + { + io_report->setWindowTitle(QApplication::translate("io_report", "Error summary", 0, QApplication::UnicodeUTF8)); + label_2->setText(QApplication::translate("io_report", "Input errors:", 0, QApplication::UnicodeUTF8)); + cbRemoveFiles->setText(QApplication::translate("io_report", "Remove files above from input file list", 0, QApplication::UnicodeUTF8)); + label->setText(QApplication::translate("io_report", "Output errors:", 0, QApplication::UnicodeUTF8)); + label_3->setText(QApplication::translate("io_report", "Reformatting not possible:", 0, QApplication::UnicodeUTF8)); + } // retranslateUi + +}; + +namespace Ui { + class io_report: public Ui_io_report {}; +} // namespace Ui + +QT_END_NAMESPACE + +#endif // UI_IO_REPORT_H diff --git a/support/highlight/src/gui-qt/ui_mainwindow.h b/support/highlight/src/gui-qt/ui_mainwindow.h new file mode 100644 index 0000000000..ca73d3b551 --- /dev/null +++ b/support/highlight/src/gui-qt/ui_mainwindow.h @@ -0,0 +1,1860 @@ +/******************************************************************************** +** Form generated from reading UI file 'mainwindow.ui' +** +** Created: Wed Mar 31 16:43:25 2010 +** by: Qt User Interface Compiler version 4.6.2 +** +** WARNING! All changes made in this file will be lost when recompiling UI file! +********************************************************************************/ + +#ifndef UI_MAINWINDOW_H +#define UI_MAINWINDOW_H + +#include <QtCore/QVariant> +#include <QtGui/QAction> +#include <QtGui/QApplication> +#include <QtGui/QButtonGroup> +#include <QtGui/QCheckBox> +#include <QtGui/QComboBox> +#include <QtGui/QFontComboBox> +#include <QtGui/QFrame> +#include <QtGui/QGridLayout> +#include <QtGui/QHBoxLayout> +#include <QtGui/QHeaderView> +#include <QtGui/QLabel> +#include <QtGui/QLineEdit> +#include <QtGui/QListWidget> +#include <QtGui/QMainWindow> +#include <QtGui/QMenu> +#include <QtGui/QMenuBar> +#include <QtGui/QProgressBar> +#include <QtGui/QPushButton> +#include <QtGui/QSpacerItem> +#include <QtGui/QSpinBox> +#include <QtGui/QStackedWidget> +#include <QtGui/QStatusBar> +#include <QtGui/QTabWidget> +#include <QtGui/QTextBrowser> +#include <QtGui/QVBoxLayout> +#include <QtGui/QWidget> + +QT_BEGIN_NAMESPACE + +class Ui_MainWindowClass +{ +public: + QAction *action_Open_files; + QAction *action_Exit; + QAction *action_Load; + QAction *action_Save; + QAction *actionLoad_default_project; + QAction *action_Manual; + QAction *action_Tips; + QAction *action_Changelog; + QAction *action_License; + QAction *action_About_Highlight; + QAction *actionAbout_translations; + QWidget *centralWidget; + QHBoxLayout *horizontalLayout_24; + QVBoxLayout *verticalLayout_7; + QTabWidget *tabIOSelection; + QWidget *tab_file_io; + QVBoxLayout *verticalLayout_3; + QPushButton *pbOpenFiles; + QListWidget *lvInputFiles; + QHBoxLayout *horizontalLayout; + QPushButton *pbClearSelection; + QPushButton *pbClearAll; + QFrame *line_11; + QVBoxLayout *verticalLayout; + QLabel *label_11; + QHBoxLayout *horizontalLayout_22; + QLineEdit *leOutputDest; + QPushButton *pbOutputDest; + QCheckBox *cbWrite2Src; + QFrame *line_2; + QPushButton *pbStartConversion; + QPushButton *pbCopyFile2CP; + QWidget *tab_clipboard; + QVBoxLayout *verticalLayout_15; + QPushButton *pbPasteFromCB; + QHBoxLayout *horizontalLayout_23; + QLabel *label_13; + QComboBox *comboSelectSyntax; + QFrame *line_14; + QPushButton *pbCopyToCP; + QSpacerItem *verticalSpacer_12; + QFrame *line_7; + QTabWidget *tabWidget; + QWidget *page_general; + QVBoxLayout *verticalLayout_2; + QHBoxLayout *horizontalLayout_8; + QLabel *label_2; + QComboBox *comboFormat; + QFrame *line_9; + QHBoxLayout *horizontalLayout_21; + QCheckBox *cbIncLineNo; + QSpacerItem *horizontalSpacer_4; + QSpinBox *sbLineNoWidth; + QCheckBox *cbPadZeroes; + QCheckBox *cbFragment; + QCheckBox *cbValidateInput; + QHBoxLayout *horizontalLayout_2; + QCheckBox *cbEncoding; + QComboBox *comboEncoding; + QSpacerItem *verticalSpacer_2; + QWidget *page_output_spec; + QGridLayout *gridLayout; + QStackedWidget *stackedSpecificOptions; + QWidget *HTMLOptions; + QVBoxLayout *verticalLayout_5; + QLabel *label_17; + QFrame *line_12; + QTabWidget *tabWidget1; + QWidget *tabWidgetPage1; + QGridLayout *gridLayout_4; + QHBoxLayout *horizontalLayout_10; + QCheckBox *cbHTMLEmbedStyle; + QCheckBox *cbHTMLInlineCSS; + QHBoxLayout *horizontalLayout_14; + QLabel *label_19; + QLineEdit *leHTMLStyleFile; + QHBoxLayout *horizontalLayout_9; + QLabel *label_20; + QLineEdit *leHTMLStyleIncFile; + QPushButton *pbHTMLChooseStyleIncFile; + QHBoxLayout *horizontalLayout_7; + QLabel *label; + QLineEdit *leHTMLCssPrefix; + QSpacerItem *verticalSpacer_9; + QWidget *tabWidgetPage2; + QVBoxLayout *verticalLayout_6; + QCheckBox *cbHTMLIndex; + QFrame *line_13; + QCheckBox *cbHTMLCtags; + QHBoxLayout *horizontalLayout_12; + QLineEdit *leHTMLCtagsFile; + QPushButton *pbHTMLChooseTagsFile; + QSpacerItem *verticalSpacer_8; + QWidget *tabWidgetPage3; + QVBoxLayout *verticalLayout_4; + QLabel *label_8; + QCheckBox *cbHTMLAnchors; + QCheckBox *cbHTMLFileNameAnchor; + QCheckBox *cbHTMLOrderedList; + QFrame *line_4; + QCheckBox *cbHTMLEnclosePreTags; + QSpacerItem *verticalSpacer; + QWidget *LATEXOptions; + QVBoxLayout *verticalLayout_12; + QLabel *label_18; + QFrame *line_8; + QCheckBox *cbLATEXEscQuotes; + QCheckBox *cbLATEXBabel; + QCheckBox *cbLATEXPrettySymbols; + QCheckBox *cbLATEXEmbedStyle; + QHBoxLayout *horizontalLayout_17; + QLabel *label_21; + QLineEdit *leLATEXStyleFile; + QHBoxLayout *horizontalLayout_15; + QLabel *label_22; + QSpacerItem *horizontalSpacer_2; + QHBoxLayout *horizontalLayout_16; + QLineEdit *leLATEXStyleIncFile; + QPushButton *pbLATEXChooseStyleIncFile; + QSpacerItem *verticalSpacer_4; + QWidget *TEXOptions; + QVBoxLayout *verticalLayout_14; + QLabel *label_26; + QFrame *line_10; + QCheckBox *cbTEXEmbedStyle; + QHBoxLayout *horizontalLayout_18; + QLabel *label_24; + QLineEdit *leTEXStyleFile; + QHBoxLayout *horizontalLayout_19; + QLabel *label_25; + QSpacerItem *horizontalSpacer_3; + QHBoxLayout *horizontalLayout_20; + QLineEdit *leTEXStyleIncFile; + QPushButton *pbTEXChooseStyleIncFile; + QSpacerItem *verticalSpacer_5; + QWidget *RTFOptions; + QVBoxLayout *verticalLayout_9; + QLabel *label_15; + QFrame *line_5; + QCheckBox *cbRTFCharStyles; + QHBoxLayout *horizontalLayout_11; + QLabel *label_9; + QComboBox *comboRTFPageSize; + QSpacerItem *verticalSpacer_6; + QWidget *SVGOptions; + QVBoxLayout *verticalLayout_10; + QLabel *label_16; + QFrame *line_6; + QLabel *label_10; + QGridLayout *gridLayout_8; + QLabel *label_3; + QLineEdit *leSVGWidth; + QLabel *label_12; + QLineEdit *leSVGHeight; + QCheckBox *cbSVGEmbedStyle; + QHBoxLayout *horizontalLayout_26; + QLabel *label_29; + QLineEdit *leSVGStyleFile; + QHBoxLayout *horizontalLayout_27; + QLabel *label_30; + QSpacerItem *horizontalSpacer_6; + QHBoxLayout *horizontalLayout_28; + QLineEdit *leSVGStyleIncFile; + QPushButton *pbSVGChooseStyleIncFile; + QSpacerItem *verticalSpacer_10; + QWidget *EmptyPage; + QVBoxLayout *verticalLayout_11; + QLabel *label_7; + QSpacerItem *verticalSpacer_3; + QWidget *page_formatting; + QVBoxLayout *verticalLayout_8; + QHBoxLayout *horizontalLayout_3; + QLabel *label_5; + QComboBox *comboTheme; + QHBoxLayout *horizontalLayout_4; + QCheckBox *cbReformat; + QComboBox *comboReformat; + QHBoxLayout *horizontalLayout_5; + QCheckBox *cbKwCase; + QComboBox *comboKwCase; + QHBoxLayout *horizontalLayout_6; + QLabel *label_6; + QSpinBox *sbTabWidth; + QGridLayout *gridLayout_2; + QCheckBox *cbWrapping; + QSpinBox *sbLineLength; + QCheckBox *cbAdvWrapping; + QSpacerItem *verticalSpacer_11; + QFrame *line_3; + QGridLayout *gridLayout_9; + QLabel *label_23; + QFontComboBox *comboFontName; + QLabel *label_4; + QLineEdit *leFontSize; + QFrame *line; + QVBoxLayout *verticalLayout_13; + QLabel *lbPreview; + QTextBrowser *browserPreview; + QHBoxLayout *horizontalLayout_13; + QLabel *label_14; + QProgressBar *progressBar; + QMenuBar *menuBar; + QMenu *menu_File; + QMenu *menu_Help; + QStatusBar *statusBar; + + void setupUi(QMainWindow *MainWindowClass) + { + if (MainWindowClass->objectName().isEmpty()) + MainWindowClass->setObjectName(QString::fromUtf8("MainWindowClass")); + MainWindowClass->setWindowModality(Qt::ApplicationModal); + MainWindowClass->resize(600, 645); + MainWindowClass->setAcceptDrops(false); + QIcon icon; + icon.addFile(QString::fromUtf8(":/hl_icon2.png"), QSize(), QIcon::Normal, QIcon::Off); + MainWindowClass->setWindowIcon(icon); + action_Open_files = new QAction(MainWindowClass); + action_Open_files->setObjectName(QString::fromUtf8("action_Open_files")); + action_Exit = new QAction(MainWindowClass); + action_Exit->setObjectName(QString::fromUtf8("action_Exit")); + action_Load = new QAction(MainWindowClass); + action_Load->setObjectName(QString::fromUtf8("action_Load")); + action_Save = new QAction(MainWindowClass); + action_Save->setObjectName(QString::fromUtf8("action_Save")); + actionLoad_default_project = new QAction(MainWindowClass); + actionLoad_default_project->setObjectName(QString::fromUtf8("actionLoad_default_project")); + action_Manual = new QAction(MainWindowClass); + action_Manual->setObjectName(QString::fromUtf8("action_Manual")); + action_Tips = new QAction(MainWindowClass); + action_Tips->setObjectName(QString::fromUtf8("action_Tips")); + action_Tips->setVisible(false); + action_Changelog = new QAction(MainWindowClass); + action_Changelog->setObjectName(QString::fromUtf8("action_Changelog")); + action_License = new QAction(MainWindowClass); + action_License->setObjectName(QString::fromUtf8("action_License")); + action_About_Highlight = new QAction(MainWindowClass); + action_About_Highlight->setObjectName(QString::fromUtf8("action_About_Highlight")); + actionAbout_translations = new QAction(MainWindowClass); + actionAbout_translations->setObjectName(QString::fromUtf8("actionAbout_translations")); + centralWidget = new QWidget(MainWindowClass); + centralWidget->setObjectName(QString::fromUtf8("centralWidget")); + horizontalLayout_24 = new QHBoxLayout(centralWidget); + horizontalLayout_24->setSpacing(6); + horizontalLayout_24->setContentsMargins(11, 11, 11, 11); + horizontalLayout_24->setObjectName(QString::fromUtf8("horizontalLayout_24")); + verticalLayout_7 = new QVBoxLayout(); + verticalLayout_7->setSpacing(6); + verticalLayout_7->setObjectName(QString::fromUtf8("verticalLayout_7")); + tabIOSelection = new QTabWidget(centralWidget); + tabIOSelection->setObjectName(QString::fromUtf8("tabIOSelection")); + QSizePolicy sizePolicy(QSizePolicy::Minimum, QSizePolicy::Expanding); + sizePolicy.setHorizontalStretch(0); + sizePolicy.setVerticalStretch(0); + sizePolicy.setHeightForWidth(tabIOSelection->sizePolicy().hasHeightForWidth()); + tabIOSelection->setSizePolicy(sizePolicy); + tabIOSelection->setMinimumSize(QSize(0, 0)); + tab_file_io = new QWidget(); + tab_file_io->setObjectName(QString::fromUtf8("tab_file_io")); + verticalLayout_3 = new QVBoxLayout(tab_file_io); + verticalLayout_3->setSpacing(6); + verticalLayout_3->setContentsMargins(11, 11, 11, 11); + verticalLayout_3->setObjectName(QString::fromUtf8("verticalLayout_3")); + pbOpenFiles = new QPushButton(tab_file_io); + pbOpenFiles->setObjectName(QString::fromUtf8("pbOpenFiles")); + + verticalLayout_3->addWidget(pbOpenFiles); + + lvInputFiles = new QListWidget(tab_file_io); + lvInputFiles->setObjectName(QString::fromUtf8("lvInputFiles")); + QSizePolicy sizePolicy1(QSizePolicy::Preferred, QSizePolicy::MinimumExpanding); + sizePolicy1.setHorizontalStretch(0); + sizePolicy1.setVerticalStretch(0); + sizePolicy1.setHeightForWidth(lvInputFiles->sizePolicy().hasHeightForWidth()); + lvInputFiles->setSizePolicy(sizePolicy1); + lvInputFiles->setMinimumSize(QSize(0, 50)); + lvInputFiles->setAcceptDrops(false); + lvInputFiles->setDragDropMode(QAbstractItemView::DropOnly); + lvInputFiles->setAlternatingRowColors(true); + lvInputFiles->setSelectionMode(QAbstractItemView::ExtendedSelection); + lvInputFiles->setSelectionBehavior(QAbstractItemView::SelectRows); + + verticalLayout_3->addWidget(lvInputFiles); + + horizontalLayout = new QHBoxLayout(); + horizontalLayout->setSpacing(6); + horizontalLayout->setObjectName(QString::fromUtf8("horizontalLayout")); + pbClearSelection = new QPushButton(tab_file_io); + pbClearSelection->setObjectName(QString::fromUtf8("pbClearSelection")); + + horizontalLayout->addWidget(pbClearSelection); + + pbClearAll = new QPushButton(tab_file_io); + pbClearAll->setObjectName(QString::fromUtf8("pbClearAll")); + + horizontalLayout->addWidget(pbClearAll); + + + verticalLayout_3->addLayout(horizontalLayout); + + line_11 = new QFrame(tab_file_io); + line_11->setObjectName(QString::fromUtf8("line_11")); + line_11->setFrameShape(QFrame::HLine); + line_11->setFrameShadow(QFrame::Sunken); + + verticalLayout_3->addWidget(line_11); + + verticalLayout = new QVBoxLayout(); + verticalLayout->setSpacing(6); + verticalLayout->setObjectName(QString::fromUtf8("verticalLayout")); + label_11 = new QLabel(tab_file_io); + label_11->setObjectName(QString::fromUtf8("label_11")); + QFont font; + font.setBold(true); + font.setWeight(75); + label_11->setFont(font); + + verticalLayout->addWidget(label_11); + + horizontalLayout_22 = new QHBoxLayout(); + horizontalLayout_22->setSpacing(6); + horizontalLayout_22->setObjectName(QString::fromUtf8("horizontalLayout_22")); + leOutputDest = new QLineEdit(tab_file_io); + leOutputDest->setObjectName(QString::fromUtf8("leOutputDest")); + QSizePolicy sizePolicy2(QSizePolicy::Minimum, QSizePolicy::Preferred); + sizePolicy2.setHorizontalStretch(0); + sizePolicy2.setVerticalStretch(0); + sizePolicy2.setHeightForWidth(leOutputDest->sizePolicy().hasHeightForWidth()); + leOutputDest->setSizePolicy(sizePolicy2); + + horizontalLayout_22->addWidget(leOutputDest); + + pbOutputDest = new QPushButton(tab_file_io); + pbOutputDest->setObjectName(QString::fromUtf8("pbOutputDest")); + QSizePolicy sizePolicy3(QSizePolicy::Fixed, QSizePolicy::Fixed); + sizePolicy3.setHorizontalStretch(0); + sizePolicy3.setVerticalStretch(0); + sizePolicy3.setHeightForWidth(pbOutputDest->sizePolicy().hasHeightForWidth()); + pbOutputDest->setSizePolicy(sizePolicy3); + pbOutputDest->setMinimumSize(QSize(20, 0)); + + horizontalLayout_22->addWidget(pbOutputDest); + + + verticalLayout->addLayout(horizontalLayout_22); + + cbWrite2Src = new QCheckBox(tab_file_io); + cbWrite2Src->setObjectName(QString::fromUtf8("cbWrite2Src")); + + verticalLayout->addWidget(cbWrite2Src); + + + verticalLayout_3->addLayout(verticalLayout); + + line_2 = new QFrame(tab_file_io); + line_2->setObjectName(QString::fromUtf8("line_2")); + line_2->setFrameShape(QFrame::HLine); + line_2->setFrameShadow(QFrame::Sunken); + + verticalLayout_3->addWidget(line_2); + + pbStartConversion = new QPushButton(tab_file_io); + pbStartConversion->setObjectName(QString::fromUtf8("pbStartConversion")); + QSizePolicy sizePolicy4(QSizePolicy::Preferred, QSizePolicy::Fixed); + sizePolicy4.setHorizontalStretch(0); + sizePolicy4.setVerticalStretch(0); + sizePolicy4.setHeightForWidth(pbStartConversion->sizePolicy().hasHeightForWidth()); + pbStartConversion->setSizePolicy(sizePolicy4); + pbStartConversion->setMinimumSize(QSize(120, 0)); + QFont font1; + font1.setFamily(QString::fromUtf8("MS Shell Dlg 2")); + font1.setPointSize(10); + font1.setBold(true); + font1.setWeight(75); + pbStartConversion->setFont(font1); + pbStartConversion->setDefault(true); + + verticalLayout_3->addWidget(pbStartConversion); + + pbCopyFile2CP = new QPushButton(tab_file_io); + pbCopyFile2CP->setObjectName(QString::fromUtf8("pbCopyFile2CP")); + + verticalLayout_3->addWidget(pbCopyFile2CP); + + tabIOSelection->addTab(tab_file_io, QString()); + tab_clipboard = new QWidget(); + tab_clipboard->setObjectName(QString::fromUtf8("tab_clipboard")); + verticalLayout_15 = new QVBoxLayout(tab_clipboard); + verticalLayout_15->setSpacing(6); + verticalLayout_15->setContentsMargins(11, 11, 11, 11); + verticalLayout_15->setObjectName(QString::fromUtf8("verticalLayout_15")); + pbPasteFromCB = new QPushButton(tab_clipboard); + pbPasteFromCB->setObjectName(QString::fromUtf8("pbPasteFromCB")); + + verticalLayout_15->addWidget(pbPasteFromCB); + + horizontalLayout_23 = new QHBoxLayout(); + horizontalLayout_23->setSpacing(6); + horizontalLayout_23->setObjectName(QString::fromUtf8("horizontalLayout_23")); + label_13 = new QLabel(tab_clipboard); + label_13->setObjectName(QString::fromUtf8("label_13")); + + horizontalLayout_23->addWidget(label_13); + + comboSelectSyntax = new QComboBox(tab_clipboard); + comboSelectSyntax->setObjectName(QString::fromUtf8("comboSelectSyntax")); + + horizontalLayout_23->addWidget(comboSelectSyntax); + + + verticalLayout_15->addLayout(horizontalLayout_23); + + line_14 = new QFrame(tab_clipboard); + line_14->setObjectName(QString::fromUtf8("line_14")); + line_14->setFrameShape(QFrame::HLine); + line_14->setFrameShadow(QFrame::Sunken); + + verticalLayout_15->addWidget(line_14); + + pbCopyToCP = new QPushButton(tab_clipboard); + pbCopyToCP->setObjectName(QString::fromUtf8("pbCopyToCP")); + pbCopyToCP->setFont(font); + + verticalLayout_15->addWidget(pbCopyToCP); + + verticalSpacer_12 = new QSpacerItem(20, 106, QSizePolicy::Minimum, QSizePolicy::Expanding); + + verticalLayout_15->addItem(verticalSpacer_12); + + tabIOSelection->addTab(tab_clipboard, QString()); + + verticalLayout_7->addWidget(tabIOSelection); + + line_7 = new QFrame(centralWidget); + line_7->setObjectName(QString::fromUtf8("line_7")); + line_7->setFrameShape(QFrame::HLine); + line_7->setFrameShadow(QFrame::Sunken); + + verticalLayout_7->addWidget(line_7); + + tabWidget = new QTabWidget(centralWidget); + tabWidget->setObjectName(QString::fromUtf8("tabWidget")); + QSizePolicy sizePolicy5(QSizePolicy::Preferred, QSizePolicy::Minimum); + sizePolicy5.setHorizontalStretch(0); + sizePolicy5.setVerticalStretch(0); + sizePolicy5.setHeightForWidth(tabWidget->sizePolicy().hasHeightForWidth()); + tabWidget->setSizePolicy(sizePolicy5); + tabWidget->setMinimumSize(QSize(0, 0)); + tabWidget->setLayoutDirection(Qt::LeftToRight); + tabWidget->setTabPosition(QTabWidget::North); + tabWidget->setTabShape(QTabWidget::Rounded); + page_general = new QWidget(); + page_general->setObjectName(QString::fromUtf8("page_general")); + verticalLayout_2 = new QVBoxLayout(page_general); + verticalLayout_2->setSpacing(6); + verticalLayout_2->setContentsMargins(11, 11, 11, 11); + verticalLayout_2->setObjectName(QString::fromUtf8("verticalLayout_2")); + horizontalLayout_8 = new QHBoxLayout(); + horizontalLayout_8->setSpacing(6); + horizontalLayout_8->setObjectName(QString::fromUtf8("horizontalLayout_8")); + label_2 = new QLabel(page_general); + label_2->setObjectName(QString::fromUtf8("label_2")); + QSizePolicy sizePolicy6(QSizePolicy::Minimum, QSizePolicy::Minimum); + sizePolicy6.setHorizontalStretch(0); + sizePolicy6.setVerticalStretch(0); + sizePolicy6.setHeightForWidth(label_2->sizePolicy().hasHeightForWidth()); + label_2->setSizePolicy(sizePolicy6); + label_2->setFont(font); + + horizontalLayout_8->addWidget(label_2); + + comboFormat = new QComboBox(page_general); + comboFormat->setObjectName(QString::fromUtf8("comboFormat")); + sizePolicy4.setHeightForWidth(comboFormat->sizePolicy().hasHeightForWidth()); + comboFormat->setSizePolicy(sizePolicy4); + comboFormat->setFont(font); + + horizontalLayout_8->addWidget(comboFormat); + + + verticalLayout_2->addLayout(horizontalLayout_8); + + line_9 = new QFrame(page_general); + line_9->setObjectName(QString::fromUtf8("line_9")); + line_9->setFrameShape(QFrame::HLine); + line_9->setFrameShadow(QFrame::Sunken); + + verticalLayout_2->addWidget(line_9); + + horizontalLayout_21 = new QHBoxLayout(); + horizontalLayout_21->setSpacing(6); + horizontalLayout_21->setObjectName(QString::fromUtf8("horizontalLayout_21")); + cbIncLineNo = new QCheckBox(page_general); + cbIncLineNo->setObjectName(QString::fromUtf8("cbIncLineNo")); + + horizontalLayout_21->addWidget(cbIncLineNo); + + horizontalSpacer_4 = new QSpacerItem(10, 20, QSizePolicy::Expanding, QSizePolicy::Minimum); + + horizontalLayout_21->addItem(horizontalSpacer_4); + + sbLineNoWidth = new QSpinBox(page_general); + sbLineNoWidth->setObjectName(QString::fromUtf8("sbLineNoWidth")); + sbLineNoWidth->setMinimum(1); + sbLineNoWidth->setMaximum(6); + sbLineNoWidth->setValue(2); + + horizontalLayout_21->addWidget(sbLineNoWidth); + + + verticalLayout_2->addLayout(horizontalLayout_21); + + cbPadZeroes = new QCheckBox(page_general); + cbPadZeroes->setObjectName(QString::fromUtf8("cbPadZeroes")); + cbPadZeroes->setEnabled(false); + + verticalLayout_2->addWidget(cbPadZeroes); + + cbFragment = new QCheckBox(page_general); + cbFragment->setObjectName(QString::fromUtf8("cbFragment")); + QSizePolicy sizePolicy7(QSizePolicy::Minimum, QSizePolicy::Fixed); + sizePolicy7.setHorizontalStretch(0); + sizePolicy7.setVerticalStretch(0); + sizePolicy7.setHeightForWidth(cbFragment->sizePolicy().hasHeightForWidth()); + cbFragment->setSizePolicy(sizePolicy7); + + verticalLayout_2->addWidget(cbFragment); + + cbValidateInput = new QCheckBox(page_general); + cbValidateInput->setObjectName(QString::fromUtf8("cbValidateInput")); + + verticalLayout_2->addWidget(cbValidateInput); + + horizontalLayout_2 = new QHBoxLayout(); + horizontalLayout_2->setSpacing(6); + horizontalLayout_2->setObjectName(QString::fromUtf8("horizontalLayout_2")); + cbEncoding = new QCheckBox(page_general); + cbEncoding->setObjectName(QString::fromUtf8("cbEncoding")); + + horizontalLayout_2->addWidget(cbEncoding); + + comboEncoding = new QComboBox(page_general); + comboEncoding->setObjectName(QString::fromUtf8("comboEncoding")); + comboEncoding->setEditable(true); + comboEncoding->setInsertPolicy(QComboBox::InsertAtBottom); + + horizontalLayout_2->addWidget(comboEncoding); + + + verticalLayout_2->addLayout(horizontalLayout_2); + + verticalSpacer_2 = new QSpacerItem(20, 40, QSizePolicy::Minimum, QSizePolicy::Expanding); + + verticalLayout_2->addItem(verticalSpacer_2); + + tabWidget->addTab(page_general, QString()); + page_output_spec = new QWidget(); + page_output_spec->setObjectName(QString::fromUtf8("page_output_spec")); + gridLayout = new QGridLayout(page_output_spec); + gridLayout->setSpacing(6); + gridLayout->setContentsMargins(11, 11, 11, 11); + gridLayout->setObjectName(QString::fromUtf8("gridLayout")); + stackedSpecificOptions = new QStackedWidget(page_output_spec); + stackedSpecificOptions->setObjectName(QString::fromUtf8("stackedSpecificOptions")); + QSizePolicy sizePolicy8(QSizePolicy::Preferred, QSizePolicy::Ignored); + sizePolicy8.setHorizontalStretch(0); + sizePolicy8.setVerticalStretch(0); + sizePolicy8.setHeightForWidth(stackedSpecificOptions->sizePolicy().hasHeightForWidth()); + stackedSpecificOptions->setSizePolicy(sizePolicy8); + stackedSpecificOptions->setMinimumSize(QSize(0, 0)); + HTMLOptions = new QWidget(); + HTMLOptions->setObjectName(QString::fromUtf8("HTMLOptions")); + verticalLayout_5 = new QVBoxLayout(HTMLOptions); + verticalLayout_5->setSpacing(6); + verticalLayout_5->setContentsMargins(11, 11, 11, 11); + verticalLayout_5->setObjectName(QString::fromUtf8("verticalLayout_5")); + label_17 = new QLabel(HTMLOptions); + label_17->setObjectName(QString::fromUtf8("label_17")); + sizePolicy4.setHeightForWidth(label_17->sizePolicy().hasHeightForWidth()); + label_17->setSizePolicy(sizePolicy4); + label_17->setFont(font); + + verticalLayout_5->addWidget(label_17); + + line_12 = new QFrame(HTMLOptions); + line_12->setObjectName(QString::fromUtf8("line_12")); + line_12->setFrameShape(QFrame::HLine); + line_12->setFrameShadow(QFrame::Sunken); + + verticalLayout_5->addWidget(line_12); + + tabWidget1 = new QTabWidget(HTMLOptions); + tabWidget1->setObjectName(QString::fromUtf8("tabWidget1")); + sizePolicy6.setHeightForWidth(tabWidget1->sizePolicy().hasHeightForWidth()); + tabWidget1->setSizePolicy(sizePolicy6); + tabWidget1->setMinimumSize(QSize(250, 0)); + tabWidgetPage1 = new QWidget(); + tabWidgetPage1->setObjectName(QString::fromUtf8("tabWidgetPage1")); + gridLayout_4 = new QGridLayout(tabWidgetPage1); + gridLayout_4->setSpacing(6); + gridLayout_4->setContentsMargins(11, 11, 11, 11); + gridLayout_4->setObjectName(QString::fromUtf8("gridLayout_4")); + horizontalLayout_10 = new QHBoxLayout(); + horizontalLayout_10->setSpacing(6); + horizontalLayout_10->setObjectName(QString::fromUtf8("horizontalLayout_10")); + cbHTMLEmbedStyle = new QCheckBox(tabWidgetPage1); + cbHTMLEmbedStyle->setObjectName(QString::fromUtf8("cbHTMLEmbedStyle")); + + horizontalLayout_10->addWidget(cbHTMLEmbedStyle); + + cbHTMLInlineCSS = new QCheckBox(tabWidgetPage1); + cbHTMLInlineCSS->setObjectName(QString::fromUtf8("cbHTMLInlineCSS")); + cbHTMLInlineCSS->setEnabled(false); + cbHTMLInlineCSS->setCheckable(true); + + horizontalLayout_10->addWidget(cbHTMLInlineCSS); + + + gridLayout_4->addLayout(horizontalLayout_10, 0, 0, 1, 1); + + horizontalLayout_14 = new QHBoxLayout(); + horizontalLayout_14->setSpacing(6); + horizontalLayout_14->setObjectName(QString::fromUtf8("horizontalLayout_14")); + label_19 = new QLabel(tabWidgetPage1); + label_19->setObjectName(QString::fromUtf8("label_19")); + + horizontalLayout_14->addWidget(label_19); + + leHTMLStyleFile = new QLineEdit(tabWidgetPage1); + leHTMLStyleFile->setObjectName(QString::fromUtf8("leHTMLStyleFile")); + sizePolicy4.setHeightForWidth(leHTMLStyleFile->sizePolicy().hasHeightForWidth()); + leHTMLStyleFile->setSizePolicy(sizePolicy4); + + horizontalLayout_14->addWidget(leHTMLStyleFile); + + + gridLayout_4->addLayout(horizontalLayout_14, 1, 0, 1, 1); + + horizontalLayout_9 = new QHBoxLayout(); + horizontalLayout_9->setSpacing(6); + horizontalLayout_9->setObjectName(QString::fromUtf8("horizontalLayout_9")); + label_20 = new QLabel(tabWidgetPage1); + label_20->setObjectName(QString::fromUtf8("label_20")); + + horizontalLayout_9->addWidget(label_20); + + leHTMLStyleIncFile = new QLineEdit(tabWidgetPage1); + leHTMLStyleIncFile->setObjectName(QString::fromUtf8("leHTMLStyleIncFile")); + + horizontalLayout_9->addWidget(leHTMLStyleIncFile); + + pbHTMLChooseStyleIncFile = new QPushButton(tabWidgetPage1); + pbHTMLChooseStyleIncFile->setObjectName(QString::fromUtf8("pbHTMLChooseStyleIncFile")); + + horizontalLayout_9->addWidget(pbHTMLChooseStyleIncFile); + + + gridLayout_4->addLayout(horizontalLayout_9, 2, 0, 1, 1); + + horizontalLayout_7 = new QHBoxLayout(); + horizontalLayout_7->setSpacing(6); + horizontalLayout_7->setObjectName(QString::fromUtf8("horizontalLayout_7")); + label = new QLabel(tabWidgetPage1); + label->setObjectName(QString::fromUtf8("label")); + + horizontalLayout_7->addWidget(label); + + leHTMLCssPrefix = new QLineEdit(tabWidgetPage1); + leHTMLCssPrefix->setObjectName(QString::fromUtf8("leHTMLCssPrefix")); + + horizontalLayout_7->addWidget(leHTMLCssPrefix); + + + gridLayout_4->addLayout(horizontalLayout_7, 3, 0, 1, 1); + + verticalSpacer_9 = new QSpacerItem(20, 40, QSizePolicy::Minimum, QSizePolicy::MinimumExpanding); + + gridLayout_4->addItem(verticalSpacer_9, 4, 0, 1, 1); + + tabWidget1->addTab(tabWidgetPage1, QString()); + tabWidgetPage2 = new QWidget(); + tabWidgetPage2->setObjectName(QString::fromUtf8("tabWidgetPage2")); + verticalLayout_6 = new QVBoxLayout(tabWidgetPage2); + verticalLayout_6->setSpacing(6); + verticalLayout_6->setContentsMargins(11, 11, 11, 11); + verticalLayout_6->setObjectName(QString::fromUtf8("verticalLayout_6")); + cbHTMLIndex = new QCheckBox(tabWidgetPage2); + cbHTMLIndex->setObjectName(QString::fromUtf8("cbHTMLIndex")); + + verticalLayout_6->addWidget(cbHTMLIndex); + + line_13 = new QFrame(tabWidgetPage2); + line_13->setObjectName(QString::fromUtf8("line_13")); + line_13->setFrameShape(QFrame::HLine); + line_13->setFrameShadow(QFrame::Sunken); + + verticalLayout_6->addWidget(line_13); + + cbHTMLCtags = new QCheckBox(tabWidgetPage2); + cbHTMLCtags->setObjectName(QString::fromUtf8("cbHTMLCtags")); + sizePolicy7.setHeightForWidth(cbHTMLCtags->sizePolicy().hasHeightForWidth()); + cbHTMLCtags->setSizePolicy(sizePolicy7); + + verticalLayout_6->addWidget(cbHTMLCtags); + + horizontalLayout_12 = new QHBoxLayout(); + horizontalLayout_12->setSpacing(6); + horizontalLayout_12->setObjectName(QString::fromUtf8("horizontalLayout_12")); + leHTMLCtagsFile = new QLineEdit(tabWidgetPage2); + leHTMLCtagsFile->setObjectName(QString::fromUtf8("leHTMLCtagsFile")); + QSizePolicy sizePolicy9(QSizePolicy::Expanding, QSizePolicy::Fixed); + sizePolicy9.setHorizontalStretch(0); + sizePolicy9.setVerticalStretch(0); + sizePolicy9.setHeightForWidth(leHTMLCtagsFile->sizePolicy().hasHeightForWidth()); + leHTMLCtagsFile->setSizePolicy(sizePolicy9); + + horizontalLayout_12->addWidget(leHTMLCtagsFile); + + pbHTMLChooseTagsFile = new QPushButton(tabWidgetPage2); + pbHTMLChooseTagsFile->setObjectName(QString::fromUtf8("pbHTMLChooseTagsFile")); + sizePolicy3.setHeightForWidth(pbHTMLChooseTagsFile->sizePolicy().hasHeightForWidth()); + pbHTMLChooseTagsFile->setSizePolicy(sizePolicy3); + + horizontalLayout_12->addWidget(pbHTMLChooseTagsFile); + + + verticalLayout_6->addLayout(horizontalLayout_12); + + verticalSpacer_8 = new QSpacerItem(20, 72, QSizePolicy::Minimum, QSizePolicy::Expanding); + + verticalLayout_6->addItem(verticalSpacer_8); + + tabWidget1->addTab(tabWidgetPage2, QString()); + tabWidgetPage3 = new QWidget(); + tabWidgetPage3->setObjectName(QString::fromUtf8("tabWidgetPage3")); + verticalLayout_4 = new QVBoxLayout(tabWidgetPage3); + verticalLayout_4->setSpacing(6); + verticalLayout_4->setContentsMargins(11, 11, 11, 11); + verticalLayout_4->setObjectName(QString::fromUtf8("verticalLayout_4")); + label_8 = new QLabel(tabWidgetPage3); + label_8->setObjectName(QString::fromUtf8("label_8")); + QFont font2; + font2.setBold(false); + font2.setWeight(50); + label_8->setFont(font2); + + verticalLayout_4->addWidget(label_8); + + cbHTMLAnchors = new QCheckBox(tabWidgetPage3); + cbHTMLAnchors->setObjectName(QString::fromUtf8("cbHTMLAnchors")); + + verticalLayout_4->addWidget(cbHTMLAnchors); + + cbHTMLFileNameAnchor = new QCheckBox(tabWidgetPage3); + cbHTMLFileNameAnchor->setObjectName(QString::fromUtf8("cbHTMLFileNameAnchor")); + + verticalLayout_4->addWidget(cbHTMLFileNameAnchor); + + cbHTMLOrderedList = new QCheckBox(tabWidgetPage3); + cbHTMLOrderedList->setObjectName(QString::fromUtf8("cbHTMLOrderedList")); + + verticalLayout_4->addWidget(cbHTMLOrderedList); + + line_4 = new QFrame(tabWidgetPage3); + line_4->setObjectName(QString::fromUtf8("line_4")); + line_4->setFrameShape(QFrame::HLine); + line_4->setFrameShadow(QFrame::Sunken); + + verticalLayout_4->addWidget(line_4); + + cbHTMLEnclosePreTags = new QCheckBox(tabWidgetPage3); + cbHTMLEnclosePreTags->setObjectName(QString::fromUtf8("cbHTMLEnclosePreTags")); + + verticalLayout_4->addWidget(cbHTMLEnclosePreTags); + + verticalSpacer = new QSpacerItem(20, 24, QSizePolicy::Minimum, QSizePolicy::Expanding); + + verticalLayout_4->addItem(verticalSpacer); + + tabWidget1->addTab(tabWidgetPage3, QString()); + + verticalLayout_5->addWidget(tabWidget1); + + stackedSpecificOptions->addWidget(HTMLOptions); + LATEXOptions = new QWidget(); + LATEXOptions->setObjectName(QString::fromUtf8("LATEXOptions")); + verticalLayout_12 = new QVBoxLayout(LATEXOptions); + verticalLayout_12->setSpacing(6); + verticalLayout_12->setContentsMargins(11, 11, 11, 11); + verticalLayout_12->setObjectName(QString::fromUtf8("verticalLayout_12")); + label_18 = new QLabel(LATEXOptions); + label_18->setObjectName(QString::fromUtf8("label_18")); + QSizePolicy sizePolicy10(QSizePolicy::Maximum, QSizePolicy::Preferred); + sizePolicy10.setHorizontalStretch(0); + sizePolicy10.setVerticalStretch(0); + sizePolicy10.setHeightForWidth(label_18->sizePolicy().hasHeightForWidth()); + label_18->setSizePolicy(sizePolicy10); + label_18->setFont(font); + + verticalLayout_12->addWidget(label_18); + + line_8 = new QFrame(LATEXOptions); + line_8->setObjectName(QString::fromUtf8("line_8")); + line_8->setFrameShape(QFrame::HLine); + line_8->setFrameShadow(QFrame::Sunken); + + verticalLayout_12->addWidget(line_8); + + cbLATEXEscQuotes = new QCheckBox(LATEXOptions); + cbLATEXEscQuotes->setObjectName(QString::fromUtf8("cbLATEXEscQuotes")); + + verticalLayout_12->addWidget(cbLATEXEscQuotes); + + cbLATEXBabel = new QCheckBox(LATEXOptions); + cbLATEXBabel->setObjectName(QString::fromUtf8("cbLATEXBabel")); + + verticalLayout_12->addWidget(cbLATEXBabel); + + cbLATEXPrettySymbols = new QCheckBox(LATEXOptions); + cbLATEXPrettySymbols->setObjectName(QString::fromUtf8("cbLATEXPrettySymbols")); + + verticalLayout_12->addWidget(cbLATEXPrettySymbols); + + cbLATEXEmbedStyle = new QCheckBox(LATEXOptions); + cbLATEXEmbedStyle->setObjectName(QString::fromUtf8("cbLATEXEmbedStyle")); + + verticalLayout_12->addWidget(cbLATEXEmbedStyle); + + horizontalLayout_17 = new QHBoxLayout(); + horizontalLayout_17->setSpacing(6); + horizontalLayout_17->setObjectName(QString::fromUtf8("horizontalLayout_17")); + label_21 = new QLabel(LATEXOptions); + label_21->setObjectName(QString::fromUtf8("label_21")); + + horizontalLayout_17->addWidget(label_21); + + leLATEXStyleFile = new QLineEdit(LATEXOptions); + leLATEXStyleFile->setObjectName(QString::fromUtf8("leLATEXStyleFile")); + + horizontalLayout_17->addWidget(leLATEXStyleFile); + + + verticalLayout_12->addLayout(horizontalLayout_17); + + horizontalLayout_15 = new QHBoxLayout(); + horizontalLayout_15->setSpacing(6); + horizontalLayout_15->setObjectName(QString::fromUtf8("horizontalLayout_15")); + label_22 = new QLabel(LATEXOptions); + label_22->setObjectName(QString::fromUtf8("label_22")); + + horizontalLayout_15->addWidget(label_22); + + horizontalSpacer_2 = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum); + + horizontalLayout_15->addItem(horizontalSpacer_2); + + + verticalLayout_12->addLayout(horizontalLayout_15); + + horizontalLayout_16 = new QHBoxLayout(); + horizontalLayout_16->setSpacing(6); + horizontalLayout_16->setObjectName(QString::fromUtf8("horizontalLayout_16")); + leLATEXStyleIncFile = new QLineEdit(LATEXOptions); + leLATEXStyleIncFile->setObjectName(QString::fromUtf8("leLATEXStyleIncFile")); + + horizontalLayout_16->addWidget(leLATEXStyleIncFile); + + pbLATEXChooseStyleIncFile = new QPushButton(LATEXOptions); + pbLATEXChooseStyleIncFile->setObjectName(QString::fromUtf8("pbLATEXChooseStyleIncFile")); + + horizontalLayout_16->addWidget(pbLATEXChooseStyleIncFile); + + + verticalLayout_12->addLayout(horizontalLayout_16); + + verticalSpacer_4 = new QSpacerItem(20, 40, QSizePolicy::Minimum, QSizePolicy::Expanding); + + verticalLayout_12->addItem(verticalSpacer_4); + + stackedSpecificOptions->addWidget(LATEXOptions); + TEXOptions = new QWidget(); + TEXOptions->setObjectName(QString::fromUtf8("TEXOptions")); + verticalLayout_14 = new QVBoxLayout(TEXOptions); + verticalLayout_14->setSpacing(6); + verticalLayout_14->setContentsMargins(11, 11, 11, 11); + verticalLayout_14->setObjectName(QString::fromUtf8("verticalLayout_14")); + label_26 = new QLabel(TEXOptions); + label_26->setObjectName(QString::fromUtf8("label_26")); + sizePolicy4.setHeightForWidth(label_26->sizePolicy().hasHeightForWidth()); + label_26->setSizePolicy(sizePolicy4); + label_26->setFont(font); + + verticalLayout_14->addWidget(label_26); + + line_10 = new QFrame(TEXOptions); + line_10->setObjectName(QString::fromUtf8("line_10")); + line_10->setFrameShape(QFrame::HLine); + line_10->setFrameShadow(QFrame::Sunken); + + verticalLayout_14->addWidget(line_10); + + cbTEXEmbedStyle = new QCheckBox(TEXOptions); + cbTEXEmbedStyle->setObjectName(QString::fromUtf8("cbTEXEmbedStyle")); + + verticalLayout_14->addWidget(cbTEXEmbedStyle); + + horizontalLayout_18 = new QHBoxLayout(); + horizontalLayout_18->setSpacing(6); + horizontalLayout_18->setObjectName(QString::fromUtf8("horizontalLayout_18")); + label_24 = new QLabel(TEXOptions); + label_24->setObjectName(QString::fromUtf8("label_24")); + + horizontalLayout_18->addWidget(label_24); + + leTEXStyleFile = new QLineEdit(TEXOptions); + leTEXStyleFile->setObjectName(QString::fromUtf8("leTEXStyleFile")); + + horizontalLayout_18->addWidget(leTEXStyleFile); + + + verticalLayout_14->addLayout(horizontalLayout_18); + + horizontalLayout_19 = new QHBoxLayout(); + horizontalLayout_19->setSpacing(6); + horizontalLayout_19->setObjectName(QString::fromUtf8("horizontalLayout_19")); + label_25 = new QLabel(TEXOptions); + label_25->setObjectName(QString::fromUtf8("label_25")); + + horizontalLayout_19->addWidget(label_25); + + horizontalSpacer_3 = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum); + + horizontalLayout_19->addItem(horizontalSpacer_3); + + + verticalLayout_14->addLayout(horizontalLayout_19); + + horizontalLayout_20 = new QHBoxLayout(); + horizontalLayout_20->setSpacing(6); + horizontalLayout_20->setObjectName(QString::fromUtf8("horizontalLayout_20")); + leTEXStyleIncFile = new QLineEdit(TEXOptions); + leTEXStyleIncFile->setObjectName(QString::fromUtf8("leTEXStyleIncFile")); + + horizontalLayout_20->addWidget(leTEXStyleIncFile); + + pbTEXChooseStyleIncFile = new QPushButton(TEXOptions); + pbTEXChooseStyleIncFile->setObjectName(QString::fromUtf8("pbTEXChooseStyleIncFile")); + + horizontalLayout_20->addWidget(pbTEXChooseStyleIncFile); + + + verticalLayout_14->addLayout(horizontalLayout_20); + + verticalSpacer_5 = new QSpacerItem(20, 40, QSizePolicy::Minimum, QSizePolicy::Expanding); + + verticalLayout_14->addItem(verticalSpacer_5); + + stackedSpecificOptions->addWidget(TEXOptions); + RTFOptions = new QWidget(); + RTFOptions->setObjectName(QString::fromUtf8("RTFOptions")); + verticalLayout_9 = new QVBoxLayout(RTFOptions); + verticalLayout_9->setSpacing(6); + verticalLayout_9->setContentsMargins(11, 11, 11, 11); + verticalLayout_9->setObjectName(QString::fromUtf8("verticalLayout_9")); + label_15 = new QLabel(RTFOptions); + label_15->setObjectName(QString::fromUtf8("label_15")); + sizePolicy4.setHeightForWidth(label_15->sizePolicy().hasHeightForWidth()); + label_15->setSizePolicy(sizePolicy4); + label_15->setFont(font); + + verticalLayout_9->addWidget(label_15); + + line_5 = new QFrame(RTFOptions); + line_5->setObjectName(QString::fromUtf8("line_5")); + line_5->setFrameShape(QFrame::HLine); + line_5->setFrameShadow(QFrame::Sunken); + + verticalLayout_9->addWidget(line_5); + + cbRTFCharStyles = new QCheckBox(RTFOptions); + cbRTFCharStyles->setObjectName(QString::fromUtf8("cbRTFCharStyles")); + + verticalLayout_9->addWidget(cbRTFCharStyles); + + horizontalLayout_11 = new QHBoxLayout(); + horizontalLayout_11->setSpacing(6); + horizontalLayout_11->setObjectName(QString::fromUtf8("horizontalLayout_11")); + label_9 = new QLabel(RTFOptions); + label_9->setObjectName(QString::fromUtf8("label_9")); + + horizontalLayout_11->addWidget(label_9); + + comboRTFPageSize = new QComboBox(RTFOptions); + comboRTFPageSize->setObjectName(QString::fromUtf8("comboRTFPageSize")); + + horizontalLayout_11->addWidget(comboRTFPageSize); + + + verticalLayout_9->addLayout(horizontalLayout_11); + + verticalSpacer_6 = new QSpacerItem(20, 40, QSizePolicy::Minimum, QSizePolicy::Expanding); + + verticalLayout_9->addItem(verticalSpacer_6); + + stackedSpecificOptions->addWidget(RTFOptions); + SVGOptions = new QWidget(); + SVGOptions->setObjectName(QString::fromUtf8("SVGOptions")); + verticalLayout_10 = new QVBoxLayout(SVGOptions); + verticalLayout_10->setSpacing(6); + verticalLayout_10->setContentsMargins(11, 11, 11, 11); + verticalLayout_10->setObjectName(QString::fromUtf8("verticalLayout_10")); + label_16 = new QLabel(SVGOptions); + label_16->setObjectName(QString::fromUtf8("label_16")); + sizePolicy4.setHeightForWidth(label_16->sizePolicy().hasHeightForWidth()); + label_16->setSizePolicy(sizePolicy4); + label_16->setFont(font); + + verticalLayout_10->addWidget(label_16); + + line_6 = new QFrame(SVGOptions); + line_6->setObjectName(QString::fromUtf8("line_6")); + line_6->setFrameShape(QFrame::HLine); + line_6->setFrameShadow(QFrame::Sunken); + + verticalLayout_10->addWidget(line_6); + + label_10 = new QLabel(SVGOptions); + label_10->setObjectName(QString::fromUtf8("label_10")); + + verticalLayout_10->addWidget(label_10); + + gridLayout_8 = new QGridLayout(); + gridLayout_8->setSpacing(6); + gridLayout_8->setObjectName(QString::fromUtf8("gridLayout_8")); + label_3 = new QLabel(SVGOptions); + label_3->setObjectName(QString::fromUtf8("label_3")); + + gridLayout_8->addWidget(label_3, 0, 0, 1, 1); + + leSVGWidth = new QLineEdit(SVGOptions); + leSVGWidth->setObjectName(QString::fromUtf8("leSVGWidth")); + + gridLayout_8->addWidget(leSVGWidth, 0, 1, 1, 1); + + label_12 = new QLabel(SVGOptions); + label_12->setObjectName(QString::fromUtf8("label_12")); + + gridLayout_8->addWidget(label_12, 1, 0, 1, 1); + + leSVGHeight = new QLineEdit(SVGOptions); + leSVGHeight->setObjectName(QString::fromUtf8("leSVGHeight")); + + gridLayout_8->addWidget(leSVGHeight, 1, 1, 1, 1); + + + verticalLayout_10->addLayout(gridLayout_8); + + cbSVGEmbedStyle = new QCheckBox(SVGOptions); + cbSVGEmbedStyle->setObjectName(QString::fromUtf8("cbSVGEmbedStyle")); + + verticalLayout_10->addWidget(cbSVGEmbedStyle); + + horizontalLayout_26 = new QHBoxLayout(); + horizontalLayout_26->setSpacing(6); + horizontalLayout_26->setObjectName(QString::fromUtf8("horizontalLayout_26")); + label_29 = new QLabel(SVGOptions); + label_29->setObjectName(QString::fromUtf8("label_29")); + + horizontalLayout_26->addWidget(label_29); + + leSVGStyleFile = new QLineEdit(SVGOptions); + leSVGStyleFile->setObjectName(QString::fromUtf8("leSVGStyleFile")); + + horizontalLayout_26->addWidget(leSVGStyleFile); + + + verticalLayout_10->addLayout(horizontalLayout_26); + + horizontalLayout_27 = new QHBoxLayout(); + horizontalLayout_27->setSpacing(6); + horizontalLayout_27->setObjectName(QString::fromUtf8("horizontalLayout_27")); + label_30 = new QLabel(SVGOptions); + label_30->setObjectName(QString::fromUtf8("label_30")); + + horizontalLayout_27->addWidget(label_30); + + horizontalSpacer_6 = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum); + + horizontalLayout_27->addItem(horizontalSpacer_6); + + + verticalLayout_10->addLayout(horizontalLayout_27); + + horizontalLayout_28 = new QHBoxLayout(); + horizontalLayout_28->setSpacing(6); + horizontalLayout_28->setObjectName(QString::fromUtf8("horizontalLayout_28")); + leSVGStyleIncFile = new QLineEdit(SVGOptions); + leSVGStyleIncFile->setObjectName(QString::fromUtf8("leSVGStyleIncFile")); + + horizontalLayout_28->addWidget(leSVGStyleIncFile); + + pbSVGChooseStyleIncFile = new QPushButton(SVGOptions); + pbSVGChooseStyleIncFile->setObjectName(QString::fromUtf8("pbSVGChooseStyleIncFile")); + + horizontalLayout_28->addWidget(pbSVGChooseStyleIncFile); + + + verticalLayout_10->addLayout(horizontalLayout_28); + + verticalSpacer_10 = new QSpacerItem(20, 40, QSizePolicy::Minimum, QSizePolicy::Expanding); + + verticalLayout_10->addItem(verticalSpacer_10); + + stackedSpecificOptions->addWidget(SVGOptions); + EmptyPage = new QWidget(); + EmptyPage->setObjectName(QString::fromUtf8("EmptyPage")); + verticalLayout_11 = new QVBoxLayout(EmptyPage); + verticalLayout_11->setSpacing(6); + verticalLayout_11->setContentsMargins(11, 11, 11, 11); + verticalLayout_11->setObjectName(QString::fromUtf8("verticalLayout_11")); + label_7 = new QLabel(EmptyPage); + label_7->setObjectName(QString::fromUtf8("label_7")); + + verticalLayout_11->addWidget(label_7); + + verticalSpacer_3 = new QSpacerItem(20, 40, QSizePolicy::Minimum, QSizePolicy::Expanding); + + verticalLayout_11->addItem(verticalSpacer_3); + + stackedSpecificOptions->addWidget(EmptyPage); + + gridLayout->addWidget(stackedSpecificOptions, 0, 0, 1, 1); + + tabWidget->addTab(page_output_spec, QString()); + page_formatting = new QWidget(); + page_formatting->setObjectName(QString::fromUtf8("page_formatting")); + verticalLayout_8 = new QVBoxLayout(page_formatting); + verticalLayout_8->setSpacing(6); + verticalLayout_8->setContentsMargins(11, 11, 11, 11); + verticalLayout_8->setObjectName(QString::fromUtf8("verticalLayout_8")); + horizontalLayout_3 = new QHBoxLayout(); + horizontalLayout_3->setSpacing(6); + horizontalLayout_3->setObjectName(QString::fromUtf8("horizontalLayout_3")); + label_5 = new QLabel(page_formatting); + label_5->setObjectName(QString::fromUtf8("label_5")); + sizePolicy6.setHeightForWidth(label_5->sizePolicy().hasHeightForWidth()); + label_5->setSizePolicy(sizePolicy6); + + horizontalLayout_3->addWidget(label_5); + + comboTheme = new QComboBox(page_formatting); + comboTheme->setObjectName(QString::fromUtf8("comboTheme")); + sizePolicy7.setHeightForWidth(comboTheme->sizePolicy().hasHeightForWidth()); + comboTheme->setSizePolicy(sizePolicy7); + + horizontalLayout_3->addWidget(comboTheme); + + + verticalLayout_8->addLayout(horizontalLayout_3); + + horizontalLayout_4 = new QHBoxLayout(); + horizontalLayout_4->setSpacing(6); + horizontalLayout_4->setObjectName(QString::fromUtf8("horizontalLayout_4")); + cbReformat = new QCheckBox(page_formatting); + cbReformat->setObjectName(QString::fromUtf8("cbReformat")); + + horizontalLayout_4->addWidget(cbReformat); + + comboReformat = new QComboBox(page_formatting); + comboReformat->setObjectName(QString::fromUtf8("comboReformat")); + sizePolicy7.setHeightForWidth(comboReformat->sizePolicy().hasHeightForWidth()); + comboReformat->setSizePolicy(sizePolicy7); + + horizontalLayout_4->addWidget(comboReformat); + + + verticalLayout_8->addLayout(horizontalLayout_4); + + horizontalLayout_5 = new QHBoxLayout(); + horizontalLayout_5->setSpacing(6); + horizontalLayout_5->setObjectName(QString::fromUtf8("horizontalLayout_5")); + cbKwCase = new QCheckBox(page_formatting); + cbKwCase->setObjectName(QString::fromUtf8("cbKwCase")); + + horizontalLayout_5->addWidget(cbKwCase); + + comboKwCase = new QComboBox(page_formatting); + comboKwCase->setObjectName(QString::fromUtf8("comboKwCase")); + sizePolicy7.setHeightForWidth(comboKwCase->sizePolicy().hasHeightForWidth()); + comboKwCase->setSizePolicy(sizePolicy7); + + horizontalLayout_5->addWidget(comboKwCase); + + + verticalLayout_8->addLayout(horizontalLayout_5); + + horizontalLayout_6 = new QHBoxLayout(); + horizontalLayout_6->setSpacing(6); + horizontalLayout_6->setObjectName(QString::fromUtf8("horizontalLayout_6")); + label_6 = new QLabel(page_formatting); + label_6->setObjectName(QString::fromUtf8("label_6")); + sizePolicy7.setHeightForWidth(label_6->sizePolicy().hasHeightForWidth()); + label_6->setSizePolicy(sizePolicy7); + + horizontalLayout_6->addWidget(label_6); + + sbTabWidth = new QSpinBox(page_formatting); + sbTabWidth->setObjectName(QString::fromUtf8("sbTabWidth")); + sbTabWidth->setMaximum(10); + + horizontalLayout_6->addWidget(sbTabWidth); + + + verticalLayout_8->addLayout(horizontalLayout_6); + + gridLayout_2 = new QGridLayout(); + gridLayout_2->setSpacing(6); + gridLayout_2->setObjectName(QString::fromUtf8("gridLayout_2")); + cbWrapping = new QCheckBox(page_formatting); + cbWrapping->setObjectName(QString::fromUtf8("cbWrapping")); + + gridLayout_2->addWidget(cbWrapping, 0, 0, 1, 1); + + sbLineLength = new QSpinBox(page_formatting); + sbLineLength->setObjectName(QString::fromUtf8("sbLineLength")); + sbLineLength->setMinimum(60); + sbLineLength->setMaximum(120); + sbLineLength->setSingleStep(2); + + gridLayout_2->addWidget(sbLineLength, 0, 1, 1, 1); + + cbAdvWrapping = new QCheckBox(page_formatting); + cbAdvWrapping->setObjectName(QString::fromUtf8("cbAdvWrapping")); + cbAdvWrapping->setEnabled(false); + + gridLayout_2->addWidget(cbAdvWrapping, 1, 0, 1, 1); + + verticalSpacer_11 = new QSpacerItem(20, 13, QSizePolicy::Minimum, QSizePolicy::Minimum); + + gridLayout_2->addItem(verticalSpacer_11, 1, 1, 1, 1); + + + verticalLayout_8->addLayout(gridLayout_2); + + line_3 = new QFrame(page_formatting); + line_3->setObjectName(QString::fromUtf8("line_3")); + line_3->setFrameShape(QFrame::HLine); + line_3->setFrameShadow(QFrame::Sunken); + + verticalLayout_8->addWidget(line_3); + + gridLayout_9 = new QGridLayout(); + gridLayout_9->setSpacing(6); + gridLayout_9->setObjectName(QString::fromUtf8("gridLayout_9")); + label_23 = new QLabel(page_formatting); + label_23->setObjectName(QString::fromUtf8("label_23")); + + gridLayout_9->addWidget(label_23, 0, 0, 1, 1); + + comboFontName = new QFontComboBox(page_formatting); + comboFontName->setObjectName(QString::fromUtf8("comboFontName")); + + gridLayout_9->addWidget(comboFontName, 0, 1, 1, 1); + + label_4 = new QLabel(page_formatting); + label_4->setObjectName(QString::fromUtf8("label_4")); + + gridLayout_9->addWidget(label_4, 1, 0, 1, 1); + + leFontSize = new QLineEdit(page_formatting); + leFontSize->setObjectName(QString::fromUtf8("leFontSize")); + sizePolicy4.setHeightForWidth(leFontSize->sizePolicy().hasHeightForWidth()); + leFontSize->setSizePolicy(sizePolicy4); + + gridLayout_9->addWidget(leFontSize, 1, 1, 1, 1); + + + verticalLayout_8->addLayout(gridLayout_9); + + tabWidget->addTab(page_formatting, QString()); + + verticalLayout_7->addWidget(tabWidget); + + + horizontalLayout_24->addLayout(verticalLayout_7); + + line = new QFrame(centralWidget); + line->setObjectName(QString::fromUtf8("line")); + line->setFrameShape(QFrame::VLine); + line->setFrameShadow(QFrame::Sunken); + + horizontalLayout_24->addWidget(line); + + verticalLayout_13 = new QVBoxLayout(); + verticalLayout_13->setSpacing(6); + verticalLayout_13->setObjectName(QString::fromUtf8("verticalLayout_13")); + lbPreview = new QLabel(centralWidget); + lbPreview->setObjectName(QString::fromUtf8("lbPreview")); + + verticalLayout_13->addWidget(lbPreview); + + browserPreview = new QTextBrowser(centralWidget); + browserPreview->setObjectName(QString::fromUtf8("browserPreview")); + QSizePolicy sizePolicy11(QSizePolicy::Expanding, QSizePolicy::Expanding); + sizePolicy11.setHorizontalStretch(0); + sizePolicy11.setVerticalStretch(0); + sizePolicy11.setHeightForWidth(browserPreview->sizePolicy().hasHeightForWidth()); + browserPreview->setSizePolicy(sizePolicy11); + + verticalLayout_13->addWidget(browserPreview); + + horizontalLayout_13 = new QHBoxLayout(); + horizontalLayout_13->setSpacing(6); + horizontalLayout_13->setObjectName(QString::fromUtf8("horizontalLayout_13")); + label_14 = new QLabel(centralWidget); + label_14->setObjectName(QString::fromUtf8("label_14")); + + horizontalLayout_13->addWidget(label_14); + + progressBar = new QProgressBar(centralWidget); + progressBar->setObjectName(QString::fromUtf8("progressBar")); + progressBar->setValue(0); + + horizontalLayout_13->addWidget(progressBar); + + + verticalLayout_13->addLayout(horizontalLayout_13); + + + horizontalLayout_24->addLayout(verticalLayout_13); + + MainWindowClass->setCentralWidget(centralWidget); + menuBar = new QMenuBar(MainWindowClass); + menuBar->setObjectName(QString::fromUtf8("menuBar")); + menuBar->setGeometry(QRect(0, 0, 600, 20)); + menu_File = new QMenu(menuBar); + menu_File->setObjectName(QString::fromUtf8("menu_File")); + menu_Help = new QMenu(menuBar); + menu_Help->setObjectName(QString::fromUtf8("menu_Help")); + MainWindowClass->setMenuBar(menuBar); + statusBar = new QStatusBar(MainWindowClass); + statusBar->setObjectName(QString::fromUtf8("statusBar")); + MainWindowClass->setStatusBar(statusBar); +#ifndef QT_NO_SHORTCUT + label_2->setBuddy(comboFormat); + label_21->setBuddy(leLATEXStyleFile); + label_24->setBuddy(leTEXStyleFile); + label_3->setBuddy(leSVGWidth); + label_12->setBuddy(leSVGHeight); + label_29->setBuddy(leSVGStyleFile); + label_5->setBuddy(comboTheme); + label_6->setBuddy(sbTabWidth); + label_23->setBuddy(comboFontName); + label_4->setBuddy(leFontSize); +#endif // QT_NO_SHORTCUT + QWidget::setTabOrder(pbOpenFiles, lvInputFiles); + QWidget::setTabOrder(lvInputFiles, pbClearSelection); + QWidget::setTabOrder(pbClearSelection, pbClearAll); + QWidget::setTabOrder(pbClearAll, tabWidget); + QWidget::setTabOrder(tabWidget, comboFormat); + QWidget::setTabOrder(comboFormat, cbIncLineNo); + QWidget::setTabOrder(cbIncLineNo, sbLineNoWidth); + QWidget::setTabOrder(sbLineNoWidth, cbPadZeroes); + QWidget::setTabOrder(cbPadZeroes, cbFragment); + QWidget::setTabOrder(cbFragment, cbValidateInput); + QWidget::setTabOrder(cbValidateInput, cbEncoding); + QWidget::setTabOrder(cbEncoding, comboEncoding); + QWidget::setTabOrder(comboEncoding, cbHTMLEmbedStyle); + QWidget::setTabOrder(cbHTMLEmbedStyle, cbHTMLInlineCSS); + QWidget::setTabOrder(cbHTMLInlineCSS, leHTMLStyleFile); + QWidget::setTabOrder(leHTMLStyleFile, leHTMLStyleIncFile); + QWidget::setTabOrder(leHTMLStyleIncFile, pbHTMLChooseStyleIncFile); + QWidget::setTabOrder(pbHTMLChooseStyleIncFile, leHTMLCssPrefix); + QWidget::setTabOrder(leHTMLCssPrefix, cbHTMLIndex); + QWidget::setTabOrder(cbHTMLIndex, cbHTMLCtags); + QWidget::setTabOrder(cbHTMLCtags, leHTMLCtagsFile); + QWidget::setTabOrder(leHTMLCtagsFile, pbHTMLChooseTagsFile); + QWidget::setTabOrder(pbHTMLChooseTagsFile, cbHTMLAnchors); + QWidget::setTabOrder(cbHTMLAnchors, cbHTMLFileNameAnchor); + QWidget::setTabOrder(cbHTMLFileNameAnchor, cbHTMLOrderedList); + QWidget::setTabOrder(cbHTMLOrderedList, cbHTMLEnclosePreTags); + QWidget::setTabOrder(cbHTMLEnclosePreTags, cbLATEXEscQuotes); + QWidget::setTabOrder(cbLATEXEscQuotes, cbLATEXBabel); + QWidget::setTabOrder(cbLATEXBabel, cbLATEXPrettySymbols); + QWidget::setTabOrder(cbLATEXPrettySymbols, cbLATEXEmbedStyle); + QWidget::setTabOrder(cbLATEXEmbedStyle, leLATEXStyleFile); + QWidget::setTabOrder(leLATEXStyleFile, leLATEXStyleIncFile); + QWidget::setTabOrder(leLATEXStyleIncFile, pbLATEXChooseStyleIncFile); + QWidget::setTabOrder(pbLATEXChooseStyleIncFile, cbTEXEmbedStyle); + QWidget::setTabOrder(cbTEXEmbedStyle, leTEXStyleFile); + QWidget::setTabOrder(leTEXStyleFile, leTEXStyleIncFile); + QWidget::setTabOrder(leTEXStyleIncFile, pbTEXChooseStyleIncFile); + QWidget::setTabOrder(pbTEXChooseStyleIncFile, cbRTFCharStyles); + QWidget::setTabOrder(cbRTFCharStyles, comboRTFPageSize); + QWidget::setTabOrder(comboRTFPageSize, leSVGWidth); + QWidget::setTabOrder(leSVGWidth, leSVGHeight); + QWidget::setTabOrder(leSVGHeight, cbSVGEmbedStyle); + QWidget::setTabOrder(cbSVGEmbedStyle, leSVGStyleFile); + QWidget::setTabOrder(leSVGStyleFile, leSVGStyleIncFile); + QWidget::setTabOrder(leSVGStyleIncFile, pbSVGChooseStyleIncFile); + QWidget::setTabOrder(pbSVGChooseStyleIncFile, comboTheme); + QWidget::setTabOrder(comboTheme, cbReformat); + QWidget::setTabOrder(cbReformat, comboReformat); + QWidget::setTabOrder(comboReformat, cbKwCase); + QWidget::setTabOrder(cbKwCase, comboKwCase); + QWidget::setTabOrder(comboKwCase, sbTabWidth); + QWidget::setTabOrder(sbTabWidth, cbWrapping); + QWidget::setTabOrder(cbWrapping, sbLineLength); + QWidget::setTabOrder(sbLineLength, cbAdvWrapping); + QWidget::setTabOrder(cbAdvWrapping, comboFontName); + QWidget::setTabOrder(comboFontName, leFontSize); + QWidget::setTabOrder(leFontSize, browserPreview); + QWidget::setTabOrder(browserPreview, pbStartConversion); + QWidget::setTabOrder(pbStartConversion, pbCopyFile2CP); + + menuBar->addAction(menu_File->menuAction()); + menuBar->addAction(menu_Help->menuAction()); + menu_File->addAction(action_Open_files); + menu_File->addSeparator(); + menu_File->addAction(action_Exit); + menu_Help->addAction(action_Tips); + menu_Help->addAction(action_Manual); + menu_Help->addAction(action_Changelog); + menu_Help->addAction(action_License); + menu_Help->addSeparator(); + menu_Help->addAction(actionAbout_translations); + menu_Help->addSeparator(); + menu_Help->addAction(action_About_Highlight); + + retranslateUi(MainWindowClass); + QObject::connect(pbClearAll, SIGNAL(clicked()), lvInputFiles, SLOT(clear())); + + tabIOSelection->setCurrentIndex(1); + tabWidget->setCurrentIndex(2); + stackedSpecificOptions->setCurrentIndex(0); + tabWidget1->setCurrentIndex(0); + comboRTFPageSize->setCurrentIndex(1); + + + QMetaObject::connectSlotsByName(MainWindowClass); + } // setupUi + + void retranslateUi(QMainWindow *MainWindowClass) + { + MainWindowClass->setWindowTitle(QApplication::translate("MainWindowClass", "Highlight", 0, QApplication::UnicodeUTF8)); + action_Open_files->setText(QApplication::translate("MainWindowClass", "&Open files", 0, QApplication::UnicodeUTF8)); + action_Exit->setText(QApplication::translate("MainWindowClass", "&Exit", 0, QApplication::UnicodeUTF8)); + action_Load->setText(QApplication::translate("MainWindowClass", "&Load", 0, QApplication::UnicodeUTF8)); + action_Save->setText(QApplication::translate("MainWindowClass", "&Save", 0, QApplication::UnicodeUTF8)); + actionLoad_default_project->setText(QApplication::translate("MainWindowClass", "Load &default project", 0, QApplication::UnicodeUTF8)); + action_Manual->setText(QApplication::translate("MainWindowClass", "Readme", 0, QApplication::UnicodeUTF8)); + action_Tips->setText(QApplication::translate("MainWindowClass", "&Tips", 0, QApplication::UnicodeUTF8)); + action_Changelog->setText(QApplication::translate("MainWindowClass", "&Changelog", 0, QApplication::UnicodeUTF8)); + action_License->setText(QApplication::translate("MainWindowClass", "&License", 0, QApplication::UnicodeUTF8)); + action_About_Highlight->setText(QApplication::translate("MainWindowClass", "&About Highlight", 0, QApplication::UnicodeUTF8)); + actionAbout_translations->setText(QApplication::translate("MainWindowClass", "About &translations", 0, QApplication::UnicodeUTF8)); +#ifndef QT_NO_TOOLTIP + pbOpenFiles->setToolTip(QApplication::translate("MainWindowClass", "Choose the source code files you want to convert.", 0, QApplication::UnicodeUTF8)); +#endif // QT_NO_TOOLTIP +#ifndef QT_NO_WHATSTHIS + pbOpenFiles->setWhatsThis(QString()); +#endif // QT_NO_WHATSTHIS + pbOpenFiles->setText(QApplication::translate("MainWindowClass", "Choose input files", 0, QApplication::UnicodeUTF8)); +#ifndef QT_NO_TOOLTIP + lvInputFiles->setToolTip(QApplication::translate("MainWindowClass", "List of input files.", 0, QApplication::UnicodeUTF8)); +#endif // QT_NO_TOOLTIP +#ifndef QT_NO_TOOLTIP + pbClearSelection->setToolTip(QApplication::translate("MainWindowClass", "Remove the selected input files.", 0, QApplication::UnicodeUTF8)); +#endif // QT_NO_TOOLTIP + pbClearSelection->setText(QApplication::translate("MainWindowClass", "Clear selection", 0, QApplication::UnicodeUTF8)); +#ifndef QT_NO_TOOLTIP + pbClearAll->setToolTip(QApplication::translate("MainWindowClass", "Remove all input files.", 0, QApplication::UnicodeUTF8)); +#endif // QT_NO_TOOLTIP + pbClearAll->setText(QApplication::translate("MainWindowClass", "Clear all", 0, QApplication::UnicodeUTF8)); + label_11->setText(QApplication::translate("MainWindowClass", "Output destination:", 0, QApplication::UnicodeUTF8)); +#ifndef QT_NO_TOOLTIP + leOutputDest->setToolTip(QApplication::translate("MainWindowClass", "Output directory", 0, QApplication::UnicodeUTF8)); +#endif // QT_NO_TOOLTIP +#ifndef QT_NO_TOOLTIP + pbOutputDest->setToolTip(QApplication::translate("MainWindowClass", "Select the output directory.", 0, QApplication::UnicodeUTF8)); +#endif // QT_NO_TOOLTIP + pbOutputDest->setText(QApplication::translate("MainWindowClass", "...", 0, QApplication::UnicodeUTF8)); +#ifndef QT_NO_TOOLTIP + cbWrite2Src->setToolTip(QApplication::translate("MainWindowClass", "Save output in the input file directories.", 0, QApplication::UnicodeUTF8)); +#endif // QT_NO_TOOLTIP + cbWrite2Src->setText(QApplication::translate("MainWindowClass", "Write to source directories", 0, QApplication::UnicodeUTF8)); +#ifndef QT_NO_TOOLTIP + pbStartConversion->setToolTip(QApplication::translate("MainWindowClass", "Start the conversion of your input files.", 0, QApplication::UnicodeUTF8)); +#endif // QT_NO_TOOLTIP + pbStartConversion->setText(QApplication::translate("MainWindowClass", "Convert files", 0, QApplication::UnicodeUTF8)); +#ifndef QT_NO_TOOLTIP + pbCopyFile2CP->setToolTip(QApplication::translate("MainWindowClass", "Copy highlighted code of the seleted file into the clipboard.", 0, QApplication::UnicodeUTF8)); +#endif // QT_NO_TOOLTIP + pbCopyFile2CP->setText(QApplication::translate("MainWindowClass", "Copy file to clipboard", 0, QApplication::UnicodeUTF8)); + tabIOSelection->setTabText(tabIOSelection->indexOf(tab_file_io), QApplication::translate("MainWindowClass", "Files", 0, QApplication::UnicodeUTF8)); +#ifndef QT_NO_TOOLTIP + pbPasteFromCB->setToolTip(QApplication::translate("MainWindowClass", "Paste clipboard content into the preview window.", 0, QApplication::UnicodeUTF8)); +#endif // QT_NO_TOOLTIP + pbPasteFromCB->setText(QApplication::translate("MainWindowClass", "Paste from clipboard", 0, QApplication::UnicodeUTF8)); + label_13->setText(QApplication::translate("MainWindowClass", "Select syntax:", 0, QApplication::UnicodeUTF8)); +#ifndef QT_NO_TOOLTIP + comboSelectSyntax->setToolTip(QApplication::translate("MainWindowClass", "Select the correct syntax of the code snippet.", 0, QApplication::UnicodeUTF8)); +#endif // QT_NO_TOOLTIP +#ifndef QT_NO_TOOLTIP + pbCopyToCP->setToolTip(QApplication::translate("MainWindowClass", "Copy highlighted code into the clipboard.", 0, QApplication::UnicodeUTF8)); +#endif // QT_NO_TOOLTIP + pbCopyToCP->setText(QApplication::translate("MainWindowClass", "Copy preview to clipboard", 0, QApplication::UnicodeUTF8)); + tabIOSelection->setTabText(tabIOSelection->indexOf(tab_clipboard), QApplication::translate("MainWindowClass", "Clipboard", 0, QApplication::UnicodeUTF8)); + label_2->setText(QApplication::translate("MainWindowClass", "Output format:", 0, QApplication::UnicodeUTF8)); + comboFormat->clear(); + comboFormat->insertItems(0, QStringList() + << QApplication::translate("MainWindowClass", "HTML", 0, QApplication::UnicodeUTF8) + << QApplication::translate("MainWindowClass", "XHTML", 0, QApplication::UnicodeUTF8) + << QApplication::translate("MainWindowClass", "LaTeX", 0, QApplication::UnicodeUTF8) + << QApplication::translate("MainWindowClass", "TeX", 0, QApplication::UnicodeUTF8) + << QApplication::translate("MainWindowClass", "RTF", 0, QApplication::UnicodeUTF8) + << QApplication::translate("MainWindowClass", "SVG", 0, QApplication::UnicodeUTF8) + << QApplication::translate("MainWindowClass", "XML", 0, QApplication::UnicodeUTF8) + << QApplication::translate("MainWindowClass", "BBCode", 0, QApplication::UnicodeUTF8) + ); +#ifndef QT_NO_TOOLTIP + comboFormat->setToolTip(QApplication::translate("MainWindowClass", "Choose an output format.", 0, QApplication::UnicodeUTF8)); +#endif // QT_NO_TOOLTIP +#ifndef QT_NO_TOOLTIP + cbIncLineNo->setToolTip(QApplication::translate("MainWindowClass", "Add line numbers to the output.", 0, QApplication::UnicodeUTF8)); +#endif // QT_NO_TOOLTIP + cbIncLineNo->setText(QApplication::translate("MainWindowClass", "Add line numbers", 0, QApplication::UnicodeUTF8)); +#ifndef QT_NO_TOOLTIP + sbLineNoWidth->setToolTip(QApplication::translate("MainWindowClass", "Select the line number width.", 0, QApplication::UnicodeUTF8)); +#endif // QT_NO_TOOLTIP +#ifndef QT_NO_TOOLTIP + cbPadZeroes->setToolTip(QApplication::translate("MainWindowClass", "Fill leading space of line numbers with zeroes.", 0, QApplication::UnicodeUTF8)); +#endif // QT_NO_TOOLTIP + cbPadZeroes->setText(QApplication::translate("MainWindowClass", "Pad with zeroes", 0, QApplication::UnicodeUTF8)); +#ifndef QT_NO_TOOLTIP + cbFragment->setToolTip(QApplication::translate("MainWindowClass", "Generate output without document header and footer.", 0, QApplication::UnicodeUTF8)); +#endif // QT_NO_TOOLTIP + cbFragment->setText(QApplication::translate("MainWindowClass", "Omit header and footer", 0, QApplication::UnicodeUTF8)); +#ifndef QT_NO_TOOLTIP + cbValidateInput->setToolTip(QApplication::translate("MainWindowClass", "Test if input data is not binary.\n" +"Removes Unicode BOM mark.", 0, QApplication::UnicodeUTF8)); +#endif // QT_NO_TOOLTIP + cbValidateInput->setText(QApplication::translate("MainWindowClass", "Validate input data", 0, QApplication::UnicodeUTF8)); +#ifndef QT_NO_TOOLTIP + cbEncoding->setToolTip(QApplication::translate("MainWindowClass", "Set the output file ancoding.", 0, QApplication::UnicodeUTF8)); +#endif // QT_NO_TOOLTIP + cbEncoding->setText(QApplication::translate("MainWindowClass", "Set encoding:", 0, QApplication::UnicodeUTF8)); + comboEncoding->clear(); + comboEncoding->insertItems(0, QStringList() + << QApplication::translate("MainWindowClass", "ISO-8859-1", 0, QApplication::UnicodeUTF8) + << QApplication::translate("MainWindowClass", "ISO-8859-2", 0, QApplication::UnicodeUTF8) + << QApplication::translate("MainWindowClass", "ISO-8859-3", 0, QApplication::UnicodeUTF8) + << QApplication::translate("MainWindowClass", "ISO-8859-4", 0, QApplication::UnicodeUTF8) + << QApplication::translate("MainWindowClass", "ISO-8859-5", 0, QApplication::UnicodeUTF8) + << QApplication::translate("MainWindowClass", "ISO-8859-6", 0, QApplication::UnicodeUTF8) + << QApplication::translate("MainWindowClass", "ISO-8859-7", 0, QApplication::UnicodeUTF8) + << QApplication::translate("MainWindowClass", "ISO-8859-8", 0, QApplication::UnicodeUTF8) + << QApplication::translate("MainWindowClass", "ISO-8859-9", 0, QApplication::UnicodeUTF8) + << QApplication::translate("MainWindowClass", "ISO-8859-10", 0, QApplication::UnicodeUTF8) + << QApplication::translate("MainWindowClass", "ISO-8859-11", 0, QApplication::UnicodeUTF8) + << QApplication::translate("MainWindowClass", "ISO-8859-12", 0, QApplication::UnicodeUTF8) + << QApplication::translate("MainWindowClass", "ISO-8859-13", 0, QApplication::UnicodeUTF8) + << QApplication::translate("MainWindowClass", "ISO-8859-14", 0, QApplication::UnicodeUTF8) + << QApplication::translate("MainWindowClass", "ISO-8859-15", 0, QApplication::UnicodeUTF8) + << QApplication::translate("MainWindowClass", "UTF-8", 0, QApplication::UnicodeUTF8) + ); +#ifndef QT_NO_TOOLTIP + comboEncoding->setToolTip(QApplication::translate("MainWindowClass", "Select or define the encoding.\n" +"The result has to match the input file encoding.", 0, QApplication::UnicodeUTF8)); +#endif // QT_NO_TOOLTIP + tabWidget->setTabText(tabWidget->indexOf(page_general), QApplication::translate("MainWindowClass", "General", 0, QApplication::UnicodeUTF8)); + label_17->setText(QApplication::translate("MainWindowClass", "HTML options", 0, QApplication::UnicodeUTF8)); +#ifndef QT_NO_TOOLTIP + cbHTMLEmbedStyle->setToolTip(QApplication::translate("MainWindowClass", "Include the style information in each output file.", 0, QApplication::UnicodeUTF8)); +#endif // QT_NO_TOOLTIP + cbHTMLEmbedStyle->setText(QApplication::translate("MainWindowClass", "Embed style (CSS)", 0, QApplication::UnicodeUTF8)); +#ifndef QT_NO_TOOLTIP + cbHTMLInlineCSS->setToolTip(QApplication::translate("MainWindowClass", "Add CSS information to each tag (do not use CSS class definitions).", 0, QApplication::UnicodeUTF8)); +#endif // QT_NO_TOOLTIP + cbHTMLInlineCSS->setText(QApplication::translate("MainWindowClass", "Inline CSS", 0, QApplication::UnicodeUTF8)); + label_19->setText(QApplication::translate("MainWindowClass", "Stylesheet file:", 0, QApplication::UnicodeUTF8)); +#ifndef QT_NO_TOOLTIP + leHTMLStyleFile->setToolTip(QApplication::translate("MainWindowClass", "Name of the referenced style file.", 0, QApplication::UnicodeUTF8)); +#endif // QT_NO_TOOLTIP + leHTMLStyleFile->setText(QApplication::translate("MainWindowClass", "highlight.css", 0, QApplication::UnicodeUTF8)); + label_20->setText(QApplication::translate("MainWindowClass", "Include:", 0, QApplication::UnicodeUTF8)); +#ifndef QT_NO_TOOLTIP + leHTMLStyleIncFile->setToolTip(QApplication::translate("MainWindowClass", "Path of the CSS include file.", 0, QApplication::UnicodeUTF8)); +#endif // QT_NO_TOOLTIP +#ifndef QT_NO_TOOLTIP + pbHTMLChooseStyleIncFile->setToolTip(QApplication::translate("MainWindowClass", "Select a CSS include file.", 0, QApplication::UnicodeUTF8)); +#endif // QT_NO_TOOLTIP + pbHTMLChooseStyleIncFile->setText(QApplication::translate("MainWindowClass", "...", 0, QApplication::UnicodeUTF8)); + label->setText(QApplication::translate("MainWindowClass", "CSS class prefix:", 0, QApplication::UnicodeUTF8)); +#ifndef QT_NO_TOOLTIP + leHTMLCssPrefix->setToolTip(QApplication::translate("MainWindowClass", "Add a CSS class name prefix to avoid namespace clashes.", 0, QApplication::UnicodeUTF8)); +#endif // QT_NO_TOOLTIP + leHTMLCssPrefix->setText(QString()); + tabWidget1->setTabText(tabWidget1->indexOf(tabWidgetPage1), QApplication::translate("MainWindowClass", "Stylesheets", 0, QApplication::UnicodeUTF8)); +#ifndef QT_NO_TOOLTIP + cbHTMLIndex->setToolTip(QApplication::translate("MainWindowClass", "Generate an index file with hyperlinks to all outputted files.", 0, QApplication::UnicodeUTF8)); +#endif // QT_NO_TOOLTIP + cbHTMLIndex->setText(QApplication::translate("MainWindowClass", "Generate index file", 0, QApplication::UnicodeUTF8)); +#ifndef QT_NO_TOOLTIP + cbHTMLCtags->setToolTip(QApplication::translate("MainWindowClass", "Read a ctags file and add the included metainformation as tooltips.\n" +"See ctags.sf.net for details.", 0, QApplication::UnicodeUTF8)); +#endif // QT_NO_TOOLTIP + cbHTMLCtags->setText(QApplication::translate("MainWindowClass", "Read ctags file:", 0, QApplication::UnicodeUTF8)); +#ifndef QT_NO_TOOLTIP + leHTMLCtagsFile->setToolTip(QApplication::translate("MainWindowClass", "Path of the ctags file.", 0, QApplication::UnicodeUTF8)); +#endif // QT_NO_TOOLTIP +#ifndef QT_NO_TOOLTIP + pbHTMLChooseTagsFile->setToolTip(QApplication::translate("MainWindowClass", "Choose a ctags file.", 0, QApplication::UnicodeUTF8)); +#endif // QT_NO_TOOLTIP + pbHTMLChooseTagsFile->setText(QApplication::translate("MainWindowClass", "...", 0, QApplication::UnicodeUTF8)); + tabWidget1->setTabText(tabWidget1->indexOf(tabWidgetPage2), QApplication::translate("MainWindowClass", "Index/ctags", 0, QApplication::UnicodeUTF8)); + label_8->setText(QApplication::translate("MainWindowClass", "Line numbering options:", 0, QApplication::UnicodeUTF8)); +#ifndef QT_NO_TOOLTIP + cbHTMLAnchors->setToolTip(QApplication::translate("MainWindowClass", "Add an achor to each line.", 0, QApplication::UnicodeUTF8)); +#endif // QT_NO_TOOLTIP + cbHTMLAnchors->setText(QApplication::translate("MainWindowClass", "Add line anchors", 0, QApplication::UnicodeUTF8)); +#ifndef QT_NO_TOOLTIP + cbHTMLFileNameAnchor->setToolTip(QApplication::translate("MainWindowClass", "Add the filename as prefix to the anchors.", 0, QApplication::UnicodeUTF8)); +#endif // QT_NO_TOOLTIP + cbHTMLFileNameAnchor->setText(QApplication::translate("MainWindowClass", "Include file name in anchor", 0, QApplication::UnicodeUTF8)); +#ifndef QT_NO_TOOLTIP + cbHTMLOrderedList->setToolTip(QApplication::translate("MainWindowClass", "Output the lines within an ordered list.", 0, QApplication::UnicodeUTF8)); +#endif // QT_NO_TOOLTIP + cbHTMLOrderedList->setText(QApplication::translate("MainWindowClass", "Output as ordered list", 0, QApplication::UnicodeUTF8)); +#ifndef QT_NO_TOOLTIP + cbHTMLEnclosePreTags->setToolTip(QApplication::translate("MainWindowClass", "Add <pre> tags to the output, if the flag \"No document header and footer\" is selected.", 0, QApplication::UnicodeUTF8)); +#endif // QT_NO_TOOLTIP + cbHTMLEnclosePreTags->setText(QApplication::translate("MainWindowClass", "Enclose in pre tags", 0, QApplication::UnicodeUTF8)); + tabWidget1->setTabText(tabWidget1->indexOf(tabWidgetPage3), QApplication::translate("MainWindowClass", "Misc", 0, QApplication::UnicodeUTF8)); + label_18->setText(QApplication::translate("MainWindowClass", "LaTeX options", 0, QApplication::UnicodeUTF8)); +#ifndef QT_NO_TOOLTIP + cbLATEXEscQuotes->setToolTip(QApplication::translate("MainWindowClass", "Replace quotes by dq sequences.", 0, QApplication::UnicodeUTF8)); +#endif // QT_NO_TOOLTIP + cbLATEXEscQuotes->setText(QApplication::translate("MainWindowClass", "Escape quotes", 0, QApplication::UnicodeUTF8)); +#ifndef QT_NO_TOOLTIP + cbLATEXBabel->setToolTip(QApplication::translate("MainWindowClass", "Make output Babel compatible.", 0, QApplication::UnicodeUTF8)); +#endif // QT_NO_TOOLTIP + cbLATEXBabel->setText(QApplication::translate("MainWindowClass", "Add Babel compatibility", 0, QApplication::UnicodeUTF8)); +#ifndef QT_NO_TOOLTIP + cbLATEXPrettySymbols->setToolTip(QApplication::translate("MainWindowClass", "Replace default symbols (brackets, tilde) by nice redefinitions.", 0, QApplication::UnicodeUTF8)); +#endif // QT_NO_TOOLTIP + cbLATEXPrettySymbols->setText(QApplication::translate("MainWindowClass", "Add pretty symbols", 0, QApplication::UnicodeUTF8)); +#ifndef QT_NO_TOOLTIP + cbLATEXEmbedStyle->setToolTip(QApplication::translate("MainWindowClass", "Include the style information in each output file.", 0, QApplication::UnicodeUTF8)); +#endif // QT_NO_TOOLTIP + cbLATEXEmbedStyle->setText(QApplication::translate("MainWindowClass", "Embed style (defs)", 0, QApplication::UnicodeUTF8)); + label_21->setText(QApplication::translate("MainWindowClass", "Stylesheet file:", 0, QApplication::UnicodeUTF8)); +#ifndef QT_NO_TOOLTIP + leLATEXStyleFile->setToolTip(QApplication::translate("MainWindowClass", "Name of the referenced style file.", 0, QApplication::UnicodeUTF8)); +#endif // QT_NO_TOOLTIP + leLATEXStyleFile->setText(QApplication::translate("MainWindowClass", "highlight.sty", 0, QApplication::UnicodeUTF8)); + label_22->setText(QApplication::translate("MainWindowClass", "Stylesheet include file:", 0, QApplication::UnicodeUTF8)); +#ifndef QT_NO_TOOLTIP + leLATEXStyleIncFile->setToolTip(QApplication::translate("MainWindowClass", "Path of the style include file.", 0, QApplication::UnicodeUTF8)); +#endif // QT_NO_TOOLTIP +#ifndef QT_NO_TOOLTIP + pbLATEXChooseStyleIncFile->setToolTip(QApplication::translate("MainWindowClass", "Select a style include file.", 0, QApplication::UnicodeUTF8)); +#endif // QT_NO_TOOLTIP + pbLATEXChooseStyleIncFile->setText(QApplication::translate("MainWindowClass", "...", 0, QApplication::UnicodeUTF8)); + label_26->setText(QApplication::translate("MainWindowClass", "TeX options", 0, QApplication::UnicodeUTF8)); +#ifndef QT_NO_TOOLTIP + cbTEXEmbedStyle->setToolTip(QApplication::translate("MainWindowClass", "Include the style information in each output file.", 0, QApplication::UnicodeUTF8)); +#endif // QT_NO_TOOLTIP + cbTEXEmbedStyle->setText(QApplication::translate("MainWindowClass", "Embed style (macros)", 0, QApplication::UnicodeUTF8)); + label_24->setText(QApplication::translate("MainWindowClass", "Stylesheet file:", 0, QApplication::UnicodeUTF8)); +#ifndef QT_NO_TOOLTIP + leTEXStyleFile->setToolTip(QApplication::translate("MainWindowClass", "Name of the referenced style file.", 0, QApplication::UnicodeUTF8)); +#endif // QT_NO_TOOLTIP + leTEXStyleFile->setText(QApplication::translate("MainWindowClass", "highlight.sty", 0, QApplication::UnicodeUTF8)); + label_25->setText(QApplication::translate("MainWindowClass", "Stylesheet include file:", 0, QApplication::UnicodeUTF8)); +#ifndef QT_NO_TOOLTIP + leTEXStyleIncFile->setToolTip(QApplication::translate("MainWindowClass", "Path of the style include file.", 0, QApplication::UnicodeUTF8)); +#endif // QT_NO_TOOLTIP +#ifndef QT_NO_TOOLTIP + pbTEXChooseStyleIncFile->setToolTip(QApplication::translate("MainWindowClass", "Select a style include file.", 0, QApplication::UnicodeUTF8)); +#endif // QT_NO_TOOLTIP + pbTEXChooseStyleIncFile->setText(QApplication::translate("MainWindowClass", "...", 0, QApplication::UnicodeUTF8)); + label_15->setText(QApplication::translate("MainWindowClass", "RTF options", 0, QApplication::UnicodeUTF8)); +#ifndef QT_NO_TOOLTIP + cbRTFCharStyles->setToolTip(QApplication::translate("MainWindowClass", "Add character stylesheets with formatting information.\n" +"You can select the stylesheets in your word processor to reformat additional text.", 0, QApplication::UnicodeUTF8)); +#endif // QT_NO_TOOLTIP + cbRTFCharStyles->setText(QApplication::translate("MainWindowClass", "Add character styles", 0, QApplication::UnicodeUTF8)); + label_9->setText(QApplication::translate("MainWindowClass", "Page size:", 0, QApplication::UnicodeUTF8)); + comboRTFPageSize->clear(); + comboRTFPageSize->insertItems(0, QStringList() + << QApplication::translate("MainWindowClass", "A3", 0, QApplication::UnicodeUTF8) + << QApplication::translate("MainWindowClass", "A4", 0, QApplication::UnicodeUTF8) + << QApplication::translate("MainWindowClass", "A5", 0, QApplication::UnicodeUTF8) + << QApplication::translate("MainWindowClass", "B4", 0, QApplication::UnicodeUTF8) + << QApplication::translate("MainWindowClass", "B5", 0, QApplication::UnicodeUTF8) + << QApplication::translate("MainWindowClass", "B6", 0, QApplication::UnicodeUTF8) + << QApplication::translate("MainWindowClass", "Letter", 0, QApplication::UnicodeUTF8) + << QApplication::translate("MainWindowClass", "Legal", 0, QApplication::UnicodeUTF8) + ); +#ifndef QT_NO_TOOLTIP + comboRTFPageSize->setToolTip(QApplication::translate("MainWindowClass", "Select a page size.", 0, QApplication::UnicodeUTF8)); +#endif // QT_NO_TOOLTIP + label_16->setText(QApplication::translate("MainWindowClass", "SVG options", 0, QApplication::UnicodeUTF8)); + label_10->setText(QApplication::translate("MainWindowClass", "Image size:", 0, QApplication::UnicodeUTF8)); + label_3->setText(QApplication::translate("MainWindowClass", "Width:", 0, QApplication::UnicodeUTF8)); +#ifndef QT_NO_TOOLTIP + leSVGWidth->setToolTip(QApplication::translate("MainWindowClass", "Enter the SVG width (may contain units).", 0, QApplication::UnicodeUTF8)); +#endif // QT_NO_TOOLTIP + label_12->setText(QApplication::translate("MainWindowClass", "Height:", 0, QApplication::UnicodeUTF8)); +#ifndef QT_NO_TOOLTIP + leSVGHeight->setToolTip(QApplication::translate("MainWindowClass", "Enter the SVG height (may contain units).", 0, QApplication::UnicodeUTF8)); +#endif // QT_NO_TOOLTIP +#ifndef QT_NO_TOOLTIP + cbSVGEmbedStyle->setToolTip(QApplication::translate("MainWindowClass", "Include the style information in each output file.", 0, QApplication::UnicodeUTF8)); +#endif // QT_NO_TOOLTIP + cbSVGEmbedStyle->setText(QApplication::translate("MainWindowClass", "Embed style (CSS)", 0, QApplication::UnicodeUTF8)); + label_29->setText(QApplication::translate("MainWindowClass", "Stylesheet file:", 0, QApplication::UnicodeUTF8)); +#ifndef QT_NO_TOOLTIP + leSVGStyleFile->setToolTip(QApplication::translate("MainWindowClass", "Name of the referenced style file.", 0, QApplication::UnicodeUTF8)); +#endif // QT_NO_TOOLTIP + leSVGStyleFile->setText(QApplication::translate("MainWindowClass", "highlight.css", 0, QApplication::UnicodeUTF8)); + label_30->setText(QApplication::translate("MainWindowClass", "Stylesheet include file:", 0, QApplication::UnicodeUTF8)); +#ifndef QT_NO_TOOLTIP + leSVGStyleIncFile->setToolTip(QApplication::translate("MainWindowClass", "Path of the CSS include file.", 0, QApplication::UnicodeUTF8)); +#endif // QT_NO_TOOLTIP +#ifndef QT_NO_TOOLTIP + pbSVGChooseStyleIncFile->setToolTip(QApplication::translate("MainWindowClass", "Select a style include file.", 0, QApplication::UnicodeUTF8)); +#endif // QT_NO_TOOLTIP + pbSVGChooseStyleIncFile->setText(QApplication::translate("MainWindowClass", "...", 0, QApplication::UnicodeUTF8)); + label_7->setText(QApplication::translate("MainWindowClass", "No options defined.", 0, QApplication::UnicodeUTF8)); + tabWidget->setTabText(tabWidget->indexOf(page_output_spec), QApplication::translate("MainWindowClass", "Output specific", 0, QApplication::UnicodeUTF8)); + label_5->setText(QApplication::translate("MainWindowClass", "Color theme:", 0, QApplication::UnicodeUTF8)); +#ifndef QT_NO_TOOLTIP + comboTheme->setToolTip(QApplication::translate("MainWindowClass", "Select a colour theme.", 0, QApplication::UnicodeUTF8)); +#endif // QT_NO_TOOLTIP +#ifndef QT_NO_TOOLTIP + cbReformat->setToolTip(QApplication::translate("MainWindowClass", "Reformat and indent your code.\n" +"This feature is enabled tor C, C++, C# and Java code.", 0, QApplication::UnicodeUTF8)); +#endif // QT_NO_TOOLTIP + cbReformat->setText(QApplication::translate("MainWindowClass", "Reformat:", 0, QApplication::UnicodeUTF8)); + comboReformat->clear(); + comboReformat->insertItems(0, QStringList() + << QApplication::translate("MainWindowClass", "Allman", 0, QApplication::UnicodeUTF8) + << QApplication::translate("MainWindowClass", "Banner", 0, QApplication::UnicodeUTF8) + << QApplication::translate("MainWindowClass", "GNU", 0, QApplication::UnicodeUTF8) + << QApplication::translate("MainWindowClass", "Horstmann", 0, QApplication::UnicodeUTF8) + << QApplication::translate("MainWindowClass", "Java", 0, QApplication::UnicodeUTF8) + << QApplication::translate("MainWindowClass", "K&R", 0, QApplication::UnicodeUTF8) + << QApplication::translate("MainWindowClass", "Linux", 0, QApplication::UnicodeUTF8) + << QApplication::translate("MainWindowClass", "OTBS", 0, QApplication::UnicodeUTF8) + << QApplication::translate("MainWindowClass", "Stroustrup", 0, QApplication::UnicodeUTF8) + << QApplication::translate("MainWindowClass", "Whitesmith", 0, QApplication::UnicodeUTF8) + ); +#ifndef QT_NO_TOOLTIP + comboReformat->setToolTip(QApplication::translate("MainWindowClass", "Choose a formatting scheme.", 0, QApplication::UnicodeUTF8)); +#endif // QT_NO_TOOLTIP +#ifndef QT_NO_TOOLTIP + cbKwCase->setToolTip(QApplication::translate("MainWindowClass", "Change the keyword case.", 0, QApplication::UnicodeUTF8)); +#endif // QT_NO_TOOLTIP + cbKwCase->setText(QApplication::translate("MainWindowClass", "Keyword case:", 0, QApplication::UnicodeUTF8)); + comboKwCase->clear(); + comboKwCase->insertItems(0, QStringList() + << QApplication::translate("MainWindowClass", "UPPER", 0, QApplication::UnicodeUTF8) + << QApplication::translate("MainWindowClass", "lower", 0, QApplication::UnicodeUTF8) + << QApplication::translate("MainWindowClass", "Capitalize", 0, QApplication::UnicodeUTF8) + ); +#ifndef QT_NO_TOOLTIP + comboKwCase->setToolTip(QApplication::translate("MainWindowClass", "Select a keyword case.", 0, QApplication::UnicodeUTF8)); +#endif // QT_NO_TOOLTIP + label_6->setText(QApplication::translate("MainWindowClass", "Tab width:", 0, QApplication::UnicodeUTF8)); +#ifndef QT_NO_TOOLTIP + sbTabWidth->setToolTip(QApplication::translate("MainWindowClass", "Enter the number of spaces which replace a tab.\n" +"Set the width to 0 to keep tabs.", 0, QApplication::UnicodeUTF8)); +#endif // QT_NO_TOOLTIP +#ifndef QT_NO_TOOLTIP + cbWrapping->setToolTip(QApplication::translate("MainWindowClass", "Enable line wrapping.", 0, QApplication::UnicodeUTF8)); +#endif // QT_NO_TOOLTIP + cbWrapping->setText(QApplication::translate("MainWindowClass", "Line wrapping", 0, QApplication::UnicodeUTF8)); +#ifndef QT_NO_TOOLTIP + sbLineLength->setToolTip(QApplication::translate("MainWindowClass", "Enter the maximum line length.", 0, QApplication::UnicodeUTF8)); +#endif // QT_NO_TOOLTIP +#ifndef QT_NO_TOOLTIP + cbAdvWrapping->setToolTip(QApplication::translate("MainWindowClass", "Indent statements and function parameters after wrapping.", 0, QApplication::UnicodeUTF8)); +#endif // QT_NO_TOOLTIP + cbAdvWrapping->setText(QApplication::translate("MainWindowClass", "Intelligent wrapping", 0, QApplication::UnicodeUTF8)); + label_23->setText(QApplication::translate("MainWindowClass", "Font name:", 0, QApplication::UnicodeUTF8)); +#ifndef QT_NO_TOOLTIP + comboFontName->setToolTip(QApplication::translate("MainWindowClass", "Select or enter the font name.", 0, QApplication::UnicodeUTF8)); +#endif // QT_NO_TOOLTIP + label_4->setText(QApplication::translate("MainWindowClass", "Font size:", 0, QApplication::UnicodeUTF8)); +#ifndef QT_NO_TOOLTIP + leFontSize->setToolTip(QApplication::translate("MainWindowClass", "Enter the font size.", 0, QApplication::UnicodeUTF8)); +#endif // QT_NO_TOOLTIP + tabWidget->setTabText(tabWidget->indexOf(page_formatting), QApplication::translate("MainWindowClass", "Formatting", 0, QApplication::UnicodeUTF8)); + lbPreview->setText(QApplication::translate("MainWindowClass", "Preview", 0, QApplication::UnicodeUTF8)); +#ifndef QT_NO_TOOLTIP + browserPreview->setToolTip(QString()); +#endif // QT_NO_TOOLTIP +#ifndef QT_NO_WHATSTHIS + browserPreview->setWhatsThis(QString()); +#endif // QT_NO_WHATSTHIS + label_14->setText(QApplication::translate("MainWindowClass", "Output progress:", 0, QApplication::UnicodeUTF8)); + menu_File->setTitle(QApplication::translate("MainWindowClass", "&File", 0, QApplication::UnicodeUTF8)); + menu_Help->setTitle(QApplication::translate("MainWindowClass", "&Help", 0, QApplication::UnicodeUTF8)); + } // retranslateUi + +}; + +namespace Ui { + class MainWindowClass: public Ui_MainWindowClass {}; +} // namespace Ui + +QT_END_NAMESPACE + +#endif // UI_MAINWINDOW_H diff --git a/support/highlight/src/gui-qt/ui_showtextfile.h b/support/highlight/src/gui-qt/ui_showtextfile.h new file mode 100644 index 0000000000..d46b490858 --- /dev/null +++ b/support/highlight/src/gui-qt/ui_showtextfile.h @@ -0,0 +1,105 @@ +/******************************************************************************** +** Form generated from reading UI file 'showtextfile.ui' +** +** Created: Wed Mar 31 16:43:25 2010 +** by: Qt User Interface Compiler version 4.6.2 +** +** WARNING! All changes made in this file will be lost when recompiling UI file! +********************************************************************************/ + +#ifndef UI_SHOWTEXTFILE_H +#define UI_SHOWTEXTFILE_H + +#include <QtCore/QVariant> +#include <QtGui/QAction> +#include <QtGui/QApplication> +#include <QtGui/QButtonGroup> +#include <QtGui/QDialog> +#include <QtGui/QHBoxLayout> +#include <QtGui/QHeaderView> +#include <QtGui/QLabel> +#include <QtGui/QPushButton> +#include <QtGui/QSpacerItem> +#include <QtGui/QTextEdit> +#include <QtGui/QVBoxLayout> + +QT_BEGIN_NAMESPACE + +class Ui_ShowTextFile +{ +public: + QVBoxLayout *verticalLayout; + QLabel *lbTitle; + QTextEdit *textEdit; + QHBoxLayout *horizontalLayout; + QSpacerItem *horizontalSpacer; + QPushButton *pushButton; + + void setupUi(QDialog *ShowTextFile) + { + if (ShowTextFile->objectName().isEmpty()) + ShowTextFile->setObjectName(QString::fromUtf8("ShowTextFile")); + ShowTextFile->setWindowModality(Qt::WindowModal); + ShowTextFile->resize(711, 442); + QIcon icon; + icon.addFile(QString::fromUtf8(":/hl_icon2.png"), QSize(), QIcon::Normal, QIcon::Off); + ShowTextFile->setWindowIcon(icon); + ShowTextFile->setModal(true); + verticalLayout = new QVBoxLayout(ShowTextFile); + verticalLayout->setObjectName(QString::fromUtf8("verticalLayout")); + lbTitle = new QLabel(ShowTextFile); + lbTitle->setObjectName(QString::fromUtf8("lbTitle")); + QFont font; + font.setPointSize(10); + font.setBold(true); + font.setWeight(75); + lbTitle->setFont(font); + + verticalLayout->addWidget(lbTitle); + + textEdit = new QTextEdit(ShowTextFile); + textEdit->setObjectName(QString::fromUtf8("textEdit")); + QFont font1; + font1.setFamily(QString::fromUtf8("Courier New")); + font1.setPointSize(8); + textEdit->setFont(font1); + + verticalLayout->addWidget(textEdit); + + horizontalLayout = new QHBoxLayout(); + horizontalLayout->setObjectName(QString::fromUtf8("horizontalLayout")); + horizontalSpacer = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum); + + horizontalLayout->addItem(horizontalSpacer); + + pushButton = new QPushButton(ShowTextFile); + pushButton->setObjectName(QString::fromUtf8("pushButton")); + pushButton->setDefault(true); + + horizontalLayout->addWidget(pushButton); + + + verticalLayout->addLayout(horizontalLayout); + + + retranslateUi(ShowTextFile); + + QMetaObject::connectSlotsByName(ShowTextFile); + } // setupUi + + void retranslateUi(QDialog *ShowTextFile) + { + ShowTextFile->setWindowTitle(QApplication::translate("ShowTextFile", "Show text", 0, QApplication::UnicodeUTF8)); + lbTitle->setText(QApplication::translate("ShowTextFile", "TextLabel", 0, QApplication::UnicodeUTF8)); + pushButton->setText(QApplication::translate("ShowTextFile", "OK", 0, QApplication::UnicodeUTF8)); + } // retranslateUi + +}; + +namespace Ui { + class ShowTextFile: public Ui_ShowTextFile {}; +} // namespace Ui + +QT_END_NAMESPACE + +#endif // UI_SHOWTEXTFILE_H diff --git a/support/highlight/src/makefile b/support/highlight/src/makefile new file mode 100644 index 0000000000..e2dbabf684 --- /dev/null +++ b/support/highlight/src/makefile @@ -0,0 +1,218 @@ +# Simple Makefile for Highlight +# This file will compile the highlight library and binaries. +# See INSTALL for instructions. + +# Add -DHL_DATA_DIR=\"/your/path/\" to CFLAGS if you want to define a +# custom installation directory not listed in INSTALL. +# Copy *.conf, ./langDefs, ./themes amd ./indentSchemes to /your/path/. +# See ../makefile for the definition of ${data_dir} + +# Add -DHL_CONFIG_DIR=\"/your/path/\" to define the configuration directory +# (default: /etc/highlight) + +# Add -DCONFIG_FILE_PATH=\"/your/path/.highlightrc\" if you want to define a +# custom path to the highlight configuration file (default: $HOME/.highlightrc) + +# See src/gui-qt/highlight.pro for the Qt GUI compilation options + +CXX=c++ + +QMAKE=qmake + +CFLAGS:=-O2 ${CFLAGS} +#CFLAGS:=-ggdb ${CFLAGS} + +SO_VERSION=2.13 + +# Source paths +CORE_DIR=./core/ +CLI_DIR=./cli/ +GUI_QT_DIR=./gui-qt/ + +# Third-Party software paths +ASTYLE_DIR=${CORE_DIR}astyle/ +REGEX_DIR=${CORE_DIR}re/ + +ifndef HL_CONFIG_DIR + HL_CONFIG_DIR = /etc/highlight/ +endif +ifndef HL_DATA_DIR + HL_DATA_DIR = /usr/share/highlight/ +endif +ifdef PIC + CFLAGS+=-fPIC +endif + +# Do not strip by default (Mac OS X lazy pointer issues) +# Add -static to avoid linking with shared libs (can cause trouble when highlight +# is run as service) +#LDFLAGS = +#LDFLAGS = ${LDFLAGS} -s +#LDFLAGS= -Wl,--as-needed + +CXX_COMPILE=${CXX} ${CFLAGS} -c -I ${CORE_DIR} + +# Data directories (data dir, configuration file dir) +CXX_DIR=-DHL_DATA_DIR=\"${HL_DATA_DIR}\" -DHL_CONFIG_DIR=\"${HL_CONFIG_DIR}\" + +AR=ar +ARFLAGS=-crs + +# objects files to build the library +CORE_OBJECTS:=configurationreader.o stylecolour.o stringtools.o \ + xhtmlgenerator.o latexgenerator.o texgenerator.o rtfgenerator.o \ + htmlgenerator.o ansigenerator.o xmlgenerator.o svggenerator.o codegenerator.o \ + xterm256generator.o bbcodegenerator.o \ + languagedefinition.o elementstyle.o documentstyle.o \ + datadir.o preformatter.o platform_fs.o ctagsreader.o\ + ASStreamIterator.o ASResource.o ASFormatter.o ASBeautifier.o ASEnhancer.o\ + Pattern.o Matcher.o + +# command line interface +CLI_OBJECTS:=arg_parser.o cmdlineoptions.o main.o help.o + +# Qt user interface +GUI_OBJECTS:=${GUI_QT_DIR}main.cpp ${GUI_QT_DIR}mainwindow.cpp ${GUI_QT_DIR}io_report.cpp ${GUI_QT_DIR}showtextfile.cpp + + +cli: libhighlight.a ${CLI_OBJECTS} + ${CXX} ${LDFLAGS} -o highlight ${CLI_OBJECTS} -L. -lhighlight + +lib-static libhighlight.a: ${CORE_OBJECTS} + ${AR} ${ARFLAGS} libhighlight.a ${CORE_OBJECTS} + +lib-shared libhighlight.so.1.0: ${CORE_OBJECTS} + ld -shared -soname libhighlight.so.1 -o libhighlight.so.${SO_VERSION} -lc ${CORE_OBJECTS} + +gui-qt: highlight-gui + +highlight-gui: libhighlight.a ${GUI_OBJECTS} + cd gui-qt && \ + ${QMAKE} 'DEFINES+=DATA_DIR=\\\"${HL_DATA_DIR}\\\" CONFIG_DIR=\\\"${HL_CONFIG_DIR}\\\" DOC_DIR=\\\"${HL_DOC_DIR}\\\"' && \ + make + +$(OBJECTFILES) : makefile + +ansigenerator.o: ${CORE_DIR}ansigenerator.cpp ${CORE_DIR}ansigenerator.h ${CORE_DIR}codegenerator.h + ${CXX_COMPILE} ${CORE_DIR}ansigenerator.cpp + +ASBeautifier.o: ${ASTYLE_DIR}ASBeautifier.cpp ${ASTYLE_DIR}astyle.h + ${CXX_COMPILE} ${ASTYLE_DIR}ASBeautifier.cpp + +ASFormatter.o: ${ASTYLE_DIR}ASFormatter.cpp ${ASTYLE_DIR}astyle.h + ${CXX_COMPILE} ${ASTYLE_DIR}ASFormatter.cpp + +ASResource.o: ${ASTYLE_DIR}ASResource.cpp ${ASTYLE_DIR}astyle.h + ${CXX_COMPILE} ${ASTYLE_DIR}ASResource.cpp + +ASEnhancer.o: ${ASTYLE_DIR}ASResource.cpp ${ASTYLE_DIR}astyle.h + ${CXX_COMPILE} ${ASTYLE_DIR}ASEnhancer.cpp + +ASStreamIterator.o: ${ASTYLE_DIR}ASStreamIterator.cpp ${ASTYLE_DIR}astyle.h + ${CXX_COMPILE} ${ASTYLE_DIR}ASStreamIterator.cpp + +cmdlineoptions.o: ${CLI_DIR}cmdlineoptions.cpp ${CLI_DIR}cmdlineoptions.h + ${CXX_COMPILE} ${CLI_DIR}cmdlineoptions.cpp + +codegenerator.o: ${CORE_DIR}codegenerator.cpp ${CORE_DIR}codegenerator.h ${CORE_DIR}languagedefinition.h \ + ${CORE_DIR}configurationreader.h ${CORE_DIR}stringtools.h ${CORE_DIR}enums.h ${CORE_DIR}documentstyle.h \ + ${CORE_DIR}elementstyle.h ${CORE_DIR}stylecolour.h ${ASTYLE_DIR}astyle.h ${CORE_DIR}preformatter.h \ + ${CORE_DIR}htmlgenerator.h ${CORE_DIR}version.h ${CORE_DIR}charcodes.h ${CORE_DIR}xhtmlgenerator.h ${CORE_DIR}rtfgenerator.h \ + ${CORE_DIR}latexgenerator.h ${CORE_DIR}texgenerator.h ${CORE_DIR}ansigenerator.h + ${CXX_COMPILE} ${CORE_DIR}codegenerator.cpp + +configurationreader.o: ${CORE_DIR}configurationreader.cpp ${CORE_DIR}configurationreader.h \ + ${CORE_DIR}stringtools.h + ${CXX_COMPILE} ${CORE_DIR}configurationreader.cpp + +datadir.o: ${CORE_DIR}datadir.cpp ${CORE_DIR}datadir.h ${CORE_DIR}platform_fs.h + ${CXX_COMPILE} ${CORE_DIR}datadir.cpp ${CXX_DIR} + +platform_fs.o: ${CORE_DIR}platform_fs.cpp ${CORE_DIR}platform_fs.h + ${CXX_COMPILE} ${CORE_DIR}platform_fs.cpp + +documentstyle.o: ${CORE_DIR}documentstyle.cpp ${CORE_DIR}documentstyle.h ${CORE_DIR}configurationreader.h \ + ${CORE_DIR}stringtools.h ${CORE_DIR}elementstyle.h ${CORE_DIR}stylecolour.h + ${CXX_COMPILE} ${CORE_DIR}documentstyle.cpp + +elementstyle.o: ${CORE_DIR}elementstyle.cpp ${CORE_DIR}elementstyle.h ${CORE_DIR}stylecolour.h + ${CXX_COMPILE} ${CORE_DIR}elementstyle.cpp + +help.o: ${CLI_DIR}help.cpp ${CLI_DIR}help.h + ${CXX_COMPILE} ${CLI_DIR}help.cpp + +htmlgenerator.o: ${CORE_DIR}htmlgenerator.cpp ${CORE_DIR}htmlgenerator.h ${CORE_DIR}codegenerator.h + ${CXX_COMPILE} ${CORE_DIR}htmlgenerator.cpp + +languagedefinition.o: ${CORE_DIR}languagedefinition.cpp ${CORE_DIR}languagedefinition.h \ + ${CORE_DIR}configurationreader.h ${CORE_DIR}platform_fs.h ${CORE_DIR}enums.h ${CORE_DIR}stringtools.h + ${CXX_COMPILE} ${CORE_DIR}languagedefinition.cpp + +latexgenerator.o: ${CORE_DIR}latexgenerator.cpp ${CORE_DIR}latexgenerator.h ${CORE_DIR}codegenerator.h + ${CXX_COMPILE} ${CORE_DIR}latexgenerator.cpp + +bbcodegenerator.o: ${CORE_DIR}bbcodegenerator.cpp ${CORE_DIR}bbcodegenerator.h ${CORE_DIR}codegenerator.h + ${CXX_COMPILE} ${CORE_DIR}bbcodegenerator.cpp + +preformatter.o: ${CORE_DIR}preformatter.cpp ${CORE_DIR}preformatter.h ${CORE_DIR}stringtools.h + ${CXX_COMPILE} ${CORE_DIR}preformatter.cpp + +main.o: ${CLI_DIR}main.cpp ${CLI_DIR}main.h ${CLI_DIR}cmdlineoptions.h ${CORE_DIR}platform_fs.h \ + ${CORE_DIR}configurationreader.h ${CORE_DIR}datadir.h ${CORE_DIR}enums.h ${CORE_DIR}codegenerator.h \ + ${CORE_DIR}languagedefinition.h ${CORE_DIR}documentstyle.h ${CORE_DIR}elementstyle.h \ + ${CORE_DIR}stylecolour.h ${ASTYLE_DIR}astyle.h ${CORE_DIR}preformatter.h \ + ${CLI_DIR}help.h ${CORE_DIR}version.h + ${CXX_COMPILE} ${CLI_DIR}main.cpp ${CXX_DIR} + +rtfgenerator.o: ${CORE_DIR}rtfgenerator.cpp ${CORE_DIR}rtfgenerator.h ${CORE_DIR}codegenerator.h + ${CXX_COMPILE} ${CORE_DIR}rtfgenerator.cpp + +stringtools.o: ${CORE_DIR}stringtools.cpp ${CORE_DIR}stringtools.h + ${CXX_COMPILE} ${CORE_DIR}stringtools.cpp + +stylecolour.o: ${CORE_DIR}stylecolour.cpp ${CORE_DIR}stylecolour.h ${CORE_DIR}enums.h ${CORE_DIR}stringtools.h + ${CXX_COMPILE} ${CORE_DIR}stylecolour.cpp + +texgenerator.o: ${CORE_DIR}texgenerator.cpp ${CORE_DIR}texgenerator.h ${CORE_DIR}codegenerator.h + ${CXX_COMPILE} ${CORE_DIR}texgenerator.cpp + +xhtmlgenerator.o: ${CORE_DIR}xhtmlgenerator.cpp ${CORE_DIR}xhtmlgenerator.h ${CORE_DIR}htmlgenerator.h \ + ${CORE_DIR}codegenerator.h + ${CXX_COMPILE} ${CORE_DIR}xhtmlgenerator.cpp + +xmlgenerator.o: ${CORE_DIR}xmlgenerator.cpp ${CORE_DIR}xmlgenerator.h ${CORE_DIR}codegenerator.h + ${CXX_COMPILE} ${CORE_DIR}xmlgenerator.cpp + +svggenerator.o: ${CORE_DIR}svggenerator.cpp ${CORE_DIR}svggenerator.h ${CORE_DIR}codegenerator.h + ${CXX_COMPILE} ${CORE_DIR}svggenerator.cpp + +xterm256generator.o: ${CORE_DIR}xterm256generator.cpp ${CORE_DIR}xterm256generator.h ${CORE_DIR}codegenerator.h + ${CXX_COMPILE} ${CORE_DIR}xterm256generator.cpp + +Matcher.o: ${REGEX_DIR}Matcher.cpp ${REGEX_DIR}Matcher.h + ${CXX_COMPILE} ${REGEX_DIR}Matcher.cpp + +Pattern.o: ${REGEX_DIR}Pattern.cpp ${REGEX_DIR}Pattern.h + ${CXX_COMPILE} ${REGEX_DIR}Pattern.cpp + +arg_parser.o: ${CLI_DIR}arg_parser.cc ${CLI_DIR}arg_parser.h + ${CXX_COMPILE} ${CLI_DIR}arg_parser.cc + +ctagsreader.o: ${CORE_DIR}ctagsreader.cpp ${CORE_DIR}ctagsreader.h + ${CXX_COMPILE} ${CORE_DIR}ctagsreader.cpp + + +.PHONY: ${GUI_OBJECTS} + +clean: + @rm -f *.o + @rm -f ./highlight + @rm -f ./highlight-gui + @rm -f ./libhighlight.a + @rm -f ./libhighlight.so.* + @rm -f ./.deps/* + @rm -f gui-qt/*.o + @rm -f gui-qt/Makefile* + @rm -f gui-qt/object_script.* + @rm -f gui-qt/ui_*.h gui-qt/qrc_*.cpp gui-qt/moc_*.cpp + @rm -rf gui-qt/highlight-gui.gch/ |