xref: /aosp_15_r20/external/coreboot/payloads/libpayload/curses/PDCurses/pdcurses/addch.c (revision b9411a12aaaa7e1e6a6fb7c5e057f44ee179a49c)
1 /* Public Domain Curses */
2 
3 #include <curspriv.h>
4 
5 RCSID("$Id: addch.c,v 1.54 2008/07/13 16:08:17 wmcbrine Exp $")
6 
7 /*man-start**************************************************************
8 
9   Name:                                                         addch
10 
11   Synopsis:
12         int addch(const chtype ch);
13         int waddch(WINDOW *win, const chtype ch);
14         int mvaddch(int y, int x, const chtype ch);
15         int mvwaddch(WINDOW *win, int y, int x, const chtype ch);
16         int echochar(const chtype ch);
17         int wechochar(WINDOW *win, const chtype ch);
18 
19         int addrawch(chtype ch);
20         int waddrawch(WINDOW *win, chtype ch);
21         int mvaddrawch(int y, int x, chtype ch);
22         int mvwaddrawch(WINDOW *win, int y, int x, chtype ch);
23 
24         int add_wch(const cchar_t *wch);
25         int wadd_wch(WINDOW *win, const cchar_t *wch);
26         int mvadd_wch(int y, int x, const cchar_t *wch);
27         int mvwadd_wch(WINDOW *win, int y, int x, const cchar_t *wch);
28         int echo_wchar(const cchar_t *wch);
29         int wecho_wchar(WINDOW *win, const cchar_t *wch);
30 
31   Description:
32         addch() adds the chtype ch to the default window (stdscr) at the
33         current cursor position, and advances the cursor. Note that
34         chtypes can convey both text (a single character) and
35         attributes, including a color pair. add_wch() is the wide-
36         character version of this function, taking a pointer to a
37         cchar_t instead of a chtype.
38 
39         waddch() is like addch(), but also lets you specify the window.
40         (This is in fact the core output routine.) wadd_wch() is the
41         wide version.
42 
43         mvaddch() moves the cursor to the specified (y, x) position, and
44         adds ch to stdscr. mvadd_wch() is the wide version.
45 
46         mvwaddch() moves the cursor to the specified position and adds
47         ch to the specified window. mvwadd_wch() is the wide version.
48 
49         echochar() adds ch to stdscr at the current cursor position and
50         calls refresh(). echo_wchar() is the wide version.
51 
52         wechochar() adds ch to the specified window and calls
53         wrefresh(). wecho_wchar() is the wide version.
54 
55         addrawch(), waddrawch(), mvaddrawch() and mvwaddrawch() are
56         PDCurses-specific wrappers for addch() etc. that disable the
57         translation of control characters.
58 
59         The following applies to all these functions:
60 
61         If the cursor moves on to the right margin, an automatic newline
62         is performed.  If scrollok is enabled, and a character is added
63         to the bottom right corner of the window, the scrolling region
64         will be scrolled up one line.  If scrolling is not allowed, ERR
65         will be returned.
66 
67         If ch is a tab, newline, or backspace, the cursor will be moved
68         appropriately within the window.  If ch is a newline, the
69         clrtoeol routine is called before the cursor is moved to the
70         beginning of the next line.  If newline mapping is off, the
71         cursor will be moved to the next line, but the x coordinate will
72         be unchanged.  If ch is a tab the cursor is moved to the next
73         tab position within the window.  If ch is another control
74         character, it will be drawn in the ^X notation.  Calling the
75         inch() routine after adding a control character returns the
76         representation of the control character, not the control
77         character.
78 
79         Video attributes can be combined with a character by ORing them
80         into the parameter. Text, including attributes, can be copied
81         from one place to another by using inch() and addch().
82 
83         Note that in PDCurses, for now, a cchar_t and a chtype are the
84         same. The text field is 16 bits wide, and is treated as Unicode
85         (UCS-2) when PDCurses is built with wide-character support
86         (define PDC_WIDE). So, in functions that take a chtype, like
87         addch(), both the wide and narrow versions will handle Unicode.
88         But for portability, you should use the wide functions.
89 
90   Return Value:
91         All functions return OK on success and ERR on error.
92 
93   Portability                                X/Open    BSD    SYS V
94         addch                                   Y       Y       Y
95         waddch                                  Y       Y       Y
96         mvaddch                                 Y       Y       Y
97         mvwaddch                                Y       Y       Y
98         echochar                                Y       -      3.0
99         wechochar                               Y       -      3.0
100         addrawch                                -       -       -
101         waddrawch                               -       -       -
102         mvaddrawch                              -       -       -
103         mvwaddrawch                             -       -       -
104         add_wch                                 Y
105         wadd_wch                                Y
106         mvadd_wch                               Y
107         mvwadd_wch                              Y
108         echo_wchar                              Y
109         wecho_wchar                             Y
110 
111 **man-end****************************************************************/
112 
waddch(WINDOW * win,const chtype ch)113 int waddch(WINDOW *win, const chtype ch)
114 {
115     int x, y;
116     chtype text, attr;
117     bool xlat;
118 
119     PDC_LOG(("waddch() - called: win=%p ch=%x (text=%c attr=0x%x)\n",
120              win, ch, ch & A_CHARTEXT, ch & A_ATTRIBUTES));
121 
122     if (!win)
123         return ERR;
124 
125     x = win->_curx;
126     y = win->_cury;
127 
128     if (y > win->_maxy || x > win->_maxx || y < 0 || x < 0)
129         return ERR;
130 
131     xlat = !SP->raw_out && !(ch & A_ALTCHARSET);
132     text = ch & A_CHARTEXT;
133     attr = ch & A_ATTRIBUTES;
134 
135     if (xlat && (text < ' ' || text == 0x7f))
136     {
137         int x2;
138 
139         switch (text)
140         {
141         case '\t':
142             for (x2 = ((x / TABSIZE) + 1) * TABSIZE; x < x2; x++)
143             {
144                 if (waddch(win, attr | ' ') == ERR)
145                     return ERR;
146 
147                 /* if tab to next line, exit the loop */
148 
149                 if (!win->_curx)
150                     break;
151             }
152             return OK;
153 
154         case '\n':
155             /* if lf -> crlf */
156 
157             if (!SP->raw_out)
158                 x = 0;
159 
160             wclrtoeol(win);
161 
162             if (++y > win->_bmarg)
163             {
164                 y--;
165 
166                 if (wscrl(win, 1) == ERR)
167                     return ERR;
168             }
169 
170             break;
171 
172         case '\b':
173             /* don't back over left margin */
174 
175             if (--x < 0)
176                 x = 0;
177             break;
178         case '\r':
179             x = 0;
180 
181             break;
182 
183         case 0x7f:
184             if (waddch(win, attr | '^') == ERR)
185                 return ERR;
186 
187             return waddch(win, attr | '?');
188 
189         default:
190             /* handle control chars */
191 
192             if (waddch(win, attr | '^') == ERR)
193                 return ERR;
194 
195             return waddch(win, ch + '@');
196         }
197     }
198     else
199     {
200         /* If the incoming character doesn't have its own attribute,
201            then use the current attributes for the window. If it has
202            attributes but not a color component, OR the attributes to
203            the current attributes for the window. If it has a color
204            component, use the attributes solely from the incoming
205            character. */
206 
207         if (!(attr & A_COLOR))
208             attr |= win->_attrs;
209 
210         /* wrs (4/10/93): Apply the same sort of logic for the window
211            background, in that it only takes precedence if other color
212            attributes are not there and that the background character
213            will only print if the printing character is blank. */
214 
215         if (!(attr & A_COLOR))
216             attr |= win->_bkgd & A_ATTRIBUTES;
217         else
218             attr |= win->_bkgd & (A_ATTRIBUTES ^ A_COLOR);
219 
220         if (text == ' ')
221             text = win->_bkgd & A_CHARTEXT;
222 
223         /* Add the attribute back into the character. */
224 
225         text |= attr;
226 
227         /* Only change _firstch/_lastch if the character to be added is
228            different from the character/attribute that is already in
229            that position in the window. */
230 
231         if (win->_y[y][x] != text)
232         {
233             if (win->_firstch[y] == _NO_CHANGE)
234                 win->_firstch[y] = win->_lastch[y] = x;
235             else
236                 if (x < win->_firstch[y])
237                     win->_firstch[y] = x;
238                 else
239                     if (x > win->_lastch[y])
240                         win->_lastch[y] = x;
241 
242             win->_y[y][x] = text;
243         }
244 
245         if (++x >= win->_maxx)
246         {
247             /* wrap around test */
248 
249             x = 0;
250 
251             if (++y > win->_bmarg)
252             {
253                 y--;
254 
255                 if (wscrl(win, 1) == ERR)
256                 {
257                     PDC_sync(win);
258                     return ERR;
259                 }
260             }
261         }
262     }
263 
264     win->_curx = x;
265     win->_cury = y;
266 
267     if (win->_immed)
268         wrefresh(win);
269     if (win->_sync)
270         wsyncup(win);
271 
272     return OK;
273 }
274 
addch(const chtype ch)275 int addch(const chtype ch)
276 {
277     PDC_LOG(("addch() - called: ch=%x\n", ch));
278 
279     return waddch(stdscr, ch);
280 }
281 
mvaddch(int y,int x,const chtype ch)282 int mvaddch(int y, int x, const chtype ch)
283 {
284     PDC_LOG(("mvaddch() - called: y=%d x=%d ch=%x\n", y, x, ch));
285 
286     if (move(y,x) == ERR)
287         return ERR;
288 
289     return waddch(stdscr, ch);
290 }
291 
mvwaddch(WINDOW * win,int y,int x,const chtype ch)292 int mvwaddch(WINDOW *win, int y, int x, const chtype ch)
293 {
294     PDC_LOG(("mvwaddch() - called: win=%p y=%d x=%d ch=%d\n", win, y, x, ch));
295 
296     if (wmove(win, y, x) == ERR)
297         return ERR;
298 
299     return waddch(win, ch);
300 }
301 
echochar(const chtype ch)302 int echochar(const chtype ch)
303 {
304     PDC_LOG(("echochar() - called: ch=%x\n", ch));
305 
306     return wechochar(stdscr, ch);
307 }
308 
wechochar(WINDOW * win,const chtype ch)309 int wechochar(WINDOW *win, const chtype ch)
310 {
311     PDC_LOG(("wechochar() - called: win=%p ch=%x\n", win, ch));
312 
313     if (waddch(win, ch) == ERR)
314         return ERR;
315 
316     return wrefresh(win);
317 }
318 
waddrawch(WINDOW * win,chtype ch)319 int waddrawch(WINDOW *win, chtype ch)
320 {
321     PDC_LOG(("waddrawch() - called: win=%p ch=%x (text=%c attr=0x%x)\n",
322              win, ch, ch & A_CHARTEXT, ch & A_ATTRIBUTES));
323 
324     if ((ch & A_CHARTEXT) < ' ' || (ch & A_CHARTEXT) == 0x7f)
325         ch |= A_ALTCHARSET;
326 
327     return waddch(win, ch);
328 }
329 
addrawch(chtype ch)330 int addrawch(chtype ch)
331 {
332     PDC_LOG(("addrawch() - called: ch=%x\n", ch));
333 
334     return waddrawch(stdscr, ch);
335 }
336 
mvaddrawch(int y,int x,chtype ch)337 int mvaddrawch(int y, int x, chtype ch)
338 {
339     PDC_LOG(("mvaddrawch() - called: y=%d x=%d ch=%d\n", y, x, ch));
340 
341     if (move(y, x) == ERR)
342         return ERR;
343 
344     return waddrawch(stdscr, ch);
345 }
346 
mvwaddrawch(WINDOW * win,int y,int x,chtype ch)347 int mvwaddrawch(WINDOW *win, int y, int x, chtype ch)
348 {
349     PDC_LOG(("mvwaddrawch() - called: win=%p y=%d x=%d ch=%d\n",
350              win, y, x, ch));
351 
352     if (wmove(win, y, x) == ERR)
353         return ERR;
354 
355     return waddrawch(win, ch);
356 }
357 
358 #ifdef PDC_WIDE
wadd_wch(WINDOW * win,const cchar_t * wch)359 int wadd_wch(WINDOW *win, const cchar_t *wch)
360 {
361     PDC_LOG(("wadd_wch() - called: win=%p wch=%x\n", win, *wch));
362 
363     return wch ? waddch(win, *wch) : ERR;
364 }
365 
add_wch(const cchar_t * wch)366 int add_wch(const cchar_t *wch)
367 {
368     PDC_LOG(("add_wch() - called: wch=%x\n", *wch));
369 
370     return wadd_wch(stdscr, wch);
371 }
372 
mvadd_wch(int y,int x,const cchar_t * wch)373 int mvadd_wch(int y, int x, const cchar_t *wch)
374 {
375     PDC_LOG(("mvaddch() - called: y=%d x=%d wch=%x\n", y, x, *wch));
376 
377     if (move(y,x) == ERR)
378         return ERR;
379 
380     return wadd_wch(stdscr, wch);
381 }
382 
mvwadd_wch(WINDOW * win,int y,int x,const cchar_t * wch)383 int mvwadd_wch(WINDOW *win, int y, int x, const cchar_t *wch)
384 {
385     PDC_LOG(("mvwaddch() - called: win=%p y=%d x=%d wch=%d\n",
386              win, y, x, *wch));
387 
388     if (wmove(win, y, x) == ERR)
389         return ERR;
390 
391     return wadd_wch(win, wch);
392 }
393 
echo_wchar(const cchar_t * wch)394 int echo_wchar(const cchar_t *wch)
395 {
396     PDC_LOG(("echo_wchar() - called: wch=%x\n", *wch));
397 
398     return wecho_wchar(stdscr, wch);
399 }
400 
wecho_wchar(WINDOW * win,const cchar_t * wch)401 int wecho_wchar(WINDOW *win, const cchar_t *wch)
402 {
403     PDC_LOG(("wecho_wchar() - called: win=%p wch=%x\n", win, *wch));
404 
405     if (!wch || (wadd_wch(win, wch) == ERR))
406         return ERR;
407 
408     return wrefresh(win);
409 }
410 #endif
411