Thread: Code Painter

  1. #16
    Dr Dipshi++ mike_g's Avatar
    Join Date
    Oct 2006
    Location
    On me hyperplane
    Posts
    1,218
    I guess that's the price you pay for coloured brackets.
    Lol yeah, I added coloured operators and text formatting (bold, italic, underlined). I have intentionally been ignoring the filesize. I'll look at reducing it again later.

    BTW, if you're generating HTML, CSS can really reduce filesizes. Plus it makes the output more easily customizable. Of course, this doesn't work for, say, BBCode.
    Yeah I'm using css in the tags atm. For example:
    Code:
    <span style="color:#00FF00;font-weight:bold;">{</span>
    Which as you can see causes just a little bit of bloat. I could save space by writing a set of classes out first, but I might be able to save even more by making custom XML tags using XLST styles. Then it may look something like:
    Code:
    <bkt>{</bkt>

  2. #17
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,613
    I'm somewhat shocked that doing something correctly is now "bloat".

    Use strong tags I guess? I'm not sure why this is such an issue in our age.

  3. #18
    System Novice siavoshkc's Avatar
    Join Date
    Jan 2006
    Location
    Tehran
    Posts
    1,246
    1) Word counts are off - Try typing some whitespace in the box, you'll see.
    2) You seem to be missing a few keywords (typename, catch, default being the three I noticed.)
    3) // Comments, on the last line, are not highlighted
    4) You write to C:\Program Files\Your\Dir ... it gets redirected to C:\Users\blah\AppData\Local\.....
    Thanks for your care.
    1) Yes, it is not really a word count. I should erase it.
    2) OK I'll add them, for now you can add them manually in options.
    3) Press enter.
    4) Can you explain more?

    By bloat you mean adding extra tags? Why it would be a problem?
    Learn C++ (C++ Books, C Books, FAQ, Forum Search)
    Code painter latest version on sourceforge DOWNLOAD NOW!
    Download FSB Data Integrity Tester.
    Siavosh K C

  4. #19
    Reverse Engineer maxorator's Avatar
    Join Date
    Aug 2005
    Location
    Estonia
    Posts
    2,318
    You need to fix those little bugs like comments not highlighted on last line etc, though it is always possible to add a new line. Because it's still a bug.

    Reminds me that I once made one in PHP too.

    http://maxx.5gigs.com (Click on the typenames ("Comments, "Preprocess") to select a color)

    It is kind of slow but that's because it's a free host and PHP isn't really designed for manual word processing.

  5. #20
    System Novice siavoshkc's Avatar
    Join Date
    Jan 2006
    Location
    Tehran
    Posts
    1,246
    http://maxx.5gigs.com (Click on the typenames ("Comments, "Preprocess") to select a color)
    Code:
    #include <iostream> //asdfafsd /*sdfsdf*/
    I think it should give <...> another color.

    [edit]
    gcc compiler is the most colorful editor, isn't it?
    Learn C++ (C++ Books, C Books, FAQ, Forum Search)
    Code painter latest version on sourceforge DOWNLOAD NOW!
    Download FSB Data Integrity Tester.
    Siavosh K C

  6. #21
    Dr Dipshi++ mike_g's Avatar
    Join Date
    Oct 2006
    Location
    On me hyperplane
    Posts
    1,218
    I think it should give <...> another color.
    Normally yes, but in the preprocesor that would be a little strange.

  7. #22
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,613
    Quote Originally Posted by Cactus_Hugger View Post
    4) You write to C:\Program Files\Your\Dir ... it gets redirected to C:\Users\blah\AppData\Local\.....
    Quote Originally Posted by siavoshkc View Post
    Thanks for your care.
    4) Can you explain more?
    Windows may be rerouting whatever you wrote to that directory because of a permissions setting on his system. But whatever the reason is, it's happening.

    I would also recommend fixing this problem. And fixing it by staying the hell away from program files. As of vista, you can no longer just write to program files without putting in a request to the user, or your application would need to be run as administrator explicitly. And... your program is just a widget that highlights syntax and has no business rooting around in there. It should not require admin permissions at all.

    It's sort of amazing that you've written a new version to a GUI application and never did this sort of quality control testing (testing for limited users, guests, and and admins) so you'd at least be aware of your programs behavior on a windows machine, but I digress.
    Last edited by whiteflags; 08-17-2008 at 06:36 PM.

  8. #23
    Reverse Engineer maxorator's Avatar
    Join Date
    Aug 2005
    Location
    Estonia
    Posts
    2,318
    Quote Originally Posted by siavoshkc View Post
    Code:
    #include <iostream> //asdfafsd /*sdfsdf*/
    I think it should give <...> another color.

    [edit]
    gcc compiler is the most colorful editor, isn't it?
    I've never worked with any IDE that colors preprocessor directives...

  9. #24
    Woof, woof! zacs7's Avatar
    Join Date
    Mar 2007
    Location
    Australia
    Posts
    3,459
    Never used VI/VIM before?

    The default C/C++ high-lighting has it...

  10. #25
    Reverse Engineer maxorator's Avatar
    Join Date
    Aug 2005
    Location
    Estonia
    Posts
    2,318
    I've used MSVC++, Code::Blocks, Dev-C++ and Notepad++. I've never programmed in Linux.

  11. #26
    int x = *((int *) NULL); Cactus_Hugger's Avatar
    Join Date
    Jul 2003
    Location
    Banks of the River Styx
    Posts
    902
    Windows may be rerouting whatever you wrote to that directory because of a permissions setting on his system. But whatever the reason is, it's happening.
    Yeah, that's the basic gist of it. I mostly just wanted him to be aware of this behavior.
    In Vista, C:\Program Files is read-only. But, many older programs require write access, so, in a good ole MS kludge, files written to C:\Program Files\SomeFolder go to &#37;USERPROFILE%\Local\VirtualStore\Program Files\SomeFolder (USERPROFILE is usually set to C:\Users\%USERNAME%, I think)
    The behavior of this whole thing reminds me of unionfs in Linux, except a whole hell of a lot more confusing. It can basically result in programs telling you "Error in file C:\Program Files\Folder\file", except that the file it's talking about isn't there. Or, it gets the wrong copy, if the file exists both places, etc. Just something to be aware of.
    Explore the AppData folder on your box, do some research, etc. It's like the .folders of a unix ~ dir... except... more confusing.

    Now, permissions for folders can be editted to avoid the above, but, you should decide where to put data. Per-user data should go in a AppData subfolder, data that the program needs but won't be changed by the users should go in C:\Program files.
    long time; /* know C? */
    Unprecedented performance: Nothing ever ran this slow before.
    Any sufficiently advanced bug is indistinguishable from a feature.
    Real Programmers confuse Halloween and Christmas, because dec 25 == oct 31.
    The best way to accelerate an IBM is at 9.8 m/s/s.
    recursion (re - cur' - zhun) n. 1. (see recursion)

  12. #27
    Internet Superhero
    Join Date
    Sep 2006
    Location
    Denmark
    Posts
    964
    After reading this thread i decided to make my own code painter, so here it is. It takes the file path to the cpp file as the first and only argument, loads it into a buffer, and then parses it and writes the code and the color tags to a stringstream and then outputs those into an html file. Oh and it uses CSS aswell. I just finished it 5 minutes ago, after having spent a couple of hours on it, i'm thinking of adding another command-line argument to specify whether the code is C or C++ so it won't highlight "class" or "throw" as keywords in a .c file (Or maybe make it able to recognize the file extensions itself and adjust accordingly).

    Also, my plan is to make the generated HTML w3c compliant to the HTML 4.01 standard, but since this is kind of a beta i haven't gotten around to that yet, and to make sure the CSS validates aswell.

    And yes i realize that there might be a possibility for some overflow errors depending on the code that is inputted, i'm working on that..

    The color scheme is similar to that in dev-c++, but it's so simple to change i won't even bother explaining how..

    Code:
    //[email protected]
    //Neo1
    #define _WIN32_WINNT 0x0500
    #include <windows.h>
    #include <iostream>
    #include <sstream>
    #include <exception>
    
    int main(int argc, char* argv[])
    {
    	const unsigned int NumOfKeywords = 62;
    	
    	//Color Codes
    	std::string CommentColor = "#00008B";
    	std::string CPPColor = "#008B00";
    	std::string QuoteColor = "#FF4500";
    	std::string ApostropheColor = "#BEBEBE";
    	
    	//Pointer to the buffer
    	char *pBuffer = NULL;
    	
    	//Array of keywords, the first 32 are C/C+++, the last 30 are C++
    	std::string Keywords[NumOfKeywords] = {"auto","const","double","float","int","short","struct","unsigned",
            "break","continue","else","for","long","signed","switch","void",
            "case","default","enum","goto","register","sizeof","typedef","volatile",
            "char","do","extern","if","return","static","union","while",
            "asm","dynamic_cast","namespace","reinterpret_cast","try","bool",
            "explicit","new","static_cast","typeid","catch","false","operator",
            "template","typename","class","friend","private","this","using",
            "const_cast","inline","public","throw","virtual","delete","mutable",
            "protected","true","wchar_t"};
    
    	//Check if the number of arguments are valid
    	if(argc != 2)
    	{
    		std::cout << "Invalid number of arguments, "
    				  << "Correct usage is: paint FILEPATH"
    				  << std::endl;
    		return 1;
    	}
    	
    	//Open the handle for the inputfile
    	HANDLE hInputFile = CreateFile(argv[1], GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
    	if(hInputFile == INVALID_HANDLE_VALUE)
    	{
    		std::cerr << "Error " << GetLastError() << " occured." << std::endl;
    		return 1;
    	}
    	
    	//Get the filesize
    	LARGE_INTEGER li;
    	if(!GetFileSizeEx(hInputFile, &li))
    	{
    		std::cerr << "Error " << GetLastError() << " occured." << std::endl;
    		return 1;
    	}
    	DWORD InputSize = li.QuadPart;
    	
    	//Needed to avoid segfault when using Readfile() and Writefile()
    	DWORD lpNumberOfBytesWritten, dwBytesRead;
    	
    	//Declare proper amount of memory for the buffer
    	try
    	{
    		pBuffer = new char[InputSize];
    	}
    	
    	catch (std::bad_alloc&)
    	{
    		std::cerr << "Error allocating memory." << std::endl;
    		return 1;
    	}
    	
    	//Declare a stringstream for the HTML code and the title
    	std::stringstream ss;
    	
    	//Figure out what to call the new .html file
    	ss << argv[1] << ".html";
    	std::string OutputFileName = ss.str();
    	
    	//Reset the stringstream and fill it with the HTML code and CSS style
    	ss.str("");
    	ss << "<html>\n<head>\n<title>" << argv[1] << "</title>\n"
    	<< "<style>\n"
    	<< "#comment {\ncolor: " << CommentColor << ";\nfont-style: italic;\n}\n"
    	<< "#cpp {\ncolor: " << CPPColor << ";\n}\n"
    	<< "#quote {\ncolor: " << QuoteColor << ";\n}\n"
    	<< "#apostrophe {\ncolor: " << ApostropheColor << ";\n}\n"
    	<< "#keyword {\nfont-weight: bold;\n}\n"
    	<< "</style>\n"
    	<< "</head>\n<body>\n"
    	<< "<pre>\n";
    	
    	//Open the handle for the outputfile
    	HANDLE hOutputFile = CreateFile(OutputFileName.c_str(), GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL);
    	if(hOutputFile == INVALID_HANDLE_VALUE)
    	{
    		std::cerr << "Error " << GetLastError() << " occured." << std::endl;
    		return 1;
    	}
    	
    	//Read the inputfile into the buffer
    	if(!ReadFile(hInputFile, pBuffer, InputSize, &dwBytesRead, NULL))
    	{
    		std::cerr << "Error " << GetLastError() << " occured." << std::endl;
    		return 1;
    	}
    	
    	char ch;
    	DWORD i = 0, j = 0, k = 0, l = 0;
    	bool IsKeyWord;
    	
    	//Main parser loop
    	for(; i < InputSize; i++)
    	{
    		//Retrieve a character from the buffer
    		ch = pBuffer[i];
    		
    		switch(ch)
    		{
    			case '#':
    				//Add the starting tag if the character is a '#'
    				ss << "<span id=\"cpp\">" << ch;
    				//Start scanning buffer until a newline is encountered
    				while(ch != '\n')
    				{
    					i++;
    					ch = pBuffer[i];
    					//Remember to replace '<' and '>' with the appropriate HTML codes
    					(ch == '<')? ss << "&lt;" : (ch == '>')? ss << "&gt;" : ss << ch;
    				}
    				//Newline found, add the closing tag
    				ss << "</span>";
    			break;
    			
    			case '"':
    				//Add the starting tag if the character is a "
    				ss << "<span id=\"quote\">" << ch;
    				//Scan through the buffer until another " is encountered
    				do
    				{
    					i++;
    					ch = pBuffer[i];
    					//Remember to replace '<' and '>' with the appropriate HTML codes
    					(ch == '<')? ss << "&lt;" : (ch == '>')? ss << "&gt;" : ss << ch;
    				} while(ch != '"' || pBuffer[i-1] == '\\');
    				//"-found, add the closing tag
    				ss << "</span>";
    			break;
    			
    			case '/':
    				//Check the next character in the buffer to check if there is 2 consecutive slashes
    				if(pBuffer[i+1] == '/')
    				{
    					//Comment found, add the starting tag
    					ss << "<span id=\"comment\">" << ch;
    					//Scan through the buffer until a newline is encountered
    					while(ch != '\n')
    					{
    						i++;
    						ch = pBuffer[i];
    						//Remember to replace '<' and '>' with the appropriate HTML codes
    						(ch == '<')? ss << "&lt;" : (ch == '>')? ss << "&gt;" : ss << ch;
    					}
    					//Newline found, add closing tag
    					ss << "</span>";
    				}
    				//If the next character is not a slash, simply add the single slash to the stringstream and continue
    				else { ss << ch; }
    			break;
    			
    			case '\'':
    				//Add the starting tag if the character is an apostrophe
    				ss << "<span id=\"apostrophe\">" << ch;
    				//Start scanning buffer until another apostrophe is encountered
    				do
    				{
    					i++;
    					ch = pBuffer[i];
    					//Remember to replace '<' and '>' with the appropriate HTML codes
    					(ch == '<')? ss << "&lt;" : (ch == '>')? ss << "&gt;" : ss << ch;
    				} while(ch != '\'');
    				//Apostrophe found, add the closing tag
    				ss << "</span>";
    			break;
    			
    			case '<':
    				//Remember to replace '<' and '>' with the appropriate HTML codes
    				ss << "&lt;";
    			break;
    			
    			case '>':
    				//Remember to replace '<' and '>' with the appropriate HTML codes
    				ss << "&gt;";
    			break;
    			
    			default:
    				//The character does not need to be color tagged if we got this far, so now we check if it is a keyword and needs to be in bold
    				//Loop through all the strings
    				for(j = 0; j < NumOfKeywords; j++)
    				{
    					//Loop through all the letters in each string
    					for(k = 0; k < Keywords[j].size(); k++)
    					{
    						//We assume that the current character is a keyword by default
    						IsKeyWord = true;
    						//Check if it matches the current character in the keyword string array
    						if(!(pBuffer[i+k] == Keywords[j][k]))
    						{
    							//If not, it ain't a keyword
    							IsKeyWord = false;
    							//Break out of the inner for-loop, and try to match it to the next word in the string-array
    							break;
    						}
    					}
    					//If we got this far and the bool is still TRUE, the current ch and the following characters in the buffer is a match to one of the keywords
    					if(IsKeyWord)
    					{
    						//Add the starting tag
    						ss << "<span id=\"keyword\">";
    						//Loop through the keyword we found, which has the length k
    						for(l = 0; l < k; l++)
    						{
    							//Remember to add the current ch (which was a match to the first letter in one of the keywords) before incrementing to the next char in buffer
    							ss << ch;
    							i++;
    							ch = pBuffer[i];
    						}
    						//Add closing tag
    						ss << "</span>";
    					}
    				}
    				//If we got this far and IsKeyWord != TRUE, no keywords was matched to the buffer at this time, so we just add the character and go on
    				if(!IsKeyWord)
    				{
    					ss << ch;
    				}
    			break;
    		}
    	}
    	
    	//Close the HTML tags
    	ss << "</pre>\n</body>\n</html>";
    	
    	//Dump the stringstream in string, so we can put it back in the dynamical memory buffer and so that we know it's size
    	std::string data = ss.str();
    	
    	//Empty the buffer again
    	delete[] pBuffer;
    	
    	//Resize it to fit the new tagged code
    	try
    	{
    		pBuffer = new char[data.length()];
    	}
    	
    	//Check for bac allocs
    	catch (std::bad_alloc&)
    	{
    		std::cerr << "Error allocating memory." << std::endl;
    		return 1;
    	}
    	
    	//Empty the string into the newly resized buffer
    	for(i = 0; i < data.length(); i++)
    	{
    		pBuffer[i] = data[i];
    	}
    	
    	//Output the new code from the buffer to the HTML file
    	if(!WriteFile(hOutputFile, pBuffer, data.length(), &lpNumberOfBytesWritten, NULL))
    	{
    		std::cerr << "Error " << GetLastError() << " occured." << std::endl;
    		return 1;
    	}
    	
    	//Close handles when done
    	if(!CloseHandle(hInputFile) || !CloseHandle(hOutputFile))
    	{
    		std::cerr << "Error " << GetLastError() << " occured." << std::endl;
    		return 1;
    	}
    	
    	//Clean up memory
    	delete[] pBuffer;
    	//Return success
    	return 0;
    }
    All feedback appreciated
    How I need a drink, alcoholic in nature, after the heavy lectures involving quantum mechanics.

  13. #28
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Some comments:

    Code:
    	DWORD i = 0, j = 0, k = 0, l = 0;
    	bool IsKeyWord;
    	
    	//Main parser loop
    	for(; i < InputSize; i++)
    Why not just have
    Code:
    for(DWORD i = 0; i < InputSize ...)
    You don't use i after the loop, so declaring it outside of the loop is meaningless, and skipping the "i = 0" is just silly - the compiler will optimize it into one initialization anyways.

    Code:
    					i++;
    					ch = pBuffer[i];
    					//Remember to replace '<' and '>' with the appropriate HTML codes
    					(ch == '<')? ss << "&lt;" : (ch == '>')? ss << "&gt;" : ss << ch;
    This is repeated MANY times. Should be a function.

    Your comment colouring doesn't cope with old C-style comments (/* ... */).

    Petty things:
    Code:
    	const unsigned int NumOfKeywords = 62;
    ...	
    	//Array of keywords, the first 32 are C/C+++, the last 30 are C++
    	std::string Keywords[NumOfKeywords] = {"auto","const","double","float","int","short","struct","unsigned",
    ...
    I prefer to figure out how many they are from sizeof(), and just leave the brackets empty - the compiler then makes the right number of them. sizeof(Keywords)/sizeof(Keywords[0]) will give you 62 - but if you have to add one (or remove), you just add it to the list, no messing about.

    Code:
    					if(IsKeyWord)
    					{
    ....
    					}
    Add a break - that way, you don't loop through another 61 keywords trying to match it with "auto".

    I also get the impression that the keyword compare will make "automatic" colour "auto" as keyword and then leave "matic" the normal colour. You probably need to check that there is a delimiter at the end of the keyword.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  14. #29
    Internet Superhero
    Join Date
    Sep 2006
    Location
    Denmark
    Posts
    964
    Thanks Mats, i added the changes you suggested, and the code now looks like this:

    Code:
    //[email protected]
    //Neo1
    #define _WIN32_WINNT 0x0500
    
    //For Win32 I/O function
    #include <windows.h>
    
    //For screen output
    #include <iostream>
    
    //For the output buffer
    #include <sstream>
    
    //For exceptions
    #include <exception>
    
    //To check for delimiters in keywords with ispunct(), isspace() and iscntrl()
    #include <cctype>
    
    //The functions for going through the code and coloring it
    void CPP(std::stringstream &SS, DWORD &i, char ch, char *pBuffer);
    void Quote(std::stringstream &SS, DWORD &i, char ch, char *pBuffer);
    void Comment(std::stringstream &SS, DWORD &i, char ch, char *pBuffer);
    void Character(std::stringstream &SS, DWORD &i, char ch, char *pBuffer);
    
    int main(int argc, char* argv[])
    {
    	
    	//Color Codes
    	std::string CommentColor = "#00008B";
    	std::string CPPColor = "#008B00";
    	std::string QuoteColor = "#FF4500";
    	std::string CharacterColor = "#BEBEBE";
    	
    	//Pointer to the raw buffer
    	char *pBuffer = NULL;
    	
    	//Array of keywords
    	std::string Keywords[] = {"auto","const","double","float","int","short","struct","unsigned",
    	"break","continue","else","for","long","signed","switch","void",
    	"case","default","enum","goto","register","sizeof","typedef","volatile",
    	"char","do","extern","if","return","static","union","while",
    	"asm","dynamic_cast","namespace","reinterpret_cast","try","bool",
    	"explicit","new","static_cast","typeid","catch","false","operator",
    	"template","typename","class","friend","private","this","using",
    	"const_cast","inline","public","throw","virtual","delete","mutable",
    	"protected","true","wchar_t"};
    	
    	//Calculate number of keywords
    	const unsigned int NumOfKeywords = ( sizeof(Keywords)/sizeof(Keywords[0]) );
    
    	//Check if the number of arguments are valid
    	if(argc != 2)
    	{
    		std::cout << "Invalid number of arguments, "
    		<< "Correct usage is: paint FILEPATH"
    		<< std::endl;
    		return 1;
    	}
    	
    	//Open the handle for the inputfile
    	HANDLE hInputFile = CreateFile(argv[1], GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
    	if(hInputFile == INVALID_HANDLE_VALUE)
    	{
    		std::cerr << "Error " << GetLastError() << " occured." << std::endl;
    		return 1;
    	}
    	
    	//Get the filesize
    	LARGE_INTEGER li;
    	if(!GetFileSizeEx(hInputFile, &li))
    	{
    		std::cerr << "Error " << GetLastError() << " occured." << std::endl;
    		return 1;
    	}
    	DWORD InputSize = li.QuadPart;
    	
    	//Needed to avoid segfault when using Readfile() and Writefile()
    	DWORD lpNumberOfBytesWritten, dwBytesRead;
    	
    	//Declare proper amount of memory for the buffer
    	try
    	{
    		pBuffer = new char[InputSize];
    	}
    	
    	catch (std::bad_alloc&)
    	{
    		std::cerr << "Error allocating memory." << std::endl;
    		return 1;
    	}
    	
    	//Declare a stringstream for the HTML code and the title
    	std::stringstream SS;
    	
    	//Figure out what to call the new .html file
    	SS << argv[1] << ".html";
    	std::string OutputFileName = SS.str();
    	
    	//Reset the stringstream and fill it with the HTML code and CSS style
    	SS.str("");
    	SS << "<html>\n<head>\n<title>" << argv[1] << "</title>\n"
    	<< "<style>\n"
    	<< "#comment {\ncolor: " << CommentColor << ";\nfont-style: italic;\n}\n"
    	<< "#cpp {\ncolor: " << CPPColor << ";\n}\n"
    	<< "#quote {\ncolor: " << QuoteColor << ";\n}\n"
    	<< "#character {\ncolor: " << CharacterColor << ";\n}\n"
    	<< "#keyword {\nfont-weight: bold;\n}\n"
    	<< "</style>\n"
    	<< "</head>\n<body>\n"
    	<< "<pre>\n";
    	
    	//Open the handle for the outputfile
    	HANDLE hOutputFile = CreateFile(OutputFileName.c_str(), GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL);
    	if(hOutputFile == INVALID_HANDLE_VALUE)
    	{
    		std::cerr << "Error " << GetLastError() << " occured." << std::endl;
    		return 1;
    	}
    	
    	//Read the inputfile into the buffer
    	if(!ReadFile(hInputFile, pBuffer, InputSize, &dwBytesRead, NULL))
    	{
    		std::cerr << "Error " << GetLastError() << " occured." << std::endl;
    		return 1;
    	}
    	
    	//To hold the active character in the code
    	char ch;
    	//To keep track of the keywords in the code
    	bool IsKeyWord;
    	
    	//Main parser loop, with all the loop counters
    	for(DWORD i = 0, j = 0, k = 0, l = 0; i < InputSize; i++)
    	{
    		//Retrieve a character from the buffer
    		ch = pBuffer[i];
    		
    		switch(ch)
    		{
    			case '#':
    				CPP(SS, i, ch, pBuffer);
    			break;
    			
    			case '"':
    				Quote(SS, i, ch, pBuffer);
    			break;
    			
    			case '/':
    				Comment(SS, i, ch, pBuffer);
    			break;
    			
    			case '\'':
    				Character(SS, i, ch, pBuffer);
    			break;
    			
    			case '<':
    				//Remember to replace '<' and '>' with the appropriate HTML codes
    				SS << "&lt;";
    			break;
    			
    			case '>':
    				//Remember to replace '<' and '>' with the appropriate HTML codes
    				SS << "&gt;";
    			break;
    			
    			default:
    				//The character does not need to be color tagged if we got this far, so now we check if it is a keyword and needs to be in bold
    				//Loop through all the strings
    				for(j = 0; j < NumOfKeywords; j++)
    				{
    					//Loop through all the letters in each string
    					for(k = 0; k < Keywords[j].size(); k++)
    					{
    						//We assume that the current character is a keyword by default
    						IsKeyWord = true;
    						//Check if it matches the current character in the keyword string array
    						if(!(pBuffer[i+k] == Keywords[j][k]))
    						{
    							//If not, it ain't a keyword
    							IsKeyWord = false;
    							//Break out of the inner for-loop, and try to match it to the next word in the string-array
    							break;
    						}
    					}
    					//If we matched some letters to a keyword, we need to check if there is a delimiter after the keyword, else it ain't a keyword
    					if(IsKeyWord)
    					{
    						//Check the next character in the buffer
    						if( !( isspace(pBuffer[i+k]) || ispunct(pBuffer[i+k]) || iscntrl(pBuffer[i+k]) ) )
    						{
    							//If it's not a space, it's not a keyword
    							IsKeyWord = false;
    						}
    					}
    					//If we got this far and the bool is still TRUE, the current ch and the following characters in the buffer is a match to one of the keywords
    					if(IsKeyWord)
    					{
    						//Add the starting tag
    						SS << "<span id=\"keyword\">";
    						//Loop through the keyword we found, which has the length k
    						for(l = 0; l < k; l++)
    						{
    							//Remember to add the current ch (which was a match to the first letter in one of the keywords) before incrementing to the next char in buffer
    							SS << ch;
    							i++;
    							ch = pBuffer[i];
    						}
    						//Add closing tag and the ch from last iteration of the loop
    						SS << "</span>";
    						SS << ch;
    						//Done, break out of outer loop
    						break;
    					}
    				}
    				//If we got this far and IsKeyWord != TRUE, no keywords was matched to the buffer at this time, so we just add the character and go on
    				if(!IsKeyWord)
    				{
    					SS << ch;
    				}
    			break;
    		}
    	}
    	
    	//Close the HTML tags
    	SS << "</pre>\n</body>\n</html>";
    	
    	//Dump the stringstream in string, so we can put it back in the dynamical memory buffer and so that we know it's size
    	std::string data = SS.str();
    	
    	//Empty the buffer again
    	delete[] pBuffer;
    	
    	//Resize it to fit the new tagged code
    	try
    	{
    		pBuffer = new char[data.length()];
    	}
    	
    	//Check for bad allocs
    	catch (std::bad_alloc&)
    	{
    		std::cerr << "Error allocating memory." << std::endl;
    		return 1;
    	}
    	
    	//Empty the string into the newly resized buffer
    	for(DWORD i = 0; i < data.length(); i++)
    	{
    		pBuffer[i] = data[i];
    	}
    	
    	//Output the new code from the buffer to the HTML file
    	if(!WriteFile(hOutputFile, pBuffer, data.length(), &lpNumberOfBytesWritten, NULL))
    	{
    		std::cerr << "Error " << GetLastError() << " occured." << std::endl;
    		return 1;
    	}
    	
    	//Close handles when done
    	if(!CloseHandle(hInputFile) || !CloseHandle(hOutputFile))
    	{
    		std::cerr << "Error " << GetLastError() << " occured." << std::endl;
    		return 1;
    	}
    	
    	//Clean up memory
    	delete[] pBuffer;
    	//Return success
    	return 0;
    }
    
    void CPP(std::stringstream &SS, DWORD &i, char ch, char *pBuffer)
    {
    	//Add the starting tag
    	SS << "<span id=\"cpp\">" << ch;
    	//Start scanning buffer until a newline is encountered
    	while(ch != '\n')
    	{
    		i++;
    		ch = pBuffer[i];
    		//Remember to replace '<' and '>' with the appropriate HTML codes
    		(ch == '<')? SS << "&lt;" : (ch == '>')? SS << "&gt;" : SS << ch;
    	}
    	//Newline found, add the closing tag
    	SS << "</span>";
    }
    
    void Quote(std::stringstream &SS, DWORD &i, char ch, char *pBuffer)
    {
    	//Add the starting tag
    	SS << "<span id=\"quote\">" << ch;
    	//Scan through the buffer until another " is encountered
    	do
    	{
    		i++;
    		ch = pBuffer[i];
    		//Remember to replace '<' and '>' with the appropriate HTML codes
    		(ch == '<')? SS << "&lt;" : (ch == '>')? SS << "&gt;" : SS << ch;
    	} while(ch != '"' || pBuffer[i-1] == '\\');
    	//"-found, add the closing tag
    	SS << "</span>";
    }
    
    void Comment(std::stringstream &SS, DWORD &i, char ch, char *pBuffer)
    {
    	//Check the next character in the buffer to check if there is 2 consecutive slashes
    	if(pBuffer[i+1] == '/')
    	{
    		//Comment found, add the starting tag
    		SS << "<span id=\"comment\">" << ch;
    		//Scan through the buffer until a newline is encountered
    		while(ch != '\n')
    		{
    			i++;
    			ch = pBuffer[i];
    			//Remember to replace '<' and '>' with the appropriate HTML codes
    			(ch == '<')? SS << "&lt;" : (ch == '>')? SS << "&gt;" : SS << ch;
    		}
    		//Newline found, add closing tag, and return
    		SS << "</span>";
    		return;
    	}
    	//Check for a C-style comment instead
    	else if(pBuffer[i+1] == '*')
    	{
    		//C-style Comment found, add the starting tag
    		SS << "<span id=\"comment\">" << ch;
    		//Scan through the buffer until a closing tag is encountered
    		while(ch != '*')
    		{
    			while(pBuffer[i+1] != '/')
    			{
    				i++;
    				ch = pBuffer[i];
    				//Remember to replace '<' and '>' with the appropriate HTML codes
    				(ch == '<')? SS << "&lt;" : (ch == '>')? SS << "&gt;" : SS << ch;
    			}
    		}
    		//Closing tag found, add closing HTML-tag, and return
    		SS << "</span>";
    		return;
    	}
    	//If the next character is not a * or a star, simply add the single slash to the stringstream and continue
    	else { SS << ch; }
    }
    
    void Character(std::stringstream &SS, DWORD &i, char ch, char *pBuffer)
    {
    	//Add the starting tag
    	SS << "<span id=\"character\">" << ch;
    	//Start scanning buffer until another character is encountered
    	do
    	{
    		i++;
    		ch = pBuffer[i];
    		//If character is an escape character, ignore it and the next character and continue
    		if(ch == '\\')
    		{
    			SS << '\\';
    			SS << pBuffer[++i];
    			continue;
    		}
    		//Remember to replace '<' and '>' with the appropriate HTML codes
    		(ch == '<')? SS << "&lt;" : (ch == '>')? SS << "&gt;" : SS << ch;
    	} while(ch != '\'');
    	//Character found, add the closing tag
    	SS << "</span>";
    }
    It now takes care of C-style comments aswell, and all the coloring code is in functions. Oh and it won't make the first half of a word like 'automatic' or 'intelligent' bold anymore. Also, it SHOULD handle backslashes properly now, had a couple of problems with that one, but it seems to be working now
    How I need a drink, alcoholic in nature, after the heavy lectures involving quantum mechanics.

  15. #30
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    Since CPP, Quote, Comment, etc all have the same function signatures, you could use an array of function pointers to call them if you wanted to. Or some C++-er way. It just might be neater than a switch statement.

    I don't really see the point of using windows-specific file handling functions -- the standard C++ header <fstream> should have all you need and more. Unless, I guess, you're more familiar with them or something.

    Code:
    pBuffer = new char[data.length()];
    I have a suspicion that you wanted data.length() + 1 there . . . .
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Enforcing Machine Code Restrictions?
    By SMurf in forum Tech Board
    Replies: 21
    Last Post: 03-30-2009, 07:34 AM
  2. Obfuscated Code Contest: The Results
    By Stack Overflow in forum Contests Board
    Replies: 29
    Last Post: 02-18-2005, 05:39 PM
  3. Obfuscated Code Contest
    By Stack Overflow in forum Contests Board
    Replies: 51
    Last Post: 01-21-2005, 04:17 PM
  4. Interface Question
    By smog890 in forum C Programming
    Replies: 11
    Last Post: 06-03-2002, 05:06 PM
  5. Replies: 0
    Last Post: 02-21-2002, 06:05 PM