[LyX/master] Remove duplicate call to Cursor::selHandle

2014-03-17 Thread Jean-Marc Lasgouttes
commit 220fe66a67602cd43b08c4c72aee0e39726ad795
Author: Jean-Marc Lasgouttes <lasgout...@lyx.org>
Date:   Mon Mar 17 10:55:49 2014 +0100

Remove duplicate call to Cursor::selHandle

diff --git a/src/Text3.cpp b/src/Text3.cpp
index da9f876..41e47a5 100644
--- a/src/Text3.cpp
+++ b/src/Text3.cpp
@@ -743,7 +743,6 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
 
if (!atFirstOrLastRow) {
needsUpdate |= cur.selHandle(select);
-   cur.selHandle(select);
cur.upDownInText(up, needsUpdate);
needsUpdate |= cur.beforeDispatchCursor().inMathed();
} else {


[LyX/master] Also show boundary when displaying Cursor value.

2014-03-17 Thread Jean-Marc Lasgouttes
commit a27333144dc193e71bcef17944b73492b7bbfa2c
Author: Jean-Marc Lasgouttes <lasgout...@lyx.org>
Date:   Mon Mar 17 11:14:19 2014 +0100

Also show boundary when displaying Cursor value.

diff --git a/src/Cursor.cpp b/src/Cursor.cpp
index be32a76..89db3a6 100644
--- a/src/Cursor.cpp
+++ b/src/Cursor.cpp
@@ -1324,7 +1324,8 @@ ostream & operator<<(ostream & os, Cursor const & cur)
os << "--- | " << cur.anchor_[i] << 
"\n";
}
os << " selection: " << cur.selection_
-  << " x_target: " << cur.x_target_ << endl;
+  << " x_target: " << cur.x_target_
+  << " boundary: " << cur.boundary() << endl;
return os;
 }
 


[LyX/master] Fix bug #8837: LyX hangs on selection

2014-03-17 Thread Jean-Marc Lasgouttes
commit 264ea28cbd2a4c24dc6b81fa77422898167fa9f4
Author: Jean-Marc Lasgouttes <lasgout...@lyx.org>
Date:   Mon Mar 17 11:15:42 2014 +0100

Fix bug #8837: LyX hangs on selection

The code that checks whether the cursor was at the end of a row in
Cursor::upDowninText was not able to set boundary correctly. This
causes a hang in because the cursor got stuck on a line and there is an
infinite loop BufferView::dispatch when trying to go down.

The fix is to avoid using the watered-down TextMetrics::x2pos wrapper
around getColumnNearX and use the real thing instead.

Eventually, the last user of x2pos (InsetTabular) should be fixed and
the method should go away.

diff --git a/src/Cursor.cpp b/src/Cursor.cpp
index 89db3a6..d431965 100644
--- a/src/Cursor.cpp
+++ b/src/Cursor.cpp
@@ -2107,17 +2107,13 @@ bool Cursor::upDownInText(bool up, bool & updateNeeded)
next_row = 0;
}
}
-   top().pos() = min(tm.x2pos(pit(), next_row, xo), 
top().lastpos());
 
-   int const xpos = tm.x2pos(pit(), next_row, xo);
-   bool const at_end_row = xpos == tm.x2pos(pit(), next_row, 
tm.width());
-   bool const at_beg_row = xpos == tm.x2pos(pit(), next_row, 0);
-
-   if (at_end_row && at_beg_row)
-   // make sure the cursor ends up on this row
-   boundary(false);
-   else
-   boundary(at_end_row);
+   Row const & real_next_row = 
tm.parMetrics(pit()).rows()[next_row];
+   bool bound = false;
+   pos_type const col = tm.getColumnNearX(pit(), real_next_row, 
+  xo, bound);
+   top().pos() = real_next_row.pos() + col;
+   boundary(bound);
 
updateNeeded |= bv().checkDepm(*this, old);
}


[LyX/2.0.x] Fix bug #8837: LyX hangs on selection

2014-03-19 Thread Jean-Marc Lasgouttes
commit e72b3f8e3e259df4fc7340e186d51c95eac8b70e
Author: Jean-Marc Lasgouttes <lasgout...@lyx.org>
Date:   Mon Mar 17 11:15:42 2014 +0100

Fix bug #8837: LyX hangs on selection

The code that checks whether the cursor was at the end of a row in
Cursor::upDowninText was not able to set boundary correctly. This
causes a hang in because the cursor got stuck on a line and there is an
infinite loop BufferView::dispatch when trying to go down.

The fix is to avoid using the watered-down TextMetrics::x2pos wrapper
around getColumnNearX and use the real thing instead.

Eventually, the last user of x2pos (InsetTabular) should be fixed and
the method should go away.

diff --git a/src/Cursor.cpp b/src/Cursor.cpp
index 7917636..7e6c399 100644
--- a/src/Cursor.cpp
+++ b/src/Cursor.cpp
@@ -2024,17 +2024,13 @@ bool Cursor::upDownInText(bool up, bool & updateNeeded)
next_row = 0;
}
}
-   top().pos() = min(tm.x2pos(pit(), next_row, xo), 
top().lastpos());
 
-   int const xpos = tm.x2pos(pit(), next_row, xo);
-   bool const at_end_row = xpos == tm.x2pos(pit(), next_row, 
tm.width());
-   bool const at_beg_row = xpos == tm.x2pos(pit(), next_row, 0);
-
-   if (at_end_row && at_beg_row)
-   // make sure the cursor ends up on this row
-   boundary(false);
-   else
-   boundary(at_end_row);
+   Row const & real_next_row = 
tm.parMetrics(pit()).rows()[next_row];
+   bool bound = false;
+   pos_type const col = tm.getColumnNearX(pit(), real_next_row, 
+  xo, bound);
+   top().pos() = real_next_row.pos() + col;
+   boundary(bound);
 
updateNeeded |= bv().checkDepm(*this, old);
}
diff --git a/status.20x b/status.20x
index c63f0f6..dd5b8de 100644
--- a/status.20x
+++ b/status.20x
@@ -83,12 +83,15 @@ What's new
 
 - Fix crash when navigating to next change (bug 8684).
 
-- Fix crash when optional argument inside a math macro was deleted (bug 8329).
+- Fix crash when optional argument inside a math macro was deleted
+  (bug 8329).
+
+- Fix hang when selecting text (bug 8837).
 
 - Fix math-ams-matrix function that could corrupt documents if not used 
properly
   (part of bug 8359).
 
-- Fix problem that led to assertion in some cases when space was at beginning 
of 
+- Fix problem that led to assertion in some cases when space was at beginning 
of
   line (bugs 8838 and 8947).
 
 - Correctly compare documents with different author sets (bug 8769).


[LyX features/str-metrics] Fix bug #9040: In RtL documents end-of-paragraph marker shifts the row display

2014-03-20 Thread Jean-Marc Lasgouttes
The branch, str-metrics, has been updated.

- Log -

commit 82c77f14dbf637e793f38a62c020b024e2eece44
Author: Jean-Marc Lasgouttes <lasgout...@lyx.org>
Date:   Thu Mar 20 11:00:14 2014 +0100

Fix bug #9040: In RtL documents end-of-paragraph marker shifts the row 
display

The fact that the bug was still present in the features/str-metrics
branch comes from a goof in the initial implementation of 'virtual'
row elements (completion and end-of-par markers). Now that this is
corrected, everything works as it should.

The fact that the bug is present in master is due to some other reason
that is not useful to investigate now.

diff --git a/src/Row.cpp b/src/Row.cpp
index 15af2c2..6e60e97 100644
--- a/src/Row.cpp
+++ b/src/Row.cpp
@@ -282,7 +282,6 @@ void Row::add(pos_type const pos, char_type const c,
Element e(STRING, pos, f, ch);
elements_.push_back(e);
}
-   //lyxerr << "FONT " <<back().font.language() << endl;
back().str += c;
back().endpos = pos + 1;
 }
@@ -294,7 +293,8 @@ void Row::addVirtual(pos_type const pos, docstring const & 
s,
finalizeLast();
Element e(VIRTUAL, pos, f, ch);
e.str = s;
-   // A completion has no size
+   e.dim.wid = theFontMetrics(f).width(s);
+   dim_.wid += e.dim.wid;
e.endpos = pos;
elements_.push_back(e);
finalizeLast();

---

Summary of changes:
 src/Row.cpp |4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)


hooks/post-receive
-- 
Repository for new features


[LyX/2.2-staging] Do not store Languages objects in completion words lists

2014-03-24 Thread Jean-Marc Lasgouttes
commit 8ac5f09c1783261018a107b54ce398733b8f97a4
Author: Jean-Marc Lasgouttes <lasgout...@lyx.org>
Date:   Fri Mar 21 12:24:47 2014 +0100

Do not store Languages objects in completion words lists

In the current code each paragraph contains a map<Language,
WordList*>, which means that it contains a full copy of the language
object. Since these objects contain translation tables nowadays, this
is a very bad idea.

This patch simply replaces the Language key by a string.

When loading the Userguide on linux/x86_64, the total memory
consumption decreases from 36.27MB to 31.50MB.

diff --git a/src/LyX.cpp b/src/LyX.cpp
index 41c69f7..b784831 100644
--- a/src/LyX.cpp
+++ b/src/LyX.cpp
@@ -33,6 +33,7 @@
 #include "FuncStatus.h"
 #include "HunspellChecker.h"
 #include "KeyMap.h"
+#include "Language.h"
 #include "LaTeXFonts.h"
 #include "LayoutFile.h"
 #include "Lexer.h"
diff --git a/src/Paragraph.cpp b/src/Paragraph.cpp
index ffcb5f2..4d9b37c 100644
--- a/src/Paragraph.cpp
+++ b/src/Paragraph.cpp
@@ -499,7 +499,7 @@ public:
TextContainer text_;
 
typedef set Words;
-   typedef map<Language, Words> LangWordsMap;
+   typedef map<string, Words> LangWordsMap;
///
LangWordsMap words_;
///
@@ -3867,7 +3867,7 @@ void Paragraph::collectWords()
if (cit == d->fontlist_.end())
return;
Language const * lang = cit->font().language();
-   d->words_[*lang].insert(word);
+   d->words_[lang->lang()].insert(word);
}
}
 }
diff --git a/src/Text.cpp b/src/Text.cpp
index c4cac88..cdcc200 100644
--- a/src/Text.cpp
+++ b/src/Text.cpp
@@ -2120,7 +2120,7 @@ bool Text::completionSupported(Cursor const & cur) const
 
 CompletionList const * Text::createCompletionList(Cursor const & cur) const
 {
-   WordList const * list = theWordList(*cur.getFont().language());
+   WordList const * list = theWordList(cur.getFont().language()->lang());
return new TextCompletionList(cur, list);
 }
 
diff --git a/src/WordList.cpp b/src/WordList.cpp
index 762e1b9..3a095af 100644
--- a/src/WordList.cpp
+++ b/src/WordList.cpp
@@ -12,14 +12,11 @@
 
 #include "WordList.h"
 
-#include "Language.h"
-
 #include "support/convert.h"
 #include "support/debug.h"
 #include "support/docstring.h"
-#include "support/weighted_btree.h"
-
 #include "support/lassert.h"
+#include "support/weighted_btree.h"
 
 #include 
 
@@ -28,12 +25,13 @@ using namespace std;
 namespace lyx {
 
 ///
-map<Language, WordList *> theGlobalWordList;
+typedef map<string, WordList *> GlobalWordList;
+GlobalWordList theGlobalWordList;
 
 
-WordList * theWordList(Language const & lang)
+WordList * theWordList(string const & lang)
 {
-   map<Language, WordList *>::iterator it = theGlobalWordList.find(lang);
+   GlobalWordList::iterator it = theGlobalWordList.find(lang);
if (it != theGlobalWordList.end())
return it->second;
else
@@ -44,7 +42,7 @@ WordList * theWordList(Language const & lang)
 
 void WordList::cleanupWordLists()
 {
-   map<Language, WordList *>::const_iterator it = 
theGlobalWordList.begin();
+   GlobalWordList::const_iterator it = theGlobalWordList.begin();
for (; it != theGlobalWordList.end(); ++it)
delete it->second;
theGlobalWordList.clear();
diff --git a/src/WordList.h b/src/WordList.h
index b7f88fb..f57f20b 100644
--- a/src/WordList.h
+++ b/src/WordList.h
@@ -14,8 +14,6 @@
 
 #include "support/docstring.h"
 
-#include "Language.h"
-
 namespace lyx {
 
 class WordList {
@@ -41,7 +39,7 @@ private:
Impl * d;
 };
 
-WordList * theWordList(Language const & lang);
+WordList * theWordList(std::string const & lang);
 
 } // namespace lyx
 


[LyX/2.1.1-staging] Do not store Languages objects in completion words lists

2014-03-26 Thread Jean-Marc Lasgouttes
commit 531e46f2b863395368d4765ece07ba5bfb93a340
Author: Jean-Marc Lasgouttes <lasgout...@lyx.org>
Date:   Fri Mar 21 12:24:47 2014 +0100

Do not store Languages objects in completion words lists

In the current code each paragraph contains a map<Language,
WordList*>, which means that it contains a full copy of the language
object. Since these objects contain translation tables nowadays, this
is a very bad idea.

This patch simply replaces the Language key by a string.

When loading the Userguide on linux/x86_64, the total memory
consumption decreases from 36.27MB to 31.50MB.

diff --git a/src/LyX.cpp b/src/LyX.cpp
index 41c69f7..b784831 100644
--- a/src/LyX.cpp
+++ b/src/LyX.cpp
@@ -33,6 +33,7 @@
 #include "FuncStatus.h"
 #include "HunspellChecker.h"
 #include "KeyMap.h"
+#include "Language.h"
 #include "LaTeXFonts.h"
 #include "LayoutFile.h"
 #include "Lexer.h"
diff --git a/src/Paragraph.cpp b/src/Paragraph.cpp
index ffcb5f2..4d9b37c 100644
--- a/src/Paragraph.cpp
+++ b/src/Paragraph.cpp
@@ -499,7 +499,7 @@ public:
TextContainer text_;
 
typedef set Words;
-   typedef map<Language, Words> LangWordsMap;
+   typedef map<string, Words> LangWordsMap;
///
LangWordsMap words_;
///
@@ -3867,7 +3867,7 @@ void Paragraph::collectWords()
if (cit == d->fontlist_.end())
return;
Language const * lang = cit->font().language();
-   d->words_[*lang].insert(word);
+   d->words_[lang->lang()].insert(word);
}
}
 }
diff --git a/src/Text.cpp b/src/Text.cpp
index c4cac88..cdcc200 100644
--- a/src/Text.cpp
+++ b/src/Text.cpp
@@ -2120,7 +2120,7 @@ bool Text::completionSupported(Cursor const & cur) const
 
 CompletionList const * Text::createCompletionList(Cursor const & cur) const
 {
-   WordList const * list = theWordList(*cur.getFont().language());
+   WordList const * list = theWordList(cur.getFont().language()->lang());
return new TextCompletionList(cur, list);
 }
 
diff --git a/src/WordList.cpp b/src/WordList.cpp
index 762e1b9..3a095af 100644
--- a/src/WordList.cpp
+++ b/src/WordList.cpp
@@ -12,14 +12,11 @@
 
 #include "WordList.h"
 
-#include "Language.h"
-
 #include "support/convert.h"
 #include "support/debug.h"
 #include "support/docstring.h"
-#include "support/weighted_btree.h"
-
 #include "support/lassert.h"
+#include "support/weighted_btree.h"
 
 #include 
 
@@ -28,12 +25,13 @@ using namespace std;
 namespace lyx {
 
 ///
-map<Language, WordList *> theGlobalWordList;
+typedef map<string, WordList *> GlobalWordList;
+GlobalWordList theGlobalWordList;
 
 
-WordList * theWordList(Language const & lang)
+WordList * theWordList(string const & lang)
 {
-   map<Language, WordList *>::iterator it = theGlobalWordList.find(lang);
+   GlobalWordList::iterator it = theGlobalWordList.find(lang);
if (it != theGlobalWordList.end())
return it->second;
else
@@ -44,7 +42,7 @@ WordList * theWordList(Language const & lang)
 
 void WordList::cleanupWordLists()
 {
-   map<Language, WordList *>::const_iterator it = 
theGlobalWordList.begin();
+   GlobalWordList::const_iterator it = theGlobalWordList.begin();
for (; it != theGlobalWordList.end(); ++it)
delete it->second;
theGlobalWordList.clear();
diff --git a/src/WordList.h b/src/WordList.h
index b7f88fb..f57f20b 100644
--- a/src/WordList.h
+++ b/src/WordList.h
@@ -14,8 +14,6 @@
 
 #include "support/docstring.h"
 
-#include "Language.h"
-
 namespace lyx {
 
 class WordList {
@@ -41,7 +39,7 @@ private:
Impl * d;
 };
 
-WordList * theWordList(Language const & lang);
+WordList * theWordList(std::string const & lang);
 
 } // namespace lyx
 
diff --git a/status.21x b/status.21x
index 4c647a9..1394ef4 100644
--- a/status.21x
+++ b/status.21x
@@ -83,6 +83,7 @@ What's new
 
 - Fix a problem when PATH changes and python command is relative (bug 8950).
 
+- Reduce memory use with large documents.
  
 
 * DOCUMENTATION AND LOCALIZATION


[LyX/2.2-staging] Fix oversight in autotools packaging selection

2014-03-31 Thread Jean-Marc Lasgouttes
commit 8ce47ecdc85e89b1ee29524099140eff47a68120
Author: Jean-Marc Lasgouttes <lasgout...@lyx.org>
Date:   Thu Mar 27 13:51:25 2014 +0100

Fix oversight in autotools packaging selection

The only consequence of this thinko is that the lyx.desktop and the svg 
icons were installed on Mac OS and Windows platform, whereas they are useless.

diff --git a/config/lyxinclude.m4 b/config/lyxinclude.m4
index d1b78f9..61ea48d 100644
--- a/config/lyxinclude.m4
+++ b/config/lyxinclude.m4
@@ -463,6 +463,7 @@ AC_ARG_WITH(packaging,
   *) lyx_use_packaging=posix;;
   esac])
 AC_MSG_RESULT($lyx_use_packaging)
+lyx_install_posix=false
 lyx_install_macosx=false
 lyx_install_cygwin=false
 lyx_install_windows=false


[LyX features/str-metrics] Fix various selection-related problems

2014-04-07 Thread Jean-Marc Lasgouttes
The branch, str-metrics, has been updated.

- Log -

commit 14f8a24b4aeeb4671a3117fb79ba56343a022f0e
Author: Jean-Marc Lasgouttes <lasgout...@lyx.org>
Date:   Fri Mar 21 11:56:42 2014 +0100

Fix various selection-related problems

All these problems are related to what happens at the extreme points of rows

 * since VIRTUAL elements have a width but no contents, they have to
   be treated specially at some places. It would have been better to
   avoid testing for them explicitly, but I did not find a way.

 * Improve and cleanup the code in breakRow and fix in passing a crash
   when clicking on the right of an incomplete MARGIN_MANUAL
   paragraph.

 * improve the computation of row width in TextMetrics::computeRowMetrics.

 * handle properly the case where a position if not found on the row
   in both cursorX and getPosNearX (actually, this happens when
   selecting).

 * Some code cleanup and comments.

diff --git a/00README_STR_METRICS_BRANCH b/00README_STR_METRICS_BRANCH
index 1bb7026..82026e8 100644
--- a/00README_STR_METRICS_BRANCH
+++ b/00README_STR_METRICS_BRANCH
@@ -44,18 +44,16 @@ What is done:
 Next steps:
 
 * check what happens with Arabic and/or Hebrew text. There may be some
-  problems related to compose characters. I suspect that some code is
-  needed in FontMetrics::width.
+  problems related to compose characters. Investigate whether RtL
+  strings could be drawn on a string-wise basis.
 
-* investigate whether RtL strings could be drawn on a string-wise basis.
-
-* investigate whether Row::SEPARATOR elements could be used only in
-  justified text. This would speed-up painting in other cases by
-  lowering the number of strings to draw.
+* investigate whether strings could be cut at separators in RowPainter
+  only in justified text. This would speed-up painting in other cases
+  by lowering the number of strings to draw.
 
 * get lots of testing.
 
-* Get rid of old code in cursorX and getColumnNearX; it has been
+* Get rid of old code in cursorX and getPosNearX; it has been
   kept for comparison purpose, guarded with KEEP_OLD_METRICS_CODE in
   order to check computations.
 
@@ -67,33 +65,38 @@ Steps for later (aka out of the scope of this branch):
 * Re-implement row painting using row elements. This is not difficult
   in principle, but the code is intricate and needs some careful
   analysis. The first thing that needs to be done is to break row
-  elements with the same criteria. Currently TextMetrics::breakRow
-  does not consider on-the-fly spell-checking and selection changes,
-  but it is not clear to me that it is required. Moreover, this thing
-  would only work if we are sure that the Row object is up-to-date
-  when drawing happens. This depends on the update machinery.
+  elements with the same criteria. Currently breakRow does not
+  consider on-the-fly spell-checking and selection changes, but it is
+  not clear to me that it is required. Moreover, this thing would only
+  work if we are sure that the Row object is up-to-date when drawing
+  happens. This depends on the update machinery.
 
   This would allow to get rid of the Bidi code.
 
 
 Known bugs:
 
-* in RtL paragraphs, the end-of-paragraph marker moves the row to the
-  right (ticket #9040, already present in master).
-
 * there are still difference in what breaks words. In particular,
   RowPainter breaks strings at: selection end, spell-checking
   extremities. This seems to be harmless.
 
-* when clicking in the right margin, GetColumnNearX does not return
+* when clicking in the right margin, getPosNearX does not return
   the same value as before. I am not sure whether this is important.
 
+* When selecting text, the display seems to move around. This is
+  because partly selected words are drawn in two parts, and in case
+  like "ef|fort" or "V|AN", there are some ligature or kerning effects
+  that change the display. I am not sure yet how to fix that.
+
 
 Other differences in behavior (aka bug fixes):
 
 * end of paragraph markers metrics are computed with the font of the
   actual text, not default font.
 
+* in RtL paragraphs, the end-of-paragraph marker does not move the row
+  to the right anymore (ticket #9040).
+
 * When cursor is after a LtR separator just before a RtL chunk, the
   cursor position is computed better with the new code.
 
diff --git a/src/Row.cpp b/src/Row.cpp
index 6e60e97..48b4fff 100644
--- a/src/Row.cpp
+++ b/src/Row.cpp
@@ -63,18 +63,19 @@ double Row::Element::pos2x(pos_type const i) const
 pos_type Row::Element::x2pos(double , bool const low) const
 {
//lyxerr << "x2pos: x=" << x << " w=" << width() << " " << *this;
-   // if element is rtl, flip x value
+   // If element is rtl, flip x value
bool const rtl = font.isVi

Re: [LyX/master] Update INSTALL

2014-04-10 Thread Jean-Marc Lasgouttes

Le 10/04/14 22:37, Vincent van Ravesteijn a écrit :

  * Other things to note

-If you make modifications to files in src/ (for example by applying a
-patch), you will need to have the GNU gettext package installed, due
-to some dependencies in the makefiles. You can get the latest version
-from:
-   ftp://ftp.gnu.org/gnu/gettext/


Are you sure? I think I left this part because of the gettext tools that 
create the .gmo files. I agree though that the description as it was is 
not really useful.


JMarc



[LyX features/str-metrics] Draw right-to-left text string-wise using Qt

2014-04-17 Thread Jean-Marc Lasgouttes
The branch, str-metrics, has been updated.

- Log -

commit b792eff2d6bd70f877ea217bccfd60893e7bd3ad
Author: Jean-Marc Lasgouttes <lasgout...@lyx.org>
Date:   Thu Apr 10 16:37:21 2014 +0200

Draw right-to-left text string-wise using Qt

We rely on Qt built-in unicode support for handling Arabic and Hebrew
compose characters. This allows to avoid to use our homegrown
machinery.

This  should provide a nice speedup at a low cost and
will eventually allow us to get rid of:
 * most of our Arabic/Hebrew machinery in Encodings.cpp,
 * Paragraph::transformChar,
 * and probably more.

diff --git a/00README_STR_METRICS_BRANCH b/00README_STR_METRICS_BRANCH
index 82026e8..359bb03 100644
--- a/00README_STR_METRICS_BRANCH
+++ b/00README_STR_METRICS_BRANCH
@@ -11,7 +11,7 @@ what we have with force_paint_single_char. Moreover there has 
been
 some code factorization in TextMetrics, where the same row-breaking
 algorithm was basically implemented 3 times.
 
-Currently everything is supposed to work for LTR text, and RTL text
+Currently everything is supposed to work for LTR text, and RtL text
 should work too except possibly metrics with Arabic and Hebrew fonts.
 
 When KEEP_OLD_METRICS_CODE is defined in TextMetrics.cpp, the new code
@@ -40,12 +40,13 @@ What is done:
   lyxrc.force_paint_single_char is false. In this case, remove also
   useless workarounds which disable kerning and ligatures.
 
+* when lyxrc.force_paint_single_char is false, draw also RtL text
+  string-wise. This both speed-up drawing and prepare for code
+  removal, since we now rely on Qt to do things we use to do by
+  ourselves (see isArabic* and isHebrew* code in Encodings.cpp).
 
-Next steps:
 
-* check what happens with Arabic and/or Hebrew text. There may be some
-  problems related to compose characters. Investigate whether RtL
-  strings could be drawn on a string-wise basis.
+Next steps:
 
 * investigate whether strings could be cut at separators in RowPainter
   only in justified text. This would speed-up painting in other cases
@@ -76,18 +77,18 @@ Steps for later (aka out of the scope of this branch):
 
 Known bugs:
 
-* there are still difference in what breaks words. In particular,
-  RowPainter breaks strings at: selection end, spell-checking
-  extremities. This seems to be harmless.
-
-* when clicking in the right margin, getPosNearX does not return
-  the same value as before. I am not sure whether this is important.
-
 * When selecting text, the display seems to move around. This is
   because partly selected words are drawn in two parts, and in case
   like "ef|fort" or "V|AN", there are some ligature or kerning effects
   that change the display. I am not sure yet how to fix that.
 
+* there are other differences in what breaks words. In particular,
+  RowPainter breaks strings at spell-checking extremities. This seems
+  to be harmless.
+
+* when clicking in the right margin, getPosNearX does not return
+  the same value as before. I am not sure whether this is important.
+
 
 Other differences in behavior (aka bug fixes):
 
diff --git a/src/Encoding.cpp b/src/Encoding.cpp
index a231106..7167d7b 100644
--- a/src/Encoding.cpp
+++ b/src/Encoding.cpp
@@ -704,6 +704,12 @@ docstring Encodings::fromLaTeXCommand(docstring const & 
cmd, int cmdtype,
 }
 
 
+bool Encodings::isHebrewChar(char_type c)
+{
+   return c >= 0x0590 && c <= 0x05ff;
+}
+
+
 bool Encodings::isHebrewComposeChar(char_type c)
 {
return c <= 0x05c2 && c >= 0x05b0 && c != 0x05be && c != 0x05c0;
diff --git a/src/Encoding.h b/src/Encoding.h
index 5f788f9..171b4f1 100644
--- a/src/Encoding.h
+++ b/src/Encoding.h
@@ -269,6 +269,8 @@ public:
///
static bool isHebrewComposeChar(char_type c);
///
+   static bool isHebrewChar(char_type c);
+   ///
static bool isArabicComposeChar(char_type c);
///
static bool isArabicSpecialChar(char_type c);
diff --git a/src/rowpainter.cpp b/src/rowpainter.cpp
index 5b69701..ea0f946 100644
--- a/src/rowpainter.cpp
+++ b/src/rowpainter.cpp
@@ -161,72 +161,7 @@ void RowPainter::paintInset(Inset const * inset, pos_type 
const pos)
 }
 
 
-void RowPainter::paintHebrewComposeChar(pos_type & vpos, FontInfo const & font)
-{
-   pos_type pos = bidi_.vis2log(vpos);
-
-   docstring str;
-
-   // first char
-   char_type c = par_.getChar(pos);
-   str += c;
-   ++vpos;
-
-   int const width = theFontMetrics(font).width(c);
-   int dx = 0;
-
-   for (pos_type i = pos - 1; i >= 0; --i) {
-   c = par_.getChar(i);
-   if (!Encodings::isHebrewComposeChar(c)) {
-   if (isPrintableNonspace(c)) {
-   int const width2 = pm_.singleWidth(i,
-   text_metrics

[LyX/master] Respect group integrity when removing stuff from the Undo stack.

2014-04-20 Thread Jean-Marc Lasgouttes
commit 4356f2254af1a0ea5e4215e29881296452b1e8d9
Author: Jean-Marc Lasgouttes <lasgout...@lyx.org>
Date:   Mon Apr 7 16:46:47 2014 +0200

Respect group integrity when removing stuff from the Undo stack.

Fixes: #9079

diff --git a/src/Undo.cpp b/src/Undo.cpp
index a335873..31eaec3 100644
--- a/src/Undo.cpp
+++ b/src/Undo.cpp
@@ -160,13 +160,17 @@ public:
/// Push an item on to the stack, deleting the bottom group on
/// overflow.
void push(UndoElement const & v) {
-   c_.push_front(v);
-   if (c_.size() > limit_) {
+   // Remove some entries if the limit has been reached.
+   // However, if the only group on the stack is the one
+   // we are currently populating, do nothing.
+   if (c_.size() >= limit_
+   && c_.front().group_id != v.group_id) {
// remove a whole group at once.
const size_t gid = c_.back().group_id;
while (!c_.empty() && c_.back().group_id == gid)
c_.pop_back();
}
+   c_.push_front(v);
}
 
/// Mark all the elements of the stack as dirty


[LyX/2.2-staging] Use subdir-objects for automake 1.14 or newer

2014-04-20 Thread Jean-Marc Lasgouttes
commit 330b4fbf5caddba022b1d86676c839ba31ecaa8e
Author: Jean-Marc Lasgouttes <lasgout...@lyx.org>
Date:   Sun Apr 20 20:20:25 2014 +0200

Use subdir-objects for automake 1.14 or newer

This option is going to be mandatory starting with automake 2.0.
LyX is able to use this since version 2.1, but it turns out that it is
badly implemented in versions of automake older than 1.14.

We rely on some (undocumented) symbol to detect automake 1.14 and
use the subdirs-objects option in this case.

For more details, see:
https://www.mail-archive.com/lyx-devel@lists.lyx.org/msg181023.html

Making everything work with autotools required making a copy of two
files from support/tests. It seems that we should not point to source files
that are handled by another Makefile.am.

diff --git a/configure.ac b/configure.ac
index 1fe6d9d..1dcb8fd 100644
--- a/configure.ac
+++ b/configure.ac
@@ -27,7 +27,11 @@ fi
 AM_MAINTAINER_MODE
 
 save_PACKAGE=$PACKAGE
-AM_INIT_AUTOMAKE([foreign dist-bzip2 no-define 1.8])
+dnl The test for _AM_PROG_CC_C_O intends to test for automake 1.14 or newer,
+dnl which are the versions where subdir-objects can beused.
+dnl see: https://www.mail-archive.com/lyx-devel@lists.lyx.org/msg181023.html
+m4_define([LYX_OBJECTS_LAYOUT], m4_ifdef([_AM_PROG_CC_C_O],[subdir-objects],))
+AM_INIT_AUTOMAKE([foreign dist-bzip2 no-define 1.8] LYX_OBJECTS_LAYOUT)
 m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])])
 PACKAGE=$save_PACKAGE
 
diff --git a/src/Makefile.am b/src/Makefile.am
index ea5ca42..2a98643 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -708,7 +708,7 @@ check_layout_SOURCES = \
Spacing.cpp \
TextClass.cpp \
tests/check_layout.cpp \
-   support/tests/boost.cpp \
-   support/tests/dummy_functions.cpp
+   tests/boost.cpp \
+   tests/dummy_functions.cpp
 
 .PHONY: alltests alltests-recursive updatetests
diff --git a/src/tests/CMakeLists.txt b/src/tests/CMakeLists.txt
index 2a8b39e..ce5b355 100644
--- a/src/tests/CMakeLists.txt
+++ b/src/tests/CMakeLists.txt
@@ -8,7 +8,7 @@ set(check_layout_SOURCES)
 foreach(_f insets/InsetLayout.cpp Color.cpp Counters.cpp Floating.cpp
FloatList.cpp FontInfo.cpp Layout.cpp LayoutFile.cpp Lexer.cpp
ModuleList.cpp Spacing.cpp TextClass.cpp tests/check_layout.cpp
-   support/tests/boost.cpp support/tests/dummy_functions.cpp)
+   tests/boost.cpp tests/dummy_functions.cpp)
   list(APPEND check_layout_SOURCES "${TOP_SRC_DIR}/src/${_f}")
 endforeach()
 
diff --git a/src/tests/boost.cpp b/src/tests/boost.cpp
new file mode 100644
index 000..426263b
--- /dev/null
+++ b/src/tests/boost.cpp
@@ -0,0 +1,36 @@
+/**
+ * \file boost.cpp
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author Lars Gullik Bjønnes
+ *
+ * Full author contact details are available in file CREDITS.
+ */
+
+#include 
+
+#include "support/lassert.h"
+
+#include 
+#include 
+
+using namespace std;
+
+namespace boost {
+
+#ifndef BOOST_NO_EXCEPTIONS
+void throw_exception(exception const & /*e*/)
+{
+   LASSERT(false, /**/);
+}
+#endif
+
+
+void assertion_failed(char const * /*expr*/, char const * /*function*/,
+ char const * /*file*/, long /*line*/)
+{
+   ::abort();
+}
+
+} // namespace boost
diff --git a/src/tests/dummy_functions.cpp b/src/tests/dummy_functions.cpp
new file mode 100644
index 000..5a99081
--- /dev/null
+++ b/src/tests/dummy_functions.cpp
@@ -0,0 +1,38 @@
+#include 
+
+#include "../Messages.h"
+
+using namespace std;
+
+namespace lyx {
+   // Dummy LyXRC support
+   class LyXRC { string icon_set; } lyxrc;
+
+   // Dummy LyXAlignment support
+   enum LyXAlignment {
+   DUMMY
+   };
+
+   // Keep the linker happy on Windows
+   void lyx_exit(int) {}
+
+   // Dummy language support
+   Messages const & getGuiMessages()
+   {
+   static Messages lyx_messages;
+
+   return lyx_messages;
+   }
+   Messages const & getMessages(string const &)
+   {
+   static Messages lyx_messages;
+
+   return lyx_messages;
+   }
+
+   string alignmentToCSS(LyXAlignment)
+   {
+   return string();
+   }
+
+}


[LyX/2.1.x] Respect group integrity when removing stuff from the Undo stack.

2014-04-20 Thread Jean-Marc Lasgouttes
commit 6bce9abfee581c5ca03670a5b7f8e50dd911d83e
Author: Jean-Marc Lasgouttes <lasgout...@lyx.org>
Date:   Mon Apr 7 16:46:47 2014 +0200

Respect group integrity when removing stuff from the Undo stack.

Fixes: #9079

diff --git a/src/Undo.cpp b/src/Undo.cpp
index a335873..31eaec3 100644
--- a/src/Undo.cpp
+++ b/src/Undo.cpp
@@ -160,13 +160,17 @@ public:
/// Push an item on to the stack, deleting the bottom group on
/// overflow.
void push(UndoElement const & v) {
-   c_.push_front(v);
-   if (c_.size() > limit_) {
+   // Remove some entries if the limit has been reached.
+   // However, if the only group on the stack is the one
+   // we are currently populating, do nothing.
+   if (c_.size() >= limit_
+   && c_.front().group_id != v.group_id) {
// remove a whole group at once.
const size_t gid = c_.back().group_id;
while (!c_.empty() && c_.back().group_id == gid)
c_.pop_back();
}
+   c_.push_front(v);
}
 
/// Mark all the elements of the stack as dirty
diff --git a/status.21x b/status.21x
index add6a75..8e794d3 100644
--- a/status.21x
+++ b/status.21x
@@ -80,6 +80,8 @@ What's new
 
 - Fix select-by-doubleclick in mathed (bug 8829).
 
+- Fix undo with many individual changes (e.g. with replace all)
+  (bug #7079).
 
 
 * INTERNALS


[LyX features/str-metrics] Speed-up drawing when text is not justified.

2014-05-02 Thread Jean-Marc Lasgouttes
The branch, str-metrics, has been updated.

- Log -

commit 37494dfbccb8c0d9a66cedd059efc39903c44385
Author: Jean-Marc Lasgouttes <lasgout...@lyx.org>
Date:   Fri May 2 15:03:20 2014 +0200

Speed-up drawing when text is not justified.

Do not cut strings at separators in RowPainter when text is not
justified. This speeds-up painting by reducing the number of strings
to draw.

Do also a modest cleanup of paintChar (remove dubious optimization).

diff --git a/00README_STR_METRICS_BRANCH b/00README_STR_METRICS_BRANCH
index e7a6f29..73f5ed3 100644
--- a/00README_STR_METRICS_BRANCH
+++ b/00README_STR_METRICS_BRANCH
@@ -40,16 +40,16 @@ What is done:
   useless workarounds which disable kerning and ligatures.
 
 * when lyxrc.force_paint_single_char is false, draw also RtL text
-  string-wise. This both speed-up drawing and prepare for code
+  string-wise. This both speeds-up drawing and prepares for code
   removal, since we now rely on Qt to do things we use to do by
   ourselves (see isArabic* and isHebrew* code in Encodings.cpp).
 
+* Do not cut strings at separators in RowPainter when text is not
+  justified. This speeds-up painting by reducing the number of strings
+  to draw.
 
-Next steps:
 
-* investigate whether strings could be cut at separators in RowPainter
-  only in justified text. This would speed-up painting in other cases
-  by lowering the number of strings to draw.
+Next steps:
 
 * get lots of testing.
 
diff --git a/src/rowpainter.cpp b/src/rowpainter.cpp
index b0708bf..8286ec7 100644
--- a/src/rowpainter.cpp
+++ b/src/rowpainter.cpp
@@ -165,10 +165,9 @@ void RowPainter::paintChars(pos_type & vpos, Font const & 
font)
// This method takes up 70% of time when typing
pos_type pos = bidi_.vis2log(vpos);
// first character
-   char_type prev_char = par_.getChar(pos);
-   vector str;
+   char_type c = par_.getChar(pos);
+   docstring str;
str.reserve(100);
-   str.push_back(prev_char);
 
// special case for arabic
string const & lang = font.language()->lang();
@@ -179,13 +178,12 @@ void RowPainter::paintChars(pos_type & vpos, Font const & 
font)
// FIXME: Why only round brackets and why the difference to
// Hebrew? See also Paragraph::getUChar
if (swap_paren) {
-   char_type c = str[0];
if (c == '(')
c = ')';
else if (c == ')')
c = '(';
-   str[0] = c;
}
+   str.push_back(c);
 
pos_type const end = row_.endpos();
FontSpan const font_span = par_.fontSpan(pos);
@@ -230,7 +228,8 @@ void RowPainter::paintChars(pos_type & vpos, Font const & 
font)
if (c == '\t')
break;
 
-   if (!isPrintableNonspace(c))
+   if (!isPrintableNonspace(c)
+   && (c != ' ' || row_.separator > 0))
break;
 
// FIXME: Why only round brackets and why the difference to
@@ -243,13 +242,10 @@ void RowPainter::paintChars(pos_type & vpos, Font const & 
font)
}
 
str.push_back(c);
-   prev_char = c;
}
 
-   docstring s([0], str.size());
-
-   if (s[0] == '\t')
-   s.replace(0,1,from_ascii(""));
+   if (str[0] == '\t')
+   str.replace(0,1,from_ascii(""));
 
/* Because we do our own bidi, at this point the strings are
 * already in visual order. However, Qt also applies its own
@@ -267,13 +263,13 @@ void RowPainter::paintChars(pos_type & vpos, Font const & 
font)
// Pop directional formatting: return to previous state
char_type const PDF = 0x202C;
if (font.isVisibleRightToLeft()) {
-   reverse(s.begin(), s.end());
-   s = RLO + s + PDF;
+   reverse(str.begin(), str.end());
+   str = RLO + str + PDF;
} else
-   s = LRO + s + PDF;
+   str = LRO + str + PDF;
 
if (!selection && !change_running.changed()) {
-   x_ += pi_.pain.text(int(x_), yo_, s, font.fontInfo());
+   x_ += pi_.pain.text(int(x_), yo_, str, font.fontInfo());
return;
}
 
@@ -283,7 +279,7 @@ void RowPainter::paintChars(pos_type & vpos, Font const & 
font)
else if (selection)
copy.setPaintColor(Color_selectiontext);
 
-   x_ += pi_.pain.text(int(x_), yo_, s, copy);
+   x_ += pi_.pain.text(int(x_), yo_, str, copy);
 }
 
 

---

Summary of changes:
 00README_STR_METRICS_BRANCH |   10 +-
 src/rowpainter.cpp  |   28 
 2 files changed, 17 insertions(+), 21 deletions(-)


hooks/post-receive
-- 
Repository for new features


[LyX/master] Cleanup the code for boost configuration

2014-05-05 Thread Jean-Marc Lasgouttes
commit 3cbd343a55780dc646833bc3a1d3373909e950ca
Author: Jean-Marc Lasgouttes <lasgout...@lyx.org>
Date:   Mon Apr 21 16:10:49 2014 +0200

Cleanup the code for boost configuration

diff --git a/config/common.am b/config/common.am
index 6f7e310..cabc35a 100644
--- a/config/common.am
+++ b/config/common.am
@@ -28,14 +28,4 @@ endif
 
 SUFFIXES = .gch
 
-if USE_INCLUDED_BOOST
-BOOST_INCLUDES = -I$(top_srcdir)/boost
-BOOST_LIBS = $(top_builddir)/boost/liblyxboost.a
-else
-BOOST_INCLUDES =
-BOOST_REGEX = -lboost_regex$(BOOST_MT)
-BOOST_SIGNALS = -lboost_signals$(BOOST_MT)
-BOOST_LIBS = $(BOOST_REGEX) $(BOOST_SIGNALS)
-endif
-
 LIBS =
diff --git a/config/lyxinclude.m4 b/config/lyxinclude.m4
index 61ea48d..ac0b642 100644
--- a/config/lyxinclude.m4
+++ b/config/lyxinclude.m4
@@ -311,28 +311,39 @@ AC_DEFUN([LYX_USE_INCLUDED_BOOST],[
[lyx_cv_with_included_boost=yes])
AM_CONDITIONAL(USE_INCLUDED_BOOST, test x$lyx_cv_with_included_boost = 
xyes)
AC_MSG_RESULT([$lyx_cv_with_included_boost])
-   if test x$lyx_cv_with_included_boost != xyes ; then
-   AC_LANG_PUSH(C++)
-   save_LIBS=$LIBS
-
-   LIBS="$save_LIBS -lboost_signals -lm"
-   AC_LINK_IFELSE([AC_LANG_PROGRAM([#include ], 
[boost::signal s;])], [lyx_boost_plain=yes], [])
-   LIBS="$save_LIBS -lboost_signals-mt -lm $LIBTHREAD"
-   AC_LINK_IFELSE([AC_LANG_PROGRAM([#include ], 
[boost::signal s;])], [lyx_boost_mt=yes], [])
-
-   LIBS=$save_LIBS
-   AC_LANG_POP(C++)
-
-   if test x$lyx_boost_mt = xyes ; then
-   BOOST_MT="-mt"
-   else
-   BOOST_MT=""
-   if test x$lyx_boost_plain != xyes ; then
-   AC_MSG_ERROR([cannot find suitable boost 
library (do not use --without-included-boost)])
-   fi
-   fi
-   AC_SUBST(BOOST_MT)
+   if test x$lyx_cv_with_included_boost = xyes ; then
+   BOOST_INCLUDES='-I$(top_srcdir)/boost'
+   BOOST_LIBS='$(top_builddir)/boost/liblyxboost.a'
+   else
+   AC_LANG_PUSH(C++)
+   save_LIBS=$LIBS
+
+   AC_MSG_CHECKING([for multithreaded boost libraries])
+   LIBS="$save_LIBS -lboost_signals-mt -lm $LIBTHREAD"
+   AC_LINK_IFELSE(
+   [AC_LANG_PROGRAM([#include ],
+   [boost::signal s;])],
+   [AC_MSG_RESULT([yes])
+BOOST_MT="-mt"],
+   [AC_MSG_RESULT([no])
+AC_MSG_CHECKING([for plain boost libraries])
+LIBS="$save_LIBS -lboost_signals -lm"
+AC_LINK_IFELSE(
+[AC_LANG_PROGRAM([#include ],
+[boost::signal s;])],
+[AC_MSG_RESULT([yes])
+ BOOST_MT=""],
+[AC_MSG_RESULT([no])
+ AC_MSG_ERROR([cannot find suitable boost library (do not 
use --without-included-boost)])
+])
+   ])
+   LIBS=$save_LIBS
+   AC_LANG_POP(C++)
+   BOOST_INCLUDES=
+   BOOST_LIBS="-lboost_regex${BOOST_MT} -lboost_signals${BOOST_MT}"
fi
+   AC_SUBST(BOOST_INCLUDES)
+   AC_SUBST(BOOST_LIBS)
 ])
 
 


[LyX/master] Turn an error message into a Debug::LOCALE warning

2014-05-06 Thread Jean-Marc Lasgouttes
commit ac9a2fa9f8eea4afc9d5afee48328b900838aa34
Author: Jean-Marc Lasgouttes <lasgout...@lyx.org>
Date:   Tue May 6 14:29:42 2014 +0200

Turn an error message into a Debug::LOCALE warning

diff --git a/src/support/Messages.cpp b/src/support/Messages.cpp
index ef6bb2d..fd5d228 100644
--- a/src/support/Messages.cpp
+++ b/src/support/Messages.cpp
@@ -250,7 +250,7 @@ bool Messages::readMoFile()
 
string const code = realCode(lang_);
if (code.empty()) {
-   LYXERR0("Cannot find translation for language " << lang_);
+   LYXERR(Debug::LOCALE, "Cannot find translation for language " 
<< lang_);
return false;
}
 


[LyX/2.1.x] Turn an error message into a Debug::LOCALE warning

2014-05-06 Thread Jean-Marc Lasgouttes
commit bd206ff5f5b2902ef87baa27c359f7a1b58f418d
Author: Jean-Marc Lasgouttes <lasgout...@lyx.org>
Date:   Tue May 6 14:29:42 2014 +0200

Turn an error message into a Debug::LOCALE warning

diff --git a/src/support/Messages.cpp b/src/support/Messages.cpp
index ef6bb2d..fd5d228 100644
--- a/src/support/Messages.cpp
+++ b/src/support/Messages.cpp
@@ -250,7 +250,7 @@ bool Messages::readMoFile()
 
string const code = realCode(lang_);
if (code.empty()) {
-   LYXERR0("Cannot find translation for language " << lang_);
+   LYXERR(Debug::LOCALE, "Cannot find translation for language " 
<< lang_);
return false;
}
 
diff --git a/status.21x b/status.21x
index 7a6b793..87cac02 100644
--- a/status.21x
+++ b/status.21x
@@ -117,6 +117,9 @@ What's new
 - Fix a problem when PATH changes and python command is relative (bug 8950).
 
 - Reduce memory use with large documents.
+
+- Disable a console message when loading a document in a language for
+  which the UI is not translated.
  
 
 * DOCUMENTATION AND LOCALIZATION


[LyX/master] Rely on Qt to handle small caps text

2014-05-07 Thread Jean-Marc Lasgouttes
commit 015333d987ae029aa1a6d3bcab3e96d70658a256
Author: Jean-Marc Lasgouttes <lasgout...@lyx.org>
Date:   Wed May 7 12:06:56 2014 +0200

Rely on Qt to handle small caps text

This has the advantage of simplifying our code and to produce the
correct output: the small capitals should have the exact same width as
the lower case letters.

The slanted fonts are also translated to oblique on Qt side, but this
does not seems to have an effect in my testing. It may be that proper
oblique fonts need to be installed.

diff --git a/src/frontends/qt4/GuiFontLoader.cpp 
b/src/frontends/qt4/GuiFontLoader.cpp
index 9fd2060..3d0f2b0 100644
--- a/src/frontends/qt4/GuiFontLoader.cpp
+++ b/src/frontends/qt4/GuiFontLoader.cpp
@@ -304,8 +304,13 @@ GuiFontInfo::GuiFontInfo(FontInfo const & f)
 
switch (f.realShape()) {
case ITALIC_SHAPE:
+   font.setStyle(QFont::StyleItalic);
+   break;
case SLANTED_SHAPE:
-   font.setItalic(true);
+   font.setStyle(QFont::StyleOblique);
+   break;
+   case SMALLCAPS_SHAPE:
+   font.setCapitalization(QFont::SmallCaps);
break;
default:
break;
@@ -327,19 +332,7 @@ GuiFontInfo::GuiFontInfo(FontInfo const & f)
 
LYXERR(Debug::FONT, "The font has size: " << font.pointSizeF());
 
-   if (f.realShape() != SMALLCAPS_SHAPE) {
-   metrics = GuiFontMetrics(font);
-   } else {
-   // handle small caps ourselves ...
-   FontInfo smallfont = f;
-   smallfont.decSize().decSize().setShape(UP_SHAPE);
-   QFont font2(font);
-   font2.setKerning(false);
-   
font2.setPointSizeF(convert(lyxrc.font_sizes[smallfont.size()])
-  * lyxrc.zoom / 100.0);
-
-   metrics = GuiFontMetrics(font, font2);
-   }
+   metrics = GuiFontMetrics(font);
 }
 
 
diff --git a/src/frontends/qt4/GuiFontMetrics.cpp 
b/src/frontends/qt4/GuiFontMetrics.cpp
index 9304465..e007b4a 100644
--- a/src/frontends/qt4/GuiFontMetrics.cpp
+++ b/src/frontends/qt4/GuiFontMetrics.cpp
@@ -40,7 +40,7 @@ namespace {
  * these are not real ucs4 characters. These are codepoints in the
  * computer modern fonts used, nothing unicode related.
  * See comment in QLPainter::text() for more explanation.
- **/   
+ **/
 inline QChar const ucs4_to_qchar(char_type const ucs4)
 {
LATTEST(is_utf16(ucs4));
@@ -49,14 +49,7 @@ inline QChar const ucs4_to_qchar(char_type const ucs4)
 } // anon namespace
 
 
-GuiFontMetrics::GuiFontMetrics(QFont const & font)
-: metrics_(font, 0), smallcaps_metrics_(font), smallcaps_shape_(false)
-{
-}
-
-
-GuiFontMetrics::GuiFontMetrics(QFont const & font, QFont const & 
smallcaps_font)
-: metrics_(font, 0), smallcaps_metrics_(smallcaps_font), smallcaps_shape_(true)
+GuiFontMetrics::GuiFontMetrics(QFont const & font) : metrics_(font, 0)
 {
 }
 
@@ -115,27 +108,6 @@ int GuiFontMetrics::rbearing(char_type c) const
 }
 
 
-int GuiFontMetrics::smallcapsWidth(char_type c) const
-{
-   // FIXME: Optimisation probably needed: we don't use the width cache.
-   if (is_utf16(c)) {
-   QChar const qc = ucs4_to_qchar(c);
-   QChar const uc = qc.toUpper();
-   if (qc != uc)
-   return smallcaps_metrics_.width(uc);
-   else
-   return metrics_.width(qc);
-   } else {
-   QString const s = toqstr(docstring(1, c));
-   QString const us = s.toUpper();
-   if (s != us)
-   return smallcaps_metrics_.width(us);
-   else
-   return metrics_.width(s);
-   }
-}
-
-
 int GuiFontMetrics::width(docstring const & s) const
 {
size_t ls = s.size();
@@ -145,10 +117,7 @@ int GuiFontMetrics::width(docstring const & s) const
/**
if isSurrogateBase(s[i]) {
docstring c = s[i];
-   if (smallcaps_shape_)
-   w += metrics_.width(toqstr(c + s[i + 1]));
-   else
-   w += smallcaps_metrics_.width(toqstr(c + s[i + 
1]));
+   w += metrics_.width(toqstr(c + s[i + 1]));
++i;
}
else
@@ -230,9 +199,6 @@ GuiFontMetrics::AscendDescend const 
GuiFontMetrics::fillMetricsCache(
 
 int GuiFontMetrics::width(char_type c) const
 {
-   if (smallcaps_shape_)
-   return smallcapsWidth(c);
-
int value = width_cache_.value(c, outOfLimitMetric);
if (value != outOfLimitMetric)
return value;
@@ -250,7 +216,7 @@ int GuiFontMetrics::width(char_type c) 

[LyX features/str-metrics] Update description of what has been done in the branch.

2014-05-12 Thread Jean-Marc Lasgouttes
The branch, str-metrics, has been updated.

- Log -

commit c8d3203da8ffa9e0547a06822a529b0b801144ee
Author: Jean-Marc Lasgouttes <lasgout...@lyx.org>
Date:   Mon May 12 11:02:22 2014 +0200

Update description of what has been done in the branch.

diff --git a/00README_STR_METRICS_BRANCH b/00README_STR_METRICS_BRANCH
index 73f5ed3..0ab1589 100644
--- a/00README_STR_METRICS_BRANCH
+++ b/00README_STR_METRICS_BRANCH
@@ -13,11 +13,8 @@ algorithm was basically implemented 3 times.
 
 Currently everything is supposed to work for both LTR and RTL text.
 
-When KEEP_OLD_METRICS_CODE is defined in TextMetrics.cpp, the new code
-is tested against the old one in getPosNearX and cursorX. This can be
-helpful when looking for discrepancies between the algorithms. Note
-that this only makes sense when force_paint_single_char=true, since
-this enforces char-by-char metrics computation.
+The bugs fixed and caused by this branch are tracked at ticket #9003:
+http://www.lyx.org/trac/ticket/9003
 
 What is done:
 
@@ -51,11 +48,11 @@ What is done:
 
 Next steps:
 
-* get lots of testing.
+* Fix bugs uncovered by testing.
 
-* Get rid of old code in cursorX and getPosNearX; it has been
-  kept for comparison purpose, guarded with KEEP_OLD_METRICS_CODE in
-  order to check computations.
+* Get rid of LyXRC::force_paint_single_char, which is only a workaround.
+
+* Maybe get rid of LyXRC::rtl_support, which does not have a real use case.
 
 * Profile and see how performance can be improved.
 
@@ -71,33 +68,6 @@ Steps for later (aka out of the scope of this branch):
   work if we are sure that the Row object is up-to-date when drawing
   happens. This depends on the update machinery.
 
-  This would allow to get rid of the Bidi code.
-
-
-Known bugs:
-
-* When selecting text, the display seems to move around. This is
-  because partly selected words are drawn in two parts, and in case
-  like "ef|fort" or "V|AN", there are some ligature or kerning effects
-  that change the display. I am not sure yet how to fix that.
-
-* there are other differences in what breaks words. In particular,
-  RowPainter breaks strings at spell-checking extremities. This seems
-  to be harmless.
-
-* when clicking in the right margin, getPosNearX does not return
-  the same value as before. I am not sure whether this is important.
-
-
-Other differences in behavior (aka bug fixes):
-
-* end of paragraph markers metrics are computed with the font of the
-  actual text, not default font.
-
-* in RtL paragraphs, the end-of-paragraph marker does not move the row
-  to the right anymore (ticket #9040).
-
-* When cursor is after a LtR separator just before a RtL chunk, the
-  cursor position is computed better with the new code.
+  This would allow to get rid of the Bidi.cpp code.
 
 

---

Summary of changes:
 00README_STR_METRICS_BRANCH |   44 ++
 1 files changed, 7 insertions(+), 37 deletions(-)


hooks/post-receive
-- 
Repository for new features


[LyX features/str-metrics] Remove support for LyXRC::force_paint_single_char

2014-05-14 Thread Jean-Marc Lasgouttes
The branch, str-metrics, has been updated.

- Log -

commit f5ed81b270502b31cf2a6969573dc7488714ea31
Author: Jean-Marc Lasgouttes <lasgout...@lyx.org>
Date:   Wed May 14 15:36:44 2014 +0200

Remove support for LyXRC::force_paint_single_char

This workaround is not necessary anymore, and it complicates the code.

The variable itself will be removed after the landing of the branch on
master.

diff --git a/00README_STR_METRICS_BRANCH b/00README_STR_METRICS_BRANCH
index 0ab1589..568ac8f 100644
--- a/00README_STR_METRICS_BRANCH
+++ b/00README_STR_METRICS_BRANCH
@@ -32,14 +32,16 @@ What is done:
 
 * Re-implement cursorX and getPosNearX using row elements.
 
-* Implement proper string metrics computation (with cache), when
-  lyxrc.force_paint_single_char is false. In this case, remove also
+* Do not honor lyxrc.force_paint_single_char anymore. This is a
+  workaround that is not necessary anymore.
+
+* Implement proper string metrics computation (with cache). Remove
   useless workarounds which disable kerning and ligatures.
 
-* when lyxrc.force_paint_single_char is false, draw also RtL text
-  string-wise. This both speeds-up drawing and prepares for code
-  removal, since we now rely on Qt to do things we use to do by
-  ourselves (see isArabic* and isHebrew* code in Encodings.cpp).
+* Draw also RtL text string-wise. This both speeds-up drawing and
+  prepares for code removal, since we now rely on Qt to do things we
+  use to do by ourselves (see isArabic* and isHebrew* code in
+  Encodings.cpp).
 
 * Do not cut strings at separators in RowPainter when text is not
   justified. This speeds-up painting by reducing the number of strings
@@ -50,7 +52,8 @@ Next steps:
 
 * Fix bugs uncovered by testing.
 
-* Get rid of LyXRC::force_paint_single_char, which is only a workaround.
+* Get rid of LyXRC::force_paint_single_char, which is not used anymore
+  in the source.
 
 * Maybe get rid of LyXRC::rtl_support, which does not have a real use case.
 
diff --git a/src/LyXRC.h b/src/LyXRC.h
index 14f73d9..405f935 100644
--- a/src/LyXRC.h
+++ b/src/LyXRC.h
@@ -551,7 +551,8 @@ public:
};
///
ScrollWheelZoom scroll_wheel_zoom;
-   ///
+   /// FIXME: this shall be removed, as the source does not refer
+   /// to it anymore.
bool force_paint_single_char;
///
int cursor_width;
diff --git a/src/frontends/qt4/GuiFontLoader.cpp 
b/src/frontends/qt4/GuiFontLoader.cpp
index 7f08817..d7c015f 100644
--- a/src/frontends/qt4/GuiFontLoader.cpp
+++ b/src/frontends/qt4/GuiFontLoader.cpp
@@ -165,8 +165,6 @@ QFont symbolFont(QString const & family, bool * ok)
upper[0] = family[0].toUpper();
 
QFont font;
-   if (lyxrc.force_paint_single_char)
-   font.setKerning(false);
font.setFamily(family);
 
if (isChosenFont(font, family)) {
@@ -257,8 +255,6 @@ static QString makeFontName(QString const & family, QString 
const & foundry)
 GuiFontInfo::GuiFontInfo(FontInfo const & f)
: metrics(QFont())
 {
-   if (lyxrc.force_paint_single_char)
-   font.setKerning(false);
QString const pat = symbolFamily(f.family());
if (!pat.isEmpty()) {
bool ok;
diff --git a/src/frontends/qt4/GuiFontMetrics.cpp 
b/src/frontends/qt4/GuiFontMetrics.cpp
index 4be0fb2..27d4446 100644
--- a/src/frontends/qt4/GuiFontMetrics.cpp
+++ b/src/frontends/qt4/GuiFontMetrics.cpp
@@ -112,18 +112,12 @@ int GuiFontMetrics::rbearing(char_type c) const
 int GuiFontMetrics::width(docstring const & s) const
 {
int w = 0;
-   if (lyxrc.force_paint_single_char) {
-   size_t const ls = s.size();
-   for (size_t i = 0; i < ls; ++i)
-   w += width(s[i]);
+   map<docstring, int>::const_iterator it = strwidth_cache_.find(s);
+   if (it != strwidth_cache_.end()) {
+   w = it->second;
} else {
-   map<docstring, int>::const_iterator it = 
strwidth_cache_.find(s);
-   if (it != strwidth_cache_.end()) {
-   w = it->second;
-   } else {
-   w = metrics_.width(toqstr(s));
-   strwidth_cache_[s] = w;
-   }
+   w = metrics_.width(toqstr(s));
+   strwidth_cache_[s] = w;
}
return w;
 }
diff --git a/src/frontends/qt4/GuiPainter.cpp b/src/frontends/qt4/GuiPainter.cpp
index ca63966..1b81d62 100644
--- a/src/frontends/qt4/GuiPainter.cpp
+++ b/src/frontends/qt4/GuiPainter.cpp
@@ -321,8 +321,6 @@ int GuiPainter::text(int x, int y, docstring const & s,
// occurs at a line-break. As a kludge, we force Qt to
// render this glyph using a one-column line.
// This is needed for some math glyphs.
-   // FIXME In texted, this behaves differently depending

[LyX/master] Rename misleading parameter.

2014-05-14 Thread Jean-Marc Lasgouttes
commit 3b3d28cf8ed2168637ff7a3491a82a330e70c28e
Author: Jean-Marc Lasgouttes <lasgout...@lyx.org>
Date:   Wed May 14 18:03:37 2014 +0200

Rename misleading parameter.

... and a typo and some whitespace.

diff --git a/src/mathed/MathData.h b/src/mathed/MathData.h
index 6f92852..e216941 100644
--- a/src/mathed/MathData.h
+++ b/src/mathed/MathData.h
@@ -145,8 +145,8 @@ public:
/// returns position of given x coordinate
int pos2x(BufferView const * bv, size_type pos, int glue) const;
/// returns position of given x coordinate
-   size_type x2pos(BufferView const * bv, int pos) const;
-   /// returns position of given x coordinate fstarting from a certain pos
+   size_type x2pos(BufferView const * bv, int targetx) const;
+   /// returns position of given x coordinate starting from a certain pos
size_type x2pos(BufferView const * bv, int targetx, int glue) const;
/// returns distance of this cell to the point given by x and y
// assumes valid position and size cache
@@ -165,7 +165,7 @@ public:
///
void swap(MathData & ar) { base_type::swap(ar); }
 
-   /// attach/detach arguments to macros, updating the cur to 
+   /// attach/detach arguments to macros, updating the cur to
/// stay visually at the same position (cur==0 is allowed)
void updateMacros(Cursor * cur, MacroContext const & mc, UpdateType);
///


[LyX/master] Do not forget last word of paragraph in completion

2014-05-16 Thread Jean-Marc Lasgouttes
commit ee7c4db72a9dd392d7e1e34463c3ae11fce670ee
Author: Jean-Marc Lasgouttes <lasgout...@lyx.org>
Date:   Fri May 16 15:17:10 2014 +0200

Do not forget last word of paragraph in completion

With the old code, the last word of a paragraph would not be added in
the completion list. The key difference is to pass `from' instead of `pos'
to FontList::fontiterator.

Slight cleanup of the code.

diff --git a/src/Paragraph.cpp b/src/Paragraph.cpp
index b6ca893..c551ea0 100644
--- a/src/Paragraph.cpp
+++ b/src/Paragraph.cpp
@@ -3840,20 +3840,19 @@ void Paragraph::locateWord(pos_type & from, pos_type & 
to,
 
 void Paragraph::collectWords()
 {
-   pos_type n = size();
-   for (pos_type pos = 0; pos < n; ++pos) {
+   for (pos_type pos = 0; pos < size(); ++pos) {
if (isWordSeparator(pos))
continue;
pos_type from = pos;
locateWord(from, pos, WHOLE_WORD);
-   if ((pos - from) >= (int)lyxrc.completion_minlength) {
-   docstring word = asString(from, pos, AS_STR_NONE);
-   FontList::const_iterator cit = 
d->fontlist_.fontIterator(pos);
-   if (cit == d->fontlist_.end())
-   return;
-   Language const * lang = cit->font().language();
-   d->words_[lang->lang()].insert(word);
-   }
+   if (pos < from + lyxrc.completion_minlength)
+   continue;
+   FontList::const_iterator cit = d->fontlist_.fontIterator(from);
+   if (cit == d->fontlist_.end())
+   return;
+   Language const * lang = cit->font().language();
+   docstring const word = asString(from, pos, AS_STR_NONE);
+   d->words_[lang->lang()].insert(word);
}
 }
 


[LyX/master] Remove unused parameter.

2014-05-16 Thread Jean-Marc Lasgouttes
commit f9e0d4a595bb568ca5f952e507d39487b05b8dd7
Author: Jean-Marc Lasgouttes <lasgout...@lyx.org>
Date:   Fri May 16 15:25:17 2014 +0200

Remove unused parameter.

diff --git a/src/insets/InsetSeparator.cpp b/src/insets/InsetSeparator.cpp
index 68b2fb8..ba98552 100644
--- a/src/insets/InsetSeparator.cpp
+++ b/src/insets/InsetSeparator.cpp
@@ -137,7 +137,7 @@ ColorCode InsetSeparator::ColorName() const
 }
 
 
-void InsetSeparator::latex(otexstream & os, OutputParams const & rp) const
+void InsetSeparator::latex(otexstream & os, OutputParams const &) const
 {
switch (params_.kind) {
case InsetSeparatorParams::PLAIN:


[LyX features/str-metrics] Fix positionning of cursor

2014-05-16 Thread Jean-Marc Lasgouttes
The branch, str-metrics, has been updated.

- Log -

commit 7b9b69f33c6d9bf0e6611e5fb8c406f3d3cefb80
Author: Jean-Marc Lasgouttes <lasgout...@lyx.org>
Date:   Wed May 14 17:46:43 2014 +0200

Fix positionning of cursor

The old implementation of Row::Element::pos2x and x2pos did not work
correctly with Arabic text, because characters can have shapes that
depend on context.

This new implementation leverages QTextLayout in a simplified way,
since only one word is added to the layout.

This allows to make Row::Element::x2pos more readable.

Fixes: #9115.

diff --git a/src/Row.cpp b/src/Row.cpp
index 48b4fff..50a47d3 100644
--- a/src/Row.cpp
+++ b/src/Row.cpp
@@ -36,78 +36,65 @@ using frontend::FontMetrics;
 
 double Row::Element::pos2x(pos_type const i) const
 {
-   LASSERT(i >= pos && i <= endpos, return 0);
+   // This can happen with inline completion when clicking on the
+   // row after the completion.
+   if (i < pos || i > endpos)
+   return 0;
 
bool const rtl = font.isVisibleRightToLeft();
 
int w = 0;
//handle first the two bounds of the element
-   if (i == pos)
-   w = 0;
+   if (i == pos || type != STRING)
+   w = rtl ? width() : 0;
else if (i == endpos)
-   w = width();
+   w = rtl ? 0 : width();
else {
-   LASSERT(type == STRING, return 0);
FontMetrics const & fm = theFontMetrics(font);
-   // FIXME Avoid caching of metrics there?
-   w = fm.width(str.substr(0, i - pos));
+   w = fm.pos2x(str, i - pos, font.isVisibleRightToLeft());
}
 
-   if (rtl)
-   return width() - w;
-   else
-   return w;
+   return w;
 }
 
 
-pos_type Row::Element::x2pos(double , bool const low) const
+pos_type Row::Element::x2pos(double ) const
 {
//lyxerr << "x2pos: x=" << x << " w=" << width() << " " << *this;
-   // If element is rtl, flip x value
bool const rtl = font.isVisibleRightToLeft();
-   double x2 = rtl ? (width() - x) : x;
+   size_t i;
 
-   double last_w = 0;
-   double w = 0;
-   size_t i = 0;
switch (type) {
-   case VIRTUAL:
-   // those elements are actually empty (but they have a width)
-   break;
case STRING: {
FontMetrics const & fm = theFontMetrics(font);
-   // FIXME: implement dichotomy search?
-   for ( ; i < str.size() ; ++i) {
-   last_w = w;
-   w = fm.width(str.substr(0, i + 1));
-   if (w > x2)
-   break;
-   }
+   // FIXME: is it really necessary for x to be a double?
+   int xx = x;
+   i = fm.x2pos(str, xx, rtl);
+   x = xx;
break;
}
+   case VIRTUAL:
+   // those elements are actually empty (but they have a width)
+   i = 0;
+   x = rtl ? width() : 0;
+   break;
case SEPARATOR:
case INSET:
case SPACE:
-   // those elements contain only one position
-   w = width();
-   }
-
-   if (type == STRING && i == str.size())
-   x2 = w;
-   // round to the closest side. The !rtl is here to obtain the
-   // same rounding as with the old code (this is cosmetic and
-   // can be eventually removed).
-   else if (type != VIRTUAL && !low && (x2 - last_w + !rtl > w - x2)) {
-   x2 = w;
-   ++i;
-   } else
-   x2 = last_w;
-
-   // is element is rtl, flip values back
-   x = rtl ? width() - x2 : x2;
+   // those elements contain only one position. Round to
+   // the closest side.
+   if (x > width()) {
+   x = width();
+   i = !rtl;
+   } else {
+   x = 0;
+   i = rtl;
+   }
 
+   }
//lyxerr << "=> p=" << pos + i << " x=" << x << endl;
return pos + i;
+
 }
 
 
@@ -389,7 +376,8 @@ void Row::shorten_if_needed(pos_type const keep, int const 
w)
// If there is a paragraph marker, it should be taken in account
if (elements_.size() == 2)
xstr -= back().width();
-   pos_type new_pos = front.x2pos(xstr, true);
+   //FIXME: use FontMetrics::x2pos here?? handle rtl?
+   pos_type new_pos = front.x2pos(xstr);
front.str = front.str.substr(0, new_pos - po

[LyX features/str-metrics] Fix bug where x2pos could return negative values

2014-05-16 Thread Jean-Marc Lasgouttes
The branch, str-metrics, has been updated.

- Log -

commit 13551a9f203a5f8d2d28ea9af4eeeb7fe15171b0
Author: Jean-Marc Lasgouttes <lasgout...@lyx.org>
Date:   Fri May 16 20:59:22 2014 +0200

Fix bug where x2pos could return negative values

diff --git a/src/Row.cpp b/src/Row.cpp
index 50a47d3..a0c0dc4 100644
--- a/src/Row.cpp
+++ b/src/Row.cpp
@@ -62,7 +62,7 @@ pos_type Row::Element::x2pos(double ) const
 {
//lyxerr << "x2pos: x=" << x << " w=" << width() << " " << *this;
bool const rtl = font.isVisibleRightToLeft();
-   size_t i;
+   size_t i = 0;
 
switch (type) {
case STRING: {
diff --git a/src/frontends/qt4/GuiFontMetrics.cpp 
b/src/frontends/qt4/GuiFontMetrics.cpp
index b6b2f5d..2ac588c 100644
--- a/src/frontends/qt4/GuiFontMetrics.cpp
+++ b/src/frontends/qt4/GuiFontMetrics.cpp
@@ -183,7 +183,12 @@ int GuiFontMetrics::x2pos(docstring const & s, int & x, 
bool const rtl) const
 {
QTextLayout tl;
setTextLayout(tl, s, font_, rtl);
-   int const pos = tl.lineForTextPosition(0).xToCursor(x) - 1;
+   int pos = tl.lineForTextPosition(0).xToCursor(x);
+   // take into account the unicode formatting characters
+   if (pos > 0)
+   --pos;
+   if (pos > int(s.length()))
+   pos = s.length();
// correct x value to the actual cursor position.
x = tl.lineForTextPosition(0).cursorToX(pos + 1);
return pos;

---

Summary of changes:
 src/Row.cpp  |2 +-
 src/frontends/qt4/GuiFontMetrics.cpp |7 ++-
 2 files changed, 7 insertions(+), 2 deletions(-)


hooks/post-receive
-- 
Repository for new features


[LyX features/str-metrics] Fix breaking of loooong word in RTL languages

2014-05-19 Thread Jean-Marc Lasgouttes
The branch, str-metrics, has been updated.

- Log -

commit c73940031ae93d40fb72798a4373eb7771090caa
Author: Jean-Marc Lasgouttes <lasgout...@lyx.org>
Date:   Mon May 19 11:35:15 2014 +0200

Fix breaking of lng word in RTL languages

Moreover, breaks row at insets when there is no suitable separator.

Also make the code of Row::shorten_if_needed somewhat simpler by using
iterators and factoring the code.

Fixes: #9120

diff --git a/src/Row.cpp b/src/Row.cpp
index a0c0dc4..b47b564 100644
--- a/src/Row.cpp
+++ b/src/Row.cpp
@@ -28,6 +28,8 @@
 #include 
 #include 
 
+#include 
+
 using namespace std;
 
 namespace lyx {
@@ -98,6 +100,27 @@ pos_type Row::Element::x2pos(double ) const
 }
 
 
+bool Row::Element::breakAt(double w)
+{
+   if (type != STRING || width() <= w)
+   return false;
+
+   bool const rtl = font.isVisibleRightToLeft();
+   if (rtl)
+   w = width() - w;
+   pos_type new_pos = x2pos(w);
+   if (new_pos == pos)
+   return false;
+   str = str.substr(0, new_pos - pos);
+   if (rtl)
+   dim.wid -= w;
+   else
+   dim.wid = w;
+   endpos = new_pos;
+   return true;
+}
+
+
 pos_type Row::Element::left_pos() const
 {
return font.isVisibleRightToLeft() ? endpos : pos;
@@ -110,7 +133,6 @@ pos_type Row::Element::right_pos() const
 }
 
 
-
 Row::Row()
: separator(0), label_hfill(0), x(0), right_margin(0),
  sel_beg(-1), sel_end(-1),
@@ -334,63 +356,63 @@ void Row::pop_back()
 }
 
 
-void Row::shorten_if_needed(pos_type const keep, int const w)
+void Row::shortenIfNeeded(pos_type const keep, int const w)
 {
-   if (empty() || width() < w)
+   if (empty() || width() <= w)
return;
 
/** First, we try to remove elements one by one from the end
-* until a separator is found.
+* until a separator is found. cit points to the first element
+* we want to remove from the row.
 */
-   int i = elements_.size();
+   Elements::iterator const beg = elements_.begin();
+   Elements::iterator const end = elements_.end();
+   Elements::iterator cit = end;
+   Elements::iterator first_below = end;
int new_end = end_;
int new_wid = dim_.wid;
-   if (i > 0 && elements_[i - 1].type == SEPARATOR && new_end > keep) {
-   --i;
-   new_end = elements_[i].pos;
-   new_wid -= elements_[i].dim.wid;
+   // if the row ends with a separator, skip it.
+   if (cit != beg && boost::prior(cit)->type == SEPARATOR && new_end > 
keep) {
+   --cit;
+   new_end = cit->pos;
+   new_wid -= cit->dim.wid;
}
 
-   while (i > 0 && elements_[i - 1].type != SEPARATOR && new_end > keep) {
-   --i;
-   new_end = elements_[i].pos;
-   new_wid -= elements_[i].dim.wid;
+   // Search for a separator where the row can be broken.
+   while (cit != beg && boost::prior(cit)->type != SEPARATOR && new_end > 
keep) {
+   --cit;
+   new_end = cit->pos;
+   new_wid -= cit->dim.wid;
+   if (new_wid < w && first_below == end)
+   first_below = cit;
}
-   if (i == 0) {
-   /* If we are here, it means that we have not found a
-* separator to shorten the row. There is one case
-* where we can do something: when we have one big
-* string, maybe with a paragraph marker after it.
-*/
-   Element & front = elements_.front();
-   if (!(front.type == STRING
- && (elements_.size() == 1
- || (elements_.size() == 2
- && back().type == VIRTUAL
-   return;
-
-   // If this is a string element, we can try to split it.
-   if (front.type != STRING)
-   return;
-   double xstr = w - x;
-   // If there is a paragraph marker, it should be taken in account
-   if (elements_.size() == 2)
-   xstr -= back().width();
-   //FIXME: use FontMetrics::x2pos here?? handle rtl?
-   pos_type new_pos = front.x2pos(xstr);
-   front.str = front.str.substr(0, new_pos - pos_);
-   front.dim.wid = xstr;
-   front.endpos = new_pos;
-   end_ = new_pos;
-   dim_.wid = x + xstr;
-   // If there is a paragraph marker, it should be removed.
-   if (elements_.size() == 2)
-   elements_.pop_back();
+
+   i

[LyX/master] Code cleanup: get rid of RenderPreview::status()

2014-05-20 Thread Jean-Marc Lasgouttes
commit 275b7af75e5367c449d0f680d0965994c92d37d9
Author: Jean-Marc Lasgouttes <lasgout...@lyx.org>
Date:   Tue May 20 12:19:26 2014 +0200

Code cleanup: get rid of RenderPreview::status()

This method is a proxy for LyXRC::preview that forces to forward
declare some wrapper around an enum...

Instead, two simple static methods previewMath() and previewText() are
introduced, that make the code much easier to follow.

diff --git a/src/LyXRC.h b/src/LyXRC.h
index 14f73d9..2814959 100644
--- a/src/LyXRC.h
+++ b/src/LyXRC.h
@@ -560,17 +560,6 @@ public:
 };
 
 
-/** \c LyXRC_PreviewStatus is a wrapper for LyXRC::PreviewStatus.
- *  It can be forward-declared and passed as a function argument without
- *  having to expose LyXRC.h.
- */
-class LyXRC_PreviewStatus {
-   LyXRC::PreviewStatus val_;
-public:
-   LyXRC_PreviewStatus(LyXRC::PreviewStatus val) : val_(val) {}
-   operator LyXRC::PreviewStatus() const { return val_; }
-};
-
 void actOnUpdatedPrefs(LyXRC const & lyxrc_orig, LyXRC const & lyxrc_new);
 
 ///
diff --git a/src/insets/InsetExternal.cpp b/src/insets/InsetExternal.cpp
index 278168a..50c6e4b 100644
--- a/src/insets/InsetExternal.cpp
+++ b/src/insets/InsetExternal.cpp
@@ -542,8 +542,7 @@ static void 
add_preview_and_start_loading(RenderMonitoredPreview & renderer,
 {
InsetExternalParams const & params = inset.params();
 
-   if (RenderPreview::status() != LyXRC::PREVIEW_OFF &&
-   isPreviewWanted(params)) {
+   if (RenderPreview::previewText() && isPreviewWanted(params)) {
renderer.setAbsFile(params.filename);
docstring const snippet = latexString(inset);
renderer.addPreview(snippet, buffer);
@@ -577,7 +576,7 @@ void InsetExternal::setParams(InsetExternalParams const & p)
|| !lyxrc.display_graphics
|| params_.preview_mode == PREVIEW_OFF
|| (params_.preview_mode == PREVIEW_INSTANT
-   && RenderPreview::status() == LyXRC::PREVIEW_OFF)) {
+   && !RenderPreview::previewText())) {
RenderButton * button_ptr = renderer_->asButton();
if (!button_ptr) {
renderer_.reset(new RenderButton);
diff --git a/src/insets/InsetIPA.cpp b/src/insets/InsetIPA.cpp
index 6fe0a90..33ede55 100644
--- a/src/insets/InsetIPA.cpp
+++ b/src/insets/InsetIPA.cpp
@@ -19,7 +19,6 @@
 #include "FuncStatus.h"
 #include "LaTeXFeatures.h"
 #include "Lexer.h"
-#include "LyXRC.h"
 #include "MetricsInfo.h"
 #include "OutputParams.h"
 #include "RenderPreview.h"
@@ -122,8 +121,7 @@ void InsetIPA::preparePreview(DocIterator const & pos) const
 
 bool InsetIPA::previewState(BufferView * bv) const
 {
-   if (!editing(bv) && (RenderPreview::status() == LyXRC::PREVIEW_ON ||
-RenderPreview::status() == 
LyXRC::PREVIEW_NO_MATH)) {
+   if (!editing(bv) && RenderPreview::previewText()) {
graphics::PreviewImage const * pimage =
preview_->getPreviewImage(bv->buffer());
return pimage && pimage->image();
diff --git a/src/insets/InsetInclude.cpp b/src/insets/InsetInclude.cpp
index 506f358..ff4a329 100644
--- a/src/insets/InsetInclude.cpp
+++ b/src/insets/InsetInclude.cpp
@@ -31,7 +31,6 @@
 #include "LayoutFile.h"
 #include "LayoutModuleList.h"
 #include "LyX.h"
-#include "LyXRC.h"
 #include "Lexer.h"
 #include "MetricsInfo.h"
 #include "output_plaintext.h"
@@ -989,7 +988,7 @@ void InsetInclude::metrics(MetricsInfo & mi, Dimension & 
dim) const
LBUFERR(mi.base.bv);
 
bool use_preview = false;
-   if (RenderPreview::status() != LyXRC::PREVIEW_OFF) {
+   if (RenderPreview::previewText()) {
graphics::PreviewImage const * pimage =
preview_->getPreviewImage(mi.base.bv->buffer());
use_preview = pimage && pimage->image();
@@ -1015,7 +1014,7 @@ void InsetInclude::draw(PainterInfo & pi, int x, int y) 
const
LBUFERR(pi.base.bv);
 
bool use_preview = false;
-   if (RenderPreview::status() != LyXRC::PREVIEW_OFF) {
+   if (RenderPreview::previewText()) {
graphics::PreviewImage const * pimage =
preview_->getPreviewImage(pi.base.bv->buffer());
use_preview = pimage && pimage->image();
@@ -1094,8 +1093,7 @@ void add_preview(RenderMonitoredPreview & renderer, 
InsetInclude const & inset,
 Buffer const & buffer)
 {
InsetCommandParams const & params = inset.params();
-   if (RenderPreview::status() != LyXRC::PREVIEW_OFF &&
-   preview_wanted

[LyX features/str-metrics] Do not split words at selection boundary

2014-05-27 Thread Jean-Marc Lasgouttes
The branch, str-metrics, has been updated.

- Log -

commit 0096a8716c2d5219ac0854a076bcaa73dab86be3
Author: Jean-Marc Lasgouttes <lasgout...@lyx.org>
Date:   Fri May 23 18:59:53 2014 +0200

Do not split words at selection boundary

The display of partially-selected word is now done in a new Painter::text 
method
which displays the string twice with different clip settings. This allows to
catter for the case where Color_selectiontext is not black.

Morover, the code that uses unicode override characters to force the
direction of a string is moved to lstrings.h.

Fixes: #9116

diff --git a/00README_STR_METRICS_BRANCH b/00README_STR_METRICS_BRANCH
index 568ac8f..2dc3cad 100644
--- a/00README_STR_METRICS_BRANCH
+++ b/00README_STR_METRICS_BRANCH
@@ -47,6 +47,10 @@ What is done:
   justified. This speeds-up painting by reducing the number of strings
   to draw.
 
+* Do not cut strings at selection boundary in RowPainter. This avoids
+  ligature/kerning breaking in latin text, and bad rendering problems
+  in Arabic.
+
 
 Next steps:
 
@@ -72,5 +76,3 @@ Steps for later (aka out of the scope of this branch):
   happens. This depends on the update machinery.
 
   This would allow to get rid of the Bidi.cpp code.
-
-
diff --git a/src/frontends/Painter.h b/src/frontends/Painter.h
index 7267839..3302d16 100644
--- a/src/frontends/Painter.h
+++ b/src/frontends/Painter.h
@@ -14,9 +14,11 @@
 #define PAINTER_H
 
 #include "support/strfwd.h"
+#include "support/types.h"
 
 namespace lyx {
 
+class Font;
 class FontInfo;
 
 namespace graphics { class Image; }
@@ -106,12 +108,26 @@ public:
virtual void image(int x, int y, int w, int h,
graphics::Image const & image) = 0;
 
-   /// draw a string at position x, y (y is the baseline)
-   /**
-   * \return the width of the drawn text.
-   */
+   /** draw a string at position x, y (y is the baseline). The
+* text direction is deduced from \c str.
+* \return the width of the drawn text.
+*/
virtual int text(int x, int y, docstring const & str, FontInfo const & 
f) = 0;
 
+   /** draw a string at position x, y (y is the baseline). The
+* text direction is enforced by the \c Font.
+* \return the width of the drawn text.
+*/
+   virtual int text(int x, int y, docstring const & str, Font const & f) = 
0;
+
+   /** draw a string at position x, y (y is the baseline), but
+* make sure that the part between \c from and \c to is in
+* \c other color. The text direction is enforced by the \c Font.
+* \return the width of the drawn text.
+*/
+   virtual int text(int x, int y, docstring const & str, Font const & f,
+Color other, size_type from, size_type to) = 0;
+
void setDrawingEnabled(bool drawing_enabled)
{ drawing_enabled_ = drawing_enabled; }
 
diff --git a/src/frontends/qt4/GuiFontMetrics.cpp 
b/src/frontends/qt4/GuiFontMetrics.cpp
index 2ac588c..492a0a9 100644
--- a/src/frontends/qt4/GuiFontMetrics.cpp
+++ b/src/frontends/qt4/GuiFontMetrics.cpp
@@ -22,10 +22,12 @@
 #include "insets/Inset.h"
 
 #include "support/lassert.h"
+#include "support/lstrings.h"
 
 #include 
 
 using namespace std;
+using namespace lyx::support;
 
 namespace lyx {
 namespace frontend {
@@ -42,7 +44,7 @@ namespace {
  * why this works well for symbol fonts used in mathed too, even though
  * these are not real ucs4 characters. These are codepoints in the
  * computer modern fonts used, nothing unicode related.
- * See comment in QLPainter::text() for more explanation.
+ * See comment in GuiPainter::text() for more explanation.
  **/
 inline QChar const ucs4_to_qchar(char_type const ucs4)
 {
@@ -146,22 +148,7 @@ namespace {
 void setTextLayout(QTextLayout & tl, docstring const & s, QFont const & font,
 bool const rtl)
 {
-   QString qs;
-   /* In LyX, the character direction is forced by the language.
-* Therefore, we have to signal that fact to Qt.
-* Source: http://www.iamcal.com/understanding-bidirectional-text/
-*/
-   // Left-to-right override: forces to draw text left-to-right
-   char_type const LRO = 0x202D;
-   // Right-to-left override: forces to draw text right-to-left
-   char_type const RLO = 0x202E;
-   // Pop directional formatting: return to previous state
-   char_type const PDF = 0x202C;
-   if (rtl)
-   qs = toqstr(RLO + s + PDF);
-   else
-   qs = toqstr(LRO + s + PDF);
-
+   QString const qs = toqstr(directedString(s, rtl));
tl.setText(qs);
tl.setFont(font);
tl.beginLayout();
@@ -175,6 +162,7 @@ int GuiFontMetrics::pos2x(docstring const & s, int const 
pos, bool c

[LyX features/str-metrics] Some cleanup of previous patch

2014-05-27 Thread Jean-Marc Lasgouttes
The branch, str-metrics, has been updated.

- Log -

commit 544c7e01ca7039b11bf9304213ca9cd94e580c09
Author: Jean-Marc Lasgouttes <lasgout...@lyx.org>
Date:   Tue May 27 16:50:49 2014 +0200

Some cleanup of previous patch

diff --git a/src/rowpainter.cpp b/src/rowpainter.cpp
index b49a94a..b6e7f24 100644
--- a/src/rowpainter.cpp
+++ b/src/rowpainter.cpp
@@ -237,11 +237,14 @@ void RowPainter::paintChars(pos_type & vpos, Font const & 
font)
str.push_back(c);
}
 
-   // At the end of the row, pos points to the last pos in the string.
+   // Make pos point to the last character in the string.
// Using "pos = bidi_.vis2log(vpos)" does not work for some reason.
if (vpos < end)
pos = bidi_.vis2log(vpos - 1);
 
+   // Now make pos point to the position _after_ the string.
+   // Using vis2log for that is not a good idea in general, we
+   // want logical ordering.
if (font.isVisibleRightToLeft())
--pos;
else
@@ -261,6 +264,7 @@ void RowPainter::paintChars(pos_type & vpos, Font const & 
font)
 */
if (font.isVisibleRightToLeft()) {
reverse(str.begin(), str.end());
+   // If the string is reversed, the positions need to be adjusted
++pos;
++start_pos;
swap(start_pos, pos);
@@ -272,8 +276,6 @@ void RowPainter::paintChars(pos_type & vpos, Font const & 
font)
// all the text selected?
bool const all_sel = (start_pos >= row_.sel_beg && pos < row_.sel_end)
|| pi_.selected;
-   if (some_sel)
-   LYXERR0("pos=[" << start_pos << ", " << pos << "[ sel=[" << 
row_.sel_beg << ", " << row_.sel_end << "[ span=[" <

[LyX features/str-metrics] Do not allow Row::shortenIfNeeded to create empty rows

2014-05-30 Thread Jean-Marc Lasgouttes
The branch, str-metrics, has been updated.

- Log -

commit 06e4a11deb2678fb712546c7ae571b7ce5f70b86
Author: Jean-Marc Lasgouttes <lasgout...@lyx.org>
Date:   Fri May 30 18:50:35 2014 +0200

Do not allow Row::shortenIfNeeded to create empty rows

Otherwise this leads to an endless loop in redoParagraph.

diff --git a/src/Row.cpp b/src/Row.cpp
index b47b564..1336d05 100644
--- a/src/Row.cpp
+++ b/src/Row.cpp
@@ -407,7 +407,7 @@ void Row::shortenIfNeeded(pos_type const keep, int const w)
dim_.wid = x + first_below->width();
// If there are other elements, they should be removed.
elements_.erase(boost::next(first_below), end);
-   } else {
+   } else if (first_below->pos > pos_) {
end_ = first_below->pos;
dim_.wid = new_wid;
// Remove all elements from first_below.

---

Summary of changes:
 src/Row.cpp |2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)


hooks/post-receive
-- 
Repository for new features


[LyX/2.1.x] Make TextMetrics::editXY more robust

2014-06-04 Thread Jean-Marc Lasgouttes
commit d4faf127d74643ce10a1a5240ea02601336e48fe
Author: Jean-Marc Lasgouttes <lasgout...@lyx.org>
Date:   Tue May 27 15:14:14 2014 +0200

Make TextMetrics::editXY more robust

This fixes a crash in examples/fa/splash.lyx when selecting text
representing menu entries. This happens because menu names are in LTR
English, while the inset itself is in RTL.

The problem is that the current code relies on the fact that
 1. getColumnNearX and checkInsetHit share the same idea about cursor
position.
 2. pos and pos + 1 are in general consecutive on screen.

It seems that 1. is wrong here (for reasons I did not try to
understand); the second assumption is definitely false with
bi-directional text. This makes editXY very fragile.

The new code should be more robust in this respect. The logic is:
 * if checkInsetHit finds an inset, use its position,
 * otherwise, ask getColumnNearX for the cursor position.

Fixes: #9142

diff --git a/src/TextMetrics.cpp b/src/TextMetrics.cpp
index a0f8f72..7f82675 100644
--- a/src/TextMetrics.cpp
+++ b/src/TextMetrics.cpp
@@ -1492,37 +1492,30 @@ Inset * TextMetrics::editXY(Cursor & cur, int x, int y,
int yy = y; // is modified by getPitAndRowNearY
Row const & row = getPitAndRowNearY(yy, pit, assert_in_view, up);
 
-   bool bound = false; // is modified by getColumnNearX
-   int xx = x; // is modified by getColumnNearX
-   pos_type const pos = row.pos()
-   + getColumnNearX(pit, row, xx, bound);
cur.pit() = pit;
-   cur.pos() = pos;
-   cur.boundary(bound);
-   cur.setTargetX(x);
 
-   // try to descend into nested insets
-   Inset * inset = checkInsetHit(x, yy);
-   //lyxerr << "inset " << inset << " hit at x: " << x << " y: " << y << 
endl;
-   if (!inset) {
+   // Do we cover an inset?
+   InsetList::InsetTable * it = checkInsetHit(pit, x, yy);
+
+   if (!it) {
+   // No inset, set position in the text
+   bool bound = false; // is modified by getColumnNearX
+   int xx = x; // is modified by getColumnNearX
+   cur.pos() = row.pos()
+   + getColumnNearX(pit, row, xx, bound);
+   cur.boundary(bound);
cur.setCurrentFont();
+   cur.setTargetX(xx);
return 0;
}
 
-   ParagraphList const & pars = text_->paragraphs();
-   Inset const * inset_before = pos ? pars[pit].getInset(pos - 1) : 0;
-
-   // This should be just before or just behind the
-   // cursor position set above.
-   LASSERT(inset == inset_before
-   || inset == pars[pit].getInset(pos), return 0);
-
-   // Make sure the cursor points to the position before
-   // this inset.
-   if (inset == inset_before) {
-   --cur.pos();
-   cur.boundary(false);
-   }
+   Inset * inset = it->inset;
+   //lyxerr << "inset " << inset << " hit at x: " << x << " y: " << y << 
endl;
+
+   // Set position in front of inset
+   cur.pos() = it->pos;
+   cur.boundary(false);
+   cur.setTargetX(x);
 
// Try to descend recursively inside the inset.
inset = inset->editXY(cur, x, yy);
@@ -1571,11 +1564,8 @@ void TextMetrics::setCursorFromCoordinates(Cursor & cur, 
int const x, int const
 
 
 //takes screen x,y coordinates
-Inset * TextMetrics::checkInsetHit(int x, int y)
+InsetList::InsetTable * TextMetrics::checkInsetHit(pit_type pit, int x, int y)
 {
-   pit_type pit = getPitNearY(y);
-   LASSERT(pit != -1, return 0);
-
Paragraph const & par = text_->paragraphs()[pit];
ParagraphMetrics const & pm = par_metrics_[pit];
 
@@ -1604,7 +1594,7 @@ Inset * TextMetrics::checkInsetHit(int x, int y)
&& y >= p.y_ - dim.asc
&& y <= p.y_ + dim.des) {
LYXERR(Debug::DEBUG, "Hit inset: " << inset);
-   return inset;
+   return const_cast(&(*iit));
}
}
 
@@ -1613,6 +1603,20 @@ Inset * TextMetrics::checkInsetHit(int x, int y)
 }
 
 
+//takes screen x,y coordinates
+Inset * TextMetrics::checkInsetHit(int x, int y)
+{
+   pit_type const pit = getPitNearY(y);
+   LASSERT(pit != -1, return 0);
+   InsetList::InsetTable * it = checkInsetHit(pit, x, y);
+
+   if (!it)
+   return 0;
+
+   return it->inset;
+}
+
+
 int TextMetrics::cursorX(CursorSlice const & sl,
bool boundary) const
 {
diff --git a/src/TextMetrics.h b/src/TextMetrics.h
index 66d310f..2acded9 100644
--- a/src/TextMetrics.h
+++ b/src/TextMetrics.h
@@ -15,6 +1

[LyX/master] Fix crash when accepting change

2014-06-05 Thread Jean-Marc Lasgouttes
commit 7c3d1d7423908c4e2481f320876400622f78f359
Author: Jean-Marc Lasgouttes <lasgout...@lyx.org>
Date:   Thu Jun 5 12:18:09 2014 +0200

Fix crash when accepting change

The problem is the use of cursor movement methods to update cursor.
Cursor::forwardPos() steps into insets, which is not always what we
want. The problem here is that there is a math inset just after the
accepted change, and that the cursor steps into it for some reason.

This code is a nightmare anyway.

Fixes: bug #9145

diff --git a/src/lyxfind.cpp b/src/lyxfind.cpp
index 0c10e19..6b9556e 100644
--- a/src/lyxfind.cpp
+++ b/src/lyxfind.cpp
@@ -400,7 +400,7 @@ bool findChange(DocIterator & cur, bool next)
if (!next)
// if we search backwards, take a step forward
// to correctly set the anchor
-   cur.forwardPos();
+   cur.top().forwardPos();
return true;
}
 


[LyX/master] Fix checkmark on current entry for InsetSeparator context menu

2014-06-13 Thread Jean-Marc Lasgouttes
commit 01ba22efffaa06e8c8ee4730b5d63ffd16e95c9f
Author: Jean-Marc Lasgouttes <lasgout...@lyx.org>
Date:   Fri Jun 13 10:30:25 2014 +0200

Fix checkmark on current entry for InsetSeparator context menu

The code supposed to do that contained a typo and was not completely 
correct.

diff --git a/src/insets/InsetSeparator.cpp b/src/insets/InsetSeparator.cpp
index eaf376f..05aa456 100644
--- a/src/insets/InsetSeparator.cpp
+++ b/src/insets/InsetSeparator.cpp
@@ -60,7 +60,7 @@ void InsetSeparatorParams::read(Lexer & lex)
 {
string token;
lex.setContext("InsetSeparatorParams::read");
-   lex >> token;   
+   lex >> token;
if (token == "plain")
kind = InsetSeparatorParams::PLAIN;
else if (token == "parbreak")
@@ -108,17 +108,19 @@ bool InsetSeparator::getStatus(Cursor & cur, FuncRequest 
const & cmd,
 {
switch (cmd.action()) {
// we handle these
-   case LFUN_INSET_MODIFY:
-   if (cmd.getArg(0) == "plain") {
-   InsetSeparatorParams params;
-   string2params(to_utf8(cmd.argument()), params);
-   status.setOnOff(params_.kind == params.kind);
-   }
+   case LFUN_INSET_MODIFY: {
+   if (cmd.getArg(0) != "separator")
+   break;
+   InsetSeparatorParams params;
+   string2params(to_utf8(cmd.argument()), params);
+   status.setOnOff(params_.kind == params.kind);
status.setEnabled(true);
return true;
+   }
default:
return Inset::getStatus(cur, cmd, status);
}
+   return false;
 }
 
 


[LyX features/str-metrics] Remove obsolete code to handle Hebrew and Arabic characters

2014-06-13 Thread Jean-Marc Lasgouttes
The branch, str-metrics, has been updated.

- Log -

commit 7a23bfc80742c7ecaf758073e818c63c07ec0009
Author: Jean-Marc Lasgouttes <lasgout...@lyx.org>
Date:   Fri Jun 13 16:33:58 2014 +0200

Remove obsolete code to handle Hebrew and Arabic characters

This is handled by Qt now.

Note that a small optimization (do not draw text that is to the left
og WorkArea) is removed because it cannot be guarranteed to be exact
anymore. It was probably not very useful anway, and would become
useless once the RowPainter is rewritten to use Row information.

diff --git a/src/Encoding.cpp b/src/Encoding.cpp
index a231106..be60107 100644
--- a/src/Encoding.cpp
+++ b/src/Encoding.cpp
@@ -41,190 +41,6 @@ Encodings::MathSymbolSet  Encodings::mathsym;
 
 namespace {
 
-char_type arabic_table[172][4] = {
-   {0xfe80, 0xfe80, 0xfe80, 0xfe80}, // 0x0621 = hamza
-   {0xfe81, 0xfe82, 0xfe81, 0xfe82}, // 0x0622 = ligature madda on alef
-   {0xfe83, 0xfe84, 0xfe83, 0xfe84}, // 0x0623 = ligature hamza on alef
-   {0xfe85, 0xfe86, 0xfe85, 0xfe86}, // 0x0624 = ligature hamza on waw
-   {0xfe87, 0xfe88, 0xfe87, 0xfe88}, // 0x0625 = ligature hamza under alef
-   {0xfe89, 0xfe8a, 0xfe8b, 0xfe8c}, // 0x0626 = ligature hamza on ya
-   {0xfe8d, 0xfe8e, 0xfe8d, 0xfe8e}, // 0x0627 = alef
-   {0xfe8f, 0xfe90, 0xfe91, 0xfe92}, // 0x0628 = baa
-   {0xfe93, 0xfe94, 0xfe93, 0xfe94}, // 0x0629 = taa marbuta
-   {0xfe95, 0xfe96, 0xfe97, 0xfe98}, // 0x062a = taa
-   {0xfe99, 0xfe9a, 0xfe9b, 0xfe9c}, // 0x062b = thaa
-   {0xfe9d, 0xfe9e, 0xfe9f, 0xfea0}, // 0x062c = jeem
-   {0xfea1, 0xfea2, 0xfea3, 0xfea4}, // 0x062d = haa
-   {0xfea5, 0xfea6, 0xfea7, 0xfea8}, // 0x062e = khaa
-   {0xfea9, 0xfeaa, 0xfea9, 0xfeaa}, // 0x062f = dal
-
-   {0xfeab, 0xfeac, 0xfeab, 0xfeac}, // 0x0630 = thal
-   {0xfead, 0xfeae, 0xfead, 0xfeae}, // 0x0631 = ra
-   {0xfeaf, 0xfeb0, 0xfeaf, 0xfeb0}, // 0x0632 = zain
-   {0xfeb1, 0xfeb2, 0xfeb3, 0xfeb4}, // 0x0633 = seen
-   {0xfeb5, 0xfeb6, 0xfeb7, 0xfeb8}, // 0x0634 = sheen
-   {0xfeb9, 0xfeba, 0xfebb, 0xfebc}, // 0x0635 = sad
-   {0xfebd, 0xfebe, 0xfebf, 0xfec0}, // 0x0636 = dad
-   {0xfec1, 0xfec2, 0xfec3, 0xfec4}, // 0x0637 = tah
-   {0xfec5, 0xfec6, 0xfec7, 0xfec8}, // 0x0638 = zah
-   {0xfec9, 0xfeca, 0xfecb, 0xfecc}, // 0x0639 = ain
-   {0xfecd, 0xfece, 0xfecf, 0xfed0}, // 0x063a = ghain
-   {0, 0, 0, 0}, // 0x063b
-   {0, 0, 0, 0}, // 0x063c
-   {0, 0, 0, 0}, // 0x063d
-   {0, 0, 0, 0}, // 0x063e
-   {0, 0, 0, 0}, // 0x063f
-
-   {0, 0, 0, 0}, // 0x0640
-   {0xfed1, 0xfed2, 0xfed3, 0xfed4}, // 0x0641 = fa
-   {0xfed5, 0xfed6, 0xfed7, 0xfed8}, // 0x0642 = qaf
-   {0xfed9, 0xfeda, 0xfedb, 0xfedc}, // 0x0643 = kaf
-   {0xfedd, 0xfede, 0xfedf, 0xfee0}, // 0x0644 = lam
-   {0xfee1, 0xfee2, 0xfee3, 0xfee4}, // 0x0645 = meem
-   {0xfee5, 0xfee6, 0xfee7, 0xfee8}, // 0x0646 = noon
-   {0xfee9, 0xfeea, 0xfeeb, 0xfeec}, // 0x0647 = ha
-   {0xfeed, 0xfeee, 0xfeed, 0xfeee}, // 0x0648 = waw
-   {0xfeef, 0xfef0, 0xfeef, 0xfef0}, // 0x0649 = alef maksura
-   {0xfef1, 0xfef2, 0xfef3, 0xfef4}, // 0x064a = ya
-   {0x065b, 0x065b, 0x065b, 0x065b}, // 0x064b = fathatan
-   {0x065c, 0x065c, 0x065c, 0x065c}, // 0x064c = dammatan
-   {0x064d, 0x064d, 0x064d, 0x064d}, // 0x064d = kasratan
-   {0x064e, 0x064e, 0x064e, 0x064e}, // 0x064e = fatha
-   {0x064f, 0x064f, 0x064f, 0x064f}, // 0x064f = damma
-
-   {0x0650, 0x0650, 0x0650, 0x0650}, // 0x0650 = kasra
-   {0x0651, 0x0651, 0x0651, 0x0651}, // 0x0651 = shadda
-   {0x0652, 0x0652, 0x0652, 0x0652}, // 0x0652 = sukun
-
-   {0, 0, 0, 0}, // 0x0653
-   {0, 0, 0, 0}, // 0x0654
-   {0, 0, 0, 0}, // 0x0655
-   {0, 0, 0, 0}, // 0x0656
-   {0, 0, 0, 0}, // 0x0657
-   {0, 0, 0, 0}, // 0x0658
-   {0, 0, 0, 0}, // 0x0659
-   {0, 0, 0, 0}, // 0x065a
-   {0, 0, 0, 0}, // 0x065b
-   {0, 0, 0, 0}, // 0x065c
-   {0, 0, 0, 0}, // 0x065d
-   {0, 0, 0, 0}, // 0x065e
-   {0, 0, 0, 0}, // 0x065f
-   {0, 0, 0, 0}, // 0x0660
-   {0, 0, 0, 0}, // 0x0661
-   {0, 0, 0, 0}, // 0x0662
-   {0, 0, 0, 0}, // 0x0663
-   {0, 0, 0, 0}, // 0x0664
-   {0, 0, 0, 0}, // 0x0665
-   {0, 0, 0, 0}, // 0x0666
-   {0, 0, 0, 0}, // 0x0667
-   {0, 0, 0, 0}, // 0x0668
-   {0, 0, 0, 0}, // 0x0669
-   {0, 0, 0, 0}, // 0x066a
-   {0, 0, 0, 0}, // 0x066b
-   {0, 0, 0, 0}, // 0x066c
-   {0, 0, 0, 0}, // 0x066d
-   {0, 0, 0, 0}, // 0x066e
-   {0, 0, 0, 0}, // 0x066f
-   {0, 0, 0, 0}, // 0x0670
-   {0, 0, 0, 0}, // 0x0671
-   {0, 0, 0, 0}, // 0x0672
-   {0, 0, 0, 0}, // 0x0673
-   {0, 0, 0, 0}, // 0x0674
-   {0, 0, 0, 0}, // 0x0675
-   {0, 0, 0, 0}, // 0x0676
-   {0, 0, 0, 0}, // 0x0677
-   {0, 0

[LyX features/str-metrics] Update 00README_STR_METRICS_BRANCH

2014-06-25 Thread Jean-Marc Lasgouttes
The branch, str-metrics, has been updated.

- Log -

commit 0bdf12ff4ff041d8a37abd8c7b7d625e17302acb
Author: Jean-Marc Lasgouttes <lasgout...@lyx.org>
Date:   Fri Jun 13 16:46:05 2014 +0200

Update 00README_STR_METRICS_BRANCH

diff --git a/00README_STR_METRICS_BRANCH b/00README_STR_METRICS_BRANCH
index 2dc3cad..6668623 100644
--- a/00README_STR_METRICS_BRANCH
+++ b/00README_STR_METRICS_BRANCH
@@ -16,6 +16,7 @@ Currently everything is supposed to work for both LTR and RTL 
text.
 The bugs fixed and caused by this branch are tracked at ticket #9003:
 http://www.lyx.org/trac/ticket/9003
 
+
 What is done:
 
 * Make TextMetrics methods operate on Row objects: breakRow and
@@ -38,10 +39,7 @@ What is done:
 * Implement proper string metrics computation (with cache). Remove
   useless workarounds which disable kerning and ligatures.
 
-* Draw also RtL text string-wise. This both speeds-up drawing and
-  prepares for code removal, since we now rely on Qt to do things we
-  use to do by ourselves (see isArabic* and isHebrew* code in
-  Encodings.cpp).
+* Draw also RtL text string-wise. This speeds-up drawing.
 
 * Do not cut strings at separators in RowPainter when text is not
   justified. This speeds-up painting by reducing the number of strings
@@ -51,16 +49,19 @@ What is done:
   ligature/kerning breaking in latin text, and bad rendering problems
   in Arabic.
 
+* Remove homebrew Arabic and Hebrew support from Encoding.cpp. We now
+  rely on Qt to do handle complex scripts.
 
-Next steps:
 
-* Fix bugs uncovered by testing.
+Next steps:
 
 * Get rid of LyXRC::force_paint_single_char, which is not used anymore
   in the source.
 
 * Maybe get rid of LyXRC::rtl_support, which does not have a real use case.
 
+* Fix bugs uncovered by testing.
+
 * Profile and see how performance can be improved.
 
 
@@ -70,9 +71,14 @@ Steps for later (aka out of the scope of this branch):
   in principle, but the code is intricate and needs some careful
   analysis. The first thing that needs to be done is to break row
   elements with the same criteria. Currently breakRow does not
-  consider on-the-fly spell-checking and selection changes, but it is
-  not clear to me that it is required. Moreover, this thing would only
-  work if we are sure that the Row object is up-to-date when drawing
-  happens. This depends on the update machinery.
+  consider on-the-fly spell-checking, but it is not clear to me that
+  it is required. Moreover, this thing would only work if we are sure
+  that the Row object is up-to-date when drawing happens. This depends
+  on the update machinery.
 
   This would allow to get rid of the Bidi.cpp code.
+
+* Change Row object to operate only on integers and not doubles. Then,
+  rewrite the computation of spacing in justified paragraphs so that
+  strings can be drawn without cutting at separators. This will improve
+  performance.

---

Summary of changes:
 00README_STR_METRICS_BRANCH |   26 --
 1 files changed, 16 insertions(+), 10 deletions(-)


hooks/post-receive
-- 
Repository for new features


[LyX features/str-metrics] Fix Qt5 incompatibility

2014-07-01 Thread Jean-Marc Lasgouttes
The branch, str-metrics, has been updated.

- Log -

commit 14ef2214cd68ad75e5a309595ef27bc34f5b4dba
Author: Jean-Marc Lasgouttes <lasgout...@lyx.org>
Date:   Tue Jul 1 23:54:14 2014 +0200

Fix Qt5 incompatibility

Support for Qt::UniteClip has been removed in Qt5. Therefore, we replace 
its use by two consecutive draw() with different clip rectangle.

diff --git a/src/frontends/qt4/GuiPainter.cpp b/src/frontends/qt4/GuiPainter.cpp
index 99d4685..a33aebf 100644
--- a/src/frontends/qt4/GuiPainter.cpp
+++ b/src/frontends/qt4/GuiPainter.cpp
@@ -426,11 +426,12 @@ int GuiPainter::text(int x, int y, docstring const & str, 
Font const & f,
setClipRect(QRect(x + xmin, y - ascent, xmax - xmin, height));
int const textwidth = text(x, y, dstr, fi);
 
-   // First the part in normal color
+   // Then the part in normal color
+   // Note that in Qt5, it is not possible to use Qt::UniteClip
fi.setPaintColor(orig);
setClipRect(QRect(x, y - ascent, xmin, height));
-   setClipRect(QRect(x + xmax, y - ascent, textwidth - xmax, height),
-   Qt::UniteClip);
+   text(x, y, dstr, fi);
+   setClipRect(QRect(x + xmax, y - ascent, textwidth - xmax, height));
text(x, y, dstr, fi);
setClipping(false);
 

---

Summary of changes:
 src/frontends/qt4/GuiPainter.cpp |7 ---
 1 files changed, 4 insertions(+), 3 deletions(-)


hooks/post-receive
-- 
Repository for new features


Re: [LyX/master] Update autotools for building with Qt5.

2014-07-19 Thread Jean-Marc Lasgouttes

Le 19/07/14 03:41, Enrico Forestieri a écrit :

commit 4bdeae27334536164cb7e37da9a9e491075fd682
Author: Enrico Forestieri 
Date:   Sat Jul 19 03:34:28 2014 +0200

 Update autotools for building with Qt5.

 The option --enable-qt5 allows configuring for Qt5. The default is Qt4.
 Nothing special is done with respect to Qt4, apart from pulling in the
 correct libraries. Indeed, other than the core and gui libraries, now
 also the concurrent and widgets libraries are needed.


Is this --enable-qt5 needed? The version number is already available, 
isn't it?


JMarc



[LyX/2.1.x] Fix error spotted by cppcheck

2014-07-19 Thread Jean-Marc Lasgouttes
commit fa67a6ae89e94fcbd1dbd7446320a7806b74ff21
Author: Jean-Marc Lasgouttes <lasgout...@lyx.org>
Date:   Sun Jul 20 00:04:45 2014 +0200

Fix error spotted by cppcheck

diff --git a/src/support/lstrings.cpp b/src/support/lstrings.cpp
index 7af8aae..d4b1ccf 100644
--- a/src/support/lstrings.cpp
+++ b/src/support/lstrings.cpp
@@ -1407,7 +1407,7 @@ docstring bformat(docstring const & fmt, char const * 
arg1, docstring arg2)
LATTEST(contains(fmt, from_ascii("%1$s")));
LATTEST(contains(fmt, from_ascii("%2$s")));
docstring str = subst(fmt, from_ascii("%1$s"), from_ascii(arg1));
-   str = subst(fmt, from_ascii("%2$s"), arg2);
+   str = subst(str, from_ascii("%2$s"), arg2);
return subst(str, from_ascii("%%"), from_ascii("%"));
 }
 
diff --git a/status.21x b/status.21x
index 0522009..3db8551 100644
--- a/status.21x
+++ b/status.21x
@@ -65,7 +65,9 @@ What's new
 
 * INTERNALS
 
-- Improve thread-safety
+- Improve thread-safety.
+
+- Fix potential bug spotted by cppcheck.
 
 
 * DOCUMENTATION AND LOCALIZATION


[LyX/2.1.x] Do not forget last word of paragraph in completion

2014-07-19 Thread Jean-Marc Lasgouttes
commit 3e60f58a92e6860d904b8c1373b9968603a1d180
Author: Jean-Marc Lasgouttes <lasgout...@lyx.org>
Date:   Fri May 16 15:17:10 2014 +0200

Do not forget last word of paragraph in completion

With the old code, the last word of a paragraph would not be added in
the completion list. The key difference is to pass `from' instead of `pos'
to FontList::fontiterator.

Slight cleanup of the code.

diff --git a/src/Paragraph.cpp b/src/Paragraph.cpp
index fccc28f..81ca225 100644
--- a/src/Paragraph.cpp
+++ b/src/Paragraph.cpp
@@ -3861,20 +3861,19 @@ void Paragraph::locateWord(pos_type & from, pos_type & 
to,
 
 void Paragraph::collectWords()
 {
-   pos_type n = size();
-   for (pos_type pos = 0; pos < n; ++pos) {
+   for (pos_type pos = 0; pos < size(); ++pos) {
if (isWordSeparator(pos))
continue;
pos_type from = pos;
locateWord(from, pos, WHOLE_WORD);
-   if ((pos - from) >= (int)lyxrc.completion_minlength) {
-   docstring word = asString(from, pos, AS_STR_NONE);
-   FontList::const_iterator cit = 
d->fontlist_.fontIterator(pos);
-   if (cit == d->fontlist_.end())
-   return;
-   Language const * lang = cit->font().language();
-   d->words_[lang->lang()].insert(word);
-   }
+   if (pos < from + lyxrc.completion_minlength)
+   continue;
+   FontList::const_iterator cit = d->fontlist_.fontIterator(from);
+   if (cit == d->fontlist_.end())
+   return;
+   Language const * lang = cit->font().language();
+   docstring const word = asString(from, pos, AS_STR_NONE);
+   d->words_[lang->lang()].insert(word);
}
 }
 
diff --git a/status.21x b/status.21x
index 3db8551..46333c2 100644
--- a/status.21x
+++ b/status.21x
@@ -55,12 +55,14 @@ What's new
 
 * LYX2LYX
 
-- Fix warning "Missing \use_indices" when converting from 1.6.x format or older
+- Fix warning "Missing \use_indices" when converting from 1.6.x format
+  or older.
 
 
 
 * USER INTERFACE
 
+- Do not forget last words of paragraphs in completion possibilities.
 
 
 * INTERNALS


[LyX features/str-metrics] Revert optimization where several words are drawn at the same time

2014-07-20 Thread Jean-Marc Lasgouttes
The branch, str-metrics, has been updated.

- Log -

commit bbe6e9f593fc585ee9f5d69275487bf3ddbcaf47
Author: Jean-Marc Lasgouttes <lasgout...@lyx.org>
Date:   Sun Jul 20 18:54:31 2014 +0200

Revert optimization where several words are drawn at the same time

This can only be done where splitting of string is identical in row 
breaking and display. It will be possible to reintroduce this when row painting 
uses the tokenized row information.

diff --git a/00README_STR_METRICS_BRANCH b/00README_STR_METRICS_BRANCH
index e901b51..342d2f6 100644
--- a/00README_STR_METRICS_BRANCH
+++ b/00README_STR_METRICS_BRANCH
@@ -39,10 +39,6 @@ What is done:
 
 * Draw also RtL text string-wise. This speeds-up drawing.
 
-* Do not cut strings at separators in RowPainter when text is not
-  justified. This speeds-up painting by reducing the number of strings
-  to draw.
-
 * Do not cut strings at selection boundary in RowPainter. This avoids
   ligature/kerning breaking in latin text, and bad rendering problems
   in Arabic.
diff --git a/src/TextMetrics.cpp b/src/TextMetrics.cpp
index 4dde5fd..45a5007 100644
--- a/src/TextMetrics.cpp
+++ b/src/TextMetrics.cpp
@@ -565,7 +565,7 @@ void TextMetrics::computeRowMetrics(pit_type const pit,
 
Paragraph const & par = text_->getPar(pit);
 
-   double w = width - row.right_margin - row.width();
+   double const w = width - row.right_margin - row.width();
// FIXME: put back this assertion when the crash on new doc is solved.
//LASSERT(w >= 0, /**/);
 
@@ -607,9 +607,7 @@ void TextMetrics::computeRowMetrics(pit_type const pit,
} else if (int(row.width()) < max_width_) {
// is it block, flushleft or flushright?
// set x how you need it
-   int const align = getAlign(par, row.pos());
-
-   switch (align) {
+   switch (getAlign(par, row.pos())) {
case LYX_ALIGN_BLOCK: {
int const ns = numberOfSeparators(row);
/** If we have separators, and this row has
@@ -650,12 +648,12 @@ void TextMetrics::computeRowMetrics(pit_type const pit,
}
 #endif
 
+   // Finally,  handle hfill insets
pos_type const endpos = row.endpos();
pos_type body_pos = par.beginOfBody();
if (body_pos > 0
&& (body_pos > endpos || !par.isLineSeparator(body_pos - 1)))
body_pos = 0;
-
ParagraphMetrics & pm = par_metrics_[pit];
Row::iterator cit = row.begin();
Row::iterator const cend = row.end();
@@ -798,8 +796,7 @@ void TextMetrics::breakRow(Row & row, int const 
right_margin, pit_type const pit
int const width = max_width_ - right_margin;
pos_type const body_pos = par.beginOfBody();
row.clear();
-   row.x = leftMargin(max_width_, pit, pos);
-   row.dimension().wid = row.x;
+   row.dimension().wid = leftMargin(max_width_, pit, pos);
row.right_margin = right_margin;
 
if (pos >= end || row.width() > width) {
diff --git a/src/frontends/qt4/GuiPainter.cpp b/src/frontends/qt4/GuiPainter.cpp
index a33aebf..2b51f47 100644
--- a/src/frontends/qt4/GuiPainter.cpp
+++ b/src/frontends/qt4/GuiPainter.cpp
@@ -273,14 +273,14 @@ void GuiPainter::image(int x, int y, int w, int h, 
graphics::Image const & i)
 
 int GuiPainter::text(int x, int y, char_type c, FontInfo const & f)
 {
-   docstring s(1, c);
-   return text(x, y, s, f);
+   return text(x, y, docstring(1, c), f);
 }
 
 
 int GuiPainter::text(int x, int y, docstring const & s,
FontInfo const & f)
 {
+   //LYXERR0("text: x=" << x << ", s=" << s);
if (s.empty())
return 0;
 
diff --git a/src/rowpainter.cpp b/src/rowpainter.cpp
index ee4cd18..8c8ac4c 100644
--- a/src/rowpainter.cpp
+++ b/src/rowpainter.cpp
@@ -186,16 +186,15 @@ void RowPainter::paintChars(pos_type & vpos, Font const & 
font)
}
str.push_back(c);
 
-   pos_type const end = row_.endpos();
FontSpan const font_span = par_.fontSpan(pos);
// Track-change status.
Change const & change_running = par_.lookupChange(pos);
-
// spelling correct?
bool const spell_state =
lyxrc.spellcheck_continuously && par_.isMisspelled(pos);
 
// collect as much similar chars as we can
+   pos_type const end = row_.endpos();
for (++vpos ; vpos < end ; ++vpos) {
pos = bidi_.vis2log(vpos);
 
@@ -218,11 +217,7 @@ void RowPainter::paintChars(pos_type & vpos, Font const & 
font)
if (c == '\t')
break;
 
-   // When row_.separator == 0, it is possible to print a
-   // string longer than a word in one fell swoop.
-  

[LyX/master] Handle boundary in getColumnNearX (and more)

2014-07-25 Thread Jean-Marc Lasgouttes
commit ff608f46fdb40aa565190aa050e49df16ee96040
Author: Jean-Marc Lasgouttes <lasgout...@lyx.org>
Date:   Sun Jul 21 20:22:32 2013 +0200

Handle boundary in getColumnNearX (and more)

Use proper font everywhere for end-of-par marker

Fix getColumnNearX for RTL text and for centered/right-justified paragraphs.

Let computeRowMetrics update the row width.

diff --git a/00README_STR_METRICS_BRANCH b/00README_STR_METRICS_BRANCH
index 0727011..2e27eee 100644
--- a/00README_STR_METRICS_BRANCH
+++ b/00README_STR_METRICS_BRANCH
@@ -8,13 +8,12 @@ What is done:
   setRowHeight instead of rowBreakPoint and rowHeight.
 
 * change breakRow operation to operate on text strings on which
-  metrics are computed. The list of elements is stored in the row object
-  in visual ordering, not logical.
+  metrics are computed. The list of elements is stored in the row
+  object in visual ordering, not logical.
 
 * re-implement cursorX using row elements
 
-* re-implement getColumnNearX using row elements (boundary is not
-  considered yet).
+* re-implement getColumnNearX using row elements.
 
 * Implement proper string metrics computation (with cache), when
   lyxrc.force_paint_single_char is false. In this case, remove also
@@ -23,7 +22,8 @@ What is done:
 Next steps:
 
 * get rid of old code of cursorX and getColumnNearX (which have been
-  kept for comparison purpose, guarded with KEEP_OLD_METRICS_CODE).
+  kept for comparison purpose, guarded with KEEP_OLD_METRICS_CODE in
+  order to check computations).
 
 * re-implement row painting using row elements (can it be done?)
 
@@ -31,17 +31,15 @@ Next steps:
 
 * Document the code
 
-Difference in behavior
+Difference in behavior (aka bug fixes)
+
 * end of paragraph markers metrics are computed with the font of the
-  actual text, not default font. This will be extended to the other
-  methods.
+  actual text, not default font.
 
-* When cursor is after a LtR separator just before a RtL chunk, the
+* When cursor is after a LTR separator just before a RTL chunk, the
   cursor posiiton is computed better with the new code.
 
-Other differences that should be considered as bugs
+Other differences (aka real bugs)
 * words longer than the screen are no monger broken at an arbitrary
   point. This is a problem for languages like chinese that do not use
   separators.
-
-* Boundary is not taken in account properly in getColumnNearX
diff --git a/src/Row.cpp b/src/Row.cpp
index c32be85..aef6efb 100644
--- a/src/Row.cpp
+++ b/src/Row.cpp
@@ -54,7 +54,7 @@ double Row::Element::pos2x(pos_type const i) const
 }
 
 
-pos_type Row::Element::x2pos(double ) const
+   pos_type Row::Element::x2pos(double , bool const low) const
 {
//lyxerr << "x2pos: x=" << x << " w=" << width() << " " << *this;
// if element is rtl, flip x value
@@ -84,7 +84,7 @@ pos_type Row::Element::x2pos(double ) const
}
 
// round to the closest side
-   if (x2 - last_w > w - x2) {
+   if (!low && (x2 - last_w > w - x2)) {
x2 = w;
++i;
} else
@@ -92,15 +92,13 @@ pos_type Row::Element::x2pos(double ) const
 
// is element is rtl, flip values
if (rtl) {
-   x = last_w - x2;
-   i = endpos - i;
+   x = width() - x2;
} else {
x = x2;
-   i = pos + i;
}
 
//lyxerr << "=> p=" << i << " x=" << x << endl;
-   return i;
+   return pos + i;
 }
 
 
@@ -335,9 +333,9 @@ void Row::pop_back()
 }
 
 
-void Row::separate_back(pos_type const keep)
+void Row::shorten_if_needed(pos_type const keep, int const w)
 {
-   if (empty())
+   if (empty() || width() < w)
return;
int i = elements_.size();
int new_end = end_;
@@ -353,15 +351,32 @@ void Row::separate_back(pos_type const keep)
new_end = elements_[i].pos;
new_wid -= elements_[i].dim.wid;
}
-   if (i == 0)
+   if (i == 0) {
+   if (elements_.size() != 1) {
+   LYXERR0("Row is too large but has more than one 
element. " << *this);
+   return;
+   }
+#if 1
return;
+#else
+   // does not work yet
+   if (back().type != STRING)
+   return;
+   double xstr = w - x;
+   pos_type new_pos = back().x2pos(xstr, true);
+   back().str = back().str.substr(0, new_pos);
+   back().endpos = new_pos;
+   end_ = new_pos;
+   dim_.wid = x + xstr;
+#endif
+   }
end_ = new_end;
dim_.wid = new_wid;
elements_.erase(elements_.begin() + i, elements_.end());
 }
 
 
-void Row::reverseRtL()
+void Row::reverseRTL()
 {
pos_typ

[LyX/master] Revert temporarily changes related to InsetSeparator

2014-07-25 Thread Jean-Marc Lasgouttes
commit edcedf33243d549c24a9ed9e37383f9c7d14d1e0
Author: Jean-Marc Lasgouttes <lasgout...@lyx.org>
Date:   Wed Jun 25 12:39:58 2014 +0200

Revert temporarily changes related to InsetSeparator

This is to avoid many conflicts with the str-metrics branch.

diff --git a/src/TextMetrics.cpp b/src/TextMetrics.cpp
index 1b434a5..66771d4 100644
--- a/src/TextMetrics.cpp
+++ b/src/TextMetrics.cpp
@@ -348,7 +348,6 @@ bool TextMetrics::isRTLBoundary(pit_type pit, pos_type pos,
// FED  FED| FED )
if (startpos == pos && endpos == pos && endpos != par.size()
&& (par.isNewline(pos - 1)
-   || par.isEnvSeparator(pos - 1)
|| par.isLineSeparator(pos - 1)
|| par.isSeparator(pos - 1)))
return false;
@@ -629,7 +628,6 @@ void TextMetrics::computeRowMetrics(pit_type const pit,
if (ns
&& row.endpos() < par.size()
&& !par.isNewline(row.endpos() - 1)
-   && !par.isEnvSeparator(row.endpos() - 1)
&& !disp_inset
) {
row.separator = w / ns;
@@ -695,13 +693,13 @@ int TextMetrics::labelFill(pit_type const pit, Row const 
& row) const
Paragraph const & par = text_->getPar(pit);
 
pos_type last = par.beginOfBody();
-   LBUFERR(last > 0 || par.isEnvSeparator(0));
+   LBUFERR(last > 0);
 
// -1 because a label ends with a space that is in the label
--last;
 
// a separator at this end does not count
-   if (last >= 0 && par.isLineSeparator(last))
+   if (par.isLineSeparator(last))
--last;
 
int w = 0;
@@ -899,7 +897,7 @@ pos_type TextMetrics::rowBreakPoint(int width, pit_type 
const pit,
break;
}
 
-   if (par.isNewline(i) || par.isEnvSeparator(i)) {
+   if (par.isNewline(i)) {
point = i + 1;
break;
}
@@ -1271,7 +1269,7 @@ pos_type TextMetrics::getColumnNearX(pit_type const pit,
if (lastrow &&
((rtl_on_lastrow  &&  left_side && vc == row.pos() && x < tmpx - 5) 
||
 (!rtl_on_lastrow && !left_side && vc == end  && x > tmpx + 5))) {
-   if (!(par.isNewline(end - 1) || par.isEnvSeparator(end - 1)))
+   if (!par.isNewline(end - 1))
c = end;
} else if (vc == row.pos()) {
c = bidi.vis2log(vc);
@@ -1320,9 +1318,7 @@ pos_type TextMetrics::getColumnNearX(pit_type const pit,
if (!c || end == par.size())
return col;
 
-   if (c==end && !par.isLineSeparator(c-1)
-  && !par.isNewline(c-1)
-  && !par.isEnvSeparator(c-1)) {
+   if (c==end && !par.isLineSeparator(c-1) && !par.isNewline(c-1)) {
boundary = true;
return col;
}
@@ -1818,8 +1814,7 @@ bool TextMetrics::cursorEnd(Cursor & cur)
bool boundary = false;
if (end != cur.lastpos()) {
if (!cur.paragraph().isLineSeparator(end-1)
-   && !cur.paragraph().isNewline(end-1)
-   && !cur.paragraph().isEnvSeparator(end-1))
+   && !cur.paragraph().isNewline(end-1))
boundary = true;
else
--end;
@@ -1902,9 +1897,7 @@ int TextMetrics::leftMargin(int max_width,
l_margin = leftMargin(max_width, newpar);
// Remove the parindent that has been added
// if the paragraph was empty.
-   if (pars[newpar].empty() &&
-   buffer.params().paragraph_separation ==
-   BufferParams::ParagraphIndentSeparation) {
+   if (pars[newpar].empty()) {
docstring pi = 
pars[newpar].layout().parindent;
l_margin -= theFontMetrics(

buffer.params().getFont()).signedWidth(pi);
@@ -1922,16 +1915,10 @@ int TextMetrics::leftMargin(int max_width,
 
// This happens after sections or environments in standard classes.
// We have to check the previous layout at same depth.
-   if (buffer.params().paragraph_separation ==
-   BufferParams::ParagraphSkipSeparation)
-   parindent.erase();
-   else if (pit > 0 &a

[LyX/master] Get rid of ugly font metrics workarounds.

2014-07-25 Thread Jean-Marc Lasgouttes
commit 01c9bcb4328b286a922215c3c1a1583949c33d10
Author: Jean-Marc Lasgouttes <lasgout...@lyx.org>
Date:   Sun Jul 21 12:24:08 2013 +0200

Get rid of ugly font metrics workarounds.

Now we have proper ligatures and kerning on screen...

diff --git a/src/LyXRC.cpp b/src/LyXRC.cpp
index 2cc0369..0138f61 100644
--- a/src/LyXRC.cpp
+++ b/src/LyXRC.cpp
@@ -448,7 +448,8 @@ LyXRC::ReturnValues LyXRC::read(Lexer & lexrc, bool 
check_format)
return ReadError;
 
// default for current rowpainter capabilities
-   force_paint_single_char = true;
+   //force_paint_single_char = true;
+   force_paint_single_char = false;
 
// format prior to 2.0 and introduction of format tag
unsigned int format = 0;
diff --git a/src/frontends/qt4/GuiApplication.cpp 
b/src/frontends/qt4/GuiApplication.cpp
index f6c8433..660b122 100644
--- a/src/frontends/qt4/GuiApplication.cpp
+++ b/src/frontends/qt4/GuiApplication.cpp
@@ -2417,7 +2417,6 @@ void GuiApplication::restoreGuiSession()
 QString const GuiApplication::romanFontName()
 {
QFont font;
-   font.setKerning(false);
font.setStyleHint(QFont::Serif);
font.setFamily("serif");
 
@@ -2428,7 +2427,6 @@ QString const GuiApplication::romanFontName()
 QString const GuiApplication::sansFontName()
 {
QFont font;
-   font.setKerning(false);
font.setStyleHint(QFont::SansSerif);
font.setFamily("sans");
 
@@ -2439,7 +2437,6 @@ QString const GuiApplication::sansFontName()
 QString const GuiApplication::typewriterFontName()
 {
QFont font;
-   font.setKerning(false);
font.setStyleHint(QFont::TypeWriter);
font.setFamily("monospace");
 
diff --git a/src/frontends/qt4/GuiFontLoader.cpp 
b/src/frontends/qt4/GuiFontLoader.cpp
index fa5370c..4b79071 100644
--- a/src/frontends/qt4/GuiFontLoader.cpp
+++ b/src/frontends/qt4/GuiFontLoader.cpp
@@ -165,7 +165,8 @@ QFont symbolFont(QString const & family, bool * ok)
upper[0] = family[0].toUpper();
 
QFont font;
-   font.setKerning(false);
+   if (lyxrc.force_paint_single_char)
+   font.setKerning(false);
font.setFamily(family);
 
if (isChosenFont(font, family)) {
@@ -256,7 +257,8 @@ static QString makeFontName(QString const & family, QString 
const & foundry)
 GuiFontInfo::GuiFontInfo(FontInfo const & f)
: metrics(QFont())
 {
-   font.setKerning(false);
+   if (lyxrc.force_paint_single_char)
+   font.setKerning(false);
QString const pat = symbolFamily(f.family());
if (!pat.isEmpty()) {
bool ok;
diff --git a/src/frontends/qt4/GuiLog.cpp b/src/frontends/qt4/GuiLog.cpp
index d81849a..2f1ef16 100644
--- a/src/frontends/qt4/GuiLog.cpp
+++ b/src/frontends/qt4/GuiLog.cpp
@@ -132,7 +132,6 @@ GuiLog::GuiLog(GuiView & lv)
 
logTB->setReadOnly(true);
QFont font(guiApp->typewriterFontName());
-   font.setKerning(false);
font.setFixedPitch(true);
font.setStyleHint(QFont::TypeWriter);
logTB->setFont(font);
diff --git a/src/frontends/qt4/GuiPrefs.cpp b/src/frontends/qt4/GuiPrefs.cpp
index 6dfd337..396cab3 100644
--- a/src/frontends/qt4/GuiPrefs.cpp
+++ b/src/frontends/qt4/GuiPrefs.cpp
@@ -314,7 +314,6 @@ static void setComboxFont(QComboBox * cb, string const & 
family,
// for bug 1063.
 
QFont font;
-   font.setKerning(false);
 
QString const font_family = toqstr(family);
if (font_family == guiApp->romanFontName()) {
diff --git a/src/frontends/qt4/GuiProgressView.cpp 
b/src/frontends/qt4/GuiProgressView.cpp
index a22ea60..2e0dfad 100644
--- a/src/frontends/qt4/GuiProgressView.cpp
+++ b/src/frontends/qt4/GuiProgressView.cpp
@@ -61,7 +61,6 @@ GuiProgressView::GuiProgressView(GuiView & parent, 
Qt::DockWidgetArea area,
setWidget(widget_);
 
QFont font(guiApp->typewriterFontName());
-   font.setKerning(false);
font.setFixedPitch(true);
font.setStyleHint(QFont::TypeWriter);
widget_->outTE->setFont(font);
diff --git a/src/frontends/qt4/GuiViewSource.cpp 
b/src/frontends/qt4/GuiViewSource.cpp
index b2df874..68041d8 100644
--- a/src/frontends/qt4/GuiViewSource.cpp
+++ b/src/frontends/qt4/GuiViewSource.cpp
@@ -72,7 +72,6 @@ ViewSourceWidget::ViewSourceWidget()
///dialog_->viewSourceTV->setAcceptRichText(false);
// this is personal. I think source code should be in fixed-size font
QFont font(guiApp->typewriterFontName());
-   font.setKerning(false);
font.setFixedPitch(true);
font.setStyleHint(QFont::TypeWriter);
viewSourceTV->setFont(font);
diff --git a/src/rowpainter.cpp b/src/rowpainter.cpp
index cfa7f51..3f664f0 100644
--- a/src/rowpainter.cpp
+++ b/src/rowpainter.cpp
@@ -264,15 +264,7 @@ void RowPainter::paintChars(pos_type & vpos, FontInfo 
con

[LyX/master] Fix line breaking algorithm

2014-07-25 Thread Jean-Marc Lasgouttes
commit 6258cebb77d63928313cae14bbba5d7f092d0a5e
Author: Jean-Marc Lasgouttes <lasgout...@lyx.org>
Date:   Tue Jul 23 16:24:01 2013 +0200

Fix line breaking algorithm

Break words longer than the screen width. The code is more complicated
than I would like, but I have no better idea right now.

Implement properly the notion of a row broken by a display inset. This is 
useful in different places.

Also fix a bug with last line of a paragraph spotted by Kornel.

diff --git a/00README_STR_METRICS_BRANCH b/00README_STR_METRICS_BRANCH
index 2e27eee..31cc489 100644
--- a/00README_STR_METRICS_BRANCH
+++ b/00README_STR_METRICS_BRANCH
@@ -1,35 +1,41 @@
 This branch is where I (jmarc) try to implement string_wise metrics
-computation. This is done through a series of cleanups. The expected
-speed improvement will only be visible at the end of the road: indeed
-for now we intend to keep unchanged behavior for testing purposes.
+computation. This is done through a series of cleanups. The goal is to
+have both good metrics computation (and font with proper kerning and
+ligatures) and better performance than what we have with
+force_paint_single_char.
+
+Currently everything is supposed to work for LTR text, and RTL text
+should work too except possibly metrics with Arabic and Hebrew fonts.
+We'll see what to do after some feedback.
 
 What is done:
+
 * Make TextMetrics methods operate on Row objects: breakRow and
   setRowHeight instead of rowBreakPoint and rowHeight.
 
-* change breakRow operation to operate on text strings on which
+* Change breakRow operation to operate on text strings on which
   metrics are computed. The list of elements is stored in the row
   object in visual ordering, not logical.
 
-* re-implement cursorX using row elements
-
-* re-implement getColumnNearX using row elements.
+* Re-implement cursorX and getColumnNearX using row elements
 
 * Implement proper string metrics computation (with cache), when
   lyxrc.force_paint_single_char is false. In this case, remove also
   useless workarounds which disable kerning and ligatures.
 
-Next steps:
 
-* get rid of old code of cursorX and getColumnNearX (which have been
+Next possible steps:
+
+* Get rid of old code of cursorX and getColumnNearX (which have been
   kept for comparison purpose, guarded with KEEP_OLD_METRICS_CODE in
   order to check computations).
 
-* re-implement row painting using row elements (can it be done?)
+* Re-implement row painting using row elements. This is not difficult
+  in principle, but the code is intricate and needs some careful
+  analysis.
 
-* profile and see how performance can be improved.
+* Profile and see how performance can be improved.
 
-* Document the code
 
 Difference in behavior (aka bug fixes)
 
@@ -39,7 +45,7 @@ Difference in behavior (aka bug fixes)
 * When cursor is after a LTR separator just before a RTL chunk, the
   cursor posiiton is computed better with the new code.
 
+
 Other differences (aka real bugs)
-* words longer than the screen are no monger broken at an arbitrary
-  point. This is a problem for languages like chinese that do not use
-  separators.
+
+You tell me.
diff --git a/src/Row.cpp b/src/Row.cpp
index aef6efb..1a3bb24 100644
--- a/src/Row.cpp
+++ b/src/Row.cpp
@@ -54,7 +54,7 @@ double Row::Element::pos2x(pos_type const i) const
 }
 
 
-   pos_type Row::Element::x2pos(double , bool const low) const
+pos_type Row::Element::x2pos(double , bool const low) const
 {
//lyxerr << "x2pos: x=" << x << " w=" << width() << " " << *this;
// if element is rtl, flip x value
@@ -104,9 +104,9 @@ double Row::Element::pos2x(pos_type const i) const
 
 Row::Row()
: separator(0), label_hfill(0), x(0), right_margin(0),
-   sel_beg(-1), sel_end(-1),
-   begin_margin_sel(false), end_margin_sel(false),
-   changed_(false), crc_(0), pos_(0), end_(0)
+ sel_beg(-1), sel_end(-1),
+ begin_margin_sel(false), end_margin_sel(false),
+ changed_(false), crc_(0), pos_(0), end_(0), right_boundary_(false)
 {}
 
 
@@ -117,18 +117,6 @@ void Row::setCrc(size_type crc) const
 }
 
 
-void Row::pos(pos_type p)
-{
-   pos_ = p;
-}
-
-
-void Row::endpos(pos_type p)
-{
-   end_ = p;
-}
-
-
 bool Row::isMarginSelected(bool left_margin, DocIterator const & beg,
DocIterator const & end) const
 {
@@ -337,6 +325,10 @@ void Row::shorten_if_needed(pos_type const keep, int const 
w)
 {
if (empty() || width() < w)
return;
+
+   /** First, we try to remove elements one by one from the end
+* until a separator is found.
+*/
int i = elements_.size();
int new_end = end_;
int new_wid = dim_.wid;
@@ -352,23 +344,35 @@ void Row::shorten_if_needed(pos_type const keep, int 
const w)
new_wid -= elements_[i].dim.wid;
}
if (i == 0) {
-

[LyX/master] Change TextMetrics::rowHeight to setRowHeight

2014-07-25 Thread Jean-Marc Lasgouttes
commit cf3107793295e5550c67a1bd7e26776309e5dbc7
Author: Jean-Marc Lasgouttes <lasgout...@lyx.org>
Date:   Fri Jun 14 19:24:29 2013 +0200

Change TextMetrics::rowHeight to setRowHeight

This new function takes a row as parameter.

Also, add direct access to Row::dim_

diff --git a/src/Row.cpp b/src/Row.cpp
index 66b1726..5fd2abb 100644
--- a/src/Row.cpp
+++ b/src/Row.cpp
@@ -41,12 +41,6 @@ void Row::setCrc(size_type crc) const
 }
 
 
-void Row::setDimension(Dimension const & dim)
-{
-   dim_ = dim;
-}
-
-
 void Row::pos(pos_type p)
 {
pos_ = p;
diff --git a/src/Row.h b/src/Row.h
index c26752b..2806824 100644
--- a/src/Row.h
+++ b/src/Row.h
@@ -61,10 +61,10 @@ public:
///
pos_type endpos() const { return end_; }
///
-   void setDimension(Dimension const & dim);
-   ///
Dimension const & dimension() const { return dim_; }
///
+   Dimension & dimension() { return dim_; }
+   ///
int height() const { return dim_.height(); }
///
int width() const { return dim_.wid; }
diff --git a/src/TextMetrics.cpp b/src/TextMetrics.cpp
index 3026367..6880e14 100644
--- a/src/TextMetrics.cpp
+++ b/src/TextMetrics.cpp
@@ -460,32 +460,27 @@ bool TextMetrics::redoParagraph(pit_type const pit)
pos_type first = 0;
size_t row_index = 0;
// maximum pixel width of a row
-   int width = max_width_ - right_margin; // - leftMargin(max_width_, pit, 
row);
do {
-   Dimension dim;
-   pos_type end = rowBreakPoint(width, pit, first);
-   if (row_index || end < par.size())
-   // If there is more than one row, expand the text to
-   // the full allowable width. This setting here is needed
-   // for the computeRowMetrics() below.
-   dim_.wid = max_width_;
-
-   dim = rowHeight(pit, first, end);
-   dim.wid = rowWidth(right_margin, pit, first, end);
if (row_index == pm.rows().size())
pm.rows().push_back(Row());
Row & row = pm.rows()[row_index];
-   row.setChanged(false);
row.pos(first);
-   row.endpos(end);
-   row.setDimension(dim);
-   int const max_row_width = max(dim_.wid, dim.wid);
+   breakRow(row, right_margin, pit);
+   setRowHeight(row, pit);
+   row.dimension().wid = rowWidth(right_margin, pit, first, 
row.endpos());
+   row.setChanged(false);
+   if (row_index || row.endpos() < par.size())
+   // If there is more than one row, expand the text to
+   // the full allowable width. This setting here is needed
+   // for the computeRowMetrics() below.
+   dim_.wid = max_width_;
+   int const max_row_width = max(dim_.wid, row.width());
computeRowMetrics(pit, row, max_row_width);
-   first = end;
+   first = row.endpos();
++row_index;
 
-   pm.dim().wid = max(pm.dim().wid, dim.wid);
-   pm.dim().des += dim.height();
+   pm.dim().wid = max(pm.dim().wid, row.width());
+   pm.dim().des += row.height();
} while (first < par.size());
 
if (row_index < pm.rows().size())
@@ -494,18 +489,17 @@ bool TextMetrics::redoParagraph(pit_type const pit)
// Make sure that if a par ends in newline, there is one more row
// under it
if (first > 0 && par.isNewline(first - 1)) {
-   Dimension dim = rowHeight(pit, first, first);
-   dim.wid = rowWidth(right_margin, pit, first, first);
if (row_index == pm.rows().size())
pm.rows().push_back(Row());
Row & row = pm.rows()[row_index];
-   row.setChanged(false);
row.pos(first);
row.endpos(first);
-   row.setDimension(dim);
-   int const max_row_width = max(dim_.wid, dim.wid);
+   row.dimension().wid = rowWidth(right_margin, pit, first, first);
+   setRowHeight(row, pit);
+   row.setChanged(false);
+   int const max_row_width = max(dim_.wid, row.width());
computeRowMetrics(pit, row, max_row_width);
-   pm.dim().des += dim.height();
+   pm.dim().des += row.height();
}
 
pm.dim().asc += pm.rows()[0].ascent();
@@ -719,7 +713,7 @@ int TextMetrics::labelFill(pit_type const pit, Row const & 
row) const
 
 
 #if 0
-// Not used, see TextMetrics::rowBreakPoint.
+// Not used, see TextMetrics::breakRow
 // this needs special handling - only newlines count as a break point
 static pos_type addressBreakPoint(pos_type i, Paragraph co

[LyX/master] Store in the Row object the list of elements it contains

2014-07-25 Thread Jean-Marc Lasgouttes
commit 452fb6035999c88279a72b3e374bd69d39a3d67f
Author: Jean-Marc Lasgouttes <lasgout...@lyx.org>
Date:   Tue Jun 25 14:57:09 2013 +0200

Store in the Row object the list of elements it contains

* Row now contains a vector of Elements
* replace Row::dump by a proper << operator
* the width is updated as elements are added
* breakRow is reimplmented to use this infrastructure

diff --git a/00README_STR_METRICS_BRANCH b/00README_STR_METRICS_BRANCH
index 53d9fd3..26c2fba 100644
--- a/00README_STR_METRICS_BRANCH
+++ b/00README_STR_METRICS_BRANCH
@@ -8,18 +8,13 @@ What is done:
   setRowHeight instead of rowBreakPoint and rowHeight.
 
 * change breakRow operation to operate on text strings on which
-  metrics are computed. Note that for now
-  FontMetrics::width(docstring) still computes the sum of character
-  widths, so that behavior is unchanged.
+  metrics are computed. The list of elements is stored in the row object
 
 * Implement proper string metrics computation (with cache), when
   lyxrc.force_paint_single_char is false.
 
 Next steps:
 
-* Make breakRow build a list of elements (string, inset,
-  separator,...) in the row. This will be reused by other methods
-
 * get rid of rowWidth (breakRow does compute this)
 
 * re-implement getColumnNearX using row elements
@@ -37,4 +32,9 @@ point. This will not be useful anymore with horizontal 
scrolling.
 actual text, not default font. This will be extended to the other
 methods.
 
-The other differences should be considered as bugs.
+Other differences that should be considered as bugs
+* there are still some difference in width computation wrt
+  TextMetrics::rowWidth. This happens in particular with Description
+  environment when the row is broken at bodypos. The method rowWidth
+  is kept for now in order to be able to detect row parsing errors,
+  but it could be removed right now.
diff --git a/src/ParagraphMetrics.cpp b/src/ParagraphMetrics.cpp
index d7fb42b..93b0461 100644
--- a/src/ParagraphMetrics.cpp
+++ b/src/ParagraphMetrics.cpp
@@ -190,8 +190,7 @@ void ParagraphMetrics::dump() const
 {
lyxerr << "Paragraph::dump: rows.size(): " << rows_.size() << endl;
for (size_t i = 0; i != rows_.size(); ++i) {
-   lyxerr << "  row " << i << ":   ";
-   rows_[i].dump();
+   lyxerr << "  row " << i << ":   " << rows_[i];
}
 }
 
diff --git a/src/Row.cpp b/src/Row.cpp
index 5fd2abb..ef2fbbb 100644
--- a/src/Row.cpp
+++ b/src/Row.cpp
@@ -20,8 +20,13 @@
 
 #include "DocIterator.h"
 
+#include "frontends/FontMetrics.h"
+
 #include "support/debug.h"
 
+#include 
+
+using namespace std;
 
 namespace lyx {
 
@@ -29,7 +34,7 @@ namespace lyx {
 Row::Row()
: separator(0), label_hfill(0), x(0),
sel_beg(-1), sel_end(-1),
-   begin_margin_sel(false), end_margin_sel(false), 
+   begin_margin_sel(false), end_margin_sel(false),
changed_(false), crc_(0), pos_(0), end_(0)
 {}
 
@@ -62,7 +67,7 @@ bool Row::isMarginSelected(bool left_margin, DocIterator 
const & beg,
// Is the chosen margin selected ?
if (sel_pos == margin_pos) {
if (beg.pos() == end.pos())
-   // This is a special case in which the space between 
after 
+   // This is a special case in which the space between 
after
// pos i-1 and before pos i is selected, i.e. the 
margins
// (see DocIterator::boundary_).
return beg.boundary() && !end.boundary();
@@ -71,21 +76,21 @@ bool Row::isMarginSelected(bool left_margin, DocIterator 
const & beg,
// drawn if the cursor is after the margin.
return !end.boundary();
else if (beg.pos() == margin_pos)
-   // If the selection begins around the margin, it is 
+   // If the selection begins around the margin, it is
// only drawn if the cursor is before the margin.
return beg.boundary();
-   else 
+   else
return true;
}
return false;
 }
 
 
-void Row::setSelectionAndMargins(DocIterator const & beg, 
+void Row::setSelectionAndMargins(DocIterator const & beg,
DocIterator const & end) const
 {
setSelection(beg.pos(), end.pos());
-   
+
if (selection()) {
end_margin_sel = isMarginSelected(false, beg, end);
begin_margin_sel = isMarginSelected(true, beg, end);
@@ -116,14 +121,151 @@ bool Row::selection() const
return sel_beg != -1 && sel_end != -1;
 }
 
+ostream & operator<<(ostream & os, Row const & row)
+{
+   os << "

[LyX/master] Implement proper handling of RtL in Rows

2014-07-25 Thread Jean-Marc Lasgouttes
commit b2eba66083f41b242faaad45d192abeb7d7480d2
Author: Jean-Marc Lasgouttes <lasgout...@lyx.org>
Date:   Wed Jul 17 00:59:34 2013 +0200

Implement proper handling of RtL in Rows

Now the row elements are sorted according to RtL/LtR.

Some additional cleanup.

diff --git a/00README_STR_METRICS_BRANCH b/00README_STR_METRICS_BRANCH
index 26c2fba..4b6ef10 100644
--- a/00README_STR_METRICS_BRANCH
+++ b/00README_STR_METRICS_BRANCH
@@ -9,6 +9,7 @@ What is done:
 
 * change breakRow operation to operate on text strings on which
   metrics are computed. The list of elements is stored in the row object
+  in visual ordering, not logical.
 
 * Implement proper string metrics computation (with cache), when
   lyxrc.force_paint_single_char is false.
@@ -26,13 +27,15 @@ Next steps:
 * profile and see how performance can be improved.
 
 Difference in behavior
-* words longer than the screen are no monger broken at an arbitrary
-point. This will not be useful anymore with horizontal scrolling.
 * end of paragraph markers metrics are computed with the font of the
-actual text, not default font. This will be extended to the other
-methods.
+  actual text, not default font. This will be extended to the other
+  methods.
 
 Other differences that should be considered as bugs
+* words longer than the screen are no monger broken at an arbitrary
+  point. This is a problem for languages like chinese that do not use
+  separators.
+
 * there are still some difference in width computation wrt
   TextMetrics::rowWidth. This happens in particular with Description
   environment when the row is broken at bodypos. The method rowWidth
diff --git a/src/Row.cpp b/src/Row.cpp
index ef2fbbb..ce1a440 100644
--- a/src/Row.cpp
+++ b/src/Row.cpp
@@ -130,16 +130,16 @@ ostream & operator<<(ostream & os, Row const & row)
Row::Elements::const_iterator it = row.elements_.begin();
for ( ; it != row.elements_.end() ; ++it) {
switch (it->type) {
-   case Row::Element::STRING_ELT:
+   case Row::Element::STRING:
os << "**STRING: " << to_utf8(it->str) << endl;
break;
-   case Row::Element::INSET_ELT:
+   case Row::Element::INSET:
os << "**INSET: " << to_utf8(it->inset->layoutName()) 
<< endl;
break;
-   case Row::Element::SEPARATOR_ELT:
+   case Row::Element::SEPARATOR:
os << "**SEPARATOR: " << endl;
break;
-   case Row::Element::SPACE_ELT:
+   case Row::Element::SPACE:
os << "**SPACE: " << it->dim.wid << endl;
break;
}
@@ -153,7 +153,7 @@ bool Row::sameString(Font const & f, Change const & ch) 
const
if (elements_.empty())
return false;
Element const & elt = elements_.back();
-   return elt.type == Element::STRING_ELT && !elt.final
+   return elt.type == Element::STRING && !elt.final
   && elt.font == f && elt.change == ch;
 }
 
@@ -167,18 +167,18 @@ void Row::finalizeLast()
return;
elt.final = true;
 
-   if (elt.type == Element::STRING_ELT) {
+   if (elt.type == Element::STRING) {
elt.dim.wid = theFontMetrics(elt.font).width(elt.str);
dim_.wid += elt.dim.wid;
}
 }
 
 
-void Row::add(pos_type const pos, Inset const * ins, Dimension const & dim)
+void Row::add(pos_type const pos, Inset const * ins, Dimension const & dim,
+ Font const & f, Change const & ch)
 {
finalizeLast();
-   Element e(Element::INSET_ELT);
-   e.pos = pos;
+   Element e(Element::INSET, pos, f, ch);
e.inset = ins;
e.dim = dim;
elements_.push_back(e);
@@ -186,27 +186,30 @@ void Row::add(pos_type const pos, Inset const * ins, 
Dimension const & dim)
 }
 
 
-void Row::add(pos_type const pos, docstring const & s,
+void Row::add(pos_type const pos, char_type const c,
  Font const & f, Change const & ch)
 {
-   if (sameString(f, ch))
-   elements_.back().str += s;
-   else {
+   if (!sameString(f, ch)) {
finalizeLast();
-   Element e(Element::STRING_ELT);
-   e.pos = pos;
-   e.str = s;
-   e.font = f;
-   e.change = ch;
+   Element e(Element::STRING, pos, f, ch);
elements_.push_back(e);
}
+   //lyxerr << "FONT " <<back().font.language() << endl;
+   back().str += c;
+   back().endpos = pos + 1;
 }
 
 
-void Row::add(pos_type const pos, char_type const c,

[LyX/master] Fix getColumnNearX for nested insets

2014-07-25 Thread Jean-Marc Lasgouttes
commit 059de2d04c40c63a013896e99a444b65529eb82d
Author: Jean-Marc Lasgouttes <lasgout...@lyx.org>
Date:   Fri Oct 11 16:12:20 2013 +0200

Fix getColumnNearX for nested insets

The horizontal position of the inset was not taken in account.
The rounding is not always the same as with the old code, but this
is not really important.

Additional changes:

 * improve debug output of rows

 * remove Bidi& argument of the RowPainter constructor, since it is always
   an empty Bifi that is passed. This means that the Bidi class is not
   used at all any more in TextMetrics.cpp. The only remaining user is
   RowPainter.

diff --git a/00README_STR_METRICS_BRANCH b/00README_STR_METRICS_BRANCH
index 31cc489..18c68ca 100644
--- a/00README_STR_METRICS_BRANCH
+++ b/00README_STR_METRICS_BRANCH
@@ -17,18 +17,24 @@ What is done:
   metrics are computed. The list of elements is stored in the row
   object in visual ordering, not logical.
 
-* Re-implement cursorX and getColumnNearX using row elements
+* Re-implement cursorX and getColumnNearX using row elements.
 
 * Implement proper string metrics computation (with cache), when
   lyxrc.force_paint_single_char is false. In this case, remove also
   useless workarounds which disable kerning and ligatures.
 
 
+Next steps needed:
+
+* check what happens with arabic and/or hebrew text. There may be some
+  problems related to compose characters. I suspect that some code is
+  needed in FontMetrics::width.
+
 Next possible steps:
 
-* Get rid of old code of cursorX and getColumnNearX (which have been
+* Get rid of old code in cursorX and getColumnNearX; it has been
   kept for comparison purpose, guarded with KEEP_OLD_METRICS_CODE in
-  order to check computations).
+  order to check computations.
 
 * Re-implement row painting using row elements. This is not difficult
   in principle, but the code is intricate and needs some careful
@@ -43,9 +49,11 @@ Difference in behavior (aka bug fixes)
   actual text, not default font.
 
 * When cursor is after a LTR separator just before a RTL chunk, the
-  cursor posiiton is computed better with the new code.
+  cursor position is computed better with the new code.
 
 
 Other differences (aka real bugs)
 
-You tell me.
+* there are still difference in what breaks words. In particular,
+  RowPainter breaks strings at: selection end, spellchecking
+  extremity.
diff --git a/src/Row.cpp b/src/Row.cpp
index 1a3bb24..d784979 100644
--- a/src/Row.cpp
+++ b/src/Row.cpp
@@ -218,9 +218,11 @@ ostream & operator<<(ostream & os, Row const & row)
   << " descent: " << row.dim_.des
   << " separator: " << row.separator
   << " label_hfill : " << row.label_hfill << "\n";
+   double x = row.x;
Row::Elements::const_iterator it = row.elements_.begin();
for ( ; it != row.elements_.end() ; ++it) {
-   os << "** " << *it << endl;
+   os << "x=" << x << " => " << *it << endl;
+   x += it->width();
}
return os;
 }
diff --git a/src/TextMetrics.cpp b/src/TextMetrics.cpp
index f4e03c3..d949e3a 100644
--- a/src/TextMetrics.cpp
+++ b/src/TextMetrics.cpp
@@ -21,7 +21,9 @@
 
 #include "TextMetrics.h"
 
+#ifdef KEEP_OLD_METRICS_CODE
 #include "Bidi.h"
+#endif
 #include "Buffer.h"
 #include "buffer_funcs.h"
 #include "BufferParams.h"
@@ -1115,9 +1117,18 @@ void TextMetrics::setRowHeight(Row & row, pit_type const 
pit,
 pos_type TextMetrics::getColumnNearX(pit_type const pit,
Row const & row, int & x, bool & boundary) const
 {
-   boundary = false;
+
+   /// For the main Text, it is possible that this pit is not
+   /// yet in the CoordCache when moving cursor up.
+   /// x Paragraph coordinate is always 0 for main text anyway.
+   int const xo = origin_.x_;
+   x -= xo;
+#ifdef KEEP_OLD_METRICS_CODE
+   int const x_orig = x;
+#endif
 
pos_type pos = row.pos();
+   boundary = false;
if (row.x >= x || row.empty())
x = row.x;
else if (x >= row.width() - row.right_margin) {
@@ -1158,16 +1169,13 @@ pos_type TextMetrics::getColumnNearX(pit_type const pit,
&& row.back().endpos == row.endpos())
boundary = row.right_boundary();
 
+   x += xo;
 #if !defined(KEEP_OLD_METRICS_CODE)
return pos - row.pos();
 #else
Buffer const & buffer = bv_->buffer();
 
-   /// For the main Text, it is possible that this pit is not
-   /// yet in the CoordCache when moving cursor up.
-   /// x Paragraph coordinate is always 0 for main text anyway.
-   int const xo = origin_.x_;
-   int x2 = x - xo;
+   int x2 = x_

[LyX/master] Implement real string width computation

2014-07-25 Thread Jean-Marc Lasgouttes
commit 8539f756ed20092fc6ea6273e77299963f6cc7b6
Author: Jean-Marc Lasgouttes <lasgout...@lyx.org>
Date:   Tue Jun 25 08:18:25 2013 +0200

Implement real string width computation

Important features:
* widths are cached in a map
* old behavior is still used when lyxrc.force_paint_single_char is true.

diff --git a/00README_STR_METRICS_BRANCH b/00README_STR_METRICS_BRANCH
index b34ba5b..53d9fd3 100644
--- a/00README_STR_METRICS_BRANCH
+++ b/00README_STR_METRICS_BRANCH
@@ -5,20 +5,29 @@ for now we intend to keep unchanged behavior for testing 
purposes.
 
 What is done:
 * Make TextMetrics methods operate on Row objects: breakRow and
-setRowHeight instead of rowBreakPoint and rowHeight.
+  setRowHeight instead of rowBreakPoint and rowHeight.
+
 * change breakRow operation to operate on text strings on which
-metrics are computed. Note that for now FontMetrics::width(docstring)
-still computes the sum of character widths, so that behavior is
-unchanged.
+  metrics are computed. Note that for now
+  FontMetrics::width(docstring) still computes the sum of character
+  widths, so that behavior is unchanged.
+
+* Implement proper string metrics computation (with cache), when
+  lyxrc.force_paint_single_char is false.
 
 Next steps:
+
 * Make breakRow build a list of elements (string, inset,
-separator,...) in the row. This will be reused by other methods
+  separator,...) in the row. This will be reused by other methods
+
 * get rid of rowWidth (breakRow does compute this)
+
 * re-implement getColumnNearX using row elements
-* re-implement x2pos using row elements
-* re-implement row painting using row elements
-* Finally, implement proper string metrics computation (with cache)
+
+* re-implement cursorX using row elements
+
+* re-implement row painting using row elements (can it be done?)
+
 * profile and see how performance can be improved.
 
 Difference in behavior
diff --git a/src/frontends/qt4/GuiFontMetrics.cpp 
b/src/frontends/qt4/GuiFontMetrics.cpp
index e007b4a..4be0fb2 100644
--- a/src/frontends/qt4/GuiFontMetrics.cpp
+++ b/src/frontends/qt4/GuiFontMetrics.cpp
@@ -15,8 +15,9 @@
 
 #include "qt_helpers.h"
 
-#include "Language.h"
 #include "Dimension.h"
+#include "Language.h"
+#include "LyXRC.h"
 
 #include "insets/Inset.h"
 
@@ -110,21 +111,20 @@ int GuiFontMetrics::rbearing(char_type c) const
 
 int GuiFontMetrics::width(docstring const & s) const
 {
-   size_t ls = s.size();
int w = 0;
-   for (unsigned int i = 0; i < ls; ++i) {
-   //FIXME: we need to detect surrogate pairs and act accordingly
-   /**
-   if isSurrogateBase(s[i]) {
-   docstring c = s[i];
-   w += metrics_.width(toqstr(c + s[i + 1]));
-   ++i;
+   if (lyxrc.force_paint_single_char) {
+   size_t const ls = s.size();
+   for (size_t i = 0; i < ls; ++i)
+   w += width(s[i]);
+   } else {
+   map<docstring, int>::const_iterator it = 
strwidth_cache_.find(s);
+   if (it != strwidth_cache_.end()) {
+   w = it->second;
+   } else {
+   w = metrics_.width(toqstr(s));
+   strwidth_cache_[s] = w;
}
-   else
-   */
-   w += width(s[i]);
}
-
return w;
 }
 
diff --git a/src/frontends/qt4/GuiFontMetrics.h 
b/src/frontends/qt4/GuiFontMetrics.h
index be36dbf..a2c57ec 100644
--- a/src/frontends/qt4/GuiFontMetrics.h
+++ b/src/frontends/qt4/GuiFontMetrics.h
@@ -16,6 +16,8 @@
 
 #include "support/docstring.h"
 
+#include 
+
 #include 
 #include 
 
@@ -59,6 +61,10 @@ private:
/// Cache of char widths
mutable QHash<char_type, int> width_cache_;
 
+   /// Cache of string widths
+   /// FIXME Try to use a QHash (this requires to define qHash(docstring))
+   mutable std::map<docstring, int> strwidth_cache_;
+
struct AscendDescend {
int ascent;
int descent;


[LyX/master] Small fixes to cursor positioning.

2014-07-25 Thread Jean-Marc Lasgouttes
commit 9ba97a85f06c6f0272d43e61a86cceefbec8fa29
Author: Jean-Marc Lasgouttes <lasgout...@lyx.org>
Date:   Fri Dec 20 12:12:27 2013 +0100

Small fixes to cursor positioning.

Two small fixed to Row::Element::x2pos:
* fix position for elements that are not strings
* make rounding match the old code

diff --git a/src/Row.cpp b/src/Row.cpp
index d7940e9..86b7d06 100644
--- a/src/Row.cpp
+++ b/src/Row.cpp
@@ -86,10 +86,12 @@ pos_type Row::Element::x2pos(double , bool const low) 
const
//  lyxerr << " NOT FOUND ";
}
 
-   if (i == str.size())
+   if (type == STRING && i == str.size())
x2 = w;
-   // round to the closest side
-   else if (!low && (x2 - last_w > w - x2)) {
+   // round to the closest side. The !rtl is here to obtain the
+   // same rounding as with the old code (this is cosmetic and
+   // can be eventually removed).
+   else if (!low && (x2 - last_w + !rtl > w - x2)) {
x2 = w;
++i;
} else


[LyX/master] New reverseRTL implementation

2014-07-25 Thread Jean-Marc Lasgouttes
commit 443a45342743615977b024ebfbaf1ecf1af7ddc8
Author: Jean-Marc Lasgouttes <lasgout...@lyx.org>
Date:   Wed Mar 19 14:44:31 2014 +0100

New reverseRTL implementation

The old version was a bit complicated and wrong for RtL paragraphs
containing LtR text. THe new one is clearer.

diff --git a/src/Row.cpp b/src/Row.cpp
index d784979..9da174f 100644
--- a/src/Row.cpp
+++ b/src/Row.cpp
@@ -382,24 +382,25 @@ void Row::shorten_if_needed(pos_type const keep, int 
const w)
 }
 
 
-void Row::reverseRTL()
+void Row::reverseRTL(bool const rtl_par)
 {
pos_type i = 0;
pos_type const end = elements_.size();
while (i < end) {
-   // skip LtR elements
-   while (i < end && !elements_[i].font.isRightToLeft())
-   ++i;
-   if (i >= end)
-   break;
-
-   // look for a RTL sequence
+   // gather a sequence of elements with the same direction
+   bool const rtl = elements_[i].font.isVisibleRightToLeft();
pos_type j = i;
-   while (j < end && elements_[j].font.isRightToLeft())
+   while (j < end && elements_[j].font.isVisibleRightToLeft() == 
rtl)
++j;
-   reverse(elements_.begin() + i, elements_.begin() + j);
+   // if the direction is not the same as the paragraph
+   // direction, the sequence has to be reverted.
+   if (rtl != rtl_par)
+   reverse(elements_.begin() + i, elements_.begin() + j);
i = j;
}
+   // If the paragraph itself is RTL, reverse everything
+   if (rtl_par)
+   reverse(elements_.begin(), elements_.end());
 }
 
 } // namespace lyx
diff --git a/src/Row.h b/src/Row.h
index 4f2bd74..2282c82 100644
--- a/src/Row.h
+++ b/src/Row.h
@@ -212,7 +212,7 @@ public:
 * Find sequences of right-to-left elements and reverse them.
 * This should be called once the row is completely built.
 */
-   void reverseRTL();
+   void reverseRTL(bool rtl_par);
 
friend std::ostream & operator<<(std::ostream & os, Row const & row);
 
diff --git a/src/TextMetrics.cpp b/src/TextMetrics.cpp
index d949e3a..ca6408d 100644
--- a/src/TextMetrics.cpp
+++ b/src/TextMetrics.cpp
@@ -929,7 +929,7 @@ void TextMetrics::breakRow(Row & row, int const 
right_margin, pit_type const pit
row.pop_back();
 
// make sure that the RTL elements are in reverse ordering
-   row.reverseRTL();
+   row.reverseRTL(text_->isRTL(par));
 
row.dimension().wid += right_margin;
 }


[LyX/master] Change getColumnNearX to getPosNearX

2014-07-25 Thread Jean-Marc Lasgouttes
commit f686375eecc92a2658425a6bb93ee184c5049ec1
Author: Jean-Marc Lasgouttes <lasgout...@lyx.org>
Date:   Fri Dec 20 14:02:31 2013 +0100

Change getColumnNearX to getPosNearX

The semantics was bad: the old implementation would return pos - row.pos(), 
and then all user of the function had to re-add row.pos().

diff --git a/00README_STR_METRICS_BRANCH b/00README_STR_METRICS_BRANCH
index e38d4b6..1983dfe 100644
--- a/00README_STR_METRICS_BRANCH
+++ b/00README_STR_METRICS_BRANCH
@@ -17,7 +17,11 @@ What is done:
   metrics are computed. The list of elements is stored in the row
   object in visual ordering, not logical.
 
-* Re-implement cursorX and getColumnNearX using row elements.
+* rename getColumnNearX to getPosNearX (and change code accordingly).
+  It does not make sense to return a position relative to the start of
+  row, since nobody needs this.
+
+* Re-implement cursorX and getPosNearX using row elements.
 
 * Implement proper string metrics computation (with cache), when
   lyxrc.force_paint_single_char is false. In this case, remove also
@@ -34,10 +38,6 @@ Next steps:
   kept for comparison purpose, guarded with KEEP_OLD_METRICS_CODE in
   order to check computations.
 
-* rename getColumnNearX to getPosNearX or x2pos (and change code
-  accordingly). It does not make sense to return a position relative
-  to the start of row, since nobody needs this.
-
 * Re-implement row painting using row elements. This is not difficult
   in principle, but the code is intricate and needs some careful
   analysis. First thing that needs to be done is to break row elements
diff --git a/src/Cursor.cpp b/src/Cursor.cpp
index 7dff932..61e4b60 100644
--- a/src/Cursor.cpp
+++ b/src/Cursor.cpp
@@ -2090,9 +2090,7 @@ bool Cursor::upDownInText(bool up, bool & updateNeeded)
 
Row const & real_next_row = 
tm.parMetrics(pit()).rows()[next_row];
bool bound = false;
-   pos_type const col = tm.getColumnNearX(pit(), real_next_row, 
-  xo, bound);
-   top().pos() = real_next_row.pos() + col;
+   top().pos() = tm.getPosNearX(pit(), real_next_row, xo, bound);
boundary(bound);
 
updateNeeded |= bv().checkDepm(*this, old);
diff --git a/src/Row.cpp b/src/Row.cpp
index 86b7d06..15af2c2 100644
--- a/src/Row.cpp
+++ b/src/Row.cpp
@@ -104,7 +104,7 @@ pos_type Row::Element::x2pos(double , bool const low) 
const
x = x2;
}
 
-   //lyxerr << "=> p=" << i << " x=" << x << endl;
+   //lyxerr << "=> p=" << pos + i << " x=" << x << endl;
return pos + i;
 }
 
diff --git a/src/TextMetrics.cpp b/src/TextMetrics.cpp
index b894133..9e775e0 100644
--- a/src/TextMetrics.cpp
+++ b/src/TextMetrics.cpp
@@ -1114,7 +1114,7 @@ void TextMetrics::setRowHeight(Row & row, pit_type const 
pit,
 // x is an absolute screen coord
 // returns the column near the specified x-coordinate of the row
 // x is set to the real beginning of this column
-pos_type TextMetrics::getColumnNearX(pit_type const pit,
+pos_type TextMetrics::getPosNearX(pit_type const pit,
Row const & row, int & x, bool & boundary) const
 {
 
@@ -1291,7 +1291,7 @@ pos_type TextMetrics::getColumnNearX(pit_type const pit,
 
if (abs(x2 - x) > 0.1 || boundary != boundary
|| c != pos) {
-   lyxerr << "getColumnNearX(" << x_orig << "): new=(x=" << x - xo 
<< ", b=" << boundary << ", p=" << pos << "), "
+   lyxerr << "getPosNearX(" << x_orig << "): new=(x=" << x - xo << 
", b=" << boundary << ", p=" << pos << "), "
   << "old=(x=" << x2 - xo << ", b=" << boundary2 << ", p=" 
<< c << "), " << row;
}
 
@@ -1307,7 +1307,7 @@ pos_type TextMetrics::getColumnNearX(pit_type const pit,
return min(col, end - 1 - row.pos());
 #endif // 0
 #endif // KEEP_OLD_METRICS_CODE
-   return pos - row.pos();
+   return pos;
 }
 
 
@@ -1322,7 +1322,7 @@ pos_type TextMetrics::x2pos(pit_type pit, int row, int x) 
const
LBUFERR(row < int(pm.rows().size()));
bool bound = false;
Row const & r = pm.rows()[row];
-   return r.pos() + getColumnNearX(pit, r, x, bound);
+   return getPosNearX(pit, r, x, bound);
 }
 
 
@@ -1482,10 +1482,9 @@ Inset * TextMetrics::editXY(Cursor & cur, int x, int y,
 
if (!it) {
// No inset, set position in the text
-   bool bound = false; // is modified by getColumnNearX
-   int xx 

[LyX/master] Update README and do a small code cleanup

2014-07-25 Thread Jean-Marc Lasgouttes
commit 1a4b3201e747c45d12044105d86cfc4a3f11af3c
Author: Jean-Marc Lasgouttes <lasgout...@lyx.org>
Date:   Mon Mar 3 15:29:37 2014 +0100

Update README and do a small code cleanup

diff --git a/00README_STR_METRICS_BRANCH b/00README_STR_METRICS_BRANCH
index 1983dfe..1bb7026 100644
--- a/00README_STR_METRICS_BRANCH
+++ b/00README_STR_METRICS_BRANCH
@@ -1,21 +1,34 @@
-This branch is where I (jmarc) try to implement string_wise metrics
-computation. This is done through a series of cleanups. The goal is to
-have both good metrics computation (and font with proper kerning and
-ligatures) and better performance than what we have with
-force_paint_single_char.
+
+
+PLEASE DO NOT DO WORK ON TOP OF THIS BRANCH.
+I INTEND TO REWRITE HISTORY LATER!!!
+
+
+This branch is where I (jmarc) try to implement string-wise metrics
+computation. The goal is to have both good metrics computation (and
+font with proper kerning and ligatures) and better performance than
+what we have with force_paint_single_char. Moreover there has been
+some code factorization in TextMetrics, where the same row-breaking
+algorithm was basically implemented 3 times.
 
 Currently everything is supposed to work for LTR text, and RTL text
 should work too except possibly metrics with Arabic and Hebrew fonts.
-We'll see what to do after some feedback.
+
+When KEEP_OLD_METRICS_CODE is defined in TextMetrics.cpp, the new code
+is tested against the old one in getPosNearX and cursorX. This can be
+helpful when looking for discrepancies between the algorithms. Note
+that this only makes sense when force_paint_single_char=true, since
+this enforces char-by-char metrics computation.
 
 What is done:
 
 * Make TextMetrics methods operate on Row objects: breakRow and
   setRowHeight instead of rowBreakPoint and rowHeight.
 
-* Change breakRow operation to operate on text strings on which
-  metrics are computed. The list of elements is stored in the row
-  object in visual ordering, not logical.
+* Change breakRow operation to operate at strings level to compute
+  metrics The list of elements is stored in the row object in visual
+  ordering, not logical. This will eventually allow to get rid of the
+  Bidi class.
 
 * rename getColumnNearX to getPosNearX (and change code accordingly).
   It does not make sense to return a position relative to the start of
@@ -30,38 +43,58 @@ What is done:
 
 Next steps:
 
-* check what happens with arabic and/or hebrew text. There may be some
+* check what happens with Arabic and/or Hebrew text. There may be some
   problems related to compose characters. I suspect that some code is
   needed in FontMetrics::width.
 
+* investigate whether RtL strings could be drawn on a string-wise basis.
+
+* investigate whether Row::SEPARATOR elements could be used only in
+  justified text. This would speed-up painting in other cases by
+  lowering the number of strings to draw.
+
+* get lots of testing.
+
 * Get rid of old code in cursorX and getColumnNearX; it has been
   kept for comparison purpose, guarded with KEEP_OLD_METRICS_CODE in
   order to check computations.
 
+* Profile and see how performance can be improved.
+
+
+Steps for later (aka out of the scope of this branch):
+
 * Re-implement row painting using row elements. This is not difficult
   in principle, but the code is intricate and needs some careful
-  analysis. First thing that needs to be done is to break row elements
-  with the same criterions. Currently TextMetrics::breakRow does not
-  consider on-the-fly spellchecking and selection changes, but it is
-  not clear to me that it is required.
+  analysis. The first thing that needs to be done is to break row
+  elements with the same criteria. Currently TextMetrics::breakRow
+  does not consider on-the-fly spell-checking and selection changes,
+  but it is not clear to me that it is required. Moreover, this thing
+  would only work if we are sure that the Row object is up-to-date
+  when drawing happens. This depends on the update machinery.
 
-* Profile and see how performance can be improved.
+  This would allow to get rid of the Bidi code.
 
 
-Difference in behavior (aka bug fixes)
+Known bugs:
+
+* in RtL paragraphs, the end-of-paragraph marker moves the row to the
+  right (ticket #9040, already present in master).
+
+* there are still difference in what breaks words. In particular,
+  RowPainter breaks strings at: selection end, spell-checking
+  extremities. This seems to be harmless.
+
+* when clicking in the right margin, GetColumnNearX does not return
+  the same value as before. I am not sure whether this is important.
+
+
+Other differences in behavior (aka bug fixes):
 
 * end of paragraph markers metrics are computed with the font of the
   actual text, not default font.
 
-* When cursor is after a LTR separator just before a RTL chunk, the
+* When cursor is after a LtR separator just before a RtL

[LyX/master] Remove debug code from TextMetrics

2014-07-25 Thread Jean-Marc Lasgouttes
commit b0543270a9055dcd43df3d72e2a5584895c77ac4
Author: Jean-Marc Lasgouttes <lasgout...@lyx.org>
Date:   Fri May 2 15:55:10 2014 +0200

Remove debug code from TextMetrics

After this, it is possible to remove one parameter to getPosNearX.

diff --git a/src/Cursor.cpp b/src/Cursor.cpp
index 61e4b60..fe03a31 100644
--- a/src/Cursor.cpp
+++ b/src/Cursor.cpp
@@ -2090,7 +2090,7 @@ bool Cursor::upDownInText(bool up, bool & updateNeeded)
 
Row const & real_next_row = 
tm.parMetrics(pit()).rows()[next_row];
bool bound = false;
-   top().pos() = tm.getPosNearX(pit(), real_next_row, xo, bound);
+   top().pos() = tm.getPosNearX(real_next_row, xo, bound);
boundary(bound);
 
updateNeeded |= bv().checkDepm(*this, old);
diff --git a/src/TextMetrics.cpp b/src/TextMetrics.cpp
index 61a0758..12a42e2 100644
--- a/src/TextMetrics.cpp
+++ b/src/TextMetrics.cpp
@@ -15,15 +15,10 @@
  * Full author contact details are available in file CREDITS.
  */
 
-//#define KEEP_OLD_METRICS_CODE 1
-
 #include 
 
 #include "TextMetrics.h"
 
-#ifdef KEEP_OLD_METRICS_CODE
-#include "Bidi.h"
-#endif
 #include "Buffer.h"
 #include "buffer_funcs.h"
 #include "BufferParams.h"
@@ -1104,17 +1099,14 @@ void TextMetrics::setRowHeight(Row & row, pit_type 
const pit,
 // x is an absolute screen coord
 // returns the column near the specified x-coordinate of the row
 // x is set to the real beginning of this column
-pos_type TextMetrics::getPosNearX(pit_type const pit,
-   Row const & row, int & x, bool & boundary) const
+pos_type TextMetrics::getPosNearX(Row const & row, int & x,
+ bool & boundary) const
 {
/// For the main Text, it is possible that this pit is not
/// yet in the CoordCache when moving cursor up.
/// x Paragraph coordinate is always 0 for main text anyway.
int const xo = origin_.x_;
x -= xo;
-#ifdef KEEP_OLD_METRICS_CODE
-   int const x_orig = x;
-#endif
 
pos_type pos = row.pos();
boundary = false;
@@ -1163,138 +1155,6 @@ pos_type TextMetrics::getPosNearX(pit_type const pit,
boundary = row.right_boundary();
 
x += xo;
-#ifdef KEEP_OLD_METRICS_CODE
-   Buffer const & buffer = bv_->buffer();
-
-   int x2 = x_orig;
-   Paragraph const & par = text_->getPar(pit);
-   Bidi bidi;
-   bidi.computeTables(par, buffer, row);
-
-   pos_type vc = row.pos();
-   pos_type const end = row.endpos();
-   pos_type c = 0;
-   Layout const & layout = par.layout();
-
-   bool left_side = false;
-
-   pos_type body_pos = par.beginOfBody();
-
-   double tmpx = row.x;
-   double last_tmpx = tmpx;
-
-   if (body_pos > 0 &&
-   (body_pos > end || !par.isLineSeparator(body_pos - 1)))
-   body_pos = 0;
-
-   // check for empty row
-   if (vc == end) {
-   x2 = int(tmpx) + xo;
-   return 0;
-   }
-
-   // This (rtl_support test) is not needed, but gives
-   // some speedup if rtl_support == false
-   bool const lastrow = lyxrc.rtl_support && row.endpos() == par.size();
-
-   // If lastrow is false, we don't need to compute
-   // the value of rtl.
-   bool const rtl_on_lastrow = lastrow ? text_->isRTL(par) : false;
-
-   while (vc < end && tmpx <= x2) {
-   c = bidi.vis2log(vc);
-   last_tmpx = tmpx;
-   if (body_pos > 0 && c == body_pos - 1) {
-   FontMetrics const & fm = theFontMetrics(
-   text_->labelFont(par));
-   tmpx += row.label_hfill + fm.width(layout.labelsep);
-   if (par.isLineSeparator(body_pos - 1))
-   tmpx -= singleWidth(pit, body_pos - 1);
-   }
-
-   tmpx += singleWidth(pit, c);
-   if (par.isSeparator(c) && c >= body_pos)
-   tmpx += row.separator;
-   ++vc;
-   }
-
-   if ((tmpx + last_tmpx) / 2 > x2) {
-   tmpx = last_tmpx;
-   left_side = true;
-   }
-
-   // This shouldn't happen. But we can reset and try to continue.
-   LASSERT(vc <= end, vc = end);
-
-   bool boundary2 = false;
-
-   if (lastrow &&
-   ((rtl_on_lastrow  &&  left_side && vc == row.pos() && x2 < tmpx - 
5) ||
-(!rtl_on_lastrow && !left_side && vc == end  && x2 > tmpx + 5))) {
-   if (!par.isNewline(end - 1))
-   c = end;
-   } else if (vc == row.pos()) {
-   c = bidi.vis2log(vc);
-   if (bidi.level(c) % 2 == 1)
-  

[LyX/master] Implement a better solution for painting of RTL text

2014-07-25 Thread Jean-Marc Lasgouttes
commit 3013ce3716603e751152e162a5b155cd455c745e
Author: Jean-Marc Lasgouttes <jean-marc.lasgout...@inria.fr>
Date:   Wed Apr 30 16:15:31 2014 +0200

Implement a better solution for painting of RTL text

Instead of relying on character range (Hebrew or Arabic) or character
direction, use RLO unicode character (Right-to-Left override) to force
painting in the direction indicated by the current font. This should
be as close as we can to the old LyX behavior (and requires less
code).

If this code works as intended, it will be possible to remove a lot of
code from Encodings.cpp.

diff --git a/00README_STR_METRICS_BRANCH b/00README_STR_METRICS_BRANCH
index 359bb03..e7a6f29 100644
--- a/00README_STR_METRICS_BRANCH
+++ b/00README_STR_METRICS_BRANCH
@@ -11,8 +11,7 @@ what we have with force_paint_single_char. Moreover there has 
been
 some code factorization in TextMetrics, where the same row-breaking
 algorithm was basically implemented 3 times.
 
-Currently everything is supposed to work for LTR text, and RtL text
-should work too except possibly metrics with Arabic and Hebrew fonts.
+Currently everything is supposed to work for both LTR and RTL text.
 
 When KEEP_OLD_METRICS_CODE is defined in TextMetrics.cpp, the new code
 is tested against the old one in getPosNearX and cursorX. This can be
diff --git a/src/Encoding.cpp b/src/Encoding.cpp
index 7c5dc87..a6f6a60 100644
--- a/src/Encoding.cpp
+++ b/src/Encoding.cpp
@@ -711,12 +711,6 @@ docstring Encodings::fromLaTeXCommand(docstring const & 
cmd, int cmdtype,
 }
 
 
-bool Encodings::isHebrewChar(char_type c)
-{
-   return c >= 0x0590 && c <= 0x05ff;
-}
-
-
 bool Encodings::isHebrewComposeChar(char_type c)
 {
return c <= 0x05c2 && c >= 0x05b0 && c != 0x05be && c != 0x05c0;
diff --git a/src/Encoding.h b/src/Encoding.h
index 63aa93b..ed9c27e 100644
--- a/src/Encoding.h
+++ b/src/Encoding.h
@@ -269,8 +269,6 @@ public:
///
static bool isHebrewComposeChar(char_type c);
///
-   static bool isHebrewChar(char_type c);
-   ///
static bool isArabicComposeChar(char_type c);
///
static bool isArabicSpecialChar(char_type c);
diff --git a/src/rowpainter.cpp b/src/rowpainter.cpp
index ea0f946..b0708bf 100644
--- a/src/rowpainter.cpp
+++ b/src/rowpainter.cpp
@@ -20,7 +20,6 @@
 #include "BufferParams.h"
 #include "BufferView.h"
 #include "Changes.h"
-#include "Encoding.h"
 #include "Language.h"
 #include "Layout.h"
 #include "LyXRC.h"
@@ -201,12 +200,6 @@ void RowPainter::paintChars(pos_type & vpos, Font const & 
font)
bool const spell_state =
lyxrc.spellcheck_continuously && par_.isMisspelled(pos);
 
-   // are we building a RtL string? 
-   //FIXME: I would like to use the new isRTL() from textutils.h,
-   // but it does not give the same results for some reason I do
-   // not understand.
-   bool const rtl = Encodings::isArabicChar(str[0]) || 
Encodings::isHebrewChar(str[0]);
-
// collect as much similar chars as we can
for (++vpos ; vpos < end ; ++vpos) {
if (lyxrc.force_paint_single_char)
@@ -234,14 +227,6 @@ void RowPainter::paintChars(pos_type & vpos, Font const & 
font)
 
char_type c = par_.getChar(pos);
 
-   //FIXME: I would like to use the new isRTL() from textutils.h,
-   // but it does not give the same results for some reason I do
-   // not understand.
-   bool const new_rtl = Encodings::isArabicChar(c) || 
Encodings::isHebrewChar(c);
-   if (new_rtl != rtl)
-   // String direction has changed
-   break;
-
if (c == '\t')
break;
 
@@ -263,20 +248,29 @@ void RowPainter::paintChars(pos_type & vpos, Font const & 
font)
 
docstring s([0], str.size());
 
+   if (s[0] == '\t')
+   s.replace(0,1,from_ascii(""));
+
/* Because we do our own bidi, at this point the strings are
 * already in visual order. However, Qt also applies its own
 * bidi algorithm to strings that it paints to the screen.
 * Therefore, if we were to paint Hebrew/Arabic words as a
 * single string, the letters in the words would get reversed
-* again. In order to avoid that, we reverse the string in advance.
+* again. In order to avoid that, we force LTR drawing.
 * See also http://thread.gmane.org/gmane.editors.lyx.devel/79740
 * for an earlier thread on the subject
 */
-   if (rtl)
+   // Left-to-right override: forces to draw text left-to-right
+   char_type const LRO = 0x202D;
+   // Right-to-left override: forces to draw text right-to-left
+   

[LyX/master] Update description of what has been done in the branch.

2014-07-25 Thread Jean-Marc Lasgouttes
commit 973adaf7d1eb874741ac140c987901367dd9e887
Author: Jean-Marc Lasgouttes <lasgout...@lyx.org>
Date:   Mon May 12 11:02:22 2014 +0200

Update description of what has been done in the branch.

diff --git a/00README_STR_METRICS_BRANCH b/00README_STR_METRICS_BRANCH
index 73f5ed3..0ab1589 100644
--- a/00README_STR_METRICS_BRANCH
+++ b/00README_STR_METRICS_BRANCH
@@ -13,11 +13,8 @@ algorithm was basically implemented 3 times.
 
 Currently everything is supposed to work for both LTR and RTL text.
 
-When KEEP_OLD_METRICS_CODE is defined in TextMetrics.cpp, the new code
-is tested against the old one in getPosNearX and cursorX. This can be
-helpful when looking for discrepancies between the algorithms. Note
-that this only makes sense when force_paint_single_char=true, since
-this enforces char-by-char metrics computation.
+The bugs fixed and caused by this branch are tracked at ticket #9003:
+http://www.lyx.org/trac/ticket/9003
 
 What is done:
 
@@ -51,11 +48,11 @@ What is done:
 
 Next steps:
 
-* get lots of testing.
+* Fix bugs uncovered by testing.
 
-* Get rid of old code in cursorX and getPosNearX; it has been
-  kept for comparison purpose, guarded with KEEP_OLD_METRICS_CODE in
-  order to check computations.
+* Get rid of LyXRC::force_paint_single_char, which is only a workaround.
+
+* Maybe get rid of LyXRC::rtl_support, which does not have a real use case.
 
 * Profile and see how performance can be improved.
 
@@ -71,33 +68,6 @@ Steps for later (aka out of the scope of this branch):
   work if we are sure that the Row object is up-to-date when drawing
   happens. This depends on the update machinery.
 
-  This would allow to get rid of the Bidi code.
-
-
-Known bugs:
-
-* When selecting text, the display seems to move around. This is
-  because partly selected words are drawn in two parts, and in case
-  like "ef|fort" or "V|AN", there are some ligature or kerning effects
-  that change the display. I am not sure yet how to fix that.
-
-* there are other differences in what breaks words. In particular,
-  RowPainter breaks strings at spell-checking extremities. This seems
-  to be harmless.
-
-* when clicking in the right margin, getPosNearX does not return
-  the same value as before. I am not sure whether this is important.
-
-
-Other differences in behavior (aka bug fixes):
-
-* end of paragraph markers metrics are computed with the font of the
-  actual text, not default font.
-
-* in RtL paragraphs, the end-of-paragraph marker does not move the row
-  to the right anymore (ticket #9040).
-
-* When cursor is after a LtR separator just before a RtL chunk, the
-  cursor position is computed better with the new code.
+  This would allow to get rid of the Bidi.cpp code.
 
 


[LyX/master] Fix positionning of cursor

2014-07-25 Thread Jean-Marc Lasgouttes
commit 2ff639a0e6d051c6411fe6655cefc36a4e902211
Author: Jean-Marc Lasgouttes <lasgout...@lyx.org>
Date:   Wed May 14 17:46:43 2014 +0200

Fix positionning of cursor

The old implementation of Row::Element::pos2x and x2pos did not work
correctly with Arabic text, because characters can have shapes that
depend on context.

This new implementation leverages QTextLayout in a simplified way,
since only one word is added to the layout.

This allows to make Row::Element::x2pos more readable.

Fixes: #9115.

diff --git a/src/Row.cpp b/src/Row.cpp
index 48b4fff..a0c0dc4 100644
--- a/src/Row.cpp
+++ b/src/Row.cpp
@@ -36,78 +36,65 @@ using frontend::FontMetrics;
 
 double Row::Element::pos2x(pos_type const i) const
 {
-   LASSERT(i >= pos && i <= endpos, return 0);
+   // This can happen with inline completion when clicking on the
+   // row after the completion.
+   if (i < pos || i > endpos)
+   return 0;
 
bool const rtl = font.isVisibleRightToLeft();
 
int w = 0;
//handle first the two bounds of the element
-   if (i == pos)
-   w = 0;
+   if (i == pos || type != STRING)
+   w = rtl ? width() : 0;
else if (i == endpos)
-   w = width();
+   w = rtl ? 0 : width();
else {
-   LASSERT(type == STRING, return 0);
FontMetrics const & fm = theFontMetrics(font);
-   // FIXME Avoid caching of metrics there?
-   w = fm.width(str.substr(0, i - pos));
+   w = fm.pos2x(str, i - pos, font.isVisibleRightToLeft());
}
 
-   if (rtl)
-   return width() - w;
-   else
-   return w;
+   return w;
 }
 
 
-pos_type Row::Element::x2pos(double , bool const low) const
+pos_type Row::Element::x2pos(double ) const
 {
//lyxerr << "x2pos: x=" << x << " w=" << width() << " " << *this;
-   // If element is rtl, flip x value
bool const rtl = font.isVisibleRightToLeft();
-   double x2 = rtl ? (width() - x) : x;
-
-   double last_w = 0;
-   double w = 0;
size_t i = 0;
+
switch (type) {
-   case VIRTUAL:
-   // those elements are actually empty (but they have a width)
-   break;
case STRING: {
FontMetrics const & fm = theFontMetrics(font);
-   // FIXME: implement dichotomy search?
-   for ( ; i < str.size() ; ++i) {
-   last_w = w;
-   w = fm.width(str.substr(0, i + 1));
-   if (w > x2)
-   break;
-   }
+   // FIXME: is it really necessary for x to be a double?
+   int xx = x;
+   i = fm.x2pos(str, xx, rtl);
+   x = xx;
break;
}
+   case VIRTUAL:
+   // those elements are actually empty (but they have a width)
+   i = 0;
+   x = rtl ? width() : 0;
+   break;
case SEPARATOR:
case INSET:
case SPACE:
-   // those elements contain only one position
-   w = width();
-   }
-
-   if (type == STRING && i == str.size())
-   x2 = w;
-   // round to the closest side. The !rtl is here to obtain the
-   // same rounding as with the old code (this is cosmetic and
-   // can be eventually removed).
-   else if (type != VIRTUAL && !low && (x2 - last_w + !rtl > w - x2)) {
-   x2 = w;
-   ++i;
-   } else
-   x2 = last_w;
-
-   // is element is rtl, flip values back
-   x = rtl ? width() - x2 : x2;
+   // those elements contain only one position. Round to
+   // the closest side.
+   if (x > width()) {
+   x = width();
+   i = !rtl;
+   } else {
+   x = 0;
+   i = rtl;
+   }
 
+   }
//lyxerr << "=> p=" << pos + i << " x=" << x << endl;
return pos + i;
+
 }
 
 
@@ -389,7 +376,8 @@ void Row::shorten_if_needed(pos_type const keep, int const 
w)
// If there is a paragraph marker, it should be taken in account
if (elements_.size() == 2)
xstr -= back().width();
-   pos_type new_pos = front.x2pos(xstr, true);
+   //FIXME: use FontMetrics::x2pos here?? handle rtl?
+   pos_type new_pos = front.x2pos(xstr);
front.str = front.str.substr(0, new_pos - pos_);
front.dim.wid = xstr;
front.endpos = new_pos;
diff --git a/src/Row.h b/src/Row.h
index 7725427.

[LyX/master] Draw right-to-left text string-wise using Qt

2014-07-25 Thread Jean-Marc Lasgouttes
commit ea1a5cb80eaef71bc1cb7021bc3dbf2ef7a793b7
Author: Jean-Marc Lasgouttes <lasgout...@lyx.org>
Date:   Thu Apr 10 16:37:21 2014 +0200

Draw right-to-left text string-wise using Qt

We rely on Qt built-in unicode support for handling Arabic and Hebrew
compose characters. This allows to avoid to use our homegrown
machinery.

This  should provide a nice speedup at a low cost and
will eventually allow us to get rid of:
 * most of our Arabic/Hebrew machinery in Encodings.cpp,
 * Paragraph::transformChar,
 * and probably more.

diff --git a/00README_STR_METRICS_BRANCH b/00README_STR_METRICS_BRANCH
index 82026e8..359bb03 100644
--- a/00README_STR_METRICS_BRANCH
+++ b/00README_STR_METRICS_BRANCH
@@ -11,7 +11,7 @@ what we have with force_paint_single_char. Moreover there has 
been
 some code factorization in TextMetrics, where the same row-breaking
 algorithm was basically implemented 3 times.
 
-Currently everything is supposed to work for LTR text, and RTL text
+Currently everything is supposed to work for LTR text, and RtL text
 should work too except possibly metrics with Arabic and Hebrew fonts.
 
 When KEEP_OLD_METRICS_CODE is defined in TextMetrics.cpp, the new code
@@ -40,12 +40,13 @@ What is done:
   lyxrc.force_paint_single_char is false. In this case, remove also
   useless workarounds which disable kerning and ligatures.
 
+* when lyxrc.force_paint_single_char is false, draw also RtL text
+  string-wise. This both speed-up drawing and prepare for code
+  removal, since we now rely on Qt to do things we use to do by
+  ourselves (see isArabic* and isHebrew* code in Encodings.cpp).
 
-Next steps:
 
-* check what happens with Arabic and/or Hebrew text. There may be some
-  problems related to compose characters. Investigate whether RtL
-  strings could be drawn on a string-wise basis.
+Next steps:
 
 * investigate whether strings could be cut at separators in RowPainter
   only in justified text. This would speed-up painting in other cases
@@ -76,18 +77,18 @@ Steps for later (aka out of the scope of this branch):
 
 Known bugs:
 
-* there are still difference in what breaks words. In particular,
-  RowPainter breaks strings at: selection end, spell-checking
-  extremities. This seems to be harmless.
-
-* when clicking in the right margin, getPosNearX does not return
-  the same value as before. I am not sure whether this is important.
-
 * When selecting text, the display seems to move around. This is
   because partly selected words are drawn in two parts, and in case
   like "ef|fort" or "V|AN", there are some ligature or kerning effects
   that change the display. I am not sure yet how to fix that.
 
+* there are other differences in what breaks words. In particular,
+  RowPainter breaks strings at spell-checking extremities. This seems
+  to be harmless.
+
+* when clicking in the right margin, getPosNearX does not return
+  the same value as before. I am not sure whether this is important.
+
 
 Other differences in behavior (aka bug fixes):
 
diff --git a/src/Encoding.cpp b/src/Encoding.cpp
index a6f6a60..7c5dc87 100644
--- a/src/Encoding.cpp
+++ b/src/Encoding.cpp
@@ -711,6 +711,12 @@ docstring Encodings::fromLaTeXCommand(docstring const & 
cmd, int cmdtype,
 }
 
 
+bool Encodings::isHebrewChar(char_type c)
+{
+   return c >= 0x0590 && c <= 0x05ff;
+}
+
+
 bool Encodings::isHebrewComposeChar(char_type c)
 {
return c <= 0x05c2 && c >= 0x05b0 && c != 0x05be && c != 0x05c0;
diff --git a/src/Encoding.h b/src/Encoding.h
index ed9c27e..63aa93b 100644
--- a/src/Encoding.h
+++ b/src/Encoding.h
@@ -269,6 +269,8 @@ public:
///
static bool isHebrewComposeChar(char_type c);
///
+   static bool isHebrewChar(char_type c);
+   ///
static bool isArabicComposeChar(char_type c);
///
static bool isArabicSpecialChar(char_type c);
diff --git a/src/rowpainter.cpp b/src/rowpainter.cpp
index 5b69701..ea0f946 100644
--- a/src/rowpainter.cpp
+++ b/src/rowpainter.cpp
@@ -161,72 +161,7 @@ void RowPainter::paintInset(Inset const * inset, pos_type 
const pos)
 }
 
 
-void RowPainter::paintHebrewComposeChar(pos_type & vpos, FontInfo const & font)
-{
-   pos_type pos = bidi_.vis2log(vpos);
-
-   docstring str;
-
-   // first char
-   char_type c = par_.getChar(pos);
-   str += c;
-   ++vpos;
-
-   int const width = theFontMetrics(font).width(c);
-   int dx = 0;
-
-   for (pos_type i = pos - 1; i >= 0; --i) {
-   c = par_.getChar(i);
-   if (!Encodings::isHebrewComposeChar(c)) {
-   if (isPrintableNonspace(c)) {
-   int const width2 = pm_.singleWidth(i,
-   text_metrics_.displayFont(pit_, i));
-   dx = (c == 0x05e8 || // resh
-

[LyX/master] Fix various selection-related problems

2014-07-25 Thread Jean-Marc Lasgouttes
commit b8170e0e01f486fefb94b19566e24dd391419c12
Author: Jean-Marc Lasgouttes <lasgout...@lyx.org>
Date:   Fri Mar 21 11:56:42 2014 +0100

Fix various selection-related problems

All these problems are related to what happens at the extreme points of rows

 * since VIRTUAL elements have a width but no contents, they have to
   be treated specially at some places. It would have been better to
   avoid testing for them explicitly, but I did not find a way.

 * Improve and cleanup the code in breakRow and fix in passing a crash
   when clicking on the right of an incomplete MARGIN_MANUAL
   paragraph.

 * improve the computation of row width in TextMetrics::computeRowMetrics.

 * handle properly the case where a position if not found on the row
   in both cursorX and getPosNearX (actually, this happens when
   selecting).

 * Some code cleanup and comments.

diff --git a/00README_STR_METRICS_BRANCH b/00README_STR_METRICS_BRANCH
index 1bb7026..82026e8 100644
--- a/00README_STR_METRICS_BRANCH
+++ b/00README_STR_METRICS_BRANCH
@@ -44,18 +44,16 @@ What is done:
 Next steps:
 
 * check what happens with Arabic and/or Hebrew text. There may be some
-  problems related to compose characters. I suspect that some code is
-  needed in FontMetrics::width.
+  problems related to compose characters. Investigate whether RtL
+  strings could be drawn on a string-wise basis.
 
-* investigate whether RtL strings could be drawn on a string-wise basis.
-
-* investigate whether Row::SEPARATOR elements could be used only in
-  justified text. This would speed-up painting in other cases by
-  lowering the number of strings to draw.
+* investigate whether strings could be cut at separators in RowPainter
+  only in justified text. This would speed-up painting in other cases
+  by lowering the number of strings to draw.
 
 * get lots of testing.
 
-* Get rid of old code in cursorX and getColumnNearX; it has been
+* Get rid of old code in cursorX and getPosNearX; it has been
   kept for comparison purpose, guarded with KEEP_OLD_METRICS_CODE in
   order to check computations.
 
@@ -67,33 +65,38 @@ Steps for later (aka out of the scope of this branch):
 * Re-implement row painting using row elements. This is not difficult
   in principle, but the code is intricate and needs some careful
   analysis. The first thing that needs to be done is to break row
-  elements with the same criteria. Currently TextMetrics::breakRow
-  does not consider on-the-fly spell-checking and selection changes,
-  but it is not clear to me that it is required. Moreover, this thing
-  would only work if we are sure that the Row object is up-to-date
-  when drawing happens. This depends on the update machinery.
+  elements with the same criteria. Currently breakRow does not
+  consider on-the-fly spell-checking and selection changes, but it is
+  not clear to me that it is required. Moreover, this thing would only
+  work if we are sure that the Row object is up-to-date when drawing
+  happens. This depends on the update machinery.
 
   This would allow to get rid of the Bidi code.
 
 
 Known bugs:
 
-* in RtL paragraphs, the end-of-paragraph marker moves the row to the
-  right (ticket #9040, already present in master).
-
 * there are still difference in what breaks words. In particular,
   RowPainter breaks strings at: selection end, spell-checking
   extremities. This seems to be harmless.
 
-* when clicking in the right margin, GetColumnNearX does not return
+* when clicking in the right margin, getPosNearX does not return
   the same value as before. I am not sure whether this is important.
 
+* When selecting text, the display seems to move around. This is
+  because partly selected words are drawn in two parts, and in case
+  like "ef|fort" or "V|AN", there are some ligature or kerning effects
+  that change the display. I am not sure yet how to fix that.
+
 
 Other differences in behavior (aka bug fixes):
 
 * end of paragraph markers metrics are computed with the font of the
   actual text, not default font.
 
+* in RtL paragraphs, the end-of-paragraph marker does not move the row
+  to the right anymore (ticket #9040).
+
 * When cursor is after a LtR separator just before a RtL chunk, the
   cursor position is computed better with the new code.
 
diff --git a/src/Row.cpp b/src/Row.cpp
index 6e60e97..48b4fff 100644
--- a/src/Row.cpp
+++ b/src/Row.cpp
@@ -63,18 +63,19 @@ double Row::Element::pos2x(pos_type const i) const
 pos_type Row::Element::x2pos(double , bool const low) const
 {
//lyxerr << "x2pos: x=" << x << " w=" << width() << " " << *this;
-   // if element is rtl, flip x value
+   // If element is rtl, flip x value
bool const rtl = font.isVisibleRightToLeft();
double x2 = rtl ? (width() - x) : x;
 
-   FontMetrics const & fm = theFontMetr

[LyX/master] Do not split words at selection boundary

2014-07-25 Thread Jean-Marc Lasgouttes
commit ec42b2e4c9daa458df1c5c0454d61fbe4987701c
Author: Jean-Marc Lasgouttes <lasgout...@lyx.org>
Date:   Fri May 23 18:59:53 2014 +0200

Do not split words at selection boundary

The display of partially-selected word is now done in a new Painter::text 
method
which displays the string twice with different clip settings. This allows to
catter for the case where Color_selectiontext is not black.

Morover, the code that uses unicode override characters to force the
direction of a string is moved to lstrings.h.

Fixes: #9116

diff --git a/00README_STR_METRICS_BRANCH b/00README_STR_METRICS_BRANCH
index 568ac8f..2dc3cad 100644
--- a/00README_STR_METRICS_BRANCH
+++ b/00README_STR_METRICS_BRANCH
@@ -47,6 +47,10 @@ What is done:
   justified. This speeds-up painting by reducing the number of strings
   to draw.
 
+* Do not cut strings at selection boundary in RowPainter. This avoids
+  ligature/kerning breaking in latin text, and bad rendering problems
+  in Arabic.
+
 
 Next steps:
 
@@ -72,5 +76,3 @@ Steps for later (aka out of the scope of this branch):
   happens. This depends on the update machinery.
 
   This would allow to get rid of the Bidi.cpp code.
-
-
diff --git a/src/frontends/Painter.h b/src/frontends/Painter.h
index 7267839..3302d16 100644
--- a/src/frontends/Painter.h
+++ b/src/frontends/Painter.h
@@ -14,9 +14,11 @@
 #define PAINTER_H
 
 #include "support/strfwd.h"
+#include "support/types.h"
 
 namespace lyx {
 
+class Font;
 class FontInfo;
 
 namespace graphics { class Image; }
@@ -106,12 +108,26 @@ public:
virtual void image(int x, int y, int w, int h,
graphics::Image const & image) = 0;
 
-   /// draw a string at position x, y (y is the baseline)
-   /**
-   * \return the width of the drawn text.
-   */
+   /** draw a string at position x, y (y is the baseline). The
+* text direction is deduced from \c str.
+* \return the width of the drawn text.
+*/
virtual int text(int x, int y, docstring const & str, FontInfo const & 
f) = 0;
 
+   /** draw a string at position x, y (y is the baseline). The
+* text direction is enforced by the \c Font.
+* \return the width of the drawn text.
+*/
+   virtual int text(int x, int y, docstring const & str, Font const & f) = 
0;
+
+   /** draw a string at position x, y (y is the baseline), but
+* make sure that the part between \c from and \c to is in
+* \c other color. The text direction is enforced by the \c Font.
+* \return the width of the drawn text.
+*/
+   virtual int text(int x, int y, docstring const & str, Font const & f,
+Color other, size_type from, size_type to) = 0;
+
void setDrawingEnabled(bool drawing_enabled)
{ drawing_enabled_ = drawing_enabled; }
 
diff --git a/src/frontends/qt4/GuiFontMetrics.cpp 
b/src/frontends/qt4/GuiFontMetrics.cpp
index 2ac588c..492a0a9 100644
--- a/src/frontends/qt4/GuiFontMetrics.cpp
+++ b/src/frontends/qt4/GuiFontMetrics.cpp
@@ -22,10 +22,12 @@
 #include "insets/Inset.h"
 
 #include "support/lassert.h"
+#include "support/lstrings.h"
 
 #include 
 
 using namespace std;
+using namespace lyx::support;
 
 namespace lyx {
 namespace frontend {
@@ -42,7 +44,7 @@ namespace {
  * why this works well for symbol fonts used in mathed too, even though
  * these are not real ucs4 characters. These are codepoints in the
  * computer modern fonts used, nothing unicode related.
- * See comment in QLPainter::text() for more explanation.
+ * See comment in GuiPainter::text() for more explanation.
  **/
 inline QChar const ucs4_to_qchar(char_type const ucs4)
 {
@@ -146,22 +148,7 @@ namespace {
 void setTextLayout(QTextLayout & tl, docstring const & s, QFont const & font,
 bool const rtl)
 {
-   QString qs;
-   /* In LyX, the character direction is forced by the language.
-* Therefore, we have to signal that fact to Qt.
-* Source: http://www.iamcal.com/understanding-bidirectional-text/
-*/
-   // Left-to-right override: forces to draw text left-to-right
-   char_type const LRO = 0x202D;
-   // Right-to-left override: forces to draw text right-to-left
-   char_type const RLO = 0x202E;
-   // Pop directional formatting: return to previous state
-   char_type const PDF = 0x202C;
-   if (rtl)
-   qs = toqstr(RLO + s + PDF);
-   else
-   qs = toqstr(LRO + s + PDF);
-
+   QString const qs = toqstr(directedString(s, rtl));
tl.setText(qs);
tl.setFont(font);
tl.beginLayout();
@@ -175,6 +162,7 @@ int GuiFontMetrics::pos2x(docstring const & s, int const 
pos, bool const rtl) co
 {
QTextLayout tl;
setTextLayout(tl, s, font_, rtl);
+   // we take into accoun

[LyX/master] Move some text from the readme file to relevant source files

2014-07-25 Thread Jean-Marc Lasgouttes
commit 4bd5a7e883b76f36d1ebc3ae1c9a6765da5165f6
Author: Jean-Marc Lasgouttes <lasgout...@lyx.org>
Date:   Mon Jun 30 15:55:30 2014 +0200

Move some text from the readme file to relevant source files

diff --git a/00README_STR_METRICS_BRANCH b/00README_STR_METRICS_BRANCH
index 6668623..1292390 100644
--- a/00README_STR_METRICS_BRANCH
+++ b/00README_STR_METRICS_BRANCH
@@ -11,8 +11,6 @@ what we have with force_paint_single_char. Moreover there has 
been
 some code factorization in TextMetrics, where the same row-breaking
 algorithm was basically implemented 3 times.
 
-Currently everything is supposed to work for both LTR and RTL text.
-
 The bugs fixed and caused by this branch are tracked at ticket #9003:
 http://www.lyx.org/trac/ticket/9003
 
@@ -59,26 +57,3 @@ Next steps:
   in the source.
 
 * Maybe get rid of LyXRC::rtl_support, which does not have a real use case.
-
-* Fix bugs uncovered by testing.
-
-* Profile and see how performance can be improved.
-
-
-Steps for later (aka out of the scope of this branch):
-
-* Re-implement row painting using row elements. This is not difficult
-  in principle, but the code is intricate and needs some careful
-  analysis. The first thing that needs to be done is to break row
-  elements with the same criteria. Currently breakRow does not
-  consider on-the-fly spell-checking, but it is not clear to me that
-  it is required. Moreover, this thing would only work if we are sure
-  that the Row object is up-to-date when drawing happens. This depends
-  on the update machinery.
-
-  This would allow to get rid of the Bidi.cpp code.
-
-* Change Row object to operate only on integers and not doubles. Then,
-  rewrite the computation of spacing in justified paragraphs so that
-  strings can be drawn without cutting at separators. This will improve
-  performance.
diff --git a/src/Row.h b/src/Row.h
index a1e707e..04890f7 100644
--- a/src/Row.h
+++ b/src/Row.h
@@ -30,6 +30,18 @@ class DocIterator;
 class Inset;
 
 /**
+ * FIXME: Change Row object to operate only on integers and not doubles.
+ *
+ * This use of double is only useful to distribute the extra
+ * horizontal space between separators in justified text. If we do
+ * integer arithmetic, then it is possible to have two groups of
+ * separators, with size s or s+1. Then strings can be drawn without
+ * cutting at separators in justfied text, as it is done in
+ * non-justified text. This will improve performance.
+ */
+
+
+/**
  * An on-screen row of text. A paragraph is broken into a RowList for
  * display. Each Row contains a tokenized description of the contents
  * of the line.
diff --git a/src/rowpainter.h b/src/rowpainter.h
index ae1a590..7e29c0e 100644
--- a/src/rowpainter.h
+++ b/src/rowpainter.h
@@ -37,6 +37,21 @@ class TextMetrics;
 namespace frontend { class Painter; }
 
 /**
+ * FIXME: Re-implement row painting using row elements.
+ *
+ * This is not difficult in principle, but the code is intricate and
+ * needs some careful analysis. The first thing that needs to be done
+ * is to break row elements with the same criteria. Currently breakRow
+ * does not consider on-the-fly spell-checking, but it is not clear to
+ * me that it is required. Moreover, this thing would only work if we
+ * are sure that the Row object is up-to-date when drawing happens.
+ * This depends on the update machinery.
+ *
+ * This would allow to get rid of the Bidi class.
+ */
+
+
+/**
  * A class used for painting an individual row of text.
  * FIXME: get rid of that class.
  */


[LyX/master] Get rid of rtl_support preference

2014-07-25 Thread Jean-Marc Lasgouttes
commit 45eb314a863a7bc76c2880f2352b7b430eeaf1c0
Author: Jean-Marc Lasgouttes <lasgout...@lyx.org>
Date:   Wed Jul 9 20:12:06 2014 +0200

Get rid of rtl_support preference

This variable was introduced to guard against any bad consequence of the 
then-new right-to-left
languages support. Let's be bold and get rid of it altogether!

Now right to left support is always enabled.

diff --git a/00README_STR_METRICS_BRANCH b/00README_STR_METRICS_BRANCH
index 7095f9f..e901b51 100644
--- a/00README_STR_METRICS_BRANCH
+++ b/00README_STR_METRICS_BRANCH
@@ -50,7 +50,4 @@ What is done:
 * Remove homebrew Arabic and Hebrew support from Encoding.cpp. We now
   rely on Qt to do handle complex scripts.
 
-
-Next steps:
-
-* Maybe get rid of LyXRC::rtl_support, which does not have a real use case.
+* Get rid of LyXRC::rtl_support, which does not have a real use case.
diff --git a/lib/configure.py b/lib/configure.py
index f0b7166..ac8df63 100644
--- a/lib/configure.py
+++ b/lib/configure.py
@@ -1479,7 +1479,7 @@ if __name__ == '__main__':
 lyx_check_config = True
 lyx_kpsewhich = True
 outfile = 'lyxrc.defaults'
-lyxrc_fileformat = 16
+lyxrc_fileformat = 17
 rc_entries = ''
 lyx_keep_temps = False
 version_suffix = ''
diff --git a/lib/scripts/prefs2prefs_prefs.py b/lib/scripts/prefs2prefs_prefs.py
index 4770fbf..9776cfe 100644
--- a/lib/scripts/prefs2prefs_prefs.py
+++ b/lib/scripts/prefs2prefs_prefs.py
@@ -70,6 +70,9 @@
 # Incremented to format 16, by lasgouttes
 #  Remove force_paint_single_char rc.
 
+# Incremented to format 17, by lasgouttes
+#  Remove rtl_support rc.
+
 # NOTE: The format should also be updated in LYXRC.cpp and
 # in configure.py.
 
@@ -321,6 +324,11 @@ def remove_force_paint_single_char(line):
return no_match
return (True, "")
 
+def remove_rtl(line):
+   if not line.lower().startswith("\\rtl "):
+   return no_match
+   return (True, "")
+
 # End conversions for LyX 2.1 to 2.2
 
 
@@ -346,5 +354,6 @@ conversions = [
[ 13, [mac_cursor_movement]],
[ 14, []],
[ 15, []],
-   [ 16, [remove_force_paint_single_char]]
+   [ 16, [remove_force_paint_single_char]],
+   [ 17, [remove_rtl]]
 ]
diff --git a/src/Bidi.cpp b/src/Bidi.cpp
index d5a631e..3b598a4 100644
--- a/src/Bidi.cpp
+++ b/src/Bidi.cpp
@@ -57,10 +57,6 @@ void Bidi::computeTables(Paragraph const & par,
Buffer const & buf, Row const & row)
 {
same_direction_ = true;
-   if (!lyxrc.rtl_support) {
-   start_ = -1;
-   return;
-   }
 
if (par.inInset().forceLTR()) {
start_ = -1;
@@ -192,7 +188,7 @@ void Bidi::computeTables(Paragraph const & par,
 bool Bidi::isBoundary(Buffer const & buf, Paragraph const & par,
pos_type pos) const
 {
-   if (!lyxrc.rtl_support || pos == 0)
+   if (pos == 0)
return false;
 
if (!inRange(pos - 1)) {
@@ -212,9 +208,6 @@ bool Bidi::isBoundary(Buffer const & buf, Paragraph const & 
par,
 bool Bidi::isBoundary(Buffer const & buf, Paragraph const & par,
pos_type pos, Font const & font) const
 {
-   if (!lyxrc.rtl_support)
-   return false;// This is just for speedup
-
bool const rtl = font.isVisibleRightToLeft();
bool const rtl2 = inRange(pos)
? level(pos) % 2
diff --git a/src/BufferView.cpp b/src/BufferView.cpp
index 301fd2a..bc8162b 100644
--- a/src/BufferView.cpp
+++ b/src/BufferView.cpp
@@ -803,14 +803,12 @@ bool BufferView::moveToPosition(pit_type bottom_pit, 
pos_type bottom_pos,
 
 void BufferView::translateAndInsert(char_type c, Text * t, Cursor & cur)
 {
-   if (lyxrc.rtl_support) {
-   if (d->cursor_.real_current_font.isRightToLeft()) {
-   if (d->intl_.keymap == Intl::PRIMARY)
-   d->intl_.keyMapSec();
-   } else {
-   if (d->intl_.keymap == Intl::SECONDARY)
-   d->intl_.keyMapPrim();
-   }
+   if (d->cursor_.real_current_font.isRightToLeft()) {
+   if (d->intl_.keymap == Intl::PRIMARY)
+   d->intl_.keyMapSec();
+   } else {
+   if (d->intl_.keymap == Intl::SECONDARY)
+   d->intl_.keyMapPrim();
}
 
d->intl_.getTransManager().translateAndInsert(c, t, cur);
diff --git a/src/LyXRC.cpp b/src/LyXRC.cpp
index 46309ee..5e1efcf 100644
--- a/src/LyXRC.cpp
+++ b/src/LyXRC.cpp
@@ -58,7 +58,7 @@ namespace {
 
 // The format should also be updated in configure.py, and conversion code
 // should be added to prefs2prefs_prefs.py.
-static unsigned int const LYXRC_FILEFORMAT = 16; // lasgouttes: remove 
\\force_paint_single_char
+static unsigned int const LYXRC

[LyX/master] Remove obsolete code to handle Hebrew and Arabic characters

2014-07-25 Thread Jean-Marc Lasgouttes
commit d6337a248847aa4c72f8a813d92d349d1035c79f
Author: Jean-Marc Lasgouttes <lasgout...@lyx.org>
Date:   Fri Jun 13 16:33:58 2014 +0200

Remove obsolete code to handle Hebrew and Arabic characters

This is handled by Qt now.

Note that a small optimization (do not draw text that is to the left
of WorkArea) is removed because it cannot be guaranteed to be exact
anymore. It was probably not very useful anyway, and would become
useless once the RowPainter is rewritten to use Row information.

Update 00README_STR_METRICS_BRANCH.

diff --git a/00README_STR_METRICS_BRANCH b/00README_STR_METRICS_BRANCH
index 2dc3cad..6668623 100644
--- a/00README_STR_METRICS_BRANCH
+++ b/00README_STR_METRICS_BRANCH
@@ -16,6 +16,7 @@ Currently everything is supposed to work for both LTR and RTL 
text.
 The bugs fixed and caused by this branch are tracked at ticket #9003:
 http://www.lyx.org/trac/ticket/9003
 
+
 What is done:
 
 * Make TextMetrics methods operate on Row objects: breakRow and
@@ -38,10 +39,7 @@ What is done:
 * Implement proper string metrics computation (with cache). Remove
   useless workarounds which disable kerning and ligatures.
 
-* Draw also RtL text string-wise. This both speeds-up drawing and
-  prepares for code removal, since we now rely on Qt to do things we
-  use to do by ourselves (see isArabic* and isHebrew* code in
-  Encodings.cpp).
+* Draw also RtL text string-wise. This speeds-up drawing.
 
 * Do not cut strings at separators in RowPainter when text is not
   justified. This speeds-up painting by reducing the number of strings
@@ -51,16 +49,19 @@ What is done:
   ligature/kerning breaking in latin text, and bad rendering problems
   in Arabic.
 
+* Remove homebrew Arabic and Hebrew support from Encoding.cpp. We now
+  rely on Qt to do handle complex scripts.
 
-Next steps:
 
-* Fix bugs uncovered by testing.
+Next steps:
 
 * Get rid of LyXRC::force_paint_single_char, which is not used anymore
   in the source.
 
 * Maybe get rid of LyXRC::rtl_support, which does not have a real use case.
 
+* Fix bugs uncovered by testing.
+
 * Profile and see how performance can be improved.
 
 
@@ -70,9 +71,14 @@ Steps for later (aka out of the scope of this branch):
   in principle, but the code is intricate and needs some careful
   analysis. The first thing that needs to be done is to break row
   elements with the same criteria. Currently breakRow does not
-  consider on-the-fly spell-checking and selection changes, but it is
-  not clear to me that it is required. Moreover, this thing would only
-  work if we are sure that the Row object is up-to-date when drawing
-  happens. This depends on the update machinery.
+  consider on-the-fly spell-checking, but it is not clear to me that
+  it is required. Moreover, this thing would only work if we are sure
+  that the Row object is up-to-date when drawing happens. This depends
+  on the update machinery.
 
   This would allow to get rid of the Bidi.cpp code.
+
+* Change Row object to operate only on integers and not doubles. Then,
+  rewrite the computation of spacing in justified paragraphs so that
+  strings can be drawn without cutting at separators. This will improve
+  performance.
diff --git a/src/Encoding.cpp b/src/Encoding.cpp
index a6f6a60..e4bbbc0 100644
--- a/src/Encoding.cpp
+++ b/src/Encoding.cpp
@@ -42,190 +42,6 @@ Encodings::MathSymbolSet  Encodings::mathsym;
 
 namespace {
 
-char_type arabic_table[172][4] = {
-   {0xfe80, 0xfe80, 0xfe80, 0xfe80}, // 0x0621 = hamza
-   {0xfe81, 0xfe82, 0xfe81, 0xfe82}, // 0x0622 = ligature madda on alef
-   {0xfe83, 0xfe84, 0xfe83, 0xfe84}, // 0x0623 = ligature hamza on alef
-   {0xfe85, 0xfe86, 0xfe85, 0xfe86}, // 0x0624 = ligature hamza on waw
-   {0xfe87, 0xfe88, 0xfe87, 0xfe88}, // 0x0625 = ligature hamza under alef
-   {0xfe89, 0xfe8a, 0xfe8b, 0xfe8c}, // 0x0626 = ligature hamza on ya
-   {0xfe8d, 0xfe8e, 0xfe8d, 0xfe8e}, // 0x0627 = alef
-   {0xfe8f, 0xfe90, 0xfe91, 0xfe92}, // 0x0628 = baa
-   {0xfe93, 0xfe94, 0xfe93, 0xfe94}, // 0x0629 = taa marbuta
-   {0xfe95, 0xfe96, 0xfe97, 0xfe98}, // 0x062a = taa
-   {0xfe99, 0xfe9a, 0xfe9b, 0xfe9c}, // 0x062b = thaa
-   {0xfe9d, 0xfe9e, 0xfe9f, 0xfea0}, // 0x062c = jeem
-   {0xfea1, 0xfea2, 0xfea3, 0xfea4}, // 0x062d = haa
-   {0xfea5, 0xfea6, 0xfea7, 0xfea8}, // 0x062e = khaa
-   {0xfea9, 0xfeaa, 0xfea9, 0xfeaa}, // 0x062f = dal
-
-   {0xfeab, 0xfeac, 0xfeab, 0xfeac}, // 0x0630 = thal
-   {0xfead, 0xfeae, 0xfead, 0xfeae}, // 0x0631 = ra
-   {0xfeaf, 0xfeb0, 0xfeaf, 0xfeb0}, // 0x0632 = zain
-   {0xfeb1, 0xfeb2, 0xfeb3, 0xfeb4}, // 0x0633 = seen
-   {0xfeb5, 0xfeb6, 0xfeb7, 0xfeb8}, // 0x0634 = sheen
-   {0xfeb9, 0xfeba, 0xfebb, 0xfebc}, // 0x0635 = sad
-   {0xfebd, 0xfebe, 0xfebf, 0xfec0}, // 0x0636 = dad
-   {0xfec1, 0xfec2, 0xfec3, 0xfec4}, // 0x0637 = tah
-   {0xfec5, 0xfec6, 0xfec7, 0xfec8}, // 0x0638

[LyX/master] Fix bug #9040: In RtL documents end-of-paragraph marker shifts the row display

2014-07-25 Thread Jean-Marc Lasgouttes
commit 7167d90b505f9b98db3de00d081023afed473913
Author: Jean-Marc Lasgouttes <lasgout...@lyx.org>
Date:   Thu Mar 20 11:00:14 2014 +0100

Fix bug #9040: In RtL documents end-of-paragraph marker shifts the row 
display

The fact that the bug was still present in the features/str-metrics
branch comes from a goof in the initial implementation of 'virtual'
row elements (completion and end-of-par markers). Now that this is
corrected, everything works as it should.

The fact that the bug is present in master is due to some other reason
that is not useful to investigate now.

diff --git a/src/Row.cpp b/src/Row.cpp
index 15af2c2..6e60e97 100644
--- a/src/Row.cpp
+++ b/src/Row.cpp
@@ -282,7 +282,6 @@ void Row::add(pos_type const pos, char_type const c,
Element e(STRING, pos, f, ch);
elements_.push_back(e);
}
-   //lyxerr << "FONT " <<back().font.language() << endl;
back().str += c;
back().endpos = pos + 1;
 }
@@ -294,7 +293,8 @@ void Row::addVirtual(pos_type const pos, docstring const & 
s,
finalizeLast();
Element e(VIRTUAL, pos, f, ch);
e.str = s;
-   // A completion has no size
+   e.dim.wid = theFontMetrics(f).width(s);
+   dim_.wid += e.dim.wid;
e.endpos = pos;
elements_.push_back(e);
finalizeLast();


[LyX/master] Fix breaking of loooong word in RTL languages

2014-07-25 Thread Jean-Marc Lasgouttes
commit e1c4cb7146e0dfd25bb705178618da251bdfde8c
Author: Jean-Marc Lasgouttes <lasgout...@lyx.org>
Date:   Mon May 19 11:35:15 2014 +0200

Fix breaking of lng word in RTL languages

Moreover, breaks row at insets when there is no suitable separator.

Also make the code of Row::shorten_if_needed somewhat simpler by using
iterators and factoring the code.

Fixes: #9120

diff --git a/src/Row.cpp b/src/Row.cpp
index a0c0dc4..1336d05 100644
--- a/src/Row.cpp
+++ b/src/Row.cpp
@@ -28,6 +28,8 @@
 #include 
 #include 
 
+#include 
+
 using namespace std;
 
 namespace lyx {
@@ -98,6 +100,27 @@ pos_type Row::Element::x2pos(double ) const
 }
 
 
+bool Row::Element::breakAt(double w)
+{
+   if (type != STRING || width() <= w)
+   return false;
+
+   bool const rtl = font.isVisibleRightToLeft();
+   if (rtl)
+   w = width() - w;
+   pos_type new_pos = x2pos(w);
+   if (new_pos == pos)
+   return false;
+   str = str.substr(0, new_pos - pos);
+   if (rtl)
+   dim.wid -= w;
+   else
+   dim.wid = w;
+   endpos = new_pos;
+   return true;
+}
+
+
 pos_type Row::Element::left_pos() const
 {
return font.isVisibleRightToLeft() ? endpos : pos;
@@ -110,7 +133,6 @@ pos_type Row::Element::right_pos() const
 }
 
 
-
 Row::Row()
: separator(0), label_hfill(0), x(0), right_margin(0),
  sel_beg(-1), sel_end(-1),
@@ -334,63 +356,63 @@ void Row::pop_back()
 }
 
 
-void Row::shorten_if_needed(pos_type const keep, int const w)
+void Row::shortenIfNeeded(pos_type const keep, int const w)
 {
-   if (empty() || width() < w)
+   if (empty() || width() <= w)
return;
 
/** First, we try to remove elements one by one from the end
-* until a separator is found.
+* until a separator is found. cit points to the first element
+* we want to remove from the row.
 */
-   int i = elements_.size();
+   Elements::iterator const beg = elements_.begin();
+   Elements::iterator const end = elements_.end();
+   Elements::iterator cit = end;
+   Elements::iterator first_below = end;
int new_end = end_;
int new_wid = dim_.wid;
-   if (i > 0 && elements_[i - 1].type == SEPARATOR && new_end > keep) {
-   --i;
-   new_end = elements_[i].pos;
-   new_wid -= elements_[i].dim.wid;
+   // if the row ends with a separator, skip it.
+   if (cit != beg && boost::prior(cit)->type == SEPARATOR && new_end > 
keep) {
+   --cit;
+   new_end = cit->pos;
+   new_wid -= cit->dim.wid;
}
 
-   while (i > 0 && elements_[i - 1].type != SEPARATOR && new_end > keep) {
-   --i;
-   new_end = elements_[i].pos;
-   new_wid -= elements_[i].dim.wid;
+   // Search for a separator where the row can be broken.
+   while (cit != beg && boost::prior(cit)->type != SEPARATOR && new_end > 
keep) {
+   --cit;
+   new_end = cit->pos;
+   new_wid -= cit->dim.wid;
+   if (new_wid < w && first_below == end)
+   first_below = cit;
}
-   if (i == 0) {
-   /* If we are here, it means that we have not found a
-* separator to shorten the row. There is one case
-* where we can do something: when we have one big
-* string, maybe with a paragraph marker after it.
-*/
-   Element & front = elements_.front();
-   if (!(front.type == STRING
- && (elements_.size() == 1
- || (elements_.size() == 2
- && back().type == VIRTUAL
-   return;
-
-   // If this is a string element, we can try to split it.
-   if (front.type != STRING)
-   return;
-   double xstr = w - x;
-   // If there is a paragraph marker, it should be taken in account
-   if (elements_.size() == 2)
-   xstr -= back().width();
-   //FIXME: use FontMetrics::x2pos here?? handle rtl?
-   pos_type new_pos = front.x2pos(xstr);
-   front.str = front.str.substr(0, new_pos - pos_);
-   front.dim.wid = xstr;
-   front.endpos = new_pos;
-   end_ = new_pos;
-   dim_.wid = x + xstr;
-   // If there is a paragraph marker, it should be removed.
-   if (elements_.size() == 2)
-   elements_.pop_back();
+
+   if (cit != beg) {
+   // We have found a suitable separator. This is the
+   // common case.
+  

[LyX/master] Remove LyXRC option force_paint_single_char

2014-07-25 Thread Jean-Marc Lasgouttes
commit 9d5c9471104cedc4600daab101ef1958f48dab76
Author: Jean-Marc Lasgouttes <lasgout...@lyx.org>
Date:   Tue Jul 8 23:12:09 2014 +0200

Remove LyXRC option force_paint_single_char

It was not honored anymore.

diff --git a/00README_STR_METRICS_BRANCH b/00README_STR_METRICS_BRANCH
index 1292390..7095f9f 100644
--- a/00README_STR_METRICS_BRANCH
+++ b/00README_STR_METRICS_BRANCH
@@ -31,8 +31,8 @@ What is done:
 
 * Re-implement cursorX and getPosNearX using row elements.
 
-* Do not honor lyxrc.force_paint_single_char anymore. This is a
-  workaround that is not necessary anymore.
+* Get rid of lyxrc.force_paint_single_char. This was a workaround that
+  is not necessary anymore.
 
 * Implement proper string metrics computation (with cache). Remove
   useless workarounds which disable kerning and ligatures.
@@ -53,7 +53,4 @@ What is done:
 
 Next steps:
 
-* Get rid of LyXRC::force_paint_single_char, which is not used anymore
-  in the source.
-
 * Maybe get rid of LyXRC::rtl_support, which does not have a real use case.
diff --git a/lib/configure.py b/lib/configure.py
index c8e8267..f0b7166 100644
--- a/lib/configure.py
+++ b/lib/configure.py
@@ -1479,7 +1479,7 @@ if __name__ == '__main__':
 lyx_check_config = True
 lyx_kpsewhich = True
 outfile = 'lyxrc.defaults'
-lyxrc_fileformat = 15
+lyxrc_fileformat = 16
 rc_entries = ''
 lyx_keep_temps = False
 version_suffix = ''
diff --git a/lib/scripts/prefs2prefs_prefs.py b/lib/scripts/prefs2prefs_prefs.py
index 66423ae..4770fbf 100644
--- a/lib/scripts/prefs2prefs_prefs.py
+++ b/lib/scripts/prefs2prefs_prefs.py
@@ -63,6 +63,13 @@
 #   New RC default_otf_view_format
 #   No conversion necessary.
 
+# Incremented to format 15, by prannoy
+#   Add fullscreen_statusbar
+#   No conversion necessary.
+
+# Incremented to format 16, by lasgouttes
+#  Remove force_paint_single_char rc.
+
 # NOTE: The format should also be updated in LYXRC.cpp and
 # in configure.py.
 
@@ -306,6 +313,17 @@ def mac_cursor_movement(line):
 
 
 
+#
+# Conversions from LyX 2.1 to 2.2
+
+def remove_force_paint_single_char(line):
+   if not line.lower().startswith("\\force_paint_single_char"):
+   return no_match
+   return (True, "")
+
+# End conversions for LyX 2.1 to 2.2
+
+
 conversions = [
[  1, [ # there were several conversions for format 1
export_menu,
@@ -327,5 +345,6 @@ conversions = [
[ 12, []],
[ 13, [mac_cursor_movement]],
[ 14, []],
-   [ 15, []]
+   [ 15, []],
+   [ 16, [remove_force_paint_single_char]]
 ]
diff --git a/src/LyXRC.cpp b/src/LyXRC.cpp
index 0138f61..46309ee 100644
--- a/src/LyXRC.cpp
+++ b/src/LyXRC.cpp
@@ -58,7 +58,7 @@ namespace {
 
 // The format should also be updated in configure.py, and conversion code
 // should be added to prefs2prefs_prefs.py.
-static unsigned int const LYXRC_FILEFORMAT = 15; // prannoy: statusbar on/off 
in full screen
+static unsigned int const LYXRC_FILEFORMAT = 16; // lasgouttes: remove 
\\force_paint_single_char
 
 // when adding something to this array keep it sorted!
 LexerKeyword lyxrcTags[] = {
@@ -106,7 +106,6 @@ LexerKeyword lyxrcTags[] = {
{ "\\example_path", LyXRC::RC_EXAMPLEPATH },
{ "\\export_overwrite", LyXRC::RC_EXPORT_OVERWRITE },
{ "\\font_encoding", LyXRC::RC_FONT_ENCODING },
-   { "\\force_paint_single_char", LyXRC::RC_FORCE_PAINT_SINGLE_CHAR },
{ "\\format", LyXRC::RC_FILEFORMAT },
{ "\\forward_search_dvi", LyXRC::RC_FORWARD_SEARCH_DVI },
{ "\\forward_search_pdf", LyXRC::RC_FORWARD_SEARCH_PDF },
@@ -447,10 +446,6 @@ LyXRC::ReturnValues LyXRC::read(Lexer & lexrc, bool 
check_format)
if (!lexrc.isOK())
return ReadError;
 
-   // default for current rowpainter capabilities
-   //force_paint_single_char = true;
-   force_paint_single_char = false;
-
// format prior to 2.0 and introduction of format tag
unsigned int format = 0;
 
@@ -556,10 +551,6 @@ LyXRC::ReturnValues LyXRC::read(Lexer & lexrc, bool 
check_format)
lexrc >> fontenc;
break;
 
-   case RC_FORCE_PAINT_SINGLE_CHAR:
-   lexrc >> force_paint_single_char;
-   break;
-
case RC_PRINTER:
lexrc >> printer;
break;
@@ -,14 +2213,6 @@ void LyXRC::write(ostream & os, bool 
ignore_system_lyxrc, string const & name) c
if (tag != RC_LAST)
break;
 
-   case RC_FORCE_PAINT_SINGLE_CHAR:
-   if (ignore_system_lyxrc ||
-   force_paint_single_char != 
system_

[LyX/master] Some fixes related to RTL text

2014-07-25 Thread Jean-Marc Lasgouttes
commit 8649ac7fe66ac0efca20918fff2fea051cc88512
Author: Jean-Marc Lasgouttes <lasgout...@lyx.org>
Date:   Wed Mar 19 14:44:53 2014 +0100

Some fixes related to RTL text

 * fix handling of boundary situations in Row::Elements::x2pos;

 * fix handling of boundary situations in TextMetrics::getColumnNearX;

 * make sure to always use Font::isVisibleRightToLeft instead of 
Font::isRightToLeft;

 * Improve debug messages.

diff --git a/00README_STR_METRICS_BRANCH b/00README_STR_METRICS_BRANCH
index 18c68ca..e38d4b6 100644
--- a/00README_STR_METRICS_BRANCH
+++ b/00README_STR_METRICS_BRANCH
@@ -24,21 +24,26 @@ What is done:
   useless workarounds which disable kerning and ligatures.
 
 
-Next steps needed:
+Next steps:
 
 * check what happens with arabic and/or hebrew text. There may be some
   problems related to compose characters. I suspect that some code is
   needed in FontMetrics::width.
 
-Next possible steps:
-
 * Get rid of old code in cursorX and getColumnNearX; it has been
   kept for comparison purpose, guarded with KEEP_OLD_METRICS_CODE in
   order to check computations.
 
+* rename getColumnNearX to getPosNearX or x2pos (and change code
+  accordingly). It does not make sense to return a position relative
+  to the start of row, since nobody needs this.
+
 * Re-implement row painting using row elements. This is not difficult
   in principle, but the code is intricate and needs some careful
-  analysis.
+  analysis. First thing that needs to be done is to break row elements
+  with the same criterions. Currently TextMetrics::breakRow does not
+  consider on-the-fly spellchecking and selection changes, but it is
+  not clear to me that it is required.
 
 * Profile and see how performance can be improved.
 
@@ -56,4 +61,7 @@ Other differences (aka real bugs)
 
 * there are still difference in what breaks words. In particular,
   RowPainter breaks strings at: selection end, spellchecking
-  extremity.
+  extremities.
+
+* when clicking in the right margin, GetColumnNearX does not return
+  the same value as before.
diff --git a/src/Row.cpp b/src/Row.cpp
index 9da174f..d074d73 100644
--- a/src/Row.cpp
+++ b/src/Row.cpp
@@ -64,27 +64,26 @@ pos_type Row::Element::x2pos(double , bool const low) 
const
FontMetrics const & fm = theFontMetrics(font);
double last_w = 0;
double w = 0;
-   size_t i = 1;
+   size_t i = 0;
// non-STRING element only contain one position
if (type != STRING) {
-   i = 0;
w = width();
} else {
// FIXME: implement dichotomy search?
-   for ( ; i <= str.size() ; ++i) {
+   for ( ; i < str.size() ; ++i) {
last_w = w;
-   w = fm.width(str.substr(0,i));
-   if (w > x2) {
-   --i;
+   w = fm.width(str.substr(0, i + 1));
+   if (w > x2)
break;
-   }
}
// if (i == str.size())
//  lyxerr << " NOT FOUND ";
}
 
+   if (i == str.size())
+   x2 = w;
// round to the closest side
-   if (!low && (x2 - last_w > w - x2)) {
+   else if (!low && (x2 - last_w > w - x2)) {
x2 = w;
++i;
} else
@@ -214,6 +213,7 @@ ostream & operator<<(ostream & os, Row const & row)
os << " pos: " << row.pos_ << " end: " << row.end_
   << " x: " << row.x
   << " width: " << row.dim_.wid
+  << " right_margin: " << row.right_margin
   << " ascent: " << row.dim_.asc
   << " descent: " << row.dim_.des
   << " separator: " << row.separator
diff --git a/src/Row.h b/src/Row.h
index 2282c82..0a45aa0 100644
--- a/src/Row.h
+++ b/src/Row.h
@@ -186,6 +186,10 @@ public:
///
bool empty() const { return elements_.empty(); }
///
+   Element & front() { return elements_.front(); }
+   ///
+   Element const & front() const { return elements_.front(); }
+   ///
Element & back() { return elements_.back(); }
///
Element const & back() const { return elements_.back(); }
diff --git a/src/TextMetrics.cpp b/src/TextMetrics.cpp
index ca6408d..8563975 100644
--- a/src/TextMetrics.cpp
+++ b/src/TextMetrics.cpp
@@ -15,7 +15,7 @@
  * Full author contact details are available in file CREDITS.
  */
 
-//#define KEEP_OLD_METRICS_CODE 1
+#define KEEP_OLD_METRICS_CODE 1
 
 #include 
 
@@ -810,8 +810,8 @@ void TextMetrics::breakRow(Row & row, int const 
right_margin, pit_type const pit
int const

[LyX/master] Speed-up drawing when text is not justified.

2014-07-25 Thread Jean-Marc Lasgouttes
commit 7734270163ed1e689dc5f7db06a85f876f96f399
Author: Jean-Marc Lasgouttes <lasgout...@lyx.org>
Date:   Fri May 2 15:03:20 2014 +0200

Speed-up drawing when text is not justified.

Do not cut strings at separators in RowPainter when text is not
justified. This speeds-up painting by reducing the number of strings
to draw.

Do also a modest cleanup of paintChar (remove dubious optimization).

diff --git a/00README_STR_METRICS_BRANCH b/00README_STR_METRICS_BRANCH
index e7a6f29..73f5ed3 100644
--- a/00README_STR_METRICS_BRANCH
+++ b/00README_STR_METRICS_BRANCH
@@ -40,16 +40,16 @@ What is done:
   useless workarounds which disable kerning and ligatures.
 
 * when lyxrc.force_paint_single_char is false, draw also RtL text
-  string-wise. This both speed-up drawing and prepare for code
+  string-wise. This both speeds-up drawing and prepares for code
   removal, since we now rely on Qt to do things we use to do by
   ourselves (see isArabic* and isHebrew* code in Encodings.cpp).
 
+* Do not cut strings at separators in RowPainter when text is not
+  justified. This speeds-up painting by reducing the number of strings
+  to draw.
 
-Next steps:
 
-* investigate whether strings could be cut at separators in RowPainter
-  only in justified text. This would speed-up painting in other cases
-  by lowering the number of strings to draw.
+Next steps:
 
 * get lots of testing.
 
diff --git a/src/rowpainter.cpp b/src/rowpainter.cpp
index b0708bf..8286ec7 100644
--- a/src/rowpainter.cpp
+++ b/src/rowpainter.cpp
@@ -165,10 +165,9 @@ void RowPainter::paintChars(pos_type & vpos, Font const & 
font)
// This method takes up 70% of time when typing
pos_type pos = bidi_.vis2log(vpos);
// first character
-   char_type prev_char = par_.getChar(pos);
-   vector str;
+   char_type c = par_.getChar(pos);
+   docstring str;
str.reserve(100);
-   str.push_back(prev_char);
 
// special case for arabic
string const & lang = font.language()->lang();
@@ -179,13 +178,12 @@ void RowPainter::paintChars(pos_type & vpos, Font const & 
font)
// FIXME: Why only round brackets and why the difference to
// Hebrew? See also Paragraph::getUChar
if (swap_paren) {
-   char_type c = str[0];
if (c == '(')
c = ')';
else if (c == ')')
c = '(';
-   str[0] = c;
}
+   str.push_back(c);
 
pos_type const end = row_.endpos();
FontSpan const font_span = par_.fontSpan(pos);
@@ -230,7 +228,8 @@ void RowPainter::paintChars(pos_type & vpos, Font const & 
font)
if (c == '\t')
break;
 
-   if (!isPrintableNonspace(c))
+   if (!isPrintableNonspace(c)
+   && (c != ' ' || row_.separator > 0))
break;
 
// FIXME: Why only round brackets and why the difference to
@@ -243,13 +242,10 @@ void RowPainter::paintChars(pos_type & vpos, Font const & 
font)
}
 
str.push_back(c);
-   prev_char = c;
}
 
-   docstring s([0], str.size());
-
-   if (s[0] == '\t')
-   s.replace(0,1,from_ascii(""));
+   if (str[0] == '\t')
+   str.replace(0,1,from_ascii(""));
 
/* Because we do our own bidi, at this point the strings are
 * already in visual order. However, Qt also applies its own
@@ -267,13 +263,13 @@ void RowPainter::paintChars(pos_type & vpos, Font const & 
font)
// Pop directional formatting: return to previous state
char_type const PDF = 0x202C;
if (font.isVisibleRightToLeft()) {
-   reverse(s.begin(), s.end());
-   s = RLO + s + PDF;
+   reverse(str.begin(), str.end());
+   str = RLO + str + PDF;
} else
-   s = LRO + s + PDF;
+   str = LRO + str + PDF;
 
if (!selection && !change_running.changed()) {
-   x_ += pi_.pain.text(int(x_), yo_, s, font.fontInfo());
+   x_ += pi_.pain.text(int(x_), yo_, str, font.fontInfo());
return;
}
 
@@ -283,7 +279,7 @@ void RowPainter::paintChars(pos_type & vpos, Font const & 
font)
else if (selection)
copy.setPaintColor(Color_selectiontext);
 
-   x_ += pi_.pain.text(int(x_), yo_, s, copy);
+   x_ += pi_.pain.text(int(x_), yo_, str, copy);
 }
 
 


[LyX/master] Revert optimization where several words are drawn at the same time

2014-07-25 Thread Jean-Marc Lasgouttes
commit bbe6e9f593fc585ee9f5d69275487bf3ddbcaf47
Author: Jean-Marc Lasgouttes <lasgout...@lyx.org>
Date:   Sun Jul 20 18:54:31 2014 +0200

Revert optimization where several words are drawn at the same time

This can only be done where splitting of string is identical in row 
breaking and display. It will be possible to reintroduce this when row painting 
uses the tokenized row information.

diff --git a/00README_STR_METRICS_BRANCH b/00README_STR_METRICS_BRANCH
index e901b51..342d2f6 100644
--- a/00README_STR_METRICS_BRANCH
+++ b/00README_STR_METRICS_BRANCH
@@ -39,10 +39,6 @@ What is done:
 
 * Draw also RtL text string-wise. This speeds-up drawing.
 
-* Do not cut strings at separators in RowPainter when text is not
-  justified. This speeds-up painting by reducing the number of strings
-  to draw.
-
 * Do not cut strings at selection boundary in RowPainter. This avoids
   ligature/kerning breaking in latin text, and bad rendering problems
   in Arabic.
diff --git a/src/TextMetrics.cpp b/src/TextMetrics.cpp
index 4dde5fd..45a5007 100644
--- a/src/TextMetrics.cpp
+++ b/src/TextMetrics.cpp
@@ -565,7 +565,7 @@ void TextMetrics::computeRowMetrics(pit_type const pit,
 
Paragraph const & par = text_->getPar(pit);
 
-   double w = width - row.right_margin - row.width();
+   double const w = width - row.right_margin - row.width();
// FIXME: put back this assertion when the crash on new doc is solved.
//LASSERT(w >= 0, /**/);
 
@@ -607,9 +607,7 @@ void TextMetrics::computeRowMetrics(pit_type const pit,
} else if (int(row.width()) < max_width_) {
// is it block, flushleft or flushright?
// set x how you need it
-   int const align = getAlign(par, row.pos());
-
-   switch (align) {
+   switch (getAlign(par, row.pos())) {
case LYX_ALIGN_BLOCK: {
int const ns = numberOfSeparators(row);
/** If we have separators, and this row has
@@ -650,12 +648,12 @@ void TextMetrics::computeRowMetrics(pit_type const pit,
}
 #endif
 
+   // Finally,  handle hfill insets
pos_type const endpos = row.endpos();
pos_type body_pos = par.beginOfBody();
if (body_pos > 0
&& (body_pos > endpos || !par.isLineSeparator(body_pos - 1)))
body_pos = 0;
-
ParagraphMetrics & pm = par_metrics_[pit];
Row::iterator cit = row.begin();
Row::iterator const cend = row.end();
@@ -798,8 +796,7 @@ void TextMetrics::breakRow(Row & row, int const 
right_margin, pit_type const pit
int const width = max_width_ - right_margin;
pos_type const body_pos = par.beginOfBody();
row.clear();
-   row.x = leftMargin(max_width_, pit, pos);
-   row.dimension().wid = row.x;
+   row.dimension().wid = leftMargin(max_width_, pit, pos);
row.right_margin = right_margin;
 
if (pos >= end || row.width() > width) {
diff --git a/src/frontends/qt4/GuiPainter.cpp b/src/frontends/qt4/GuiPainter.cpp
index a33aebf..2b51f47 100644
--- a/src/frontends/qt4/GuiPainter.cpp
+++ b/src/frontends/qt4/GuiPainter.cpp
@@ -273,14 +273,14 @@ void GuiPainter::image(int x, int y, int w, int h, 
graphics::Image const & i)
 
 int GuiPainter::text(int x, int y, char_type c, FontInfo const & f)
 {
-   docstring s(1, c);
-   return text(x, y, s, f);
+   return text(x, y, docstring(1, c), f);
 }
 
 
 int GuiPainter::text(int x, int y, docstring const & s,
FontInfo const & f)
 {
+   //LYXERR0("text: x=" << x << ", s=" << s);
if (s.empty())
return 0;
 
diff --git a/src/rowpainter.cpp b/src/rowpainter.cpp
index ee4cd18..8c8ac4c 100644
--- a/src/rowpainter.cpp
+++ b/src/rowpainter.cpp
@@ -186,16 +186,15 @@ void RowPainter::paintChars(pos_type & vpos, Font const & 
font)
}
str.push_back(c);
 
-   pos_type const end = row_.endpos();
FontSpan const font_span = par_.fontSpan(pos);
// Track-change status.
Change const & change_running = par_.lookupChange(pos);
-
// spelling correct?
bool const spell_state =
lyxrc.spellcheck_continuously && par_.isMisspelled(pos);
 
// collect as much similar chars as we can
+   pos_type const end = row_.endpos();
for (++vpos ; vpos < end ; ++vpos) {
pos = bidi_.vis2log(vpos);
 
@@ -218,11 +217,7 @@ void RowPainter::paintChars(pos_type & vpos, Font const & 
font)
if (c == '\t')
break;
 
-   // When row_.separator == 0, it is possible to print a
-   // string longer than a word in one fell swoop.
-   // Therefore there is no need to break at spaces.
-   if (!isPrintableNonspace(c)

[LyX/master] More fixes to cursorX

2014-07-25 Thread Jean-Marc Lasgouttes
commit 79014c7551de71488bb18e58ae8344cdbbde9490
Author: Jean-Marc Lasgouttes <lasgout...@lyx.org>
Date:   Fri Oct 18 17:55:30 2013 +0200

More fixes to cursorX

In Row::Element::pos2x, handle the boundaries in a cleaner way.

diff --git a/src/Row.cpp b/src/Row.cpp
index d074d73..d7940e9 100644
--- a/src/Row.cpp
+++ b/src/Row.cpp
@@ -36,17 +36,23 @@ using frontend::FontMetrics;
 
 double Row::Element::pos2x(pos_type const i) const
 {
+   LASSERT(i >= pos && i <= endpos, return 0);
+
bool const rtl = font.isVisibleRightToLeft();
 
-   // handle first the two bounds of the element
-   if ((!rtl && pos >= i) || (rtl && endpos <= i))
-   return 0;
-   if ((!rtl && endpos <= i) || (rtl && pos >= i))
-   return width();
+   int w = 0;
+   //handle first the two bounds of the element
+   if (i == pos)
+   w = 0;
+   else if (i == endpos)
+   w = width();
+   else {
+   LASSERT(type == STRING, return 0);
+   FontMetrics const & fm = theFontMetrics(font);
+   // FIXME Avoid caching of metrics there?
+   w = fm.width(str.substr(0, i - pos));
+   }
 
-   FontMetrics const & fm = theFontMetrics(font);
-   // FIXME Avoid caching of metrics there?
-   int const w = fm.width(str.substr(0, i - pos));
if (rtl)
return width() - w;
else
diff --git a/src/TextMetrics.cpp b/src/TextMetrics.cpp
index 8563975..b894133 100644
--- a/src/TextMetrics.cpp
+++ b/src/TextMetrics.cpp
@@ -1613,15 +1613,16 @@ int TextMetrics::cursorX(CursorSlice const & sl,
double x = row.x;
 
/**
-* When boundary is true, position is on the row element (pos, endpos)
+* When boundary is true, position i is in the row element (pos, endpos)
 * if
-*pos < pos <= endpos
+*pos < i <= endpos
 * whereas, when boundary is false, the test is
-*pos <= pos < endpos
+*pos <= i < endpos
 * The correction below allows to handle both cases.
*/
int const boundary_corr = (boundary && pos) ? -1 : 0;
 
+   //?
if (row.empty()
|| (row.begin()->font.isVisibleRightToLeft()
&& pos == row.begin()->endpos))


[LyX/master] Re-implement getColumNearX using row elements

2014-07-25 Thread Jean-Marc Lasgouttes
commit f215bb3b926d8b7d9240f0f08793fc3d731d5398
Author: Jean-Marc Lasgouttes <lasgout...@lyx.org>
Date:   Sun Jul 21 20:22:32 2013 +0200

Re-implement getColumNearX using row elements

The code is now so much shorter that it is scary... Expect that
further changes will be necessary

Cursor boundary is not handled yet.

diff --git a/00README_STR_METRICS_BRANCH b/00README_STR_METRICS_BRANCH
index 7c87c0a..0727011 100644
--- a/00README_STR_METRICS_BRANCH
+++ b/00README_STR_METRICS_BRANCH
@@ -13,15 +13,17 @@ What is done:
 
 * re-implement cursorX using row elements
 
+* re-implement getColumnNearX using row elements (boundary is not
+  considered yet).
+
 * Implement proper string metrics computation (with cache), when
-  lyxrc.force_paint_single_char is false.
+  lyxrc.force_paint_single_char is false. In this case, remove also
+  useless workarounds which disable kerning and ligatures.
 
 Next steps:
 
-* re-implement getColumnNearX using row elements
-
 * get rid of old code of cursorX and getColumnNearX (which have been
-  kept for comparison purpose).
+  kept for comparison purpose, guarded with KEEP_OLD_METRICS_CODE).
 
 * re-implement row painting using row elements (can it be done?)
 
@@ -41,3 +43,5 @@ Other differences that should be considered as bugs
 * words longer than the screen are no monger broken at an arbitrary
   point. This is a problem for languages like chinese that do not use
   separators.
+
+* Boundary is not taken in account properly in getColumnNearX
diff --git a/src/Row.cpp b/src/Row.cpp
index 9e40986..c32be85 100644
--- a/src/Row.cpp
+++ b/src/Row.cpp
@@ -54,8 +54,58 @@ double Row::Element::pos2x(pos_type const i) const
 }
 
 
+pos_type Row::Element::x2pos(double ) const
+{
+   //lyxerr << "x2pos: x=" << x << " w=" << width() << " " << *this;
+   // if element is rtl, flip x value
+   bool const rtl = font.isVisibleRightToLeft();
+   double x2 = rtl ? (width() - x) : x;
+
+   FontMetrics const & fm = theFontMetrics(font);
+   double last_w = 0;
+   double w = 0;
+   size_t i = 1;
+   // non-STRING element only contain one position
+   if (type != STRING) {
+   i = 0;
+   w = width();
+   } else {
+   // FIXME: implement dichotomy search?
+   for ( ; i <= str.size() ; ++i) {
+   last_w = w;
+   w = fm.width(str.substr(0,i));
+   if (w > x2) {
+   --i;
+   break;
+   }
+   }
+   // if (i == str.size())
+   //  lyxerr << " NOT FOUND ";
+   }
+
+   // round to the closest side
+   if (x2 - last_w > w - x2) {
+   x2 = w;
+   ++i;
+   } else
+   x2 = last_w;
+
+   // is element is rtl, flip values
+   if (rtl) {
+   x = last_w - x2;
+   i = endpos - i;
+   } else {
+   x = x2;
+   i = pos + i;
+   }
+
+   //lyxerr << "=> p=" << i << " x=" << x << endl;
+   return i;
+}
+
+
 Row::Row()
-   : separator(0), label_hfill(0), x(0),
+   : separator(0), label_hfill(0), x(0), right_margin(0),
sel_beg(-1), sel_end(-1),
begin_margin_sel(false), end_margin_sel(false),
changed_(false), crc_(0), pos_(0), end_(0)
@@ -153,19 +203,19 @@ ostream & operator<<(ostream & os, Row::Element const & e)
os << e.pos << ">>" << e.endpos << " ";
 
switch (e.type) {
-   case Row::Element::STRING:
-   os << "STRING: `" << to_utf8(e.str) << "'";
+   case Row::STRING:
+   os << "STRING: `" << to_utf8(e.str) << "' " << e.dim.wid;
break;
-   case Row::Element::COMPLETION:
-   os << "COMPLETION: `" << to_utf8(e.str) << "'";
+   case Row::VIRTUAL:
+   os << "VIRTUAL: `" << to_utf8(e.str) << "'";
break;
-   case Row::Element::INSET:
+   case Row::INSET:
os << "INSET: " << to_utf8(e.inset->layoutName());
break;
-   case Row::Element::SEPARATOR:
+   case Row::SEPARATOR:
os << "SEPARATOR: " << e.dim.wid << "+" << e.extra;
break;
-   case Row::Element::SPACE:
+   case Row::SPACE:
os << "SPACE: " << e.dim.wid;
break;
}
@@ -176,6 +226,7 @@ ostream & operator<<(ostream &am

[LyX/master] Reintroduce the code related to InsetEnvSeparator

2014-07-25 Thread Jean-Marc Lasgouttes
commit f3924a52b32cdddec0fbcac40d631a3f27761e37
Author: Jean-Marc Lasgouttes <lasgout...@lyx.org>
Date:   Mon Jun 30 11:45:24 2014 +0200

Reintroduce the code related to InsetEnvSeparator

This commits (tries to) reintroduce properly the code that was reverted at 
the beginning of this branch. This had to be done because these patches 
interefered with the big refactoring of TextMetrics.cpp.

This commit reintroduces the changes to TextMetrics.cpp contained in 
c668ebf6, c85dbfea9 and 061509bf.

diff --git a/src/TextMetrics.cpp b/src/TextMetrics.cpp
index bda3b2f..c168998 100644
--- a/src/TextMetrics.cpp
+++ b/src/TextMetrics.cpp
@@ -346,6 +346,7 @@ bool TextMetrics::isRTLBoundary(pit_type pit, pos_type pos,
// FED  FED| FED )
if (startpos == pos && endpos == pos && endpos != par.size()
&& (par.isNewline(pos - 1)
+   || par.isEnvSeparator(pos - 1)
|| par.isLineSeparator(pos - 1)
|| par.isSeparator(pos - 1)))
return false;
@@ -680,7 +681,7 @@ void TextMetrics::computeRowMetrics(pit_type const pit,
 int TextMetrics::labelFill(pit_type const pit, Row const & row) const
 {
Paragraph const & par = text_->getPar(pit);
-   LBUFERR(par.beginOfBody() > 0);
+   LBUFERR(par.beginOfBody() > 0 || par.isEnvSeparator(0));
 
int w = 0;
Row::const_iterator cit = row.begin();
@@ -876,7 +877,7 @@ void TextMetrics::breakRow(Row & row, int const 
right_margin, pit_type const pit
// - Before a display inset
// - After a display inset
Inset const * inset = 0;
-   if (par.isNewline(i)
+   if (par.isNewline(i) || par.isEnvSeparator(i)
|| (i + 1 < end && (inset = par.getInset(i + 1))
&& inset->display())
|| (!row.empty() && row.back().inset
@@ -1547,7 +1548,8 @@ bool TextMetrics::cursorEnd(Cursor & cur)
bool boundary = false;
if (end != cur.lastpos()) {
if (!cur.paragraph().isLineSeparator(end-1)
-   && !cur.paragraph().isNewline(end-1))
+   && !cur.paragraph().isNewline(end-1)
+   && !cur.paragraph().isEnvSeparator(end-1))
boundary = true;
else
--end;
@@ -1630,7 +1632,9 @@ int TextMetrics::leftMargin(int max_width,
l_margin = leftMargin(max_width, newpar);
// Remove the parindent that has been added
// if the paragraph was empty.
-   if (pars[newpar].empty()) {
+   if (pars[newpar].empty() &&
+   buffer.params().paragraph_separation ==
+   BufferParams::ParagraphIndentSeparation) {
docstring pi = 
pars[newpar].layout().parindent;
l_margin -= theFontMetrics(

buffer.params().getFont()).signedWidth(pi);
@@ -1648,10 +1652,16 @@ int TextMetrics::leftMargin(int max_width,
 
// This happens after sections or environments in standard classes.
// We have to check the previous layout at same depth.
-   if (tclass.isDefaultLayout(par.layout()) && pit > 0
-   && pars[pit - 1].getDepth() >= par.getDepth()) {
+   if (buffer.params().paragraph_separation ==
+   BufferParams::ParagraphSkipSeparation)
+   parindent.erase();
+   else if (pit > 0 && pars[pit - 1].getDepth() >= par.getDepth()) {
pit_type prev = text_->depthHook(pit, par.getDepth());
-   if (pars[prev < pit ? prev : pit - 1].layout().nextnoindent)
+   if (par.layout() == pars[prev].layout()) {
+   if (prev != pit - 1
+   && pars[pit - 1].layout().nextnoindent)
+   parindent.erase();
+   } else if (pars[prev].layout().nextnoindent)
parindent.erase();
}
 


[LyX/master] Add a readme file describing the state of the branch

2014-07-25 Thread Jean-Marc Lasgouttes
commit b044696d592b1602015828eb3db66c54562751c9
Author: Jean-Marc Lasgouttes <lasgout...@lyx.org>
Date:   Tue Jun 18 10:18:32 2013 +0200

Add a readme file describing the state of the branch

diff --git a/00README_STR_METRICS_BRANCH b/00README_STR_METRICS_BRANCH
new file mode 100644
index 000..b34ba5b
--- /dev/null
+++ b/00README_STR_METRICS_BRANCH
@@ -0,0 +1,31 @@
+This branch is where I (jmarc) try to implement string_wise metrics
+computation. This is done through a series of cleanups. The expected
+speed improvement will only be visible at the end of the road: indeed
+for now we intend to keep unchanged behavior for testing purposes.
+
+What is done:
+* Make TextMetrics methods operate on Row objects: breakRow and
+setRowHeight instead of rowBreakPoint and rowHeight.
+* change breakRow operation to operate on text strings on which
+metrics are computed. Note that for now FontMetrics::width(docstring)
+still computes the sum of character widths, so that behavior is
+unchanged.
+
+Next steps:
+* Make breakRow build a list of elements (string, inset,
+separator,...) in the row. This will be reused by other methods
+* get rid of rowWidth (breakRow does compute this)
+* re-implement getColumnNearX using row elements
+* re-implement x2pos using row elements
+* re-implement row painting using row elements
+* Finally, implement proper string metrics computation (with cache)
+* profile and see how performance can be improved.
+
+Difference in behavior
+* words longer than the screen are no monger broken at an arbitrary
+point. This will not be useful anymore with horizontal scrolling.
+* end of paragraph markers metrics are computed with the font of the
+actual text, not default font. This will be extended to the other
+methods.
+
+The other differences should be considered as bugs.


[LyX/master] Cleanup TextMetrics::rowBreakPoint.

2014-07-25 Thread Jean-Marc Lasgouttes
commit fe8c3b4348b47099171957ea76daf9ccc019a5d1
Author: Jean-Marc Lasgouttes <lasgout...@lyx.org>
Date:   Fri Jun 14 00:01:49 2013 +0200

Cleanup TextMetrics::rowBreakPoint.

Collect properly all strings to compute string metrics

Some changes with respect to existing code
 - end of paragraph font is now the one of the text
 - words longer than a line are not broken anymore. I think this is not 
useful  if we have horizontal scrollbar

Other than that, the code is still compatible with rowWidth and friends.

diff --git a/src/TextMetrics.cpp b/src/TextMetrics.cpp
index 66771d4..3026367 100644
--- a/src/TextMetrics.cpp
+++ b/src/TextMetrics.cpp
@@ -27,6 +27,7 @@
 #include "CoordCache.h"
 #include "Cursor.h"
 #include "CutAndPaste.h"
+#include "Encoding.h"
 #include "HSpace.h"
 #include "InsetList.h"
 #include "Layout.h"
@@ -800,26 +801,25 @@ private:
 
 } // anon namespace
 
-pos_type TextMetrics::rowBreakPoint(int width, pit_type const pit,
-   pos_type pos) const
+pos_type TextMetrics::rowBreakPoint(int const width, pit_type const pit,
+   pos_type const pos) const
 {
-   ParagraphMetrics const & pm = par_metrics_[pit];
Paragraph const & par = text_->getPar(pit);
pos_type const end = par.size();
if (pos == end || width < 0)
return end;
 
-   Layout const & layout = par.layout();
+   ParagraphMetrics const & pm = par_metrics_[pit];
+   ParagraphList const & pars = text_->paragraphs();
 
 #if 0
//FIXME: As long as leftMargin() is not correctly implemented for
// MARGIN_RIGHT_ADDRESS_BOX, we should also not do this here.
// Otherwise, long rows will be painted off the screen.
-   if (layout.margintype == MARGIN_RIGHT_ADDRESS_BOX)
+   if (par.layout().margintype == MARGIN_RIGHT_ADDRESS_BOX)
return addressBreakPoint(pos, par);
 #endif
 
-   pos_type const body_pos = par.beginOfBody();
 
// check for possible inline completion
DocIterator const & inlineCompletionPos = bv_->inlineCompletionPos();
@@ -831,70 +831,69 @@ pos_type TextMetrics::rowBreakPoint(int width, pit_type 
const pit,
inlineCompletionLPos = inlineCompletionPos.pos() - 1;
}
 
-   // Now we iterate through until we reach the right margin
-   // or the end of the par, then choose the possible break
-   // nearest that.
-
-   int label_end = labelEnd(pit);
int const left = leftMargin(max_width_, pit, pos);
+   pos_type const body_pos = par.beginOfBody();
int x = left;
-
-   // pixel width since last breakpoint
-   int chunkwidth = 0;
-
-   docstring const s(1, char_type(0x00B6));
-   Font f;
-   int par_marker_width = theFontMetrics(f).width(s);
+   pos_type point = end;
 
FontIterator fi = FontIterator(*this, par, pit, pos);
-   pos_type point = end;
-   pos_type i = pos;
+   // Accumulator for character strings
+   docstring chunkstr;
+   Font chunkfont = *fi;
 
-   ParagraphList const & pars_ = text_->paragraphs();
-   bool const draw_par_end_marker = lyxrc.paragraph_markers
-   && size_type(pit + 1) < pars_.size();
+   // Now we iterate through until we reach the right margin
+   // or the end of the par, then choose the possible break
+   // nearest that.
 
+   pos_type i = pos;
for ( ; i < end; ++i, ++fi) {
-   int thiswidth = pm.singleWidth(i, *fi);
+   // Add the chunk width when it is finished
+   if (par.isInset(i) || *fi != chunkfont
+   || (body_pos && i == body_pos)) {
+   x += theFontMetrics(chunkfont).width(chunkstr);
+   chunkstr.clear();
+   chunkfont = *fi;
+   }
+
+   char_type c = par.getChar(i);
+   Language const * language = fi->language();
+   // The most special cases are handled first.
+   if (par.isInset(i)) {
+   x += pm.insetDimension(par.getInset(i)).wid;
+   } else if (c == '\t')
+   chunkstr += "";
+   else if (language->rightToLeft()) {
+   if (language->lang() == "arabic_arabtex" ||
+   language->lang() == "arabic_arabi" ||
+   language->lang() == "farsi") {
+   if (!Encodings::isArabicComposeChar(c))
+   chunkstr += par.transformChar(c, i);
+   } else if (language->lang() == "hebrew" &&
+  !Encodings::isHebrewComposeChar(c)) {
+  

[LyX/master] Rename rowpainter.* to RowPainter.*

2014-07-25 Thread Jean-Marc Lasgouttes
commit b54deb36839c97886ac9ff607e248cf16b0443c7
Author: Jean-Marc Lasgouttes <lasgout...@lyx.org>
Date:   Fri Jul 25 21:55:08 2014 +0200

Rename rowpainter.* to RowPainter.*

This is the convention for files that define classes.

diff --git a/src/Makefile.am b/src/Makefile.am
index e40a3bc..17bad02 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -168,7 +168,7 @@ SOURCEFILESCORE = \
ParIterator.cpp \
PDFOptions.cpp \
Row.cpp \
-   rowpainter.cpp \
+   RowPainter.cpp \
Server.cpp \
ServerSocket.cpp \
sgml.cpp \
@@ -273,7 +273,7 @@ HEADERFILESCORE = \
ParIterator.h \
PDFOptions.h \
Row.h \
-   rowpainter.h \
+   RowPainter.h \
Server.h \
ServerSocket.h \
Session.h \
diff --git a/src/RowPainter.cpp b/src/RowPainter.cpp
new file mode 100644
index 000..bf9f280
--- /dev/null
+++ b/src/RowPainter.cpp
@@ -0,0 +1,975 @@
+/**
+ * \file RowPainter.cpp
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author various
+ * \author John Levon
+ *
+ * Full author contact details are available in file CREDITS.
+ */
+
+#include 
+#include 
+
+#include "RowPainter.h"
+
+#include "Buffer.h"
+#include "CoordCache.h"
+#include "Cursor.h"
+#include "BufferParams.h"
+#include "BufferView.h"
+#include "Changes.h"
+#include "Language.h"
+#include "Layout.h"
+#include "LyXRC.h"
+#include "Row.h"
+#include "MetricsInfo.h"
+#include "Paragraph.h"
+#include "ParagraphMetrics.h"
+#include "ParagraphParameters.h"
+#include "TextMetrics.h"
+#include "VSpace.h"
+
+#include "frontends/FontMetrics.h"
+#include "frontends/Painter.h"
+
+#include "insets/InsetText.h"
+
+#include "mathed/InsetMath.h"
+
+#include "support/debug.h"
+#include "support/gettext.h"
+#include "support/textutils.h"
+
+#include "support/lassert.h"
+#include 
+
+using namespace std;
+
+namespace lyx {
+
+using frontend::Painter;
+using frontend::FontMetrics;
+
+
+RowPainter::RowPainter(PainterInfo & pi,
+   Text const & text, pit_type pit, Row const & row, int x, int y)
+   : pi_(pi), text_(text),
+ text_metrics_(pi_.base.bv->textMetrics()),
+ pars_(text.paragraphs()),
+ row_(row), pit_(pit), par_(text.paragraphs()[pit]),
+ pm_(text_metrics_.parMetrics(pit)), change_(pi_.change_),
+ xo_(x), yo_(y), width_(text_metrics_.width()),
+ solid_line_thickness_(1.0), solid_line_offset_(1),
+ dotted_line_thickness_(1.0), dotted_line_offset_(2)
+{
+   bidi_.computeTables(par_, pi_.base.bv->buffer(), row_);
+
+   if (lyxrc.zoom >= 200) {
+   // derive the line thickness from zoom factor
+   // the zoom is given in percent
+   // (increase thickness at 250%, 450% etc.)
+   solid_line_thickness_ = (float)(int((lyxrc.zoom + 50) / 200.0));
+   // adjust line_offset_ too
+   solid_line_offset_ = 1 + int(0.5 * solid_line_thickness_);
+   }
+   if (lyxrc.zoom >= 100) {
+   // derive the line thickness from zoom factor
+   // the zoom is given in percent
+   // (increase thickness at 150%, 250% etc.)
+   dotted_line_thickness_ = (float)(int((lyxrc.zoom + 50) / 
100.0));
+   // adjust line_offset_ too
+   dotted_line_offset_ = int(0.5 * dotted_line_thickness_) + 1;
+   }
+
+   x_ = row_.x + xo_;
+
+   //lyxerr << "RowPainter: x: " << x_ << " xo: " << xo_ << " yo: " << yo_ 
<< endl;
+   //row_.dump();
+
+   LBUFERR(pit >= 0);
+   LBUFERR(pit < int(text.paragraphs().size()));
+}
+
+
+FontInfo RowPainter::labelFont() const
+{
+   FontInfo f = text_.labelFont(par_);
+   // selected text?
+   if (row_.begin_margin_sel || pi_.selected)
+   f.setPaintColor(Color_selectiontext);
+   return f;
+}
+
+
+int RowPainter::leftMargin() const
+{
+   return text_metrics_.leftMargin(text_metrics_.width(), pit_,
+   row_.pos());
+}
+
+// If you want to debug inset metrics uncomment the following line:
+//#define DEBUG_METRICS
+// This draws green lines around each inset.
+
+
+void RowPainter::paintInset(Inset const * inset, pos_type const pos)
+{
+   Font const font = text_metrics_.displayFont(pit_, pos);
+
+   LASSERT(inset, return);
+   // Backup full_repaint status because some insets (InsetTabular)
+   // requires a full repaint
+   bool pi_full_repaint = pi_.full_repaint;
+
+   pi_.base.font = inset->inheritFont() ? font.fontInfo() :
+  

[LyX/master] Whitespace only

2014-07-25 Thread Jean-Marc Lasgouttes
commit 5e126d2920df9fd48d24967f7b0a4a04e61aac65
Author: Jean-Marc Lasgouttes <lasgout...@lyx.org>
Date:   Fri Jul 25 22:35:08 2014 +0200

Whitespace only

diff --git a/src/BufferView.cpp b/src/BufferView.cpp
index bc8162b..faa08f0 100644
--- a/src/BufferView.cpp
+++ b/src/BufferView.cpp
@@ -118,12 +118,12 @@ bool findNextInset(DocIterator & dit, vector 
const & codes,
while (tmpdit) {
Inset const * inset = tmpdit.nextInset();
if (inset) {
-   bool const valid_code = std::find(codes.begin(), 
codes.end(), 
+   bool const valid_code = std::find(codes.begin(), 
codes.end(),
inset->lyxCode()) != codes.end();
InsetCommand const * ic = inset->asInsetCommand();
bool const same_or_no_contents =  contents.empty()
|| (ic && (ic->getFirstNonOptParam() == 
contents));
-   
+
if (valid_code && same_or_no_contents) {
dit = tmpdit;
return true;
@@ -228,7 +228,7 @@ struct BufferView::Private
Private(BufferView & bv): wh_(0), cursor_(bv),
anchor_pit_(0), anchor_ypos_(0),
inlineCompletionUniqueChars_(0),
-   last_inset_(0), clickable_inset_(false), 
+   last_inset_(0), clickable_inset_(false),
mouse_position_cache_(),
bookmark_edit_position_(-1), gui_(0)
{}
@@ -325,9 +325,9 @@ BufferView::~BufferView()
fp.pit = d->cursor_.bottom().pit();
fp.pos = d->cursor_.bottom().pos();
theSession().lastFilePos().save(buffer_.fileName(), fp);
-   
+
if (d->last_inset_)
-   d->last_inset_->setMouseHover(this, false); 
+   d->last_inset_->setMouseHover(this, false);
 
delete d;
 }
@@ -498,7 +498,7 @@ void BufferView::updateScrollbar()
d->scrollbarParameters_.page_step = height_;
 
Text & t = buffer_.text();
-   TextMetrics & tm = d->text_metrics_[];
+   TextMetrics & tm = d->text_metrics_[];
 
LYXERR(Debug::GUI, " Updating scrollbar: height: "
<< t.paragraphs().size()
@@ -658,7 +658,7 @@ void BufferView::setCursorFromScrollbar()
case CUR_INSIDE:
int const y = getPos(oldcur).y_;
newy = min(last, max(y, first));
-   if (y == newy) 
+   if (y == newy)
return;
}
// We reset the cursor because cursorStatus() does not
@@ -778,7 +778,7 @@ bool BufferView::moveToPosition(pit_type bottom_pit, 
pos_type bottom_pos,
// the bookmark.
if (bottom_pit < int(buffer_.paragraphs().size())) {
dit = doc_iterator_begin(_);
-   
+
dit.pit() = bottom_pit;
dit.pos() = min(bottom_pos, dit.paragraph().size());
success = true;
@@ -958,7 +958,7 @@ void BufferView::makeDocumentClass()
 void BufferView::updateDocumentClass(DocumentClassConstPtr olddc)
 {
message(_("Converting document to new document class..."));
-   
+
StableDocIterator backcur(d->cursor_);
ErrorList & el = buffer_.errorList("Class Switch");
cap::switchBetweenClasses(
@@ -1222,7 +1222,7 @@ void BufferView::dispatch(FuncRequest const & cmd, 
DispatchResult & dr)
Cursor & cur = d->cursor_;
 
// Don't dispatch function that does not apply to internal buffers.
-   if (buffer_.isInternal() 
+   if (buffer_.isInternal()
&& lyxaction.funcHasFlag(cmd.action(), LyXAction::NoInternal))
return;
 
@@ -1246,7 +1246,7 @@ void BufferView::dispatch(FuncRequest const & cmd, 
DispatchResult & dr)
<< (unknown_tokens == 1 ? "" : 
"s"));
}
updateDocumentClass(olddc);
-   
+
// We are most certainly here because of a change in the 
document
// It is then better to make sure that all dialogs are in sync 
with
// current document settings.
@@ -1254,7 +1254,7 @@ void BufferView::dispatch(FuncRequest const & cmd, 
DispatchResult & dr)
dr.forceBufferUpdate();
break;
}
-   
+
case LFUN_LAYOUT_MODULES_CLEAR: {
cur.recordUndoFullDocument();
buffer_.params().clearLayoutModules();
@@ -1267,7 +1267,7 @@ void BufferView::dispatch(FuncRequest const & cmd, 
DispatchResult & dr)
case LFUN_LAYOUT_MODULE_ADD: {
BufferParams const &a

[LyX features/scroll-reloaded] Fine tune the scroll offset setting code

2014-07-26 Thread Jean-Marc Lasgouttes
The branch, scroll-reloaded, has been updated.

- Log -

commit b5e4ba6fa7cf3937a09eed143f4e17f236afe424
Author: Jean-Marc Lasgouttes <lasgout...@lyx.org>
Date:   Sat Jul 26 16:25:56 2014 +0200

Fine tune the scroll offset setting code

The new code should feel a bit more natural. It avoids explicit pixel 
values for the margins and does not scroll in some cases where it is not 
necessary.

diff --git a/src/BufferView.cpp b/src/BufferView.cpp
index 4bd1c12..e4e2a83 100644
--- a/src/BufferView.cpp
+++ b/src/BufferView.cpp
@@ -35,6 +35,7 @@
 #include "Language.h"
 #include "LaTeXFeatures.h"
 #include "LayoutFile.h"
+#include "Length.h"
 #include "Lexer.h"
 #include "LyX.h"
 #include "LyXAction.h"
@@ -2937,20 +2938,17 @@ void BufferView::checkCursorScrollOffset(PainterInfo & 
pi)
 
// Horizontal scroll offset of the cursor row in pixels
int offset = d->horiz_scroll_offset_;
-   int const MARGIN = 10;
+   int const MARGIN = Length(2, Length::EM).inPixels(workWidth());
if (cur_x < offset + MARGIN) {
// scroll right
offset = cur_x - MARGIN;
} else if (cur_x > offset + workWidth() - MARGIN) {
// scroll left
offset = cur_x - workWidth() + MARGIN;
-   } else if(offset > 0
- && row.width() - offset < workWidth()){
-   offset = row.width() - workWidth();
}
 
-   if (offset != d->horiz_scroll_offset_)
-   LYXERR0("Offset is now " << offset);
+   if (offset < 0 || row.width() <= workWidth())
+   offset = 0;
 
if (d->update_strategy_ == NoScreenUpdate
&& (offset != d->horiz_scroll_offset_

---

Summary of changes:
 src/BufferView.cpp |   10 --
 1 files changed, 4 insertions(+), 6 deletions(-)


hooks/post-receive
-- 
Repository for new features


[LyX/master] Whitespace

2014-07-26 Thread Jean-Marc Lasgouttes
commit 7f7dc5d314791ed6894d9d18cda032f32093af21
Author: Jean-Marc Lasgouttes <lasgout...@lyx.org>
Date:   Sat Jul 26 16:29:23 2014 +0200

Whitespace

diff --git a/src/insets/InsetTabular.cpp b/src/insets/InsetTabular.cpp
index 8a8c212..ac8e723 100644
--- a/src/insets/InsetTabular.cpp
+++ b/src/insets/InsetTabular.cpp
@@ -542,7 +542,7 @@ InsetTableCell splitCell(InsetTableCell & head, docstring 
const & align_d, bool
if (hassep) {
pit_type const psize = head.paragraphs().front().size();
head.paragraphs().front().eraseChars(dit.pos(), psize, false);
-   tail.paragraphs().front().eraseChars(0, 
+   tail.paragraphs().front().eraseChars(0,
dit.pos() < psize ? dit.pos() + 1 : psize, false);
}
 
@@ -738,9 +738,9 @@ void Tabular::appendRow(row_type row)
 void Tabular::insertRow(row_type const row, bool copy)
 {
row_info.insert(row_info.begin() + row + 1, RowData(row_info[row]));
-   cell_info.insert(cell_info.begin() + row + 1, 
+   cell_info.insert(cell_info.begin() + row + 1,
cell_vector(0, CellData(buffer_)));
-   
+
for (col_type c = 0; c < ncols(); ++c) {
cell_info[row + 1].insert(cell_info[row + 1].begin() + c,
copy ? CellData(cell_info[row][c]) : CellData(buffer_));
@@ -749,7 +749,7 @@ void Tabular::insertRow(row_type const row, bool copy)
if (cell_info[row][c].multirow == CELL_BEGIN_OF_MULTIROW)
cell_info[row + 1][c].multirow = CELL_PART_OF_MULTIROW;
}
-   
+
updateIndexes();
for (col_type c = 0; c < ncols(); ++c) {
if (isPartOfMultiRow(row, c))
@@ -846,7 +846,7 @@ void Tabular::copyColumn(col_type const col)
 
 
 void Tabular::appendColumn(col_type col)
-{  
+{
insertColumn(col, false);
 }
 
@@ -1029,7 +1029,7 @@ bool Tabular::updateColumnWidths()
if (columnSpan(i) == 1) {
if (getAlignment(i) == LYX_ALIGN_DECIMAL
&& cell_info[r][c].decimal_width!=0)
-   new_width = max(new_width, 
cellInfo(i).width 
+   new_width = max(new_width, 
cellInfo(i).width
+ max_dwidth[c] - 
cellInfo(i).decimal_width);
else
new_width = max(new_width, 
cellInfo(i).width);
@@ -1098,8 +1098,8 @@ void Tabular::setAlignment(idx_type cell, LyXAlignment 
align,
if (align == LYX_ALIGN_DECIMAL && dpoint.empty())
dpoint = from_utf8(lyxrc.default_decimal_point);
} else {
-   cellInfo(cell).alignment = align; 
-   cellInset(cell).get()->setContentAlignment(align); 
+   cellInfo(cell).alignment = align;
+   cellInset(cell).get()->setContentAlignment(align);
}
 }
 
@@ -1289,7 +1289,7 @@ bool Tabular::columnRightLine(col_type c) const
idx_type i = cellIndex(r, c);
if (c == cellColumn(i) + columnSpan(i) - 1) {
++total;
-   bool left = (c + 1 < ncols() 
+   bool left = (c + 1 < ncols()
&& cellInfo(cellIndex(r, c + 1)).left_line)
|| c + 1 == ncols();
if (cellInfo(i).right_line && left)
@@ -1304,7 +1304,7 @@ LyXAlignment Tabular::getAlignment(idx_type cell, bool 
onlycolumn) const
 {
if (!onlycolumn && (isMultiColumn(cell) || isMultiRow(cell)))
return cellInfo(cell).alignment;
-   
+
return column_info[cellColumn(cell)].alignment;
 }
 
@@ -1376,7 +1376,7 @@ int Tabular::textVOffset(idx_type cell) const
int voffset = cellInfo(cell).voffset;
if (isMultiRow(cell)) {
row_type const row = cellRow(cell);
-   voffset += (cellHeight(cell) - rowAscent(row) - 
rowDescent(row))/2; 
+   voffset += (cellHeight(cell) - rowAscent(row) - 
rowDescent(row))/2;
}
return voffset;
 }
@@ -1651,7 +1651,7 @@ void Tabular::read(Lexer & lex)
 
 bool Tabular::isMultiColumn(idx_type cell) const
 {
-   return (cellInfo(cell).multicolumn == CELL_BEGIN_OF_MULTICOLUMN 
+   return (cellInfo(cell).multicolumn == CELL_BEGIN_OF_MULTICOLUMN
|| cellInfo(cell).multicolumn == CELL_PART_OF_MULTICOLUMN);
 }
 
@@ -1769,7 +1769,7 @@ Tabular::idx_type Tabular::rowSpan(idx_type cell) const
col_type row = cellRow(cell) + 1;
while (row < nrows() && isPartOfMultiRow(row, column))
++row;
-   
+
return row - cellRow(cell);
 }
 
@@ -1849,7 +1849,7 @@ Tabular::idx_type Tabular::cel

[LyX features/scroll-reloaded] Remove the special horizontal scrolling support in InsetTabular

2014-07-26 Thread Jean-Marc Lasgouttes
The branch, scroll-reloaded, has been updated.

- Log -

commit 3e44bc8bee905a4997ff55b4d8c9ecf0f292d274
Author: Jean-Marc Lasgouttes <lasgout...@lyx.org>
Date:   Sat Jul 26 22:25:48 2014 +0200

Remove the special horizontal scrolling support in InsetTabular

It is not necessary anymore now that there is a global mechanism.

Also, fix the clearing of rows in SingleParUpdate mode.

diff --git a/src/BufferView.cpp b/src/BufferView.cpp
index e4e2a83..6c95d8d 100644
--- a/src/BufferView.cpp
+++ b/src/BufferView.cpp
@@ -2955,7 +2955,7 @@ void BufferView::checkCursorScrollOffset(PainterInfo & pi)
|| !d->last_row_slice_.empty())) {
// FIXME: if one uses SingleParUpdate, then home/end
// will not work on long rows. Why?
-   d->update_strategy_ = FullScreenUpdate;//DecorationUpdate;
+   d->update_strategy_ = FullScreenUpdate;
}
 
d->horiz_scroll_offset_ = offset;
@@ -2982,6 +2982,7 @@ void BufferView::draw(frontend::Painter & pain)
case NoScreenUpdate:
// If no screen painting is actually needed, only some the 
different
// coordinates of insets and paragraphs needs to be updated.
+   LYXERR(Debug::PAINTING, "Strategy: NoScreenUpdate");
pi.full_repaint = true;
pi.pain.setDrawingEnabled(false);
tm.draw(pi, 0, y);
@@ -2989,6 +2990,7 @@ void BufferView::draw(frontend::Painter & pain)
 
case SingleParUpdate:
pi.full_repaint = false;
+   LYXERR(Debug::PAINTING, "Strategy: SingleParUpdate");
// In general, only the current row of the outermost paragraph
// will be redrawn. Particular cases where selection spans
// multiple paragraph are correctly detected in TextMetrics.
@@ -3001,6 +3003,12 @@ void BufferView::draw(frontend::Painter & pain)
// because of the single backing pixmap.
 
case FullScreenUpdate:
+
+   LYXERR(Debug::PAINTING,
+  ((d->update_strategy_ == FullScreenUpdate)
+   ? "Strategy: FullScreenUpdate"
+   : "Strategy: DecorationUpdate"));
+
// The whole screen, including insets, will be refreshed.
pi.full_repaint = true;
 
diff --git a/src/TextMetrics.cpp b/src/TextMetrics.cpp
index f325da7..e41874a 100644
--- a/src/TextMetrics.cpp
+++ b/src/TextMetrics.cpp
@@ -1903,7 +1903,10 @@ void TextMetrics::drawParagraph(PainterInfo & pi, 
pit_type pit, int x, int y) co
// Clear background of this row if paragraph background was not
// already cleared because of a full repaint.
if (!pi.full_repaint && row_has_changed) {
-   pi.pain.fillRectangle(x, y - row.ascent(),
+   LYXERR(Debug::PAINTING, "Clear rect@(" 
+  << max(x, 0) << ", " << y-row.ascent() << ")=" 
+  << width() << " x " << row.height());
+   pi.pain.fillRectangle(max(x, 0), y - row.ascent(),
width(), row.height(), pi.background_color);
}
 
diff --git a/src/insets/InsetTabular.cpp b/src/insets/InsetTabular.cpp
index 8a8c212..507f302 100644
--- a/src/insets/InsetTabular.cpp
+++ b/src/insets/InsetTabular.cpp
@@ -3456,14 +3456,14 @@ docstring InsetTableCell::xhtml(XHTMLStream & xs, 
OutputParams const & rp) const
 
 InsetTabular::InsetTabular(Buffer * buf, row_type rows,
   col_type columns)
-   : Inset(buf), tabular(buf, max(rows, row_type(1)), max(columns, 
col_type(1))), scx_(0), 
+   : Inset(buf), tabular(buf, max(rows, row_type(1)), max(columns, 
col_type(1))),
rowselect_(false), colselect_(false)
 {
 }
 
 
 InsetTabular::InsetTabular(InsetTabular const & tab)
-   : Inset(tab), tabular(tab.tabular),  scx_(0)
+   : Inset(tab), tabular(tab.tabular)
 {
 }
 
@@ -3714,11 +3714,10 @@ bool InsetTabular::isCellSelected(Cursor & cur, 
row_type row, col_type col)
 
 void InsetTabular::draw(PainterInfo & pi, int x, int y) const
 {
-   x += scx_ + ADD_TO_TABULAR_WIDTH;
+   x += ADD_TO_TABULAR_WIDTH;
 
BufferView * bv = pi.base.bv;
Cursor & cur = pi.base.bv->cursor();
-   resetPos(cur);
 
// FIXME: As the full background is painted in drawBackground(),
// we have no choice but to do a full repaint for the Text cells.
@@ -3766,7 +3765,7 @@ void InsetTabular::draw(PainterInfo & pi, int x, int y) 
const
 
 void InsetTabular::drawBackground(PainterInfo & pi, int x, int y)

[LyX features/scroll-reloaded] Fix some display glitches

2014-07-27 Thread Jean-Marc Lasgouttes
The branch, scroll-reloaded, has been updated.

- Log -

commit 14ba5154aa10a7e0f7977e17f3b66483727644d1
Author: Jean-Marc Lasgouttes <lasgout...@lyx.org>
Date:   Sun Jul 27 17:30:57 2014 +0200

Fix some display glitches

* When doing a redraw with drawing disabled (to set inset positions 
properly), take horizontal scroll offset in account

* reset horizontal scroll offset when it is smaller than the left margin.

* when drawing a paragraph, do not modify x globally, only for the row that 
is offset.

diff --git a/src/BufferView.cpp b/src/BufferView.cpp
index 6c95d8d..92ce6f6 100644
--- a/src/BufferView.cpp
+++ b/src/BufferView.cpp
@@ -2929,7 +2929,8 @@ void BufferView::checkCursorScrollOffset(PainterInfo & pi)
bool const drawing = pi.pain.isDrawingEnabled();
pi.pain.setDrawingEnabled(false);
// No need to care about vertical position.
-   RowPainter rp(pi, buffer().text(), d->cursor_.bottom().pit(), row, 0, 
0);
+   RowPainter rp(pi, buffer().text(), d->cursor_.bottom().pit(), row,
+ -d->horiz_scroll_offset_, 0);
rp.paintText();
pi.pain.setDrawingEnabled(drawing);
 
@@ -2947,9 +2948,13 @@ void BufferView::checkCursorScrollOffset(PainterInfo & 
pi)
offset = cur_x - workWidth() + MARGIN;
}
 
-   if (offset < 0 || row.width() <= workWidth())
+   if (offset < row.x || row.width() <= workWidth())
offset = 0;
 
+   if (offset != d->horiz_scroll_offset_)
+   LYXERR(Debug::PAINTING, "Horiz. scroll offset changed from "
+  << d->horiz_scroll_offset_ << " to " << offset);
+
if (d->update_strategy_ == NoScreenUpdate
&& (offset != d->horiz_scroll_offset_
|| !d->last_row_slice_.empty())) {
diff --git a/src/TextMetrics.cpp b/src/TextMetrics.cpp
index e41874a..ab857a5 100644
--- a/src/TextMetrics.cpp
+++ b/src/TextMetrics.cpp
@@ -1807,7 +1807,7 @@ void TextMetrics::draw(PainterInfo & pi, int x, int y) 
const
 }
 
 
-void TextMetrics::drawParagraph(PainterInfo & pi, pit_type pit, int x, int y) 
const
+void TextMetrics::drawParagraph(PainterInfo & pi, pit_type const pit, int 
const x, int y) const
 {
BufferParams const & bparams = bv_->buffer().params();
ParagraphMetrics const & pm = par_metrics_[pit];
@@ -1847,6 +1847,7 @@ void TextMetrics::drawParagraph(PainterInfo & pi, 
pit_type pit, int x, int y) co
for (size_t i = 0; i != nrows; ++i) {
 
Row const & row = pm.rows()[i];
+   int row_x = x;
if (i)
y += row.ascent();
 
@@ -1859,12 +1860,12 @@ void TextMetrics::drawParagraph(PainterInfo & pi, 
pit_type pit, int x, int y) co
 
// Adapt to cursor row scroll offset if applicable.
if (bv_->currentRowSlice() == rowSlice)
-   x -= bv_->horizScrollOffset();
+   row_x -= bv_->horizScrollOffset();
 
// It is not needed to draw on screen if we are not inside.
pi.pain.setDrawingEnabled(inside && original_drawing_state);
 
-   RowPainter rp(pi, *text_, pit, row, x, y);
+   RowPainter rp(pi, *text_, pit, row, row_x, y);
 
if (selection)
row.setSelectionAndMargins(sel_beg_par, sel_end_par);
@@ -1903,10 +1904,10 @@ void TextMetrics::drawParagraph(PainterInfo & pi, 
pit_type pit, int x, int y) co
// Clear background of this row if paragraph background was not
// already cleared because of a full repaint.
if (!pi.full_repaint && row_has_changed) {
-   LYXERR(Debug::PAINTING, "Clear rect@(" 
-  << max(x, 0) << ", " << y-row.ascent() << ")=" 
+   LYXERR(Debug::PAINTING, "Clear rect@("
+  << max(row_x, 0) << ", " << y-row.ascent() << 
")="
   << width() << " x " << row.height());
-   pi.pain.fillRectangle(max(x, 0), y - row.ascent(),
+   pi.pain.fillRectangle(max(row_x, 0), y - row.ascent(),
width(), row.height(), pi.background_color);
}
 

---

Summary of changes:
 src/BufferView.cpp  |9 +++--
 src/TextMetrics.cpp |   13 +++--
 2 files changed, 14 insertions(+), 8 deletions(-)


hooks/post-receive
-- 
Repository for new features


[LyX features/scroll-reloaded] Add marks to indicate when a row is too large

2014-07-27 Thread Jean-Marc Lasgouttes
The branch, scroll-reloaded, has been updated.

- Log -

commit b13ce27430f78fff9c8c58e1bd26d73c9f355aec
Author: Jean-Marc Lasgouttes <lasgout...@lyx.org>
Date:   Sun Jul 27 18:55:10 2014 +0200

Add marks to indicate when a row is too large

A dotted line is shown on the left or on the right to indicate that a part 
of the row is not visible.

For now, the color is hardcoded to Color_red.

diff --git a/src/RowPainter.cpp b/src/RowPainter.cpp
index 4f7e667..59b6770 100644
--- a/src/RowPainter.cpp
+++ b/src/RowPainter.cpp
@@ -439,6 +439,23 @@ int RowPainter::paintAppendixStart(int y)
 }
 
 
+void RowPainter::paintTooLargeMarks(bool const left, bool const right)
+{
+   if (left)
+   pi_.pain.line(dotted_line_thickness_, yo_ - row_.ascent(),
+ dotted_line_thickness_, yo_ + row_.descent(),
+ Color_red,
+ Painter::line_onoffdash, dotted_line_thickness_);
+   if (right) {
+   int const wwidth = pi_.base.bv->workWidth() - 
dotted_line_thickness_;
+   pi_.pain.line(wwidth, yo_ - row_.ascent(),
+ wwidth, yo_ + row_.descent(),
+ Color_red,
+ Painter::line_onoffdash, dotted_line_thickness_);
+   }
+}
+
+
 void RowPainter::paintFirst()
 {
BufferParams const & bparams = pi_.base.bv->buffer().params();
diff --git a/src/RowPainter.h b/src/RowPainter.h
index aebd73e..0628f32 100644
--- a/src/RowPainter.h
+++ b/src/RowPainter.h
@@ -66,6 +66,7 @@ public:
void paintAppendix();
void paintDepthBar();
void paintChangeBar();
+   void paintTooLargeMarks(bool const left, bool const right);
void paintFirst();
void paintLast();
void paintText();
diff --git a/src/TextMetrics.cpp b/src/TextMetrics.cpp
index ab857a5..9a6b67d 100644
--- a/src/TextMetrics.cpp
+++ b/src/TextMetrics.cpp
@@ -1942,6 +1942,8 @@ void TextMetrics::drawParagraph(PainterInfo & pi, 
pit_type const pit, int const
rp.paintLast();
if (i == 0 && is_rtl)
rp.paintFirst();
+   rp.paintTooLargeMarks(row_x < 0,
+ row_x + row.width() > bv_->workWidth());
y += row.descent();
 
// Restore full_repaint status.

---

Summary of changes:
 src/RowPainter.cpp  |   17 +
 src/RowPainter.h|1 +
 src/TextMetrics.cpp |2 ++
 3 files changed, 20 insertions(+), 0 deletions(-)


hooks/post-receive
-- 
Repository for new features


[LyX/master] Fix compilation warnings on windows.

2014-07-28 Thread Jean-Marc Lasgouttes
commit f9caebd29ff52ceee774af7152f0ad6bd1434071
Author: Jean-Marc Lasgouttes <lasgout...@lyx.org>
Date:   Mon Jul 28 09:46:13 2014 +0200

Fix compilation warnings on windows.

diff --git a/src/Row.cpp b/src/Row.cpp
index 1336d05..cab3ab7 100644
--- a/src/Row.cpp
+++ b/src/Row.cpp
@@ -45,7 +45,7 @@ double Row::Element::pos2x(pos_type const i) const
 
bool const rtl = font.isVisibleRightToLeft();
 
-   int w = 0;
+   double w = 0;
//handle first the two bounds of the element
if (i == pos || type != STRING)
w = rtl ? width() : 0;
@@ -70,7 +70,7 @@ pos_type Row::Element::x2pos(double ) const
case STRING: {
FontMetrics const & fm = theFontMetrics(font);
// FIXME: is it really necessary for x to be a double?
-   int xx = x;
+   int xx = int(x);
i = fm.x2pos(str, xx, rtl);
x = xx;
break;
@@ -113,9 +113,9 @@ bool Row::Element::breakAt(double w)
return false;
str = str.substr(0, new_pos - pos);
if (rtl)
-   dim.wid -= w;
+   dim.wid -= int(w);
else
-   dim.wid = w;
+   dim.wid = int(w);
endpos = new_pos;
return true;
 }
@@ -404,7 +404,7 @@ void Row::shortenIfNeeded(pos_type const keep, int const w)
double max_w = w - x;
if (first_below->breakAt(max_w)) {
end_ = first_below->endpos;
-   dim_.wid = x + first_below->width();
+   dim_.wid = int(x + first_below->width());
// If there are other elements, they should be removed.
elements_.erase(boost::next(first_below), end);
} else if (first_below->pos > pos_) {
diff --git a/src/TextMetrics.cpp b/src/TextMetrics.cpp
index a5f0364..0e16ab4 100644
--- a/src/TextMetrics.cpp
+++ b/src/TextMetrics.cpp
@@ -627,7 +627,7 @@ void TextMetrics::computeRowMetrics(pit_type const pit,
row.x += w;
break;
case LYX_ALIGN_CENTER:
-   row.dimension().wid = width - w / 2;
+   row.dimension().wid = width - int(w / 2);
row.x += w / 2;
break;
}
@@ -660,7 +660,7 @@ void TextMetrics::computeRowMetrics(pit_type const pit,
for ( ; cit != cend; ++cit) {
if (row.label_hfill && cit->endpos == body_pos
&& cit->type == Row::SPACE)
-   cit->dim.wid -= row.label_hfill * (nlh - 1);
+   cit->dim.wid -= int(row.label_hfill * (nlh - 1));
if (!cit->inset || !cit->inset->isHfill())
continue;
if (pm.hfillExpansion(row, cit->pos))
@@ -680,7 +680,7 @@ int TextMetrics::labelFill(pit_type const pit, Row const & 
row) const
Paragraph const & par = text_->getPar(pit);
LBUFERR(par.beginOfBody() > 0 || par.isEnvSeparator(0));
 
-   int w = 0;
+   double w = 0;
Row::const_iterator cit = row.begin();
Row::const_iterator const end = row.end();
// iterate over elements before main body (except the last one,
@@ -697,7 +697,7 @@ int TextMetrics::labelFill(pit_type const pit, Row const & 
row) const
FontMetrics const & fm
= theFontMetrics(text_->labelFont(par));
 
-   return max(0, fm.width(label) - w);
+   return max(0, fm.width(label) - int(w));
 }
 
 
@@ -1108,10 +1108,10 @@ pos_type TextMetrics::getPosNearX(Row const & row, int 
& x,
pos_type pos = row.pos();
boundary = false;
if (row.empty())
-   x = row.x;
+   x = int(row.x);
else if (x <= row.x) {
pos = row.front().left_pos();
-   x = row.x;
+   x = int(row.x);
} else if (x >= row.width() - row.right_margin) {
pos = row.back().right_pos();
x = row.width() - row.right_margin;
@@ -1123,7 +1123,7 @@ pos_type TextMetrics::getPosNearX(Row const & row, int & 
x,
if (w <= x &&  w + cit->width() > x) {
double x_offset = x - w;
pos = cit->x2pos(x_offset);
-   x = x_offset + w;
+   x = int(x_offset + w);
break;
}
w += cit->width();
diff --git a/src/frontends/qt4/ui/PrefLanguageUi.ui 
b/src/frontends/qt4/ui/PrefLanguageUi.ui
index 2684ee0..44f2014 100644
--- a/src/frontends/qt4/ui/PrefLanguageUi.ui
+++ b/src/frontends/qt4/ui/PrefLanguageUi.ui
@@ -305,7 +305,6 @@
   autoBeginCB
   autoEndCB
   markForeignCB
-  rtlGB
   logicalCursorRB
   visualCursorRB
 

[LyX/master] Use enum instead of int in TextMetrics::getAlign

2014-07-29 Thread Jean-Marc Lasgouttes
commit 37fd7b24ba60d9357fde0c218de051b71e222f80
Author: Jean-Marc Lasgouttes <lasgout...@lyx.org>
Date:   Tue Jul 29 11:05:14 2014 +0200

Use enum instead of int in TextMetrics::getAlign

This is just a code cleanup, no (intented) effect.

diff --git a/src/TextMetrics.cpp b/src/TextMetrics.cpp
index 2927ca8..eb71f74 100644
--- a/src/TextMetrics.cpp
+++ b/src/TextMetrics.cpp
@@ -506,11 +506,11 @@ bool TextMetrics::redoParagraph(pit_type const pit)
 }
 
 
-int TextMetrics::getAlign(Paragraph const & par, pos_type const pos) const
+LyXAlignment TextMetrics::getAlign(Paragraph const & par, pos_type const pos) 
const
 {
Layout const & layout = par.layout();
 
-   int align;
+   LyXAlignment align;
if (par.params().align() == LYX_ALIGN_LAYOUT)
align = layout.align;
else
@@ -630,6 +630,12 @@ void TextMetrics::computeRowMetrics(pit_type const pit,
row.dimension().wid = width - int(w / 2);
row.x += w / 2;
break;
+   case LYX_ALIGN_LEFT:
+   case LYX_ALIGN_NONE:
+   case LYX_ALIGN_LAYOUT:
+   case LYX_ALIGN_SPECIAL:
+   case LYX_ALIGN_DECIMAL:
+   break;
}
}
 
diff --git a/src/TextMetrics.h b/src/TextMetrics.h
index 92b1962..4e9fc0d 100644
--- a/src/TextMetrics.h
+++ b/src/TextMetrics.h
@@ -16,6 +16,7 @@
 
 #include "Font.h"
 #include "InsetList.h"
+#include "LayoutEnums.h"
 #include "ParagraphMetrics.h"
 
 #include "support/types.h"
@@ -136,7 +137,7 @@ private:
void breakRow(Row & row, int right_margin, pit_type const pit) const;
 
// Expand the alignment of paragraph \param par at position \param pos
-   int getAlign(Paragraph const & par, pos_type pos) const;
+   LyXAlignment getAlign(Paragraph const & par, pos_type pos) const;
/** this calculates the specified parameters. needed when setting
 * the cursor and when creating a visible row */
void computeRowMetrics(pit_type pit, Row & row, int width) const;


[LyX/master] Fix ticket #9276: Labeling cursor off by several characters

2014-10-09 Thread Jean-Marc Lasgouttes
commit d605048b5c3efd3088c4db31147a633284ec30c9
Author: Jean-Marc Lasgouttes <lasgout...@lyx.org>
Date:   Thu Oct 9 22:09:33 2014 +0200

Fix ticket #9276: Labeling cursor off by several characters

The length of STRING row elements is not updated until finalizeLast() is 
called.

diff --git a/src/TextMetrics.cpp b/src/TextMetrics.cpp
index eb71f74..c99517c 100644
--- a/src/TextMetrics.cpp
+++ b/src/TextMetrics.cpp
@@ -849,6 +849,8 @@ void TextMetrics::breakRow(Row & row, int const 
right_margin, pit_type const pit
// before body_pos. Instead, insert some spacing to
// align text
FontMetrics const & fm = 
theFontMetrics(text_->labelFont(par));
+   // this is needed to make sure that the row width is 
correct
+   row.finalizeLast();
int const add = max(fm.width(par.layout().labelsep),
labelEnd(pit) - row.width());
row.addSpace(i, add, *fi, par.lookupChange(i));


Re: [LyX/master] pass git commit hash within CPPFLAGS to add it to version info

2014-10-09 Thread Jean-Marc Lasgouttes

Le 28/08/2014 08:31, Stephan Witt a écrit :

commit f2aeca65b491f4a2396ec2b8834713e5c156c5ef
Author: Stephan Witt 
Date:   Thu Aug 28 08:30:45 2014 +0200

 pass git commit hash within CPPFLAGS to add it to version info


Stephan, I was about to add this to autotools and then I wonder: where 
is this used???


JMarc


diff --git a/development/LyX-Mac-binary-release.sh 
b/development/LyX-Mac-binary-release.sh
index 4fb7547..45adfd8 100644
--- a/development/LyX-Mac-binary-release.sh
+++ b/development/LyX-Mac-binary-release.sh
@@ -303,6 +303,11 @@ if [ -z "${LyXVersion}" ]; then
LyXVersion=$(grep AC_INIT "${LyxSourceDir}"/configure.ac | cut -d, -f2 | tr -d 
" ()")
  fi
  LyXVersionSuffix=${LyXVersionSuffix:-$(echo "${LyXVersion}" | cut -d. -f1-2)}
+case "${LyXVersion}" in
+*dev*)
+   LyXGitCommitHash=$(cd "${LyxSourceDir}" ; git log -1 --pretty=format:%H)
+   ;;
+esac

  LyxName="LyX"
  LyxBase="${LyxName}-${LyXVersion}"
@@ -627,6 +632,10 @@ build_lyx() {
CPPFLAGS="${SDKROOT:+-isysroot ${SDKROOT}} -arch ${arch} 
${MYCFLAGS}"
LDFLAGS="${SDKROOT:+-isysroot ${SDKROOT}} -arch ${arch} 
${MYCFLAGS}"

+   if [ -n "${LyXGitCommitHash}" ]; then
+   CPPFLAGS="${CPPFLAGS} 
-DLYX_GIT_COMMIT_HASH='${LyXGitCommitHash}'"
+   fi
+
if [ "$configure_qt_frameworks" = "yes" ]; then
export QT_CORE_CFLAGS="-FQtCore"
export QT_CORE_LIBS="-framework QtCore"





Re: [LyX/master] Some more SVG icons

2014-10-10 Thread Jean-Marc Lasgouttes

Le 10/10/2014 14:01, Juergen Spitzmueller a écrit :

commit 8e12587910195a6dbfbae2838be0c0066cf30669
Author: Juergen Spitzmueller 
Date:   Fri Oct 10 14:00:52 2014 +0200

 Some more SVG icons


Hi Juergen,

Why do we have a mix of svg and svgz files? Is that desirable?

JMarc



[LyX/master] Fix ticket #9224: text overflows through adjacent insets

2014-10-16 Thread Jean-Marc Lasgouttes
commit ac018bd8db4e81c92320fe026cceff4e9f2181d2
Author: Jean-Marc Lasgouttes <lasgout...@lyx.org>
Date:   Wed Oct 15 17:34:56 2014 +0200

Fix ticket #9224: text overflows through adjacent insets

The logic of Row::shortenIfNeeded is completely changed to look at the row 
from the start and not the end. This leads to clearer code.

diff --git a/src/Row.cpp b/src/Row.cpp
index aeede91..d1f589c 100644
--- a/src/Row.cpp
+++ b/src/Row.cpp
@@ -362,37 +362,50 @@ void Row::shortenIfNeeded(pos_type const keep, int const 
w)
if (empty() || width() <= w)
return;
 
-   /** First, we try to remove elements one by one from the end
-* until a separator is found. cit points to the first element
-* we want to remove from the row.
-*/
Elements::iterator const beg = elements_.begin();
Elements::iterator const end = elements_.end();
-   Elements::iterator cit = end;
-   Elements::iterator first_below = end;
-   int new_end = end_;
-   int new_wid = dim_.wid;
-   // if the row ends with a separator, skip it.
-   if (cit != beg && boost::prior(cit)->type == SEPARATOR && new_end > 
keep) {
-   --cit;
-   new_end = cit->pos;
-   new_wid -= cit->dim.wid;
+   Elements::iterator last_sep = elements_.end();
+   double last_width = 0;
+   double wid = x;
+
+   Elements::iterator cit = beg;
+   for ( ; cit != end ; ++cit) {
+   if (cit->type == SEPARATOR && cit->pos >= keep) {
+   last_sep = cit;
+   last_width = wid;
+   }
+   if (wid + cit->width() > w)
+   break;
+   wid += cit->width();
}
 
-   // Search for a separator where the row can be broken.
-   while (cit != beg && boost::prior(cit)->type != SEPARATOR && new_end > 
keep) {
+   if (last_sep != end) {
+   // We have found a suitable separator. This is the
+   // common case.
+   end_ = last_sep->endpos;
+   dim_.wid = last_width;
+   elements_.erase(last_sep, end);
+   return;
+   }
+
+   if (cit == end) {
+   // This should not happen since the row is too long.
+   LYXERR0("Something is wrong cannot shorten row: " << *this);
+   return;
+   }
+
+   if (cit != beg && cit->type == VIRTUAL) {
+   // It is not possible to separate a virtual element from the
+   // previous one.
--cit;
-   new_end = cit->pos;
-   new_wid -= cit->dim.wid;
-   if (new_wid < w && first_below == end)
-   first_below = cit;
+   wid -= cit->width();
}
 
if (cit != beg) {
-   // We have found a suitable separator. This is the
-   // common case.
-   end_ = new_end;
-   dim_.wid = new_wid;
+   // There is no separator, but several elements (probably
+   // insets) have been added. We can cut at this place.
+   end_ = cit->pos;
+   dim_.wid = wid;
elements_.erase(cit, end);
return;
}
@@ -402,17 +415,11 @@ void Row::shortenIfNeeded(pos_type const keep, int const 
w)
 * something: when we have one big string, maybe with some
 * other things after it.
 */
-   double max_w = w - x;
-   if (first_below->breakAt(max_w)) {
-   end_ = first_below->endpos;
-   dim_.wid = int(x + first_below->width());
+   if (cit->breakAt(w - x)) {
+   end_ = cit->endpos;
+   dim_.wid = int(x + cit->width());
// If there are other elements, they should be removed.
-   elements_.erase(boost::next(first_below), end);
-   } else if (first_below->pos > pos_) {
-   end_ = first_below->pos;
-   dim_.wid = new_wid;
-   // Remove all elements from first_below.
-   elements_.erase(first_below, end);
+   elements_.erase(boost::next(cit), end);
}
 }
 
diff --git a/src/TextMetrics.cpp b/src/TextMetrics.cpp
index c99517c..637ce1f 100644
--- a/src/TextMetrics.cpp
+++ b/src/TextMetrics.cpp
@@ -802,7 +802,9 @@ void TextMetrics::breakRow(Row & row, int const 
right_margin, pit_type const pit
int const width = max_width_ - right_margin;
pos_type const body_pos = par.beginOfBody();
row.clear();
-   row.dimension().wid = leftMargin(max_width_, pit, pos);
+   // This make get changed in computeRowMetrics depending on RTL
+   row.x = leftMargin(max_width_, pit, pos);
+   row.dimension().wid = row.x;
row.right_margin = right_margin;
 
if (pos >= end || row.width() > width) {


[LyX/master] Erase correctly math multi-cell selection

2014-10-16 Thread Jean-Marc Lasgouttes
commit f58d9f27a239db757efbab54524bd5a6bb6a1532
Author: Jean-Marc Lasgouttes <lasgout...@lyx.org>
Date:   Thu Oct 16 16:16:15 2014 +0200

Erase correctly math multi-cell selection

What a selection spans several cells in mathed, and a deletion occurs 
though LFUN_CHAR_DELETE_FORWARD for example, only the case of a proper grid was 
handled. When no such grid exists, all cells between the first and the last 
index are cleared now.

diff --git a/src/CutAndPaste.cpp b/src/CutAndPaste.cpp
index ad3ad7e..7329c24 100644
--- a/src/CutAndPaste.cpp
+++ b/src/CutAndPaste.cpp
@@ -1254,31 +1254,43 @@ void eraseSelection(Cursor & cur)
//lyxerr << "cap::eraseSelection begin: " << cur << endl;
CursorSlice const & i1 = cur.selBegin();
CursorSlice const & i2 = cur.selEnd();
-   if (i1.inset().asInsetMath()) {
-   saveSelection(cur);
-   cur.top() = i1;
-   if (i1.idx() == i2.idx()) {
-   i1.cell().erase(i1.pos(), i2.pos());
-   // We may have deleted i1.cell(cur.pos()).
-   // Make sure that pos is valid.
-   if (cur.pos() > cur.lastpos())
-   cur.pos() = cur.lastpos();
-   } else {
-   InsetMath * p = i1.asInsetMath();
-   Inset::row_type r1, r2;
-   Inset::col_type c1, c2;
-   region(i1, i2, r1, r2, c1, c2);
-   for (Inset::row_type row = r1; row <= r2; ++row)
-   for (Inset::col_type col = c1; col <= c2; ++col)
-   p->cell(p->index(row, col)).clear();
-   // We've deleted the whole cell. Only pos 0 is valid.
-   cur.pos() = 0;
-   }
-   // need a valid cursor. (Lgb)
-   cur.clearSelection();
+   if (!i1.asInsetMath()) {
+   LYXERR0("Can't erase this selection");
+   return;
+   }
+
+   saveSelection(cur);
+   cur.top() = i1;
+   InsetMath * p = i1.asInsetMath();
+   if (i1.idx() == i2.idx()) {
+   i1.cell().erase(i1.pos(), i2.pos());
+   // We may have deleted i1.cell(cur.pos()).
+   // Make sure that pos is valid.
+   if (cur.pos() > cur.lastpos())
+   cur.pos() = cur.lastpos();
+   } else if (p->nrows() > 0 && p->ncols() > 0) {
+   // This is a grid, delete a nice square region
+   Inset::row_type r1, r2;
+   Inset::col_type c1, c2;
+   region(i1, i2, r1, r2, c1, c2);
+   for (Inset::row_type row = r1; row <= r2; ++row)
+   for (Inset::col_type col = c1; col <= c2; ++col)
+   p->cell(p->index(row, col)).clear();
+   // We've deleted the whole cell. Only pos 0 is valid.
+   cur.pos() = 0;
} else {
-   lyxerr << "can't erase this selection 1" << endl;
+   Inset::idx_type idx1 = i1.idx();
+   Inset::idx_type idx2 = i2.idx();
+   if (idx1 > idx2)
+   swap(idx1, idx2);
+   for (Inset::idx_type idx = idx1 ; idx <= idx2; ++idx)
+   p->cell(idx).clear();
+   // We've deleted the whole cell. Only pos 0 is valid.
+   cur.pos() = 0;
}
+
+   // need a valid cursor. (Lgb)
+   cur.clearSelection();
//lyxerr << "cap::eraseSelection end: " << cur << endl;
 }
 


[LyX/master] Add Stéphane Mourey as contributor

2014-10-23 Thread Jean-Marc Lasgouttes
commit 3706d900374407add26cea4b53ff5ece01d0659a
Author: Jean-Marc Lasgouttes <lasgout...@lyx.org>
Date:   Thu Oct 23 15:58:41 2014 +0200

Add Stéphane Mourey as contributor

diff --git a/lib/CREDITS b/lib/CREDITS
index afa88c1..048aca4 100644
--- a/lib/CREDITS
+++ b/lib/CREDITS
@@ -336,6 +336,9 @@
 @bJoan Montané
 @iE-mail: jmontane () gmail ! com
Catalan translations of menus
+@bStéphane Mourey
+@iE-mail: stephane.mourey () impossible-exil ! info
+   New lfun server-get-statistics
 @bIñaki Larrañaga Murgoitio
 @iE-mail: dooteo () euskalgnu ! org
Basque documentation and localization
diff --git a/lib/generate_contributions.py b/lib/generate_contributions.py
index 2fc7df2..c2244a0 100755
--- a/lib/generate_contributions.py
+++ b/lib/generate_contributions.py
@@ -1219,6 +1219,14 @@ contributors = [
  "21 August 2007",
  u"Catalan translations of menus"),
 
+ contributor(u"Stéphane Mourey",
+ "stephane.mourey () impossible-exil ! info",
+ "GPL",
+ "Re: gpl",
+ "m=141381522413781",
+ "20 October 2014",
+ u"New lfun server-get-statistics"),
+
  contributor(u"Iñaki Larrañaga Murgoitio",
  "dooteo () euskalgnu ! org",
  "GPL",


[LyX/master] Add LFUN_SERVER_GET_STATISTICS command

2014-10-23 Thread Jean-Marc Lasgouttes
commit 11e679f73ecca718c61307973c3d67739354e1c7
Author: brokenclock 
Date:   Tue Oct 14 21:55:04 2014 +0200

Add LFUN_SERVER_GET_STATISTICS command

This function can be used with the LyX server to obtain the word, character 
or character+space count in the current document or selection.

diff --git a/lib/doc/LFUNs.lyx b/lib/doc/LFUNs.lyx
index b0ac9f4..0d9bb93 100644
--- a/lib/doc/LFUNs.lyx
+++ b/lib/doc/LFUNs.lyx
@@ -98,7 +98,7 @@ The LyX Team
 \end_layout
 
 \begin_layout Date
-2014-02-13
+2014-10-23
 \end_layout
 
 \begin_layout Section*
@@ -3076,6 +3076,22 @@ Origin lasgouttes, 14 Jan 2009
 \end_layout
 
 \begin_layout Subsection*
+separator-insert
+\end_layout
+\begin_layout Description
+Action Inserts an environment separator or paragraph break.
+\end_layout
+\begin_layout Description
+Syntax separator-insert []
+\end_layout
+\begin_layout Description
+Params :  default: plain
+\end_layout
+\begin_layout Description
+Origin ef, 2 May 2014
+\end_layout
+
+\begin_layout Subsection*
 set-graphics-group
 \end_layout
 \begin_layout Description
@@ -5321,6 +5337,37 @@ Syntax server-get-layout
 \end_layout
 
 \begin_layout Subsection*
+server-get-statistics
+\end_layout
+\begin_layout Description
+Action Returns the statistics (number of words and characters) in the document 
or in the given selection.
+\end_layout
+\begin_layout Description
+Notion Note that this function gives the number of words/chars written, not 
the number of characters which will be typeset.
+\end_layout
+\begin_layout Description
+Syntax server-get-statistics []
+\end_layout
+\begin_layout Description
+Params :  The requested count; if not 
specified, the three values are returned, separated by a space.
+\begin_inset Newline newline
+\end_inset
+
+words: count words.
+\begin_inset Newline newline
+\end_inset
+
+chars: count characters.
+\begin_inset Newline newline
+\end_inset
+
+chars-space: count characters and spaces.
+\end_layout
+\begin_layout Description
+Origin brokenclock, Oct 10 2014
+\end_layout
+
+\begin_layout Subsection*
 server-get-xy
 \end_layout
 \begin_layout Description
@@ -5411,7 +5458,7 @@ Origin SLior, 11 Jun 2000
 statistics
 \end_layout
 \begin_layout Description
-Action Count the statistics (number of words and characters) in the document 
or in the given selection.
+Action Count the statistics (number of words and characters) in the document 
or in the given selection and display it in a dialog box.
 \end_layout
 \begin_layout Description
 Notion Note that this function gives the number of words/chars written, not 
the number of characters which will be typeset.
diff --git a/src/FuncCode.h b/src/FuncCode.h
index 2ae820a..3bd0cd0 100644
--- a/src/FuncCode.h
+++ b/src/FuncCode.h
@@ -458,6 +458,7 @@ enum FuncCode
// 355
LFUN_SPELLING_CONTINUOUSLY, // vfr, 20130324
LFUN_SEPARATOR_INSERT,  // ef 20140502
+   LFUN_SERVER_GET_STATISTICS, // brokenclock 20141010
LFUN_LASTACTION // end of the table
 };
 
diff --git a/src/LyXAction.cpp b/src/LyXAction.cpp
index 175f68e..0efbb3c 100644
--- a/src/LyXAction.cpp
+++ b/src/LyXAction.cpp
@@ -3517,7 +3517,8 @@ void LyXAction::init()
 /*!
  * \var lyx::FuncCode lyx::LFUN_STATISTICS
  * \li Action: Count the statistics (number of words and characters)
-   in the document or in the given selection.
+   in the document or in the given selection and display it
+   in a dialog box.
  * \li Notion: Note that this function gives the number of words/chars written,
not the number of characters which will be typeset.
  * \li Syntax: statistics
@@ -3526,6 +3527,23 @@ void LyXAction::init()
  */
{ LFUN_STATISTICS, "statistics", ReadOnly, System },
 /*!
+ * \var lyx::FuncCode lyx::LFUN_SERVER_GET_STATISTICS
+ * \li Action: Returns the statistics (number of words and characters)
+   in the document or in the given selection.
+ * \li Notion: Note that this function gives the number of words/chars written,
+   not the number of characters which will be typeset.
+ * \li Syntax: server-get-statistics []
+ * \li Params: :  The requested count; if not
+   specified, the three values are returned, separated
+   by a space.\n
+words: count words.\n
+chars: count characters.\n
+chars-space: count characters and spaces.
+ * \li Origin: brokenclock, Oct 10 2014
+ * \endvar
+ */
+   { LFUN_SERVER_GET_STATISTICS, "server-get-statistics", 
ReadOnly, System },
+/*!
  * \var lyx::FuncCode lyx::LFUN_COMPLETION_INLINE
  * \li Action: Show the inline completion at the cursor position.
  * \li Syntax: completion-inline
diff --git a/src/Text3.cpp b/src/Text3.cpp
index 79711f4..6bf3bc6 100644
--- a/src/Text3.cpp
+++ b/src/Text3.cpp
@@ 

[LyX/master] Fix wrong test: boolean variable is never negative

2014-11-01 Thread Jean-Marc Lasgouttes
commit c559f85ccb3040af4117daa139a7a2c9c1f12b8a
Author: Jean-Marc Lasgouttes <lasgout...@lyx.org>
Date:   Sat Nov 1 16:02:34 2014 +0100

Fix wrong test: boolean variable is never negative

This has been spotted by clang++.

diff --git a/src/Server.cpp b/src/Server.cpp
index 1de758a..b7fa35e 100644
--- a/src/Server.cpp
+++ b/src/Server.cpp
@@ -878,7 +878,7 @@ void LyXComm::endPipe(int & fd, string const & filename, 
bool write)
   << '\n' << strerror(errno) << endl;
}
 
-   if (FileName(filename).removeFile() < 0) {
+   if (!FileName(filename).removeFile()) {
lyxerr << "LyXComm: Could not remove pipe " << filename
   << '\n' << strerror(errno) << endl;
}


Re: [LyX/master] Fix wrong test: boolean variable is never negative

2014-11-01 Thread Jean-Marc Lasgouttes

Le 01/11/2014 16:37, Jean-Marc Lasgouttes a écrit :

commit c559f85ccb3040af4117daa139a7a2c9c1f12b8a
Author: Jean-Marc Lasgouttes <lasgout...@lyx.org>
Date:   Sat Nov 1 16:02:34 2014 +0100

 Fix wrong test: boolean variable is never negative

 This has been spotted by clang++.


Richard, OK for branch?

JMarc


diff --git a/src/Server.cpp b/src/Server.cpp
index 1de758a..b7fa35e 100644
--- a/src/Server.cpp
+++ b/src/Server.cpp
@@ -878,7 +878,7 @@ void LyXComm::endPipe(int & fd, string const & filename, 
bool write)
   << '\n' << strerror(errno) << endl;
}

-   if (FileName(filename).removeFile() < 0) {
+   if (!FileName(filename).removeFile()) {
lyxerr << "LyXComm: Could not remove pipe " << filename
   << '\n' << strerror(errno) << endl;
}





[LyX/master] Reimplement inset-select-all in a generic way

2014-11-01 Thread Jean-Marc Lasgouttes
commit e52a38549328a58b6fe8efeecef21a71fb9c8d65
Author: Jean-Marc Lasgouttes <lasgout...@lyx.org>
Date:   Sun Oct 19 20:43:17 2014 +0200

Reimplement inset-select-all in a generic way

There are 3 possible actions (in order)
* select current cell
* select all calls of inset
* select the inset from outside (in the containing inset)

This fixes completely #7727.

diff --git a/src/BufferView.cpp b/src/BufferView.cpp
index faa08f0..47e6512 100644
--- a/src/BufferView.cpp
+++ b/src/BufferView.cpp
@@ -1087,6 +1087,7 @@ bool BufferView::getStatus(FuncRequest const & cmd, 
FuncStatus & flag)
case LFUN_KEYMAP_PRIMARY:
case LFUN_KEYMAP_SECONDARY:
case LFUN_KEYMAP_TOGGLE:
+   case LFUN_INSET_SELECT_ALL:
flag.setEnabled(true);
break;
 
@@ -1800,6 +1801,38 @@ void BufferView::dispatch(FuncRequest const & cmd, 
DispatchResult & dr)
}
 
 
+   case LFUN_INSET_SELECT_ALL:
+   if (cur.depth() > 1
+   && cur.selBegin().at_begin()
+   && cur.selEnd().at_end()) {
+   // All the contents of the inset if selected.
+   // Select the inset from outside.
+   cur.pop();
+   cur.resetAnchor();
+   cur.setSelection(true);
+   cur.posForward();
+   } else if (cur.selBegin().idx() != cur.selEnd().idx()
+  || (cur.selBegin().at_cell_begin()
+  && cur.selEnd().at_cell_end())) {
+   // At least one complete cell is selected.
+   // Select all cells
+   cur.pos() = 0;
+   cur.idx() = 0;
+   cur.resetAnchor();
+   cur.setSelection(true);
+   cur.idx() = cur.lastidx();
+   cur.pos() = cur.lastpos();
+   } else {
+   // select current cell
+   cur.pos() = 0;
+   cur.resetAnchor();
+   cur.setSelection(true);
+   cur.pos() = cur.lastpos();
+   }
+   dr.screenUpdate(Update::Force);
+   break;
+
+
// This would be in Buffer class if only Cursor did not
// require a bufferview
case LFUN_INSET_FORALL: {
diff --git a/src/CursorSlice.cpp b/src/CursorSlice.cpp
index 0e46c07..e7ef90e 100644
--- a/src/CursorSlice.cpp
+++ b/src/CursorSlice.cpp
@@ -158,15 +158,27 @@ void CursorSlice::backwardPos()
 }
 
 
-bool CursorSlice::at_end() const 
+bool CursorSlice::at_cell_end() const
 {
-   return idx_ == lastidx() && pit_ == lastpit() && pos_ == lastpos();
+   return pit_ == lastpit() && pos_ == lastpos();
+}
+
+
+bool CursorSlice::at_cell_begin() const
+{
+   return pit_ == 0 && pos_ == 0;
+}
+
+
+bool CursorSlice::at_end() const
+{
+   return idx_ == lastidx() && at_cell_end();
 }
 
 
 bool CursorSlice::at_begin() const
 {
-   return idx_ == 0 && pit_ == 0 && pos_ == 0;
+   return idx_ == 0 && at_cell_begin();
 }
 
 
diff --git a/src/CursorSlice.h b/src/CursorSlice.h
index 01634bd..d703cb4 100644
--- a/src/CursorSlice.h
+++ b/src/CursorSlice.h
@@ -132,6 +132,10 @@ public:
void forwardIdx();
/// move to previous cell
void backwardIdx();
+   /// are we at the end of the cell
+   bool at_cell_end() const;
+   /// are we at the start of the cell
+   bool at_cell_begin() const;
/// are we at the end of this slice
bool at_end() const;
/// are we at the start of this slice
diff --git a/src/Text3.cpp b/src/Text3.cpp
index 6bf3bc6..20885dd 100644
--- a/src/Text3.cpp
+++ b/src/Text3.cpp
@@ -599,18 +599,6 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
cur.screenUpdateFlags(Update::FitCursor);
break;
 
-   case LFUN_INSET_SELECT_ALL:
-   if (cur.depth() == 1 || !cur.selection() || 
!cur.selBegin().at_begin()
- || !cur.selEnd().at_end()) {
-   needsUpdate |= cur.selHandle(false);
-   needsUpdate |= cursorTop(cur);
-   needsUpdate |= cur.selHandle(true);
-   needsUpdate |= cursorBottom(cur);
-   } else
-   cur.undispatched();
-   cur.screenUpdateFlags(Update::FitCursor);
-   break;
-
case LFUN_CHAR_FORWARD:
case LFUN_CHAR_FORWARD_SELECT:
//LYXERR0(" LFUN_CHAR_FORWARD[SEL]:\n" << cur);
@@ -3118,7 +3106,6 @@ bool Text::getStatus(Cursor & cur, FuncRequest const & 
cmd,
case LFUN_INSET_END:
case LFUN_INSET_BEGIN_SELECT:
 

[LyX/master] Implement "callstack printing" checking for autotools

2014-11-04 Thread Jean-Marc Lasgouttes
commit dc7ef3c81ff6e906c41da5ad40117ab87ac214da
Author: Jean-Marc Lasgouttes <lasgout...@lyx.org>
Date:   Tue Nov 4 23:30:53 2014 +0100

Implement "callstack printing" checking for autotools

Contrary to cmake, we do not rely on platform/compiler check, but on the
availability of the reauired API.

diff --git a/config/lyxinclude.m4 b/config/lyxinclude.m4
index c781c1e..6b8d7a5 100644
--- a/config/lyxinclude.m4
+++ b/config/lyxinclude.m4
@@ -358,6 +358,29 @@ AC_DEFUN([LYX_USE_INCLUDED_BOOST],[
 ])
 
 
+dnl Usage: LYX_CHECK_CALLSTACK_PRINTING: define LYX_CALLSTACK_PRINTING if the
+dnlnecessary APIs are available to print callstacks.
+AC_DEFUN([LYX_CHECK_CALLSTACK_PRINTING],
+[AC_CACHE_CHECK([whether printing callstack is possible],
+   [lyx_cv_callstack_printing],
+[AC_TRY_COMPILE([
+#include 
+#include 
+], [
+   void* array[200];
+   size_t size = backtrace(array, 200);
+   backtrace_symbols(array, size);
+   int status = 0;
+   abi::__cxa_demangle("abcd", 0, 0, );
+],
+[lyx_cv_callstack_printing=yes], [lyx_cv_callstack_printing=no])])
+if test x"$lyx_cv_callstack_printing" = xyes; then
+  AC_DEFINE([LYX_CALLSTACK_PRINTING], 1,
+[Define if callstack can be printed])
+fi
+])
+
+
 dnl Usage: LYX_USE_INCLUDED_MYTHES : select if the included MyThes should
 dnlbe used.
 AC_DEFUN([LYX_USE_INCLUDED_MYTHES],[
diff --git a/configure.ac b/configure.ac
index 8539c7c..e05681c 100644
--- a/configure.ac
+++ b/configure.ac
@@ -104,6 +104,9 @@ LYX_USE_INCLUDED_MYTHES
 ### we need to know the byte order for unicode conversions
 AC_C_BIGENDIAN
 
+# Nice to have when an assertion triggers
+LYX_CHECK_CALLSTACK_PRINTING
+
 # Needed for our char_type
 AC_CHECK_SIZEOF(wchar_t)
 


[LyX/2.1.x] Fix wrong test: boolean variable is never negative

2014-11-05 Thread Jean-Marc Lasgouttes
commit 02a22417278f8dffcce65a170f87f18661df41af
Author: Jean-Marc Lasgouttes <lasgout...@lyx.org>
Date:   Sat Nov 1 16:02:34 2014 +0100

Fix wrong test: boolean variable is never negative

This has been spotted by clang++.

diff --git a/src/Server.cpp b/src/Server.cpp
index 1de758a..b7fa35e 100644
--- a/src/Server.cpp
+++ b/src/Server.cpp
@@ -878,7 +878,7 @@ void LyXComm::endPipe(int & fd, string const & filename, 
bool write)
   << '\n' << strerror(errno) << endl;
}
 
-   if (FileName(filename).removeFile() < 0) {
+   if (!FileName(filename).removeFile()) {
lyxerr << "LyXComm: Could not remove pipe " << filename
   << '\n' << strerror(errno) << endl;
}
diff --git a/status.21x b/status.21x
index 1147844..6cc1f12 100644
--- a/status.21x
+++ b/status.21x
@@ -70,7 +70,7 @@ What's new
 
 - Fix export of documents that use the LaTeX-packages mhchem and wasysym
   (bug 9266).
-  
+
 - Remove unnecessary preamble code in LaTeX export
   of documents using the class REVTeX 4.1 file (bug 4625).
 
@@ -96,6 +96,7 @@ What's new
 
 * INTERNALS
 
+- Fix wrong test in LyX server.
 
 
 * DOCUMENTATION AND LOCALIZATION


Re: [LyX/master] Fix wrong test: boolean variable is never negative

2014-11-05 Thread Jean-Marc Lasgouttes

Le 01/11/2014 19:23, Richard Heck a écrit :

On 11/01/2014 11:47 AM, Jean-Marc Lasgouttes wrote:

Le 01/11/2014 16:37, Jean-Marc Lasgouttes a écrit :

commit c559f85ccb3040af4117daa139a7a2c9c1f12b8a
Author: Jean-Marc Lasgouttes <lasgout...@lyx.org>
Date:   Sat Nov 1 16:02:34 2014 +0100

 Fix wrong test: boolean variable is never negative

 This has been spotted by clang++.


Richard, OK for branch?


Yes, sure.


Done.

JMarc



[LyX/master] Fix some glitches in inset-select-all

2014-11-14 Thread Jean-Marc Lasgouttes
commit 3cbdfa17629e4a1f78901c88231faf7e3d6470e3
Author: Jean-Marc Lasgouttes <lasgout...@lyx.org>
Date:   Fri Nov 14 10:10:29 2014 +0100

Fix some glitches in inset-select-all

Fix a crash reported in #7727. This happened because cur.pos() was reset 
before cur.pit(). In this case, cur.lastpos() will usually be wrong.

Fix bad behaviour when selecting at top level with several paragraphs.

Update documentation.

diff --git a/lib/doc/LFUNs.lyx b/lib/doc/LFUNs.lyx
index 0d9bb93..e36e00b 100644
--- a/lib/doc/LFUNs.lyx
+++ b/lib/doc/LFUNs.lyx
@@ -98,7 +98,7 @@ The LyX Team
 \end_layout
 
 \begin_layout Date
-2014-10-23
+2014-11-14
 \end_layout
 
 \begin_layout Section*
@@ -2171,13 +2171,16 @@ Sample inset-modify note Note Comment
 inset-select-all
 \end_layout
 \begin_layout Description
-Action Selects all contents of an inset.
+Action Select all contents of an inset.
+\end_layout
+\begin_layout Description
+Notion There are 3 successive levels: select current cell, select all cells of 
inset, select the inset from outside (in the enclosing inset).
 \end_layout
 \begin_layout Description
 Syntax inset-select-all
 \end_layout
 \begin_layout Description
-Origin vfr, 22 Aug 2009
+Origin vfr, 22 Aug 2009; lasgouttes 1 Nov 2014
 \end_layout
 
 \begin_layout Subsection*
@@ -3047,7 +3050,7 @@ Origin Abdel, Dec 27 2007
 section-select
 \end_layout
 \begin_layout Description
-Action Selects the whole section.
+Action Select the whole section.
 \end_layout
 \begin_layout Description
 Notion The cursor should be in a section heading before calling this lfun.
diff --git a/src/BufferView.cpp b/src/BufferView.cpp
index f404816..e982409 100644
--- a/src/BufferView.cpp
+++ b/src/BufferView.cpp
@@ -1812,24 +1812,25 @@ void BufferView::dispatch(FuncRequest const & cmd, 
DispatchResult & dr)
cur.setSelection(true);
cur.posForward();
} else if (cur.selBegin().idx() != cur.selEnd().idx()
-  || (cur.selBegin().at_cell_begin()
+  || (cur.depth() > 1
+  && cur.selBegin().at_cell_begin()
   && cur.selEnd().at_cell_end())) {
// At least one complete cell is selected.
// Select all cells
-   cur.pos() = 0;
cur.idx() = 0;
+   cur.pos() = 0;
cur.resetAnchor();
cur.setSelection(true);
cur.idx() = cur.lastidx();
cur.pos() = cur.lastpos();
} else {
// select current cell
-   cur.pos() = 0;
cur.pit() = 0;
+   cur.pos() = 0;
cur.resetAnchor();
cur.setSelection(true);
-   cur.pos() = cur.lastpos();
cur.pit() = cur.lastpit();
+   cur.pos() = cur.lastpos();
}
dr.screenUpdate(Update::Force);
break;
diff --git a/src/LyXAction.cpp b/src/LyXAction.cpp
index 0efbb3c..01ddb19 100644
--- a/src/LyXAction.cpp
+++ b/src/LyXAction.cpp
@@ -1150,16 +1150,19 @@ void LyXAction::init()
 
 /*!
  * \var lyx::FuncCode lyx::LFUN_INSET_SELECT_ALL
- * \li Action: Selects all contents of an inset.
+ * \li Action: Select all contents of an inset.
+ * \li Notion: There are 3 successive levels: select current cell,
+ *   select all cells of inset, select the inset from outside
+ *   (in the enclosing inset).
  * \li Syntax: inset-select-all
- * \li Origin: vfr, 22 Aug 2009
+ * \li Origin: vfr, 22 Aug 2009; lasgouttes 1 Nov 2014
  * \endvar
  */
{ LFUN_INSET_SELECT_ALL, "inset-select-all", ReadOnly, Edit },
 
 /*!
  * \var lyx::FuncCode lyx::LFUN_SECTION_SELECT
- * \li Action: Selects the whole section.
+ * \li Action: Select the whole section.
  * \li Notion: The cursor should be in a section heading
before calling this lfun.
  * \li Syntax: section-select


[LyX/master] Fix overflow of inset over text (see #9224)

2014-11-14 Thread Jean-Marc Lasgouttes
commit 81badf8550f2fd5e614a22261c4885d747a72106
Author: Jean-Marc Lasgouttes <lasgout...@lyx.org>
Date:   Fri Nov 14 11:13:38 2014 +0100

Fix overflow of inset over text (see #9224)

The symptoms are the same as the original #9224, but the reason is 
different. In the new code, the width of justified rows includes the 
Row::separator value. Therefore the CRC computed in 
ParagrahMetrics::computeRowSignature is not updated in some cases.

The fix is to add Row::separator as one of the elements of the row crc.

diff --git a/src/ParagraphMetrics.cpp b/src/ParagraphMetrics.cpp
index 97170bb..a911d14 100644
--- a/src/ParagraphMetrics.cpp
+++ b/src/ParagraphMetrics.cpp
@@ -97,13 +97,16 @@ size_t ParagraphMetrics::computeRowSignature(Row const & 
row,
char_type const b[] = { 
static_cast(change.type) };
// 1 byte is enough to encode Change::Type
crc.process_bytes(b, 1);
-   }   
+   }
}
 
Dimension const & d = row.dimension();
char_type const b[] = { static_cast(row.sel_beg),
-   static_cast(row.sel_end),
-   row.begin_margin_sel, row.end_margin_sel, d.wid, d.asc, d.des};
+   static_cast(row.sel_end),
+   row.begin_margin_sel,
+   row.end_margin_sel,
+   row.separator,
+   d.wid, d.asc, d.des };
crc.process_bytes(b, sizeof(b));
 
return crc.checksum();


[LyX/master] Make sure that UpdateLocker is used correctly in the future

2014-11-17 Thread Jean-Marc Lasgouttes
commit 689e54f34a4d735e6081b1b1ac8487bf028f3982
Author: Jean-Marc Lasgouttes <lasgout...@lyx.org>
Date:   Mon Nov 17 11:52:14 2014 +0100

Make sure that UpdateLocker is used correctly in the future

diff --git a/src/mathed/MathMacro.cpp b/src/mathed/MathMacro.cpp
index 941e29a..38d07e6 100644
--- a/src/mathed/MathMacro.cpp
+++ b/src/mathed/MathMacro.cpp
@@ -326,6 +326,13 @@ public:
 private:
MathMacro & mac;
 };
+/** Avoid wrong usage of UpdateLocker.
+To avoid wrong usage:
+UpdateLocker(...); // wrong
+UpdateLocker locker(...); // right
+*/
+#define UpdateLocker(x) unnamed_UpdateLocker;
+// Tip gotten from Bobby Schmidt's column in C/C++ Users Journal
 
 
 void MathMacro::updateRepresentation(Cursor * cur, MacroContext const & mc,


<    3   4   5   6   7   8   9   10   11   12   >