]> git.lyx.org Git - lyx.git/blob - src/mathed/MathClass.cpp
Linearize macros in box edit mode too.
[lyx.git] / src / mathed / MathClass.cpp
1 /**
2  * \file MathClass.cpp
3  * This file is part of LyX, the document processor.
4  * Licence details can be found in the file COPYING.
5  *
6  * \author Jean-Marc Lasgouttes
7  *
8  * Full author contact details are available in file CREDITS.
9  */
10
11 #include <config.h>
12
13 #include "MathClass.h"
14 #include "MathSupport.h"
15
16 #include "MetricsInfo.h"
17 #include "FontInfo.h"
18
19 #include "support/debug.h"
20 #include "support/docstring.h"
21 #include "support/lassert.h"
22
23 #include <ostream>
24
25 using namespace std;
26
27 namespace lyx {
28
29
30 docstring const class_to_string(MathClass const mc)
31 {
32         string s;
33         switch (mc) {
34         case MC_ORD:
35                 s = "mathord";
36                 break;
37         case MC_OP:
38                 s = "mathop";
39                 break;
40         case MC_BIN:
41                 s = "mathbin";
42                 break;
43         case MC_REL:
44                 s = "mathrel";
45                 break;
46         case MC_OPEN:
47                 s = "mathopen";
48                 break;
49         case MC_CLOSE:
50                 s = "mathclose";
51                 break;
52         case MC_PUNCT:
53                 s = "mathpunct";
54                 break;
55         case MC_INNER:
56                 s = "mathinner";
57                 break;
58         case MC_UNKNOWN:
59                 LATTEST(false);
60                 s = "mathord";
61         }
62         return from_ascii(s);
63 }
64
65
66 MathClass string_to_class(docstring const &s)
67 {
68         if (s  == "mathop")
69                 return MC_OP;
70         else if (s  == "mathbin")
71                 return MC_BIN;
72         else if (s  == "mathrel")
73                 return MC_REL;
74         else if (s  == "mathopen")
75                 return MC_OPEN;
76         else if (s  == "mathclose")
77                 return MC_CLOSE;
78         else if (s  == "mathpunct")
79                 return MC_PUNCT;
80         else if (s  == "mathinner")
81                 return MC_INNER;
82         else  if (s  == "mathord")
83                 return MC_ORD;
84         else
85                 return MC_UNKNOWN;
86 }
87
88
89 /*
90  * The TeXbook presents in Appendix G a set of 22 rules (!) explaining
91  * how to typeset mathematic formulas. Of interest here are rules 5
92  * and 6:
93
94  * 5. If the current item is a Bin atom, and if this was the first
95  *    atom in the list, or if the most recent previous atom was Bin,
96  *    Op, Rel, Open, or Punct, change the current Bin to Ord [and
97  *    continue with Rule 14. Otherwise continue with Rule 17]
98  *
99  * 6. If the current item is a Rel or Close or Punct atom, and if the
100  *    most recent previous atom was Bin, change that previous Bin to
101  *    Ord. [Continue with Rule 17.]
102  */
103 void update_class(MathClass & mc, MathClass const prev, MathClass const next)
104 {
105         if (mc == MC_BIN
106                 && (prev == MC_BIN || prev == MC_OP || prev == MC_OPEN
107                         || prev == MC_PUNCT || prev == MC_REL
108                         || next == MC_CLOSE || next == MC_PUNCT || next == MC_REL))
109                 mc = MC_ORD;
110 }
111
112
113 /*
114  * This table of spacing between two classes can be found p. 170 of
115  * The TeXbook.
116  *
117  * The line is the class of the first class, and the column the second
118  * class. The number encodes the spacing between the two atoms, as
119  * follows
120  *
121  * + 0: no spacing
122  * + 1: thin mu skip
123  * + 2: med mu skip
124  * + 3: thick mu skip
125  * + 9: should never happen
126  * + negative value: either 0 if the atom is in script or scriptscript mode,
127  *   or the spacing given by the absolute value.
128  */
129 int pair_spc[MC_UNKNOWN][MC_UNKNOWN] = {
130 //       ORD    OP   BIN   REL  OPEN CLOSE PUNCT INNER
131         {  0,    1,   -2,   -3,    0,    0,    0,   -1}, // ORD
132         {  1,    1,    9,   -3,    0,    0,    0,   -1}, // OP
133         { -2,   -2,    9,    9,   -2,    9,    9,   -2}, // BIN
134         { -3,   -3,    9,    0,   -3,    0,    0,   -3}, // REL
135         {  0,    0,    9,    0,    0,    0,    0,    0}, // OPEN
136         {  0,    1,   -2,   -3,    0,    0,    0,   -1}, // CLOSE
137         { -1,   -1,    9,   -1,   -1,   -1,   -1,   -1}, // PUNCT
138         { -1,    1,   -2,   -3,   -1,    0,   -1,   -1}, // INNER
139 };
140
141
142 int class_spacing(MathClass const mc1, MathClass const mc2,
143                   MetricsBase const & mb)
144 {
145         int spc_code = pair_spc[mc1][mc2];
146         //lyxerr << class_to_string(mc1) << "+" << class_to_string(mc2)
147         //         << "=" << spc_code << " @" << mb.style << endl;
148         if (spc_code < 0) {
149                 switch (mb.font.style()) {
150                 case LM_ST_DISPLAY:
151                 case LM_ST_TEXT:
152                         spc_code = abs(spc_code);
153                         break;
154                 case LM_ST_SCRIPT:
155                 case LM_ST_SCRIPTSCRIPT:
156                         spc_code = 0;
157                 }
158         }
159
160         int spc = 0;
161         switch(spc_code) {
162         case 0:
163                 break;
164         case 1:
165                 spc = mathed_thinmuskip(mb.font);
166                 break;
167         case 2:
168                 spc = mathed_medmuskip(mb.font);
169                 break;
170         case 3:
171                 spc = mathed_thickmuskip(mb.font);
172                 break;
173         default:
174                 LYXERR0("Impossible pair of classes: (" << mc1 << ", " << mc2 << ")");
175                 LATTEST(false);
176         }
177         return spc;
178 }
179
180 } // namespace lyx