Fixed the terminal not fully functional error
[utio.git] / gc.cc
blob2098d2e3cea5e8263ad6362a1e3958346c346da0
1 // This file is part of the utio library, a terminal I/O library.
2 //
3 // Copyright (C) 2004 by Mike Sharov <msharov@users.sourceforge.net>
4 // This file is free software, distributed under the MIT License.
5 //
6 // gc.cc
7 //
9 #include "gc.h"
10 #include "ti.h"
12 namespace utio {
14 //----------------------------------------------------------------------
16 CGC::CGC (void)
17 : m_Canvas (),
18 m_Template (),
19 m_Size (0, 0),
20 m_TabSize (8)
24 void CGC::Resize (Size2d sz)
26 fill (m_Size, 0);
27 m_Canvas.clear();
28 m_Canvas.resize (sz[0] * sz[1]);
29 m_Size = sz;
32 inline CGC::canvas_t::iterator CGC::CanvasAt (Point2d p)
34 return (m_Canvas.begin() + p[1] * m_Size[0] + p[0]);
37 inline CGC::canvas_t::const_iterator CGC::CanvasAt (Point2d p) const
39 return (m_Canvas.begin() + p[1] * m_Size[0] + p[0]);
42 /// Clears the canvas with spaces with current attributes.
43 void CGC::Clear (wchar_t c)
45 const CCharCell vlc (c, m_Template);
46 fill (m_Canvas, vlc);
49 /// Draws a line art box.
50 void CGC::Box (Rect r)
52 Clip (r);
53 if ((r.Width() < 2) | (r.Height() < 2))
54 return;
55 r[1] -= 1;
56 Point2d trCorner (r[1][0], r[0][1]);
57 Point2d blCorner (r[0][0], r[1][1]);
58 const Rect rr (trCorner, blCorner);
59 HLine (r[0], r.Width());
60 HLine (rr[1], r.Width());
61 VLine (r[0], r.Height());
62 VLine (rr[0], r.Height());
63 *CanvasAt(rr[0]) = CCharCell (acsv_UpperRightCorner, m_Template);
64 *CanvasAt(rr[1]) = CCharCell (acsv_LowerLeftCorner, m_Template);
65 *CanvasAt(r[1]) = CCharCell (acsv_LowerRightCorner, m_Template);
66 *CanvasAt(r[0]) = CCharCell (acsv_UpperLeftCorner, m_Template);
69 /// Draws a box with character \p c as the border.
70 void CGC::Bar (Rect r, wchar_t c)
72 Clip (r);
73 const CCharCell vlc (c, m_Template);
74 for (dim_t y = 0; y < r.Height(); ++ y)
75 fill_n (CanvasAt (Point2d (r[0][0], r[0][1] + y)), r.Width(), vlc);
78 /// Draws a horizontal line from \p p of length \p l.
79 void CGC::HLine (Point2d p, dim_t l)
81 if (!Clip (p))
82 return;
83 if (coord_t(l) > m_Size[0] - p[0])
84 l = m_Size[0] - p[0];
85 const CCharCell vlc (acsv_HLine, m_Template);
86 fill_n (CanvasAt(p), l, vlc);
89 /// Draws a vertical line from \p p of length \p l.
90 void CGC::VLine (Point2d p, dim_t l)
92 if (!Clip (p))
93 return;
94 if (coord_t(l) > m_Size[1] - p[1])
95 l = m_Size[1] - p[1];
96 const CCharCell vlc (acsv_VLine, m_Template);
97 for (dim_t i = 0; i < l; ++ i)
98 *CanvasAt (Point2d (p[0], p[1] + i)) = vlc;
101 /// Copies canvas data from \p r into \p cells.
102 void CGC::GetImage (Rect r, canvas_t& cells) const
104 const size_t inyskip = Width() - r.Width();
105 Clip (r);
106 cells.resize (r.Width() * r.Height());
107 canvas_t::iterator dout (cells.begin());
108 canvas_t::const_iterator din (CanvasAt (r[0]));
109 for (dim_t y = 0; y < r.Height(); ++ y, din += inyskip)
110 for (dim_t x = 0; x < r.Width(); ++ x, ++ din, ++ dout)
111 if (din->m_Char)
112 *dout = *din;
115 /// Copies canvas data from \p cells into \p r.
116 void CGC::Image (Rect r, const canvas_t& cells)
118 const size_t outyskip = Width() - r.Width();
119 Clip (r);
120 canvas_t::const_iterator din (cells.begin());
121 canvas_t::iterator dout (CanvasAt (r[0]));
122 for (dim_t y = 0; y < r.Height(); ++ y, dout += outyskip)
123 for (dim_t x = 0; x < r.Width(); ++ x, ++ din, ++ dout)
124 if (din->m_Char)
125 *dout = *din;
128 /// Zeroes out cells which are identical to those in \p src.
129 bool CGC::MakeDiffFrom (const CGC& src)
131 assert (src.Canvas().size() == m_Canvas.size() && "Diffs can only be made on equally sized canvasses");
132 register canvas_t::pointer inew (Canvas().begin());
133 register canvas_t::const_pointer iold (src.Canvas().begin());
134 const canvas_t::const_pointer iend (src.Canvas().end());
135 const CCharCell nullCell (0, color_Preserve, color_Preserve, 0);
136 bool bHaveChanges = false;
137 for (; iold < iend; ++iold, ++inew) {
138 const bool bSameCell (*iold == *inew);
139 if (bSameCell)
140 *inew = nullCell;
141 bHaveChanges |= !bSameCell;
143 return (bHaveChanges);
146 /// Prints character \p c.
147 void CGC::Char (Point2d p, wchar_t c)
149 if (Clip (p))
150 *CanvasAt(p) = CCharCell (c, m_Template);
153 /// Prints string \p str at \p p.
154 void CGC::Text (Point2d p, const string& str)
156 if (!Clip (p))
157 return;
158 const canvas_t::iterator doutstart (CanvasAt (p));
159 const canvas_t::iterator doutend = doutstart + (m_Size[0] - p[0]);
160 assert (doutend >= doutstart);
161 canvas_t::iterator dout (doutstart);
162 for (string::utf8_iterator si = str.utf8_begin(); (si < str.utf8_end()) & (dout < doutend); ++si) {
163 if (*si == '\t') {
164 const size_t absX = p[0] + distance (doutstart, dout);
165 size_t toTab = Align (absX + 1, m_TabSize) - absX;
166 toTab = min (toTab, size_t(distance (dout, doutend)));
167 dout = fill_n (dout, toTab, CCharCell (' ', m_Template));
168 } else
169 *dout++ = CCharCell (*si, m_Template);
173 static const CGC::Point2d c_ZeroPoint (0, 0);
175 /// Clips point \p pt to the canvas size.
176 bool CGC::Clip (Point2d& pt) const
178 const Point2d oldPoint (pt);
179 Point2d bottomright (m_Size);
180 bottomright -= 1;
181 simd::pmax (c_ZeroPoint, pt);
182 simd::pmin (bottomright, pt);
183 return ((oldPoint == pt) & (m_Size[0] > 0) & (m_Size[1] > 0));
186 /// Clips rectangle \p r to the canvas.
187 bool CGC::Clip (Rect& r) const
189 const Rect oldRect (r);
190 const Point2d bottomright (m_Size);
191 simd::pmax (c_ZeroPoint, r[0]);
192 simd::pmin (bottomright, r[0]);
193 simd::pmax (c_ZeroPoint, r[1]);
194 simd::pmin (bottomright, r[1]);
195 if (r[0][1] > r[1][1])
196 swap (r[0], r[1]);
197 if (r[0][0] > r[1][0])
198 swap (r[0][0], r[1][0]);
199 simd::pmax (r[0], r[1]);
200 return (oldRect == r);
203 //----------------------------------------------------------------------
205 } // namespace usio