]> git.saurik.com Git - wxWidgets.git/blobdiff - samples/richedit/wxllist.h
fix for wxExecute(subprocess which produces a lot of output) bug
[wxWidgets.git] / samples / richedit / wxllist.h
index 5bc7fbae19ba4a3ca72de5bdb195bf8761fcc7dd..0669c2580422434db023a889eab78945a4f63a8a 100644 (file)
@@ -1,7 +1,7 @@
 /*-*- c++ -*-********************************************************
  * wxLayoutList.h - a formatted text rendering engine for wxWindows *
  *                                                                  *
- * (C) 1999 by Karsten Ballüder (Ballueder@usa.net)                 *
+ * (C) 1999-2000 by Karsten Ballüder (ballueder@gmx.net)            *
  *                                                                  *
  * $Id$
  *******************************************************************/
 
 #include   "kbList.h"
 
-#include   "wx/wx.h"
-#include   "wx/print.h"
-#include   "wx/printdlg.h"
-#include   "wx/generic/printps.h"
-#include   "wx/generic/prntdlgg.h"
-#include   "wx/dataobj.h"
+#include   <wx/wx.h>
+#include   <wx/print.h>
+#include   <wx/printdlg.h>
+#include   <wx/generic/printps.h>
+#include   <wx/generic/prntdlgg.h>
+#include   <wx/dataobj.h>
 
 // skip the following defines if embedded in M application
 #ifndef   M_BASEDIR
 #   define WXMENU_LAYOUT_LCLICK     1111
 #   define WXMENU_LAYOUT_RCLICK     1112
 #   define WXMENU_LAYOUT_DBLCLICK   1113
+#else // for Mahogany only
+#   include "MObject.h"
 #endif
 
 // use the wxWindows caret class instead of home grown cursor whenever possible
 #ifdef __WXMSW__
-    #undef WXLAYOUT_USE_CARET
-    #define WXLAYOUT_USE_CARET 1
+#   undef WXLAYOUT_USE_CARET
+#   define WXLAYOUT_USE_CARET 1
 #endif // __WXMSW__
 
-// do not enable debug mode within Mahogany
-#if defined(__WXDEBUG__)  && ! defined(M_BASEDIR)
+// do not enable debug mode within Mahogany unless in debug mode
+#if defined(__WXDEBUG__) && (( ! defined(M_BASEDIR) )|| defined(DEBUG))
 #   define   WXLAYOUT_DEBUG
 #endif
 
 #ifdef WXLAYOUT_DEBUG
 #   define WXLO_TRACE(x)   wxLogDebug(x)
+// activate profiling: #   define WXLO_PROFILE
 #else
 #   define WXLO_TRACE(x)
 #endif
 
+/* Some profiling code: */
+#if defined (WXLO_PROFILE)
+#include <sys/time.h>
+#include <unistd.h>
+
+#   define WXLO_TIMER_DEFINE(x)    static struct timeval  x
+#   define WXLO_TIMER_START(x)     gettimeofday(&x,NULL)
+#   define WXLO_TIMER_STOP(x)      { struct timeval y; \
+                                gettimeofday(&y,NULL); \
+                                x.tv_sec -= y.tv_sec; x.tv_usec -= y.tv_usec; }
+#   define   WXLO_TIMER_PRINT(x)   wxLogDebug("Timer " #x " elapsed: %ld", \
+                                         (long)(x.tv_sec * -1000 - x.tv_usec));
+#else
+#   define   WXLO_TIMER_DEFINE(x)
+#   define   WXLO_TIMER_START(x)
+#   define   WXLO_TIMER_STOP(x)
+#   define   WXLO_TIMER_PRINT(x)
+#endif
+
+
 #define WXLO_DEBUG_URECT 0
 
 #ifndef WXLO_DEFAULTFONTSIZE
@@ -69,7 +92,9 @@ enum wxLayoutObjectType
    /// command object, containing font or colour changes
    WXLO_TYPE_CMD,
    /// icon object, any kind of image
-   WXLO_TYPE_ICON
+   WXLO_TYPE_ICON,
+   /// a linebreak, does not exist as an object
+   WXLO_TYPE_LINEBREAK
 };
 
 /// Type used for coordinates in drawing. Must be signed.
@@ -96,6 +121,9 @@ class WXDLLEXPORT wxFont;
     its size.
 */
 class wxLayoutObject
+#ifdef M_BASEDIR
+   : public MObject
+#endif
 {
 public:
    /** This structure can be used to contain data associated with the
@@ -166,7 +194,7 @@ public:
    virtual ~wxLayoutObject() { if(m_UserData) m_UserData->DecRef(); }
 
 #ifdef WXLAYOUT_DEBUG
-   virtual void Debug(void);
+   virtual wxString DebugDump(void) const;
 #endif
 
    /** Tells the object about some user data. This data is associated
@@ -203,9 +231,16 @@ public:
    */
    static wxLayoutObject *Read(wxString &istr);
    //@}
+
+   /// returns TRUE if the object is shown on the screen (i.e. not cmd object)
+   bool IsVisibleObject() const { return GetType() != WXLO_TYPE_CMD; }
+
 protected:
    /// optional data for application's use
    UserData *m_UserData;
+#if defined (M_BASEDIR) && defined (DEBUG)
+   MOBJECT_NAME(wxLayoutObject)
+#endif
 };
 
 /// Define a list type of wxLayoutObject pointers.
@@ -214,7 +249,7 @@ KBLIST_DEFINE(wxLayoutObjectList, wxLayoutObject);
 /// An illegal iterator to save typing.
 #define NULLIT (wxLayoutObjectList::iterator(NULL))
 /// The iterator type.
-#define wxLOiterator   wxLayoutObjectList::iterator
+typedef wxLayoutObjectList::iterator wxLOiterator;
 
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 
@@ -254,7 +289,7 @@ public:
    static wxLayoutObjectText *Read(wxString &istr);
 
 #ifdef WXLAYOUT_DEBUG
-   virtual void Debug(void);
+   virtual wxString DebugDump(void) const;
 #endif
 
    virtual CoordType GetLength(void) const { return strlen(m_Text.c_str()); }
@@ -316,8 +351,7 @@ private:
    wxBitmap *m_Icon;
 };
 
-/** This structure holds all formatting information. Members which are
-    undefined (for a CmdObject this means: no change), are set to -1.
+/** This structure holds all formatting information.
 */
 struct wxLayoutStyleInfo
 {
@@ -328,11 +362,10 @@ struct wxLayoutStyleInfo
                      int iul = -1,
                      wxColour *fg = NULL,
                      wxColour *bg = NULL);
-   wxColour & GetBGColour()
-      {
-         return m_bg;
-      }
    wxLayoutStyleInfo & operator=(const wxLayoutStyleInfo &right);
+
+   wxColour & GetBGColour() { return m_bg; }
+
    /// Font change parameters.
    int  size, family, style, weight, underline;
    /// Colours
@@ -340,7 +373,7 @@ struct wxLayoutStyleInfo
    int m_fg_valid, m_bg_valid; // bool, but must be int!
 };
 
-
+/// a cached font
 class wxFontCacheEntry
 {
 public:
@@ -366,6 +399,8 @@ public:
       }
 private:
    wxFont *m_Font;
+
+   // VZ: I wonder why it doesn't use wxLayoutStyleInfo instead of those?
    int  m_Family, m_Size, m_Style, m_Weight;
    bool m_Underline;
 };
@@ -409,6 +444,7 @@ public:
                      int underline = -1,
                      wxColour *fg = NULL,
                      wxColour *bg = NULL);
+   wxLayoutObjectCmd(const wxLayoutStyleInfo &si);
    ~wxLayoutObjectCmd();
    /** Stores the current style in the styleinfo structure */
    wxLayoutStyleInfo * GetStyle(void) const;
@@ -462,11 +498,18 @@ public:
    void Append(wxLayoutObject * obj)
       {
          wxASSERT(obj);
-
          m_ObjectList.push_back(obj);
          m_Length += obj->GetLength();
       }
 
+   /** This function prepends an object to the line. */
+   void Prepend(wxLayoutObject * obj)
+      {
+         wxASSERT(obj);
+         m_ObjectList.push_front(obj);
+         m_Length += obj->GetLength();
+      }
+       
    /** This function appens the next line to this, i.e. joins the two
        lines into one.
    */
@@ -485,6 +528,13 @@ public:
    */
    wxLayoutLine *Break(CoordType xpos, wxLayoutList *llist);
 
+   /** This function wraps the line: breaks it at  a suitable point
+       and merges it with the next.
+       @param wrapmargin
+       @return TRUE if broken
+   */
+   bool Wrap(CoordType wrapmargin, wxLayoutList *llist);
+   
    /** Deletes the next word from this position, including leading
        whitespace.
        This function does not delete over font changes, i.e. a word
@@ -516,12 +566,14 @@ public:
    /** Finds the object which covers the screen position xpos in this
        line.
        @param dc the wxDC to use for calculations
+       @param llist the layout list to which this line belongs
        @param xpos the screen x coordinate
        @param offset where to store the difference between xpos and
        the object's head
        @return iterator to the object or NULLIT
    */
    wxLayoutObjectList::iterator FindObjectScreen(wxDC &dc,
+                                                 wxLayoutList *llist,
                                                  CoordType xpos,
                                                  CoordType *offset,
                                                  bool *found = NULL) const ;
@@ -537,11 +589,18 @@ public:
        functions to export the list.
        @return iterator to the first object
    */
-   wxLayoutObjectList::iterator GetFirstObject(void)
+   wxLayoutObjectList::iterator GetFirstObject(void) const
       {
          return m_ObjectList.begin();
       }
 
+   /** Get the last object in the list.
+    */
+   wxLayoutObjectList::iterator GetLastObject(void) const
+      {
+         return m_ObjectList.tail();
+      }
+
    /** Deletes this line, returns pointer to next line.
        @param update If true, update all following lines.
    */
@@ -576,6 +635,7 @@ public:
        @param llist th   e wxLayoutList
        @param cursorPos if not NULL, set cursor screen position in there
        @param cursorSize if not cursorPos != NULL, set cursor size in there
+       @param cursorStyle if non NULL where to store styleinfo for cursor pos
        @param cx if cursorPos != NULL, the cursor x position
        @param suppressStyleUpdate FALSe normally, only to suppress updating of m_StyleInfo
    */
@@ -583,6 +643,7 @@ public:
                wxLayoutList *llist,
                wxPoint *cursorPos = NULL,
                wxPoint *cursorSize = NULL,
+               wxLayoutStyleInfo *cursorStyle = NULL,
                int cx = 0,
                bool suppressStyleUpdate = FALSE);
    /** This function finds an object belonging to a given cursor
@@ -594,13 +655,14 @@ public:
        for that position
        @return pointer to the object
    */
-   wxLayoutObject * FindObjectScreen(wxDC &dc, CoordType xpos, bool
-                                     *found = NULL);
+   wxLayoutObject * FindObjectScreen(wxDC &dc,
+                                     CoordType xpos,
+                                     bool *found = NULL);
    /** This sets the style info for the beginning of this line.
        @param si styleinfo structure
     */
    void ApplyStyle(const wxLayoutStyleInfo &si)
-      {   m_StyleInfo = si; }
+      { m_StyleInfo = si; }
 
    //@}
 
@@ -624,15 +686,6 @@ public:
    CoordType GetHeight(void) const { return m_Height; }
    /// Returns the width of this line.
    CoordType GetWidth(void) const { return m_Width; }
-   /** This will recalculate the position and size of this line.
-       If called recursively it will abort if the position of an
-       object is unchanged, assuming that none of the following
-       objects need to move.
-       @param recurse if greater 0 then it will be used as the
-       minimum(!) recursion level, continue with all lines till the end of
-       the list or until the coordinates no longer changed.
-   */
-   void RecalculatePositions(int recurse, wxLayoutList *llist);
    /// Recalculates the position of this line on the canvas.
    wxPoint RecalculatePosition(wxLayoutList *llist);
 
@@ -646,7 +699,7 @@ public:
              CoordType to = -1);
 
 #ifdef WXLAYOUT_DEBUG
-   void Debug(void);
+   void Debug(void) const;
 #endif
    wxLayoutStyleInfo const & GetStyleInfo() const { return m_StyleInfo; }
 
@@ -664,11 +717,8 @@ public:
       }
 
       m_Dirty = true;
+      if(m_Next) m_Next->MarkDirty();
    }
-   /** Marks the following lines as dirty.
-       @param recurse if -1 recurse to end of list, otherwise depth of recursion.
-   */
-   void MarkNextDirty(int recurse = 0);
    /// Reset the dirty flag
    void MarkClean() { m_Dirty = false; m_updateLeft = -1; }
 
@@ -683,17 +733,10 @@ private:
        @param height new height
    */
    void SetHeight(CoordType height, wxLayoutList *llist)
-      { m_Height = height; RecalculatePositions(true, llist); }
+      { m_Height = height; MarkDirty(); }
 
-   /** Moves the linenumbers one on, because a line has been inserted
-       or deleted.
-       @param delta either +1 or -1
-    */
-   void MoveLines(int delta)
-      {
-         m_LineNumber += delta;
-         if(m_Next) m_Next->MoveLines(delta);
-      }
+   /** Updates the line numbers. */
+   void ReNumber(void);
    //@}
 private:
    /// The line number.
@@ -760,6 +803,14 @@ public:
    /// Empty: clear the list but leave font settings.
    void Empty(void);
 
+   /** Enable or disable auto-formatting. Normally, while editing this 
+       should be enabled which is the default. While
+       inserting/deleting lots of text, it makes sense to temporarily
+       disable this.
+       @param enable TRUE to enable, FALSE to disable
+   */
+   void SetAutoFormatting(bool enable = TRUE)
+      { m_AutoFormat = enable; }
    /**@name Cursor Management */
    //@{
    /** Set new cursor position.
@@ -779,9 +830,11 @@ public:
    bool MoveCursorHorizontally(int n);
    /** Move cursor to the left or right counting in words
        @param n = number of positions in words
+       @param untilNext: puts the cursor at the start of the next word if true,
+              leaves it at the end of the current one otherwise
        @return bool if it could be moved
    */
-   bool MoveCursorWord(int n);
+   bool MoveCursorWord(int n, bool untilNext = true);
 
    /// Move cursor to end of line.
    void MoveCursorToEndOfLine(void)
@@ -790,13 +843,24 @@ public:
          MoveCursorHorizontally(m_CursorLine->GetLength()-m_CursorPos.x);
       }
 
-   /// Move cursor to begin of line.
+   /// Move cursor to the start of line.
    void MoveCursorToBeginOfLine(void)
       { MoveCursorHorizontally(-m_CursorPos.x); }
 
+   /// get the number of lines in the list
+   size_t GetNumLines() const { return m_numLines; }
+
    /// Returns current cursor position.
    const wxPoint &GetCursorPos(wxDC &dc) const { return m_CursorPos; }
    const wxPoint &GetCursorPos() const { return m_CursorPos; }
+   wxLayoutLine * GetCursorLine(void) { return m_CursorLine; }
+   
+   /// move cursor to the end of text
+   void MoveCursorToEnd(void)
+   {
+      MoveCursorTo(wxPoint(0, GetNumLines() - 1));
+      MoveCursorToEndOfLine();
+   }
 
    //@}
 
@@ -820,6 +884,12 @@ public:
        @return true if line got broken
    */
    bool WrapLine(CoordType column);
+
+   /** Wraps the complete buffer.
+       @param column the break position for the line, maximum length
+       @return true if line got broken
+   */
+   bool WrapAll(CoordType column);
    /** This function deletes npos cursor positions.
        @param npos how many positions
        @return true if everything got deleted
@@ -904,7 +974,6 @@ public:
    inline void SetFontColour(wxColour *fg, wxColour *bg = NULL)
       { SetFont(-1,-1,-1,-1,-1,fg,bg); }
 
-
    /**
       Returns a pointer to the default settings.
       This is only valid temporarily and should not be stored
@@ -913,6 +982,28 @@ public:
    */
    wxLayoutStyleInfo &GetDefaultStyleInfo(void) { return m_DefaultStyleInfo ; }
    wxLayoutStyleInfo &GetStyleInfo(void) { return m_CurrentStyleInfo ; }
+   const wxLayoutStyleInfo &GetStyleInfo(void) const { return m_CurrentStyleInfo ; }
+   const wxLayoutStyleInfo &GetCursorStyleInfo(void) const { return m_CursorStyleInfo ; }
+
+   /// is the current font underlined?
+   bool IsFontUnderlined() const { return GetCursorStyleInfo().underline != 0; }
+   /// is the current font bold?
+   bool IsFontBold() const { return GetCursorStyleInfo().weight == wxBOLD; }
+   /// is the current font italic?
+   bool IsFontItalic() const { return GetCursorStyleInfo().style == wxITALIC; }
+
+   /// set underline if it was off, turn it off if it was on
+   void ToggleFontUnderline()
+      { SetFontUnderline(!IsFontUnderlined()); }
+
+   /// make font bold if it was normal or make it normal if it was bold
+   void ToggleFontWeight()
+      { SetFontWeight(IsFontBold() ? wxNORMAL : wxBOLD); }
+
+   /// make font italic if it was normal or make it normal if it was italic
+   void ToggleFontItalics()
+      { SetFontStyle(IsFontItalic() ? wxNORMAL : wxITALIC); }
+
    //@}
 
    /**@name Drawing */
@@ -922,18 +1013,42 @@ public:
        @param offset an optional offset to shift printout
        @param top optional y coordinate where to start drawing
        @param bottom optional y coordinate where to stop drawing
+       @param clipStrictly if set, do not draw objects which reach
+       beyond "bottom". Set this when printing.
    */
    void Draw(wxDC &dc,
              const wxPoint &offset = wxPoint(0,0),
-             CoordType top = -1, CoordType bottom = -1);
+             CoordType top = -1, CoordType bottom = -1,
+             bool clipStrictly = false);
 
    /** Calculates new layout for the list, like Draw() but does not
        actually draw it.
        @param dc the wxDC to draw on
        @param bottom optional y coordinate where to stop calculating
        @param forceAll force re-layout of all lines
+       @param cpos Can hold a cursorposition, and will be overwritten
+       with the corresponding DC position.
+       @param csize Will hold the cursor size relating to cpos.
    */
-   void Layout(wxDC &dc, CoordType bottom = -1, bool forceAll = false);
+   void Layout(wxDC &dc, CoordType bottom = -1, bool forceAll = false,
+               wxPoint *cpos = NULL,
+               wxPoint *csize = NULL);
+
+   /** Ensure that the whole list will be recalculate on the next call 
+       to Layout() or Draw().
+       @param redrawAll TRUE or FALSE to reset it
+   */
+   void ForceTotalLayout(bool redrawAll = TRUE)
+      { m_ReLayoutAll = redrawAll; }
+   
+   /** Returns the screen coordinates relating to a given cursor
+       position and the size of the cursor at that position.
+       @param dc for which to calculate it
+       @param cpos Cursor position to look for.
+       @param csize If non-NULL, will be set to the cursor size.
+       @return The cursor position on the DC.
+   */
+   wxPoint GetScreenPos(wxDC &dc, const wxPoint &cpos, wxPoint *csize = NULL);
 
    /** Calculates new sizes for everything in the list, like Layout()
        but this is needed after the list got changed.
@@ -951,19 +1066,8 @@ public:
    wxPoint GetSize(void) const;
 
    /** Returns the cursor position on the screen.
-       @return cursor position in pixels
-   */
-   wxPoint GetCursorScreenPos(wxDC &dc);
-   /** Calculates the cursor position on the screen.
-       @param dc the dc to use for cursor position calculations
-       @param resetCursorMovedFlag: if true, reset "cursor moved" flag
-       @param translate optional translation of cursor coords on screen
-       
    */
-   void UpdateCursorScreenPos(wxDC &dc,
-                              bool resetCursorMovedFlag = true,
-                              const wxPoint& translate = wxPoint(0,
-                                                                 0));
+   wxPoint GetCursorScreenPos(void) const;
 
    /** Draws the cursor.
        @param active If true, draw a bold cursor to mark window as
@@ -1000,11 +1104,11 @@ public:
    /// adds the cursor position to the update rectangle
    void AddCursorPosToUpdateRect()
    {
-      #ifndef WXLAYOUT_USE_CARET
-         SetUpdateRect(m_CursorScreenPos);
-         SetUpdateRect(m_CursorScreenPos+m_CursorSize);
+#ifndef WXLAYOUT_USE_CARET
+      SetUpdateRect(m_CursorScreenPos);
+      SetUpdateRect(m_CursorScreenPos+m_CursorSize);
       //#else - the caret will take care of refreshing itself
-      #endif // !WXLAYOUT_USE_CARET
+#endif // !WXLAYOUT_USE_CARET
    }
    /// Invalidates the update rectangle.
    void InvalidateUpdateRect(void) { m_UpdateRectValid = false; }
@@ -1037,9 +1141,9 @@ public:
    /// Discard the current selection
    void DiscardSelection();
    /// Are we still selecting text?
-   bool IsSelecting(void);
+   bool IsSelecting(void) const;
    /// Is the given point (text coords) selected?
-   bool IsSelected(const wxPoint &cursor);
+   bool IsSelected(const wxPoint &cursor) const;
    /// Do we have a non null selection?
    bool HasSelection() const
       { return m_Selection.m_valid || m_Selection.m_selecting; }
@@ -1076,16 +1180,37 @@ public:
    void Debug(void);
 #endif
 
+   // for wxLayoutLine usage only
+   void IncNumLines() { m_numLines++; }
+   void DecNumLines() { m_numLines--; }
+
+   /// get the line by number
+   wxLayoutLine *GetLine(CoordType index) const;
+
+   /** Reads objects from a string and inserts them. Returns NULL if
+       string is empty or a linebreak was  found.
+       @param istr stream to read from, will bee changed
+   */
+   void Read(wxString &istr);
+
 private:
    /// Clear the list.
    void InternalClear(void);
 
    /// The list of lines.
    wxLayoutLine *m_FirstLine;
+   /// The number of lines in the list (store instead recalculating for speed)
+   size_t m_numLines;
+
    /// The update rectangle which needs to be refreshed:
    wxRect  m_UpdateRect;
    /// Is the update rectangle valid?
    bool    m_UpdateRectValid;
+
+   /// Shall we auto-format?
+   bool    m_AutoFormat;
+   /// Shall we re-layout everything?
+   bool    m_ReLayoutAll;
    /**@name Cursor Management */
    //@{
    /// Where the text cursor (column,line) is.
@@ -1107,9 +1232,11 @@ private:
    /// selection.state and begin/end coordinates
    struct Selection
    {
-      Selection() { m_valid = false; m_selecting = false; }
+      Selection() { m_valid = m_selecting = m_discarded = false; }
+
       bool m_valid;
       bool m_selecting;
+      bool m_discarded; // may be TRUE only until the next redraw
 
       // returns true if we already have the screen coordinates of the
       // selection start and end
@@ -1130,6 +1257,8 @@ private:
    wxLayoutStyleInfo m_DefaultStyleInfo;
    /// the current setting:
    wxLayoutStyleInfo m_CurrentStyleInfo;
+   /// the current setting:
+   wxLayoutStyleInfo m_CursorStyleInfo;
    //@}
 };
 
@@ -1139,14 +1268,18 @@ private:
    own format.
 
  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-class wxLayoutDataObject : public wxPrivateDataObject
+class wxLayoutDataObject : public wxCustomDataObject
 {
 public:
-   wxLayoutDataObject(void)
+   wxLayoutDataObject()
       {
-         SetId("application/wxlayoutlist");
-         //m_format.SetAtom((GdkAtom) 222222);
+         SetFormat("application/wxlayoutlist");
       }
+
+   // type safe wrappers
+   void SetLayoutData(const wxString& text)
+      { SetData(text.length() + 1, text.c_str()); }
+   const char *GetLayoutData() const { return (const char *)GetData(); }
 };
 
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *