/* Include files for X 11 */
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <termio.h>
#include <stdio.h>
#include <errno.h>
#include <sys/file.h>
#include <sys/fcntl.h>
#include <string.h>
#include <unistd.h>
#include "digitizer.h"
/* ---------------------------------------------------------------------- */
#define DIGI_MSG_LEN 13 /* Laenge der Digitizer Message */
#define MAX_MSG 5 /* Anzahl der MSG die ueberlesen werden */
#define DIGI_INIT_STRING "@cG\"" /* Stream-Mode / Grid-Mode */
#define TRUE (0==0)
#define FALSE (1==0)
/* #define DEBUG Um Debugging einzuschalten */
/* ---------------------------------------------------------------------- */
/* Modulglobale Variable */
static int device;
static int win_x,
win_y,
win_w,
win_h;
static int display_height;
static int win_pos_unknown = TRUE;
/* ---------------------------------------------------------------------- */
/*
Position und Groesse des LaTeXDraw-Fensters speichern
*/
void save_win_pos(x, y, w, h)
int x, y, w, h;
{
if (win_pos_unknown)
{
/* Erster Aufruf ==> alles merken */
win_x = x;
win_y = y;
win_w = w;
win_h = h;
win_pos_unknown = FALSE;
#ifdef DEBUG
fprintf(stderr, "Alles neu : (%d|%d|%d|%d)\n",
win_x, win_y, win_w, win_h);
#endif
}
else {
if ((win_w == w) && (win_h == h))
{
/* Position des Fensters hat sich veraendert */
win_x = x;
win_y = y;
#ifdef DEBUG
fprintf(stderr, "Neue Position : (%d|%d)\n", win_x, win_y);
#endif
}
else {
/* Groesse des Fensters hat sich veraendert */
win_w = w;
win_h = h;
#ifdef DEBUG
fprintf(stderr, "Neue Groesse : (%d|%d)\n", win_w, win_h);
#endif
}
}
}
/* ---------------------------------------------------------------------- */
/*
Verbindung zum Digitizer herstellen und Digitizer initialisieren
*/
int init_digitizer(display)
Display *display;
{
char config[32];
int i;
struct termio termbuf;
XWindowAttributes attribs;
device = open("/dev/tty01", O_RDWR);
if (-1 == device)
{
printf("\r\nDevice konnte nicht geoeffnet werden");
return(-1);
}
if (-1 == ioctl(device,TCGETA,&termbuf))
{
printf("\r\nFehler beim lesen der KONFIG, Fehler %d",errno);
return(-1);
}
termbuf.c_iflag &= ~(INLCR | ICRNL | IUCLC | ISTRIP | BRKINT);
termbuf.c_oflag &= ~OPOST;
termbuf.c_lflag &= ~(ICANON | ISIG | ECHO);
termbuf.c_cc[VMIN] = 0;
termbuf.c_cc[VTIME] = 0;
termbuf.c_cflag &= ~CBAUD;
termbuf.c_cflag |= B9600;
termbuf.c_cflag &= ~CSIZE;
termbuf.c_cflag |= CS8;
termbuf.c_cflag &= ~CSTOPB;
termbuf.c_cflag &= ~PARENB;
if (-1 == ioctl(device,TCSETA,&termbuf))
{
printf("\r\nFehler device %d",errno);
return(-1);
}
/* presence stream mode */
strcpy(config, DIGI_INIT_STRING);
for (i=0; i<strlen(config); i++)
write(device, &config[i], 1);
/* Groesse des Displays holen und Digitizer skalieren */
XGetWindowAttributes(display, DefaultRootWindow(display), &attribs);
config[0] = 'r';
config[1] = attribs.width & 0xff;
config[2] = (attribs.width & 0xff00) >> 8;
config[3] = attribs.height & 0xff;
config[4] = (attribs.height & 0xff00) >> 8;
write(device, config, 5);
display_height = attribs.height;
return(1);
}
/* ---------------------------------------------------------------------- */
/*
Aus der seriellen Schnittstelle ankommende Zeichen lesen
Insgesamt werden MAX_MSG Nachrichten eingelesen, von denen die letzte
in *x,*y,*button zurueckgegeben wird
*/
static int readit(x,y,button)
int *x,
*y,
*button;
{
/* Zwischenspeicher fuer eingegangene Meldungen */
static char zwsp[(MAX_MSG+1)*DIGI_MSG_LEN];
static int count = 0;
/* Kommandos fuer Digitizer Mode */
char cmd1[] = "G!"; /* Wert nur nach Bewegung */
char cmd2[] = "G "; /* Immer Werte senden */
char buffer[MAX_MSG*DIGI_MSG_LEN];
int i,n;
int erg;
/* Im Zweifelsfall kein Ergebniss vorhanden */
erg = 0;
/* Maximal eine Nachricht einlesen */
n = read(device, buffer, 4*DIGI_MSG_LEN);
/* Gelesene Zeichen in den Puffer kopieren */
if (0 != n)
{
for (i=0; i<n; i++)
zwsp[count++] = buffer[i];
}
/* Eine komplette Nachricht da ? */
while (count >= DIGI_MSG_LEN)
{
/* Ist der String korrekt aufgebaut */
if (zwsp[12] == 10)
{
/* Korrekter String */
*x = *y = *button = 0;
for (i=0;i<4;i++)
{
*x = *x * 10 + (zwsp[i] - '0');
*y = *y * 10 + (zwsp[5+i] - '0');
}
*button = zwsp[10] - '0';
count -= DIGI_MSG_LEN;
for (i=0; i<count ; i++)
zwsp[i] = zwsp[DIGI_MSG_LEN+i];
if (*button != 0)
write(device, cmd2, strlen(cmd2));
else
write(device, cmd1, strlen(cmd1));
erg = 1;
}
else
{
/* Nachricht war Muell also neuen Beginn suchen */
buffer[0] = 0;
while (10 != buffer[0])
read(device, buffer, 1);
/* Puffer als geloescht markieren */
count = 0;
}
/* fprintf(stderr,"(%d|%d | %d)\n", *x, *y, *button); */
}
return (erg);
}
/* ---------------------------------------------------------------------- */
/*
Digitizer Koordinaten so umwandeln, dass aus ihnen LaTeXDraw-Koordinaten
werden
*/
static void translate_digi_to_ltd(x_in, y_in, x_out, y_out)
int x_in,
y_in;
int *x_out,
*y_out;
{
*x_out = x_in;
*y_out = win_h - y_in;
#ifdef DEBUG
fprintf(stderr, "(%d|%d) ==> (%d|%d)\n",
x_in,y_in, *x_out, *y_out);
#endif
}
/* ---------------------------------------------------------------------- */
/*
Koordianten eines Digitizer-Events in LTD-Koordinaten umrechnen
*/
void translate_x_to_ltd(x_in, y_in, x_out, y_out)
int x_in,
y_in;
double *x_out,
*y_out;
{
*x_out = (double)x_in;
/* *y_out = (double)(y_in - win_h); */
*y_out = (double)(win_h - y_in);
#ifdef DEBUG
fprintf(stderr, "x->digi (%d|%d) ==> (%f|%f)\n",
x_in,y_in, *x_out, *y_out);
#endif
}
/* ---------------------------------------------------------------------- */
/*
Digitizer-Nachrichten erzeugen
*/
int process_digitizer(display, window)
Display *display;
Window window;
{
static int old_x = -1;
static int old_y = -1;
static int old_b = -1;
int x,y,
this_x,
this_y,
this_b;
int stateField[] = {0,
Button2Mask, Button1Mask,
Button4Mask, Button3Mask};
int buttonField[] = {0, 2, 1, 4, 3};
long motionEventField[] = {0,
Button2MotionMask, Button1MotionMask,
Button4MotionMask, Button3MotionMask};
XEvent myEvent;
int event_b;
long event_mask;
/* Wert vom Digitizer holen */
if (0 == readit(&x, &y, &this_b))
return(FALSE);
/* Koordinaten fuer LaTeXDraw umsetzen */
translate_digi_to_ltd(x,y, &this_x, &this_y);
if ((this_x != old_x) || (this_y != old_y))
{
/* Bewegung des Cursors ausfuehren */
XWarpPointer(display,
None, window, /*DefaultRootWindow(display),*/
0, 0, 0, 0,
this_x,
this_y);
old_x = this_x;
old_y = this_y;
if ((this_b != 0) && (this_b <= 4))
{
myEvent.type = MotionNotify;
myEvent.xany.display = display;
myEvent.xmotion.window = window;
myEvent.xmotion.x = this_x;
myEvent.xmotion.y = this_y;
myEvent.xmotion.state = stateField[this_b];
event_mask = motionEventField[this_b];
XSendEvent(display, PointerWindow, 0, event_mask, &myEvent);
}
}
/* Button - Event */
if ((this_b != abs(old_b)) && (this_b <= 4))
{
/* Button press oder release */
if (old_b < 0)
{
event_b = -old_b;
old_b = 0;
myEvent.type = ButtonRelease;
event_mask = ButtonReleaseMask;
}
else
{
event_b = this_b;
old_b = -this_b;
myEvent.type = ButtonPress;
event_mask = ButtonPressMask;
}
myEvent.xany.display = display;
myEvent.xbutton.window = window;
myEvent.xbutton.x = this_x;
myEvent.xbutton.y = this_y;
myEvent.xbutton.state = stateField[event_b];
myEvent.xbutton.button = buttonField[event_b];
XSendEvent(display, PointerWindow, 0, event_mask, &myEvent);
}
/* XEvent rausschreiben */
XSync(display, 0);
return(TRUE);
}