File:  [Research Unix] / researchv9 / X11 / src / X.V11R1 / lib / Xtk / TMstate.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Tue Apr 24 17:22:00 2018 UTC (8 years, 1 month ago) by root
Branches: belllabs, MAIN
CVS tags: researchv9-SUN3_old, researchv9-SUN3, HEAD
researchv9-SUN3(old)

#ifndef lint
static char rcsid[] = "$Header: /var/lib/cvsd/repos/research/researchv9/X11/src/X.V11R1/lib/Xtk/TMstate.c,v 1.1.1.1 2018/04/24 17:22:00 root Exp $";
#endif lint

/*
 * Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
 * 
 *                         All Rights Reserved
 * 
 * Permission to use, copy, modify, and distribute this software and its 
 * documentation for any purpose and without fee is hereby granted, 
 * provided that the above copyright notice appear in all copies and that
 * both that copyright notice and this permission notice appear in 
 * supporting documentation, and that the name of Digital Equipment
 * Corporation not be used in advertising or publicity pertaining to
 * distribution of the software without specific, written prior permission.  
 * 
 * 
 * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
 * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
 * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
 * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
 * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
 * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
 * SOFTWARE.
 */
/* TMstate.c -- maintains the state table of actions for the translation 
 *              manager.
 */

#include "Xlib.h"
#include "Intrinsic.h"
#include "Atoms.h"
#include "TM.h"
#include "TMprivate.h"

extern char *strcpy();

static void FreeActionRecs(action)
  ActionPtr action;
{
    int i;
    if (action->next != NULL)
        FreeActionRecs(action->next);
    if (action->param != NULL)
        for (i=0; i<action->paramNum; i++)
            XtFree(action->param[i]);
    XtFree(action->token);
    XtFree((char *)action->param);
    XtFree((char *)action);
}


static void FreeStateRecs(state)
  StatePtr state;
{
    if (state->next != NULL)
	FreeStateRecs(state->next);
    if (state->nextLevel != NULL)
	FreeStateRecs(state->nextLevel);
    if (state->actions != NULL)
        FreeActionRecs(state->actions);
    XtFree((char *)state->actions);
    XtFree((char *)state->next);
    XtFree((char *)state->nextLevel);
}

static void PrintModifiers(mask, mod)
    unsigned long mask, mod;
{
    if (mask & ShiftMask)
	(void) printf("<%sShift>", ((mod & ShiftMask) ? "" : "~"));
    if (mask & ControlMask)
	(void) printf("<%sCtrl>", ((mod & ControlMask) ? "" : "~"));
    if (mask & LockMask)
	(void) printf("<%sLock>", ((mod & LockMask) ? "" : "~"));
    if (mask & Mod1Mask)
	(void) printf("<%sMeta>", ((mod & Mod1Mask) ? "" : "~"));
    if (mask & Mod2Mask)
	(void) printf("<%sMod2>", ((mod & Mod2Mask) ? "" : "~"));
    if (mask & Mod3Mask)
	(void) printf("<%sMod3>", ((mod & Mod3Mask) ? "" : "~"));
    if (mask & Mod4Mask)
	(void) printf("<%sMod4>", ((mod & Mod4Mask) ? "" : "~"));
    if (mask & Mod5Mask)
	(void) printf("<%sMod5>", ((mod & Mod5Mask) ? "" : "~"));
}

static void PrintEvent(event, endStr)
    unsigned long event;
    char * endStr;
{
    (void) strcpy(endStr, "");
    switch (event) {
	case KeyPressMask:
	    (void) printf("<Key>");
	    break;
	case KeyReleaseMask:
	    (void) printf("<Key>");
	    break;
	case ButtonPressMask:
	    (void) printf("<Btn");
	    (void) strcpy(endStr, "Down>");
	    break;
	case ButtonReleaseMask:
	    (void) printf("<Btn");
	    (void) strcpy(endStr, "Up>");
	    break;
    }
}

static void PrintCode(code)
    unsigned long code;
{
    char ch;
    ch = code - 'a' + 'A';
    if (ch >= 'A' && ch <= 'Z')
	(void) printf("%c",ch);
    else
        (void) printf("%d", code);
}

static void PrintActions(ev, code, mask, modif, actions, j)
    unsigned long ev[], mask[], modif[], code[];
    ActionPtr actions;
    int j;
{
    char endStr[20];
    int i;
    for (i=0; i<j; i++) {
	PrintModifiers(mask[i], modif[i]);
	PrintEvent(ev[i], endStr);
	PrintCode(code[i]);
        (void) printf("%s ",endStr);
    }
    while (actions != NULL && actions->token != NULL) {
        (void) printf("---------> action = %s\n", actions->token);
	actions = actions->next;
    }
    (void) printf("\n");
}

/*
 * there are certain cases where you want to ignore the event and stay
 * in the same state.
 */
static Boolean SpecialCase(event)
  EventSeqPtr event;   
{
    if (event->eventType == MotionNotify || event->eventType == ButtonPress ||
	event->eventType == ButtonRelease)
	    return TRUE;
    else
	    return FALSE;
}


static int FindEvent(translations, eventSeq) 
  _XtTranslations translations;
  EventSeqPtr eventSeq;
{
    EventObjPtr eventTbl = translations->eventObjTbl;
    int i;

    for (i=0; i < translations->numEvents; i++) {
        if (
	    (eventTbl[i].eventType	== eventSeq->eventType) &&
            (eventTbl[i].eventCode	== eventSeq->eventCode) &&
	    (eventTbl[i].eventCodeMask	== eventSeq->eventCodeMask) &&
	    (eventTbl[i].modifiers	== eventSeq->modifiers) &&
	    (eventTbl[i].modifierMask	== eventSeq->modifierMask)
	   )
		return(i);
   }
    return(-1);
}


static int MatchEvent(translations, eventSeq) 
  _XtTranslations translations;
  EventSeqPtr eventSeq;
{
    EventObjPtr eventTbl = translations->eventObjTbl;
    int i;

    for (i=0; i < translations->numEvents; i++) {
        if ((eventTbl[i].eventType == eventSeq->eventType) &&
            (eventTbl[i].eventCode ==
		(eventTbl[i].eventCodeMask & eventSeq->eventCode)) &&
	    (eventTbl[i].modifiers ==
		(eventTbl[i].modifierMask & eventSeq->modifiers))
	   ) 
		return(i);
   }
    return(-1);
}


static EventObjPtr  CreateStates(translations, index, eventSeq)
    _XtTranslations translations;
    int index;
    EventSeqPtr eventSeq;
{
    EventObjPtr eventObjTbl = translations->eventObjTbl;
    StatePtr state;
    Boolean found = FALSE;
    ActionPtr actions = eventSeq->actions;

    if (eventObjTbl[index].state == NULL) {  
	eventObjTbl[index].state = (StatePtr) XtMalloc((unsigned)sizeof(StateRec));
        state = eventObjTbl[index].state;
        state->index = index;
        state->nextLevel = NULL;
        state->next = NULL;
        state->actions = NULL; ;
    } else {
        state = eventObjTbl[index].state;
	do {
	    found = FALSE;
	    if (eventSeq->next != NULL && state->nextLevel != NULL) {
		eventSeq = eventSeq->next;
		index = FindEvent(translations, eventSeq);
		state = state->nextLevel;
		if (state->index == index) 
		    found = TRUE;
		while (state->next != NULL && !found) {
	            state = state->next;
		    if (state->index == index) 
		        found = TRUE;
		}
		if (!found) {
		    state->next = (StatePtr) XtMalloc((unsigned)sizeof(StateRec));
		    state = state->next;
		    state->index = index;
		    state->nextLevel = NULL;
		    state->next = NULL;
		    state->actions = NULL;
		}
	    }
	} while (found);
    }
    while (eventSeq->next != NULL) {
	eventSeq = eventSeq->next;
 	index = FindEvent(translations, eventSeq);
	state->nextLevel = (StatePtr) XtMalloc((unsigned)sizeof(StateRec));
	state = state->nextLevel;
	state->index = index;
	state->nextLevel = NULL;
	state->next = NULL;
	state->actions = NULL;
    }
    if (state->actions != NULL) 
	FreeActionRecs(state->actions);
    state->actions = actions;

    return eventObjTbl;
}


/*** Public procedures ***/
EventObjPtr EventMapObjectCreate(translations, eventSeq)
  _XtTranslations	translations;
  EventSeqPtr eventSeq;
{
    EventObjPtr new;

    if (FindEvent(translations, eventSeq) >= 0)
	return translations->eventObjTbl;

    if (translations->numEvents == translations->eventTblSize) {
        translations->eventTblSize += 100;
	translations->eventObjTbl = (EventObjPtr) XtRealloc(
	    (char *)translations->eventObjTbl, 
	    translations->eventTblSize*sizeof(EventObjRec));
    }

    new = &translations->eventObjTbl[translations->numEvents];

    new->eventType	= eventSeq->eventType;
    new->eventCodeMask	= eventSeq->eventCodeMask;
    new->eventCode	= eventSeq->eventCode;
    new->modifierMask	= eventSeq->modifierMask;
    new->modifiers	= eventSeq->modifiers;
    new->state		= NULL;

    translations->numEvents++;
    return translations->eventObjTbl;
}


EventObjPtr EventMapObjectGet(translations, eventSeq)
  _XtTranslations translations;
  EventSeqPtr eventSeq;
{
    EventObjPtr eventTbl = translations->eventObjTbl;
    int index;
    if ((index = FindEvent(translations, eventSeq)) < 0)
	return NULL;
    else
        return &eventTbl[index];
}


EventObjPtr EventMapObjectSet(translations, eventSeq)
  _XtTranslations translations;
  EventSeqPtr eventSeq;
{
    EventObjPtr eventTbl = translations->eventObjTbl;
    int index;
    if ((index = FindEvent(translations, eventSeq)) >= 0)
        eventTbl = CreateStates(translations, index, eventSeq);
    return eventTbl;
}


/* ARGSUSED */
void TranslateEvent(w, closure, event)
  Widget w;
  Opaque closure;
  register XEvent *event;
{
    static unsigned long upTime=0;
    static Boolean buttonUp = FALSE;
    static StatePtr curState = NULL;
    StatePtr oldState;
    EventSeqRec curEvent;
    int index;
    ActionPtr actions;
    Boolean specialCase;

    oldState = 0;
    specialCase = FALSE;
    curEvent.eventCodeMask = 0;
    curEvent.eventCode = 0;
    curEvent.modifierMask = 0;
    curEvent.modifiers = 0;
    curEvent.eventType = event->type;
    switch (event->type) {
	case KeyPress:
	case KeyRelease:
	    buttonUp = FALSE;
	    curEvent.modifiers = event->xkey.state;
	    event->xkey.state = 0;
	    curEvent.eventCode = XLookupKeysym(&event->xkey, 0);
	    event->xkey.state = curEvent.modifiers;
	    break;
	case ButtonPress:
	    if (buttonUp && curState != NULL) 
		if ((unsigned long)
	            (upTime - event->xbutton.time) >
		    w->core.translations->clickTime)
		    curState = NULL;
	    buttonUp = FALSE;
 	    curEvent.eventCode = event->xbutton.button;
	    curEvent.modifiers = event->xbutton.state;
	    break;
	case ButtonRelease:
	    buttonUp = TRUE;
	    upTime = event->xbutton.time;
	    curEvent.eventCode = event->xbutton.button;
	    curEvent.modifiers = event->xbutton.state;
	    break;
	case MotionNotify:
	    buttonUp = FALSE;
	    curEvent.modifiers = event->xmotion.state;
	    break;
	case EnterNotify:
	case LeaveNotify:
	    buttonUp = FALSE;
	    curEvent.modifiers = event->xcrossing.state;
	    break;
	default:
	    buttonUp = FALSE;
	    break;
    }
    if (curState != NULL) {	/* check the current level */
	index = MatchEvent(w->core.translations, &curEvent);
	oldState = curState;
	while (curState != NULL && curState->index != index)
	    curState = curState->next;
	if (curState == NULL)
	    if (SpecialCase(&curEvent)) {
	        curState = oldState;
	        specialCase = TRUE;
	    } else {  /* nothing at level but you performed an action on the
			 last event---> start over with this new event. */
		if (oldState->actions != NULL) {
		    curState = oldState;
		    index = MatchEvent(w->core.translations, &curEvent);
        	    curState = w->core.translations->eventObjTbl[index].state;
		}
           }
    } else {
	index = MatchEvent(w->core.translations, &curEvent);
	if (index == -1) return;
        curState = w->core.translations->eventObjTbl[index].state;
    }
    if (curState != NULL && !specialCase) {
	actions = curState->actions;
	while (actions != NULL)  { /* perform any actions */
	    if (actions->proc != NULL)
			/*!!!!! should have params here */
		(*(actions->proc))(w, event);
	    actions = actions->next;
        }
        curState = curState->nextLevel;
    }
}

void TranslateTableFree(translations)
    _XtTranslations translations;
{
    EventObjPtr tbl = translations->eventObjTbl;
    int i;

    /* !!! ref count this, it may be shared */

    for (i=0; i<translations->numEvents; i++) {
	if (tbl[i].state != NULL) FreeStateRecs(tbl[i].state);
    }
    XtFree((char *)tbl);
    XtFree((char *)translations);
}


void TranslateTablePrint(translations)
    _XtTranslations translations;
{
    EventObjPtr tbl = translations->eventObjTbl;
    int i, j;
    unsigned long ev[100], code[100], mask[100], modif[100];
    StatePtr stack[100], state;
	
    for (i=0; i<translations->numEvents; i++) {
	j=0;
	if (tbl[i].state != NULL) {
	    state = tbl[i].state;
	    stack[j] = tbl[i].state;
	    ev[j] = tbl[i].eventType;
	    code[j] = tbl[i].eventCode;
	    mask[j] = tbl[i].modifierMask;
	    modif[j++] = tbl[i].modifiers;
            if (state->actions != NULL)
	        PrintActions(ev, code, mask, modif, state->actions, j);
	    do {
	        do {
	            while (state->nextLevel != NULL) {
	                state = state->nextLevel;
	                stack[j] = state;
	                ev[j] = tbl[state->index].eventType;
		        code[j] = tbl[state->index].eventCode;
			mask[j] =  tbl[state->index].modifierMask;
	                modif[j++] = tbl[state->index].modifiers;
                    	if (state->actions != NULL)
	                    PrintActions(
				ev, code, mask, modif, state->actions, j);
	            }
	            j--;
	            if (state->next != NULL) {
	            	state = state->next;
	            	stack[j] = state;
	            	ev[j] = tbl[state->index].eventType;
	            	code[j] = tbl[state->index].eventCode;
	            	mask[j] = tbl[state->index].modifierMask;
	            	modif[j++] = tbl[state->index].modifiers;
                    	if (state->actions != NULL)
	                    PrintActions(
				ev, code, mask, modif, state->actions, j);
	            }
	     	} while (state->next != NULL &&  state->nextLevel != NULL);
	    	j--;
	    	state = stack[j];
	    	if (state->next != NULL) {
	            state = state->next;
		    stack[j] = state;
	            ev[j] = tbl[state->index].eventType;
	            code[j] = tbl[state->index].eventCode;
	            mask[j] = tbl[state->index].modifierMask;
	            modif[j++] = tbl[state->index].modifiers;
                    if (state->actions != NULL)
	                PrintActions(ev, code, mask, modif, state->actions, j);
	        } else
		    j--;
	    } while (j-1>0);
	}
    }
}

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.