pdcurses/slk.c

changeset 97
2d43f05b284c
equal deleted inserted replaced
96:5314ebdcb38d 97:2d43f05b284c
1 /* Public Domain Curses */
2
3 #include <curspriv.h>
4
5 RCSID("$Id: slk.c,v 1.61 2008/07/13 16:08:18 wmcbrine Exp $")
6
7 /*man-start**************************************************************
8
9 Name: slk
10
11 Synopsis:
12 int slk_init(int fmt);
13 int slk_set(int labnum, const char *label, int justify);
14 int slk_refresh(void);
15 int slk_noutrefresh(void);
16 char *slk_label(int labnum);
17 int slk_clear(void);
18 int slk_restore(void);
19 int slk_touch(void);
20 int slk_attron(const chtype attrs);
21 int slk_attr_on(const attr_t attrs, void *opts);
22 int slk_attrset(const chtype attrs);
23 int slk_attr_set(const attr_t attrs, short color_pair, void *opts);
24 int slk_attroff(const chtype attrs);
25 int slk_attr_off(const attr_t attrs, void *opts);
26 int slk_color(short color_pair);
27
28 int slk_wset(int labnum, const wchar_t *label, int justify);
29
30 int PDC_mouse_in_slk(int y, int x);
31 void PDC_slk_free(void);
32 void PDC_slk_initialize(void);
33
34 wchar_t *slk_wlabel(int labnum)
35
36 Description:
37 These functions manipulate a window that contain Soft Label Keys
38 (SLK). To use the SLK functions, a call to slk_init() must be
39 made BEFORE initscr() or newterm(). slk_init() removes 1 or 2
40 lines from the useable screen, depending on the format selected.
41
42 The line(s) removed from the screen are used as a separate
43 window, in which SLKs are displayed.
44
45 slk_init() requires a single parameter which describes the
46 format of the SLKs as follows:
47
48 0 3-2-3 format
49 1 4-4 format
50 2 4-4-4 format (ncurses extension)
51 3 4-4-4 format with index line (ncurses extension)
52 2 lines used
53 55 5-5 format (pdcurses format)
54
55 slk_refresh(), slk_noutrefresh() and slk_touch() are analogous
56 to refresh(), noutrefresh() and touch().
57
58 Return Value:
59 All functions return OK on success and ERR on error.
60
61 Portability X/Open BSD SYS V
62 slk_init Y - Y
63 slk_set Y - Y
64 slk_refresh Y - Y
65 slk_noutrefresh Y - Y
66 slk_label Y - Y
67 slk_clear Y - Y
68 slk_restore Y - Y
69 slk_touch Y - Y
70 slk_attron Y - Y
71 slk_attrset Y - Y
72 slk_attroff Y - Y
73 slk_attr_on Y
74 slk_attr_set Y
75 slk_attr_off Y
76 slk_wset Y
77 PDC_mouse_in_slk - - -
78 PDC_slk_free - - -
79 PDC_slk_initialize - - -
80 slk_wlabel - - -
81
82 **man-end****************************************************************/
83
84 #include <stdlib.h>
85
86 enum { LABEL_NORMAL = 8, LABEL_EXTENDED = 10, LABEL_NCURSES_EXTENDED = 12 };
87
88 static int label_length = 0;
89 static int labels = 0;
90 static int label_fmt = 0;
91 static int label_line = 0;
92 static bool hidden = FALSE;
93
94 static struct SLK {
95 chtype label[32];
96 int len;
97 int format;
98 int start_col;
99 } *slk = (struct SLK *)NULL;
100
101 /* slk_init() is the slk initialization routine.
102 This must be called before initscr().
103
104 label_fmt = 0, 1 or 55.
105 0 = 3-2-3 format
106 1 = 4 - 4 format
107 2 = 4-4-4 format (ncurses extension for PC 12 function keys)
108 3 = 4-4-4 format (ncurses extension for PC 12 function keys -
109 with index line)
110 55 = 5 - 5 format (extended for PC, 10 function keys) */
111
112 int slk_init(int fmt)
113 {
114 PDC_LOG(("slk_init() - called\n"));
115
116 if (SP)
117 return ERR;
118
119 switch (fmt)
120 {
121 case 0: /* 3 - 2 - 3 */
122 labels = LABEL_NORMAL;
123 break;
124
125 case 1: /* 4 - 4 */
126 labels = LABEL_NORMAL;
127 break;
128
129 case 2: /* 4 4 4 */
130 labels = LABEL_NCURSES_EXTENDED;
131 break;
132
133 case 3: /* 4 4 4 with index */
134 labels = LABEL_NCURSES_EXTENDED;
135 break;
136
137 case 55: /* 5 - 5 */
138 labels = LABEL_EXTENDED;
139 break;
140
141 default:
142 return ERR;
143 }
144
145 label_fmt = fmt;
146
147 slk = calloc(labels, sizeof(struct SLK));
148
149 if (!slk)
150 labels = 0;
151
152 return slk ? OK : ERR;
153 }
154
155 /* draw a single button */
156
157 static void _drawone(int num)
158 {
159 int i, col, slen;
160
161 if (hidden)
162 return;
163
164 slen = slk[num].len;
165
166 switch (slk[num].format)
167 {
168 case 0: /* LEFT */
169 col = 0;
170 break;
171
172 case 1: /* CENTER */
173 col = (label_length - slen) / 2;
174
175 if (col + slen > label_length)
176 --col;
177 break;
178
179 default: /* RIGHT */
180 col = label_length - slen;
181 }
182
183 wmove(SP->slk_winptr, label_line, slk[num].start_col);
184
185 for (i = 0; i < label_length; ++i)
186 waddch(SP->slk_winptr, (i >= col && i < (col + slen)) ?
187 slk[num].label[i - col] : ' ');
188 }
189
190 /* redraw each button */
191
192 static void _redraw(void)
193 {
194 int i;
195
196 for (i = 0; i < labels; ++i)
197 _drawone(i);
198 }
199
200 /* slk_set() Used to set a slk label to a string.
201
202 labnum = 1 - 8 (or 10) (number of the label)
203 label = string (8 or 7 bytes total), or NULL
204 justify = 0 : left, 1 : center, 2 : right */
205
206 int slk_set(int labnum, const char *label, int justify)
207 {
208 #ifdef PDC_WIDE
209 wchar_t wlabel[32];
210
211 PDC_mbstowcs(wlabel, label, 31);
212 return slk_wset(labnum, wlabel, justify);
213 #else
214 PDC_LOG(("slk_set() - called\n"));
215
216 if (labnum < 1 || labnum > labels || justify < 0 || justify > 2)
217 return ERR;
218
219 labnum--;
220
221 if (!label || !(*label))
222 {
223 /* Clear the label */
224
225 *slk[labnum].label = 0;
226 slk[labnum].format = 0;
227 slk[labnum].len = 0;
228 }
229 else
230 {
231 int i, j = 0;
232
233 /* Skip leading spaces */
234
235 while (label[j] == ' ')
236 j++;
237
238 /* Copy it */
239
240 for (i = 0; i < label_length; i++)
241 {
242 chtype ch = label[i + j];
243
244 slk[labnum].label[i] = ch;
245
246 if (!ch)
247 break;
248 }
249
250 /* Drop trailing spaces */
251
252 while ((i + j) && (label[i + j - 1] == ' '))
253 i--;
254
255 slk[labnum].label[i] = 0;
256 slk[labnum].format = justify;
257 slk[labnum].len = i;
258 }
259
260 _drawone(labnum);
261
262 return OK;
263 #endif
264 }
265
266 int slk_refresh(void)
267 {
268 PDC_LOG(("slk_refresh() - called\n"));
269
270 return (slk_noutrefresh() == ERR) ? ERR : doupdate();
271 }
272
273 int slk_noutrefresh(void)
274 {
275 PDC_LOG(("slk_noutrefresh() - called\n"));
276
277 return wnoutrefresh(SP->slk_winptr);
278 }
279
280 char *slk_label(int labnum)
281 {
282 static char temp[33];
283 #ifdef PDC_WIDE
284 wchar_t *wtemp = slk_wlabel(labnum);
285
286 PDC_wcstombs(temp, wtemp, 32);
287 #else
288 chtype *p;
289 int i;
290
291 PDC_LOG(("slk_label() - called\n"));
292
293 if (labnum < 1 || labnum > labels)
294 return (char *)0;
295
296 for (i = 0, p = slk[labnum - 1].label; *p; i++)
297 temp[i] = *p++;
298
299 temp[i] = '\0';
300 #endif
301 return temp;
302 }
303
304 int slk_clear(void)
305 {
306 PDC_LOG(("slk_clear() - called\n"));
307
308 hidden = TRUE;
309 werase(SP->slk_winptr);
310 return wrefresh(SP->slk_winptr);
311 }
312
313 int slk_restore(void)
314 {
315 PDC_LOG(("slk_restore() - called\n"));
316
317 hidden = FALSE;
318 _redraw();
319 return wrefresh(SP->slk_winptr);
320 }
321
322 int slk_touch(void)
323 {
324 PDC_LOG(("slk_touch() - called\n"));
325
326 return touchwin(SP->slk_winptr);
327 }
328
329 int slk_attron(const chtype attrs)
330 {
331 int rc;
332
333 PDC_LOG(("slk_attron() - called\n"));
334
335 rc = wattron(SP->slk_winptr, attrs);
336 _redraw();
337
338 return rc;
339 }
340
341 int slk_attr_on(const attr_t attrs, void *opts)
342 {
343 PDC_LOG(("slk_attr_on() - called\n"));
344
345 return slk_attron(attrs);
346 }
347
348 int slk_attroff(const chtype attrs)
349 {
350 int rc;
351
352 PDC_LOG(("slk_attroff() - called\n"));
353
354 rc = wattroff(SP->slk_winptr, attrs);
355 _redraw();
356
357 return rc;
358 }
359
360 int slk_attr_off(const attr_t attrs, void *opts)
361 {
362 PDC_LOG(("slk_attr_off() - called\n"));
363
364 return slk_attroff(attrs);
365 }
366
367 int slk_attrset(const chtype attrs)
368 {
369 int rc;
370
371 PDC_LOG(("slk_attrset() - called\n"));
372
373 rc = wattrset(SP->slk_winptr, attrs);
374 _redraw();
375
376 return rc;
377 }
378
379 int slk_color(short color_pair)
380 {
381 int rc;
382
383 PDC_LOG(("slk_color() - called\n"));
384
385 rc = wcolor_set(SP->slk_winptr, color_pair, NULL);
386 _redraw();
387
388 return rc;
389 }
390
391 int slk_attr_set(const attr_t attrs, short color_pair, void *opts)
392 {
393 PDC_LOG(("slk_attr_set() - called\n"));
394
395 return slk_attrset(attrs | COLOR_PAIR(color_pair));
396 }
397
398 static void _slk_calc(void)
399 {
400 int i, center, col = 0;
401 label_length = COLS / labels;
402
403 if (label_length > 31)
404 label_length = 31;
405
406 switch (label_fmt)
407 {
408 case 0: /* 3 - 2 - 3 F-Key layout */
409
410 --label_length;
411
412 slk[0].start_col = col;
413 slk[1].start_col = (col += label_length);
414 slk[2].start_col = (col += label_length);
415
416 center = COLS / 2;
417
418 slk[3].start_col = center - label_length + 1;
419 slk[4].start_col = center + 1;
420
421 col = COLS - (label_length * 3) + 1;
422
423 slk[5].start_col = col;
424 slk[6].start_col = (col += label_length);
425 slk[7].start_col = (col += label_length);
426 break;
427
428 case 1: /* 4 - 4 F-Key layout */
429
430 for (i = 0; i < 8; i++)
431 {
432 slk[i].start_col = col;
433 col += label_length;
434
435 if (i == 3)
436 col = COLS - (label_length * 4) + 1;
437 }
438
439 break;
440
441 case 2: /* 4 4 4 F-Key layout */
442 case 3: /* 4 4 4 F-Key layout with index */
443
444 for (i = 0; i < 4; i++)
445 {
446 slk[i].start_col = col;
447 col += label_length;
448 }
449
450 center = COLS/2;
451
452 slk[4].start_col = center - (label_length * 2) + 1;
453 slk[5].start_col = center - label_length - 1;
454 slk[6].start_col = center + 1;
455 slk[7].start_col = center + label_length + 1;
456
457 col = COLS - (label_length * 4) + 1;
458
459 for (i = 8; i < 12; i++)
460 {
461 slk[i].start_col = col;
462 col += label_length;
463 }
464
465 break;
466
467 default: /* 5 - 5 F-Key layout */
468
469 for (i = 0; i < 10; i++)
470 {
471 slk[i].start_col = col;
472 col += label_length;
473
474 if (i == 4)
475 col = COLS - (label_length * 5) + 1;
476 }
477 }
478
479 --label_length;
480
481 /* make sure labels are all in window */
482
483 _redraw();
484 }
485
486 void PDC_slk_initialize(void)
487 {
488 if (slk)
489 {
490 if (label_fmt == 3)
491 {
492 SP->slklines = 2;
493 label_line = 1;
494 }
495 else
496 SP->slklines = 1;
497
498 if (!SP->slk_winptr)
499 {
500 if ( !(SP->slk_winptr = newwin(SP->slklines, COLS,
501 LINES - SP->slklines, 0)) )
502 return;
503
504 wattrset(SP->slk_winptr, A_REVERSE);
505 }
506
507 _slk_calc();
508
509 /* if we have an index line, display it now */
510
511 if (label_fmt == 3)
512 {
513 chtype save_attr;
514 int i;
515
516 save_attr = SP->slk_winptr->_attrs;
517 wattrset(SP->slk_winptr, A_NORMAL);
518 wmove(SP->slk_winptr, 0, 0);
519 whline(SP->slk_winptr, 0, COLS);
520
521 for (i = 0; i < labels; i++)
522 mvwprintw(SP->slk_winptr, 0, slk[i].start_col, "F%d", i + 1);
523
524 SP->slk_winptr->_attrs = save_attr;
525 }
526
527 touchwin(SP->slk_winptr);
528 }
529 }
530
531 void PDC_slk_free(void)
532 {
533 if (slk)
534 {
535 if (SP->slk_winptr)
536 {
537 delwin(SP->slk_winptr);
538 SP->slk_winptr = (WINDOW *)NULL;
539 }
540
541 free(slk);
542 slk = (struct SLK *)NULL;
543
544 label_length = 0;
545 labels = 0;
546 label_fmt = 0;
547 label_line = 0;
548 hidden = FALSE;
549 }
550 }
551
552 int PDC_mouse_in_slk(int y, int x)
553 {
554 int i;
555
556 PDC_LOG(("PDC_mouse_in_slk() - called: y->%d x->%d\n", y, x));
557
558 /* If the line on which the mouse was clicked is NOT the last line
559 of the screen, we are not interested in it. */
560
561 if (!slk || !SP->slk_winptr || (y != SP->slk_winptr->_begy + label_line))
562 return 0;
563
564 for (i = 0; i < labels; i++)
565 if (x >= slk[i].start_col && x < (slk[i].start_col + label_length))
566 return i + 1;
567
568 return 0;
569 }
570
571 #ifdef PDC_WIDE
572 int slk_wset(int labnum, const wchar_t *label, int justify)
573 {
574 PDC_LOG(("slk_wset() - called\n"));
575
576 if (labnum < 1 || labnum > labels || justify < 0 || justify > 2)
577 return ERR;
578
579 labnum--;
580
581 if (!label || !(*label))
582 {
583 /* Clear the label */
584
585 *slk[labnum].label = 0;
586 slk[labnum].format = 0;
587 slk[labnum].len = 0;
588 }
589 else
590 {
591 int i, j = 0;
592
593 /* Skip leading spaces */
594
595 while (label[j] == L' ')
596 j++;
597
598 /* Copy it */
599
600 for (i = 0; i < label_length; i++)
601 {
602 chtype ch = label[i + j];
603
604 slk[labnum].label[i] = ch;
605
606 if (!ch)
607 break;
608 }
609
610 /* Drop trailing spaces */
611
612 while ((i + j) && (label[i + j - 1] == L' '))
613 i--;
614
615 slk[labnum].label[i] = 0;
616 slk[labnum].format = justify;
617 slk[labnum].len = i;
618 }
619
620 _drawone(labnum);
621
622 return OK;
623 }
624
625 wchar_t *slk_wlabel(int labnum)
626 {
627 static wchar_t temp[33];
628 chtype *p;
629 int i;
630
631 PDC_LOG(("slk_wlabel() - called\n"));
632
633 if (labnum < 1 || labnum > labels)
634 return (wchar_t *)0;
635
636 for (i = 0, p = slk[labnum - 1].label; *p; i++)
637 temp[i] = *p++;
638
639 temp[i] = '\0';
640
641 return temp;
642 }
643 #endif

mercurial