1 // daemon/Screen.hh
2 // This file is part of AnyTerm; see http://anyterm.org/
3 // (C) 2006-2007 Philip Endecott
4 
5 // This program is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation; either version 2 of the License, or
8 // any later version.
9 //
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 // GNU General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License
16 // along with this program; if not, write to the Free Software
17 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 
19 #ifndef Screen_hh
20 #define Screen_hh
21 
22 #include <vector>
23 #include <algorithm>
24 
25 #include "Cell.hh"
26 
27 
28 class Screen {
29   int rows_;
30   int cols_;
31   int scrollback_;
32   typedef std::vector<Cell> row_t;
33   typedef std::vector<row_t*> cells_t;
34   cells_t cells;
35   unsigned int wrap;
36 
37 public:
Screen(int rows,int cols,int scrollback=0)38   Screen(int rows, int cols, int scrollback=0):
39     rows_(rows), cols_(cols), scrollback_(scrollback),
40     wrap(0),
41     cursor_row(0), cursor_col(0), cursor_visible(true)
42   {
43     for (int r=0; r<scrollback; ++r) {
44       cells.push_back(new row_t(cols));  // leaks if it throws
45     }
46     for (int r=0; r<rows; ++r) {
47       cells.push_back(new row_t(cols));  // leaks if it throws
48     }
49   }
50 
~Screen()51   ~Screen() {
52     for (cells_t::iterator i = cells.begin();
53          i != cells.end(); ++i) {
54       delete *i;
55     }
56   }
57 
rows() const58   int rows() const {
59     return rows_;
60   }
61 
cols() const62   int cols() const {
63     return cols_;
64   }
65 
scrollback() const66   int scrollback() const {
67     return scrollback_;
68   }
69 
operator ()(int r,int c)70   Cell& operator()(int r, int c)
71   {
72     return (*cells[row_idx(r)])[c];
73   }
74 
operator ()(int r,int c) const75   const Cell& operator()(int r, int c) const
76   {
77     return (*cells[row_idx(r)])[c];
78   }
79 
scroll_down(int top,int bottom,int n=1)80   void scroll_down(int top, int bottom, int n=1)
81   {
82     // If we're asked to scroll the whole visible screen down, we scroll
83     // into the scrollback region.  Otherwise, the scrollback region is
84     // not changed.
85     if (top==0 && bottom==rows()-1) {
86       wrap = (wrap+n)%(rows()+scrollback());
87     } else {
88       normalise_wrap();
89       std::rotate(cells.begin()+scrollback()+top, cells.begin()+scrollback()+top+n,
90                   cells.begin()+scrollback()+bottom+1);
91     }
92     for (int r=bottom+1-n; r<=bottom; ++r) {
93       clear_row(r);
94     }
95   }
96 
scroll_up(int top,int bottom,int n=1)97   void scroll_up(int top, int bottom, int n=1)
98   {
99     // Never touch the scrollback region.
100     if (scrollback()==0 && top==0 && bottom==rows()-1) {
101       wrap = (wrap-n)%(rows()+scrollback());
102     } else {
103       normalise_wrap();
104       std::rotate(cells.begin()+scrollback()+top, cells.begin()+scrollback()+bottom+1-n,
105                   cells.begin()+scrollback()+bottom+1);
106     }
107     for (int r=top; r<top+n; ++r) {
108       clear_row(r);
109     }
110   }
111 
112   int cursor_row;
113   int cursor_col;
114   bool cursor_visible;
115 
116 
117 private:
row_idx(int r) const118   int row_idx(int r) const {
119     return (r+scrollback()+wrap)%(rows()+scrollback());
120   }
121 
clear_row(int r)122   void clear_row(int r) {
123     row_t& row = *(cells[row_idx(r)]);
124     for (int c=0; c<cols(); ++c) {
125       row[c] = Cell();   // FIXME this should probably use the terminal's current attributes
126                          // (e.g. background colour)
127     }
128   }
129 
normalise_wrap()130   void normalise_wrap() {
131     if (wrap==0) {
132       return;
133     }
134     std::rotate(cells.begin(), cells.begin()+wrap, cells.end());
135     wrap=0;
136   }
137 };
138 
139 
140 #endif
141