1 //  This may look like C code, but it is really -*- C++ -*-
2 
3 //  ------------------------------------------------------------------
4 //  The Goldware Library
5 //  Copyright (C) 1990-1999 Odinn Sorensen
6 //  Copyright (C) 1999-2000 Alexander S. Aganichev
7 //  ------------------------------------------------------------------
8 //  This library is free software; you can redistribute it and/or
9 //  modify it under the terms of the GNU Library General Public
10 //  License as published by the Free Software Foundation; either
11 //  version 2 of the License, or (at your option) any later version.
12 //
13 //  This library is distributed in the hope that it will be useful,
14 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
15 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16 //  Library General Public License for more details.
17 //
18 //  You should have received a copy of the GNU Library General Public
19 //  License along with this program; if not, write to the Free
20 //  Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
21 //  MA 02111-1307, USA
22 //  ------------------------------------------------------------------
23 //  $Id: gwinline.cpp,v 1.1 2011/02/18 19:46:02 stas_degteff Exp $
24 //  ------------------------------------------------------------------
25 //  GCUI: Golded+ Character-oriented User Interface.
26 //  Functions for line drawing.
27 //  Based on CXL by Mike Smedley.
28 //  ------------------------------------------------------------------
29 //  whline() draws a horizontal text line in active window
30 //  wvline() draws a vertical text line in active window
31 //  ------------------------------------------------------------------
32 
33 #include <gwinall.h>
34 
35 
36 //  ------------------------------------------------------------------
37 
38 #define HORZ  0
39 #define VERT  1
40 
41 
42 //  ------------------------------------------------------------------
43 
44 #define ULC   _box_table(bt, 0)    // upper left corner
45 #define UHL   _box_table(bt, 1)    // upper horizontal line
46 #define URC   _box_table(bt, 2)    // upper right corner
47 #define LVL   _box_table(bt, 3)    // left vertical line
48 #define RVL   _box_table(bt, 4)    // right vertical line
49 #define LLC   _box_table(bt, 5)    // lower left corner
50 #define LHL   _box_table(bt, 6)    // lower horizontal line
51 #define LRC   _box_table(bt, 7)    // lower right corner
52 #define MJ    _box_table(bt, 8)    // middle junction
53 #define LVJ   _box_table(bt, 9)    // left vertical junction
54 #define RVJ   _box_table(bt, 10)   // right vertical junction
55 #define UHJ   _box_table(bt, 11)   // upper horizontal junction
56 #define LHJ   _box_table(bt, 12)   // lower horizontal junction
57 
58 
59 //  ------------------------------------------------------------------
60 
disp_char(int wrow,int wcol,vattr attr,int btype,vchar ch,int direc)61 static int disp_char(int wrow,int wcol, vattr attr,int btype,vchar ch,int direc) {
62 
63   attr = attr|ACSET;
64 
65   // see if next to a border, if so, connect to it
66   if(gwin.active->border) {
67 
68     // abbreviate pointer
69     const int bt = btype;
70 
71     // calculate effective row and column
72     int row = gwin.active->srow+gwin.active->border+wrow;
73     int col = gwin.active->scol+gwin.active->border+wcol;
74 
75     // see if this is a horizontal or vertical line
76     if(direc==HORZ) {
77 
78       // make sure that the box type characters match
79       if(LVL==_box_table(gwin.active->btype, 3)) {
80 
81         // check left border
82         if(col==(gwin.active->scol+1)) {
83           vputc(row,gwin.active->scol,attr,LVJ);
84           ch=UHL;
85         }
86 
87         // check right border
88         if(col==(gwin.active->ecol-1)) {
89           vputc(row,gwin.active->ecol,attr,RVJ);
90           ch=UHL;
91         }
92       }
93     }
94     else {
95 
96       // make sure that the box type characters match
97       if(UHL==_box_table(gwin.active->btype, 1)) {
98 
99         // check top border
100         if(row==(gwin.active->srow+1)) {
101           vputc(gwin.active->srow,col,attr,UHJ);
102           ch=LVL;
103         }
104 
105         // check bottom border
106         if(row==(gwin.active->erow-1)) {
107           vputc(gwin.active->erow,col,attr,LHJ);
108           ch=LVL;
109         }
110       }
111     }
112   }
113 
114   // display character
115   if(wprintc(wrow,wcol,attr,ch))
116     return gwin.werrno;
117 
118   // return normally
119   return 0;
120 } /* disp_char() */
121 
122 
123 //  ------------------------------------------------------------------
124 
isupvert(int btype,vchar ch)125 static inline int isupvert(int btype, vchar ch) {
126 
127   const int bt = btype;
128   return (ch==LVL or ch==UHJ or ch==ULC or ch==URC or ch==LVJ or ch==RVJ or ch==MJ) ? YES : NO;
129 }
130 
131 
132 //  ------------------------------------------------------------------
133 
isdownvert(int btype,vchar ch)134 static inline int isdownvert(int btype, vchar ch) {
135 
136   const int bt = btype;
137   return (ch==LVL or ch==LHJ or ch==LLC or ch==LRC or ch==LVJ or ch==RVJ or ch==MJ) ? YES : NO;
138 }
139 
140 
141 //  ------------------------------------------------------------------
142 
islefthorz(int btype,vchar ch)143 static inline int islefthorz(int btype, vchar ch) {
144 
145   const int bt = btype;
146   return (ch==UHL or ch==LVJ or ch==LLC or ch==ULC or ch==UHJ or ch==LHJ or ch==MJ) ? YES : NO;
147 }
148 
149 
150 //  ------------------------------------------------------------------
151 
isrighthorz(int btype,vchar ch)152 static inline int isrighthorz(int btype, vchar ch) {
153 
154   const int bt = btype;
155   return (ch==UHL or ch==RVJ or ch==LRC or ch==URC or ch==UHJ or ch==LHJ or ch==MJ) ? YES : NO;
156 }
157 
158 
159 //  ------------------------------------------------------------------
160 
whline(int wsrow,int wscol,int count,int btype,vattr attr)161 int whline(int wsrow, int wscol, int count, int btype, vattr attr) {
162 
163   register int bt;
164   int row,col,up,down;
165   vchar ch;
166 
167   row=wsrow;
168   col=wscol;
169 
170   // abbreviate pointer
171   bt = btype;
172 
173   if(count) {
174 
175     // see if a left junction or corner is needed
176     up   = isupvert  (btype,wgetc(row-1,col));
177     down = isdownvert(btype,wgetc(row+1,col));
178     if(up and down)
179       ch=LVJ;
180     else if(up)
181       ch=LLC;
182     else if(down)
183       ch=ULC;
184     else
185       ch=UHL;
186 
187     // display leftmost character
188     if(disp_char(row,col,attr,btype,ch,HORZ))
189       return gwin.werrno;
190     col++;
191     count--;
192   }
193 
194   // do while not last character
195   while(count>1) {
196 
197     // see if a middle junction is needed
198     up   = isupvert  (btype,wgetc(row-1,col));
199     down = isdownvert(btype,wgetc(row+1,col));
200     if(up and down)
201       ch=MJ;
202     else if(up)
203       ch=LHJ;
204     else if(down)
205       ch=UHJ;
206     else
207       ch=UHL;
208 
209     // display middle character
210     if(disp_char(row,col,attr,btype,ch,HORZ))
211       return gwin.werrno;
212     col++;
213     count--;
214   }
215 
216   if(count) {
217 
218     // see if a right junction or corner is needed
219     up   = isupvert  (btype,wgetc(row-1,col));
220     down = isdownvert(btype,wgetc(row+1,col));
221     if(up and down)
222       ch=RVJ;
223     else if(up)
224       ch=LRC;
225     else if(down)
226       ch=URC;
227     else
228       ch=UHL;
229 
230     // display rightmost character
231     if(disp_char(row,col,attr,btype,ch,HORZ))
232       return gwin.werrno;
233   }
234 
235   // return normally
236   return gwin.werrno=W_NOERROR;
237 } /* whline() */
238 
239 
240 //  ------------------------------------------------------------------
241 
wvline(int wsrow,int wscol,int count,int btype,vattr attr)242 int wvline(int wsrow, int wscol, int count, int btype, vattr attr) {
243 
244   register int bt;
245   int row,col,left,right;
246   vchar ch;
247 
248   row=wsrow;
249   col=wscol;
250 
251   // abbreviate pointer
252   bt = btype;
253 
254   if(count) {
255 
256     // see if a top junction or corner is needed
257     left  = islefthorz (btype,wgetc(row,col-1));
258     right = isrighthorz(btype,wgetc(row,col+1));
259     if(left and right)
260       ch=UHJ;
261     else if(left)
262       ch=URC;
263     else if(right)
264       ch=ULC;
265     else
266       ch=LVL;
267 
268     // display uppermost character
269     if(disp_char(row,col,attr,btype,ch,VERT))
270       return gwin.werrno;
271     row++;
272     count--;
273   }
274 
275   // do while not last character
276   while(count>1) {
277     left  = islefthorz (btype,wgetc(row,col-1));
278     right = isrighthorz(btype,wgetc(row,col+1));
279     if(left and right)
280       ch=MJ;
281     else if(left)
282       ch=RVJ;
283     else if(right)
284       ch=LVJ;
285     else
286       ch=LVL;
287 
288     // display middle character
289     if(disp_char(row,col,attr,btype,ch,VERT))
290       return gwin.werrno;
291     row++;
292     count--;
293   }
294 
295   if(count) {
296 
297     // see if a bottom junction or corner is needed
298     left  = islefthorz (btype,wgetc(row,col-1));
299     right = isrighthorz(btype,wgetc(row,col+1));
300     if(left and right)
301       ch=LHJ;
302     else if(left)
303       ch=LRC;
304     else if(right)
305       ch=LLC;
306     else
307       ch=LVL;
308 
309     // display bottommost character
310     if(disp_char(row,col,attr,btype,ch,VERT))
311       return gwin.werrno;
312   }
313 
314   // return normally
315   return gwin.werrno=W_NOERROR;
316 } /* wvline() */
317 
318 //  ------------------------------------------------------------------
319