1: /* webcpp - theme.cpp
     2:  * Copyright (C)2001-2003 Jeffrey Bakker
     3: 
     4:  * This program is free software; you can redistribute it and/or modify
     5:  * it under the terms of the GNU General Public License as published by
     6:  * the Free Software Foundation; either version 2 of the License, or
     7:  * (at your option) any later version.
     8: 
     9:  * This program is distributed in the hope that it will be useful,
    10:  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    11:  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    12:  * GNU General Public License for more details.
    13: 
    14:  * You should have received a copy of the GNU General Public License
    15:  * along with this program; if not, write to the Free Software
    16:  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
    17:    ___________________________________ .. .
    18:  */
    19: 
    20: 
    21: /*
    22: Finished
    23: 
    24: Asm
    25: Asp
    26: C
    27: C#
    28: C++
    29: CG
    30: Fortran
    31: HTML
    32: Java
    33: Modula*
    34: Objective C
    35: Pascal
    36: Shell
    37: 
    38: */
    39: 
    40: #include "theme.h" 
    41: #include <cctype> 
    42: using namespace std;
    43: 
    44: // (de)construction -----------------------------------------------------------
    45: Theme::~Theme() {
    46: 
    47: 	close();
    48: }
    49: Theme::Theme()  {
    50: 
    51: 	typical();
    52: 
    53: 	format2 = true;
    54: 	Picture = "\0";
    55: } //---------------------------------------------------------------------------
    56: // set file -------------------------------------------------------------------
    57: bool Theme::setFile(string filename) {
    58: 
    59: 	SCSfile = filename;
    60: 
    61: 	if(filename.rfind(".Scs2") == -1) {
    62: 
    63: 		if(filename.rfind(".scs") != -1) {
    64: 			format2 = false;
    65: 		}
    66: 		else
    67: 		filename += ".Scs2";
    68: 	}
    69: 	if( openR(filename) ) {
    70: 
    71: 		return load();
    72: 	}
    73: 	return false;
    74: }
    75: // set background picture -----------------------------------------------------
    76: void Theme::setPicture(string picture) {
    77: 
    78: 	Picture = picture;
    79: }
    80: // get the name of the theme --------------------------------------------------
    81: string Theme::getThemeName() {
    82: 
    83: 	return SCSfile;
    84: }
    85: // get background picture -----------------------------------------------------
    86: string Theme::getImageFile() {
    87: 
    88: 	return Picture;
    89: }
    90: // loading a theme ------------------------------------------------------------
    91: bool Theme::load() {
    92: 
    93: 	// load an Scs2-format file
    94: 	if(format2) {
    95: 
    96: 		string     Scs2buf;
    97: 		CFdatapair ScsXml;
    98: 
    99: 		// check for xml tag
   100: 		getline(ifile,Scs2buf);
   101: 		if(Scs2buf.find("<?xml version=\"1.0\"") == -1)
   102: 		{return false;}
   103: 		// check for the document type
   104: 		getline(ifile,Scs2buf);
   105: 		if(Scs2buf.find("<!DOCTYPE SyntaxColourScheme2") == -1)
   106: 		{return false;}
   107: 		// check for Scs2 data section
   108: 		getline(ifile,Scs2buf);
   109: 		if(Scs2buf.find("<SyntaxColourScheme2>") == -1)
   110: 		{return false;}
   111: 
   112: 		// load the Scs2 data which may be in random order
   113: 		getline(ifile,Scs2buf);
   114: 		while(ifile) {
   115: 
   116: //			cerr << "\nScs2: " << Scs2buf << endl;
   117: 
   118: 			ScsXml << Scs2buf;
   119: 			ScsVec.push_back(Scs2buf);
   120: 			getline(ifile,Scs2buf);
   121: 		}
   122: 
   123: //		for(int j=0; j < ScsVec.size(); j++) {
   124: 
   125: //			cerr << endl << ScsVec[j].info_nv() << endl;
   126: //		}
   127: 
   128: 		// sort the Scs2 data
   129: 		Colours2[BGCOLOR] = getColour("bgcolor");
   130: 		Colours2[PREPROC] = getColour("preproc");
   131: 		Colours2[NORTEXT] = getColour("nortext");
   132: 		Colours2[SYMBOLS] = getColour("symbols");
   133: 		Colours2[KEYWORD] = getColour("keyword");
   134: 		Colours2[KEYTYPE] = getColour("keytype");
   135: 		Colours2[INTEGER] = getColour("integer");
   136: 		Colours2[FLOATPT] = getColour("floatpt");
   137: 		Colours2[DBLQUOT] = getColour("dblquot");
   138: 		Colours2[SINQUOT] = getColour("sinquot");
   139: 		Colours2[COMMENT] = getColour("comment");
   140: 		// use a background image, if found
   141: 		Picture = getColour("background");
   142: 
   143: 		// check the format of all the colours
   144: 		for(int i=BGCOLOR; i <= COMMENT; i++) {
   145: 
   146: 			if(Colours2[i] == "\0") {
   147: 				typical();
   148: 				return false;
   149: 			}
   150: 
   151: 			if(Colours2[i][0] != '#') {
   152: 				Colours2[i].insert(0,"#");
   153: 			}
   154: 
   155: 			// verify data is in the right format
   156: 			if(!verifyFormat(Colours2[i])) {
   157: 				typical();
   158: 				return false;
   159: 			}
   160: 			// if not, use the defulat scheme
   161: 		}
   162: 		return true;
   163: 	}
   164: 	// load an original SCS-format file
   165: 	for(int i=BGCOLOR; i <= COMMENT; i++) {
   166: 
   167: 		ifile >> Colours2[i];
   168: 
   169: 		// convert old Scs to Scs2 format
   170: 		if(i == NORTEXT) {
   171:                 	Colours2[SYMBOLS] = Colours2[NORTEXT];
   172: 			i++;
   173: 		}
   174: 		else
   175: 		if(i == KEYWORD) {
   176:                 	Colours2[KEYTYPE] = Colours2[KEYWORD];
   177: 			i++;
   178: 		}
   179: 		else
   180: 		if(i == INTEGER) {
   181:                 	Colours2[FLOATPT] = Colours2[INTEGER];
   182: 			i++;
   183: 		}
   184: 		else
   185: 		if(i == DBLQUOT) {
   186:                 	Colours2[SINQUOT] = Colours2[DBLQUOT];
   187: 			i++;
   188: 		}
   189: 		// they will look exactly the same as the old style
   190: 
   191: 		if(!verifyFormat(Colours2[i])) {
   192: 			typical();
   193: 			return false;
   194: 		}
   195: 	}
   196: 	return true;
   197: }
   198: 
   199: 
   200: string	Theme::getColour(string Name) {
   201: 
   202: 	for(int i=0; i < ScsVec.size(); i++) {
   203: 
   204: 		if(ScsVec[i].getname() == Name)
   205: 			return ScsVec[i].getvalue();
   206: 	}
   207: //	cerr << "\nScs2: " << Name << " was not found!\n";
   208: 	return "\0";
   209: }
   210: // write a stylesheet ---------------------------------------------------------
   211: bool Theme::writeCSS(string cssfile) {
   212: 
   213: 	if(!openW(cssfile,true)) {return false;}
   214: 	ofile << getCSSdata();
   215: 	closeW();
   216: 	return true;
   217: }
   218: // set a colour in the theme --------------------------------------------------
   219: void Theme::setColour(string colour, int num) {
   220: 
   221: 	Colours2[num] = colour;
   222: }
   223: // set default theme ----------------------------------------------------------
   224: void Theme::typical() {
   225: 
   226: 	SCSfile = "typical";
   227: 
   228: 	setColour("#f1f1f1",BGCOLOR);
   229: 	setColour("#a900a9",PREPROC); //a900a9
   230: 	setColour("#000000",NORTEXT);
   231: 	setColour("#0077dd",SYMBOLS);
   232: 	setColour("#224fff",KEYWORD);
   233: 	setColour("#ff9933",KEYTYPE); //224fff  //ff9933
   234: 	setColour("#ff0032",INTEGER);
   235: 	setColour("#ff23a6",FLOATPT);
   236: 	setColour("#00b800",DBLQUOT);
   237: 	setColour("#00b86b",SINQUOT);
   238: 	setColour("#666666",COMMENT);
   239: }
   240: // enforces proper colour format ----------------------------------------------
   241: bool Theme::verifyFormat(string hexData) {
   242: 
   243: 	// make sure string is the right length
   244: 	if (hexData.size() != 7) {
   245: 		 cerr << hexData << "\a is an invalid colour.\n";
   246: 		 return false;
   247: 	}
   248: 
   249: 	// string must start with '#'
   250: 	if (hexData[0] != '#') {
   251: 		cerr << hexData << "\a is an invalid colour.\n";
   252: 		return false;
   253: 	}
   254: 
   255: 	// change string to uppercase
   256: 	for (int i=1; i < 7; i++) {hexData[i] = toupper(hexData[i]);}
   257: 
   258: 	// enforce range from #000000 to #FFFFFF
   259: 	for (int j=1; j < 7; j++) {
   260: 
   261: 		if (hexData[j] < '0' || hexData[j] > 'F') {
   262: 			cerr << hexData << "\a is an invalid colour.\n";
   263: 			return false;
   264: 		}
   265: 		if (ispunct(hexData[j]) || isspace(hexData[j])) {
   266: 			cerr << hexData << "\a is an invalid colour.\n";
   267: 			return false;
   268: 		}
   269: 	}
   270: 
   271: 	return true;
   272: } //---------------------------------------------------------------------------
   273: string Theme::getCSSdata() {
   274: 
   275: 	string CSS;
   276: 
   277: 	CSS =
   278: 
   279: "/*\nWebcpp v0.8.0 compatible StyleSheet\nhttp://webcpp.sf.net\n"
   280: "Theme: "  +  SCSfile  + "\n*/\n\n"
   281: "body\n{\nbackground-color: "  + Colours2[BGCOLOR] +
   282: 
   283: ( (Picture == "\0")
   284: ? "\n}\n\n": ";\nbackground-image: url(\"" + Picture +
   285: "\");\nbackground-attachment: fixed\n}\n\n" ) +
   286: 
   287: "a:link    {color:"        + Colours2[DBLQUOT] + "}\n"
   288: "a:visited {color:"        + Colours2[COMMENT] + "}\n"
   289: "a:active  {color:"        + Colours2[KEYWORD] + "}\n"
   290: "a:hover   {color:"        + Colours2[PREPROC] + "}\n\n"
   291: "pre\n{\ncolor: "          + Colours2[NORTEXT] + "\n}\n\n"
   292: "font\n{\nfont-size:100%\n}\n\n"
   293: "font.symbols\n{\ncolor: " + Colours2[SYMBOLS] + "\n}\n\n"
   294: "font.preproc\n{\ncolor: " + Colours2[PREPROC] + "\n}\n\n"
   295: "font.integer\n{\ncolor: " + Colours2[INTEGER] + "\n}\n\n"
   296: "font.floatpt\n{\ncolor: " + Colours2[FLOATPT] + "\n}\n\n"
   297: "font.dblquot\n{\ncolor: " + Colours2[DBLQUOT] + "\n}\n\n"
   298: "font.sinquot\n{\ncolor: " + Colours2[SINQUOT] + "\n}\n\n"
   299: "font.keyword\n{\ncolor: " + Colours2[KEYWORD] + ";\nfont-weight: bold\n}\n\n"
   300: "font.keytype\n{\ncolor: " + Colours2[KEYTYPE] + ";\nfont-weight: bold\n}\n\n"
   301: "font.comment\n{\ncolor: " + Colours2[COMMENT] + ";\nfont-style: italic\n}\n\n";
   302: 
   303: 	return CSS;
   304: }
   305: //-----------------------------------------------------------------------------
   306: 



w e b c p p
web c plus plus