1 /* Public Domain Curses */
2 
3 #include <curspriv.h>
4 
5 /*man-start**************************************************************
6 
7 overlay
8 -------
9 
10 ### Synopsis
11 
12     int overlay(const WINDOW *src_w, WINDOW *dst_w)
13     int overwrite(const WINDOW *src_w, WINDOW *dst_w)
14     int copywin(const WINDOW *src_w, WINDOW *dst_w, int src_tr,
15     int src_tc, int dst_tr, int dst_tc, int dst_br,
16     int dst_bc, bool overlay)
17 
18 ### Description
19 
20    overlay() and overwrite() copy all the text from src_w into
21    dst_w. The windows need not be the same size. Those characters
22    in the source window that intersect with the destination window
23    are copied, so that the characters appear in the same physical
24    position on the screen. The difference between the two functions
25    is that overlay() is non-destructive (blanks are not copied)
26    while overwrite() is destructive (blanks are copied).
27 
28    copywin() is similar, but doesn't require that the two windows
29    overlap. The arguments src_tc and src_tr specify the top left
30    corner of the region to be copied. dst_tc, dst_tr, dst_br, and
31    dst_bc specify the region within the destination window to copy
32    to. The argument "overlay", if TRUE, indicates that the copy is
33    done non-destructively (as in overlay()); blanks in the source
34    window are not copied to the destination window. When overlay is
35    FALSE, blanks are copied.
36 
37 ### Return Value
38 
39    All functions return OK on success and ERR on error.
40 
41 ### Portability
42                              X/Open    BSD    SYS V
43     overlay                     Y       Y       Y
44     overwrite                   Y       Y       Y
45     copywin                     Y       -      3.0
46 
47 **man-end****************************************************************/
48 
49 /* Thanks to Andreas Otte <venn@@uni-paderborn.de> for the
50    corrected overlay()/overwrite() behavior. */
51 
_copy_win(const WINDOW * src_w,WINDOW * dst_w,int src_tr,int src_tc,int src_br,int src_bc,int dst_tr,int dst_tc,bool _overlay)52 static int _copy_win(const WINDOW *src_w, WINDOW *dst_w, int src_tr,
53                      int src_tc, int src_br, int src_bc, int dst_tr,
54                      int dst_tc, bool _overlay)
55 {
56     int col, line, y1, fc, *minchng, *maxchng;
57     chtype *w1ptr, *w2ptr;
58 
59     int lc = 0;
60     int xdiff = src_bc - src_tc;
61     int ydiff = src_br - src_tr;
62 
63     if (!src_w || !dst_w)
64         return ERR;
65 
66     minchng = dst_w->_firstch;
67     maxchng = dst_w->_lastch;
68 
69     for (y1 = 0; y1 < dst_tr; y1++)
70     {
71         minchng++;
72         maxchng++;
73     }
74 
75     for (line = 0; line < ydiff; line++)
76     {
77         w1ptr = src_w->_y[line + src_tr] + src_tc;
78         w2ptr = dst_w->_y[line + dst_tr] + dst_tc;
79 
80         fc = _NO_CHANGE;
81 
82         for (col = 0; col < xdiff; col++)
83         {
84             if ((*w1ptr) != (*w2ptr) &&
85                 !((*w1ptr & A_CHARTEXT) == ' ' && _overlay))
86             {
87                 *w2ptr = *w1ptr;
88 
89                 if (fc == _NO_CHANGE)
90                     fc = col + dst_tc;
91 
92                 lc = col + dst_tc;
93             }
94 
95             w1ptr++;
96             w2ptr++;
97         }
98 
99         if (*minchng == _NO_CHANGE)
100         {
101             *minchng = fc;
102             *maxchng = lc;
103         }
104         else if (fc != _NO_CHANGE)
105         {
106             if (fc < *minchng)
107                 *minchng = fc;
108             if (lc > *maxchng)
109                 *maxchng = lc;
110         }
111 
112         minchng++;
113         maxchng++;
114     }
115 
116     return OK;
117 }
118 
_copy_overlap(const WINDOW * src_w,WINDOW * dst_w,bool overlay)119 int _copy_overlap(const WINDOW *src_w, WINDOW *dst_w, bool overlay)
120 {
121     int first_line, first_col, last_line, last_col;
122     int src_start_x, src_start_y, dst_start_x, dst_start_y;
123     int xdiff, ydiff;
124 
125     if (!src_w || !dst_w)
126         return ERR;
127 
128     first_col = max(dst_w->_begx, src_w->_begx);
129     first_line = max(dst_w->_begy, src_w->_begy);
130 
131     last_col = min(src_w->_begx + src_w->_maxx, dst_w->_begx + dst_w->_maxx);
132     last_line = min(src_w->_begy + src_w->_maxy, dst_w->_begy + dst_w->_maxy);
133 
134     /* determine the overlapping region of the two windows in real
135        coordinates */
136 
137     /* if no overlapping region, do nothing */
138 
139     if ((last_col < first_col) || (last_line < first_line))
140         return OK;
141 
142     /* size of overlapping region */
143 
144     xdiff = last_col - first_col;
145     ydiff = last_line - first_line;
146 
147     if (src_w->_begx <= dst_w->_begx)
148     {
149         src_start_x = dst_w->_begx - src_w->_begx;
150         dst_start_x = 0;
151     }
152     else
153     {
154         dst_start_x = src_w->_begx - dst_w->_begx;
155         src_start_x = 0;
156     }
157 
158     if (src_w->_begy <= dst_w->_begy)
159     {
160         src_start_y = dst_w->_begy - src_w->_begy;
161         dst_start_y = 0;
162     }
163     else
164     {
165         dst_start_y = src_w->_begy - dst_w->_begy;
166         src_start_y = 0;
167     }
168 
169     return _copy_win(src_w, dst_w, src_start_y, src_start_x,
170                      src_start_y + ydiff, src_start_x + xdiff,
171                      dst_start_y, dst_start_x, overlay);
172 }
173 
overlay(const WINDOW * src_w,WINDOW * dst_w)174 int overlay(const WINDOW *src_w, WINDOW *dst_w)
175 {
176     PDC_LOG(("overlay() - called\n"));
177 
178     return _copy_overlap(src_w, dst_w, TRUE);
179 }
180 
overwrite(const WINDOW * src_w,WINDOW * dst_w)181 int overwrite(const WINDOW *src_w, WINDOW *dst_w)
182 {
183     PDC_LOG(("overwrite() - called\n"));
184 
185     return _copy_overlap(src_w, dst_w, FALSE);
186 }
187 
copywin(const WINDOW * src_w,WINDOW * dst_w,int src_tr,int src_tc,int dst_tr,int dst_tc,int dst_br,int dst_bc,int _overlay)188 int copywin(const WINDOW *src_w, WINDOW *dst_w, int src_tr, int src_tc,
189             int dst_tr, int dst_tc, int dst_br, int dst_bc, int _overlay)
190 {
191     int src_end_x, src_end_y;
192     int src_rows, src_cols, dst_rows, dst_cols;
193     int min_rows, min_cols;
194 
195     PDC_LOG(("copywin() - called\n"));
196 
197     if (!src_w || !dst_w || dst_w == curscr || dst_br >= dst_w->_maxy
198         || dst_bc >= dst_w->_maxx || dst_tr < 0 || dst_tc < 0)
199         return ERR;
200 
201     src_rows = src_w->_maxy - src_tr;
202     src_cols = src_w->_maxx - src_tc;
203     dst_rows = dst_br - dst_tr + 1;
204     dst_cols = dst_bc - dst_tc + 1;
205 
206     min_rows = min(src_rows, dst_rows);
207     min_cols = min(src_cols, dst_cols);
208 
209     src_end_y = src_tr + min_rows;
210     src_end_x = src_tc + min_cols;
211 
212     return _copy_win(src_w, dst_w, src_tr, src_tc, src_end_y, src_end_x,
213                      dst_tr, dst_tc, (bool)_overlay);
214 }
215