home *** CD-ROM | disk | FTP | other *** search
- /*
- File: HTMLParser.cp
-
- Contains: A simplistic parse of a sub-set of HTML.
- Used to allow styles in dialogs.
-
- Written by: Arno Gourdol
-
- Copyright: © 1996 by Apple Computer, Inc., all rights reserved.
-
- */
-
- #include "HTMLParser.h"
- #include "assert.h"
- #include "macros.h"
-
- #include <TextUtils.h>
-
-
-
- // --------------------------------------------------------------------
- // HTMLParser
- // --------------------------------------------------------------------
-
- HTMLParser::HTMLParser(Handle text, SInt32 fromIndex, SInt32 toIndex) :
- fTextHandle(text),
- fCursor(fromIndex - 1),
- fFinalCursor(toIndex),
- fContinue(true)
- {
- assert(text != NULL);
- assert(fromIndex >= 0);
-
- if (toIndex < 0)
- fFinalCursor = ::GetHandleSize(text) - 1;
-
- fSavedHandleState = HGetState(fTextHandle);
- HLock(fTextHandle);
- fText = *fTextHandle;
- }
-
-
-
- // --------------------------------------------------------------------
- // ~HTMLParser
- // --------------------------------------------------------------------
-
- HTMLParser::~HTMLParser()
- {
- HSetState(fTextHandle, fSavedHandleState);
- }
-
-
-
- // --------------------------------------------------------------------
- // IsTag
- // --------------------------------------------------------------------
-
- Boolean HTMLParser::IsTag(SInt32 tagStart, SInt32 tagEnd,
- ConstStr255Param tag)
- {
- #pragma unused (tagStart)
- #pragma unused (tagEnd)
- #pragma unused (tag)
- SInt16 result = IdenticalText(&fText[tagStart], &tag[1],
- tag[0] - 1, tag[0] - 1, NULL);
-
- // Furthermore, the next character must be white space or
- // end of tag ???
-
- return (result == 0);
- }
-
-
-
- // --------------------------------------------------------------------
- // Tag
- // --------------------------------------------------------------------
-
- void HTMLParser::Tag(SInt32 tagStart, SInt32 tagEnd)
- {
- if (IsTag(tagStart, tagEnd, "\p<B>"))
- {
- TagBoldStart(tagStart, tagEnd);
- }
- else if (IsTag(tagStart, tagEnd, "\p</B>"))
- {
- TagBoldEnd(tagStart, tagEnd);
- }
- else if (IsTag(tagStart, tagEnd, "\p<I>"))
- {
- TagItalicStart(tagStart, tagEnd);
- }
- else if (IsTag(tagStart, tagEnd, "\p</I>"))
- {
- TagItalicEnd(tagStart, tagEnd);
- }
- }
-
-
-
- // --------------------------------------------------------------------
- // TagBoldStart
- // --------------------------------------------------------------------
-
- void HTMLParser::TagBoldStart(SInt32 tagStart, SInt32 tagEnd)
- {
- #pragma unused (tagStart)
- #pragma unused (tagEnd)
- }
-
-
-
- // --------------------------------------------------------------------
- // TagBoldEnd
- // --------------------------------------------------------------------
-
- void HTMLParser::TagBoldEnd(SInt32 tagStart, SInt32 tagEnd)
- {
- #pragma unused (tagStart)
- #pragma unused (tagEnd)
- }
-
-
-
- // --------------------------------------------------------------------
- // TagItalicStart
- // --------------------------------------------------------------------
-
- void HTMLParser::TagItalicStart(SInt32 tagStart, SInt32 tagEnd)
- {
- #pragma unused (tagStart)
- #pragma unused (tagEnd)
- }
-
-
-
- // --------------------------------------------------------------------
- // TagItalicEnd
- // --------------------------------------------------------------------
-
- void HTMLParser::TagItalicEnd(SInt32 tagStart, SInt32 tagEnd)
- {
- #pragma unused (tagStart)
- #pragma unused (tagEnd)
- }
-
-
-
- // --------------------------------------------------------------------
- // EndOfText
- // --------------------------------------------------------------------
-
- void HTMLParser::EndOfText(SInt32 endOfText)
- {
- #pragma unused (endOfText)
- }
-
-
-
- // --------------------------------------------------------------------
- // Parse
- // --------------------------------------------------------------------
-
- void HTMLParser::Parse(void)
- {
- UInt16 c;
- while (fContinue)
- {
- c = GetChar();
- if (c == '<')
- {
- // Potential start of a tag
- UInt32 startTag = GetCursor();
-
- UInt32 endTag = FindChar('>');
-
- if (endTag >= 0)
- {
- Tag(startTag, endTag);
- SetCursor(endTag);
- }
- }
- }
- EndOfText(max(GetCursor(), GetFinalCursor()));
- }
-
-
-
- // --------------------------------------------------------------------
- // SkipWhiteSpaces
- // --------------------------------------------------------------------
-
- void HTMLParser::SkipWhiteSpaces(void)
- {
- UInt16 c;
-
- do
- {
- c = GetChar();
- } while (c == ' ');
- // ??? Use Character type to catch all the white spaces
-
- // Roll back one if we have found white space
- SetCursor(GetCursor() - 1);
- }
-
-
-
- // --------------------------------------------------------------------
- // GetChar
- // --------------------------------------------------------------------
-
- UInt16 HTMLParser::GetChar(void)
- {
- if (GetCursor() >= GetFinalCursor())
- {
- Abort();
- return 0;
- }
- else
- {
- Byte c;
- // ??? Should use FillParseTable to take into account
- // 2-bytes characters
- c = fText[++fCursor];
- return c;
- }
- }
-
-
-
- // --------------------------------------------------------------------
- // FindChar
- // --------------------------------------------------------------------
- //
- // Find a character in the text stream, return its index
- // -1 if not found
- // Do not change the cursor
-
- SInt32 HTMLParser::FindChar(UInt16 c)
- {
- SInt32 result;
- SInt32 saveCursor = GetCursor();
-
- Byte currentChar;
-
- do
- {
- currentChar = GetChar();
- } while (fContinue && currentChar != c);
-
- if (!fContinue)
- result = -1;
- else
- result = GetCursor();
-
- SetCursor(saveCursor);
-
- return result;
- }
-
-
-
- // --------------------------------------------------------------------
- // HTMLToStyledText
- // --------------------------------------------------------------------
-
- HTMLToStyledText::HTMLToStyledText(CRect frame, Handle text) :
- HTMLParser(text),
- fFrame(frame),
- fStyledText(NULL),
- fLastTextStyleChange(0),
- fBold(0),
- fItalic(0)
- {
- // fStyledText = TEStyleNew(fFrame, fFrame);
- }
-
-
-
- // --------------------------------------------------------------------
- // GetStyledText
- // --------------------------------------------------------------------
-
- TEHandle HTMLToStyledText::GetStyledText(void)
- {
- return fStyledText;
- }
-
-
-
- // --------------------------------------------------------------------
- // ApplyTextStyles
- // --------------------------------------------------------------------
-
- void HTMLToStyledText::ApplyTextStyles(SInt32 upToIndex)
- {
- assert(upToIndex >= -1 && upToIndex <= GetFinalCursor());
-
- if (fStyledText == NULL)
- {
- fStyledText = TEStyleNew(fFrame, fFrame);
- }
-
- {
- {
- SInt32 endOfText = GetHandleSize((**fStyledText).hText);
-
- OSErr err = PtrAndHand(&fText[fLastTextStyleChange],
- (**fStyledText).hText,
- (upToIndex - fLastTextStyleChange) + 1);
- assert(err == noErr);
-
- TESetSelect(endOfText, 32000, fStyledText);
- }
- {
- TextStyle newStyle;
- newStyle.tsFace = normal;
- newStyle.filler = 0; // Workaround for style
- // TextEdit bug see TE.16
- if (fBold > 0)
- newStyle.tsFace |= bold;
- if (fItalic > 0)
- newStyle.tsFace |= italic;
-
- TESetStyle(doFace, &newStyle, false, fStyledText);
- }
- }
- }
-
-
-
- // --------------------------------------------------------------------
- // TagBoldStart
- // --------------------------------------------------------------------
-
- void HTMLToStyledText::TagBoldStart(SInt32 tagStart, SInt32 tagEnd)
- {
- ApplyTextStyles(tagStart - 1);
- fLastTextStyleChange = tagEnd + 1;
- fBold++;
- }
-
-
-
- // --------------------------------------------------------------------
- // TagBoldEnd
- // --------------------------------------------------------------------
-
- void HTMLToStyledText::TagBoldEnd(SInt32 tagStart, SInt32 tagEnd)
- {
- ApplyTextStyles(tagStart - 1);
- fLastTextStyleChange = tagEnd + 1;
- fBold--;
- }
-
-
-
- // --------------------------------------------------------------------
- // TagItalicStart
- // --------------------------------------------------------------------
-
- void HTMLToStyledText::TagItalicStart(SInt32 tagStart, SInt32 tagEnd)
- {
- ApplyTextStyles(tagStart - 1);
- fLastTextStyleChange = tagEnd + 1;
- fItalic++;
- }
-
-
-
- // --------------------------------------------------------------------
- // TagItalicEnd
- // --------------------------------------------------------------------
-
- void HTMLToStyledText::TagItalicEnd(SInt32 tagStart, SInt32 tagEnd)
- {
- ApplyTextStyles(tagStart - 1);
- fLastTextStyleChange = tagEnd + 1;
- fItalic--;
- }
-
-
-
- // --------------------------------------------------------------------
- // EndOfText
- // --------------------------------------------------------------------
- //
- // endOfText is the index to the last character
-
- void HTMLToStyledText::EndOfText(SInt32 endOfText)
- {
- if (fStyledText != NULL)
- {
- ApplyTextStyles(endOfText);
- TESetSelect(GetHandleSize((**fStyledText).hText) - 1,
- GetHandleSize((**fStyledText).hText), fStyledText);
- {
- TextStyle newStyle;
- newStyle.tsFace = bold;
- newStyle.filler = 0; // Workaround for style
- // TextEdit bug see TE.16
- TESetStyle(doFace, &newStyle, false, fStyledText);
- }
- TECalText(fStyledText);
- }
- }
-
-
-
- // --------------------------------------------------------------------
- // ConvertHTMLToStyledText
- // --------------------------------------------------------------------
- // Parses "text". If it contains HTML tags, create a new TextEdit
- // record with all the styles set appropriately.
- // Returns NULL otherwise.
-
- void ConvertHTMLToStyledText(Handle text, CRect frame,
- TEHandle* textEdit)
- {
- HTMLToStyledText parser(frame, text);
-
- parser.Parse();
-
- *textEdit = parser.GetStyledText();
- }
-
-
-
-