home *** CD-ROM | disk | FTP | other *** search
/ Dream 52 / Amiga_Dream_52.iso / Linux / Divers / lyx-0.13.2.tar.gz / lyx-0.13.2.tar / lyx-0.13.2 / src / screen.C < prev    next >
C/C++ Source or Header  |  1998-04-23  |  13KB  |  607 lines

  1. /* This file is part of
  2. * ======================================================
  3. *           LyX, The Document Processor
  4. *      
  5. *        Copyright (C) 1995 Matthias Ettrich
  6. *           Copyright (C) 1995-1998 The LyX Team
  7. *
  8. *======================================================*/
  9.  
  10. #include <config.h>
  11.  
  12. #ifdef __GNUG__
  13. #pragma implementation "lyxscreen.h"
  14. #endif
  15.  
  16. #include "lyxscreen.h"
  17. #include "lyxdraw.h"
  18. #include "lyxtext.h"
  19.  
  20. //     $Id: screen.C,v 1.1.1.1 1998/04/23 16:02:54 larsbj Exp $    
  21.  
  22. #if !defined(lint) && !defined(WITH_WARNINGS)
  23. static char vcid[] = "$Id: screen.C,v 1.1.1.1 1998/04/23 16:02:54 larsbj Exp $";
  24. #endif /* lint */
  25.  
  26. // Constructor
  27. LyXScreen::LyXScreen(Window window,
  28.              Dimension width, 
  29.              Dimension height,
  30.              Dimension offset_x,
  31.              Dimension offset_y,
  32.              LyXText *text_ptr)
  33.     : text(text_ptr),_window(window), 
  34.       _width(width),_height(height),
  35.       _offset_x(offset_x), _offset_y(offset_y)
  36. {
  37.     first = 0;
  38.    
  39.     /* the cursor isnt yet visible */ 
  40.     cursor_visible = false;
  41.     screen_refresh_y = -1;
  42.  
  43.     /* create the foreground pixmap */
  44.     foreground = XCreatePixmap (fl_display,
  45.                     RootWindow(fl_display, 0),
  46.                     _width, _height, 
  47.                     fl_get_visual_depth());
  48.     cursor_pixmap = 0;
  49.     cursor_pixmap_x = 0;
  50.     cursor_pixmap_y = 0;
  51.     cursor_pixmap_w = 0;
  52.     cursor_pixmap_h = 0;
  53. }
  54.  
  55.  
  56. // Destructor
  57. LyXScreen::~LyXScreen()
  58. {
  59.     XFreePixmap(fl_display, foreground);
  60. }
  61.  
  62.  
  63. void LyXScreen::Redraw()
  64. {
  65.     DrawFromTo(0, _height);
  66.     screen_refresh_y = -1;
  67.     expose(0, 0, _width, _height);
  68.     if (cursor_visible) {
  69.         cursor_visible = false;
  70.         ShowCursor();
  71.     }
  72. }
  73.  
  74.  
  75. void LyXScreen::expose(int x, int y, int exp_width, int exp_height)
  76. {
  77.     XCopyArea(fl_display,
  78.           foreground,
  79.           _window,
  80.           getGC(gc_copy),
  81.           x, y,
  82.           exp_width, exp_height,
  83.           x+_offset_x, y+_offset_y);
  84. }
  85.  
  86.  
  87. void LyXScreen::DrawFromTo(int y1, int y2)
  88. {
  89.     Row* row = 0;
  90.     long  y_text = 0;
  91.     long y = 0;
  92.     
  93.     y_text = first + y1;
  94.    
  95.     /* get the first needed row */ 
  96.     row = text->GetRowNearY(y_text);
  97.     /* y_text is now the real beginning of the row */
  98.    
  99.     y = y_text - first;
  100.     /* y1 is now the real beginning of row on the screen */
  101.     
  102.     while (row != NULL && y < y2) {
  103.  
  104.         text->GetVisibleRow(*this, y, row, y + first);
  105.         y += row->height;
  106.         row = row -> next;
  107.  
  108.     }
  109.    
  110.     /* maybe we have to clear the screen at the bottom */ 
  111.     if (y < y2) {
  112.         fillRectangle(gc_lighted,
  113.                   0,
  114.                   y,
  115.                   _width,
  116.                   y2 - y);
  117.     }
  118. }
  119.  
  120.  
  121. void LyXScreen::DrawOneRow(Row *row, long &y_text)
  122. {
  123.     long y = 0;
  124.    
  125.     y = y_text - first;
  126.       
  127.     if (y + row->height > 0 && y - row->height <= _height) {
  128.         /* ok there is something visible */
  129.         text->GetVisibleRow(*this, y, row, y + first);
  130.     }
  131.     y_text+=row->height;
  132. }
  133.  
  134.  
  135. /* draws the screen, starting with textposition y. uses as much already
  136. * printed pixels as possible */
  137. void LyXScreen::Draw(long  y)
  138. {
  139.     if (cursor_visible) HideCursor();
  140.  
  141.     if (y<0) y = 0;
  142.     long old_first = first;
  143.     first = y;
  144.  
  145.     /* is any optimiziation possible? */ 
  146.     if ((y - old_first) < _height 
  147.         && (old_first - y) < _height) {
  148.         if (first < old_first) {
  149.             DrawFromTo(0, old_first - first);
  150.             XCopyArea (fl_display,
  151.                    _window,
  152.                    _window,
  153.                    getGC(gc_copy),
  154.                    _offset_x, _offset_y, 
  155.                    _width , _height - old_first + first,
  156.                    _offset_x, _offset_y + old_first - first);
  157.             // expose the area drawn
  158.             expose(0, 0, _width, old_first - first);
  159.         } else  {
  160.             DrawFromTo(_height + old_first - first, _height);
  161.             XCopyArea (fl_display,
  162.                    _window,
  163.                    _window,
  164.                    getGC(gc_copy),
  165.                    _offset_x, _offset_y + first - old_first, 
  166.                    _width , _height + old_first - first, 
  167.                    _offset_x, _offset_y);
  168.             // expose the area drawn
  169.             expose(0, _height + old_first - first, 
  170.                    _width, first - old_first);
  171.         }
  172.     } else {
  173.         /* make a dumb new-draw */ 
  174.         DrawFromTo(0, _height);
  175.         expose(0, 0, _width, _height);
  176.     }
  177. }
  178.  
  179.  
  180. void LyXScreen::ShowCursor()
  181. {
  182.     long x = 0;
  183.     long y1 = 0;
  184.     long y2 = 0;
  185.    
  186.     if (cursor_visible) return;
  187.    
  188.     x = text->cursor.x;
  189.     
  190.     y1 = text->cursor.y - text->real_current_font.maxAscent() - first;
  191.     if (y1 < 0) y1 = 0;
  192.     
  193.     y2 = text->cursor.y + text->real_current_font.maxDescent() - first;
  194.     if (y2 > _height) y2 = _height;
  195.  
  196.     // Secure against very strange situations
  197.     if (y2 < y1) y2 = y1;
  198.  
  199.     if (cursor_pixmap){
  200.         XFreePixmap(fl_display, cursor_pixmap);
  201.         cursor_pixmap = 0;
  202.     }
  203.     
  204.     if (y2 > 0 && y1 < _height) {
  205.         cursor_pixmap_w = 1;
  206.         cursor_pixmap_h = y2 - y1 + 1;
  207.         cursor_pixmap_x = x;
  208.         cursor_pixmap_y = y1;
  209.         cursor_pixmap =
  210.             XCreatePixmap(fl_display,
  211.                       RootWindow(fl_display, 0),
  212.                       cursor_pixmap_w,
  213.                       cursor_pixmap_h,
  214.                       fl_get_visual_depth());
  215.         XCopyArea(fl_display,
  216.               _window,
  217.               cursor_pixmap,
  218.               getGC(gc_copy),
  219.               _offset_x + cursor_pixmap_x, 
  220.               _offset_y + cursor_pixmap_y,
  221.               cursor_pixmap_w, cursor_pixmap_h,
  222.               0, 0);
  223.         XDrawLine(fl_display,
  224.               _window, getGC(gc_copy),
  225.               x + _offset_x,
  226.               y1 + _offset_y,
  227.               x + _offset_x,
  228.               y2 + _offset_y); 
  229.         cursor_visible = true;
  230.     }
  231. }
  232.  
  233.  
  234. /* returns 1 if first has changed, otherwise 0 */ 
  235. int LyXScreen::FitManualCursor(long /*x*/, long y, int asc, int desc)
  236. {
  237.     long  newtop = first;
  238.   
  239.     if (y + desc  - first >= _height)
  240.         newtop = y - 3*_height / 4;   /* the scroll region must be so big!! */
  241.     else if (y - asc < first 
  242.          && first > 0) {
  243.         newtop = y - _height / 4;
  244.     }
  245.     if (newtop < 0)
  246.         newtop = 0;
  247.   
  248.     if (newtop != first){
  249.         Draw(newtop);
  250.         first = newtop;
  251.         return 1;
  252.     }
  253.     return 0;
  254. }
  255.  
  256.  
  257. void  LyXScreen::HideManualCursor(long /*x*/, long /*y*/,
  258.                   int /*asc*/, int /*desc*/)
  259. {
  260.     HideCursor();
  261. }
  262.  
  263.  
  264. void  LyXScreen::ShowManualCursor(long x, long y, int asc, int desc)
  265. {
  266.     long y1 = 0;
  267.     long y2 = 0;
  268.     
  269.     y1 = y - first - asc;
  270.     if (y1 < 0)
  271.         y1 =0;
  272.     y2 = y -first + desc;
  273.     if (y2 > _height)
  274.         y2 = _height;
  275.     
  276.     if (cursor_pixmap){
  277.         XFreePixmap(fl_display, cursor_pixmap);
  278.         cursor_pixmap = 0;
  279.     }
  280.     
  281.     if (y2 > 0 && y1 < _height) {
  282.         cursor_pixmap_w = 1;
  283.         cursor_pixmap_h = y2 - y1 + 1;
  284.         cursor_pixmap_x = x,
  285.             cursor_pixmap_y = y1;
  286.         cursor_pixmap =
  287.             XCreatePixmap (fl_display,
  288.                        RootWindow(fl_display, 0),
  289.                        cursor_pixmap_w,
  290.                        cursor_pixmap_h,
  291.                        fl_get_visual_depth());
  292.         
  293.         XCopyArea (fl_display,
  294.                _window,
  295.                cursor_pixmap,
  296.                getGC(gc_copy),
  297.                _offset_x + cursor_pixmap_x,
  298.                _offset_y + cursor_pixmap_y,
  299.                cursor_pixmap_w,
  300.                cursor_pixmap_h,
  301.                0, 0);
  302.         XDrawLine(fl_display,
  303.               _window, getGC(gc_copy),
  304.               x+_offset_x,
  305.               y1+_offset_y,
  306.               x+_offset_x,
  307.               y2+_offset_y);            
  308.     }
  309.     cursor_visible = true;
  310. }
  311.  
  312.  
  313. void LyXScreen::HideCursor()
  314. {
  315.     if (!cursor_visible) return;
  316.     
  317.     if (cursor_pixmap){
  318.         XCopyArea (fl_display, 
  319.                cursor_pixmap,
  320.                _window,
  321.                getGC(gc_copy),
  322.                0, 0, 
  323.                cursor_pixmap_w, cursor_pixmap_h,
  324.                cursor_pixmap_x + _offset_x,
  325.                cursor_pixmap_y + _offset_y);
  326.     }
  327.     cursor_visible = false;
  328. }
  329.  
  330.  
  331. void LyXScreen::CursorToggle()
  332. {
  333.     if (cursor_visible)
  334.         HideCursor();
  335.     else
  336.         ShowCursor();
  337. }
  338.  
  339.  
  340. /* returns a new top so that the cursor is visible */ 
  341. long LyXScreen::TopCursorVisible()
  342. {
  343.     long  newtop = first;
  344.  
  345.     if (text->cursor.y
  346.         - text->cursor.row->baseline
  347.         + text->cursor.row->height
  348.         - first >= _height) {
  349.         if (text->cursor.row->height < _height
  350.             && text->cursor.row->height > _height/4)
  351.             newtop = text->cursor.y
  352.                 + text->cursor.row->height
  353.                 - text->cursor.row->baseline - _height;
  354.         else
  355.             newtop = text->cursor.y
  356.                 - 3*_height / 4;   /* the scroll region must be so big!! */
  357.     } else if (text->cursor.y - text->cursor.row->baseline < first 
  358.            && first > 0) {
  359.         if (text->cursor.row->height < _height
  360.             && text->cursor.row->height > _height/4)
  361.             newtop = text->cursor.y - text->cursor.row->baseline;
  362.         else {
  363.             newtop = text->cursor.y - _height / 4;
  364.             if (newtop > first)
  365.                 newtop = first;
  366.         }
  367.     }
  368.     if (newtop < 0)
  369.         newtop = 0;
  370.     
  371.     return newtop;
  372. }
  373.  
  374.  
  375. /* scrolls the screen so that the cursor is visible, if necessary.
  376. * returns 1 if a change was made, otherwise 0 */ 
  377. int LyXScreen::FitCursor()
  378. {
  379.     /* is a change necessary */ 
  380.     long  newtop = TopCursorVisible();
  381.     int result = (newtop != first);
  382.     if (result)
  383.         Draw(newtop);
  384.     return result;
  385. }
  386.  
  387.    
  388. void LyXScreen::Update()
  389. {
  390.     long y = 0;
  391.  
  392.     if (text->status == LyXText::NEED_MORE_REFRESH
  393.         || screen_refresh_y > -1 ) {
  394.         if (screen_refresh_y > -1
  395.             && screen_refresh_y < text->refresh_y)
  396.             y = screen_refresh_y;
  397.         else
  398.             y = text->refresh_y;
  399.         
  400.         if (y < first) y = first;
  401.         
  402.         DrawFromTo(y - first, _height);
  403.         text->refresh_y = 0;
  404.         text->status = LyXText::UNCHANGED;
  405.         screen_refresh_y = -1;
  406.         expose(0, y-first, _width, _height - (y - first));
  407.     } else if (text->status == LyXText::NEED_VERY_LITTLE_REFRESH) {
  408.         /* ok I will update the current cursor row */
  409.         y = text->refresh_y;
  410.         DrawOneRow(text->refresh_row, y);
  411.         text->status = LyXText::UNCHANGED;
  412.         expose(0, text->refresh_y-first,
  413.              _width, text->refresh_row->height);
  414.     }
  415. }
  416.  
  417.  
  418. void LyXScreen::SmallUpdate()
  419. {
  420.     Row *row = 0;
  421.     long y = 0;
  422.     long y2 = 0;
  423.     
  424.     if (text->status == LyXText::NEED_MORE_REFRESH){
  425.         /* ok I will update till the current cursor row */
  426.         row = text->refresh_row;
  427.         y = text->refresh_y;
  428.         y2 = y;
  429.       
  430.         if (y > text->cursor.y) {
  431.             Update();
  432.             return;
  433.         }
  434.      
  435.         while (row && row != text->cursor.row && y < first + _height) {
  436.             DrawOneRow(row, y);
  437.             row = row->next;
  438.         }
  439.       
  440.         DrawOneRow(row, y);
  441.         screen_refresh_y = y;
  442.         screen_refresh_row = row->next;
  443.         text->status = LyXText::UNCHANGED;
  444.         // Is the right regin exposed?
  445.         expose(0, y2-first, _width, y-y2);
  446.     } else if (text->status == LyXText::NEED_VERY_LITTLE_REFRESH) {
  447.         /* ok I will update the current cursor row */
  448.         row = text->refresh_row;
  449.         y = text->refresh_y;
  450.         DrawOneRow(row, y);
  451.         text->status = LyXText::UNCHANGED;
  452.         expose(0, text->refresh_y - first,
  453.                _width, row->height);
  454.     }
  455. }
  456.  
  457.  
  458. void LyXScreen::ToggleSelection(bool kill_selection)
  459. {
  460.     long top = 0;
  461.     long bottom = 0;
  462.    
  463.     /* only if there is a selection */ 
  464.     if (!text->selection)
  465.         return;
  466.     
  467.     top = text->sel_start_cursor.y
  468.         - text->sel_start_cursor.row->baseline;
  469.     bottom = text->sel_end_cursor.y
  470.         - text->sel_end_cursor.row->baseline 
  471.         + text->sel_end_cursor.row->height;
  472.     
  473.     if (top - first < 0)
  474.         top = first;
  475.     if (bottom - first < 0)
  476.         bottom = first;
  477.     
  478.     if (bottom - first > _height)
  479.         bottom = first + _height;
  480.     if (top - first > _height)
  481.         top = first + _height;
  482.     
  483.     if (kill_selection)
  484.         text->selection = 0;
  485.     DrawFromTo(top - first, bottom - first);
  486.     expose(0, top - first, _width, bottom - first - (top - first));
  487. }
  488.   
  489.    
  490. void LyXScreen::ToggleToggle()
  491. {
  492.     long top = 0;
  493.     long bottom = 0;
  494.     
  495.     if (text->toggle_cursor.par == text->toggle_end_cursor.par
  496.         && text->toggle_cursor.pos == text->toggle_end_cursor.pos)
  497.         return;
  498.  
  499.     top = text->toggle_cursor.y
  500.         - text->toggle_cursor.row->baseline;
  501.     bottom = text->toggle_end_cursor.y
  502.         - text->toggle_end_cursor.row->baseline 
  503.         + text->toggle_end_cursor.row->height;
  504.     
  505.     if (top - first < 0)
  506.         top = first;
  507.     if (bottom - first < 0)
  508.         bottom = first;
  509.     
  510.     if (bottom - first > _height)
  511.         bottom = first + _height;
  512.     if (top - first > _height)
  513.         top = first + _height;
  514.     
  515.     DrawFromTo(top - first, bottom - first);
  516.     expose(0, top - first, _width, bottom - first - (top - first));
  517. }
  518.  
  519.  
  520.     
  521. void LyXScreen::drawTableLine(int baseline, int x, int length, bool on_off)
  522. {
  523.     GC gc;
  524.     if (on_off)
  525.         gc = getGC(gc_thin_on_off_line);
  526.     else
  527.         gc = getGC(gc_copy);
  528.     drawLine(gc,
  529.          x,
  530.          baseline,
  531.          x + length,
  532.          baseline);
  533. }
  534.  
  535.     
  536. void LyXScreen::drawVerticalTableLine(int x, int y1, int y2, bool on_off)
  537. {
  538.     GC gc;
  539.     if (on_off)
  540.         gc = getGC(gc_thin_on_off_line);
  541.     else
  542.         gc = getGC(gc_copy);
  543.     drawLine(gc,
  544.          x,
  545.          y1,
  546.          x,
  547.          y2);
  548. }
  549.  
  550.  
  551. void LyXScreen::drawFrame(int /*ft*/, int x, int y, int w, int h,
  552.               FL_COLOR /*col*/, int /*b*/)
  553. {
  554. // Everything works now isn't it?    
  555. // #ifdef WITH_WARNINGS
  556. // #warning Implement this using X11 calls, and the repaint problems are gone!
  557. // #endif
  558. // At least, I think that should do it since we only have them after
  559. // one of these buttons are displayed now! Lars, it seems you've hit the
  560. // nail :-) (Asger)
  561. //    fl_winset(foreground);
  562. //    fl_drw_frame(ft, x,  y,  w,  h, col, b);
  563.     // This should be changed to draw a button like frame, in the
  564.     // mean time we'll just use a regular rectangle
  565.      
  566.          // I want the buttons back before 0.12. OK, this is very simple,
  567.          // like what is done in xforms sources.  (Ale)
  568.  
  569.     // This one is too dirty. Get rid of it.
  570.     extern GC fl_gc;
  571.  
  572.     // Please comment this anonymous variable.
  573.     int d = 2;
  574.  
  575.     // I think these calls to fl_color might make xforms sometimes
  576.     // draw the wrong color on other objects.
  577.     fl_color(FL_TOP_BCOL);
  578.     XFillRectangle(fl_display, foreground, fl_gc,x-d,y-d,w+2*d,d);
  579.     fl_color(FL_BOTTOM_BCOL);
  580.     XFillRectangle(fl_display, foreground, fl_gc,x-d,y+h,w+2*d,d);
  581.  
  582.     // Now a couple of trapezoids
  583.     XPoint pl[4], pr[4]; 
  584.  
  585.     pl[0].x = x-d;   pl[0].y = y-d;
  586.     pl[1].x = x-d;   pl[1].y = y+h+d;
  587.     pl[2].x = x;     pl[2].y = y+h;
  588.     pl[3].x = x;     pl[3].y = y;
  589.     
  590.     pr[0].x = x+w+d; pr[0].y = y-d;
  591.     pr[1].x = x+w+d; pr[1].y = y+h+d;
  592.     pr[2].x = x+w;   pr[2].y = y+h;
  593.     pr[3].x = x+w;   pr[3].y = y;
  594.     
  595.     fl_color(FL_LEFT_BCOL);
  596.     XFillPolygon(fl_display,
  597.              foreground,
  598.              fl_gc, pl, 4,
  599.              Convex, CoordModeOrigin); 
  600.     fl_color(FL_RIGHT_BCOL);
  601.     XFillPolygon(fl_display,
  602.              foreground,
  603.              fl_gc, pr, 4,
  604.              Convex, CoordModeOrigin); 
  605. }
  606.