|
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 |