commit 89ce0c9069d36748bea0701c52225a32d5e5d66b
Author: Juergen Spitzmueller <[email protected]>
Date:   Mon Dec 26 14:03:48 2016 +0100

    Support for CJK quotation marks
    
    File format change
    
    Fixes: #2712
---
 development/FORMAT          |    5 ++
 lib/doc/LFUNs.lyx           |    4 +-
 lib/doc/UserGuide.lyx       |  162 +++++++++++++++++++++++++++++++++++++++++--
 lib/languages               |   38 ++++++-----
 lib/lyx2lyx/lyx_2_3.py      |  142 +++++++++++++++++++++++++++++++++++++-
 src/BufferParams.cpp        |    4 +-
 src/LyXAction.cpp           |    5 +-
 src/frontends/qt4/Menus.cpp |   18 +++++
 src/insets/InsetQuotes.cpp  |   89 +++++++++++++++++++++++-
 src/insets/InsetQuotes.h    |    4 +
 src/tex2lyx/TODO.txt        |    3 +
 src/version.h               |    4 +-
 12 files changed, 444 insertions(+), 34 deletions(-)

diff --git a/development/FORMAT b/development/FORMAT
index 68066a0..51d51bc 100644
--- a/development/FORMAT
+++ b/development/FORMAT
@@ -11,6 +11,11 @@ adjustments are made to tex2lyx and bugs are fixed in 
lyx2lyx.
 
 -----------------------
 
+2016-12-26 Jürgen Spitzmüller <[email protected]>
+       * Format incremented to 523: Implement cjk quotation marks.
+          - cjk (corner marks): \begin_inset Quotes j..
+          - cjkangle (angle brackets): \begin_inset Quotes k..
+
 2016-12-25 Jürgen Spitzmüller <[email protected]>
        * Format incremented to 522: Implement dynamic quotation marks.
           \begin_inset Quotes x..
diff --git a/lib/doc/LFUNs.lyx b/lib/doc/LFUNs.lyx
index 9e4cd6d..026513a 100644
--- a/lib/doc/LFUNs.lyx
+++ b/lib/doc/LFUNs.lyx
@@ -3446,7 +3446,7 @@ Action Inserts quotes according to the type and 
quote-language preference.
 \end_layout
 
 \begin_layout Description
-Notion Currently English, Swedish, German, Polish, French, Danish quotes are 
distinguished.
+Notion Currently 15 different quote styles are distinguished (see params).
 \end_layout
 
 \begin_layout Description
@@ -3454,7 +3454,7 @@ Syntax quote-insert [<LEVEL>] [<SIDE>] [<STYLE>]
 \end_layout
 
 \begin_layout Description
-Params <LEVEL>: 'inner' for (i.e., secondary, usually single) quotes, 
otherwise outer (i.e., primary, usually double) quotes will be used. <SIDE>:  
'opening' for opening quotes, 'closing' for closing quotes, otherwise the side 
will be guessed from the context. <STYLE>: 'british' for `British' quote style 
(with ``inner quotation'') 'danish' for >>Danish<< quote style (with >inner 
quotation<) 'english' for ``English'' quote style (with `inner quotation') 
'french' for <<french>> quote style (with ``inner quotation'') 'frenchin' for 
<<frenchin>> quote style (with <<inner quotation>>) ["in" = Imprimerie 
Nationale] 'german' for ,,German`` quote style (with ,inner quotation`) 'plain' 
for "Plain" quote style (with 'inner quotation') 'polish' for ,,Polish'' quote 
style (with ,inner quotation') 'swedish' for ''Swedish'' quote style (with 
'inner quotation') 'swedishg' for >>swedishg>> quote style (with 'inner 
quotation') ["g" = Guillemets] 'swiss' for <<Swiss>> quote style (with <inner 
quotation>) 'russian' for <<Russian>> quote style (with ,,inner quotation``) 
'dynamic' for Dynamic quotation marks which inherit the global document style 
If no quote style is specified, the document-wide will be used.
+Params <LEVEL>: 'inner' for (i.e., secondary, usually single) quotes, 
otherwise outer (i.e., primary, usually double) quotes will be used. <SIDE>:  
'opening' for opening quotes, 'closing' for closing quotes, otherwise the side 
will be guessed from the context. <STYLE>: 'british' for `British' quote style 
(with ``inner quotation'') 'cjk' for Chinese/Japanese/Korean corner bracket 
quotation marks 'cjk-angle' for Chinese/Japanese/Korean angle bracket quotation 
marks 'danish' for >>Danish<< quote style (with >inner quotation<) 'english' 
for ``English'' quote style (with `inner quotation') 'french' for <<french>> 
quote style (with ``inner quotation'') 'frenchin' for <<frenchin>> quote style 
(with <<inner quotation>>) ["in" = Imprimerie Nationale] 'german' for 
,,German`` quote style (with ,inner quotation`) 'plain' for "Plain" quote style 
(with 'inner quotation') 'polish' for ,,Polish'' quote style (with ,inner 
quotation') 'swedish' for ''Swedish'' quote style (with 'inner quotation') 
'swedishg' for >>swedishg>> quote style (with 'inner quotation') ["g" = 
Guillemets] 'swiss' for <<Swiss>> quote style (with <inner quotation>) 
'russian' for <<Russian>> quote style (with ,,inner quotation``) 'dynamic' for 
Dynamic quotation marks which inherit the global document style If no quote 
style is specified, the document-wide will be used.
 \end_layout
 
 \begin_layout Subsection*
diff --git a/lib/doc/UserGuide.lyx b/lib/doc/UserGuide.lyx
index 5625dec..3b71940 100644
--- a/lib/doc/UserGuide.lyx
+++ b/lib/doc/UserGuide.lyx
@@ -1,5 +1,5 @@
 #LyX 2.3 created this file. For more info see http://www.lyx.org/
-\lyxformat 522
+\lyxformat 523
 \begin_document
 \begin_header
 \save_transient_properties true
@@ -101,7 +101,7 @@ enumitem
 \use_package mathtools 0
 \use_package mhchem 1
 \use_package stackrel 0
-\use_package stmaryrd 0
+\use_package stmaryrd 1
 \use_package undertilde 0
 \cite_engine basic
 \cite_engine_type default
@@ -17086,8 +17086,8 @@ Quote Style
  There are 
 \change_deleted -712698321 1482666221
 six
-\change_inserted -712698321 1482666222
-twelve
+\change_inserted -712698321 1482756786
+14
 \change_unchanged
  choices:
 \end_layout
@@ -17851,7 +17851,7 @@ g., in Russia)
 \begin_layout Labeling
 \labelwidthstring <<Outer>> and <<inner>>:
 
-\change_inserted -712698321 1482666852
+\change_inserted -712698321 1482756796
 
 \family sans
 \begin_inset Quotes wld
@@ -17896,6 +17896,158 @@ these inner
 \end_inset
 
  quotation marks (another style common in Sweden)
+\end_layout
+
+\begin_layout Labeling
+\labelwidthstring <<Outer>> and <<inner>>:
+
+\change_inserted -712698321 1482757086
+\begin_inset Quotes jld
+\end_inset
+
+
+\family sans
+Outer
+\family default
+
+\begin_inset Quotes jrd
+\end_inset
+
+
+\family sans
+
+\begin_inset space ~
+\end_inset
+
+and
+\begin_inset space ~
+\end_inset
+
+
+\family default
+
+\begin_inset Quotes jls
+\end_inset
+
+
+\family sans
+inner
+\family default
+
+\begin_inset Quotes jrs
+\end_inset
+
+ Produces 
+\begin_inset Quotes jld
+\end_inset
+
+these outer
+\begin_inset Quotes jrd
+\end_inset
+
+ and 
+\begin_inset Quotes jls
+\end_inset
+
+these inner
+\begin_inset Quotes jrs
+\end_inset
+
+ quotation marks (as common, e.
+\begin_inset space \thinspace{}
+\end_inset
+
+g., in Japan)
+\begin_inset Foot
+status collapsed
+
+\begin_layout Plain Layout
+
+\change_inserted -712698321 1482757158
+Note that these characters are just emulated with similar-looking math symbols
+ in many encodings that do not cover these glyphs.
+\change_unchanged
+
+\end_layout
+
+\end_inset
+
+
+\end_layout
+
+\begin_layout Labeling
+\labelwidthstring <<Outer>> and <<inner>>:
+
+\change_inserted -712698321 1482757171
+\begin_inset Quotes kld
+\end_inset
+
+
+\family sans
+Outer
+\family default
+
+\begin_inset Quotes krd
+\end_inset
+
+
+\family sans
+
+\begin_inset space ~
+\end_inset
+
+and
+\begin_inset space ~
+\end_inset
+
+
+\family default
+
+\begin_inset Quotes kls
+\end_inset
+
+
+\family sans
+inner
+\family default
+
+\begin_inset Quotes krs
+\end_inset
+
+ Produces 
+\begin_inset Quotes kld
+\end_inset
+
+these outer
+\begin_inset Quotes krd
+\end_inset
+
+ and 
+\begin_inset Quotes kls
+\end_inset
+
+these inner
+\begin_inset Quotes krs
+\end_inset
+
+ quotation marks (as common, e.
+\begin_inset space \thinspace{}
+\end_inset
+
+g., in North Korea and China)
+\begin_inset Foot
+status collapsed
+
+\begin_layout Plain Layout
+
+\change_inserted -712698321 1482757171
+Note that these characters are just emulated with similar-looking math symbols
+ in many encodings that do not cover these glyphs.
+\end_layout
+
+\end_inset
+
+
 \change_unchanged
 
 \end_layout
diff --git a/lib/languages b/lib/languages
index 3a0b6ad..8ec526e 100644
--- a/lib/languages
+++ b/lib/languages
@@ -44,19 +44,21 @@
 #   (UK) -- try to select the entry that is most generic -- here
 #   English.
 # * The QuoteStyle arguments correspond to the following styles:
-#              PRIMARY         SECONDARY
-#   - british: `text'          ``text''        (6_9 -- 66_99)
-#   - danish:  >>text<<        >text<          (inward guillemets)
-#   - english: ``text''        `text'          (66_99 -- 6_9)
-#   - french:  <<text>>        ``text''        (outward guillemets -- 66_99)
-#   - frenchin: <<text>>       <<text>>        (French Imprimerie Nationale 
style)
-#   - german:  ,,text``        ,text`          (99/66 -- 9/6)
-#   - polish:  ,,text''        ,text'          (99/99 -- 9/9)
-#   - russian:  <<text>>        ,,text``       (outward guillemets -- 99/66)
-#   - swedish: ''text''        'text'          (99_99 -- 9_9)
-#   - swedishg: >>text>>       'text'          (Swedish Guillemets)
-#   - swiss:   <<text>>        <text>          (outward guillemets)
-#   - plain:   "text"          'text'          (non-typographical quotes)
+#                 PRIMARY              SECONDARY
+#   - british:   `text'                ``text''        (6_9 -- 66_99)
+#   - cjk:        corner brackets      white corner br.
+#   - cjk-angle:  double angle br.     angle br.
+#   - danish:    >>text<<              >text<          (inward guillemets)
+#   - english:   ``text''              `text'          (66_99 -- 6_9)
+#   - french:    <<text>>              ``text''        (outward guillemets -- 
66_99)
+#   - frenchin:   <<text>>             <<text>>        (French Imprimerie 
Nationale style)
+#   - german:    ,,text``              ,text`          (99/66 -- 9/6)
+#   - polish:    ,,text''              ,text'          (99/99 -- 9/9)
+#   - russian:    <<text>>             ,,text``        (outward guillemets -- 
99/66)
+#   - swedish:   ''text''              'text'          (99_99 -- 9_9)
+#   - swedishg:   >>text>>             'text'          (Swedish Guillemets)
+#   - swiss:     <<text>>              <text>          (outward guillemets)
+#   - plain:     "text"                'text'          (non-typographical 
quotes)
 #   Note that the option names have been selected (rather arbitrarily)
 #   because the respective styles are common in the respective countries.
 #   Of course this does not imply any fixed relation to those countries.
@@ -381,9 +383,9 @@ End
 Language chinese-traditional
        GuiName         "Chinese (traditional)"
        HasGuiSupport    true
-       QuoteStyle       english
-       Encoding        utf8-cjk
-       LangCode        zh_TW
+       QuoteStyle       cjk
+       Encoding         utf8-cjk
+       LangCode         zh_TW
        Requires         CJK
 End
 
@@ -718,6 +720,7 @@ Language japanese
        Requires         japanese
        InternalEncoding true
        FontEncoding     None
+       QuoteStyle       cjk
 End
 
 # uses CJK package
@@ -726,6 +729,7 @@ Language japanese-cjk
        Encoding        euc-jp
        LangCode        ja_JP
        Requires        CJK
+       QuoteStyle      cjk
 End
 
 # not supported by babel
@@ -759,7 +763,7 @@ End
 Language korean
        GuiName         "Korean"
        Encoding        euc-kr
-       QuoteStyle      english
+       QuoteStyle      cjkangle
        LangCode        ko_KR
        Requires        CJK
 End
diff --git a/lib/lyx2lyx/lyx_2_3.py b/lib/lyx2lyx/lyx_2_3.py
index 5351800..20bfde9 100644
--- a/lib/lyx2lyx/lyx_2_3.py
+++ b/lib/lyx2lyx/lyx_2_3.py
@@ -753,7 +753,7 @@ def revert_britishquotes(document):
             # opening mark
             newval = newval.replace("d", "s")
         else:
-            # inner marks
+            # closing mark
             newval = newval.replace("s", "d")
         document.body[i] = document.body[i].replace(val, newval)
         i += 1
@@ -865,7 +865,7 @@ def revert_dynamicquotes(document):
     else:
         style = get_value(document.header, "\\quotes_style", i)
 
-    s = ""
+    s = "e"
     if style == "english":
         s = "e"
     elif style == "swedish":
@@ -901,6 +901,140 @@ def revert_dynamicquotes(document):
         i += 1
 
 
+def revert_cjkquotes(document):
+    " Revert cjk quote insets "
+
+    # Get global style
+    style = "english"
+    i = find_token(document.header, "\\quotes_style", 0)
+    if i == -1:
+        document.warning("Malformed document! Missing \\quotes_style")
+    else:
+        style = get_value(document.header, "\\quotes_style", i)
+
+    global_cjk = style.find("cjk") != -1
+
+    if global_cjk:
+        document.header[i] = "\\quotes_style english"
+        # transform dynamic insets
+        s = "j"
+        if style == "cjkangle":
+            s = "k"
+        i = 0
+        while True:
+            i = find_token(document.body, '\\begin_inset Quotes x', i)
+            if i == -1:
+                break
+            document.body[i] = document.body[i].replace("x", s)
+            i += 1
+
+    cjk_langs = ["chinese-simplified", "chinese-traditional", "japanese", 
"japanese-cjk", "korean"]
+
+    i = 0
+    j = 0
+    while True:
+        k = find_token(document.body, '\\begin_inset Quotes j', i)
+        if k == -1:
+            break
+        l = find_end_of_inset(document.body, k)
+        if l == -1:
+            document.warning("Malformed LyX document: Can't find end of Quote 
inset at line " + str(k))
+            i = k
+            continue
+        cjk = False
+        parent = get_containing_layout(document.body, k)
+        ql = find_token_backwards(document.body, "\\lang", k)
+        if ql == -1 or ql < parent[1]:
+            cjk = document.language in cjk_langs
+        elif document.body[ql].split()[1] in cjk_langs:
+            cjk = True
+        val = get_value(document.body, "\\begin_inset Quotes", i)[7:]
+        replace = []
+        if val[2] == "s":
+            # inner marks
+            if val[1] == "l":
+                # inner opening mark
+                if cjk:
+                    replace = [u"\u300E"]
+                else:
+                    replace = ["\\begin_inset Formula $\\llceil$", 
"\\end_inset"]
+            else:
+                # inner closing mark
+                if cjk:
+                    replace = [u"\u300F"]
+                else:
+                    replace = ["\\begin_inset Formula $\\rrfloor$", 
"\\end_inset"]
+        else:
+            # outer marks
+            if val[1] == "l":
+                # outer opening mark
+                if cjk:
+                    replace = [u"\u300C"]
+                else:
+                    replace = ["\\begin_inset Formula $\\lceil$", 
"\\end_inset"]
+            else:
+                # outer closing mark
+                if cjk:
+                    replace = [u"\u300D"]
+                else:
+                    replace = ["\\begin_inset Formula $\\rfloor$", 
"\\end_inset"]
+
+        document.body[k:l+1] = replace
+        i = l
+
+    i = 0
+    j = 0
+    while True:
+        k = find_token(document.body, '\\begin_inset Quotes k', i)
+        if k == -1:
+            return
+        l = find_end_of_inset(document.body, k)
+        if l == -1:
+            document.warning("Malformed LyX document: Can't find end of Quote 
inset at line " + str(k))
+            i = k
+            continue
+        cjk = False
+        parent = get_containing_layout(document.body, k)
+        ql = find_token_backwards(document.body, "\\lang", k)
+        if ql == -1 or ql < parent[1]:
+            cjk = document.language in cjk_langs
+        elif document.body[ql].split()[1] in cjk_langs:
+            cjk = True
+        val = get_value(document.body, "\\begin_inset Quotes", i)[7:]
+        replace = []
+        if val[2] == "s":
+            # inner marks
+            if val[1] == "l":
+                # inner opening mark
+                if cjk:
+                    replace = [u"\u3008"]
+                else:
+                    replace = ["\\begin_inset Formula $\\langle$", 
"\\end_inset"]
+            else:
+                # inner closing mark
+                if cjk:
+                    replace = [u"\u3009"]
+                else:
+                    replace = ["\\begin_inset Formula $\\rangle$", 
"\\end_inset"]
+        else:
+            # outer marks
+            if val[1] == "l":
+                # outer opening mark
+                if cjk:
+                    replace = [u"\u300A"]
+                else:
+                    replace = ["\\begin_inset Formula $\\langle\\kern 
-2.5pt\\langle$$", "\\end_inset"]
+            else:
+                # outer closing mark
+                if cjk:
+                    replace = [u"\u300B"]
+                else:
+                    replace = ["\\begin_inset Formula $\\rangle\\kern 
-2.5pt\\rangle$", "\\end_inset"]
+
+        document.body[k:l+1] = replace
+        i = l
+
+
 ##
 # Conversion hub
 #
@@ -920,10 +1054,12 @@ convert = [
            [519, [convert_quotestyle]],
            [520, []],
            [521, [convert_frenchquotes]],
-           [522, []]
+           [522, []],
+           [523, []]
           ]
 
 revert =  [
+           [522, [revert_cjkquotes]],
            [521, [revert_dynamicquotes]],
            [520, [revert_britishquotes, revert_swedishgquotes, 
revert_frenchquotes, revert_frenchinquotes, revert_russianquotes, 
revert_swissquotes]],
            [519, [revert_plainquote]],
diff --git a/src/BufferParams.cpp b/src/BufferParams.cpp
index c48e1cf..fa0b7c3 100644
--- a/src/BufferParams.cpp
+++ b/src/BufferParams.cpp
@@ -73,7 +73,7 @@ static char const * const string_paragraph_separation[] = {
 
 static char const * const string_quotes_style[] = {
        "english", "swedish", "german", "polish", "swiss", "danish", "plain",
-       "british", "swedishg", "french", "frenchin", "russian", ""
+       "british", "swedishg", "french", "frenchin", "russian", "cjk", 
"cjkangle", ""
 };
 
 
@@ -147,6 +147,8 @@ QuotesStyleTranslator const init_quotesstyletranslator()
        translator.addPair(string_quotes_style[9], 
InsetQuotesParams::FrenchQuotes);
        translator.addPair(string_quotes_style[10], 
InsetQuotesParams::FrenchINQuotes);
        translator.addPair(string_quotes_style[11], 
InsetQuotesParams::RussianQuotes);
+       translator.addPair(string_quotes_style[12], 
InsetQuotesParams::CJKQuotes);
+       translator.addPair(string_quotes_style[13], 
InsetQuotesParams::CJKAngleQuotes);
        return translator;
 }
 
diff --git a/src/LyXAction.cpp b/src/LyXAction.cpp
index a522c17..b6b6675 100644
--- a/src/LyXAction.cpp
+++ b/src/LyXAction.cpp
@@ -401,14 +401,15 @@ void LyXAction::init()
 /*!
  * \var lyx::FuncCode lyx::LFUN_QUOTE_INSERT
  * \li Action: Inserts quotes according to the type and quote-language 
preference.
- * \li Notion: Currently English, Swedish, German, Polish, French, Danish 
quotes
-               are distinguished.
+ * \li Notion: Currently 15 different quote styles are distinguished (see 
params).
  * \li Syntax: quote-insert [<LEVEL>] [<SIDE>] [<STYLE>]
  * \li Params: <LEVEL>: 'inner' for (i.e., secondary, usually single) quotes, 
otherwise
  *                       outer (i.e., primary, usually double) quotes will be 
used.
  *             <SIDE>:  'opening' for opening quotes, 'closing' for closing 
quotes,
  *                       otherwise the side will be guessed from the context.
  *             <STYLE>: 'british' for `British' quote style (with ``inner 
quotation'')
+ *                      'cjk' for Chinese/Japanese/Korean corner bracket 
quotation marks
+ *                      'cjk-angle' for Chinese/Japanese/Korean angle bracket 
quotation marks
  *                      'danish' for >>Danish<< quote style (with >inner 
quotation<)
  *                      'english' for ``English'' quote style (with `inner 
quotation')
  *                      'french' for <<french>> quote style (with ``inner 
quotation'')
diff --git a/src/frontends/qt4/Menus.cpp b/src/frontends/qt4/Menus.cpp
index 1119cc3..81ce576 100644
--- a/src/frontends/qt4/Menus.cpp
+++ b/src/frontends/qt4/Menus.cpp
@@ -1687,6 +1687,8 @@ void MenuDefinition::expandQuotes(BufferView const * bv)
        MenuDefinition fqs;
        MenuDefinition iqs;
        MenuDefinition rqs;
+       MenuDefinition jqs;
+       MenuDefinition kqs;
        MenuDefinition xqs;
        InsetQuotesParams::QuoteStyle globalqs =
                        bv->buffer().masterBuffer()->params().quotes_style;
@@ -1758,6 +1760,10 @@ void MenuDefinition::expandQuotes(BufferView const * bv)
                        iqs.add(MenuItem(MenuItem::Command, toqstr(desc), cmd));
                else if (prefixIs(style, 'r') && !prefixIs(qtype, "r"))
                        rqs.add(MenuItem(MenuItem::Command, toqstr(desc), cmd));
+               else if (prefixIs(style, 'j') && !prefixIs(qtype, "j"))
+                       jqs.add(MenuItem(MenuItem::Command, toqstr(desc), cmd));
+               else if (prefixIs(style, 'k') && !prefixIs(qtype, "k"))
+                       kqs.add(MenuItem(MenuItem::Command, toqstr(desc), cmd));
        }
 
        if (!xqs.empty()) {
@@ -1837,6 +1843,18 @@ void MenuDefinition::expandQuotes(BufferView const * bv)
                item.setSubmenu(rqs);
                add(item);
        }
+       if (!jqs.empty()) {
+               MenuItem item(MenuItem::Submenu,
+                             
toqstr(quoteparams.getGuiLabel(InsetQuotesParams::CJKQuotes)));
+               item.setSubmenu(jqs);
+               add(item);
+       }
+       if (!kqs.empty()) {
+               MenuItem item(MenuItem::Submenu,
+                             
toqstr(quoteparams.getGuiLabel(InsetQuotesParams::CJKAngleQuotes)));
+               item.setSubmenu(kqs);
+               add(item);
+       }
 }
 
 
diff --git a/src/insets/InsetQuotes.cpp b/src/insets/InsetQuotes.cpp
index 06df769..bc5d6d5 100644
--- a/src/insets/InsetQuotes.cpp
+++ b/src/insets/InsetQuotes.cpp
@@ -18,6 +18,7 @@
 #include "BufferView.h"
 #include "Cursor.h"
 #include "Dimension.h"
+#include "Encoding.h"
 #include "Font.h"
 #include "FuncStatus.h"
 #include "FuncRequest.h"
@@ -64,10 +65,12 @@ namespace {
  * f    <<french>>   (``inner quotation'')
  * i    <<frenchin>> (<<inner quotation>>) ["in" = Imprimerie Nationale]
  * r    <<russian>>  (,,inner quotation``)
+ * j    [U+300C]cjk[U+300D]  ([U+300E]inner quotation[U+300F]) [CORNER 
BRACKETS]
+ * k    [U+300A]cjkangle[U+300B]  ([U+3008]inner quotation[U+3009]) [ANGLE 
BRACKETS]
  * x    dynamic style (inherits document settings)
  */
 
-char const * const style_char = "esgpcaqbwfirx";
+char const * const style_char = "esgpcaqbwfirjkx";
 char const * const side_char = "lr" ;
 char const * const level_char = "sd";
 
@@ -186,6 +189,20 @@ char_type InsetQuotesParams::getQuoteChar(QuoteStyle const 
& style, QuoteLevel c
                right_secondary = 0x201c; // ``
                break;
        }
+       case CJKQuotes:{
+               left_primary = 0x300c; // LEFT CORNER BRACKET
+               right_primary = 0x300d; // RIGHT CORNER BRACKET
+               left_secondary =  0x300e; // LEFT WHITE CORNER BRACKET
+               right_secondary = 0x300f; // RIGHT WHITE CORNER BRACKET
+               break;
+       }
+       case CJKAngleQuotes:{
+               left_primary = 0x300a; // LEFT DOUBLE ANGLE BRACKET
+               right_primary = 0x300b; // RIGHT DOUBLE ANGLE BRACKET
+               left_secondary =  0x3008; // LEFT ANGLE BRACKET
+               right_secondary = 0x3009; // RIGHT ANGLE BRACKET
+               break;
+       }
        case DynamicQuotes:
        default:
                // should not happen
@@ -299,6 +316,33 @@ docstring InsetQuotesParams::getLaTeXQuote(char_type c, 
string const & op) const
                res = "\\textquotedbl";
                break;
        }
+       // The following are fakes
+       // This is just to get something symbolic
+       // in encodings where this chars would not be used ayway
+       case 0x300c: // LEFT CORNER BRACKET
+               res = "\\ensuremath{\\lceil}";
+               break;
+       case 0x300d: // RIGHT CORNER BRACKET
+               res = "\\ensuremath{\\rfloor}";
+               break;
+       case 0x300e: // LEFT WHITE CORNER BRACKET
+               res = "\\ensuremath{\\llceil}";
+               break;
+       case 0x300f: // RIGHT WHITE CORNER BRACKET
+               res = "\\ensuremath{\\rrfloor}";
+               break;
+       case 0x300a: // LEFT DOUBLE ANGLE BRACKET
+               res = "\\ensuremath{\\langle\\kern-2.5pt\\langle}";
+               break;
+       case 0x300b: // RIGHT DOUBLE ANGLE BRACKET
+               res = "\\ensuremath{\\rangle\\kern-2.5pt\\rangle}";
+               break;
+       case 0x3008: // LEFT ANGLE BRACKET
+               res = "\\ensuremath{\\langle}";
+               break;
+       case 0x3009: // RIGHT ANGLE BRACKET
+               res = "\\ensuremath{\\rangle}";
+               break;
        default:
                break;
        }
@@ -348,6 +392,30 @@ docstring InsetQuotesParams::getHTMLQuote(char_type c) 
const
        case 0x0022: // "
                res = "&quot;";
                break;
+       case 0x300c: // LEFT CORNER BRACKET
+               res = "&#x300c;";
+               break;
+       case 0x300d: // RIGHT CORNER BRACKET
+               res = "&#x300d;";
+               break;
+       case 0x300e: // LEFT WHITE CORNER BRACKET
+               res = "&#x300e;";
+               break;
+       case 0x300f: // RIGHT WHITE CORNER BRACKET
+               res = "&#x300f;";
+               break;
+       case 0x300a: // LEFT DOUBLE ANGLE BRACKET
+               res = "&#x300a;";
+               break;
+       case 0x300b: // RIGHT DOUBLE ANGLE BRACKET
+               res = "&#x300b;";
+               break;
+       case 0x3008: // LEFT ANGLE BRACKET
+               res = "&#x3008;";
+               break;
+       case 0x3009: // RIGHT ANGLE BRACKET
+               res = "&#x3009;";
+               break;
        default:
                break;
        }
@@ -550,6 +618,10 @@ InsetQuotesParams::QuoteStyle InsetQuotes::getStyle(string 
const & s)
                qs = InsetQuotesParams::FrenchINQuotes;
        else if (s == "russian")
                qs = InsetQuotesParams::RussianQuotes;
+       else if (s == "cjk")
+               qs = InsetQuotesParams::CJKQuotes;
+       else if (s == "cjkangle")
+               qs = InsetQuotesParams::CJKAngleQuotes;
        else if (s == "dynamic")
                qs = InsetQuotesParams::DynamicQuotes;
 
@@ -700,6 +772,12 @@ void InsetQuotes::latex(otexstream & os, OutputParams 
const & runparams) const
                // (spacing and kerning is then handled respectively)
                qstr = docstring(1, quotechar);
        }
+       else if (style == InsetQuotesParams::CJKQuotes || style  == 
InsetQuotesParams::CJKAngleQuotes) {
+               if (runparams.encoding && 
runparams.encoding->encodable(quotechar))
+                       qstr = docstring(1, quotechar);
+               else
+                       qstr = quoteparams.getLaTeXQuote(quotechar, "int");
+       }
        else if ((style == InsetQuotesParams::SwissQuotes
                 || style == InsetQuotesParams::FrenchQuotes
                 || style == InsetQuotesParams::FrenchINQuotes)
@@ -750,7 +828,7 @@ void InsetQuotes::latex(otexstream & os, OutputParams const 
& runparams) const
 
        os << qstr;
 
-       if (prefixIs(qstr, from_ascii("\\")))
+       if (prefixIs(qstr, from_ascii("\\")) && !suffixIs(qstr, '}'))
                // properly terminate the command depending on the context
                os << termcmd;
 }
@@ -876,6 +954,13 @@ void InsetQuotes::validate(LaTeXFeatures & features) const
                        features.require("textquotedbl");
                break;
        }
+       // we fake these from math
+       case 0x300e: // LEFT WHITE CORNER BRACKET
+       case 0x300f: // RIGHT WHITE CORNER BRACKET
+               if (!features.runparams().encoding
+                   || !features.runparams().encoding->encodable(type))
+                       features.require("stmaryrd");
+               break;
        default:
                break;
        }
diff --git a/src/insets/InsetQuotes.h b/src/insets/InsetQuotes.h
index 9b19a84..0a7c20f 100644
--- a/src/insets/InsetQuotes.h
+++ b/src/insets/InsetQuotes.h
@@ -52,6 +52,10 @@ public:
                ///
                RussianQuotes,
                ///
+               CJKQuotes,
+               ///
+               CJKAngleQuotes,
+               ///
                DynamicQuotes
        };
        ///
diff --git a/src/tex2lyx/TODO.txt b/src/tex2lyx/TODO.txt
index e5e0433..aaf647d 100644
--- a/src/tex2lyx/TODO.txt
+++ b/src/tex2lyx/TODO.txt
@@ -97,6 +97,9 @@ Format LaTeX feature                        LyX feature
        - Inner quotes are now ``..''.
        - Former french style is now
          called "swiss"
+523    CJK Quote Styles                      InsetQuote
+       - cjk (corner brackets)               \begin_inset Quotes j..
+       - cjkangle (angle brackets)           \begin_inset Quotes k..
 
 General
 
diff --git a/src/version.h b/src/version.h
index 3421616..d62781f 100644
--- a/src/version.h
+++ b/src/version.h
@@ -32,8 +32,8 @@ extern char const * const lyx_version_info;
 
 // Do not remove the comment below, so we get merge conflict in
 // independent branches. Instead add your own.
-#define LYX_FORMAT_LYX 522 // spitz: dynamic quotes styles
-#define LYX_FORMAT_TEX2LYX 522
+#define LYX_FORMAT_LYX 523 // spitz: cjk quotes styles
+#define LYX_FORMAT_TEX2LYX 523
 
 #if LYX_FORMAT_TEX2LYX != LYX_FORMAT_LYX
 #ifndef _MSC_VER

Reply via email to