/* MikMod example player (c) 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: mwindow.c,v 1.2 2003/09/30 01:53:30 raph Exp $ Some window functions ==============================================================================*/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include #ifdef HAVE_SYS_IOCTL_H #include #endif #include "display.h" #include #include "player.h" #include "mwindow.h" #include "attr.h" #define PANEL_HELP 1 #define PANEL_SAMPLE 2 #define PANEL_INSTR 3 #define PANEL_COMMENT 4 #define PANEL_LIST 5 #define PANEL_CONFIG 6 #define PANEL_CNT 7 #ifndef ACS_ULCORNER #if defined(__OS2__)||defined(__EMX__) #define BOX_UL '\xDA' #define BOX_UR '\xBF' #define BOX_LL '\xC0' #define BOX_LR '\xD9' #define BOX_HLINE '\xC4' #define BOX_VLINE '\xB3' #else #define BOX_UL '+' #define BOX_UR '+' #define BOX_LL '+' #define BOX_LR '+' #define BOX_HLINE '-' #define BOX_VLINE '|' #endif #else #define BOX_UL ACS_ULCORNER #define BOX_UR ACS_URCORNER #define BOX_LL ACS_LLCORNER #define BOX_LR ACS_LRCORNER #define BOX_HLINE ACS_HLINE #define BOX_VLINE ACS_VLINE #endif /* text creation buffer */ char storage[STORAGELEN]; static int root_y1=7,root_y2=0; /* size of visible root window partions */ static BOOL curses_on=0,win_quiet=1; static int cur_panel=0,old_panel=0; static MWINDOW *panel[PANEL_CNT],*cur_window=NULL; /* screen size */ static int winx=0,winy=0; #if !defined(__OS2__)&&!defined(__EMX__) static BOOL resize=0; static int cursor_old=0; #endif #if defined(__OS2__)||defined(__EMX__) static HVIO hvio=0; static VIOCURSORINFO viocursorinfo; static BYTE clearscreen[2]={0xff,A_NORMAL}; static BYTE mvattr=A_NORMAL; #endif /*========== Display routines */ /* old AIX curses are very limited */ #if defined(AIX) && !defined(mvaddnstr) void mvaddnstr(int y,int x,char *str,int len) { char buffer[STORAGELEN]; int l=strlen(str); strncpy(buffer,str,len); if (lwidth-x>0) { clearscreen[1]=mvattr; VioWrtNCell(clearscreen,cur_window->width-x, cur_window->y+y,cur_window->x+x,hvio); } } /* clear to end of line on root window */ void win_clrtoeol_root(int x,int y) { clearscreen[1]=mvattr; VioWrtNCell(clearscreen,winx-x,y,x,hvio); } #else /* #if defined(__OS2__)||defined(__EMX__) */ /* handler for terminal resize events */ RETSIGTYPE sigwinch_handler(int signum) { /* schedule a resizeterm() */ resize=1; signal(SIGWINCH,sigwinch_handler); } /* update window */ void win_refresh(void) { if (win_quiet) return; refresh(); } void win_cursor_set(BOOL visible) { if (cursor_old!=ERR) { if (visible) curs_set(cursor_old); else curs_set(0); } } static void init_curses(void) { initscr(); cbreak(); noecho(); nonl(); nodelay(stdscr,TRUE); #if !defined(AIX) || defined(NCURSES_VERSION) timeout(0); #endif keypad(stdscr,TRUE); cursor_old=curs_set(0); curses_on=1; } /* init window functions(e.g. init curses) */ void win_init(BOOL quiet) { win_quiet=quiet; if (!win_quiet) { init_curses(); getmaxyx(stdscr,winy,winx); signal(SIGWINCH,sigwinch_handler); } win_open(0,0,winx,winy,0,NULL); win_set_resize(1,NULL); } /* clean up(e.g. exit curses) */ void win_exit(void) { if (win_quiet || !curses_on) return; signal(SIGWINCH,SIG_DFL); clear(); mvaddnstr(winy-2,0,mikversion,winx); win_refresh(); win_cursor_set(1); endwin(); curses_on=0; } /* clear to end of line on uppermost window */ void win_clrtoeol(int x,int y) { int i,len=cur_window->width-x; if (len>0) { for (i=0;iy+y,cur_window->x+x,storage,len); } } /* clear to end of line on root window */ void win_clrtoeol_root(int x,int y) { move(y,x);clrtoeol(); } #endif BOOL win_clear_win(MWINDOW *win) { int i; if ((win->width>0)&&(win->height>0)) { for (i=0;iwidth;i++) storage[i]=' '; storage[i]='\0'; for (i=0;iheight;i++) mvaddnstr(win->y+i,win->x,storage,win->width); } return 1; } /* clear uppermost window */ void win_clear(void) { win_clear_win(cur_window); } /* clear root window */ void win_clear_root(void) { MWINDOW *win=panel[0]; int i; if ((win->width>0)&&(win->height>0)) { for (i=0;iwidth;i++) storage[i]=' '; storage[i]='\0'; for (i=0;iheight && iy+i,win->x,storage,win->width); i=win->height-root_y2; if (i<0) i=0; for (;iheight;i++) mvaddnstr(win->y+i,win->x,storage,win->width); } } void win_box(int x1,int y1,int x2,int y2,char *title) { int i,sx1,sx2,sy1,sy2; if (win_quiet) return; sx1=x1>=0?x1+1:0; sx2=x2=root_y1?y1+1:root_y1; sy2=y2=0) mvaddch(y2,x1,BOX_LL); if (x2=root_y1) { if (x1>=0) mvaddch(y1,x1,BOX_UL); if (x2=0) mvaddch(i,x1,BOX_VLINE); if (x2winy-ofs) height=winy-y-ofs; } else { if (ywiny-ofs-root_y2) height=winy-y-ofs-root_y2; } if (x+width>winx-ofs) width=winx-x-ofs; if (width<0) width=0; if (height<0) height=0; if (border &&(dst_panel==cur_panel)) win_box(x-1,y-1,x+width,y+height,title); win->x=x; win->y=y; win->width=width; win->height=height; win->border=border; win->resize=0; if (title) win->title=strdup(title); else win->title=NULL; win->next=NULL; win->repaint=win_clear_win; win->handle_key=NULL; for (help=panel[dst_panel];help && help->next;help=help->next); if (help) help->next=win; else panel[dst_panel]=win; if (dst_panel==cur_panel) cur_window=win; return win; } /* open new window on current panel */ MWINDOW* win_open(int x,int y,int width,int height,BOOL border,char *title) { return win_panel_open(cur_panel,x,y,width,height,border,title); } MWINDOW *win_get_first(int dst_panel) { MWINDOW *win; for (win=panel[dst_panel];win && win->next;win=win->next); return win; } /* set function which sould be called on a repaint request */ void win_set_repaint(WinRepaintFunc func) { cur_window->repaint=func; } void win_panel_set_repaint(int panel,WinRepaintFunc func) { win_get_first(panel)->repaint=func; } /* set function which sould be called on a key press */ void win_set_handle_key(WinKeyFunc func) { cur_window->handle_key=func; } void win_panel_set_handle_key(int panel,WinKeyFunc func) { win_get_first(panel)->handle_key=func; } /* should window be automatically resized? should a function be called on resize? */ void win_set_resize(BOOL auto_resize,WinResizeFunc func) { cur_window->resize=auto_resize; cur_window->handle_resize=func; } void win_panel_set_resize(int panel,BOOL auto_resize,WinResizeFunc func) { win_get_first(panel)->resize=auto_resize; win_get_first(panel)->handle_resize=func; } /* set private data */ void win_set_data(void *data) { cur_window->data=data; } void win_panel_set_data(int panel,void *data) { win_get_first(panel)->data=data; } void win_do_resize(int dx,int dy,BOOL root) { MWINDOW *win; int i=root?0:1; if (win_quiet) return; for (;inext) { if (win->resize) { win->width+=dx; if (win->width<0) win->width=0; win->height+=dy; if (win->height<0) win->height=0; } if (win->handle_resize) win->handle_resize(win,dx,dy); } win_panel_repaint(); } /* check if a resize was scheduled and do it */ BOOL win_check_resize(void) { if (win_quiet) return 0; #if !defined(__OS2__)&&!defined(__EMX__) /* if a resize was scheduled,do it now */ if (resize) { int oldx,oldy; #if (NCURSES_VERSION_MAJOR >= 4) && defined(TIOCGWINSZ) && defined(HAVE_NCURSES_RESIZETERM) struct winsize ws; ws.ws_col=ws.ws_row=0; ioctl(0,TIOCGWINSZ,&ws); if (ws.ws_col && ws.ws_row) resizeterm(ws.ws_row,ws.ws_col); #else endwin(); init_curses(); win_refresh(); #endif resize=0; oldx=winx;oldy=winy; getmaxyx(stdscr,winy,winx); win_do_resize(winx-oldx,winy-oldy,1); return 1; } #endif return 0; } static char status_message[MAXWIDTH+2]; static void win_status_repaint(void) { MWINDOW *win=panel[0]; int i; if (win_quiet) return; attr_bottom_status_line1(); if ((root_y2>1)&&(win->height>1)) for (i=0;iwidth;i++) mvaddch(win->height-2,i,BOX_HLINE); attr_normal(); } /* init the status line(height=0,1,2 0: no status line) */ void win_init_status(int height) { int old_y2=root_y2; if (height!=root_y2) { root_y2=height<0?0:(height>2?2:height); #if defined(__OS2__)||defined(__EMX__) status_message[0]='\0'; #else status_message[0]='\n'; status_message[1]='\0'; #endif win_do_resize(0,old_y2-root_y2,0); } } /* set the status line */ void win_status(char *msg) { MWINDOW *win=panel[0]; int len=0; if (msg) { len=strlen(msg); if (len>MAXWIDTH) len=MAXWIDTH; strncpy(status_message,msg,len); } #if defined(__OS2__)||defined(__EMX__) status_message[len]='\0'; #else status_message[len]='\n'; status_message[len+1]='\0'; #endif if (win_quiet) return; if ((root_y2>0)&&(win->height>0)) { mvaddnstr(win->y+win->height-1,win->x,status_message,win->width); #if defined(__OS2__)||defined(__EMX__) win_clrtoeol_root(win->x+len,win->y+win->height-1); #endif } } /* repaint the whole panel */ void win_panel_repaint(void) { if (win_quiet) return; clear(); if (panel[0]->repaint) if (!panel[0]->repaint(panel[0])) return; for (cur_window=panel[cur_panel];cur_window;cur_window=cur_window->next) { if (cur_window->border) win_box(cur_window->x-1,cur_window->y-1, cur_window->x+cur_window->width,cur_window->y+cur_window->height, cur_window->title); if (cur_window->repaint && cur_window->width>0 && cur_window->height>0) if (!cur_window->repaint(cur_window)) return; } win_status_repaint(); for (cur_window=panel[cur_panel];cur_window && cur_window->next;cur_window=cur_window->next); } /* close uppermost window */ void win_close(void) { if (cur_window) { MWINDOW *win; for (win=panel[cur_panel];win->next!=cur_window;win=win->next); if (cur_window->title) free(cur_window->title); free(cur_window); win->next=NULL; cur_window=win; win_panel_repaint(); } } /* close window win */ void win_close_win(MWINDOW *win) { int i; MWINDOW *pos; for (i=0;inext) if (pos==win) { if (win==cur_window) for (cur_window=panel[i]; cur_window->next!=win; cur_window=cur_window->next); for (pos=panel[i]; pos->next!=win; pos=pos->next); pos->next=win->next; if (win->title) free(win->title); free(win); if (i==cur_panel) win_panel_repaint(); return; } } /* get size of uppermost window */ void win_get_size(int *x,int *y) { *x=cur_window->width; *y=cur_window->height; } /* get size of whole screen */ void win_get_size_root(int *x,int *y) { *x=panel[0]->width; *y=panel[0]->height; } /* get maximal size of a new window without a border and therefore the needed minimal y position */ void win_get_size_max(int *y,int *width,int *height) { *y=root_y1; *width=panel[0]->width; *height=panel[0]->height-root_y1-root_y2; if (*height<0) *height=0; } /* get uppermost window */ MWINDOW *win_get_window(void) { return cur_window; } /* print string in current window(cur_window) */ void win_print(int x,int y,char *str) { int len=strlen(str); #if defined(__OS2__)||defined(__EMX__) if ((str[len-1]=='\n')&&(str[len-2]=='\r')) len--; #endif if ((x>=cur_window->width)||(y>=cur_window->height)|| ((cur_window!=panel[0])&&(y+cur_window->y>=winy-root_y2))|| (!len)||win_quiet) return; if (len+x>cur_window->width) len=cur_window->width-x; if ((str[len-1]=='\n')||(str[len-1]=='\r')) #if !defined(__OS2__)&&!defined(__EMX__) if (cur_window->x+cur_window->widthy,x+cur_window->x,str,len); } /* print string on root window */ void win_print_root(int x,int y,char *str) { MWINDOW *win=cur_window; cur_window=panel[0]; win_print(x,y,str); cur_window=win; } /* draw horizontal line(rev: in reverse) */ void win_line(int x1,int x2,int y) { int x; if ((yheight) &&(!win_quiet)) for (x=x1;x<=x2 && xwidth;x++) mvaddch(y+cur_window->y,x+cur_window->x,BOX_HLINE); } /* set attribute for the following output operations */ void win_attrset(int attrs) { attrset(attrs); } /* change current panel */ void win_change_panel(int new_panel) { if (new_panel==cur_panel) new_panel=old_panel; old_panel=cur_panel; if (new_panel!=cur_panel) { cur_panel=new_panel; for (cur_window=panel[cur_panel];cur_window && cur_window->next;cur_window=cur_window->next); win_panel_repaint(); } } /* handle key press(panel change and call of key handler of uppermost window),return: was key handled */ BOOL win_handle_key(int ch) { switch (ch) { case KEY_F(1): win_change_panel(PANEL_HELP); break; case KEY_F(2): win_change_panel(PANEL_SAMPLE); break; case KEY_F(3): win_change_panel(PANEL_INSTR); break; case KEY_F(4): #if defined(__OS2__)||defined(__EMX__) case KEY_SF(9): /* shift-F9 */ #else case KEY_F(19): /* shift-F9 on some curses implementations */ #endif win_change_panel(PANEL_COMMENT); break; case KEY_F(5): win_change_panel(PANEL_LIST); break; case KEY_F(6): win_change_panel(PANEL_CONFIG); break; default: if (cur_window->handle_key) return cur_window->handle_key(cur_window,ch); else return 0; } return 1; } /* ex:set ts=4: */