download, progress, improved screen updates...
[oftp] / src / unix / tgfx.c
1 #include <curses.h>
2 #include "tgfx.h"
3 #include "util.h"
4
5 struct cpair {
6         int pair;
7         int fg, bg;
8 };
9 static struct cpair *colors;
10 static int num_colors;
11
12 static int fgcol, bgcol;
13 static int bgchar;
14 static int cur_pair;
15 static int cur_x, cur_y;
16
17 static int curses_color(int col);
18 static void upd_color(void);
19
20 void tg_init(void)
21 {
22         initscr();
23         cbreak();
24         keypad(stdscr, TRUE);
25         nodelay(stdscr, TRUE);
26         noecho();
27         curs_set(0);
28         start_color();
29
30         fgcol = curses_color(TGFX_WHITE);
31         bgcol = curses_color(TGFX_BLACK);
32         bgchar = ' ';
33
34         colors = malloc_nf(COLORS * sizeof *colors);
35         num_colors = 0;
36 }
37
38 void tg_cleanup(void)
39 {
40         endwin();
41 }
42
43 void tg_redraw(void)
44 {
45         move(cur_y, cur_x);
46         refresh();
47 }
48
49 void tg_clear(void)
50 {
51         clear();
52 }
53
54
55 void tg_fgcolor(int col)
56 {
57         fgcol = curses_color(col);
58 }
59
60 void tg_bgcolor(int col)
61 {
62         bgcol = curses_color(col);
63 }
64
65 void tg_color(int col)
66 {
67         fgcol = curses_color(col & 0xf);
68         bgcol = curses_color((col >> 4) & 0xf);
69 }
70
71 void tg_bgchar(int c)
72 {
73         bgchar = c;
74 }
75
76
77 void tg_setcursor(int x, int y)
78 {
79         move(y, x);
80         cur_x = x;
81         cur_y = y;
82 }
83
84
85 void tg_text(int x, int y, const char *fmt, ...)
86 {
87         va_list ap;
88
89         va_start(ap, fmt);
90         tg_vtext(x, y, fmt, ap);
91         va_end(ap);
92 }
93
94 void tg_vtext(int x, int y, const char *fmt, va_list ap)
95 {
96         upd_color();
97         attron(COLOR_PAIR(cur_pair));
98         move(y, x);
99         vw_printw(stdscr, fmt, ap);
100         attroff(COLOR_PAIR(cur_pair));
101 }
102
103
104 void tg_rect(const char *label, int x, int y, int xsz, int ysz, unsigned int flags)
105 {
106         int i;
107
108         upd_color();
109         attron(COLOR_PAIR(cur_pair));
110
111         for(i=0; i<ysz; i++) {
112                 move(y + i, x);
113                 hline(bgchar, xsz);
114         }
115
116         if(flags & TGFX_FRAME) {
117                 move(y, x + 1);
118                 hline(ACS_HLINE, xsz - 2);
119                 move(y + ysz - 1, x + 1);
120                 hline(ACS_HLINE, xsz - 2);
121                 move(y + 1, x);
122                 vline(ACS_VLINE, ysz - 2);
123                 move(y + 1, x + xsz - 1);
124                 vline(ACS_VLINE, ysz - 2);
125
126                 mvaddch(y, x, ACS_ULCORNER);
127                 mvaddch(y, x + xsz - 1, ACS_URCORNER);
128                 mvaddch(y + ysz - 1, x, ACS_LLCORNER);
129                 mvaddch(y + ysz - 1, x + xsz - 1, ACS_LRCORNER);
130         }
131
132         if(label) {
133                 tg_text(x + 2, y, "%s", label);
134         }
135
136         attroff(COLOR_PAIR(cur_pair));
137         refresh();
138 }
139
140 int tg_gchar(int gchar)
141 {
142         switch(gchar) {
143         case TGFX_LARROW:
144                 return ACS_LARROW;
145         case TGFX_RARROW:
146                 return ACS_RARROW;
147         default:
148                 break;
149         }
150         return '@';
151 }
152
153 static int curses_color(int col)
154 {
155         switch(col) {
156         case TGFX_RED:
157                 return COLOR_RED;
158         case TGFX_BLUE:
159                 return COLOR_BLUE;
160         case TGFX_CYAN:
161                 return COLOR_CYAN;
162         case TGFX_YELLOW:
163                 return COLOR_YELLOW;
164         default:
165                 break;
166         }
167         return col;
168 }
169
170 static void upd_color(void)
171 {
172         int i;
173
174         for(i=0; i<num_colors; i++) {
175                 if(fgcol == colors[i].fg && bgcol == colors[i].bg) {
176                         cur_pair = colors[i].pair;
177                         return;
178                 }
179         }
180
181         /* not found, allocate a new color pair */
182         if(num_colors >= COLORS) {
183                 return;
184         }
185         i = num_colors++;
186         cur_pair = num_colors;
187
188         colors[i].fg = fgcol;
189         colors[i].bg = bgcol;
190         colors[i].pair = cur_pair;
191         init_pair(cur_pair, fgcol, bgcol);
192 }