]> git.lyx.org Git - lyx.git/blob - src/text_funcs.C
last Friday's text*.C -> text_func shuffle
[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
29 bool transposeChars(LyXCursor const & cursor)
30 {
31         ParagraphList::iterator tmppit = cursor.par();
32         pos_type tmppos = cursor.pos();
33
34         // First decide if it is possible to transpose at all
35
36         if (tmppos == 0 || tmppos == tmppit->size())
37                 return false;
38
39         if (isDeletedText(*tmppit, tmppos - 1)
40                 || isDeletedText(*tmppit, tmppos))
41                 return false;
42
43         unsigned char c1 = tmppit->getChar(tmppos);
44         unsigned char c2 = tmppit->getChar(tmppos - 1);
45
46         // We should have an implementation that handles insets
47         // as well, but that will have to come later. (Lgb)
48         if (c1 == Paragraph::META_INSET || c2 == Paragraph::META_INSET)
49                 return false;
50
51         bool const erased = tmppit->erase(tmppos - 1, tmppos + 1);
52         size_t const ipos = erased ? tmppos - 1 : tmppos + 1;
53
54         tmppit->insertChar(ipos, c1);
55         tmppit->insertChar(ipos + 1, c2);
56         return true;
57 }
58
59
60 void cursorLeftOneWord(LyXCursor & cursor, ParagraphList const & pars)
61 {
62         // treat HFills, floats and Insets as words
63
64         ParagraphList::iterator pit = cursor.par();
65         size_t pos = cursor.pos();
66
67         while (pos &&
68                (pit->isSeparator(pos - 1) ||
69                 pit->isKomma(pos - 1) ||
70                 pit->isNewline(pos - 1)) &&
71                !(pit->isHfill(pos - 1) ||
72                  pit->isInset(pos - 1)))
73                 --pos;
74
75         if (pos &&
76             (pit->isInset(pos - 1) ||
77              pit->isHfill(pos - 1))) {
78                 --pos;
79         } else if (!pos) {
80                 if (pit != pars.begin()) {
81                         --pit;
82                         pos = pit->size();
83                 }
84         } else {                // Here, cur != 0
85                 while (pos > 0 && pit->isWord(pos - 1))
86                         --pos;
87         }
88
89         cursor.par(pit);
90         cursor.pos(pos);
91 }
92
93
94 void cursorRightOneWord(LyXCursor & cursor, ParagraphList const & pars)
95 {
96         // treat floats, HFills and Insets as words
97         ParagraphList::iterator pit = cursor.par();
98         pos_type pos = cursor.pos();
99
100         // CHECK See comment on top of text.C
101
102         if (pos == pit->size() && boost::next(pit) != pars.end()) {
103                 ++pit;
104                 pos = 0;
105         } else {
106                 // Skip through initial nonword stuff.
107                 while (pos < pit->size() && !pit->isWord(pos)) {
108                         ++pos;
109                 }
110                 // Advance through word.
111                 while (pos < pit->size() && pit->isWord(pos)) {
112                         ++pos;
113                 }
114         }
115
116         cursor.par(pit);
117         cursor.pos(pos);
118 }
119
120
121 // Select current word. This depends on behaviour of
122 // CursorLeftOneWord(), so it is patched as well.
123 void getWord(LyXCursor & from, LyXCursor & to, word_location const loc,
124         ParagraphList const & pars)
125 {
126         switch (loc) {
127         case lyx::WHOLE_WORD_STRICT:
128                 if (from.pos() == 0 || from.pos() == from.par()->size()
129                     || from.par()->isSeparator(from.pos())
130                     || from.par()->isKomma(from.pos())
131                     || from.par()->isNewline(from.pos())
132                     || from.par()->isSeparator(from.pos() - 1)
133                     || from.par()->isKomma(from.pos() - 1)
134                     || from.par()->isNewline(from.pos() - 1)) {
135                         to = from;
136                         return;
137                 }
138                 // no break here, we go to the next
139
140         case lyx::WHOLE_WORD:
141                 // Move cursor to the beginning, when not already there.
142                 if (from.pos() && !from.par()->isSeparator(from.pos() - 1)
143                     && !(from.par()->isKomma(from.pos() - 1)
144                          || from.par()->isNewline(from.pos() - 1)))
145                         cursorLeftOneWord(from, pars);
146                 break;
147         case lyx::PREVIOUS_WORD:
148                 // always move the cursor to the beginning of previous word
149                 cursorLeftOneWord(from, pars);
150                 break;
151         case lyx::NEXT_WORD:
152                 lyxerr << "LyXText::getWord: NEXT_WORD not implemented yet\n";
153                 break;
154         case lyx::PARTIAL_WORD:
155                 break;
156         }
157         to = from;
158         while (to.pos() < to.par()->size()
159                && !to.par()->isSeparator(to.pos())
160                && !to.par()->isKomma(to.pos())
161                && !to.par()->isNewline(to.pos())
162                && !to.par()->isHfill(to.pos())
163                && !to.par()->isInset(to.pos()))
164         {
165                 to.pos(to.pos() + 1);
166         }
167 }