]> git.lyx.org Git - lyx.git/blob - src/text_funcs.C
ws changes only
[lyx.git] / src / text_funcs.C
1 /**
2  * \file text_funcs.C
3  * This file is part of LyX, the document processor.
4  * Licence details can be found in the file COPYING.
5  *
6  * \author Lars Gullik Bjønnes
7  * \author John Levon
8  *
9  * Full author contact details are available in file CREDITS.
10  *
11  * This file contains some utility functions for actually mutating
12  * the text contents of a document
13  */
14
15 #include <config.h>
16
17 #include "text_funcs.h"
18 #include "debug.h"
19 #include "lyxcursor.h"
20 #include "lyxtext.h"
21 #include "paragraph.h"
22
23 #include <boost/next_prior.hpp>
24
25 using lyx::pos_type;
26 using lyx::word_location;
27
28 using std::endl;
29
30
31 bool transposeChars(LyXText & text, LyXCursor const & cursor)
32 {
33         ParagraphList::iterator tmppit = text.cursorPar();
34         pos_type tmppos = cursor.pos();
35
36         // First decide if it is possible to transpose at all
37
38         if (tmppos == 0 || tmppos == tmppit->size())
39                 return false;
40
41         if (isDeletedText(*tmppit, tmppos - 1)
42                 || isDeletedText(*tmppit, tmppos))
43                 return false;
44
45         unsigned char c1 = tmppit->getChar(tmppos);
46         unsigned char c2 = tmppit->getChar(tmppos - 1);
47
48         // We should have an implementation that handles insets
49         // as well, but that will have to come later. (Lgb)
50         if (c1 == Paragraph::META_INSET || c2 == Paragraph::META_INSET)
51                 return false;
52
53         bool const erased = tmppit->erase(tmppos - 1, tmppos + 1);
54         size_t const ipos = erased ? tmppos - 1 : tmppos + 1;
55
56         tmppit->insertChar(ipos, c1);
57         tmppit->insertChar(ipos + 1, c2);
58         return true;
59 }
60
61
62 void cursorLeftOneWord(LyXText & text,
63         LyXCursor & cursor, ParagraphList const & pars)
64 {
65         // treat HFills, floats and Insets as words
66
67         ParagraphList::iterator pit = text.cursorPar();
68         size_t pos = cursor.pos();
69
70         while (pos &&
71                (pit->isSeparator(pos - 1) ||
72                 pit->isKomma(pos - 1) ||
73                 pit->isNewline(pos - 1)) &&
74                !(pit->isHfill(pos - 1) ||
75                  pit->isInset(pos - 1)))
76                 --pos;
77
78         if (pos &&
79             (pit->isInset(pos - 1) ||
80              pit->isHfill(pos - 1))) {
81                 --pos;
82         } else if (!pos) {
83                 // cast only for BSD's g++ 2.95
84                 if (pit != const_cast<ParagraphList &>(pars).begin()) {
85                         --pit;
86                         pos = pit->size();
87                 }
88         } else {                // Here, cur != 0
89                 while (pos > 0 && pit->isWord(pos - 1))
90                         --pos;
91         }
92
93         cursor.par(text.parOffset(pit));
94         cursor.pos(pos);
95 }
96
97
98 void cursorRightOneWord(LyXText & text,
99         LyXCursor & cursor, ParagraphList const & pars)
100 {
101         // treat floats, HFills and Insets as words
102         ParagraphList::iterator pit = text.cursorPar();
103         pos_type pos = cursor.pos();
104
105         // CHECK See comment on top of text.C
106
107         // cast only for BSD's g++ 2.95
108         if (pos == pit->size() &&
109                 boost::next(pit) != const_cast<ParagraphList &>(pars).end()) {
110                 ++pit;
111                 pos = 0;
112         } else {
113                 // Skip through initial nonword stuff.
114                 while (pos < pit->size() && !pit->isWord(pos)) {
115                         ++pos;
116                 }
117                 // Advance through word.
118                 while (pos < pit->size() && pit->isWord(pos)) {
119                         ++pos;
120                 }
121         }
122
123         cursor.par(text.parOffset(pit));
124         cursor.pos(pos);
125 }
126
127
128 // Select current word. This depends on behaviour of
129 // CursorLeftOneWord(), so it is patched as well.
130 void getWord(LyXText & text, LyXCursor & from, LyXCursor & to,
131         word_location const loc, ParagraphList const & pars)
132 {
133         ParagraphList::iterator from_par = text.getPar(from);
134         ParagraphList::iterator to_par = text.getPar(to);
135         switch (loc) {
136         case lyx::WHOLE_WORD_STRICT:
137                 if (from.pos() == 0 || from.pos() == from_par->size()
138                     || from_par->isSeparator(from.pos())
139                     || from_par->isKomma(from.pos())
140                     || from_par->isNewline(from.pos())
141                     || from_par->isSeparator(from.pos() - 1)
142                     || from_par->isKomma(from.pos() - 1)
143                     || from_par->isNewline(from.pos() - 1)) {
144                         to = from;
145                         return;
146                 }
147                 // no break here, we go to the next
148
149         case lyx::WHOLE_WORD:
150                 // Move cursor to the beginning, when not already there.
151                 if (from.pos() && !from_par->isSeparator(from.pos() - 1)
152                     && !(from_par->isKomma(from.pos() - 1)
153                          || from_par->isNewline(from.pos() - 1)))
154                         cursorLeftOneWord(text, from, pars);
155                 break;
156         case lyx::PREVIOUS_WORD:
157                 // always move the cursor to the beginning of previous word
158                 cursorLeftOneWord(text, from, pars);
159                 break;
160         case lyx::NEXT_WORD:
161                 lyxerr << "LyXText::getWord: NEXT_WORD not implemented yet"
162                        << endl;
163                 break;
164         case lyx::PARTIAL_WORD:
165                 break;
166         }
167         to = from;
168         while (to.pos() < to_par->size()
169                && !to_par->isSeparator(to.pos())
170                && !to_par->isKomma(to.pos())
171                && !to_par->isNewline(to.pos())
172                && !to_par->isHfill(to.pos())
173                && !to_par->isInset(to.pos()))
174         {
175                 to.pos(to.pos() + 1);
176         }
177 }