| Here is the program.
It uses a mailbox to communicate with another process. I assume this part
of the program is not the cause of the virtual memory leak.
/*
File name : 51XXTERM11.C
*/
/*---------------------- XWindows --------------------------------------------*/
#include <Xlib.h>
#include <Xutil.h>
/*---------------------- C IO ------------------------------------------------*/
#include <stdio.h>
#include <iodef.h>
#include <ssdef.h>
#include <descrip.h>
/*---------------------- Private ---------------------------------------------*/
#include "51XXTerm11.h"
#define DECTERM_WMNAME "51XXTerm1"
#define RETRIES 3
/*----------------------------------------------------------------------------*/
char mice_buffer[6];
unsigned int mbx_buffer[3];
int mice_counter;
short mice_channel;
short mbx_channel;
short mbx_channel_a;
IO_STATUS mice_status;
IO_STATUS mbx_status;
IO_STATUS mbxa_status;
Display *display;
Cursor cursor;
Window root = 0,
term = 0,
parent,
child,
focus;
XWindowAttributes
xwa;
unsigned long mask = ButtonPressMask | ButtonReleaseMask | PointerMotionMask;
MICE mice;
int any_rc;
unsigned event_flag_LAT;
unsigned event_flag_MBX;
unsigned event_alarm_MBX;
unsigned event_flag_timer;
$DESCRIPTOR( t_str, "0 ::.01"/* string for SYS$BINTIM for 10 msec */ );
unsigned long t_pause[2]; /* quadword for time in internal format */
mouse_interrupt()
{
short is_short;
unsigned char *to_char;
int state;
int io_rc;
while ( 1 ) /* added for use break */
{
/* only if mouse init was send */
if( !mice.send )
break;
/* move only if on screen */
XGetInputFocus( display, &focus, &state );
if( focus != term )
{
if ( mice.grab )
XSetInputFocus( display, term, RevertToParent, CurrentTime );
else
break;
}
XQueryPointer( display, term, &parent, &child,
&mice.abs_x, &mice.abs_y, &mice.x, &mice.y,
&mice.buttons );
if (!mice.grab )
{
mice.x -= mice.x_offset; /* Adjust mice response area */
mice.y -= mice.y_offset;
if( mice.x < 1 || mice.x > mice.area_width ||
mice.y < 1 || mice.y > mice.area_height )
break;
}
if ( mice.x == mice.previous_x &&
mice.y == mice.previous_y &&
mice.buttons == mice.previous_buttons )
break;
mice_buffer[0] = (unsigned char)0x87; /* 10000111 */
if( mice.buttons & Button1Mask )
mice_buffer[0] &= (unsigned char)0x83; /* 10000011 */
if( mice.buttons & Button2Mask )
mice_buffer[0] &= (unsigned char)0x85; /* 10000101 */
if( mice.buttons & Button3Mask )
mice_buffer[0] &= (unsigned char)0x86; /* 10000110 */
is_short = (short)mice.x;
to_char = &is_short;
mice_buffer[2] = *to_char++;
mice_buffer[1] = *to_char;
is_short = (short)mice.y;
to_char = &is_short;
mice_buffer[4] = *to_char++;
mice_buffer[3] = *to_char;
mice.previous_x = mice.x;
mice.previous_y = mice.y;
mice.previous_buttons = mice.buttons;
if( ( ( io_rc = SYS$QIOW( event_flag_LAT, mice_channel,
IO$_WRITEPBLK | IO$M_NOFORMAT,
&mice_status, 0, 0,
mice_buffer, 5, 0, 0, 0, 0 ) ) != SS$_NORMAL ) ||
( mice_status.condition != SS$_NORMAL ) )
{
printf("Error after: %s in main, status %d, iosb %d\n",
"SYS$QIOW", io_rc, mice_status.condition );
if ( connect_lat() )
go_out();
else
{
if( ( ( io_rc = SYS$QIOW( event_flag_LAT, mice_channel,
IO$_WRITEPBLK | IO$M_NOFORMAT,
&mice_status, 0, 0,
mice_buffer, 5, 0, 0, 0, 0 ) ) != SS$_NORMAL )
|| ( mice_status.condition != SS$_NORMAL ) )
{
printf("Error after: %s in main, status %d, iosb %d\n",
"SYS$QIOW", io_rc, mice_status.condition );
go_out();
}
}
}
break;
}
/* set AST for read mouse coordinates and clicks every 10 msec */
SYS$SETIMR ( event_flag_timer, &t_pause[0], mouse_interrupt, 0, 0 );
}
/*----------------------------------------------------------------------*\
|* Main subroutine. *|
\*----------------------------------------------------------------------*/
main()
{
SYS$BINTIM ( &t_str, &t_pause[0] ); /* build the quadword time */
/* get event flag for LAT_port */
if (any_rc = LIB$GET_EF( &event_flag_LAT) != SS$_NORMAL )
{
printf( "Error after: %s in main, status %d\n", "LIB$GET_EF for LAT", any_rc );
send_alarm();
exit( any_rc );
}
/* get event flag for main MBX */
if( any_rc = LIB$GET_EF( &event_flag_MBX) != SS$_NORMAL )
{
printf( "Error after: %s in main, status %d\n", "LIB$GET_EF for MBX", any_rc );
LIB$FREE_EF( &event_flag_LAT );
send_alarm();
exit( any_rc );
}
/* get event flag for alarm MBX */
if( any_rc = LIB$GET_EF( &event_alarm_MBX) != SS$_NORMAL )
{
printf( "Error after: %s in main, status %d\n", "LIB$GET_EF for alarm MBX", any_rc );
LIB$FREE_EF( &event_flag_LAT );
LIB$FREE_EF( &event_flag_MBX );
send_alarm();
exit( any_rc );
}
/* get event flag for timer */
if( any_rc = LIB$GET_EF( &event_flag_timer) != SS$_NORMAL )
{
printf( "Error after: %s in main, status %d\n", "LIB$GET_EF for timer", any_rc );
LIB$FREE_EF( &event_flag_LAT );
LIB$FREE_EF( &event_flag_LAT );
LIB$FREE_EF( &event_alarm_MBX );
send_alarm();
exit( any_rc );
}
if( open_mail() )
go_out();
if( open_channel() )
go_out();
if( open_display() )
go_out();
/* set AST for read mouse coordinates and clicks every 10 msec */
SYS$SETIMR ( event_flag_timer, &t_pause[0], mouse_interrupt, 0, 0 );
mlisten();
/* if mlisten finished -> stop */
LIB$FREE_EF( &event_flag_timer );
close_display();
go_out();
}
go_out()
{
SYS$QIOW(event_flag_LAT, mice_channel, IO$_TTY_PORT | IO$M_LT_DISCON,
&mice_status, 0, 0, 0, 0, 0, 0, 0, 0);
SYS$DASSGN( mice_channel );
any_rc = LIB$FREE_EF( &event_flag_LAT );
any_rc = LIB$FREE_EF( &event_flag_MBX );
any_rc = LIB$FREE_EF( &event_alarm_MBX );
send_alarm();
exit( 0 );
}
send_alarm()
{
int alarm;
alarm = 1;
SYS$QIOW( event_alarm_MBX, mbx_channel_a,
IO$_WRITEVBLK | IO$M_NOW | IO$M_NORSWAIT,
&mbxa_status, 0, 0,
&alarm, 4, 0, 0, 0, 0);
}
/*======================================================================*\
|*================ Subroutines =========================================*|
\*======================================================================*/
/*----------------------------------------------------------------------*\
|* open_mail subroutine: establish connection with the mail box. *|
\*----------------------------------------------------------------------*/
open_mail()
{
int io_rc;
$DESCRIPTOR( mbx, "51XXMOUSE$MBX" );
$DESCRIPTOR( mbx_a, "51XXMOUSE_A$MBX" );
if( ( io_rc = SYS$CREMBX( 0, &mbx_channel, 12, 120, 0, 0, &mbx ) ) != SS$_NORMAL )
{
printf( "Error after: %s in open_mail, status %d\n", "SYS$CREMBX", io_rc );
return( 1 );
}
if( ( io_rc = SYS$CREMBX( 0, &mbx_channel_a, 4, 40, 0, 0, &mbx_a ) ) != SS$_NORMAL )
{
printf( "Error after: %s in open_mail, status %d\n", "SYS$CREMBX", io_rc );
return( 1 );
}
return ( 0 );
}
/*----------------------------------------------------------------------*\
|* mlisten subroutine: receive change mouse status command *|
|* from the parent process. *|
\*----------------------------------------------------------------------*/
void mlisten()
{
char dummy;
int io_rc;
int mice_xx, mice_yy; /* this x,y coordinates for move_mouse only */
int state, i;
unsigned short
is_short;
unsigned char *to_char;
while ( 1 )
{
if( ( io_rc = SYS$QIOW( event_flag_MBX, mbx_channel, IO$_READVBLK, &mbx_status,
0, 0, mbx_buffer, 12, 0, 0, 0, 0 ) != SS$_NORMAL ) ||
( mbx_status.condition != SS$_NORMAL ) ||
( mbx_status.count != 12 ) )
{
printf( "Error after: %s in mlisten, status %d, iosb %d, buffer size %d\n",
"SYS$QIOW", io_rc, mbx_status.condition, mbx_status.count );
return;
}
/* all mouse function activates only if in focus */
XGetInputFocus( display, &focus, &state );
if( focus != term ) /* if not in focus then set the mouse to focus */
XSetInputFocus( display, term, RevertToParent, CurrentTime );
switch( mbx_buffer[0] )
{
case INIT_MOUSE:
XWarpPointer( display, None, term, 0, 0, 0, 0,
mice.x_offset, mice.y_offset );
mice.send = 1;
break;
case GRAB_MOUSE:
if( mice.send && !mice.grab )
{
XDefineCursor( display, term, cursor );
XGrabPointer ( display, term, 0, mask, GrabModeAsync, GrabModeAsync,
term, cursor, CurrentTime );
mice.grab = 1;
}
break;
case FREE_MOUSE:
if( mice.send && mice.grab )
{
XUndefineCursor( display, term );
XUngrabPointer( display, CurrentTime );
mice.grab = 0;
}
break;
case MOVE_MOUSE:
if( mice.send )
{
mice_xx = mbx_buffer[1];
mice_yy = mbx_buffer[2];
if ( !mice.grab )
XGrabPointer( display, term, 1, mask, GrabModeAsync, GrabModeAsync,
None, None, CurrentTime );
XWarpPointer( display, None,term /* term*/, 0, 0, 0, 0,
mice_xx, mice_yy );
if ( !mice.grab )
XUngrabPointer( display, CurrentTime );
}
break;
}
}
return;
}
/*----------------------------------------------------------------------*\
|* open_channel subroutine: assign the channel for the mouse output. *|
\*----------------------------------------------------------------------*/
open_channel()
{
int io_rc;
$DESCRIPTOR( port, "51XXMOUSE$PORT" );
if( ( io_rc = SYS$ASSIGN( &port, &mice_channel, 0, 0 ) ) != SS$_NORMAL )
{
printf( "Error after: %s in open_channel, status %d\n", "SYS$ASSIGN", io_rc );
return( 1 );
}
/* In order to allow hangup notification, enable CTRL/Y AST */
/* delivery for the LTAxxx: device. The CTRL/Y AST is called */
/* if an abnormal termination occurs to the remote application */
/* device */
if( ( ( io_rc = SYS$QIOW( event_flag_LAT, mice_channel, IO$_SETMODE | IO$M_CTRLYAST,
&mice_status, 0, 0,
ts_hangup, 0, 3 /* user mode */, 0, 0, 0 ) ) != SS$_NORMAL ) ||
( mice_status.condition != SS$_NORMAL ) )
{
printf( "Error after: %s in open_channel, status %d, iosb %d\n",
"SYS$QIOW (mode)", io_rc, mice_status.condition );
return( 1 );
}
if ( connect_lat() )
return ( 1 );
else
return ( 0 );
}
/*----------------------------------------------------------------------*\
|* connect_lat subroutine: connect to LAT port. *|
\*----------------------------------------------------------------------*/
connect_lat(void)
{
int i,io_rc;
static float pause = 0.5;
/* solicit the connection to the LT device */
for ( i=0; i<RETRIES; i++)
{
SYS$QIOW(event_flag_LAT, mice_channel, IO$_TTY_PORT | IO$M_LT_DISCON,
&mice_status, 0, 0, 0, 0, 0, 0, 0, 0);
if( (( io_rc = SYS$QIOW( event_flag_LAT, mice_channel,
IO$_TTY_PORT | IO$M_LT_CONNECT,
&mice_status, 0, 0,
0, 0, 0, 0, 0, 0 ) ) != SS$_NORMAL ) ||
( mice_status.condition != SS$_NORMAL ) )
{
printf("Error after: %s in connect_lat, status %d, iosb %d, rejection %d (pg 8-58)\n",
"SYS$QIOW (connect)", io_rc, mice_status.condition,
mice_status.count );
LIB$WAIT( &pause );
}
else
return ( 0 ) ;
}
return ( 1 );
}
/*----------------------------------------------------------------------*\
|* ts_hungup subroutine: handle T.S disconnections *|
\*----------------------------------------------------------------------*/
void ts_hangup(void)
{
printf("Hungup Error, trying to reconnect\n");
if ( connect_lat() )
go_out();
return;
}
/*----------------------------------------------------------------------*\
|* open_display subroutine: initialize Xwindow & find terminal window *|
|* properties *|
\*----------------------------------------------------------------------*/
open_display()
{
float pause = 3.0;
int i;
unsigned int cursor_width,
cursor_height;
char cursor_bits[] =
{
0x80, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
Pixmap cursor_shape;
XColor cursor_fore,
cursor_back;
display = XOpenDisplay( 0 );
if( !display )
{
printf( "Could not open display\n" );
return( 1 );
}
root = XRootWindow( display, DefaultScreen( display ) );
memset( (char *)&cursor_fore, 0x00, sizeof( XColor ) );
memset( (char *)&cursor_back, 0x00, sizeof( XColor ) );
cursor_shape = XCreatePixmapFromBitmapData( display, root, cursor_bits, 16, 16, 1, 0, 1 );
XQueryBestCursor( display, root, 16, 16,
&cursor_width, &cursor_height );
cursor = XCreatePixmapCursor( display, cursor_shape, cursor_shape,
&cursor_fore, &cursor_back, 0, 0 );
term = fetch_window( display, root );
if( term == NULL )
{
printf( "Could not fetch DECTerm window trying again\n" );
return( 1 );
}
XGetWindowAttributes( display, term, &xwa );
memset( mice_buffer, 0, sizeof( mice_buffer ) );
mice.send = 0;
mice.grab = 0;
mice.x_offset = xwa.width / WINDOW_COLUMNS;
mice.y_offset = ( xwa.height - Y_OFFSET ) / WINDOW_LINES;
mice.area_width = mice.x_offset * AREA_COLUMNS;
mice.area_height = mice.y_offset * AREA_LINES;
mice.x_offset += X_OFFSET;
mice.y_offset += Y_OFFSET;
return( 0 );
}
/*----------------------------------------------------------------------*\
|* close_display subroutine: end window activity. *|
\*----------------------------------------------------------------------*/
void close_display()
{
if (mice.grab)
{
XUndefineCursor( display, term );
XUngrabPointer ( display, CurrentTime );
mice.grab = 0;
}
mice.send = 0;
XFreeCursor( display, cursor );
XCloseDisplay( display );
return;
}
/*----------------------------------------------------------------------*\
|* fetch_window subroutine: fetch DECTerm window ID. *|
|* To do this look for window in the center of the screen. *|
\*----------------------------------------------------------------------*/
Window fetch_window( display, top )
Display *display;
Window top;
{
Window *w[10];
int i, x, y, jx, jy;
XGetWindowAttributes( display, top, &xwa );
x = xwa.width / 2;
y = xwa.height / 2;
XTranslateCoordinates( display, top, top, x, y, &jx, &jy, &w[0] );
for( i = 0; i < 9 && w[i] > 0; ++i )
XTranslateCoordinates( display, top, w[i], x, y, &jx, &jy, &w[i + 1] );
return( w[i - 1] );
}
The private header file:
/*
File name : 51XXTERM11.H
Programer name : Anatoly Lerman
Writen date : 26/04/94
last update :
external tasks :
external subroutine :
file description : This file is the header file for the
51XXTERM11.C file.
*/
/*----------------------------------------------------------------------------*/
#define PAUSE 0.010
#define WINDOW_LINES 28
#define WINDOW_COLUMNS 82
#define AREA_LINES 24
#define AREA_COLUMNS 80
#define X_OFFSET 3
#define Y_OFFSET 7
#define MONITOR_X 512
#define MONITOR_Y 480
#define OPEN_WINDOW 1
#define CLOSE_WINDOW 2
#define MOVE_WINDOW 3
#define ACTIVATE_WINDOW 4
#define SET_CURSOR 5
#define CLEAR_WINDOW 6
#define INIT_MOUSE 7
#define GRAB_MOUSE 8
#define FREE_MOUSE 9
#define RESET_DISPLAY 10
#define STOP_MOUSE 11
#define MOVE_MOUSE 15
#define TRUE 1
#define FALSE 0
/*----------------------------------------------------------------------------*/
typedef struct
{
short condition;
short count;
int info;
} IO_STATUS;
typedef struct
{
int abs_x, abs_y,
x, y, previous_x, previous_y;
unsigned int buttons, previous_buttons;
unsigned char send;
unsigned char grab;
unsigned int area_width,
area_height,
x_offset,
y_offset;
} MICE;
/*----------------------------------------------------------------------------*/
void close_display();
void mlisten();
Window fetch_window();
int connect_lat(void);
void ts_hangup(void);
|