123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265 |
- /* GCSx
- ** EDITBOX.H
- **
- ** Multi-line textbox window
- */
- /*****************************************************************************
- ** Copyright (C) 2003-2006 Janson
- **
- ** This program is free software; you can redistribute it and/or modify
- ** it under the terms of the GNU General Public License as published by
- ** the Free Software Foundation; either version 2 of the License, or
- ** (at your option) any later version.
- **
- ** This program is distributed in the hope that it will be useful,
- ** but WITHOUT ANY WARRANTY; without even the implied warranty of
- ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- ** GNU General Public License for more details.
- **
- ** You should have received a copy of the GNU General Public License
- ** along with this program; if not, write to the Free Software
- ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
- *****************************************************************************/
- #ifndef __GCSx_EDITBOX_H_
- #define __GCSx_EDITBOX_H_
- // d) Data line- one line in storage
- // v) Virtual line- one line displayed
- // One data line results in one OR MORE virtual lines
- class EditBox : public Window {
- public:
- // Definition of a point within textbox- points to the character it is before
- struct TextPoint {
- int vRow;
- int column;
- int pixelX;
- };
-
- protected:
- // Maps virtual lines to data
- struct VLine {
- int dLine;
- std::list<std::string>::iterator dLineI;
- int colStart; // first row will have 0
- int length; // length of 5 means chars 0-4 plus a blank spot at the end
- const std::string getStr() const { return (*dLineI).substr(colStart, length); }
- };
- std::list<VLine> lineMap;
- void fillLineMap();
- // Returns number of vlines added
- // doesn't update vNumLines or dNumLines; does update vLongestLength
- int addLineWrapped(int dLine, std::list<std::string>::iterator& iter, std::list<VLine>::iterator& insertAt);
- int breakLineBefore(const std::string& line, int xPixel);
- // Assumes contents, starting at given line, have been deleted or added already
- // Call in sequence for a modification of x lines
- // Doesn't adjust insertion/selection, resize, or dirty
- // (insert adjusts vLongestLength)
- void eraseLineMap(int dLineFirst, int count, int* getVLineAt = NULL, int* getVLineCount = NULL);
- void insertLineMap(int dLineAt, int count, int* getVLineAt = NULL, int* getVLineCount = NULL);
- void dumpLineMap();
-
- // Adjusts cursor/selection and resizes
- void contentModifyHelper(int vLine, int vCount);
-
- // Call if you modify within a single line only- does everything except update insertion/selection
- // and doesn't call pre/post modify
- // Assumes you've called vLineToDLineAllPoints and that points are in dlines right now
- // (update linemap, resize, dirty)
- // All changes that don't go through pasteText() go through this function
- void modifyDLine(int dLine);
-
- // Helper function
- void doIndent(int dLine, int count, int function);
-
- int open;
- int haveFocus;
-
- class FrameWindow* myFrame;
- class WidgetScroll* myScroll;
-
- int font;
- int readonly;
- int wordwrap;
- int wrappedTo;
- int autoIndent;
-
- // Dirty range, in Vlines
- int vDirtyFirst;
- int vDirtyLast;
- // A copy of storage for convenience
- std::list<std::string>* contents;
- int dNumLines;
- int vNumLines;
- int vLongestLength; // In pixels
- int lineHeight;
-
- // Iterator control for quickly finding a spot in the middle
- std::list<VLine>::iterator lastSpot;
- int lastSpotLine;
- std::list<VLine>::iterator findVLine(int line);
- // Finds FIRST of a given data line
- std::list<VLine>::iterator findDLine(int dLine, int* getVLineNum = NULL);
-
- // Insertion point and selection
- // Selection begin OR end will ALWAYS match insertpoint UNLESS
- // there is no selection, in which case both are indeterminate
- TextPoint insertion;
- TextPoint selectBegin;
- TextPoint selectEnd;
- int isSelect;
-
- // Insertion point
- int insertYOffset;
- int insertHeight;
- int insertBlink;
- Uint32 insertBlinkMs;
-
- // Characters that make up "words"
- static const std::string wordChars;
- enum {
- GUI_EDITBOX_INSERTPOINTWIDTH = 2,
- // Margin is blank space inside textbox border
- GUI_EDITBOX_INNERMARGIN = 0,
- // Padding is added to edges of text within textbox, but only shows when
- // fully scrolled to that end of the text
- GUI_EDITBOX_LEFTPAD = 3,
- GUI_EDITBOX_RIGHTPAD = 3,
- // Preferred number of pixels to show in excess on each side when scrolling
- GUI_EDITBOX_SCROLLAHEAD = 10,
- // MS to wait between blinks
- DELAY_CURSOR_BLINK = 500,
- // These only apply when used as a widget!
- // This is the number of X characters to fit in a standard width
- GUI_EDITBOX_DEFAULTWIDTH = 30,
- // Default number of lines to show
- GUI_EDITBOX_DEFAULTLINES = 20,
-
- // Tab size (replaced with spaces)
- TAB_SIZE = 3,
- };
-
- // Sets dirty and resets cursor blink
- void setDirtyAndBlink();
-
- // Sets range of lines dirty
- void setDirtyRange(int first, int last);
-
- // Move one character left or right; pixelX will not be accurate
- void goLeft(TextPoint& point);
- void goRight(TextPoint& point);
-
- // Convert a textpoint from vline to dline position and back
- // A dline textpoint is useless until converted back, but can be
- // used to help retain relative position when doing modifications
- // Converting to VLine also updates xpixel.
- void vLineToDLine(TextPoint& point);
- void dLineToVLine(TextPoint& point);
- void vLineToDLineAllPoints();
- void dLineToVLineAllPoints();
-
- // Called whenever content changes, BEFORE and AFTER it changes
- // Will consist of any number of operations (in any order) ending in DONE
- // Reminder: line numbers are 0-based
- enum ContentChangeType {
- EDITBOX_REMOVE_LINES = 1,
- EDITBOX_INSERT_LINES, // It's assumed these are modified as well
- EDITBOX_MODIFY_LINE, // Only one at a time
- EDITBOX_MODIFY_DONE, // Called after each batch (even if just one) of modifications
- };
- virtual void contentModifiedPre(ContentChangeType type, int firstRow, int numRows);
- virtual void contentModifiedPost(ContentChangeType type, int firstRow, int numRows);
-
- // Update titlebar of frame
- virtual void updateTitlebar();
- virtual void prepOpen();
- virtual void paintText(const std::string& text, const std::string& entireLine, int posInLine, int x, int y, SDL_Surface* destSurface, int isSelected = 0) const;
-
- public:
- // Edited directly in storage
- EditBox(std::list<std::string>* storage, int myFont = FONT_STANDARD, int isReadOnly = 0);
- virtual ~EditBox();
-
- virtual int event(int hasFocus, const SDL_Event* event);
- void load();
- void apply();
- void display(SDL_Surface* destSurface, Rect& toDisplay, const Rect& clipArea, int xOffset, int yOffset);
- virtual CommandSupport supportsCommand(int code) const;
- WindowType windowType() const;
- // Creates a FrameWindow, adds self to desktop
- class FrameWindow* runWindowed();
-
- // Adds self to dialog using a WScroll
- void addTo(class Dialog* dialog, int showWidth = -1, int showLines = -1);
- // Returns the insertion position, given a pixel X/Y offset; X/Y offset
- // does not need to be within the actual display boundaries (IE you can drag
- // past the edges) .pixelX member is not accurate
- TextPoint insertWhere(int x, int y);
- // Same, but given a row instead of y pixel
- TextPoint insertWhereRow(int x, int row);
-
- // Handle special keystrokes
- void keyBackspace();
- void keyDelete();
- void indent(int dLine, int count);
- void unindent(int dLine, int count);
-
- // Query or set the insertion point, which also clears selection and
- // scrolls if needed to view; if drag is true, this drags the current
- // insertion point to the given position, modifying the selection as well
- const TextPoint& insertionState() const;
- // .pixelX member does not need to be accurate
- // .pixelX member is modified to be accurate in original and return
- // no other modifications are done to newPos
- const TextPoint& insertionState(TextPoint& newPos, int drag = 0);
-
- // (sel = ins if no selection at this time)
- void getCursorData(TextPoint& ins, TextPoint& selBegin, TextPoint& selEnd) const;
- // Intended to be called during undo process, but should be safe regardless
- // May change .pixelX members- but not gauranteed
- void setCursorData(TextPoint& ins, TextPoint& selBegin, TextPoint& selEnd);
- // Selects entire text, scrolls to end
- void selectAll();
-
- // Inserts text at the insertion point, overwriting any selection
- // No text = clear selection
- // Newlines are interpreted
- // Resets selection and adjusts insertion and scroll points
- // MOST changes go through this function; see modifyDLine
- void pasteText(const std::string& text);
-
- // Alerts editbox that its contents have changed in some way
- // Automatically handles dirty, scroll, moving insertion point, etc as needed
- // (line numbers 0-based)
- // Lines are DATA lines
- void contentModify(int dLine, int countLines);
- void contentInsert(int dLine, int countLines);
- void contentDelete(int dLine, int countLines);
-
- // Copies current selection to buffer
- // Copies "" if no selection
- // Newlines are inserted between lines
- void copyText(std::string& buffer);
-
- // Are we open?
- int isOpen() const { return open; }
-
- void resize(int newWidth, int newHeight, int newViewWidth = -1, int newViewHeight = -1, int fromParent = 0);
- };
- #endif
|