From: John Levon Date: Thu, 23 May 2002 15:43:25 +0000 (+0000) Subject: more guii moving around. X-Git-Tag: 1.6.10~19224 X-Git-Url: https://git.lyx.org/gitweb/?a=commitdiff_plain;h=98b254c810d26a76aa81c7a58202a3d9d40d09aa;p=features.git more guii moving around. git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@4192 a592a061-630c-0410-9148-cb99ea01b6c8 --- diff --git a/src/BufferView.C b/src/BufferView.C index 26fefa39ee..41c7775141 100644 --- a/src/BufferView.C +++ b/src/BufferView.C @@ -17,7 +17,7 @@ #include "BufferView.h" #include "BufferView_pimpl.h" #include "lyxtext.h" -#include "lyxscreen.h" +#include "frontends/screen.h" BufferView::BufferView(LyXView * o, int xpos, int ypos, diff --git a/src/BufferView2.C b/src/BufferView2.C index 996791f362..fb7c29762d 100644 --- a/src/BufferView2.C +++ b/src/BufferView2.C @@ -16,7 +16,7 @@ #include "lyxtext.h" #include "frontends/LyXView.h" #include "bufferlist.h" -#include "lyxscreen.h" +#include "frontends/screen.h" #include "LaTeX.h" #include "BufferView_pimpl.h" #include "language.h" diff --git a/src/BufferView_pimpl.C b/src/BufferView_pimpl.C index 613cc3b363..aef9714b7d 100644 --- a/src/BufferView_pimpl.C +++ b/src/BufferView_pimpl.C @@ -5,8 +5,8 @@ #endif #include "BufferView_pimpl.h" -#include "WorkArea.h" -#include "lyxscreen.h" +#include "frontends/WorkArea.h" +#include "frontends/screen.h" #include "lyxtext.h" #include "lyxrow.h" #include "paragraph.h" diff --git a/src/BufferView_pimpl.h b/src/BufferView_pimpl.h index cc9929b4fe..3702405385 100644 --- a/src/BufferView_pimpl.h +++ b/src/BufferView_pimpl.h @@ -6,7 +6,8 @@ #include "BufferView.h" #include "commandtags.h" #include "frontends/Timeout.h" -#include "WorkArea.h" +// FIXME remove me +#include "frontends/WorkArea.h" #include "box.h" #include "insets/insetspecialchar.h" #include "support/types.h" diff --git a/src/Makefile.am b/src/Makefile.am index 3624d2a11c..781714b83b 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -91,8 +91,6 @@ lyx_SOURCES = \ Thesaurus.h \ ToolbarDefaults.C \ ToolbarDefaults.h \ - WorkArea.C \ - WorkArea.h \ box.h \ box.C \ broken_headers.h \ @@ -163,13 +161,10 @@ lyx_SOURCES = \ lyxlex.h \ lyxlex_pimpl.C \ lyxlex_pimpl.h \ - lyxlookup.C \ - lyxlookup.h \ lyxrc.C \ lyxrc.h \ lyxrow.C \ lyxrow.h \ - lyxscreen.h \ lyxserver.C \ lyxserver.h \ lyxtext.h \ @@ -186,7 +181,6 @@ lyx_SOURCES = \ paragraph.h \ paragraph_pimpl.C \ paragraph_pimpl.h \ - screen.C \ sp_base.h \ sp_spell.C \ sp_ispell.h \ diff --git a/src/WorkArea.C b/src/WorkArea.C deleted file mode 100644 index d2235da633..0000000000 --- a/src/WorkArea.C +++ /dev/null @@ -1,625 +0,0 @@ -/* This file is part of - * ====================================================== - * - * LyX, The Document Processor - * - * Copyright 1995 Matthias Ettrich - * Copyright 1995-2001 The LyX Team. - * - * ====================================================== */ - -#include - -#ifdef __GNUG__ -#pragma implementation -#endif - -#include "WorkArea.h" -#include "debug.h" -#include "frontends/LyXView.h" -#include "lyxrc.h" // lyxrc.show_banner -#include "version.h" // lyx_version - -#if FL_REVISION < 89 || (FL_REVISION == 89 && FL_FIXLEVEL < 5) -#include "lyxlookup.h" -#endif - -#include "support/filetools.h" // LibFileSearch -#include "support/lstrings.h" -#include "support/LAssert.h" - -#include -#include - -// xforms doesn't define this (but it should be in ). -extern "C" -FL_APPEVENT_CB fl_set_preemptive_callback(Window, FL_APPEVENT_CB, void *); - -using std::endl; -using std::abs; -using std::hex; - -namespace { - -inline -void waitForX() -{ - XSync(fl_get_display(), 0); -} - -} // anon namespace - - -extern "C" { - // Just a bunch of C wrappers around static members of WorkArea - static - void C_WorkArea_scroll_cb(FL_OBJECT * ob, long buf) - { - WorkArea::scroll_cb(ob, buf); - } - - - static - int C_WorkArea_work_area_handler(FL_OBJECT * ob, int event, - FL_Coord, FL_Coord, - int key, void * xev) - { - return WorkArea::work_area_handler(ob, event, - 0, 0, key, xev); - } - - static - int C_WorkAreaEventCB(FL_FORM * form, void * xev) { - WorkArea * wa = static_cast(form->u_vdata); - return wa->event_cb(static_cast(xev)); - } -} - - -WorkArea::WorkArea(int xpos, int ypos, int width, int height) - : splash_(0), splash_text_(0), workareapixmap(0), painter_(*this) -{ - fl_freeze_all_forms(); - - if (lyxerr.debugging(Debug::WORKAREA)) - lyxerr << "Creating work area: +" - << xpos << '+' << ypos << ' ' - << width << 'x' << height << endl; - // - FL_OBJECT * obj; - int const bw = int(abs(fl_get_border_width())); - - // a box - if (lyxerr.debugging(Debug::WORKAREA)) - 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); - - // Add a splash screen to the centre of the work area - string const splash_file = (lyxrc.show_banner) ? - LibFileSearch("images", "banner", "xpm") : string(); - - if (!splash_file.empty()) { - int const splash_w = 425; - int const splash_h = 290; - int const splash_x = xpos + (width - 15 - splash_w) / 2; - int const splash_y = ypos + (height - splash_h) / 2; - splash_ = obj = - fl_add_pixmapbutton(FL_NORMAL_BUTTON, - splash_x, splash_y, - splash_w, splash_h, ""); - fl_set_pixmapbutton_file(obj, splash_file.c_str()); - fl_set_pixmapbutton_focus_outline(obj, 3); - fl_set_object_boxtype(obj, FL_NO_BOX); - - int const text_x = splash_x + 260; - int const text_y = splash_y + 255; - splash_text_ = obj = - fl_add_text(FL_NORMAL_TEXT, text_x, text_y, 160, 16, - lyx_version); - fl_set_object_lsize(obj, FL_NORMAL_SIZE); - fl_mapcolor(FL_FREE_COL2, 0x2b, 0x47, 0x82); - fl_mapcolor(FL_FREE_COL3, 0xe1, 0xd2, 0x9b); - fl_set_object_color(obj, FL_FREE_COL2, FL_FREE_COL2); - fl_set_object_lcol(obj, FL_FREE_COL3); - fl_set_object_lalign(obj, FL_ALIGN_LEFT|FL_ALIGN_INSIDE); - fl_set_object_lstyle(obj, FL_BOLD_STYLE); - } - - // - // THE SCROLLBAR - // - - scrollbar = obj = fl_add_scrollbar(FL_VERT_SCROLLBAR, - xpos + width - 15, - ypos, 17, height, ""); - 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, C_WorkArea_scroll_cb, 0); - setScrollbarBounds(0.0, 0.0); - - /// - /// The free object - - // Create the workarea pixmap - createPixmap(width - 15 - 2 * bw, height - 2 * bw); - - // We add this object as late as possible to avoit problems - // with drawing. - if (lyxerr.debugging(Debug::WORKAREA)) - lyxerr << "\tfree object: +" - << xpos + bw << '+' << ypos + bw << ' ' - << width - 15 - 2 * bw << 'x' - << height - 2 * bw << endl; - - work_area = obj = fl_add_free(FL_ALL_FREE, - xpos + bw, ypos + bw, - width - 15 - 2 * bw, // scrollbarwidth - height - 2 * bw, "", - C_WorkArea_work_area_handler); - obj->wantkey = FL_KEY_ALL; - 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); - - /// X selection hook - xforms gets it wrong - fl_current_form->u_vdata = this; - fl_register_raw_callback(fl_current_form, FL_ALL_EVENT, C_WorkAreaEventCB); - - fl_unfreeze_all_forms(); -} - - -WorkArea::~WorkArea() -{ - if (workareapixmap) - XFreePixmap(fl_get_display(), workareapixmap); -} - - -bool WorkArea::belowMouse() const -{ - FL_Coord x, y; - unsigned int button; - fl_get_mouse(&x, &y, &button); - FL_Coord ulx = work_area->form->x + work_area->x; - FL_Coord uly = work_area->form->y + work_area->y; - FL_Coord w = work_area->w; - FL_Coord h = work_area->h; - if (x > ulx && y > uly && x < ulx + h && y < uly + w) - return true; - return false; -} - - -void WorkArea::resize(int xpos, int ypos, int width, int height) -{ - fl_freeze_all_forms(); - - int const bw = int(abs(fl_get_border_width())); - - // a box - fl_set_object_geometry(backgroundbox, xpos, ypos, width - 15, height); - - // - // THE SCROLLBAR - // - fl_set_object_geometry(scrollbar, xpos + width - 15, - ypos, 17, height); - - // Create the workarea pixmap - createPixmap(width - 15 - 2 * bw, height - 2 * bw); - - // the free object - fl_set_object_geometry(work_area, xpos + bw, ypos + bw, - width - 15 - 2 * bw, - height - 2 * bw); - - fl_unfreeze_all_forms(); -} - - -namespace { -void destroy_object(FL_OBJECT * obj) -{ - if (!obj) - return; - - if (obj->visible) { - fl_hide_object(obj); - } - fl_delete_object(obj); - fl_free_object(obj); -} -} // namespace anon - - -void WorkArea::createPixmap(int width, int height) -{ - // Three calls to createPixmap are needed to draw the initial view - // of LyX. Any more and the splash is destroyed. - static int counter = 0; - if (++counter == 4) { - destroy_object(splash_); - splash_ = 0; - destroy_object(splash_text_); - splash_text_ = 0; - } - - 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_get_display(), workareapixmap); - - if (lyxerr.debugging(Debug::WORKAREA)) - lyxerr << "Creating pixmap (" - << width << 'x' << height << ")" << endl; - - workareapixmap = XCreatePixmap(fl_get_display(), - RootWindow(fl_get_display(), 0), - width, - height, - fl_get_visual_depth()); - if (lyxerr.debugging(Debug::WORKAREA)) - lyxerr << "\tpixmap=" << workareapixmap << endl; -} - - -void WorkArea::greyOut() const -{ - if (!splash_) { - 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_scrollbar_value(scrollbar, pos); - fl_set_scrollbar_size(scrollbar, scrollbar->h * length_fraction); -} - - -void WorkArea::setScrollbarBounds(double l1, double l2) const -{ - fl_set_scrollbar_bounds(scrollbar, l1, l2); -} - - -void WorkArea::setScrollbarIncrements(double inc) const -{ - fl_set_scrollbar_increment(scrollbar, work_area->h - inc, inc); -} - - -// Callback for scrollbar slider -void WorkArea::scroll_cb(FL_OBJECT * ob, long) -{ - WorkArea * area = static_cast(ob->u_vdata); - // If we really want the accellerating scroll we can do that - // from here. IMHO that is a waste of effort since we already - // have other ways to move fast around in the document. (Lgb) - area->scrollCB(fl_get_scrollbar_value(ob)); - waitForX(); -} - - -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] << "Workarea event: DRAW" << endl; - area->createPixmap(area->workWidth(), area->height()); - area->workAreaExpose(); - break; - case FL_PUSH: - if (!ev || ev->xbutton.button == 0) break; - // Should really have used xbutton.state - lyxerr[Debug::WORKAREA] << "Workarea event: PUSH" << endl; - area->workAreaButtonPress(ev->xbutton.x - ob->x, - ev->xbutton.y - ob->y, - ev->xbutton.button); - //area->workAreaKeyPress(XK_Pointer_Button1, ev->xbutton.state); - break; - case FL_RELEASE: - if (!ev || ev->xbutton.button == 0) break; - // Should really have used xbutton.state - lyxerr[Debug::WORKAREA] << "Workarea event: RELEASE" << endl; - area->workAreaButtonRelease(ev->xbutton.x - ob->x, - ev->xbutton.y - ob->y, - ev->xbutton.button); - break; -#if FL_REVISION < 89 - case FL_MOUSE: -#else - case FL_DRAG: -#endif - if (!ev || ! area->scrollbar) break; - if (ev->xmotion.x != x_old || - ev->xmotion.y != y_old || - fl_get_scrollbar_value(area->scrollbar) != scrollbar_value_old - ) { - lyxerr[Debug::WORKAREA] << "Workarea event: MOUSE" << endl; - area->workAreaMotionNotify(ev->xmotion.x - ob->x, - ev->xmotion.y - ob->y, - ev->xbutton.state); - } - break; -#if FL_REVISION < 89 - case FL_KEYBOARD: -#else - case FL_KEYPRESS: -#endif - { - lyxerr[Debug::WORKAREA] << "Workarea event: KEYBOARD" << endl; - - KeySym keysym = 0; - char dummy[1]; - XKeyEvent * xke = reinterpret_cast(ev); -#if FL_REVISION < 89 || (FL_REVISION == 89 && FL_FIXLEVEL < 5) - // XForms < 0.89.5 does not have compose support - // so we are using our own compose support - LyXLookupString(ev, dummy, 1, &keysym); -#else - XLookupString(xke, dummy, 1, &keysym, 0); -// int num_keys = XLookupString(xke, dummy, 10, &keysym, &xcs); -// lyxerr << "We have " << num_keys << " keys in the returned buffer" << endl; -// lyxerr << "Our dummy string is " << dummy << endl; -#endif - if (lyxerr.debugging(Debug::KEY)) { - char const * tmp = XKeysymToString(key); - char const * tmp2 = XKeysymToString(keysym); - string const stm = (tmp ? tmp : ""); - string const stm2 = (tmp2 ? tmp2 : ""); - - lyxerr[Debug::KEY] << "WorkArea: Key is `" << stm << "' [" - << key << "]" << endl; - lyxerr[Debug::KEY] << "WorkArea: Keysym is `" << stm2 << "' [" - << keysym << "]" << endl; - } - -#if FL_REVISION < 89 || (FL_REVISION == 89 && FL_FIXLEVEL < 5) - if (keysym == NoSymbol) { - lyxerr[Debug::KEY] - << "Empty kdb action (probably composing)" - << endl; - break; - } - KeySym ret_key = keysym; -#else - // Note that we need this handling because of a bug - // in XForms 0.89, if this bug is resolved in the way I hope - // we can just use the keysym directly with out looking - // at key at all. (Lgb) - KeySym ret_key = 0; - if (!key) { - // We migth have to add more keysyms here also, - // we will do that as the issues arise. (Lgb) - if (keysym == XK_space) { - ret_key = keysym; - lyxerr[Debug::KEY] << "Using keysym [A]" - << endl; - } else - break; - } else { - // It seems that this was a bit optimistic... - // With this hacking things seems to be better (Lgb) - //if (!iscntrl(key)) { - // ret_key = key; - // lyxerr[Debug::KEY] - // << "Using key [B]\n" - // << "Uchar[" - // << static_cast(key) - // << endl; - //} else { - ret_key = (keysym ? keysym : key); - lyxerr[Debug::KEY] << "Using keysym [B]" - << endl; - //} - } - -#endif - unsigned int const ret_state = xke->state; - - // If you have a better way to handle "wild-output" of - // characters after the key has been released than the one - // below, please contact me. (Lgb) - static Time last_time_pressed; - static unsigned int last_key_pressed; - static unsigned int last_state_pressed; - lyxerr[Debug::KEY] << "Workarea Diff: " - << xke->time - last_time_pressed - << endl; - if (xke->time - last_time_pressed < 25 // should perhaps be tunable - && ret_state == last_state_pressed - && xke->keycode == last_key_pressed) { - lyxerr[Debug::KEY] - << "Workarea: Purging X events." << endl; - //lyxerr << "Workarea Events: " - // << XEventsQueued(fl_get_display(), QueuedAlready) - // << endl; - if (XEventsQueued(fl_get_display(), QueuedAlready) > 0) - XSync(fl_get_display(), 1); - // This purge make f.ex. scrolling stop immidiatly when - // releasing the PageDown button. The question is if - // this purging of XEvents can cause any harm... - // after some testing I can see no problems, but - // I'd like other reports too. - break; - } - last_time_pressed = xke->time; - last_key_pressed = xke->keycode; - last_state_pressed = ret_state; - - area->workAreaKeyPress(ret_key, ret_state); - } - break; - -#if FL_REVISION >= 89 - case FL_KEYRELEASE: - lyxerr[Debug::WORKAREA] << "Workarea event: KEYRELEASE" << endl; - break; -#endif - - case FL_FOCUS: - lyxerr[Debug::WORKAREA] << "Workarea event: FOCUS" << endl; - area->workAreaFocus(); - break; - case FL_UNFOCUS: - lyxerr[Debug::WORKAREA] << "Workarea event: UNFOCUS" << endl; - area->workAreaUnfocus(); - break; - case FL_ENTER: - lyxerr[Debug::WORKAREA] << "Workarea event: ENTER" << endl; - area->workAreaEnter(); - break; - case FL_LEAVE: - lyxerr[Debug::WORKAREA] << "Workarea event: LEAVE" << endl; - area->workAreaLeave(); - break; - case FL_DBLCLICK: - if (!ev) break; - lyxerr[Debug::WORKAREA] << "Workarea event: DBLCLICK" << endl; - area->workAreaDoubleClick(ev->xbutton.x - ob->x, - ev->xbutton.y - ob->y, - ev->xbutton.button); - break; - case FL_TRPLCLICK: - if (!ev) break; - lyxerr[Debug::WORKAREA] << "Workarea event: TRPLCLICK" << endl; - area->workAreaTripleClick(ev->xbutton.x - ob->x, - ev->xbutton.y - ob->y, - ev->xbutton.button); - break; - case FL_OTHER: - if (!ev) break; - lyxerr[Debug::WORKAREA] << "Workarea event: OTHER" << endl; - break; - } - - return 1; -} - - -namespace { - -string clipboard_selection; -bool clipboard_read = false; - -extern "C" { - - static - int request_clipboard_cb(FL_OBJECT * /*ob*/, long /*type*/, - void const * data, long size) - { - clipboard_selection.erase(); - - if (size > 0) - clipboard_selection.reserve(size); - for (int i = 0; i < size; ++i) - clipboard_selection += - static_cast(data)[i]; - clipboard_read = true; - return 0; - } - -} - -} // namespace anon - - -int WorkArea::event_cb(XEvent * xev) -{ - int ret = 0; - switch (xev->type) { - case SelectionRequest: - lyxerr[Debug::GUI] << "X requested selection." << endl; - selectionRequested.emit(); - break; - case SelectionClear: - lyxerr[Debug::GUI] << "Lost selection." << endl; - selectionLost.emit(); - break; - } - return ret; -} - - -void WorkArea::haveSelection(bool yes) const -{ - if (!yes) { - XSetSelectionOwner(fl_get_display(), XA_PRIMARY, None, CurrentTime); - return; - } - - XSetSelectionOwner(fl_get_display(), XA_PRIMARY, FL_ObjWin(work_area), CurrentTime); -} - - -string const WorkArea::getClipboard() const -{ - clipboard_read = false; - - if (fl_request_clipboard(work_area, 0, request_clipboard_cb) == -1) - return string(); - - XEvent ev; - - while (!clipboard_read) { - if (fl_check_forms() == FL_EVENT) { - fl_XNextEvent(&ev); - lyxerr << "Received unhandled X11 event" << endl; - lyxerr << "Type: 0x" << hex << ev.xany.type << - " Target: 0x" << hex << ev.xany.window << endl; - } - } - return clipboard_selection; -} - - -void WorkArea::putClipboard(string const & s) const -{ - static string hold; - hold = s; - - fl_stuff_clipboard(work_area, 0, hold.data(), hold.size(), 0); -} diff --git a/src/WorkArea.h b/src/WorkArea.h deleted file mode 100644 index 90fc8f690e..0000000000 --- a/src/WorkArea.h +++ /dev/null @@ -1,157 +0,0 @@ -// -*- C++ -*- -/* This file is part of - * ====================================================== - * - * LyX, The Document Processor - * - * Copyright 1995 Matthias Ettrich - * Copyright 1995-2001 The LyX Team. - * - * ======================================================*/ - -#ifndef WORKAREA_H -#define WORKAREA_H - -#ifdef __GNUG__ -#pragma interface -#endif - -#include - -#include - -#include FORMS_H_LOCATION -#include "frontends/Painter.h" - -/// -class WorkArea { -public: - /// - WorkArea(int xpos, int ypos, int width, int height); - /// - ~WorkArea(); - /// - Painter & getPainter() { return painter_; } - /// - int workWidth() const { return work_area->w; } - /// - unsigned int width() const { return work_area->w + scrollbar->w; } - //unsigned int width() const { return backgroundbox->w + 15; } - /// - unsigned int height() const { return work_area->h; } - //unsigned int height() const { return backgroundbox->h; } - /// - int xpos() const { return work_area->x; } - //int xpos() const { return backgroundbox->x; } - /// - int ypos() const { return work_area->y; } - //int ypos() const { return backgroundbox->y; } - /// - void resize(int xpos, int ypos, int width, int height); - /// - void redraw() const { - fl_redraw_object(work_area); - fl_redraw_object(scrollbar); - } - /// - 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 belowMouse() const; - /// - 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_scrollbar_value(scrollbar, y); - } - /// - void setScrollbarBounds(double, double) const; - /// - void setScrollbarIncrements(double inc) const; - /// - double getScrollbarValue() const { - return fl_get_scrollbar_value(scrollbar); - } - /// - std::pair const getScrollbarBounds() const { - std::pair p; - fl_get_scrollbar_bounds(scrollbar, &p.first, &p.second); - return p; - } - /// - Pixmap getPixmap() const { return workareapixmap; } - /// xforms callback - static int work_area_handler(FL_OBJECT *, int event, - FL_Coord, FL_Coord, - int /*key*/, void * xev); - /// xforms callback - static void scroll_cb(FL_OBJECT *, long); - /// a selection exists - void haveSelection(bool) const; - /// - string const getClipboard() const; - /// - void putClipboard(string const &) const; - // Signals - /// - SigC::Signal0 workAreaExpose; - /// - SigC::Signal1 scrollCB; - /// - SigC::Signal2 workAreaKeyPress; - /// - SigC::Signal3 workAreaButtonPress; - /// - SigC::Signal3 workAreaButtonRelease; - /// - SigC::Signal3 workAreaMotionNotify; - /// - SigC::Signal0 workAreaFocus; - /// - SigC::Signal0 workAreaUnfocus; - /// - SigC::Signal0 workAreaEnter; - /// - SigC::Signal0 workAreaLeave; - /// - SigC::Signal3 workAreaDoubleClick; - /// - SigC::Signal3 workAreaTripleClick; - /// emitted when an X client has requested our selection - SigC::Signal0 selectionRequested; - /// emitted when another X client has stolen our selection - SigC::Signal0 selectionLost; - - /// handles SelectionRequest X Event, to fill the clipboard - int event_cb(XEvent * xev); -private: - /// - void createPixmap(int, int); - - /// - FL_OBJECT * backgroundbox; - /// - FL_OBJECT * work_area; - /// - FL_OBJECT * scrollbar; - /// - mutable FL_OBJECT * splash_; - /// - mutable FL_OBJECT * splash_text_; - /// The pixmap overlay on the workarea - Pixmap workareapixmap; - /// - Painter painter_; - /// if we call redraw with true needed for locking-insets - bool screen_cleared; -}; -#endif diff --git a/src/frontends/ChangeLog b/src/frontends/ChangeLog index 70fd733d9c..29b57aff26 100644 --- a/src/frontends/ChangeLog +++ b/src/frontends/ChangeLog @@ -1,3 +1,12 @@ +2002-05-23 John Levon + + * WorkArea.h: + * WorkArea.C: + * Makefile.am: move here + + * screen.h: + * screen.C: move here + 2002-05-23 John Levon * Liason.C: diff --git a/src/frontends/Makefile.am b/src/frontends/Makefile.am index f54c3cca05..fc6ac70405 100644 --- a/src/frontends/Makefile.am +++ b/src/frontends/Makefile.am @@ -33,4 +33,8 @@ libfrontends_la_SOURCES = \ Toolbar.C \ Toolbar.h \ LyXView.C \ - LyXView.h + LyXView.h \ + WorkArea.C \ + WorkArea.h \ + screen.C \ + screen.h diff --git a/src/frontends/WorkArea.C b/src/frontends/WorkArea.C new file mode 100644 index 0000000000..49ee9d69d6 --- /dev/null +++ b/src/frontends/WorkArea.C @@ -0,0 +1,625 @@ +/* This file is part of + * ====================================================== + * + * LyX, The Document Processor + * + * Copyright 1995 Matthias Ettrich + * Copyright 1995-2001 The LyX Team. + * + * ====================================================== */ + +#include + +#ifdef __GNUG__ +#pragma implementation +#endif + +#include "WorkArea.h" +#include "debug.h" +#include "frontends/LyXView.h" +#include "lyxrc.h" // lyxrc.show_banner +#include "version.h" // lyx_version + +#if FL_REVISION < 89 || (FL_REVISION == 89 && FL_FIXLEVEL < 5) +#include "frontends/xforms/lyxlookup.h" +#endif + +#include "support/filetools.h" // LibFileSearch +#include "support/lstrings.h" +#include "support/LAssert.h" + +#include +#include + +// xforms doesn't define this (but it should be in ). +extern "C" +FL_APPEVENT_CB fl_set_preemptive_callback(Window, FL_APPEVENT_CB, void *); + +using std::endl; +using std::abs; +using std::hex; + +namespace { + +inline +void waitForX() +{ + XSync(fl_get_display(), 0); +} + +} // anon namespace + + +extern "C" { + // Just a bunch of C wrappers around static members of WorkArea + static + void C_WorkArea_scroll_cb(FL_OBJECT * ob, long buf) + { + WorkArea::scroll_cb(ob, buf); + } + + + static + int C_WorkArea_work_area_handler(FL_OBJECT * ob, int event, + FL_Coord, FL_Coord, + int key, void * xev) + { + return WorkArea::work_area_handler(ob, event, + 0, 0, key, xev); + } + + static + int C_WorkAreaEventCB(FL_FORM * form, void * xev) { + WorkArea * wa = static_cast(form->u_vdata); + return wa->event_cb(static_cast(xev)); + } +} + + +WorkArea::WorkArea(int xpos, int ypos, int width, int height) + : splash_(0), splash_text_(0), workareapixmap(0), painter_(*this) +{ + fl_freeze_all_forms(); + + if (lyxerr.debugging(Debug::WORKAREA)) + lyxerr << "Creating work area: +" + << xpos << '+' << ypos << ' ' + << width << 'x' << height << endl; + // + FL_OBJECT * obj; + int const bw = int(abs(fl_get_border_width())); + + // a box + if (lyxerr.debugging(Debug::WORKAREA)) + 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); + + // Add a splash screen to the centre of the work area + string const splash_file = (lyxrc.show_banner) ? + LibFileSearch("images", "banner", "xpm") : string(); + + if (!splash_file.empty()) { + int const splash_w = 425; + int const splash_h = 290; + int const splash_x = xpos + (width - 15 - splash_w) / 2; + int const splash_y = ypos + (height - splash_h) / 2; + splash_ = obj = + fl_add_pixmapbutton(FL_NORMAL_BUTTON, + splash_x, splash_y, + splash_w, splash_h, ""); + fl_set_pixmapbutton_file(obj, splash_file.c_str()); + fl_set_pixmapbutton_focus_outline(obj, 3); + fl_set_object_boxtype(obj, FL_NO_BOX); + + int const text_x = splash_x + 260; + int const text_y = splash_y + 255; + splash_text_ = obj = + fl_add_text(FL_NORMAL_TEXT, text_x, text_y, 160, 16, + lyx_version); + fl_set_object_lsize(obj, FL_NORMAL_SIZE); + fl_mapcolor(FL_FREE_COL2, 0x2b, 0x47, 0x82); + fl_mapcolor(FL_FREE_COL3, 0xe1, 0xd2, 0x9b); + fl_set_object_color(obj, FL_FREE_COL2, FL_FREE_COL2); + fl_set_object_lcol(obj, FL_FREE_COL3); + fl_set_object_lalign(obj, FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + fl_set_object_lstyle(obj, FL_BOLD_STYLE); + } + + // + // THE SCROLLBAR + // + + scrollbar = obj = fl_add_scrollbar(FL_VERT_SCROLLBAR, + xpos + width - 15, + ypos, 17, height, ""); + 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, C_WorkArea_scroll_cb, 0); + setScrollbarBounds(0.0, 0.0); + + /// + /// The free object + + // Create the workarea pixmap + createPixmap(width - 15 - 2 * bw, height - 2 * bw); + + // We add this object as late as possible to avoit problems + // with drawing. + if (lyxerr.debugging(Debug::WORKAREA)) + lyxerr << "\tfree object: +" + << xpos + bw << '+' << ypos + bw << ' ' + << width - 15 - 2 * bw << 'x' + << height - 2 * bw << endl; + + work_area = obj = fl_add_free(FL_ALL_FREE, + xpos + bw, ypos + bw, + width - 15 - 2 * bw, // scrollbarwidth + height - 2 * bw, "", + C_WorkArea_work_area_handler); + obj->wantkey = FL_KEY_ALL; + 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); + + /// X selection hook - xforms gets it wrong + fl_current_form->u_vdata = this; + fl_register_raw_callback(fl_current_form, FL_ALL_EVENT, C_WorkAreaEventCB); + + fl_unfreeze_all_forms(); +} + + +WorkArea::~WorkArea() +{ + if (workareapixmap) + XFreePixmap(fl_get_display(), workareapixmap); +} + + +bool WorkArea::belowMouse() const +{ + FL_Coord x, y; + unsigned int button; + fl_get_mouse(&x, &y, &button); + FL_Coord ulx = work_area->form->x + work_area->x; + FL_Coord uly = work_area->form->y + work_area->y; + FL_Coord w = work_area->w; + FL_Coord h = work_area->h; + if (x > ulx && y > uly && x < ulx + h && y < uly + w) + return true; + return false; +} + + +void WorkArea::resize(int xpos, int ypos, int width, int height) +{ + fl_freeze_all_forms(); + + int const bw = int(abs(fl_get_border_width())); + + // a box + fl_set_object_geometry(backgroundbox, xpos, ypos, width - 15, height); + + // + // THE SCROLLBAR + // + fl_set_object_geometry(scrollbar, xpos + width - 15, + ypos, 17, height); + + // Create the workarea pixmap + createPixmap(width - 15 - 2 * bw, height - 2 * bw); + + // the free object + fl_set_object_geometry(work_area, xpos + bw, ypos + bw, + width - 15 - 2 * bw, + height - 2 * bw); + + fl_unfreeze_all_forms(); +} + + +namespace { +void destroy_object(FL_OBJECT * obj) +{ + if (!obj) + return; + + if (obj->visible) { + fl_hide_object(obj); + } + fl_delete_object(obj); + fl_free_object(obj); +} +} // namespace anon + + +void WorkArea::createPixmap(int width, int height) +{ + // Three calls to createPixmap are needed to draw the initial view + // of LyX. Any more and the splash is destroyed. + static int counter = 0; + if (++counter == 4) { + destroy_object(splash_); + splash_ = 0; + destroy_object(splash_text_); + splash_text_ = 0; + } + + 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_get_display(), workareapixmap); + + if (lyxerr.debugging(Debug::WORKAREA)) + lyxerr << "Creating pixmap (" + << width << 'x' << height << ")" << endl; + + workareapixmap = XCreatePixmap(fl_get_display(), + RootWindow(fl_get_display(), 0), + width, + height, + fl_get_visual_depth()); + if (lyxerr.debugging(Debug::WORKAREA)) + lyxerr << "\tpixmap=" << workareapixmap << endl; +} + + +void WorkArea::greyOut() const +{ + if (!splash_) { + 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_scrollbar_value(scrollbar, pos); + fl_set_scrollbar_size(scrollbar, scrollbar->h * length_fraction); +} + + +void WorkArea::setScrollbarBounds(double l1, double l2) const +{ + fl_set_scrollbar_bounds(scrollbar, l1, l2); +} + + +void WorkArea::setScrollbarIncrements(double inc) const +{ + fl_set_scrollbar_increment(scrollbar, work_area->h - inc, inc); +} + + +// Callback for scrollbar slider +void WorkArea::scroll_cb(FL_OBJECT * ob, long) +{ + WorkArea * area = static_cast(ob->u_vdata); + // If we really want the accellerating scroll we can do that + // from here. IMHO that is a waste of effort since we already + // have other ways to move fast around in the document. (Lgb) + area->scrollCB(fl_get_scrollbar_value(ob)); + waitForX(); +} + + +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] << "Workarea event: DRAW" << endl; + area->createPixmap(area->workWidth(), area->height()); + area->workAreaExpose(); + break; + case FL_PUSH: + if (!ev || ev->xbutton.button == 0) break; + // Should really have used xbutton.state + lyxerr[Debug::WORKAREA] << "Workarea event: PUSH" << endl; + area->workAreaButtonPress(ev->xbutton.x - ob->x, + ev->xbutton.y - ob->y, + ev->xbutton.button); + //area->workAreaKeyPress(XK_Pointer_Button1, ev->xbutton.state); + break; + case FL_RELEASE: + if (!ev || ev->xbutton.button == 0) break; + // Should really have used xbutton.state + lyxerr[Debug::WORKAREA] << "Workarea event: RELEASE" << endl; + area->workAreaButtonRelease(ev->xbutton.x - ob->x, + ev->xbutton.y - ob->y, + ev->xbutton.button); + break; +#if FL_REVISION < 89 + case FL_MOUSE: +#else + case FL_DRAG: +#endif + if (!ev || ! area->scrollbar) break; + if (ev->xmotion.x != x_old || + ev->xmotion.y != y_old || + fl_get_scrollbar_value(area->scrollbar) != scrollbar_value_old + ) { + lyxerr[Debug::WORKAREA] << "Workarea event: MOUSE" << endl; + area->workAreaMotionNotify(ev->xmotion.x - ob->x, + ev->xmotion.y - ob->y, + ev->xbutton.state); + } + break; +#if FL_REVISION < 89 + case FL_KEYBOARD: +#else + case FL_KEYPRESS: +#endif + { + lyxerr[Debug::WORKAREA] << "Workarea event: KEYBOARD" << endl; + + KeySym keysym = 0; + char dummy[1]; + XKeyEvent * xke = reinterpret_cast(ev); +#if FL_REVISION < 89 || (FL_REVISION == 89 && FL_FIXLEVEL < 5) + // XForms < 0.89.5 does not have compose support + // so we are using our own compose support + LyXLookupString(ev, dummy, 1, &keysym); +#else + XLookupString(xke, dummy, 1, &keysym, 0); +// int num_keys = XLookupString(xke, dummy, 10, &keysym, &xcs); +// lyxerr << "We have " << num_keys << " keys in the returned buffer" << endl; +// lyxerr << "Our dummy string is " << dummy << endl; +#endif + if (lyxerr.debugging(Debug::KEY)) { + char const * tmp = XKeysymToString(key); + char const * tmp2 = XKeysymToString(keysym); + string const stm = (tmp ? tmp : ""); + string const stm2 = (tmp2 ? tmp2 : ""); + + lyxerr[Debug::KEY] << "WorkArea: Key is `" << stm << "' [" + << key << "]" << endl; + lyxerr[Debug::KEY] << "WorkArea: Keysym is `" << stm2 << "' [" + << keysym << "]" << endl; + } + +#if FL_REVISION < 89 || (FL_REVISION == 89 && FL_FIXLEVEL < 5) + if (keysym == NoSymbol) { + lyxerr[Debug::KEY] + << "Empty kdb action (probably composing)" + << endl; + break; + } + KeySym ret_key = keysym; +#else + // Note that we need this handling because of a bug + // in XForms 0.89, if this bug is resolved in the way I hope + // we can just use the keysym directly with out looking + // at key at all. (Lgb) + KeySym ret_key = 0; + if (!key) { + // We migth have to add more keysyms here also, + // we will do that as the issues arise. (Lgb) + if (keysym == XK_space) { + ret_key = keysym; + lyxerr[Debug::KEY] << "Using keysym [A]" + << endl; + } else + break; + } else { + // It seems that this was a bit optimistic... + // With this hacking things seems to be better (Lgb) + //if (!iscntrl(key)) { + // ret_key = key; + // lyxerr[Debug::KEY] + // << "Using key [B]\n" + // << "Uchar[" + // << static_cast(key) + // << endl; + //} else { + ret_key = (keysym ? keysym : key); + lyxerr[Debug::KEY] << "Using keysym [B]" + << endl; + //} + } + +#endif + unsigned int const ret_state = xke->state; + + // If you have a better way to handle "wild-output" of + // characters after the key has been released than the one + // below, please contact me. (Lgb) + static Time last_time_pressed; + static unsigned int last_key_pressed; + static unsigned int last_state_pressed; + lyxerr[Debug::KEY] << "Workarea Diff: " + << xke->time - last_time_pressed + << endl; + if (xke->time - last_time_pressed < 25 // should perhaps be tunable + && ret_state == last_state_pressed + && xke->keycode == last_key_pressed) { + lyxerr[Debug::KEY] + << "Workarea: Purging X events." << endl; + //lyxerr << "Workarea Events: " + // << XEventsQueued(fl_get_display(), QueuedAlready) + // << endl; + if (XEventsQueued(fl_get_display(), QueuedAlready) > 0) + XSync(fl_get_display(), 1); + // This purge make f.ex. scrolling stop immidiatly when + // releasing the PageDown button. The question is if + // this purging of XEvents can cause any harm... + // after some testing I can see no problems, but + // I'd like other reports too. + break; + } + last_time_pressed = xke->time; + last_key_pressed = xke->keycode; + last_state_pressed = ret_state; + + area->workAreaKeyPress(ret_key, ret_state); + } + break; + +#if FL_REVISION >= 89 + case FL_KEYRELEASE: + lyxerr[Debug::WORKAREA] << "Workarea event: KEYRELEASE" << endl; + break; +#endif + + case FL_FOCUS: + lyxerr[Debug::WORKAREA] << "Workarea event: FOCUS" << endl; + area->workAreaFocus(); + break; + case FL_UNFOCUS: + lyxerr[Debug::WORKAREA] << "Workarea event: UNFOCUS" << endl; + area->workAreaUnfocus(); + break; + case FL_ENTER: + lyxerr[Debug::WORKAREA] << "Workarea event: ENTER" << endl; + area->workAreaEnter(); + break; + case FL_LEAVE: + lyxerr[Debug::WORKAREA] << "Workarea event: LEAVE" << endl; + area->workAreaLeave(); + break; + case FL_DBLCLICK: + if (!ev) break; + lyxerr[Debug::WORKAREA] << "Workarea event: DBLCLICK" << endl; + area->workAreaDoubleClick(ev->xbutton.x - ob->x, + ev->xbutton.y - ob->y, + ev->xbutton.button); + break; + case FL_TRPLCLICK: + if (!ev) break; + lyxerr[Debug::WORKAREA] << "Workarea event: TRPLCLICK" << endl; + area->workAreaTripleClick(ev->xbutton.x - ob->x, + ev->xbutton.y - ob->y, + ev->xbutton.button); + break; + case FL_OTHER: + if (!ev) break; + lyxerr[Debug::WORKAREA] << "Workarea event: OTHER" << endl; + break; + } + + return 1; +} + + +namespace { + +string clipboard_selection; +bool clipboard_read = false; + +extern "C" { + + static + int request_clipboard_cb(FL_OBJECT * /*ob*/, long /*type*/, + void const * data, long size) + { + clipboard_selection.erase(); + + if (size > 0) + clipboard_selection.reserve(size); + for (int i = 0; i < size; ++i) + clipboard_selection += + static_cast(data)[i]; + clipboard_read = true; + return 0; + } + +} + +} // namespace anon + + +int WorkArea::event_cb(XEvent * xev) +{ + int ret = 0; + switch (xev->type) { + case SelectionRequest: + lyxerr[Debug::GUI] << "X requested selection." << endl; + selectionRequested.emit(); + break; + case SelectionClear: + lyxerr[Debug::GUI] << "Lost selection." << endl; + selectionLost.emit(); + break; + } + return ret; +} + + +void WorkArea::haveSelection(bool yes) const +{ + if (!yes) { + XSetSelectionOwner(fl_get_display(), XA_PRIMARY, None, CurrentTime); + return; + } + + XSetSelectionOwner(fl_get_display(), XA_PRIMARY, FL_ObjWin(work_area), CurrentTime); +} + + +string const WorkArea::getClipboard() const +{ + clipboard_read = false; + + if (fl_request_clipboard(work_area, 0, request_clipboard_cb) == -1) + return string(); + + XEvent ev; + + while (!clipboard_read) { + if (fl_check_forms() == FL_EVENT) { + fl_XNextEvent(&ev); + lyxerr << "Received unhandled X11 event" << endl; + lyxerr << "Type: 0x" << hex << ev.xany.type << + " Target: 0x" << hex << ev.xany.window << endl; + } + } + return clipboard_selection; +} + + +void WorkArea::putClipboard(string const & s) const +{ + static string hold; + hold = s; + + fl_stuff_clipboard(work_area, 0, hold.data(), hold.size(), 0); +} diff --git a/src/frontends/WorkArea.h b/src/frontends/WorkArea.h new file mode 100644 index 0000000000..90fc8f690e --- /dev/null +++ b/src/frontends/WorkArea.h @@ -0,0 +1,157 @@ +// -*- C++ -*- +/* This file is part of + * ====================================================== + * + * LyX, The Document Processor + * + * Copyright 1995 Matthias Ettrich + * Copyright 1995-2001 The LyX Team. + * + * ======================================================*/ + +#ifndef WORKAREA_H +#define WORKAREA_H + +#ifdef __GNUG__ +#pragma interface +#endif + +#include + +#include + +#include FORMS_H_LOCATION +#include "frontends/Painter.h" + +/// +class WorkArea { +public: + /// + WorkArea(int xpos, int ypos, int width, int height); + /// + ~WorkArea(); + /// + Painter & getPainter() { return painter_; } + /// + int workWidth() const { return work_area->w; } + /// + unsigned int width() const { return work_area->w + scrollbar->w; } + //unsigned int width() const { return backgroundbox->w + 15; } + /// + unsigned int height() const { return work_area->h; } + //unsigned int height() const { return backgroundbox->h; } + /// + int xpos() const { return work_area->x; } + //int xpos() const { return backgroundbox->x; } + /// + int ypos() const { return work_area->y; } + //int ypos() const { return backgroundbox->y; } + /// + void resize(int xpos, int ypos, int width, int height); + /// + void redraw() const { + fl_redraw_object(work_area); + fl_redraw_object(scrollbar); + } + /// + 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 belowMouse() const; + /// + 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_scrollbar_value(scrollbar, y); + } + /// + void setScrollbarBounds(double, double) const; + /// + void setScrollbarIncrements(double inc) const; + /// + double getScrollbarValue() const { + return fl_get_scrollbar_value(scrollbar); + } + /// + std::pair const getScrollbarBounds() const { + std::pair p; + fl_get_scrollbar_bounds(scrollbar, &p.first, &p.second); + return p; + } + /// + Pixmap getPixmap() const { return workareapixmap; } + /// xforms callback + static int work_area_handler(FL_OBJECT *, int event, + FL_Coord, FL_Coord, + int /*key*/, void * xev); + /// xforms callback + static void scroll_cb(FL_OBJECT *, long); + /// a selection exists + void haveSelection(bool) const; + /// + string const getClipboard() const; + /// + void putClipboard(string const &) const; + // Signals + /// + SigC::Signal0 workAreaExpose; + /// + SigC::Signal1 scrollCB; + /// + SigC::Signal2 workAreaKeyPress; + /// + SigC::Signal3 workAreaButtonPress; + /// + SigC::Signal3 workAreaButtonRelease; + /// + SigC::Signal3 workAreaMotionNotify; + /// + SigC::Signal0 workAreaFocus; + /// + SigC::Signal0 workAreaUnfocus; + /// + SigC::Signal0 workAreaEnter; + /// + SigC::Signal0 workAreaLeave; + /// + SigC::Signal3 workAreaDoubleClick; + /// + SigC::Signal3 workAreaTripleClick; + /// emitted when an X client has requested our selection + SigC::Signal0 selectionRequested; + /// emitted when another X client has stolen our selection + SigC::Signal0 selectionLost; + + /// handles SelectionRequest X Event, to fill the clipboard + int event_cb(XEvent * xev); +private: + /// + void createPixmap(int, int); + + /// + FL_OBJECT * backgroundbox; + /// + FL_OBJECT * work_area; + /// + FL_OBJECT * scrollbar; + /// + mutable FL_OBJECT * splash_; + /// + mutable FL_OBJECT * splash_text_; + /// The pixmap overlay on the workarea + Pixmap workareapixmap; + /// + Painter painter_; + /// if we call redraw with true needed for locking-insets + bool screen_cleared; +}; +#endif diff --git a/src/frontends/screen.C b/src/frontends/screen.C new file mode 100644 index 0000000000..dbf850e110 --- /dev/null +++ b/src/frontends/screen.C @@ -0,0 +1,530 @@ +/* This file is part of +* ====================================================== +* +* LyX, The Document Processor +* +* Copyright 1995 Matthias Ettrich +* Copyright 1995-1998 The LyX Team +* +* ====================================================== */ + +#include + +#ifdef __GNUG__ +#pragma implementation +#endif + +#include + +#include "screen.h" +#include "lyxtext.h" +#include "lyxrow.h" +#include "frontends/Painter.h" +#include "frontends/WorkArea.h" +#include "buffer.h" +#include "BufferView.h" +#include "font.h" +#include "insets/insettext.h" +#include "ColorHandler.h" +#include "language.h" + +using std::max; +using std::min; + +namespace { + +GC createGC() +{ + XGCValues val; + val.foreground = BlackPixel(fl_get_display(), + DefaultScreen(fl_get_display())); + + val.function = GXcopy; + val.graphics_exposures = false; + val.line_style = LineSolid; + val.line_width = 0; + return XCreateGC(fl_get_display(), RootWindow(fl_get_display(), 0), + GCForeground | GCFunction | GCGraphicsExposures + | GCLineWidth | GCLineStyle , &val); +} + +} // namespace anon + + +// Constructor +LyXScreen::LyXScreen(WorkArea & o) + : owner(o), force_clear(true) +{ + // the cursor isnt yet visible + cursor_visible = false; + cursor_pixmap = 0; + cursor_pixmap_x = 0; + cursor_pixmap_y = 0; + cursor_pixmap_w = 0; + cursor_pixmap_h = 0; + + // We need this GC + gc_copy = createGC(); +} + + +LyXScreen::~LyXScreen() +{ + XFreeGC(fl_get_display(), gc_copy); +} + + +void LyXScreen::setCursorColor() +{ + if (!lyxColorHandler.get()) return; + + GC gc = lyxColorHandler->getGCForeground(LColor::cursor); + + XGCValues val; + XGetGCValues(fl_get_display(), + gc, GCForeground, &val); + XChangeGC(fl_get_display(), gc_copy, GCForeground, &val); +} + + +void LyXScreen::redraw(LyXText * text, BufferView * bv) +{ + drawFromTo(text, bv, 0, owner.height(), 0, 0, text == bv->text); + expose(0, 0, owner.workWidth(), owner.height()); + if (cursor_visible) { + cursor_visible = false; + bv->showCursor(); + } +} + + +void LyXScreen::expose(int x, int y, int exp_width, int exp_height) +{ + XCopyArea(fl_get_display(), + owner.getPixmap(), + owner.getWin(), + gc_copy, + x, y, + exp_width, exp_height, + x + owner.xpos(), + y + owner.ypos()); +} + + +void LyXScreen::drawFromTo(LyXText * text, BufferView * bv, + int y1, int y2, int y_offset, int x_offset, + bool internal) +{ + int y_text = text->first_y + y1; + + // get the first needed row + Row * row = text->getRowNearY(y_text); + // y_text is now the real beginning of the row + + int y = y_text - text->first_y; + // y1 is now the real beginning of row on the screen + + while (row != 0 && y < y2) { + LyXText::text_status st = text->status(); + text->getVisibleRow(bv, y + y_offset, + x_offset, row, y + text->first_y); + internal = internal && (st != LyXText::CHANGED_IN_DRAW); + while (internal && text->status() == LyXText::CHANGED_IN_DRAW) { + text->fullRebreak(bv); + st = LyXText::NEED_MORE_REFRESH; + text->setCursor(bv, text->cursor.par(), + text->cursor.pos()); + text->status(bv, st); + // we should be sure our row-pointer is still valid, so it's + // better to recompute it. + y_text = y + text->first_y; + row = text->getRowNearY(y_text); + y = y_text - text->first_y; + text->getVisibleRow(bv, y + y_offset, + x_offset, row, y + text->first_y); + } + y += row->height(); + row = row->next(); + } + force_clear = false; + + // maybe we have to clear the screen at the bottom + if ((y < y2) && text->bv_owner) { + owner.getPainter().fillRectangle(0, y, + owner.workWidth(), + y2 - y, + LColor::bottomarea); + } +} + + +void LyXScreen::drawOneRow(LyXText * text, BufferView * bv, Row * row, + int y_text, int y_offset, int x_offset) +{ + int const y = y_text - text->first_y + y_offset; + + if (((y + row->height()) > 0) && + ((y - row->height()) <= static_cast(owner.height()))) { + // ok there is something visible + text->getVisibleRow(bv, y, x_offset, row, y + text->first_y); + } + force_clear = false; +} + + +/* draws the screen, starting with textposition y. uses as much already + * printed pixels as possible */ +void LyXScreen::draw(LyXText * text, BufferView * bv, unsigned int y) +{ + if (cursor_visible) hideCursor(); + + int const old_first = text->first_y; + bool internal = (text == bv->text); + text->first_y = y; + + // is any optimiziation possible? + if ((y - old_first) < owner.height() + && (old_first - y) < owner.height()) + { + if (text->first_y < old_first) { + drawFromTo(text, bv, 0, + old_first - text->first_y, 0, 0, internal); + XCopyArea (fl_get_display(), + owner.getWin(), + owner.getWin(), + gc_copy, + owner.xpos(), + owner.ypos(), + owner.workWidth(), + owner.height() - old_first + text->first_y, + owner.xpos(), + owner.ypos() + old_first - text->first_y + ); + // expose the area drawn + expose(0, 0, + owner.workWidth(), + old_first - text->first_y); + } else { + drawFromTo(text, bv, + owner.height() + old_first - text->first_y, + owner.height(), 0, 0, internal); + XCopyArea (fl_get_display(), + owner.getWin(), + owner.getWin(), + gc_copy, + owner.xpos(), + owner.ypos() + text->first_y - old_first, + owner.workWidth(), + owner.height() + old_first - text->first_y, + owner.xpos(), + owner.ypos()); + // expose the area drawn + expose(0, owner.height() + old_first - text->first_y, + owner.workWidth(), text->first_y - old_first); + } + } else { + // make a dumb new-draw + drawFromTo(text, bv, 0, owner.height(), 0, 0, internal); + expose(0, 0, owner.workWidth(), owner.height()); + } +} + + +void LyXScreen::showCursor(LyXText const * text, BufferView const * bv) +{ + if (!cursor_visible) { + Cursor_Shape shape = BAR_SHAPE; + if (text->real_current_font.language() != + bv->buffer()->params.language + || text->real_current_font.isVisibleRightToLeft() + != bv->buffer()->params.language->RightToLeft()) + shape = (text->real_current_font.isVisibleRightToLeft()) + ? REVERSED_L_SHAPE : L_SHAPE; + showManualCursor(text, text->cursor.x(), text->cursor.y(), + lyxfont::maxAscent(text->real_current_font), + lyxfont::maxDescent(text->real_current_font), + shape); + } +} + + +/* returns true if first has changed, otherwise false */ +bool LyXScreen::fitManualCursor(LyXText * text, BufferView * bv, + int /*x*/, int y, int asc, int desc) +{ + int newtop = text->first_y; + + if (y + desc - text->first_y >= static_cast(owner.height())) + newtop = y - 3 * owner.height() / 4; // the scroll region must be so big!! + else if (y - asc < text->first_y + && text->first_y > 0) { + newtop = y - owner.height() / 4; + } + + newtop = max(newtop, 0); // can newtop ever be < 0? (Lgb) + + if (newtop != text->first_y) { + draw(text, bv, newtop); + text->first_y = newtop; + return true; + } + return false; +} + + +void LyXScreen::showManualCursor(LyXText const * text, int x, int y, + int asc, int desc, Cursor_Shape shape) +{ + // Update the cursor color. + setCursorColor(); + + int const y1 = max(y - text->first_y - asc, 0); + int const y_tmp = min(y - text->first_y + desc, + static_cast(owner.height())); + + // Secure against very strange situations + int const y2 = max(y_tmp, y1); + + if (cursor_pixmap) { + XFreePixmap(fl_get_display(), cursor_pixmap); + cursor_pixmap = 0; + } + + if (y2 > 0 && y1 < int(owner.height())) { + cursor_pixmap_h = y2 - y1 + 1; + cursor_pixmap_y = y1; + + switch (shape) { + case BAR_SHAPE: + cursor_pixmap_w = 1; + cursor_pixmap_x = x; + break; + case L_SHAPE: + cursor_pixmap_w = cursor_pixmap_h/3; + cursor_pixmap_x = x; + break; + case REVERSED_L_SHAPE: + cursor_pixmap_w = cursor_pixmap_h/3; + cursor_pixmap_x = x - cursor_pixmap_w + 1; + break; + } + + cursor_pixmap = + XCreatePixmap (fl_get_display(), + fl_root, + cursor_pixmap_w, + cursor_pixmap_h, + fl_get_visual_depth()); + XCopyArea (fl_get_display(), + owner.getWin(), + cursor_pixmap, + gc_copy, + owner.xpos() + cursor_pixmap_x, + owner.ypos() + cursor_pixmap_y, + cursor_pixmap_w, + cursor_pixmap_h, + 0, 0); + XDrawLine(fl_get_display(), + owner.getWin(), + gc_copy, + x + owner.xpos(), + y1 + owner.ypos(), + x + owner.xpos(), + y2 + owner.ypos()); + switch (shape) { + case BAR_SHAPE: + break; + case L_SHAPE: + case REVERSED_L_SHAPE: + int const rectangle_h = (cursor_pixmap_h + 10) / 20; + XFillRectangle(fl_get_display(), + owner.getWin(), + gc_copy, + cursor_pixmap_x + owner.xpos(), + y2 - rectangle_h + 1 + owner.ypos(), + cursor_pixmap_w - 1, rectangle_h); + break; + } + + } + cursor_visible = true; +} + + +void LyXScreen::hideCursor() +{ + if (!cursor_visible) return; + + if (cursor_pixmap) { + XCopyArea (fl_get_display(), + cursor_pixmap, + owner.getWin(), + gc_copy, + 0, 0, + cursor_pixmap_w, cursor_pixmap_h, + cursor_pixmap_x + owner.xpos(), + cursor_pixmap_y + owner.ypos()); + } + cursor_visible = false; +} + + +void LyXScreen::cursorToggle(BufferView * bv) const +{ + if (cursor_visible) + bv->hideCursor(); + else + bv->showCursor(); +} + + +/* returns a new top so that the cursor is visible */ +unsigned int LyXScreen::topCursorVisible(LyXText const * text) +{ + int newtop = text->first_y; + + Row * row = text->cursor.row(); + + // Is this a hack? Yes, probably... (Lgb) + if (!row) + return max(newtop, 0); + + if (text->cursor.y() - row->baseline() + row->height() + - text->first_y >= owner.height()) { + if (row->height() < owner.height() + && row->height() > owner.height() / 4) { + newtop = text->cursor.y() + + row->height() + - row->baseline() - owner.height(); + } else { + // scroll down + newtop = text->cursor.y() + - owner.height() / 2; /* the scroll region must be so big!! */ + } + + } else if (static_cast((text->cursor.y()) - row->baseline()) < + text->first_y && text->first_y > 0) { + if (row->height() < owner.height() + && row->height() > owner.height() / 4) { + newtop = text->cursor.y() - row->baseline(); + } else { + // scroll up + newtop = text->cursor.y() - owner.height() / 2; + newtop = min(newtop, text->first_y); + } + } + + newtop = max(newtop, 0); + + return newtop; +} + + +/* scrolls the screen so that the cursor is visible, if necessary. +* returns true if a change was made, otherwise false */ +bool LyXScreen::fitCursor(LyXText * text, BufferView * bv) +{ + // Is a change necessary? + int const newtop = topCursorVisible(text); + bool const result = (newtop != text->first_y); + if (result) + draw(text, bv, newtop); + return result; +} + + +void LyXScreen::update(LyXText * text, BufferView * bv, + int y_offset, int x_offset) +{ + switch (text->status()) { + case LyXText::NEED_MORE_REFRESH: + { + int const y = max(int(text->refresh_y - text->first_y), 0); + drawFromTo(text, bv, y, owner.height(), y_offset, x_offset); + text->refresh_y = 0; + // otherwise this is called ONLY from BufferView_pimpl(update) + // or we should see to set this flag accordingly + if (text != bv->text) + text->status(bv, LyXText::UNCHANGED); + expose(0, y, owner.workWidth(), owner.height() - y); + } + break; + case LyXText::NEED_VERY_LITTLE_REFRESH: + { + // ok I will update the current cursor row + drawOneRow(text, bv, text->refresh_row, text->refresh_y, + y_offset, x_offset); + // this because if we had a major update the refresh_row could + // have been set to 0! + if (text->refresh_row) { + // otherwise this is called ONLY from BufferView_pimpl(update) + // or we should see to set this flag accordingly + if (text != bv->text) + text->status(bv, LyXText::UNCHANGED); + expose(0, text->refresh_y - text->first_y + y_offset, + owner.workWidth(), text->refresh_row->height()); + } + } + break; + case LyXText::CHANGED_IN_DRAW: // just to remove the warning + case LyXText::UNCHANGED: + // Nothing needs done + break; + } +} + + +void LyXScreen::toggleSelection(LyXText * text, BufferView * bv, + bool kill_selection, + int y_offset, int x_offset) +{ + // only if there is a selection + if (!text->selection.set()) return; + + int const bottom = min( + max(static_cast(text->selection.end.y() + - text->selection.end.row()->baseline() + + text->selection.end.row()->height()), + text->first_y), + static_cast(text->first_y + owner.height())); + int const top = min( + max(static_cast(text->selection.start.y() - + text->selection.start.row()->baseline()), + text->first_y), + static_cast(text->first_y + owner.height())); + + if (kill_selection) + text->selection.set(false); + drawFromTo(text, bv, top - text->first_y, bottom - text->first_y, + y_offset, x_offset); + expose(0, top - text->first_y, + owner.workWidth(), + bottom - text->first_y - (top - text->first_y)); +} + + +void LyXScreen::toggleToggle(LyXText * text, BufferView * bv, + int y_offset, int x_offset) +{ + if (text->toggle_cursor.par() == text->toggle_end_cursor.par() + && text->toggle_cursor.pos() == text->toggle_end_cursor.pos()) + return; + + int const top_tmp = text->toggle_cursor.y() + - text->toggle_cursor.row()->baseline(); + int const bottom_tmp = text->toggle_end_cursor.y() + - text->toggle_end_cursor.row()->baseline() + + text->toggle_end_cursor.row()->height(); + + int const offset = y_offset < 0 ? y_offset : 0; + int const bottom = min(max(bottom_tmp, text->first_y), + static_cast(text->first_y + owner.height()))-offset; + int const top = min(max(top_tmp, text->first_y), + static_cast(text->first_y + owner.height()))-offset; + + drawFromTo(text, bv, top - text->first_y, + bottom - text->first_y, y_offset, + x_offset); + expose(0, top - text->first_y, owner.workWidth(), + bottom - text->first_y - (top - text->first_y)); +} diff --git a/src/frontends/screen.h b/src/frontends/screen.h new file mode 100644 index 0000000000..f611e8a6e1 --- /dev/null +++ b/src/frontends/screen.h @@ -0,0 +1,126 @@ +// -*- C++ -*- +/* This file is part of + * ====================================================== + * + * LyX, The Document Processor + * + * Copyright 1995 Matthias Ettrich + * Copyright 1995-2001 The LyX Team + * + * ====================================================== */ + +#ifndef LYXSCREEN_H +#define LYXSCREEN_H + +#ifdef __GNUG__ +#pragma interface +#endif + +#include + +class LyXText; +class WorkArea; +class Buffer; +class BufferView; + +struct Row; + +/** 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. + This class also handles the drawing of the cursor and partly the selection. + */ +class LyXScreen { +public: + /// + enum Cursor_Shape { + /// + BAR_SHAPE, + /// + L_SHAPE, + /// + REVERSED_L_SHAPE + }; + + /// + LyXScreen(WorkArea &); + + /// + ~LyXScreen(); + + /// Sets the cursor color to LColor::cursor. + void setCursorColor(); + + /** Draws the screen form textposition y. Uses as much of + the already printed pixmap as possible */ + void draw(LyXText *, BufferView *, unsigned int y); + + /// Redraws the screen, without using existing pixmap + void redraw(LyXText *, BufferView *); + + /// Returns a new top so that the cursor is visible + unsigned int topCursorVisible(LyXText const *); + /// Redraws the screen such that the cursor is visible + bool fitCursor(LyXText *, BufferView *); + /// + void showCursor(LyXText const *, BufferView const *); + /// + void hideCursor(); + /// + void cursorToggle(BufferView *) const; + /// + void showManualCursor(LyXText const *, int x, int y, + int asc, int desc, + Cursor_Shape shape); + /// returns 1 if first has changed, otherwise 0 + bool fitManualCursor(LyXText *, BufferView *, int, int, int, int); + /// + void toggleSelection(LyXText *, BufferView *, bool = true, + int y_offset = 0, int x_offset = 0); + /// + void toggleToggle(LyXText *, BufferView *, + int y_offset = 0, int x_offset = 0); + + /** Updates part of the screen. If text->status is + LyXText::NEED_MORE_REFRESH, we update from the + point of change and to the end of the screen. + If text->status is LyXText::NEED_VERY_LITTLE_REFRESH, + we only update the current row. */ + void update(LyXText *, BufferView *, int y_offset=0, int x_offset=0); + /// + bool forceClear() const { return force_clear; } + + /// + bool cursor_visible; +private: + /// Copies specified area of pixmap to screen + void expose(int x, int y, int exp_width, int exp_height); + + /// y1 and y2 are coordinates of the screen + void drawFromTo(LyXText *, BufferView *, int y1, int y2, + int y_offset = 0, int x_offset = 0, bool internal=false); + + /// y is a coordinate of the text + void drawOneRow(LyXText *, BufferView *, Row * row, + int y_text, int y_offset = 0, int x_offset = 0); + + /// + WorkArea & owner; + + /// + Pixmap cursor_pixmap; + /// + int cursor_pixmap_x; + /// + int cursor_pixmap_y; + /// + int cursor_pixmap_w; + /// + int cursor_pixmap_h; + /// + GC gc_copy; + /// + bool force_clear; +}; + +#endif diff --git a/src/frontends/xforms/ChangeLog b/src/frontends/xforms/ChangeLog index 35834cf5b0..808180616c 100644 --- a/src/frontends/xforms/ChangeLog +++ b/src/frontends/xforms/ChangeLog @@ -1,3 +1,10 @@ +2002-05-23 John Levon + + * XFormsView.C: + * lyxlookup.h: + * lyxlookup.C: + * Makefile.am: move here + 2002-05-23 John Levon * DropDown.h: diff --git a/src/frontends/xforms/Makefile.am b/src/frontends/xforms/Makefile.am index f32f0f37af..52b1d68cef 100644 --- a/src/frontends/xforms/Makefile.am +++ b/src/frontends/xforms/Makefile.am @@ -196,6 +196,8 @@ libxforms_la_SOURCES = \ GUIRunTime.C \ input_validators.C \ input_validators.h \ + lyxlookup.C \ + lyxlookup.h \ MathsSymbols.C \ MathsSymbols.h \ Menubar_pimpl.C \ diff --git a/src/frontends/xforms/XFormsView.C b/src/frontends/xforms/XFormsView.C index bb73db762b..d09d6c1c2f 100644 --- a/src/frontends/xforms/XFormsView.C +++ b/src/frontends/xforms/XFormsView.C @@ -16,7 +16,7 @@ #include "XFormsView.h" #if FL_REVISION < 89 || (FL_REVISION == 89 && FL_FIXLEVEL < 5) -#include "lyxlookup.h" +#include "frontends/xforms/lyxlookup.h" #endif #include "minibuffer.h" #include "debug.h" diff --git a/src/frontends/xforms/lyxlookup.C b/src/frontends/xforms/lyxlookup.C new file mode 100644 index 0000000000..228e1920c6 --- /dev/null +++ b/src/frontends/xforms/lyxlookup.C @@ -0,0 +1,284 @@ +/* This file is part of + * ====================================================== + * + * LyX, The Document Processor + * + * Copyright 1995 Matthias Ettrich + * Copyright 1995-2001 The LyX team. + * + * ====================================================== */ + +#ifdef __GNUG__ +#pragma implementation +#endif + +#include + +#ifdef HAVE_XOPENIM +// This part is the full blown Input Method manager for X11R5 and up. +// For the plain-and-old-X11R4 version, see later. +#include +#include +#include +#ifdef HAVE_LOCALE_H +#include +#endif +#include + +#include "lyxlookup.h" +#include "debug.h" +#include "lyxrc.h" + +using std::endl; + +namespace { + +XIM xim; +XIC xic; +XComposeStatus compose_status= {0, 0}; + +} // namespace anon + + +// This is called after the main LyX window has been created +void InitLyXLookup(Display * display, Window window) +{ + xic = 0; + + lyxerr[Debug::KEY] + << "InitLyXLookup: creating an input context." + << endl; + + // This part could be done before opening display + string oldlocale = setlocale(LC_CTYPE, 0); + setlocale(LC_CTYPE, ""); + if (!XSupportsLocale()) { + lyxerr[Debug::KEY] + << "InitLyXLookup: X does not support this locale." + << endl; + return; + } + // reset the LC_CTYPE locale to previous value. + setlocale(LC_CTYPE, oldlocale.c_str()); + + char const * locmod; + if (!(locmod = XSetLocaleModifiers(""))) { + lyxerr[Debug::KEY] << "InitLyXLookup: Could not set modifiers " + "for this locale." << endl; + return; + } + else + lyxerr[Debug::KEY] << "InitLyXLookup: X locale modifiers are `" + << locmod << '\'' << endl; + + // This part will have to be done for each frame + xim = XOpenIM (display, 0, 0, 0); + if (xim) { + xic = XCreateIC(xim, + XNInputStyle, + XIMPreeditNothing|XIMStatusNothing, + XNClientWindow, window, + XNFocusWindow, window, + 0); + + if (!xic) { + lyxerr[Debug::KEY] << "InitLyXLookup: " + "could not create an input context" << endl; + XCloseIM (xim); + xim = 0; + } + } + else + lyxerr[Debug::KEY] << "InitLyXLookup: could not open " + "an input method." << endl; +} + + +namespace { + +bool isDeadEvent(KeySym keysym) +{ + // Can this be done safely in any other way? + // This is all the dead keys I know of in X11R6.1 + switch (keysym) { +#ifdef XK_dead_grave + case XK_dead_grave: +#endif +#ifdef XK_dead_acute + case XK_dead_acute: +#endif +#ifdef XK_dead_circumflex + case XK_dead_circumflex: +#endif +#ifdef XK_dead_tilde + case XK_dead_tilde: +#endif +#ifdef XK_dead_macron + case XK_dead_macron: +#endif +#ifdef XK_dead_breve + case XK_dead_breve: +#endif +#ifdef XK_dead_abovedot + case XK_dead_abovedot: +#endif +#ifdef XK_dead_diaeresis + case XK_dead_diaeresis: +#endif +#ifdef XK_dead_abovering + case XK_dead_abovering: +#endif +#ifdef XK_dead_doubleacute + case XK_dead_doubleacute: +#endif +#ifdef XK_dead_caron + case XK_dead_caron: +#endif +#ifdef XK_dead_cedilla + case XK_dead_cedilla: +#endif +#ifdef XK_dead_ogonek + case XK_dead_ogonek: +#endif +#ifdef XK_dead_iota + case XK_dead_iota: +#endif +#ifdef XK_dead_voiced_sound + case XK_dead_voiced_sound: +#endif +#ifdef XK_dead_semivoiced_sound + case XK_dead_semivoiced_sound: +#endif +#ifdef XK_dead_belowdot + case XK_dead_belowdot: +#endif + return true; + default: + return false; + } +} + +} // namespace anon + + +// This is called instead of XLookupString() +int LyXLookupString(XEvent * event, + char * buffer_return, int bytes_buffer, + KeySym * keysym_return) +{ + if (event->type != KeyPress) { + lyxerr << "LyXLookupString: wrong event type: " + << event->type << endl; + return 0; + } + + int result = 0; + if (xic) { +#if 1 + // somehow it is necessary to do the lookup. Why? (JMarc) + XLookupString(&event->xkey, buffer_return, + bytes_buffer, keysym_return, + 0); + + if (lyxrc.override_x_deadkeys && + isDeadEvent(*keysym_return)) { + lyxerr[Debug::KEY] + << "LyXLookupString: found DeadEvent" << endl; + return 0; + } +#endif +#if 1 + if (XFilterEvent (event, None)) { + lyxerr[Debug::KEY] <<"XFilterEvent" << endl; + *keysym_return = NoSymbol; + return 0; + } +#endif + Status status_return = 0; + + result = XmbLookupString(xic, &event->xkey, buffer_return, + bytes_buffer, keysym_return, + &status_return); + switch (status_return) { + case XBufferOverflow: + lyxerr[Debug::KEY] << "XBufferOverflow" << endl; + break; + case XLookupBoth: + lyxerr[Debug::KEY] << "XLookupBoth " + << string(buffer_return, result) + << endl; + break; + case XLookupChars: + lyxerr[Debug::KEY] << "XLookupChars " + << string(buffer_return, result) + << endl; + + *keysym_return = NoSymbol; + break; + case XLookupKeySym: + lyxerr[Debug::KEY] << "XLookupKeySym" << endl; + result = 0; + break; + case XLookupNone: + lyxerr[Debug::KEY] << "XLookupNone" << endl; + *keysym_return = NoSymbol; + result = 0; + break; + default: + lyxerr << "Unknown status_return from" + " XmbLookupString" << endl; + break; + } + } else { + result = XLookupString(&event->xkey, buffer_return, + bytes_buffer, keysym_return, + &compose_status); + } + return result; +} + + +// This is called after the main window has been destroyed +void CloseLyXLookup() +{ + if (xic) { + lyxerr[Debug::KEY] << "CloseLyXLookup: destroying input context" + << endl; + XDestroyIC(xic); + xic = 0; + XCloseIM(xim); + } +} + + +#else // We do not have XOpenIM, so we stick with normal XLookupString + +#include +#include + +XComposeStatus compose_status= {0, 0}; + +// This is called after the main LyX window has been created +void InitLyXLookup(Display *, Window) +{ + //Nothing to do. +} + +// This is called instead of XLookupString(). I this particular case, +// this *is* XLookupString... +int LyXLookupString(XEvent * event, + char * buffer_return, int bytes_buffer, + KeySym * keysym_return) +{ + return XLookupString(&event->xkey, buffer_return, + bytes_buffer, keysym_return, + &compose_status); +} + +// This is called after the main window has been destroyed +void CloseLyXLookup() +{ + // Nothing to do +} + +#endif // HAVE_XOPENIM diff --git a/src/frontends/xforms/lyxlookup.h b/src/frontends/xforms/lyxlookup.h new file mode 100644 index 0000000000..7eadbdf7b3 --- /dev/null +++ b/src/frontends/xforms/lyxlookup.h @@ -0,0 +1,31 @@ +/* This file is part of -*- C++ -*- +* ====================================================== +* +* LyX, The Document Processor +* +* Copyright 1995 Matthias Ettrich +* Copyright 1995-2001 The LyX Team. +* +* ====================================================== */ + +/* This header file defines wrappers around the X input method related + functions. This should probably be moved into LyXView (to have + different input methods for different frames, but for now we can + keep it as it is. */ +#ifndef LYXLOOKUP_H +#define LYXLOOKUP_H + +#include + +/// Initialize the compose key handling +extern void InitLyXLookup(Display *, Window); + +/// Read a keysym and/or a string (like XLookupString) +extern int LyXLookupString(XEvent * event, + char * buffer_return, int bytes_buffer, + KeySym * keysym_return); + +/// Call this when you destroy your window +extern void CloseLyXLookup(); + +#endif diff --git a/src/insets/ChangeLog b/src/insets/ChangeLog index 291df21dd5..42640ae993 100644 --- a/src/insets/ChangeLog +++ b/src/insets/ChangeLog @@ -1,3 +1,7 @@ +2002-05-23 John Levon + + * insettext.C: screen moved + 2002-05-23 John Levon * insetbib.C: diff --git a/src/insets/insettext.C b/src/insets/insettext.C index 268613f621..120e260efd 100644 --- a/src/insets/insettext.C +++ b/src/insets/insettext.C @@ -35,7 +35,7 @@ #include "lyxrc.h" #include "intl.h" #include "trans_mgr.h" -#include "lyxscreen.h" +#include "frontends/screen.h" #include "gettext.h" #include "lyxfunc.h" #include "ParagraphParameters.h" diff --git a/src/lyx_gui.C b/src/lyx_gui.C index 6bfe005cfd..188757da4c 100644 --- a/src/lyx_gui.C +++ b/src/lyx_gui.C @@ -27,7 +27,7 @@ #include "lyxrc.h" #include "gettext.h" #if FL_REVISION < 89 || (FL_REVISION == 89 && FL_FIXLEVEL < 5) -#include "lyxlookup.h" +#include "frontends/xforms/lyxlookup.h" #endif #include "bufferlist.h" #include "ColorHandler.h" diff --git a/src/lyxlookup.C b/src/lyxlookup.C deleted file mode 100644 index 228e1920c6..0000000000 --- a/src/lyxlookup.C +++ /dev/null @@ -1,284 +0,0 @@ -/* This file is part of - * ====================================================== - * - * LyX, The Document Processor - * - * Copyright 1995 Matthias Ettrich - * Copyright 1995-2001 The LyX team. - * - * ====================================================== */ - -#ifdef __GNUG__ -#pragma implementation -#endif - -#include - -#ifdef HAVE_XOPENIM -// This part is the full blown Input Method manager for X11R5 and up. -// For the plain-and-old-X11R4 version, see later. -#include -#include -#include -#ifdef HAVE_LOCALE_H -#include -#endif -#include - -#include "lyxlookup.h" -#include "debug.h" -#include "lyxrc.h" - -using std::endl; - -namespace { - -XIM xim; -XIC xic; -XComposeStatus compose_status= {0, 0}; - -} // namespace anon - - -// This is called after the main LyX window has been created -void InitLyXLookup(Display * display, Window window) -{ - xic = 0; - - lyxerr[Debug::KEY] - << "InitLyXLookup: creating an input context." - << endl; - - // This part could be done before opening display - string oldlocale = setlocale(LC_CTYPE, 0); - setlocale(LC_CTYPE, ""); - if (!XSupportsLocale()) { - lyxerr[Debug::KEY] - << "InitLyXLookup: X does not support this locale." - << endl; - return; - } - // reset the LC_CTYPE locale to previous value. - setlocale(LC_CTYPE, oldlocale.c_str()); - - char const * locmod; - if (!(locmod = XSetLocaleModifiers(""))) { - lyxerr[Debug::KEY] << "InitLyXLookup: Could not set modifiers " - "for this locale." << endl; - return; - } - else - lyxerr[Debug::KEY] << "InitLyXLookup: X locale modifiers are `" - << locmod << '\'' << endl; - - // This part will have to be done for each frame - xim = XOpenIM (display, 0, 0, 0); - if (xim) { - xic = XCreateIC(xim, - XNInputStyle, - XIMPreeditNothing|XIMStatusNothing, - XNClientWindow, window, - XNFocusWindow, window, - 0); - - if (!xic) { - lyxerr[Debug::KEY] << "InitLyXLookup: " - "could not create an input context" << endl; - XCloseIM (xim); - xim = 0; - } - } - else - lyxerr[Debug::KEY] << "InitLyXLookup: could not open " - "an input method." << endl; -} - - -namespace { - -bool isDeadEvent(KeySym keysym) -{ - // Can this be done safely in any other way? - // This is all the dead keys I know of in X11R6.1 - switch (keysym) { -#ifdef XK_dead_grave - case XK_dead_grave: -#endif -#ifdef XK_dead_acute - case XK_dead_acute: -#endif -#ifdef XK_dead_circumflex - case XK_dead_circumflex: -#endif -#ifdef XK_dead_tilde - case XK_dead_tilde: -#endif -#ifdef XK_dead_macron - case XK_dead_macron: -#endif -#ifdef XK_dead_breve - case XK_dead_breve: -#endif -#ifdef XK_dead_abovedot - case XK_dead_abovedot: -#endif -#ifdef XK_dead_diaeresis - case XK_dead_diaeresis: -#endif -#ifdef XK_dead_abovering - case XK_dead_abovering: -#endif -#ifdef XK_dead_doubleacute - case XK_dead_doubleacute: -#endif -#ifdef XK_dead_caron - case XK_dead_caron: -#endif -#ifdef XK_dead_cedilla - case XK_dead_cedilla: -#endif -#ifdef XK_dead_ogonek - case XK_dead_ogonek: -#endif -#ifdef XK_dead_iota - case XK_dead_iota: -#endif -#ifdef XK_dead_voiced_sound - case XK_dead_voiced_sound: -#endif -#ifdef XK_dead_semivoiced_sound - case XK_dead_semivoiced_sound: -#endif -#ifdef XK_dead_belowdot - case XK_dead_belowdot: -#endif - return true; - default: - return false; - } -} - -} // namespace anon - - -// This is called instead of XLookupString() -int LyXLookupString(XEvent * event, - char * buffer_return, int bytes_buffer, - KeySym * keysym_return) -{ - if (event->type != KeyPress) { - lyxerr << "LyXLookupString: wrong event type: " - << event->type << endl; - return 0; - } - - int result = 0; - if (xic) { -#if 1 - // somehow it is necessary to do the lookup. Why? (JMarc) - XLookupString(&event->xkey, buffer_return, - bytes_buffer, keysym_return, - 0); - - if (lyxrc.override_x_deadkeys && - isDeadEvent(*keysym_return)) { - lyxerr[Debug::KEY] - << "LyXLookupString: found DeadEvent" << endl; - return 0; - } -#endif -#if 1 - if (XFilterEvent (event, None)) { - lyxerr[Debug::KEY] <<"XFilterEvent" << endl; - *keysym_return = NoSymbol; - return 0; - } -#endif - Status status_return = 0; - - result = XmbLookupString(xic, &event->xkey, buffer_return, - bytes_buffer, keysym_return, - &status_return); - switch (status_return) { - case XBufferOverflow: - lyxerr[Debug::KEY] << "XBufferOverflow" << endl; - break; - case XLookupBoth: - lyxerr[Debug::KEY] << "XLookupBoth " - << string(buffer_return, result) - << endl; - break; - case XLookupChars: - lyxerr[Debug::KEY] << "XLookupChars " - << string(buffer_return, result) - << endl; - - *keysym_return = NoSymbol; - break; - case XLookupKeySym: - lyxerr[Debug::KEY] << "XLookupKeySym" << endl; - result = 0; - break; - case XLookupNone: - lyxerr[Debug::KEY] << "XLookupNone" << endl; - *keysym_return = NoSymbol; - result = 0; - break; - default: - lyxerr << "Unknown status_return from" - " XmbLookupString" << endl; - break; - } - } else { - result = XLookupString(&event->xkey, buffer_return, - bytes_buffer, keysym_return, - &compose_status); - } - return result; -} - - -// This is called after the main window has been destroyed -void CloseLyXLookup() -{ - if (xic) { - lyxerr[Debug::KEY] << "CloseLyXLookup: destroying input context" - << endl; - XDestroyIC(xic); - xic = 0; - XCloseIM(xim); - } -} - - -#else // We do not have XOpenIM, so we stick with normal XLookupString - -#include -#include - -XComposeStatus compose_status= {0, 0}; - -// This is called after the main LyX window has been created -void InitLyXLookup(Display *, Window) -{ - //Nothing to do. -} - -// This is called instead of XLookupString(). I this particular case, -// this *is* XLookupString... -int LyXLookupString(XEvent * event, - char * buffer_return, int bytes_buffer, - KeySym * keysym_return) -{ - return XLookupString(&event->xkey, buffer_return, - bytes_buffer, keysym_return, - &compose_status); -} - -// This is called after the main window has been destroyed -void CloseLyXLookup() -{ - // Nothing to do -} - -#endif // HAVE_XOPENIM diff --git a/src/lyxlookup.h b/src/lyxlookup.h deleted file mode 100644 index 7eadbdf7b3..0000000000 --- a/src/lyxlookup.h +++ /dev/null @@ -1,31 +0,0 @@ -/* This file is part of -*- C++ -*- -* ====================================================== -* -* LyX, The Document Processor -* -* Copyright 1995 Matthias Ettrich -* Copyright 1995-2001 The LyX Team. -* -* ====================================================== */ - -/* This header file defines wrappers around the X input method related - functions. This should probably be moved into LyXView (to have - different input methods for different frames, but for now we can - keep it as it is. */ -#ifndef LYXLOOKUP_H -#define LYXLOOKUP_H - -#include - -/// Initialize the compose key handling -extern void InitLyXLookup(Display *, Window); - -/// Read a keysym and/or a string (like XLookupString) -extern int LyXLookupString(XEvent * event, - char * buffer_return, int bytes_buffer, - KeySym * keysym_return); - -/// Call this when you destroy your window -extern void CloseLyXLookup(); - -#endif diff --git a/src/lyxscreen.h b/src/lyxscreen.h deleted file mode 100644 index f611e8a6e1..0000000000 --- a/src/lyxscreen.h +++ /dev/null @@ -1,126 +0,0 @@ -// -*- C++ -*- -/* This file is part of - * ====================================================== - * - * LyX, The Document Processor - * - * Copyright 1995 Matthias Ettrich - * Copyright 1995-2001 The LyX Team - * - * ====================================================== */ - -#ifndef LYXSCREEN_H -#define LYXSCREEN_H - -#ifdef __GNUG__ -#pragma interface -#endif - -#include - -class LyXText; -class WorkArea; -class Buffer; -class BufferView; - -struct Row; - -/** 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. - This class also handles the drawing of the cursor and partly the selection. - */ -class LyXScreen { -public: - /// - enum Cursor_Shape { - /// - BAR_SHAPE, - /// - L_SHAPE, - /// - REVERSED_L_SHAPE - }; - - /// - LyXScreen(WorkArea &); - - /// - ~LyXScreen(); - - /// Sets the cursor color to LColor::cursor. - void setCursorColor(); - - /** Draws the screen form textposition y. Uses as much of - the already printed pixmap as possible */ - void draw(LyXText *, BufferView *, unsigned int y); - - /// Redraws the screen, without using existing pixmap - void redraw(LyXText *, BufferView *); - - /// Returns a new top so that the cursor is visible - unsigned int topCursorVisible(LyXText const *); - /// Redraws the screen such that the cursor is visible - bool fitCursor(LyXText *, BufferView *); - /// - void showCursor(LyXText const *, BufferView const *); - /// - void hideCursor(); - /// - void cursorToggle(BufferView *) const; - /// - void showManualCursor(LyXText const *, int x, int y, - int asc, int desc, - Cursor_Shape shape); - /// returns 1 if first has changed, otherwise 0 - bool fitManualCursor(LyXText *, BufferView *, int, int, int, int); - /// - void toggleSelection(LyXText *, BufferView *, bool = true, - int y_offset = 0, int x_offset = 0); - /// - void toggleToggle(LyXText *, BufferView *, - int y_offset = 0, int x_offset = 0); - - /** Updates part of the screen. If text->status is - LyXText::NEED_MORE_REFRESH, we update from the - point of change and to the end of the screen. - If text->status is LyXText::NEED_VERY_LITTLE_REFRESH, - we only update the current row. */ - void update(LyXText *, BufferView *, int y_offset=0, int x_offset=0); - /// - bool forceClear() const { return force_clear; } - - /// - bool cursor_visible; -private: - /// Copies specified area of pixmap to screen - void expose(int x, int y, int exp_width, int exp_height); - - /// y1 and y2 are coordinates of the screen - void drawFromTo(LyXText *, BufferView *, int y1, int y2, - int y_offset = 0, int x_offset = 0, bool internal=false); - - /// y is a coordinate of the text - void drawOneRow(LyXText *, BufferView *, Row * row, - int y_text, int y_offset = 0, int x_offset = 0); - - /// - WorkArea & owner; - - /// - Pixmap cursor_pixmap; - /// - int cursor_pixmap_x; - /// - int cursor_pixmap_y; - /// - int cursor_pixmap_w; - /// - int cursor_pixmap_h; - /// - GC gc_copy; - /// - bool force_clear; -}; - -#endif diff --git a/src/screen.C b/src/screen.C deleted file mode 100644 index 26ab6e7973..0000000000 --- a/src/screen.C +++ /dev/null @@ -1,530 +0,0 @@ -/* This file is part of -* ====================================================== -* -* LyX, The Document Processor -* -* Copyright 1995 Matthias Ettrich -* Copyright 1995-1998 The LyX Team -* -* ====================================================== */ - -#include - -#ifdef __GNUG__ -#pragma implementation "lyxscreen.h" -#endif - -#include - -#include "lyxscreen.h" -#include "lyxtext.h" -#include "lyxrow.h" -#include "frontends/Painter.h" -#include "WorkArea.h" -#include "buffer.h" -#include "BufferView.h" -#include "font.h" -#include "insets/insettext.h" -#include "ColorHandler.h" -#include "language.h" - -using std::max; -using std::min; - -namespace { - -GC createGC() -{ - XGCValues val; - val.foreground = BlackPixel(fl_get_display(), - DefaultScreen(fl_get_display())); - - val.function = GXcopy; - val.graphics_exposures = false; - val.line_style = LineSolid; - val.line_width = 0; - return XCreateGC(fl_get_display(), RootWindow(fl_get_display(), 0), - GCForeground | GCFunction | GCGraphicsExposures - | GCLineWidth | GCLineStyle , &val); -} - -} // namespace anon - - -// Constructor -LyXScreen::LyXScreen(WorkArea & o) - : owner(o), force_clear(true) -{ - // the cursor isnt yet visible - cursor_visible = false; - cursor_pixmap = 0; - cursor_pixmap_x = 0; - cursor_pixmap_y = 0; - cursor_pixmap_w = 0; - cursor_pixmap_h = 0; - - // We need this GC - gc_copy = createGC(); -} - - -LyXScreen::~LyXScreen() -{ - XFreeGC(fl_get_display(), gc_copy); -} - - -void LyXScreen::setCursorColor() -{ - if (!lyxColorHandler.get()) return; - - GC gc = lyxColorHandler->getGCForeground(LColor::cursor); - - XGCValues val; - XGetGCValues(fl_get_display(), - gc, GCForeground, &val); - XChangeGC(fl_get_display(), gc_copy, GCForeground, &val); -} - - -void LyXScreen::redraw(LyXText * text, BufferView * bv) -{ - drawFromTo(text, bv, 0, owner.height(), 0, 0, text == bv->text); - expose(0, 0, owner.workWidth(), owner.height()); - if (cursor_visible) { - cursor_visible = false; - bv->showCursor(); - } -} - - -void LyXScreen::expose(int x, int y, int exp_width, int exp_height) -{ - XCopyArea(fl_get_display(), - owner.getPixmap(), - owner.getWin(), - gc_copy, - x, y, - exp_width, exp_height, - x + owner.xpos(), - y + owner.ypos()); -} - - -void LyXScreen::drawFromTo(LyXText * text, BufferView * bv, - int y1, int y2, int y_offset, int x_offset, - bool internal) -{ - int y_text = text->first_y + y1; - - // get the first needed row - Row * row = text->getRowNearY(y_text); - // y_text is now the real beginning of the row - - int y = y_text - text->first_y; - // y1 is now the real beginning of row on the screen - - while (row != 0 && y < y2) { - LyXText::text_status st = text->status(); - text->getVisibleRow(bv, y + y_offset, - x_offset, row, y + text->first_y); - internal = internal && (st != LyXText::CHANGED_IN_DRAW); - while (internal && text->status() == LyXText::CHANGED_IN_DRAW) { - text->fullRebreak(bv); - st = LyXText::NEED_MORE_REFRESH; - text->setCursor(bv, text->cursor.par(), - text->cursor.pos()); - text->status(bv, st); - // we should be sure our row-pointer is still valid, so it's - // better to recompute it. - y_text = y + text->first_y; - row = text->getRowNearY(y_text); - y = y_text - text->first_y; - text->getVisibleRow(bv, y + y_offset, - x_offset, row, y + text->first_y); - } - y += row->height(); - row = row->next(); - } - force_clear = false; - - // maybe we have to clear the screen at the bottom - if ((y < y2) && text->bv_owner) { - owner.getPainter().fillRectangle(0, y, - owner.workWidth(), - y2 - y, - LColor::bottomarea); - } -} - - -void LyXScreen::drawOneRow(LyXText * text, BufferView * bv, Row * row, - int y_text, int y_offset, int x_offset) -{ - int const y = y_text - text->first_y + y_offset; - - if (((y + row->height()) > 0) && - ((y - row->height()) <= static_cast(owner.height()))) { - // ok there is something visible - text->getVisibleRow(bv, y, x_offset, row, y + text->first_y); - } - force_clear = false; -} - - -/* draws the screen, starting with textposition y. uses as much already - * printed pixels as possible */ -void LyXScreen::draw(LyXText * text, BufferView * bv, unsigned int y) -{ - if (cursor_visible) hideCursor(); - - int const old_first = text->first_y; - bool internal = (text == bv->text); - text->first_y = y; - - // is any optimiziation possible? - if ((y - old_first) < owner.height() - && (old_first - y) < owner.height()) - { - if (text->first_y < old_first) { - drawFromTo(text, bv, 0, - old_first - text->first_y, 0, 0, internal); - XCopyArea (fl_get_display(), - owner.getWin(), - owner.getWin(), - gc_copy, - owner.xpos(), - owner.ypos(), - owner.workWidth(), - owner.height() - old_first + text->first_y, - owner.xpos(), - owner.ypos() + old_first - text->first_y - ); - // expose the area drawn - expose(0, 0, - owner.workWidth(), - old_first - text->first_y); - } else { - drawFromTo(text, bv, - owner.height() + old_first - text->first_y, - owner.height(), 0, 0, internal); - XCopyArea (fl_get_display(), - owner.getWin(), - owner.getWin(), - gc_copy, - owner.xpos(), - owner.ypos() + text->first_y - old_first, - owner.workWidth(), - owner.height() + old_first - text->first_y, - owner.xpos(), - owner.ypos()); - // expose the area drawn - expose(0, owner.height() + old_first - text->first_y, - owner.workWidth(), text->first_y - old_first); - } - } else { - // make a dumb new-draw - drawFromTo(text, bv, 0, owner.height(), 0, 0, internal); - expose(0, 0, owner.workWidth(), owner.height()); - } -} - - -void LyXScreen::showCursor(LyXText const * text, BufferView const * bv) -{ - if (!cursor_visible) { - Cursor_Shape shape = BAR_SHAPE; - if (text->real_current_font.language() != - bv->buffer()->params.language - || text->real_current_font.isVisibleRightToLeft() - != bv->buffer()->params.language->RightToLeft()) - shape = (text->real_current_font.isVisibleRightToLeft()) - ? REVERSED_L_SHAPE : L_SHAPE; - showManualCursor(text, text->cursor.x(), text->cursor.y(), - lyxfont::maxAscent(text->real_current_font), - lyxfont::maxDescent(text->real_current_font), - shape); - } -} - - -/* returns true if first has changed, otherwise false */ -bool LyXScreen::fitManualCursor(LyXText * text, BufferView * bv, - int /*x*/, int y, int asc, int desc) -{ - int newtop = text->first_y; - - if (y + desc - text->first_y >= static_cast(owner.height())) - newtop = y - 3 * owner.height() / 4; // the scroll region must be so big!! - else if (y - asc < text->first_y - && text->first_y > 0) { - newtop = y - owner.height() / 4; - } - - newtop = max(newtop, 0); // can newtop ever be < 0? (Lgb) - - if (newtop != text->first_y) { - draw(text, bv, newtop); - text->first_y = newtop; - return true; - } - return false; -} - - -void LyXScreen::showManualCursor(LyXText const * text, int x, int y, - int asc, int desc, Cursor_Shape shape) -{ - // Update the cursor color. - setCursorColor(); - - int const y1 = max(y - text->first_y - asc, 0); - int const y_tmp = min(y - text->first_y + desc, - static_cast(owner.height())); - - // Secure against very strange situations - int const y2 = max(y_tmp, y1); - - if (cursor_pixmap) { - XFreePixmap(fl_get_display(), cursor_pixmap); - cursor_pixmap = 0; - } - - if (y2 > 0 && y1 < int(owner.height())) { - cursor_pixmap_h = y2 - y1 + 1; - cursor_pixmap_y = y1; - - switch (shape) { - case BAR_SHAPE: - cursor_pixmap_w = 1; - cursor_pixmap_x = x; - break; - case L_SHAPE: - cursor_pixmap_w = cursor_pixmap_h/3; - cursor_pixmap_x = x; - break; - case REVERSED_L_SHAPE: - cursor_pixmap_w = cursor_pixmap_h/3; - cursor_pixmap_x = x - cursor_pixmap_w + 1; - break; - } - - cursor_pixmap = - XCreatePixmap (fl_get_display(), - fl_root, - cursor_pixmap_w, - cursor_pixmap_h, - fl_get_visual_depth()); - XCopyArea (fl_get_display(), - owner.getWin(), - cursor_pixmap, - gc_copy, - owner.xpos() + cursor_pixmap_x, - owner.ypos() + cursor_pixmap_y, - cursor_pixmap_w, - cursor_pixmap_h, - 0, 0); - XDrawLine(fl_get_display(), - owner.getWin(), - gc_copy, - x + owner.xpos(), - y1 + owner.ypos(), - x + owner.xpos(), - y2 + owner.ypos()); - switch (shape) { - case BAR_SHAPE: - break; - case L_SHAPE: - case REVERSED_L_SHAPE: - int const rectangle_h = (cursor_pixmap_h + 10) / 20; - XFillRectangle(fl_get_display(), - owner.getWin(), - gc_copy, - cursor_pixmap_x + owner.xpos(), - y2 - rectangle_h + 1 + owner.ypos(), - cursor_pixmap_w - 1, rectangle_h); - break; - } - - } - cursor_visible = true; -} - - -void LyXScreen::hideCursor() -{ - if (!cursor_visible) return; - - if (cursor_pixmap) { - XCopyArea (fl_get_display(), - cursor_pixmap, - owner.getWin(), - gc_copy, - 0, 0, - cursor_pixmap_w, cursor_pixmap_h, - cursor_pixmap_x + owner.xpos(), - cursor_pixmap_y + owner.ypos()); - } - cursor_visible = false; -} - - -void LyXScreen::cursorToggle(BufferView * bv) const -{ - if (cursor_visible) - bv->hideCursor(); - else - bv->showCursor(); -} - - -/* returns a new top so that the cursor is visible */ -unsigned int LyXScreen::topCursorVisible(LyXText const * text) -{ - int newtop = text->first_y; - - Row * row = text->cursor.row(); - - // Is this a hack? Yes, probably... (Lgb) - if (!row) - return max(newtop, 0); - - if (text->cursor.y() - row->baseline() + row->height() - - text->first_y >= owner.height()) { - if (row->height() < owner.height() - && row->height() > owner.height() / 4) { - newtop = text->cursor.y() - + row->height() - - row->baseline() - owner.height(); - } else { - // scroll down - newtop = text->cursor.y() - - owner.height() / 2; /* the scroll region must be so big!! */ - } - - } else if (static_cast((text->cursor.y()) - row->baseline()) < - text->first_y && text->first_y > 0) { - if (row->height() < owner.height() - && row->height() > owner.height() / 4) { - newtop = text->cursor.y() - row->baseline(); - } else { - // scroll up - newtop = text->cursor.y() - owner.height() / 2; - newtop = min(newtop, text->first_y); - } - } - - newtop = max(newtop, 0); - - return newtop; -} - - -/* scrolls the screen so that the cursor is visible, if necessary. -* returns true if a change was made, otherwise false */ -bool LyXScreen::fitCursor(LyXText * text, BufferView * bv) -{ - // Is a change necessary? - int const newtop = topCursorVisible(text); - bool const result = (newtop != text->first_y); - if (result) - draw(text, bv, newtop); - return result; -} - - -void LyXScreen::update(LyXText * text, BufferView * bv, - int y_offset, int x_offset) -{ - switch (text->status()) { - case LyXText::NEED_MORE_REFRESH: - { - int const y = max(int(text->refresh_y - text->first_y), 0); - drawFromTo(text, bv, y, owner.height(), y_offset, x_offset); - text->refresh_y = 0; - // otherwise this is called ONLY from BufferView_pimpl(update) - // or we should see to set this flag accordingly - if (text != bv->text) - text->status(bv, LyXText::UNCHANGED); - expose(0, y, owner.workWidth(), owner.height() - y); - } - break; - case LyXText::NEED_VERY_LITTLE_REFRESH: - { - // ok I will update the current cursor row - drawOneRow(text, bv, text->refresh_row, text->refresh_y, - y_offset, x_offset); - // this because if we had a major update the refresh_row could - // have been set to 0! - if (text->refresh_row) { - // otherwise this is called ONLY from BufferView_pimpl(update) - // or we should see to set this flag accordingly - if (text != bv->text) - text->status(bv, LyXText::UNCHANGED); - expose(0, text->refresh_y - text->first_y + y_offset, - owner.workWidth(), text->refresh_row->height()); - } - } - break; - case LyXText::CHANGED_IN_DRAW: // just to remove the warning - case LyXText::UNCHANGED: - // Nothing needs done - break; - } -} - - -void LyXScreen::toggleSelection(LyXText * text, BufferView * bv, - bool kill_selection, - int y_offset, int x_offset) -{ - // only if there is a selection - if (!text->selection.set()) return; - - int const bottom = min( - max(static_cast(text->selection.end.y() - - text->selection.end.row()->baseline() - + text->selection.end.row()->height()), - text->first_y), - static_cast(text->first_y + owner.height())); - int const top = min( - max(static_cast(text->selection.start.y() - - text->selection.start.row()->baseline()), - text->first_y), - static_cast(text->first_y + owner.height())); - - if (kill_selection) - text->selection.set(false); - drawFromTo(text, bv, top - text->first_y, bottom - text->first_y, - y_offset, x_offset); - expose(0, top - text->first_y, - owner.workWidth(), - bottom - text->first_y - (top - text->first_y)); -} - - -void LyXScreen::toggleToggle(LyXText * text, BufferView * bv, - int y_offset, int x_offset) -{ - if (text->toggle_cursor.par() == text->toggle_end_cursor.par() - && text->toggle_cursor.pos() == text->toggle_end_cursor.pos()) - return; - - int const top_tmp = text->toggle_cursor.y() - - text->toggle_cursor.row()->baseline(); - int const bottom_tmp = text->toggle_end_cursor.y() - - text->toggle_end_cursor.row()->baseline() - + text->toggle_end_cursor.row()->height(); - - int const offset = y_offset < 0 ? y_offset : 0; - int const bottom = min(max(bottom_tmp, text->first_y), - static_cast(text->first_y + owner.height()))-offset; - int const top = min(max(top_tmp, text->first_y), - static_cast(text->first_y + owner.height()))-offset; - - drawFromTo(text, bv, top - text->first_y, - bottom - text->first_y, y_offset, - x_offset); - expose(0, top - text->first_y, owner.workWidth(), - bottom - text->first_y - (top - text->first_y)); -} diff --git a/src/text.C b/src/text.C index 1b28196ab0..e376fff0af 100644 --- a/src/text.C +++ b/src/text.C @@ -21,10 +21,10 @@ #include "lyxrc.h" #include "frontends/LyXView.h" #include "frontends/Painter.h" +#include "frontends/screen.h" #include "tracer.h" #include "font.h" #include "encoding.h" -#include "lyxscreen.h" #include "bufferview_funcs.h" #include "BufferView.h" #include "language.h"