]> git.lyx.org Git - lyx.git/blob - src/paragraph_funcs.C
Collapse all those LFUN_XYZ_APPLY to a single LFUN_INSET_APPLY.
[lyx.git] / src / paragraph_funcs.C
1 /**
2  * \file paragraph_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  *
8  * Full author contact details are available in file CREDITS
9  */
10
11 #include <config.h>
12
13 #include "paragraph_funcs.h"
14 #include "paragraph_pimpl.h"
15 #include "buffer.h"
16 #include "ParagraphParameters.h"
17 #include "lyxtextclasslist.h"
18 #include "debug.h"
19
20 using lyx::pos_type;
21 //using lyx::layout_type;
22 using std::endl;
23
24
25 void breakParagraph(BufferParams const & bparams,
26                     Paragraph * par,
27                     pos_type pos,
28                     int flag)
29 {
30         // create a new paragraph
31         Paragraph * tmp = new Paragraph(par);
32         // without doing that we get a crash when typing <Return> at the
33         // end of a paragraph
34         tmp->layout(bparams.getLyXTextClass().defaultLayout());
35         // remember to set the inset_owner
36         tmp->setInsetOwner(par->inInset());
37
38         if (bparams.tracking_changes)
39                 tmp->trackChanges();
40  
41         // this is an idea for a more userfriendly layout handling, I will
42         // see what the users say
43
44         // layout stays the same with latex-environments
45         if (flag) {
46                 tmp->layout(par->layout());
47                 tmp->setLabelWidthString(par->params().labelWidthString());
48         }
49
50         bool const isempty = (par->layout()->keepempty && par->empty());
51
52         if (!isempty && (par->size() > pos || par->empty() || flag == 2)) {
53                 tmp->layout(par->layout());
54                 tmp->params().align(par->params().align());
55                 tmp->setLabelWidthString(par->params().labelWidthString());
56
57                 tmp->params().lineBottom(par->params().lineBottom());
58                 par->params().lineBottom(false);
59                 tmp->params().pagebreakBottom(par->params().pagebreakBottom());
60                 par->params().pagebreakBottom(false);
61                 tmp->params().spaceBottom(par->params().spaceBottom());
62                 par->params().spaceBottom(VSpace(VSpace::NONE));
63
64                 tmp->params().depth(par->params().depth());
65                 tmp->params().noindent(par->params().noindent());
66
67                 // copy everything behind the break-position
68                 // to the new paragraph
69
70 #ifdef WITH_WARNINGS
71 #warning this seems wrong
72 #endif
73                 /* FIXME: if !keepempty, empty() == true, then we reach
74                  * here with size() == 0. So pos_end becomes - 1. Why
75                  * doesn't this cause problems ???
76                  */
77                 pos_type pos_end = par->size() - 1;
78                 pos_type i = pos;
79                 pos_type j = pos;
80
81                 for (; i <= pos_end; ++i) {
82                         Change::Type change(par->lookupChange(i));
83                         par->cutIntoMinibuffer(bparams, i);
84                         if (tmp->insertFromMinibuffer(j - pos)) {
85                                 tmp->pimpl_->setChange(j - pos, change);
86                                 ++j;
87                         }
88                 }
89                 for (i = pos_end; i >= pos; --i) {
90                         par->pimpl_->eraseIntern(i);
91                 }
92         }
93
94         if (pos)
95                 return;
96
97         tmp->params().lineTop(par->params().lineTop());
98         tmp->params().pagebreakTop(par->params().pagebreakTop());
99         tmp->params().spaceTop(par->params().spaceTop());
100         par->params().clear();
101
102         par->layout(bparams.getLyXTextClass().defaultLayout());
103
104         // layout stays the same with latex-environments
105         if (flag) {
106                 par->layout(tmp->layout());
107                 par->setLabelWidthString(tmp->params().labelWidthString());
108                 par->params().depth(tmp->params().depth());
109         }
110
111         // subtle, but needed to get empty pars working right
112         if (bparams.tracking_changes) {
113                 if (!par->size()) {
114                         par->cleanChanges();
115                 } else if (!tmp->size()) {
116                         tmp->cleanChanges();
117                 }
118         }
119 }
120
121
122 void breakParagraphConservative(BufferParams const & bparams,
123                                 Paragraph * par,
124                                 pos_type pos)
125 {
126         // create a new paragraph
127         Paragraph * tmp = new Paragraph(par);
128         tmp->makeSameLayout(par);
129
130         // When can pos > Last()?
131         // I guess pos == Last() is possible.
132         if (par->size() > pos) {
133                 // copy everything behind the break-position to the new
134                 // paragraph
135                 pos_type pos_end = par->size() - 1;
136
137                 for (pos_type i = pos, j = pos; i <= pos_end; ++i) {
138                         par->cutIntoMinibuffer(bparams, i);
139                         if (tmp->insertFromMinibuffer(j - pos))
140                                 ++j;
141                 }
142
143                 for (pos_type k = pos_end; k >= pos; --k) {
144                         par->erase(k);
145                 }
146         }
147 }
148
149
150 void mergeParagraph(BufferParams const & bparams, Paragraph * par)
151 {
152         Paragraph * the_next = par->next();
153
154         // first the DTP-stuff
155         par->params().lineBottom(the_next->params().lineBottom());
156         par->params().spaceBottom(the_next->params().spaceBottom());
157         par->params().pagebreakBottom(the_next->params().pagebreakBottom());
158
159         pos_type pos_end = the_next->size() - 1;
160         pos_type pos_insert = par->size();
161
162         // ok, now copy the paragraph
163         for (pos_type i = 0, j = 0; i <= pos_end; ++i) {
164                 the_next->cutIntoMinibuffer(bparams, i);
165                 if (par->insertFromMinibuffer(pos_insert + j))
166                         ++j;
167         }
168
169         // delete the next paragraph
170         Paragraph * ppar = the_next->previous();
171         Paragraph * npar = the_next->next();
172         delete the_next;
173         ppar->next(npar);
174 }
175
176
177 #if 0
178 Paragraph * depthHook(Paragraph * par, Paragraph::depth_type depth)
179 {
180         Paragraph * newpar = par;
181
182         do {
183                 newpar = newpar->previous();
184         } while (newpar && newpar->getDepth() > depth);
185
186         if (!newpar) {
187                 if (par->previous() || par->getDepth())
188                         lyxerr << "Error (depthHook): "
189                                << "no hook." << endl;
190                 newpar = par;
191         }
192         return newpar;
193 }
194
195
196 Paragraph * outerHook(Paragraph * par)
197 {
198         if (!par->getDepth())
199                 return 0;
200         return depthHook(par, Paragraph::depth_type(par->getDepth() - 1));
201 }
202
203
204 bool isFirstInSequence(Paragraph * par)
205 {
206         Paragraph const * dhook = depthHook(par, par->getDepth());
207         return (dhook == par
208                 || dhook->getLayout() != par->getLayout()
209                 || dhook->getDepth() != par->getDepth());
210 }
211
212
213 int getEndLabel(Paragraph * para, BufferParams const & bparams)
214 {
215         Paragraph * par = para;
216         while (par) {
217                 Paragraph::depth_type par_depth = par->getDepth();
218                 layout_type layout = par->getLayout();
219                 int const endlabeltype =
220                         textclasslist.Style(bparams.textclass,
221                                             layout).endlabeltype;
222                 if (endlabeltype != END_LABEL_NO_LABEL) {
223                         if (!para->next())
224                                 return endlabeltype;
225
226                         Paragraph::depth_type const next_depth =
227                                 para->next()->getDepth();
228                         if (par_depth > next_depth ||
229                             (par_depth == next_depth
230                              && layout != para->next()->getLayout()))
231                                 return endlabeltype;
232                         break;
233                 }
234                 if (par_depth == 0)
235                         break;
236                 par = outerHook(par);
237         }
238         return END_LABEL_NO_LABEL;
239 }
240 #endif