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