1 /////////////////////////////////////////
2 //
3 //             OpenLieroX
4 //
5 // code under LGPL, based on JasonBs work,
6 // enhanced by Dark Charlie and Albert Zeyer
7 //
8 //
9 /////////////////////////////////////////
10 
11 
12 // Custom browser class
13 // Created 7/6/02
14 // Jason Boettcher
15 
16 
17 #ifndef __CBROWSER_H__DEPRECATED_GUI__
18 #define __CBROWSER_H__DEPRECATED_GUI__
19 
20 
21 #include "InputEvents.h"
22 #include <libxml/HTMLparser.h>
23 #include <stack>
24 #include "LieroX.h"
25 #include "Timer.h"
26 #include "Protocol.h"
27 #include "CScrollbar.h"
28 #include "HTTP.h"
29 #include "GfxPrimitives.h"
30 
31 
32 namespace DeprecatedGUI {
33 
34 #define BORDER_SIZE 2
35 
36 // Browser messages
37 enum {
38 	BRW_NONE = -1,
39 	BRW_KEY_PROCESSED = 0,
40 	BRW_KEY_NOT_PROCESSED
41 };
42 
43 struct FontFormat  {
FontFormatFontFormat44 	FontFormat() : bold(false), underline(false), italics(false), preformatted(false), size(0) {}
45 	bool bold;
46 	bool underline;
47 	bool italics;
48 	bool preformatted;
49 	int size;
50 	Color color;
51 };
52 
53 
54 // Browser class
55 class CBrowser : public CWidget {
56 public:
CBrowser()57 	CBrowser() :
58 		bFinished(false),
59 		tHtmlDocument(NULL),
60 		tRootNode(NULL),
61 		fLastMouseScroll(0),
62 		iBorderSize(BORDER_SIZE),
63 		iDocumentHeight(0),
64 		tCurrentLine(NULL),
65 		curX(0),
66 		curY(0),
67 		iCurIndent(0),
68 		iCursorColumn(0),
69 		iCursorLine(0),
70 		iSelectionStartLine(0),
71 		iSelectionStartColumn(0),
72 		iSelectionEndLine(0),
73 		iSelectionEndColumn(0),
74 		bSelectionGrabbed(false),
75 		bDrawCursor(true),
76 		tTimer(NULL),
77 		bmpBuffer(NULL),
78 		bNeedsRender(false)
79 	{
80 		tCurrentContext.tCurrentGroup = NULL;
81 		tBgColor = Color(0,0,0,0);
82 	}
83 
84 public:
85 
86 	// Everything in the browser is an object - a chunk of text, a link, ...
87 	// Objects are included in lines
88 	class CBrowserObject  {
89 	public:
90 		enum Type  {
91 			objNone = -1,
92 			objText = 0,
93 			objHr,
94 			objList
95 		};
96 
97 		typedef void(CBrowser::*EventHandler)(CBrowserObject *);
98 	public:
CBrowserObject(CBrowser * parent,const SDL_Rect & rect)99 		CBrowserObject(CBrowser *parent, const SDL_Rect& rect) :
100 		  tRect(rect),
101 		  tClickFunc(NULL),
102 		  tMouseMoveFunc(NULL),
103 		  tParent(parent),
104 		  iType(objNone),
105 		  bSelectable(false)
106 		  {}
107 
CBrowserObject()108 		CBrowserObject() :
109 		  tClickFunc(NULL),
110 		  tMouseMoveFunc(NULL),
111 		  tParent(NULL),
112 		  iType(objNone),
113 		  bSelectable(false)
114 		  { tRect = MakeRect(0, 0, 0, 0); }
115 
CBrowserObject(const CBrowserObject & oth)116 		CBrowserObject(const CBrowserObject& oth)  { operator=(oth); }
117 
~CBrowserObject()118 		virtual ~CBrowserObject() {}
119 
120 	protected:
121 		friend class CBrowser;
122 		SDL_Rect	tRect; // HINT: position in the document, not on screen!
123 		EventHandler tClickFunc;
124 		EventHandler tMouseMoveFunc;
125 		CBrowser	*tParent;
126 		Type		iType;
127 		bool		bSelectable;
128 
129 	public:
InBox(int x,int y)130 		bool	InBox(int x, int y) const  { return x >= tRect.x && x < (tRect.x + tRect.w)
131 			&& y >= tRect.y && y < (tRect.y + tRect.h); }
getWidth()132 		int		getWidth()		{ return tRect.w; }
getHeight()133 		int		getHeight()		{ return tRect.h; }
isSelectable()134 		bool	isSelectable()	{ return bSelectable; }
135 
136 	protected:
DoMouseMove(int x,int y)137 		virtual void	DoMouseMove(int x, int y)	{  }
DoMouseDown(int x,int y)138 		virtual void	DoMouseDown(int x, int y)	{  }
DoClick(int x,int y)139 		virtual void	DoClick(int x, int y)		{  }
CopyPropertiesTo(CBrowserObject * obj)140 		void CopyPropertiesTo(CBrowserObject *obj) const  {
141 			obj->tRect = tRect;
142 			obj->tClickFunc = tClickFunc;
143 			obj->tMouseMoveFunc = tMouseMoveFunc;
144 			obj->tParent = tParent;
145 			obj->iType = iType;
146 			obj->bSelectable = bSelectable;
147 		}
148 
149 	public:
getParent()150 		CBrowser *getParent() const			{ return tParent; }
getType()151 		Type getType() const				{ return iType; }
setClickHandler(EventHandler h)152 		void setClickHandler(EventHandler h) { tClickFunc = h; }
setMouseMoveHandler(EventHandler h)153 		void setMouseMoveHandler(EventHandler h) { tMouseMoveFunc = h; }
154 
Clear()155 		virtual void Clear()  { tRect = MakeRect(0, 0, 0, 0);
156 				tClickFunc = NULL; tMouseMoveFunc = NULL; tClickFunc = NULL; tParent = NULL; }
157 
158 		CBrowserObject& operator=(const CBrowserObject& oth)  {
159 			assert(false);
160 			return *this;
161 		}
162 
163 		virtual void Render(SDL_Surface *dest, int x, int y) = 0;
164 
165 		virtual CBrowserObject *Clone() const = 0;
166 
167 	};
168 
169 	// Group of objects
170 	// An example of a group is a link (<a></a>)
171 	class CObjectGroup  {
172 	private:
173 		std::list<CBrowserObject *> tObjects;
174 
175 	protected:
CopyPropertiesTo(CObjectGroup * oth)176 		void CopyPropertiesTo(CObjectGroup *oth) const {
177 			oth->tObjects = tObjects;
178 		}
179 	public:
CObjectGroup()180 		CObjectGroup()  {}
CObjectGroup(const CObjectGroup & oth)181 		CObjectGroup(const CObjectGroup& oth)  { operator=(oth); }
182 		CObjectGroup& operator=(const CObjectGroup& oth)  {
183 			assert(false);
184 			return *this;
185 		}
~CObjectGroup()186 		virtual ~CObjectGroup() {}
187 
DoMouseMove(int x,int y)188 		virtual void DoMouseMove(int x, int y)	{}
DoClick(int x,int y)189 		virtual void DoClick(int x, int y)		{}
190 
191 		virtual CObjectGroup *Clone() const = 0;
192 
getObjects()193 		const std::list<CBrowserObject *>& getObjects()	{ return tObjects; }
addObject(CBrowserObject * obj)194 		void addObject(CBrowserObject *obj)				{ tObjects.push_back(obj); }
195 		bool InBox(int x, int y);
196 	};
197 
198 private:
199 	class CBrowserLine  {
200 	public:
CBrowserLine()201 		CBrowserLine() : iHeight(0), iLeftMargin(0), iMaxWidth(0), iDocumentY(0) {}
CBrowserLine(int margin)202 		CBrowserLine(int margin) : iHeight(0), iLeftMargin(margin), iMaxWidth(0), iDocumentY(0) {}
203 
CBrowserLine(const CBrowserLine & oth)204 		CBrowserLine(const CBrowserLine& oth)  { operator=(oth); }
205 		CBrowserLine& operator=(const CBrowserLine& oth)  {
206 			if (&oth != this)  {
207 				iHeight = oth.iHeight;
208 				iLeftMargin = oth.iLeftMargin;
209 				iMaxWidth = oth.iMaxWidth;
210 				iDocumentY = oth.iDocumentY;
211 				tObjects = oth.tObjects;
212 				sPureText = oth.sPureText;
213 			}
214 			return *this;
215 		}
216 
217 		~CBrowserLine();
218 	private:
219 		int			iHeight;
220 		int			iLeftMargin;
221 		int			iMaxWidth;
222 		int			iDocumentY;
223 		std::list<CBrowserObject *> tObjects;
224 		std::string	sPureText; // For better selection handling
225 
226 	public:
setHeight(int h)227 		void setHeight(int h)		{ iHeight = h; }
setLeftMargin(int m)228 		void setLeftMargin(int m)	{ iLeftMargin = m; }
setMaxWidth(int m)229 		void setMaxWidth(int m)		{ iMaxWidth = m; }
setDocumentY(int y)230 		void setDocumentY(int y)	{ iDocumentY = y; }
getHeight()231 		int	getHeight()				{ return iHeight; }
getLeftMargin()232 		int	getLeftMargin()			{ return iLeftMargin; }
getMaxWidth()233 		int getMaxWidth()			{ return iMaxWidth; }
getDocumentY()234 		int getDocumentY()			{ return iDocumentY; }
isEmpty()235 		bool isEmpty()				{ return tObjects.empty(); }
ClearObjects()236 		void ClearObjects()			{ tObjects.clear(); sPureText.clear(); }
getPureText()237 		const std::string& getPureText()	{ return sPureText; }
238 
getObjects()239 		std::list<CBrowserObject *>& getObjects()	{ return tObjects; }
240 		void addObject(CBrowserObject *obj);
241 	};
242 
243 	class ParseContext  {
244 	public:
245 		FontFormat		tFormat;
246 		CObjectGroup	*tCurrentGroup;
247 	};
248 
249 private:
250 	// Attributes
251 	CHttp					cHttp;
252 	std::string				sURL;
253 	std::string				sHostName;
254 	bool					bFinished;
255 	htmlDocPtr				tHtmlDocument;
256 	htmlNodePtr				tRootNode;
257 	std::vector<CBrowserLine *>	tLines;
258 	std::list<CObjectGroup *>	tGroups;
259 	AbsTime					fLastMouseScroll;
260 	int						iBorderSize;
261 	size_t					iDocumentHeight;
262 
263 	// Parsing temps
264 	ParseContext			tCurrentContext;
265 	std::stack<ParseContext> tContextStack;
266 	CBrowserLine			*tCurrentLine;
267 	Color					tBgColor;
268 	int						curX;
269 	int						curY;
270 	int						iCurIndent; // Where the new lines should start (left margin)
271 
272 	// Selection & caret
273 	size_t					iCursorColumn;
274 	size_t					iCursorLine;
275 	size_t					iSelectionStartLine;
276 	size_t					iSelectionStartColumn;
277 	size_t					iSelectionEndLine;
278 	size_t					iSelectionEndColumn;
279 
280 	size_t					iSelectionGrabLine;
281 	size_t					iSelectionGrabColumn;
282 	bool					bSelectionGrabbed;
283 	bool					bDrawCursor;
284 	Timer					*tTimer;  // For cursor blink
285 
286 	// Window attributes
287 	CScrollbar				cScrollbar;
288 	bool					bUseScroll;
289 	bool					bFingerDragged;
290 	int						iFingerDraggedPos;
291 
292 	// Other
293 	SmartPointer<SDL_Surface>	bmpBuffer;
294 	bool					bNeedsRender;
295 
296 	// Methods
297 	htmlDocPtr				ParseHTML(const std::string& data);
298 	void					AppendDocument(htmlDocPtr doc);
299 	void					AppendNode(xmlNodePtr node);
300 	void					UpdateRenderObjects();
301 	void					ClearParser();
302 	void					InitNodeWalk();
303 	void					EndNodeWalk();
304 	void					RenderContent();
305 	bool					GetDrawSelectionBounds(size_t& top_line, size_t& bot_line);
306 	void					DrawSelectionForText(CBrowserObject *obj, size_t& line, size_t& column, int scroll_y);
307 	void					DrawSelection();
308 	void					AddObject(CBrowserObject *obj);
309 	void					AddTextObject(const std::string& text);
310 	void					ParseText(const std::string& text);
311 	void					WalkNodes(xmlNodePtr node);
312 	void					WalkChildren(xmlNodePtr node);
313 	bool					InSelection(size_t line, size_t column);
314 	std::string				GetSelectedText();
315 	bool					IsSelectionEmpty();
316 	void					ClearSelection();
317 	void					SwapSelectionEnds();
318 	void					EndLine();
319 	void					AdjustScrollbar(bool mouse = false);
320 	void					ReRender();
321 	void					DrawCursor(SDL_Surface *bmpDest);
322 	void					ResetScrollbar();
323 	void					AdjustBuffer();
324 	void					OnTimerEvent(Timer::EventData ev);
PushContext()325 	void					PushContext()	{ tContextStack.push(tCurrentContext); }
PopContext()326 	void					PopContext()	{ tCurrentContext = tContextStack.top(); tContextStack.pop(); }
327 
328 
329 	// Link helper functions
330 	void					StartLink(const std::string& url);
331 	void					EndLink();
332 	std::string				GetFullURL(const std::string& url);
333 
334 
335 public:
336 	// Methods
337 
338 
339 	void	Create();
340 	void	Destroy();
341 
ClearDocument()342 	void	ClearDocument()	{ ClearParser(); bNeedsRender = true; }
343 
344 	//These events return an event id, otherwise they return -1
345 	int		MouseOver(mouse_t *tMouse);
346 	int		MouseUp(mouse_t *tMouse, int nDown);
347 	int		MouseWheelDown(mouse_t *tMouse);
348 	int		MouseWheelUp(mouse_t *tMouse);
349 	int		MouseDown(mouse_t *tMouse, int nDown);
350 	int		KeyDown(UnicodeChar c, int keysym, const ModifiersState& modstate);
KeyUp(UnicodeChar c,int keysym,const ModifiersState & modstate)351 	int		KeyUp(UnicodeChar c, int keysym, const ModifiersState& modstate) { return BRW_NONE; }
352 
SendMessage(int iMsg,DWORD Param1,DWORD Param2)353 	DWORD SendMessage(int iMsg, DWORD Param1, DWORD Param2) { return 0; }
SendMessage(int iMsg,const std::string & sStr,DWORD Param)354 	DWORD SendMessage(int iMsg, const std::string& sStr, DWORD Param) { return 0; }
SendMessage(int iMsg,std::string * sStr,DWORD Param)355 	DWORD SendMessage(int iMsg, std::string *sStr, DWORD Param)  { return 0; }
356 
357 	void	Draw(SDL_Surface * bmpDest);
358 
359 	void	MousePosToCursorPos(int ms_x, int ms_y, size_t& cur_x, size_t& cur_y);
360 	void	CursorPosToMousePos(size_t cur_x, size_t cur_y, int& ms_x, int& ms_y);
361 
362 	void	LoadFromHTTP(const std::string& url);
363 	void	LoadFromFile(const std::string& file);
364 	void	LoadFromString(const std::string& data);
365 	void	AppendData(const std::string& data);
366 	void	ProcessHTTP();
367 
getBorderSize()368 	int		getBorderSize()		{ return iBorderSize; }
setBorderSize(int size)369 	void	setBorderSize(int size)	{ iBorderSize = size; }
370 
371 	// TODO: create a descendant chatbox class and move the chatbox things there, they do not belong to browser
372 	void	InitializeChatBox( const std::string & initText = "" );
373 	void	AddChatBoxLine(const std::string & text, Color color, TXT_TYPE textType, bool bold = false, bool underline = false);
374 	std::string GetChatBoxText();
375 	void	CleanUpChatBox( const std::vector<TXT_TYPE> & removedText, int maxLineCount );
376 	void	ScrollToLastLine();
NeedsRepaint()377 	bool	NeedsRepaint()  { return bNeedsRender; }
378 
IsLoaded()379 	bool	IsLoaded()		{ return bFinished; }
380 
GetHttp()381 	CHttp&	GetHttp()		{ return cHttp; }
382 
383 	// TODO: add function for getting individual text lines & their color
384 };
385 
386 }; // namespace DeprecatedGUI
387 
388 #endif  //  __CBROWSER_H__DEPRECATED_GUI__
389