
/*
 * XKOBO, a video-oriented game
 * Copyright (C) 1995  Akira Higuchi
 *     a-higuti@math.hokudai.ac.jp
 * 
 * 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.,
 * 675 Mass Ave, Cambridge, MA 02139, USA.
 * 
 */

#include <unistd.h>
#include <signal.h>
#include <sys/time.h>
#include <sys/types.h>
#include "xkobo.h"
#include "config.h"
#include "tiff.h"
#include "screen.h"
#include "manage.h"
#include "key.h"

#ifdef USE_SEMAPHORE
#include <sys/sem.h>
#include <sys/ipc.h>
#endif

/*           kobo          */


win_cmap        wbase;
win_chip        wchip(SCREEN_SIZEX + WSIZE, SCREEN_SIZEY + WSIZE);
win_backing     wradar;
win_backing     wscore;


static struct itimerval value, ovalue;

#ifdef USE_SEMAPHORE
unsigned int    count_time_in  = 0;
unsigned int    count_time_out = 0;
static struct sembuf down_1 = { 0, -1, 0 };
static struct sembuf up_1   = { 0,  1, 0 };
static int semaphore;
void sig_handle(int)
{
    signal(SIGALRM, sig_handle);
    semop(semaphore, &up_1, 1);
}
#else
void sig_handle(int)
{
    signal(SIGALRM, sig_handle);
}
#endif // USE_SEMAPHORE

void key_press_callback(win&)
{
    KeySym sym;
    sym = XKeycodeToKeysym(win::disp, win::xevt.xkey.keycode, 0);
    key.press(sym);
}

void key_release_callback(win&)
{
    KeySym sym;
    sym = XKeycodeToKeysym(win::disp, win::xevt.xkey.keycode, 0);
    key.release(sym);
}

void focus_in_callback(win&)
{
    key.clear();
}

void focus_out_callback(win&)
{
    ;
}

void client_message_callback(win&)
{
    Atom wm_protocols, wm_delete_window;
    wm_protocols = XInternAtom(win::disp, "WM_PROTOCOLS", False);
    wm_delete_window = XInternAtom(win::disp, "WM_DELETE_WINDOW", False);
    if ((win::xevt.xclient.message_type == wm_protocols) &&
        (win::xevt.xclient.data.l[0] == wm_delete_window)){
        _manage::exit_button();
        _manage::exit_button();
    }
}

int main()
{
    wbase.event(KeyPress,      &key_press_callback     );
    wbase.event(KeyRelease,    &key_release_callback   );
    wbase.event(FocusIn,       &focus_in_callback      );
    wbase.event(FocusOut,      &focus_out_callback     );
    wbase.event(ClientMessage, &client_message_callback);
    wscore.event(ClientMessage, &client_message_callback);
    wbase.make(NULL   ,         0,   0, WIN_SIZEX   , WIN_SIZEY   );
    wchip.make(&wbase ,    MARGIN,  10, WSIZE       , WSIZE       );
    wradar.make(&wbase, WIN_SIZEY, 106, MAP_SIZEX   , MAP_SIZEY   );
    wscore.make(NULL  ,         0,   0, WSCORE_SIZEX, WSCORE_SIZEY);
    
    wbase.title("xkobo");
    wbase.set_wm_close();
    wbase.hold_size();
    wbase.font(NORMAL_FONT);
    wbase.foreground(248);
    wbase.background(0);
    wbase.map();
    wbase.clear();
    wchip.foreground(200);
    wchip.background(0);
    wchip.setborder(0);
    wchip.map();
    wradar.setborder(0);
    wradar.map();
    wscore.title("xkobo-score");
    wscore.set_wm_close();
    wscore.hold_size();
    wscore.font(NORMAL_FONT);
    wscore.background(0);
    wscore.foreground(253);
    wscore.map();
    wscore.clear();
    
    if (link_tiff(spdata, wbase, wchip)) return 1;
    
    manage.init();
    signal(SIGALRM, sig_handle);

#ifdef USE_SEMAPHORE
    semaphore = semget(IPC_PRIVATE, 1, 0666);
    union semun sem_union;
    for (;;){
        value.it_interval.tv_sec = 0;
        value.it_interval.tv_usec = 0;
        value.it_value.tv_sec = 0;
        value.it_value.tv_usec = 1000 * WAIT_MSEC;
        setitimer(ITIMER_REAL, &value, &ovalue);
        sem_union.val = 0;
        semctl(semaphore, 0, SETVAL, sem_union);
        if (manage.mainloop()) break;
        if (semop(semaphore, &down_1, 1))
          count_time_in++;
        else
          count_time_out++;
    }
    semctl(semaphore, 0, IPC_RMID, sem_union);
#else
     for (;;){
        value.it_interval.tv_sec = 0;
        value.it_interval.tv_usec = 1000 * WAIT_MSEC;
        value.it_value.tv_sec = 0;
        value.it_value.tv_usec = 1000 * WAIT_MSEC;
        setitimer(ITIMER_REAL, &value, &ovalue);
        if (manage.mainloop()) break;
        pause();
    }
#endif // USE_SEMAPHORE
    return 0;
}
