/* MikMod example player (c) 2003 Raphael Assenat -- see file AUTHORS for complete list. (c) 1998, 1999 Miodrag Vallat and others - see file AUTHORS for complete list. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /*============================================================================== $Id: display.c,v 1.12 2003/10/08 02:08:48 raph Exp $ Display routines for the different panels and the playlist menu ==============================================================================*/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #ifdef HAVE_UNISTD_H #include #endif #include #include #include #include #include #include #if !defined(__OS2__)&&!defined(__EMX__) #ifdef HAVE_SYS_IOCTL_H #include #endif #ifndef GWINSZ_IN_SYS_IOCTL #include #endif #endif #include "display.h" #include #include "player.h" #include "mutilities.h" #include "mwindow.h" #include "mmenu.h" #include "mdialog.h" #include "mconfedit.h" #include "attr.h" /*========== Display layout */ /* minimum width of one column */ #define MINWIDTH (20) /* minimum width of second column */ #define MINVISIBLE (10) /* half width */ int halfwidth; /* format used for message/banner lines : like "%-80.80s" */ char fmt_fullwidth[20]; /* format used for sample/instrument lines - like "%3i %-36.36s" (the number being halfwidth-4) */ char fmt_halfwidth[20]; /* start of information panels */ #define PANEL_Y 7 typedef struct { MMENU *menu; int *actLine; } MENU_DATA; /*========== Variables */ extern BOOL quiet,semiquiet; extern MODULE *mf; static int cur_display=DISPLAY_SAMPLE,old_display=DISPLAY_SAMPLE; /* first line of displayed information in the panels */ static int first_help=0,first_sample=0,first_inst=0,first_comment=0,first_list=0; static BOOL remove_msg=0; static time_t start_time; static char old_message[121]; /* ================ Prototypes */ void set_term_title(char *songname); /* computes printf templates when screen size changes, so that two-column display fills the screen */ static void setup_printf(void) { int maxx,winy; win_get_size_root(&maxx,&winy); if (maxx>MAXWIDTH) maxx=MAXWIDTH; halfwidth=maxx>>1; if (halfwidth120) len=120; strncpy(old_message,str,len); old_message[len]='\0'; win_attrset(A_REVERSE); win_print_root(strlen(mikversion)+1,0,str); win_attrset(A_NORMAL); remove_msg=1; start_time=time(NULL); } /* changes the warning message */ static void update_message(void) { if ((remove_msg)&&(old_message[0])) { win_attrset(A_REVERSE); win_print_root(strlen(mikversion)+1,0,old_message); win_attrset(A_NORMAL); } } /* removes the warning message */ static void remove_message(void) { if (remove_msg) { time_t end_time=time(NULL); if (end_time-start_time>=6) { win_clrtoeol_root(strlen(mikversion)+1,0); remove_msg=0; } } } /* display a banner/message from line skip, at position origin returns updated skip value if it is out of bounds and would prevent the message from being seen. */ static int display_banner(char* banner,BOOL root,int origin,int skip,BOOL wrap) { char *buf=banner,str[MAXWIDTH+1]; int i,n,t,winx,winy; if (root) win_get_size_root(&winx,&winy); else win_get_size(&winx,&winy); if (winx<5) return skip; /* count message lines */ for (t=0;*buf;t++) { n=0; while ((((nt) skip=t-winy+origin; if (skip<0) skip=0; if (t-skip+origin>winy) t=winy-origin+skip; /* skip first lines */ buf=banner; for (i=0;iName,(md_mode&DMODE_16BITS)?16:8, (md_mode&DMODE_INTERP)? (md_mode&DMODE_SURROUND?"interp. surround":"interpolated"): (md_mode&DMODE_SURROUND?"surround":"normal"), (md_mode&DMODE_STEREO)?"stereo":"mono",md_mixfreq,reverb); attr_driver2(); win_print_root(res,1,storage); attr_normal(); } /* third line : filename */ static void display_file(void) { PLAYENTRY *entry; int pos; if (quiet) return; if ((entry=PL_GetCurrent(&playlist))) { CHAR *archive=entry->archive,*file; if (archive && !config.fullpaths) { archive=strrchr(entry->archive,PATH_SEP); if (archive) archive++; else archive=entry->archive; } file=strrchr(entry->file,PATH_SEP); if (file && !config.fullpaths) file++; else file=entry->file; attr_file1(); win_print_root(0,2,"File: "); attr_normal(); #ifdef HAVE_SNPRINTF snprintf(storage,STORAGELEN,"%.70s\n",file); #else sprintf(storage,"%.70s\n",file); #endif attr_file2(); win_print_root(6,2,storage); attr_normal(); pos = 6 + strlen(storage); // calculate where the archive name should start /* If the file is part of an archive, append the name inside () */ if ((archive)&&(strlen(file)MAXWIDTH-10) { archive+=strlen(archive)-(MAXWIDTH-13-strlen(file)); #ifdef HAVE_SNPRINTF snprintf(storage,STORAGELEN,"(...%s)\n",archive); #else sprintf(storage,"(...%s)\n",archive); #endif } else #ifdef HAVE_SNPRINTF snprintf(storage,STORAGELEN,"(%s)\n",archive); #else sprintf(storage,"(%s)\n",archive); #endif attr_file3(); win_print_root(pos,2,storage); attr_normal(); } } } /* fourth and fifth lines : module name and format */ static void display_name(void) { int pos=0; if ((quiet)||(!mf)) return; set_term_title(mf->songname); attr_song_name1(); win_print_root(0,3,"Name: "); attr_normal(); #ifdef HAVE_SNPRINTF snprintf(storage,STORAGELEN,"%.70s\n",mf->songname); #else sprintf(storage,"%.70s\n",mf->songname); #endif attr_song_name2(); win_print_root(6,3,storage); attr_normal(); /* Type label */ attr_type1(); win_print_root(0,4,"Type: "); pos += 6; attr_normal(); /* The type field */ attr_type2(); win_print_root(pos, 4, mf->modtype); pos += strlen(mf->modtype); win_print_root(pos, 4, ", "); pos += 2; attr_normal(); /* Period label */ attr_type3(); win_print_root(pos, 4, "Periods: "); pos += strlen("Periods: "); attr_normal(); /* The Period field */ attr_type4(); if (mf->flags&UF_XMPERIODS) { win_print_root(pos, 4, "XM type, "); pos += strlen("XM type, "); } else { win_print_root(pos, 4, "mod type, "); pos += strlen("mod type, "); } attr_normal(); /* The linear/log field */ attr_type5(); if (mf->flags&UF_LINEAR) { win_print_root(pos, 4, "linear"); pos += strlen("linear"); } else { win_print_root(pos, 4, "log"); pos += 3; } attr_normal(); #if 0 #ifdef HAVE_SNPRINTF snprintf #else sprintf #endif (storage, #ifdef HAVE_SNPRINTF STORAGELEN, #endif "Type: %s, Periods: %s, %s\n", mf->modtype, (mf->flags&UF_XMPERIODS)?"XM type":"mod type", (mf->flags&UF_LINEAR)?"linear":"log"); win_print_root(0,4,storage); #endif } /* sixth line : player status */ void display_status(void) { int pos; if (quiet) return; if (win_check_resize()) { setup_printf(); win_panel_repaint(); } remove_message(); if ((!mf)||Player_Paused()) return; if (mf->sngposnumpos) { PLAYENTRY *cur=PL_GetCurrent(&playlist); char time[7]=""; char channels[17]=""; /* Build time string */ if (cur && cur->time>0) { #ifdef HAVE_SNPRINTF snprintf(time,7,"/%2d:%02d", (int)((cur->time/60)%60),(int)(cur->time%60)); #else sprintf(time,"/%2d:%02d", (int)((cur->time/60)%60),(int)(cur->time%60)); #endif } /* Build Channels string */ #if LIBMIKMOD_VERSION >= 0x030107 if (mf->flags&UF_NNA) { #ifdef HAVE_SNPRINTF snprintf(channels,17,"%2d/%d+%d->%d", mf->realchn,mf->numchn,mf->totalchn-mf->realchn,mf->totalchn); #else sprintf(channels,"%2d/%d+%d->%d", mf->realchn,mf->numchn,mf->totalchn-mf->realchn,mf->totalchn); #endif } else #endif { #ifdef HAVE_SNPRINTF snprintf(channels,17,"%2d/%d ",mf->realchn,mf->numchn); #else sprintf(channels,"%2d/%d ",mf->realchn,mf->numchn); #endif } /* Print stuff to screen */ pos = 0; /* pattern label */ attr_status_line1(); win_print_root(pos, 5, "pat:"); pos += 4; /* pattern field */ #ifdef HAVE_SNPRINTF snprintf(storage, STORAGELEN, "%03d/%03d ",mf->sngpos,mf->numpos-1); #else sprintf(storage, "%03d/%03d ",mf->sngpos,mf->numpos-1); #endif attr_status_line2(); win_print_root(pos, 5, storage); pos += strlen(storage); /* pos label */ attr_status_line3(); win_print_root(pos, 5, "pos:"); pos += 4; /* pos field */ #ifdef HAVE_SNPRINTF snprintf(storage, STORAGELEN, "%02.2X ",mf->patpos); #else sprintf(storage, "%02.2X ",mf->patpos); #endif attr_status_line4(); win_print_root(pos, 5, storage); pos += strlen(storage); /* spd label */ attr_status_line5(); win_print_root(pos, 5, "spd:"); pos += 4; /* spd field */ #ifdef HAVE_SNPRINTF snprintf(storage, STORAGELEN, "%2d/%3d ",mf->sngspd,mf->bpm); #else sprintf(storage, "%2d/%3d ",mf->sngspd,mf->bpm); #endif attr_status_line6(); win_print_root(pos, 5, storage); pos += strlen(storage); /* vol label */ attr_status_line7(); win_print_root(pos, 5, "vol:"); pos += 4; /* vol field */ #ifdef HAVE_SNPRINTF snprintf(storage, STORAGELEN, "%3d%%/%3d%% ", (mf->volume*100+64)>>7, (md_volume*100+64)>>7); #else sprintf(storage, "%3d%%/%3d%% ", (mf->volume*100+64)>>7, (md_volume*100+64)>>7); #endif attr_status_line8(); win_print_root(pos, 5, storage); pos += strlen(storage); /* time label */ attr_status_line9(); win_print_root(pos, 5, "time:"); pos += 5; /* time field */ #ifdef HAVE_SNPRINTF snprintf(storage, STORAGELEN, "%2d:%02d%s ", (int)(((mf->sngtime>>10)/60)%60), (int)((mf->sngtime>>10)%60), time); #else sprintf(storage, "%2d:%02d%s ", (int)(((mf->sngtime>>10)/60)%60), (int)((mf->sngtime>>10)%60), time); #endif attr_status_line10(); win_print_root(pos, 5, storage); pos += strlen(storage); /* chn label */ attr_status_line11(); win_print_root(pos, 5, "chn:"); pos += 4; /* chn field */ #ifdef HAVE_SNPRINTF snprintf(storage, STORAGELEN, "%s \n", channels); #else sprintf(storage, STORAGELEN, "%s \n", channels); #endif attr_status_line12(); win_print_root(pos, 5, storage); pos += strlen(storage); attr_normal(); #if 0 #ifdef HAVE_SNPRINTF snprintf #else sprintf #endif (storage, #ifdef HAVE_SNPRINTF STORAGELEN, #endif "pat:%03d/%03d pos:%02.2X spd:%2d/%3d " "vol:%3d%%/%3d%% time:%2d:%02d%s chn:%s \n", mf->sngpos,mf->numpos-1,mf->patpos,mf->sngspd,mf->bpm, (mf->volume*100+64)>>7,(md_volume*100+64)>>7, (int)(((mf->sngtime>>10)/60)%60),(int)((mf->sngtime>>10)%60), time,channels); win_print_root(0,5,storage); #endif } } /* help panel */ static void display_help(int diff) { static char helptext[]= "\n" #if !defined(__OS2__)&&!defined(__EMX__) "Keys help (depending on your terminal and your curses library, \n" "========= some of these keys might not be recognized) \n" #else "Keys help\n" "=========\n" #endif "\n" "H/F1 show help panel () decrease/increase tempo \n" "S/F2 show samples panel {} decrease/increase bpm \n" "I/F3 show instrument panel :/; toggle interpolation \n" "M/F4 show message panel U toggle surround sound \n" "L/F5 show list panel 1..0 volume 10%..100% \n" "C/F6 show config panel <> decrease/increase volume \n" "ENTER in list panel, activate menu P switch to previous module\n" "Left/- previous pattern N switch to next module \n" "Right/+ next pattern R restart module \n" "Up/Down scroll panel Space toggle pause \n" "PgUp/PgDn scroll panel (faster) ^L refresh screen \n" "Home/End start/end of panel Q exit MikMod \n"; first_help+=diff; first_help=display_banner(helptext,0,0,first_help,0); } static void convert_string(char *str) { for (;str&&*str;str++) if (*str<' ') *str=' '; } /* sample panel */ static void display_sample(int diff) { int count,semicount,t,x,winx; char smp_name[20], smp_num[10]; first_sample+=diff; win_get_size(&winx,&semicount); if (winx=mf->numsmp-count) first_sample=mf->numsmp-count; if (first_sample<0) first_sample=0; if ((mf->numsmp>semicount)&&(mf->numsmpnumsmp+1)>>1; if (winxnumsmp&&t<(count+first_sample);t++) { x=((t-first_sample)samples[t].samplename?mf->samples[t].samplename:""); convert_string(storage); snprintf(smp_num, 10, "%3i ", t); attr_sample_num(); win_print(x,(t-first_sample)%semicount,smp_num); attr_sample_name(); win_print(x+4,(t-first_sample)%semicount,storage); attr_normal(); } } } /* instrument panel */ static void display_inst(int diff) { int count,semicount,t,x,winx; char inst_name[20], inst_num[10]; first_inst+=diff; win_get_size(&winx,&semicount); if (winx=mf->numins-count) first_inst=mf->numins-count; if (first_inst<0) first_inst=0; if (mf->numins>semicount&&mf->numinsnumins+1)>>1; if (winxnumins&&t<(count+first_inst);t++) { x=((t-first_inst)instruments[t].insname ? mf->instruments[t].insname:""); convert_string(storage); snprintf(inst_num, 10, "%3i ", t); attr_inst_num(); win_print(x,(t-first_sample)%semicount,inst_num); attr_inst_name(); win_print(x+4,(t-first_inst)%semicount,storage); } } attr_normal(); } /* comment panel */ static void display_comment(int diff) { first_comment+=diff; win_clear(); first_comment=display_banner(mf->comment,0,0,first_comment,1); } /* remove an entry from the playlist */ static void remove_entry(int entry) { int cur=PL_GetCurrentPos(&playlist); if (cur==entry) { if (cur==PL_GetLength(&playlist)-1) Player_SetNextMod(0); else Player_SetNextMod(entry); } PL_DelEntry(&playlist,entry); } /* remove an entry from the playlist and delete the associated module */ static void cb_delete_entry(int button,void *input,void *entry) { if (!button) { PLAYENTRY *cur=PL_GetEntry(&playlist,(long)entry); if (cur->archive) { if (unlink(cur->archive)==-1) dlg_error_show("Error deleting file!\n(%s)"); } else { if (unlink(cur->file)==-1) dlg_error_show("Error deleting file!\n(%s)"); } remove_entry((long)entry); } } /* split a filename into the name and the last extension */ static void split_name(char *file,char **name,char **ext) { *name=strrchr(file,PATH_SEP); if (!*name) *name=file; *ext=strrchr(*name,'.'); if (!*ext) *ext=&(*name[strlen(*name)]); } static BOOL sort_rev=0; static enum {SORT_NAME,SORT_EXT,SORT_PATH,SORT_TIME} sort_mode=SORT_NAME; static int cb_cmp_sort(PLAYENTRY *small,PLAYENTRY *big) { char ch_s=' ',ch_b=' ',*ext_s,*ext_b,*name_s,*name_b; int ret=0; switch (sort_mode) { case SORT_NAME: split_name(small->file,&name_s,&ext_s); split_name(big->file,&name_b,&ext_b); ch_s=*ext_s;ch_b=*ext_b; *ext_s='\0';*ext_b='\0'; ret=strcasecmp(name_s,name_b); *ext_s=ch_s;*ext_b=ch_b; break; case SORT_EXT: split_name(small->file,&name_s,&ext_s); split_name(big->file,&name_b,&ext_b); ret=strcasecmp(ext_s,ext_b); break; case SORT_PATH: ext_s=small->archive; if (!ext_s) ext_s=small->file; name_s=strrchr(ext_s,PATH_SEP); if (name_s) { ch_s=*name_s;*name_s='\0'; } ext_b=big->archive; if (!ext_b) ext_b=big->file; name_b=strrchr(ext_b,PATH_SEP); if (name_b) { ch_b=*name_b;*name_b='\0'; } ret=strcasecmp(ext_s,ext_b); if (name_s) *name_s=ch_s; if (name_b) *name_b=ch_b; break; case SORT_TIME: ret=(small->time==big->time?0: (small->timetime?-1:1)); break; } return (sort_rev)?-ret:ret; } /* overwrites an existdng playlist */ static void cb_overwrite(int button,void *input,void *file) { if (!button) { if (PL_Save(&playlist,file)) CF_set_string(&config.pl_name,file,PATH_MAX); else dlg_error_show("Error saving playlist!\n(%s)"); } if (file) free(file); } /* saves a playlist */ static void cb_save_as(int button,void *input,void *data) { if (!button) { if (file_exist(input)) { char *f_copy=strdup(input); char *msg=str_sprintf("File \"%s\" exists.\n" "Really overwrite the file?",f_copy); dlg_message_open(msg,"&Yes|&No",1,cb_overwrite,f_copy); free(msg); } else { if (PL_Save(&playlist,input)) CF_set_string(&config.pl_name,input,PATH_MAX); else dlg_error_show("Error saving playlist!\n(%s)"); } } } /* loads or merges a playlist */ static void cb_load_playlist(int button,void *input,void *data) { if (!button) { int actLine=(long)data; /* <0: Load list/module */ if (actLine<0) PL_ClearList(&playlist); else PL_StartInsert(&playlist,actLine); MA_FindFiles(&playlist,input); PL_StopInsert(&playlist); if (actLine<0) { PL_InitCurrent(&playlist); Player_SetNextMod(-1); } else { /* remove duplicates entries */ int current,old_cur=PL_GetCurrentPos(&playlist); PL_DelDouble(&playlist); current=PL_GetCurrentPos(&playlist); if (current!=old_cur) Player_SetNextMod(current); } } } /* playlist menu handler */ static void cb_handle_menu(MMENU *menu) { MENU_DATA *data=menu->data; int actLine=*data->actLine; PLAYENTRY *cur; char *name,*msg; /* main menu */ if (!menu->id) { switch (menu->cur) { /* play highlighted module */ case 0: if (actLine>=0) Player_SetNextMod(actLine); break; /* remove highlighted module */ case 1: if (actLine>=0) remove_entry(actLine); break; /* delete highlighted module */ case 2: cur=PL_GetEntry(&playlist,actLine); if (!cur) break; if (cur->archive) { name=strrchr(cur->file,PATH_SEP); if (name) name++; else name=cur->file; if (strlen(cur->archive)>60) msg=str_sprintf2("File \"%s\" is in an archive!\n" "Really delete whole archive\n" " \"...%s\"?",name, &(cur->archive[strlen(cur->archive)-57])); else msg=str_sprintf2("File \"%s\" is in an archive!\n" "Really delete whole archive\n" " \"%s\"?",name,cur->archive); dlg_message_open(msg,"&Yes|&No",1, cb_delete_entry,(void*)(long)actLine); } else { if (strlen(cur->file)>50) msg=str_sprintf("Delete file \"...%s\"?", &(cur->file[strlen(cur->file)-47])); else msg=str_sprintf("Delete file \"%s\"?",cur->file); dlg_message_open(msg,"&Yes|&No",1, cb_delete_entry,(void*)(long)actLine); } free(msg); break; /* shuffle list */ case 5: PL_Randomize(&playlist,1); break; /* cancel */ case 7: break; default: return; } /* file menu */ } else if (menu->id == 1) { switch (menu->cur) { /* load */ case 0: dlg_input_str("Load playlist/module:",config.pl_name,PATH_MAX, cb_load_playlist,(void*)-1); break; /* insert */ case 1: dlg_input_str("Insert playlist/module:",config.pl_name,PATH_MAX, cb_load_playlist,(void*)(long)actLine); break; /* save */ case 2: if (!PL_Save(&playlist,config.pl_name)) dlg_error_show("Error saving playlist!\n(%s)"); break; /* save as */ case 3: dlg_input_str("Save playlist as:",config.pl_name,PATH_MAX, cb_save_as,NULL); break; default: return; } /* sort menu */ } else { /* reverse flag */ sort_rev=(long)menu->entries[5].data; switch (menu->cur) { /* by name */ case 0: sort_mode=SORT_NAME; PL_Sort(&playlist,cb_cmp_sort); break; /* by extension */ case 1: sort_mode=SORT_EXT; PL_Sort(&playlist,cb_cmp_sort); break; /* by path */ case 2: sort_mode=SORT_PATH; PL_Sort(&playlist,cb_cmp_sort); break; /* by time */ case 3: sort_mode=SORT_TIME; PL_Sort(&playlist,cb_cmp_sort); break; default: return; } } menu_close(data->menu); return; } static void display_playentry(PLAYENTRY *pos,PLAYENTRY *cur,int nr,int y,int x,BOOL reverse,int width) { char *name,sort; char time[8]="",tmpfmt[30]; int timelen=0; if (pos->time>0) { #ifdef HAVE_SNPRINTF snprintf(time,7," %2d:%02d", (int)((pos->time/60)%60),(int)(pos->time%60)); #else sprintf(time," %2d:%02d", (int)((pos->time/60)%60),(int)(pos->time%60)); #endif timelen=strlen(time); } name=strrchr(pos->file,PATH_SEP); if (name && !config.fullpaths) name++; else name=pos->file; if (pos==cur) sort='>'; else if (pos->played) sort='*'; else sort=' '; /* Display number */ attr_list_num(); #ifdef HAVE_SNPRINTF snprintf(storage, STORAGELEN, "%4i ", nr); #else snprintf(storage, "%4i ", nr); #endif win_print(x,y,storage); x += strlen(storage); attr_normal(); /* Display sort */ attr_list_sort(); #ifdef HAVE_SNPRINTF snprintf(storage, STORAGELEN, "%c", sort); #else snprintf(storage, "%c", sort); #endif win_print(x,y,storage); x += strlen(storage); attr_normal(); if (pos->archive) { if (strlen(name)>width-13-timelen) { name=name+strlen(name)-(width-16-timelen); if (timelen) { sprintf(tmpfmt,"...%%-%ds%%s",width-22); #ifdef HAVE_SNPRINTF snprintf(storage,STORAGELEN,tmpfmt,name,time); #else sprintf(storage,tmpfmt,name,time); #endif } else { sprintf(tmpfmt,"...%%-%ds",width-16); #ifdef HAVE_SNPRINTF snprintf(storage,STORAGELEN,tmpfmt,name); #else sprintf(storage,tmpfmt,name); #endif } } else { if (timelen) { sprintf(tmpfmt,"%%-%ds%%s",width-19); #ifdef HAVE_SNPRINTF snprintf(storage,STORAGELEN,tmpfmt,name,time); #else sprintf(storage,tmpfmt,name,time); #endif } else { sprintf(tmpfmt,"%%-%ds",width-13); #ifdef HAVE_SNPRINTF snprintf(storage,STORAGELEN,tmpfmt,name); #else sprintf(storage,tmpfmt,name); #endif } } } else if (strlen(name)>width-7-timelen) { name=name+strlen(name)-(width-10-timelen); if (timelen) { sprintf(tmpfmt,"...%%-%ds%%s",width-16); #ifdef HAVE_SNPRINTF snprintf(storage,STORAGELEN,tmpfmt,name,time); #else sprintf(storage,tmpfmt,name,time); #endif } else { sprintf(tmpfmt,"...%%-%ds",width-10); #ifdef HAVE_SNPRINTF snprintf(storage,STORAGELEN,tmpfmt,name); #else sprintf(storage,tmpfmt,name); #endif } } else { if (timelen) { sprintf(tmpfmt,"%%-%ds%%s",width-13); #ifdef HAVE_SNPRINTF snprintf(storage,STORAGELEN,tmpfmt,name,time); #else sprintf(storage,tmpfmt,name,time); #endif } else { sprintf(tmpfmt,"%%-%ds",width-7); #ifdef HAVE_SNPRINTF snprintf(storage,STORAGELEN,tmpfmt,name); #else sprintf(storage,tmpfmt,name); #endif } } if (reverse) win_attrset(A_REVERSE); attr_list_name(); win_print(x,y,storage); x+=strlen(storage); win_attrset(A_NORMAL); attr_normal(); if (pos->archive) { attr_list_pack(); win_print(x,y,"(pack)"); attr_normal(); } // win_print(x,y,storage); } /* playlist panel */ static void display_list(int diff,COMMAND com) { static char *no_data ="\nPlaylist is empty!\n"; static MENU_DATA menu_data; static int actLine=-1; static MENTRY file_entries[]={ {"&Load...", 0,"Load new playlist/module"}, {"&Insert...", 0,"Insert new playlist/module in current playlist"}, {"&Save", 0,NULL}, {"Save &as...",0,"Save playlist in a specified file"}, }; static MMENU file_menu={0,0,4,1,file_entries,cb_handle_menu,NULL,&menu_data,1}; static MENTRY sort_entries[]={ {"by &name", 0,"Sort list by name of modules"}, {"by &extension",0,"Sort list by extension of modules"}, {"by &path", 0,"Sort list by path of modules/archives"}, {"by &time", 0,"Sort list by playing time of modules"}, {"----------", 0,NULL}, {"[%c] &reverse",0,"Smaller to bigger or reverse sort"}}; static MMENU sort_menu={0,0,6,1,sort_entries,cb_handle_menu,NULL,&menu_data,2}; static MENTRY entries[]={ {"&Play", 0,"Play selected entry"}, {"&Remove", 0,"Remove selected entry from list"}, {"&Delete...", 0,"Remove selected entry from list and delete it on disk"}, {"-----------", 0,NULL}, {"&File >",&file_menu,"Load/Save playlist/modules"}, {"&Shuffle", 0,"Shuffle the list"}, {"S&ort >",&sort_menu,"Sort the list"}, {"&Back", 0,"Leave menu"}}; static MMENU menu={0,0,8,1,entries,cb_handle_menu,NULL,&menu_data,0}; int count,semicount,playcount,t,winx,x,width; PLAYENTRY *cur; playcount=PL_GetLength(&playlist); if (actLine>=playcount) actLine=playcount-1; if (com==MENU_ACTIVATE) { menu_data.menu=&menu; menu_data.actLine=&actLine; set_help(&file_entries[2],"Save list in '%s'",config.pl_name); menu_open(&menu,5,5); return; } win_clear(); if (playcount) { win_get_size(&winx,&semicount); if (winx<40+MINVISIBLE) { count=semicount; width=winx; } else { count=semicount*2; width=winx>>1; } cur=PL_GetCurrent(&playlist); if (actLine<0) { actLine=PL_GetCurrentPos(&playlist); first_list=actLine-semicount/2; if (first_list<0) first_list=0; } actLine+=diff; if (actLine<0) actLine=0; else if (actLine>=playcount) actLine=playcount-1; if (actLine=first_list+count) first_list=actLine-count+1; for (t=first_list;tflags&UF_INST)))|| ((cur_display==DISPLAY_COMMENT)&&(!mf->comment))) { cur_display=(cur_display==old_display)?DISPLAY_SAMPLE:old_display; change=1; } else break; } if (change) { win_change_panel(cur_display); return 0; } /* set panel title */ switch(cur_display) { case DISPLAY_HELP: strcpy(paneltitle,"[ Help ]"); break; case DISPLAY_INST: #ifdef HAVE_SNPRINTF snprintf(paneltitle,STORAGELEN,"[ %d Instruments ]",mf->numins); #else sprintf(paneltitle,"[ %d Instruments ]",mf->numins); #endif break; case DISPLAY_SAMPLE: #ifdef HAVE_SNPRINTF snprintf(paneltitle,STORAGELEN,"[ %d Samples ]",mf->numsmp); #else sprintf(paneltitle,"[ %d Samples ]",mf->numsmp); #endif break; case DISPLAY_COMMENT: strcpy(paneltitle,"[ Message ]"); break; case DISPLAY_LIST: #ifdef HAVE_SNPRINTF snprintf(paneltitle,STORAGELEN,"[ %d Modules ]",PL_GetLength(&playlist)); #else sprintf(paneltitle,"[ %d Modules ]",PL_GetLength(&playlist)); #endif break; case DISPLAY_CONFIG: strcpy(paneltitle,"[ Config ]"); break; } pos = 0; attr_info1(); win_print_root(pos, 6, paneltitle); pos += strlen(paneltitle); attr_info2(); win_print_root(pos, 6, " --"); pos += 3; /* set available panel information */ strcpy(otherpanels," --"); if (cur_display!=DISPLAY_HELP) { //strcat(otherpanels," H:[help]"); attr_info3(); win_print_root(pos, 6, " H:"); pos += 3; attr_info4(); win_print_root(pos, 6, "[help]"); pos += 6; } if ((cur_display!=DISPLAY_INST) && mf && (mf->flags&UF_INST)) { //strcat(otherpanels," I:[instruments]"); attr_info3(); win_print_root(pos, 6, " I:"); pos += 3; attr_info4(); win_print_root(pos, 6, "[instruments]"); pos += 13; } if (cur_display!=DISPLAY_SAMPLE && mf) { //strcat(otherpanels," S:[samples]"); attr_info3(); win_print_root(pos, 6, " S:"); pos += 3; attr_info4(); win_print_root(pos, 6, "[samples]"); pos += 9; } if ((cur_display!=DISPLAY_COMMENT) && mf && (mf->comment)) { //strcat(otherpanels," M:[message]"); attr_info3(); win_print_root(pos, 6, " M:"); pos += 3; attr_info4(); win_print_root(pos, 6, "[messages]"); pos += 10; } if (cur_display!=DISPLAY_LIST) { //strcat(otherpanels," L:[playlist]"); attr_info3(); win_print_root(pos, 6, " L:"); pos += 3; attr_info4(); win_print_root(pos, 6, "[playlist]"); pos += 10; } if (cur_display!=DISPLAY_CONFIG) { //strcat(otherpanels," C:[config]"); attr_info3(); win_print_root(pos, 6, " C:"); pos += 3; attr_info4(); win_print_root(pos, 6, "[config]"); pos += 8; } attr_normal(); //strcat (otherpanels,"\n"); // win_attrset(A_REVERSE); // win_print_root(0,6,paneltitle); // win_attrset(A_NORMAL); // win_print_root(strlen(paneltitle),6,otherpanels); /* display panel contents */ switch(cur_display) { case DISPLAY_HELP: display_help(diff); break; case DISPLAY_INST: display_inst(diff); break; case DISPLAY_SAMPLE: display_sample(diff); break; case DISPLAY_COMMENT: display_comment(diff); break; case DISPLAY_LIST: display_list(diff,com); break; case DISPLAY_CONFIG: display_config(diff); break; } return 1; } /* displays the top of the screen */ void display_header(void) { if (quiet) return; display_version(); update_message(); if (Player_Paused()) display_pausebanner(); else { display_driver(); display_file(); display_name(); display_status(); } } static BOOL display_head_repaint(MWINDOW *win) { display_header(); return 1; } static BOOL display_inf_repaint(MWINDOW *win) { if ((long)win->data!=cur_display) old_display=cur_display; cur_display=(long)win->data; return display_information(0,COM_NONE); } void display_start(void) { if (quiet) return; first_inst=first_sample=first_comment=0; win_panel_repaint(); } /* handle interface-specific keys */ static BOOL display_handle_key(MWINDOW *win,int ch) { switch (ch) { case KEY_DOWN: display_information(1,COM_NONE); break; case KEY_UP: display_information(-1,COM_NONE); break; case KEY_RIGHT: if (cur_display!=DISPLAY_LIST) return 0; /* fall through */ case KEY_NPAGE: display_information(win->height,COM_NONE); break; case KEY_LEFT: if (cur_display!=DISPLAY_LIST) return 0; /* fall through */ case KEY_PPAGE: display_information(-win->height,COM_NONE); break; case KEY_HOME: display_information(-32000,COM_NONE); break; #ifdef KEY_END case KEY_END: display_information(32000,COM_NONE); break; #endif case KEY_ENTER: case '\r': if (cur_display==DISPLAY_LIST) display_information(0,MENU_ACTIVATE); else return 0; break; default: return 0; } return 1; } /* setup interface */ void display_init(void) { int i; win_panel_set_repaint(DISPLAY_ROOT,display_head_repaint); for (i=1;i<=DISPLAY_CONFIG;i++) { win_panel_open(i,0,PANEL_Y,999,999,0,NULL); win_panel_set_repaint(i,display_inf_repaint); win_panel_set_handle_key(i,display_handle_key); win_panel_set_resize(i,1,NULL); win_panel_set_data(i,(void*)(long)i); } win_change_panel(cur_display); setup_printf(); } /* This will set the xterm (or equivalent) Title and Icon title. * * The title contains -= MikMod x.x.x =- (%s) where %s is the song name * the icon contains -= MikMod x.x.x =- * * pass NULL as songname to reset the title * * Written using the 'Xterm-Title mini-howto' */ void set_term_title(char *songname) { char *env_term; static int last_config=0; if (!config.xterm_title && !last_config) { return; } if (last_config && !config.xterm_title) { /* xterm title setting has just been disabled */ songname = NULL; } last_config = config.xterm_title; env_term = getenv("TERM"); if (env_term==NULL) { return; } if (songname!=NULL) { #ifdef HAVE_SNPRINTF snprintf(storage,STORAGELEN,"%s (%s)", mikversion, songname); #else sprintf(storage,"%s: (%s)", mikversion, songname); #endif } else { #ifdef HAVE_SNPRINTF snprintf(storage,STORAGELEN,""); #else sprintf(storage,""); #endif } if ( strcmp(env_term, "xterm")==0 || strcmp(env_term, "xterm-color")==0 || strcmp(env_term, "rxvt")==0 || strcmp(env_term, "aixterm")==0 || strcmp(env_term, "dtterm")==0 || strcmp(env_term, "xterm-color")==0 || strcmp(env_term, "xterm-color")==0 || strcmp(env_term, "xterm-color")==0 ) { printf("%c]0;%s%c", '\033', storage, '\007'); printf("%c]1;%s%c", '\033', mikversion, '\007'); } else if (strcmp(env_term, "iris-ansi")==0) { printf("%cP1.y%s%c\\", '\033', storage, '\033'); printf("%cP3.y%s%c\\", '\033', mikversion, '\033'); } else if (strcmp(env_term, "hpterm")==0) { printf("\033&f0k%dD%s", strlen(storage), storage); printf("\033&f-1k%dD%s", strlen(mikversion), mikversion); } } /* ex:set ts=4: */