#include <stdio.h>
#include <gpm.h>
#include <linux/keyboard.h>
#include <ncurses.h>

typedef struct _WIN {
    int nlines;
    int ncols;
    int y;
    int x;
    WINDOW *p_win;
   }WIN;

void create_windows(WIN my_windows[]);
void set_win_params(WIN *win, int nlines, int ncols, int y, int x);

/*Handler gilt für alle 4 Fenster, Wir benutzen die Variable data als übergabe um
   welches Fenster es sich handelt*/
int my_handler(Gpm_Event *p_event, void *data)
{
  WINDOW *current_win;
  WIN *my_win;

  my_win = (WIN *)data;
  current_win = my_win -> p_win;

  if(p_event->type & GPM_ENTER)
      mvwprintw(current_win, 1, 1, "Willkommen......");
  if(p_event->type & GPM_LEAVE)
      mvwprintw(current_win, 1, 1, "Und Tschuess......");
  if(p_event->type & GPM_DOWN)
       {
         mvwprintw(current_win, my_win->nlines - 2, 1, "Mausbutton gedrückt");
         if(p_event->buttons & GPM_B_LEFT)
             mvwprintw(current_win, my_win->nlines/2, 1,"Linke Maustaste gedrückt ");
         if(p_event->buttons & GPM_B_RIGHT)
             mvwprintw(current_win, my_win->nlines/2, 1,"Rechte Maustaste gedrückt");
         if(p_event->buttons & GPM_B_MIDDLE)
             mvwprintw(current_win, my_win->nlines/2, 1,"Mittlere Maustaste gedrückt");
       }
  if(p_event->type & GPM_UP)
       {
         mvwprintw(current_win, my_win->nlines - 2, 1, "Mausbutton losgelassen ");
         if(p_event->buttons & GPM_B_LEFT)
             mvwprintw(current_win, my_win->nlines/2, 1,"Linke Maustaste gedrückt");
         if(p_event->buttons & GPM_B_RIGHT)
             mvwprintw(current_win, my_win->nlines/2, 1,"Rechte Maustaste gedrückt ");
         if(p_event->buttons & GPM_B_MIDDLE)
             mvwprintw(current_win, my_win->nlines/2, 1,"Mittlere Maustaste gedrückt");
       }
  wrefresh(current_win);
  return 1;
}

int main()
{
  Gpm_Connect conn;
  WIN my_windows[4];
  int i, mask, c;

  conn.eventMask = ~0; /*Alle Mausereignisse*/
  conn.defaultMask = 0; /*nix geht an gpm*/
  conn.minMod = 0;        /*keine Taste muss gedrückt werden*/
  conn.maxMod = ~0;      /*Tasten dürfen aber gedrückt werden*/


  if(Gpm_Open(&conn, 0) == -1) /*Verbindung zum Mausserver*/
    {
      fprintf(stderr, "Kann keine Verbindung zum Mausserver herstellen.....\n");
      exit(0);
    }

  initscr();    /*Curses initialisieren*/
  clear();      /*Bildschirm löschen*/
  refresh();
  noecho();   /*Keine Ausgabe auf dem Bildschirm*/
  cbreak();    /*Zeilenpufferung ausschalten*/

  create_windows(my_windows);
/*Unser Interessieren nur die Ereignisse Maus drücken und loslassen und*/
/*   Eintritt bzw. Austritt aus dem Region of Interest - Bereich*/
  mask = GPM_UP | GPM_DOWN | GPM_ENTER | GPM_LEAVE;
  for(i = 0;i < 4; ++i)
    {
       box(my_windows[i].p_win, 0, 0); /*Rahmen um die Fenster*/
       wrefresh(my_windows[i].p_win); /*Zeichenen*/
/*Handler für die einzelnen Regionen einrichten*/
       Gpm_PushRoi(my_windows[i].x, my_windows[i].y, /*obere linke Ecke bis......*/
       my_windows[i].x + my_windows[i].ncols - 1,
       my_windows[i].y + my_windows[i].nlines - 1, /*....untere rechte Ecke*/
       mask, my_handler, &my_windows[i]); /*Ereignisshandler und die Daten*/
    }
  gpm_visiblepointer = 1; /*Zeiger immer sichtbar*/
  gpm_zerobased = 1; /*linke obere ist 1/1*/
  gpm_roi_handler = my_handler; /*Handler einrichten für restlichen Bereich*/
  gpm_roi_data = stdscr;
  while((c = Gpm_Wgetch()) != EOF) /*Und Daten lesen*/
    {
      if(c == 4) /*CTRL & D*/
         break;
    }
  Gpm_Close(); /*Verbindung wieder beenden*/
  endwin(); /*curses beenden*/

  return 0;
}

/*Wir erzeugen 4 neue Fenster, alle Daten werden an die Struktur WIN übergeben*/
void create_windows(WIN my_windows[])
{
  int nlines = (LINES - 3) / 2;
  int ncols = (COLS - 3) / 2;
/*Fenster links oben*/
  my_windows[0].p_win = newwin(nlines, ncols, 1, 1);
  set_win_params(&my_windows[0], nlines, ncols, 1, 1);
/*Fenster rechts oben*/
  my_windows[1].p_win = newwin(nlines, ncols, 2 + nlines, 1);
  set_win_params(&my_windows[1], nlines, ncols, 2 + nlines, 1);
/*Fenster links unten*/
  my_windows[2].p_win = newwin(nlines, ncols, 1, 2 + ncols);
  set_win_params(&my_windows[2], nlines, ncols, 1, 2 + ncols);
/*Fenster rechts unten*/
  my_windows[3].p_win = newwin(nlines, ncols, 2 + nlines, 2 + ncols);
  set_win_params(&my_windows[3], nlines, ncols, 2 + nlines, 2 + ncols);
}

/*Die Restlichen Parameter an unsere selbstdefinierte Struktur WIN*/
void set_win_params(WIN *win, int nlines, int ncols, int y, int x)
{
  win->nlines = nlines;
  win->ncols = ncols;
  win->y = y;
  win->x = x;
}