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