| |
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 |
| |
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 case '\r': |
| |
177 x = 0; |
| |
178 |
| |
179 break; |
| |
180 |
| |
181 case 0x7f: |
| |
182 if (waddch(win, attr | '^') == ERR) |
| |
183 return ERR; |
| |
184 |
| |
185 return waddch(win, attr | '?'); |
| |
186 |
| |
187 default: |
| |
188 /* handle control chars */ |
| |
189 |
| |
190 if (waddch(win, attr | '^') == ERR) |
| |
191 return ERR; |
| |
192 |
| |
193 return waddch(win, ch + '@'); |
| |
194 } |
| |
195 } |
| |
196 else |
| |
197 { |
| |
198 /* If the incoming character doesn't have its own attribute, |
| |
199 then use the current attributes for the window. If it has |
| |
200 attributes but not a color component, OR the attributes to |
| |
201 the current attributes for the window. If it has a color |
| |
202 component, use the attributes solely from the incoming |
| |
203 character. */ |
| |
204 |
| |
205 if (!(attr & A_COLOR)) |
| |
206 attr |= win->_attrs; |
| |
207 |
| |
208 /* wrs (4/10/93): Apply the same sort of logic for the window |
| |
209 background, in that it only takes precedence if other color |
| |
210 attributes are not there and that the background character |
| |
211 will only print if the printing character is blank. */ |
| |
212 |
| |
213 if (!(attr & A_COLOR)) |
| |
214 attr |= win->_bkgd & A_ATTRIBUTES; |
| |
215 else |
| |
216 attr |= win->_bkgd & (A_ATTRIBUTES ^ A_COLOR); |
| |
217 |
| |
218 if (text == ' ') |
| |
219 text = win->_bkgd & A_CHARTEXT; |
| |
220 |
| |
221 /* Add the attribute back into the character. */ |
| |
222 |
| |
223 text |= attr; |
| |
224 |
| |
225 /* Only change _firstch/_lastch if the character to be added is |
| |
226 different from the character/attribute that is already in |
| |
227 that position in the window. */ |
| |
228 |
| |
229 if (win->_y[y][x] != text) |
| |
230 { |
| |
231 if (win->_firstch[y] == _NO_CHANGE) |
| |
232 win->_firstch[y] = win->_lastch[y] = x; |
| |
233 else |
| |
234 if (x < win->_firstch[y]) |
| |
235 win->_firstch[y] = x; |
| |
236 else |
| |
237 if (x > win->_lastch[y]) |
| |
238 win->_lastch[y] = x; |
| |
239 |
| |
240 win->_y[y][x] = text; |
| |
241 } |
| |
242 |
| |
243 if (++x >= win->_maxx) |
| |
244 { |
| |
245 /* wrap around test */ |
| |
246 |
| |
247 x = 0; |
| |
248 |
| |
249 if (++y > win->_bmarg) |
| |
250 { |
| |
251 y--; |
| |
252 |
| |
253 if (wscrl(win, 1) == ERR) |
| |
254 { |
| |
255 PDC_sync(win); |
| |
256 return ERR; |
| |
257 } |
| |
258 } |
| |
259 } |
| |
260 } |
| |
261 |
| |
262 win->_curx = x; |
| |
263 win->_cury = y; |
| |
264 |
| |
265 if (win->_immed) |
| |
266 wrefresh(win); |
| |
267 if (win->_sync) |
| |
268 wsyncup(win); |
| |
269 |
| |
270 return OK; |
| |
271 } |
| |
272 |
| |
273 int addch(const chtype ch) |
| |
274 { |
| |
275 PDC_LOG(("addch() - called: ch=%x\n", ch)); |
| |
276 |
| |
277 return waddch(stdscr, ch); |
| |
278 } |
| |
279 |
| |
280 int mvaddch(int y, int x, const chtype ch) |
| |
281 { |
| |
282 PDC_LOG(("mvaddch() - called: y=%d x=%d ch=%x\n", y, x, ch)); |
| |
283 |
| |
284 if (move(y,x) == ERR) |
| |
285 return ERR; |
| |
286 |
| |
287 return waddch(stdscr, ch); |
| |
288 } |
| |
289 |
| |
290 int mvwaddch(WINDOW *win, int y, int x, const chtype ch) |
| |
291 { |
| |
292 PDC_LOG(("mvwaddch() - called: win=%p y=%d x=%d ch=%d\n", win, y, x, ch)); |
| |
293 |
| |
294 if (wmove(win, y, x) == ERR) |
| |
295 return ERR; |
| |
296 |
| |
297 return waddch(win, ch); |
| |
298 } |
| |
299 |
| |
300 int echochar(const chtype ch) |
| |
301 { |
| |
302 PDC_LOG(("echochar() - called: ch=%x\n", ch)); |
| |
303 |
| |
304 return wechochar(stdscr, ch); |
| |
305 } |
| |
306 |
| |
307 int wechochar(WINDOW *win, const chtype ch) |
| |
308 { |
| |
309 PDC_LOG(("wechochar() - called: win=%p ch=%x\n", win, ch)); |
| |
310 |
| |
311 if (waddch(win, ch) == ERR) |
| |
312 return ERR; |
| |
313 |
| |
314 return wrefresh(win); |
| |
315 } |
| |
316 |
| |
317 int waddrawch(WINDOW *win, chtype ch) |
| |
318 { |
| |
319 PDC_LOG(("waddrawch() - called: win=%p ch=%x (text=%c attr=0x%x)\n", |
| |
320 win, ch, ch & A_CHARTEXT, ch & A_ATTRIBUTES)); |
| |
321 |
| |
322 if ((ch & A_CHARTEXT) < ' ' || (ch & A_CHARTEXT) == 0x7f) |
| |
323 ch |= A_ALTCHARSET; |
| |
324 |
| |
325 return waddch(win, ch); |
| |
326 } |
| |
327 |
| |
328 int addrawch(chtype ch) |
| |
329 { |
| |
330 PDC_LOG(("addrawch() - called: ch=%x\n", ch)); |
| |
331 |
| |
332 return waddrawch(stdscr, ch); |
| |
333 } |
| |
334 |
| |
335 int mvaddrawch(int y, int x, chtype ch) |
| |
336 { |
| |
337 PDC_LOG(("mvaddrawch() - called: y=%d x=%d ch=%d\n", y, x, ch)); |
| |
338 |
| |
339 if (move(y, x) == ERR) |
| |
340 return ERR; |
| |
341 |
| |
342 return waddrawch(stdscr, ch); |
| |
343 } |
| |
344 |
| |
345 int mvwaddrawch(WINDOW *win, int y, int x, chtype ch) |
| |
346 { |
| |
347 PDC_LOG(("mvwaddrawch() - called: win=%p y=%d x=%d ch=%d\n", |
| |
348 win, y, x, ch)); |
| |
349 |
| |
350 if (wmove(win, y, x) == ERR) |
| |
351 return ERR; |
| |
352 |
| |
353 return waddrawch(win, ch); |
| |
354 } |
| |
355 |
| |
356 #ifdef PDC_WIDE |
| |
357 int wadd_wch(WINDOW *win, const cchar_t *wch) |
| |
358 { |
| |
359 PDC_LOG(("wadd_wch() - called: win=%p wch=%x\n", win, *wch)); |
| |
360 |
| |
361 return wch ? waddch(win, *wch) : ERR; |
| |
362 } |
| |
363 |
| |
364 int add_wch(const cchar_t *wch) |
| |
365 { |
| |
366 PDC_LOG(("add_wch() - called: wch=%x\n", *wch)); |
| |
367 |
| |
368 return wadd_wch(stdscr, wch); |
| |
369 } |
| |
370 |
| |
371 int mvadd_wch(int y, int x, const cchar_t *wch) |
| |
372 { |
| |
373 PDC_LOG(("mvaddch() - called: y=%d x=%d wch=%x\n", y, x, *wch)); |
| |
374 |
| |
375 if (move(y,x) == ERR) |
| |
376 return ERR; |
| |
377 |
| |
378 return wadd_wch(stdscr, wch); |
| |
379 } |
| |
380 |
| |
381 int mvwadd_wch(WINDOW *win, int y, int x, const cchar_t *wch) |
| |
382 { |
| |
383 PDC_LOG(("mvwaddch() - called: win=%p y=%d x=%d wch=%d\n", |
| |
384 win, y, x, *wch)); |
| |
385 |
| |
386 if (wmove(win, y, x) == ERR) |
| |
387 return ERR; |
| |
388 |
| |
389 return wadd_wch(win, wch); |
| |
390 } |
| |
391 |
| |
392 int echo_wchar(const cchar_t *wch) |
| |
393 { |
| |
394 PDC_LOG(("echo_wchar() - called: wch=%x\n", *wch)); |
| |
395 |
| |
396 return wecho_wchar(stdscr, wch); |
| |
397 } |
| |
398 |
| |
399 int wecho_wchar(WINDOW *win, const cchar_t *wch) |
| |
400 { |
| |
401 PDC_LOG(("wecho_wchar() - called: win=%p wch=%x\n", win, *wch)); |
| |
402 |
| |
403 if (!wch || (wadd_wch(win, wch) == ERR)) |
| |
404 return ERR; |
| |
405 |
| |
406 return wrefresh(win); |
| |
407 } |
| |
408 #endif |