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