Annotation of embedaddon/trafshow/selector.c, revision 1.1.1.1
1.1 misho 1: /*
2: * Copyright (c) 1998,2004 Rinet Corp., Novosibirsk, Russia
3: *
4: * Redistribution and use in source forms, with and without modification,
5: * are permitted provided that this entire comment appears intact.
6: *
7: * THIS SOURCE CODE IS PROVIDED ``AS IS'' WITHOUT ANY WARRANTIES OF ANY KIND.
8: */
9:
10: #ifdef HAVE_CONFIG_H
11: #include <config.h>
12: #endif
13:
14: #ifdef HAVE_SLCURSES
15: #include <slcurses.h>
16: #elif HAVE_NCURSES
17: #include <ncurses.h>
18: #else
19: #include <curses.h>
20: #endif
21: #include <stdlib.h>
22: #include <string.h>
23:
24: #include "selector.h"
25: #include "screen.h"
26: #include "getkey.h"
27:
28: #define BLANK ' '
29:
30: #ifdef ACS_HLINE
31: #define HLINE ACS_HLINE
32: #else
33: #define HLINE '-'
34: #endif
35:
36: static void get_size(const SELECTOR *sp, int *lines, int *cols);
37: static void get_colors(const SELECTOR *sp, int *foreground, int *cursor);
38:
39: static void
40: get_size(sp, lines, cols)
41: const SELECTOR *sp;
42: int *lines, *cols;
43: {
44: int ln = LINES, cl = COLS;
45: if (sp) {
46: if (sp->LINES > 0 && sp->LINES < LINES)
47: ln = sp->LINES;
48: if (sp->get_header)
49: ln -= 2;
50: if (sp->get_footer)
51: ln -= 2;
52: if (ln < 1)
53: ln = 1;
54:
55: if (sp->COLS > 0 && sp->COLS < COLS)
56: cl = sp->COLS;
57: if (cl < 1)
58: cl = 1;
59: }
60: if (lines) *lines = ln;
61: if (cols) *cols = cl;
62: }
63:
64: static void
65: get_colors(sp, fore, curs)
66: const SELECTOR *sp;
67: int *fore, *curs;
68: {
69: int fg = A_NORMAL, cr = A_REVERSE;
70: if (sp && use_colors) {
71: if (sp->window_color != -1)
72: fg = sp->window_color;
73: if (sp->cursor_color != -1)
74: cr = sp->cursor_color;
75: }
76: if (prompt_mode) cr = fg;
77: if (fore) *fore = fg;
78: if (curs) *curs = cr;
79: }
80:
81: /*
82: * Allocate & initialize selector handler.
83: */
84: SELECTOR *
85: selector_init()
86: {
87: SELECTOR *sp = (SELECTOR *)malloc(sizeof(SELECTOR));
88: if (sp) {
89: memset(sp, 0, sizeof(SELECTOR));
90: sp->window_color = -1;
91: sp->cursor_color = -1;
92: }
93: return sp;
94: }
95:
96: /*
97: * Redraw selector region and refresh screen.
98: */
99: void
100: selector_redraw(sp)
101: SELECTOR *sp;
102: {
103: int i, l, r, lines, cols, first_line, first_col;
104: int fg_color, cr_color, attr;
105: char *cp, buf[1024];
106:
107: /* sanity check */
108: if (!sp) return;
109:
110: if (sp->index >= sp->items)
111: selector_set(sp->items - 1, sp);
112:
113: get_size(sp, &lines, &cols);
114: get_colors(sp, &fg_color, &cr_color);
115:
116: first_line = sp->LINE;
117: first_col = sp->COL;
118:
119: attrset(A_NORMAL);
120:
121: #ifdef HAVE_WREDRAWLN
122: wredrawln(stdscr, first_line, lines + 2);
123: #endif
124:
125: /* draw header */
126: if (sp->get_header) {
127: attr = fg_color;
128: attr |= (*sp->get_header)(buf, sizeof(buf), sp->header);
129:
130: move(first_line, first_col);
131: r = cols;
132: for (cp = buf; *cp && r-- > 0; cp++) {
133: if (*cp > ' ')
134: addch(*cp | attr);
135: else addch(BLANK | attr);
136: }
137: while (r-- > 0) addch(BLANK | attr);
138:
139: move(first_line + 1, first_col);
140: r = cols;
141: while (r-- > 0) addch(HLINE | attr);
142:
143: first_line += 2;
144: }
145:
146: /* draw main area */
147: for (i = sp->fline, l = 0; l < lines; i++, l++) {
148: attr = fg_color;
149: move(first_line + l, first_col);
150: r = cols;
151: if (i < sp->items && sp->get_line) {
152: attr |= (*sp->get_line)(buf, sizeof(buf), sp->list, i);
153: if (i == sp->index)
154: attr = cr_color;
155: for (cp = buf; *cp && r-- > 0; cp++) {
156: if (*cp > ' ')
157: addch(*cp | attr);
158: else addch(BLANK | attr);
159:
160: /* workaround -- last attr mustbe foreground */
161: if (r == 1 && i == sp->items - 1)
162: attr = fg_color;
163: }
164: }
165: while (r-- > 0) addch(BLANK | attr);
166: }
167:
168: /* draw footer */
169: if (sp->get_footer) {
170: attr = fg_color;
171: attr |= (*sp->get_footer)(buf, sizeof(buf), sp->footer);
172:
173: first_line += l;
174: move(first_line++, first_col);
175: r = cols;
176: while (r-- > 0) addch(HLINE | attr);
177:
178: if (!prompt_mode || first_line != LINES-1) {
179: move(first_line, first_col);
180: r = cols;
181: for (cp = buf; *cp && r-- > 0; cp++) {
182: if (*cp > ' ')
183: addch(*cp | attr);
184: else addch(BLANK | attr);
185: }
186: while (r-- > 0) addch(BLANK | attr);
187: }
188: }
189:
190: /* refresh screen */
191: screen_update();
192: }
193:
194: /*
195: * Withdraw selector from the screen.
196: */
197: void
198: selector_withdraw(sp)
199: SELECTOR *sp;
200: {
201: int i, l, r, lines, cols, first_line, first_col;
202: int fg_color, attr;
203: char *cp, buf[1024];
204:
205: /* sanity check */
206: if (!sp || !sp->get_line) return;
207:
208: get_size(sp, &lines, &cols);
209: get_colors(sp, &fg_color, 0);
210:
211: first_line = sp->LINE;
212: first_col = sp->COL;
213:
214: attrset(A_NORMAL);
215:
216: if (sp->get_header)
217: first_line += 2;
218:
219: #ifdef HAVE_WREDRAWLN
220: wredrawln(stdscr, first_line, lines);
221: #endif
222: for (i = sp->fline, l = 0; l < lines; i++, l++) {
223: if (i != sp->index)
224: continue;
225: attr = fg_color;
226: move(first_line + l, first_col);
227: r = cols;
228: if (i < sp->items && sp->get_line) {
229: attr |= (*sp->get_line)(buf, sizeof(buf), sp->list, i);
230: for (cp = buf; *cp && r-- > 0; cp++) {
231: if (*cp > ' ')
232: addch(*cp | attr);
233: else addch(BLANK | attr);
234:
235: /* workaround -- last attr mustbe foreground */
236: if (r == 1 && i == sp->items - 1)
237: attr = fg_color;
238: }
239: while (r-- > 0) addch(BLANK | attr);
240: }
241: break;
242: }
243: }
244:
245: /*
246: * Return current selector position or -1 if no selector present.
247: */
248: int
249: selector_get(sp)
250: SELECTOR *sp;
251: {
252: /* sanity check */
253: if (!sp || !sp->list || sp->items < 1 ||
254: sp->index < 0 || sp->index >= sp->items)
255: return -1;
256: return sp->index;
257: }
258:
259: /*
260: * Set selector to requested position.
261: */
262: void
263: selector_set(new_index, sp)
264: int new_index;
265: SELECTOR *sp;
266: {
267: int lines;
268:
269: /* sanity check */
270: if (!sp) return;
271:
272: if (sp->items < 1) {
273: sp->index = 0;
274: sp->fline = 0;
275: sp->cline = 0;
276: return;
277: }
278: get_size(sp, &lines, 0);
279:
280: if (new_index >= sp->items)
281: new_index = sp->items - 1;
282:
283: sp->fline = (new_index / lines) * lines;
284: sp->cline = new_index % lines;
285: if (sp->fline + lines >= sp->items) {
286: sp->fline = sp->items - lines;
287: if (sp->fline < 0) sp->fline = 0;
288: sp->cline = new_index - sp->fline;
289: }
290: sp->index = new_index;
291: }
292:
293: /*
294: * Move selector on screen.
295: * Return index selected or -1.
296: */
297: int
298: selector_move(ch, sp)
299: int ch;
300: SELECTOR *sp;
301: {
302: int lines;
303:
304: /* sanity check */
305: if (!sp) return -1;
306:
307: get_size(sp, &lines, 0);
308:
309: switch (ch) {
310: case 'k':
311: case K_CTRL('P'):
312: case K_UP: /* line up */
313: if (sp->index - 1 < 0) break;
314: sp->index--;
315: if (--sp->cline < 0 && sp->fline) {
316: sp->cline = 0;
317: if (--sp->fline < 0)
318: sp->fline = 0;
319: }
320: break;
321:
322: case 'j':
323: case K_CTRL('N'):
324: case K_DOWN: /* line down */
325: if (sp->index + 1 >= sp->items) break;
326: sp->index++;
327: if (++sp->cline >= lines) {
328: sp->cline--;
329: sp->fline = sp->index - sp->cline;
330: }
331: break;
332:
333: case K_BS:
334: case K_CTRL('U'):
335: case K_CTRL('B'):
336: case K_PAGEUP: /* page up */
337: if (sp->cline > 0) {
338: sp->index -= sp->cline;
339: } else {
340: sp->index -= lines;
341: sp->fline -= lines;
342: if (sp->index < 0 || sp->fline < 0)
343: sp->index = sp->fline = 0;
344: }
345: sp->cline = 0;
346: break;
347:
348: case ' ':
349: case K_CTRL('D'):
350: case K_CTRL('F'):
351: case K_PAGEDOWN: /* page down */
352: if (sp->items <= lines) {
353: sp->index = sp->cline = sp->items - 1;
354: } else {
355: if (sp->cline < lines - 1) {
356: sp->index += lines - sp->cline - 1;
357: } else {
358: sp->index += lines;
359: sp->fline = sp->index - lines + 1;
360: }
361: if (sp->index >= sp->items) {
362: sp->index = sp->items - 1;
363: sp->fline = sp->items - lines;
364: }
365: sp->cline = lines - 1;
366: }
367: break;
368:
369: case K_CTRL('A'):
370: case K_HOME: /* home */
371: sp->index = 0;
372: sp->fline = 0;
373: sp->cline = 0;
374: break;
375:
376: case K_CTRL('E'):
377: case K_END: /* end */
378: if (sp->items <= lines) {
379: sp->index = sp->cline = sp->items - 1;
380: } else {
381: sp->index = sp->items - 1;
382: sp->fline = sp->items - lines;
383: sp->cline = lines - 1;
384: }
385: break;
386:
387: case K_CR: /* select index */
388: case K_NL:
389: return sp->index;
390:
391: case K_CTRL('G'): /* trace; for debug purpose only */
392: mvprintw(LINES-1, 0, "items=%d index=%d fline=%d cline=%d LINE=%d COL=%d LINES=%d func=%p",
393: sp->items, sp->index, sp->fline,
394: sp->cline, sp->LINE, sp->COL,
395: lines, sp->get_line);
396: clrtoeol();
397: break;
398: }
399: return -1;
400: }
401:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>