Code

The background color can now be assigned to 'none' (use the current color).
[ncmpc.git] / screen.c
1 /* 
2  * (c) 2004 by Kalle Wallin (kaw@linux.se)
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  * You should have received a copy of the GNU General Public License
14  * along with this program; if not, write to the Free Software
15  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16  *
17  */
19 #include <stdlib.h>
20 #include <unistd.h>
21 #include <stdarg.h>
22 #include <string.h>
23 #include <time.h>
24 #include <signal.h>
25 #include <glib.h>
26 #include <ncurses.h>
28 #include "libmpdclient.h"
29 #include "mpc.h"
30 #include "command.h"
31 #include "options.h"
32 #include "screen.h"
33 #include "screen_play.h"
34 #include "screen_file.h"
35 #include "screen_help.h"
36 #include "screen_search.h"
37 #include "screen_utils.h"
39 #define ENABLE_MP_FLAGS_DISPLAY
40 #undef  ENABLE_STATUS_LINE_CLOCK
42 #define DEFAULT_CROSSFADE_TIME 10
44 #define STATUS_MESSAGE_TIMEOUT 3
45 #define STATUS_LINE_MAX_SIZE   512
47 #ifdef ENABLE_KEYDEF_SCREEN
48 extern screen_functions_t *get_screen_keydef(void);
49 #endif
51 static screen_t *screen = NULL;
52 static screen_functions_t *mode_fn = NULL;
54 static void
55 switch_screen_mode(screen_mode_t new_mode, mpd_client_t *c)
56 {
57   if( new_mode == screen->mode )
58     return;
60   /* close the old mode */
61   if( mode_fn && mode_fn->close )
62     mode_fn->close();
64   /* get functions for the new mode */
65   switch(new_mode)
66     {
67     case SCREEN_PLAY_WINDOW:
68       mode_fn = get_screen_playlist();
69       break;
70     case SCREEN_FILE_WINDOW:
71       mode_fn = get_screen_file();
72       break;
73     case SCREEN_HELP_WINDOW:
74       mode_fn = get_screen_help();
75       break;
76 #ifdef ENABLE_KEYDEF_SCREEN
77     case SCREEN_KEYDEF_WINDOW:
78       mode_fn = get_screen_keydef();
79       break;
80 #endif
81     default:
82       break;
83     }
85  screen->mode = new_mode;
86  screen->painted = 0;
88  /* open the new mode */
89  if( mode_fn && mode_fn->open )
90    mode_fn->open(screen, c);
92 }
94 static void
95 paint_top_window(char *header, mpd_client_t *c, int clear)
96 {
97   static int prev_volume = -1;
98   static int prev_header_len = -1;
99   WINDOW *w = screen->top_window.w;
101   if(prev_header_len!=strlen(header))
102     {
103       prev_header_len = strlen(header);
104       clear = 1;
105     }
107   if(clear)
108     {
109       wmove(w, 0, 0);
110       wclrtoeol(w);
111     }
113   if(prev_volume!=c->status->volume || clear)
114     {
115       char buf[12];
117       if( header[0] )
118         {
119           wattron(w, A_BOLD);
120           mvwaddstr(w, 0, 0, header);
121           wattroff(w, A_BOLD);
122         }
123       else
124         {
125           wattron(w, A_BOLD);
126           waddstr(w, get_key_names(CMD_SCREEN_HELP, FALSE));
127           wattroff(w, A_BOLD);
128           waddstr(w, ":Help  ");
129           wattron(w, A_BOLD);
130           waddstr(w, get_key_names(CMD_SCREEN_PLAY, FALSE));
131           wattroff(w, A_BOLD);
132           waddstr(w, ":Playlist  ");
133           wattron(w, A_BOLD);
134           waddstr(w, get_key_names(CMD_SCREEN_FILE, FALSE));
135           wattroff(w, A_BOLD);
136           waddstr(w, ":Browse");
137         }
138       if( c->status->volume==MPD_STATUS_NO_VOLUME )
139         {
140           snprintf(buf, 12, "Volume n/a ");
141         }
142       else
143         {
144           snprintf(buf, 12, "Volume %3d%%", c->status->volume); 
145         }
146       mvwaddstr(w, 0, screen->top_window.cols-12, buf);
148       if( options.enable_colors )
149         wattron(w, LINE_COLORS);
151 #ifdef ENABLE_MP_FLAGS_DISPLAY
152       {
153         char buf[4];
155         buf[0] = 0;
156         if( c->status->repeat )
157           strcat(buf, "r");
158         if( c->status->random )
159           strcat(buf, "z");
160         if( c->status->crossfade )
161           strcat(buf, "x");
163         mvwhline(w, 1, 0, ACS_HLINE, screen->top_window.cols);
164         if( buf[0] )
165           {
166             wmove(w,1,screen->top_window.cols-strlen(buf)-3);
167             waddch(w, '[');
168             wattron(w, A_BOLD);
169             waddstr(w, buf);
170             wattroff(w, A_BOLD);
171             waddch(w, ']');
172           }
173       }
174 #else
175       mvwhline(w, 1, 0, ACS_HLINE, screen->top_window.cols);
176 #endif
178       if( options.enable_colors )
179         wattroff(w, LINE_COLORS);
181       wnoutrefresh(w);
182     }
185 static void
186 paint_progress_window(mpd_client_t *c)
188   double p;
189   int width;
190   int elapsedTime = c->status->elapsedTime;
192   if( c->status==NULL || IS_STOPPED(c->status->state) )
193     {
194       mvwhline(screen->progress_window.w, 0, 0, ACS_HLINE, 
195                screen->progress_window.cols);
196       wnoutrefresh(screen->progress_window.w);
197       return;
198     }
200   if( c->seek_song_id == c->song_id )
201     elapsedTime = c->seek_target_time;
203   p = ((double) elapsedTime) / ((double) c->status->totalTime);
204   
205   width = (int) (p * (double) screen->progress_window.cols);
206   mvwhline(screen->progress_window.w, 
207            0, 0,
208            ACS_HLINE, 
209            screen->progress_window.cols);
210   whline(screen->progress_window.w, '=', width-1);
211   mvwaddch(screen->progress_window.w, 0, width-1, 'O');
212   wnoutrefresh(screen->progress_window.w);
215 static void 
216 paint_status_window(mpd_client_t *c)
218   WINDOW *w = screen->status_window.w;
219   mpd_Status *status = c->status;
220   mpd_Song *song   = c->song;
221   int elapsedTime = c->status->elapsedTime;
222   int x = 0;
224   if( time(NULL) - screen->status_timestamp <= STATUS_MESSAGE_TIMEOUT )
225     return;
226   
227   wmove(w, 0, 0);
228   wclrtoeol(w);
229   
230   switch(status->state)
231     {
232     case MPD_STATUS_STATE_STOP:
233       wattron(w, A_BOLD);
234       waddstr(w, "Stopped! ");
235       wattroff(w, A_BOLD);
236       break;
237     case MPD_STATUS_STATE_PLAY:
238       wattron(w, A_BOLD);
239       waddstr(w, "Playing:");
240       wattroff(w, A_BOLD);
241       break;
242     case MPD_STATUS_STATE_PAUSE:
243       wattron(w, A_BOLD);
244       waddstr(w, "[Paused]");
245       wattroff(w, A_BOLD);
246       break;
247     default:
248       my_waddstr(w, 
249                  "Warning: Music Player Daemon in unknown state!", 
250                  ALERT_COLORS);
251       break;
252     }
253   x += 10;
255   if( (IS_PLAYING(status->state) || IS_PAUSED(status->state)) &&  song )
256     {
257       mvwaddstr(w, 0, x, mpc_get_song_name(song));
258     }
259   
261   /* time */
262   if( c->seek_song_id == c->song_id )
263     elapsedTime = c->seek_target_time;
264   if( IS_PLAYING(status->state) || IS_PAUSED(status->state) )
265     {
266       x = screen->status_window.cols - strlen(screen->buf);
268       snprintf(screen->buf, screen->buf_size, 
269                " [%i:%02i/%i:%02i] ",
270                elapsedTime/60, elapsedTime%60,
271                status->totalTime/60,   status->totalTime%60 );
272       mvwaddstr(w, 0, x, screen->buf);
273         
274     }
275 #ifdef ENABLE_STATUS_LINE_CLOCK
276   else if( c->status->state == MPD_STATUS_STATE_STOP )
277     {
278       time_t timep;
280       /* Note: setlocale(LC_TIME,"") should be used first */
281       time(&timep);
282       strftime(screen->buf, screen->buf_size, "%X ",  localtime(&timep));
283       x = screen->status_window.cols - strlen(screen->buf) ;
284       mvwaddstr(w, 0, x, screen->buf);
285     }
286 #endif
287   
289   wnoutrefresh(w);
294 int
295 screen_exit(void)
297   endwin();
298   if( screen )
299     {
300       GList *list = g_list_first(screen->screen_list);
302       /* close and exit all screens (playlist,browse,help...) */
303       while( list )
304         {
305           screen_functions_t *mode_fn = list->data;
307           if( mode_fn && mode_fn->close )
308             mode_fn->close();
309           if( mode_fn && mode_fn->exit )
310             mode_fn->exit();
311           list->data = NULL;
312           list=list->next;
313         }
314       g_list_free(screen->screen_list);
316       g_free(screen->buf);
317       g_free(screen->findbuf);
318       g_free(screen);
319       screen = NULL;
320     }
321   return 0;
324 void
325 screen_resize(void)
327   GList *list;
329 #ifdef DEBUG
330   fprintf(stderr, "Resize rows %d->%d, cols %d->%d\n",
331           screen->rows, LINES,
332           screen->cols, COLS);
333 #endif
334       
335   if( COLS<SCREEN_MIN_COLS || LINES<SCREEN_MIN_ROWS )
336     {
337       screen_exit();
338       fprintf(stderr, "Error: Screen to small!\n");
339       exit(EXIT_FAILURE);
340     }
342   resizeterm(LINES, COLS);
344   screen->cols = COLS;
345   screen->rows = LINES;
347   /* top window */
348   screen->top_window.cols = screen->cols;
349   wresize(screen->top_window.w, 2, screen->cols);
351   /* main window */
352   screen->main_window.cols = screen->cols;
353   screen->main_window.rows = screen->rows-4;
354   wresize(screen->main_window.w, screen->main_window.rows, screen->cols);
355   wclear(screen->main_window.w);
357   /* progress window */
358   screen->progress_window.cols = screen->cols;
359   wresize(screen->progress_window.w, 1, screen->cols);
360   mvwin(screen->progress_window.w, screen->rows-2, 0);
362   /* status window */
363   screen->status_window.cols = screen->cols;
364   wresize(screen->status_window.w, 1, screen->cols);
365   mvwin(screen->status_window.w, screen->rows-1, 0);
367   screen->buf_size = screen->cols;
368   g_free(screen->buf);
369   screen->buf = g_malloc(screen->cols);
371   list = g_list_first(screen->screen_list);
372   while( list )
373     {
374       screen_functions_t *mode_fn = list->data;
376       if( mode_fn && mode_fn->resize )
377         mode_fn->resize(screen->main_window.cols, screen->main_window.rows);
379       list=list->next;
380     }
382   /* ? - without this the cursor becomes visible with aterm & Eterm */
383   curs_set(1);
384   curs_set(0);     
386   screen->painted = 0;
389 void 
390 screen_status_message(char *msg)
392   WINDOW *w = screen->status_window.w;
394   wmove(w, 0, 0);
395   wclrtoeol(w);
396   wattron(w, A_BOLD);
397   my_waddstr(w, msg, ALERT_COLORS);
398   wattroff(w, A_BOLD);
399   wnoutrefresh(w);
400   screen->status_timestamp = time(NULL);
403 void 
404 screen_status_printf(char *format, ...)
406   char buffer[STATUS_LINE_MAX_SIZE];
407   va_list ap;
408   
409   va_start(ap,format);
410   vsnprintf(buffer,sizeof(buffer),format,ap);
411   va_end(ap);
412   screen_status_message(buffer);
415 int
416 screen_init(void)
418   GList *list;
420   /* initialize the curses library */
421   initscr();        
422   if( has_colors() )
423     {
424       start_color();
425       use_default_colors();
426       if( options.enable_colors )
427         {
428           init_pair(1, options.title_color,    options.bg_color);
429           init_pair(2, options.line_color,     options.bg_color);
430           init_pair(3, options.list_color,     options.bg_color);
431           init_pair(4, options.progress_color, options.bg_color);
432           init_pair(5, options.status_color,   options.bg_color);
433           init_pair(6, options.alert_color,    options.bg_color);
434         }
435     }
436   else if( options.enable_colors )
437     {
438       fprintf(stderr, "Terminal lacks color capabilities.\n");
439       options.enable_colors = 0;
440     }
442   /* tell curses not to do NL->CR/NL on output */
443   nonl();          
444   /* take input chars one at a time, no wait for \n */  
445   cbreak();       
446   /* don't echo input */
447   noecho();    
448   /* set cursor invisible */     
449   curs_set(0);     
450   /* return from getch() without blocking */
451   //  nodelay(stdscr, TRUE); 
452   keypad(stdscr, TRUE);  
453   timeout(SCREEN_TIMEOUT);
455   if( COLS<SCREEN_MIN_COLS || LINES<SCREEN_MIN_ROWS )
456     {
457       fprintf(stderr, "Error: Screen to small!\n");
458       exit(EXIT_FAILURE);
459     }
461   screen = g_malloc(sizeof(screen_t));
462   memset(screen, 0, sizeof(screen_t));
463   screen->mode = SCREEN_PLAY_WINDOW;
464   screen->cols = COLS;
465   screen->rows = LINES;
466   screen->buf  = g_malloc(screen->cols);
467   screen->buf_size = screen->cols;
468   screen->findbuf = NULL;
469   screen->painted = 0;
470   screen->start_timestamp = time(NULL);
471   screen->input_timestamp = time(NULL);
472   screen->last_cmd = CMD_NONE;
474   /* create top window */
475   screen->top_window.rows = 2;
476   screen->top_window.cols = screen->cols;
477   screen->top_window.w = newwin(screen->top_window.rows, 
478                                   screen->top_window.cols,
479                                   0, 0);
480   leaveok(screen->top_window.w, TRUE);
481   keypad(screen->top_window.w, TRUE);  
483   /* create main window */
484   screen->main_window.rows = screen->rows-4;
485   screen->main_window.cols = screen->cols;
486   screen->main_window.w = newwin(screen->main_window.rows, 
487                                  screen->main_window.cols,
488                                  2, 
489                                  0);
491   //  leaveok(screen->main_window.w, TRUE); temporary disabled
492   keypad(screen->main_window.w, TRUE);  
494   /* create progress window */
495   screen->progress_window.rows = 1;
496   screen->progress_window.cols = screen->cols;
497   screen->progress_window.w = newwin(screen->progress_window.rows, 
498                                      screen->progress_window.cols,
499                                      screen->rows-2, 
500                                      0);
501   leaveok(screen->progress_window.w, TRUE);
502   
503   /* create status window */
504   screen->status_window.rows = 1;
505   screen->status_window.cols = screen->cols;
506   screen->status_window.w = newwin(screen->status_window.rows, 
507                                    screen->status_window.cols,
508                                    screen->rows-1, 
509                                    0);
511   leaveok(screen->status_window.w, FALSE);
512   keypad(screen->status_window.w, TRUE);  
514   if( options.enable_colors )
515     {
516       /* set background attributes */
517       wbkgd(screen->main_window.w, LIST_COLORS);
518       wbkgd(screen->top_window.w, TITLE_COLORS);
519       wbkgd(screen->progress_window.w, PROGRESS_COLORS);
520       wbkgd(screen->status_window.w, STATUS_COLORS);
521     }
523   /* initialize screens */
524   screen->screen_list = NULL;
525   screen->screen_list = g_list_append(screen->screen_list, 
526                                       (gpointer) get_screen_playlist());
527   screen->screen_list = g_list_append(screen->screen_list, 
528                                       (gpointer) get_screen_file());
529   screen->screen_list = g_list_append(screen->screen_list, 
530                                       (gpointer) get_screen_help());
531 #ifdef ENABLE_KEYDEF_SCREEN
532   screen->screen_list = g_list_append(screen->screen_list, 
533                                       (gpointer) get_screen_keydef());
534 #endif
536   list = screen->screen_list;
537   while( list )
538     {
539       screen_functions_t *fn = list->data;
540       
541       if( fn && fn->init )
542         fn->init(screen->main_window.w, 
543                  screen->main_window.cols,
544                  screen->main_window.rows);
545       
546       list = list->next;
547     }
549   mode_fn = get_screen_playlist();
551   return 0;
554 void 
555 screen_paint(mpd_client_t *c)
557   /* paint the title/header window */
558   if( mode_fn && mode_fn->get_title )
559     paint_top_window(mode_fn->get_title(), c, 1);
560   else
561     paint_top_window("", c, 1);
563   /* paint the main window */
564   if( mode_fn && mode_fn->paint )
565     mode_fn->paint(screen, c);
566   
567   paint_progress_window(c);
568   paint_status_window(c);
569   screen->painted = 1;
570   wmove(screen->main_window.w, 0, 0);  
571   wnoutrefresh(screen->main_window.w);
573   /* tell curses to update */
574   doupdate();
577 void 
578 screen_update(mpd_client_t *c)
580   static int repeat = -1;
581   static int random = -1;
582   static int crossfade = -1;
583   static int welcome = 1;
584   list_window_t *lw = NULL;
586   if( !screen->painted )
587     return screen_paint(c);
589   /* print a message if mpd status has changed */
590   if( repeat<0 )
591     {
592       repeat = c->status->repeat;
593       random = c->status->random;
594       crossfade = c->status->crossfade;
595     }
596   if( repeat != c->status->repeat )
597     screen_status_printf("Repeat is %s", 
598                          c->status->repeat  ? "On" : "Off");
599   if( random != c->status->random )
600     screen_status_printf("Random is %s", 
601                          c->status->random ? "On" : "Off");
602   if( crossfade != c->status->crossfade )
603     screen_status_printf("Crossfade %d seconds", c->status->crossfade);
605   repeat = c->status->repeat;
606   random = c->status->random;
607   crossfade = c->status->crossfade;
609   /* update title/header window */
610   if( welcome && screen->last_cmd==CMD_NONE &&
611       time(NULL)-screen->start_timestamp <= SCREEN_WELCOME_TIME)
612     paint_top_window("", c, 0);
613   else if( mode_fn && mode_fn->get_title )
614     {
615       paint_top_window(mode_fn->get_title(), c, 0);
616       welcome = 0;
617     }
618   else
619     paint_top_window("", c, 0);
621   /* update the main window */
622   if( mode_fn && mode_fn->paint )
623     mode_fn->update(screen, c);
625   if( mode_fn && mode_fn->get_lw )
626     lw = mode_fn->get_lw();
628   /* update progress window */
629   paint_progress_window(c);
631   /* update status window */
632   paint_status_window(c);
634   /* move the cursor to the selected row in the main window */
635   if( lw )
636     wmove(screen->main_window.w, LW_ROW(lw), 0);   
637   else
638     wmove(screen->main_window.w, 0, 0);   
639   wnoutrefresh(screen->main_window.w);
641   /* tell curses to update */
642   doupdate();
645 void
646 screen_idle(mpd_client_t *c)
648   if( c->seek_song_id ==  c->song_id &&
649       (screen->last_cmd == CMD_SEEK_FORWARD || 
650        screen->last_cmd == CMD_SEEK_BACKWARD) )
651     {
652       mpd_sendSeekCommand(c->connection, 
653                           c->seek_song_id, 
654                           c->seek_target_time);
655       mpd_finishCommand(c->connection);
656     }
658   screen->last_cmd = CMD_NONE;
659   c->seek_song_id = -1;
662 void 
663 screen_cmd(mpd_client_t *c, command_t cmd)
665   int n;
666   screen_mode_t new_mode = screen->mode;
668   screen->input_timestamp = time(NULL);
669   screen->last_cmd = cmd;
671   if( mode_fn && mode_fn->cmd && mode_fn->cmd(screen, c, cmd) )
672     return;
674   switch(cmd)
675     {
676     case CMD_PLAY:
677       mpd_sendPlayCommand(c->connection, play_get_selected());
678       mpd_finishCommand(c->connection);
679       break;
680     case CMD_PAUSE:
681       mpd_sendPauseCommand(c->connection);
682       mpd_finishCommand(c->connection);
683       break;
684     case CMD_STOP:
685       mpd_sendStopCommand(c->connection);
686       mpd_finishCommand(c->connection);
687       break;
688     case CMD_SEEK_FORWARD:
689       if( !IS_STOPPED(c->status->state) )
690         {
691           if( c->seek_song_id != c->song_id )
692             {
693               c->seek_song_id = c->song_id;
694               c->seek_target_time = c->status->elapsedTime;
695             }
696           c->seek_target_time++;
697           if( c->seek_target_time < c->status->totalTime )
698             break;
699           c->seek_target_time=0;
700         }
701       /* fall through... */
702     case CMD_TRACK_NEXT:
703       if( !IS_STOPPED(c->status->state) )
704         {
705           mpd_sendNextCommand(c->connection);
706           mpd_finishCommand(c->connection);
707         }
708       break;
709     case CMD_SEEK_BACKWARD:
710       if( !IS_STOPPED(c->status->state) )
711         {
712           if( c->seek_song_id != c->song_id )
713             {
714               c->seek_song_id = c->song_id;
715               c->seek_target_time = c->status->elapsedTime;
716             }
717           c->seek_target_time--;
718           if( c->seek_target_time < 0 )
719             c->seek_target_time=0;
720         }
721       break;
722     case CMD_TRACK_PREVIOUS:
723       if( !IS_STOPPED(c->status->state) )
724         {
725           mpd_sendPrevCommand(c->connection);
726           mpd_finishCommand(c->connection);
727         }
728       break;   
729     case CMD_SHUFFLE:
730       mpd_sendShuffleCommand(c->connection);
731       mpd_finishCommand(c->connection);
732       screen_status_message("Shuffled playlist!");
733       break;
734     case CMD_CLEAR:
735       mpd_sendClearCommand(c->connection);
736       mpd_finishCommand(c->connection);
737       file_clear_highlights(c);
738       screen_status_message("Cleared playlist!");
739       break;
740     case CMD_REPEAT:
741       n = !c->status->repeat;
742       mpd_sendRepeatCommand(c->connection, n);
743       mpd_finishCommand(c->connection);
744       break;
745     case CMD_RANDOM:
746       n = !c->status->random;
747       mpd_sendRandomCommand(c->connection, n);
748       mpd_finishCommand(c->connection);
749       break;
750     case CMD_CROSSFADE:
751       if( c->status->crossfade )
752         n = 0;
753       else
754         n = DEFAULT_CROSSFADE_TIME;
755       mpd_sendCrossfadeCommand(c->connection, n);
756       mpd_finishCommand(c->connection);
757       break;
758     case CMD_VOLUME_UP:
759       if( c->status->volume!=MPD_STATUS_NO_VOLUME && c->status->volume<100 )
760         {
761           c->status->volume=c->status->volume+1;
762           mpd_sendSetvolCommand(c->connection, c->status->volume  );
763           mpd_finishCommand(c->connection);
764           screen_status_printf("Volume %d%%", c->status->volume);
765         }
766       break;
767     case CMD_VOLUME_DOWN:
768       if( c->status->volume!=MPD_STATUS_NO_VOLUME && c->status->volume>0 )
769         {
770           c->status->volume=c->status->volume-1;
771           mpd_sendSetvolCommand(c->connection, c->status->volume  );
772           mpd_finishCommand(c->connection);
773           screen_status_printf("Volume %d%%", c->status->volume);
774         }
775       break;
776     case CMD_TOGGLE_FIND_WRAP:
777       options.find_wrap = !options.find_wrap;
778       screen_status_printf("Find mode: %s", 
779                            options.find_wrap ? "Wrapped" : "Normal");
780       break;
781     case CMD_TOGGLE_AUTOCENTER:
782       options.auto_center = !options.auto_center;
783       screen_status_printf("Auto center mode: %s", 
784                            options.auto_center ? "On" : "Off");
785       break;
786     case CMD_SCREEN_PREVIOUS:
787       if( screen->mode > SCREEN_PLAY_WINDOW )
788         new_mode = screen->mode - 1;
789       else
790         new_mode = SCREEN_HELP_WINDOW-1;
791       switch_screen_mode(new_mode, c);
792       break;
793     case CMD_SCREEN_NEXT:
794       new_mode = screen->mode + 1;
795       if( new_mode >= SCREEN_HELP_WINDOW )
796         new_mode = SCREEN_PLAY_WINDOW;
797       switch_screen_mode(new_mode, c);
798       break;
799     case CMD_SCREEN_PLAY:
800       switch_screen_mode(SCREEN_PLAY_WINDOW, c);
801       break;
802     case CMD_SCREEN_FILE:
803       switch_screen_mode(SCREEN_FILE_WINDOW, c);
804       break;
805     case CMD_SCREEN_SEARCH:
806       switch_screen_mode(SCREEN_SEARCH_WINDOW, c);
807       break;
808     case CMD_SCREEN_HELP:
809       switch_screen_mode(SCREEN_HELP_WINDOW, c);
810       break;
811 #ifdef ENABLE_KEYDEF_SCREEN 
812     case CMD_SCREEN_KEYDEF:
813       switch_screen_mode(SCREEN_KEYDEF_WINDOW, c);
814       break;
815 #endif
816     case CMD_QUIT:
817       exit(EXIT_SUCCESS);
818     default:
819       break;
820     }