3 * Purpose: Interaction and drawing for mathed
4 * Author: Alejandro Aguilar Sierra <asierra@servidor.unam.mx>
5 * Created: January 1996
6 * Description: Math drawing and interaction for a WYSIWYG math editor.
8 * Dependencies: Xlib, XForms
10 * Copyright: (c) 1996, Alejandro Aguilar Sierra
12 * Version: 0.8beta, Mathed & Lyx project.
14 * You are free to use and modify this code under the terms of
15 * the GNU General Public Licence version 2 or later.
19 #include FORMS_H_LOCATION
20 #include "math_cursor.h"
21 #include "math_parser.h"
27 extern LyXFont mathed_get_font(short type, int size);
29 extern void mathed_set_font(short type, int style);
31 extern int mathed_char_width(short type, int style, byte c);
32 extern int mathed_string_width(short type, int style, byte const* s, int ls);
33 extern int mathed_string_height(short, int, byte const*, int, int&, int&);
34 extern int mathed_char_height(short, int, byte, int&, int&);
37 GC canvasGC= 0, mathGC= 0, mathLineGC= 0, latexGC= 0, cursorGC= 0, mathFrameGC= 0;
42 unsigned long MathedInset::pm;
47 MathSpaceInset::draw(Painter & pain, int x, int y)
50 // XPoint p[4] = {{++x, y-3}, {x, y}, {x+width-2, y}, {x+width-2, y-3}};
52 // Sadly, HP-UX CC can't handle that kind of initialization.
57 xp[0] = ++x; yp[0] = y - 3;
59 xp[2] = x + width - 2; yp[2] = y;
60 xp[3] = x + width - 2; yp[3] = y - 3;
62 pain.lines(xp, yp, 4, (space) ? LColor::latex : LColor::math);
66 MathSpaceInset::Draw(int x, int y)
69 // XPoint p[4] = {{++x, y-3}, {x, y}, {x+width-2, y}, {x+width-2, y-3}};
71 // Sadly, HP-UX CC can't handle that kind of initialization.
74 p[0].x = ++x; p[0].y = y-3;
75 p[1].x = x; p[1].y = y;
76 p[2].x = x+width-2; p[2].y = y;
77 p[3].x = x+width-2; p[3].y = y-3;
79 XDrawLines(fl_display, pm,(space) ? latexGC: mathGC, p, 4, CoordModeOrigin);
87 MathParInset::draw(Painter & pain, int x, int y)
91 int asc = df_asc, des = 0;
95 if (!array || array->empty()) {
97 MathedXIter data(this);
100 pain.rectangle(x, y - df_asc, df_width, df_asc, LColor::mathline);
103 MathedXIter data(this);
109 byte * s = data.GetString(ls);
110 drawStr(pain, data.FCode(), size, x, y, s, ls);
111 mathed_char_height(LM_TC_CONST, size, 'y', asc, des);
115 if (MathIsInset(cx)) {
117 MathedInset * p = data.GetInset();
118 if (cx == LM_TC_UP) {
120 x -= (xp>p->Width()) ? p->Width()+(xp-p->Width())/2: xp;
121 yy -= (asc + p->Descent()+4);
123 yy -= (p->Descent()>asc) ? p->Descent()+4: asc;
125 if (cx == LM_TC_DOWN) {
127 x -= (xp>p->Width()) ? p->Width()+(xp-p->Width())/2: xp;
128 yy += des + p->Ascent() + 2;
130 yy += des + p->Ascent()/2;
135 p->draw(pain, x, yy);
136 if (cx!= LM_TC_UP && cx!= LM_TC_DOWN) {
137 limits = p->GetLimits();
138 if (limits) xp = p->Width();
142 if (cx == LM_TC_TAB) {
143 if ((cxp == cx || cxp == LM_TC_CR || data.IsFirst())) { // && objtype == L
144 pain.rectangle(x, y - df_asc, df_width, df_asc,
150 if (cx == LM_TC_CR) {
151 if (cxp == LM_TC_TAB || cxp == LM_TC_CR || data.IsFirst()) { // && objtype == LM_OT_MATRIX) {
152 pain.rectangle(x, y - df_asc, df_width, df_asc,
159 lyxerr << "GMathed Error: Unrecognized code[" << cx
166 if (cxp == LM_TC_TAB || cxp == LM_TC_CR) { // && objtype == LM_OT_MATRIX) {
168 pain.rectangle(x, y - df_asc, df_width, df_asc, LColor::mathline);
173 MathParInset::Draw(int x, int y)
177 int asc= df_asc, des= 0;
181 if (!array || array->empty()) {
182 mathed_set_font(LM_TC_VAR, 1);
184 MathedXIter data(this);
187 XDrawRectangle(fl_display, pm, mathLineGC, x, y-df_asc, df_width, df_asc);
191 MathedXIter data(this);
197 byte *s = data.GetString(ls);
198 drawStr(data.FCode(), size, x, y, s, ls);
199 mathed_char_height(LM_TC_CONST, size, 'y', asc, des);
203 if (MathIsInset(cx)) {
205 MathedInset *p = data.GetInset();
206 if (cx == LM_TC_UP) {
208 x -= (xp>p->Width()) ? p->Width()+(xp-p->Width())/2: xp;
209 yy -= (asc + p->Descent()+4);
211 yy -= (p->Descent()>asc) ? p->Descent()+4: asc;
213 if (cx == LM_TC_DOWN) {
215 x -= (xp>p->Width()) ? p->Width()+(xp-p->Width())/2: xp;
216 yy += des + p->Ascent() + 2;
218 yy += des + p->Ascent()/2;
224 if (cx!= LM_TC_UP && cx!= LM_TC_DOWN) {
225 limits = p->GetLimits();
226 if (limits) xp = p->Width();
230 if (cx == LM_TC_TAB) {
231 if ((cxp == cx || cxp == LM_TC_CR || data.IsFirst())) { // && objtype == L
232 XDrawRectangle(fl_display, pm, mathLineGC,
233 x, y-df_asc, df_width, df_asc);
240 if (cx == LM_TC_CR) {
241 if (cxp == LM_TC_TAB || cxp == LM_TC_CR || data.IsFirst()) { // && objtype == LM_OT_MATRIX) {
242 XDrawRectangle(fl_display, pm, mathLineGC, x, y-df_asc, df_width, df_asc);
248 lyxerr << "GMathed Error: Unrecognized code[" << cx
255 if (cxp == LM_TC_TAB || cxp == LM_TC_CR) { // && objtype == LM_OT_MATRIX) {
257 XDrawRectangle(fl_display, pm, mathLineGC, x, y-df_asc, df_width, df_asc);
265 MathParInset::Metrics()
269 int asc= df_asc, des= 0;
274 ascent = df_asc;//mathed_char_height(LM_TC_VAR, size, 'I', asc, des);
278 if (array->empty()) return;
281 MathedXIter data(this);
286 s = data.GetString(ls);
287 mathed_string_height(data.FCode(), size, s, ls, asc, des);
288 if (asc > ascent) ascent = asc;
289 if (des > descent) descent = des;
291 mathed_char_height(LM_TC_CONST, size, 'y', asc, des);
293 if (MathIsInset(cx)) {
294 MathedInset *p = data.GetInset();
297 if (cx == LM_TC_UP) {
298 asc += (limits) ? p->Height()+4: p->Ascent() +
299 ((p->Descent()>asc) ? p->Descent()-asc+4: 0);
301 if (cx == LM_TC_DOWN) {
302 des += ((limits) ? p->Height()+4: p->Height()-p->Ascent()/2);
307 if (asc > ascent) ascent = asc;
308 if (des > descent) descent = des;
309 if (cx!= LM_TC_UP && cx!= LM_TC_DOWN)
310 limits = p->GetLimits();
313 if (cx == LM_TC_TAB) {
315 data.GetIncPos(x, y);
316 if (data.IsFirst() || cxp == LM_TC_TAB || cxp == LM_TC_CR) {
317 if (ascent<df_asc) ascent = df_asc;
320 data.setTab(x-tb, tab);
326 if (cx == LM_TC_CR) {
329 data.GetIncPos(x, y);
330 if (data.IsFirst() || cxp == LM_TC_TAB || cxp == LM_TC_CR) {
331 if (ascent<df_asc) ascent = df_asc;
334 data.setTab(x-tb, tab);
335 } else //if (GetColumns() == 1)
338 data.GetIncPos(x, y);
340 if (ascent<df_asc) ascent = df_asc;
343 data.subMetrics(ascent, descent);
349 lyxerr << "Mathed Error: Unrecognized code[" << cx
355 data.GetIncPos(width, ls);
357 // No matter how simple is a matrix, it is NOT a subparagraph
359 if (cxp == LM_TC_TAB) {
360 if (ascent<df_asc) ascent = df_asc;
363 data.setTab(width-tb, tab);
367 data.subMetrics(ascent, descent);
373 MathSqrtInset::draw(Painter & pain, int x, int y)
375 MathParInset::draw(pain, x + hmax + 2, y);
378 int h2 = Height() / 2;
379 int w2 = (Height() > 4 * hmax) ? hmax : hmax / 2;
381 xp[0] = x + hmax + wbody; yp[0] = y - h;
382 xp[1] = x + hmax; yp[1] = y - h;
383 xp[2] = x + w2; yp[2] = y + d;
384 xp[3] = x; yp[3] = y + d - h2;
385 pain.lines(xp, yp, 4, LColor::mathline);
389 MathSqrtInset::Draw(int x, int y)
391 MathParInset::Draw(x+hmax+2, y);
394 int h2 = Height() / 2;
395 int w2 = (Height() > 4 * hmax) ? hmax : hmax / 2;
397 p[0].x = x + hmax + wbody; p[0].y = y - h;
398 p[1].x = x + hmax; p[1].y = y - h;
399 p[2].x = x + w2; p[2].y = y + d;
400 p[3].x = x; p[3].y = y + d - h2;
401 XDrawLines(fl_display, pm, mathLineGC, p, 4, CoordModeOrigin);
408 MathSqrtInset::Metrics()
410 MathParInset::Metrics();
414 hmax = mathed_char_height(LM_TC_VAR, size, 'I', a, b);
415 if (hmax < 10) hmax = 10;
423 MathFracInset::draw(Painter & pain, int x, int y)
429 if (size == LM_ST_DISPLAY) ++size;
430 MathParInset::draw(pain, x + (width - w0) / 2, y - des0);
431 den->draw(pain, x + (width - w1) / 2, y + den->Ascent() + 2 - dh);
433 if (objtype == LM_OT_FRAC)
434 pain.line(x + 2, y - dh, x + width - 4, y - dh, LColor::mathline);
439 MathFracInset::Draw(int x, int y)
445 if (size == LM_ST_DISPLAY) ++size;
446 MathParInset::Draw(x + (width - w0) / 2, y - des0);
447 den->Draw(x + (width - w1) / 2, y + den->Ascent() + 2 - dh);
449 if (objtype == LM_OT_FRAC)
450 XDrawLine(fl_display, pm, mathLineGC,
451 x + 2, y - dh, x + width - 4, y - dh);
459 MathFracInset::Metrics()
463 dh = mathed_char_height(LM_TC_CONST, size, 'I', a, b)/2;
468 if (size == LM_ST_DISPLAY) ++size;
469 MathParInset::Metrics();
472 int as = Height() + 2 + dh;
473 des0 = Descent() + 2 + dh;
476 width = ((w0 > w1) ? w0: w1) + 12;
478 descent = den->Height()+ 2 - dh;
485 MathBigopInset::draw(Painter & pain, int x, int y)
492 if (sym < 256 || sym == LM_oint) {
494 c = (sym == LM_oint) ? LM_int : sym;
502 if (sym == LM_oint) {
503 pain.arc(x, y - 5 * width / 4, width, width, 0, 360*64,
507 pain.text(x, y, s, ls, mathed_get_font(t, size));
511 MathBigopInset::Draw(int x, int y)
518 if (sym<256 || sym == LM_oint) {
520 c = (sym == LM_oint) ? LM_int: sym;
528 mathed_set_font(t, size);
529 if (sym == LM_oint) {
530 XDrawArc(fl_display, pm, mathLineGC, x, y-5*width/4, width, width, 0, 23040);
534 XDrawString(fl_display, pm, mathGC, x, y, s, ls);
542 MathBigopInset::Metrics()
549 if (sym < 256 || sym == LM_oint) {
551 c = (sym == LM_oint) ? LM_int: sym;
559 mathed_string_height(t, size,
560 reinterpret_cast<const unsigned char*>(s),
561 ls, ascent, descent);
562 width = mathed_string_width(t, size,
563 reinterpret_cast<const unsigned char*>(s),
565 if (sym == LM_oint) width += 2;
569 MathBigopInset::Metrics()
576 if (sym<256 || sym == LM_oint) {
578 c = (sym == LM_oint) ? LM_int: sym;
586 mathed_set_font(t, size);
587 mathed_string_height(t, size, reinterpret_cast<const unsigned char*>(s), ls, ascent, descent);
588 width = mathed_string_width(t, size, reinterpret_cast<const unsigned char*>(s), ls);
589 if (sym == LM_oint) width += 2;