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&);
36 GC canvasGC= 0, mathGC= 0, mathLineGC= 0, latexGC= 0, cursorGC= 0, mathFrameGC= 0;
40 unsigned long MathedInset::pm;
45 MathSpaceInset::draw(Painter & pain, int x, int y)
48 // XPoint p[4] = {{++x, y-3}, {x, y}, {x+width-2, y}, {x+width-2, y-3}};
50 // Sadly, HP-UX CC can't handle that kind of initialization.
55 xp[0] = ++x; yp[0] = y - 3;
57 xp[2] = x + width - 2; yp[2] = y;
58 xp[3] = x + width - 2; yp[3] = y - 3;
60 pain.lines(xp, yp, 4, (space) ? LColor::latex : LColor::math);
64 MathSpaceInset::Draw(int x, int y)
67 // XPoint p[4] = {{++x, y-3}, {x, y}, {x+width-2, y}, {x+width-2, y-3}};
69 // Sadly, HP-UX CC can't handle that kind of initialization.
72 p[0].x = ++x; p[0].y = y-3;
73 p[1].x = x; p[1].y = y;
74 p[2].x = x+width-2; p[2].y = y;
75 p[3].x = x+width-2; p[3].y = y-3;
77 XDrawLines(fl_display, pm,(space) ? latexGC: mathGC, p, 4, CoordModeOrigin);
85 MathParInset::draw(Painter & pain, int x, int y)
89 int asc = df_asc, des = 0;
93 if (!array || array->empty()) {
95 MathedXIter data(this);
98 pain.rectangle(x, y - df_asc, df_width, df_asc, LColor::mathline);
101 MathedXIter data(this);
107 byte * s = data.GetString(ls);
108 drawStr(pain, data.FCode(), size, x, y, s, ls);
109 mathed_char_height(LM_TC_CONST, size, 'y', asc, des);
113 if (MathIsInset(cx)) {
115 MathedInset * p = data.GetInset();
116 if (cx == LM_TC_UP) {
118 x -= (xp>p->Width()) ? p->Width()+(xp-p->Width())/2: xp;
119 yy -= (asc + p->Descent()+4);
121 yy -= (p->Descent()>asc) ? p->Descent()+4: asc;
123 if (cx == LM_TC_DOWN) {
125 x -= (xp>p->Width()) ? p->Width()+(xp-p->Width())/2: xp;
126 yy += des + p->Ascent() + 2;
128 yy += des + p->Ascent()/2;
133 p->draw(pain, x, yy);
134 if (cx!= LM_TC_UP && cx!= LM_TC_DOWN) {
135 limits = p->GetLimits();
136 if (limits) xp = p->Width();
140 if (cx == LM_TC_TAB) {
141 if ((cxp == cx || cxp == LM_TC_CR || data.IsFirst())) { // && objtype == L
142 pain.rectangle(x, y - df_asc, df_width, df_asc,
148 if (cx == LM_TC_CR) {
149 if (cxp == LM_TC_TAB || cxp == LM_TC_CR || data.IsFirst()) { // && objtype == LM_OT_MATRIX) {
150 pain.rectangle(x, y - df_asc, df_width, df_asc,
157 lyxerr << "GMathed Error: Unrecognized code[" << cx
164 if (cxp == LM_TC_TAB || cxp == LM_TC_CR) { // && objtype == LM_OT_MATRIX) {
166 pain.rectangle(x, y - df_asc, df_width, df_asc, LColor::mathline);
171 MathParInset::Draw(int x, int y)
175 int asc= df_asc, des= 0;
179 if (!array || array->empty()) {
180 mathed_set_font(LM_TC_VAR, 1);
182 MathedXIter data(this);
185 XDrawRectangle(fl_display, pm, mathLineGC, x, y-df_asc, df_width, df_asc);
189 MathedXIter data(this);
195 byte *s = data.GetString(ls);
196 drawStr(data.FCode(), size, x, y, s, ls);
197 mathed_char_height(LM_TC_CONST, size, 'y', asc, des);
201 if (MathIsInset(cx)) {
203 MathedInset *p = data.GetInset();
204 if (cx == LM_TC_UP) {
206 x -= (xp>p->Width()) ? p->Width()+(xp-p->Width())/2: xp;
207 yy -= (asc + p->Descent()+4);
209 yy -= (p->Descent()>asc) ? p->Descent()+4: asc;
211 if (cx == LM_TC_DOWN) {
213 x -= (xp>p->Width()) ? p->Width()+(xp-p->Width())/2: xp;
214 yy += des + p->Ascent() + 2;
216 yy += des + p->Ascent()/2;
222 if (cx!= LM_TC_UP && cx!= LM_TC_DOWN) {
223 limits = p->GetLimits();
224 if (limits) xp = p->Width();
228 if (cx == LM_TC_TAB) {
229 if ((cxp == cx || cxp == LM_TC_CR || data.IsFirst())) { // && objtype == L
230 XDrawRectangle(fl_display, pm, mathLineGC,
231 x, y-df_asc, df_width, df_asc);
238 if (cx == LM_TC_CR) {
239 if (cxp == LM_TC_TAB || cxp == LM_TC_CR || data.IsFirst()) { // && objtype == LM_OT_MATRIX) {
240 XDrawRectangle(fl_display, pm, mathLineGC, x, y-df_asc, df_width, df_asc);
246 lyxerr << "GMathed Error: Unrecognized code[" << cx
253 if (cxp == LM_TC_TAB || cxp == LM_TC_CR) { // && objtype == LM_OT_MATRIX) {
255 XDrawRectangle(fl_display, pm, mathLineGC, x, y-df_asc, df_width, df_asc);
263 MathParInset::Metrics()
267 int asc= df_asc, des= 0;
272 ascent = df_asc;//mathed_char_height(LM_TC_VAR, size, 'I', asc, des);
276 if (array->empty()) return;
279 MathedXIter data(this);
284 s = data.GetString(ls);
285 mathed_string_height(data.FCode(), size, s, ls, asc, des);
286 if (asc > ascent) ascent = asc;
287 if (des > descent) descent = des;
289 mathed_char_height(LM_TC_CONST, size, 'y', asc, des);
291 if (MathIsInset(cx)) {
292 MathedInset *p = data.GetInset();
295 if (cx == LM_TC_UP) {
296 asc += (limits) ? p->Height()+4: p->Ascent() +
297 ((p->Descent()>asc) ? p->Descent()-asc+4: 0);
299 if (cx == LM_TC_DOWN) {
300 des += ((limits) ? p->Height()+4: p->Height()-p->Ascent()/2);
305 if (asc > ascent) ascent = asc;
306 if (des > descent) descent = des;
307 if (cx!= LM_TC_UP && cx!= LM_TC_DOWN)
308 limits = p->GetLimits();
311 if (cx == LM_TC_TAB) {
313 data.GetIncPos(x, y);
314 if (data.IsFirst() || cxp == LM_TC_TAB || cxp == LM_TC_CR) {
315 if (ascent<df_asc) ascent = df_asc;
318 data.setTab(x-tb, tab);
324 if (cx == LM_TC_CR) {
327 data.GetIncPos(x, y);
328 if (data.IsFirst() || cxp == LM_TC_TAB || cxp == LM_TC_CR) {
329 if (ascent<df_asc) ascent = df_asc;
332 data.setTab(x-tb, tab);
333 } else //if (GetColumns() == 1)
336 data.GetIncPos(x, y);
338 if (ascent<df_asc) ascent = df_asc;
341 data.subMetrics(ascent, descent);
347 lyxerr << "Mathed Error: Unrecognized code[" << cx
353 data.GetIncPos(width, ls);
355 // No matter how simple is a matrix, it is NOT a subparagraph
357 if (cxp == LM_TC_TAB) {
358 if (ascent<df_asc) ascent = df_asc;
361 data.setTab(width-tb, tab);
365 data.subMetrics(ascent, descent);
371 MathSqrtInset::draw(Painter & pain, int x, int y)
373 MathParInset::draw(pain, x + hmax + 2, y);
376 int h2 = Height() / 2;
377 int w2 = (Height() > 4 * hmax) ? hmax : hmax / 2;
379 xp[0] = x + hmax + wbody; yp[0] = y - h;
380 xp[1] = x + hmax; yp[1] = y - h;
381 xp[2] = x + w2; yp[2] = y + d;
382 xp[3] = x; yp[3] = y + d - h2;
383 pain.lines(xp, yp, 4, LColor::mathline);
387 MathSqrtInset::Draw(int x, int y)
389 MathParInset::Draw(x+hmax+2, y);
392 int h2 = Height() / 2;
393 int w2 = (Height() > 4 * hmax) ? hmax : hmax / 2;
395 p[0].x = x + hmax + wbody; p[0].y = y - h;
396 p[1].x = x + hmax; p[1].y = y - h;
397 p[2].x = x + w2; p[2].y = y + d;
398 p[3].x = x; p[3].y = y + d - h2;
399 XDrawLines(fl_display, pm, mathLineGC, p, 4, CoordModeOrigin);
406 MathSqrtInset::Metrics()
408 MathParInset::Metrics();
412 hmax = mathed_char_height(LM_TC_VAR, size, 'I', a, b);
413 if (hmax < 10) hmax = 10;
421 MathFracInset::draw(Painter & pain, int x, int y)
427 if (size == LM_ST_DISPLAY) ++size;
428 MathParInset::draw(pain, x + (width - w0) / 2, y - des0);
429 den->draw(pain, x + (width - w1) / 2, y + den->Ascent() + 2 - dh);
431 if (objtype == LM_OT_FRAC)
432 pain.line(x + 2, y - dh, x + width - 4, y - dh, LColor::mathline);
437 MathFracInset::Draw(int x, int y)
443 if (size == LM_ST_DISPLAY) ++size;
444 MathParInset::Draw(x + (width - w0) / 2, y - des0);
445 den->Draw(x + (width - w1) / 2, y + den->Ascent() + 2 - dh);
447 if (objtype == LM_OT_FRAC)
448 XDrawLine(fl_display, pm, mathLineGC,
449 x + 2, y - dh, x + width - 4, y - dh);
457 MathFracInset::Metrics()
461 dh = mathed_char_height(LM_TC_CONST, size, 'I', a, b)/2;
466 if (size == LM_ST_DISPLAY) ++size;
467 MathParInset::Metrics();
470 int as = Height() + 2 + dh;
471 des0 = Descent() + 2 + dh;
474 width = ((w0 > w1) ? w0: w1) + 12;
476 descent = den->Height()+ 2 - dh;
483 MathBigopInset::draw(Painter & pain, int x, int y)
490 if (sym < 256 || sym == LM_oint) {
492 c = (sym == LM_oint) ? LM_int : sym;
500 if (sym == LM_oint) {
501 pain.arc(x, y - 5 * width / 4, width, width, 0, 360*64,
505 pain.text(x, y, s, ls, mathed_get_font(t, size));
509 MathBigopInset::Draw(int x, int y)
516 if (sym<256 || sym == LM_oint) {
518 c = (sym == LM_oint) ? LM_int: sym;
526 mathed_set_font(t, size);
527 if (sym == LM_oint) {
528 XDrawArc(fl_display, pm, mathLineGC, x, y-5*width/4, width, width, 0, 23040);
532 XDrawString(fl_display, pm, mathGC, x, y, s, ls);
540 MathBigopInset::Metrics()
547 if (sym < 256 || sym == LM_oint) {
549 c = (sym == LM_oint) ? LM_int: sym;
557 mathed_string_height(t, size,
558 reinterpret_cast<const unsigned char*>(s),
559 ls, ascent, descent);
560 width = mathed_string_width(t, size,
561 reinterpret_cast<const unsigned char*>(s),
563 if (sym == LM_oint) width += 2;
567 MathBigopInset::Metrics()
574 if (sym<256 || sym == LM_oint) {
576 c = (sym == LM_oint) ? LM_int: sym;
584 mathed_set_font(t, size);
585 mathed_string_height(t, size, reinterpret_cast<const unsigned char*>(s), ls, ascent, descent);
586 width = mathed_string_width(t, size, reinterpret_cast<const unsigned char*>(s), ls);
587 if (sym == LM_oint) width += 2;