1 /* 2 ** Copyright 2003-2011, Double Precision Inc. 3 ** 4 ** See COPYING for distribution information. 5 */ 6 #ifndef curseseditmessage_H 7 #define curseseditmessage_H 8 9 /////////////////////////////////////////////////////////////////////////////// 10 // 11 // The message editor 12 13 #include "config.h" 14 #include "curses/cursescontainer.H" 15 #include "curses/curseskeyhandler.H" 16 #include "curses/cursesflowedline.H" 17 #include "libmail/objectmonitor.H" 18 #include <courier-unicode.h> 19 #include "spellcheckerbase.H" 20 #include <time.h> 21 22 #include <vector> 23 #include <string> 24 25 #define LINEW 77 26 27 namespace mail { 28 class Search; 29 } 30 31 class CursesEditMessage : public Curses, 32 public CursesKeyHandler, 33 public mail::obj { 34 35 // Text that's being edited 36 37 std::vector<CursesFlowedLine> text_UTF8; 38 39 public: numLines()40 size_t numLines() const { return text_UTF8.size(); } 41 void getText(size_t line, std::u32string &textRef); 42 void getText(size_t line, std::u32string &textRef, 43 bool &wrapped); getText(size_t line,CursesFlowedLine & textRef)44 void getText(size_t line, CursesFlowedLine &textRef) 45 { 46 textRef=line >= text_UTF8.size() ? CursesFlowedLine() 47 : text_UTF8[line]; 48 } 49 50 // Retrieve text in its native UTF-8 format. Optionally append a 51 // space if the line of text is flowed. 52 53 std::string getUTF8Text(size_t line, 54 bool useflowedformat); 55 56 private: 57 void setText(size_t line, const std::u32string &textRef); 58 void setText(size_t line, const CursesFlowedLine &textRef); 59 60 void getTextBeforeAfter(std::u32string &before, 61 std::u32string &after); 62 63 void getTextBeforeAfter(std::u32string &before, 64 std::u32string &after, 65 bool &flowed); 66 67 void setTextBeforeAfter(const std::u32string &before, 68 const std::u32string &after, 69 bool flowed=false); 70 71 bool justifiable(size_t lineNum); 72 73 void insertKeyPos(char32_t key); 74 75 template<typename iter_type> 76 void replaceTextLines(size_t start, size_t cnt, 77 iter_type beg_iter, iter_type end_iter); 78 79 template<typename iter_type> 80 void replaceTextLinesImpl(size_t start, size_t cnt, 81 iter_type beg_iter, iter_type end_iter); 82 83 template<typename value_type> 84 void replaceTextLine(size_t line, const value_type &value); 85 86 template<typename iter_category> 87 class replace_text_lines_helper; 88 89 class get_file_helper; 90 91 class unicode_wordwrap_iterator; 92 class unicode_wordwrap_rewrapper; 93 94 class unicode_wordwrap_oiterator; 95 public: 96 template<typename iter_category> 97 friend class replace_text_lines_helper; 98 private: 99 // 100 // Whenever cursor row changes, leaf wants to update the status bar. 101 // Rather then remembering to call a function each time the cursor 102 // row variable gets modified, the cursor row # is this object, which 103 // automatically invokes cursorRowChanged() each time it's poked. 104 // 105 106 class CursorRowUpdate { 107 108 size_t r; 109 public: 110 CursesEditMessage *me; 111 CursorRowUpdate()112 CursorRowUpdate() : r(0), me(NULL) {} ~CursorRowUpdate()113 ~CursorRowUpdate() {} 114 size_t()115 operator size_t() 116 { 117 return r; 118 } 119 120 size_t operator=(size_t newRow) 121 { 122 r=newRow; 123 if (me) 124 me->cursorRowChanged(); 125 return r; 126 } 127 128 size_t operator--() 129 { 130 return ((*this)=r-1); 131 } 132 133 size_t operator++() 134 { 135 return ((*this)=r+1); 136 } 137 138 }; 139 140 CursorRowUpdate cursorRow; 141 size_t cursorCol; // Current cursor column 142 size_t cursorLineHorizShift; // Current horiz scroll offset 143 144 bool marked; // Region being marked 145 size_t markRow; // The other end of the region. 146 size_t markCursorPos; 147 148 std::string defaultSearchStr; // Prev search string 149 std::string defaultReplaceStr; // Prev replace string 150 151 // 152 // Given horizontal position #col, return an iterator to the character 153 // in "line" that's shown at the given horizontal position. 154 // 155 std::u32string 156 ::iterator getIndexOfCol(std::u32string &line, 157 size_t col); 158 159 // 160 // Same thing, except that the starting position of each character 161 // in 'line' is precomputed in pos 162 // 163 static std::u32string 164 ::iterator getIndexOfCol(std::u32string &line, 165 std::vector<size_t> &pos, 166 size_t colNum); 167 168 // Return the horizontal location of the given character 169 170 static size_t getTextHorizPos(const std::u32string &line, 171 size_t column); 172 173 class SpellCheckerManager; 174 175 public: 176 virtual void cursorRowChanged(); 177 178 CursesEditMessage(CursesContainer *parent); 179 ~CursesEditMessage(); 180 181 static time_t autosaveInterval; 182 183 int getWidth() const; 184 int getHeight() const; 185 186 void load(std::istream &i, bool isflowed, bool delsp); 187 void save(std::ostream &o, bool isflowed); 188 bool isFocusable(); 189 bool processKeyInFocus(const Key &key); 190 int getCursorPosition(int &row, int &col); 191 192 void draw(); 193 void erase(); 194 195 void enterKey(); 196 setCurrentLine(size_t row)197 void setCurrentLine(size_t row) 198 { 199 if (row < numLines()) 200 { 201 cursorRow=row; 202 cursorCol=0; 203 } 204 } 205 currentLine()206 size_t currentLine() { return cursorRow; } 207 208 private: 209 virtual void macroDefined(); 210 void processMacroKey(std::string &repl_utf8); 211 212 void inserted(); 213 void drawLine(size_t lineNum); 214 void left(bool); 215 void right(); 216 void deleteChar(bool is_clreol_key); 217 bool checkReplace(bool &, std::string &, SpellCheckerBase::Manager *); 218 class ReplacePrompt; 219 220 bool search(bool doUpdate, bool doWrap, mail::Search &engine); 221 void mark(); 222 void end(); 223 224 void yank(const std::list<CursesFlowedLine> &yankText, 225 const std::string &chset, 226 bool doUpdate); 227 228 bool getMarkedRegion(size_t &row1, size_t &row2, 229 size_t &col1, size_t &col2); 230 231 static size_t colToPos(std::string &, std::vector<size_t> &, size_t, 232 bool); 233 234 Curses::Key lastKey; 235 bool processKey(const Curses::Key &key); 236 bool listKeys( std::vector< std::pair<std::string, std::string> > 237 &list); 238 239 virtual void modified()=0; 240 virtual std::string getConfigDir(); 241 virtual void extedited(); 242 243 public: 244 static std::string externalEditor; 245 }; 246 247 #endif 248