1 /* select box
2 
3    Written by Matthias Hensler
4    Copyright WSPse 1999-2004
5    eMail: wsp@gmx.de
6 
7 Created: 1999/06/08
8 Updated: 2004/04/15
9 */
10 
11 /* Copying:
12    This program is free software; you can redistribute it and/or modify it under
13    the terms of the GNU Gerneral Public License as published by the Free Soft-
14    ware Foundation; either version 2 of License, or (at your option) any later
15    version.
16 
17    This program is distributed in the hope that it will be useful, but WITHOUT
18    ANY WARRANTY; without even the implied warranty of MERCHANTABILTY or
19    FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
20    more details.
21 
22    You should have received a copy of the GNU General Public License along with
23    this program; if not, write to the Free Software Foundation, Inc., 675 Mass
24    Ave, Cambridge, MA 02139, USA.
25    */
26 
27 #ifdef HAVE_CONFIG_H
28 #include <config.h>
29 #endif
30 
31 #include <stdio.h>
32 #include <ncurses.h>
33 #include "mp3creat.h"
34 
35 extern char *mp3_genre[];
36 extern void wuuush(int);
37 extern WINDOW *c_newwin(int h, int l, int y, int x, void *proc, int arg1, int arg2);
38 extern int set_active_win(WINDOW *win);
39 extern void c_delwin(WINDOW *win);
40 extern void free_field_select(field_select_typ **anchor);
41 extern void store_win_poi(WINDOW *win, void *pointer);
42 extern void *pop_win_poi(WINDOW *win);
43 extern void win_effect(WINDOW *win, BOOL e_refresh, BOOL save_coor);
44 extern char *copy_char_str(char *old);
45 extern signed char config_fancy_colors;
46 extern BOOL careful_batch;
47 extern char *def_unknown_gen;
48 
49 field_select_typ *top_an, *curr_an;
50 int curr_line;
51 int sb_pressed_key;
52 
build_win(WINDOW * fs_win,char * tx,int i)53 void build_win(WINDOW *fs_win, char *tx, int i)
54 {
55   chtype old_ch;
56   int maxx, maxy;
57   int j;
58   int pos;
59 
60   getmaxyx(stdscr, maxy, maxx);
61   j = (maxy)>>1;
62   wclear(fs_win);
63   wbkgd(fs_win, COLOR_PAIR(1) | A_BOLD);
64   box(fs_win, 0, 0);
65   old_ch = getbkgd(fs_win);
66   wbkgdset(fs_win, COLOR_PAIR(2) | A_BOLD);
67   pos = i-strlen(tx);
68   if(pos < 2) pos=2;
69   mvwaddnstr(fs_win, 0, pos>>1, tx, i-2);
70 }
71 
sign_line(field_select_typ * elem,int len,BOOL marked,int line,WINDOW * fs_win)72 void sign_line(field_select_typ *elem, int len, BOOL marked, int line, WINDOW *fs_win)
73 {
74   chtype old_ch;
75   int maxy, maxx;
76   int remain_len;
77   chtype col_1, col_2;
78 
79   getmaxyx(stdscr, maxy, maxx);
80   old_ch = getbkgd(fs_win);
81 
82   if(marked) {
83     col_1 = COLOR_PAIR(3);
84     col_2 = COLOR_PAIR(4) | A_BOLD;
85   } else {
86     col_1 = COLOR_PAIR(1);
87     col_2 = COLOR_PAIR(2) | A_BOLD;
88   }
89 
90   wbkgdset(fs_win, col_1);
91   wmove(fs_win, line, 1);
92   whline(fs_win, ' ', len);
93   waddnstr(fs_win, elem->field, len);
94   if(elem->dest) {
95     remain_len = len - strlen(elem->field);
96     waddnstr(fs_win, " [", remain_len);
97     remain_len -= 2;
98     wbkgdset(fs_win, col_2);
99     waddnstr(fs_win, elem->dest, remain_len);
100     wbkgdset(fs_win, col_1);
101     remain_len -= strlen(elem->dest);
102     if(remain_len > 0) waddch(fs_win, ']');
103   }
104 
105   wbkgdset(fs_win, old_ch);
106 }
107 
fill_lines(int len,WINDOW * fs_win)108 void fill_lines(int len, WINDOW *fs_win)
109 {
110   int maxy, maxx;
111   int i,j;
112   field_select_typ *curr;
113 
114   getmaxyx(stdscr, maxy, maxx);
115   j =  maxy>>1;
116 
117   curr = top_an;
118   i = 1;
119   while((curr != NULL) && (i <= j)) {
120     if(curr == curr_an) sign_line(curr, len, TRUE, i, fs_win);
121     else                sign_line(curr, len, FALSE, i, fs_win);
122     i++;
123     curr = curr->next;
124   }
125 }
126 
rebuild(WINDOW * fs_win,int i,int i2)127 void rebuild(WINDOW *fs_win, int i, int i2)
128 {
129   int maxy, maxx;
130   int j;
131 
132   getmaxyx(stdscr, maxy, maxx);
133   j = (maxy>>1);
134   if(i2 && j > i2) j = i2;
135   wresize(fs_win, j+2, i+2);
136   maxx = (maxx-(i+2))>>1;
137   maxy = (maxy-(j+2))>>1;
138   mvwin(fs_win, maxy, maxx);
139   build_win(fs_win, pop_win_poi(fs_win), i);
140   fill_lines(i, fs_win);
141 
142   wrefresh(fs_win);
143 }
144 
do_pos1(int len,int height,WINDOW * fs_win)145 void do_pos1(int len, int height, WINDOW *fs_win)
146 {
147   if(curr_line != 1) {
148     sign_line(curr_an, len, FALSE, curr_line, fs_win);
149     curr_an   = top_an;
150     curr_line = 1;
151     sign_line(curr_an, len, TRUE, curr_line, fs_win);
152     wrefresh(fs_win);
153     return;
154   }
155   if(top_an->prev) {
156     while(top_an->prev) top_an  = top_an->prev;
157     curr_an = top_an;
158     fill_lines(len, fs_win);
159     wrefresh(fs_win);
160   }
161   return;
162 }
163 
do_end(int len,int height,WINDOW * fs_win)164 void do_end(int len, int height, WINDOW *fs_win)
165 {
166   if(curr_an->next == NULL) return;
167 
168   if(curr_line != height) {
169     sign_line(curr_an, len, FALSE, curr_line, fs_win);
170     while(curr_line != height) {
171       curr_an = curr_an->next;
172       curr_line++;
173       if(curr_an->next == NULL) break;
174     }
175     sign_line(curr_an, len, TRUE, curr_line, fs_win);
176   } else {
177     while(curr_an->next != NULL) {
178       curr_an = curr_an->next;
179       top_an  = top_an->next;
180     }
181     fill_lines(len, fs_win);
182   }
183   wrefresh(fs_win);
184 }
185 
do_ppage(int len,int height,WINDOW * fs_win)186 void do_ppage(int len, int height, WINDOW *fs_win)
187 {
188   int i;
189 
190   if(top_an->prev == NULL) {
191     if(curr_line != 1) do_pos1(len, height, fs_win);
192     return;
193   }
194 
195   for(i=0;i<height;i++) {
196     if(top_an->prev != NULL) {
197       top_an  = top_an->prev;
198       curr_an = curr_an->prev;
199     }
200     else if(curr_line == 1) break;
201     else {
202       curr_line--;
203       curr_an = curr_an->prev;
204     }
205   }
206   fill_lines(len, fs_win);
207   wrefresh(fs_win);
208 }
209 
do_npage(int len,int height,WINDOW * fs_win)210 void do_npage(int len, int height, WINDOW *fs_win)
211 {
212   int i;
213   BOOL fill;
214 
215   if(curr_an->next == NULL) return;
216 
217   fill = FALSE;
218   sign_line(curr_an, len, FALSE, curr_line, fs_win);
219   for(i=0;i<height;i++) {
220     if(curr_an->next == NULL) break;
221     if(curr_line != height) {
222       curr_an = curr_an->next;
223       curr_line++;
224     } else {
225       fill = TRUE;
226       curr_an = curr_an->next;
227       top_an  = top_an->next;
228     }
229   }
230 
231   if(! fill) sign_line(curr_an, len, TRUE, curr_line, fs_win);
232   else       fill_lines(len, fs_win);
233 
234   wrefresh(fs_win);
235 }
236 
select_field_box(field_select_typ * fs_anchor,int max_length,char * stat_text,BOOL use_old,BOOL allow_space)237 field_select_typ *select_field_box(field_select_typ *fs_anchor, int max_length, char *stat_text,
238 				   BOOL use_old, BOOL allow_space)
239 {
240   int i, j, i2;
241   int maxx, maxy;
242   int inp_ch;
243   WINDOW *fs_win;
244   field_select_typ *curr;
245 
246   sb_pressed_key = 0;
247 
248   if(careful_batch) return NULL;
249   /* No select tree ---> no select box ---> no result */
250   if(fs_anchor == NULL) return NULL;
251 
252   getmaxyx(stdscr, maxy, maxx);
253   i = max_length+2;
254   if(i>maxx) i = maxx;
255   j = (maxy)>>1;
256   i2 = 0;
257   curr = fs_anchor;
258   while(curr) {
259     i2++;
260     curr = curr->next;
261   }
262   if(i2 && j > i2) j = i2;
263   fs_win = c_newwin(j+2, i, (maxy-(j+2))>>1, (maxx-i)>>1, rebuild, i-2, i2);
264   store_win_poi(fs_win, stat_text);
265   i -= 2;
266 
267   build_win(fs_win, stat_text, i);
268   if(use_old) {
269     if((! top_an) || (! curr_an)) use_old = FALSE;
270     if(curr_line > (maxy>>1)) use_old = FALSE;
271   }
272 
273   if(! use_old) {
274     top_an    = fs_anchor;
275     curr_an   = fs_anchor;
276     curr_line = 1;
277   }
278   fill_lines(i, fs_win);
279   wrefresh(fs_win);
280 
281   cbreak();
282   noecho();
283   keypad(fs_win, TRUE);
284   if(config_fancy_colors)
285     halfdelay(1);
286   else
287     nodelay(fs_win, FALSE);
288 
289   while(1) {
290     inp_ch = wgetch(fs_win);
291     if(config_fancy_colors) win_effect(fs_win, TRUE, FALSE);
292     getmaxyx(stdscr, maxy, maxx);
293     j = (maxy)>>1;
294     switch(inp_ch) {
295       case '\n':
296       case '\r':
297       case KEY_ENTER:
298 	c_delwin(fs_win);
299 	return curr_an;
300 	break;
301       case ' ':
302 	if(allow_space) {
303 	  c_delwin(fs_win);
304 	  sb_pressed_key = inp_ch;
305 	  return curr_an;
306 	}
307 	break;
308       case 27:
309       case 'q':
310       case 'Q':
311       case KEY_F(12):
312       case '\'':
313 	c_delwin(fs_win);
314 	return NULL;
315 	break;
316       case '':
317 	set_active_win(fs_win);
318 	break;
319       case KEY_DOWN:
320 	if(curr_an->next) {
321 	  sign_line(curr_an, i, FALSE, curr_line, fs_win);
322 	  if(curr_line < j) {
323 	    curr_line++;
324 	    curr_an = curr_an->next;
325 	    sign_line(curr_an, i, TRUE, curr_line, fs_win);
326 	  } else {
327 	    top_an  = top_an->next;
328 	    curr_an = curr_an->next;
329 	    fill_lines(i, fs_win);
330 	  }
331 	  wrefresh(fs_win);
332 	}
333 	break;
334       case KEY_UP:
335 	if(curr_an->prev) {
336 	  sign_line(curr_an, i, FALSE, curr_line, fs_win);
337 	  if(curr_line > 1) {
338 	    curr_line--;
339 	    curr_an = curr_an->prev;
340 	    sign_line(curr_an, i, TRUE, curr_line, fs_win);
341 	  } else {
342 	    top_an  = top_an->prev;
343 	    curr_an = curr_an->prev;
344 	    fill_lines(i, fs_win);
345 	  }
346 	  wrefresh(fs_win);
347 	}
348 	break;
349       case KEY_PPAGE:
350 	do_ppage(i,j, fs_win);
351 	break;
352       case KEY_NPAGE:
353 	do_npage(i,j, fs_win);
354 	break;
355       case KEY_HOME:
356       case 362:
357 	do_pos1(i,j, fs_win);
358 	break;
359       case KEY_END:
360       case 385:
361 	do_end(i,j, fs_win);
362 	break;
363     }
364   }
365 }
366 
select_genre()367 int select_genre()
368 {
369   int i;
370   field_select_typ *new, *anchor;
371   char *tmp;
372 
373   anchor = NULL;
374   for(i=TOT_GENRES;i>=0;i--) {
375     new = (field_select_typ *) malloc(sizeof(field_select_typ));
376     if(new == NULL) {
377       perror("malloc");
378       wuuush(1);
379     }
380     new->dest = NULL;
381     tmp = (char *) malloc(sizeof(char));
382     if(tmp == NULL) {
383       perror("malloc");
384       wuuush(1);
385     }
386     *tmp = (unsigned char) i;
387     new->information = tmp;
388 
389     if(i == TOT_GENRES) {
390       new->field = copy_char_str(def_unknown_gen);
391     } else {
392       new->field = copy_char_str(mp3_genre[i]);
393     }
394     new->prev = NULL;
395     new->next = anchor;
396     if(anchor) anchor->prev = new;
397     anchor = new;
398   }
399 
400   new = select_field_box(anchor, 25, _("select genre"), FALSE, FALSE);
401   if(new) i = (int) ((unsigned char) *(new->information));
402   else    i = -1;
403 
404   free_field_select(&anchor);
405   return i;
406 }
407 
408 BOOL ynb_field;
409 
ynb_show(WINDOW * win,BOOL flag)410 void ynb_show(WINDOW *win, BOOL flag)
411 {
412   int maxy, maxx;
413   chtype old_ch;
414   int i;
415 
416   getmaxyx(win, maxy, maxx);
417 
418   old_ch = getbkgd(win);
419   if(flag) wbkgdset(win, COLOR_PAIR(4) | A_BOLD);
420   else     wbkgdset(win, COLOR_PAIR(1));
421   i = 1 + ((maxx-12)>>2);
422   mvwaddstr(win, 2, i, _("[Yes]"));
423 
424   if(flag) wbkgdset(win, COLOR_PAIR(1));
425   else     wbkgdset(win, COLOR_PAIR(4) | A_BOLD);
426   i = 1 + ((maxx-12)>>2);
427   mvwaddstr(win, 2, maxx-i-4, _("[No]"));
428 
429   wbkgdset(win, old_ch);
430   wrefresh(win);
431 }
432 
ynb_build(WINDOW * win,int dum1,int dum2)433 void ynb_build(WINDOW *win, int dum1, int dum2)
434 {
435   int maxy, maxx;
436   int i;
437   char *tx;
438 
439   getmaxyx(stdscr, maxy, maxx);
440   tx = pop_win_poi(win);
441   i = 0;
442   if(tx) i = strlen(tx)+2;
443   if(i < 12) i = 12;
444   if(i > maxx) i = maxx;
445   mvwin(win, (maxy-4)>>1, (maxx-i)>>1);
446   wresize(win, 4, i);
447 
448   wbkgd(win, COLOR_PAIR(1) | A_BOLD);
449   wclear(win);
450   box(win,0,0);
451 
452   if(tx) {
453     i = (i-1) - strlen(tx);
454     if(i<0) i = 0;
455     i = (i>>1);
456     mvwaddnstr(win, 1, i+1, tx, maxx-2);
457   }
458   ynb_show(win, ynb_field);
459 }
460 
461 /* select yes/no. */
select_yesno_box(char * tx)462 BOOL select_yesno_box(char *tx)
463 {
464   WINDOW *ynb_win;
465   int maxy, maxx;
466   int inp_ch;
467 
468   if(careful_batch) return TRUE;
469   ynb_field = FALSE;
470 
471   getmaxyx(stdscr, maxy, maxx);
472   inp_ch = 0;
473   if(tx) inp_ch = strlen(tx) + 2;
474   if(inp_ch < 12) inp_ch = 12;
475   if(inp_ch > maxx) inp_ch = maxx;
476   ynb_win = c_newwin((maxy-4)>>1, (maxx-inp_ch)>>1, 4, inp_ch,
477 		     ynb_build, 0, 0);
478   store_win_poi(ynb_win, tx);
479   ynb_build(ynb_win, 0, 0);
480 
481   cbreak();
482   noecho();
483   keypad(ynb_win, TRUE);
484   if(config_fancy_colors)
485     halfdelay(1);
486   else
487     nodelay(ynb_win, FALSE);
488 
489   while(1) {
490     inp_ch = wgetch(ynb_win);
491     if(config_fancy_colors)
492       win_effect(ynb_win, TRUE, FALSE);
493 
494     if(strchr(_("yY"), inp_ch))      inp_ch = 'y';
495     else if(strchr(_("nN"), inp_ch)) inp_ch = 'n';
496     switch(inp_ch) {
497       case '\t':
498       case KEY_RIGHT:
499       case KEY_LEFT:
500       case KEY_DOWN:
501       case KEY_UP:
502 	if(ynb_field) ynb_field = FALSE;
503 	else          ynb_field = TRUE;
504 	ynb_show(ynb_win, ynb_field);
505 	break;
506       case 27:
507       case KEY_F(12):
508       case '\'':
509 	c_delwin(ynb_win);
510 	return FALSE;
511 	break;
512       case KEY_ENTER:
513       case '\n':
514       case '\r':
515 	c_delwin(ynb_win);
516 	return ynb_field;
517 	break;
518       case 'y':
519 	c_delwin(ynb_win);
520 	return TRUE;
521 	break;
522       case 'n':
523 	c_delwin(ynb_win);
524 	return FALSE;
525     }
526   }
527 }
528 
529