slk.c revision 1.2.4.2 1 1.2.4.2 bouyer /* $NetBSD: slk.c,v 1.2.4.2 2017/04/21 16:53:10 bouyer Exp $ */
2 1.2.4.2 bouyer
3 1.2.4.2 bouyer /*-
4 1.2.4.2 bouyer * Copyright (c) 2017 The NetBSD Foundation, Inc.
5 1.2.4.2 bouyer * All rights reserved.
6 1.2.4.2 bouyer *
7 1.2.4.2 bouyer * This code is derived from software contributed to The NetBSD Foundation
8 1.2.4.2 bouyer * by Roy Marples.
9 1.2.4.2 bouyer *
10 1.2.4.2 bouyer * Redistribution and use in source and binary forms, with or without
11 1.2.4.2 bouyer * modification, are permitted provided that the following conditions
12 1.2.4.2 bouyer * are met:
13 1.2.4.2 bouyer * 1. Redistributions of source code must retain the above copyright
14 1.2.4.2 bouyer * notice, this list of conditions and the following disclaimer.
15 1.2.4.2 bouyer * 2. Redistributions in binary form must reproduce the above copyright
16 1.2.4.2 bouyer * notice, this list of conditions and the following disclaimer in the
17 1.2.4.2 bouyer * documentation and/or other materials provided with the distribution.
18 1.2.4.2 bouyer *
19 1.2.4.2 bouyer * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 1.2.4.2 bouyer * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 1.2.4.2 bouyer * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 1.2.4.2 bouyer * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 1.2.4.2 bouyer * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 1.2.4.2 bouyer * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 1.2.4.2 bouyer * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 1.2.4.2 bouyer * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 1.2.4.2 bouyer * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 1.2.4.2 bouyer * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 1.2.4.2 bouyer * POSSIBILITY OF SUCH DAMAGE.
30 1.2.4.2 bouyer */
31 1.2.4.2 bouyer
32 1.2.4.2 bouyer #include <sys/cdefs.h>
33 1.2.4.2 bouyer #ifndef lint
34 1.2.4.2 bouyer __RCSID("$NetBSD: slk.c,v 1.2.4.2 2017/04/21 16:53:10 bouyer Exp $");
35 1.2.4.2 bouyer #endif /* not lint */
36 1.2.4.2 bouyer
37 1.2.4.2 bouyer #include <ctype.h>
38 1.2.4.2 bouyer #include <stdlib.h>
39 1.2.4.2 bouyer #include <string.h>
40 1.2.4.2 bouyer #ifdef HAVE_WCHAR
41 1.2.4.2 bouyer #include <wctype.h>
42 1.2.4.2 bouyer #endif
43 1.2.4.2 bouyer
44 1.2.4.2 bouyer #include "curses.h"
45 1.2.4.2 bouyer #include "curses_private.h"
46 1.2.4.2 bouyer
47 1.2.4.2 bouyer /* Terminals with real soft labels have NOT been tested.
48 1.2.4.2 bouyer * If you have such a device, please let us know so this comment
49 1.2.4.2 bouyer * can be adjusted. */
50 1.2.4.2 bouyer
51 1.2.4.2 bouyer /* POSIX says that each label can be up to 8 columns.
52 1.2.4.2 bouyer * However, our implementation can allow labels to expand beyond that. */
53 1.2.4.2 bouyer //#define SLK_SIZE_DYNAMIC
54 1.2.4.2 bouyer #ifdef SLK_SIZE_DYNAMIC
55 1.2.4.2 bouyer #define SLK_SIZE MAX_SLK_LABEL
56 1.2.4.2 bouyer #else
57 1.2.4.2 bouyer #define SLK_SIZE MAX_SLK_COLS
58 1.2.4.2 bouyer #endif
59 1.2.4.2 bouyer
60 1.2.4.2 bouyer static int slk_fmt; /* fmt of slk_init */
61 1.2.4.2 bouyer
62 1.2.4.2 bouyer /* Safe variants of public functions. */
63 1.2.4.2 bouyer static int __slk_attron(SCREEN *, const chtype);
64 1.2.4.2 bouyer static int __slk_attr_on(SCREEN *, const attr_t, void *);
65 1.2.4.2 bouyer static int __slk_attroff(SCREEN *, const chtype);
66 1.2.4.2 bouyer static int __slk_attr_off(SCREEN *, const attr_t, void *);
67 1.2.4.2 bouyer static int __slk_attrset(SCREEN *, const chtype);
68 1.2.4.2 bouyer static int __slk_attr_set(SCREEN *, const attr_t, short, void *opt);
69 1.2.4.2 bouyer static int __slk_color(SCREEN *, short);
70 1.2.4.2 bouyer static int __slk_clear(SCREEN *);
71 1.2.4.2 bouyer static char *__slk_label(SCREEN *, int);
72 1.2.4.2 bouyer static int __slk_restore(SCREEN *);
73 1.2.4.2 bouyer static int __slk_set(SCREEN *, int, const char *, int);
74 1.2.4.2 bouyer static int __slk_touch(SCREEN *);
75 1.2.4.2 bouyer static int __slk_wset(SCREEN *, int, const wchar_t *, int);
76 1.2.4.2 bouyer
77 1.2.4.2 bouyer /* Internal engine parts. */
78 1.2.4.2 bouyer static int __slk_ripoffline(WINDOW *, int);
79 1.2.4.2 bouyer static int __slk_set_finalise(SCREEN *, int);
80 1.2.4.2 bouyer static int __slk_draw(SCREEN *, int);
81 1.2.4.2 bouyer static int __slk_redraw(SCREEN *);
82 1.2.4.2 bouyer
83 1.2.4.2 bouyer /*
84 1.2.4.2 bouyer * slk_init --
85 1.2.4.2 bouyer * Init Soft Label Keys.
86 1.2.4.2 bouyer */
87 1.2.4.2 bouyer int
88 1.2.4.2 bouyer slk_init(int fmt)
89 1.2.4.2 bouyer {
90 1.2.4.2 bouyer
91 1.2.4.2 bouyer switch(fmt) {
92 1.2.4.2 bouyer case SLK_FMT_3_2_3:
93 1.2.4.2 bouyer case SLK_FMT_4_4:
94 1.2.4.2 bouyer break;
95 1.2.4.2 bouyer default:
96 1.2.4.2 bouyer return ERR;
97 1.2.4.2 bouyer }
98 1.2.4.2 bouyer
99 1.2.4.2 bouyer slk_fmt = fmt;
100 1.2.4.2 bouyer /* Even if the terminal supports soft label keys directly,
101 1.2.4.2 bouyer * we need to reserve a line. */
102 1.2.4.2 bouyer return ripoffline(-1, __slk_ripoffline);
103 1.2.4.2 bouyer }
104 1.2.4.2 bouyer
105 1.2.4.2 bouyer /*
106 1.2.4.2 bouyer * slk_attron --
107 1.2.4.2 bouyer * Test and set attributes on ripped off slk window.
108 1.2.4.2 bouyer */
109 1.2.4.2 bouyer int
110 1.2.4.2 bouyer slk_attron(const chtype attr)
111 1.2.4.2 bouyer {
112 1.2.4.2 bouyer
113 1.2.4.2 bouyer return __slk_attron(_cursesi_screen, attr);
114 1.2.4.2 bouyer }
115 1.2.4.2 bouyer
116 1.2.4.2 bouyer /*
117 1.2.4.2 bouyer * slk_attr_on --
118 1.2.4.2 bouyer * Test and set wide attributes on ripped off slk window.
119 1.2.4.2 bouyer */
120 1.2.4.2 bouyer int
121 1.2.4.2 bouyer slk_attr_on(const attr_t attr, void *opt)
122 1.2.4.2 bouyer {
123 1.2.4.2 bouyer
124 1.2.4.2 bouyer return __slk_attr_on(_cursesi_screen, attr, opt);
125 1.2.4.2 bouyer }
126 1.2.4.2 bouyer
127 1.2.4.2 bouyer /*
128 1.2.4.2 bouyer * slk_attroff --
129 1.2.4.2 bouyer * Test and unset attributes on ripped off slk window.
130 1.2.4.2 bouyer */
131 1.2.4.2 bouyer int
132 1.2.4.2 bouyer slk_attroff(const chtype attr)
133 1.2.4.2 bouyer {
134 1.2.4.2 bouyer
135 1.2.4.2 bouyer return __slk_attroff(_cursesi_screen, attr);
136 1.2.4.2 bouyer }
137 1.2.4.2 bouyer
138 1.2.4.2 bouyer /*
139 1.2.4.2 bouyer * slk_attr_off --
140 1.2.4.2 bouyer * Test and unset wide attributes on ripped off slk window.
141 1.2.4.2 bouyer */
142 1.2.4.2 bouyer int
143 1.2.4.2 bouyer slk_attr_off(const attr_t attr, void *opt)
144 1.2.4.2 bouyer {
145 1.2.4.2 bouyer
146 1.2.4.2 bouyer return __slk_attr_off(_cursesi_screen, attr, opt);
147 1.2.4.2 bouyer }
148 1.2.4.2 bouyer
149 1.2.4.2 bouyer /*
150 1.2.4.2 bouyer * slk_attrset --
151 1.2.4.2 bouyer * Set attributes and color pair on ripped off slk window.
152 1.2.4.2 bouyer */
153 1.2.4.2 bouyer int
154 1.2.4.2 bouyer slk_attrset(const chtype attr)
155 1.2.4.2 bouyer {
156 1.2.4.2 bouyer
157 1.2.4.2 bouyer return __slk_attrset(_cursesi_screen, attr);
158 1.2.4.2 bouyer }
159 1.2.4.2 bouyer
160 1.2.4.2 bouyer /*
161 1.2.4.2 bouyer * slk_attr_set --
162 1.2.4.2 bouyer * Set wide attributes and color pair on ripped off slk window.
163 1.2.4.2 bouyer */
164 1.2.4.2 bouyer int
165 1.2.4.2 bouyer slk_attr_set(const attr_t attr, short pair, void *opt)
166 1.2.4.2 bouyer {
167 1.2.4.2 bouyer
168 1.2.4.2 bouyer return __slk_attr_set(_cursesi_screen, attr, pair, opt);
169 1.2.4.2 bouyer }
170 1.2.4.2 bouyer
171 1.2.4.2 bouyer /*
172 1.2.4.2 bouyer * slk_clear --
173 1.2.4.2 bouyer * Clear slk from the current screen.
174 1.2.4.2 bouyer */
175 1.2.4.2 bouyer int
176 1.2.4.2 bouyer slk_clear(void)
177 1.2.4.2 bouyer {
178 1.2.4.2 bouyer
179 1.2.4.2 bouyer return __slk_clear(_cursesi_screen);
180 1.2.4.2 bouyer }
181 1.2.4.2 bouyer
182 1.2.4.2 bouyer /*
183 1.2.4.2 bouyer * slk_color --
184 1.2.4.2 bouyer * Set color pair on ripped off slk window.
185 1.2.4.2 bouyer */
186 1.2.4.2 bouyer int
187 1.2.4.2 bouyer slk_color(short pair)
188 1.2.4.2 bouyer {
189 1.2.4.2 bouyer
190 1.2.4.2 bouyer return __slk_color(_cursesi_screen, pair);
191 1.2.4.2 bouyer }
192 1.2.4.2 bouyer
193 1.2.4.2 bouyer /*
194 1.2.4.2 bouyer * slk_label --
195 1.2.4.2 bouyer * Return a pointer to the saved label for key labnum.
196 1.2.4.2 bouyer */
197 1.2.4.2 bouyer char *
198 1.2.4.2 bouyer slk_label(int labnum)
199 1.2.4.2 bouyer {
200 1.2.4.2 bouyer
201 1.2.4.2 bouyer return __slk_label(_cursesi_screen, labnum);
202 1.2.4.2 bouyer }
203 1.2.4.2 bouyer
204 1.2.4.2 bouyer /*
205 1.2.4.2 bouyer * slk_wnoutrefresh --
206 1.2.4.2 bouyer * Add the contents of the ripped off slk window to the virtual window.
207 1.2.4.2 bouyer */
208 1.2.4.2 bouyer int
209 1.2.4.2 bouyer slk_noutrefresh(void)
210 1.2.4.2 bouyer {
211 1.2.4.2 bouyer
212 1.2.4.2 bouyer return __slk_noutrefresh(_cursesi_screen);
213 1.2.4.2 bouyer }
214 1.2.4.2 bouyer
215 1.2.4.2 bouyer /*
216 1.2.4.2 bouyer * slk_refresh --
217 1.2.4.2 bouyer * Force a refresh for the ripped off slk window.
218 1.2.4.2 bouyer */
219 1.2.4.2 bouyer int
220 1.2.4.2 bouyer slk_refresh(void)
221 1.2.4.2 bouyer {
222 1.2.4.2 bouyer
223 1.2.4.2 bouyer if (slk_noutrefresh() == ERR)
224 1.2.4.2 bouyer return ERR;
225 1.2.4.2 bouyer return doupdate();
226 1.2.4.2 bouyer }
227 1.2.4.2 bouyer
228 1.2.4.2 bouyer /*
229 1.2.4.2 bouyer * slk_restore --
230 1.2.4.2 bouyer * Retore slk to the screen after a slk_clear.
231 1.2.4.2 bouyer */
232 1.2.4.2 bouyer int
233 1.2.4.2 bouyer slk_restore(void)
234 1.2.4.2 bouyer {
235 1.2.4.2 bouyer
236 1.2.4.2 bouyer return __slk_restore(_cursesi_screen);
237 1.2.4.2 bouyer }
238 1.2.4.2 bouyer
239 1.2.4.2 bouyer /*
240 1.2.4.2 bouyer * slk_set --
241 1.2.4.2 bouyer * Sets the text of the label specified by labnum
242 1.2.4.2 bouyer * and how it is displayed.
243 1.2.4.2 bouyer */
244 1.2.4.2 bouyer int
245 1.2.4.2 bouyer slk_set(int labnum, const char *label, int justify)
246 1.2.4.2 bouyer {
247 1.2.4.2 bouyer
248 1.2.4.2 bouyer return __slk_set(_cursesi_screen, labnum, label, justify);
249 1.2.4.2 bouyer }
250 1.2.4.2 bouyer
251 1.2.4.2 bouyer /*
252 1.2.4.2 bouyer * slk_touch --
253 1.2.4.2 bouyer * Sets the ripped off slk window as modified.
254 1.2.4.2 bouyer */
255 1.2.4.2 bouyer int
256 1.2.4.2 bouyer slk_touch(void)
257 1.2.4.2 bouyer {
258 1.2.4.2 bouyer
259 1.2.4.2 bouyer return __slk_touch(_cursesi_screen);
260 1.2.4.2 bouyer }
261 1.2.4.2 bouyer
262 1.2.4.2 bouyer /*
263 1.2.4.2 bouyer * slk_wset --
264 1.2.4.2 bouyer * Sets the wide text of the label specified by labnum
265 1.2.4.2 bouyer * and how it is displayed.
266 1.2.4.2 bouyer */
267 1.2.4.2 bouyer int
268 1.2.4.2 bouyer slk_wset(int labnum, const wchar_t *label, int justify)
269 1.2.4.2 bouyer {
270 1.2.4.2 bouyer
271 1.2.4.2 bouyer return __slk_wset(_cursesi_screen, labnum, label, justify);
272 1.2.4.2 bouyer }
273 1.2.4.2 bouyer
274 1.2.4.2 bouyer /*
275 1.2.4.2 bouyer * __slk_attron --
276 1.2.4.2 bouyer * Test and set attributes on ripped off slk window.
277 1.2.4.2 bouyer */
278 1.2.4.2 bouyer static int
279 1.2.4.2 bouyer __slk_attron(SCREEN *screen, const chtype attr)
280 1.2.4.2 bouyer {
281 1.2.4.2 bouyer
282 1.2.4.2 bouyer if (screen == NULL || screen->slk_window == NULL)
283 1.2.4.2 bouyer return ERR;
284 1.2.4.2 bouyer return wattron(screen->slk_window, attr);
285 1.2.4.2 bouyer }
286 1.2.4.2 bouyer
287 1.2.4.2 bouyer /*
288 1.2.4.2 bouyer * __slk_attr_on --
289 1.2.4.2 bouyer * Test and set wide attributes on ripped off slk window.
290 1.2.4.2 bouyer */
291 1.2.4.2 bouyer static int
292 1.2.4.2 bouyer __slk_attr_on(SCREEN *screen, const attr_t attr, void *opt)
293 1.2.4.2 bouyer {
294 1.2.4.2 bouyer
295 1.2.4.2 bouyer if (screen == NULL || screen->slk_window == NULL)
296 1.2.4.2 bouyer return ERR;
297 1.2.4.2 bouyer return wattr_on(screen->slk_window, attr, opt);
298 1.2.4.2 bouyer }
299 1.2.4.2 bouyer
300 1.2.4.2 bouyer /*
301 1.2.4.2 bouyer * __slk_attroff --
302 1.2.4.2 bouyer * Test and unset attributes on ripped off slk window.
303 1.2.4.2 bouyer */
304 1.2.4.2 bouyer static int
305 1.2.4.2 bouyer __slk_attroff(SCREEN *screen, const chtype attr)
306 1.2.4.2 bouyer {
307 1.2.4.2 bouyer
308 1.2.4.2 bouyer if (screen == NULL || screen->slk_window == NULL)
309 1.2.4.2 bouyer return ERR;
310 1.2.4.2 bouyer return wattroff(screen->slk_window, attr);
311 1.2.4.2 bouyer }
312 1.2.4.2 bouyer
313 1.2.4.2 bouyer /*
314 1.2.4.2 bouyer * __slk_attr_off --
315 1.2.4.2 bouyer * Test and unset wide attributes on ripped off slk window.
316 1.2.4.2 bouyer */
317 1.2.4.2 bouyer static int
318 1.2.4.2 bouyer __slk_attr_off(SCREEN *screen, const attr_t attr, void *opt)
319 1.2.4.2 bouyer {
320 1.2.4.2 bouyer
321 1.2.4.2 bouyer if (screen == NULL || screen->slk_window == NULL)
322 1.2.4.2 bouyer return ERR;
323 1.2.4.2 bouyer return wattr_off(screen->slk_window, attr, opt);
324 1.2.4.2 bouyer }
325 1.2.4.2 bouyer
326 1.2.4.2 bouyer /*
327 1.2.4.2 bouyer * __slk_attrset --
328 1.2.4.2 bouyer * Set attributes and color pair on ripped off slk window.
329 1.2.4.2 bouyer */
330 1.2.4.2 bouyer static int
331 1.2.4.2 bouyer __slk_attrset(SCREEN *screen, const chtype attr)
332 1.2.4.2 bouyer {
333 1.2.4.2 bouyer
334 1.2.4.2 bouyer if (screen == NULL || screen->slk_window == NULL)
335 1.2.4.2 bouyer return ERR;
336 1.2.4.2 bouyer return wattrset(screen->slk_window, attr);
337 1.2.4.2 bouyer }
338 1.2.4.2 bouyer
339 1.2.4.2 bouyer /*
340 1.2.4.2 bouyer * __slk_attr_set --
341 1.2.4.2 bouyer * Set wide attributes and color pair on ripped off slk window.
342 1.2.4.2 bouyer */
343 1.2.4.2 bouyer static int
344 1.2.4.2 bouyer __slk_attr_set(SCREEN *screen, const attr_t attr, short pair, void *opt)
345 1.2.4.2 bouyer {
346 1.2.4.2 bouyer
347 1.2.4.2 bouyer if (screen == NULL || screen->slk_window == NULL)
348 1.2.4.2 bouyer return ERR;
349 1.2.4.2 bouyer return wattr_set(screen->slk_window, attr, pair, opt);
350 1.2.4.2 bouyer }
351 1.2.4.2 bouyer
352 1.2.4.2 bouyer /*
353 1.2.4.2 bouyer * __slk_clear --
354 1.2.4.2 bouyer * Clear slk from the current screen.
355 1.2.4.2 bouyer */
356 1.2.4.2 bouyer static int
357 1.2.4.2 bouyer __slk_clear(SCREEN *screen)
358 1.2.4.2 bouyer {
359 1.2.4.2 bouyer
360 1.2.4.2 bouyer if (screen == NULL)
361 1.2.4.2 bouyer return ERR;
362 1.2.4.2 bouyer screen->slk_hidden = true;
363 1.2.4.2 bouyer if (screen->is_term_slk) {
364 1.2.4.2 bouyer if (t_label_off(screen->term) == NULL)
365 1.2.4.2 bouyer return ERR;
366 1.2.4.2 bouyer return ti_putp(screen->term,
367 1.2.4.2 bouyer ti_tiparm(screen->term, t_label_off(screen->term)));
368 1.2.4.2 bouyer }
369 1.2.4.2 bouyer if (screen->slk_window == NULL)
370 1.2.4.2 bouyer return ERR;
371 1.2.4.2 bouyer werase(screen->slk_window);
372 1.2.4.2 bouyer return wrefresh(screen->slk_window);
373 1.2.4.2 bouyer }
374 1.2.4.2 bouyer
375 1.2.4.2 bouyer /*
376 1.2.4.2 bouyer * __slk_color --
377 1.2.4.2 bouyer * Set color pair on ripped off slk window.
378 1.2.4.2 bouyer */
379 1.2.4.2 bouyer static int
380 1.2.4.2 bouyer __slk_color(SCREEN *screen, short pair)
381 1.2.4.2 bouyer {
382 1.2.4.2 bouyer
383 1.2.4.2 bouyer if (screen == NULL || screen->slk_window == NULL)
384 1.2.4.2 bouyer return ERR;
385 1.2.4.2 bouyer return wcolor_set(screen->slk_window, pair, NULL);
386 1.2.4.2 bouyer }
387 1.2.4.2 bouyer
388 1.2.4.2 bouyer
389 1.2.4.2 bouyer /*
390 1.2.4.2 bouyer * __slk_label --
391 1.2.4.2 bouyer * Return a pointer to the saved label for key labnum.
392 1.2.4.2 bouyer */
393 1.2.4.2 bouyer static char *
394 1.2.4.2 bouyer __slk_label(SCREEN *screen, int labnum)
395 1.2.4.2 bouyer {
396 1.2.4.2 bouyer
397 1.2.4.2 bouyer if (screen == NULL || labnum < 1 || labnum > screen->slk_nlabels)
398 1.2.4.2 bouyer return NULL;
399 1.2.4.2 bouyer return screen->slk_labels[--labnum].text;
400 1.2.4.2 bouyer }
401 1.2.4.2 bouyer
402 1.2.4.2 bouyer /*
403 1.2.4.2 bouyer * __slk_wnoutrefresh --
404 1.2.4.2 bouyer * Add the contents of the ripped off slk window to the virtual window.
405 1.2.4.2 bouyer */
406 1.2.4.2 bouyer int
407 1.2.4.2 bouyer __slk_noutrefresh(SCREEN *screen)
408 1.2.4.2 bouyer {
409 1.2.4.2 bouyer
410 1.2.4.2 bouyer if (screen == NULL || screen->slk_window == NULL)
411 1.2.4.2 bouyer return ERR;
412 1.2.4.2 bouyer return wnoutrefresh(screen->slk_window);
413 1.2.4.2 bouyer }
414 1.2.4.2 bouyer
415 1.2.4.2 bouyer /*
416 1.2.4.2 bouyer * __slk_restore --
417 1.2.4.2 bouyer * Retore slk to the screen after a slk_clear.
418 1.2.4.2 bouyer */
419 1.2.4.2 bouyer static int
420 1.2.4.2 bouyer __slk_restore(SCREEN *screen)
421 1.2.4.2 bouyer {
422 1.2.4.2 bouyer
423 1.2.4.2 bouyer if (screen == NULL)
424 1.2.4.2 bouyer return ERR;
425 1.2.4.2 bouyer screen->slk_hidden = false;
426 1.2.4.2 bouyer if (screen->is_term_slk) {
427 1.2.4.2 bouyer if (t_label_on(screen->term) == NULL)
428 1.2.4.2 bouyer return ERR;
429 1.2.4.2 bouyer return ti_putp(screen->term,
430 1.2.4.2 bouyer ti_tiparm(screen->term, t_label_on(screen->term)));
431 1.2.4.2 bouyer }
432 1.2.4.2 bouyer if (screen->slk_window == NULL)
433 1.2.4.2 bouyer return ERR;
434 1.2.4.2 bouyer if (__slk_redraw(screen) == ERR)
435 1.2.4.2 bouyer return ERR;
436 1.2.4.2 bouyer return wrefresh(screen->slk_window);
437 1.2.4.2 bouyer }
438 1.2.4.2 bouyer
439 1.2.4.2 bouyer /*
440 1.2.4.2 bouyer * __slk_set --
441 1.2.4.2 bouyer * Sets the text of the label specified by labnum
442 1.2.4.2 bouyer * and how it is displayed.
443 1.2.4.2 bouyer */
444 1.2.4.2 bouyer static int
445 1.2.4.2 bouyer __slk_set(SCREEN *screen, int labnum, const char *label, int justify)
446 1.2.4.2 bouyer {
447 1.2.4.2 bouyer struct __slk_label *l;
448 1.2.4.2 bouyer const char *end;
449 1.2.4.2 bouyer size_t len;
450 1.2.4.2 bouyer char *text;
451 1.2.4.2 bouyer #ifdef HAVE_WCHAR
452 1.2.4.2 bouyer wchar_t wc;
453 1.2.4.2 bouyer size_t wc_len;
454 1.2.4.2 bouyer #endif
455 1.2.4.2 bouyer
456 1.2.4.2 bouyer /* Check args. */
457 1.2.4.2 bouyer if (screen == NULL || labnum < 1 || labnum > screen->slk_nlabels)
458 1.2.4.2 bouyer return ERR;
459 1.2.4.2 bouyer switch(justify) {
460 1.2.4.2 bouyer case SLK_JUSTIFY_LEFT:
461 1.2.4.2 bouyer case SLK_JUSTIFY_CENTER:
462 1.2.4.2 bouyer case SLK_JUSTIFY_RIGHT:
463 1.2.4.2 bouyer break;
464 1.2.4.2 bouyer default:
465 1.2.4.2 bouyer return ERR;
466 1.2.4.2 bouyer }
467 1.2.4.2 bouyer if (label == NULL)
468 1.2.4.2 bouyer label = "";
469 1.2.4.2 bouyer
470 1.2.4.2 bouyer /* Skip leading whitespace. */
471 1.2.4.2 bouyer while(isspace((unsigned char)*label))
472 1.2.4.2 bouyer label++;
473 1.2.4.2 bouyer /* Grab end. */
474 1.2.4.2 bouyer end = label;
475 1.2.4.2 bouyer
476 1.2.4.2 bouyer #ifdef HAVE_WCHAR
477 1.2.4.2 bouyer len = 0;
478 1.2.4.2 bouyer while (*end != '\0') {
479 1.2.4.2 bouyer if ((wc_len = mbrtowc(0, end, strlen(end), &screen->sp)) == -1)
480 1.2.4.2 bouyer return ERR;
481 1.2.4.2 bouyer mbrtowc(&wc, end, wc_len, &screen->sp);
482 1.2.4.2 bouyer if (!iswprint((wint_t)wc))
483 1.2.4.2 bouyer break;
484 1.2.4.2 bouyer len += wcwidth(wc);
485 1.2.4.2 bouyer end += wc_len;
486 1.2.4.2 bouyer }
487 1.2.4.2 bouyer #else
488 1.2.4.2 bouyer while(isprint((unsigned char)*end))
489 1.2.4.2 bouyer end++;
490 1.2.4.2 bouyer len = end - label;
491 1.2.4.2 bouyer #endif
492 1.2.4.2 bouyer
493 1.2.4.2 bouyer /* Take a backup, in-case we can grow the label. */
494 1.2.4.2 bouyer if ((text = strndup(label, len)) == NULL)
495 1.2.4.2 bouyer return ERR;
496 1.2.4.2 bouyer
497 1.2.4.2 bouyer /* All checks out, assign. */
498 1.2.4.2 bouyer l = &screen->slk_labels[--labnum]; /* internal zero based index */
499 1.2.4.2 bouyer l->text = text;
500 1.2.4.2 bouyer l->justify = justify;
501 1.2.4.2 bouyer
502 1.2.4.2 bouyer __slk_set_finalise(screen, labnum);
503 1.2.4.2 bouyer return OK;
504 1.2.4.2 bouyer }
505 1.2.4.2 bouyer
506 1.2.4.2 bouyer /*
507 1.2.4.2 bouyer * __slk_touch --
508 1.2.4.2 bouyer * Sets the ripped off slk window as modified.
509 1.2.4.2 bouyer */
510 1.2.4.2 bouyer static int
511 1.2.4.2 bouyer __slk_touch(SCREEN *screen)
512 1.2.4.2 bouyer {
513 1.2.4.2 bouyer
514 1.2.4.2 bouyer if (screen == NULL || screen->slk_window == NULL)
515 1.2.4.2 bouyer return ERR;
516 1.2.4.2 bouyer return touchwin(screen->slk_window);
517 1.2.4.2 bouyer }
518 1.2.4.2 bouyer
519 1.2.4.2 bouyer /*
520 1.2.4.2 bouyer * __slk_wset --
521 1.2.4.2 bouyer * Sets the wide text of the label specified by labnum
522 1.2.4.2 bouyer * and how it is displayed.
523 1.2.4.2 bouyer */
524 1.2.4.2 bouyer static int
525 1.2.4.2 bouyer __slk_wset(SCREEN *screen, int labnum, const wchar_t *label, int justify)
526 1.2.4.2 bouyer {
527 1.2.4.2 bouyer #ifdef HAVE_WCHAR
528 1.2.4.2 bouyer const wchar_t *olabel;
529 1.2.4.2 bouyer size_t len;
530 1.2.4.2 bouyer char *str;
531 1.2.4.2 bouyer int result = ERR;
532 1.2.4.2 bouyer
533 1.2.4.2 bouyer if (screen == NULL)
534 1.2.4.2 bouyer return ERR;
535 1.2.4.2 bouyer olabel = label;
536 1.2.4.2 bouyer if ((len = wcsrtombs(NULL, &olabel, 0, &screen->sp)) == -1)
537 1.2.4.2 bouyer return ERR;
538 1.2.4.2 bouyer len++; /* We need to store the NULL character. */
539 1.2.4.2 bouyer if ((str = malloc(len)) == NULL)
540 1.2.4.2 bouyer return ERR;
541 1.2.4.2 bouyer olabel = label;
542 1.2.4.2 bouyer if (wcsrtombs(str, &olabel, len, &screen->sp) == -1)
543 1.2.4.2 bouyer goto out;
544 1.2.4.2 bouyer result = __slk_set(screen, labnum, str, justify);
545 1.2.4.2 bouyer out:
546 1.2.4.2 bouyer free(str);
547 1.2.4.2 bouyer return result;
548 1.2.4.2 bouyer #else
549 1.2.4.2 bouyer return ERR;
550 1.2.4.2 bouyer #endif
551 1.2.4.2 bouyer }
552 1.2.4.2 bouyer
553 1.2.4.2 bouyer
554 1.2.4.2 bouyer /*
555 1.2.4.2 bouyer * __slk_init --
556 1.2.4.2 bouyer * Allocate structures.
557 1.2.4.2 bouyer */
558 1.2.4.2 bouyer int
559 1.2.4.2 bouyer __slk_init(SCREEN *screen)
560 1.2.4.2 bouyer {
561 1.2.4.2 bouyer
562 1.2.4.2 bouyer __slk_free(screen); /* safety */
563 1.2.4.2 bouyer
564 1.2.4.2 bouyer screen->slk_format = slk_fmt;
565 1.2.4.2 bouyer switch(screen->slk_format) {
566 1.2.4.2 bouyer case SLK_FMT_3_2_3:
567 1.2.4.2 bouyer case SLK_FMT_4_4:
568 1.2.4.2 bouyer screen->slk_nlabels = 8;
569 1.2.4.2 bouyer break;
570 1.2.4.2 bouyer default: /* impossible */
571 1.2.4.2 bouyer return ERR;
572 1.2.4.2 bouyer }
573 1.2.4.2 bouyer
574 1.2.4.2 bouyer screen->slk_labels = calloc(screen->slk_nlabels,
575 1.2.4.2 bouyer sizeof(*screen->slk_labels));
576 1.2.4.2 bouyer if (screen->slk_labels == NULL)
577 1.2.4.2 bouyer return ERR;
578 1.2.4.2 bouyer
579 1.2.4.2 bouyer screen->is_term_slk =
580 1.2.4.2 bouyer t_plab_norm(screen->term) != NULL &&
581 1.2.4.2 bouyer t_num_labels(screen->term) > 0;
582 1.2.4.2 bouyer if (screen->is_term_slk) {
583 1.2.4.2 bouyer __unripoffline(__slk_ripoffline);
584 1.2.4.2 bouyer screen->slk_nlabels = t_num_labels(screen->term);
585 1.2.4.2 bouyer screen->slk_label_len = t_label_width(screen->term);
586 1.2.4.2 bouyer /* XXX label_height, label_format? */
587 1.2.4.2 bouyer }
588 1.2.4.2 bouyer
589 1.2.4.2 bouyer return OK;
590 1.2.4.2 bouyer }
591 1.2.4.2 bouyer
592 1.2.4.2 bouyer /*
593 1.2.4.2 bouyer * __slk_free --
594 1.2.4.2 bouyer * Free allocates resources.
595 1.2.4.2 bouyer */
596 1.2.4.2 bouyer void
597 1.2.4.2 bouyer __slk_free(SCREEN *screen)
598 1.2.4.2 bouyer {
599 1.2.4.2 bouyer int i;
600 1.2.4.2 bouyer
601 1.2.4.2 bouyer if (screen->slk_window != NULL)
602 1.2.4.2 bouyer delwin(screen->slk_window);
603 1.2.4.2 bouyer for (i = 0; i < screen->slk_nlabels; i++)
604 1.2.4.2 bouyer free(screen->slk_labels[i].text);
605 1.2.4.2 bouyer free(screen->slk_labels);
606 1.2.4.2 bouyer }
607 1.2.4.2 bouyer
608 1.2.4.2 bouyer /*
609 1.2.4.2 bouyer * __slk_ripoffline --
610 1.2.4.2 bouyer * ripoffline callback to accept a WINDOW to create our keys.
611 1.2.4.2 bouyer */
612 1.2.4.2 bouyer static int
613 1.2.4.2 bouyer __slk_ripoffline(WINDOW *window, int cols)
614 1.2.4.2 bouyer {
615 1.2.4.2 bouyer
616 1.2.4.2 bouyer if (window == NULL)
617 1.2.4.2 bouyer return ERR;
618 1.2.4.2 bouyer window->screen->slk_window = window;
619 1.2.4.2 bouyer wattron(window,
620 1.2.4.2 bouyer (t_no_color_video(window->screen->term) & 1) == 0
621 1.2.4.2 bouyer ? A_STANDOUT : A_REVERSE);
622 1.2.4.2 bouyer __slk_resize(window->screen, cols);
623 1.2.4.2 bouyer return OK;
624 1.2.4.2 bouyer }
625 1.2.4.2 bouyer
626 1.2.4.2 bouyer /*
627 1.2.4.2 bouyer * __slk_resize --
628 1.2.4.2 bouyer * Size and position the labels in the ripped off slk window.
629 1.2.4.2 bouyer */
630 1.2.4.2 bouyer int
631 1.2.4.2 bouyer __slk_resize(SCREEN *screen, int cols)
632 1.2.4.2 bouyer {
633 1.2.4.2 bouyer int x = 0;
634 1.2.4.2 bouyer struct __slk_label *l;
635 1.2.4.2 bouyer
636 1.2.4.2 bouyer if (screen == NULL)
637 1.2.4.2 bouyer return ERR;
638 1.2.4.2 bouyer if (screen->is_term_slk || screen->slk_nlabels == 0)
639 1.2.4.2 bouyer return OK;
640 1.2.4.2 bouyer
641 1.2.4.2 bouyer screen->slk_label_len = (cols / screen->slk_nlabels) - 1;
642 1.2.4.2 bouyer if (screen->slk_label_len > SLK_SIZE)
643 1.2.4.2 bouyer screen->slk_label_len = SLK_SIZE;
644 1.2.4.2 bouyer
645 1.2.4.2 bouyer l = screen->slk_labels;
646 1.2.4.2 bouyer
647 1.2.4.2 bouyer switch(screen->slk_format) {
648 1.2.4.2 bouyer case SLK_FMT_3_2_3:
649 1.2.4.2 bouyer /* Left 3 */
650 1.2.4.2 bouyer (l++)->x = x;
651 1.2.4.2 bouyer (l++)->x = (x += screen->slk_label_len + 1);
652 1.2.4.2 bouyer (l++)->x = (x += screen->slk_label_len + 1);
653 1.2.4.2 bouyer
654 1.2.4.2 bouyer /* Middle 2 */
655 1.2.4.2 bouyer x = cols / 2;
656 1.2.4.2 bouyer (l++)->x = x -(screen->slk_label_len + 1);
657 1.2.4.2 bouyer (l++)->x = x + 1;
658 1.2.4.2 bouyer
659 1.2.4.2 bouyer /* Right 3 */
660 1.2.4.2 bouyer x = (cols - ((screen->slk_label_len + 1) * 3)) + 1;
661 1.2.4.2 bouyer (l++)->x = x;
662 1.2.4.2 bouyer (l++)->x = (x += screen->slk_label_len + 1);
663 1.2.4.2 bouyer (l++)->x = (x += screen->slk_label_len + 1);
664 1.2.4.2 bouyer break;
665 1.2.4.2 bouyer
666 1.2.4.2 bouyer case SLK_FMT_4_4:
667 1.2.4.2 bouyer {
668 1.2.4.2 bouyer int i, half;
669 1.2.4.2 bouyer
670 1.2.4.2 bouyer half = screen->slk_nlabels / 2;
671 1.2.4.2 bouyer for (i = 0; i < screen->slk_nlabels; i++) {
672 1.2.4.2 bouyer (l++)->x = x;
673 1.2.4.2 bouyer x += screen->slk_label_len;
674 1.2.4.2 bouyer /* Split labels in half */
675 1.2.4.2 bouyer if (i == half - 1)
676 1.2.4.2 bouyer x = cols - (screen->slk_label_len * half) + 1;
677 1.2.4.2 bouyer }
678 1.2.4.2 bouyer break;
679 1.2.4.2 bouyer }
680 1.2.4.2 bouyer }
681 1.2.4.2 bouyer
682 1.2.4.2 bouyer /* Write text to the labels. */
683 1.2.4.2 bouyer for (x = 0; x < screen->slk_nlabels; x++)
684 1.2.4.2 bouyer __slk_set_finalise(screen, x);
685 1.2.4.2 bouyer
686 1.2.4.2 bouyer return __slk_redraw(screen);
687 1.2.4.2 bouyer }
688 1.2.4.2 bouyer
689 1.2.4.2 bouyer /*
690 1.2.4.2 bouyer * __slk_set_finalise --
691 1.2.4.2 bouyer * Does the grunt work of positioning and sizing the text in the label.
692 1.2.4.2 bouyer */
693 1.2.4.2 bouyer static int
694 1.2.4.2 bouyer __slk_set_finalise(SCREEN *screen, int labnum)
695 1.2.4.2 bouyer {
696 1.2.4.2 bouyer struct __slk_label *l;
697 1.2.4.2 bouyer size_t spc, len, x;
698 1.2.4.2 bouyer char *p;
699 1.2.4.2 bouyer
700 1.2.4.2 bouyer l = &screen->slk_labels[labnum];
701 1.2.4.2 bouyer spc = screen->slk_label_len;
702 1.2.4.2 bouyer
703 1.2.4.2 bouyer #ifdef HAVE_WCHAR
704 1.2.4.2 bouyer len = 0;
705 1.2.4.2 bouyer if (l->text != NULL) {
706 1.2.4.2 bouyer wchar_t wc;
707 1.2.4.2 bouyer
708 1.2.4.2 bouyer p = l->text;
709 1.2.4.2 bouyer while (*p != '\0') {
710 1.2.4.2 bouyer if ((x = mbrtowc(0, p, strlen(p), &screen->sp)) == -1)
711 1.2.4.2 bouyer return ERR;
712 1.2.4.2 bouyer mbrtowc(&wc, p, x, &screen->sp);
713 1.2.4.2 bouyer if (len + wcwidth(wc) > spc)
714 1.2.4.2 bouyer break;
715 1.2.4.2 bouyer len += wcwidth(wc);
716 1.2.4.2 bouyer p += x;
717 1.2.4.2 bouyer }
718 1.2.4.2 bouyer }
719 1.2.4.2 bouyer #else
720 1.2.4.2 bouyer len = l->text == NULL ? 0 : strlen(l->text);
721 1.2.4.2 bouyer if (len > spc)
722 1.2.4.2 bouyer len = spc;
723 1.2.4.2 bouyer #endif
724 1.2.4.2 bouyer
725 1.2.4.2 bouyer switch(l->justify) {
726 1.2.4.2 bouyer case SLK_JUSTIFY_LEFT:
727 1.2.4.2 bouyer x = 0;
728 1.2.4.2 bouyer break;
729 1.2.4.2 bouyer case SLK_JUSTIFY_CENTER:
730 1.2.4.2 bouyer x = (spc - len) / 2;
731 1.2.4.2 bouyer if (x + len > spc)
732 1.2.4.2 bouyer x--;
733 1.2.4.2 bouyer break;
734 1.2.4.2 bouyer case SLK_JUSTIFY_RIGHT:
735 1.2.4.2 bouyer x = spc - len;
736 1.2.4.2 bouyer break;
737 1.2.4.2 bouyer default:
738 1.2.4.2 bouyer return ERR; /* impossible */
739 1.2.4.2 bouyer }
740 1.2.4.2 bouyer
741 1.2.4.2 bouyer p = l->label;
742 1.2.4.2 bouyer if (x != 0) {
743 1.2.4.2 bouyer memset(p, ' ', x);
744 1.2.4.2 bouyer p += x;
745 1.2.4.2 bouyer spc -= x;
746 1.2.4.2 bouyer }
747 1.2.4.2 bouyer if (len != 0) {
748 1.2.4.2 bouyer memcpy(p, l->text, len);
749 1.2.4.2 bouyer p += len;
750 1.2.4.2 bouyer spc -= len;
751 1.2.4.2 bouyer }
752 1.2.4.2 bouyer if (spc != 0) {
753 1.2.4.2 bouyer memset(p, ' ', spc);
754 1.2.4.2 bouyer p += spc;
755 1.2.4.2 bouyer }
756 1.2.4.2 bouyer *p = '\0'; /* Terminate for plab_norm. */
757 1.2.4.2 bouyer
758 1.2.4.2 bouyer return __slk_draw(screen, labnum);
759 1.2.4.2 bouyer }
760 1.2.4.2 bouyer
761 1.2.4.2 bouyer /*
762 1.2.4.2 bouyer * __slk_draw --
763 1.2.4.2 bouyer * Draws the specified key.
764 1.2.4.2 bouyer */
765 1.2.4.2 bouyer static int
766 1.2.4.2 bouyer __slk_draw(SCREEN *screen, int labnum)
767 1.2.4.2 bouyer {
768 1.2.4.2 bouyer const struct __slk_label *l;
769 1.2.4.2 bouyer
770 1.2.4.2 bouyer if (screen->slk_hidden)
771 1.2.4.2 bouyer return OK;
772 1.2.4.2 bouyer
773 1.2.4.2 bouyer l = &screen->slk_labels[labnum];
774 1.2.4.2 bouyer if (screen->is_term_slk)
775 1.2.4.2 bouyer return ti_putp(screen->term,
776 1.2.4.2 bouyer ti_tiparm(screen->term,
777 1.2.4.2 bouyer t_plab_norm(screen->term), labnum + 1, l->label));
778 1.2.4.2 bouyer else if (screen->slk_window != NULL)
779 1.2.4.2 bouyer return mvwaddnstr(screen->slk_window, 0, l->x,
780 1.2.4.2 bouyer l->label, screen->slk_label_len);
781 1.2.4.2 bouyer else
782 1.2.4.2 bouyer return ERR;
783 1.2.4.2 bouyer }
784 1.2.4.2 bouyer
785 1.2.4.2 bouyer /*
786 1.2.4.2 bouyer * __slk_draw --
787 1.2.4.2 bouyer * Draws all the keys.
788 1.2.4.2 bouyer */
789 1.2.4.2 bouyer static int
790 1.2.4.2 bouyer __slk_redraw(SCREEN *screen)
791 1.2.4.2 bouyer {
792 1.2.4.2 bouyer int i, result = OK;
793 1.2.4.2 bouyer
794 1.2.4.2 bouyer for (i = 0; i < screen->slk_nlabels; i++) {
795 1.2.4.2 bouyer if (__slk_draw(screen, i) == ERR)
796 1.2.4.2 bouyer result = ERR;
797 1.2.4.2 bouyer }
798 1.2.4.2 bouyer return result;
799 1.2.4.2 bouyer }
800