1 /* MikMod module player
2 (c) 1998 - 2000 Miodrag Vallat and others - see file AUTHORS for
3 complete list.
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
18 02111-1307, USA.
19 */
20
21 /*==============================================================================
22
23 $Id: mwindow.c,v 1.1.1.1 2004/01/16 02:07:36 raph Exp $
24
25 Some window functions
26
27 ==============================================================================*/
28
29 #ifdef HAVE_CONFIG_H
30 #include "config.h"
31 #endif
32 #include <signal.h>
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <stdarg.h>
36 #include <string.h>
37
38 #if !defined(__OS2__)&&!defined(__EMX__)&&!defined(__DJGPP__)&&!defined(_WIN32)
39 #ifdef HAVE_SYS_IOCTL_H
40 #include <sys/ioctl.h>
41 #endif
42 #if !defined(GWINSZ_IN_SYS_IOCTL) && defined(HAVE_TERMIOS_H)
43 #include <termios.h>
44 #endif
45 #endif
46
47 #if defined(__OS2__)||defined(__EMX__)||defined(__DJGPP__)||defined(_WIN32)
48 #if defined(__OS2__)||defined(__EMX__)
49 #define INCL_VIO
50 #define INCL_DOS
51 #define INCL_KBD
52 #define INCL_DOSPROCESS
53 #endif
54 #include <conio.h>
55 #endif
56
57 #ifdef HAVE_UNISTD_H
58 #include <unistd.h>
59 #endif
60
61 #include <mikmod.h>
62 #include "display.h"
63 #include "player.h"
64 #include "mwindow.h"
65 #include "mutilities.h"
66 #include "keys.h"
67 #include "mthreads.h"
68
69 #define INVISIBLE(w) (win_quiet || ((w)!=cur_window && (w)!=panel[0]))
70 #define INVISIBLE_RET(w) if (win_quiet || ((w)!=cur_window && (w)!=panel[0])) return;
71
72 #ifdef ACS_ULCORNER
73
74 #define BOX_UL ACS_ULCORNER
75 #define BOX_UR ACS_URCORNER
76 #define BOX_LL ACS_LLCORNER
77 #define BOX_LR ACS_LRCORNER
78 #define BOX_HLINE ACS_HLINE
79 #define BOX_VLINE ACS_VLINE
80
81 #else
82
83 #if defined(__OS2__)||defined(__EMX__)||defined(__DJGPP__)||defined(_WIN32)
84 #define BOX_UL '\xda'
85 #define BOX_UR '\xbf'
86 #define BOX_LL '\xc0'
87 #define BOX_LR '\xd9'
88 #define BOX_HLINE '\xc4'
89 #define BOX_VLINE '\xb3'
90 #else
91 #define BOX_UL '+'
92 #define BOX_UR '+'
93 #define BOX_LL '+'
94 #define BOX_LR '+'
95 #define BOX_HLINE '-'
96 #define BOX_VLINE '|'
97 #endif
98
99 #endif
100
101 void win_do_resize(int dx, int dy, BOOL root);
102
103 /* text creation buffer */
104 char storage[STORAGELEN+2];
105
106 static int root_y1 = 7, root_y2 = 0; /* size of visible root window partions */
107 static BOOL curses_on = 0, win_quiet = 1;
108 static int cur_panel = 0, old_panel = 0;
109 static MWINDOW *panel[DISPLAY_COUNT], *cur_window = NULL;
110
111 static BOOL use_colors = 1;
112 static int act_color = A_NORMAL;
113 static THEME *theme = NULL;
114
115 static int winx = 0, winy = 0; /* screen size */
116
117 typedef struct TIMEOUT {
118 WinTimeoutFunc func;
119 void *data;
120 int interval;
121 /* remaining time for the execution of this timeout compared
122 to the timeout located in the timeouts array before this one */
123 int remaining;
124 } TIMEOUT;
125
126 static int cnt_timeouts = 0;
127 static TIMEOUT *timeouts = NULL;
128
129 /*========== Display routines */
130
131 #if defined(__OS2__)||defined(__EMX__)
132 #include "os2video.inc"
133
134 #elif defined(__DJGPP__)
135 #include "dosvideo.inc"
136
137 #elif defined(_WIN32)
138 #include "winvideo.inc"
139
140 #else /* unix, ncurses */
141
142 static int cursor_old = 0;
143 static BOOL resize = 0;
144
145 /* old AIX curses are very limited */
146 #if defined(AIX) && !defined(mvaddnstr)
mvaddnstr(int y,int x,const char * str,int len)147 void mvaddnstr(int y, int x, const char *str, int len)
148 {
149 char buffer[STORAGELEN];
150 int l = strlen(str);
151
152 strncpy(buffer, str, len);
153 if (l < len)
154 while (l < len)
155 buffer[l++] = ' ';
156 buffer[len] = '\0';
157 mvaddstr(y, x, buffer);
158 }
159 #endif
160
161 /* HP-UX curses macros don't work with every cpp */
162 #if defined(__hpux)
getmaxyx_hpux(MWINDOW * win,int * y,int * x)163 void getmaxyx_hpux(MWINDOW * win, int *y, int *x)
164 {
165 *y = __getmaxy(win);
166 *x = __getmaxx(win);
167 }
168
169 #define getmaxyx(win,y,x) getmaxyx_hpux((win),&(y),&(x))
170 #endif
171
172 #if defined(AIX) && !defined(NCURSES_VERSION) && !defined(getmaxyx)
173 #define getmaxyx(win,y,x) (y = LINES, x = COLS)
174 #endif
175
176 #if !defined(getmaxyx)
177 #define getmaxyx(w,y,x) ((y) = getmaxy(w), (x) = getmaxx(w))
178 #endif
179
180 /* handler for terminal resize events */
sigwinch_handler(int signum)181 RETSIGTYPE sigwinch_handler(int signum)
182 {
183 /* schedule a resizeterm() */
184 resize = 1;
185
186 signal(SIGWINCH, sigwinch_handler);
187 }
188
189 /* update window */
win_refresh(void)190 void win_refresh(void)
191 {
192 if (win_quiet)
193 return;
194 refresh();
195 }
196
win_cursor_set(BOOL visible)197 void win_cursor_set(BOOL visible)
198 {
199 if (cursor_old != MIK_CURSES_ERROR) {
200 if (visible)
201 curs_set(cursor_old);
202 else
203 curs_set(0);
204 }
205 }
206
207 #define COLOR_CNT 8
init_curses(void)208 static void init_curses(void)
209 {
210 initscr();
211 cbreak();
212 noecho();
213 nonl();
214 nodelay(stdscr, TRUE);
215 #if !defined(AIX) || defined(NCURSES_VERSION)
216 timeout(0);
217 #endif
218 keypad(stdscr, TRUE);
219 cursor_old = curs_set(0);
220 curses_on = 1;
221
222 /* Color setup */
223 start_color();
224 if (has_colors() && (COLOR_PAIRS >= COLOR_CNT*COLOR_CNT)) {
225 static short colors[] = {
226 COLOR_BLACK,
227 COLOR_BLUE,
228 COLOR_GREEN,
229 COLOR_CYAN,
230 COLOR_RED,
231 COLOR_MAGENTA,
232 COLOR_YELLOW,
233 COLOR_WHITE
234 };
235 int i,j;
236 for (i = 0; i < COLOR_CNT; i++)
237 for (j = 0; j < COLOR_CNT; j++)
238 if (i*COLOR_CNT+j+1 < COLOR_CNT*COLOR_CNT)
239 init_pair(i*COLOR_CNT+j+1, colors[j], colors[i]);
240 use_colors = 1;
241 } else
242 use_colors = 0;
243 }
244
color_to_pair(int attrs)245 static int color_to_pair (int attrs)
246 {
247 return 1 +
248 ((attrs & COLOR_FMASK) >> COLOR_FSHIFT) +
249 ((attrs & COLOR_BMASK) >> COLOR_BSHIFT) * COLOR_CNT;
250 }
251
252 /* system dependant window init function */
win_init_system(void)253 void win_init_system(void)
254 {
255 if (!win_quiet) {
256 init_curses();
257 getmaxyx(stdscr, winy, winx);
258 signal(SIGWINCH, sigwinch_handler);
259 }
260 }
261
262 /* clean up (e.g. exit curses) */
win_exit(void)263 void win_exit(void)
264 {
265 if (win_quiet || !curses_on)
266 return;
267
268 signal(SIGWINCH, SIG_DFL);
269 clear();
270 mvaddnstr(winy - 2, 0, mikversion, winx);
271 win_refresh();
272 win_cursor_set(1);
273 endwin();
274 curses_on = 0;
275 }
276
277 /* clear to end of line on window win */
win_clrtoeol(MWINDOW * win,int x,int y)278 void win_clrtoeol(MWINDOW *win, int x, int y)
279 {
280 int len = win->width - x;
281
282 INVISIBLE_RET(win);
283
284 if (len > 0) {
285 memset(storage, ' ', len);
286 storage[len] = '\0';
287 mvaddnstr(win->y + y, win->x + x, storage, len);
288 }
289 }
290
291 /* check if a resize was scheduled and do it */
win_check_resize(void)292 BOOL win_check_resize(void)
293 {
294 static BOOL in_check_resize = 0;
295
296 if (win_quiet || in_check_resize)
297 return 0;
298 in_check_resize = 1;
299
300 /* if a resize was scheduled, do it now */
301 if (resize) {
302 int oldx, oldy;
303 #if (NCURSES_VERSION_MAJOR >= 4) && defined(TIOCGWINSZ) && defined(HAVE_NCURSES_RESIZETERM)
304 struct winsize ws;
305
306 ws.ws_col = ws.ws_row = 0;
307 ioctl(0, TIOCGWINSZ, &ws);
308 if (ws.ws_col && ws.ws_row)
309 resizeterm(ws.ws_row, ws.ws_col);
310 #else
311 endwin();
312 init_curses();
313 win_refresh();
314 #endif
315 resize = 0;
316 oldx = winx;
317 oldy = winy;
318 getmaxyx(stdscr, winy, winx);
319 win_do_resize(winx - oldx, winy - oldy, 1);
320 in_check_resize = 0;
321 return 1;
322 }
323 in_check_resize = 0;
324 return 0;
325 }
326
win_getch(void)327 static int win_getch(void)
328 {
329 int c = getch();
330 win_check_resize();
331 /* if (c>0) fprintf (stderr," %d ",c);*/
332 return c == MIK_CURSES_ERROR ? 0 : c;
333 }
334
335 #endif /* #ifdef unix */
336
337 /*========== Windowing system */
338
339 /* init window functions (e.g. init curses) */
win_init(BOOL quiet)340 void win_init(BOOL quiet)
341 {
342 win_quiet = quiet;
343
344 win_init_system();
345
346 win_open(0, 0, winx, winy, 0, NULL, ATTR_SONG_STATUS);
347 win_set_resize(1, NULL);
348 }
349
350 /* Does the terminal support colors? */
win_has_colors(void)351 BOOL win_has_colors (void)
352 {
353 return use_colors;
354 }
355
356 /* set the attribute translation table */
win_set_theme(THEME * new_theme)357 void win_set_theme (THEME *new_theme)
358 {
359 theme = new_theme;
360 }
361
362 /* clear window win */
win_clear(MWINDOW * win)363 BOOL win_clear(MWINDOW * win)
364 {
365 if (INVISIBLE(win)) return 1;
366
367 if ((win->width > 0) && (win->height > 0)) {
368 int i;
369
370 win_attrset(win->attrs);
371 memset(storage, ' ', win->width);
372 storage[win->width] = '\0';
373
374 if (win==panel[0]) {
375 for (i = 0; i < win->height && i < root_y1; i++)
376 mvaddnstr(win->y + i, win->x, storage, win->width);
377 i = win->height - root_y2;
378 if (i < 0)
379 i = 0;
380 for (; i < win->height; i++)
381 mvaddnstr(win->y + i, win->x, storage, win->width);
382 } else {
383 for (i = 0; i < win->height; i++)
384 mvaddnstr(win->y + i, win->x, storage, win->width);
385 }
386 }
387 return 1;
388 }
389
win_box_win(int x1,int y1,int x2,int y2,const char * title)390 void win_box_win(int x1, int y1, int x2, int y2, const char *title)
391 {
392 int i, sx1, sx2, sy1, sy2;
393
394 if (win_quiet)
395 return;
396
397 sx1 = x1 >= 0 ? x1 + 1 : 0;
398 sx2 = x2 < winx ? x2 - 1 : winx - 1;
399 sy1 = y1 >= root_y1 ? y1 + 1 : root_y1;
400 sy2 = y2 < winy - root_y2 ? y2 - 1 : winy - root_y2;
401
402 if (y2 < winy - root_y2) {
403 if (x1 >= 0)
404 mvaddch(y2, x1, BOX_LL);
405 if (x2 < winx)
406 mvaddch(y2, x2, BOX_LR);
407
408 for (i = sx1; i <= sx2; i++)
409 mvaddch(y2, i, BOX_HLINE);
410 }
411 if (y1 >= root_y1) {
412 if (x1 >= 0)
413 mvaddch(y1, x1, BOX_UL);
414 if (x2 < winx)
415 mvaddch(y1, x2, BOX_UR);
416
417 i = sx1;
418 if (title)
419 for (; i <= sx2 && *title; i++)
420 mvaddch(y1, i, *title++);
421 for (; i <= sx2; i++)
422 mvaddch(y1, i, BOX_HLINE);
423 }
424 for (i = sy1; i <= sy2; i++) {
425 if (x1 >= 0)
426 mvaddch(i, x1, BOX_VLINE);
427 if (x2 < winx)
428 mvaddch(i, x2, BOX_VLINE);
429 }
430 }
431
432 /* open new window on panel 'panel' */
win_panel_open(int dst_panel,int x,int y,int width,int height,BOOL border,const char * title,ATTRS attrs)433 MWINDOW *win_panel_open(int dst_panel, int x, int y, int width, int height,
434 BOOL border, const char *title, ATTRS attrs)
435 {
436 MWINDOW *win = (MWINDOW *) malloc(sizeof(MWINDOW)), *help;
437
438 int ofs = (border ? 1 : 0);
439
440 if (x < ofs)
441 x = ofs;
442 if (!dst_panel) { /* root panel */
443 if (y < ofs)
444 y = ofs;
445 if (y + height > winy - ofs)
446 height = winy - y - ofs;
447 } else {
448 if (y < ofs + root_y1)
449 y = ofs + root_y1;
450 if (y + height > winy - ofs - root_y2)
451 height = winy - y - ofs - root_y2;
452 }
453 if (x + width > winx - ofs)
454 width = winx - x - ofs;
455 if (width < 0)
456 width = 0;
457
458 if (height < 0)
459 height = 0;
460
461 win_attrset(attrs);
462 if (border && (dst_panel == cur_panel))
463 win_box_win(x - 1, y - 1, x + width, y + height, title);
464
465 win->x = x;
466 win->y = y;
467 win->width = width;
468 win->height = height;
469 win->attrs = attrs;
470 win->border = border;
471 win->resize = 0;
472 if (title)
473 win->title = strdup(title);
474 else
475 win->title = NULL;
476 win->next = NULL;
477 win->repaint = win_clear;
478 win->handle_key = NULL;
479 win->handle_resize = NULL;
480 for (help = panel[dst_panel]; help && help->next; help = help->next);
481 if (help)
482 help->next = win;
483 else
484 panel[dst_panel] = win;
485 if (dst_panel == cur_panel)
486 cur_window = win;
487 return win;
488 }
489
490 /* open new window on current panel */
win_open(int x,int y,int width,int height,BOOL border,const char * title,ATTRS attrs)491 MWINDOW *win_open(int x, int y, int width, int height, BOOL border,
492 const char *title, ATTRS attrs)
493 {
494 return win_panel_open(cur_panel, x, y, width, height, border, title, attrs);
495 }
496
win_get_first(int dst_panel)497 MWINDOW *win_get_first(int dst_panel)
498 {
499 MWINDOW *win;
500 for (win = panel[dst_panel]; win && win->next; win = win->next);
501 return win;
502 }
503
504 /* set function which sould be called on a repaint request */
win_set_repaint(WinRepaintFunc func)505 void win_set_repaint(WinRepaintFunc func)
506 {
507 cur_window->repaint = func;
508 }
win_panel_set_repaint(int _panel,WinRepaintFunc func)509 void win_panel_set_repaint(int _panel, WinRepaintFunc func)
510 {
511 win_get_first(_panel)->repaint = func;
512 }
513
514 /* set function which sould be called on a key press */
win_set_handle_key(WinKeyFunc func)515 void win_set_handle_key(WinKeyFunc func)
516 {
517 cur_window->handle_key = func;
518 }
win_panel_set_handle_key(int _panel,WinKeyFunc func)519 void win_panel_set_handle_key(int _panel, WinKeyFunc func)
520 {
521 win_get_first(_panel)->handle_key = func;
522 }
523
524 /* should window be automatically resized?
525 should a function be called on resize? */
win_set_resize(BOOL auto_resize,WinResizeFunc func)526 void win_set_resize(BOOL auto_resize, WinResizeFunc func)
527 {
528 cur_window->resize = auto_resize;
529 cur_window->handle_resize = func;
530 }
win_panel_set_resize(int _panel,BOOL auto_resize,WinResizeFunc func)531 void win_panel_set_resize(int _panel, BOOL auto_resize, WinResizeFunc func)
532 {
533 MWINDOW *win = win_get_first(_panel);
534 win->resize = auto_resize;
535 win->handle_resize = func;
536 }
537
538 /* set private data */
win_set_data(void * data)539 void win_set_data(void *data)
540 {
541 cur_window->data = data;
542 }
543
win_panel_set_data(int _panel,void * data)544 void win_panel_set_data(int _panel, void *data)
545 {
546 win_get_first(_panel)->data = data;
547 }
548
win_do_resize(int dx,int dy,BOOL root)549 void win_do_resize(int dx, int dy, BOOL root)
550 {
551 MWINDOW *win;
552 int i = root ? 0 : 1;
553
554 if (win_quiet)
555 return;
556
557 for (; i < DISPLAY_COUNT; i++)
558 for (win = panel[i]; win; win = win->next) {
559 if (win->resize) {
560 win->width += dx;
561 win->height += dy;
562 }
563 if (win->handle_resize)
564 win->handle_resize(win, dx, dy);
565 }
566 win_panel_repaint_force();
567 }
568
569 static char status_message[MAXWIDTH + 2];
570
win_status_repaint(void)571 static void win_status_repaint(void)
572 {
573 MWINDOW *win = panel[0];
574 int i;
575 if (win_quiet)
576 return;
577
578 if ((root_y2 > 1) && (win->height > root_y1+1)) {
579 win_attrset(ATTR_STATUS_LINE);
580 for (i = 0; i < win->width; i++)
581 mvaddch(win->height - 2, i, BOX_HLINE);
582 }
583 }
584
585 /* init the status line(height=0,1,2 0: no status line) */
win_init_status(int height)586 void win_init_status(int height)
587 {
588 int old_y2 = root_y2;
589
590 if (height != root_y2) {
591 root_y2 = height < 0 ? 0 : (height > 2 ? 2 : height);
592 #if defined(__OS2__)||defined(__EMX__)||defined(__DJGPP__)||defined(_WIN32)
593 status_message[0] = '\0';
594 #else
595 status_message[0] = '\n';
596 status_message[1] = '\0';
597 #endif
598 win_do_resize(0, old_y2 - root_y2, 0);
599 }
600 }
601
602 /* set the status line */
win_status(const char * msg)603 void win_status(const char *msg)
604 {
605 MWINDOW *win = panel[0];
606 int len;
607
608 if (msg) {
609 len = strlen(msg);
610 if (len > MAXWIDTH)
611 len = MAXWIDTH;
612 strncpy(status_message, msg, len);
613 } else
614 len = strlen(status_message);
615 status_message[len] = '\0';
616
617 if (win_quiet)
618 return;
619 if ((root_y2 > 0) && (win->height > root_y1) && (win->width>0)) {
620 win_attrset(ATTR_STATUS_TEXT);
621 mvaddnstr(win->y + win->height - 1, win->x, status_message,
622 win->width);
623 win_clrtoeol(win, win->x + len, win->y + win->height - 1);
624 }
625 }
626
627 /* repaint the whole panel */
win_panel_repaint(void)628 void win_panel_repaint(void)
629 {
630 if (win_quiet)
631 return;
632
633 if (panel[cur_panel])
634 win_clear(panel[cur_panel]);
635
636 if (panel[0]->repaint)
637 if (!panel[0]->repaint(panel[0]))
638 return;
639 for (cur_window = panel[cur_panel]; cur_window;
640 cur_window = cur_window->next) {
641 win_attrset(cur_window->attrs);
642 if (cur_window->border && cur_window->width >= 0 &&
643 cur_window->height >= 0)
644 win_box_win(cur_window->x - 1, cur_window->y - 1,
645 cur_window->x + cur_window->width,
646 cur_window->y + cur_window->height, cur_window->title);
647 if (cur_window->repaint && cur_window->width > 0 &&
648 cur_window->height > 0)
649 if (!cur_window->repaint(cur_window))
650 return;
651 }
652 win_status_repaint();
653 win_status(NULL);
654 for (cur_window = panel[cur_panel]; cur_window && cur_window->next;
655 cur_window = cur_window->next);
656 }
657
658 /* repaint the whole panel, clear whole panel before */
win_panel_repaint_force(void)659 void win_panel_repaint_force(void)
660 {
661 if (win_quiet) return;
662 clear();
663 win_panel_repaint();
664 }
665
666 /* close window win */
win_close(MWINDOW * win)667 void win_close(MWINDOW * win)
668 {
669 int i;
670 MWINDOW *pos;
671
672 for (i = 0; i < DISPLAY_COUNT; i++)
673 for (pos = panel[i]; pos; pos = pos->next)
674 if (pos == win) {
675 if (win == cur_window)
676 for (cur_window = panel[i]; cur_window->next != win;
677 cur_window = cur_window->next);
678 for (pos = panel[i]; pos->next != win; pos = pos->next);
679 pos->next = win->next;
680 if (win->title)
681 free(win->title);
682 free(win);
683 if (i == cur_panel)
684 win_panel_repaint();
685 return;
686 }
687 }
688
689 /* get size of window win */
win_get_size(MWINDOW * win,int * x,int * y)690 void win_get_size(MWINDOW *win, int *x, int *y)
691 {
692 *x = win->width;
693 *y = win->height;
694 }
695
696 /* get maximal size of a new window without a border and therefore the needed
697 minimal y position */
win_get_size_max(int * y,int * width,int * height)698 void win_get_size_max(int *y, int *width, int *height)
699 {
700 *y = root_y1;
701 *width = panel[0]->width;
702 *height = panel[0]->height - root_y1 - root_y2;
703 if (*height < 0)
704 *height = 0;
705 }
706
707 /* get uppermost window */
win_get_window(void)708 MWINDOW *win_get_window(void)
709 {
710 return cur_window;
711 }
712
713 /* get root window */
win_get_window_root(void)714 MWINDOW *win_get_window_root(void)
715 {
716 return panel[0];
717 }
718
719 /* print string in window win */
win_print(MWINDOW * win,int x,int y,const char * str)720 void win_print(MWINDOW *win, int x, int y, const char *str)
721 {
722 int len = strlen(str);
723
724 #if defined(__OS2__)||defined(__EMX__)||defined(__DJGPP__)||defined(_WIN32)
725 if (len > 1 && str[len - 1] == '\n' && str[len - 2] == '\r')
726 len--;
727 #endif
728 INVISIBLE_RET(win);
729
730 if ((x >= win->width) || (y >= win->height) ||
731 ((win != panel[0]) && (y + win->y >= winy - root_y2)) ||
732 (!len))
733 return;
734
735 if (len + x > win->width)
736 len = win->width - x;
737 if (len > 0 && (str[len - 1] == '\n' || str[len - 1] == '\r'))
738 #if !defined(__OS2__)&&!defined(__EMX__)&&!defined(__DJGPP__)&&!defined(_WIN32)
739 if (win->x + win->width < winx)
740 #endif
741 {
742 len--;
743 win_clrtoeol(win, x + len, y);
744 }
745 mvaddnstr(y + win->y, x + win->x, str, len);
746 }
747
748 /* draw horizontal/verticall line */
win_line(MWINDOW * win,int x1,int y1,int x2,int y2)749 void win_line(MWINDOW *win, int x1, int y1, int x2, int y2)
750 {
751 int i;
752
753 INVISIBLE_RET(win);
754
755 if (y1 == y2) {
756 if (y1 < cur_window->height)
757 for (i = x1; i <= x2 && i < cur_window->width; i++)
758 mvaddch(y1 + cur_window->y, i + cur_window->x, BOX_HLINE);
759 } else {
760 if (x1 < cur_window->width)
761 for (i = y1; i <= y2 && i < cur_window->height; i++)
762 mvaddch(i + cur_window->y, x1 + cur_window->x, BOX_VLINE);
763 }
764 }
765
766 /* draw a box with colored background
767 back: background colors from UL UR LR LL to UL */
win_box_color(MWINDOW * win,int x1,int y1,int x2,int y2,ATTRS * back)768 void win_box_color(MWINDOW *win, int x1, int y1, int x2, int y2, ATTRS *back)
769 {
770 int i, j, k, sx1, sx2, sy1, sy2, maxx, maxy;
771
772 INVISIBLE_RET(win);
773
774 x1 += win->x;
775 x2 += win->x;
776 y1 += win->y;
777 y2 += win->y;
778
779 maxx = win->x+win->width-1;
780 maxy = win->y+win->height-1;
781
782 sx1 = x1>=win->x ? x1+1 : win->x;
783 sy1 = y1>=win->y ? y1+1 : win->y;
784 sx2 = x2<=maxx ? x2 - 1 : maxx;
785 sy2 = y2<=maxy ? y2 - 1 : maxy;
786
787 if (y2 <= maxy) {
788 if (x1 >= win->x) {
789 if (back)
790 win_set_background (back[x2-x1+x2-x1+y2-y1]);
791 mvaddch(y2, x1, BOX_LL);
792 }
793 if (x2 <= maxx) {
794 if (back)
795 win_set_background (back[x2-x1+y2-y1]);
796 mvaddch(y2, x2, BOX_LR);
797 }
798 j = x2-x1+x2-sx1+y2-y1;
799 for (i = sx1; i <= sx2; i++) {
800 if (back)
801 win_set_background (back[j--]);
802 mvaddch(y2, i, BOX_HLINE);
803 }
804 }
805 if (y1 >= win->y) {
806 if (x1 >= win->x) {
807 if (back)
808 win_set_background (back[0]);
809 mvaddch(y1, x1, BOX_UL);
810 }
811 if (x2 <= maxx) {
812 if (back)
813 win_set_background (back[x2-x1]);
814 mvaddch(y1, x2, BOX_UR);
815 }
816 j = sx1-x1;
817 for (i=sx1; i <= sx2; i++) {
818 if (back)
819 win_set_background (back[j++]);
820 mvaddch(y1, i, BOX_HLINE);
821 }
822 }
823 j = x2-x1+sy1-y1;
824 k = x2-x1+x2-x1+y2-y1+y2-sy1;
825 for (i = sy1; i <= sy2; i++) {
826 if (x1 >= win->x) {
827 if (back)
828 win_set_background (back[k--]);
829 mvaddch(i, x1, BOX_VLINE);
830 }
831 if (x2 <= maxx) {
832 if (back)
833 win_set_background (back[j++]);
834 mvaddch(i, x2, BOX_VLINE);
835 }
836 }
837 }
838 /* draw a box */
win_box(MWINDOW * win,int x1,int y1,int x2,int y2)839 void win_box(MWINDOW *win, int x1, int y1, int x2, int y2)
840 {
841 win_box_color (win, x1, y1, x2, y2, NULL);
842 }
843
844 /* set attribute for the following output operations,
845 "attrs" is an index into the theme->attr translation table */
win_attrset(ATTRS attrs)846 void win_attrset(ATTRS attrs)
847 {
848 if (theme && !win_quiet) {
849 int theme_attr = theme->attrs[attrs];
850 act_color = theme_attr;
851 #if !defined(__OS2__)&&!defined(__EMX__)&&!defined(__DJGPP__)&&!defined(_WIN32)
852 if (theme->color) {
853 int pair;
854 if (theme_attr == ((COLOR_CNT-1) << COLOR_BSHIFT) + ((COLOR_CNT-1) << COLOR_FSHIFT))
855 theme_attr = ((COLOR_CNT-1) << COLOR_BSHIFT) + ((COLOR_CNT-2) << COLOR_FSHIFT);
856 act_color = theme_attr;
857 pair = COLOR_PAIR(color_to_pair(theme_attr));
858 if (theme_attr & COLOR_BOLDMASK)
859 attrset(pair | A_BOLD);
860 else
861 attrset(pair);
862 } else
863 #endif
864 attrset(theme_attr);
865 }
866 }
867
win_get_theme_color(ATTRS attrs)868 ATTRS win_get_theme_color (ATTRS attrs)
869 {
870 if (theme) {
871 int theme_attr = theme->attrs[attrs];
872 #if !defined(__OS2__)&&!defined(__EMX__)&&!defined(__DJGPP__)&&!defined(_WIN32)
873 if (theme->color)
874 if (theme_attr == ((COLOR_CNT-1) << COLOR_BSHIFT) + ((COLOR_CNT-1) << COLOR_FSHIFT))
875 theme_attr = ((COLOR_CNT-1) << COLOR_BSHIFT) + ((COLOR_CNT-2) << COLOR_FSHIFT);
876 #endif
877 return theme_attr;
878 } else
879 return 0;
880 }
881
882 /* set color for the following output operations */
win_set_color(ATTRS attrs)883 void win_set_color(ATTRS attrs)
884 {
885 if (win_quiet) return;
886
887 act_color = attrs;
888 #if !defined(__OS2__)&&!defined(__EMX__)&&!defined(__DJGPP__)&&!defined(_WIN32)
889 if (win_has_colors()) {
890 int pair;
891 if (attrs == ((COLOR_CNT-1) << COLOR_BSHIFT) + ((COLOR_CNT-1) << COLOR_FSHIFT))
892 attrs = ((COLOR_CNT-1) << COLOR_BSHIFT) + ((COLOR_CNT-2) << COLOR_FSHIFT);
893 act_color = attrs;
894 pair = COLOR_PAIR(color_to_pair(attrs));
895 if (attrs & COLOR_BOLDMASK)
896 attrset(pair | A_BOLD);
897 else
898 attrset(pair);
899 } else
900 #endif
901 attrset(attrs);
902 }
903
win_set_forground(ATTRS fg)904 void win_set_forground(ATTRS fg)
905 {
906 if (win_has_colors())
907 win_set_color ((act_color & COLOR_BMASK) + (fg << COLOR_FSHIFT));
908 }
909
win_set_background(ATTRS bg)910 void win_set_background(ATTRS bg)
911 {
912 if (win_has_colors())
913 win_set_color ((act_color & COLOR_FMASK) + (bg << COLOR_BSHIFT));
914 }
915
916 /* change current panel */
win_change_panel(int new_panel)917 void win_change_panel(int new_panel)
918 {
919 if (new_panel == cur_panel)
920 new_panel = old_panel;
921 old_panel = cur_panel;
922 if (new_panel != cur_panel) {
923 cur_panel = new_panel;
924 for (cur_window = panel[cur_panel]; cur_window && cur_window->next;
925 cur_window = cur_window->next);
926 win_panel_repaint();
927 }
928 }
929
win_get_panel(void)930 int win_get_panel(void)
931 {
932 return cur_panel;
933 }
934
935 /* handle key press(panel change and call of key handler
936 of uppermost window),return: was key handled */
win_handle_key(int ch)937 BOOL win_handle_key(int ch)
938 {
939 int ret;
940 switch (ch) {
941 case KEY_F(1):
942 win_change_panel(DISPLAY_HELP);
943 break;
944 case KEY_F(2):
945 win_change_panel(DISPLAY_SAMPLE);
946 break;
947 case KEY_F(3):
948 win_change_panel(DISPLAY_INST);
949 break;
950 case KEY_F(4):
951 #if defined(__OS2__)||defined(__EMX__)||defined(__DJGPP__)||defined(_WIN32)
952 case KEY_SF(9): /* shift-F9 */
953 #else
954 case KEY_F(19): /* shift-F9 on some curses implementations */
955 #endif
956 win_change_panel(DISPLAY_MESSAGE);
957 break;
958 case KEY_F(5):
959 win_change_panel(DISPLAY_LIST);
960 break;
961 case KEY_F(6):
962 win_change_panel(DISPLAY_CONFIG);
963 break;
964 #if LIBMIKMOD_VERSION >= 0x030200
965 case KEY_F(7):
966 win_change_panel(DISPLAY_VOLBARS);
967 break;
968 #endif
969 default:
970 ret = 0;
971 if (cur_window->handle_key)
972 ret = cur_window->handle_key(cur_window, ch);
973 if (!ret && panel[0]->handle_key)
974 ret = panel[0]->handle_key(panel[0], ch);
975 return ret;
976 }
977 return 1;
978 }
979
980 /* Insert src (src!=NULL) or timeouts[0] (src==NULL) sorted after next
981 execution in timeouts and set remaining appropriate.
982 Expand timeouts array if src!=NULL. */
win_timeout_insert(TIMEOUT * src)983 static void win_timeout_insert (TIMEOUT *src)
984 {
985 int time;
986 int sum = 0, oldsum = 0, pos = 0, i;
987
988 if (!src) {
989 time = timeouts[0].interval;
990 pos++;
991 } else
992 time = src->interval;
993
994 for (; pos<=cnt_timeouts; pos++) {
995 oldsum = sum;
996 if (pos<cnt_timeouts)
997 sum += timeouts[pos].remaining;
998 if (sum>time || pos==cnt_timeouts) {
999 if (src) {
1000 timeouts = (TIMEOUT *) realloc (timeouts,
1001 sizeof(TIMEOUT)*(++cnt_timeouts));
1002 for (i=cnt_timeouts-1; i>pos; i--)
1003 timeouts[i] = timeouts[i-1];
1004 timeouts[pos] = *src;
1005 } else {
1006 TIMEOUT help = timeouts[0];
1007 pos--;
1008 for (i=0; i<pos; i++)
1009 timeouts[i] = timeouts[i+1];
1010 timeouts[pos] = help;
1011 }
1012 timeouts[pos].remaining = time-oldsum;
1013 return;
1014 }
1015 }
1016 }
1017
1018 /* add a new timeout function called approx. every interval ms */
win_timeout_add(int interval,WinTimeoutFunc func,void * data)1019 void win_timeout_add (int interval, WinTimeoutFunc func, void *data)
1020 {
1021 TIMEOUT new_timeout;
1022 new_timeout.func = func;
1023 new_timeout.data = data;
1024 new_timeout.interval = interval;
1025 win_timeout_insert (&new_timeout);
1026 }
1027
win_timeout_remove(int number)1028 static void win_timeout_remove (int number)
1029 {
1030 int i;
1031 for (i=number+1; i<cnt_timeouts; i++)
1032 timeouts[i-1] = timeouts[i];
1033 cnt_timeouts--;
1034 if (cnt_timeouts) {
1035 timeouts = (TIMEOUT *) realloc (timeouts,sizeof(TIMEOUT)*cnt_timeouts);
1036 } else {
1037 free (timeouts);
1038 timeouts = NULL;
1039 }
1040 }
1041
1042 /* Handle scheduled timeouts and up to one key press,
1043 return 1 if key presses are pending */
win_main_iteration(void)1044 BOOL win_main_iteration(void)
1045 {
1046 static unsigned long last_time = 0, time;
1047 static int last_ch = 0;
1048 int ch;
1049
1050 time = Time1000();
1051 if (timeouts && last_time)
1052 timeouts[0].remaining -= time-last_time;
1053 last_time = time;
1054
1055 while (timeouts && timeouts[0].remaining <= 0) {
1056 if (timeouts[0].func &&
1057 ! timeouts[0].func (cur_window, timeouts[0].data)) {
1058 win_timeout_remove (0);
1059 } else
1060 win_timeout_insert (NULL);
1061 }
1062
1063 if (win_quiet) return 0;
1064
1065 if (last_ch)
1066 ch = last_ch;
1067 else
1068 ch = win_getch();
1069 if (ch) {
1070 win_handle_key(ch);
1071 #if !defined(__OS2__)&&!defined(__EMX__)&&!defined(__DJGPP__)&&!defined(_WIN32)
1072 /* flushinp(); */
1073 #endif
1074 last_ch = win_getch();
1075 }
1076
1077 return last_ch != 0;
1078 }
1079
win_run(void)1080 void win_run(void)
1081 {
1082 do {
1083 while (win_main_iteration());
1084 SLEEP(1);
1085 } while (1);
1086 }
1087
1088 /* ex:set ts=4: */
1089