]> git.saurik.com Git - wxWidgets.git/blob - samples/richedit/wxllist.h
Implement NSMenuValidation protocol for the wxNSMenuItemTarget
[wxWidgets.git] / samples / richedit / wxllist.h
1 /*-*- c++ -*-********************************************************
2 * wxLayoutList.h - a formatted text rendering engine for wxWindows *
3 * *
4 * (C) 1999-2000 by Karsten Ballüder (ballueder@gmx.net) *
5 * *
6 * $Id$
7 *******************************************************************/
8
9
10 #ifndef WXLLIST_H
11 #define WXLLIST_H
12
13 #ifdef __GNUG__
14 # pragma interface "wxllist.h"
15 #endif
16
17 #include "kbList.h"
18
19 #include <wx/wx.h>
20 #include <wx/print.h>
21 #include <wx/printdlg.h>
22 #include <wx/generic/printps.h>
23 #include <wx/generic/prntdlgg.h>
24 #include <wx/dataobj.h>
25
26 // skip the following defines if embedded in M application
27 #ifndef M_BASEDIR
28 # define WXMENU_LAYOUT_LCLICK 1111
29 # define WXMENU_LAYOUT_RCLICK 1112
30 # define WXMENU_LAYOUT_DBLCLICK 1113
31 #else // for Mahogany only
32 # include "MObject.h"
33 #endif
34
35 // use the wxWindows caret class instead of home grown cursor whenever possible
36 #ifdef __WXMSW__
37 # undef WXLAYOUT_USE_CARET
38 # define WXLAYOUT_USE_CARET 1
39 #endif // __WXMSW__
40
41 // do not enable debug mode within Mahogany unless in debug mode
42 #if defined(__WXDEBUG__) && (( ! defined(M_BASEDIR) )|| defined(DEBUG))
43 # define WXLAYOUT_DEBUG
44 #endif
45
46 #ifdef WXLAYOUT_DEBUG
47 # define WXLO_TRACE(x) wxLogDebug(x)
48 // activate profiling: # define WXLO_PROFILE
49 #else
50 # define WXLO_TRACE(x)
51 #endif
52
53 /* Some profiling code: */
54 #if defined (WXLO_PROFILE)
55 #include <sys/time.h>
56 #include <unistd.h>
57
58 # define WXLO_TIMER_DEFINE(x) static struct timeval x
59 # define WXLO_TIMER_START(x) gettimeofday(&x,NULL)
60 # define WXLO_TIMER_STOP(x) { struct timeval y; \
61 gettimeofday(&y,NULL); \
62 x.tv_sec -= y.tv_sec; x.tv_usec -= y.tv_usec; }
63 # define WXLO_TIMER_PRINT(x) wxLogDebug("Timer " #x " elapsed: %ld", \
64 (long)(x.tv_sec * -1000 - x.tv_usec));
65 #else
66 # define WXLO_TIMER_DEFINE(x)
67 # define WXLO_TIMER_START(x)
68 # define WXLO_TIMER_STOP(x)
69 # define WXLO_TIMER_PRINT(x)
70 #endif
71
72
73 #define WXLO_DEBUG_URECT 0
74
75 #ifndef WXLO_DEFAULTFONTSIZE
76 # define WXLO_DEFAULTFONTSIZE 12
77 #endif
78
79 #ifdef __WXMSW__
80 # define WXLO_BITMAP_FORMAT wxBITMAP_TYPE_BMP
81 #else
82 # define WXLO_BITMAP_FORMAT wxBITMAP_TYPE_PNG
83 #endif
84
85 /// Types of currently supported layout objects.
86 enum wxLayoutObjectType
87 {
88 /// illegal object type, should never appear
89 WXLO_TYPE_INVALID = 0,
90 /// text object, containing normal text
91 WXLO_TYPE_TEXT,
92 /// command object, containing font or colour changes
93 WXLO_TYPE_CMD,
94 /// icon object, any kind of image
95 WXLO_TYPE_ICON,
96 /// a linebreak, does not exist as an object
97 WXLO_TYPE_LINEBREAK
98 };
99
100 /// Type used for coordinates in drawing. Must be signed.
101 typedef long CoordType;
102
103 // Forward declarations.
104 class wxLayoutList;
105 class wxLayoutLine;
106 class wxLayoutObject;
107
108 class WXDLLEXPORT wxCaret;
109 class WXDLLEXPORT wxColour;
110 class WXDLLEXPORT wxDC;
111 class WXDLLEXPORT wxFont;
112
113 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
114
115 The wxLayout objects which make up the lines.
116
117 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
118
119 /** The base class defining the interface to each object which can be
120 part of the layout. Each object needs to draw itself and calculate
121 its size.
122 */
123 class wxLayoutObject
124 #ifdef M_BASEDIR
125 : public MObject
126 #endif
127 {
128 public:
129 /** This structure can be used to contain data associated with the
130 object.
131 It is refcounted, so the caller has to do a DecRef() on it
132 instead of a delete.
133 */
134 struct UserData
135 {
136 UserData() { m_refcount = 1; }
137 inline void IncRef(void) { m_refcount++; }
138 inline void DecRef(void) { m_refcount--; if(m_refcount == 0) delete this;}
139 inline void SetLabel(const wxString &l) { m_label = l; }
140 inline const wxString & GetLabel(void) const { return m_label; }
141 private:
142 int m_refcount;
143 wxString m_label;
144 protected:
145 virtual ~UserData() { wxASSERT(m_refcount == 0); }
146 /// prevents gcc from generating stupid warnings
147 friend class dummy_UserData;
148 };
149
150 /// return the type of this object
151 virtual wxLayoutObjectType GetType(void) const { return WXLO_TYPE_INVALID; }
152 /** Calculates the size of an object.
153 @param dc the wxDC to draw on
154 @param llist the wxLayoutList
155 */
156 virtual void Layout(wxDC &dc, wxLayoutList *llist) = 0;
157
158 /** Draws an object.
159 @param dc the wxDC to draw on
160 @param coords where to draw the baseline of the object.
161 @param wxllist pointer to wxLayoutList
162 @param begin if !=-1, from which position on to highlight it
163 @param end if begin !=-1, how many positions to highlight it
164 */
165 virtual void Draw(wxDC & /* dc */,
166 wxPoint const & /* coords */,
167 wxLayoutList *wxllist,
168 CoordType begin = -1,
169 CoordType end = -1) { }
170
171 /** Calculates and returns the size of the object.
172 @param top where to store height above baseline
173 @param bottom where to store height below baseline
174 @return the size of the object's box in pixels
175 */
176 virtual wxPoint GetSize(CoordType * top, CoordType *bottom) const
177 { *top = 0; *bottom = 0; return wxPoint(0,0); }
178
179 /// Return just the width of the object on the screen.
180 virtual CoordType GetWidth(void) const { return 0; }
181 /// returns the number of cursor positions occupied by this object
182 virtual CoordType GetLength(void) const { return 1; }
183 /** Returns the cursor offset relating to the screen x position
184 relative to begin of object.
185 @param dc the wxDC to use for calculations
186 @param xpos relative x position from head of object
187 @return cursor coordinate offset
188 */
189 virtual CoordType GetOffsetScreen(wxDC &dc, CoordType xpos) const { return 0; }
190
191 /// constructor
192 wxLayoutObject() { m_UserData = NULL; }
193 /// delete the user data
194 virtual ~wxLayoutObject() { if(m_UserData) m_UserData->DecRef(); }
195
196 #ifdef WXLAYOUT_DEBUG
197 virtual wxString DebugDump(void) const;
198 #endif
199
200 /** Tells the object about some user data. This data is associated
201 with the object and will be deleted at destruction time.
202 It is reference counted.
203 */
204 void SetUserData(UserData *data)
205 {
206 if(m_UserData)
207 m_UserData->DecRef();
208 m_UserData = data;
209 if(m_UserData)
210 m_UserData->IncRef();
211 }
212
213 /** Return the user data.
214 Increments the object's reference count. When no longer needed,
215 caller must call DecRef() on the pointer returned.
216 */
217 UserData * GetUserData(void) const { if(m_UserData) m_UserData->IncRef(); return m_UserData; }
218
219 /** Makes a copy of this object.
220 */
221 virtual wxLayoutObject *Copy(void) = 0;
222
223 /** Clipboard support function. Read and write objects to
224 strings. */
225 //@{
226 /// Writes the object to the string.
227 virtual void Write(wxString &ostr) = 0;
228 /** Reads an object.
229 @param str stream to read from, will bee changed
230 @return true on success
231 */
232 static wxLayoutObject *Read(wxString &istr);
233 //@}
234
235 /// returns TRUE if the object is shown on the screen (i.e. not cmd object)
236 bool IsVisibleObject() const { return GetType() != WXLO_TYPE_CMD; }
237
238 protected:
239 /// optional data for application's use
240 UserData *m_UserData;
241 #if defined (M_BASEDIR) && defined (DEBUG)
242 MOBJECT_NAME(wxLayoutObject)
243 #endif
244 };
245
246 /// Define a list type of wxLayoutObject pointers.
247 KBLIST_DEFINE(wxLayoutObjectList, wxLayoutObject);
248
249 /// An illegal iterator to save typing.
250 #define NULLIT (wxLayoutObjectList::iterator(NULL))
251 /// The iterator type.
252 typedef wxLayoutObjectList::iterator wxLOiterator;
253
254 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
255
256 wxLayoutObjectText
257
258 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
259 /** This class implements a wxLayoutObject holding plain text.
260 */
261 class wxLayoutObjectText : public wxLayoutObject
262 {
263 public:
264 wxLayoutObjectText(const wxString &txt = "");
265
266 virtual wxLayoutObjectType GetType(void) const { return WXLO_TYPE_TEXT; }
267 virtual void Layout(wxDC &dc, wxLayoutList *llist);
268 virtual void Draw(wxDC &dc, wxPoint const &coords,
269 wxLayoutList *wxllist,
270 CoordType begin = -1,
271 CoordType end = -1);
272 /** Calculates and returns the size of the object.
273 @param top where to store height above baseline
274 @param bottom where to store height below baseline
275 @return the size of the object's box in pixels
276 */
277 virtual wxPoint GetSize(CoordType * top, CoordType *bottom) const;
278 /// Return just the width of the object on the screen.
279 virtual CoordType GetWidth(void) const { return m_Width; }
280 /** Returns the cursor offset relating to the screen x position
281 relative to begin of object.
282 @param dc the wxDC to use for calculations
283 @param xpos relative x position from head of object
284 @return cursor coordinate offset
285 */
286 virtual CoordType GetOffsetScreen(wxDC &dc, CoordType xpos) const;
287
288 virtual void Write(wxString &ostr);
289 static wxLayoutObjectText *Read(wxString &istr);
290
291 #ifdef WXLAYOUT_DEBUG
292 virtual wxString DebugDump(void) const;
293 #endif
294
295 virtual CoordType GetLength(void) const { return wxStrlen(m_Text.c_str()); }
296
297 // for editing:
298 wxString & GetText(void) { return m_Text; }
299 void SetText(wxString const &text) { m_Text = text; }
300 /** Makes a copy of this object.
301 */
302 virtual wxLayoutObject *Copy(void);
303 private:
304 wxString m_Text;
305 /// size of the box containing text
306 long m_Width, m_Height;
307 /// Height above baseline.
308 long m_Top;
309 /// Height below baseline.
310 long m_Bottom;
311 };
312
313 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
314
315 wxLayoutObjectIcon
316
317 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
318 /** This class implements a wxLayoutObject holding a graphic.
319 */
320 class wxLayoutObjectIcon : public wxLayoutObject
321 {
322 public:
323 wxLayoutObjectIcon(wxBitmap *icon = NULL);
324 wxLayoutObjectIcon(wxBitmap const &icon);
325
326 ~wxLayoutObjectIcon() { if(m_Icon) delete m_Icon; }
327
328 virtual wxLayoutObjectType GetType(void) const { return WXLO_TYPE_ICON; }
329 virtual void Layout(wxDC &dc, wxLayoutList *llist);
330 virtual void Draw(wxDC &dc, wxPoint const &coords,
331 wxLayoutList *wxllist,
332 CoordType begin = -1,
333 CoordType end = -1);
334
335 /** Calculates and returns the size of the object.
336 @param top where to store height above baseline
337 @param bottom where to store height below baseline
338 @return the size of the object's box in pixels
339 */
340 virtual wxPoint GetSize(CoordType * top, CoordType *bottom) const;
341 /// Return just the width of the object on the screen.
342 virtual CoordType GetWidth(void) const { return m_Icon->GetWidth(); }
343 // return a pointer to the icon
344 wxBitmap *GetIcon(void) const { return m_Icon; }
345 /** Makes a copy of this object.
346 */
347 virtual wxLayoutObject *Copy(void);
348 virtual void Write(wxString &ostr);
349 static wxLayoutObjectIcon *Read(wxString &istr);
350 private:
351 wxBitmap *m_Icon;
352 };
353
354 /** This structure holds all formatting information.
355 */
356 struct wxLayoutStyleInfo
357 {
358 wxLayoutStyleInfo(int ifamily = -1,
359 int isize = -1,
360 int istyle = -1,
361 int iweight = -1,
362 int iul = -1,
363 wxColour *fg = NULL,
364 wxColour *bg = NULL);
365 wxLayoutStyleInfo & operator=(const wxLayoutStyleInfo &right);
366
367 wxColour & GetBGColour() { return m_bg; }
368
369 /// Font change parameters.
370 int size, family, style, weight, underline;
371 /// Colours
372 wxColour m_bg, m_fg;
373 int m_fg_valid, m_bg_valid; // bool, but must be int!
374 };
375
376 /// a cached font
377 class wxFontCacheEntry
378 {
379 public:
380 wxFontCacheEntry(int family, int size, int style, int weight,
381 bool underline)
382 {
383 m_Family = family; m_Size = size; m_Style = style;
384 m_Weight = weight; m_Underline = underline;
385 m_Font = new wxFont(m_Size, m_Family,
386 m_Style, m_Weight, m_Underline);
387 }
388 bool Matches(int family, int size, int style, int weight,
389 bool underline) const
390 {
391 return size == m_Size && family == m_Family
392 && style == m_Style && weight == m_Weight
393 && underline == m_Underline;
394 }
395 wxFont & GetFont(void) { return *m_Font; }
396 ~wxFontCacheEntry()
397 {
398 delete m_Font;
399 }
400 private:
401 wxFont *m_Font;
402
403 // VZ: I wonder why it doesn't use wxLayoutStyleInfo instead of those?
404 int m_Family, m_Size, m_Style, m_Weight;
405 bool m_Underline;
406 };
407
408 KBLIST_DEFINE(wxFCEList, wxFontCacheEntry);
409
410 class wxFontCache
411 {
412 public:
413 wxFont & GetFont(int family, int size, int style, int weight,
414 bool underline);
415 wxFont & GetFont(wxLayoutStyleInfo const &si)
416 {
417 return GetFont(si.family, si.size, si.style, si.weight,
418 si.underline != 0);
419 }
420 private:
421 wxFCEList m_FontList;
422 };
423
424 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
425
426 wxLayoutObjectCmd
427
428 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
429 /** This class implements a wxLayoutObject holding style change commands.
430 */
431 class wxLayoutObjectCmd : public wxLayoutObject
432 {
433 public:
434 virtual wxLayoutObjectType GetType(void) const { return WXLO_TYPE_CMD; }
435 virtual void Layout(wxDC &dc, wxLayoutList *llist);
436 virtual void Draw(wxDC &dc, wxPoint const &coords,
437 wxLayoutList *wxllist,
438 CoordType begin = -1,
439 CoordType end = -1);
440 wxLayoutObjectCmd(int family = -1,
441 int size = -1,
442 int style = -1,
443 int weight = -1,
444 int underline = -1,
445 wxColour *fg = NULL,
446 wxColour *bg = NULL);
447 wxLayoutObjectCmd(const wxLayoutStyleInfo &si);
448 ~wxLayoutObjectCmd();
449 /** Stores the current style in the styleinfo structure */
450 wxLayoutStyleInfo * GetStyle(void) const;
451 /** Makes a copy of this object.
452 */
453 virtual wxLayoutObject *Copy(void);
454 virtual void Write(wxString &ostr);
455 static wxLayoutObjectCmd *Read(wxString &istr);
456 private:
457 wxLayoutStyleInfo *m_StyleInfo;
458 };
459
460 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
461
462 The wxLayoutLine object
463
464 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
465
466 /** This class represents a single line of objects to be displayed.
467 It knows its height and total size and whether it needs to be
468 redrawn or not.
469 It has pointers to its first and next line so it can automatically
470 update them as needed.
471 */
472 class wxLayoutLine
473 {
474 public:
475 /** Constructor.
476 @param prev pointer to previous line or NULL
477 @param next pointer to following line or NULL
478 @param llist pointer to layout list
479 */
480 wxLayoutLine(wxLayoutLine *prev, wxLayoutList *llist);
481 /** This function inserts a new object at cursor position xpos.
482 @param xpos where to insert new object
483 @param obj the object to insert
484 @return true if that xpos existed and the object was inserted
485 */
486 bool Insert(CoordType xpos, wxLayoutObject *obj);
487
488 /** This function inserts text at cursor position xpos.
489 @param xpos where to insert
490 @param text the text to insert
491 @return true if that xpos existed and the object was inserted
492 */
493 bool Insert(CoordType xpos, const wxString& text);
494
495 /** This function appends an object to the line.
496 @param obj the object to insert
497 */
498 void Append(wxLayoutObject * obj)
499 {
500 wxASSERT(obj);
501 m_ObjectList.push_back(obj);
502 m_Length += obj->GetLength();
503 }
504
505 /** This function prepends an object to the line. */
506 void Prepend(wxLayoutObject * obj)
507 {
508 wxASSERT(obj);
509 m_ObjectList.push_front(obj);
510 m_Length += obj->GetLength();
511 }
512
513 /** This function appens the next line to this, i.e. joins the two
514 lines into one.
515 */
516 void MergeNextLine(wxLayoutList *llist);
517
518 /** This function deletes npos cursor positions from position xpos.
519 @param xpos where to delete
520 @param npos how many positions
521 @return number of positions still to be deleted
522 */
523 CoordType Delete(CoordType xpos, CoordType npos);
524
525 /** This function breaks the line at a given cursor position.
526 @param xpos where to break it
527 @return pointer to the new line object replacing the old one
528 */
529 wxLayoutLine *Break(CoordType xpos, wxLayoutList *llist);
530
531 /** This function wraps the line: breaks it at a suitable point
532 and merges it with the next.
533 @param wrapmargin
534 @return TRUE if broken
535 */
536 bool Wrap(CoordType wrapmargin, wxLayoutList *llist);
537
538 /** Deletes the next word from this position, including leading
539 whitespace.
540 This function does not delete over font changes, i.e. a word
541 with formatting instructions in the middle of it is treated as
542 two (three actually!) words. In fact, if the cursor is on a non-text object, that
543 one is treated as a word.
544 @param xpos from where to delete
545 @return true if a word was deleted
546 */
547 bool DeleteWord(CoordType npos);
548
549 /** Finds a suitable position left to the given column to break the
550 line.
551 @param column we want to break the line to the left of this
552 @return column for breaking line or -1 if no suitable location found
553 */
554 CoordType GetWrapPosition(CoordType column);
555
556 /** Finds the object which covers the cursor position xpos in this
557 line.
558 @param xpos the column number
559 @param offset where to store the difference between xpos and
560 the object's head
561 @return iterator to the object or NULLIT
562 */
563 wxLayoutObjectList::iterator FindObject(CoordType xpos, CoordType
564 *offset) const ;
565
566 /** Finds the object which covers the screen position xpos in this
567 line.
568 @param dc the wxDC to use for calculations
569 @param llist the layout list to which this line belongs
570 @param xpos the screen x coordinate
571 @param offset where to store the difference between xpos and
572 the object's head
573 @return iterator to the object or NULLIT
574 */
575 wxLayoutObjectList::iterator FindObjectScreen(wxDC &dc,
576 wxLayoutList *llist,
577 CoordType xpos,
578 CoordType *offset,
579 bool *found = NULL) const ;
580
581 /** Finds text in this line.
582 @param needle the text to find
583 @param xpos the position where to start the search
584 @return the cursoor coord where it was found or -1
585 */
586 CoordType FindText(const wxString &needle, CoordType xpos = 0) const;
587
588 /** Get the first object in the list. This is used by the wxlparser
589 functions to export the list.
590 @return iterator to the first object
591 */
592 wxLayoutObjectList::iterator GetFirstObject(void) const
593 {
594 return m_ObjectList.begin();
595 }
596
597 /** Get the last object in the list.
598 */
599 wxLayoutObjectList::iterator GetLastObject(void) const
600 {
601 return m_ObjectList.tail();
602 }
603
604 /** Deletes this line, returns pointer to next line.
605 @param update If true, update all following lines.
606 */
607 wxLayoutLine *DeleteLine(bool update, wxLayoutList *llist);
608
609 /**@name Cursor Management */
610 //@{
611 /** Return the line number of this line.
612 @return the line number
613 */
614 inline CoordType GetLineNumber(void) const { return m_LineNumber; }
615 /** Return the length of the line.
616 @return line lenght in cursor positions
617 */
618 inline CoordType GetLength(void) const { return m_Length; }
619 //@}
620
621 /**@name Drawing and Layout */
622 //@{
623 /** Draws the line on a wxDC.
624 @param dc the wxDC to draw on
625 @param llist the wxLayoutList
626 @param offset an optional offset to shift printout
627 */
628 void Draw(wxDC &dc,
629 wxLayoutList *llist,
630 const wxPoint &offset = wxPoint(0,0)) const;
631
632 /** Recalculates the positions of objects and the height of the
633 line.
634 @param dc the wxDC to draw on
635 @param llist th e wxLayoutList
636 @param cursorPos if not NULL, set cursor screen position in there
637 @param cursorSize if not cursorPos != NULL, set cursor size in there
638 @param cursorStyle if non NULL where to store styleinfo for cursor pos
639 @param cx if cursorPos != NULL, the cursor x position
640 @param suppressStyleUpdate FALSe normally, only to suppress updating of m_StyleInfo
641 */
642 void Layout(wxDC &dc,
643 wxLayoutList *llist,
644 wxPoint *cursorPos = NULL,
645 wxPoint *cursorSize = NULL,
646 wxLayoutStyleInfo *cursorStyle = NULL,
647 int cx = 0,
648 bool suppressStyleUpdate = FALSE);
649 /** This function finds an object belonging to a given cursor
650 position. It assumes that Layout() has been called before.
651 @param dc the wxDC to use for calculations
652 @param xpos screen x position
653 @param found if non-NULL set to false if we return the last
654 object before the cursor, to true if we really have an object
655 for that position
656 @return pointer to the object
657 */
658 wxLayoutObject * FindObjectScreen(wxDC &dc,
659 CoordType xpos,
660 bool *found = NULL);
661 /** This sets the style info for the beginning of this line.
662 @param si styleinfo structure
663 */
664 void ApplyStyle(const wxLayoutStyleInfo &si)
665 { m_StyleInfo = si; }
666
667 //@}
668
669 /**@name List traversal */
670 //@{
671 /// Returns pointer to next line.
672 wxLayoutLine *GetNextLine(void) const { return m_Next; }
673 /// Returns pointer to previous line.
674 wxLayoutLine *GetPreviousLine(void) const { return m_Previous; }
675 /// Sets the link to the next line.
676 void SetNext(wxLayoutLine *next)
677 { m_Next = next; if(next) next->m_Previous = this; }
678 /// Sets the link to the previous line.
679 void SetPrevious(wxLayoutLine *previous)
680 { m_Previous = previous; if(previous) previous->m_Next = this; }
681 //@}
682
683 /// Returns the position of this line on the canvas.
684 wxPoint GetPosition(void) const { return m_Position; }
685 /// Returns the height of this line.
686 CoordType GetHeight(void) const { return m_Height; }
687 /// Returns the width of this line.
688 CoordType GetWidth(void) const { return m_Width; }
689 /// Recalculates the position of this line on the canvas.
690 wxPoint RecalculatePosition(wxLayoutList *llist);
691
692 /** Copies the contents of this line to another wxLayoutList
693 @param llist the wxLayoutList destination
694 @param from x cursor coordinate where to start
695 @param to x cursor coordinate where to stop, -1 for end of line
696 */
697 void Copy(wxLayoutList *llist,
698 CoordType from = 0,
699 CoordType to = -1);
700
701 #ifdef WXLAYOUT_DEBUG
702 void Debug(void) const;
703 #endif
704 wxLayoutStyleInfo const & GetStyleInfo() const { return m_StyleInfo; }
705
706 /// Returns dirty state
707 bool IsDirty(void) const { return m_Dirty; }
708 /** Marks this line as diry.
709 @param left xpos from where it is dirty or -1 for all
710 */
711 void MarkDirty(CoordType left = -1)
712 {
713 if ( left != -1 )
714 {
715 if ( m_updateLeft == -1 || left < m_updateLeft )
716 m_updateLeft = left;
717 }
718
719 m_Dirty = true;
720 if(m_Next) m_Next->MarkDirty();
721 }
722 /// Reset the dirty flag
723 void MarkClean() { m_Dirty = false; m_updateLeft = -1; }
724
725 private:
726 /// Destructor is private. Use DeleteLine() to remove it.
727 ~wxLayoutLine();
728
729 /**@name Functions to let the lines synchronise with each other. */
730 //@{
731 /** Sets the height of this line. Will mark following lines as
732 dirty.
733 @param height new height
734 */
735 void SetHeight(CoordType height, wxLayoutList *llist)
736 { m_Height = height; MarkDirty(); }
737
738 /** Updates the line numbers. */
739 void ReNumber(void);
740 //@}
741 private:
742 /// The line number.
743 CoordType m_LineNumber;
744 /// The line length in cursor positions.
745 CoordType m_Length;
746 /// The total height of the line.
747 CoordType m_Height;
748 /// The total width of the line on screen.
749 CoordType m_Width;
750 /// The baseline for drawing objects
751 CoordType m_BaseLine;
752 /// The position on the canvas.
753 wxPoint m_Position;
754 /// The list of objects
755 wxLayoutObjectList m_ObjectList;
756 /// Have we been changed since the last layout?
757 bool m_Dirty;
758 /// The coordinate of the left boundary of the update rectangle (if m_Dirty)
759 CoordType m_updateLeft;
760 /// Pointer to previous line if it exists.
761 wxLayoutLine *m_Previous;
762 /// Pointer to next line if it exists.
763 wxLayoutLine *m_Next;
764 /// A StyleInfo structure, holding the current settings.
765 wxLayoutStyleInfo m_StyleInfo;
766 /// Just to suppress gcc compiler warnings.
767 friend class dummy;
768 private:
769 wxLayoutLine(const wxLayoutLine &);
770 };
771
772
773 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
774
775 The wxLayoutList object
776
777 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
778 /** The wxLayoutList is a list of wxLayoutLine objects. It provides a
779 higher level of abstraction for the text and can generally be considered
780 as representing "the text".
781 */
782 class wxLayoutList
783 {
784 public:
785 /// Constructor.
786 wxLayoutList();
787 /// Destructor.
788 ~wxLayoutList();
789
790 #ifdef WXLAYOUT_USE_CARET
791 /// give us the pointer to the caret to use
792 void SetCaret(wxCaret *caret) { m_caret = caret; }
793 #endif // WXLAYOUT_USE_CARET
794
795 /// Clear the list.
796 void Clear(int family = wxROMAN,
797 int size=WXLO_DEFAULTFONTSIZE,
798 int style=wxNORMAL,
799 int weight=wxNORMAL,
800 int underline=0,
801 wxColour *fg=NULL,
802 wxColour *bg=NULL);
803 /// Empty: clear the list but leave font settings.
804 void Empty(void);
805
806 /** Enable or disable auto-formatting. Normally, while editing this
807 should be enabled which is the default. While
808 inserting/deleting lots of text, it makes sense to temporarily
809 disable this.
810 @param enable TRUE to enable, FALSE to disable
811 */
812 void SetAutoFormatting(bool enable = TRUE)
813 { m_AutoFormat = enable; }
814 /**@name Cursor Management */
815 //@{
816 /** Set new cursor position.
817 @param p new position
818 @return bool if it could be set
819 */
820 bool MoveCursorTo(wxPoint const &p);
821 /** Move cursor up or down.
822 @param n
823 @return bool if it could be moved
824 */
825 bool MoveCursorVertically(int n);
826 /** Move cursor left or right.
827 @param n = number of positions to move
828 @return bool if it could be moved
829 */
830 bool MoveCursorHorizontally(int n);
831 /** Move cursor to the left or right counting in words
832 @param n = number of positions in words
833 @param untilNext: puts the cursor at the start of the next word if true,
834 leaves it at the end of the current one otherwise
835 @return bool if it could be moved
836 */
837 bool MoveCursorWord(int n, bool untilNext = true);
838
839 /// Move cursor to end of line.
840 void MoveCursorToEndOfLine(void)
841 {
842 wxASSERT(m_CursorLine);
843 MoveCursorHorizontally(m_CursorLine->GetLength()-m_CursorPos.x);
844 }
845
846 /// Move cursor to the start of line.
847 void MoveCursorToBeginOfLine(void)
848 { MoveCursorHorizontally(-m_CursorPos.x); }
849
850 /// get the number of lines in the list
851 size_t GetNumLines() const { return m_numLines; }
852
853 /// Returns current cursor position.
854 const wxPoint &GetCursorPos(wxDC &dc) const { return m_CursorPos; }
855 const wxPoint &GetCursorPos() const { return m_CursorPos; }
856 wxLayoutLine * GetCursorLine(void) { return m_CursorLine; }
857
858 /// move cursor to the end of text
859 void MoveCursorToEnd(void)
860 {
861 MoveCursorTo(wxPoint(0, GetNumLines() - 1));
862 MoveCursorToEndOfLine();
863 }
864
865 //@}
866
867 /**@name Editing functions.
868 All of these functions return true on success and false on
869 failure. */
870 //@{
871 /// Insert text at current cursor position.
872 bool Insert(wxString const &text);
873 /// Insert some other object at current cursor position.
874 bool Insert(wxLayoutObject *obj);
875 /// Inserts objects at current cursor positions
876 bool Insert(wxLayoutList *llist);
877
878 /// Inserts a linebreak at current cursor position.
879 bool LineBreak(void);
880 /** Wraps the current line. Searches to the left of the cursor to
881 break the line. Does nothing if the cursor position is before
882 the break position parameter.
883 @param column the break position for the line, maximum length
884 @return true if line got broken
885 */
886 bool WrapLine(CoordType column);
887
888 /** Wraps the complete buffer.
889 @param column the break position for the line, maximum length
890 @return true if line got broken
891 */
892 bool WrapAll(CoordType column);
893 /** This function deletes npos cursor positions.
894 @param npos how many positions
895 @return true if everything got deleted
896 */
897 bool Delete(CoordType npos);
898
899 /** Delete the next n lines.
900 @param n how many lines to delete
901 @return how many it could not delete
902 */
903 int DeleteLines(int n);
904
905 /// Delete to end of line.
906 void DeleteToEndOfLine(void)
907 {
908 wxASSERT(m_CursorLine);
909 Delete(m_CursorLine->GetLength()-m_CursorPos.x);
910 }
911 /// Delete to begin of line.
912 void DeleteToBeginOfLine(void)
913 {
914 wxASSERT(m_CursorLine);
915 CoordType n = m_CursorPos.x;
916 #ifdef WXLAYOUT_DEBUG
917 wxASSERT(MoveCursorHorizontally(-n));
918 #else
919 MoveCursorHorizontally(-n);
920 #endif
921 Delete(n);
922 }
923
924 /** Delete the next word.
925 */
926 void DeleteWord(void)
927 {
928 wxASSERT(m_CursorLine);
929 m_CursorLine->DeleteWord(m_CursorPos.x);
930 }
931
932 //@}
933
934 /** Finds text in this list.
935 @param needle the text to find
936 @param cpos the position where to start the search
937 @return the cursor coord where it was found or (-1,-1)
938 */
939 wxPoint FindText(const wxString &needle, const wxPoint &cpos = wxPoint(0,0)) const;
940
941 /**@name Formatting options */
942 //@{
943 /// sets font parameters
944 void SetFont(int family, int size, int style,
945 int weight, int underline,
946 wxColour *fg,
947 wxColour *bg);
948 /// sets font parameters, colours by name
949 void SetFont(int family=-1, int size = -1, int style=-1,
950 int weight=-1, int underline = -1,
951 char const *fg = NULL,
952 char const *bg = NULL);
953 /// changes to the next larger font size
954 inline void SetFontLarger(void)
955 { SetFont(-1,(12*m_CurrentStyleInfo.size)/10); }
956 /// changes to the next smaller font size
957 inline void SetFontSmaller(void)
958 { SetFont(-1,(10*m_CurrentStyleInfo.size)/12); }
959
960 /// set font family
961 inline void SetFontFamily(int family) { SetFont(family); }
962 /// set font size
963 inline void SetFontSize(int size) { SetFont(-1,size); }
964 /// set font style
965 inline void SetFontStyle(int style) { SetFont(-1,-1,style); }
966 /// set font weight
967 inline void SetFontWeight(int weight) { SetFont(-1,-1,-1,weight); }
968 /// toggle underline flag
969 inline void SetFontUnderline(bool ul) { SetFont(-1,-1,-1,-1,(int)ul); }
970 /// set font colours by name
971 inline void SetFontColour(char const *fg, char const *bg = NULL)
972 { SetFont(-1,-1,-1,-1,-1,fg,bg); }
973 /// set font colours by colour
974 inline void SetFontColour(wxColour *fg, wxColour *bg = NULL)
975 { SetFont(-1,-1,-1,-1,-1,fg,bg); }
976
977 /**
978 Returns a pointer to the default settings.
979 This is only valid temporarily and should not be stored
980 anywhere.
981 @return the default settings of the list
982 */
983 wxLayoutStyleInfo &GetDefaultStyleInfo(void) { return m_DefaultStyleInfo ; }
984 wxLayoutStyleInfo &GetStyleInfo(void) { return m_CurrentStyleInfo ; }
985 const wxLayoutStyleInfo &GetStyleInfo(void) const { return m_CurrentStyleInfo ; }
986 const wxLayoutStyleInfo &GetCursorStyleInfo(void) const { return m_CursorStyleInfo ; }
987
988 /// is the current font underlined?
989 bool IsFontUnderlined() const { return GetCursorStyleInfo().underline != 0; }
990 /// is the current font bold?
991 bool IsFontBold() const { return GetCursorStyleInfo().weight == wxBOLD; }
992 /// is the current font italic?
993 bool IsFontItalic() const { return GetCursorStyleInfo().style == wxITALIC; }
994
995 /// set underline if it was off, turn it off if it was on
996 void ToggleFontUnderline()
997 { SetFontUnderline(!IsFontUnderlined()); }
998
999 /// make font bold if it was normal or make it normal if it was bold
1000 void ToggleFontWeight()
1001 { SetFontWeight(IsFontBold() ? wxNORMAL : wxBOLD); }
1002
1003 /// make font italic if it was normal or make it normal if it was italic
1004 void ToggleFontItalics()
1005 { SetFontStyle(IsFontItalic() ? wxNORMAL : wxITALIC); }
1006
1007 //@}
1008
1009 /**@name Drawing */
1010 //@{
1011 /** Draws the complete list on a wxDC.
1012 @param dc the wxDC to draw on
1013 @param offset an optional offset to shift printout
1014 @param top optional y coordinate where to start drawing
1015 @param bottom optional y coordinate where to stop drawing
1016 @param clipStrictly if set, do not draw objects which reach
1017 beyond "bottom". Set this when printing.
1018 */
1019 void Draw(wxDC &dc,
1020 const wxPoint &offset = wxPoint(0,0),
1021 CoordType top = -1, CoordType bottom = -1,
1022 bool clipStrictly = false);
1023
1024 /** Calculates new layout for the list, like Draw() but does not
1025 actually draw it.
1026 @param dc the wxDC to draw on
1027 @param bottom optional y coordinate where to stop calculating
1028 @param forceAll force re-layout of all lines
1029 @param cpos Can hold a cursorposition, and will be overwritten
1030 with the corresponding DC position.
1031 @param csize Will hold the cursor size relating to cpos.
1032 */
1033 void Layout(wxDC &dc, CoordType bottom = -1, bool forceAll = false,
1034 wxPoint *cpos = NULL,
1035 wxPoint *csize = NULL);
1036
1037 /** Ensure that the whole list will be recalculate on the next call
1038 to Layout() or Draw().
1039 @param redrawAll TRUE or FALSE to reset it
1040 */
1041 void ForceTotalLayout(bool redrawAll = TRUE)
1042 { m_ReLayoutAll = redrawAll; }
1043
1044 /** Returns the screen coordinates relating to a given cursor
1045 position and the size of the cursor at that position.
1046 @param dc for which to calculate it
1047 @param cpos Cursor position to look for.
1048 @param csize If non-NULL, will be set to the cursor size.
1049 @return The cursor position on the DC.
1050 */
1051 wxPoint GetScreenPos(wxDC &dc, const wxPoint &cpos, wxPoint *csize = NULL);
1052
1053 /** Calculates new sizes for everything in the list, like Layout()
1054 but this is needed after the list got changed.
1055 @param dc the wxDC to draw on
1056 @param bottom optional y coordinate where to stop calculating
1057 */
1058 void Recalculate(wxDC &dc, CoordType bottom = -1);
1059
1060 /** Returns the size of the list in screen coordinates.
1061 The return value only makes sense after the list has been
1062 drawn.
1063 @return a wxPoint holding the maximal x/y coordinates used for
1064 drawing
1065 */
1066 wxPoint GetSize(void) const;
1067
1068 /** Returns the cursor position on the screen.
1069 */
1070 wxPoint GetCursorScreenPos(void) const;
1071
1072 /** Draws the cursor.
1073 @param active If true, draw a bold cursor to mark window as
1074 active.
1075 @param translate optional translation of cursor coords on screen
1076 */
1077 void DrawCursor(wxDC &dc,
1078 bool active = true,
1079 const wxPoint & translate = wxPoint(0,0));
1080
1081 /** This function finds an object belonging to a given screen
1082 position. It assumes that Layout() has been called before.
1083 @param pos screen position
1084 @param cursorPos if non NULL, store cursor position in there
1085 @param found if used, set this to true if we really found an
1086 object, to false if we had to take the object near to it
1087 @return pointer to the object
1088 */
1089 wxLayoutObject * FindObjectScreen(wxDC &dc,
1090 wxPoint const pos,
1091 wxPoint *cursorPos = NULL,
1092 bool *found = NULL);
1093
1094 /** Called by the objects to update the update rectangle.
1095 @param x horizontal coordinate to include in rectangle
1096 @param y vertical coordinate to include in rectangle
1097 */
1098 void SetUpdateRect(CoordType x, CoordType y);
1099 /** Called by the objects to update the update rectangle.
1100 @param p a point to include in it
1101 */
1102 void SetUpdateRect(const wxPoint &p)
1103 { SetUpdateRect(p.x,p.y); }
1104 /// adds the cursor position to the update rectangle
1105 void AddCursorPosToUpdateRect()
1106 {
1107 #ifndef WXLAYOUT_USE_CARET
1108 SetUpdateRect(m_CursorScreenPos);
1109 SetUpdateRect(m_CursorScreenPos+m_CursorSize);
1110 //#else - the caret will take care of refreshing itself
1111 #endif // !WXLAYOUT_USE_CARET
1112 }
1113 /// Invalidates the update rectangle.
1114 void InvalidateUpdateRect(void) { m_UpdateRectValid = false; }
1115 /// Returns the update rectangle.
1116 const wxRect *GetUpdateRect(void) const { return &m_UpdateRect; }
1117 //@}
1118
1119 /// get the current cursor size
1120 const wxPoint& GetCursorSize() const { return m_CursorSize; }
1121
1122 /**@name For exporting one object after another. */
1123 //@{
1124 /** Returns a pointer to the first line in the list. */
1125 wxLayoutLine *GetFirstLine(void)
1126 {
1127 wxASSERT(m_FirstLine);
1128 return m_FirstLine;
1129 }
1130 //@}
1131
1132 /// Begin selecting text
1133 void StartSelection(const wxPoint& cpos = wxPoint(-1,-1),
1134 const wxPoint& spos = wxPoint(-1,-1));
1135 // Continue selecting text
1136 void ContinueSelection(const wxPoint& cpos = wxPoint(-1,-1),
1137 const wxPoint& spos = wxPoint(-1,-1));
1138 /// End selecting text.
1139 void EndSelection(const wxPoint& cpos = wxPoint(-1,-1),
1140 const wxPoint& spos = wxPoint(-1,-1));
1141 /// Discard the current selection
1142 void DiscardSelection();
1143 /// Are we still selecting text?
1144 bool IsSelecting(void) const;
1145 /// Is the given point (text coords) selected?
1146 bool IsSelected(const wxPoint &cursor) const;
1147 /// Do we have a non null selection?
1148 bool HasSelection() const
1149 { return m_Selection.m_valid || m_Selection.m_selecting; }
1150
1151 /** Return the selection as a wxLayoutList.
1152 @param invalidate if true, the selection will be invalidated after this and can no longer be used.
1153 @return Another layout list object holding the selection, must be freed by caller
1154 */
1155 wxLayoutList *GetSelection(class wxLayoutDataObject *wxldo = NULL, bool invalidate = TRUE);
1156 /// Delete selected bit
1157 void DeleteSelection(void);
1158
1159 wxLayoutList *Copy(const wxPoint &from = wxPoint(0,0),
1160 const wxPoint &to = wxPoint(-1,-1));
1161
1162 /// starts highlighting of text for selections
1163 void StartHighlighting(wxDC &dc);
1164 /// ends highlighting of text for selections
1165 void EndHighlighting(wxDC &dc);
1166
1167 /** Tests whether this layout line is selected and needs
1168 highlighting.
1169 @param line to test for
1170 @param from set to first cursorpos to be highlighted (for returncode == -1)
1171 @param to set to last cursorpos to be highlighted (for returncode == -1)
1172 @return 0 = not selected, 1 = fully selected, -1 = partially
1173 selected
1174
1175 */
1176 int IsSelected(const wxLayoutLine *line, CoordType *from, CoordType *to);
1177
1178 void ApplyStyle(wxLayoutStyleInfo const &si, wxDC &dc);
1179 #ifdef WXLAYOUT_DEBUG
1180 void Debug(void);
1181 #endif
1182
1183 // for wxLayoutLine usage only
1184 void IncNumLines() { m_numLines++; }
1185 void DecNumLines() { m_numLines--; }
1186
1187 /// get the line by number
1188 wxLayoutLine *GetLine(CoordType index) const;
1189
1190 /** Reads objects from a string and inserts them. Returns NULL if
1191 string is empty or a linebreak was found.
1192 @param istr stream to read from, will bee changed
1193 */
1194 void Read(wxString &istr);
1195
1196 private:
1197 /// Clear the list.
1198 void InternalClear(void);
1199
1200 /// The list of lines.
1201 wxLayoutLine *m_FirstLine;
1202 /// The number of lines in the list (store instead recalculating for speed)
1203 size_t m_numLines;
1204
1205 /// The update rectangle which needs to be refreshed:
1206 wxRect m_UpdateRect;
1207 /// Is the update rectangle valid?
1208 bool m_UpdateRectValid;
1209
1210 /// Shall we auto-format?
1211 bool m_AutoFormat;
1212 /// Shall we re-layout everything?
1213 bool m_ReLayoutAll;
1214 /**@name Cursor Management */
1215 //@{
1216 /// Where the text cursor (column,line) is.
1217 wxPoint m_CursorPos;
1218 /// Where the cursor should be drawn.
1219 wxPoint m_CursorScreenPos;
1220 /// The line where the cursor is.
1221 wxLayoutLine *m_CursorLine;
1222 /// The size of the cursor.
1223 wxPoint m_CursorSize;
1224 /// Has the cursor moved (is m_CursorScreenPos up to date)?
1225 bool m_movedCursor;
1226 #ifdef WXLAYOUT_USE_CARET
1227 /// the caret
1228 wxCaret *m_caret;
1229 #endif // WXLAYOUT_USE_CARET
1230 //@}
1231
1232 /// selection.state and begin/end coordinates
1233 struct Selection
1234 {
1235 Selection() { m_valid = m_selecting = m_discarded = false; }
1236
1237 bool m_valid;
1238 bool m_selecting;
1239 bool m_discarded; // may be TRUE only until the next redraw
1240
1241 // returns true if we already have the screen coordinates of the
1242 // selection start and end
1243 bool HasValidScreenCoords() const
1244 { return m_ScreenA.x != -1 && m_ScreenB.x != -1; }
1245
1246 // the start and end of the selection coordinates in pixels
1247 wxPoint m_ScreenA, m_ScreenB;
1248
1249 // these coordinates are in text positions, not in pixels
1250 wxPoint m_CursorA, m_CursorB;
1251 } m_Selection;
1252 /** @name Font parameters. */
1253 //@{
1254 /// this object manages the fonts for us
1255 wxFontCache m_FontCache;
1256 /// the default setting:
1257 wxLayoutStyleInfo m_DefaultStyleInfo;
1258 /// the current setting:
1259 wxLayoutStyleInfo m_CurrentStyleInfo;
1260 /// the current setting:
1261 wxLayoutStyleInfo m_CursorStyleInfo;
1262 //@}
1263 };
1264
1265 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
1266
1267 The wxLayoutDataObject for exporting data to the clipboard in our
1268 own format.
1269
1270 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1271 class wxLayoutDataObject : public wxCustomDataObject
1272 {
1273 public:
1274 wxLayoutDataObject()
1275 {
1276 SetFormat(wxT("application/wxlayoutlist"));
1277 }
1278
1279 // type safe wrappers
1280 void SetLayoutData(const wxString& text)
1281 { SetData(text.length() + 1, text.c_str()); }
1282 const char *GetLayoutData() const { return (const char *)GetData(); }
1283 };
1284
1285 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
1286
1287 The wxLayoutPrintout object for printing within the wxWindows print
1288 framework.
1289
1290 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1291 /** This class implements a wxPrintout for printing a wxLayoutList within
1292 the wxWindows printing framework.
1293 */
1294 class wxLayoutPrintout: public wxPrintout
1295 {
1296 public:
1297 /** Constructor.
1298 @param llist pointer to the wxLayoutList to be printed
1299 @param title title for PS file or windows
1300 */
1301 wxLayoutPrintout(wxLayoutList *llist,
1302 wxString const & title =
1303 "wxLayout Printout");
1304 /// Destructor.
1305 ~wxLayoutPrintout();
1306
1307 /** Function which prints the n-th page.
1308 @param page the page number to print
1309 @return bool true if we are not at end of document yet
1310 */
1311 bool OnPrintPage(int page);
1312 /** Checks whether page exists in document.
1313 @param page number of page
1314 @return true if page exists
1315 */
1316 bool HasPage(int page);
1317
1318 /** Gets called from wxWindows to find out which pages are existing.
1319 I'm not totally sure about the parameters though.
1320 @param minPage the first page in the document
1321 @param maxPage the last page in the document
1322 @param selPageFrom the first page to be printed
1323 @param selPageTo the last page to be printed
1324 */
1325 void GetPageInfo(int *minPage, int *maxPage,
1326 int *selPageFrom, int *selPageTo);
1327 protected:
1328 /** This little function scales the DC so that the printout has
1329 roughly the same size as the output on screen.
1330 @param dc the wxDC to scale
1331 @return the scale that was applied
1332 */
1333 float ScaleDC(wxDC *dc);
1334
1335 /* no longer used
1336 virtual void DrawHeader(wxDC &dc, wxPoint topleft, wxPoint bottomright, int pageno);
1337 */
1338 private:
1339 /// The list to print.
1340 wxLayoutList *m_llist;
1341 /// Title for PS file or window.
1342 wxString m_title;
1343 /// The real paper size.
1344 int m_PageHeight, m_PageWidth;
1345 /// How much we actually print per page.
1346 int m_PrintoutHeight;
1347 /// How many pages we need to print.
1348 int m_NumOfPages;
1349 /// Top left corner where we start printing.
1350 wxPoint m_Offset;
1351 };
1352
1353
1354 #endif // WXLLIST_H