From cfdd73ea94c3cc0058459d67b1c62fabd31fbeb1 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Lars=20Gullik=20Bj=C3=B8nnes?= Date: Thu, 10 Feb 2000 17:53:36 +0000 Subject: [PATCH] new painter,workarea and lcolor. Read the diff/sources and ChangeLog... git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@550 a592a061-630c-0410-9148-cb99ea01b6c8 --- ChangeLog | 11 + po/POTFILES.in | 2 + src/BufferView.C | 975 ++++++++++++- src/BufferView.h | 81 +- src/FontLoader.C | 4 + src/LColor.C | 176 +++ src/LColor.h | 208 +++ src/LyXView.C | 16 +- src/Makefile.am | 8 + src/Painter.C | 456 ++++++ src/Painter.h | 140 ++ src/PainterBase.C | 145 ++ src/PainterBase.h | 206 +++ src/WorkArea.C | 421 ++++++ src/WorkArea.h | 149 ++ src/bmtable.c | 14 +- src/insets/figinset.C | 171 ++- src/insets/figinset.h | 12 + src/insets/insetbib.C | 47 +- src/insets/insetbib.h | 2 +- src/insets/insetcommand.C | 65 + src/insets/insetcommand.h | 15 +- src/insets/inseterror.C | 53 +- src/insets/inseterror.h | 15 +- src/insets/insetinfo.C | 45 + src/insets/insetinfo.h | 11 + src/insets/insetlatexaccent.C | 416 +++++- src/insets/insetlatexaccent.h | 23 +- src/insets/insetquotes.C | 45 + src/insets/insetquotes.h | 11 + src/insets/insetspecialchar.C | 96 +- src/insets/insetspecialchar.h | 11 + src/insets/inseturl.h | 2 +- src/insets/lyxinset.h | 23 +- src/lyx_cb.C | 20 +- src/lyx_gui.C | 2 + src/lyxdraw.C | 9 + src/lyxdraw.h | 3 + src/lyxfont.C | 260 +++- src/lyxfont.h | 331 ++++- src/lyxfr1.C | 8 +- src/lyxfunc.C | 58 +- src/lyxscreen.h | 30 +- src/lyxtext.h | 31 +- src/mathed/formula.C | 142 +- src/mathed/formula.h | 11 + src/mathed/formulamacro.C | 65 + src/mathed/formulamacro.h | 11 + src/mathed/math_cursor.C | 105 +- src/mathed/math_cursor.h | 15 +- src/mathed/math_defs.h | 28 +- src/mathed/math_delim.C | 137 +- src/mathed/math_draw.C | 239 +++- src/mathed/math_inset.C | 9 +- src/mathed/math_inset.h | 44 + src/mathed/math_macro.C | 52 + src/mathed/math_macro.h | 15 + src/mathed/math_root.C | 12 + src/mathed/math_root.h | 5 + src/minibuffer.C | 8 + src/paragraph.C | 16 + src/screen.C | 221 ++- src/text.C | 2472 +++++++++++++++++++++++++-------- src/text2.C | 9 +- 64 files changed, 7630 insertions(+), 813 deletions(-) create mode 100644 src/LColor.C create mode 100644 src/LColor.h create mode 100644 src/Painter.C create mode 100644 src/Painter.h create mode 100644 src/PainterBase.C create mode 100644 src/PainterBase.h create mode 100644 src/WorkArea.C create mode 100644 src/WorkArea.h diff --git a/ChangeLog b/ChangeLog index 165ee0f5c1..b05ab52d45 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,14 @@ +2000-02-10 Lars Gullik Bjønnes + + * a lot of files: The Painter, LColor and WorkArea from the old + devel branch has been ported to lyx-devel. Some new files and a + lot of #ifdeffed code. The new workarea is enabled by default, but + if you want to test the new Painter and LColor you have to compile + with USE_PAINTER defined (do this in config.h f.ex.) There are + still some rought edges, and I'd like some help to clear those + out. It looks stable (loads and displays the Userguide very well). + + 2000-02-10 Jean-Marc Lasgouttes * src/buffer.C (pop_tag): revert to the previous implementation diff --git a/po/POTFILES.in b/po/POTFILES.in index b41b7f4c2e..7f6a48b17b 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -49,6 +49,7 @@ src/LaTeXLog.C src/latexoptions.C src/layout.C src/layout_forms.C +src/LColor.C src/Literate.C src/LyXAction.C src/lyx.C @@ -74,6 +75,7 @@ src/mathed/math_panel.C src/menus.C src/minibuffer.C src/minibuffer.h +src/Painter.C src/PaperLayout.C src/paragraph.C src/ParagraphExtra.C diff --git a/src/BufferView.C b/src/BufferView.C index 66ac7d4bf6..0cb2be39db 100644 --- a/src/BufferView.C +++ b/src/BufferView.C @@ -34,8 +34,12 @@ using std::for_each; #include "insets/lyxinset.h" #include "minibuffer.h" #include "lyxscreen.h" + +#ifndef NEW_WA #include "up.xpm" #include "down.xpm" +#endif + #include "debug.h" #include "lyxdraw.h" #include "lyx_gui_misc.h" @@ -48,6 +52,7 @@ using std::for_each; #include "intl.h" #include "lyxrc.h" #include "lyxrow.h" +#include "WorkArea.h" using std::find_if; @@ -65,8 +70,10 @@ extern InsetUpdateStruct * InsetUpdateList; extern void UpdateInsetUpdateList(); extern void FreeUpdateTimer(); +#ifndef NEW_WA // This is _very_ temporary FL_OBJECT * figinset_canvas; +#endif BufferView::BufferView(LyXView * o, int xpos, int ypos, int width, int height) @@ -75,17 +82,25 @@ BufferView::BufferView(LyXView * o, int xpos, int ypos, buffer_ = 0; text = 0; screen = 0; - work_area = 0; +#ifdef NEW_WA + workarea = new WorkArea(this, xpos, ypos, width, height); +#else figinset_canvas = 0; + work_area = 0; scrollbar = 0; button_down = 0; button_up = 0; +#endif timer_cursor = 0; - current_scrollbar_value = 0; create_view(xpos, ypos, width, height); + current_scrollbar_value = 0; // Activate the timer for the cursor fl_set_timer(timer_cursor, 0.4); +#ifdef NEW_WA + workarea->setFocus(); +#else fl_set_focus_object(owner_->getForm(), work_area); +#endif work_area_focus = true; lyx_focus = false; the_locking_inset = 0; @@ -98,7 +113,15 @@ BufferView::~BufferView() delete text; } - + +#ifdef USE_PAINTER +Painter & BufferView::painter() +{ + return workarea->getPainter(); +} +#endif + + void BufferView::buffer(Buffer * b) { lyxerr[Debug::INFO] << "Setting buffer in BufferView (" @@ -150,7 +173,11 @@ void BufferView::buffer(Buffer * b) lyxerr[Debug::INFO] << " No Buffer!" << endl; owner_->getMenus()->hideMenus(); updateScrollbar(); +#ifdef NEW_WA + workarea->redraw(); +#else fl_redraw_object(work_area); +#endif // Also remove all remaining text's from the testcache. // (there should not be any!) (if there is any it is a @@ -170,13 +197,34 @@ void BufferView::updateScreen() { // Regenerate the screen. delete screen; +#ifdef NEW_WA + screen = new LyXScreen(this, + workarea->getWin(), + workarea->getPixmap(), + workarea->workWidth(), + workarea->height(), + workarea->xpos(), + workarea->ypos(), + text); +#else screen = new LyXScreen(FL_ObjWin(work_area), work_area->w, work_area->h, work_area->x, work_area->y, text); +#endif +} + + +#ifdef NEW_WA +void BufferView::resize(int xpos, int ypos, int width, int height) +{ + workarea->resize(xpos, ypos, width, height); + update(3); + redraw(); } +#endif void BufferView::resize() @@ -187,23 +235,30 @@ void BufferView::resize() } +#ifndef NEW_WA static bool lgb_hack = false; +#endif void BufferView::redraw() { lyxerr[Debug::INFO] << "BufferView::redraw()" << endl; +#ifdef NEW_WA + workarea->redraw(); +#else lgb_hack = true; fl_redraw_object(work_area); fl_redraw_object(scrollbar); fl_redraw_object(button_down); fl_redraw_object(button_up); lgb_hack = false; +#endif } void BufferView::fitCursor() { if (screen) screen->FitCursor(); + updateScrollbar(); } @@ -220,8 +275,12 @@ void BufferView::updateScrollbar() * be possible */ if (!buffer_) { +#ifdef NEW_WA + workarea->setScrollbar(0, 1.0); +#else fl_set_slider_value(scrollbar, 0); fl_set_slider_size(scrollbar, scrollbar->h); +#endif return; } @@ -237,27 +296,65 @@ void BufferView::updateScrollbar() cbsf = screen->first; // check if anything has changed. +#ifdef NEW_WA + if (max2 == cbth && + height2 == workarea->height() && + current_scrollbar_value == cbsf) + return; // no + max2 = cbth; + height2 = workarea->height(); + current_scrollbar_value = cbsf; +#else if (max2 == cbth && height2 == work_area->h && current_scrollbar_value == cbsf) return; // no - max2 = cbth; height2 = work_area->h; current_scrollbar_value = cbsf; +#endif if (cbth <= height2) { // text is smaller than screen +#ifdef NEW_WA + workarea->setScrollbar(0, 1.0); // right? +#else fl_set_slider_size(scrollbar, scrollbar->h); +#endif return; } - + +#ifdef NEW_WA + long maximum_height = workarea->height() * 3 / 4 + cbth; +#else long maximum_height = work_area->h * 3 / 4 + cbth; +#endif long value = cbsf; // set the scrollbar +#ifdef NEW_WA + double hfloat = workarea->height(); +#else double hfloat = work_area->h; +#endif double maxfloat = maximum_height; - + +#ifdef NEW_WA + float slider_size = 0.0; + int slider_value = value; + + workarea->setScrollbarBounds(0, text->height - workarea->height()); + double lineh = text->DefaultHeight(); + workarea->setScrollbarIncrements(lineh); + if (maxfloat > 0.0) { + if ((hfloat / maxfloat) * float(height2) < 3) + slider_size = 3.0/float(height2); + else + slider_size = hfloat / maxfloat; + } else + slider_size = hfloat; + + workarea->setScrollbar(slider_value, slider_size / workarea->height()); +#else fl_set_slider_value(scrollbar, value); fl_set_slider_bounds(scrollbar, 0, maximum_height - work_area->h); @@ -275,6 +372,7 @@ void BufferView::updateScrollbar() } else fl_set_slider_size(scrollbar, hfloat); fl_set_slider_precision(scrollbar, 0); +#endif } @@ -315,11 +413,19 @@ int BufferView::resizeCurrentBuffer() selection = text->selection; mark_set = text->mark_set; delete text; +#ifdef NEW_WA + text = new LyXText(this, workarea->workWidth(), buffer_); +#else text = new LyXText(work_area->w, buffer_); +#endif } else { // See if we have a text in TextCache that fits // the new buffer_ with the correct width. +#ifdef NEW_WA + text = textcache.findFit(buffer_, workarea->workWidth()); +#else text = textcache.findFit(buffer_, work_area->w); +#endif if (text) { if (lyxerr.debugging()) { lyxerr << "Found a LyXText that fits:\n"; @@ -328,7 +434,11 @@ int BufferView::resizeCurrentBuffer() if (lyxerr.debugging()) textcache.show(lyxerr, "resizeCurrentBuffer"); } else { +#ifdef NEW_WA + text = new LyXText(this, workarea->workWidth(), buffer_); +#else text = new LyXText(work_area->w, buffer_); +#endif } } updateScreen(); @@ -399,6 +509,14 @@ void BufferView::gotoError() } +#ifdef NEW_WA +extern "C" { + void C_BufferView_CursorToggleCB(FL_OBJECT * ob, long buf) + { + BufferView::CursorToggleCB(ob, buf); + } +} +#else extern "C" { // Just a bunch of C wrappers around static members of BufferView void C_BufferView_UpCB(FL_OBJECT * ob, long buf) @@ -433,11 +551,13 @@ extern "C" { 0, 0, key, xev); } } +#endif void BufferView::create_view(int xpos, int ypos, int width, int height) { FL_OBJECT * obj; +#ifndef NEW_WA int const bw = abs(fl_get_border_width()); // a hack for the figinsets (Matthias) @@ -523,7 +643,7 @@ void BufferView::create_view(int xpos, int ypos, int width, int height) // Remove the blue feedback rectangle fl_set_pixmapbutton_focus_outline(obj, 0); - +#endif // // TIMERS // @@ -537,6 +657,24 @@ void BufferView::create_view(int xpos, int ypos, int width, int height) // Callback for scrollbar up button +#ifdef NEW_WA +void BufferView::UpCB(long time, int button) +{ + if (buffer_ == 0) return; + + switch (button) { + case 3: + ScrollUpOnePage(); + break; + case 2: + ScrollDownOnePage(); + break; + default: + ScrollUp(time); + break; + } +} +#else void BufferView::UpCB(FL_OBJECT * ob, long) { BufferView * view = static_cast(ob->u_vdata); @@ -557,6 +695,7 @@ void BufferView::UpCB(FL_OBJECT * ob, long) view->ScrollUp(time++); break; } } +#endif static inline @@ -567,6 +706,41 @@ void waitForX() // Callback for scrollbar slider +#ifdef NEW_WA +void BufferView::ScrollCB(double value) +{ + extern bool cursor_follows_scrollbar; + + if (buffer_ == 0) return; + + current_scrollbar_value = long(value); + if (current_scrollbar_value < 0) + current_scrollbar_value = 0; + + if (!screen) + return; + + screen->Draw(current_scrollbar_value); + + if (cursor_follows_scrollbar) { + LyXText * vbt = text; + int height = vbt->DefaultHeight(); + + if (vbt->cursor.y < screen->first + height) { + vbt->SetCursorFromCoordinates(0, + screen->first + + height); + } else if (vbt->cursor.y > + screen->first + workarea->height() - height) { + vbt->SetCursorFromCoordinates(0, + screen->first + + workarea->height() - + height); + } + } + waitForX(); +} +#else void BufferView::ScrollCB(FL_OBJECT * ob, long) { BufferView * view = static_cast(ob->u_vdata); @@ -602,9 +776,28 @@ void BufferView::ScrollCB(FL_OBJECT * ob, long) } waitForX(); } +#endif // Callback for scrollbar down button +#ifdef NEW_WA +void BufferView::DownCB(long time, int button) +{ + if (buffer_ == 0) return; + + switch (button) { + case 2: + ScrollUpOnePage(); + break; + case 3: + ScrollDownOnePage(); + break; + default: + ScrollDown(time); + break; + } +} +#else void BufferView::DownCB(FL_OBJECT * ob, long) { BufferView * view = static_cast(ob->u_vdata); @@ -626,8 +819,37 @@ void BufferView::DownCB(FL_OBJECT * ob, long) view->ScrollDown(time++); break; } } +#endif + + +#ifdef NEW_WA +int BufferView::ScrollUp(long time) +{ + if (buffer_ == 0) return 0; + if (!screen) return 0; + + double value = workarea->getScrollbarValue(); + + if (value == 0) return 0; + float add_value = (text->DefaultHeight() + + float(time) * float(time) * 0.125); + + if (add_value > workarea->height()) + add_value = float(workarea->height() - + text->DefaultHeight()); + + value -= add_value; + if (value < 0) + value = 0; + + workarea->setScrollbarValue(value); + + ScrollCB(value); + return 0; +} +#else int BufferView::ScrollUp(long time) { if (buffer_ == 0) return 0; @@ -654,8 +876,39 @@ int BufferView::ScrollUp(long time) ScrollCB(scrollbar, 0); return 0; } +#endif + + +#ifdef NEW_WA +int BufferView::ScrollDown(long time) +{ + if (buffer_ == 0) return 0; + if (!screen) return 0; + + double value= workarea->getScrollbarValue(); + pair p = workarea->getScrollbarBounds(); + double max = p.second; + + if (value == max) return 0; + float add_value = (text->DefaultHeight() + + float(time) * float(time) * 0.125); + + if (add_value > workarea->height()) + add_value = float(workarea->height() - + text->DefaultHeight()); + + value += add_value; + + if (value > max) + value = max; + workarea->setScrollbarValue(value); + + ScrollCB(value); + return 0; +} +#else int BufferView::ScrollDown(long time) { if (buffer_ == 0) return 0; @@ -684,8 +937,28 @@ int BufferView::ScrollDown(long time) ScrollCB(scrollbar, 0); return 0; } +#endif + + +#ifdef NEW_WA +void BufferView::ScrollUpOnePage() +{ + if (buffer_ == 0) return; + if (!screen) return; + + long y = screen->first; + if (!y) return; + + Row * row = text->GetRowNearY(y); + + y = y - workarea->height() + row->height; + workarea->setScrollbarValue(y); + + ScrollCB(y); +} +#else void BufferView::ScrollUpOnePage(long /*time*/) { if (buffer_ == 0) return; @@ -703,8 +976,28 @@ void BufferView::ScrollUpOnePage(long /*time*/) ScrollCB(scrollbar, 0); } +#endif + +#ifdef NEW_WA +void BufferView::ScrollDownOnePage() +{ + if (buffer_ == 0) return; + if (!screen) return; + + long y = screen->first; + + if (y > text->height - workarea->height()) + return; + + y += workarea->height(); + text->GetRowNearY(y); + workarea->setScrollbarValue(y); + + ScrollCB(y); +} +#else void BufferView::ScrollDownOnePage(long /*time*/) { if (buffer_ == 0) return; @@ -724,8 +1017,10 @@ void BufferView::ScrollDownOnePage(long /*time*/) ScrollCB(scrollbar, 0); } +#endif +#ifndef NEW_WA int BufferView::work_area_handler(FL_OBJECT * ob, int event, FL_Coord, FL_Coord , int /*key*/, void * xev) @@ -827,7 +1122,47 @@ int BufferView::work_area_handler(FL_OBJECT * ob, int event, } return 1; } +#endif + + +#ifdef NEW_WA +void BufferView::WorkAreaMotionNotify(int x, int y, unsigned int state) +{ + if (buffer_ == 0 || !screen) return; + + // Check for inset locking + if (the_locking_inset) { + LyXCursor cursor = text->cursor; + the_locking_inset-> + InsetMotionNotify(x - cursor.x, + y - cursor.y, + state); + return; + } + + // Only use motion with button 1 + if (!state & Button1MotionMask) + return; + + /* The selection possible is needed, that only motion events are + * used, where the bottom press event was on the drawing area too */ + if (selection_possible) { + screen->HideCursor(); + text->SetCursorFromCoordinates(x, y + screen->first); + + if (!text->selection) + update(-3); // Maybe an empty line was deleted + + text->SetSelection(); + screen->ToggleToggle(); + if (screen->FitCursor()) + updateScrollbar(); + screen->ShowCursor(); + } + return; +} +#else int BufferView::WorkAreaMotionNotify(FL_OBJECT * ob, Window, int /*w*/, int /*h*/, XEvent * ev, void * /*d*/) @@ -870,52 +1205,190 @@ int BufferView::WorkAreaMotionNotify(FL_OBJECT * ob, Window, } return 0; } +#endif - +#ifdef USE_PAINTER +extern int bibitemMaxWidth(Painter &, LyXFont const &); +#else extern int bibitemMaxWidth(LyXFont const &); +#endif // Single-click on work area -int BufferView::WorkAreaButtonPress(FL_OBJECT * ob, Window, - int /*w*/, int /*h*/, - XEvent * ev, void */*d*/) +#ifdef NEW_WA +void BufferView::WorkAreaButtonPress(int xpos, int ypos, unsigned int button) { last_click_x = -1; last_click_y = -1; - if (buffer_ == 0) return 0; - if (!screen) return 0; + if (buffer_ == 0 || !screen) return; - int const x = ev->xbutton.x - ob->x; - int const y = ev->xbutton.y - ob->y; - // If we hit an inset, we have the inset coordinates in these - // and inset_hit points to the inset. If we do not hit an - // inset, inset_hit is 0, and inset_x == x, inset_y == y. - int inset_x = x; - int inset_y = y; - Inset * inset_hit = checkInsetHit(inset_x, inset_y); + Inset * inset_hit = checkInsetHit(xpos, ypos); // ok ok, this is a hack. - int button = ev->xbutton.button; - if (button == 4 || button == 5) goto wheel; - - { - if (the_locking_inset) { - // We are in inset locking mode + if (button == 4 || button == 5) { + switch (button) { + case 4: + ScrollUp(100); // This number is only temporary + break; + case 5: + ScrollDown(100); + break; + } + } + + if (the_locking_inset) { + // We are in inset locking mode - /* Check whether the inset was hit. If not reset mode, - otherwise give the event to the inset */ - if (inset_hit != 0) { - the_locking_inset-> - InsetButtonPress(inset_x, inset_y, - button); - return 0; - } else { - unlockInset(the_locking_inset); - } + /* Check whether the inset was hit. If not reset mode, + otherwise give the event to the inset */ + if (inset_hit) { + the_locking_inset-> + InsetButtonPress(xpos, ypos, + button); + return; + } else { + unlockInset(the_locking_inset); } - - selection_possible = true; - screen->HideCursor(); + } + + selection_possible = true; + screen->HideCursor(); + + // Right button mouse click on a table + if (button == 3 && + (text->cursor.par->table || + text->MouseHitInTable(xpos, ypos + screen->first))) { + // Set the cursor to the press-position + text->SetCursorFromCoordinates(xpos, ypos + screen->first); + bool doit = true; + + // Only show the table popup if the hit is in + // the table, too + if (!text->HitInTable(text->cursor.row, xpos)) + doit = false; + + // Hit above or below the table? + if (doit) { + if (!text->selection) { + screen->ToggleSelection(); + text->ClearSelection(); + text->FullRebreak(); + screen->Update(); + updateScrollbar(); + } + // Popup table popup when on a table. + // This is obviously temporary, since we + // should be able to popup various + // context-sensitive-menus with the + // the right mouse. So this should be done more + // general in the future. Matthias. + selection_possible = false; + owner_->getLyXFunc() + ->Dispatch(LFUN_LAYOUT_TABLE, + "true"); + return; + } + } + + int screen_first = screen->first; + + // Middle button press pastes if we have a selection + bool paste_internally = false; + if (button == 2 + && text->selection) { + owner_->getLyXFunc()->Dispatch(LFUN_COPY); + paste_internally = true; + } + + // Clear the selection + screen->ToggleSelection(); + text->ClearSelection(); + text->FullRebreak(); + screen->Update(); + updateScrollbar(); + + // Single left click in math inset? + if (inset_hit != 0 && inset_hit->Editable() == 2) { + // Highly editable inset, like math + selection_possible = false; + owner_->updateLayoutChoice(); + owner_->getMiniBuffer()->Set(inset_hit->EditMessage()); + inset_hit->Edit(xpos, ypos); + return; + } + + // Right click on a footnote flag opens float menu + if (button == 3) { + selection_possible = false; + return; + } + + text->SetCursorFromCoordinates(xpos, ypos + screen_first); + text->FinishUndo(); + text->sel_cursor = text->cursor; + text->cursor.x_fix = text->cursor.x; + + owner_->updateLayoutChoice(); + if (screen->FitCursor()){ + updateScrollbar(); + selection_possible = false; + } + + // Insert primary selection with middle mouse + // if there is a local selection in the current buffer, + // insert this + if (button == 2) { + if (paste_internally) + owner_->getLyXFunc()->Dispatch(LFUN_PASTE); + else + owner_->getLyXFunc()->Dispatch(LFUN_PASTESELECTION, + "paragraph"); + selection_possible = false; + return; + } +} +#else +int BufferView::WorkAreaButtonPress(FL_OBJECT * ob, Window, + int /*w*/, int /*h*/, + XEvent * ev, void */*d*/) +{ + last_click_x = -1; + last_click_y = -1; + + if (buffer_ == 0) return 0; + if (!screen) return 0; + + int const x = ev->xbutton.x - ob->x; + int const y = ev->xbutton.y - ob->y; + // If we hit an inset, we have the inset coordinates in these + // and inset_hit points to the inset. If we do not hit an + // inset, inset_hit is 0, and inset_x == x, inset_y == y. + int inset_x = x; + int inset_y = y; + Inset * inset_hit = checkInsetHit(inset_x, inset_y); + + // ok ok, this is a hack. + int button = ev->xbutton.button; + if (button == 4 || button == 5) goto wheel; + + { + if (the_locking_inset) { + // We are in inset locking mode + + /* Check whether the inset was hit. If not reset mode, + otherwise give the event to the inset */ + if (inset_hit != 0) { + the_locking_inset-> + InsetButtonPress(inset_x, inset_y, + button); + return 0; + } else { + unlockInset(the_locking_inset); + } + } + + selection_possible = true; + screen->HideCursor(); // Right button mouse click on a table if (button == 3 && @@ -1039,8 +1512,164 @@ int BufferView::WorkAreaButtonPress(FL_OBJECT * ob, Window, return 0; } +#endif + + +#ifdef NEW_WA +void BufferView::WorkAreaButtonRelease(int x, int y, unsigned int button) +{ + if (buffer_ == 0 || screen == 0) return; + // If we hit an inset, we have the inset coordinates in these + // and inset_hit points to the inset. If we do not hit an + // inset, inset_hit is 0, and inset_x == x, inset_y == y. + Inset * inset_hit = checkInsetHit(x, y); + + if (the_locking_inset) { + // We are in inset locking mode. + /* LyX does a kind of work-area grabbing for insets. + Only a ButtonPress Event outside the inset will + force a InsetUnlock. */ + the_locking_inset-> + InsetButtonRelease(x, x, button); + return; + } + + selection_possible = false; + if (text->cursor.par->table) { + int cell = text-> + NumberOfCell(text->cursor.par, + text->cursor.pos); + if (text->cursor.par->table->IsContRow(cell) && + text->cursor.par->table-> + CellHasContRow(text->cursor.par->table-> + GetCellAbove(cell))<0) { + text->CursorUp(); + } + } + + if (button >= 2) return; + + SetState(); + owner_->getMiniBuffer()->Set(CurrentState()); + + // Did we hit an editable inset? + if (inset_hit != 0) { + // Inset like error, notes and figures + selection_possible = false; +#ifdef WITH_WARNINGS +#warning fix this proper in 0.13 +#endif + // Following a ref shouldn't issue + // a push on the undo-stack + // anylonger, now that we have + // keybindings for following + // references and returning from + // references. IMHO though, it + // should be the inset's own business + // to push or not push on the undo + // stack. They don't *have* to + // alter the document... + // (Joacim) + // ...or maybe the SetCursorParUndo() + // below isn't necessary at all anylonger? + if (inset_hit->LyxCode() == Inset::REF_CODE) { + text->SetCursorParUndo(); + } + + owner_->getMiniBuffer()->Set(inset_hit->EditMessage()); + inset_hit->Edit(x, y); + return; + } + + // check whether we want to open a float + if (text) { + bool hit = false; + char c = ' '; + if (text->cursor.pos < + text->cursor.par->Last()) { + c = text->cursor.par-> + GetChar(text->cursor.pos); + } + if (c == LyXParagraph::META_FOOTNOTE + || c == LyXParagraph::META_MARGIN + || c == LyXParagraph::META_FIG + || c == LyXParagraph::META_TAB + || c == LyXParagraph::META_WIDE_FIG + || c == LyXParagraph::META_WIDE_TAB + || c == LyXParagraph::META_ALGORITHM){ + hit = true; + } else if (text->cursor.pos - 1 >= 0) { + c = text->cursor.par-> + GetChar(text->cursor.pos - 1); + if (c == LyXParagraph::META_FOOTNOTE + || c == LyXParagraph::META_MARGIN + || c == LyXParagraph::META_FIG + || c == LyXParagraph::META_TAB + || c == LyXParagraph::META_WIDE_FIG + || c == LyXParagraph::META_WIDE_TAB + || c == LyXParagraph::META_ALGORITHM){ + // We are one step too far to the right + text->CursorLeft(); + hit = true; + } + } + if (hit == true) { + toggleFloat(); + selection_possible = false; + return; + } + } + + // Do we want to close a float? (click on the float-label) + if (text->cursor.row->par->footnoteflag == + LyXParagraph::OPEN_FOOTNOTE + //&& text->cursor.pos == 0 + && text->cursor.row->previous && + text->cursor.row->previous->par-> + footnoteflag != LyXParagraph::OPEN_FOOTNOTE){ + LyXFont font (LyXFont::ALL_SANE); + font.setSize(LyXFont::SIZE_FOOTNOTE); + + int box_x = 20; // LYX_PAPER_MARGIN; + box_x += font.textWidth(" wide-tab ", 10); + + int screen_first = screen->first; + + if (x < box_x + && y + screen_first > text->cursor.y - + text->cursor.row->baseline + && y + screen_first < text->cursor.y - + text->cursor.row->baseline + + font.maxAscent() * 1.2 + font.maxDescent() * 1.2) { + toggleFloat(); + selection_possible = false; + return; + } + } + + // Maybe we want to edit a bibitem ale970302 +#ifdef USE_PAINTER + if (text->cursor.par->bibkey && x < 20 + + bibitemMaxWidth(painter(), + textclasslist + .TextClass(buffer_-> + params.textclass).defaultfont())) { + text->cursor.par->bibkey->Edit(0, 0); + } +#else + if (text->cursor.par->bibkey && x < 20 + + bibitemMaxWidth(textclasslist + .TextClass(buffer_-> + params.textclass).defaultfont())) { + text->cursor.par->bibkey->Edit(0, 0); + } +#endif + + return; +} +#else int BufferView::WorkAreaButtonRelease(FL_OBJECT * ob, Window , int /*w*/, int /*h*/, XEvent * ev, void * /*d*/) @@ -1198,13 +1827,81 @@ int BufferView::WorkAreaButtonRelease(FL_OBJECT * ob, Window , return 0; } - +#endif /* * Returns an inset if inset was hit. 0 otherwise. * If hit, the coordinates are changed relative to the inset. * Otherwise coordinates are not changed, and false is returned. */ +#ifdef USE_PAINTER +Inset * BufferView::checkInsetHit(int & x, int & y) +{ + if (!getScreen()) + return 0; + + int y_tmp = y + getScreen()->first; + + LyXCursor & cursor = text->cursor; + LyXDirection direction = text->real_current_font.getFontDirection(); + + if (cursor.pos < cursor.par->Last() + && cursor.par->GetChar(cursor.pos) == LyXParagraph::META_INSET + && cursor.par->GetInset(cursor.pos) + && cursor.par->GetInset(cursor.pos)->Editable()) { + + // Check whether the inset really was hit + Inset * tmpinset = cursor.par->GetInset(cursor.pos); + LyXFont font = text->GetFont(cursor.par, cursor.pos); + int start_x, end_x; + if (direction == LYX_DIR_LEFT_TO_RIGHT) { + start_x = cursor.x; + end_x = cursor.x + tmpinset->width(painter(), font); + } else { + start_x = cursor.x - tmpinset->width(painter(), font); + end_x = cursor.x; + } + + if (x > start_x && x < end_x + && y_tmp > cursor.y - tmpinset->ascent(painter(), font) + && y_tmp < cursor.y + tmpinset->descent(painter(), font)) { + x = x - start_x; + // The origin of an inset is on the baseline + y = y_tmp - (cursor.y); + return tmpinset; + } + } + + if (cursor.pos - 1 >= 0 + && cursor.par->GetChar(cursor.pos - 1) == LyXParagraph::META_INSET + && cursor.par->GetInset(cursor.pos - 1) + && cursor.par->GetInset(cursor.pos - 1)->Editable()) { + text->CursorLeft(); + Inset * tmpinset = cursor.par->GetInset(cursor.pos); + LyXFont font = text->GetFont(cursor.par, cursor.pos); + int start_x, end_x; + if (direction == LYX_DIR_LEFT_TO_RIGHT) { + start_x = cursor.x; + end_x = cursor.x + tmpinset->width(painter(), font); + } else { + start_x = cursor.x - tmpinset->width(painter(), font); + end_x = cursor.x; + } + if (x > start_x && x < end_x + && y_tmp > cursor.y - tmpinset->ascent(painter(), font) + && y_tmp < cursor.y + tmpinset->descent(painter(), font)) { + x = x - start_x; + // The origin of an inset is on the baseline + y = y_tmp - (cursor.y); + return tmpinset; + } else { + text->CursorRight(); + return 0; + } + } + return 0; +} +#else Inset * BufferView::checkInsetHit(int & x, int & y) { if (!getScreen()) @@ -1271,8 +1968,65 @@ Inset * BufferView::checkInsetHit(int & x, int & y) } return 0; } +#endif + +#ifdef NEW_WA +void BufferView::workAreaExpose() +{ + // this is a hack to ensure that we only call this through + // BufferView::redraw(). + //if (!lgb_hack) { + // redraw(); + //} + + static int work_area_width = -1; + static int work_area_height = -1; + + bool widthChange = workarea->workWidth() != work_area_width; + bool heightChange = workarea->height() != work_area_height; + + // update from work area + work_area_width = workarea->workWidth(); + work_area_height = workarea->height(); + if (buffer_ != 0) { + if (widthChange) { + // All buffers need a resize + bufferlist.resize(); + + // Remove all texts from the textcache + // This is not _really_ what we want to do. What + // we really want to do is to delete in textcache + // that does not have a BufferView with matching + // width, but as long as we have only one BufferView + // deleting all gives the same result. + if (lyxerr.debugging()) + textcache.show(lyxerr, "Expose delete all"); + textcache.clear(); + } else if (heightChange) { + // Rebuild image of current screen + updateScreen(); + // fitCursor() ensures we don't jump back + // to the start of the document on vertical + // resize + fitCursor(); + + // The main window size has changed, repaint most stuff + redraw(); + // ...including the minibuffer + owner_->getMiniBuffer()->Init(); + } else if (screen) screen->Redraw(); + } else { + // Grey box when we don't have a buffer + workarea->greyOut(); + } + // always make sure that the scrollbar is sane. + updateScrollbar(); + owner_->updateLayoutChoice(); + return; +} +#else int BufferView::workAreaExpose() { if (!work_area || !work_area->form->visible) @@ -1333,6 +2087,7 @@ int BufferView::workAreaExpose() owner_->updateLayoutChoice(); return 1; } +#endif // Callback for cursor timer @@ -1440,6 +2195,83 @@ void BufferView::CursorToggleCB(FL_OBJECT * ob, long) } +#ifdef NEW_WA +static +string fromClipboard(Window win, XEvent * event) +{ + string strret; + if (event->xselection.type == XA_STRING + && event->xselection.property) { + Atom tmpatom; + unsigned long ul1; + unsigned long ul2; + unsigned char * uc = 0; + int tmpint; + if (XGetWindowProperty( + event->xselection.display, // display + win, // w + event->xselection.property, // property + 0, // long_offset + 0, // logn_length + False, // delete + XA_STRING, // req_type + &tmpatom, // actual_type_return + &tmpint, // actual_format_return + &ul1, + &ul2, + &uc // prop_return + ) != Success) { + return strret; + } + if (uc) { + free(uc); + uc = 0; + } + if (XGetWindowProperty( + event->xselection.display, // display + win, // w + event->xselection.property, // property + 0, // long_offset + ul2/4+1, // long_length + True, // delete + XA_STRING, // req_type + &tmpatom, // actual_type_return + &tmpint, // actual_format_return + &ul1, // nitems_return + &ul2, // bytes_after_return + &uc // prop_return */ + ) != Success) { + return strret; + } + if (uc) { + strret = reinterpret_cast(uc); + free(uc); // yes free! + uc = 0; + } + } + return strret; +} + + +void BufferView::WorkAreaSelectionNotify(Window win, XEvent * event) +{ + if (buffer_ == 0) return; + + screen->HideCursor(); + beforeChange(); + string clb = fromClipboard(win, event); + if (!clb.empty()) { + if (!ascii_type) + text->InsertStringA(clb.c_str()); + else + text->InsertStringB(clb.c_str()); + + update(1); + + } +} + +#else int BufferView::WorkAreaSelectionNotify(FL_OBJECT *, Window win, int /*w*/, int /*h*/, XEvent * event, void */*d*/) @@ -1513,8 +2345,29 @@ int BufferView::WorkAreaSelectionNotify(FL_OBJECT *, Window win, } return 0; } +#endif +#ifdef NEW_WA +void BufferView::cursorPrevious() +{ + if (!text->cursor.row->previous) return; + + long y = getScreen()->first; + Row * cursorrow = text->cursor.row; + text->SetCursorFromCoordinates(text->cursor.x_fix, y); + text->FinishUndo(); + // This is to allow jumping over large insets + if ((cursorrow == text->cursor.row)) + text->CursorUp(); + + if (text->cursor.row->height < workarea->height()) + getScreen()->Draw(text->cursor.y + - text->cursor.row->baseline + + text->cursor.row->height + - workarea->height() + 1 ); +} +#else void BufferView::cursorPrevious() { if (!text->cursor.row->previous) return; @@ -1533,8 +2386,29 @@ void BufferView::cursorPrevious() + text->cursor.row->height - work_area->h +1 ); } +#endif +#ifdef NEW_WA +void BufferView::cursorNext() +{ + if (!text->cursor.row->next) return; + + long y = getScreen()->first; + text->GetRowNearY(y); + Row * cursorrow = text->cursor.row; + text->SetCursorFromCoordinates(text->cursor.x_fix, y + + workarea->height()); + text->FinishUndo(); + // This is to allow jumping over large insets + if ((cursorrow == text->cursor.row)) + text->CursorDown(); + + if (text->cursor.row->height < workarea->height()) + getScreen()->Draw(text->cursor.y + - text->cursor.row->baseline); +} +#else void BufferView::cursorNext() { if (!text->cursor.row->next) return; @@ -1552,6 +2426,7 @@ void BufferView::cursorNext() getScreen()->Draw(text->cursor.y - text->cursor.row->baseline); } +#endif bool BufferView::available() const @@ -1692,3 +2567,21 @@ void BufferView::insetUnlock() inset_slept = false; } } + + +bool BufferView::focus() const +{ + return workarea->hasFocus(); +} + + +void BufferView::focus(bool f) +{ + if (f) workarea->setFocus(); +} + + +bool BufferView::active() const +{ + return workarea->active(); +} diff --git a/src/BufferView.h b/src/BufferView.h index fee341f300..abbc288d0d 100644 --- a/src/BufferView.h +++ b/src/BufferView.h @@ -21,11 +21,14 @@ #include "LaTeX.h" #include "undo.h" +#define NEW_WA 1 + class LyXView; class Buffer; class LyXScreen; class Inset; class LyXText; +class WorkArea; /// class BufferView { @@ -36,10 +39,23 @@ public: ~BufferView(); /// Buffer * buffer() const { return buffer_; } +#ifdef USE_PAINTER + /// + Painter & painter(); +#endif +#ifdef NEW_WA + /// + WorkArea * getWorkArea() { return workarea; } +#else /// FL_OBJECT * getWorkArea() { return work_area; } +#endif /// void buffer(Buffer * b); +#ifdef NEW_WA + /// + void resize(int, int, int, int); +#endif /// void resize(); /// @@ -175,10 +191,25 @@ public: /// void lockedInsetStoreUndo(Undo::undo_kind kind); private: + friend class WorkArea; + /// Update pixmap of screen void updateScreen(); +#ifdef NEW_WA + /// + void workAreaExpose(); + /// + void ScrollUpOnePage(); + /// + void ScrollDownOnePage(); +#else /// int workAreaExpose(); + /// + void ScrollUpOnePage(long /*time*/); + /// + void ScrollDownOnePage(long /*time*/); +#endif /// void create_view(int, int, int, int); /// @@ -187,20 +218,31 @@ private: int ScrollUp(long time); /// int ScrollDown(long time); - /// - void ScrollUpOnePage(long /*time*/); - /// - void ScrollDownOnePage(long /*time*/); public: + +#ifdef NEW_WA + /// + bool focus() const; + /// + void focus(bool); + /// + bool active() const; + /// A callback for the up arrow in the scrollbar. + void UpCB(long time, int button); + /// A callback for the slider in the scrollbar. + void ScrollCB(double); + /// A callback for the down arrow in the scrollbar. + void DownCB(long time, int button); +#else /// A callback for the up arrow in the scrollbar. static void UpCB(FL_OBJECT * ob, long); - /// A callback for the slider in the scrollbar. static void ScrollCB(FL_OBJECT * ob, long); /// A callback for the down arrow in the scrollbar. static void DownCB(FL_OBJECT * ob, long); +#endif /// static void CursorToggleCB(FL_OBJECT * ob, long); @@ -213,16 +255,22 @@ public: void SetState(); private: +#ifdef NEW_WA + /// + void WorkAreaMotionNotify(int x, int y, unsigned int state); + /// + void WorkAreaButtonPress(int x, int y, unsigned int button); + /// + void WorkAreaButtonRelease(int x, int y, unsigned int button); + /// + void WorkAreaSelectionNotify(Window win, XEvent * event); +#else /// int WorkAreaMotionNotify(FL_OBJECT * ob, Window win, int w, int h, XEvent * ev, void * d); /// - int WorkAreaSelectionNotify(FL_OBJECT *, Window win, - int /*w*/, int /*h*/, - XEvent * event, void * /*d*/); - /// int WorkAreaButtonPress(FL_OBJECT * ob, Window win, int w, int h, @@ -233,6 +281,11 @@ private: int w, int h, XEvent * ev, void * d); /// + int WorkAreaSelectionNotify(FL_OBJECT *, Window win, + int /*w*/, int /*h*/, + XEvent * event, void * /*d*/); +#endif + /// LyXView * owner_; /// Buffer * buffer_; @@ -244,22 +297,28 @@ private: bool lyx_focus; /// bool work_area_focus; +#ifndef NEW_WA /// FL_OBJECT * work_area; /// - FL_OBJECT * figinset_canvas; - /// FL_OBJECT * scrollbar; /// FL_OBJECT * button_down; /// FL_OBJECT * button_up; +#endif + /// + FL_OBJECT * figinset_canvas; /// FL_OBJECT * timer_cursor; /// BackStack backstack; /// int last_click_x, last_click_y; +#ifdef NEW_WA + /// + WorkArea * workarea; +#endif }; #endif diff --git a/src/FontLoader.C b/src/FontLoader.C index befabfb290..bc93386963 100644 --- a/src/FontLoader.C +++ b/src/FontLoader.C @@ -240,7 +240,11 @@ XFontStruct * FontLoader::doLoad(LyXFont::FONT_FAMILY family, f.setUnderbar(LyXFont::INHERIT); f.setNoun(LyXFont::INHERIT); f.setLatex(LyXFont::INHERIT); +#ifdef USE_PAINTER + f.setColor(LColor::inherit); +#else f.setColor(LyXFont::INHERIT_COLOR); +#endif lyxerr << "Font '" << f.stateText() << "' matched by\n" << font << endl; } diff --git a/src/LColor.C b/src/LColor.C new file mode 100644 index 0000000000..7dc85d233d --- /dev/null +++ b/src/LColor.C @@ -0,0 +1,176 @@ +// -*- C++ -*- +/* This file is part of + * ====================================================== + * + * LyX, The Document Processor + * + * Copyright 1998-2000 The LyX Team + * + *======================================================*/ + +#include + +#ifdef USE_PAINTER + +#ifdef __GNUG__ +#pragma implementation +#endif + +#include + +#include "debug.h" +#include "LColor.h" +#include "support/LAssert.h" +#include "gettext.h" +#include "support/lstrings.h" + + +void LColor::fill(LColor::color col, string const & gui, + string const & latex, string const & x11, + string const & lyx) { + information in; + in.guiname = gui; + in.latexname = latex; + in.x11name = x11; + in.lyxname = lyx; + + infotab[col] = in; +} + + +LColor::LColor() +{ + // LColor::color, gui, latex, x11, lyx + fill(none, _("none"), "none", "black", "none"); + fill(black, _("black"), "black", "black", "black"); + fill(white, _("white"), "white", "white", "white"); + fill(red, _("red"), "red", "red", "red"); + fill(green, _("green"), "green", "green", "green"); + fill(blue, _("blue"), "blue", "blue", "blue"); + fill(cyan, _("cyan"), "cyan", "cyan", "cyan"); + fill(magenta, _("magenta"), "magenta", "magenta", "magenta"); + fill(yellow, _("yellow"), "yellow", "yellow", "yellow"); + fill(background, _("background"), "background", "linen", "background"); + fill(foreground, _("foreground"), "foreground", "black", "foreground"); + fill(selection, _("selection"), "selection", "LightBlue", "selection"); + fill(latex, _("latex"), "latex", "DarkRed", "latex"); + fill(floats, _("floats"), "floats", "red", "floats"); + fill(note, _("note"), "note", "black", "note"); + fill(notebg, _("note background"), "notebg", "yellow", "notebg"); + fill(noteframe, _("note frame"), "noteframe", "black", "noteframe"); + fill(command, _("command-inset"), "command", "black", "command"); + fill(commandbg, _("command-inset background"), "commandbg", "grey50", "commandbg"); + fill(commandframe, _("inset frame"), "commandframe", "black", "commandframe"); + fill(accent, _("accent"), "accent", "black", "accent"); + fill(accentbg, _("accent background"), "accentbg", "offwhite", "accentbg"); + fill(accentframe, _("accent frame"), "accentframe", "linen", "accentframe"); + fill(minipageline, _("minipage line"), "minipageline", "violet", "minipageline"); + fill(special, _("special char"), "special", "RoyalBlue", "special"); + fill(math, _("math"), "math", "DarkBlue", "math"); + fill(mathbg, _("math background"), "mathbg", "AntiqueWhite", "mathbg"); + fill(mathframe, _("math frame"), "mathframe", "Magenta", "mathframe"); + fill(mathcursor, _("math cursor"), "mathcursor", "black", "mathcursor"); + fill(mathline, _("math line"), "mathline", "Blue", "mathline"); + fill(footnote, _("footnote"), "footnote", "DarkRed", "footnote"); + fill(footnotebg, _("footnote background"), "footnotebg", "grey40", "footnotebg"); + fill(footnoteframe, _("footnote frame"), "footnoteframe", "IndianRed", "footnoteframe"); + fill(ert, _("ert"), "ert", "DarkRed", "ert"); + fill(inset, _("inset"), "inset", "black", "inset"); + fill(insetbg, _("inset background"), "insetbg", "grey40", "insetbg"); + fill(insetframe, _("inset frame"), "insetframe", "IndianRed", "insetframe"); + fill(error, _("error"), "error", "Red", "error"); + fill(eolmarker, _("end-of-line marker"), "eolmarker", "Brown", "eolmarker"); + fill(appendixline, _("appendix line"), "appendixline", "Brown", "appendixline"); + fill(vfillline, _("vfill line"), "vfillline", "Brown", "vfillline"); + fill(topline, _("top/bottom line"), "topline", "Brown", "topline"); + fill(tableline, _("table line"), "tableline", "black", "tableline"); + fill(bottomarea, _("bottom area"), "bottomarea", "grey40", "bottomarea"); + fill(pagebreak, _("page break"), "pagebreak", "RoyalBlue", "pagebreak"); + fill(top, _("top of button"), "top", "grey80", "top"); + fill(bottom, _("bottom of button"), "bottom", "grey40", "bottom"); + fill(left, _("left of button"), "left", "grey80", "left"); + fill(right, _("right of button"), "right", "grey40", "right"); + fill(buttonbg, _("button background"), "buttonbg", "grey60", "buttonbg"); + fill(inherit, _("inherit"), "inherit", "black", "inherit"); + fill(ignore, _("ignore"), "ignore", "black", "ignore"); +} + + +string LColor::getGUIName(LColor::color c) const +{ + InfoTab::const_iterator ici = infotab.find(c); + if (ici != infotab.end()) + return (*ici).second.guiname; + + return "none"; +} + + +string LColor::getX11Name(LColor::color c) const +{ + InfoTab::const_iterator ici = infotab.find(c); + if (ici != infotab.end()) + return (*ici).second.x11name; + + lyxerr << "LyX internal error: Missing color" + " entry in LColor.C for " << int(c) << '\n'; + lyxerr << "Using black.\n"; + return "black"; +} + + +string LColor::getLaTeXName(LColor::color c) const +{ + InfoTab::const_iterator ici = infotab.find(c); + if (ici != infotab.end()) + return (*ici).second.latexname; + return "black"; +} + + +string LColor::getLyXName(LColor::color c) const +{ + InfoTab::const_iterator ici = infotab.find(c); + if (ici != infotab.end()) + return (*ici).second.lyxname; + return "black"; +} + + +void LColor::setColor(LColor::color col, string const & x11name) +{ + InfoTab::iterator iti = infotab.find(col); + if (iti != infotab.end()) { + (*iti).second.x11name = x11name; + return; + } + lyxerr << "LyX internal error: color and such.\n"; + Assert(false); +} + + +LColor::color LColor::getFromGUIName(string const & guiname) const +{ + InfoTab::const_iterator ici = infotab.begin(); + for (; ici != infotab.end(); ++ici) { + if (!compare_no_case((*ici).second.guiname, guiname)) + return (*ici).first; + } + return LColor::ignore; +} + + +LColor::color LColor::getFromLyXName(string const & lyxname) const +{ + InfoTab::const_iterator ici = infotab.begin(); + for (; ici != infotab.end(); ++ici) { + if (!compare_no_case((*ici).second.lyxname, lyxname)) + return (*ici).first; + } + return LColor::ignore; +} + +// The evil global LColor instance +LColor lcolor; + +#endif diff --git a/src/LColor.h b/src/LColor.h new file mode 100644 index 0000000000..848a29c700 --- /dev/null +++ b/src/LColor.h @@ -0,0 +1,208 @@ +// -*- C++ -*- +/* This file is part of + * ====================================================== + * + * LyX, The Document Processor + * + * Copyright 1998-2000 The LyX Team + * + *======================================================*/ + +#ifdef USE_PAINTER + +#ifndef LCOLOR_H +#define LCOLOR_H + +#ifdef __GNUG__ +#pragma interface +#endif + +#include + +#include "LString.h" + +/** + This is a stateless class. + + It has one basic purposes: + To serve as a color-namespace container (the Color enum). + + A color can be one of the following kinds: + + - A real, predefined color, such as black, white, red or green. + - A logical color, such as no color, inherit, math + + */ + +class LColor { +public: + /// Names of colors, including all logical colors + enum color { + /// No particular color---clear or default + none, + /// The different text colors + black, + /// + white, + /// + red, + /// + green, + /// + blue, + /// + cyan, + /// + magenta, + /// + yellow, + + /// Needed interface colors + + /// Background color + background, + /// Foreground color + foreground, + /// Background color of selected text + selection, + /// Text color in LaTeX mode + latex, + /// Titles color of floats + floats, + + /// Text color for notes + note, + /// Background color of notes + notebg, + /// Frame color for notes + noteframe, + + + /// Text color for command insets + command, + /// Background color for command insets + commandbg, + /// Frame color for command insets + commandframe, + + /// Text color for accents we can't handle nicely + accent, + /// + accentbg, + /// + accentframe, + + /// Minipage line color + minipageline, + + /// Special chars text color + special, + + /// Math inset text color + math, + /// Math inset background color + mathbg, + /// Math inset frame color + mathframe, + /// Math cursor color + mathcursor, + /// Math line color + mathline, + + /// Footnote marker text + footnote, + /// Footnote marker background color + footnotebg, + /// Footnote line color + footnoteframe, + + /// ERT marker text + ert, + + /// Text color for inset marker + inset, + /// Inset marker background color + insetbg, + /// Inset marker frame color + insetframe, + + /// Error box text color + error, + /// EOL marker color + eolmarker, + /// Appendix line color + appendixline, + /// VFill line color + vfillline, + /// Top and bottom line color + topline, + /// Table line color + tableline, + /// Bottom area color + bottomarea, + /// Page break color + pagebreak, + + /// Color used for top of boxes + top, + /// Color used for bottom of boxes + bottom, + /// Color used for left side of boxes + left, + /// Color used for right side of boxes + right, + /// Color used for bottom background + buttonbg, + + /// Logical attributes + + /// Color is inherited + inherit, + /// For ignoring updates of a color + ignore + }; + + /// + LColor(); + /// + void setColor(LColor::color col, string const & x11name); + /// Get GUI name of color + string getGUIName(LColor::color c) const; + + /// Get X11 name of color + string getX11Name(LColor::color c) const; + + /// Get LaTeX name of color + string getLaTeXName(LColor::color c) const; + + /// Get LyX name of color + string getLyXName(LColor::color c) const; + /// + LColor::color getFromGUIName(string const & guiname) const; + /// + LColor::color getFromLyXName(string const & lyxname) const; +private: + /// + struct information { + string guiname; + string latexname; + string x11name; + string lyxname; + }; + + /// + void fill(LColor::color col, string const & gui, + string const & latex, string const & x11, + string const & lyx); + + /// + typedef map > InfoTab; + + InfoTab infotab; +}; + +extern LColor lcolor; + +#endif + +#endif diff --git a/src/LyXView.C b/src/LyXView.C index 148ff63dda..e083bb851f 100644 --- a/src/LyXView.C +++ b/src/LyXView.C @@ -351,8 +351,14 @@ int LyXView::KeyPressMask_raw_callback(FL_FORM * fl, void * xev) // also KeyRelease-events are passed through:-( // [It seems that XForms puts them in pairs... (JMarc)] if (static_cast(xev)->type == KeyPress +#ifdef NEW_WA + && view->bufferview->focus() + && view->bufferview->active()) +#else && view->bufferview->getWorkArea()->focus - && view->bufferview->getWorkArea()->active) { + && view->bufferview->getWorkArea()->active) +#endif + { #ifdef USE_XSYNC last_time_pressed = xke->time; last_key_pressed = xke->keycode; @@ -363,8 +369,14 @@ int LyXView::KeyPressMask_raw_callback(FL_FORM * fl, void * xev) } #ifdef USE_XSYNC else if (static_cast(xev)->type == KeyRelease +#ifdef NEW_WA + && view->bufferview->focus() + && view->bufferview->active()) +#else && view->bufferview->getWorkArea()->focus - && view->bufferview->getWorkArea()->active) { + && view->bufferview->getWorkArea()->active) +#endif +{ last_time_released = xke->time; last_key_released = xke->keycode; last_state_released = xke->state; diff --git a/src/Makefile.am b/src/Makefile.am index b4f1f1c114..1e9d043a95 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -28,6 +28,8 @@ lyx_SOURCES = \ ImportLaTeX.h \ ImportNoweb.C \ ImportNoweb.h \ + LColor.C \ + LColor.h \ LString.h \ LaTeX.C \ LaTeX.h \ @@ -42,6 +44,10 @@ lyx_SOURCES = \ LyXView.C \ LyXView.h \ Makefile.in \ + Painter.C \ + Painter.h \ + PainterBase.C \ + PainterBase.h \ PaperLayout.C \ ParagraphExtra.C \ Spacing.C \ @@ -49,6 +55,8 @@ lyx_SOURCES = \ TableLayout.C \ TextCache.C \ TextCache.h \ + WorkArea.C \ + WorkArea.h \ bibforms.h \ bmtable.c \ bmtable.h \ diff --git a/src/Painter.C b/src/Painter.C new file mode 100644 index 0000000000..d052f05b4f --- /dev/null +++ b/src/Painter.C @@ -0,0 +1,456 @@ +// -*- C++ -*- +/* This file is part of + * ====================================================== + * + * LyX, The Document Processor + * + * Copyright 1998-2000 The LyX Team + * + *======================================================*/ + +#include + +#ifdef USE_PAINTER + +#ifdef __GNUG__ +#pragma implementation +#endif + +#include + +#ifdef USE_STL_MEMORY +#include +#endif + +#include FORMS_H_LOCATION +#include "Painter.h" +#include "LString.h" +#include "debug.h" +#include "lyxfont.h" +#include "support/LAssert.h" +#include "support/lstrings.h" + +Painter::Painter(WorkArea & wa) + : PainterBase(wa) +{ + colormap = fl_state[fl_get_vclass()].colormap; + // Clear the GC cache + for (int i=0; i <= LColor::ignore; ++i) { + colorGCcache[i] = 0; + } +} + + +Painter::~Painter() { + // Release all the registered GCs + for (int i=0; i <= LColor::ignore; ++i) { + if (colorGCcache[i] != 0) { + XFreeGC(display, colorGCcache[i]); + } + } + // Iterate over the line cache and Free the GCs + LineGCCache::iterator lit = lineGCcache.begin(); + for (; lit != lineGCcache.end(); ++lit) { + XFreeGC(display, (*lit).second); + } +} + + +/* Basic drawing routines */ + +extern bool Lgb_bug_find_hack; + +Painter & Painter::point(int x, int y, LColor::color c) +{ + if (lyxerr.debugging()) { + if (!Lgb_bug_find_hack) + lyxerr << "point not called from " + "workarea::workhandler\n"; + lyxerr.debug() << "Painter drawable: " << drawable << endl; + } + + XDrawPoint(display, drawable, getGCForeground(c), x, y); + return *this; +} + + +Painter & Painter::line(int x1, int y1, int x2, int y2, + LColor::color col, + enum line_style ls, + enum line_width lw) +{ + if (lyxerr.debugging()) { + if (!Lgb_bug_find_hack) + lyxerr << "line not called from " + "workarea::workhandler\n"; + lyxerr.debug() << "Painter drawable: " << drawable << endl; + } + + XDrawLine(display, drawable, + getGCLinepars(ls, lw, col), x1, y1, x2, y2); + return *this; +} + + +Painter & Painter::lines(int const * xp, int const * yp, int np, + LColor::color col, + enum line_style ls, + enum line_width lw) +{ + if (lyxerr.debugging()) { + if (!Lgb_bug_find_hack) + lyxerr << "lines not called from " + "workarea::workhandler\n"; + lyxerr.debug() << "Painter drawable: " << drawable << endl; + } + +#ifndef HAVE_AUTO_PTR + XPoint * points = new XPoint[np]; +#else + auto_ptr points(new Xpoint[np]); +#endif + for (int i=0; i points(new XPoint[np]); +#endif + for (int i=0; i s(new XSegment[ns]); +#endif + for (int i=0; iwidth(s, f)); + return *this; +} + + +Painter & Painter::text(int x, int y, char const * s, int ls, + LyXFont const & f) +{ + if (lyxerr.debugging()) { + if (!Lgb_bug_find_hack) + lyxerr << "text not called from " + "workarea::workhandler\n"; + lyxerr << "Painter drawable: " << drawable << endl; + } + + GC gc = getGCForeground(f.realColor()); + XSetFont(display, gc, f.getFontID()); + XDrawString(display, drawable, gc, x, y, s, ls); + underline(f, x, y, this->width(s, ls, f)); + return *this; +} + + +Painter & Painter::text(int x, int y, char c, LyXFont const & f) +{ + if (lyxerr.debugging()) { + if (!Lgb_bug_find_hack) + lyxerr << "text not called from " + "workarea::workhandler\n"; + lyxerr << "Painter drawable: " << drawable << endl; + } + + GC gc = getGCForeground(f.realColor()); + XSetFont(display, gc, f.getFontID()); + char s[2]; + s[0] = c; s[1] = '\0'; + XDrawString(display, drawable, gc, x, y, s, 1); + underline(f, x, y, this->width(c, f)); + return *this; +} + + +void Painter::underline(LyXFont const & f, int x, int y, int width) { + // What about underbars? + if (f.underbar() == LyXFont::ON && f.latex() != LyXFont::ON) { + int below = f.maxDescent() / 2; + if (below < 2) below = 2; + int height = (f.maxDescent() / 4) - 1; + if (height < 0) height = 0; + fillRectangle(x, y + below, width, below + height, f.color()); + } +} + + +// Gets GC according to color +// Uses caching +GC Painter::getGCForeground(LColor::color c) +{ + if (lyxerr.debugging()) { + lyxerr << "Painter drawable: " << drawable << endl; + } + + if (colorGCcache[c] != 0) return colorGCcache[c]; + + XColor xcol, ccol; + string s = lcolor.getX11Name(c); + XGCValues val; + + // Look up the RGB values for the color, and an approximate + // color that we can hope to get on this display. + if (XLookupColor(display, colormap, s.c_str(), &xcol, &ccol) == 0) { + lyxerr << _("LyX: Unknown X11 color ") << s + << _(" for ") << lcolor.getGUIName(c) << '\n' + << _(" Using black instead, sorry!.") << endl; + unsigned long bla = BlackPixel(display, + DefaultScreen(display)); + val.foreground = bla; + // Try the exact RGB values first, then the approximate. + } else if (XAllocColor(display, colormap, &xcol) != 0) { + lyxerr << _("LyX: X11 color ") << s + << _(" allocated for ") + << lcolor.getGUIName(c) << endl; + val.foreground = xcol.pixel; + } else if (XAllocColor(display, colormap, &ccol)) { + lyxerr << _("LyX: Using approximated X11 color ") << s + << _(" allocated for ") + << lcolor.getGUIName(c) << endl; + val.foreground = xcol.pixel; + } else { + // Here we are traversing the current colormap to find + // the color closest to the one we want. + Visual * vi = DefaultVisual(display, DefaultScreen(display)); + + XColor * cmap = new XColor[vi->map_entries]; + + for(int i = 0; i < vi->map_entries; ++i) { + cmap[i].pixel = i; + } + XQueryColors(display, colormap, cmap, vi->map_entries); + + // Walk through the cmap and look for close colors. + int closest_pixel = 0; + double closest_distance = 1e20; // we want to minimize this + double distance = 0; + for(int t = 0; t < vi->map_entries; ++t) { + // The Euclidean distance between two points in + // a three-dimensional space, the RGB color-cube, + // is used as the distance measurement between two + // colors. + + // Since square-root is monotonous, we don't have to + // take the square-root to find the minimum, and thus + // we use the squared distance instead to be faster. + + // If we want to get fancy, we could convert the RGB + // coordinates to a different color-cube, maybe HSV, + // but the RGB cube seems to work great. (Asger) + distance = pow(cmap[t].red - xcol.red, 2.0) + + pow(cmap[t].green - xcol.green, 2.0) + + pow(cmap[t].blue - xcol.blue, 2.0); + if (distance < closest_distance) { + closest_distance = distance; + closest_pixel = t; + } + } + lyxerr << _("LyX: Couldn't allocate '") << s + << _("' for ") << lcolor.getGUIName(c) + << _(" with (r,g,b)=(") + << xcol.red << "," << xcol.green << "," + << xcol.blue << ").\n" + << _(" Using closest allocated " + "color with (r,g,b)=(") + << cmap[closest_pixel].red << "," + << cmap[closest_pixel].green << "," + << cmap[closest_pixel].blue << ") instead.\n" + << "Pixel [" << closest_pixel << "] is used." << endl; + val.foreground = cmap[closest_pixel].pixel; + delete[] cmap; + } + + val.function = GXcopy; + return colorGCcache[c] = XCreateGC(display, drawable, + GCForeground | GCFunction, &val); +} + + +// Gets GC for line +GC Painter::getGCLinepars(enum line_style ls, + enum line_width lw, LColor::color c) +{ + if (lyxerr.debugging()) { + lyxerr << "Painter drawable: " << drawable << endl; + } + + int index = lw + (ls << 1) + (c << 3); + + if (lineGCcache.find(index) != lineGCcache.end()) + return lineGCcache[index]; + + XGCValues val; + XGetGCValues(display, getGCForeground(c), GCForeground, &val); + + switch (lw) { + case line_thin: val.line_width = 0; break; + case line_thick: val.line_width = 2; break; + } + + switch (ls) { + case line_solid: val.line_style = LineSolid; break; + case line_onoffdash: val.line_style = LineOnOffDash; break; + case line_doubledash: val.line_style = LineDoubleDash; break; + } + + + val.cap_style = CapRound; + val.join_style = JoinRound; + val.function = GXcopy; + + return lineGCcache[index] = + XCreateGC(display, drawable, + GCForeground | GCLineStyle | GCLineWidth | + GCCapStyle | GCJoinStyle | GCFunction, &val); +} + +#endif diff --git a/src/Painter.h b/src/Painter.h new file mode 100644 index 0000000000..0c7ed2a933 --- /dev/null +++ b/src/Painter.h @@ -0,0 +1,140 @@ +// -*- C++ -*- +/* This file is part of + * ====================================================== + * + * LyX, The Document Processor + * + * Copyright 1999-2000 The LyX Team + * + * ======================================================*/ + +#ifdef USE_PAINTER + +#ifndef PAINTER_H +#define PAINTER_H + +#ifdef __GNUG__ +#pragma interface +#endif + +#include "config.h" +#include "LString.h" + +// This is only included to provide stuff for the non-public sections +#include + +#include +#include "PainterBase.h" +#include "LColor.h" + +class LyXFont; +class WorkArea; + +/** An inplementation for the X Window System. Xlib. + + Classes similar to this one can be made for gtk+, Qt, etc. + */ +class Painter : public PainterBase { +public: + /// Constructor + Painter(WorkArea &); + + /// Destructor + ~Painter(); + + /**@Basic drawing routines */ + /// Draw a line from point to point + Painter & line(int x1, int y1, int x2, int y2, + LColor::color = LColor::foreground, + enum line_style = line_solid, + enum line_width = line_thin); + + /// Here xp and yp are arrays of points + Painter & lines(int const * xp, int const * yp, int np, + LColor::color = LColor::foreground, + enum line_style = line_solid, + enum line_width = line_thin); + + /// Here xp and yp are arrays of points + Painter & fillPolygon(int const * xp, int const * yp, int np, + LColor::color = LColor::foreground); + + /// Draw lines from x1,y1 to x2,y2. They are arrays + Painter & segments(int const * x1, int const * y1, + int const * x2, int const * y2, int ns, + LColor::color = LColor::foreground, + enum line_style = line_solid, + enum line_width = line_thin); + + /// Draw a rectangle + Painter & rectangle(int x, int y, int w, int h, + LColor::color = LColor::foreground, + enum line_style = line_solid, + enum line_width = line_thin); + + /// Draw an arc + Painter & arc(int x, int y, unsigned int w, unsigned int h, + int a1, int a2, + LColor::color = LColor::foreground); + + /// Draw a pixel + Painter & point(int x, int y, LColor::color = LColor::foreground); + + /// Fill a rectangle + Painter & fillRectangle(int x, int y, int w, int h, + LColor::color = LColor::background); + + /**@Image stuff */ + + /// For the figure inset + Painter & pixmap(int x, int y, Pixmap bitmap); + + /**@String functions */ + + /// Draw a string at position x, y (y is the baseline) + Painter & text(int x, int y, string const & str, LyXFont const & f); + + /** Draw a string at position x, y (y is the baseline) + This is just for fast drawing */ + Painter & text(int x, int y, char const * str, int l, + LyXFont const & f); + + /// Draw a char at position x, y (y is the baseline) + Painter & text(int x, int y, char c, LyXFont const & f); + +protected: + /**@Support for X only, by now */ + friend class WorkArea; + /// + Painter & setDisplay(Display * d) { display = d; return *this; } + + /// + Painter & setDrawable(Drawable d) { drawable = d; return *this; } + + /// Get foreground color in ordinary GC + GC getGCForeground(LColor::color c); + + /// Set up GC according to line style + GC getGCLinepars(enum line_style, enum line_width, LColor::color c); + + /// Check the font, and if set, draw an underline + void underline(LyXFont const & f, int x, int y, int width); + + /**@Low level X parameters */ + /// + Display * display; + /// + Drawable drawable; + /// + Colormap colormap; + + /// Caching of ordinary color GCs + GC colorGCcache[LColor::ignore + 1]; + /// Caching of GCs used for lines + typedef map > LineGCCache; + /// + LineGCCache lineGCcache; +}; +#endif + +#endif diff --git a/src/PainterBase.C b/src/PainterBase.C new file mode 100644 index 0000000000..30e1ea9210 --- /dev/null +++ b/src/PainterBase.C @@ -0,0 +1,145 @@ +/* This file is part of + * ====================================================== + * + * LyX, The Document Processor + * + * Copyright 1998-2000 The LyX Team + * + *======================================================*/ + +#include + +#ifdef USE_PAINTER + +#ifdef __GNUG__ +#pragma implementation +#endif + +#include "PainterBase.h" +#include "lyxfont.h" +#include "WorkArea.h" + + +int PainterBase::dummy1 = 0; +int PainterBase::dummy2 = 0; +int PainterBase::dummy3 = 0; + +int PainterBase::paperMargin() +{ + return 20; +} + + +int PainterBase::paperWidth() +{ + return owner.workWidth(); +} + + +int PainterBase::width(string const & s, LyXFont const & f) +{ + return f.stringWidth(s); +} + + +int PainterBase::width(char const * s, int l, LyXFont const & f) +{ + return f.textWidth(s, l); +} + + +int PainterBase::width(char c, LyXFont const & f) +{ + return f.width(c); +} + + +PainterBase & PainterBase::circle(int x, int y, unsigned int d, + LColor::color col = LColor::foreground) +{ + return ellipse(x, y, d, d, col); +} + + +PainterBase & PainterBase::ellipse(int x, int y, + unsigned int w, unsigned int h, + LColor::color col = LColor::foreground) +{ + return arc(x, y, w, h, 0, 0, col); +} + + +PainterBase & PainterBase::button(int x, int y, int w, int h) +{ + fillRectangle(x, y, w, h, LColor::buttonbg); + buttonFrame(x, y, w, h); + return * this; +} + + +PainterBase & PainterBase::buttonFrame(int x, int y, int w, int h) +{ + // Width of a side of the button + int d = 2; + + fillRectangle(x, y, w, d, LColor::top); + fillRectangle(x, (y+h-d), w, d, LColor::bottom); + + // Now a couple of trapezoids + int x1[4], y1[4]; + + x1[0] = x+d; y1[0] = y+d; + x1[1] = x+d; y1[1] = (y+h-d); + x1[2] = x; y1[2] = y+h; + x1[3] = x; y1[3] = y; + fillPolygon(x1, y1, 4, LColor::left); + + x1[0] = (x+w-d); y1[0] = y+d; + x1[1] = (x+w-d); y1[1] = (y+h-d); + x1[2] = x+w; y1[2] = (y+h-d); + x1[3] = x+w; y1[3] = y; + fillPolygon(x1, y1, 4, LColor::right); + + return *this; +} + + +PainterBase & PainterBase::rectText(int x, int baseline, + string const & str, + LyXFont const & font, + LColor::color back, + LColor::color frame, bool draw, + int & width, int & ascent, int & descent) +{ + static int const d = 2; + width = this->width(str, font) + d * 2 + 2; + ascent = font.maxAscent() + d; + descent = font.maxDescent() + d; + + if (!draw) return *this; + + rectangle(x, baseline - ascent, width, ascent + descent, frame); + fillRectangle(x + 1, baseline - ascent + 1, width - 1, + ascent + descent - 1, back); + text(x + d, baseline, str, font); + return *this; +} + + +PainterBase & PainterBase::buttonText(int x, int baseline, + string const & str, + LyXFont const & font, bool draw, + int & width, int & ascent, int & descent) +{ + width = this->width(str, font) + 8; + ascent = font.maxAscent() + 3; + descent = font.maxDescent() + 3; + + if (!draw) return *this; + + button(x, baseline - ascent, width, descent + ascent); + text(x + 4, baseline, str, font); + return *this; +} + +#endif diff --git a/src/PainterBase.h b/src/PainterBase.h new file mode 100644 index 0000000000..ab05dda522 --- /dev/null +++ b/src/PainterBase.h @@ -0,0 +1,206 @@ +// -*- C++ -*- +/* This file is part of + * ====================================================== + * + * LyX, The Document Processor + * + * Copyright 1998-2000 The LyX Team + * + *======================================================*/ + +#ifdef USE_PAINTER + +#ifndef PAINTERBASE_H +#define PAINTERBASE_H + +#ifdef __GNUG__ +#pragma interface +#endif + +#include "LString.h" +#include "LColor.h" + +class WorkArea; +class LyXFont; +class LyXScreen; + +/** A painter class to encapsulate all graphics parameters and operations + + Every graphics operation in LyX should be made by this class. It will + be initialized and managed by the Screen class, and will be passed + as a parameter to inset. + + It hides low level windows system parameters so insets and other + clients don't have to worry about them and we can control graphics and + GUI toolkit dependent drawing functions inside this single class. + + */ +class PainterBase { +protected: + /// + static int dummy1, dummy2, dummy3; +public: + /// + enum line_width { + /// + line_thin, + /// + line_thick + }; + + /// + enum line_style { + /// + line_solid, + /// + line_doubledash, + /// + line_onoffdash + }; + + /// + PainterBase(WorkArea & wa) : owner(wa) {} + + /// + virtual ~PainterBase() {} + + /** Screen geometry */ + /// + int paperMargin(); + /// + int paperWidth(); + + /**@Basic drawing routines */ + /// Draw a line from point to point + virtual PainterBase & line( + int x1, int y1, int x2, int y2, + LColor::color = LColor::foreground, + enum line_style = line_solid, + enum line_width = line_thin) = 0; + + /** Draw the lines between the lines in xp and yp. + xp and yp are arrays of points, and np is the + number of them. */ + virtual PainterBase & lines( + int const * xp, int const * yp, int np, + LColor::color = LColor::foreground, + enum line_style = line_solid, + enum line_width = line_thin) = 0; + + /// Here xp and yp are arrays of points + virtual PainterBase & fillPolygon( + int const * xp, int const * yp, + int np, + LColor::color =LColor::foreground) = 0; + + /// Draw lines from x1,y1 to x2,y2. They are arrays + virtual PainterBase & segments( + int const * x1, int const * y1, + int const * x2, int const * y2, int ns, + LColor::color = LColor::foreground, + enum line_style = line_solid, + enum line_width = line_thin) = 0; + + /// Draw a rectangle + virtual PainterBase & rectangle( + int x, int y, int w, int h, + LColor::color = LColor::foreground, + enum line_style = line_solid, + enum line_width = line_thin) = 0; + + /// Draw a circle, d is the diameter, not the radious + virtual PainterBase & circle( + int x, int y, unsigned int d, + LColor::color = LColor::foreground); + + /// Draw an ellipse + virtual PainterBase & ellipse( + int x, int y, + unsigned int w, unsigned int h, + LColor::color = LColor::foreground); + + /// Draw an arc + virtual PainterBase & arc( + int x, int y, + unsigned int w, unsigned int h, + int a1, int a2, + LColor::color = LColor::foreground) = 0; + + /// Draw a pixel + virtual PainterBase & point( + int x, int y, + LColor::color = LColor::foreground) = 0; + + /// Fill a rectangle + virtual PainterBase & fillRectangle( + int x, int y, int w, int h, + LColor::color = LColor::background) = 0; + + /// A filled rectangle with the shape of a 3D button + virtual PainterBase & button(int x, int y, int w, int h); + + /// + virtual PainterBase & buttonFrame(int x, int y, int w, int h); + + /**@Image stuff */ + + /// For the figure inset + // This can't be part of the base since we don't know what window + // system we will be useing, or if are going to use pixmaps at all. + //virtual PainterBase & pixmap(int x, int y, Pixmap bitmap)=0; + + + /**@String functions */ + + /// Draw a string at position x, y (y is the baseline) + virtual PainterBase & text(int x, int y, + string const &str, LyXFont const & f) = 0; + + /** Draw a string at position x, y (y is the baseline) + This is just for fast drawing */ + virtual PainterBase & text(int x, int y, char const * str, int l, + LyXFont const & f) = 0; + + /// Draw a char at position x, y (y is the baseline) + virtual PainterBase & text(int x, int y, char c, LyXFont const & f)=0; + + /// Get the width of text + int width(string const & s, LyXFont const & f); + + /** Get the width of text + This is just for fast width */ + int width(char const * s, int l, LyXFont const & f); + + /// Get the width of text + int width(char c, LyXFont const & f); + + /** Draws a string and encloses it inside a rectangle. Returns + the size of the rectangle. If draw is false, we only calculate + the size. */ + virtual PainterBase & rectText(int x, int baseline, + string const & string, + LyXFont const & font, + LColor::color back, + LColor::color frame, bool draw = true, + int & width = PainterBase::dummy1, + int & ascent = PainterBase::dummy2, + int & descent = PainterBase::dummy3); + + /** Draw a string and encloses it inside a button frame. Returns + the size of the frame. If draw is false, we only calculate + the size. */ + virtual PainterBase & buttonText(int x, int baseline, string const & s, + LyXFont const & font, bool draw = true, + int & width = PainterBase::dummy1, + int & ascent = PainterBase::dummy2, + int & descent = PainterBase::dummy3); + /// This is preliminary + //BufferView const * getOwner() const { return &owner; } + +private: + WorkArea & owner; +}; + +#endif + +#endif diff --git a/src/WorkArea.C b/src/WorkArea.C new file mode 100644 index 0000000000..68a62c53eb --- /dev/null +++ b/src/WorkArea.C @@ -0,0 +1,421 @@ +/* This file is part of + * ====================================================== + * + * LyX, The Document Processor + * + * Copyright 1995 Matthias Ettrich + * Copyright 1995-2000 The LyX Team. + * + * ====================================================== */ + +#include +#include + +#ifdef __GNUG__ +#pragma implementation +#endif + +#include "WorkArea.h" +#include "up.xpm" +#include "down.xpm" +#include "debug.h" +#include "support/lstrings.h" +#include "BufferView.h" + +#ifdef NEW_WA +FL_OBJECT * figinset_canvas; +#endif + +static inline +void waitForX() +{ + XSync(fl_get_display(), 0); +} + + +WorkArea::WorkArea(BufferView * o, int xpos, int ypos, int width, int height) + : owner(o), workareapixmap(0) +#ifdef USE_PAINTER + , painter_(*this) +#endif +{ + fl_freeze_all_forms(); + + figinset_canvas = 0; + + lyxerr << "Creating work area: +" + << xpos << '+' << ypos << ' ' + << width << 'x' << height << endl; + // + FL_OBJECT * obj; + const int bw = int(abs(float(fl_get_border_width()))); + + // We really want to get rid of figinset_canvas. + ::figinset_canvas = figinset_canvas = obj = + fl_add_canvas(FL_NORMAL_CANVAS, + xpos + 1, ypos + 1, 1, 1, ""); + fl_set_object_boxtype(obj, FL_NO_BOX); + fl_set_object_resize(obj, FL_RESIZE_ALL); + fl_set_object_gravity(obj, NorthWestGravity, NorthWestGravity); + + // a box + lyxerr << "\tbackground box: +" + << xpos << '+' << ypos << ' ' + << width - 15 << 'x' << height << endl; + backgroundbox = obj = fl_add_box(FL_BORDER_BOX, + xpos, ypos, + width - 15, + height,""); + fl_set_object_resize(obj, FL_RESIZE_ALL); + fl_set_object_gravity(obj, NorthWestGravity, SouthEastGravity); + + // + // THE SCROLLBAR + // + + // up - scrollbar button + fl_set_border_width(-1); + + lyxerr << "\tup button: +" + << xpos + width - 15 << '+' << ypos << ' ' + << 15 << 'x' << 15 << endl; + button_up = obj = fl_add_pixmapbutton(FL_TOUCH_BUTTON, + xpos + width - 15, + ypos, + 15, 15, ""); + fl_set_object_boxtype(obj,FL_UP_BOX); + fl_set_object_color(obj,FL_MCOL,FL_BLUE); + fl_set_object_resize(obj, FL_RESIZE_ALL); + fl_set_object_gravity(obj,NorthEastGravity, NorthEastGravity); + obj->u_vdata = this; + fl_set_object_callback(obj,up_cb, 0); + fl_set_pixmapbutton_data(obj, const_cast(up_xpm)); + + // Remove the blue feedback rectangle + fl_set_pixmapbutton_focus_outline(obj,0); + + // the scrollbar slider + fl_set_border_width(-bw); + lyxerr << "\tscrollbar slider: +" + << xpos + width - 15 << '+' << ypos + 15 << ' ' + << 15 << 'x' << height - 30 << endl; + scrollbar = obj = fl_add_slider(FL_VERT_SLIDER, + xpos + width - 15, + ypos + 15, + 15, height - 30, ""); + fl_set_object_color(obj,FL_COL1,FL_MCOL); + fl_set_object_boxtype(obj, FL_UP_BOX); + fl_set_object_resize(obj, FL_RESIZE_ALL); + fl_set_object_gravity(obj, NorthEastGravity, SouthEastGravity); + obj->u_vdata = this; + fl_set_object_callback(obj, scroll_cb, 0); + fl_set_slider_precision(obj, 0); + + // down - scrollbar button + fl_set_border_width(-1); + + lyxerr << "\tdown button: +" + << xpos + width - 15 << '+' << ypos + height - 15 << ' ' + << 15 << 'x' << 15 << endl; + button_down = obj = fl_add_pixmapbutton(FL_TOUCH_BUTTON, + xpos + width - 15, + ypos + height - 15, + 15, 15, ""); + fl_set_object_boxtype(obj,FL_UP_BOX); + fl_set_object_color(obj,FL_MCOL,FL_BLUE); + fl_set_object_resize(obj, FL_RESIZE_ALL); + fl_set_object_gravity(obj, SouthEastGravity, SouthEastGravity); + obj->u_vdata = this; + fl_set_object_callback(obj, down_cb, 0); + fl_set_pixmapbutton_data(obj, const_cast(down_xpm)); + + fl_set_border_width(-bw); + + // Remove the blue feedback rectangle + fl_set_pixmapbutton_focus_outline(obj,0); + + /// + /// The free object + + // Create the workarea pixmap + createPixmap(width - 15 - 2 * bw, height - 2 * bw); +#ifdef USE_PAINTER + // setup the painter + painter_.setDisplay(fl_display); + painter_.setDrawable(workareapixmap); +#endif + + // We add this object as late as possible to avoit problems + // with drawing. + lyxerr << "\tfree object: +" + << xpos + bw << '+' << ypos + bw << ' ' + << width - 15 - 2 * bw << 'x' << height - 2 * bw << endl; + work_area = obj = fl_add_free(FL_INPUT_FREE, + xpos + bw, ypos + bw, + width - 15 - 2 * bw, // scrollbarwidth + height - 2 * bw, "", + work_area_handler); + obj->wantkey = FL_KEY_TAB; + obj->u_vdata = this; /* This is how we pass the WorkArea + to the work_area_handler. */ + fl_set_object_boxtype(obj,FL_DOWN_BOX); + fl_set_object_resize(obj, FL_RESIZE_ALL); + fl_set_object_gravity(obj, NorthWestGravity, SouthEastGravity); + + fl_unfreeze_all_forms(); +} + + +WorkArea::~WorkArea() +{ + if (workareapixmap) + XFreePixmap(fl_display, workareapixmap); +} + + +void WorkArea::resize(int xpos, int ypos, int width, int height) +{ + fl_freeze_all_forms(); + + const int bw = int(abs(float(fl_get_border_width()))); + + // a box + fl_set_object_geometry(backgroundbox, xpos, ypos, width - 15, height); + + // + // THE SCROLLBAR + // + + // up - scrollbar button + fl_set_object_geometry(button_up, xpos + width - 15, + ypos, + 15, 15); + // the scrollbar slider + fl_set_object_geometry(scrollbar, xpos + width - 15, + ypos + 15, + 15, height - 30); + // down - scrollbar button + fl_set_object_geometry(button_down, xpos + width - 15, + ypos + height - 15, + 15, 15); + + // Create the workarea pixmap + createPixmap(width - 15 - 2 * bw, height - 2 * bw); + +#ifdef USE_PAINTER + // reset the painter + painter_.setDrawable(workareapixmap); +#endif + + // the free object + fl_set_object_geometry(work_area, xpos + bw, ypos + bw, + width - 15 - 2 * bw, + height - 2 * bw); + + fl_unfreeze_all_forms(); + +} + + +void WorkArea::createPixmap(int width, int height) +{ + static int cur_width = -1; + static int cur_height = -1; + + if (cur_width == width && cur_height == height && workareapixmap) + return; + + cur_width = width; + cur_height = height; + + if (workareapixmap) + XFreePixmap(fl_display, workareapixmap); + + lyxerr << "Creating pixmap (" << width << 'x' << height << ")" << endl; + + workareapixmap = XCreatePixmap(fl_display, + RootWindow(fl_display, 0), + width, + height, + fl_get_visual_depth()); + lyxerr << "\tpixmap=" << workareapixmap << endl; +} + + +void WorkArea::greyOut() const +{ + fl_winset(FL_ObjWin(work_area)); + fl_rectangle(1, work_area->x, work_area->y, + work_area->w, work_area->h, FL_GRAY63); +} + + +void WorkArea::setFocus() const +{ + fl_set_focus_object(work_area->form, work_area); +} + + +void WorkArea::setScrollbar(double pos, double length_fraction) const +{ + fl_set_slider_value(scrollbar, pos); + fl_set_slider_size(scrollbar, scrollbar->h * length_fraction); +} + + +void WorkArea::setScrollbarBounds(double l1, double l2) const +{ + fl_set_slider_bounds(scrollbar, l1, l2); +} + + +void WorkArea::setScrollbarIncrements(float inc) const +{ + fl_set_slider_increment(scrollbar, work_area->h - inc, inc); +} + + +void WorkArea::up_cb(FL_OBJECT * ob, long) +{ + WorkArea * area = static_cast(ob->u_vdata); + XEvent const * ev2 = fl_last_event(); + static long time = 0; + ev2 = fl_last_event(); + if (ev2->type == ButtonPress || ev2->type == ButtonRelease) + time = 0; + //area->up(time++, fl_get_button_numb(ob)); + area->owner->UpCB(time++, fl_get_button_numb(ob)); +} + + +void WorkArea::down_cb(FL_OBJECT * ob, long) +{ + WorkArea * area = static_cast(ob->u_vdata); + XEvent const * ev2 = fl_last_event(); + static long time = 0; + if (ev2->type == ButtonPress || ev2->type == ButtonRelease) + time = 0; + //area->down(time++, fl_get_button_numb(ob)); + area->owner->DownCB(time++, fl_get_button_numb(ob)); +} + + +// Callback for scrollbar slider +void WorkArea::scroll_cb(FL_OBJECT * ob, long) +{ + WorkArea * area = static_cast(ob->u_vdata); + + //area->scroll(fl_get_slider_value(ob)); + area->owner->ScrollCB(fl_get_slider_value(ob)); + waitForX(); +} + +bool Lgb_bug_find_hack = false; + +int WorkArea::work_area_handler(FL_OBJECT * ob, int event, + FL_Coord, FL_Coord , + int /*key*/, void * xev) +{ + static int x_old = -1; + static int y_old = -1; + static long scrollbar_value_old = -1; + + XEvent * ev = static_cast(xev); + WorkArea * area = static_cast(ob->u_vdata); + + if (!area) return 1; + + switch (event){ + case FL_DRAW: + if (!area->work_area || + !area->work_area->form->visible) + return 1; + lyxerr.debug() << "Workarea event: DRAW" << endl; + area->createPixmap(area->workWidth(), area->height()); + Lgb_bug_find_hack = true; + //area->expose(); + area->owner->workAreaExpose(); + Lgb_bug_find_hack = false; + break; + case FL_PUSH: + if (!ev) break; + // Should really have used xbutton.state + lyxerr.debug() << "Workarea event: PUSH" << endl; + //area->buttonPress(ev->xbutton.x - ob->x, + // ev->xbutton.y - ob->y, + // ev->xbutton.button); + area->owner->WorkAreaButtonPress(ev->xbutton.x - ob->x, + ev->xbutton.y - ob->y, + ev->xbutton.button); + break; + case FL_RELEASE: + if (!ev) break; + // Should really have used xbutton.state + lyxerr.debug() << "Workarea event: RELEASE" << endl; + //area->buttonRelease(ev->xbutton.x - ob->x, + // ev->xbutton.y - ob->y, + // ev->xbutton.button); + area->owner->WorkAreaButtonRelease(ev->xbutton.x - ob->x, + ev->xbutton.y - ob->y, + ev->xbutton.button); + break; + case FL_MOUSE: + if (!ev || ! area->scrollbar) break; + if (ev->xmotion.x != x_old || + ev->xmotion.y != y_old || + fl_get_slider_value(area->scrollbar) != scrollbar_value_old) { + lyxerr.debug() << "Workarea event: MOUSE" << endl; + //area->motion(ev->xmotion.x - ob->x, + // ev->xmotion.y - ob->y, + // ev->xbutton.state); + area->owner->WorkAreaMotionNotify(ev->xmotion.x - ob->x, + ev->xmotion.y - ob->y, + ev->xbutton.state); + } + break; + // Done by the raw callback: + // case FL_KEYBOARD: WorkAreaKeyPress(ob, 0,0,0,ev,0); break; + case FL_FOCUS: + lyxerr.debug() << "Workarea event: FOCUS" << endl; + //area->focus(); + break; + case FL_UNFOCUS: + lyxerr.debug() << "Workarea event: UNFOCUS" << endl; + //area->unfocus(); + break; + case FL_ENTER: + lyxerr.debug() << "Workarea event: ENTER" << endl; + //area->enter(); + break; + case FL_LEAVE: + lyxerr.debug() << "Workarea event: LEAVE" << endl; + //area->leave(); + break; + case FL_DBLCLICK: + if (!ev) break; + lyxerr.debug() << "Workarea event: DBLCLICK" << endl;; + //area->doubleclick(ev->xbutton.x, + // ev->xbutton.y, + // ev->xbutton.button); + break; + case FL_TRPLCLICK: + if (!ev) break; + lyxerr.debug() << "Workarea event: TRPLCLICK" << endl; + //area->trippleclick(ev->xbutton.x, + // ev->xbutton.y, + // ev->xbutton.button); + break; + case FL_OTHER: + if (!ev) break; + if (ev->type == SelectionNotify) { + lyxerr.debug() << "Workarea event: SELECTION" << endl; + //area->selection(area->work_area->form->window, ev); + area->owner->WorkAreaSelectionNotify(area->work_area->form->window, ev); + } else + lyxerr.debug() << "Workarea event: OTHER" << endl; + + break; + } + + return 1; +} diff --git a/src/WorkArea.h b/src/WorkArea.h new file mode 100644 index 0000000000..99cf3d538f --- /dev/null +++ b/src/WorkArea.h @@ -0,0 +1,149 @@ +// -*- C++ -*- +/* This file is part of + * ====================================================== + * + * LyX, The Document Processor + * + * Copyright 1995 Matthias Ettrich + * Copyright 1995-2000 The LyX Team. + * + * ======================================================*/ + +#ifndef WORKAREA_H +#define WORKAREA_H + +#ifdef __GNUG__ +#pragma interface +#endif + +#include + +#include FORMS_H_LOCATION +#include "Painter.h" + +class BufferView; + +class WorkArea { +public: + /// + WorkArea(BufferView *, int xpos, int ypos, int width, int height); + /// + ~WorkArea(); +#ifdef USE_PAINTER + /// + Painter & getPainter() { return painter_; } +#endif + /// + int workWidth() const { return work_area->w; } + /// + int width() const { return work_area->w + scrollbar->w; } + /// + int height() const { return work_area->h; } + /// + int xpos() const { return work_area->x; } + /// + int ypos() const { return work_area->y; } + /// + void resize(int xpos, int ypos, int width, int height); + /// + void redraw() const { + fl_redraw_object(work_area); + fl_redraw_object(scrollbar); + fl_redraw_object(button_down); + fl_redraw_object(button_up); + } + /// + void setFocus() const; + /// + Window getWin() const { return work_area->form->window; } + /// + bool hasFocus() const { return work_area->focus; } + /// + bool active() const { return work_area->active; } + /// + bool visible() const { return work_area->form->visible; } + /// + void greyOut() const; + /// + void setScrollbar(double pos, double length_fraction) const; + /// + void setScrollbarValue(double y) const { fl_set_slider_value(scrollbar, y); } + /// + void setScrollbarBounds(double, double) const; + /// + void setScrollbarIncrements(float inc) const; + /// + double getScrollbarValue() const { + return fl_get_slider_value(scrollbar); + } + /// + pair getScrollbarBounds() const { + pair p; + fl_get_slider_bounds(scrollbar, &p.first, &p.second); + return p; + } + /// + Pixmap getPixmap() const { return workareapixmap; } + /// + //Signal2 up; + /// + //Signal2 down; + /// + //Signal1 scroll; + /// + //Signal0 expose; + /// + //Signal3 buttonPress; + /// + //Signal3 buttonRelease; + /// + //Signal3 motion; + /// + //Signal0 focus; + /// + //Signal0 unfocus; + /// + //Signal0 enter; + /// + //Signal0 leave; + /// + //Signal3 doubleclick; + /// + //Signal3 trippleclick; + /// + //Signal2 selection; +private: + /// + void createPixmap(int, int); + /// xforms callback + static int work_area_handler(FL_OBJECT *, int event, + FL_Coord, FL_Coord, + int /*key*/, void * xev); + /// xforms callback + static void up_cb(FL_OBJECT *, long); + /// xforms callback + static void down_cb(FL_OBJECT *, long); + /// xforms callback + static void scroll_cb(FL_OBJECT *, long); + /// + FL_OBJECT * backgroundbox; + /// + FL_OBJECT * work_area; + /// + FL_OBJECT * scrollbar; + /// + FL_OBJECT * button_down; + /// + FL_OBJECT * button_up; + /// + BufferView * owner; + /// The pixmap overlay on the workarea + Pixmap workareapixmap; +#ifdef USE_PAINTER + /// + Painter painter_; +#endif + /// + FL_OBJECT * figinset_canvas; +}; +#endif diff --git a/src/bmtable.c b/src/bmtable.c index 4e98d7a29b..ae87405a25 100644 --- a/src/bmtable.c +++ b/src/bmtable.c @@ -253,10 +253,9 @@ void fl_set_bmtable_pixmap_data(FL_OBJECT * ob, int nx, int ny, char ** pdata) { BMTABLE_SPEC * sp = (BMTABLE_SPEC *)ob->spec; - extern Colormap color_map; if (sp) { Pixmap dummy_shapemask = 0; - XpmAttributes dumb_attributes; + XpmAttributes dumb_attributes = { 0 }; sp->nx = nx; sp->ny = ny; sp->bx = FL_abs(ob->bw); @@ -266,7 +265,7 @@ void fl_set_bmtable_pixmap_data(FL_OBJECT * ob, int nx, int ny, sp->i = -1; sp->maxi = sp->nx * sp->ny; sp->bdata = 0; - dumb_attributes.colormap = color_map; + dumb_attributes.colormap = fl_state[fl_get_vclass()].colormap; dumb_attributes.closeness = 30000; dumb_attributes.valuemask = XpmColormap | XpmCloseness; if (XCreatePixmapFromData(fl_display, fl_winget(), pdata, @@ -279,7 +278,6 @@ void fl_set_bmtable_pixmap_data(FL_OBJECT * ob, int nx, int ny, XFreePixmap(fl_display, dummy_shapemask); } } - XFlush(fl_display); } } @@ -315,11 +313,11 @@ void fl_set_bmtable_file(FL_OBJECT * ob, int nx, int ny, char const * filename) void fl_set_bmtable_pixmap_file(FL_OBJECT *ob, int nx, int ny, char const *filename) { - extern Colormap color_map; + //extern Colormap color_map; BMTABLE_SPEC *sp = (BMTABLE_SPEC *)ob->spec; if (sp) { Pixmap dummy_shapemask = 0; - XpmAttributes dumb_attributes; + XpmAttributes dumb_attributes = { 0 }; sp->nx = nx; sp->ny = ny; sp->bx = FL_abs(ob->bw); @@ -330,7 +328,7 @@ void fl_set_bmtable_pixmap_file(FL_OBJECT *ob, int nx, int ny, char const *filen sp->maxi = sp->nx * sp->ny; sp->bdata = 0; - dumb_attributes.colormap = color_map; + dumb_attributes.colormap = fl_state[fl_get_vclass()].colormap; dumb_attributes.closeness = 30000; dumb_attributes.valuemask = XpmColormap | XpmCloseness; @@ -344,7 +342,7 @@ void fl_set_bmtable_pixmap_file(FL_OBJECT *ob, int nx, int ny, char const *filen XFreePixmap(fl_display, dummy_shapemask); } } - XFlush(fl_display); + //XFlush(fl_display); } } diff --git a/src/insets/figinset.C b/src/insets/figinset.C index ff31fbf71f..0c43edfb02 100644 --- a/src/insets/figinset.C +++ b/src/insets/figinset.C @@ -65,6 +65,7 @@ using std::flush; #include "lyx_gui_misc.h" // CancelCloseBoxCB #include "support/FileInfo.h" #include "support/lyxlib.h" +#include "Painter.h" extern BufferView * current_view; extern FL_OBJECT * figinset_canvas; @@ -112,7 +113,29 @@ static int gs_allcolors; // number of all colors static list pidwaitlist; // pid wait list -extern Colormap color_map; +//extern Colormap color_map; + + + +static +GC createGC() +{ + XGCValues val; + val.foreground = BlackPixel(fl_display, + DefaultScreen(fl_display)); + + val.function=GXcopy; + val.graphics_exposures = false; + val.line_style = LineSolid; + val.line_width = 0; + return XCreateGC(fl_display, RootWindow(fl_display, 0), + GCForeground | GCFunction | GCGraphicsExposures + | GCLineWidth | GCLineStyle , &val); +} + +static +GC local_gc_copy; + void addpidwait(int pid) { @@ -158,11 +181,15 @@ extern "C" int GhostscriptMsg(FL_OBJECT *, Window, int, int, //XColor * cmap; XWindowAttributes wa; register XImage * im; - int i, y, wid1, spc1 = gs_spc-1, - spc2 = gs_spc * gs_spc, wid = p->wid, - forkstat; + int i; + int y; + int wid1; + int spc1 = gs_spc-1; + int spc2 = gs_spc * gs_spc; + int wid = p->wid; + int forkstat; Display * tmpdisp; - GC gc = getGC(gc_copy); + GC gc = local_gc_copy; XGetWindowAttributes(fl_display, fl_get_canvas_id( @@ -212,7 +239,11 @@ extern "C" int GhostscriptMsg(FL_OBJECT *, Window, int, int, // query current colormap XColor * cmap = new XColor[gs_allcolors]; for (i = 0; i < gs_allcolors; ++i) cmap[i].pixel = i; +#if 1 + XQueryColors(tmpdisp, fl_state[fl_get_vclass()].colormap, cmap, gs_allcolors); +#else XQueryColors(tmpdisp, color_map, cmap, gs_allcolors); +#endif XFlush(tmpdisp); wid1 = p->wid - 1; // now we process all the image @@ -297,8 +328,10 @@ static void AllocColors(int num) xcol.green = 65535 * ((i / num) % num) / (num - 1); xcol.blue = 65535 * (i % num) / (num - 1); xcol.flags = DoRed | DoGreen | DoBlue; - if (!XAllocColor(fl_display, color_map, &xcol)) { - if (i) XFreeColors(fl_display, color_map, + if (!XAllocColor(fl_display, + fl_state[fl_get_vclass()].colormap, &xcol)) { + if (i) XFreeColors(fl_display, + fl_state[fl_get_vclass()].colormap, gs_pixels, i, 0); if(lyxerr.debugging()) { lyxerr << "Cannot allocate color cube " @@ -335,8 +368,10 @@ void AllocGrays(int num) for (int i = 0; i < num; ++i) { xcol.red = xcol.green = xcol.blue = 65535 * i / (num - 1); xcol.flags = DoRed | DoGreen | DoBlue; - if (!XAllocColor(fl_display, color_map, &xcol)) { - if (i) XFreeColors(fl_display, color_map, + if (!XAllocColor(fl_display, + fl_state[fl_get_vclass()].colormap, &xcol)) { + if (i) XFreeColors(fl_display, + fl_state[fl_get_vclass()].colormap, gs_pixels, i, 0); if (lyxerr.debugging()) { lyxerr << "Cannot allocate grayscale " @@ -358,12 +393,8 @@ void InitFigures() bmparrsize = figarrsize = figallocchunk; typedef Figref * Figref_p; figures = new Figref_p[figallocchunk]; - //figures = static_cast - // (malloc(sizeof(Figref*) * figallocchunk)); typedef figdata * figdata_p; bitmaps = new figdata_p[figallocchunk]; - //bitmaps = static_cast - //(malloc(sizeof(figdata*) * figallocchunk)); unsigned int k; for (unsigned int i = 0; i < 256; ++i) { @@ -376,12 +407,15 @@ void InitFigures() fl_add_canvas_handler(figinset_canvas, ClientMessage, GhostscriptMsg, current_view->owner()->getMainForm()); +#if 0 // now we have to init color_map if (!color_map) color_map = DefaultColormap(fl_display, DefaultScreen(fl_display)); +#endif // allocate color cube on pseudo-color display // first get visual gs_color = false; + local_gc_copy = createGC(); Visual * vi = DefaultVisual(fl_display, DefaultScreen(fl_display)); if (lyxerr.debugging()) { @@ -410,8 +444,6 @@ void InitFigures() void DoneFigures() { - //free(figures); - //free(bitmaps); delete[] figures; delete[] bitmaps; figarrsize = 0; @@ -422,12 +454,14 @@ void DoneFigures() fl_remove_canvas_handler(figinset_canvas, ClientMessage, GhostscriptMsg); +#if 0 if (gs_color) { lyxerr.debug() << "Freeing up the colors..." << endl; XFreeColors(fl_display, color_map, gs_pixels, gs_num_pixels, 0); /******????????????????? what's planes in this case ??????***/ } +#endif } @@ -609,6 +643,17 @@ static void runqueue() break; } +#ifdef USE_PAINTER + if (reverse_video) { + sprintf(tbuf+1, " %ld %ld", WhitePixelOfScreen( + DefaultScreenOfDisplay(fl_display)), + fl_get_pixel(FL_BLACK)); + } else { + sprintf(tbuf+1, " %ld %ld", BlackPixelOfScreen( + DefaultScreenOfDisplay(fl_display)), + fl_get_pixel(FL_WHITE)); + } +#else if (reverse_video) { sprintf(tbuf+1, " %ld %ld", WhitePixelOfScreen( DefaultScreenOfDisplay(fl_display)), @@ -618,6 +663,7 @@ static void runqueue() DefaultScreenOfDisplay(fl_display)), background_pixels); } +#endif XChangeProperty(tempdisp, fl_get_canvas_id(figinset_canvas), @@ -638,8 +684,6 @@ static void runqueue() while (environ[ne]) ++ne; typedef char * char_p; env = new char_p[ne + 2]; - //env = static_cast - // (malloc(sizeof(char*) * (ne + 2))); env[0] = tbuf2; memcpy(&env[1], environ, sizeof(char*) * (ne + 1)); environ = env; @@ -735,12 +779,9 @@ static figdata * getfigdata(int wid, int hgh, string const & fname, bmparrsize += figallocchunk; typedef figdata * figdata_p; figdata ** tmp = new figdata_p[bmparrsize]; - //figdata ** tmp = static_cast - // (malloc(sizeof(figdata*) * bmparrsize)); memcpy(tmp, bitmaps, sizeof(figdata*) * (bmparrsize - figallocchunk)); delete[] bitmaps; - //free(bitmaps); bitmaps = tmp; } figdata * p = new figdata; @@ -799,7 +840,6 @@ static void makeupdatelist(figdata * p) << figures[i]->inset << endl; } - //UpdateInset(figures[i]->inset); // add inset figures[i]->inset into to_update list PutInsetIntoInsetUpdateList(figures[i]->inset); } @@ -907,12 +947,9 @@ static void RegisterFigure(InsetFig * fi) figarrsize += figallocchunk; typedef Figref * Figref_p; Figref ** tmp = new Figref_p[figarrsize]; - //Figref ** tmp = static_cast - // (malloc(sizeof(Figref*)*figarrsize)); memcpy(tmp, figures, sizeof(Figref*)*(figarrsize-figallocchunk)); delete[] figures; - //free(figures); figures = tmp; } Figref * tmpfig = new Figref; @@ -1013,24 +1050,98 @@ InsetFig::~InsetFig() } +#ifdef USE_PAINTER +int InsetFig::ascent(Painter &, LyXFont const &) const +{ + return hgh + 3; +} +#else int InsetFig::Ascent(LyXFont const &) const { return hgh + 3; } +#endif +#ifdef USE_PAINTER +int InsetFig::descent(Painter &, LyXFont const &) const +{ + return 1; +} +#else int InsetFig::Descent(LyXFont const &) const { return 1; } +#endif +#ifdef USE_PAINTER +int InsetFig::width(Painter &, LyXFont const &) const +{ + return wid + 2; +} +#else int InsetFig::Width(LyXFont const &) const { return wid + 2; } +#endif + + +#ifdef USE_PAINTER +void InsetFig::draw(Painter & pain, LyXFont const & f, + int baseline, float & x) const +{ + LyXFont font(f); + + if (bitmap_waiting) getbitmaps(); + + // I wish that I didn't have to use this + // but the figinset code is so complicated so + // I don't want to fiddle with it now. +#if 0 + unsigned long pm = pain.getScreen()->getForeground(); + if (figure && figure->data && figure->data->bitmap && + !figure->data->reading && !figure->data->broken) { + // draw the bitmap + XCopyArea(fl_display, figure->data->bitmap, pm, getGC(gc_copy), + 0, 0, wid, hgh, int(x+1), baseline-hgh); + XFlush(fl_display); + if (flags & 4) XDrawRectangle(fl_display, pm, getGC(gc_copy), + int(x), baseline - hgh - 1, + wid+1, hgh+1); + } else { +#endif + char * msg = 0; + // draw frame + pain.rectangle(x, baseline - hgh - 1, wid + 1, hgh + 1); + if (figure && figure->data) { + if (figure->data->broken) msg = _("[render error]"); + else if (figure->data->reading) msg = _("[rendering ... ]"); + } else + if (fname.empty()) msg = _("[no file]"); + else if ((flags & 3) == 0) msg = _("[not displayed]"); + else if (lyxrc->ps_command.empty()) msg = _("[no ghostscript]"); + + if (!msg) msg = _("[unknown error]"); + + font.setFamily(LyXFont::SANS_FAMILY); + font.setSize(LyXFont::SIZE_FOOTNOTE); + string justname = OnlyFilename (fname); + pain.text(int(x + 8), baseline - font.maxAscent() - 4, + justname, font); + + font.setSize(LyXFont::SIZE_TINY); + pain.text(int(x + 8), baseline - 4, msg, strlen(msg), font); +#if 0 + } +#endif + x += width(pain, font); // ? +} +#else void InsetFig::Draw(LyXFont font, LyXScreen & scr, int baseline, float & x) { if (bitmap_waiting) getbitmaps(); @@ -1043,16 +1154,16 @@ void InsetFig::Draw(LyXFont font, LyXScreen & scr, int baseline, float & x) if (figure && figure->data && figure->data->bitmap && !figure->data->reading && !figure->data->broken) { // draw the bitmap - XCopyArea(fl_display, figure->data->bitmap, pm, getGC(gc_copy), + XCopyArea(fl_display, figure->data->bitmap, pm, local_gc_copy, 0, 0, wid, hgh, int(x+1), baseline-hgh); XFlush(fl_display); - if (flags & 4) XDrawRectangle(fl_display, pm, getGC(gc_copy), + if (flags & 4) XDrawRectangle(fl_display, pm, local_gc_copy, int(x), baseline - hgh - 1, wid+1, hgh+1); } else { char * msg = 0; // draw frame - XDrawRectangle(fl_display, pm, getGC(gc_copy), + XDrawRectangle(fl_display, pm, local_gc_copy, int(x), baseline - hgh - 1, wid+1, hgh+1); if (figure && figure->data) { @@ -1079,6 +1190,7 @@ void InsetFig::Draw(LyXFont font, LyXScreen & scr, int baseline, float & x) } x += Width(font); // ? } +#endif void InsetFig::Write(ostream & os) @@ -1324,7 +1436,6 @@ void InsetFig::Regenerate() cmd = "\\fbox{\\rule[-0.5in]{0pt}{1in}"; cmd += _("empty figure path"); cmd += '}'; - //if (form) fl_set_object_label(form->cmd, ""); return; } @@ -1434,8 +1545,6 @@ void InsetFig::Regenerate() } cmd = cmdbuf; - - //if (form) fl_set_object_label(form->cmd, cmd.c_str()); } @@ -1452,8 +1561,6 @@ void InsetFig::TempRegenerate() float txhgh = atof(fl_get_input(form->Height)); if (!tfname || !*tfname) { - //fl_set_object_label(form->cmd, ""); - //fl_redraw_object(form->cmd); cmd = "\\fbox{\\rule[-0.5in]{0pt}{1in}"; cmd += _("empty figure path"); cmd += '}'; diff --git a/src/insets/figinset.h b/src/insets/figinset.h index 43d29e2173..ee06f05b5d 100644 --- a/src/insets/figinset.h +++ b/src/insets/figinset.h @@ -24,6 +24,17 @@ public: InsetFig(int tmpx, int tmpy, Buffer *); /// ~InsetFig(); +#ifdef USE_PAINTER + /// + int ascent(Painter &, LyXFont const & font) const; + /// + int descent(Painter &, LyXFont const & font) const; + /// + int width(Painter &, LyXFont const & font) const; + /// + void draw(Painter &, LyXFont const & font, + int baseline, float & x) const; +#else /// int Ascent(LyXFont const & font) const; /// @@ -32,6 +43,7 @@ public: int Width(LyXFont const & font) const; /// void Draw(LyXFont font, LyXScreen & scr, int baseline, float & x); +#endif /// void Write(ostream &); /// diff --git a/src/insets/insetbib.C b/src/insets/insetbib.C index 26bc362f67..7b8eb3e7ef 100644 --- a/src/insets/insetbib.C +++ b/src/insets/insetbib.C @@ -472,6 +472,23 @@ void BibitemUpdate(Combox * combox) // ale070405 This function maybe shouldn't be here. We'll fix this at 0.13. +#ifdef USE_PAINTER +int bibitemMaxWidth(Painter & pain, LyXFont const & font) +{ + int w = 0; + // Does look like a hack? It is! (but will change at 0.13) + LyXParagraph * par = current_view->buffer()->paragraph; + + while (par) { + if (par->bibkey) { + int wx = par->bibkey->width(pain, font); + if (wx > w) w = wx; + } + par = par->next; + } + return w; +} +#else int bibitemMaxWidth(LyXFont const & font) { int w = 0; @@ -487,9 +504,36 @@ int bibitemMaxWidth(LyXFont const & font) } return w; } +#endif -// ale070405 +// ale070405 +#ifdef USE_PAINTER +string bibitemWidthest(Painter & pain) +{ + int w = 0; + // Does look like a hack? It is! (but will change at 0.13) + LyXParagraph * par = current_view->buffer()->paragraph; + InsetBibKey * bkey = 0; + LyXFont font; + + while (par) { + if (par->bibkey) { + int wx = par->bibkey->width(pain, font); + if (wx > w) { + w = wx; + bkey = par->bibkey; + } + } + par = par->next; + } + + if (bkey && !bkey->getScreenLabel().empty()) + return bkey->getScreenLabel(); + + return "99"; +} +#else string bibitemWidthest() { int w = 0; @@ -514,3 +558,4 @@ string bibitemWidthest() return "99"; } +#endif diff --git a/src/insets/insetbib.h b/src/insets/insetbib.h index 0c023f6051..04ec9d3d5e 100644 --- a/src/insets/insetbib.h +++ b/src/insets/insetbib.h @@ -5,7 +5,7 @@ * LyX, The Document Processor * * Copyright 1995 Matthias Ettrich - * Copyright 1995-1999 The LyX Team. + * Copyright 1995-2000 The LyX Team. * * ====================================================== */ diff --git a/src/insets/insetcommand.C b/src/insets/insetcommand.C index 9f85c9ea5c..1b0566ff05 100644 --- a/src/insets/insetcommand.C +++ b/src/insets/insetcommand.C @@ -17,6 +17,7 @@ #include "insetcommand.h" #include "lyxdraw.h" #include "debug.h" +#include "Painter.h" InsetCommand::InsetCommand() { @@ -30,22 +31,49 @@ InsetCommand::InsetCommand(string const & cmd, string const & arg, } +#ifdef USE_PAINTER +int InsetCommand::ascent(Painter &, LyXFont const & font) const +{ + LyXFont f = font; + f.decSize(); + return f.maxAscent() + 3; +} +#else int InsetCommand::Ascent(LyXFont const & font) const { LyXFont f = font; f.decSize(); return f.maxAscent() + 3; } +#endif +#ifdef USE_PAINTER +int InsetCommand::descent(Painter &, LyXFont const & font) const +{ + LyXFont f = font; + f.decSize(); + return f.maxDescent() + 3; +} +#else int InsetCommand::Descent(LyXFont const & font) const { LyXFont f = font; f.decSize(); return f.maxDescent() + 3; } +#endif +#ifdef USE_PAINTER +int InsetCommand::width(Painter &, LyXFont const & font) const +{ + LyXFont f = font; + f.decSize(); + string s = getScreenLabel(); + return 10 + f.stringWidth(s); +} +#else int InsetCommand::Width(LyXFont const & font) const { LyXFont f = font; @@ -53,8 +81,44 @@ int InsetCommand::Width(LyXFont const & font) const string s = getScreenLabel(); return 10 + f.stringWidth(s); } +#endif +#ifdef USE_PAINTER +void InsetCommand::draw(Painter & pain, LyXFont const & font, + int baseline, float & x) const +{ + // Draw it as a box with the LaTeX text + x += 3; + + pain.fillRectangle(int(x), baseline - ascent(pain, font) + 1, + width(pain, font) - 6, + ascent(pain, font) + descent(pain, font) - 2, + LColor::insetbg); + // Tell whether this slows down the drawing (ale) + // lets draw editable and non-editable insets differently + if (Editable()) { + int y = baseline - ascent(pain, font) + 1; + int w = width(pain, font) - 6; + int h = ascent(pain, font) + descent(pain, font) - 2; + pain.rectangle(int(x), y, w, h, LColor::insetframe); + } else { + + pain.rectangle(int(x), baseline - ascent(pain, font) + 1, + width(pain, font) - 6, + ascent(pain, font) + descent(pain, font) - 2, + LColor::insetframe); + } + string s = getScreenLabel(); + LyXFont f(font); + f.decSize(); + f.setColor(LColor::none); + f.setLatex(LyXFont::OFF); + pain.text(int(x + 2), baseline, s, f); + + x += width(pain, font) - 3; +} +#else void InsetCommand::Draw(LyXFont font, LyXScreen & scr, int baseline, float & x) { @@ -86,6 +150,7 @@ void InsetCommand::Draw(LyXFont font, LyXScreen & scr, x += Width(font) - 3; } +#endif // In lyxf3 this will be just LaTeX diff --git a/src/insets/insetcommand.h b/src/insets/insetcommand.h index af2c590412..c271b9f331 100644 --- a/src/insets/insetcommand.h +++ b/src/insets/insetcommand.h @@ -4,8 +4,8 @@ * * LyX, The Document Processor * - * Copyright 1995 Matthias Ettrich - * Copyright 1996-2000 The LyX Team. + * Copyright 1995 Matthias Ettrich + * Copyright 1995-2000 The LyX Team. * * ====================================================== */ @@ -32,6 +32,16 @@ public: /// InsetCommand(string const & name, string const & arg = string(), string const & opt = string()); +#ifdef USE_PAINTER + /// + int ascent(Painter &, LyXFont const &) const; + /// + int descent(Painter &, LyXFont const &) const; + /// + int width(Painter &, LyXFont const &) const; + /// + void draw(Painter &, LyXFont const &, int baseline, float & x) const; +#else /// int Ascent(LyXFont const & font) const; /// @@ -40,6 +50,7 @@ public: int Width(LyXFont const & font) const; /// void Draw(LyXFont, LyXScreen & scr, int baseline, float & x); +#endif /// void Write(ostream &); /// Parse the command. diff --git a/src/insets/inseterror.C b/src/insets/inseterror.C index 74c0cc7c79..163c7275ec 100644 --- a/src/insets/inseterror.C +++ b/src/insets/inseterror.C @@ -18,6 +18,7 @@ #include "lyxdraw.h" #include "gettext.h" #include "lyx_gui_misc.h" // CancelCloseBoxCB +#include "Painter.h" /* Error, used for the LaTeX-Error Messages */ @@ -44,30 +45,80 @@ InsetError::~InsetError() } +#ifdef USE_PAINTER +int InsetError::ascent(Painter &, LyXFont const & font) const +{ + LyXFont efont; + efont.setSize(font.size()).decSize(); + return efont.maxAscent() + 1; +} +#else int InsetError::Ascent(LyXFont const & font) const { LyXFont efont; efont.setSize(font.size()).decSize(); return efont.maxAscent()+1; } +#endif +#ifdef USE_PAINTER +int InsetError::descent(Painter &, LyXFont const & font) const +{ + LyXFont efont; + efont.setSize(font.size()).decSize(); + return efont.maxDescent() + 1; +} +#else int InsetError::Descent(LyXFont const & font) const { LyXFont efont; efont.setSize(font.size()).decSize(); return efont.maxDescent()+1; } +#endif +#ifdef USE_PAINTER +int InsetError::width(Painter &, LyXFont const & font) const +{ + LyXFont efont; + efont.setSize(font.size()).decSize(); + return 6 + efont.textWidth(_("Error"), strlen(_("Error"))); +} +#else int InsetError::Width(LyXFont const & font) const { LyXFont efont; efont.setSize(font.size()).decSize(); return 6 + efont.textWidth(_("Error"), strlen(_("Error"))); } +#endif +#ifdef USE_PAINTER +void InsetError::draw(Painter & pain, LyXFont const & font, + int baseline, float & x) const +{ + LyXFont efont; + efont.setSize(font.size()).decSize(); + efont.setColor(LColor::error); + + // Draw as "Error" in a framed box + x += 1; + pain.fillRectangle(int(x), baseline - ascent(pain, font) + 1, + width(pain, font) - 2, + ascent(pain, font) + descent(pain, font) - 2, + LColor::insetbg); + pain.rectangle(int(x), baseline - ascent(pain, font) + 1, + width(pain, font) - 2, + ascent(pain, font) + descent(pain, font) - 2, + LColor::error); + pain.text(int(x + 2), baseline, _("Error"), efont); + + x += width(pain, font) - 1; +} +#else void InsetError::Draw(LyXFont font, LyXScreen & scr, int baseline, float & x) { @@ -87,7 +138,7 @@ void InsetError::Draw(LyXFont font, LyXScreen & scr, x += Width(font) - 1; } - +#endif void InsetError::Write(ostream &) { diff --git a/src/insets/inseterror.h b/src/insets/inseterror.h index 4179e6cb78..998a755cfc 100644 --- a/src/insets/inseterror.h +++ b/src/insets/inseterror.h @@ -4,7 +4,8 @@ * * LyX, The Document Processor * - * Copyright (C) 1995 Matthias Ettrich + * Copyright 1995 Matthias Ettrich + * Copyright 1995-2000 The LyX Team. * * ====================================================== */ @@ -33,6 +34,17 @@ public: InsetError(); /// ~InsetError(); +#ifdef USE_PAINTER + /// + int ascent(Painter &, LyXFont const & font) const; + /// + int descent(Painter &, LyXFont const & font) const; + /// + int width(Painter &, LyXFont const & font) const; + /// + void draw(Painter &, LyXFont const & font, + int baseline, float & x) const; +#else /// int Ascent(LyXFont const & font) const; /// @@ -41,6 +53,7 @@ public: int Width(LyXFont const & font) const; /// void Draw(LyXFont font, LyXScreen & scr, int baseline, float & x); +#endif /// void Write(ostream &); /// diff --git a/src/insets/insetinfo.C b/src/insets/insetinfo.C index 24cc383658..ba8dce83c0 100644 --- a/src/insets/insetinfo.C +++ b/src/insets/insetinfo.C @@ -24,6 +24,7 @@ #include "lyx_gui_misc.h" // CancelCloseBoxCB #include "buffer.h" #include "support/lstrings.h" +#include "Painter.h" /* Info, used for the Info boxes */ @@ -53,24 +54,67 @@ InsetInfo::~InsetInfo() } +#ifdef USE_PAINTER +int InsetInfo::ascent(Painter &, LyXFont const & font) const +{ + return font.maxAscent() + 1; +} +#else int InsetInfo::Ascent(LyXFont const & font) const { return font.maxAscent() + 1; } +#endif +#ifdef USE_PAINTER +int InsetInfo::descent(Painter &, LyXFont const & font) const +{ + return font.maxDescent() + 1; +} +#else int InsetInfo::Descent(LyXFont const & font) const { return font.maxDescent() + 1; } +#endif +#ifdef USE_PAINTER +int InsetInfo::width(Painter &, LyXFont const & font) const +{ + return 6 + font.textWidth(_("Note"), strlen(_("Note"))); +} +#else int InsetInfo::Width(LyXFont const & font) const { return 6 + font.textWidth(_("Note"), strlen(_("Note"))); } +#endif + +#ifdef USE_PAINTER +void InsetInfo::draw(Painter & pain, LyXFont const & f, + int baseline, float & x) const +{ + LyXFont font(f); + + /* Info-insets are never LaTeX, so just correct the font */ + font.setLatex(LyXFont::OFF); + // Draw as "Note" in a yellow box + x += 1; + pain.fillRectangle(int(x), baseline - ascent(pain, font) + 1, + width(pain, font) - 2, + ascent(pain, font) + descent(pain, font) - 2); + pain.rectangle(int(x), baseline - ascent(pain, font) + 1, + width(pain, font) - 2, + ascent(pain, font) + descent(pain, font) - 2); + + pain.text(int(x + 2), baseline, _("Note"), font); + x += width(pain, font) - 1; +} +#else void InsetInfo::Draw(LyXFont font, LyXScreen & scr, int baseline, float & x) { @@ -89,6 +133,7 @@ void InsetInfo::Draw(LyXFont font, LyXScreen & scr, scr.drawString(font, _("Note"), baseline, int(x+2)); x += Width(font) - 1; } +#endif void InsetInfo::Write(ostream & os) diff --git a/src/insets/insetinfo.h b/src/insets/insetinfo.h index b4f9fe9dbb..170d729c81 100644 --- a/src/insets/insetinfo.h +++ b/src/insets/insetinfo.h @@ -36,6 +36,16 @@ public: InsetInfo(string const & string); /// ~InsetInfo(); +#ifdef USE_PAINTER + /// + int ascent(Painter &, LyXFont const &) const; + /// + int descent(Painter &, LyXFont const &) const; + /// + int width(Painter &, LyXFont const &) const; + /// + void draw(Painter &, LyXFont const &, int baseline, float & x) const; +#else /// int Ascent(LyXFont const & font) const; /// @@ -44,6 +54,7 @@ public: int Width(LyXFont const & font) const; /// void Draw(LyXFont font, LyXScreen & scr, int baseline, float & x); +#endif /// void Write(ostream &); /// diff --git a/src/insets/insetlatexaccent.C b/src/insets/insetlatexaccent.C index 4693c2eaa6..dd97fcf585 100644 --- a/src/insets/insetlatexaccent.C +++ b/src/insets/insetlatexaccent.C @@ -19,6 +19,7 @@ #include "lyxrc.h" #include "lyxdraw.h" #include "support/lstrings.h" +#include "Painter.h" extern LyXRC * lyxrc; @@ -252,6 +253,26 @@ void InsetLatexAccent::checkContents() } +#ifdef USE_PAINTER +int InsetLatexAccent::ascent(Painter &, LyXFont const & font) const +{ + // This function is a bit too simplistix and is just a + // "try to make a fit for all accents" approach, to + // make it better we need to know what kind of accent is + // used and add to max based on that. + int max; + if (candisp) { + if (ic == ' ') + max = font.ascent('a'); + else + max = font.ascent(ic); + if (plusasc) + max += (font.maxAscent() + 3) / 3; + } else + max = font.maxAscent() + 4; + return max; +} +#else int InsetLatexAccent::Ascent(LyXFont const & font) const { // This function is a bit too simplistix and is just a @@ -270,8 +291,25 @@ int InsetLatexAccent::Ascent(LyXFont const & font) const max = font.maxAscent() + 4; return max; } +#endif +#ifdef USE_PAINTER +int InsetLatexAccent::descent(Painter &, LyXFont const & font) const +{ + int max; + if (candisp) { + if (ic == ' ') + max = font.descent('a'); + else + max = font.descent(ic); + if (plusdesc) + max += 3; + } else + max = font.maxDescent() + 4; + return max; +} +#else int InsetLatexAccent::Descent(LyXFont const & font) const { int max; @@ -286,8 +324,18 @@ int InsetLatexAccent::Descent(LyXFont const & font) const max = font.maxDescent() + 4; return max; } +#endif +#ifdef USE_PAINTER +int InsetLatexAccent::width(Painter &, LyXFont const & font) const +{ + if (candisp) + return font.textWidth(&ic, 1); + else + return font.stringWidth(contents) + 4; +} +#else int InsetLatexAccent::Width(LyXFont const & font) const { if (candisp) @@ -295,6 +343,7 @@ int InsetLatexAccent::Width(LyXFont const & font) const else return font.stringWidth(contents) + 4; } +#endif int InsetLatexAccent::Lbearing(LyXFont const & font) const @@ -309,6 +358,49 @@ int InsetLatexAccent::Rbearing(LyXFont const & font) const } +#ifdef USE_PAINTER +bool InsetLatexAccent::DisplayISO8859_9(Painter & pain, LyXFont const & font, + int baseline, + float & x) const +{ + unsigned char tmpic = ic; + + switch (modtype) { + case CEDILLA: + { + if (ic == 'c') tmpic = 0xe7; + if (ic == 'C') tmpic = 0xc7; + if (ic == 's') tmpic = 0xfe; + if (ic == 'S') tmpic = 0xde; + break; + } + case BREVE: + { if (ic == 'g') tmpic = 0xf0; + if (ic == 'G') tmpic = 0xd0; + break; + } + case UMLAUT: + { + if (ic == 'o') tmpic = 0xf6; + if (ic == 'O') tmpic = 0xd6; + if (ic == 'u') tmpic = 0xfc; + if (ic == 'U') tmpic = 0xdc; + break; + } + case DOT: if (ic == 'I') tmpic = 0xdd; break; + case DOT_LESS_I: tmpic = 0xfd; break; + default: return false; + } + if (tmpic != ic) { + char ch = char(tmpic); + pain.text(x, baseline, ch, font); + x += width(pain, font); + return true; + } + else + return false; +} +#else bool InsetLatexAccent::DisplayISO8859_9(LyXFont font, LyXScreen & scr, int baseline, @@ -351,8 +443,314 @@ bool InsetLatexAccent::DisplayISO8859_9(LyXFont font, else return false; } +#endif + + +#ifdef USE_PAINTER +void InsetLatexAccent::draw(Painter & pain, LyXFont const & font, + int baseline, float & x) const +{ + if (lyxrc->font_norm == "iso8859-9") + if (DisplayISO8859_9(pain, font, baseline, x)) + return; + + /* draw it! */ + // All the manually drawn accents in this function could use an + // overhaul. Different ways of drawing (what metrics to use) + // should also be considered. + + if (candisp) { + int asc = ascent(pain, font); + int desc = descent(pain, font); + int wid = width(pain, font); + float x2 = x + (Rbearing(font) - Lbearing(font)) / 2.0; + float hg; + int y; + if (plusasc) { + // mark at the top + hg = font.maxDescent(); + y = baseline - asc; + + if (font.shape() == LyXFont::ITALIC_SHAPE) + x2 += (4.0 * hg) / 5.0; // italic + } else { + // at the bottom + hg = desc; + y = baseline; + } + float hg35 = float(hg * 3.0) / 5.0; + // display with proper accent mark + // first the letter + pain.text(int(x), baseline, ic, font); + +#if 0 + GC pgc = GetAccentGC(font, int((hg + 3.0) / 5.0)); +#endif + + if (remdot) { + int tmpvar = baseline - font.ascent('i'); + float tmpx = 0; + if (font.shape() == LyXFont::ITALIC_SHAPE) + tmpx += (8.0 * hg) / 10.0; // italic + lyxerr[Debug::KEY] << "Removing dot." << endl; + // remove the dot first + pain.fillRectangle(int(x + tmpx), tmpvar, wid, + font.ascent('i') - + font.ascent('x') - 1, + LColor::background); + // the five lines below is a simple hack to + // make the display of accent 'i' and 'j' + // better. It makes the accent be written + // closer to the top of the dot-less 'i' or 'j'. + char tmpic = ic; // store the ic when we + ic = 'x'; // calculates the ascent of + asc = ascent(pain, font); // the dot-less version (here: 'x') + ic = tmpic; // set the orig ic back + y = baseline - asc; // update to new y coord. + } + // now the rest - draw within (x, y, x+wid, y+hg) + switch (modtype) { + case ACUTE: // acute + { + pain.line(int(x2), int(y + hg), + int(x2 + hg35), y + hg35); + break; + } + case GRAVE: // grave + { + pain.line(int(x2), int(y + hg), + int(x2 - hg35), y + hg35); + break; + } + case MACRON: // macron + { + pain.line(int(x2 - wid * 0.4), + int(y + hg), + int(x2 + wid * 0.4), + int(y + hg)); + break; + } + case TILDE: // tilde + { + if (hg35 > 2.0) hg35 -= 1.0; + x2 += (hg35 / 2.0); + int xp[4], yp[4]; + + xp[0] = int(x2 - 2.0 * hg35); + yp[0] = int(y + hg); + + xp[1] = int(x2 - hg35); + yp[1] = int(y + hg35); + + xp[2] = int(x2); + yp[2] = int(y + hg); + + xp[3] = int(x2 + hg35); + yp[3] = int(y + hg35); + + pain.lines(xp, yp, 4); + break; + } + case UNDERBAR: // underbar + { + pain.line(int(x2 - wid * 0.4), + y + hg / 2.0, + int(x2 + wid * 0.4), + y + hg / 2.0); + break; + } + case CEDILLA: // cedilla + { + int xp[4], yp[4]; + + xp[0] = int(x2); + yp[0] = y; + + xp[1] = int(x2); + yp[1] = y + int(hg / 3.0); + + xp[2] = int(x2 + (hg / 3.0)); + yp[2] = y + int(hg / 2.0); + + xp[3] = int(x2 - (hg / 4.0)); + yp[3] = y + int(hg); + + pain.lines(xp, yp, 4); + break; + } + case UNDERDOT: // underdot + { + pain.arc(int(x2), y + hg35, + 3, 3, 0, 360 * 64); + break; + } + + case DOT: // dot + { + pain.arc(int(x2), y + hg * 0.5, + (hg + 3.0)/5.0, + (hg + 3.0)/5.0, + 0, 360 * 64); + break; + } + + case CIRCLE: // circle + { + pain.arc(int(x2 - (hg / 2.0)), + y + (hg / 2.0), hg, hg , 0, + 360 * 64); + break; + } + case TIE: // tie + { + pain.arc(int(x2 + hg35), y + hg / 2.0, + 2 * hg, hg, 0, 360 * 32); + break; + } + case BREVE: // breve + { + pain.arc(int(x2 - (hg / 2.0)), y, + hg, hg, 0, -360*32); + break; + } + case CARON: // caron + { + int xp[3], yp[3]; + + xp[0] = int(x2 - hg35); yp[0] = int(y + hg35); + xp[1] = int(x2); yp[1] = int(y + hg); + xp[2] = int(x2 + hg35); yp[2] = int(y + hg35); + pain.lines(xp, yp, 3); + break; + } + case SPECIAL_CARON: // special caron + { + switch (ic) { + case 'L': wid = int(4.0 * wid / 5.0); break; + case 't': y -= int(hg35 / 2.0); break; + } + int xp[3], yp[3]; + xp[0] = int(x + wid); + yp[0] = int(y + hg35 + hg); + + xp[1] = int(x + wid + (hg35 / 2.0)); + yp[1] = int(y + hg + (hg35 / 2.0)); + + xp[2] = int(x + wid + (hg35 / 2.0)); + yp[2] = y + int(hg); + + pain.lines(xp, yp, 3); + break; + } + case HUNGARIAN_UMLAUT: // hung. umlaut + { + int xs1[2], xs2[2], ys1[2], ys2[2]; + + xs1[0] = int(x2 - (hg / 2.0)); + ys1[0] = int(y + hg); + + xs2[0] = int(x2 + hg35 - (hg / 2.0)); + ys2[0] = int(y + hg35); + + xs1[1] = int(x2 + (hg / 2.0)); + ys1[1] = int(y + hg); + + xs2[1] = int(x2 + hg35 + (hg / 2.0)); + ys2[1] = int(y + hg35); + + pain.segments(xs1, ys1, xs2, ys2, 2); + break; + } + case UMLAUT: // umlaut + { + float rad = hg / 2.0; + if (rad <= 1.0) { + pain.point(int(x2 - 4.0 * hg / 7.0), + y + hg35); + pain.point(int(x2 + 4.0 * hg / 7.0), + y + hg35); + } else { + rad += .5; // this ensures that f.ex. 1.5 will + // not be rounded down to .5 and then + // converted to int = 0 + pain.arc(int(x2 - 2.0 * hg / 4.0), + y + hg35, + rad, rad, + 0, 360 * 64); + pain.arc(int(x2 + 2.0 * hg / 4.0), + y + hg35, + rad, rad, 0, 360*64); + } + break; + } + case CIRCUMFLEX: // circumflex + { + int xp[3], yp[3]; + + xp[0] = int(x2 - hg35); yp[0] = y + int(hg); + xp[1] = int(x2); yp[1] = int(y + hg35); + xp[2] = int(x2 + hg35); yp[2] = y + int(hg); + pain.lines(xp, yp, 3); + break; + } + case OGONEK: // ogonek + { + // this does probably not look like an ogonek, so + // it should certainly be refined + int xp[4], yp[4]; + + xp[0] = int(x2); + yp[0] = y; + + xp[1] = int(x2); + yp[1] = y + int(hg35); + + xp[2] = int(x2 - hg35); + yp[2] = y + int(hg / 2.0); + + xp[3] = int(x2 + hg / 4.0); + yp[3] = y + int(hg); + + pain.lines(xp, yp, 4); + break; + } + case lSLASH: + case LSLASH: + { + int xp[2], yp[2]; + + xp[0] = int(x); + yp[0] = y + int(3.0 * hg); + + xp[1] = int(x + float(wid) * 0.75); + yp[1] = y + int(hg); + + pain.lines(xp, yp, 2); + break; + } + case DOT_LESS_I: // dotless-i + case DOT_LESS_J: // dotless-j + { + // nothing to do for these + break; + } + } + } else { + pain.fillRectangle(int(x + 1), + baseline - ascent(pain, font) + 1, + width(pain, font) - 2, + ascent(pain, font) + + descent(pain, font) - 2); + pain.rectangle(int(x + 1), baseline - ascent(pain, font) + 1, + width(pain, font) - 2, + ascent(pain, font) + descent(pain, font) - 2); + pain.text(int(x + 2), baseline, contents, font); + } + x += width(pain, font); +} +#else void InsetLatexAccent::Draw(LyXFont font, LyXScreen & scr, int baseline, @@ -462,7 +860,6 @@ void InsetLatexAccent::Draw(LyXFont font, } case CEDILLA: // cedilla { -#if 1 XPoint p[4]; p[0].x = int(x2); p[0].y = y; p[1].x = int(x2); p[1].y = y + int(hg / 3.0); @@ -470,44 +867,28 @@ void InsetLatexAccent::Draw(LyXFont font, p[2].y = y + int(hg / 2.0); p[3].x = int(x2 - (hg / 4.0)); p[3].y = y + int(hg); scr.drawLines(pgc, p, 4); -#endif - //scr.drawLine(pgc, - // x2, y, - // x2 - hg / 4.0, y + hg); - // and then we need a circle thingie. - // ... break; } case UNDERDOT: // underdot { -#if 1 scr.fillArc(pgc, int(x2), y + hg35, 3, 3, 0, 360*64); -#endif - //scr.drawText(font, "·", 1, y + 2 * hg, x2); break; } case DOT: // dot { -#if 1 scr.fillArc(pgc, int(x2), y + hg * 0.5, (hg + 3.0)/5.0, (hg + 3.0)/5.0, 0, 360*64); -#endif - //scr.drawText(font, "·", 1, y + 2.0 * hg, x2); break; } case CIRCLE: // circle { -#if 1 scr.drawArc(pgc, int(x2 - (hg / 2.0)), y + (hg / 2.0), hg, hg, 0, 360*64); -#endif - //scr.drawText(font, "°", 1, y + 2.0 * hg, x2); - break; } case TIE: // tie @@ -640,6 +1021,7 @@ void InsetLatexAccent::Draw(LyXFont font, } x += Width(font); } +#endif void InsetLatexAccent::Write(ostream & os) diff --git a/src/insets/insetlatexaccent.h b/src/insets/insetlatexaccent.h index 297c6f9e84..b8085e016b 100644 --- a/src/insets/insetlatexaccent.h +++ b/src/insets/insetlatexaccent.h @@ -33,21 +33,38 @@ public: InsetLatexAccent(); /// InsetLatexAccent(string const & string); +#ifdef USE_PAINTER + /// + int ascent(Painter &, LyXFont const &) const; + /// + int descent(Painter &, LyXFont const &) const; + /// + int width(Painter &, LyXFont const &) const; + /// + void draw(Painter &, LyXFont const &, int baseline, float & x) const; +#else /// int Ascent(LyXFont const & font) const; /// int Descent(LyXFont const & font) const; /// int Width(LyXFont const & font) const; + /// + void Draw(LyXFont, LyXScreen & scr, int baseline, float & x); +#endif /// int Lbearing(LyXFont const & font) const; /// int Rbearing(LyXFont const & font) const; +#ifdef USE_PAINTER + /// + bool DisplayISO8859_9(Painter &, LyXFont const & font, + int baseline, float & x) const; +#else /// bool DisplayISO8859_9(LyXFont font, LyXScreen & scr, int baseline, float & x); - /// - void Draw(LyXFont font, LyXScreen & scr, int baseline, float & x); +#endif /// void Write(ostream &); /// @@ -133,7 +150,7 @@ private: /// add something to descent - underlined char bool plusdesc; /// international char - char ic; + mutable char ic; }; bool InsetLatexAccent::CanDisplay() diff --git a/src/insets/insetquotes.C b/src/insets/insetquotes.C index d069cc2d6b..b7a4da1c63 100644 --- a/src/insets/insetquotes.C +++ b/src/insets/insetquotes.C @@ -22,6 +22,7 @@ #include "buffer.h" #include "LaTeXFeatures.h" #include "support/lstrings.h" +#include "Painter.h" // Quotes. Used for the various quotes. German, English, French, // Danish, Polish, all either double or single. @@ -155,18 +156,50 @@ string InsetQuotes::DispString() const } +#ifdef USE_PAINTER +int InsetQuotes::ascent(Painter &, LyXFont const & font) const +{ + return font.maxAscent(); +} +#else int InsetQuotes::Ascent(LyXFont const & font) const { return font.maxAscent(); } +#endif +#ifdef USE_PAINTER +int InsetQuotes::descent(Painter &, LyXFont const & font) const +{ + return font.maxDescent(); +} +#else int InsetQuotes::Descent(LyXFont const & font) const { return font.maxDescent(); } +#endif +#ifdef USE_PAINTER +int InsetQuotes::width(Painter &, LyXFont const & font) const +{ + string text = DispString(); + int w = 0; + + for (string::size_type i = 0; i < text.length(); ++i) { + if (text[i] == ' ') + w += font.width('i'); + else if (i == 0 || text[i] != text[i-1]) + w += font.width(text[i]); + else + w += font.width(','); + } + + return w; +} +#else int InsetQuotes::Width(LyXFont const & font) const { string text = DispString(); @@ -183,6 +216,7 @@ int InsetQuotes::Width(LyXFont const & font) const return w; } +#endif LyXFont InsetQuotes::ConvertFont(LyXFont font) @@ -193,6 +227,16 @@ LyXFont InsetQuotes::ConvertFont(LyXFont font) } +#ifdef USE_PAINTER +void InsetQuotes::draw(Painter & pain, LyXFont const & font, + int baseline, float & x) const +{ + string text = DispString(); + + pain.text(int(x), baseline, text, font); + x += width(pain, font); +} +#else void InsetQuotes::Draw(LyXFont font, LyXScreen & scr, int baseline, float & x) { @@ -201,6 +245,7 @@ void InsetQuotes::Draw(LyXFont font, LyXScreen & scr, scr.drawString(font, text, baseline, int(x)); x += Width(font); } +#endif void InsetQuotes::Write(ostream & os) diff --git a/src/insets/insetquotes.h b/src/insets/insetquotes.h index 006b519e76..abd48cdfe4 100644 --- a/src/insets/insetquotes.h +++ b/src/insets/insetquotes.h @@ -70,6 +70,16 @@ public: /// Create the right quote inset after character c InsetQuotes(char c, BufferParams const & params); +#ifdef USE_PAINTER + /// + int ascent(Painter &, LyXFont const &) const; + /// + int descent(Painter &, LyXFont const &) const; + /// + int width(Painter &, LyXFont const &) const; + /// + void draw(Painter &, LyXFont const &, int baseline, float & x) const; +#else /// int Ascent(LyXFont const & font) const; /// @@ -78,6 +88,7 @@ public: int Width(LyXFont const & font) const; /// void Draw(LyXFont font, LyXScreen & scr, int baseline, float & x); +#endif /// LyXFont ConvertFont(LyXFont font); /// diff --git a/src/insets/insetspecialchar.C b/src/insets/insetspecialchar.C index f1074c604f..3b831ed654 100644 --- a/src/insets/insetspecialchar.C +++ b/src/insets/insetspecialchar.C @@ -17,24 +17,66 @@ #include "lyxdraw.h" #include "debug.h" #include "LaTeXFeatures.h" +#include "Painter.h" InsetSpecialChar::InsetSpecialChar(Kind k) : kind(k) {} +#ifdef USE_PAINTER +int InsetSpecialChar::ascent(Painter &, LyXFont const & font) const +{ + return font.maxAscent(); +} +#else int InsetSpecialChar::Ascent(LyXFont const & font) const { return font.maxAscent(); } +#endif +#ifdef USE_PAINTER +int InsetSpecialChar::descent(Painter &, LyXFont const & font) const +{ + return font.maxDescent(); +} +#else int InsetSpecialChar::Descent(LyXFont const & font) const { return font.maxDescent(); } +#endif +#ifdef USE_PAINTER +int InsetSpecialChar::width(Painter &, LyXFont const & font) const +{ + LyXFont f(font); + switch (kind) { + case HYPHENATION: + { + int w = f.textWidth("-", 1); + if (w > 5) + w -= 2; // to make it look shorter + return w; + } + case END_OF_SENTENCE: + { + return f.textWidth(".", 1); + } + case LDOTS: + { + return f.textWidth(". . .", 5); + } + case MENU_SEPARATOR: { + return f.textWidth(" x ", 3); + } + } + return 1; // To shut up gcc +} +#else int InsetSpecialChar::Width(LyXFont const & font) const { LyXFont f = font; @@ -60,29 +102,76 @@ int InsetSpecialChar::Width(LyXFont const & font) const } return 1; // To shut up gcc } +#endif +#ifdef USE_PAINTER +void InsetSpecialChar::draw(Painter & pain, LyXFont const & f, + int baseline, float & x) const +{ + LyXFont font(f); + switch (kind) { + case HYPHENATION: + { + font.setColor(LColor::magenta); + pain.text(int(x), baseline, "-", font); + x += width(pain, font); + break; + } + case END_OF_SENTENCE: + { + font.setColor(LColor::magenta); + pain.text(int(x), baseline, ".", font); + x += width(pain, font); + break; + } + case LDOTS: + { + font.setColor(LColor::magenta); + pain.text(int(x), baseline, ". . .", font); + x += width(pain, font); + break; + } + case MENU_SEPARATOR: + { +#if 0 + // A triangle the width and height of an 'x' + int w = font.textWidth("x", 1); + int ox = font.textWidth(" ", 1) + int(x); + int h = font.ascent('x'); + XPoint p[4]; + p[0].x = ox; p[0].y = baseline; + p[1].x = ox; p[1].y = baseline - h; + p[2].x = ox + w;p[2].y = baseline - h/2; + p[3].x = ox; p[3].y = baseline; + scr.drawLines(getGC(gc_copy), p, 4); +#endif + x += width(pain, font); + } + } +} +#else void InsetSpecialChar::Draw(LyXFont font, LyXScreen & scr, int baseline, float & x) { switch (kind) { case HYPHENATION: { - font.setColor(LyXFont::MAGENTA); + font.setColor(LyXFont::BLUE); scr.drawText(font, "-", 1, baseline, int(x)); x += Width(font); break; } case END_OF_SENTENCE: { - font.setColor(LyXFont::MAGENTA); + font.setColor(LyXFont::BLUE); scr.drawText(font, ".", 1, baseline, int(x)); x += Width(font); break; } case LDOTS: { - font.setColor(LyXFont::MAGENTA); + font.setColor(LyXFont::BLUE); scr.drawText(font, ". . .", 5, baseline, int(x)); x += Width(font); break; @@ -103,6 +192,7 @@ void InsetSpecialChar::Draw(LyXFont font, LyXScreen & scr, } } } +#endif // In lyxf3 this will be just LaTeX diff --git a/src/insets/insetspecialchar.h b/src/insets/insetspecialchar.h index 406c793301..164ff1085b 100644 --- a/src/insets/insetspecialchar.h +++ b/src/insets/insetspecialchar.h @@ -40,6 +40,16 @@ public: InsetSpecialChar() {} /// InsetSpecialChar(Kind k); +#ifdef USE_PAINTER + /// + int ascent(Painter &, LyXFont const &) const; + /// + int descent(Painter &, LyXFont const &) const; + /// + int width(Painter &, LyXFont const &) const; + /// + void draw(Painter &, LyXFont const &, int baseline, float & x) const; +#else /// int Ascent(LyXFont const & font) const; /// @@ -48,6 +58,7 @@ public: int Width(LyXFont const & font) const; /// void Draw(LyXFont, LyXScreen & scr, int baseline, float & x); +#endif /// void Write(ostream &); /// Will not be used when lyxf3 diff --git a/src/insets/inseturl.h b/src/insets/inseturl.h index b7478a114f..f008ea88bf 100644 --- a/src/insets/inseturl.h +++ b/src/insets/inseturl.h @@ -4,7 +4,7 @@ * * LyX, The Document Processor * - * Copyright (C) 1997 LyX Team (this file was created this year) + * Copyright 1997-2000 The LyX Team. * * ====================================================== */ diff --git a/src/insets/lyxinset.h b/src/insets/lyxinset.h index 42d37b6b6b..5905b7bc16 100644 --- a/src/insets/lyxinset.h +++ b/src/insets/lyxinset.h @@ -21,6 +21,11 @@ #include "lyxlex.h" #include "lyxscreen.h" +//#define USE_PAINTER 1 + +#ifdef USE_PAINTER +class Painter; +#endif class Buffer; struct LaTeXFeatures; @@ -80,6 +85,17 @@ public: /// virtual ~Inset() {} +#ifdef USE_PAINTER + /// + virtual int ascent(Painter &, LyXFont const &) const = 0; + /// + virtual int descent(Painter &, LyXFont const &) const = 0; + /// + virtual int width(Painter &, LyXFont const &) const = 0; + /// + virtual void draw(Painter &, LyXFont const &, + int baseline, float & x) const = 0; +#else /// virtual int Ascent(LyXFont const & font) const = 0; /// @@ -87,10 +103,11 @@ public: /// virtual int Width(LyXFont const & font) const = 0; /// - virtual LyXFont ConvertFont(LyXFont font); - /// virtual void Draw(LyXFont font, LyXScreen & scr, int baseline, float & x) = 0; +#endif + /// + virtual LyXFont ConvertFont(LyXFont font); /// what appears in the minibuffer when opening virtual char const * EditMessage() const {return _("Opened inset");} /// @@ -200,6 +217,6 @@ public: bool isCursorVisible() const { return cursor_visible; } protected: /// - bool cursor_visible; + mutable bool cursor_visible; }; #endif diff --git a/src/lyx_cb.C b/src/lyx_cb.C index 7591c60f97..f0f6f26b68 100644 --- a/src/lyx_cb.C +++ b/src/lyx_cb.C @@ -244,9 +244,10 @@ void AllowInput() if (fd_form_character->form_character->visible) XUndefineCursor(fl_display, fd_form_character->form_character->window); +#ifndef NEW_WA if (current_view->getWorkArea()->belowmouse) SetXtermCursor(current_view->owner()->getForm()->window); - +#endif XFlush(fl_display); fl_activate_all_forms(); } @@ -2270,6 +2271,21 @@ LyXFont UserFreeFont() } pos = fl_get_choice(fd_form_character->choice_color); +#ifdef USE_PAINTER + switch(pos) { + case 1: font.setColor(LColor::ignore); break; + case 2: font.setColor(LColor::none); break; + case 3: font.setColor(LColor::black); break; + case 4: font.setColor(LColor::white); break; + case 5: font.setColor(LColor::red); break; + case 6: font.setColor(LColor::green); break; + case 7: font.setColor(LColor::blue); break; + case 8: font.setColor(LColor::cyan); break; + case 9: font.setColor(LColor::magenta); break; + case 10: font.setColor(LColor::yellow); break; + case 11: font.setColor(LColor::inherit); break; + } +#else switch(pos) { case 1: font.setColor(LyXFont::IGNORE_COLOR); break; case 2: font.setColor(LyXFont::NONE); break; @@ -2283,7 +2299,7 @@ LyXFont UserFreeFont() case 10: font.setColor(LyXFont::YELLOW); break; case 11: font.setColor(LyXFont::INHERIT_COLOR); break; } - +#endif return font; } diff --git a/src/lyx_gui.C b/src/lyx_gui.C index b93365bb82..594d5aa714 100644 --- a/src/lyx_gui.C +++ b/src/lyx_gui.C @@ -297,10 +297,12 @@ void LyXGUI::init() // 0.13 it should be moved again... lyxserver = new LyXServer(lyxViews->getLyXFunc(), lyxrc->lyxpipes); +#ifndef USE_PAINTER // This is to make sure we get the selection color getGC(gc_selection); // This is to make sure we set the background_pixels getGC(gc_clear); +#endif } diff --git a/src/lyxdraw.C b/src/lyxdraw.C index fe2e9d1859..44347c107d 100644 --- a/src/lyxdraw.C +++ b/src/lyxdraw.C @@ -1,5 +1,8 @@ + #include +#ifndef USE_PAINTER + #include "lyxdraw.h" #include "debug.h" @@ -418,7 +421,11 @@ GC GetLightedGC() } +#ifdef USE_PAINTER +GC GetColorGC(LColor::color color) +#else GC GetColorGC(LyXFont::FONT_COLOR color) +#endif { if (color_gc[color]) return color_gc[color]; @@ -549,3 +556,5 @@ GC getGC(gc_type typ) } return gc; } + +#endif diff --git a/src/lyxdraw.h b/src/lyxdraw.h index f50975a7cb..6ee8f00941 100644 --- a/src/lyxdraw.h +++ b/src/lyxdraw.h @@ -1,4 +1,5 @@ // -*- C++ -*- +#ifndef USE_PAINTER #ifndef LYX_DRAW_H #define LYX_DRAW_H @@ -52,3 +53,5 @@ extern GC GetAccentGC(LyXFont const &f, int line_width); extern GC GetColorGC(LyXFont::FONT_COLOR color); #endif + +#endif diff --git a/src/lyxfont.C b/src/lyxfont.C index d7231df75a..82c42aec7a 100644 --- a/src/lyxfont.C +++ b/src/lyxfont.C @@ -62,11 +62,14 @@ string const GUIMiscNames[5] = string const GUIDirectionNames[5] = { N_("LTR"), N_("RTL"), N_("Toggle"), N_("Inherit"), N_("Ignore") }; + +#ifndef USE_PAINTER string const GUIColorNames[13] = { N_("None"), N_("Black"), N_("White"), N_("Red"), N_("Green"), N_("Blue"), N_("Cyan"), N_("Magenta"), N_("Yellow"), N_("Math"), N_("Inset"), N_("Inherit"), N_("Ignore") }; - +#endif + // // Strings used to read and write .lyx format files // @@ -87,9 +90,11 @@ string const LyXSizeNames[14] = string const LyXMiscNames[12] = { "off", "on", "toggle", "default", "error" }; +#ifndef USE_PAINTER string const LyXColorNames[13] = { "none", "black", "white", "red", "green", "blue", "cyan", "magenta", "yellow", "matherror", "inseterror", "default", "error" }; +#endif // // Strings used to write LaTeX files @@ -107,10 +112,59 @@ string const LaTeXShapeNames[6] = string const LaTeXSizeNames[14] = { "tiny", "scriptsize", "footnotesize", "small", "normalsize", "large", "Large", "LARGE", "huge", "Huge", "error8", "error9", "error10", "error11" }; - + +#ifndef USE_PAINTER string const LaTeXColorNames[13] = { "none", "black", "white", "red", "green", "blue", "cyan", "magenta", "yellow", "error12", "error13", "error14", "error15" }; +#endif + +#ifdef NEW_BITS +LyXFont::FontBits LyXFont::sane = { ROMAN_FAMILY, + MEDIUM_SERIES, + UP_SHAPE, + SIZE_NORMAL, +#ifdef USE_PAINTER + LColor::none, +#else + NONE, +#endif + OFF, + OFF, + OFF, + OFF, + LTR_DIR }; + +LyXFont::FontBits LyXFont::inherit = { INHERIT_FAMILY, + INHERIT_SERIES, + INHERIT_SHAPE, + INHERIT_SIZE, +#ifdef USE_PAINTER + LColor::inherit, +#else + INHERIT_COLOR, +#endif + INHERIT, + INHERIT, + INHERIT, + INHERIT, + INHERIT_DIR }; + +LyXFont::FontBits LyXFont::ignore = { IGNORE_FAMILY, + IGNORE_SERIES, + IGNORE_SHAPE, + IGNORE_SIZE, +#ifdef USE_PAINTER + LColor::ignore, +#else + IGNORE_COLOR, +#endif + IGNORE, + IGNORE, + IGNORE, + IGNORE, + IGNORE_DIR }; +#endif /// Decreases font size by one LyXFont & LyXFont::decSize() @@ -139,7 +193,7 @@ LyXFont & LyXFont::decSize() lyxerr <<"Can't LyXFont::decSize on IGNORE_SIZE" << endl; break; } - return (*this); + return *this; } @@ -170,7 +224,7 @@ LyXFont & LyXFont::incSize() lyxerr <<"Can't LyXFont::incSize on IGNORE_SIZE" << endl; break; } - return (*this); + return *this; } @@ -256,10 +310,17 @@ void LyXFont::update(LyXFont const & newfont, bool toggleall) setDirection(newfont.direction()); } +#ifdef USE_PAINTER + if(newfont.color() == color() && toggleall) + setColor(LColor::inherit); // toggle 'back' + else if (newfont.color() != LColor::ignore) + setColor(newfont.color()); +#else if(newfont.color() == color() && toggleall) - setColor(INHERIT_COLOR); // toggle 'back' - else if (newfont.color() != IGNORE_COLOR) + setColor(LyXFont::INHERIT_COLOR); // toggle 'back' + else if (newfont.color() != LyXFont::IGNORE_COLOR) setColor(newfont.color()); +#endif } @@ -282,8 +343,13 @@ void LyXFont::reduce(LyXFont const & tmplt) setNoun(INHERIT); if (latex() == tmplt.latex()) setLatex(INHERIT); +#ifdef USE_PAINTER if (color() == tmplt.color()) - setColor(INHERIT_COLOR); + setColor(LColor::inherit); +#else + if (color() == tmplt.color()) + setColor(LyXFont::INHERIT_COLOR); +#endif if (direction() == tmplt.direction()) setDirection(INHERIT_DIR); } @@ -291,6 +357,54 @@ void LyXFont::reduce(LyXFont const & tmplt) /// Realize font from a template // This one is not pretty, but it's extremely fast (Asger) +#ifdef NEW_BITS +LyXFont & LyXFont::realize(LyXFont const & tmplt) +{ + if (bits == inherit) { + bits = tmplt.bits; + return *this; + } + + if (bits.family == INHERIT_FAMILY) { + bits.family = tmplt.bits.family; + } + if (bits.series == INHERIT_SERIES) { + bits.series = tmplt.bits.series; + } + if (bits.shape == INHERIT_SHAPE) { + bits.shape = tmplt.bits.shape; + } + if (bits.size == INHERIT_SIZE) { + bits.size = tmplt.bits.size; + } + if (bits.emph == INHERIT) { + bits.emph = tmplt.bits.emph; + } + if (bits.underbar == INHERIT) { + bits.underbar = tmplt.bits.underbar; + } + if (bits.noun == INHERIT) { + bits.noun = tmplt.bits.noun; + } + if (bits.latex == INHERIT) { + bits.latex = tmplt.bits.latex; + } +#ifdef USE_PAINTER + if (bits.color == LColor::inherit) { + bits.color = tmplt.bits.color; + } +#else + if (bits.color == INHERIT_COLOR) { + bits.color = tmplt.bits.color; + } +#endif + if (bits.direction == INHERIT_DIR) { + bits.direction = tmplt.bits.direction; + } + + return *this; +} +#else LyXFont & LyXFont::realize(LyXFont const & tmplt) { if (bits == inherit) { @@ -338,11 +452,19 @@ LyXFont & LyXFont::realize(LyXFont const & tmplt) bits &= ~(Misc_Mask << Lat_Pos); bits |= (tmplt.bits & Misc_Mask << Lat_Pos); } +#ifdef USE_PAINTER + if ((bits & (Col_Mask << Col_Pos)) == ui32(LColor::inherit) << Col_Pos) + { + bits &= ~(Col_Mask << Col_Pos); + bits |= (tmplt.bits & Col_Mask << Col_Pos); + } +#else if ((bits & (Col_Mask << Col_Pos)) == ui32(INHERIT_COLOR) << Col_Pos) { bits &= ~(Col_Mask << Col_Pos); bits |= (tmplt.bits & Col_Mask << Col_Pos); } +#endif if ((bits & (Dir_Mask << Dir_Pos)) == ui32(INHERIT_DIR) << Dir_Pos) { bits &= ~(Dir_Mask << Dir_Pos); @@ -351,9 +473,21 @@ LyXFont & LyXFont::realize(LyXFont const & tmplt) return *this; } +#endif /// Is font resolved? +#ifdef USE_PAINTER +bool LyXFont::resolved() const +{ + return (family() != INHERIT_FAMILY && series() != INHERIT_SERIES && + shape() != INHERIT_SHAPE && size() != INHERIT_SIZE && + emph() != INHERIT && underbar() != INHERIT && + noun() != INHERIT && latex() != INHERIT && + color() != LColor::inherit && + direction() != INHERIT_DIR); +} +#else bool LyXFont::resolved() const { return (family() != INHERIT_FAMILY && series() != INHERIT_SERIES && @@ -363,6 +497,7 @@ bool LyXFont::resolved() const color() != INHERIT_COLOR && direction() != INHERIT_DIR); } +#endif /// Build GUI description of font state @@ -377,9 +512,13 @@ string LyXFont::stateText() const buf += string(_(GUIShapeNames[shape()].c_str())) + ", "; if (size() != INHERIT_SIZE) buf += string(_(GUISizeNames[size()].c_str())) + ", "; +#ifdef USE_PAINTER + if (color() != LColor::inherit) + buf += lcolor.getGUIName(color()) + ", "; +#else if (color() != INHERIT_COLOR) buf += string(_(GUIColorNames[color()].c_str())) + ", "; - +#endif if (emph() != INHERIT) buf += string(_("Emphasis ")) + _(GUIMiscNames[emph()].c_str()) + ", "; if (underbar() != INHERIT) @@ -476,6 +615,9 @@ LyXFont::FONT_MISC_STATE LyXFont::setLyXMisc(string const & siz) /// Sets color after LyX text format LyXFont & LyXFont::setLyXColor(string const & col) { +#ifdef USE_PAINTER + setColor(lcolor.getFromLyXName(col)); +#else string s = lowercase(col); int i= 0; while (s != LyXColorNames[i] && LyXColorNames[i] != "error") ++i; @@ -484,6 +626,7 @@ LyXFont & LyXFont::setLyXColor(string const & col) } else lyxerr << "LyXFont::setLyXColor: Unknown Color `" << s << '\'' << endl; +#endif return *this; } @@ -491,6 +634,12 @@ LyXFont & LyXFont::setLyXColor(string const & col) /// Sets size after GUI name LyXFont & LyXFont::setGUISize(string const & siz) { +#ifdef USE_PAINTER + /// ?????? + // this is how it was how it was done in the lyx repository... + // but this does not make sense. + setColor(lcolor.getFromGUIName(siz)); +#else string s = lowercase(siz); int i = 0; while (!lGUISizeNames[i].empty() && @@ -501,6 +650,7 @@ LyXFont & LyXFont::setGUISize(string const & siz) } else lyxerr << "LyXFont::setGUISize: Unknown Size `" << s << '\'' << endl; +#endif return *this; } @@ -592,7 +742,7 @@ LyXFont & LyXFont::lyxRead(LyXLex & lex) error = true; } } - return * this; + return *this; } @@ -650,9 +800,15 @@ void LyXFont::lyxWriteChanges(LyXFont const & orgfont, ostream & os) const break; } } +#ifdef USE_PAINTER + if (orgfont.color() != color()) { + os << "\\color " << lcolor.getLyXName(color()) << "\n"; + } +#else if (orgfont.color() != color()) { os << "\\color " << LyXColorNames[color()] << "\n"; } +#endif if (orgfont.direction() != direction()) { switch (direction()) { case RTL_DIR: os << "\\direction rtl \n"; break; @@ -672,7 +828,8 @@ void LyXFont::lyxWriteChanges(LyXFont const & orgfont, ostream & os) const /// Writes the head of the LaTeX needed to impose this font // Returns number of chars written. -int LyXFont::latexWriteStartChanges(string & file, LyXFont const & base, LyXFont const & prev) const +int LyXFont::latexWriteStartChanges(string & file, LyXFont const & base, + LyXFont const & prev) const { LyXFont f = *this; f.reduce(base); @@ -718,6 +875,15 @@ int LyXFont::latexWriteStartChanges(string & file, LyXFont const & base, LyXFont count += LaTeXShapeNames[f.shape()].length() + 2; env = true; //We have opened a new environment } +#ifdef USE_PAINTER + if (f.color() != LColor::inherit) { + file += "\\textcolor{"; + file += lcolor.getLaTeXName(f.color()); + file += "}{"; + count += lcolor.getLaTeXName(f.color()).length() + 13; + env = true; //We have opened a new environment + } +#else if (f.color() != INHERIT_COLOR) { file += "\\textcolor{"; file += LaTeXColorNames[f.color()]; @@ -725,6 +891,7 @@ int LyXFont::latexWriteStartChanges(string & file, LyXFont const & base, LyXFont count += LaTeXColorNames[f.color()].length() + 13; env = true; //We have opened a new environment } +#endif if (f.emph() == ON) { file += "\\emph{"; count += 6; @@ -759,7 +926,8 @@ int LyXFont::latexWriteStartChanges(string & file, LyXFont const & base, LyXFont /// Writes ending block of LaTeX needed to close use of this font // Returns number of chars written // This one corresponds to latexWriteStartChanges(). (Asger) -int LyXFont::latexWriteEndChanges(string & file, LyXFont const & base, LyXFont const & next) const +int LyXFont::latexWriteEndChanges(string & file, LyXFont const & base, + LyXFont const & next) const { LyXFont f = *this; // why do you need this? f.reduce(base); // why isn't this just "reduce(base);" (Lgb) @@ -796,11 +964,19 @@ int LyXFont::latexWriteEndChanges(string & file, LyXFont const & base, LyXFont c ++count; env = true; // Size change need not bother about closing env. } +#ifdef USE_PAINTER + if (f.color() != LColor::inherit) { + file += '}'; + ++count; + env = true; // Size change need not bother about closing env. + } +#else if (f.color() != INHERIT_COLOR) { file += '}'; ++count; env = true; // Size change need not bother about closing env. } +#endif if (f.emph() == ON) { file += '}'; ++count; @@ -828,6 +1004,18 @@ int LyXFont::latexWriteEndChanges(string & file, LyXFont const & base, LyXFont c } +#ifdef USE_PAINTER +LColor::color LyXFont::realColor() const +{ + if (latex() == ON) + return LColor::latex; + if (color() == LColor::none) + return LColor::foreground; + return color(); +} +#endif + + // Convert logical attributes to concrete shape attribute LyXFont::FONT_SHAPE LyXFont::realShape() const { @@ -845,6 +1033,7 @@ LyXFont::FONT_SHAPE LyXFont::realShape() const } +#ifndef USE_PAINTER GC LyXFont::getGC() const { GC gc; @@ -864,6 +1053,7 @@ GC LyXFont::getGC() const XSetFont(fl_display, gc, getXFontstruct()->fid); return gc; } +#endif XFontStruct * LyXFont::getXFontstruct() const @@ -991,6 +1181,53 @@ int LyXFont::signedStringWidth(string const & s) const } +#ifdef USE_PAINTER +int LyXFont::drawText(char const * s, int n, Pixmap, + int, int x) const +{ + if (realShape() != LyXFont::SMALLCAPS_SHAPE) { + /* XDrawString(fl_display, + pm, + getGC(), + x, baseline, + s, n); + XFlush(fl_display); */ + return XTextWidth(getXFontstruct(), s, n); + + } else { + // emulate smallcaps since X doesn't support this + char c; + int sx = x; + LyXFont smallfont = *this; + smallfont.decSize(); + smallfont.decSize(); + smallfont.setShape(LyXFont::UP_SHAPE); + for (int i = 0; i < n; ++i) { + c = s[i]; + if (islower(static_cast(c))){ + c = toupper(c); + /* XDrawString(fl_display, + pm, + smallfont.getGC(), + x, baseline, + &c, 1); */ + x += XTextWidth(smallfont.getXFontstruct(), + &c, 1); + //XFlush(fl_display); + } else { + /* XDrawString(fl_display, + pm, + getGC(), + x, baseline, + &c, 1);*/ + x += XTextWidth(getXFontstruct(), &c, 1); + //XFlush(fl_display); + } + } + return x - sx; + } +} +#else int LyXFont::drawText(char const * s, int n, Pixmap pm, int baseline, int x) const { @@ -1036,6 +1273,7 @@ int LyXFont::drawText(char const * s, int n, Pixmap pm, return x - sx; } } +#endif int LyXFont::drawString(string const & s, Pixmap pm, int baseline, int x) const diff --git a/src/lyxfont.h b/src/lyxfont.h index a3cbfc4e25..69711ef045 100644 --- a/src/lyxfont.h +++ b/src/lyxfont.h @@ -19,6 +19,7 @@ #include "LString.h" #include "debug.h" #include "direction.h" +#include "LColor.h" // It might happen that locale.h defines ON and OFF. This is not good // for us, since we use these names below. But of course this is due @@ -35,6 +36,8 @@ class LyXLex; +#define NEW_BITS 1 + /// class LyXFont { public: @@ -145,7 +148,8 @@ public: /// IGNORE }; - + +#ifndef USE_PAINTER /// enum FONT_COLOR { /// @@ -175,7 +179,8 @@ public: /// IGNORE_COLOR }; - +#endif + /// Trick to overload constructor and make it megafast enum FONT_INIT1 { /// @@ -237,9 +242,14 @@ public: /// FONT_MISC_STATE latex() const; - + +#ifdef USE_PAINTER + /// + LColor::color color() const; +#else /// FONT_COLOR color() const; +#endif /// FONT_DIRECTION direction() const; @@ -263,8 +273,13 @@ public: LyXFont & setNoun(LyXFont::FONT_MISC_STATE n); /// LyXFont & setLatex(LyXFont::FONT_MISC_STATE l); +#ifdef USE_PAINTER + /// + LyXFont & setColor(LColor::color c); +#else /// LyXFont & setColor(LyXFont::FONT_COLOR c); +#endif /// LyXFont & setDirection(LyXFont::FONT_DIRECTION d); @@ -315,7 +330,7 @@ public: bool resolved() const; /// Read a font specification from LyXLex. Used for layout files. - LyXFont & lyxRead(LyXLex&); + LyXFont & lyxRead(LyXLex &); /// Writes the changes from this font to orgfont in .lyx format in file void lyxWriteChanges(LyXFont const & orgfont, ostream &) const; @@ -369,14 +384,25 @@ public: int signedStringWidth(string const & s) const; /// Draws text and returns width of text - int drawText(char const*, int n, Pixmap, int baseline, int x) const; + int drawText(char const *, int n, Pixmap, int baseline, int x) const; /// int drawString(string const &, Pixmap pm, int baseline, int x) const; +#ifdef USE_PAINTER /// - GC getGC() const; + LColor::color realColor() const; +#endif + /// + XID getFontID() const { + return getXFontstruct()->fid; + } + +#ifndef USE_PAINTER + /// + GC getGC() const; +#endif /// friend inline bool operator==(LyXFont const & font1, LyXFont const & font2) { @@ -393,22 +419,78 @@ public: bool equalExceptLatex(LyXFont const &) const; private: +#ifdef NEW_BITS + /// + struct FontBits { + bool operator==(FontBits const & fb1) const { + return fb1.family == family && + fb1.series == series && + fb1.shape == shape && + fb1.size == size && + fb1.color == color && + fb1.emph == emph && + fb1.underbar == underbar && + fb1.noun == noun && + fb1.latex == latex && + fb1.direction == direction; + } + bool operator!=(FontBits const & fb1) const { + return !(fb1 == *this); + } + + FONT_FAMILY family; + FONT_SERIES series; + FONT_SHAPE shape; + FONT_SIZE size; +#ifdef USE_PAINTER + LColor::color color; +#else + FONT_COLOR color; +#endif + FONT_MISC_STATE emph; + FONT_MISC_STATE underbar; + FONT_MISC_STATE noun; + FONT_MISC_STATE latex; + FONT_DIRECTION direction; + }; +#else /// This have to be at least 32 bits, but 64 or more does not hurt typedef unsigned int ui32; +#endif /** Representation: bit table Layout of bit table: - 11 1111 111 122 222 222 2233 + 11 1111 111 122 222 222 2233 Bit 012 34 567 8901 2345 678 901 234 567 8901 - FFF SS SSS SSSS CCCC EEE UUU NNN LLL - aaa ee hhh iiii oooo mmm nnn ooo aaa - mmm rr aaa zzzz llll ppp ddd uuu ttt - + FFF SS SSS SSSS CCCC EEE UUU NNN LLL + aaa ee hhh iiii oooo mmm nnn ooo aaa + mmm rr aaa zzzz llll ppp ddd uuu ttt + + Bit 76543210 76543210 76543210 76543210 + --- Fam_Pos + -- Ser_Pos + --- Sha_Pos + ---- Siz_Pos + ---- Col_Pos + --- Emp_Pos + --- Und_Pos + - -- Nou_Pos + --- Lat_Pos + ---- Dir_Pos + Some might think this is a dirty representation, but it gives - us at least 25% speed-up, so why not? + us at least 25% speed-up, so why not? (Asger) + + First of all it is a maintence nightmare...and now that we need + to enlarge the Color bits with 2 (from 4 to 6), we have a problem + since a 32 bit entity is not large enough... (Lgb) */ - ui32 bits; +#ifdef NEW_BITS + FontBits bits; +#else + ui32 bits; + /// enum FONT_POSITION { /// @@ -450,25 +532,46 @@ private: /// Misc_Mask = 0x07 }; +#endif + + +#ifdef NEW_BITS + /// Sane font + static FontBits sane; + + /// All inherit font + static FontBits inherit; + /// All ignore font + static FontBits ignore; + +#else /// Sane font enum { sane = ui32(ROMAN_FAMILY) << Fam_Pos | ui32(MEDIUM_SERIES) << Ser_Pos | ui32(UP_SHAPE) << Sha_Pos | ui32(SIZE_NORMAL) << Siz_Pos +#ifdef USE_PAINTER + | ui32(LColor::none) << Col_Pos +#else | ui32(NONE) << Col_Pos +#endif | ui32(OFF) << Emp_Pos | ui32(OFF) << Und_Pos | ui32(OFF) << Nou_Pos | ui32(OFF) << Lat_Pos | ui32(LTR_DIR) << Dir_Pos}; - + /// All inherit font enum{ inherit = ui32(INHERIT_FAMILY) << Fam_Pos | ui32(INHERIT_SERIES) << Ser_Pos | ui32(INHERIT_SHAPE) << Sha_Pos | ui32(INHERIT_SIZE) << Siz_Pos +#ifdef USE_PAINTER + | ui32(LColor::inherit) << Col_Pos +#else | ui32(INHERIT_COLOR) << Col_Pos +#endif | ui32(INHERIT) << Emp_Pos | ui32(INHERIT) << Und_Pos | ui32(INHERIT) << Nou_Pos @@ -480,13 +583,17 @@ private: | ui32(IGNORE_SERIES) << Ser_Pos | ui32(IGNORE_SHAPE) << Sha_Pos | ui32(IGNORE_SIZE) << Siz_Pos +#ifdef USE_PAINTER + | ui32(LColor::ignore) << Col_Pos +#else | ui32(IGNORE_COLOR) << Col_Pos +#endif | ui32(IGNORE) << Emp_Pos | ui32(IGNORE) << Und_Pos | ui32(IGNORE) << Nou_Pos | ui32(IGNORE) << Lat_Pos | ui32(IGNORE_DIR) << Dir_Pos}; - +#endif /// Updates a misc setting according to request LyXFont::FONT_MISC_STATE setMisc(LyXFont::FONT_MISC_STATE newfont, LyXFont::FONT_MISC_STATE org); @@ -495,7 +602,7 @@ private: LyXFont::FONT_SHAPE realShape() const; /// - XFontStruct* getXFontstruct() const; + XFontStruct * getXFontstruct() const; }; ostream & operator<<(ostream &, LyXFont::FONT_MISC_STATE); @@ -537,8 +644,178 @@ inline LyXFont & LyXFont::operator=(LyXFont const & x) } +#ifdef NEW_BITS +// You don't have to understand the stuff below :-) +// It works, and it's bloody fast. (Asger) +// And impossible to work with. (Lgb) + +inline +LyXFont::FONT_FAMILY LyXFont::family() const +{ + return bits.family; +} + + +inline +LyXFont::FONT_SERIES LyXFont::series() const +{ + return bits.series; +} + + +inline +LyXFont::FONT_SHAPE LyXFont::shape() const +{ + return bits.shape; +} + + +inline +LyXFont::FONT_SIZE LyXFont::size() const +{ + return bits.size; +} + + +inline +LyXFont::FONT_MISC_STATE LyXFont::emph() const +{ + return bits.emph; +} + + +inline +LyXFont::FONT_MISC_STATE LyXFont::underbar() const +{ + return bits.underbar; +} + + +inline +LyXFont::FONT_MISC_STATE LyXFont::noun() const +{ + return bits.noun; +} + + +inline +LyXFont::FONT_MISC_STATE LyXFont::latex() const +{ + return bits.latex; +} + + +#ifdef USE_PAINTER +inline +LColor::color LyXFont::color() const +{ + return bits.color; +} +#else +inline +LyXFont::FONT_COLOR LyXFont::color() const +{ + return bits.color; +} +#endif + + +inline +LyXFont::FONT_DIRECTION LyXFont::direction() const +{ + return bits.direction; +} + +inline +LyXFont & LyXFont::setFamily(LyXFont::FONT_FAMILY f) +{ + bits.family = f; + return *this; +} + + +inline +LyXFont & LyXFont::setSeries(LyXFont::FONT_SERIES s) +{ + bits.series = s; + return *this; +} + + +inline +LyXFont & LyXFont::setShape(LyXFont::FONT_SHAPE s) +{ + bits.shape = s; + return *this; +} + + +inline +LyXFont & LyXFont::setSize(LyXFont::FONT_SIZE s) +{ + bits.size = s; + return *this; +} + + +inline +LyXFont & LyXFont::setEmph(LyXFont::FONT_MISC_STATE e) +{ + bits.emph = e; + return *this; +} + + +inline +LyXFont & LyXFont::setUnderbar(LyXFont::FONT_MISC_STATE u) +{ + bits.underbar = u; + return *this; +} + + +inline +LyXFont & LyXFont::setNoun(LyXFont::FONT_MISC_STATE n) +{ + bits.noun = n; + return *this; +} + +inline +LyXFont & LyXFont::setLatex(LyXFont::FONT_MISC_STATE l) +{ + bits.latex = l; + return *this; +} + + +#ifdef USE_PAINTER +inline +LyXFont & LyXFont::setColor(LColor::color c) +{ + bits.color = c; + return *this; +} +#else +inline +LyXFont & LyXFont::setColor(LyXFont::FONT_COLOR c) +{ + bits.color = c; + return *this; +} +#endif + +inline +LyXFont & LyXFont::setDirection(LyXFont::FONT_DIRECTION d) +{ + bits.direction = d; + return *this; +} +#else // You don't have to understand the stuff below :-) // It works, and it's bloody fast. (Asger) +// And impossible to work with. (Lgb) + inline LyXFont::FONT_FAMILY LyXFont::family() const { return LyXFont::FONT_FAMILY((bits >> Fam_Pos) & Fam_Mask); @@ -587,10 +864,18 @@ inline LyXFont::FONT_MISC_STATE LyXFont::latex() const } -inline LyXFont::FONT_COLOR LyXFont::color() const +#ifdef USE_PAINTER +inline LColor::color LyXFont::color() const +{ + return LColor::color((bits >> Col_Pos) & Col_Mask); +} +#else +inline LyXFont::FONT_COLOR LyXFont::color() const { - return LyXFont::FONT_COLOR((bits >> Col_Pos) & Col_Mask); + return FONT_COLOR((bits >> Col_Pos) & Col_Mask); } +#endif + inline LyXFont::FONT_DIRECTION LyXFont::direction() const { @@ -660,12 +945,21 @@ inline LyXFont & LyXFont::setLatex(LyXFont::FONT_MISC_STATE l) } +#ifdef USE_PAINTER +inline LyXFont & LyXFont::setColor(LColor::color c) +{ + bits &= ~(Col_Mask << Col_Pos); + bits |= ui32(c) << Col_Pos; + return *this; +} +#else inline LyXFont & LyXFont::setColor(LyXFont::FONT_COLOR c) { bits &= ~(Col_Mask << Col_Pos); bits |= ui32(c) << Col_Pos; return *this; } +#endif inline LyXFont & LyXFont::setDirection(LyXFont::FONT_DIRECTION d) { @@ -673,5 +967,6 @@ inline LyXFont & LyXFont::setDirection(LyXFont::FONT_DIRECTION d) bits |= ui32(d) << Dir_Pos; return *this; } +#endif #endif diff --git a/src/lyxfr1.C b/src/lyxfr1.C index 5e8461fee0..6143c9d8f1 100644 --- a/src/lyxfr1.C +++ b/src/lyxfr1.C @@ -265,10 +265,14 @@ bool LyXFindReplace1::SearchCB(bool fForward) current_view->owner()->getMiniBuffer()->Set(_("String not found!")); result = false; } - + +#ifdef NEW_WA + if (current_view->focus()) + current_view->getScreen()->ShowCursor(); +#else if (current_view->getWorkArea()->focus) current_view->getScreen()->ShowCursor(); - +#endif return result; } diff --git a/src/lyxfunc.C b/src/lyxfunc.C index 59508367fb..4fa02f314e 100644 --- a/src/lyxfunc.C +++ b/src/lyxfunc.C @@ -63,6 +63,7 @@ #include "ImportLaTeX.h" #include "ImportNoweb.h" #include "layout.h" +#include "WorkArea.h" extern bool cursor_follows_scrollbar; @@ -662,10 +663,20 @@ string LyXFunc::Dispatch(int ac, case LFUN_CENTER: // this is center and redraw. owner->view()->beforeChange(); if (owner->view()->text->cursor.y > - owner->view()->getWorkArea()->h / 2) { +#ifdef NEW_WA + owner->view()->getWorkArea()->height() / 2) +#else + owner->view()->getWorkArea()->h / 2) +#endif + { owner->view()->getScreen()-> Draw(owner->view()->text->cursor.y - - owner->view()->getWorkArea()->h / 2); +#ifdef NEW_WA + owner->view()->getWorkArea()->height() / 2 +#else + owner->view()->getWorkArea()->h / 2 +#endif + ); } else { // <= owner->view()->getScreen()-> Draw(0); @@ -1299,6 +1310,34 @@ string LyXFunc::Dispatch(int ac, case LFUN_LEFT: { +#ifdef USE_PAINTER + // This is soooo ugly. Isn`t it possible to make + // it simpler? (Lgb) + LyXText * txt = owner->view()->text; + LyXDirection direction = txt->cursor.par->getParDirection(); + if(!txt->mark_set) owner->view()->beforeChange(); + owner->view()->update(-2); + if (direction == LYX_DIR_LEFT_TO_RIGHT) + txt->CursorLeft(); + if (txt->cursor.pos < txt->cursor.par->Last() + && txt->cursor.par->GetChar(txt->cursor.pos) + == LyXParagraph::META_INSET + && txt->cursor.par->GetInset(txt->cursor.pos) + && txt->cursor.par->GetInset(txt->cursor.pos)->Editable() == 2) { + Inset * tmpinset = txt->cursor.par->GetInset(txt->cursor.pos); + setMessage(tmpinset->EditMessage()); + tmpinset->Edit(tmpinset->width(owner->view()->painter(), + txt->GetFont(txt->cursor.par, + txt->cursor.pos)), 0); + break; + } + if (direction == LYX_DIR_RIGHT_TO_LEFT) + txt->CursorRight(); + + owner->view()->text->FinishUndo(); + moveCursorUpdate(false); + owner->getMiniBuffer()->Set(CurrentState()); +#else // This is soooo ugly. Isn`t it possible to make // it simpler? (Lgb) LyXText * txt = owner->view()->text; @@ -1324,6 +1363,7 @@ string LyXFunc::Dispatch(int ac, owner->view()->text->FinishUndo(); moveCursorUpdate(false); owner->getMiniBuffer()->Set(CurrentState()); +#endif } break; @@ -1970,10 +2010,20 @@ string LyXFunc::Dispatch(int ac, // Recenter screen owner->view()->beforeChange(); if (owner->view()->text->cursor.y > - owner->view()->getWorkArea()->h / 2) { +#ifdef NEW_WA + owner->view()->getWorkArea()->height() / 2 +#else + owner->view()->getWorkArea()->h / 2 +#endif + ) { owner->view()->getScreen()-> Draw(owner->view()->text->cursor.y - - owner->view()->getWorkArea()->h/2); +#ifdef NEW_WA + owner->view()->getWorkArea()->height() / 2 +#else + owner->view()->getWorkArea()->h / 2 +#endif + ); } else { // <= owner->view()->getScreen()-> Draw(0); diff --git a/src/lyxscreen.h b/src/lyxscreen.h index 22731d3268..75c411410d 100644 --- a/src/lyxscreen.h +++ b/src/lyxscreen.h @@ -4,8 +4,8 @@ * * LyX, The Document Processor * - * Copyright 1995 Matthias Ettrich - * Copyright 1995-1999 The LyX Team + * Copyright 1995 Matthias Ettrich + * Copyright 1995-2000 The LyX Team * * ====================================================== */ @@ -24,6 +24,10 @@ class LyXText; struct Row; typedef unsigned short Dimension; +class BufferView; + +#define NEW_WA 1 + /** The class LyXScreen is used for the main Textbody. Concretely, the screen is held in a pixmap. This pixmap is kept up to date and used to optimize drawing on the screen. @@ -32,12 +36,15 @@ typedef unsigned short Dimension; class LyXScreen { public: /// - LyXScreen(Window window, + LyXScreen(BufferView *, Window window, +#ifdef NEW_WA + Pixmap p, +#endif Dimension width, Dimension height, Dimension offset_x, Dimension offset_y, - LyXText *text_ptr); + LyXText * text_ptr); /// ~LyXScreen(); @@ -86,6 +93,7 @@ public: or only current row */ void SmallUpdate(); +#ifndef USE_PAINTER /** Functions for drawing into the LyXScreen. The number of drawing functions should be minimized, now there is too many. And also there is mixed X and XForms drawing @@ -132,7 +140,7 @@ public: /// int drawString(LyXFont const & font, string const & str, int baseline, int x); - +#endif /// first visible pixel-row long first; @@ -148,6 +156,9 @@ private: /// y is a coordinate of the text void DrawOneRow(Row * row, long & y_text); + /// + BufferView * owner; + /// LyXText * text; @@ -178,11 +189,15 @@ private: /// Row * screen_refresh_row; /// - friend class InsetFormula; + friend class InsetFormula; +#ifdef USE_PAINTER + /// + GC gc_copy; +#endif }; // Some of the easy to inline draw methods: - +#ifndef USE_PAINTER inline void LyXScreen::drawPoint(GC gc, int x, int y) { @@ -315,5 +330,6 @@ int LyXScreen::drawString(LyXFont const & font, string const & str, { return font.drawString(str, foreground, baseline, x); } +#endif #endif diff --git a/src/lyxtext.h b/src/lyxtext.h index ccc024fd8c..b9fe99cb20 100644 --- a/src/lyxtext.h +++ b/src/lyxtext.h @@ -26,6 +26,7 @@ class Buffer; class BufferParams; class LyXScreen; class Row; +class BufferView; /** This class holds the mapping between buffer paragraphs and screen rows. @@ -58,11 +59,14 @@ public: mutable LyXFont real_current_font; /// Constructor - LyXText(int paperwidth, Buffer *); + LyXText(BufferView *, int paperwidth, Buffer *); /// Destructor ~LyXText(); - + + /// + void owner(BufferView *); + /// LyXFont GetFont(LyXParagraph * par, LyXParagraph::size_type pos) const; @@ -285,9 +289,14 @@ public: /** returns a printed row in a pixmap. The y value is needed to decide, wether it is selected text or not. This is a strange solution but faster. - */ + */ +#ifdef USE_PAINTER + void GetVisibleRow(int offset, + Row * row_ptr, long y); +#else void GetVisibleRow(LyXScreen & scr, int offset, Row * row_ptr, long y); +#endif /* footnotes: */ /// @@ -474,6 +483,9 @@ public: /// unsigned short paperWidth() const { return paperwidth; } private: + /// + BufferView * owner_; + /// width of the paper unsigned short paperwidth; @@ -543,10 +555,17 @@ private: /// int SingleWidth(LyXParagraph * par, LyXParagraph::size_type pos, char c) const; +#ifdef USE_PAINTER + /// + void draw(Row const * row, + LyXParagraph::size_type & pos, + int offset, float & x); +#else /// void Draw(Row const * row, LyXParagraph::size_type & pos, LyXScreen & scr, int offset, float & x); +#endif /// get the next breakpoint in a given paragraph LyXParagraph::size_type NextBreakPoint(Row const * row, int width) const; @@ -610,7 +629,8 @@ private: LyXParagraph::size_type offset) const; /// Maps positions in the visual string to positions in logical string. - inline LyXParagraph::size_type log2vis(LyXParagraph::size_type pos) const { + inline + LyXParagraph::size_type log2vis(LyXParagraph::size_type pos) const { if (bidi_start == -1) return pos; else @@ -618,7 +638,8 @@ private: } /// Maps positions in the logical string to positions in visual string. - inline LyXParagraph::size_type vis2log(LyXParagraph::size_type pos) const { + inline + LyXParagraph::size_type vis2log(LyXParagraph::size_type pos) const { if (bidi_start == -1) return pos; else diff --git a/src/mathed/formula.C b/src/mathed/formula.C index 8a05232bb3..0da5e63e5c 100644 --- a/src/mathed/formula.C +++ b/src/mathed/formula.C @@ -39,6 +39,7 @@ #include "lyx_gui_misc.h" #include "support/LOstream.h" #include "LyXView.h" +#include "Painter.h" extern void UpdateInset(BufferView *, Inset * inset, bool mark_dirty = true); @@ -141,9 +142,14 @@ LyXFont WhichFont(short type, int size) lyxerr << "Mathed Error: wrong font size: " << size << endl; break; } - + +#ifdef USE_PAINTER if (type != LM_TC_TEXTRM) - f.setColor(LyXFont::MATH); + f.setColor(LColor::math); +#else + if (type != LM_TC_TEXTRM) + f.setColor(LyXFont::MATH); +#endif return f; } @@ -183,7 +189,16 @@ void mathed_init_fonts() //removed 'static' because DEC cxx does not MathedInset::df_width = f.width('I'); } - +#ifdef USE_PAINTER +LyXFont mathed_get_font(short type, int size) +{ + LyXFont f = WhichFont(type, size); + if (type == LM_TC_TEX) { + f.setLatex(LyXFont::ON); + } + return f; +} +#else void mathed_set_font(short type, int size) { if (!canvasGC) { @@ -200,6 +215,7 @@ void mathed_set_font(short type, int size) } else mathGC = f.getGC(); } +#endif int mathed_string_width(short type, int size, byte const * s, int ls) @@ -256,6 +272,23 @@ int mathed_char_height(short type, int size, byte c, int & asc, int & des) // In a near future maybe we use a better fonts renderer +#ifdef USE_PAINTER +void MathedInset::drawStr(Painter & pain, short type, int size, + int x, int y, byte * s, int ls) +{ + string st; + if (MathIsBinary(type)) { + for (int i = 0; i < ls; ++i) { +#warning What conversion should be done for s[i] here? + st += string(" ") + char(s[i]) + ' '; + } + } else { + st = string(reinterpret_cast(s), ls); + } + LyXFont mf = mathed_get_font(type, size); + pain.text(x, y, st, mf); +} +#else void MathedInset::drawStr(short type, int siz, int x, int y, byte * s, int ls) { mathed_set_font(type, siz); @@ -275,6 +308,7 @@ void MathedInset::drawStr(short type, int siz, int x, int y, byte * s, int ls) XDrawString(fl_display, pm, gc, x, y, reinterpret_cast(s), ls); XFlush(fl_display); } +#endif InsetFormula::InsetFormula(bool display) @@ -395,26 +429,108 @@ void InsetFormula::Read(LyXLex & lex) } +#ifdef USE_PAINTER +int InsetFormula::ascent(Painter &, LyXFont const &) const +{ + return par->Ascent() + ((disp_flag) ? 8 : 1); +} +#else int InsetFormula::Ascent(LyXFont const &) const { return par->Ascent() + ((disp_flag) ? 8 : 1); } +#endif +#ifdef USE_PAINTER +int InsetFormula::descent(Painter &, LyXFont const &) const +{ + return par->Descent() + ((disp_flag) ? 8 : 1); +} +#else int InsetFormula::Descent(LyXFont const &) const { return par->Descent() + ((disp_flag) ? 8 : 1); } +#endif +#ifdef USE_PAINTER +int InsetFormula::width(Painter &, LyXFont const & f) const +{ + lfont_size = f.size(); + par->Metrics(); + return par->Width(); //+2; +} +#else int InsetFormula::Width(LyXFont const & f) const { lfont_size = f.size(); par->Metrics(); return par->Width(); //+2; } +#endif +#ifdef USE_PAINTER +void InsetFormula::draw(Painter & pain, LyXFont const &, + int baseline, float & x) const +{ + LyXFont font = mathed_get_font(LM_TC_TEXTRM, LM_ST_TEXT); + + lfont_size = font.size(); + /// Let's try to wait a bit with this... (Lgb) + //UpdatableInset::draw(pain, font, baseline, x); + + // otherwise a segfault could occur + // in some XDrawRectangles (i.e. matrix) (Matthias) + if (mathcursor && mathcursor->GetPar() == par) { + if (mathcursor->Selection()) { + int n; + int * xp = 0; + int * yp = 0; + mathcursor->SelGetArea(xp, yp, n); + pain.fillPolygon(xp, yp, n, LColor::selection); + } + mathcursor->draw(pain, int(x), baseline); + } else { + par->draw(pain, int(x), baseline); + } + x += float(width(pain, font)); + + if (par->GetType() == LM_OT_PARN || par->GetType() == LM_OT_MPARN) { + LyXFont font = WhichFont(LM_TC_BF, par->size); + font.setLatex(LyXFont::OFF); + + if (par->GetType() == LM_OT_PARN) { + string str; + if (!label.empty()) + str = string("(") + label + ")"; + else + str = string("(#)"); + pain.text(int(x + 20), baseline, str, font); + } else if (par->GetType() == LM_OT_MPARN) { + MathMatrixInset * mt = + static_cast(par); + int y; + MathedRowSt const * crow = mt->getRowSt(); + while (crow) { + y = baseline + crow->getBaseline(); + if (crow->isNumbered()) { + string str; + if (crow->getLabel()) + str = string("(") + crow->getLabel() + ")"; + else + str = "(#)"; + pain.text(int(x + 20), y, str, font); + } + crow = crow->getNext(); + } + } + } + cursor_visible = false; +} +#else void InsetFormula::Draw(LyXFont f, LyXScreen & scr, int baseline, float & x) { // This is Alejandros domain so I'll use this @@ -469,6 +585,7 @@ void InsetFormula::Draw(LyXFont f, LyXScreen & scr, int baseline, float & x) } cursor_visible = false; } +#endif void InsetFormula::Edit(int x, int y) @@ -1211,6 +1328,23 @@ bool InsetFormula::LocalDispatch(int action, char const * arg) } +#ifdef USE_PAINTER +void +MathFuncInset::draw(Painter & pain, int x, int y) +{ + if (name && name[0] > ' ') { + LyXFont font = WhichFont(LM_TC_TEXTRM, size); + font.setLatex(LyXFont::ON); + x += (font.textWidth("I", 1) + 3) / 4; + if (mono_video) { + int a = font.maxAscent(); + int d = font.maxDescent(); + pain.fillRectangle(x, y - a, font.textWidth(name, strlen(name)), a + d); + } + pain.text(x, y, name, font); + } +} +#else void MathFuncInset::Draw(int x, int y) { @@ -1228,7 +1362,7 @@ MathFuncInset::Draw(int x, int y) font.drawString(name, pm, y, x); } } - +#endif void MathFuncInset::Metrics() { diff --git a/src/mathed/formula.h b/src/mathed/formula.h index 1205e2ced3..491616ed99 100644 --- a/src/mathed/formula.h +++ b/src/mathed/formula.h @@ -36,6 +36,16 @@ public: InsetFormula(MathParInset *); /// ~InsetFormula(); +#ifdef USE_PAINTER + /// + int ascent(Painter &, LyXFont const &) const; + /// + int descent(Painter &, LyXFont const &) const; + /// + int width(Painter &, LyXFont const &) const; + /// + void draw(Painter &, LyXFont const &, int baseline, float & x) const; +#else /// int Ascent(LyXFont const & font) const; /// @@ -44,6 +54,7 @@ public: int Width(LyXFont const & font) const; /// void Draw(LyXFont font, LyXScreen & scr, int baseline, float & x); +#endif /// void Write(ostream &); /// diff --git a/src/mathed/formulamacro.C b/src/mathed/formulamacro.C index fa9f94cd89..90576cbdd9 100644 --- a/src/mathed/formulamacro.C +++ b/src/mathed/formulamacro.C @@ -31,6 +31,7 @@ #include "lyxscreen.h" #include "lyxdraw.h" #include "gettext.h" +#include "Painter.h" InsetFormulaMacro::InsetFormulaMacro() @@ -115,6 +116,16 @@ void InsetFormulaMacro::Read(LyXLex & lex) } +#ifdef USE_PAINTER +int InsetFormulaMacro::ascent(Painter & pain, LyXFont const & f) const +{ + if (opened) { + tmacro->update(); + return InsetFormula::ascent(pain, f); + } + return f.maxAscent()+3; +} +#else int InsetFormulaMacro::Ascent(LyXFont const & f) const { if (opened) { @@ -123,8 +134,19 @@ int InsetFormulaMacro::Ascent(LyXFont const & f) const } return f.maxAscent()+3; } +#endif +#ifdef USE_PAINTER +int InsetFormulaMacro::descent(Painter & pain, LyXFont const & f) const +{ + if (opened) { + tmacro->update(); + return InsetFormula::descent(pain, f); + } + return f.maxDescent()+1; +} +#else int InsetFormulaMacro::Descent(LyXFont const & f) const { if (opened) { @@ -133,8 +155,21 @@ int InsetFormulaMacro::Descent(LyXFont const & f) const } return f.maxDescent()+1; } +#endif +#ifdef USE_PAINTER +int InsetFormulaMacro::width(Painter & pain, LyXFont const & f) const +{ + if (opened) { + tmacro->update(); + return InsetFormula::width(pain, f); + } + string ilabel(_("Macro: ")); + ilabel += name; + return 6 + f.stringWidth(ilabel); +} +#else int InsetFormulaMacro::Width(LyXFont const & f) const { if (opened) { @@ -145,8 +180,37 @@ int InsetFormulaMacro::Width(LyXFont const & f) const ilabel += name; return 6 + f.stringWidth(ilabel); } +#endif +#ifdef USE_PAINTER +void InsetFormulaMacro::draw(Painter & pain, LyXFont const & f, + int baseline, float & x) const +{ + LyXFont font(f); + tmacro->update(); + if (opened) { + tmacro->setEditMode(true); + InsetFormula::draw(pain, font, baseline, x); + tmacro->setEditMode(false); + } else { + font.setColor(LColor::math); + + int y = baseline - ascent(pain, font) + 1; + int w = width(pain, font) - 2; + int h = (ascent(pain, font) + descent(pain, font) - 2); + + + pain.fillRectangle(int(x), y, w, h, LColor::mathbg); + pain.rectangle(int(x), y, w, h, LColor::mathframe); + + string s(_("Macro: ")); + s += name; + pain.text(int(x + 2), baseline, s, font); + x += width(pain, font) - 1; + } +} +#else void InsetFormulaMacro::Draw(LyXFont font, LyXScreen & scr, int baseline, float & x) { @@ -171,6 +235,7 @@ void InsetFormulaMacro::Draw(LyXFont font, LyXScreen & scr, x += Width(font) - 1; } } +#endif void InsetFormulaMacro::Edit(int x, int y) diff --git a/src/mathed/formulamacro.h b/src/mathed/formulamacro.h index 486b16ae06..d2ce795473 100644 --- a/src/mathed/formulamacro.h +++ b/src/mathed/formulamacro.h @@ -35,6 +35,16 @@ public: InsetFormulaMacro(string name, int na = 0, bool env = false); /// ~InsetFormulaMacro(); +#ifdef USE_PAINTER + /// + int ascent(Painter &, LyXFont const &) const; + /// + int descent(Painter &, LyXFont const &) const; + /// + int width(Painter &, LyXFont const &) const; + /// + void draw(Painter &, LyXFont const &, int baseline, float & x) const; +#else /// int Ascent(LyXFont const & font) const; /// @@ -43,6 +53,7 @@ public: int Width(LyXFont const & font) const; /// void Draw(LyXFont font, LyXScreen & scr, int baseline, float & x); +#endif /// void Read(LyXLex & lex); /// diff --git a/src/mathed/math_cursor.C b/src/mathed/math_cursor.C index f33026ae04..90c5beb193 100644 --- a/src/mathed/math_cursor.C +++ b/src/mathed/math_cursor.C @@ -28,6 +28,8 @@ #include "math_root.h" #include "support/lstrings.h" #include "debug.h" +#include "LColor.h" +#include "Painter.h" extern void mathed_set_font(short type, int style); @@ -149,6 +151,25 @@ void MathedCursor::SetPar(MathParInset * p) } +#ifdef USE_PAINTER +void MathedCursor::draw(Painter & pain, int x, int y) +{ + // lyxerr << "Cursor[" << x << " " << y << "] "; + //win = pm; // win = (mathedCanvas) ? mathedCanvas: pm; + par->Metrics(); + int w = par->Width() + 2; + int a = par->Ascent() + 1; + int h = par->Height() + 1; + if (par->GetType() > LM_OT_PAR) { a += 4; h += 8; } + + pain.rectangle(x - 1, y - a, + x - 1 + w, y - a + h, + LColor::mathframe); + + par->draw(pain, x, y); + cursor->Adjust(); +} +#else void MathedCursor::Draw(long unsigned pm, int x, int y) { // lyxerr << "Cursor[" << x << " " << y << "] "; @@ -165,8 +186,24 @@ void MathedCursor::Draw(long unsigned pm, int x, int y) par->Draw(x, y); cursor->Adjust(); } +#endif +#ifdef USE_PAINTER +void MathedCursor::Redraw(Painter & pain) +{ + lyxerr[Debug::MATHED] << "Mathed: Redrawing!" << endl; + par->Metrics(); + int w = par->Width(), h = par->Height(); + int x, y; + par->GetXY(x, y); + //mathed_set_font(LM_TC_VAR, 1); + pain.fillRectangle(x, y - par->Ascent(), + x + w, y - par->Ascent() + h, + LColor::mathbg); + par->draw(pain, x, y); +} +#else void MathedCursor::Redraw() { lyxerr[Debug::MATHED] << "Mathed: Redrawing!" << endl; @@ -180,6 +217,7 @@ void MathedCursor::Redraw() MathParInset::pm = win; par->Draw(x, y); } +#endif bool MathedCursor::Left(bool sel) @@ -920,6 +958,71 @@ void MathedCursor::SelBalance() } +#ifdef USE_PAINTER +void MathedCursor::SelGetArea(int * xp, int * yp, int & np) +{ + if (!selection) { + np = 0; + return; + } + + static int xpoint[10]; + static int ypoint[10]; + + // single row selection + int i = 0, x, y, a, d, xo, yo, x1, y1, a1, d1; + + // Balance anchor and cursor + SelBalance(); + + cursor->p->GetXY(xo, yo); + int w = cursor->p->Width(); + cursor->GetPos(x1, y1); + cursor->getAD(a1, d1); + anchor->GetPos(x, y); + anchor->getAD(a, d); + + xpoint[i] = x; + ypoint[i++] = y + d; + xpoint[i] = x; + ypoint[i++] = y - a; + + if (y != y1) { + xpoint[i] = xo + w; + ypoint[i++] = y - a; + + if (x1 < xo + w) { + xpoint[i] = xo + w; + ypoint[i++] = y1 - a; + } + } + + xpoint[i] = x1; + ypoint[i++] = y1 - a; + xpoint[i] = x1; + ypoint[i++] = y1 + d; + + if (y != y1) { + xpoint[i] = xo; + ypoint[i++] = y1 + d; + if (x > xo) { + xpoint[i] = xo; + ypoint[i++] = y + d; + } + } + xpoint[i] = xpoint[0]; + ypoint[i++] = ypoint[0]; + + xp = &xpoint[0]; + yp = &ypoint[0]; + np = i; +// lyxerr << "AN[" << x << " " << y << " " << x1 << " " << y1 << "] "; +// lyxerr << "MT[" << a << " " << d << " " << a1 << " " << d1 << "] "; +// for (i = 0; i < np; ++i) +// lyxerr << "XY[" << point[i].x << " " << point[i].y << "] "; + +} +#else XPoint * MathedCursor::SelGetArea(int & np) { if (!selection) { @@ -979,7 +1082,7 @@ XPoint * MathedCursor::SelGetArea(int & np) return &point[0]; } - +#endif void MathedCursor::setAccent(int ac) diff --git a/src/mathed/math_cursor.h b/src/mathed/math_cursor.h index 1772357f3e..c8c16e9094 100644 --- a/src/mathed/math_cursor.h +++ b/src/mathed/math_cursor.h @@ -37,7 +37,7 @@ class MathedCursor { /// void Insert(byte, MathedTextCodes t = LM_TC_MIN); /// - void Insert(MathedInset*, int t = LM_TC_INSET); + void Insert(MathedInset *, int t = LM_TC_INSET); /// void Home(); /// @@ -56,10 +56,17 @@ class MathedCursor { bool Push(); /// Pull out an argument from its container inset bool pullArg(); +#ifdef USE_PAINTER + /// + void draw(Painter &, int x, int y); + /// + void Redraw(Painter &); +#else /// void Draw(long unsigned pm, int x, int y); /// void Redraw(); +#endif /// void Delete(); /// @@ -115,9 +122,13 @@ class MathedCursor { /// void SelClear(); /// - void SelBalance(); + void SelBalance(); +#ifdef USE_PAINTER + void SelGetArea(int * xp, int * yp, int & n); +#else /// XPoint * SelGetArea(int &); +#endif /// void clearLastCode() { lastcode = LM_TC_MIN; } /// diff --git a/src/mathed/math_defs.h b/src/mathed/math_defs.h index 0dc1679cd8..f9cdbabc46 100644 --- a/src/mathed/math_defs.h +++ b/src/mathed/math_defs.h @@ -31,6 +31,8 @@ #include "array.h" +class Painter; + /// enum math_align { @@ -224,9 +226,14 @@ class MathedInset { MathedInset(MathedInset *); /// virtual ~MathedInset() {} - + +#ifdef USE_PAINTER + /// Draw the object + virtual void draw(Painter &, int x, int baseline) = 0; +#else /// Draw the object virtual void Draw(int x, int baseline) = 0; +#endif /// Write LaTeX and Lyx code virtual void Write(ostream &) = 0; @@ -267,8 +274,10 @@ class MathedInset { virtual void SetStyle(short st) { size = st; } // Metrics(); /// virtual void SetName(char const * n) { name = n; } +#ifndef USE_PAINTER /// void setDrawable(long unsigned int d) { pm = d; } +#endif protected: /// @@ -283,14 +292,20 @@ class MathedInset { int descent; /// short size; +#ifndef USE_PAINTER /// This works while only one process can draw unless /// the process have their own data - static long unsigned int pm; + static unsigned long pm; +#endif /// Default metrics static int df_asc, df_des, df_width; /// In a near future maybe we use a better fonts renderer than X +#ifdef USE_PAINTER + void drawStr(Painter &, short, int, int, int, byte *, int); +#else void drawStr(short, int, int, int, byte *, int); +#endif /// friend class MathedCursor; /// @@ -332,7 +347,11 @@ class MathParInset: public MathedInset { virtual MathedInset * Clone(); /// Draw the object on a drawable +#ifdef USE_PAINTER + virtual void draw(Painter &, int x, int baseline); +#else virtual void Draw(int x, int baseline); +#endif /// Write LaTeX code virtual void Write(ostream &); @@ -490,8 +509,13 @@ class MathMatrixInset: public MathParInset { MathedInset * Clone(); /// virtual ~MathMatrixInset(); +#ifdef USE_PAINTER + /// + void draw(Painter &, int, int); +#else /// void Draw(int, int); +#endif /// void Write(ostream &); /// diff --git a/src/mathed/math_delim.C b/src/mathed/math_delim.C index 995973bbfe..9f5a462f6b 100644 --- a/src/mathed/math_delim.C +++ b/src/mathed/math_delim.C @@ -21,6 +21,8 @@ #include #include "symbol_def.h" #include "math_inset.h" +#include "LColor.h" +#include "Painter.h" /* * Internal struct of a drawing: code n x1 y1 ... xn yn, where code is: @@ -296,7 +298,73 @@ static int search_deco(int code) if (!math_deco_table[i].code) i = -1; return i; } - + + +#ifdef USE_PAINTER +void mathed_draw_deco(Painter & pain, int x, int y, int w, int h, int code) +{ + Matriz mt, sqmt; + float xx, yy, x2, y2; + int i = 0; + + int j = search_deco(code); + if (j < 0) return; + + int r = math_deco_table[j].angle; + float * d = math_deco_table[j].data; + + if (h > 70 && (math_deco_table[j].code == int('(') || math_deco_table[j].code == int(')'))) + d = parenthHigh; + + mt.rota(r); + mt.escala(w, h); + + int n = (w < h) ? w: h; + sqmt.rota(r); + sqmt.escala(n, n); + if (r > 0 && r < 3) y += h; + if (r >= 2) x += w; + do { + code = int(d[i++]); + switch (code) { + case 0: break; + case 1: + case 3: + { + xx = d[i++]; yy = d[i++]; + x2 = d[i++]; y2 = d[i++]; + if (code == 3) + sqmt.transf(xx, yy, xx, yy); + else + mt.transf(xx, yy, xx, yy); + mt.transf(x2, y2, x2, y2); + pain.line(x + int(xx), y + int(yy), + x + int(x2), y + int(y2), + LColor::mathline); + break; + } + case 2: + case 4: + { + int xp[32], yp[32]; + n = int(d[i++]); + for (j = 0; j < n; ++j) { + xx = d[i++]; yy = d[i++]; +// lyxerr << " " << xx << " " << yy << " "; + if (code == 4) + sqmt.transf(xx, yy, xx, yy); + else + mt.transf(xx, yy, xx, yy); + xp[j] = x + int(xx); + yp[j] = y + int(yy); + // lyxerr << "P[" << j " " << xx << " " << yy << " " << x << " " << y << "]"; + } + pain.lines(xp, yp, n, LColor::mathline); + } + } + } while (code); +} +#else void mathed_draw_deco(Window win, int x, int y, int w, int h, int code) { Matriz mt, sqmt; @@ -361,7 +429,31 @@ void mathed_draw_deco(Window win, int x, int y, int w, int h, int code) } } while (code); } +#endif + +#ifdef USE_PAINTER +void +MathDelimInset::draw(Painter & pain, int x, int y) +{ + xo = x; yo = y; + MathParInset::draw(pain, x + dw + 2, y - dh); + + if (left == '.') { + pain.line(x + 4, yo - ascent, + x + 4, yo + descent, + LColor::mathcursor); + } else + mathed_draw_deco(pain, x, y - ascent, dw, Height(), left); + x += Width()-dw-2; + if (right == '.') { + pain.line(x + 4, yo - ascent, + x + 4, yo + descent, + LColor::mathcursor); + } else + mathed_draw_deco(pain, x, y-ascent, dw, Height(), right); +} +#else void MathDelimInset::Draw(int x, int y) { @@ -383,6 +475,8 @@ MathDelimInset::Draw(int x, int y) else mathed_draw_deco(pm, x, y-ascent, dw, Height(), right); } +#endif + void MathDelimInset::Metrics() @@ -401,12 +495,21 @@ MathDelimInset::Metrics() } +#ifdef USE_PAINTER +void +MathDecorationInset::draw(Painter & pain, int x, int y) +{ + MathParInset::draw(pain, x + (width - dw) / 2, y); + mathed_draw_deco(pain, x, y + dy, width, dh, deco); +} +#else void MathDecorationInset::Draw(int x, int y) { MathParInset::Draw(x+(width-dw)/2, y); mathed_draw_deco(pm, x, y+dy, width, dh, deco); } +#endif void @@ -430,6 +533,22 @@ MathDecorationInset::Metrics() width = w; } + +#ifdef USE_PAINTER +void +MathAccentInset::draw(Painter & pain, int x, int y) +{ + int dw = width - 2; + + if (inset) { + inset->draw(pain, x, y); + } else { + drawStr(pain, fn, size, x, y, &c, 1); + } + x += (code == LM_not) ? (width-dw) / 2 : 2; + mathed_draw_deco(pain, x, y - dy, dw, dh, code); +} +#else void MathAccentInset::Draw(int x, int y) { @@ -453,6 +572,8 @@ MathAccentInset::Draw(int x, int y) x += (code == LM_not) ? (width-dw)/2: 2; mathed_draw_deco(pm, x, y-dy, dw, dh, code); } +#endif + void MathAccentInset::Metrics() @@ -482,6 +603,16 @@ MathAccentInset::Metrics() } +#ifdef USE_PAINTER +void +MathDotsInset::draw(Painter & pain, int x, int y) +{ + mathed_draw_deco(pain, x + 2, y - dh, width - 2, ascent, code); + if (code == LM_vdots || code == LM_ddots) ++x; + if (code != LM_vdots) --y; + mathed_draw_deco(pain, x + 2, y - dh, width - 2, ascent, code); +} +#else void MathDotsInset::Draw(int x, int y) { @@ -489,7 +620,9 @@ MathDotsInset::Draw(int x, int y) if (code == LM_vdots || code == LM_ddots) ++x; if (code!= LM_vdots) --y; mathed_draw_deco(pm, x + 2, y - dh, width - 2, ascent, code); -} +} +#endif + void MathDotsInset::Metrics() diff --git a/src/mathed/math_draw.C b/src/mathed/math_draw.C index aece4abd22..9efb95adcf 100644 --- a/src/mathed/math_draw.C +++ b/src/mathed/math_draw.C @@ -20,8 +20,14 @@ #include "math_cursor.h" #include "math_parser.h" #include "debug.h" +#include "lyxfont.h" +#include "Painter.h" +#ifdef USE_PAINTER +extern LyXFont mathed_get_font(short type, int size); +#else extern void mathed_set_font(short type, int style); +#endif extern int mathed_char_width(short type, int style, byte c); extern int mathed_string_width(short type, int style, byte const* s, int ls); extern int mathed_string_height(short, int, byte const*, int, int&, int&); @@ -30,8 +36,30 @@ extern int mathed_char_height(short, int, byte, int&, int&); GC canvasGC= 0, mathGC= 0, mathLineGC= 0, latexGC= 0, cursorGC= 0, mathFrameGC= 0; -long unsigned int MathedInset::pm; +#ifndef USE_PAINTER +unsigned long MathedInset::pm; +#endif +#ifdef USE_PAINTER +void +MathSpaceInset::draw(Painter & pain, int x, int y) +{ + +// XPoint p[4] = {{++x, y-3}, {x, y}, {x+width-2, y}, {x+width-2, y-3}}; + +// Sadly, HP-UX CC can't handle that kind of initialization. + + int xp[4]; + int yp[4]; + + xp[0] = ++x; yp[0] = y - 3; + xp[1] = x; yp[1] = y; + xp[2] = x + width - 2; yp[2] = y; + xp[3] = x + width - 2; yp[3] = y - 3; + + pain.lines(xp, yp, 4, (space) ? LColor::latex : LColor::math); +} +#else void MathSpaceInset::Draw(int x, int y) { @@ -49,7 +77,96 @@ MathSpaceInset::Draw(int x, int y) XDrawLines(fl_display, pm,(space) ? latexGC: mathGC, p, 4, CoordModeOrigin); XFlush(fl_display); } +#endif + +#ifdef USE_PAINTER +void +MathParInset::draw(Painter & pain, int x, int y) +{ + byte cx, cxp = 0; + int xp = 0, ls; + int asc = df_asc, des = 0; + bool limits = false; + + xo = x; yo = y; + if (!array || array->empty()) { + if (array) { + MathedXIter data(this); + data.GetPos(x, y); + } + pain.rectangle(x, y - df_asc, df_width, df_asc, LColor::mathline); + return; + } + MathedXIter data(this); + data.GoBegin(); + while (data.OK()) { + data.GetPos(x, y); + cx = data.GetChar(); + if (cx >= ' ') { + byte * s = data.GetString(ls); + drawStr(pain, data.FCode(), size, x, y, s, ls); + mathed_char_height(LM_TC_CONST, size, 'y', asc, des); + limits = false; + } else { + if (cx == 0) break; + if (MathIsInset(cx)) { + int yy = y; + MathedInset * p = data.GetInset(); + if (cx == LM_TC_UP) { + if (limits) { + x -= (xp>p->Width()) ? p->Width()+(xp-p->Width())/2: xp; + yy -= (asc + p->Descent()+4); + } else + yy -= (p->Descent()>asc) ? p->Descent()+4: asc; + } else + if (cx == LM_TC_DOWN) { + if (limits) { + x -= (xp>p->Width()) ? p->Width()+(xp-p->Width())/2: xp; + yy += des + p->Ascent() + 2; + } else + yy += des + p->Ascent()/2; + } else { + asc = p->Ascent(); + des = p->Descent(); + } + p->draw(pain, x, yy); + if (cx!= LM_TC_UP && cx!= LM_TC_DOWN) { + limits = p->GetLimits(); + if (limits) xp = p->Width(); + } + data.Next(); + } else + if (cx == LM_TC_TAB) { + if ((cxp == cx || cxp == LM_TC_CR || data.IsFirst())) { // && objtype == L + pain.rectangle(x, y - df_asc, df_width, df_asc, + LColor::mathline); + } + data.Next(); + limits = false; + } else + if (cx == LM_TC_CR) { + if (cxp == LM_TC_TAB || cxp == LM_TC_CR || data.IsFirst()) { // && objtype == LM_OT_MATRIX) { + pain.rectangle(x, y - df_asc, df_width, df_asc, + LColor::mathline); + } + data.Next(); + limits = false; + } + else { + lyxerr << "GMathed Error: Unrecognized code[" << cx + << "]" << endl; + break; + } + } + cxp = cx; + } + if (cxp == LM_TC_TAB || cxp == LM_TC_CR) { // && objtype == LM_OT_MATRIX) { + data.GetPos(x, y); + pain.rectangle(x, y - df_asc, df_width, df_asc, LColor::mathline); + } +} +#else void MathParInset::Draw(int x, int y) { @@ -139,6 +256,7 @@ MathParInset::Draw(int x, int y) XFlush(fl_display); } } +#endif void @@ -248,19 +366,41 @@ MathParInset::Metrics() } +#ifdef USE_PAINTER +void +MathSqrtInset::draw(Painter & pain, int x, int y) +{ + MathParInset::draw(pain, x + hmax + 2, y); + int h = ascent; + int d = descent; + int h2 = Height() / 2; + int w2 = (Height() > 4 * hmax) ? hmax : hmax / 2; + int xp[4], yp[4]; + xp[0] = x + hmax + wbody; yp[0] = y - h; + xp[1] = x + hmax; yp[1] = y - h; + xp[2] = x + w2; yp[2] = y + d; + xp[3] = x; yp[3] = y + d - h2; + pain.lines(xp, yp, 4, LColor::mathline); +} +#else void MathSqrtInset::Draw(int x, int y) { MathParInset::Draw(x+hmax+2, y); - int h= ascent, d= descent, h2= Height()/2, w2 = (Height()>4*hmax)?hmax:hmax/2; + int h = ascent; + int d = descent; + int h2 = Height() / 2; + int w2 = (Height() > 4 * hmax) ? hmax : hmax / 2; XPoint p[4]; - p[0].x = x + hmax + wbody, p[0].y = y-h; - p[1].x = x+hmax, p[1].y = y-h; - p[2].x = x+w2, p[2].y = y+d; - p[3].x = x, p[3].y = y+d-h2; + p[0].x = x + hmax + wbody; p[0].y = y - h; + p[1].x = x + hmax; p[1].y = y - h; + p[2].x = x + w2; p[2].y = y + d; + p[3].x = x; p[3].y = y + d - h2; XDrawLines(fl_display, pm, mathLineGC, p, 4, CoordModeOrigin); XFlush(fl_display); } +#endif + void MathSqrtInset::Metrics() @@ -270,11 +410,29 @@ MathSqrtInset::Metrics() descent += 2; int a, b; hmax = mathed_char_height(LM_TC_VAR, size, 'I', a, b); - if (hmax<10) hmax = 10; + if (hmax < 10) hmax = 10; wbody = width + 4; width += hmax + 4; } + +#ifdef USE_PAINTER +void +MathFracInset::draw(Painter & pain, int x, int y) +{ + short idxp = idx; + short sizex = size; + + idx = 0; + if (size == LM_ST_DISPLAY) ++size; + MathParInset::draw(pain, x + (width - w0) / 2, y - des0); + den->draw(pain, x + (width - w1) / 2, y + den->Ascent() + 2 - dh); + size = sizex; + if (objtype == LM_OT_FRAC) + pain.line(x + 2, y - dh, x + width - 4, y - dh, LColor::mathline); + idx = idxp; +} +#else void MathFracInset::Draw(int x, int y) { @@ -283,14 +441,17 @@ MathFracInset::Draw(int x, int y) idx = 0; if (size == LM_ST_DISPLAY) ++size; - MathParInset::Draw(x+(width-w0)/2, y - des0); - den->Draw(x+(width-w1)/2, y + den->Ascent() + 2 - dh); + MathParInset::Draw(x + (width - w0) / 2, y - des0); + den->Draw(x + (width - w1) / 2, y + den->Ascent() + 2 - dh); size = sizex; if (objtype == LM_OT_FRAC) - XDrawLine(fl_display, pm, mathLineGC, x+2, y-dh, x+width-4, y - dh); + XDrawLine(fl_display, pm, mathLineGC, + x + 2, y - dh, x + width - 4, y - dh); XFlush(fl_display); idx = idxp; } +#endif + void MathFracInset::Metrics() @@ -317,6 +478,33 @@ MathFracInset::Metrics() } +#ifdef USE_PAINTER +void +MathBigopInset::draw(Painter & pain, int x, int y) +{ + int ls; + char c; + char const *s; + short t; + + if (sym < 256 || sym == LM_oint) { + ls = 1; + c = (sym == LM_oint) ? LM_int : sym; + s = &c; + t = LM_TC_BSYM; + } else { + s = name; + ls = strlen(name); + t = LM_TC_TEXTRM; + } + if (sym == LM_oint) { + pain.arc(x, y - 5 * width / 4, width, width, 0, 360*64, + LColor::mathline); + ++x; + } + pain.text(x, y, s, ls, mathed_get_font(t, size)); +} +#else void MathBigopInset::Draw(int x, int y) { @@ -344,7 +532,37 @@ MathBigopInset::Draw(int x, int y) XDrawString(fl_display, pm, mathGC, x, y, s, ls); XFlush(fl_display); } +#endif + +#ifdef USE_PAINTER +void +MathBigopInset::Metrics() +{ + int ls; + char c; + char const *s; + short t; + + if (sym < 256 || sym == LM_oint) { + ls = 1; + c = (sym == LM_oint) ? LM_int: sym; + s = &c; + t = LM_TC_BSYM; + } else { + s = name; + ls = strlen(name); + t = LM_TC_TEXTRM; + } + mathed_string_height(t, size, + reinterpret_cast(s), + ls, ascent, descent); + width = mathed_string_width(t, size, + reinterpret_cast(s), + ls); + if (sym == LM_oint) width += 2; +} +#else void MathBigopInset::Metrics() { @@ -368,4 +586,5 @@ MathBigopInset::Metrics() width = mathed_string_width(t, size, reinterpret_cast(s), ls); if (sym == LM_oint) width += 2; } +#endif diff --git a/src/mathed/math_inset.C b/src/mathed/math_inset.C index ea81e507bd..da543e7a25 100644 --- a/src/mathed/math_inset.C +++ b/src/mathed/math_inset.C @@ -416,10 +416,17 @@ void MathMatrixInset::SetData(LyxArrayBase * a) } +#ifdef USE_PAINTER +void MathMatrixInset::draw(Painter & pain, int x, int baseline) +{ + MathParInset::draw(pain, x, baseline); +} +#else void MathMatrixInset::Draw(int x, int baseline) { MathParInset::Draw(x, baseline); -} +} +#endif void MathMatrixInset::Metrics() diff --git a/src/mathed/math_inset.h b/src/mathed/math_inset.h index 536e83458d..c128fca9cb 100644 --- a/src/mathed/math_inset.h +++ b/src/mathed/math_inset.h @@ -43,8 +43,13 @@ public: ~MathFuncInset(); /// MathedInset * Clone(); +#ifdef USE_PAINTER + /// + void draw(Painter &, int, int); +#else /// void Draw(int, int); +#endif /// void Write(ostream &); /// @@ -74,8 +79,13 @@ public: ~MathAccentInset(); /// MathedInset * Clone(); +#ifdef USE_PAINTER + /// + void draw(Painter &, int, int); +#else /// void Draw(int, int); +#endif /// void Write(ostream &); /// @@ -106,8 +116,13 @@ public: MathDotsInset(char const *, int, short st = LM_ST_TEXT); /// MathedInset * Clone(); +#ifdef USE_PAINTER + /// + void draw(Painter &, int, int); +#else /// void Draw(int, int); +#endif /// void Write(ostream &); /// @@ -127,8 +142,13 @@ public: MathSpaceInset(int sp, short ot = LM_OT_SPACE, short st = LM_ST_TEXT); /// MathedInset * Clone(); +#ifdef USE_PAINTER + /// + void draw(Painter &, int, int); +#else /// void Draw(int, int); +#endif /// void Write(ostream &); /// @@ -152,8 +172,13 @@ public: MathBigopInset(char const *, int, short st = LM_ST_TEXT); /// MathedInset * Clone(); +#ifdef USE_PAINTER + /// + void draw(Painter &, int, int); +#else /// void Draw(int, int); +#endif /// void Write(ostream &); /// @@ -181,8 +206,12 @@ public: MathSqrtInset(short st = LM_ST_TEXT); /// MathedInset * Clone(); +#ifdef USE_PAINTER + void draw(Painter &, int x, int baseline); +#else /// void Draw(int x, int baseline); +#endif /// void Write(ostream &); /// @@ -206,8 +235,13 @@ public: ~MathFracInset(); /// MathedInset * Clone(); +#ifdef USE_PAINTER + /// + void draw(Painter &, int x, int baseline); +#else /// void Draw(int x, int baseline); +#endif /// void Write(ostream &); /// @@ -254,8 +288,13 @@ public: MathDelimInset(int, int, short st = LM_ST_TEXT); /// MathedInset * Clone(); +#ifdef USE_PAINTER + /// + void draw(Painter &, int, int); +#else /// void Draw(int, int); +#endif /// void Write(ostream &); /// @@ -277,8 +316,13 @@ public: MathDecorationInset(int, short st = LM_ST_TEXT); /// MathedInset * Clone(); +#ifdef USE_PAINTER + /// + void draw(Painter &, int, int); +#else /// void Draw(int, int); +#endif /// void Write(ostream &); /// diff --git a/src/mathed/math_macro.C b/src/mathed/math_macro.C index c4d8bfddac..708c422b75 100644 --- a/src/mathed/math_macro.C +++ b/src/mathed/math_macro.C @@ -119,6 +119,19 @@ void MathMacro::Metrics() } +#ifdef USE_PAINTER +void MathMacro::draw(Painter & pain, int x, int y) +{ + xo = x; yo = y; + Metrics(); + tmplate->update(this); + tmplate->SetStyle(size); + mathGC = latexGC; + tmplate->draw(pain, x, y); + for (int i = 0; i < nargs; ++i) + tmplate->GetMacroXY(i, args[i].x, args[i].y); +} +#else void MathMacro::Draw(int x, int y) { xo = x; yo = y; @@ -130,6 +143,7 @@ void MathMacro::Draw(int x, int y) for (int i = 0; i < nargs; ++i) tmplate->GetMacroXY(i, args[i].x, args[i].y); } +#endif int MathMacro::GetColumns() @@ -222,6 +236,18 @@ MathMacroArgument::MathMacroArgument(int n) } +#ifdef USE_PAINTER +void MathMacroArgument::draw(Painter & pain, int x, int baseline) +{ + if (expnd_mode) { + MathParInset::draw(pain, x, baseline); + } else { + unsigned char s[3]; + sprintf(reinterpret_cast(s), "#%d", number); + drawStr(pain, LM_TC_TEX, size, x, baseline, &s[0], 2); + } +} +#else void MathMacroArgument::Draw(int x, int baseline) { if (expnd_mode) { @@ -232,6 +258,7 @@ void MathMacroArgument::Draw(int x, int baseline) drawStr(LM_TC_TEX, size, x, baseline, &s[0], 2); } } +#endif void MathMacroArgument::Metrics() @@ -310,6 +337,30 @@ void MathMacroTemplate::setEditMode(bool ed) } +#ifdef USE_PAINTER +void MathMacroTemplate::draw(Painter & pain, int x, int y) +{ + int x2, y2; + bool expnd = (nargs > 0) ? args[0].getExpand(): false; + if (flags & MMF_Edit) { + for (int i = 0; i < nargs; ++i) { + args[i].setExpand(false); + } + x2 = x; y2 = y; + } else { + for (int i = 0; i < nargs; ++i) { + args[i].setExpand(true); + } + x2 = xo; y2 = yo; + } + MathParInset::draw(pain, x, y); + xo = x2; yo = y2; + + for (int i = 0; i < nargs; ++i) { + args[i].setExpand(expnd); + } +} +#else void MathMacroTemplate::Draw(int x, int y) { int x2, y2; @@ -332,6 +383,7 @@ void MathMacroTemplate::Draw(int x, int y) args[i].setExpand(expnd); } } +#endif void MathMacroTemplate::Metrics() diff --git a/src/mathed/math_macro.h b/src/mathed/math_macro.h index f25ffb2029..abf40f2eb4 100644 --- a/src/mathed/math_macro.h +++ b/src/mathed/math_macro.h @@ -42,8 +42,13 @@ class MathMacro : public MathParInset MathMacro(MathMacro *); /// ~MathMacro(); +#ifdef USE_PAINTER + /// + void draw(Painter &, int, int); +#else /// void Draw(int, int); +#endif /// void Metrics(); /// @@ -115,8 +120,13 @@ class MathMacroArgument: public MathParInset MathedInset * Clone() { return this; } /// void Metrics(); +#ifdef USE_PAINTER + /// + void draw(Painter &, int x, int baseline); +#else /// void Draw(int x, int baseline); +#endif /// void Write(ostream &); /// @@ -144,8 +154,13 @@ class MathMacroTemplate: public MathParInset MathMacroTemplate(char const *, int na = 0, int f = 0); /// ~MathMacroTemplate(); +#ifdef USE_PAINTER + /// + void draw(Painter &, int, int); +#else /// void Draw(int, int); +#endif /// void Metrics(); /// diff --git a/src/mathed/math_root.C b/src/mathed/math_root.C index 791f7cd74c..bce021dafc 100644 --- a/src/mathed/math_root.C +++ b/src/mathed/math_root.C @@ -109,6 +109,17 @@ void MathRootInset::Metrics() } +#ifdef USE_PAINTER +void MathRootInset::draw(Painter & pain, int x, int y) +{ + int idxp = idx; + + idx = 1; + uroot->draw(pain, x, y - dh); + MathSqrtInset::draw(pain, x + wroot, y); + idx = idxp; +} +#else void MathRootInset::Draw(int x, int y) { int idxp = idx; @@ -119,6 +130,7 @@ void MathRootInset::Draw(int x, int y) XFlush(fl_display); idx = idxp; } +#endif void MathRootInset::SetStyle(short st) diff --git a/src/mathed/math_root.h b/src/mathed/math_root.h index b9e5569a53..41a00ecb3a 100644 --- a/src/mathed/math_root.h +++ b/src/mathed/math_root.h @@ -36,8 +36,13 @@ class MathRootInset: public MathSqrtInset { ~MathRootInset(); /// MathedInset * Clone(); +#ifdef USE_PAINTER + /// + void draw(Painter &, int x, int baseline); +#else /// void Draw(int x, int baseline); +#endif /// void Write(ostream &); /// diff --git a/src/minibuffer.C b/src/minibuffer.C index 5b0126d22c..1ddc787088 100644 --- a/src/minibuffer.C +++ b/src/minibuffer.C @@ -46,8 +46,12 @@ void MiniBuffer::ExecutingCB(FL_OBJECT * ob, long) { MiniBuffer * obj = static_cast(ob->u_vdata); lyxerr.debug() << "Getting ready to execute: " << obj->cur_cmd << endl; +#ifdef NEW_WA + obj->owner->view()->focus(true); +#else fl_set_focus_object(obj->owner->getForm(), obj->owner->view()->getWorkArea()); +#endif if (obj->cur_cmd.empty()) { obj->Init(); return ; @@ -100,8 +104,12 @@ int MiniBuffer::peek_event(FL_OBJECT * ob, int event, FL_Coord, FL_Coord, case 27: case XK_Escape: // Abort +#ifdef NEW_WA + mini->owner->view()->focus(true); +#else fl_set_focus_object(mini->owner->getForm(), mini->owner->view()->getWorkArea()); +#endif mini->Init(); return 1; case 13: diff --git a/src/paragraph.C b/src/paragraph.C index 1bd9a76d95..0d65e12ee8 100644 --- a/src/paragraph.C +++ b/src/paragraph.C @@ -43,7 +43,11 @@ extern LyXRC * lyxrc; // ale970405 +#ifdef USE_PAINTER +extern string bibitemWidthest(Painter &); +#else extern string bibitemWidthest(); +#endif // this is a minibuffer static char minibuffer_char; @@ -344,10 +348,17 @@ void LyXParagraph::validate(LaTeXFeatures & features) const << endl; } switch ((*cit).font.color()) { +#ifdef USE_PAINTER + case LColor::none: + case LColor::inherit: + case LColor::ignore: + break; +#else case LyXFont::NONE: case LyXFont::INHERIT_COLOR: case LyXFont::IGNORE_COLOR: break; +#endif default: features.color = true; lyxerr[Debug::LATEX] << "Color enabled. Font: " @@ -3403,7 +3414,12 @@ LyXParagraph * LyXParagraph::TeXEnvironment(string & file, TexRow & texrow, } else if (style.labeltype == LABEL_BIBLIO) { // ale970405 file += "\\begin{" + style.latexname() + "}{" +#ifdef USE_PAINTER + + bibitemWidthest(current_view->painter()) + + "}\n"; +#else + bibitemWidthest() + "}\n"; +#endif } else if (style.latextype == LATEX_ITEM_ENVIRONMENT) { #ifdef FANCY_FOOTNOTE_CODE if (foot_count < 0) { diff --git a/src/screen.C b/src/screen.C index 97ceae396c..ded4be2502 100644 --- a/src/screen.C +++ b/src/screen.C @@ -18,18 +18,42 @@ #include "lyxdraw.h" #include "lyxtext.h" #include "lyxrow.h" +#include "BufferView.h" +#include "Painter.h" extern int mono_video; extern int fast_selection; +#ifdef USE_PAINTER +static +GC createGC() +{ + XGCValues val; + val.foreground = BlackPixel(fl_display, + DefaultScreen(fl_display)); + + val.function=GXcopy; + val.graphics_exposures = false; + val.line_style = LineSolid; + val.line_width = 0; + return XCreateGC(fl_display, RootWindow(fl_display, 0), + GCForeground | GCFunction | GCGraphicsExposures + | GCLineWidth | GCLineStyle , &val); +} +#endif + + // Constructor -LyXScreen::LyXScreen(Window window, +LyXScreen::LyXScreen(BufferView * o, Window window, +#ifdef NEW_WA + Pixmap p, +#endif Dimension width, Dimension height, Dimension offset_x, Dimension offset_y, LyXText *text_ptr) - : text(text_ptr), _window(window), + : owner(o), text(text_ptr), _window(window), _width(width), _height(height), _offset_x(offset_x), _offset_y(offset_y) { @@ -40,22 +64,33 @@ LyXScreen::LyXScreen(Window window, screen_refresh_y = -1; /* create the foreground pixmap */ +#ifdef NEW_WA + foreground = p; +#else foreground = XCreatePixmap (fl_display, fl_root, _width, _height, fl_get_visual_depth()); +#endif cursor_pixmap = 0; cursor_pixmap_x = 0; cursor_pixmap_y = 0; cursor_pixmap_w = 0; cursor_pixmap_h = 0; + +#ifdef USE_PAINTER + // We need this GC + gc_copy = createGC(); +#endif } // Destructor LyXScreen::~LyXScreen() { +#ifndef NEW_WA XFreePixmap(fl_display, foreground); +#endif } @@ -71,6 +106,18 @@ void LyXScreen::Redraw() } +#ifdef USE_PAINTER +void LyXScreen::expose(int x, int y, int exp_width, int exp_height) +{ + XCopyArea(fl_display, + foreground, + _window, + gc_copy, + x, y, + exp_width, exp_height, + x+_offset_x, y+_offset_y); +} +#else void LyXScreen::expose(int x, int y, int exp_width, int exp_height) { XCopyArea(fl_display, @@ -81,8 +128,36 @@ void LyXScreen::expose(int x, int y, int exp_width, int exp_height) exp_width, exp_height, x+_offset_x, y+_offset_y); } +#endif +#ifdef USE_PAINTER +void LyXScreen::DrawFromTo(int y1, int y2) +{ + long y_text = first + y1; + + /* get the first needed row */ + Row * row = text->GetRowNearY(y_text); + /* y_text is now the real beginning of the row */ + + long y = y_text - first; + /* y1 is now the real beginning of row on the screen */ + + while (row != 0 && y < y2) { + + text->GetVisibleRow(y, row, y + first); + y += row->height; + row = row -> next; + + } + + /* maybe we have to clear the screen at the bottom */ + if (y < y2) { + owner->painter().fillRectangle(0, y, _width, y2 - y, + LColor::bottomarea); + } +} +#else void LyXScreen::DrawFromTo(int y1, int y2) { long y_text = first + y1; @@ -111,6 +186,7 @@ void LyXScreen::DrawFromTo(int y1, int y2) y2 - y); } } +#endif void LyXScreen::DrawOneRow(Row * row, long & y_text) @@ -119,7 +195,11 @@ void LyXScreen::DrawOneRow(Row * row, long & y_text) if (y + row->height > 0 && y - row->height <= _height) { /* ok there is something visible */ +#ifdef USE_PAINTER + text->GetVisibleRow(y, row, y + first); +#else text->GetVisibleRow(*this, y, row, y + first); +#endif } y_text+= row->height; } @@ -127,6 +207,49 @@ void LyXScreen::DrawOneRow(Row * row, long & y_text) /* draws the screen, starting with textposition y. uses as much already * printed pixels as possible */ +#ifdef USE_PAINTER +void LyXScreen::Draw(long y) +{ + if (cursor_visible) HideCursor(); + + if (y < 0) y = 0; + long old_first = first; + first = y; + + /* is any optimiziation possible? */ + if ((y - old_first) < _height + && (old_first - y) < _height) { + if (first < old_first) { + DrawFromTo(0, old_first - first); + XCopyArea (fl_display, + _window, + _window, + gc_copy, + _offset_x, _offset_y, + _width , _height - old_first + first, + _offset_x, _offset_y + old_first - first); + // expose the area drawn + expose(0, 0, _width, old_first - first); + } else { + DrawFromTo(_height + old_first - first, _height); + XCopyArea (fl_display, + _window, + _window, + gc_copy, + _offset_x, _offset_y + first - old_first, + _width , _height + old_first - first, + _offset_x, _offset_y); + // expose the area drawn + expose(0, _height + old_first - first, + _width, first - old_first); + } + } else { + /* make a dumb new-draw */ + DrawFromTo(0, _height); + expose(0, 0, _width, _height); + } +} +#else void LyXScreen::Draw(long y) { if (cursor_visible) HideCursor(); @@ -168,6 +291,7 @@ void LyXScreen::Draw(long y) expose(0, 0, _width, _height); } } +#endif void LyXScreen::ShowCursor() @@ -189,6 +313,7 @@ void LyXScreen::ShowCursor() // Secure against very strange situations if (y2 < y1) y2 = y1; +#ifndef USE_PAINTER if (fast_selection || mono_video) { if (y2 > 0 && y1 < _height) { XDrawLine(fl_display, @@ -200,6 +325,7 @@ void LyXScreen::ShowCursor() cursor_visible = true; } } else { +#endif if (cursor_pixmap){ XFreePixmap(fl_display, cursor_pixmap); cursor_pixmap = 0; @@ -216,6 +342,22 @@ void LyXScreen::ShowCursor() cursor_pixmap_w, cursor_pixmap_h, fl_get_visual_depth()); +#ifdef USE_PAINTER + XCopyArea(fl_display, + _window, + cursor_pixmap, + gc_copy, + _offset_x + cursor_pixmap_x, + _offset_y + cursor_pixmap_y, + cursor_pixmap_w, cursor_pixmap_h, + 0, 0); + XDrawLine(fl_display, + _window, gc_copy, + x + _offset_x, + y1 + _offset_y, + x + _offset_x, + y2 + _offset_y); +#else XCopyArea(fl_display, _window, cursor_pixmap, @@ -225,14 +367,18 @@ void LyXScreen::ShowCursor() cursor_pixmap_w, cursor_pixmap_h, 0, 0); XDrawLine(fl_display, - _window, getGC(gc_copy), + _window, + getGC(gc_copy), x + _offset_x, y1 + _offset_y, x + _offset_x, - y2 + _offset_y); + y2 + _offset_y); +#endif cursor_visible = true; } +#ifndef USE_PAINTER } +#endif } @@ -279,7 +425,8 @@ void LyXScreen::ShowManualCursor(long x, long y, int asc, int desc) y2 = y -first + desc; if (y2 > _height) y2 = _height; - + +#ifndef USE_PAINTER if (fast_selection || mono_video) { if (y2 > 0 && y1 < _height) { XDrawLine(fl_display, @@ -290,6 +437,7 @@ void LyXScreen::ShowManualCursor(long x, long y, int asc, int desc) y2+_offset_y); } } else { +#endif if (cursor_pixmap){ XFreePixmap(fl_display, cursor_pixmap); cursor_pixmap = 0; @@ -306,7 +454,23 @@ void LyXScreen::ShowManualCursor(long x, long y, int asc, int desc) cursor_pixmap_w, cursor_pixmap_h, fl_get_visual_depth()); - +#ifdef USE_PAINTER + XCopyArea (fl_display, + _window, + cursor_pixmap, + gc_copy, + _offset_x + cursor_pixmap_x, + _offset_y + cursor_pixmap_y, + cursor_pixmap_w, + cursor_pixmap_h, + 0, 0); + XDrawLine(fl_display, + _window, gc_copy, + x+_offset_x, + y1+_offset_y, + x+_offset_x, + y2+_offset_y); +#else XCopyArea (fl_display, _window, cursor_pixmap, @@ -317,27 +481,43 @@ void LyXScreen::ShowManualCursor(long x, long y, int asc, int desc) cursor_pixmap_h, 0, 0); XDrawLine(fl_display, - _window, getGC(gc_copy), + _window, + getGC(gc_copy), x+_offset_x, y1+_offset_y, x+_offset_x, - y2+_offset_y); + y2+_offset_y); +#endif } cursor_visible = true; +#ifndef USE_PAINTER } +#endif } void LyXScreen::HideCursor() { if (!cursor_visible) return; - + +#ifndef USE_PAINTER if (fast_selection || mono_video) { cursor_visible = false; ShowCursor(); cursor_visible = false; } else { +#endif if (cursor_pixmap){ +#ifdef USE_PAINTER + XCopyArea (fl_display, + cursor_pixmap, + _window, + gc_copy, + 0, 0, + cursor_pixmap_w, cursor_pixmap_h, + cursor_pixmap_x + _offset_x, + cursor_pixmap_y + _offset_y); +#else XCopyArea (fl_display, cursor_pixmap, _window, @@ -346,9 +526,12 @@ void LyXScreen::HideCursor() cursor_pixmap_w, cursor_pixmap_h, cursor_pixmap_x + _offset_x, cursor_pixmap_y + _offset_y); +#endif } cursor_visible = false; +#ifndef USE_PAINTER } +#endif } @@ -364,7 +547,7 @@ void LyXScreen::CursorToggle() /* returns a new top so that the cursor is visible */ long LyXScreen::TopCursorVisible() { - long newtop = first; + long newtop = first; if (text->cursor.y - text->cursor.row->baseline @@ -488,7 +671,7 @@ void LyXScreen::ToggleSelection(bool kill_selection) long top = 0; long bottom = 0; - +#ifndef USE_PAINTER if (fast_selection || mono_video) { /* selection only in one row ?*/ @@ -603,6 +786,7 @@ void LyXScreen::ToggleSelection(bool kill_selection) } } } else { +#endif top = text->sel_start_cursor.y - text->sel_start_cursor.row->baseline; bottom = text->sel_end_cursor.y @@ -623,7 +807,9 @@ void LyXScreen::ToggleSelection(bool kill_selection) text->selection = 0; DrawFromTo(top - first, bottom - first); expose(0, top - first, _width, bottom - first - (top - first)); +#ifndef USE_PAINTER } +#endif } @@ -636,6 +822,7 @@ void LyXScreen::ToggleToggle() && text->toggle_cursor.pos == text->toggle_end_cursor.pos) return; +#ifndef USE_PAINTER if (fast_selection || mono_video) { /* selection only in one row ?*/ @@ -729,6 +916,7 @@ void LyXScreen::ToggleToggle() } } } else { +#endif top = text->toggle_cursor.y - text->toggle_cursor.row->baseline; bottom = text->toggle_end_cursor.y @@ -747,11 +935,13 @@ void LyXScreen::ToggleToggle() DrawFromTo(top - first, bottom - first); expose(0, top - first, _width, bottom - first - (top - first)); +#ifndef USE_PAINTER } +#endif } - +#ifndef USE_PAINTER void LyXScreen::drawTableLine(int baseline, int x, int length, bool on_off) { GC gc; @@ -765,8 +955,10 @@ void LyXScreen::drawTableLine(int baseline, int x, int length, bool on_off) x + length, baseline); } +#endif - + +#ifndef USE_PAINTER void LyXScreen::drawVerticalTableLine(int x, int y1, int y2, bool on_off) { GC gc; @@ -780,8 +972,10 @@ void LyXScreen::drawVerticalTableLine(int x, int y1, int y2, bool on_off) x, y2); } +#endif +#ifndef USE_PAINTER void LyXScreen::drawFrame(int /*ft*/, int x, int y, int w, int h, FL_COLOR /*col*/, int /*b*/) { @@ -836,3 +1030,4 @@ void LyXScreen::drawFrame(int /*ft*/, int x, int y, int w, int h, fl_gc, pr, 4, Convex, CoordModeOrigin); } +#endif diff --git a/src/text.C b/src/text.C index e6c18259c3..6f9d5cb112 100644 --- a/src/text.C +++ b/src/text.C @@ -31,6 +31,7 @@ #include "lyxrc.h" #include "LyXView.h" #include "lyxrow.h" +#include "Painter.h" using std::max; using std::min; @@ -44,7 +45,11 @@ extern BufferView * current_view; extern LyXRC * lyxrc; // ale070405 +#ifdef USE_PAINTER +extern int bibitemMaxWidth(Painter &, LyXFont const &); +#else extern int bibitemMaxWidth(LyXFont const &); +#endif #define FIX_DOUBLE_SPACE 1 @@ -56,6 +61,68 @@ int LyXText::SingleWidth(LyXParagraph * par, } +#ifdef USE_PAINTER +int LyXText::SingleWidth(LyXParagraph * par, + LyXParagraph::size_type pos, char c) const +{ + LyXFont font = GetFont(par, pos); + + // The most common case is handled first (Asger) + if (IsPrintable(c)) { + return font.width(c); + + } else if (IsHfillChar(c)) { + return 3; /* Because of the representation + * as vertical lines */ + } else if (c == LyXParagraph::META_FOOTNOTE || + c == LyXParagraph::META_MARGIN || + c == LyXParagraph::META_FIG || + c == LyXParagraph::META_TAB || + c == LyXParagraph::META_WIDE_FIG || + c == LyXParagraph::META_WIDE_TAB || + c == LyXParagraph::META_ALGORITHM) { + string fs; + switch (c) { + case LyXParagraph::META_MARGIN: + fs = "margin"; + break; + case LyXParagraph::META_FIG: + fs = "fig"; + break; + case LyXParagraph::META_TAB: + fs = "tab"; + break; + case LyXParagraph::META_ALGORITHM: + fs = "alg"; + break; + case LyXParagraph::META_WIDE_FIG: + fs = "wide-fig"; + break; + case LyXParagraph::META_WIDE_TAB: + fs = "wide-tab"; + break; + case LyXParagraph::META_FOOTNOTE: + fs = "foot"; + break; + } + font.decSize(); + font.decSize(); + return font.stringWidth(fs); + } else if (c == LyXParagraph::META_INSET) { + Inset * tmpinset= par->GetInset(pos); + if (tmpinset) + return par->GetInset(pos)->width(owner_->painter(), + font); + else + return 0; + + } else if (IsSeparatorChar(c)) + c = ' '; + else if (IsNewlineChar(c)) + c = 'n'; + return font.width(c); +} +#else int LyXText::SingleWidth(LyXParagraph * par, LyXParagraph::size_type pos, char c) const { @@ -119,6 +186,7 @@ int LyXText::SingleWidth(LyXParagraph * par, c = 'n'; return font.width(c); } +#endif // Returns the paragraph position of the last character in the specified row @@ -292,6 +360,226 @@ void LyXText::ComputeBidiTablesFromTo(Row * row, } +#ifdef USE_PAINTER +void LyXText::draw(Row const * row, + LyXParagraph::size_type & vpos, + int offset, float & x) +{ + Painter & pain = owner_->painter(); + + LyXParagraph::size_type pos = vis2log(vpos); + char c = row->par->GetChar(pos); + + if (IsNewlineChar(c)) { + ++vpos; + // Draw end-of-line marker + LyXFont font = GetFont(row->par, pos); + int wid = font.width('n'); + int asc = font.maxAscent(); + int y = offset + row->baseline; +#ifdef USE_PAINTER + int xp[3], yp[3]; + + if (row->par->getLetterDirection(pos) == LYX_DIR_LEFT_TO_RIGHT) { + xp[0] = int(x + wid * 0.375); + yp[0] = int(y - 0.875 * asc * 0.75); + + xp[1] = int(x); + yp[1] = int(y - 0.500 * asc * 0.75); + + xp[2] = int(x + wid * 0.375); + yp[2] = int(y - 0.125 * asc * 0.75); + + pain.lines(xp, yp, 3, LColor::eolmarker); + + xp[0] = int(x); + yp[0] = int(y - 0.500 * asc * 0.75); + + xp[1] = int(x + wid); + yp[1] = int(y - 0.500 * asc * 0.75); + + xp[2] = int(x + wid); + yp[2] = int(y - asc * 0.75); + + pain.lines(xp, yp, 3, LColor::eolmarker); + } else { + xp[0] = int(x + wid * 0.625); + yp[0] = int(y - 0.875 * asc * 0.75); + + xp[1] = int(x + wid); + yp[1] = int(y - 0.500 * asc * 0.75); + + xp[2] = int(x + wid * 0.625); + yp[2] = int(y - 0.125 * asc * 0.75); + + pain.lines(xp, yp, 3, LColor::eolmarker); + + xp[0] = int(x + wid); + yp[0] = int(y - 0.500 * asc * 0.75); + + xp[1] = int(x); + yp[1] = int(y - 0.500 * asc * 0.75); + + xp[2] = int(x); + yp[2] = int(y - asc * 0.75); + + pain.lines(xp, yp, 3, LColor::eolmarker); + } +#else + XPoint p[3]; + + if (row->par->getLetterDirection(pos) == LYX_DIR_LEFT_TO_RIGHT) { + p[0].x = int(x + wid*0.375); p[0].y = int(y - 0.875*asc*0.75); + p[1].x = int(x); p[1].y = int(y - 0.500*asc*0.75); + p[2].x = int(x + wid*0.375); p[2].y = int(y - 0.125*asc*0.75); + scr.drawLines(::getGC(gc_new_line), p, 3); + + p[0].x = int(x); p[0].y = int(y - 0.500*asc*0.75); + p[1].x = int(x + wid); p[1].y = int(y - 0.500*asc*0.75); + p[2].x = int(x + wid); p[2].y = int(y - asc*0.75); + scr.drawLines(::getGC(gc_new_line), p, 3); + } else { + p[0].x = int(x + wid*0.625); p[0].y = int(y - 0.875*asc*0.75); + p[1].x = int(x + wid); p[1].y = int(y - 0.500*asc*0.75); + p[2].x = int(x + wid*0.625); p[2].y = int(y - 0.125*asc*0.75); + scr.drawLines(::getGC(gc_new_line), p, 3); + + p[0].x = int(x + wid); p[0].y = int(y - 0.500*asc*0.75); + p[1].x = int(x); p[1].y = int(y - 0.500*asc*0.75); + p[2].x = int(x); p[2].y = int(y - asc*0.75); + scr.drawLines(::getGC(gc_new_line), p, 3); + } +#endif + x += wid; + return; + } + + LyXFont font = GetFont(row->par, pos); + LyXFont font2 = font; + + if (c == LyXParagraph::META_FOOTNOTE + || c == LyXParagraph::META_MARGIN + || c == LyXParagraph::META_FIG + || c == LyXParagraph::META_TAB + || c == LyXParagraph::META_WIDE_FIG + || c == LyXParagraph::META_WIDE_TAB + || c == LyXParagraph::META_ALGORITHM) { + string fs; + switch (c) { + case LyXParagraph::META_MARGIN: + fs = "margin"; + // Draw a sign at the left margin! + owner_->painter() + .text((LYX_PAPER_MARGIN - font.width('!'))/2, + offset + row->baseline, "!", 1, font); + break; + case LyXParagraph::META_FIG: + fs = "fig"; + break; + case LyXParagraph::META_TAB: + fs = "tab"; + break; + case LyXParagraph::META_ALGORITHM: + fs = "alg"; + break; + case LyXParagraph::META_WIDE_FIG: + fs = "wide-fig"; + break; + case LyXParagraph::META_WIDE_TAB: + fs = "wide-tab"; + break; + case LyXParagraph::META_FOOTNOTE: + fs = "foot"; + break; + } + font.decSize(); + font.decSize(); + + // calculate the position of the footnotemark + int y = (row->baseline - font2.maxAscent() + + font.maxAscent()); + + font.setColor(LColor::footnote); + + float tmpx = x; + + // draw it and set new x position + + pain.text(int(x), offset + y, fs, font); + x += pain.width(fs, font); + pain.line(int(tmpx), offset + row->baseline, + int(x), offset + row->baseline, + LColor::footnote); + + + ++vpos; + return; + } else if (c == LyXParagraph::META_INSET) { + Inset * tmpinset = row->par->GetInset(pos); + if (tmpinset) + tmpinset->draw(owner_->painter(), font, + offset + row->baseline, x); + ++vpos; + return; + } + + /* usual characters, no insets */ + + // Collect character that we can draw in one command + + // This is dirty, but fast. Notice that it will never be too small. + // For the record, I'll note that Microsoft Word has a limit + // of 768 here. We have none :-) (Asger) + // Ok. I am the first to admit that the use of std::string will be + // a tiny bit slower than using a POD char array. However, I claim + // that this slowdown is so small that it is close to inperceptive. + // So IMHO we should go with the easier and clearer implementation. + // And even if 1024 is a large number here it might overflow, string + // will only overflow if the machine is out of memory... + static string textstring; + textstring = c; + ++vpos; + + LyXParagraph::size_type last = RowLast(row); + + while (vpos <= last && + (pos = vis2log(vpos)) >= 0 + && static_cast(c = row->par->GetChar(pos)) > ' ' + && font2 == GetFont(row->par, pos)) { + textstring += c; + ++vpos; + } + float tmpx = x; + +#if 0 + // If monochrome and LaTeX mode, provide reverse background + if (mono_video && + font.latex() == LyXFont::ON) { + int a = font.maxAscent(); + int d = font.maxDescent(); + scr.fillRectangle(gc_copy, int(tmpx), + offset + row->baseline - a, + font.textWidth(textstring.c_str(), + textstring.length()), a + d); + } +#endif + + // Draw text and set the new x position + pain.text(int(x), offset + row->baseline, textstring, font); + x += pain.width(textstring, font); + + // what about underbars? + if (font.underbar() == LyXFont::ON && font.latex() != LyXFont::ON) { + pain.line(tmpx, offset + row->baseline + 2, + x, offset + row->baseline + 2); + + } + + // If we want ulem.sty support, drawing + // routines should go here. (Asger) + // Why shouldn't LyXFont::drawText handle it internally? +} +#else void LyXText::Draw(Row const * row, LyXParagraph::size_type & vpos, LyXScreen & scr, int offset, float & x) { @@ -375,8 +663,12 @@ void LyXText::Draw(Row const * row, LyXParagraph::size_type & vpos, // calculate the position of the footnotemark int y = (row->baseline - font2.maxAscent() + font.maxAscent()); - - font.setColor(LyXFont::INSET); + +#ifdef USE_PAINTER + font.setColor(LColor::footnote); +#else + font.setColor(LyXFont::RED); +#endif float tmpx = x; @@ -450,6 +742,7 @@ void LyXText::Draw(Row const * row, LyXParagraph::size_type & vpos, // routines should go here. (Asger) // Why shouldn't LyXFont::drawText handle it internally? } +#endif // Returns the left beginning of the text. @@ -655,10 +948,18 @@ int LyXText::LeftMargin(Row const * row) const else if (layout.labeltype == LABEL_BIBLIO) { // ale970405 Right width for bibitems +#ifdef USE_PAINTER + x += bibitemMaxWidth(owner_->painter(), + textclasslist + .TextClass(parameters + ->textclass) + .defaultfont()); +#else x += bibitemMaxWidth(textclasslist .TextClass(parameters ->textclass) .defaultfont()); +#endif } } @@ -1144,10 +1445,11 @@ bool LyXText::HfillExpansion(Row const * row_ptr, } +#ifdef USE_PAINTER void LyXText::SetHeightOfRow(Row * row_ptr) const { /* get the maximum ascent and the maximum descent */ - int asc, maxasc, desc, maxdesc, pos_end, pos, labeladdon; + int asc, desc, pos; float layoutasc = 0; float layoutdesc = 0; float tmptop = 0; @@ -1170,7 +1472,8 @@ void LyXText::SetHeightOfRow(Row * row_ptr) const LyXParagraph * par = row_ptr->par->LastPhysicalPar(); LyXParagraph * firstpar = row_ptr->par->FirstPhysicalPar(); - LyXLayout const & layout = textclasslist.Style(parameters->textclass, firstpar->GetLayout()); + LyXLayout const & layout = textclasslist.Style(parameters->textclass, + firstpar->GetLayout()); LyXFont font = GetFont(par, par->Last()-1); LyXFont::FONT_SIZE size = font.size(); @@ -1179,16 +1482,16 @@ void LyXText::SetHeightOfRow(Row * row_ptr) const LyXFont labelfont = GetFont(par, -2); - maxasc = int(font.maxAscent() * + int maxasc = int(font.maxAscent() * layout.spacing.getValue() * parameters->spacing.getValue()); - maxdesc = int(font.maxDescent() * + int maxdesc = int(font.maxDescent() * layout.spacing.getValue() * parameters->spacing.getValue()); - pos_end = RowLast(row_ptr); + int pos_end = RowLast(row_ptr); - labeladdon = 0; + int labeladdon = 0; // Check if any insets are larger for (pos = row_ptr->pos; pos <= pos_end; ++pos) { @@ -1196,8 +1499,8 @@ void LyXText::SetHeightOfRow(Row * row_ptr) const tmpfont = GetFont(row_ptr->par, pos); tmpinset = row_ptr->par->GetInset(pos); if (tmpinset) { - asc = tmpinset->Ascent(tmpfont); - desc = tmpinset->Descent(tmpfont); + asc = tmpinset->ascent(owner_->painter(), tmpfont); + desc = tmpinset->descent(owner_->painter(), tmpfont); if (asc > maxasc) maxasc = asc; if (desc > maxdesc) @@ -1304,7 +1607,7 @@ void LyXText::SetHeightOfRow(Row * row_ptr) const * or between the items of a itemize or enumerate environment */ if (!firstpar->pagebreak_top) { - LyXParagraph *prev = row_ptr->par->Previous(); + LyXParagraph * prev = row_ptr->par->Previous(); if (prev) prev = row_ptr->par->DepthHook(row_ptr->par->GetDepth()); if (prev && prev->GetLayout() == firstpar->GetLayout() @@ -1371,8 +1674,8 @@ void LyXText::SetHeightOfRow(Row * row_ptr) const /* and now the layout spaces, for example before and after a section, * or between the items of a itemize or enumerate environment */ if (!firstpar->pagebreak_bottom && row_ptr->par->Next()) { - LyXParagraph *nextpar = row_ptr->par->Next(); - LyXParagraph *comparepar = row_ptr->par; + LyXParagraph * nextpar = row_ptr->par->Next(); + LyXParagraph * comparepar = row_ptr->par; float usual = 0; float unusual = 0; @@ -1413,274 +1716,550 @@ void LyXText::SetHeightOfRow(Row * row_ptr) const /* calculate the new height of the text */ height -= row_ptr->height; - row_ptr->height= maxasc+maxdesc+labeladdon; - row_ptr->baseline= maxasc+labeladdon; + row_ptr->height = maxasc + maxdesc + labeladdon; + row_ptr->baseline = maxasc + labeladdon; height += row_ptr->height; } - - -/* Appends the implicit specified paragraph behind the specified row, - * start at the implicit given position */ -void LyXText::AppendParagraph(Row * row) const +#else +void LyXText::SetHeightOfRow(Row * row_ptr) const { - bool not_ready = true; - - // The last character position of a paragraph is an invariant so we can - // safely get it here. (Asger) - int lastposition = row->par->Last(); + /* get the maximum ascent and the maximum descent */ + int asc, maxasc, desc, maxdesc, pos_end, pos, labeladdon; + float layoutasc = 0; + float layoutdesc = 0; + float tmptop = 0; + LyXFont tmpfont; + Inset * tmpinset; - do { - // Get the next breakpoint - int z = NextBreakPoint(row, paperwidth); - - Row * tmprow = row; + /* this must not happen before the currentrow for clear reasons. + so the trick is just to set the current row onto this row */ + long unused_y; + GetRow(row_ptr->par, row_ptr->pos, unused_y); - // Insert the new row - if (z < lastposition) { - ++z; - InsertRow(row, row->par, z); - row = row->next; + /* ok , let us initialize the maxasc and maxdesc value. + * This depends in LaTeX of the font of the last character + * in the paragraph. The hack below is necessary because + * of the possibility of open footnotes */ - row->height = 0; - } else - not_ready = false; - - // Set the dimensions of the row - tmprow->fill = Fill(tmprow, paperwidth); - SetHeightOfRow(tmprow); + /* Correction: only the fontsize count. The other properties + are taken from the layoutfont. Nicer on the screen :) */ + + LyXParagraph * par = row_ptr->par->LastPhysicalPar(); + LyXParagraph * firstpar = row_ptr->par->FirstPhysicalPar(); + + LyXLayout const & layout = textclasslist.Style(parameters->textclass, firstpar->GetLayout()); + + LyXFont font = GetFont(par, par->Last()-1); + LyXFont::FONT_SIZE size = font.size(); + font = GetFont(par, -1); + font.setSize(size); - } while (not_ready); -} + LyXFont labelfont = GetFont(par, -2); + maxasc = int(font.maxAscent() * + layout.spacing.getValue() * + parameters->spacing.getValue()); + maxdesc = int(font.maxDescent() * + layout.spacing.getValue() * + parameters->spacing.getValue()); -void LyXText::BreakAgain(Row * row) const -{ - bool not_ready = true; + pos_end = RowLast(row_ptr); - do { - /* get the next breakpoint */ - LyXParagraph::size_type z = - NextBreakPoint(row, paperwidth); - Row * tmprow = row; - - if (z < row->par->Last() ) { - if (!row->next || (row->next && row->next->par != row->par)) { - // insert a new row - ++z; - InsertRow(row, row->par, z); - row = row->next; - row->height = 0; - } else { - row = row->next; - ++z; - if (row->pos == z) - not_ready = false; // the rest will not change - else { - row->pos = z; - } - } - } else { - /* if there are some rows too much, delete them */ - /* only if you broke the whole paragraph! */ - Row * tmprow2 = row; - while (tmprow2->next && tmprow2->next->par == row->par) { - tmprow2 = tmprow2->next; - } - while (tmprow2 != row) { - tmprow2 = tmprow2->previous; - RemoveRow(tmprow2->next); - } - not_ready = false; - } - - /* set the dimensions of the row */ - tmprow->fill = Fill(tmprow, paperwidth); - SetHeightOfRow(tmprow); - } while (not_ready); -} - + labeladdon = 0; -/* this is just a little changed version of break again */ -void LyXText::BreakAgainOneRow(Row * row) -{ - /* get the next breakpoint */ - LyXParagraph::size_type z = NextBreakPoint(row, paperwidth); - Row * tmprow = row; - - if (z < row->par->Last() ) { - if (!row->next || (row->next && row->next->par != row->par)) { - /* insert a new row */ - ++z; - InsertRow(row, row->par, z); - row = row->next; - row->height = 0; - } - else { - row= row->next; - ++z; - if (row->pos != z) - row->pos = z; - } - } - else { - /* if there are some rows too much, delete them */ - /* only if you broke the whole paragraph! */ - Row * tmprow2 = row; - while (tmprow2->next && tmprow2->next->par == row->par) { - tmprow2 = tmprow2->next; - } - while (tmprow2 != row) { - tmprow2 = tmprow2->previous; - RemoveRow(tmprow2->next); + // Check if any insets are larger + for (pos = row_ptr->pos; pos <= pos_end; ++pos) { + if (row_ptr->par->GetChar(pos) == LyXParagraph::META_INSET) { + tmpfont = GetFont(row_ptr->par, pos); + tmpinset = row_ptr->par->GetInset(pos); + if (tmpinset) { + asc = tmpinset->Ascent(tmpfont); + desc = tmpinset->Descent(tmpfont); + if (asc > maxasc) + maxasc = asc; + if (desc > maxdesc) + maxdesc = desc; + } } } - - /* set the dimensions of the row */ - tmprow->fill = Fill(tmprow, paperwidth); - SetHeightOfRow(tmprow); -} + // Check if any custom fonts are larger (Asger) + // This is not completely correct, but we can live with the small, + // cosmetic error for now. + LyXFont::FONT_SIZE maxsize = row_ptr->par->HighestFontInRange(row_ptr->pos, + pos_end); + if (maxsize > font.size()) { + font.setSize(maxsize); -void LyXText::BreakParagraph(char keep_layout) -{ - LyXLayout const & layout = textclasslist.Style(parameters->textclass, - cursor.par->GetLayout()); - - /* table stuff -- begin */ - if (cursor.par->table) { - // breaking of tables is only allowed at the beginning or the end */ - if (cursor.pos && cursor.pos < cursor.par->size() && - !cursor.par->table->ShouldBeVeryLastCell(NumberOfCell(cursor.par, cursor.pos))) - return; // no breaking of tables allowed + asc = font.maxAscent(); + desc = font.maxDescent(); + if (asc > maxasc) + maxasc = asc; + if (desc > maxdesc) + maxdesc = desc; } - /* table stuff -- end */ - - // this is only allowed, if the current paragraph is not empty or caption - if ((cursor.par->Last() <= 0 && !cursor.par->IsDummy()) - && - layout.labeltype!= LABEL_SENSITIVE) - return; - - SetUndo(Undo::INSERT, - cursor.par->ParFromPos(cursor.pos)->previous, - cursor.par->ParFromPos(cursor.pos)->next); - /* table stuff -- begin */ - if (cursor.par->table) { - int cell = NumberOfCell(cursor.par, cursor.pos); - if (cursor.par->table->ShouldBeVeryLastCell(cell)) - SetCursor(cursor.par, cursor.par->text.size()); + /* table stuff -- begin*/ + if (row_ptr->par->table){ + // stretch the rows a bit + maxasc += 1; + maxdesc += 1; } - /* table stuff -- end */ - - // please break always behind a space - if (cursor.pos < cursor.par->Last() - && cursor.par->IsLineSeparator(cursor.pos)) - cursor.pos++; - - // break the paragraph - if (keep_layout) - keep_layout = 2; - else - keep_layout = layout.isEnvironment(); - cursor.par->BreakParagraph(cursor.pos, keep_layout); + /* table stuff -- end*/ - /* table stuff -- begin */ - if (cursor.par->table){ - // the table should stay with the contents - if (!cursor.pos){ - cursor.par->Next()->table = cursor.par->table; - cursor.par->table = 0; - } - } - /* table stuff -- end */ + // This is nicer with box insets: + ++maxasc; + ++maxdesc; - // well this is the caption hack since one caption is really enough - if (layout.labeltype == LABEL_SENSITIVE){ - if (!cursor.pos) - cursor.par->SetLayout(0); // set to standard-layout - else - cursor.par->Next()->SetLayout(0); // set to standard-layout - } - - /* if the cursor is at the beginning of a row without prior newline, - * move one row up! - * This touches only the screen-update. Otherwise we would may have - * an empty row on the screen */ - if (cursor.pos && !cursor.row->par->IsNewline(cursor.row->pos -1) && - cursor.row->pos == cursor.pos) { - CursorLeft(); - } - - status = LyXText::NEED_MORE_REFRESH; - refresh_row = cursor.row; - refresh_y = cursor.y - cursor.row->baseline; + row_ptr->ascent_of_text = maxasc; - // Do not forget the special right address boxes - if (layout.margintype == MARGIN_RIGHT_ADDRESS_BOX) { - while (refresh_row->previous && - refresh_row->previous->par == refresh_row->par) { - refresh_row = refresh_row->previous; - refresh_y -= refresh_row->height; - } + /* is it a top line? */ + if (row_ptr->pos == 0 + && row_ptr->par == firstpar) { + + /* some parksips VERY EASY IMPLEMENTATION */ + if (parameters->paragraph_separation == BufferParams::PARSEP_SKIP) { + if (layout.isParagraph() + && firstpar->GetDepth() == 0 + && firstpar->Previous()) + maxasc += parameters->getDefSkip().inPixels(); + else if (firstpar->Previous() + && textclasslist.Style(parameters->textclass, + firstpar->Previous()->GetLayout()).isParagraph() + && firstpar->Previous()->GetDepth() == 0) + // is it right to use defskip here too? (AS) + maxasc += parameters->getDefSkip().inPixels(); + } + + /* the paper margins */ + if (!row_ptr->par->previous) + maxasc += LYX_PAPER_MARGIN; + + /* add the vertical spaces, that the user added */ + if (firstpar->added_space_top.kind() != VSpace::NONE) + maxasc += int(firstpar->added_space_top.inPixels()); + + /* do not forget the DTP-lines! + * there height depends on the font of the nearest character */ + if (firstpar->line_top) + maxasc += 2 * GetFont(firstpar, 0).ascent('x'); + + /* and now the pagebreaks */ + if (firstpar->pagebreak_top) + maxasc += 3 * DefaultHeight(); + + /* this is special code for the chapter, since the label of this + * layout is printed in an extra row */ + if (layout.labeltype == LABEL_COUNTER_CHAPTER + && parameters->secnumdepth>= 0) { + labeladdon = int(labelfont.maxDescent() * + layout.spacing.getValue() * + parameters->spacing.getValue()) + + int(labelfont.maxAscent() * + layout.spacing.getValue() * + parameters->spacing.getValue()); + } + + /* special code for the top label */ + if ((layout.labeltype == LABEL_TOP_ENVIRONMENT + || layout.labeltype == LABEL_BIBLIO + || layout.labeltype == LABEL_CENTERED_TOP_ENVIRONMENT) + && row_ptr->par->IsFirstInSequence() + && !row_ptr->par->GetLabestring().empty()) { + labeladdon = int( + (labelfont.maxAscent() * + layout.spacing.getValue() * + parameters->spacing.getValue()) + +(labelfont.maxDescent() * + layout.spacing.getValue() * + parameters->spacing.getValue()) + + layout.topsep * DefaultHeight() + + layout.labelbottomsep * DefaultHeight()); + } + + /* and now the layout spaces, for example before and after a section, + * or between the items of a itemize or enumerate environment */ + + if (!firstpar->pagebreak_top) { + LyXParagraph *prev = row_ptr->par->Previous(); + if (prev) + prev = row_ptr->par->DepthHook(row_ptr->par->GetDepth()); + if (prev && prev->GetLayout() == firstpar->GetLayout() + && prev->GetDepth() == firstpar->GetDepth() + && prev->GetLabelWidthString() == firstpar->GetLabelWidthString()) + { + layoutasc = (layout.itemsep * DefaultHeight()); + } + else if (row_ptr->previous) { + tmptop = layout.topsep; + + if (row_ptr->previous->par->GetDepth() >= row_ptr->par->GetDepth()) + tmptop-= textclasslist.Style(parameters->textclass, row_ptr->previous->par->GetLayout()).bottomsep; + + if (tmptop > 0) + layoutasc = (tmptop * DefaultHeight()); + } + else if (row_ptr->par->line_top){ + tmptop = layout.topsep; + + if (tmptop > 0) + layoutasc = (tmptop * DefaultHeight()); + } + + prev = row_ptr->par->DepthHook(row_ptr->par->GetDepth()-1); + if (prev) { + maxasc += int(textclasslist.Style(parameters->textclass, + prev->GetLayout()).parsep * DefaultHeight()); + } + else { + if (firstpar->Previous() + && firstpar->Previous()->GetDepth() == 0 + && firstpar->Previous()->GetLayout() != firstpar->GetLayout()) { + /* avoid parsep */ + } + else if (firstpar->Previous()){ + maxasc += int(layout.parsep * DefaultHeight()); + } + } + } } - RemoveParagraph(cursor.row); - // set the dimensions of the cursor row - cursor.row->fill = Fill(cursor.row, paperwidth); + /* is it a bottom line? */ + if (row_ptr->par->ParFromPos(RowLast(row_ptr) + 1) == par + && (!row_ptr->next || row_ptr->next->par != row_ptr->par)) { + + /* the paper margins */ + if (!par->next) + maxdesc += LYX_PAPER_MARGIN; + + /* add the vertical spaces, that the user added */ + if (firstpar->added_space_bottom.kind() != VSpace::NONE) + maxdesc += int(firstpar->added_space_bottom.inPixels()); + + /* do not forget the DTP-lines! + * there height depends on the font of the nearest character */ + if (firstpar->line_bottom) + maxdesc += 2 * (GetFont(par, par->Last()-1).ascent('x')); + + /* and now the pagebreaks */ + if (firstpar->pagebreak_bottom) + maxdesc += 3 * DefaultHeight(); + + /* and now the layout spaces, for example before and after a section, + * or between the items of a itemize or enumerate environment */ + if (!firstpar->pagebreak_bottom && row_ptr->par->Next()) { + LyXParagraph *nextpar = row_ptr->par->Next(); + LyXParagraph *comparepar = row_ptr->par; + float usual = 0; + float unusual = 0; + + if (comparepar->GetDepth() > nextpar->GetDepth()) { + usual = (textclasslist.Style(parameters->textclass, comparepar->GetLayout()).bottomsep * DefaultHeight()); + comparepar = comparepar->DepthHook(nextpar->GetDepth()); + if (comparepar->GetLayout()!= nextpar->GetLayout() + || nextpar->GetLabelWidthString() != + comparepar->GetLabelWidthString()) + unusual = (textclasslist.Style(parameters->textclass, comparepar->GetLayout()).bottomsep * DefaultHeight()); + + if (unusual > usual) + layoutdesc = unusual; + else + layoutdesc = usual; + } + else if (comparepar->GetDepth() == nextpar->GetDepth()) { + + if (comparepar->GetLayout()!= nextpar->GetLayout() + || nextpar->GetLabelWidthString() != + comparepar->GetLabelWidthString()) + layoutdesc = int(textclasslist.Style(parameters->textclass, comparepar->GetLayout()).bottomsep * DefaultHeight()); + } + } + } + + /* incalculate the layout spaces */ + maxasc += int(layoutasc * 2 / (2 + firstpar->GetDepth())); + maxdesc += int(layoutdesc * 2 / (2 + firstpar->GetDepth())); - SetHeightOfRow(cursor.row); + /* table stuff -- begin*/ + if (row_ptr->par->table){ + maxasc += row_ptr->par->table-> + AdditionalHeight(NumberOfCell(row_ptr->par, row_ptr->pos)); + } + /* table stuff -- end*/ - while (!cursor.par->Next()->table && cursor.par->Next()->Last() - && cursor.par->Next()->IsNewline(0)) - cursor.par->Next()->Erase(0); + /* calculate the new height of the text */ + height -= row_ptr->height; - InsertParagraph(cursor.par->Next(), cursor.row); - - UpdateCounters(cursor.row->previous); + row_ptr->height= maxasc+maxdesc+labeladdon; + row_ptr->baseline= maxasc+labeladdon; - /* This check is necessary. Otherwise the new empty paragraph will - * be deleted automatically. And it is more friendly for the user! */ - if (cursor.pos) - SetCursor(cursor.par->Next(), 0); - else - SetCursor(cursor.par, 0); + height += row_ptr->height; +} +#endif + + +/* Appends the implicit specified paragraph behind the specified row, + * start at the implicit given position */ +void LyXText::AppendParagraph(Row * row) const +{ + bool not_ready = true; - if (cursor.row->next) - BreakAgain(cursor.row->next); + // The last character position of a paragraph is an invariant so we can + // safely get it here. (Asger) + int lastposition = row->par->Last(); - need_break_row = 0; + do { + // Get the next breakpoint + int z = NextBreakPoint(row, paperwidth); + + Row * tmprow = row; + + // Insert the new row + if (z < lastposition) { + ++z; + InsertRow(row, row->par, z); + row = row->next; + + row->height = 0; + } else + not_ready = false; + + // Set the dimensions of the row + tmprow->fill = Fill(tmprow, paperwidth); + SetHeightOfRow(tmprow); + + } while (not_ready); } -void LyXText::OpenFootnote() +void LyXText::BreakAgain(Row * row) const { - LyXParagraph * endpar,* tmppar; - Row * row; - - LyXParagraph * par = cursor.par->ParFromPos(cursor.pos); - - /* if there is no footnote in this paragraph, just return. */ - if (!par->next - || par->next->footnoteflag != LyXParagraph::CLOSED_FOOTNOTE) - return; - - /* ok, move the cursor right before the footnote */ - - /* just a little faster than using CursorRight() */ - for (cursor.pos = 0; - cursor.par->ParFromPos(cursor.pos) != par; cursor.pos++); - /* now the cursor is at the beginning of the physical par */ - SetCursor(cursor.par, - cursor.pos + cursor.par->ParFromPos(cursor.pos)->text.size()); - - /* the cursor must be exactly before the footnote */ - par = cursor.par->ParFromPos(cursor.pos); - - status = LyXText::NEED_MORE_REFRESH; - refresh_row = cursor.row; - refresh_y = cursor.y - cursor.row->baseline; + bool not_ready = true; + + do { + /* get the next breakpoint */ + LyXParagraph::size_type z = + NextBreakPoint(row, paperwidth); + Row * tmprow = row; + + if (z < row->par->Last() ) { + if (!row->next || (row->next && row->next->par != row->par)) { + // insert a new row + ++z; + InsertRow(row, row->par, z); + row = row->next; + row->height = 0; + } else { + row = row->next; + ++z; + if (row->pos == z) + not_ready = false; // the rest will not change + else { + row->pos = z; + } + } + } else { + /* if there are some rows too much, delete them */ + /* only if you broke the whole paragraph! */ + Row * tmprow2 = row; + while (tmprow2->next && tmprow2->next->par == row->par) { + tmprow2 = tmprow2->next; + } + while (tmprow2 != row) { + tmprow2 = tmprow2->previous; + RemoveRow(tmprow2->next); + } + not_ready = false; + } + + /* set the dimensions of the row */ + tmprow->fill = Fill(tmprow, paperwidth); + SetHeightOfRow(tmprow); + } while (not_ready); +} + + +/* this is just a little changed version of break again */ +void LyXText::BreakAgainOneRow(Row * row) +{ + /* get the next breakpoint */ + LyXParagraph::size_type z = NextBreakPoint(row, paperwidth); + Row * tmprow = row; + + if (z < row->par->Last() ) { + if (!row->next || (row->next && row->next->par != row->par)) { + /* insert a new row */ + ++z; + InsertRow(row, row->par, z); + row = row->next; + row->height = 0; + } + else { + row= row->next; + ++z; + if (row->pos != z) + row->pos = z; + } + } + else { + /* if there are some rows too much, delete them */ + /* only if you broke the whole paragraph! */ + Row * tmprow2 = row; + while (tmprow2->next && tmprow2->next->par == row->par) { + tmprow2 = tmprow2->next; + } + while (tmprow2 != row) { + tmprow2 = tmprow2->previous; + RemoveRow(tmprow2->next); + } + } + + /* set the dimensions of the row */ + tmprow->fill = Fill(tmprow, paperwidth); + SetHeightOfRow(tmprow); +} + + +void LyXText::BreakParagraph(char keep_layout) +{ + LyXLayout const & layout = textclasslist.Style(parameters->textclass, + cursor.par->GetLayout()); + + /* table stuff -- begin */ + if (cursor.par->table) { + // breaking of tables is only allowed at the beginning or the end */ + if (cursor.pos && cursor.pos < cursor.par->size() && + !cursor.par->table->ShouldBeVeryLastCell(NumberOfCell(cursor.par, cursor.pos))) + return; // no breaking of tables allowed + } + /* table stuff -- end */ + + // this is only allowed, if the current paragraph is not empty or caption + if ((cursor.par->Last() <= 0 && !cursor.par->IsDummy()) + && + layout.labeltype!= LABEL_SENSITIVE) + return; + + SetUndo(Undo::INSERT, + cursor.par->ParFromPos(cursor.pos)->previous, + cursor.par->ParFromPos(cursor.pos)->next); + + /* table stuff -- begin */ + if (cursor.par->table) { + int cell = NumberOfCell(cursor.par, cursor.pos); + if (cursor.par->table->ShouldBeVeryLastCell(cell)) + SetCursor(cursor.par, cursor.par->text.size()); + } + /* table stuff -- end */ + + // please break always behind a space + if (cursor.pos < cursor.par->Last() + && cursor.par->IsLineSeparator(cursor.pos)) + cursor.pos++; + + // break the paragraph + if (keep_layout) + keep_layout = 2; + else + keep_layout = layout.isEnvironment(); + cursor.par->BreakParagraph(cursor.pos, keep_layout); + + /* table stuff -- begin */ + if (cursor.par->table){ + // the table should stay with the contents + if (!cursor.pos){ + cursor.par->Next()->table = cursor.par->table; + cursor.par->table = 0; + } + } + /* table stuff -- end */ + + // well this is the caption hack since one caption is really enough + if (layout.labeltype == LABEL_SENSITIVE){ + if (!cursor.pos) + cursor.par->SetLayout(0); // set to standard-layout + else + cursor.par->Next()->SetLayout(0); // set to standard-layout + } + + /* if the cursor is at the beginning of a row without prior newline, + * move one row up! + * This touches only the screen-update. Otherwise we would may have + * an empty row on the screen */ + if (cursor.pos && !cursor.row->par->IsNewline(cursor.row->pos -1) && + cursor.row->pos == cursor.pos) { + CursorLeft(); + } + + status = LyXText::NEED_MORE_REFRESH; + refresh_row = cursor.row; + refresh_y = cursor.y - cursor.row->baseline; + + // Do not forget the special right address boxes + if (layout.margintype == MARGIN_RIGHT_ADDRESS_BOX) { + while (refresh_row->previous && + refresh_row->previous->par == refresh_row->par) { + refresh_row = refresh_row->previous; + refresh_y -= refresh_row->height; + } + } + RemoveParagraph(cursor.row); + + // set the dimensions of the cursor row + cursor.row->fill = Fill(cursor.row, paperwidth); + + SetHeightOfRow(cursor.row); + + while (!cursor.par->Next()->table && cursor.par->Next()->Last() + && cursor.par->Next()->IsNewline(0)) + cursor.par->Next()->Erase(0); + + InsertParagraph(cursor.par->Next(), cursor.row); + + UpdateCounters(cursor.row->previous); + + /* This check is necessary. Otherwise the new empty paragraph will + * be deleted automatically. And it is more friendly for the user! */ + if (cursor.pos) + SetCursor(cursor.par->Next(), 0); + else + SetCursor(cursor.par, 0); + + if (cursor.row->next) + BreakAgain(cursor.row->next); + + need_break_row = 0; +} + + +void LyXText::OpenFootnote() +{ + LyXParagraph * endpar,* tmppar; + Row * row; + + LyXParagraph * par = cursor.par->ParFromPos(cursor.pos); + + /* if there is no footnote in this paragraph, just return. */ + if (!par->next + || par->next->footnoteflag != LyXParagraph::CLOSED_FOOTNOTE) + return; + + /* ok, move the cursor right before the footnote */ + + /* just a little faster than using CursorRight() */ + for (cursor.pos = 0; + cursor.par->ParFromPos(cursor.pos) != par; cursor.pos++); + /* now the cursor is at the beginning of the physical par */ + SetCursor(cursor.par, + cursor.pos + cursor.par->ParFromPos(cursor.pos)->text.size()); + + /* the cursor must be exactly before the footnote */ + par = cursor.par->ParFromPos(cursor.pos); + + status = LyXText::NEED_MORE_REFRESH; + refresh_row = cursor.row; + refresh_y = cursor.y - cursor.row->baseline; tmppar = cursor.par; endpar = cursor.par->Next(); @@ -3101,405 +3680,1092 @@ void LyXText::DeleteLineForward() } -// Change the case of a word at cursor position. The meaning of action -// is: -// 0 change to lowercase -// 1 capitalize word -// 2 change to uppercase -// This function directly manipulates LyXParagraph::text because there -// is no LyXParagraph::SetChar currently. I did what I could to ensure -// that it is correct. I guess part of it should be moved to -// LyXParagraph, but it will have to change for 1.1 anyway. At least -// it does not access outside of the allocated array as the older -// version did. (JMarc) -void LyXText::ChangeWordCase(LyXText::TextCase action) +// Change the case of a word at cursor position. The meaning of action +// is: +// 0 change to lowercase +// 1 capitalize word +// 2 change to uppercase +// This function directly manipulates LyXParagraph::text because there +// is no LyXParagraph::SetChar currently. I did what I could to ensure +// that it is correct. I guess part of it should be moved to +// LyXParagraph, but it will have to change for 1.1 anyway. At least +// it does not access outside of the allocated array as the older +// version did. (JMarc) +void LyXText::ChangeWordCase(LyXText::TextCase action) +{ + LyXParagraph * tmppar = cursor.par->ParFromPos(cursor.pos); + + SetUndo(Undo::FINISH, tmppar->previous, tmppar->next); + + LyXParagraph::size_type tmppos = + cursor.par->PositionInParFromPos(cursor.pos); + while (tmppos < tmppar->size()) { + unsigned char c = tmppar->text[tmppos]; + if (IsKommaChar(c) || IsLineSeparatorChar(c)) + break; + if (c != LyXParagraph::META_INSET) { + switch (action) { + case text_lowercase: + c = tolower(c); + break; + case text_capitalization: + c = toupper(c); + action = text_lowercase; + break; + case text_uppercase: + c = toupper(c); + break; + } + } + + tmppar->text[tmppos] = c; + ++tmppos; + } + CheckParagraph(tmppar, tmppos); + CursorRightOneWord(); +} + + +void LyXText::Delete() +{ + // this is a very easy implementation + + LyXCursor old_cursor = cursor; + int old_cur_par_id = old_cursor.par->id(); + int old_cur_par_prev_id = old_cursor.par->previous ? + old_cursor.par->previous->id() : 0; + + // just move to the right + CursorRightIntern(); + + // This check is not very good... + // The CursorRightIntern calls DeleteEmptyParagrapgMechanism + // and that can very well delete the par or par->previous in + // old_cursor. Will a solution where we compare paragraph id's + //work better? +#if 1 + if ((cursor.par->previous ? cursor.par->previous->id() : 0) + == old_cur_par_prev_id + && cursor.par->id() != old_cur_par_id) + return; // delete-empty-paragraph-mechanism has done it +#else + if (cursor.par->previous == old_cursor.par->previous + && cursor.par != old_cursor.par) + return; // delete-empty-paragraph-mechanism has done it +#endif + // if you had success make a backspace + if (old_cursor.par != cursor.par || old_cursor.pos != cursor.pos) { + LyXCursor tmpcursor = cursor; + cursor = old_cursor; // to make sure undo gets the right cursor position + SetUndo(Undo::DELETE, + cursor.par->ParFromPos(cursor.pos)->previous, + cursor.par->ParFromPos(cursor.pos)->next); + cursor = tmpcursor; + Backspace(); + } +} + + +void LyXText::Backspace() +{ + LyXParagraph * tmppar; + Row * tmprow, * row; + long y; + int tmpheight; + + /* table stuff -- begin */ + if (cursor.par->table) { + BackspaceInTable(); + return; + } + /* table stuff -- end */ + + LyXFont rawtmpfont = current_font; + LyXFont realtmpfont = real_current_font; + + // Get the font that is used to calculate the baselineskip + int const lastpos = cursor.par->Last(); + LyXFont rawparfont = cursor.par->GetFontSettings(lastpos - 1); + + if (cursor.pos == 0) { + // we may paste some paragraphs + + // is it an empty paragraph? + + if ((lastpos == 0 + || (lastpos == 1 && cursor.par->IsSeparator(0))) + && !(cursor.par->Next() + && cursor.par->footnoteflag == + LyXParagraph::NO_FOOTNOTE + && cursor.par->Next()->footnoteflag == + LyXParagraph::OPEN_FOOTNOTE)) { + + if (cursor.par->previous) { + tmppar = cursor.par->previous->FirstPhysicalPar(); + if (cursor.par->GetLayout() == tmppar->GetLayout() + && cursor.par->footnoteflag == tmppar->footnoteflag + && cursor.par->GetAlign() == tmppar->GetAlign()) { + + tmppar->line_bottom = cursor.par->line_bottom; + tmppar->added_space_bottom = cursor.par->added_space_bottom; + tmppar->pagebreak_bottom = cursor.par->pagebreak_bottom; + } + + CursorLeftIntern(); + + // the layout things can change the height of a row ! + tmpheight = cursor.row->height; + SetHeightOfRow(cursor.row); + if (cursor.row->height != tmpheight) { + refresh_y = cursor.y - cursor.row->baseline; + refresh_row = cursor.row; + status = LyXText::NEED_MORE_REFRESH; + } + return; + } + } + if (cursor.par->ParFromPos(cursor.pos)->previous){ + SetUndo(Undo::DELETE, + cursor.par->ParFromPos(cursor.pos)->previous->previous, + cursor.par->ParFromPos(cursor.pos)->next); + } + tmppar = cursor.par; + tmprow = cursor.row; + CursorLeftIntern(); + /* Pasting is not allowed, if the paragraphs have different + layout. I think it is a real bug of all other + word processors to allow it. It confuses the user. + Even so with a footnote paragraph and a non-footnote + paragraph. I will not allow pasting in this case, + because the user would be confused if the footnote behaves + different wether it is open or closed. + + Correction: Pasting is always allowed with standard-layout + */ + if (cursor.par != tmppar + && (cursor.par->GetLayout() == tmppar->GetLayout() + || !tmppar->GetLayout()) + && cursor.par->footnoteflag == tmppar->footnoteflag + /* table stuff -- begin*/ + && !cursor.par->table /* no pasting of tables */ + /* table stuff -- end*/ + && cursor.par->GetAlign() == tmppar->GetAlign()) { + + cursor.par->PasteParagraph(); + + if (!(cursor.pos && + cursor.par->IsSeparator(cursor.pos - 1))) + cursor.par->InsertChar(cursor.pos, ' '); + else + if (cursor.pos) + cursor.pos--; + + status = LyXText::NEED_MORE_REFRESH; + refresh_row = cursor.row; + refresh_y = cursor.y - cursor.row->baseline; + + // remove the lost paragraph + RemoveParagraph(tmprow); + RemoveRow(tmprow); + + AppendParagraph(cursor.row); + UpdateCounters(cursor.row); + + // the row may have changed, block, hfills etc. + SetCursor(cursor.par, cursor.pos); + } + } else { + /* this is the code for a normal backspace, not pasting + * any paragraphs */ + SetUndo(Undo::DELETE, + cursor.par->ParFromPos(cursor.pos)->previous, + cursor.par->ParFromPos(cursor.pos)->next); + CursorLeftIntern(); + + // some insets are undeletable here + if (cursor.par->GetChar(cursor.pos) == LyXParagraph::META_INSET) { + if (!cursor.par->GetInset(cursor.pos)->Deletable()) + return; + // force complete redo when erasing display insets + // this is a cruel mathod but save..... Matthias + if (cursor.par->GetInset(cursor.pos)->display()){ + cursor.par->Erase(cursor.pos); + RedoParagraph(); + return; + } + } + + row = cursor.row; + y = cursor.y - row->baseline; + LyXParagraph::size_type z; + /* remember that a space at the end of a row doesnt count + * when calculating the fill */ + if (cursor.pos < RowLast(row) || + !cursor.par->IsLineSeparator(cursor.pos)) { + row->fill += SingleWidth(cursor.par, cursor.pos); + } + + /* some special code when deleting a newline. This is similar + * to the behavior when pasting paragraphs */ + if (cursor.pos && cursor.par->IsNewline(cursor.pos)) { + cursor.par->Erase(cursor.pos); + // refresh the positions + tmprow = row; + while (tmprow->next && tmprow->next->par == row->par) { + tmprow = tmprow->next; + tmprow->pos--; + } + if (cursor.par->IsLineSeparator(cursor.pos - 1)) + cursor.pos--; + + if (cursor.pos < cursor.par->Last() && !cursor.par->IsSeparator(cursor.pos)) { + cursor.par->InsertChar(cursor.pos, ' '); + // refresh the positions + tmprow = row; + while (tmprow->next && tmprow->next->par == row->par) { + tmprow = tmprow->next; + tmprow->pos++; + } + } + } else { + cursor.par->Erase(cursor.pos); + + // refresh the positions + tmprow = row; + while (tmprow->next && tmprow->next->par == row->par) { + tmprow = tmprow->next; + tmprow->pos--; + } + +#ifndef FIX_DOUBLE_SPACE + // delete superfluous blanks + if (cursor.pos < cursor.par->Last() - 1 && + (cursor.par->IsLineSeparator(cursor.pos))) { + + if (cursor.pos == BeginningOfMainBody(cursor.par) + || !cursor.pos + || cursor.par->IsLineSeparator(cursor.pos - 1)) { + cursor.par->Erase(cursor.pos); + // refresh the positions + tmprow = row; + while (tmprow->next && + tmprow->next->par == row->par) { + tmprow = tmprow->next; + tmprow->pos--; + } + if (cursor.pos) // move one character left + cursor.pos--; + } + } +#endif + + // delete newlines at the beginning of paragraphs + while (cursor.par->Last() && + cursor.par->IsNewline(cursor.pos) && + cursor.pos == BeginningOfMainBody(cursor.par)) { + cursor.par->Erase(cursor.pos); + // refresh the positions + tmprow = row; + while (tmprow->next && + tmprow->next->par == row->par) { + tmprow = tmprow->next; + tmprow->pos--; + } + } + } + + // is there a break one row above + if (row->previous && row->previous->par == row->par) { + z = NextBreakPoint(row->previous, paperwidth); + if ( z >= row->pos) { + row->pos = z + 1; + + tmprow = row->previous; + + // maybe the current row is now empty + if (row->pos >= row->par->Last()) { + // remove it + RemoveRow(row); + need_break_row = 0; + } else { + BreakAgainOneRow(row); + if (row->next && row->next->par == row->par) + need_break_row = row->next; + else + need_break_row = 0; + } + + // set the dimensions of the row above + y -= tmprow->height; + tmprow->fill = Fill(tmprow, paperwidth); + SetHeightOfRow(tmprow); + + refresh_y = y; + refresh_row = tmprow; + status = LyXText::NEED_MORE_REFRESH; + current_font = rawtmpfont; + real_current_font = realtmpfont; + SetCursor(cursor.par, cursor.pos, false); + // check, whether the last character's font has changed. + rawtmpfont = cursor.par->GetFontSettings(cursor.par->Last() - 1); + if (rawparfont != rawtmpfont) + RedoHeightOfParagraph(cursor); + return; + } + } + + // break the cursor row again + z = NextBreakPoint(row, paperwidth); + + if (z != RowLast(row) || + (row->next && row->next->par == row->par && + RowLast(row) == row->par->Last() - 1)){ + + /* it can happen that a paragraph loses one row + * without a real breakup. This is when a word + * is to long to be broken. Well, I don t care this + * hack ;-) */ + if (row->next && row->next->par == row->par && + RowLast(row) == row->par->Last() - 1) + RemoveRow(row->next); + + refresh_y = y; + refresh_row = row; + status = LyXText::NEED_MORE_REFRESH; + + BreakAgainOneRow(row); + current_font = rawtmpfont; + real_current_font = realtmpfont; + SetCursor(cursor.par, cursor.pos, false); + // cursor MUST be in row now + + if (row->next && row->next->par == row->par) + need_break_row = row->next; + else + need_break_row = 0; + } else { + // set the dimensions of the row + row->fill = Fill(row, paperwidth); + int tmpheight = row->height; + SetHeightOfRow(row); + if (tmpheight == row->height) + status = LyXText::NEED_VERY_LITTLE_REFRESH; + else + status = LyXText::NEED_MORE_REFRESH; + refresh_y = y; + refresh_row = row; + current_font = rawtmpfont; + real_current_font = realtmpfont; + SetCursor(cursor.par, cursor.pos, false); + } + } + + // restore the current font + // That is what a user expects! + current_font = rawtmpfont; + real_current_font = realtmpfont; + + // check, wether the last characters font has changed. + rawtmpfont = cursor.par->GetFontSettings(cursor.par->Last() - 1); + if (rawparfont != rawtmpfont) { + RedoHeightOfParagraph(cursor); + } else { + // now the special right address boxes + if (textclasslist.Style(parameters->textclass, + cursor.par->GetLayout()).margintype == MARGIN_RIGHT_ADDRESS_BOX) { + RedoDrawingOfParagraph(cursor); + } + } +} + + +#ifdef USE_PAINTER +void LyXText::GetVisibleRow(int offset, + Row * row_ptr, long y) { - LyXParagraph * tmppar = cursor.par->ParFromPos(cursor.pos); + /* returns a printed row */ + Painter & pain = owner_->painter(); + + LyXDirection direction = row_ptr->par->getParDirection(); + LyXParagraph::size_type vpos, pos, pos_end; + float x, tmpx; + int y_top, y_bottom; + float fill_separator, fill_hfill, fill_label_hfill; + LyXParagraph * par, * firstpar; + LyXFont font; + int maxdesc; + if (row_ptr->height <= 0) { + lyxerr << "LYX_ERROR: row.height: " << row_ptr->height << endl; + return; + } + PrepareToPrint(row_ptr, x, fill_separator, + fill_hfill, fill_label_hfill); - SetUndo(Undo::FINISH, tmppar->previous, tmppar->next); + /* initialize the pixmap */ + + pain.fillRectangle(0, offset, paperwidth, row_ptr->height); + + // check for NOT FAST SELECTION + if (!fast_selection && !mono_video && selection) { + /* selection code */ + if (sel_start_cursor.row == row_ptr && + sel_end_cursor.row == row_ptr) { + if (sel_start_cursor.x < sel_end_cursor.x) + pain.fillRectangle(sel_start_cursor.x, offset, + sel_end_cursor.x, + row_ptr->height, + LColor::selection); + else + pain.fillRectangle(sel_end_cursor.x, offset, + sel_start_cursor.x, + row_ptr->height, + LColor::selection); + } + else if (sel_start_cursor.row == row_ptr) { + if (direction == LYX_DIR_LEFT_TO_RIGHT) + pain.fillRectangle(sel_start_cursor.x, offset, + paperwidth - sel_start_cursor.x, + row_ptr->height, + LColor::selection); + else + pain.fillRectangle(0, offset, + sel_start_cursor.x, + row_ptr->height, + LColor::selection); + } else if (sel_end_cursor.row == row_ptr) { + if (direction == LYX_DIR_LEFT_TO_RIGHT) + pain.fillRectangle(0, offset, + sel_end_cursor.x, + row_ptr->height, + LColor::selection); + else + pain.fillRectangle(sel_end_cursor.x, offset, + paperwidth - sel_end_cursor.x, + row_ptr->height, + LColor::selection); - LyXParagraph::size_type tmppos = - cursor.par->PositionInParFromPos(cursor.pos); - while (tmppos < tmppar->size()) { - unsigned char c = tmppar->text[tmppos]; - if (IsKommaChar(c) || IsLineSeparatorChar(c)) - break; - if (c != LyXParagraph::META_INSET) { - switch (action) { - case text_lowercase: - c = tolower(c); + } else if (y > sel_start_cursor.y && y < sel_end_cursor.y) { + pain.fillRectangle(0, offset, + paperwidth, row_ptr->height, + LColor::selection); + } + } // end of NOT FAST SELECTION code + + if (row_ptr->par->appendix){ + pain.line(1, offset, + 1, offset + row_ptr->height, + LColor::appendixline); + pain.line(paperwidth - 2, offset, + paperwidth - 2, offset + row_ptr->height, + LColor::appendixline); + } + + if (row_ptr->par->pextra_type == LyXParagraph::PEXTRA_MINIPAGE) { + /* draw a marker at the left margin! */ + LyXFont font = GetFont(row_ptr->par, 0); + int asc = font.maxAscent(); + int x = (LYX_PAPER_MARGIN - font.width('|')) / 2; + int y1 = (offset + row_ptr->baseline); + int y2 = (offset + row_ptr->baseline) - asc; + pain.line(x, y1, x, y2, LColor::minipageline); + } + if (row_ptr->par->footnoteflag == LyXParagraph::OPEN_FOOTNOTE) { + LyXFont font(LyXFont::ALL_SANE); + font.setSize(LyXFont::SIZE_FOOTNOTE); + font.setColor(LColor::red); + + int box_x = LYX_PAPER_MARGIN; + box_x += font.textWidth(" wide-tab ", 10); + if (row_ptr->previous && + row_ptr->previous->par->footnoteflag != LyXParagraph::OPEN_FOOTNOTE){ + string fs; + switch (row_ptr->par->footnotekind) { + case LyXParagraph::MARGIN: + fs = " margin"; break; - case text_capitalization: - c = toupper(c); - action = text_lowercase; + case LyXParagraph::FIG: + fs = " fig"; break; - case text_uppercase: - c = toupper(c); + case LyXParagraph::TAB: + fs = " tab"; + break; + case LyXParagraph::WIDE_FIG: + fs = " wide-fig"; + break; + case LyXParagraph::WIDE_TAB: + fs = " wide-tab"; + break; + case LyXParagraph::ALGORITHM: + fs = " alg"; + break; + case LyXParagraph::FOOTNOTE: + fs = " foot"; break; } - } - - tmppar->text[tmppos] = c; - ++tmppos; - } - CheckParagraph(tmppar, tmppos); - CursorRightOneWord(); -} - - -void LyXText::Delete() -{ - // this is a very easy implementation - - LyXCursor old_cursor = cursor; - int old_cur_par_id = old_cursor.par->id(); - int old_cur_par_prev_id = old_cursor.par->previous ? - old_cursor.par->previous->id() : 0; - - // just move to the right - CursorRightIntern(); - // This check is not very good... - // The CursorRightIntern calls DeleteEmptyParagrapgMechanism - // and that can very well delete the par or par->previous in - // old_cursor. Will a solution where we compare paragraph id's - //work better? -#if 1 - if ((cursor.par->previous ? cursor.par->previous->id() : 0) - == old_cur_par_prev_id - && cursor.par->id() != old_cur_par_id) - return; // delete-empty-paragraph-mechanism has done it -#else - if (cursor.par->previous == old_cursor.par->previous - && cursor.par != old_cursor.par) - return; // delete-empty-paragraph-mechanism has done it +#if 0 + // Determine background color. + gc_type back = gc_lighted; + if (mono_video) { + back = gc_clear; + } #endif - // if you had success make a backspace - if (old_cursor.par != cursor.par || old_cursor.pos != cursor.pos) { - LyXCursor tmpcursor = cursor; - cursor = old_cursor; // to make sure undo gets the right cursor position - SetUndo(Undo::DELETE, - cursor.par->ParFromPos(cursor.pos)->previous, - cursor.par->ParFromPos(cursor.pos)->next); - cursor = tmpcursor; - Backspace(); - } -} - + pain.fillRectangle(LYX_PAPER_MARGIN, + offset + 1, + box_x - LYX_PAPER_MARGIN, + int(font.maxAscent() + + font.maxDescent()), + LColor::footnotebg); + + pain.line(LYX_PAPER_MARGIN, offset, + paperwidth - LYX_PAPER_MARGIN, offset, + LColor::footnoteframe); + + pain.text(LYX_PAPER_MARGIN, + offset + int(font.maxAscent()) + 1, + fs, font); + + pain.line(LYX_PAPER_MARGIN, offset, + LYX_PAPER_MARGIN, + offset + int(font.maxAscent() + + font.maxDescent()), + LColor::footnoteframe); + + pain.line(LYX_PAPER_MARGIN, + offset + int(font.maxAscent() + + font.maxDescent()) + 1, + box_x, + offset + int(font.maxAscent() + + font.maxDescent()) + 1, + LColor::footnoteframe); + + } + + /* draw the open floats in a red box */ + pain.line(box_x, offset, + box_x, offset + row_ptr->height, + LColor::footnoteframe); + + pain.line(paperwidth - LYX_PAPER_MARGIN, + offset, + paperwidth - LYX_PAPER_MARGIN, + offset + row_ptr->height, + LColor::footnoteframe); + } else { + if (row_ptr->previous && + row_ptr->previous->par->footnoteflag == LyXParagraph::OPEN_FOOTNOTE) { + LyXFont font(LyXFont::ALL_SANE); + font.setSize(LyXFont::SIZE_FOOTNOTE); -void LyXText::Backspace() -{ - LyXParagraph * tmppar; - Row * tmprow, * row; - long y; - int tmpheight; + int box_x = LYX_PAPER_MARGIN; + box_x += font.textWidth(" wide-tab ", 10); - /* table stuff -- begin */ - if (cursor.par->table) { - BackspaceInTable(); - return; + pain.line(box_x, offset, + paperwidth - LYX_PAPER_MARGIN, + offset, LColor::footnote); + } } - /* table stuff -- end */ - LyXFont rawtmpfont = current_font; - LyXFont realtmpfont = real_current_font; - - // Get the font that is used to calculate the baselineskip - int const lastpos = cursor.par->Last(); - LyXFont rawparfont = cursor.par->GetFontSettings(lastpos - 1); - - if (cursor.pos == 0) { - // we may paste some paragraphs - - // is it an empty paragraph? - - if ((lastpos == 0 - || (lastpos == 1 && cursor.par->IsSeparator(0))) - && !(cursor.par->Next() - && cursor.par->footnoteflag == - LyXParagraph::NO_FOOTNOTE - && cursor.par->Next()->footnoteflag == - LyXParagraph::OPEN_FOOTNOTE)) { - - if (cursor.par->previous) { - tmppar = cursor.par->previous->FirstPhysicalPar(); - if (cursor.par->GetLayout() == tmppar->GetLayout() - && cursor.par->footnoteflag == tmppar->footnoteflag - && cursor.par->GetAlign() == tmppar->GetAlign()) { - - tmppar->line_bottom = cursor.par->line_bottom; - tmppar->added_space_bottom = cursor.par->added_space_bottom; - tmppar->pagebreak_bottom = cursor.par->pagebreak_bottom; - } - - CursorLeftIntern(); - - // the layout things can change the height of a row ! - tmpheight = cursor.row->height; - SetHeightOfRow(cursor.row); - if (cursor.row->height != tmpheight) { - refresh_y = cursor.y - cursor.row->baseline; - refresh_row = cursor.row; - status = LyXText::NEED_MORE_REFRESH; - } - return; - } + LyXLayout const & layout = textclasslist.Style(parameters->textclass, + row_ptr->par->GetLayout()); + firstpar = row_ptr->par->FirstPhysicalPar(); + + y_top = 0; + y_bottom = row_ptr->height; + + /* is it a first row? */ + if (row_ptr->pos == 0 + && row_ptr->par == firstpar) { + + /* start of appendix? */ + if (row_ptr->par->start_of_appendix){ + owner_->painter().line(1, offset, + paperwidth - 2, offset, + LColor::appendixline); } - if (cursor.par->ParFromPos(cursor.pos)->previous){ - SetUndo(Undo::DELETE, - cursor.par->ParFromPos(cursor.pos)->previous->previous, - cursor.par->ParFromPos(cursor.pos)->next); + + /* think about the margins */ + if (!row_ptr->previous) + y_top += LYX_PAPER_MARGIN; + + if (row_ptr->par->pagebreak_top){ /* draw a top pagebreak */ + pain.line(0, offset + y_top + 2 * DefaultHeight(), + paperwidth, offset + y_top + 2 * DefaultHeight(), + LColor::pagebreak, Painter::line_onoffdash); + y_top += 3 * DefaultHeight(); } - tmppar = cursor.par; - tmprow = cursor.row; - CursorLeftIntern(); - /* Pasting is not allowed, if the paragraphs have different - layout. I think it is a real bug of all other - word processors to allow it. It confuses the user. - Even so with a footnote paragraph and a non-footnote - paragraph. I will not allow pasting in this case, - because the user would be confused if the footnote behaves - different wether it is open or closed. - - Correction: Pasting is always allowed with standard-layout - */ - if (cursor.par != tmppar - && (cursor.par->GetLayout() == tmppar->GetLayout() - || !tmppar->GetLayout()) - && cursor.par->footnoteflag == tmppar->footnoteflag - /* table stuff -- begin*/ - && !cursor.par->table /* no pasting of tables */ - /* table stuff -- end*/ - && cursor.par->GetAlign() == tmppar->GetAlign()) { - - cursor.par->PasteParagraph(); - - if (!(cursor.pos && - cursor.par->IsSeparator(cursor.pos - 1))) - cursor.par->InsertChar(cursor.pos, ' '); - else - if (cursor.pos) - cursor.pos--; - - status = LyXText::NEED_MORE_REFRESH; - refresh_row = cursor.row; - refresh_y = cursor.y - cursor.row->baseline; + + if (row_ptr->par->added_space_top.kind() == VSpace::VFILL) { + /* draw a vfill top */ + pain.line(0, offset + 2 + y_top, + LYX_PAPER_MARGIN, offset + 2 + y_top, + LColor::vfillline); - // remove the lost paragraph - RemoveParagraph(tmprow); - RemoveRow(tmprow); + pain.line(0, offset + y_top + 3 * DefaultHeight(), + LYX_PAPER_MARGIN, + offset + y_top + 3 * DefaultHeight(), + LColor::vfillline); - AppendParagraph(cursor.row); - UpdateCounters(cursor.row); + pain.line(LYX_PAPER_MARGIN / 2, offset + 2 + y_top, + LYX_PAPER_MARGIN / 2, + offset + y_top + 3 * DefaultHeight(), + LColor::vfillline); - // the row may have changed, block, hfills etc. - SetCursor(cursor.par, cursor.pos); + y_top += 3 * DefaultHeight(); } - } else { - /* this is the code for a normal backspace, not pasting - * any paragraphs */ - SetUndo(Undo::DELETE, - cursor.par->ParFromPos(cursor.pos)->previous, - cursor.par->ParFromPos(cursor.pos)->next); - CursorLeftIntern(); - // some insets are undeletable here - if (cursor.par->GetChar(cursor.pos) == LyXParagraph::META_INSET) { - if (!cursor.par->GetInset(cursor.pos)->Deletable()) - return; - // force complete redo when erasing display insets - // this is a cruel mathod but save..... Matthias - if (cursor.par->GetInset(cursor.pos)->display()){ - cursor.par->Erase(cursor.pos); - RedoParagraph(); - return; - } - } + /* think about user added space */ + y_top += int(row_ptr->par->added_space_top.inPixels()); - row = cursor.row; - y = cursor.y - row->baseline; - LyXParagraph::size_type z; - /* remember that a space at the end of a row doesnt count - * when calculating the fill */ - if (cursor.pos < RowLast(row) || - !cursor.par->IsLineSeparator(cursor.pos)) { - row->fill += SingleWidth(cursor.par, cursor.pos); + /* think about the parskip */ + /* some parskips VERY EASY IMPLEMENTATION */ + if (parameters->paragraph_separation == BufferParams::PARSEP_SKIP) { + if (layout.latextype == LATEX_PARAGRAPH + && firstpar->GetDepth() == 0 + && firstpar->Previous()) + y_top += parameters->getDefSkip().inPixels(); + else if (firstpar->Previous() + && textclasslist.Style(parameters->textclass, + firstpar->Previous()->GetLayout()).latextype == LATEX_PARAGRAPH + && firstpar->Previous()->GetDepth() == 0) + // is it right to use defskip here, too? (AS) + y_top += parameters->getDefSkip().inPixels(); } - /* some special code when deleting a newline. This is similar - * to the behavior when pasting paragraphs */ - if (cursor.pos && cursor.par->IsNewline(cursor.pos)) { - cursor.par->Erase(cursor.pos); - // refresh the positions - tmprow = row; - while (tmprow->next && tmprow->next->par == row->par) { - tmprow = tmprow->next; - tmprow->pos--; - } - if (cursor.par->IsLineSeparator(cursor.pos - 1)) - cursor.pos--; - - if (cursor.pos < cursor.par->Last() && !cursor.par->IsSeparator(cursor.pos)) { - cursor.par->InsertChar(cursor.pos, ' '); - // refresh the positions - tmprow = row; - while (tmprow->next && tmprow->next->par == row->par) { - tmprow = tmprow->next; - tmprow->pos++; - } - } - } else { - cursor.par->Erase(cursor.pos); - - // refresh the positions - tmprow = row; - while (tmprow->next && tmprow->next->par == row->par) { - tmprow = tmprow->next; - tmprow->pos--; - } + if (row_ptr->par->line_top) { /* draw a top line */ + y_top += GetFont(row_ptr->par, 0).ascent('x'); -#ifndef FIX_DOUBLE_SPACE - // delete superfluous blanks - if (cursor.pos < cursor.par->Last() - 1 && - (cursor.par->IsLineSeparator(cursor.pos))) { + pain.line(0, offset + y_top, + paperwidth, offset + y_top, + LColor::topline, + Painter::line_solid, + Painter::line_thick); + + y_top += GetFont(row_ptr->par, 0).ascent('x'); + } + + /* should we print a label? */ + if (layout.labeltype >= LABEL_STATIC + && (layout.labeltype != LABEL_STATIC + || layout.latextype != LATEX_ENVIRONMENT + || row_ptr->par->IsFirstInSequence())) { + font = GetFont(row_ptr->par, -2); + if (!row_ptr->par->GetLabestring().empty()) { + tmpx = x; + string tmpstring = row_ptr->par->GetLabestring(); - if (cursor.pos == BeginningOfMainBody(cursor.par) - || !cursor.pos - || cursor.par->IsLineSeparator(cursor.pos - 1)) { - cursor.par->Erase(cursor.pos); - // refresh the positions - tmprow = row; - while (tmprow->next && - tmprow->next->par == row->par) { - tmprow = tmprow->next; - tmprow->pos--; + if (layout.labeltype == LABEL_COUNTER_CHAPTER) { + if (parameters->secnumdepth >= 0){ + /* this is special code for the chapter layout. This is printed in + * an extra row and has a pagebreak at the top. */ + maxdesc = int(font.maxDescent() * layout.spacing.getValue() * parameters->spacing.getValue()) + + int(layout.parsep) * DefaultHeight(); + if (direction == LYX_DIR_RIGHT_TO_LEFT) + tmpx = paperwidth - LeftMargin(row_ptr) - + font.stringWidth(tmpstring); + pain.text(int(tmpx), + offset + row_ptr->baseline - row_ptr->ascent_of_text - maxdesc, + tmpstring, font); } - if (cursor.pos) // move one character left - cursor.pos--; + } else { + if (direction == LYX_DIR_LEFT_TO_RIGHT) + tmpx = x - font.stringWidth(layout.labelsep) + - font.stringWidth(tmpstring); + else { + tmpx = paperwidth - LeftMargin(row_ptr) + + font.stringWidth(layout.labelsep); + if (row_ptr->par->footnoteflag == LyXParagraph::OPEN_FOOTNOTE) { + LyXFont font(LyXFont::ALL_SANE); + font.setSize(LyXFont::SIZE_SMALL); + tmpx += font.textWidth("Mwide-figM", 10); + } + } + /* draw it! */ + pain.text(int(tmpx), + offset + row_ptr->baseline, + tmpstring, font); } } -#endif - - // delete newlines at the beginning of paragraphs - while (cursor.par->Last() && - cursor.par->IsNewline(cursor.pos) && - cursor.pos == BeginningOfMainBody(cursor.par)) { - cursor.par->Erase(cursor.pos); - // refresh the positions - tmprow = row; - while (tmprow->next && - tmprow->next->par == row->par) { - tmprow = tmprow->next; - tmprow->pos--; + /* the labels at the top of an environment. More or less for bibliography */ + } else if (layout.labeltype == LABEL_TOP_ENVIRONMENT || + layout.labeltype == LABEL_BIBLIO || + layout.labeltype == LABEL_CENTERED_TOP_ENVIRONMENT) { + if (row_ptr->par->IsFirstInSequence()) { + font = GetFont(row_ptr->par, -2); + if (!row_ptr->par->GetLabestring().empty()) { + string tmpstring = row_ptr->par->GetLabestring(); + + maxdesc = int(font.maxDescent() * layout.spacing.getValue() * parameters->spacing.getValue() + + (layout.labelbottomsep * DefaultHeight())); + + tmpx = x; + if (layout.labeltype == LABEL_CENTERED_TOP_ENVIRONMENT){ + tmpx = ( ((direction == LYX_DIR_LEFT_TO_RIGHT) + ? x : LeftMargin(row_ptr) ) + + paperwidth - RightMargin(row_ptr) ) / 2; + tmpx -= (font.stringWidth(tmpstring)/2); + } else if (direction == LYX_DIR_RIGHT_TO_LEFT) + tmpx = paperwidth - LeftMargin(row_ptr) - + font.stringWidth(tmpstring); + pain.text(int(tmpx), + offset + row_ptr->baseline + - row_ptr->ascent_of_text + - maxdesc, + tmpstring, font); } } } + if (layout.labeltype == LABEL_BIBLIO) { // ale970302 + if (row_ptr->par->bibkey) { + font = GetFont(row_ptr->par, -1); + if (direction == LYX_DIR_LEFT_TO_RIGHT) + tmpx = x - font.stringWidth(layout.labelsep) + - row_ptr->par->bibkey->width(owner_->painter(), font); + else + tmpx = paperwidth - LeftMargin(row_ptr) + + font.stringWidth(layout.labelsep); + row_ptr->par->bibkey->draw(owner_->painter(), + font, + offset + row_ptr->baseline, + tmpx); + } + } + } + + /* is it a last row? */ + par = row_ptr->par->LastPhysicalPar(); + if (row_ptr->par->ParFromPos(RowLast(row_ptr) + 1) == par + && (!row_ptr->next || row_ptr->next->par != row_ptr->par)) { + + /* think about the margins */ + if (!row_ptr->next) + y_bottom -= LYX_PAPER_MARGIN; + + /* draw a bottom pagebreak */ + if (firstpar->pagebreak_bottom) { + pain.line(0, offset + y_bottom - 2 * DefaultHeight(), + paperwidth, + offset + y_bottom - 2 * DefaultHeight(), + LColor::pagebreak); + y_bottom -= 3 * DefaultHeight(); + } + + if (firstpar->added_space_bottom.kind() == VSpace::VFILL) { + /* draw a vfill bottom */ + pain.line(0, offset + y_bottom - 3 * DefaultHeight(), + LYX_PAPER_MARGIN, + offset + y_bottom - 3 * DefaultHeight(), + LColor::vfillline); + pain.line(0, offset + y_bottom - 2, + LYX_PAPER_MARGIN, + offset + y_bottom - 2, + LColor::vfillline); + pain.line(LYX_PAPER_MARGIN / 2, + offset + y_bottom - 3 * DefaultHeight(), + LYX_PAPER_MARGIN / 2, + offset + y_bottom - 2, + LColor::vfillline); + y_bottom -= 3* DefaultHeight(); + } + + /* think about user added space */ + y_bottom -= int(firstpar->added_space_bottom.inPixels()); + + if (firstpar->line_bottom) { + /* draw a bottom line */ + y_bottom -= GetFont(par, par->Last() - 1).ascent('x'); + pain.line(0, offset + y_bottom, + paperwidth, offset + y_bottom, + LColor::topline, Painter::line_solid, + Painter::line_thick); + y_bottom -= GetFont(par, par->Last() - 1).ascent('x'); + } + } + + /* draw the text in the pixmap */ + pos_end = RowLast(row_ptr); + + vpos = row_ptr->pos; + /* table stuff -- begin*/ + if (row_ptr->par->table) { + bool on_off; + int cell = NumberOfCell(row_ptr->par, row_ptr->pos); + float x_old = x; + x += row_ptr->par->table->GetBeginningOfTextInCell(cell); - // is there a break one row above - if (row->previous && row->previous->par == row->par) { - z = NextBreakPoint(row->previous, paperwidth); - if ( z >= row->pos) { - row->pos = z + 1; + while (vpos <= pos_end) { + pos = vis2log(vpos); + if (row_ptr->par->IsNewline(pos)) { - tmprow = row->previous; + x = x_old + row_ptr->par->table->WidthOfColumn(cell); + /* draw the table lines, still very simple */ + on_off = !row_ptr->par->table->TopLine(cell); + if ((!on_off || + !row_ptr->par->table->TopAlreadyDrawed(cell)) && + !row_ptr->par->table->IsContRow(cell)) + pain.line(int(x_old), + offset + row_ptr->baseline - row_ptr->ascent_of_text, + int(x - x_old), + offset + row_ptr->baseline - row_ptr->ascent_of_text, + LColor::tableline); - // maybe the current row is now empty - if (row->pos >= row->par->Last()) { - // remove it - RemoveRow(row); - need_break_row = 0; - } else { - BreakAgainOneRow(row); - if (row->next && row->next->par == row->par) - need_break_row = row->next; - else - need_break_row = 0; - } + on_off = !row_ptr->par->table->BottomLine(cell); + if ((!on_off && !row_ptr->par->table->RowHasContRow(cell)) || + row_ptr->par->table->VeryLastRow(cell)) + + pain.line(int(x_old), + offset + y_bottom - 1, + int(x - x_old), + offset + y_bottom - 1, + LColor::tableline); + + on_off = !row_ptr->par->table->LeftLine(cell); + + pain.line(int(x_old), + offset + row_ptr->baseline - row_ptr->ascent_of_text, + int(x_old), + offset + y_bottom, + LColor::tableline, + Painter::line_onoffdash); - // set the dimensions of the row above - y -= tmprow->height; - tmprow->fill = Fill(tmprow, paperwidth); - SetHeightOfRow(tmprow); + on_off = !row_ptr->par->table->RightLine(cell); + + pain.line(int(x) - row_ptr->par->table->AdditionalWidth(cell), + offset + row_ptr->baseline - row_ptr->ascent_of_text, + int(x) - row_ptr->par->table->AdditionalWidth(cell), + offset + y_bottom - 1, + LColor::tableline, + Painter::line_onoffdash); - refresh_y = y; - refresh_row = tmprow; - status = LyXText::NEED_MORE_REFRESH; - current_font = rawtmpfont; - real_current_font = realtmpfont; - SetCursor(cursor.par, cursor.pos, false); - // check, whether the last character's font has changed. - rawtmpfont = cursor.par->GetFontSettings(cursor.par->Last() - 1); - if (rawparfont != rawtmpfont) - RedoHeightOfParagraph(cursor); - return; + x_old = x; + /* take care about the alignment and other spaces */ + ++cell; + x += row_ptr->par->table->GetBeginningOfTextInCell(cell); + if (row_ptr->par->table->IsFirstCell(cell)) + --cell; // little hack, sorry + ++vpos; + } else if (row_ptr->par->IsHfill(pos)) { + x += 1; + + pain.line(int(x), + offset + row_ptr->baseline - DefaultHeight() / 2, + int(x), + offset + row_ptr->baseline, + LColor::vfillline); + + x += 2; + ++vpos; + } else { + if (row_ptr->par->IsSeparator(pos)) { + tmpx = x; + x+= SingleWidth(row_ptr->par, pos); + /* -------> Only draw protected spaces when not in + * free-spacing mode. */ + if (row_ptr->par->GetChar(pos) == LyXParagraph::META_PROTECTED_SEPARATOR && !layout.free_spacing) { + pain.line(int(tmpx), + offset + row_ptr->baseline - 3, + int(tmpx), + offset + row_ptr->baseline - 1, + LColor::vfillline); + + pain.line(int(tmpx), + offset + row_ptr->baseline - 1, + int(x - tmpx - 2), + offset + row_ptr->baseline - 1, + LColor::vfillline); + + pain.line(int(x - 2), + offset + row_ptr->baseline - 3, + int(x - 2), + offset + row_ptr->baseline - 1, + LColor::vfillline); + + /* what about underbars? */ + font = GetFont(row_ptr->par, pos); + if (font.underbar() == LyXFont::ON + && font.latex() != LyXFont::ON) { + pain.line(int(tmpx), + offset + row_ptr->baseline + 2, + int(x - tmpx), + offset + row_ptr->baseline + 2); + } + } + ++vpos; + } else + draw(row_ptr, vpos, offset, x); } } - // break the cursor row again - z = NextBreakPoint(row, paperwidth); - - if (z != RowLast(row) || - (row->next && row->next->par == row->par && - RowLast(row) == row->par->Last() - 1)){ - - /* it can happen that a paragraph loses one row - * without a real breakup. This is when a word - * is to long to be broken. Well, I don t care this - * hack ;-) */ - if (row->next && row->next->par == row->par && - RowLast(row) == row->par->Last() - 1) - RemoveRow(row->next); - - refresh_y = y; - refresh_row = row; - status = LyXText::NEED_MORE_REFRESH; + /* do not forget the very last cell. This has no NEWLINE so + * ignored by the code above*/ + if (cell == row_ptr->par->table->GetNumberOfCells()-1){ + x = x_old + row_ptr->par->table->WidthOfColumn(cell); + on_off = !row_ptr->par->table->TopLine(cell); + if ((!on_off || + !row_ptr->par->table->TopAlreadyDrawed(cell)) && + !row_ptr->par->table->IsContRow(cell)) + + pain.line(int(x_old), + offset + row_ptr->baseline - row_ptr->ascent_of_text, + int(x - x_old), + offset + row_ptr->baseline - row_ptr->ascent_of_text, + LColor::tableline, + Painter::line_onoffdash); + on_off = !row_ptr->par->table->BottomLine(cell); + if ((!on_off && !row_ptr->par->table->RowHasContRow(cell)) || + row_ptr->par->table->VeryLastRow(cell)) + + pain.line(int(x_old), + offset + y_bottom - 1, + int(x - x_old), + offset + y_bottom - 1, + LColor::tableline, + Painter::line_onoffdash); - BreakAgainOneRow(row); - current_font = rawtmpfont; - real_current_font = realtmpfont; - SetCursor(cursor.par, cursor.pos, false); - // cursor MUST be in row now + on_off = !row_ptr->par->table->LeftLine(cell); + + pain.line(int(x_old), + offset + row_ptr->baseline - row_ptr->ascent_of_text, + int(x_old), + offset + y_bottom - 1, + LColor::tableline, + Painter::line_onoffdash); - if (row->next && row->next->par == row->par) - need_break_row = row->next; - else - need_break_row = 0; - } else { - // set the dimensions of the row - row->fill = Fill(row, paperwidth); - int tmpheight = row->height; - SetHeightOfRow(row); - if (tmpheight == row->height) - status = LyXText::NEED_VERY_LITTLE_REFRESH; - else - status = LyXText::NEED_MORE_REFRESH; - refresh_y = y; - refresh_row = row; - current_font = rawtmpfont; - real_current_font = realtmpfont; - SetCursor(cursor.par, cursor.pos, false); + on_off = !row_ptr->par->table->RightLine(cell); + + pain.line(int(x) - row_ptr->par->table->AdditionalWidth(cell), + offset + row_ptr->baseline - row_ptr->ascent_of_text, + int(x) - row_ptr->par->table->AdditionalWidth(cell), + offset + y_bottom - 1, + LColor::tableline, + Painter::line_onoffdash); } - } - - // restore the current font - // That is what a user expects! - current_font = rawtmpfont; - real_current_font = realtmpfont; - - // check, wether the last characters font has changed. - rawtmpfont = cursor.par->GetFontSettings(cursor.par->Last() - 1); - if (rawparfont != rawtmpfont) { - RedoHeightOfParagraph(cursor); } else { - // now the special right address boxes - if (textclasslist.Style(parameters->textclass, - cursor.par->GetLayout()).margintype == MARGIN_RIGHT_ADDRESS_BOX) { - RedoDrawingOfParagraph(cursor); + /* table stuff -- end*/ + LyXParagraph::size_type main_body = + BeginningOfMainBody(row_ptr->par); + if (main_body > 0 && + (main_body-1 > pos_end || + !row_ptr->par->IsLineSeparator(main_body-1))) + main_body = 0; + + while (vpos <= pos_end) { + pos = vis2log(vpos); + if (main_body > 0 && pos == main_body-1) { + x += fill_label_hfill + + GetFont(row_ptr->par, -2).stringWidth(layout.labelsep) + - SingleWidth(row_ptr->par, main_body-1); + } + + if (row_ptr->par->IsHfill(pos)) { + x += 1; + pain.line(int(x), + offset + row_ptr->baseline - DefaultHeight() / 2, + int(x), + offset + row_ptr->baseline, + LColor::vfillline); + + if (HfillExpansion(row_ptr, pos)) { + if (pos >= main_body) { + pain.line(int(x), + offset + row_ptr->baseline - DefaultHeight() / 4, + int(fill_hfill), + offset + row_ptr->baseline - DefaultHeight() / 4, + LColor::vfillline, + Painter::line_onoffdash); + x += fill_hfill; + } else { + pain.line(int(x), + offset + row_ptr->baseline - DefaultHeight() / 4, + int(fill_label_hfill), + offset + row_ptr->baseline - DefaultHeight() / 4, + LColor::vfillline, + Painter::line_onoffdash); + + x += fill_label_hfill; + } + pain.line(int(x), + offset + row_ptr->baseline - DefaultHeight() / 2, + int(x), + offset + row_ptr->baseline, + LColor::vfillline); + } + x += 2; + ++vpos; + } else { + if (row_ptr->par->IsSeparator(pos)) { + tmpx = x; + x+= SingleWidth(row_ptr->par, pos); + if (pos >= main_body) + x+= fill_separator; + /* -------> Only draw protected spaces when not in + * free-spacing mode. */ + if (row_ptr->par->GetChar(pos) == LyXParagraph::META_PROTECTED_SEPARATOR && !layout.free_spacing) { + + pain.line(int(tmpx), + offset + row_ptr->baseline - 3, + int(tmpx), + offset + row_ptr->baseline - 1, + LColor::vfillline); + + pain.line(int(tmpx), + offset + row_ptr->baseline - 1, + int(tmpx), + offset + row_ptr->baseline - 1, + LColor::vfillline); + + pain.line(int(x - 2), + offset + row_ptr->baseline - 3, + int(x - 2), + offset + row_ptr->baseline - 1, + LColor::vfillline); + + /* what about underbars? */ + font = GetFont(row_ptr->par, pos); + if (font.underbar() == LyXFont::ON + && font.latex() != LyXFont::ON) { + pain.line(int(tmpx), + offset + row_ptr->baseline + 2, + int(x - tmpx), + offset + row_ptr->baseline + 2); + } + } + ++vpos; + } else + draw(row_ptr, vpos, offset, x); + } + } + } +#if 0 + // check for FAST SELECTION + if (fast_selection || mono_video) { + if (selection) { + + /* selection code */ + if (sel_start_cursor.row == row_ptr && sel_end_cursor.row == row_ptr) { + scr.fillRectangle(gc_select, sel_start_cursor.x, offset, + sel_end_cursor.x - sel_start_cursor.x, + row_ptr->height); + } else if (sel_start_cursor.row == row_ptr) { + scr.fillRectangle(gc_select, sel_start_cursor.x, offset, + paperwidth - sel_start_cursor.x, + row_ptr->height); + } else if (sel_end_cursor.row == row_ptr) { + scr.fillRectangle(gc_select, 0, offset, + sel_end_cursor.x, + row_ptr->height); + } else if (y > sel_start_cursor.y && y < sel_end_cursor.y) { + scr.fillRectangle(gc_select, 0, offset, + paperwidth, row_ptr->height); + + } } } +// end of FAST SELECTION code + /* thats it */ +#endif } - - +#else void LyXText::GetVisibleRow(LyXScreen & scr, int offset, Row * row_ptr, long y) { @@ -3582,7 +4848,11 @@ void LyXText::GetVisibleRow(LyXScreen & scr, int offset, if (row_ptr->par->footnoteflag == LyXParagraph::OPEN_FOOTNOTE) { LyXFont font(LyXFont::ALL_SANE); font.setSize(LyXFont::SIZE_FOOTNOTE); +#ifdef USE_PAINTER + font.setColor(LColor::footnote); +#else font.setColor(LyXFont::RED); +#endif int box_x = LYX_PAPER_MARGIN; box_x += font.textWidth(" wide-tab ", 10); @@ -4105,7 +5375,7 @@ void LyXText::GetVisibleRow(LyXScreen & scr, int offset, // end of FAST SELECTION code /* thats it */ } - +#endif int LyXText::DefaultHeight() const { diff --git a/src/text2.C b/src/text2.C index 249607947a..4652c1c803 100644 --- a/src/text2.C +++ b/src/text2.C @@ -42,8 +42,9 @@ extern BufferView * current_view; using std::copy; -LyXText::LyXText(int pw, Buffer * p) +LyXText::LyXText(BufferView * bv, int pw, Buffer * p) { + owner_ = bv; firstrow = 0; lastrow = 0; currentrow = 0; @@ -96,6 +97,12 @@ LyXText::~LyXText() } +void LyXText::owner(BufferView * bv) +{ + if (owner_) lyxerr << "LyXText::owner_ already set!" << endl; + owner_ = bv; +} + // Gets the fully instantiated font at a given position in a paragraph // Basically the same routine as LyXParagraph::getFont() in paragraph.C. // The difference is that this one is used for displaying, and thus we -- 2.39.5