]> git.lyx.org Git - lyx.git/blob - src/text_funcs.C
Point fix, earlier forgotten
[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 "debug.h"
18 #include "lyxcursor.h"
19 #include "ParagraphList.h"
20
21 #include "support/types.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(LyXCursor const & cursor)
32 {
33         ParagraphList::iterator tmppit = cursor.par();
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(LyXCursor & cursor, ParagraphList const & pars)
63 {
64         // treat HFills, floats and Insets as words
65
66         ParagraphList::iterator pit = cursor.par();
67         size_t pos = cursor.pos();
68
69         while (pos &&
70                (pit->isSeparator(pos - 1) ||
71                 pit->isKomma(pos - 1) ||
72                 pit->isNewline(pos - 1)) &&
73                !(pit->isHfill(pos - 1) ||
74                  pit->isInset(pos - 1)))
75                 --pos;
76
77         if (pos &&
78             (pit->isInset(pos - 1) ||
79              pit->isHfill(pos - 1))) {
80                 --pos;
81         } else if (!pos) {
82                 // cast only for BSD's g++ 2.95
83                 if (pit != const_cast<ParagraphList &>(pars).begin()) {
84                         --pit;
85                         pos = pit->size();
86                 }
87         } else {                // Here, cur != 0
88                 while (pos > 0 && pit->isWord(pos - 1))
89                         --pos;
90         }
91
92         cursor.par(pit);
93         cursor.pos(pos);
94 }
95
96
97 void cursorRightOneWord(LyXCursor & cursor, ParagraphList const & pars)
98 {
99         // treat floats, HFills and Insets as words
100         ParagraphList::iterator pit = cursor.par();
101         pos_type pos = cursor.pos();
102
103         // CHECK See comment on top of text.C
104
105         // cast only for BSD's g++ 2.95
106         if (pos == pit->size() &&
107                 boost::next(pit) != const_cast<ParagraphList &>(pars).end()) {
108                 ++pit;
109                 pos = 0;
110         } else {
111                 // Skip through initial nonword stuff.
112                 while (pos < pit->size() && !pit->isWord(pos)) {
113                         ++pos;
114                 }
115                 // Advance through word.
116                 while (pos < pit->size() && pit->isWord(pos)) {
117                         ++pos;
118                 }
119         }
120
121         cursor.par(pit);
122         cursor.pos(pos);
123 }
124
125
126 // Select current word. This depends on behaviour of
127 // CursorLeftOneWord(), so it is patched as well.
128 void getWord(LyXCursor & from, LyXCursor & to, word_location const loc,
129         ParagraphList const & pars)
130 {
131         switch (loc) {
132         case lyx::WHOLE_WORD_STRICT:
133                 if (from.pos() == 0 || from.pos() == from.par()->size()
134                     || from.par()->isSeparator(from.pos())
135                     || from.par()->isKomma(from.pos())
136                     || from.par()->isNewline(from.pos())
137                     || from.par()->isSeparator(from.pos() - 1)
138                     || from.par()->isKomma(from.pos() - 1)
139                     || from.par()->isNewline(from.pos() - 1)) {
140                         to = from;
141                         return;
142                 }
143                 // no break here, we go to the next
144
145         case lyx::WHOLE_WORD:
146                 // Move cursor to the beginning, when not already there.
147                 if (from.pos() && !from.par()->isSeparator(from.pos() - 1)
148                     && !(from.par()->isKomma(from.pos() - 1)
149                          || from.par()->isNewline(from.pos() - 1)))
150                         cursorLeftOneWord(from, pars);
151                 break;
152         case lyx::PREVIOUS_WORD:
153                 // always move the cursor to the beginning of previous word
154                 cursorLeftOneWord(from, pars);
155                 break;
156         case lyx::NEXT_WORD:
157                 lyxerr << "LyXText::getWord: NEXT_WORD not implemented yet"
158                        << endl;
159                 break;
160         case lyx::PARTIAL_WORD:
161                 break;
162         }
163         to = from;
164         while (to.pos() < to.par()->size()
165                && !to.par()->isSeparator(to.pos())
166                && !to.par()->isKomma(to.pos())
167                && !to.par()->isNewline(to.pos())
168                && !to.par()->isHfill(to.pos())
169                && !to.par()->isInset(to.pos()))
170         {
171                 to.pos(to.pos() + 1);
172         }
173 }