PDA

View Full Version : Code Painter



siavoshkc
08-09-2008, 07:29 AM
//By SiavoshKC
#include <iostream>
using namespace std;
int main()
{
int a =12;
int b =9;
cout<< "Hello" << a+ b << endl;
return 0;

}

This code was painted using my Code Painter. Download it by link in my signature.

DavidP
08-09-2008, 08:50 AM
I'm not sure if I trust that download link.

Fordy
08-09-2008, 09:01 AM
If you are going to distribute this then it should come with the code. I dont run .exe files I download unless I am pretty sure they wont do anything nasty

Yarin
08-09-2008, 09:35 AM
Isn't this considered spam? :D

Fordy
08-09-2008, 10:44 AM
Isn't this considered spam? :D


No...

SlyMaelstrom
08-09-2008, 03:33 PM
Well, in the mean time... just looking at the code you posted, I can't say I like the colors. Datatypes are colored the same as keywords and preprocessor directives. Libraries are colored the same as string constants. It's all a little confusing.

whiteflags
08-09-2008, 05:28 PM
Well it's close to the color scheme Visual Studio would use by default, not that I'm defending it.

What I don't like is the boldface, that was a mistake. If you've ever read a black & white printout of some code, you'd understand why, siavoshc. Bold can play a much more important role if you don't print in color.

siavoshkc
08-10-2008, 01:36 AM
I am going to upload whole source code after some clean-ups. It is in C++\CLI.
The selected color for each item is not a problem. It is too simple to change them.

#include <iostream>

mike_g
08-12-2008, 03:51 PM
This looked like fun so I had a go too. So far it only works with C and the tags create a lot of bloat, but it seems to work ok, which is the main thing. I put the code on webpage generated by the prog. Heres a link to my syntax highlighter (http://grundez.googlepages.com/syntax_hilighter.html).

Cheers.

zacs7
08-12-2008, 04:47 PM
Doesn't even come close to codeform by dwks (http://cboard.cprogramming.com/showthread.php?p=627656) ;)

twomers
08-12-2008, 05:08 PM
Or its painted self... http://dwks.theprogrammingsite.com/myprogs/codeform/formself.htm
And online self... http://dwks.theprogrammingsite.com/myprogs/cfonline.htm

Cactus_Hugger
08-12-2008, 08:56 PM
Is this an installer... inside a WinRAR self extractor... that's been run through UPX? >.<
Furthermore, your program wants admin privileges to install >.>

So, like, a 1.5MB executable to ship ~80KB exe?

Some comments:
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\.....

dwks
08-13-2008, 04:44 PM
Glad to see codeform has a following. :D (Don't forget the clipboard Perl scripts!)

By the way: in the latest version of codeform (1.2.0), tags that are the same colour are merged together, eliminating the "bloat" that I assume mike_g was referring to. I can't remember how I did it, but I'm sure you could find out by looking at its source. :) (Basically, record the starting tag, allow skipping over whitespace, and check if the next tag is the same as the previous one.)

mike_g
08-14-2008, 06:14 AM
Basically, record the starting tag, allow skipping over whitespace, and check if the next tag is the same as the previous one.
Yeah, thats the same as what I had done. It chopped a third off the size. Last night I added colouring to the brackets and all the space I had saved was lost again :/ I might see if I can shrink the tags using xml.

dwks
08-15-2008, 01:48 PM
I guess that's the price you pay for coloured brackets. :)

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.

mike_g
08-15-2008, 04:02 PM
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:

<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:

<bkt>{</bkt>

whiteflags
08-16-2008, 01:11 AM
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.

siavoshkc
08-16-2008, 07:44 AM
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?

maxorator
08-16-2008, 02:29 PM
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.

siavoshkc
08-17-2008, 04:03 PM
http://maxx.5gigs.com (Click on the typenames ("Comments, "Preprocess") to select a color)
#include <iostream> //asdfafsd /*sdfsdf*/

I think it should give <...> another color.

[edit]
gcc compiler is the most colorful editor, isn't it?

mike_g
08-17-2008, 05:31 PM
I think it should give <...> another color.
Normally yes, but in the preprocesor that would be a little strange.

whiteflags
08-17-2008, 06:33 PM
4) You write to C:\Program Files\Your\Dir ... it gets redirected to C:\Users\blah\AppData\Local\.....


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.

maxorator
08-18-2008, 03:22 AM
#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...

zacs7
08-18-2008, 04:00 AM
Never used VI/VIM before?

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

maxorator
08-18-2008, 05:08 AM
I've used MSVC++, Code::Blocks, Dev-C++ and Notepad++. I've never programmed in Linux. :p

Cactus_Hugger
08-18-2008, 05:30 PM
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.

Neo1
08-21-2008, 02:44 PM
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..


//tue.haulund@gmail.com
//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 :)

matsp
08-21-2008, 04:37 PM
Some comments:



DWORD i = 0, j = 0, k = 0, l = 0;
bool IsKeyWord;

//Main parser loop
for(; i < InputSize; i++)

Why not just have

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.



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:


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.



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

Neo1
08-26-2008, 01:24 PM
Thanks Mats, i added the changes you suggested, and the code now looks like this:


//tue.haulund@gmail.com
//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 :)

dwks
08-26-2008, 03:59 PM
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.


pBuffer = new char[data.length()];

I have a suspicion that you wanted data.length() + 1 there . . . .

matsp
08-27-2008, 04:55 AM
Minor detail:


!(pBuffer[i+k] == Keywords[j][k])

would be easier to read as:


(pBuffer[i+k] != Keywords[j][k])

(And it's shorter to write).

Also, along the lines of what dwks says, there is a lot of code repetition in your functions still - particularly the bit that "take next character and output either itself or &gt/&lt. I think all of the loops can be translated into a generic function that loops around until some end condition - perhaps use strchr() to see if it's in a list of characters to terminate the current colour?

--
Mats

dwks
08-31-2008, 04:21 PM
I was just reading through this thread quickly, and I noticed something that I thought I should comment on:

(ch == '<')? SS << "&lt;" : (ch == '>')? SS << "&gt;" : SS << ch;

That might be easier to read as

SS << (ch == '<' ? "&lt;" : (ch == '>' ? "&gt;" : ch));
I really don't like nesting the conditional operator, though, so I'd suggest using if/else or switch instead. Or, better yet, perhaps something like this:

const char *find = "<>";
const char *replace[] = {"&lt;", "&gt;"};
const char *p;

if((p = strchr(find, ch))) SS << replace[p - find];
else SS << ch;
But maybe that's just overkill. ;)