3 * This file is part of LyX, the document processor.
4 * Licence details can be found in the file COPYING.
6 * \author Alejandro Aguilar Sierra
8 * \author Lars Gullik Bjønnes
9 * \author Matthias Ettrich
10 * \author André Pönitz
12 * Full author contact details are available in file CREDITS.
19 #include "buffer_funcs.h"
21 #include "BufferList.h"
22 #include "BufferParams.h"
23 #include "BufferView.h"
24 #include "CoordCache.h"
26 #include "Dimension.h"
27 #include "DispatchResult.h"
28 #include "FuncRequest.h"
29 #include "FuncStatus.h"
30 #include "MetricsInfo.h"
32 #include "TextClass.h"
34 #include "frontends/Application.h"
35 #include "frontends/Painter.h"
37 #include "support/debug.h"
38 #include "support/docstream.h"
39 #include "support/ExceptionMessage.h"
40 #include "support/gettext.h"
41 #include "support/lassert.h"
46 using namespace lyx::support
;
52 InsetName(string
const & n
, InsetCode c
) : name(n
), code(c
) {}
58 typedef map
<string
, InsetCode
> TranslatorMap
;
61 static TranslatorMap
const build_translator()
63 InsetName
const insetnames
[] = {
64 InsetName("toc", TOC_CODE
),
65 InsetName("quote", QUOTE_CODE
),
66 InsetName("ref", REF_CODE
),
67 InsetName("href", HYPERLINK_CODE
),
68 InsetName("separator", SEPARATOR_CODE
),
69 InsetName("ending", ENDING_CODE
),
70 InsetName("label", LABEL_CODE
),
71 InsetName("note", NOTE_CODE
),
72 InsetName("phantom", PHANTOM_CODE
),
73 InsetName("accent", ACCENT_CODE
),
74 InsetName("math", MATH_CODE
),
75 InsetName("index", INDEX_CODE
),
76 InsetName("nomenclature", NOMENCL_CODE
),
77 InsetName("include", INCLUDE_CODE
),
78 InsetName("graphics", GRAPHICS_CODE
),
79 InsetName("bibitem", BIBITEM_CODE
),
80 InsetName("bibtex", BIBTEX_CODE
),
81 InsetName("text", TEXT_CODE
),
82 InsetName("ert", ERT_CODE
),
83 InsetName("foot", FOOT_CODE
),
84 InsetName("margin", MARGIN_CODE
),
85 InsetName("float", FLOAT_CODE
),
86 InsetName("wrap", WRAP_CODE
),
87 InsetName("specialchar", SPECIALCHAR_CODE
),
88 InsetName("tabular", TABULAR_CODE
),
89 InsetName("external", EXTERNAL_CODE
),
90 InsetName("caption", CAPTION_CODE
),
91 InsetName("mathmacro", MATHMACRO_CODE
),
92 InsetName("citation", CITE_CODE
),
93 InsetName("floatlist", FLOAT_LIST_CODE
),
94 InsetName("index_print", INDEX_PRINT_CODE
),
95 InsetName("nomencl_print", NOMENCL_PRINT_CODE
),
96 InsetName("optarg", OPTARG_CODE
),
97 InsetName("newline", NEWLINE_CODE
),
98 InsetName("line", LINE_CODE
),
99 InsetName("branch", BRANCH_CODE
),
100 InsetName("box", BOX_CODE
),
101 InsetName("flex", FLEX_CODE
),
102 InsetName("space", SPACE_CODE
),
103 InsetName("vspace", VSPACE_CODE
),
104 InsetName("mathmacroarg", MATHMACROARG_CODE
),
105 InsetName("listings", LISTINGS_CODE
),
106 InsetName("info", INFO_CODE
),
107 InsetName("collapsable", COLLAPSABLE_CODE
),
108 InsetName("newpage", NEWPAGE_CODE
),
109 InsetName("tablecell", CELL_CODE
)
112 size_t const insetnames_size
=
113 sizeof(insetnames
) / sizeof(insetnames
[0]);
115 map
<string
, InsetCode
> data
;
116 for (size_t i
= 0; i
!= insetnames_size
; ++i
) {
117 InsetName
const & var
= insetnames
[i
];
118 data
[var
.name
] = var
.code
;
125 void Inset::setBuffer(Buffer
& buffer
)
131 Buffer
& Inset::buffer()
135 lyxerr
<< "LyX Code: " << lyxCode() << " name: " << name() << std::endl
;
136 s
<< "LyX Code: " << lyxCode() << " name: " << name();
137 LASSERT(false, /**/);
138 throw ExceptionMessage(BufferException
,
139 from_ascii("Inset::buffer_ member not initialized!"), s
.str());
145 Buffer
const & Inset::buffer() const
147 return const_cast<Inset
*>(this)->buffer();
151 bool Inset::isBufferValid() const
153 return buffer_
&& theBufferList().isLoaded(buffer_
);
157 docstring
Inset::name() const
159 return from_ascii("unknown");
163 bool Inset::isFreeSpacing() const
165 return getLayout().isFreeSpacing();
169 bool Inset::allowEmpty() const
171 return getLayout().isKeepEmpty();
174 bool Inset::forceLTR() const
176 return getLayout().forceLTR();
179 void Inset::initView()
182 buffer().updateLabels();
186 docstring
Inset::toolTip(BufferView
const &, int, int) const
192 docstring
Inset::contextMenu(BufferView
const &, int, int) const
198 Dimension
const Inset::dimension(BufferView
const & bv
) const
200 return bv
.coordCache().getInsets().dim(this);
204 InsetCode
insetCode(string
const & name
)
206 static TranslatorMap
const translator
= build_translator();
208 TranslatorMap::const_iterator it
= translator
.find(name
);
209 return it
== translator
.end() ? NO_CODE
: it
->second
;
213 string
insetName(InsetCode c
)
215 static TranslatorMap
const translator
= build_translator();
217 TranslatorMap::const_iterator it
= translator
.begin();
218 TranslatorMap::const_iterator end
= translator
.end();
219 for (; it
!= end
; ++it
) {
227 void Inset::dispatch(Cursor
& cur
, FuncRequest
& cmd
)
229 LASSERT(cur
.buffer() == buffer_
, return);
230 cur
.updateFlags(Update::Force
| Update::FitCursor
);
232 doDispatch(cur
, cmd
);
236 void Inset::doDispatch(Cursor
& cur
, FuncRequest
&cmd
)
238 switch (cmd
.action
) {
239 case LFUN_MOUSE_RELEASE
:
240 // if the derived inset did not explicitly handle mouse_release,
241 // we assume we request the settings dialog
242 if (!cur
.selection() && cmd
.button() == mouse_button::button1
244 FuncRequest
tmpcmd(LFUN_INSET_SETTINGS
);
245 dispatch(cur
, tmpcmd
);
249 case LFUN_INSET_SETTINGS
:
250 if (cmd
.argument().empty() || cmd
.getArg(0) == insetName(lyxCode())) {
251 showInsetDialog(&cur
.bv());
265 bool Inset::getStatus(Cursor
&, FuncRequest
const & cmd
,
266 FuncStatus
& flag
) const
268 // LFUN_INSET_APPLY is sent from the dialogs when the data should
269 // be applied. This is either changed to LFUN_INSET_MODIFY (if the
270 // dialog belongs to us) or LFUN_INSET_INSERT (if the dialog does
271 // not belong to us, i. e. the dialog was open, and the user moved
272 // the cursor in our inset) in LyXFunc::getStatus().
273 // Dialogs::checkStatus() ensures that the dialog is deactivated if
274 // LFUN_INSET_APPLY is disabled.
276 switch (cmd
.action
) {
277 case LFUN_INSET_MODIFY
:
278 // Allow modification of our data.
279 // This needs to be handled in the doDispatch method of our
280 // instantiatable children.
281 flag
.setEnabled(true);
284 case LFUN_INSET_INSERT
:
285 // Don't allow insertion of new insets.
286 // Every inset that wants to allow new insets from open
287 // dialogs needs to override this.
288 flag
.setEnabled(false);
291 case LFUN_INSET_SETTINGS
:
292 if (cmd
.argument().empty() || cmd
.getArg(0) == insetName(lyxCode())) {
293 bool const enable
= hasSettings();
294 flag
.setEnabled(enable
);
297 flag
.setEnabled(false);
308 void Inset::edit(Cursor
&, bool, EntryDirection
)
310 LYXERR(Debug::INSETS
, "edit left/right");
314 Inset
* Inset::editXY(Cursor
&, int x
, int y
)
316 LYXERR(Debug::INSETS
, "x: " << x
<< " y: " << y
);
321 Inset::idx_type
Inset::index(row_type row
, col_type col
) const
324 LYXERR0("illegal row: " << row
);
326 LYXERR0("illegal col: " << col
);
331 bool Inset::idxBetween(idx_type idx
, idx_type from
, idx_type to
) const
333 return from
<= idx
&& idx
<= to
;
337 bool Inset::idxUpDown(Cursor
&, bool) const
343 int Inset::docbook(odocstream
&, OutputParams
const &) const
349 docstring
Inset::xhtml(odocstream
& od
, OutputParams
const &) const
351 od
<< "[[Inset: " << from_ascii(insetName(lyxCode())) << "]]";
355 bool Inset::directWrite() const
361 bool Inset::editable() const
367 bool Inset::hasSettings() const
374 bool Inset::autoDelete() const
380 void Inset::cursorPos(BufferView
const & /*bv*/, CursorSlice
const &,
381 bool, int & x
, int & y
) const
383 LYXERR0("Inset::cursorPos called directly");
389 void Inset::metricsMarkers(Dimension
& dim
, int framesize
) const
391 dim
.wid
+= 2 * framesize
;
392 dim
.des
+= framesize
;
396 void Inset::metricsMarkers2(Dimension
& dim
, int framesize
) const
398 dim
.wid
+= 2 * framesize
;
399 dim
.asc
+= framesize
;
400 dim
.des
+= framesize
;
404 void Inset::drawMarkers(PainterInfo
& pi
, int x
, int y
) const
406 ColorCode pen_color
= mouseHovered() || editing(pi
.base
.bv
)?
407 Color_mathframe
: Color_mathcorners
;
409 Dimension
const dim
= dimension(*pi
.base
.bv
);
411 int const t
= x
+ dim
.width() - 1;
412 int const d
= y
+ dim
.descent();
413 pi
.pain
.line(x
, d
- 3, x
, d
, pen_color
);
414 pi
.pain
.line(t
, d
- 3, t
, d
, pen_color
);
415 pi
.pain
.line(x
, d
, x
+ 3, d
, pen_color
);
416 pi
.pain
.line(t
- 3, d
, t
, d
, pen_color
);
417 setPosCache(pi
, x
, y
);
421 void Inset::drawMarkers2(PainterInfo
& pi
, int x
, int y
) const
423 ColorCode pen_color
= mouseHovered() || editing(pi
.base
.bv
)?
424 Color_mathframe
: Color_mathcorners
;
426 drawMarkers(pi
, x
, y
);
427 Dimension
const dim
= dimension(*pi
.base
.bv
);
428 int const t
= x
+ dim
.width() - 1;
429 int const a
= y
- dim
.ascent();
430 pi
.pain
.line(x
, a
+ 3, x
, a
, pen_color
);
431 pi
.pain
.line(t
, a
+ 3, t
, a
, pen_color
);
432 pi
.pain
.line(x
, a
, x
+ 3, a
, pen_color
);
433 pi
.pain
.line(t
- 3, a
, t
, a
, pen_color
);
434 setPosCache(pi
, x
, y
);
438 bool Inset::editing(BufferView
const * bv
) const
440 return bv
->cursor().isInside(this);
444 int Inset::xo(BufferView
const & bv
) const
446 return bv
.coordCache().getInsets().x(this);
450 int Inset::yo(BufferView
const & bv
) const
452 return bv
.coordCache().getInsets().y(this);
456 bool Inset::covers(BufferView
const & bv
, int x
, int y
) const
458 return bv
.coordCache().getInsets().covers(this, x
, y
);
462 InsetLayout
const & Inset::getLayout() const
465 return DocumentClass::plainInsetLayout();
466 return buffer().params().documentClass().insetLayout(name());
470 bool Inset::undefined() const
472 docstring
const & n
= getLayout().name();
473 return n
.empty() || n
== DocumentClass::plainInsetLayout().name();
477 void Inset::dump() const
483 ColorCode
Inset::backgroundColor() const
489 ColorCode
Inset::labelColor() const
491 return Color_foreground
;
495 void Inset::setPosCache(PainterInfo
const & pi
, int x
, int y
) const
497 //LYXERR("Inset: set position cache to " << x << " " << y);
498 pi
.base
.bv
->coordCache().insets().add(this, x
, y
);
502 void Inset::setDimCache(MetricsInfo
const & mi
, Dimension
const & dim
) const
504 mi
.base
.bv
->coordCache().insets().add(this, dim
);
508 Buffer
const * Inset::updateFrontend() const
510 return theApp() ? theApp()->updateInset(this) : 0;
514 docstring
Inset::completionPrefix(Cursor
const &) const