ftp.nice.ch/pub/next/developer/languages/c/djgpp-NS.s.tar.gz#/djgpp/go32/event.c

This is event.c in view mode; [Download] [Up]

/**
 ** EVENT.C
 **
 **  Copyright (C) 1992, Csaba Biegl
 **    820 Stirrup Dr, Nashville, TN, 37221
 **    csaba@vuse.vanderbilt.edu
 **
 **  This file is distributed under the terms listed in the document
 **  "copying.cb", available from the author at the address above.
 **  A copy of "copying.cb" should accompany this file; if not, a copy
 **  should be available from where this file was obtained.  This file
 **  may not be distributed without a verbatim copy of "copying.cb".
 **  You should also have received a copy of the GNU General Public
 **  License along with this program (it is in the file "copying");
 **  if not, write to the Free Software Foundation, Inc., 675 Mass Ave,
 **  Cambridge, MA 02139, USA.
 **
 **  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.
 **/

#ifndef  __TURBOC__
#error	 Don't even try to compile it with this compiler
#endif

#pragma  inline

#include <stdlib.h>
#include <string.h>
#include <alloc.h>
#include <stdio.h>
#include <time.h>
#include <dos.h>

#include "eventque.h"

extern int  far _ev_interss;	/* interrupt stack segment */
extern int  far _ev_interds;	/* interrupt data segment */
extern int  far _ev_kbintsp;	/* keyboard interrupt stack */
extern int  far _ev_msintsp;	/* mouse interrupt stack */
extern int  far _ev_kbinter;	/* keyboard interrupt flag */
extern int  ctrl_c_flag;

extern void interrupt (* far _ev_oldkbint)(void);

extern void far	      _ev_mouseint(void);
extern void interrupt _ev_keybdint(void);

static void dummydraw(void) {}

static EventQueue *queue = NULL;
static void (*mousedraw)(void) = dummydraw;
static char *stack = NULL;
static char *qsave = NULL;

static int  ms_xpos;
static int  ms_ypos;
static int  ms_xmickey;
static int  ms_ymickey;

#ifdef FOR_GO32
#ifndef  USE_AT_BIOS		/* always use AT BIOS calls for GO32 version */
#define  USE_AT_BIOS
#endif
#else
static int  first_call = 1;
#endif

#define MS_ENABLE   EVENT_ENABLE(EVENT_MOUSE)
#define KB_ENABLE   EVENT_ENABLE(EVENT_KEYBD)

#define KB_SSIZE    128		/* keyboard handler stack size */
#define MS_SSIZE    128		/* mouse handler MINIMAL stack size */

#define IABS(x)	    (((x) > 0) ? (x) : -(x))

/* This is an ARDI hack to fit all the bits showing both right and left
 * shift, control, and alt keys (from both normal and extended keyboards)
 * into a single byte.  This format is only set if EVENT_RAWKEY events are 
 * chosen.  See eventque.h for the KB_RAW flags for testing these states.
 */

static unsigned char
fetch_kb_flags (void)
{
	unsigned short flags;

#ifdef USE_AT_BIOS
	_AX = 0x1200;
#else
	_AX = 0x200;
#endif
	geninterrupt(0x16);
	flags = _AX;
	if (!(queue->evq_enable & EVENT_ENABLE (EVENT_RAWKEY)))
		return flags;
	else
		return ((flags & 3) << 4) | ((flags >> 8) & 0xCF);
	/* This returns extended flags replacing scroll/num locks with shifts */
}

void far _ev_mousehandler(int msk,int btn,int mx,int my)
{
	EventRecord *ep;
	int moved = 0;
	int diff;

	if((diff = mx - ms_xmickey) != 0) {
	    ms_xmickey += diff;
	    ms_xpos    += diff;
	    if((diff = ms_xpos / queue->evq_xspeed) != 0) {
		ms_xpos %= queue->evq_xspeed;
		if(IABS(diff) >= queue->evq_thresh) diff *= queue->evq_accel;
		diff += queue->evq_xpos;
		if(diff <= queue->evq_xmin) diff = queue->evq_xmin;
		if(diff >= queue->evq_xmax) diff = queue->evq_xmax;
		if(diff != queue->evq_xpos) {
		    queue->evq_xpos  = diff;
		    queue->evq_moved = moved = 1;
		}
	    }
	}
	if((diff = my - ms_ymickey) != 0) {
	    ms_ymickey += diff;
	    ms_ypos    += diff;
	    if((diff = ms_ypos / queue->evq_yspeed) != 0) {
		ms_ypos %= queue->evq_yspeed;
		if(IABS(diff) >= queue->evq_thresh) diff *= queue->evq_accel;
		diff += queue->evq_ypos;
		if(diff <= queue->evq_ymin) diff = queue->evq_ymin;
		if(diff >= queue->evq_ymax) diff = queue->evq_ymax;
		if(diff != queue->evq_ypos) {
		    queue->evq_ypos  = diff;
		    queue->evq_moved = moved = 1;
		}
	    }
	}
	if((msk & ~1) && (queue->evq_enable & MS_ENABLE)) {
	    disable();
	    ep = &queue->evq_events[queue->evq_wrptr];
	    if(++queue->evq_wrptr == queue->evq_maxsize)
		queue->evq_wrptr = 0;
	    if(queue->evq_cursize < queue->evq_maxsize)
		queue->evq_cursize++;
	    else if(++queue->evq_rdptr == queue->evq_maxsize)
		queue->evq_rdptr = 0;
	    enable();
	    ep->evt_kbstat = fetch_kb_flags();
	    ep->evt_type   = EVENT_MOUSE;
	    ep->evt_mask   = msk;
	    ep->evt_button = btn;
	    ep->evt_xpos   = queue->evq_xpos;
	    ep->evt_ypos   = queue->evq_ypos;
	    ep->evt_time   = clock();
	}
	if(moved && queue->evq_drawmouse) (*mousedraw)();
}

void far _ev_keybdhandler(void)
{
	EventRecord *ep;
	int keycode,scancode;

	/* This section ARDI mods merged by C. Sandmann */
	if (queue->evq_enable & EVENT_ENABLE (EVENT_RAWKEY)) {
	    /* Fetch raw scancode from the keyboard.
	       Assume 0 means nothing there. */
	    scancode = inportb (0x60) << 8;
	    if (scancode != 0) {
		/* Queue up the event. */
		disable ();
		ep = &queue->evq_events[queue->evq_wrptr];
		if(++queue->evq_wrptr == queue->evq_maxsize)
		    queue->evq_wrptr = 0;
		if(queue->evq_cursize < queue->evq_maxsize)
		    queue->evq_cursize++;
		else if(++queue->evq_rdptr == queue->evq_maxsize)
		    queue->evq_rdptr = 0;
		enable();
		ep->evt_kbstat   = fetch_kb_flags ();
		ep->evt_keycode  = 0;
		ep->evt_scancode = scancode;
		ep->evt_type     = EVENT_RAWKEY;
		ep->evt_time     = clock();
	    }
	}

	if(queue->evq_enable & KB_ENABLE) for( ; ; ) {
#ifdef USE_AT_BIOS
	    _AX = 0x1100;
#else
	    _AX = 0x100;
#endif
	    geninterrupt(0x16);
	    asm jnz  charpresent;
	    return;
	  charpresent:
	    scancode = _AX;
	    if(scancode == 0)ctrl_c_flag = 1;
	    keycode  = (_AL == 0) ? _AH + 0x100 :
#ifdef USE_AT_BIOS
		(_AL == 0xe0) ? _AH + 0x200 :
#endif
		_AL;
	    if(queue->evq_delchar) {
#ifdef USE_AT_BIOS
		_AX = 0x1000;
#else
		_AX = 0;
#endif
		geninterrupt(0x16);
	    }
	    disable();
	    ep = &queue->evq_events[queue->evq_wrptr];
	    if(++queue->evq_wrptr == queue->evq_maxsize)
		queue->evq_wrptr = 0;
	    if(queue->evq_cursize < queue->evq_maxsize)
		queue->evq_cursize++;
	    else if(++queue->evq_rdptr == queue->evq_maxsize)
		queue->evq_rdptr = 0;
	    enable();
	    ep->evt_kbstat   = fetch_kb_flags();
	    ep->evt_keycode  = keycode;
	    ep->evt_scancode = scancode;
	    ep->evt_type     = EVENT_KEYBD;
	    ep->evt_time     = clock();
	}
}

void EventQueueDeInit(void)
{
	if(stack != NULL) {
	    _AX = 0;
	    geninterrupt(0x33);
#ifdef FOR_GO32
	    _ev_kbinter = 1;
#else
	    setvect(9,_ev_oldkbint);
#endif
	    free(stack);
	    free(qsave);
	    stack = NULL;
	}
}

EventQueue *EventQueueInit(int qsize,int ms_stksize,void (*msdraw)(void))
{
	if(stack != NULL) EventQueueDeInit();
	if(qsize < 20) qsize = 20;
	if(ms_stksize < MS_SSIZE) ms_stksize = MS_SSIZE;
	stack = malloc(KB_SSIZE + ms_stksize);
	qsave = malloc(sizeof(EventQueue)+(sizeof(EventRecord)*(qsize-1))+4);
	if((stack == NULL) || (qsave == NULL)) {
	    if(stack != NULL) { free(stack); stack = NULL; }
	    if(qsave != NULL) { free(qsave); qsave = NULL; }
	    return(NULL);
	}
	_ev_interds = FP_SEG(&ms_xpos);
	_ev_interss = FP_SEG(stack);
	_ev_kbintsp = FP_OFF(stack) + KB_SSIZE;
	_ev_msintsp = FP_OFF(stack) + KB_SSIZE + ms_stksize;
	ms_xpos = ms_xmickey = 0;
	ms_ypos = ms_ymickey = 0;
	queue = (EventQueue *)(((long)qsave + 3L) & ~3L);
	memset(queue,0,sizeof(EventQueue));
	queue->evq_maxsize   = qsize;
	queue->evq_xmax	     = 79;
	queue->evq_ymax	     = 24;
	queue->evq_xspeed    = 8;
	queue->evq_yspeed    = 16;
	queue->evq_thresh    = 100;
	queue->evq_accel     = 1;
	queue->evq_delchar   = 1;
	queue->evq_enable    = MS_ENABLE | KB_ENABLE;
	_AX = 0;
	geninterrupt(0x33);
	if(_AX != 0) {
	    _AX = 11;
	    geninterrupt(0x33);
	    mousedraw = (msdraw != NULL) ? msdraw : dummydraw;
	    _ES = FP_SEG(_ev_mouseint);
	    _DX = FP_OFF(_ev_mouseint);
	    _CX = 0xff;
	    _AX = 0x0c;
	    geninterrupt(0x33);
	} else					/* so mouse requiring progs */
	    queue->evq_enable &= ~MS_ENABLE;	/* can die gracefully */
#ifndef FOR_GO32
	_ev_oldkbint = getvect(9);
	setvect(9,_ev_keybdint);
	if(first_call) {
	    atexit(EventQueueDeInit);
	    first_call = 0;
	}
#endif
	_ev_kbinter = (-1);
	return(queue);
}

These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.