1350 lines
		
	
	
		
			37 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			1350 lines
		
	
	
		
			37 KiB
		
	
	
	
		
			C
		
	
	
	
| /* $Xorg: xkbconfig.c,v 1.4 2000/08/17 19:46:43 cpqbld Exp $ */
 | |
| /************************************************************
 | |
|  Copyright (c) 1995 by Silicon Graphics Computer Systems, Inc.
 | |
| 
 | |
|  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 Silicon Graphics not be 
 | |
|  used in advertising or publicity pertaining to distribution 
 | |
|  of the software without specific prior written permission.
 | |
|  Silicon Graphics makes no representation about the suitability 
 | |
|  of this software for any purpose. It is provided "as is"
 | |
|  without any express or implied warranty.
 | |
|  
 | |
|  SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS 
 | |
|  SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 
 | |
|  AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
 | |
|  GRAPHICS 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.
 | |
| 
 | |
|  ********************************************************/
 | |
| /* $XFree86: xc/lib/xkbfile/xkbconfig.c,v 3.7 2001/11/30 12:11:51 eich Exp $ */
 | |
| 
 | |
| #include <stdio.h>
 | |
| #include <ctype.h>
 | |
| #include <stdlib.h>
 | |
| 
 | |
| #include <X11/Xfuncs.h>
 | |
| 
 | |
| #include <X11/Xfuncs.h>
 | |
| 
 | |
| #ifndef XKB_IN_SERVER
 | |
| 
 | |
| #include <X11/Xos.h>
 | |
| #include <X11/Xlib.h>
 | |
| #include <X11/keysym.h>
 | |
| #include <X11/XKBlib.h>
 | |
| #include "XKBfileInt.h"
 | |
| 
 | |
| #else
 | |
| 
 | |
| #include "X.h"
 | |
| #define	NEED_EVENTS
 | |
| #include <X11/keysym.h>
 | |
| #include "Xproto.h"
 | |
| #include "misc.h"
 | |
| #include "inputstr.h"
 | |
| #include "dix.h"
 | |
| #define	XKBSRV_NEED_FILE_FUNCS
 | |
| #include "XKBsrv.h"
 | |
| #endif
 | |
| 
 | |
| #include <X11/extensions/XKBconfig.h>
 | |
| 
 | |
| /***====================================================================***/
 | |
| 
 | |
| #define	XKBCF_MAX_STR_LEN	100
 | |
| static char _XkbCF_rtrn[XKBCF_MAX_STR_LEN+1];
 | |
| 
 | |
| static int
 | |
| ScanIdent(FILE *file,int ch,XkbCFScanResultPtr val_rtrn)
 | |
| {
 | |
| register int	i;
 | |
| char *		str;
 | |
| 
 | |
|     val_rtrn->str= str= _XkbCF_rtrn;
 | |
|     for (i=0;(isalpha(ch)||isdigit(ch)||(ch=='_'));ch=getc(file)) {
 | |
| 	if (i<XKBCF_MAX_STR_LEN)
 | |
| 	    str[i++]= ch;
 | |
|     }
 | |
|     if ((ch!=EOF)&&(ch!=' ')&&(ch!='\t'))
 | |
| 	ungetc(ch,file);
 | |
|     str[i]= '\0';
 | |
|     return XkbCF_Ident;
 | |
| }
 | |
| 
 | |
| static int
 | |
| ScanString(FILE *file,int quote,XkbCFScanResultPtr val_rtrn)
 | |
| {
 | |
| int	ch,nInBuf;
 | |
| 
 | |
|     nInBuf = 0;
 | |
|     while ( ((ch=getc(file))!=EOF) && (ch!='\n') && (ch!=quote) ) {
 | |
| 	if ( ch == '\\' ) {
 | |
| 	    if ((ch = getc(file))!=EOF) {
 | |
| 		if ( ch=='n' )		ch = '\n';
 | |
| 		else if ( ch == 't' )	ch = '\t';
 | |
| 		else if ( ch == 'v' )	ch = '\v';
 | |
| 		else if ( ch == 'b' )	ch = '\b';
 | |
| 		else if ( ch == 'r' )	ch = '\r';
 | |
| 		else if ( ch == 'f' )	ch = '\f';
 | |
| 		else if ( ch == 'e' )	ch = '\033';
 | |
| 		else if ( ch == '0' ) {
 | |
| 		    int tmp,stop;
 | |
| 		    ch = stop = 0;
 | |
| 		    if (((tmp=getc(file))!=EOF) && (isdigit(tmp)) && 
 | |
| 						(tmp!='8') && (tmp!='9')) {
 | |
| 			ch= (ch*8)+(tmp-'0');
 | |
| 		    }
 | |
| 		    else {
 | |
| 			stop= 1;
 | |
| 			ungetc(tmp,file);
 | |
| 		    }
 | |
| 		    if ((!stop) && ((tmp=getc(file))!=EOF) && (isdigit(tmp)) && 
 | |
| 						(tmp!='8') && (tmp!='9')) {
 | |
| 			ch= (ch*8)+(tmp-'0');
 | |
| 		    }
 | |
| 		    else {
 | |
| 			stop= 1;
 | |
| 			ungetc(tmp,file);
 | |
| 		    }
 | |
| 		    if ((!stop) && ((tmp=getc(file))!=EOF) && (isdigit(tmp)) && 
 | |
| 						(tmp!='8') && (tmp!='9')) {
 | |
| 			ch= (ch*8)+(tmp-'0');
 | |
| 		    }
 | |
| 		    else {
 | |
| 			stop= 1;
 | |
| 			ungetc(tmp,file);
 | |
| 		    }
 | |
| 		}
 | |
| 	    }
 | |
| 	    else return XkbCF_EOF;
 | |
| 	}
 | |
| 
 | |
| 	if ( nInBuf < XKBCF_MAX_STR_LEN-1 ) 
 | |
| 	    _XkbCF_rtrn[nInBuf++] = ch;
 | |
|     }
 | |
|     if ( ch == quote ) {
 | |
| 	_XkbCF_rtrn[nInBuf++] = '\0';
 | |
| 	val_rtrn->str= _XkbCF_rtrn;
 | |
| 	return XkbCF_String;
 | |
|     }
 | |
|     return XkbCF_UnterminatedString;
 | |
| }
 | |
| 
 | |
| static int
 | |
| ScanInteger(FILE *file,int ch,XkbCFScanResultPtr val_rtrn)
 | |
| {
 | |
| int	i;
 | |
| 
 | |
|     if (isdigit(ch))
 | |
| 	ungetc(ch,file);
 | |
|     if (fscanf(file,"%i",&i)==1) {
 | |
| 	val_rtrn->ival= i;
 | |
| 	return XkbCF_Integer;
 | |
|     }
 | |
|     return XkbCF_Unknown;
 | |
| }
 | |
| 
 | |
| int 
 | |
| XkbCFScan(FILE *file,XkbCFScanResultPtr val_rtrn,XkbConfigRtrnPtr rtrn)
 | |
| {
 | |
| int	ch;
 | |
| 
 | |
|     do {
 | |
| 	ch= getc(file);
 | |
|     } while ((ch=='\t')||(ch==' '));
 | |
|     if (isalpha(ch))
 | |
| 	 return ScanIdent(file,ch,val_rtrn);
 | |
|     else if (isdigit(ch))
 | |
| 	 return ScanInteger(file,ch,val_rtrn);
 | |
|     else if (ch=='"')
 | |
| 	 return ScanString(file,ch,val_rtrn);
 | |
|     else if (ch=='\n') {
 | |
| 	rtrn->line++;
 | |
| 	return XkbCF_EOL;
 | |
|     }
 | |
|     else if (ch==';')
 | |
| 	return XkbCF_Semi;
 | |
|     else if (ch=='=')
 | |
| 	return XkbCF_Equals;
 | |
|     else if (ch=='+') {
 | |
| 	ch= getc(file);
 | |
| 	if (ch=='=')
 | |
| 	    return XkbCF_PlusEquals;
 | |
| 	if ((ch!=EOF)&&(ch!=' ')&&(ch!='\t'))
 | |
| 	    ungetc(ch,file);
 | |
| 	return XkbCF_Plus;
 | |
|     }
 | |
|     else if (ch=='-') {
 | |
| 	ch= getc(file);
 | |
| 	if (ch=='=')
 | |
| 	    return XkbCF_MinusEquals;
 | |
| 	if ((ch!=EOF)&&(ch!=' ')&&(ch!='\t'))
 | |
| 	    ungetc(ch,file);
 | |
| 	return XkbCF_Minus;
 | |
|     }
 | |
|     else if (ch==EOF)
 | |
| 	return XkbCF_EOF;
 | |
|     else if ((ch=='#')||((ch=='/')&&(getc(file)=='/'))) {
 | |
| 	while ((ch!='\n')&&(ch!=EOF))
 | |
| 	    ch= getc(file);
 | |
| 	rtrn->line++;
 | |
| 	return XkbCF_EOL;
 | |
|     }
 | |
|     return XkbCF_Unknown;
 | |
| }
 | |
| 
 | |
| /***====================================================================***/
 | |
| 
 | |
| #define	_XkbCF_Illegal			0
 | |
| #define	_XkbCF_Keymap		 	1
 | |
| #define	_XkbCF_Keycodes		 	2
 | |
| #define	_XkbCF_Geometry		 	3
 | |
| #define	_XkbCF_PhysSymbols	 	4
 | |
| #define _XkbCF_Symbols		 	5
 | |
| #define	_XkbCF_Types		 	6
 | |
| #define	_XkbCF_CompatMap	 	7
 | |
| 
 | |
| #define	_XkbCF_RulesFile		8
 | |
| #define	_XkbCF_Model			9
 | |
| #define	_XkbCF_Layout			10
 | |
| #define	_XkbCF_Variant			11
 | |
| #define	_XkbCF_Options			12
 | |
| 	
 | |
| #define	_XkbCF_InitialMods	 	13
 | |
| #define	_XkbCF_InitialCtrls	 	14
 | |
| 
 | |
| #define	_XkbCF_ClickVolume	 	15
 | |
| #define	_XkbCF_BellVolume	 	16
 | |
| #define	_XkbCF_BellPitch	 	17
 | |
| #define	_XkbCF_BellDuration	 	18
 | |
| #define	_XkbCF_RepeatDelay	 	19
 | |
| #define	_XkbCF_RepeatInterval	 	20
 | |
| #define	_XkbCF_SlowKeysDelay	 	21
 | |
| #define	_XkbCF_DebounceDelay		22
 | |
| #define	_XkbCF_MouseKeysDelay		23
 | |
| #define	_XkbCF_MouseKeysInterval	24
 | |
| #define	_XkbCF_MouseKeysTimeToMax	25
 | |
| #define	_XkbCF_MouseKeysMaxSpeed	26
 | |
| #define	_XkbCF_MouseKeysCurve		27
 | |
| #define	_XkbCF_AccessXTimeout		28
 | |
| #define	_XkbCF_AccessXTimeoutCtrlsOn	29
 | |
| #define	_XkbCF_AccessXTimeoutCtrlsOff	30
 | |
| #define	_XkbCF_AccessXTimeoutOptsOn	31
 | |
| #define	_XkbCF_AccessXTimeoutOptsOff	32
 | |
| 
 | |
| #define	_XkbCF_IgnoreLockMods		33
 | |
| #define	_XkbCF_IgnoreGroupLock		34
 | |
| #define	_XkbCF_InternalMods		35
 | |
| 
 | |
| #define	_XkbCF_GroupsWrap		36
 | |
| #define	_XkbCF_InitialFeedback		37
 | |
| 
 | |
| static Bool
 | |
| AddCtrlByName(XkbConfigRtrnPtr rtrn,char *name,unsigned long *ctrls_rtrn)
 | |
| {
 | |
|     if ((_XkbStrCaseCmp(name,"repeat")==0)||
 | |
| 	(_XkbStrCaseCmp(name,"repeatkeys")==0))
 | |
| 	*ctrls_rtrn= XkbRepeatKeysMask;
 | |
|     else if (_XkbStrCaseCmp(name,"slowkeys")==0)
 | |
| 	*ctrls_rtrn= XkbSlowKeysMask;
 | |
|     else if (_XkbStrCaseCmp(name,"bouncekeys")==0)
 | |
| 	*ctrls_rtrn= XkbBounceKeysMask;
 | |
|     else if (_XkbStrCaseCmp(name,"stickykeys")==0)
 | |
| 	*ctrls_rtrn= XkbStickyKeysMask;
 | |
|     else if (_XkbStrCaseCmp(name,"mousekeys")==0)
 | |
| 	*ctrls_rtrn= XkbMouseKeysMask;
 | |
|     else if (_XkbStrCaseCmp(name,"mousekeysaccel")==0)
 | |
| 	*ctrls_rtrn= XkbMouseKeysAccelMask;
 | |
|     else if (_XkbStrCaseCmp(name,"accessxkeys")==0)
 | |
| 	*ctrls_rtrn= XkbAccessXKeysMask;
 | |
|     else if (_XkbStrCaseCmp(name,"accessxtimeout")==0)
 | |
| 	*ctrls_rtrn= XkbAccessXTimeoutMask;
 | |
|     else if (_XkbStrCaseCmp(name,"accessxfeedback")==0)
 | |
| 	*ctrls_rtrn= XkbAccessXFeedbackMask;
 | |
|     else if (_XkbStrCaseCmp(name,"audiblebell")==0)
 | |
| 	*ctrls_rtrn= XkbAudibleBellMask;
 | |
|     else if (_XkbStrCaseCmp(name,"overlay1")==0)
 | |
| 	*ctrls_rtrn= XkbOverlay1Mask;
 | |
|     else if (_XkbStrCaseCmp(name,"overlay2")==0)
 | |
| 	*ctrls_rtrn= XkbOverlay2Mask;
 | |
|     else if (_XkbStrCaseCmp(name,"ignoregrouplock")==0)
 | |
| 	*ctrls_rtrn= XkbIgnoreGroupLockMask;
 | |
|     else {
 | |
| 	rtrn->error= XkbCF_ExpectedControl;
 | |
| 	return False;
 | |
|     }
 | |
|     return True;
 | |
| }
 | |
| 
 | |
| static Bool
 | |
| AddAXTimeoutOptByName(	XkbConfigRtrnPtr	rtrn,
 | |
| 			char *			name,
 | |
| 			unsigned short *	opts_rtrn)
 | |
| {
 | |
|     if (_XkbStrCaseCmp(name,"slowkeyspress")==0)
 | |
| 	*opts_rtrn= XkbAX_SKPressFBMask;
 | |
|     else if (_XkbStrCaseCmp(name,"slowkeysaccept")==0)
 | |
| 	*opts_rtrn= XkbAX_SKAcceptFBMask;
 | |
|     else if (_XkbStrCaseCmp(name,"feature")==0)
 | |
| 	*opts_rtrn= XkbAX_FeatureFBMask;
 | |
|     else if (_XkbStrCaseCmp(name,"slowwarn")==0)
 | |
| 	*opts_rtrn= XkbAX_SlowWarnFBMask;
 | |
|     else if (_XkbStrCaseCmp(name,"indicator")==0)
 | |
| 	*opts_rtrn= XkbAX_IndicatorFBMask;
 | |
|     else if (_XkbStrCaseCmp(name,"stickykeys")==0)
 | |
| 	*opts_rtrn= XkbAX_StickyKeysFBMask;
 | |
|     else if (_XkbStrCaseCmp(name,"twokeys")==0)
 | |
| 	*opts_rtrn= XkbAX_TwoKeysMask;
 | |
|     else if (_XkbStrCaseCmp(name,"latchtolock")==0)
 | |
| 	*opts_rtrn= XkbAX_LatchToLockMask;
 | |
|     else if (_XkbStrCaseCmp(name,"slowkeysrelease")==0)
 | |
| 	*opts_rtrn= XkbAX_SKReleaseFBMask;
 | |
|     else if (_XkbStrCaseCmp(name,"slowkeysreject")==0)
 | |
| 	*opts_rtrn= XkbAX_SKRejectFBMask;
 | |
|     else if (_XkbStrCaseCmp(name,"bouncekeysreject")==0)
 | |
| 	*opts_rtrn= XkbAX_BKRejectFBMask;
 | |
|     else if (_XkbStrCaseCmp(name,"dumbbell")==0)
 | |
| 	*opts_rtrn= XkbAX_DumbBellFBMask;
 | |
|     else {
 | |
| 	rtrn->error= XkbCF_ExpectedControl;
 | |
| 	return False;
 | |
|     }
 | |
|     return True;
 | |
| }
 | |
| 
 | |
| XkbConfigUnboundModPtr
 | |
| XkbCFAddModByName(	XkbConfigRtrnPtr	rtrn,
 | |
| 			int			what,
 | |
| 			char *			name,
 | |
| 			Bool			merge,
 | |
| 			XkbConfigUnboundModPtr	last)
 | |
| {
 | |
|     if (rtrn->num_unbound_mods>=rtrn->sz_unbound_mods) {
 | |
| 	rtrn->sz_unbound_mods+= 5;
 | |
| 	rtrn->unbound_mods= _XkbTypedRealloc(rtrn->unbound_mods,
 | |
| 						  rtrn->sz_unbound_mods,
 | |
| 						  XkbConfigUnboundModRec);
 | |
| 	if (rtrn->unbound_mods==NULL) {
 | |
| 	    rtrn->error= XkbCF_BadAlloc;
 | |
| 	    return False;
 | |
| 	}
 | |
|     }
 | |
|     if (last==NULL) {
 | |
| 	last= &rtrn->unbound_mods[rtrn->num_unbound_mods++];
 | |
| 	last->what= what;
 | |
| 	last->mods= 0;
 | |
| 	last->vmods= 0;
 | |
| 	last->merge= merge;
 | |
| 	last->name= NULL;
 | |
|     }
 | |
|     if (_XkbStrCaseCmp(name,"shift")==0)
 | |
| 	last->mods|= ShiftMask;
 | |
|     else if (_XkbStrCaseCmp(name,"lock")==0)
 | |
| 	last->mods|= LockMask;
 | |
|     else if ((_XkbStrCaseCmp(name,"control")==0)||
 | |
| 		(_XkbStrCaseCmp(name,"ctrl")==0))
 | |
| 	last->mods|= ControlMask;
 | |
|     else if (_XkbStrCaseCmp(name,"mod1")==0)
 | |
| 	last->mods|= Mod1Mask;
 | |
|     else if (_XkbStrCaseCmp(name,"mod2")==0)
 | |
| 	last->mods|= Mod2Mask;
 | |
|     else if (_XkbStrCaseCmp(name,"mod3")==0)
 | |
| 	last->mods|= Mod3Mask;
 | |
|     else if (_XkbStrCaseCmp(name,"mod4")==0)
 | |
| 	last->mods|= Mod4Mask;
 | |
|     else if (_XkbStrCaseCmp(name,"mod5")==0)
 | |
| 	last->mods|= Mod5Mask;
 | |
|     else {
 | |
| 	if (last->name!=NULL) {
 | |
| 	    last= &rtrn->unbound_mods[rtrn->num_unbound_mods++];
 | |
| 	    last->what= what;
 | |
| 	    last->mods= 0;
 | |
| 	    last->vmods= 0;
 | |
| 	    last->merge= merge;
 | |
| 	    last->name= NULL;
 | |
| 	}
 | |
| 	last->name= _XkbDupString(name);
 | |
|     }
 | |
|     return last;
 | |
| }
 | |
| 
 | |
| int
 | |
| XkbCFBindMods(XkbConfigRtrnPtr rtrn,XkbDescPtr xkb)
 | |
| {
 | |
| register int 		n,v;
 | |
| Atom			name;
 | |
| XkbConfigUnboundModPtr	mod;
 | |
| int			missing;
 | |
| 
 | |
|     if (rtrn->num_unbound_mods<1)
 | |
| 	return 0;
 | |
|     if ((xkb==NULL) || (xkb->names==NULL))
 | |
| 	return -1;
 | |
| 
 | |
|     missing= 0;
 | |
|     for (n=0,mod=rtrn->unbound_mods;n<rtrn->num_unbound_mods;n++,mod++) {
 | |
| 	if (mod->name!=NULL) {
 | |
| 	    name= XkbInternAtom(xkb->dpy,mod->name,True);
 | |
| 	    if (name==None)
 | |
| 		continue;
 | |
| 	    for (v=0;v<XkbNumVirtualMods;v++) {
 | |
| 		if (xkb->names->vmods[v]==name) {
 | |
| 		    mod->vmods= (1<<v);
 | |
| 		    _XkbFree(mod->name);
 | |
| 		    mod->name= NULL;
 | |
| 		    break;
 | |
| 		}
 | |
| 	    }
 | |
| 	    if (mod->name!=NULL)
 | |
| 		missing++;
 | |
| 	}
 | |
|     }
 | |
|     return missing;
 | |
| }
 | |
| 
 | |
| Bool
 | |
| XkbCFApplyMods(XkbConfigRtrnPtr rtrn,int what,XkbConfigModInfoPtr info)
 | |
| {
 | |
| register int 		n;
 | |
| XkbConfigUnboundModPtr	mod;
 | |
| 
 | |
|     if (rtrn->num_unbound_mods<1)
 | |
| 	return True;
 | |
| 
 | |
|     for (n=0,mod=rtrn->unbound_mods;n<rtrn->num_unbound_mods;n++,mod++) {
 | |
| 	if (mod->what!=what)
 | |
| 	    continue;
 | |
|  	if (mod->merge==XkbCF_MergeRemove) {
 | |
| 	    info->mods_clear|= mod->mods;
 | |
| 	    info->vmods_clear|= mod->vmods;
 | |
| 	}
 | |
| 	else {
 | |
| 	    if (mod->merge==XkbCF_MergeSet)
 | |
| 		info->replace= True;
 | |
| 	    info->mods|= mod->mods;
 | |
| 	    info->vmods|= mod->vmods;
 | |
| 	}
 | |
| 	if (mod->name==NULL) {
 | |
| 	    mod->what= _XkbCF_Illegal;
 | |
| 	}
 | |
| 	else {
 | |
| 	    mod->mods= 0;
 | |
| 	    mod->vmods= 0;
 | |
| 	}
 | |
|     }
 | |
|     return True;
 | |
| }
 | |
| 
 | |
| /*ARGSUSED*/
 | |
| static Bool
 | |
| DefaultParser(	FILE *			file,
 | |
| 		XkbConfigFieldsPtr	fields,
 | |
| 		XkbConfigFieldPtr	field,
 | |
| 		XkbDescPtr		xkb,
 | |
| 		XkbConfigRtrnPtr	rtrn)
 | |
| {
 | |
| int			tok;
 | |
| XkbCFScanResultRec	val;
 | |
| char **			str;
 | |
| int			merge;
 | |
| unsigned long *		ctrls, ctrls_mask;
 | |
| unsigned short *	opts, opts_mask;
 | |
| int *			pival, sign;
 | |
| int			onoff;
 | |
| XkbConfigUnboundModPtr	last;
 | |
| unsigned		what;
 | |
| 
 | |
|     tok= XkbCFScan(file,&val,rtrn);
 | |
|     str= NULL;
 | |
|     onoff= 0;
 | |
|     pival= NULL;
 | |
|     switch (field->field_id) {
 | |
| 	case _XkbCF_RulesFile:	if (!str)	str= &rtrn->rules_file;
 | |
| 	case _XkbCF_Model:	if (!str)	str= &rtrn->model;
 | |
| 	case _XkbCF_Layout:	if (!str)	str= &rtrn->layout;
 | |
| 	case _XkbCF_Variant:	if (!str)	str= &rtrn->variant;
 | |
| 	case _XkbCF_Options:	if (!str)	str= &rtrn->options;
 | |
| 	case _XkbCF_Keymap: 	if (!str)	str= &rtrn->keymap;
 | |
| 	case _XkbCF_Keycodes: 	if (!str)	str= &rtrn->keycodes;
 | |
| 	case _XkbCF_Geometry: 	if (!str)	str= &rtrn->geometry;
 | |
| 	case _XkbCF_PhysSymbols:if (!str)	str= &rtrn->phys_symbols;
 | |
| 	case _XkbCF_Symbols: 	if (!str)	str= &rtrn->symbols;
 | |
| 	case _XkbCF_Types: 	if (!str)	str= &rtrn->types;
 | |
| 	case _XkbCF_CompatMap:	if (!str)	str= &rtrn->compat;
 | |
| 	    if (tok!=XkbCF_Equals) {
 | |
| 		rtrn->error= XkbCF_MissingEquals;
 | |
| 		goto BAILOUT;
 | |
| 	    }
 | |
| 	    tok= XkbCFScan(file,&val,rtrn);
 | |
| 	    if ((tok!=XkbCF_String)&&(tok!=XkbCF_Ident)) {
 | |
| 		rtrn->error= XkbCF_ExpectedString;
 | |
| 		return False;
 | |
| 	    }
 | |
| 	    tok= XkbCFScan(file,&val,rtrn);
 | |
| 	    if ((tok!=XkbCF_EOL)&&(tok!=XkbCF_Semi)&&(tok!=XkbCF_EOF)) {
 | |
| 		rtrn->error= XkbCF_ExpectedEOS;
 | |
| 		return False;
 | |
| 	    }
 | |
| 	    if (*str!=NULL)
 | |
| 		_XkbFree(*str);
 | |
| 	    *str= _XkbDupString(val.str);
 | |
| 	    break;
 | |
| 	case _XkbCF_InitialMods:
 | |
| 	case _XkbCF_IgnoreLockMods:
 | |
| 	case _XkbCF_InternalMods:
 | |
| 	    what= XkbCF_InitialMods;
 | |
| 	    if (field->field_id==_XkbCF_InitialMods)
 | |
| 		rtrn->defined|= (what=XkbCF_InitialMods);
 | |
| 	    else if (field->field_id==_XkbCF_InternalMods)
 | |
| 		rtrn->defined|= (what=XkbCF_InternalMods);
 | |
| 	    else if (field->field_id==_XkbCF_IgnoreLockMods)
 | |
| 		rtrn->defined|= (what=XkbCF_IgnoreLockMods);
 | |
| 	    if (tok==XkbCF_Equals)		merge= XkbCF_MergeSet;
 | |
| 	    else if (tok==XkbCF_MinusEquals)	merge= XkbCF_MergeRemove;
 | |
| 	    else if (tok==XkbCF_PlusEquals)	merge= XkbCF_MergeAdd;
 | |
| 	    else {
 | |
| 		rtrn->error= XkbCF_MissingEquals;
 | |
| 		goto BAILOUT;
 | |
| 	    }
 | |
| 	    tok= XkbCFScan(file,&val,rtrn);
 | |
| 	    if ((tok==XkbCF_EOL)||(tok==XkbCF_Semi)||(tok==XkbCF_EOF)) {
 | |
| 		rtrn->error= XkbCF_ExpectedModifier;
 | |
| 		return False;
 | |
| 	    }
 | |
| 	    last= NULL;
 | |
| 	    while ((tok!=XkbCF_EOL)&&(tok!=XkbCF_Semi)&&(tok!=XkbCF_EOF)) {
 | |
| 		if ((tok!=XkbCF_Ident)&&(tok!=XkbCF_String)) {
 | |
| 		    rtrn->error= XkbCF_ExpectedModifier;
 | |
| 		    return False;
 | |
| 		}
 | |
| 		last=XkbCFAddModByName(rtrn,what,val.str,merge,last);
 | |
| 		if (last==NULL)
 | |
| 		    return False;
 | |
| 		if (merge==XkbCF_MergeSet)
 | |
| 		    merge= XkbCF_MergeAdd;
 | |
| 		tok= XkbCFScan(file,&val,rtrn);
 | |
| 		if ((tok!=XkbCF_EOL)&&(tok!=XkbCF_EOF)&&(tok!=XkbCF_Semi)) {
 | |
| 		    if (tok!=XkbCF_Plus) {
 | |
| 			rtrn->error= XkbCF_ExpectedOperator;
 | |
| 			return False;
 | |
| 		    }
 | |
| 		    tok= XkbCFScan(file,&val,rtrn);
 | |
| 		}
 | |
| 	    }
 | |
| 	    break;
 | |
| 	case _XkbCF_InitialCtrls:
 | |
| 	    rtrn->defined|= XkbCF_InitialCtrls;
 | |
| 	    ctrls= NULL;
 | |
| 	    if (tok==XkbCF_PlusEquals)
 | |
| 		ctrls= &rtrn->initial_ctrls;
 | |
| 	    else if (tok==XkbCF_MinusEquals)
 | |
| 		ctrls= &rtrn->initial_ctrls_clear;
 | |
| 	    else if (tok==XkbCF_Equals) {
 | |
| 		ctrls= &rtrn->initial_ctrls;
 | |
| 		rtrn->replace_initial_ctrls= True;
 | |
| 		*ctrls= 0;
 | |
| 	    }
 | |
| 	    else {
 | |
| 		rtrn->error= XkbCF_MissingEquals;
 | |
| 		goto BAILOUT;
 | |
| 	    }
 | |
| 	    tok= XkbCFScan(file,&val,rtrn);
 | |
| 	    if ((tok==XkbCF_EOL)||(tok==XkbCF_Semi)||(tok==XkbCF_EOF)) {
 | |
| 		rtrn->error= XkbCF_ExpectedControl;
 | |
| 		return False;
 | |
| 	    }
 | |
| 	    while ((tok!=XkbCF_EOL)&&(tok!=XkbCF_Semi)&&(tok!=XkbCF_EOF)) {
 | |
| 		if ((tok!=XkbCF_Ident)&&(tok!=XkbCF_String)) {
 | |
| 		    rtrn->error= XkbCF_ExpectedControl;
 | |
| 		    return False;
 | |
| 		}
 | |
| 		if (!AddCtrlByName(rtrn,val.str,&ctrls_mask)) {
 | |
| 		    return False;
 | |
| 		}
 | |
| 		*ctrls |= ctrls_mask;
 | |
| 		tok= XkbCFScan(file,&val,rtrn);
 | |
| 		if ((tok!=XkbCF_EOL)&&(tok!=XkbCF_EOF)&&(tok!=XkbCF_Semi)) {
 | |
| 		    if (tok!=XkbCF_Plus) {
 | |
| 			rtrn->error= XkbCF_ExpectedOperator;
 | |
| 			return False;
 | |
| 		    }
 | |
| 		    tok= XkbCFScan(file,&val,rtrn);
 | |
| 		}
 | |
| 	    }
 | |
| 	    break;
 | |
| 	case _XkbCF_AccessXTimeoutCtrlsOn:
 | |
| 	case _XkbCF_AccessXTimeoutCtrlsOff:
 | |
| 	    opts= NULL;
 | |
| 	    if (tok==XkbCF_MinusEquals) {
 | |
| 		ctrls= &rtrn->axt_ctrls_ignore;
 | |
| 		opts= &rtrn->axt_opts_ignore;
 | |
| 	    }
 | |
| 	    else if ((tok==XkbCF_PlusEquals)||(tok==XkbCF_Equals)) {
 | |
| 		if (field->field_id==_XkbCF_AccessXTimeoutCtrlsOff) {
 | |
| 		    ctrls= &rtrn->axt_ctrls_off;
 | |
| 		    opts= &rtrn->axt_opts_off;
 | |
| 		    if (tok==XkbCF_Equals)
 | |
| 			rtrn->replace_axt_ctrls_off= True;
 | |
| 		}
 | |
| 		else {
 | |
| 		    ctrls= &rtrn->axt_ctrls_on;
 | |
| 		    opts= &rtrn->axt_opts_on;
 | |
| 		    if (tok==XkbCF_Equals)
 | |
| 			rtrn->replace_axt_ctrls_on= True;
 | |
| 		}
 | |
| 		*ctrls= 0;
 | |
| 	    }
 | |
| 	    else {
 | |
| 		rtrn->error= XkbCF_MissingEquals;
 | |
| 		goto BAILOUT;
 | |
| 	    }
 | |
| 	    tok= XkbCFScan(file,&val,rtrn);
 | |
| 	    if ((tok==XkbCF_EOL)||(tok==XkbCF_Semi)||(tok==XkbCF_EOF)) {
 | |
| 		rtrn->error= XkbCF_ExpectedControl;
 | |
| 		return False;
 | |
| 	    }
 | |
| 	    while ((tok!=XkbCF_EOL)&&(tok!=XkbCF_Semi)&&(tok!=XkbCF_EOF)) {
 | |
| 		if ((tok!=XkbCF_Ident)&&(tok!=XkbCF_String)) {
 | |
| 		    rtrn->error= XkbCF_ExpectedControl;
 | |
| 		    return False;
 | |
| 		}
 | |
| 		if (!AddCtrlByName(rtrn,val.str,&ctrls_mask)) {
 | |
| 		    if (!AddAXTimeoutOptByName(rtrn,val.str,&opts_mask))
 | |
| 			return False;
 | |
| 		    *opts |= opts_mask;
 | |
| 		    if (field->field_id==_XkbCF_AccessXTimeoutCtrlsOff) {
 | |
| 			rtrn->defined|= XkbCF_AccessXTimeoutOptsOff;
 | |
| 			if (rtrn->replace_axt_ctrls_off)
 | |
| 			    rtrn->replace_axt_opts_off= True;
 | |
| 		    }
 | |
| 		    else {
 | |
| 			rtrn->defined|= XkbCF_AccessXTimeoutOptsOn;
 | |
| 			if (rtrn->replace_axt_ctrls_on)
 | |
| 			    rtrn->replace_axt_opts_on= True;
 | |
| 		    }
 | |
| 		}
 | |
| 		else
 | |
| 		    *ctrls |= ctrls_mask;
 | |
| 		tok= XkbCFScan(file,&val,rtrn);
 | |
| 		if ((tok!=XkbCF_EOL)&&(tok!=XkbCF_EOF)&&(tok!=XkbCF_Semi)) {
 | |
| 		    if (tok!=XkbCF_Plus) {
 | |
| 			rtrn->error= XkbCF_ExpectedOperator;
 | |
| 			return False;
 | |
| 		    }
 | |
| 		    tok= XkbCFScan(file,&val,rtrn);
 | |
| 		}
 | |
| 	    }
 | |
| 	    break;
 | |
| 	case _XkbCF_InitialFeedback:
 | |
| 	    rtrn->defined|= XkbCF_InitialOpts;
 | |
| 	    opts= NULL;
 | |
| 	    if (tok==XkbCF_PlusEquals)
 | |
| 		opts= &rtrn->initial_opts;
 | |
| 	    else if (tok==XkbCF_MinusEquals)
 | |
| 		opts= &rtrn->initial_opts_clear;
 | |
| 	    else if (tok==XkbCF_Equals) {
 | |
| 		opts= &rtrn->initial_opts;
 | |
| 		rtrn->replace_initial_opts= True;
 | |
| 		*opts= 0;
 | |
| 	    }
 | |
| 	    else {
 | |
| 		rtrn->error= XkbCF_MissingEquals;
 | |
| 		goto BAILOUT;
 | |
| 	    }
 | |
| 	    tok= XkbCFScan(file,&val,rtrn);
 | |
| 	    if ((tok==XkbCF_EOL)||(tok==XkbCF_Semi)||(tok==XkbCF_EOF)) {
 | |
| 		rtrn->error= XkbCF_ExpectedAXOption;
 | |
| 		return False;
 | |
| 	    }
 | |
| 	    while ((tok!=XkbCF_EOL)&&(tok!=XkbCF_Semi)&&(tok!=XkbCF_EOF)) {
 | |
| 		if ((tok!=XkbCF_Ident)&&(tok!=XkbCF_String)) {
 | |
| 		    rtrn->error= XkbCF_ExpectedAXOption;
 | |
| 		    return False;
 | |
| 		}
 | |
| 		if (!AddAXTimeoutOptByName(rtrn,val.str,&opts_mask)) {
 | |
| 		    return False;
 | |
| 		}
 | |
| 		*opts |= opts_mask;
 | |
| 		tok= XkbCFScan(file,&val,rtrn);
 | |
| 		if ((tok!=XkbCF_EOL)&&(tok!=XkbCF_EOF)&&(tok!=XkbCF_Semi)) {
 | |
| 		    if (tok!=XkbCF_Plus) {
 | |
| 			rtrn->error= XkbCF_ExpectedOperator;
 | |
| 			return False;
 | |
| 		    }
 | |
| 		    tok= XkbCFScan(file,&val,rtrn);
 | |
| 		}
 | |
| 	    }
 | |
| 	    break;
 | |
| 	case _XkbCF_AccessXTimeoutOptsOff:
 | |
| 	case _XkbCF_AccessXTimeoutOptsOn:
 | |
| 	    opts= NULL;
 | |
| 	    if (tok==XkbCF_MinusEquals)
 | |
| 		opts= &rtrn->axt_opts_ignore;
 | |
| 	    else if ((tok==XkbCF_PlusEquals)||(tok==XkbCF_Equals)) {
 | |
| 		if (field->field_id==_XkbCF_AccessXTimeoutOptsOff) {
 | |
| 		    opts= &rtrn->axt_opts_off;
 | |
| 		    if (tok==XkbCF_Equals)
 | |
| 			rtrn->replace_axt_opts_off= True;
 | |
| 		}
 | |
| 		else {
 | |
| 		    opts= &rtrn->axt_opts_on;
 | |
| 		    if (tok==XkbCF_Equals)
 | |
| 			rtrn->replace_axt_opts_on= True;
 | |
| 		}
 | |
| 		*opts = 0;
 | |
| 	    }
 | |
| 	    else {
 | |
| 		rtrn->error= XkbCF_MissingEquals;
 | |
| 		goto BAILOUT;
 | |
| 	    }
 | |
| 	    tok= XkbCFScan(file,&val,rtrn);
 | |
| 	    if ((tok==XkbCF_EOL)||(tok==XkbCF_Semi)||(tok==XkbCF_EOF)) {
 | |
| 		rtrn->error= XkbCF_ExpectedControl;
 | |
| 		return False;
 | |
| 	    }
 | |
| 	    while ((tok!=XkbCF_EOL)&&(tok!=XkbCF_Semi)&&(tok!=XkbCF_EOF)) {
 | |
| 		if ((tok!=XkbCF_Ident)&&(tok!=XkbCF_String)) {
 | |
| 		    rtrn->error= XkbCF_ExpectedControl;
 | |
| 		    return False;
 | |
| 		}
 | |
| 		if (!AddAXTimeoutOptByName(rtrn,val.str,&opts_mask))
 | |
| 		    return False;
 | |
| 		*opts |= opts_mask;
 | |
| 
 | |
| 		tok= XkbCFScan(file,&val,rtrn);
 | |
| 		if ((tok!=XkbCF_EOL)&&(tok!=XkbCF_EOF)&&(tok!=XkbCF_Semi)) {
 | |
| 		    if (tok!=XkbCF_Plus) {
 | |
| 			rtrn->error= XkbCF_ExpectedOperator;
 | |
| 			return False;
 | |
| 		    }
 | |
| 		    tok= XkbCFScan(file,&val,rtrn);
 | |
| 		}
 | |
| 	    }
 | |
| 	    break;
 | |
| 	case _XkbCF_ClickVolume:	
 | |
| 	    if (!pival) {
 | |
| 		pival= &rtrn->click_volume;
 | |
| 		onoff= 100;
 | |
| 	    }
 | |
| 	case _XkbCF_BellVolume:
 | |
| 	    if (!pival) {
 | |
| 		pival= &rtrn->bell_volume;
 | |
| 		onoff= 100;
 | |
| 	    }
 | |
| 	case _XkbCF_BellPitch:
 | |
| 	    if (!pival)
 | |
| 		pival= &rtrn->bell_pitch;
 | |
| 	case _XkbCF_BellDuration:
 | |
| 	    if (!pival)
 | |
| 		pival= &rtrn->bell_duration;
 | |
| 	case _XkbCF_RepeatDelay:
 | |
| 	    if (!pival)
 | |
| 		pival= &rtrn->repeat_delay;
 | |
| 	case _XkbCF_RepeatInterval:
 | |
| 	    if (!pival) 
 | |
| 		pival= &rtrn->repeat_interval;
 | |
| 	case _XkbCF_SlowKeysDelay:
 | |
| 	    if (!pival) 
 | |
| 		pival= &rtrn->slow_keys_delay;
 | |
| 	case _XkbCF_DebounceDelay:
 | |
| 	    if (!pival) 
 | |
| 		pival= &rtrn->debounce_delay;
 | |
| 	case _XkbCF_MouseKeysDelay:
 | |
| 	    if (!pival) 
 | |
| 		pival= &rtrn->mk_delay;
 | |
| 	case _XkbCF_MouseKeysInterval:
 | |
| 	    if (!pival) 
 | |
| 		pival= &rtrn->mk_interval;
 | |
| 	case _XkbCF_MouseKeysTimeToMax:
 | |
| 	    if (!pival) 
 | |
| 		pival= &rtrn->mk_time_to_max;
 | |
| 	case _XkbCF_MouseKeysMaxSpeed:
 | |
| 	    if (!pival) 
 | |
| 		pival= &rtrn->mk_max_speed;
 | |
| 	case _XkbCF_MouseKeysCurve:
 | |
| 	    if (!pival) 
 | |
| 		pival= &rtrn->mk_curve;
 | |
| 	case _XkbCF_AccessXTimeout:
 | |
| 	    if (!pival) 
 | |
| 		pival= &rtrn->ax_timeout;
 | |
| 	    if (tok!=XkbCF_Equals) {
 | |
| 		rtrn->error= XkbCF_MissingEquals;
 | |
| 		goto BAILOUT;
 | |
| 	    }
 | |
| 	    tok= XkbCFScan(file,&val,rtrn);
 | |
| 	    if (tok == XkbCF_Minus && field->field_id == _XkbCF_MouseKeysCurve) {
 | |
| 		/* This can be a negative value */
 | |
| 		tok = XkbCFScan(file,&val,rtrn);
 | |
| 		sign = -1;
 | |
| 	    }
 | |
| 	    else
 | |
| 		sign = 1;
 | |
| 	    if (tok!=XkbCF_Integer) {
 | |
| 		Bool ok= False;
 | |
| 		if ((onoff)&&(tok==XkbCF_Ident)&&(val.str!=NULL)) {
 | |
| 		    if (_XkbStrCaseCmp(val.str,"on")) {
 | |
| 			val.ival= onoff;
 | |
| 			ok= True;
 | |
| 		    }
 | |
| 		    else if (_XkbStrCaseCmp(val.str,"off")) {
 | |
| 			val.ival= 0;
 | |
| 			ok= True;
 | |
| 		    }
 | |
| 		}
 | |
| 		if (!ok) {
 | |
| 		    rtrn->error= XkbCF_ExpectedInteger;
 | |
| 		    goto BAILOUT;
 | |
| 		}
 | |
| 	    }
 | |
| 	    *pival= val.ival * sign;
 | |
| 	    if (field->field_id == _XkbCF_AccessXTimeout)
 | |
| 	        rtrn->defined|=XkbCF_AccessXTimeout;
 | |
| 	    tok= XkbCFScan(file,&val,rtrn);
 | |
| 	    if ((tok!=XkbCF_EOL)&&(tok!=XkbCF_Semi)&&(tok!=XkbCF_EOF)) {
 | |
| 		rtrn->error= XkbCF_ExpectedEOS;
 | |
| 		return False;
 | |
| 	    }
 | |
| 	    break;
 | |
| 	case _XkbCF_GroupsWrap:
 | |
| 	    if (tok!=XkbCF_Equals) {
 | |
| 		rtrn->error= XkbCF_MissingEquals;
 | |
| 		goto BAILOUT;
 | |
| 	    }
 | |
| 	    tok= XkbCFScan(file,&val,rtrn);
 | |
| 	    if (tok==XkbCF_Ident) {
 | |
| 		if (_XkbStrCaseCmp(val.str,"wrap")==0) {
 | |
| 		    rtrn->groups_wrap= XkbSetGroupInfo(0,XkbWrapIntoRange,0);
 | |
| 		}
 | |
| 		else if (_XkbStrCaseCmp(val.str,"clamp")==0) {
 | |
| 		    rtrn->groups_wrap= XkbSetGroupInfo(0,XkbClampIntoRange,0);
 | |
| 		}
 | |
| 		else {
 | |
| 		    rtrn->error= XkbCF_ExpectedOORGroupBehavior;
 | |
| 		    return False;
 | |
| 		}
 | |
| 	    }
 | |
| 	    else if ((tok==XkbCF_Integer)&&(XkbIsLegalGroup(val.ival-1))) {
 | |
| 		rtrn->groups_wrap= XkbSetGroupInfo(0,XkbRedirectIntoRange,
 | |
| 								val.ival-1);
 | |
| 	    }
 | |
| 	    else {
 | |
| 		rtrn->error= XkbCF_ExpectedOORGroupBehavior;
 | |
| 		return False;
 | |
| 	    }
 | |
| 	    rtrn->defined|= XkbCF_GroupsWrap;
 | |
| 	    tok= XkbCFScan(file,&val,rtrn);
 | |
| 	    if ((tok!=XkbCF_EOL)&&(tok!=XkbCF_Semi)&&(tok!=XkbCF_EOF)) {
 | |
| 		rtrn->error= XkbCF_ExpectedEOS;
 | |
| 		return False;
 | |
| 	    }
 | |
| 	    break;
 | |
| 	default:
 | |
| 	    rtrn->error= XkbCF_ExpectedInteger;
 | |
| 	    goto BAILOUT;
 | |
| 	    
 | |
|     }
 | |
|     return True;
 | |
| BAILOUT:
 | |
|     return False;
 | |
| }
 | |
| 
 | |
| static Bool
 | |
| DefaultCleanUp(XkbConfigRtrnPtr rtrn)
 | |
| {
 | |
|     if (rtrn->keymap)	_XkbFree(rtrn->keymap);
 | |
|     if (rtrn->keycodes)	_XkbFree(rtrn->keycodes);
 | |
|     if (rtrn->geometry)	_XkbFree(rtrn->geometry);
 | |
|     if (rtrn->phys_symbols)	_XkbFree(rtrn->phys_symbols);
 | |
|     if (rtrn->symbols)	_XkbFree(rtrn->symbols);
 | |
|     if (rtrn->types)	_XkbFree(rtrn->types);
 | |
|     if (rtrn->compat)	_XkbFree(rtrn->compat);
 | |
|     rtrn->keycodes= rtrn->geometry= NULL;
 | |
|     rtrn->symbols= rtrn->phys_symbols= NULL;
 | |
|     rtrn->types= rtrn->compat= NULL;
 | |
|     if ((rtrn->unbound_mods!=NULL)&&(rtrn->num_unbound_mods>0)) {
 | |
| 	register int i;
 | |
| 	for (i=0;i<rtrn->num_unbound_mods;i++) {
 | |
| 	    if (rtrn->unbound_mods[i].name!=NULL) {
 | |
| 		_XkbFree(rtrn->unbound_mods[i].name);
 | |
| 		rtrn->unbound_mods[i].name= NULL;
 | |
| 	    }
 | |
| 	}
 | |
| 	_XkbFree(rtrn->unbound_mods);
 | |
| 	rtrn->sz_unbound_mods= 0;
 | |
| 	rtrn->num_unbound_mods= 0;
 | |
| 	rtrn->unbound_mods= NULL;
 | |
|     }
 | |
|     return True;
 | |
| }
 | |
| 
 | |
| static Bool
 | |
| DefaultApplyNames(XkbConfigRtrnPtr rtrn,XkbDescPtr xkb)
 | |
| {
 | |
| char *str;
 | |
| 
 | |
|     if (XkbAllocNames(xkb,XkbComponentNamesMask,0,0)!=Success)
 | |
| 	return False;
 | |
|     if ((str=rtrn->keycodes)!=NULL) {
 | |
| 	xkb->names->keycodes= XkbInternAtom(xkb->dpy,str,False);
 | |
| 	_XkbFree(str);
 | |
| 	rtrn->keycodes= NULL;
 | |
|     }
 | |
|     if ((str=rtrn->geometry)!=NULL) {
 | |
| 	xkb->names->geometry= XkbInternAtom(xkb->dpy,str,False);
 | |
| 	_XkbFree(str);
 | |
| 	rtrn->geometry= NULL;
 | |
|     }
 | |
|     if ((str=rtrn->symbols)!=NULL) {
 | |
| 	xkb->names->symbols= XkbInternAtom(xkb->dpy,str,False);
 | |
| 	_XkbFree(str);
 | |
| 	rtrn->symbols= NULL;
 | |
|     }
 | |
|     if ((str=rtrn->phys_symbols)!=NULL) {
 | |
| 	xkb->names->phys_symbols= XkbInternAtom(xkb->dpy,str,False);
 | |
| 	_XkbFree(str);
 | |
| 	rtrn->phys_symbols= NULL;
 | |
|     }
 | |
|     if ((str=rtrn->types)!=NULL) {
 | |
| 	xkb->names->types= XkbInternAtom(xkb->dpy,str,False);
 | |
| 	_XkbFree(str);
 | |
| 	rtrn->types= NULL;
 | |
|     }
 | |
|     if ((str=rtrn->compat)!=NULL) {
 | |
| 	xkb->names->compat= XkbInternAtom(xkb->dpy,str,False);
 | |
| 	_XkbFree(str);
 | |
| 	rtrn->compat= NULL;
 | |
|     }
 | |
|     return True;
 | |
| }
 | |
| 
 | |
| static Bool
 | |
| DefaultApplyControls(XkbConfigRtrnPtr rtrn,XkbDescPtr xkb)
 | |
| {
 | |
| unsigned	on,off;
 | |
| XkbControlsPtr	ctrls;
 | |
| unsigned int	mask;
 | |
| 
 | |
|     if (XkbAllocControls(xkb,XkbAllControlsMask)!=Success)
 | |
| 	return False;
 | |
|     ctrls= xkb->ctrls;
 | |
|     if (rtrn->replace_initial_ctrls)
 | |
| 	 ctrls->enabled_ctrls=  rtrn->initial_ctrls;
 | |
|     else ctrls->enabled_ctrls|= rtrn->initial_ctrls;
 | |
|     ctrls->enabled_ctrls&= ~rtrn->initial_ctrls_clear;
 | |
|     if (rtrn->internal_mods.replace) {
 | |
| 	ctrls->internal.real_mods= rtrn->internal_mods.mods;
 | |
| 	ctrls->internal.vmods= rtrn->internal_mods.vmods;
 | |
|     }
 | |
|     else {
 | |
| 	ctrls->internal.real_mods&= ~rtrn->internal_mods.mods_clear;
 | |
| 	ctrls->internal.vmods&= ~rtrn->internal_mods.vmods_clear;
 | |
| 	ctrls->internal.real_mods|= rtrn->internal_mods.mods;
 | |
| 	ctrls->internal.vmods|= rtrn->internal_mods.vmods;
 | |
|     }
 | |
|     mask= 0;
 | |
|     (void)XkbVirtualModsToReal(xkb,ctrls->internal.vmods,&mask);
 | |
|     ctrls->internal.mask= (ctrls->internal.real_mods|mask);
 | |
| 
 | |
|     if (rtrn->ignore_lock_mods.replace) {
 | |
| 	ctrls->ignore_lock.real_mods= rtrn->ignore_lock_mods.mods;
 | |
| 	ctrls->ignore_lock.vmods= rtrn->ignore_lock_mods.vmods;
 | |
|     }
 | |
|     else {
 | |
| 	ctrls->ignore_lock.real_mods&= ~rtrn->ignore_lock_mods.mods_clear;
 | |
| 	ctrls->ignore_lock.vmods&= ~rtrn->ignore_lock_mods.vmods_clear;
 | |
| 	ctrls->ignore_lock.real_mods|= rtrn->ignore_lock_mods.mods;
 | |
| 	ctrls->ignore_lock.vmods|= rtrn->ignore_lock_mods.vmods;
 | |
|     }
 | |
|     mask= 0;
 | |
|     (void)XkbVirtualModsToReal(xkb,ctrls->ignore_lock.vmods,&mask);
 | |
|     ctrls->ignore_lock.mask= (ctrls->ignore_lock.real_mods|mask);
 | |
| 
 | |
|     if (rtrn->repeat_delay>0)
 | |
| 	ctrls->repeat_delay= rtrn->repeat_delay;
 | |
|     if (rtrn->repeat_interval>0)
 | |
| 	ctrls->repeat_interval= rtrn->repeat_interval;
 | |
|     if (rtrn->slow_keys_delay>0)
 | |
| 	ctrls->slow_keys_delay= rtrn->slow_keys_delay;
 | |
|     if (rtrn->debounce_delay>0)
 | |
| 	ctrls->debounce_delay= rtrn->debounce_delay;
 | |
|     if (rtrn->mk_delay>0)
 | |
| 	ctrls->mk_delay= rtrn->mk_delay;
 | |
|     if (rtrn->mk_interval>0)
 | |
| 	ctrls->mk_interval= rtrn->mk_interval;
 | |
|     if (rtrn->mk_time_to_max>0)
 | |
| 	ctrls->mk_time_to_max= rtrn->mk_time_to_max;
 | |
|     if (rtrn->mk_max_speed>0)
 | |
| 	ctrls->mk_max_speed= rtrn->mk_max_speed;
 | |
|     if (rtrn->mk_curve>0)
 | |
| 	ctrls->mk_curve= rtrn->mk_curve;
 | |
|     if (rtrn->defined&XkbCF_AccessXTimeout && rtrn->ax_timeout > 0)
 | |
| 	ctrls->ax_timeout= rtrn->ax_timeout;
 | |
| 
 | |
|     /* any value set to both off and on is reset to ignore */
 | |
|     if ((off=(rtrn->axt_ctrls_on&rtrn->axt_ctrls_off))!=0)
 | |
| 	rtrn->axt_ctrls_ignore|= off;
 | |
| 
 | |
|     /* ignore takes priority over on and off */
 | |
|     rtrn->axt_ctrls_on&= ~rtrn->axt_ctrls_ignore;
 | |
|     rtrn->axt_ctrls_off&= ~rtrn->axt_ctrls_ignore;
 | |
| 
 | |
|     if (!rtrn->replace_axt_ctrls_off) {
 | |
| 	 off= (ctrls->axt_ctrls_mask&(~ctrls->axt_ctrls_values));
 | |
| 	 off&= ~rtrn->axt_ctrls_on;
 | |
| 	 off|= rtrn->axt_ctrls_off;
 | |
|     }
 | |
|     else off= rtrn->axt_ctrls_off;
 | |
|     if (!rtrn->replace_axt_ctrls_on) {
 | |
| 	 on= (ctrls->axt_ctrls_mask&ctrls->axt_ctrls_values);
 | |
| 	 on&= ~rtrn->axt_ctrls_off;
 | |
| 	 on|= rtrn->axt_ctrls_on;
 | |
|     }
 | |
|     else on= rtrn->axt_ctrls_on;
 | |
|     ctrls->axt_ctrls_mask= (on|off)&~rtrn->axt_ctrls_ignore;
 | |
|     ctrls->axt_ctrls_values= on&~rtrn->axt_ctrls_ignore;
 | |
| 
 | |
|     /* any value set to both off and on is reset to ignore */
 | |
|     if ((off=(rtrn->axt_opts_on&rtrn->axt_opts_off))!=0)
 | |
| 	rtrn->axt_opts_ignore|= off;
 | |
| 
 | |
|     /* ignore takes priority over on and off */
 | |
|     rtrn->axt_opts_on&= ~rtrn->axt_opts_ignore;
 | |
|     rtrn->axt_opts_off&= ~rtrn->axt_opts_ignore;
 | |
| 
 | |
|     if (rtrn->replace_axt_opts_off) {
 | |
| 	 off= (ctrls->axt_opts_mask&(~ctrls->axt_opts_values));
 | |
| 	 off&= ~rtrn->axt_opts_on;
 | |
| 	 off|= rtrn->axt_opts_off;
 | |
|     }
 | |
|     else off= rtrn->axt_opts_off;
 | |
|     if (!rtrn->replace_axt_opts_on) {
 | |
| 	 on= (ctrls->axt_opts_mask&ctrls->axt_opts_values);
 | |
| 	 on&= ~rtrn->axt_opts_off;
 | |
| 	 on|= rtrn->axt_opts_on;
 | |
|     }
 | |
|     else on= rtrn->axt_opts_on;
 | |
|     ctrls->axt_opts_mask= (unsigned short)((on|off)&~rtrn->axt_ctrls_ignore);
 | |
|     ctrls->axt_opts_values= (unsigned short)(on&~rtrn->axt_ctrls_ignore);
 | |
| 
 | |
|     if (rtrn->defined&XkbCF_GroupsWrap) {
 | |
| 	int n;
 | |
| 	n= XkbNumGroups(ctrls->groups_wrap);
 | |
| 	rtrn->groups_wrap= XkbSetNumGroups(rtrn->groups_wrap,n);
 | |
| 	ctrls->groups_wrap= rtrn->groups_wrap;
 | |
|     }
 | |
|     return True;
 | |
| }
 | |
| 
 | |
| /*ARGSUSED*/
 | |
| static Bool
 | |
| DefaultFinish(	XkbConfigFieldsPtr	fields,
 | |
| 		XkbDescPtr		xkb,
 | |
| 		XkbConfigRtrnPtr	rtrn,
 | |
| 		int			what)
 | |
| {
 | |
|     if ((what==XkbCF_Destroy)||(what==XkbCF_CleanUp))
 | |
| 	return DefaultCleanUp(rtrn);
 | |
|     if (what==XkbCF_Check) {
 | |
| 	if ((rtrn->symbols==NULL)&&(rtrn->phys_symbols!=NULL))
 | |
| 	    rtrn->symbols= _XkbDupString(rtrn->phys_symbols);
 | |
|     }
 | |
|     if ((what==XkbCF_Apply)||(what==XkbCF_Check)) {
 | |
| 	if (xkb && xkb->names && (rtrn->num_unbound_mods>0))
 | |
| 	    XkbCFBindMods(rtrn,xkb);
 | |
| 	XkbCFApplyMods(rtrn,XkbCF_InitialMods,&rtrn->initial_mods);
 | |
| 	XkbCFApplyMods(rtrn,XkbCF_InternalMods,&rtrn->internal_mods);
 | |
| 	XkbCFApplyMods(rtrn,XkbCF_IgnoreLockMods,&rtrn->ignore_lock_mods);
 | |
|     }
 | |
|     if (what==XkbCF_Apply) {
 | |
| 	if (xkb!=NULL) {
 | |
| 	    DefaultApplyNames(rtrn,xkb);
 | |
| 	    DefaultApplyControls(rtrn,xkb);
 | |
| 	    XkbCFBindMods(rtrn,xkb);
 | |
| 	}
 | |
|     }
 | |
|     return True;
 | |
| }
 | |
| 
 | |
| static XkbConfigFieldRec _XkbCFDfltFields[] = {
 | |
| 	{ "rules",	_XkbCF_RulesFile },
 | |
| 	{ "model",	_XkbCF_Model },
 | |
| 	{ "layout",	_XkbCF_Layout },
 | |
| 	{ "variant",	_XkbCF_Variant },
 | |
| 	{ "options",	_XkbCF_Options },
 | |
| 	{ "keymap",	_XkbCF_Keymap },
 | |
| 	{ "keycodes",	_XkbCF_Keycodes },
 | |
| 	{ "geometry",	_XkbCF_Geometry },
 | |
| 	{ "realsymbols",_XkbCF_PhysSymbols },
 | |
| 	{ "actualsymbols",_XkbCF_PhysSymbols },
 | |
| 	{ "symbols",	_XkbCF_Symbols },
 | |
| 	{ "symbolstouse",_XkbCF_Symbols },
 | |
| 	{ "types",	_XkbCF_Types },
 | |
| 	{ "compat",	_XkbCF_CompatMap },
 | |
| 	{ "modifiers",	_XkbCF_InitialMods },
 | |
| 	{ "controls",	_XkbCF_InitialCtrls },
 | |
| 	{ "click",	_XkbCF_ClickVolume },
 | |
| 	{ "clickvolume",_XkbCF_ClickVolume },
 | |
| 	{ "bell",	_XkbCF_BellVolume },
 | |
| 	{ "bellvolume",	_XkbCF_BellVolume },
 | |
| 	{ "bellpitch",	_XkbCF_BellPitch },
 | |
| 	{ "bellduration",_XkbCF_BellDuration },
 | |
| 	{ "repeatdelay",_XkbCF_RepeatDelay },
 | |
| 	{ "repeatinterval",_XkbCF_RepeatInterval },
 | |
| 	{ "slowkeysdelay",_XkbCF_SlowKeysDelay	},
 | |
| 	{ "debouncedelay",_XkbCF_DebounceDelay },
 | |
| 	{ "mousekeysdelay",_XkbCF_MouseKeysDelay },
 | |
| 	{ "mousekeysinterval",_XkbCF_MouseKeysInterval },
 | |
| 	{ "mousekeystimetomax",_XkbCF_MouseKeysTimeToMax },
 | |
| 	{ "mousekeysmaxspeed",_XkbCF_MouseKeysMaxSpeed },
 | |
| 	{ "mousekeyscurve",_XkbCF_MouseKeysCurve },
 | |
| 	{ "accessxtimeout",_XkbCF_AccessXTimeout },
 | |
| 	{ "axtimeout",_XkbCF_AccessXTimeout },
 | |
| 	{ "accessxtimeoutctrlson",_XkbCF_AccessXTimeoutCtrlsOn },
 | |
| 	{ "axtctrlson",	_XkbCF_AccessXTimeoutCtrlsOn },
 | |
| 	{ "accessxtimeoutctrlsoff",_XkbCF_AccessXTimeoutCtrlsOff },
 | |
| 	{ "axtctrlsoff",_XkbCF_AccessXTimeoutCtrlsOff },
 | |
| 	{ "accessxtimeoutfeedbackon", _XkbCF_AccessXTimeoutOptsOn },
 | |
| 	{ "axtfeedbackon", _XkbCF_AccessXTimeoutOptsOn },
 | |
| 	{ "accessxtimeoutfeedbackoff", _XkbCF_AccessXTimeoutOptsOff },
 | |
| 	{ "axtfeedbackoff", _XkbCF_AccessXTimeoutOptsOff },
 | |
| 	{ "ignorelockmods",_XkbCF_IgnoreLockMods },
 | |
| 	{ "ignorelockmodifiers",_XkbCF_IgnoreLockMods },
 | |
| 	{ "ignoregrouplock",_XkbCF_IgnoreGroupLock },
 | |
| 	{ "internalmods",_XkbCF_InternalMods },
 | |
| 	{ "internalmodifiers",_XkbCF_InternalMods },
 | |
| 	{ "outofrangegroups",_XkbCF_GroupsWrap },
 | |
| 	{ "groups", _XkbCF_GroupsWrap },
 | |
| 	{ "feedback", _XkbCF_InitialFeedback },
 | |
| };
 | |
| #define	_XkbCFNumDfltFields (sizeof(_XkbCFDfltFields)/sizeof(XkbConfigFieldRec))
 | |
| 
 | |
| static XkbConfigFieldsRec _XkbCFDflts = {
 | |
| 	0,			/* cfg_id */
 | |
| 	_XkbCFNumDfltFields,	/* num_fields */
 | |
| 	_XkbCFDfltFields,	/* fields */
 | |
| 	DefaultParser,	/* parser */
 | |
| 	DefaultFinish,	/* finish */
 | |
| 	NULL,			/* priv */
 | |
| 	NULL			/* next */
 | |
| };
 | |
| 
 | |
| XkbConfigFieldsPtr	XkbCFDflts= &_XkbCFDflts;
 | |
| 
 | |
| /***====================================================================***/
 | |
| 
 | |
| XkbConfigFieldsPtr
 | |
| XkbCFDup(XkbConfigFieldsPtr fields)
 | |
| {
 | |
| XkbConfigFieldsPtr	pNew;
 | |
| 
 | |
|     pNew= _XkbTypedAlloc(XkbConfigFieldsRec);
 | |
|     if (pNew!=NULL) {
 | |
| 	memcpy(pNew,fields,sizeof(XkbConfigFieldsRec));
 | |
| 	if ((pNew->fields!=NULL)&&(pNew->num_fields>0)) {
 | |
| 	    pNew->fields= _XkbTypedCalloc(pNew->num_fields,XkbConfigFieldRec);
 | |
| 	    if (pNew->fields) {
 | |
| 		memcpy(fields->fields,pNew->fields,
 | |
| 				(pNew->num_fields*sizeof(XkbConfigFieldRec)));
 | |
| 	    }
 | |
| 	    else {
 | |
| 		_XkbFree(pNew);
 | |
| 		return NULL;
 | |
| 	    }
 | |
| 	}
 | |
| 	else {
 | |
| 	    pNew->num_fields= 0;
 | |
| 	    pNew->fields= NULL;
 | |
| 	}
 | |
| 	pNew->next= NULL;
 | |
|     }
 | |
|     return pNew;
 | |
| }
 | |
| 
 | |
| XkbConfigFieldsPtr 
 | |
| XkbCFFree(XkbConfigFieldsPtr fields,Bool all)
 | |
| {
 | |
| XkbConfigFieldsPtr	next;
 | |
| 
 | |
|     next= NULL;
 | |
|     while (fields!=NULL) {
 | |
| 	next= fields->next;
 | |
| 	if (fields!=XkbCFDflts) {
 | |
| 	    if (fields->fields) {
 | |
| 		_XkbFree(fields->fields);
 | |
| 		fields->fields= NULL;
 | |
| 		fields->num_fields= 0;
 | |
| 	    }
 | |
| 	    _XkbFree(fields);
 | |
| 	}
 | |
| 	fields= (all?next:NULL);
 | |
|     }
 | |
|     return next;
 | |
| }
 | |
| 
 | |
| Bool
 | |
| XkbCFApplyRtrnValues(	XkbConfigRtrnPtr	rtrn,
 | |
| 			XkbConfigFieldsPtr	fields,
 | |
| 			XkbDescPtr		xkb)
 | |
| {
 | |
| Bool			ok;
 | |
| 
 | |
|     if ((fields==NULL)||(rtrn==NULL)||(xkb==NULL))
 | |
| 	return False;
 | |
|     for (ok=True;fields!=NULL;fields=fields->next) {
 | |
| 	if (fields->finish!=NULL)
 | |
| 	    ok= (*fields->finish)(fields,xkb,rtrn,XkbCF_Apply)&&ok;
 | |
|     }
 | |
|     return ok;
 | |
| }
 | |
| 
 | |
| XkbConfigRtrnPrivPtr
 | |
| XkbCFAddPrivate(	XkbConfigRtrnPtr	rtrn,
 | |
| 			XkbConfigFieldsPtr	fields,
 | |
| 			XPointer		ptr)
 | |
| {
 | |
| XkbConfigRtrnPrivPtr	priv;
 | |
| 
 | |
|     if ((rtrn==NULL)||(fields==NULL))
 | |
| 	return NULL;
 | |
|     priv= _XkbTypedAlloc(XkbConfigRtrnPrivRec);
 | |
|     if (priv!=NULL) {
 | |
| 	priv->cfg_id= 	fields->cfg_id;
 | |
| 	priv->priv=	ptr;
 | |
| 	priv->next= 	rtrn->priv;
 | |
| 	rtrn->priv=	priv;
 | |
|     }
 | |
|     return priv;
 | |
| }
 | |
| 
 | |
| void
 | |
| XkbCFFreeRtrn(	XkbConfigRtrnPtr	rtrn,
 | |
| 		XkbConfigFieldsPtr	fields,
 | |
| 		XkbDescPtr		xkb)
 | |
| {
 | |
| XkbConfigRtrnPrivPtr	tmp,next;
 | |
| 
 | |
|     if ((fields==NULL)||(rtrn==NULL))
 | |
| 	return;
 | |
|     while (fields!=NULL) {
 | |
| 	if (fields->finish!=NULL)
 | |
| 	    (*fields->finish)(fields,xkb,rtrn,XkbCF_Destroy);
 | |
| 	fields= fields->next;
 | |
|     }
 | |
|     for (tmp=rtrn->priv;tmp!=NULL;tmp=next) {
 | |
| 	next= tmp->next;
 | |
| 	bzero((char *)tmp,sizeof(XkbConfigRtrnPrivRec));
 | |
| 	_XkbFree(tmp);
 | |
|     }
 | |
|     bzero((char *)rtrn,sizeof(XkbConfigRtrnRec));
 | |
|     return;
 | |
| }
 | |
| 
 | |
| Bool
 | |
| XkbCFParse(	FILE *			file,
 | |
| 		XkbConfigFieldsPtr	fields,
 | |
| 		XkbDescPtr		xkb,
 | |
| 		XkbConfigRtrnPtr	rtrn)
 | |
| {
 | |
| int			tok;
 | |
| XkbCFScanResultRec	val;
 | |
| XkbConfigFieldsPtr	tmp;
 | |
| 
 | |
|     if ((file==NULL)||(fields==NULL)||(rtrn==NULL))
 | |
| 	return False;
 | |
|     for (tok=0,tmp=fields;tmp!=NULL;tmp=tmp->next,tok++) {
 | |
| 	fields->cfg_id= tok;
 | |
|     }
 | |
|     bzero((char *)rtrn,sizeof(XkbConfigRtrnRec));
 | |
|     rtrn->line= 1;
 | |
|     rtrn->click_volume= -1;
 | |
|     rtrn->bell_volume= -1;
 | |
|     while ((tok=XkbCFScan(file,&val,rtrn))!=XkbCF_EOF) {
 | |
| 	if (tok==XkbCF_Ident) {
 | |
| 	    Bool		done;
 | |
| 	    for (tmp=fields,done=False;(tmp!=NULL)&&(!done);tmp=tmp->next) {
 | |
| 		register int 		i;
 | |
| 		XkbConfigFieldPtr	f;
 | |
| 
 | |
| 		for (i=0,f=tmp->fields;(i<tmp->num_fields)&&(!done);i++,f++) {
 | |
| 		    if (_XkbStrCaseCmp(val.str,f->field)!=0)
 | |
| 			continue;
 | |
| 		    if ((*tmp->parser)(file,tmp,f,xkb,rtrn))
 | |
| 			 done= True;
 | |
| 		    else goto BAILOUT;
 | |
| 		}
 | |
| 	    }
 | |
| 	}
 | |
| 	else if ((tok!=XkbCF_EOL)&&(tok!=XkbCF_Semi)) {
 | |
| 	    rtrn->error= XkbCF_MissingIdent;
 | |
| 	    goto BAILOUT;
 | |
| 	}
 | |
|     }
 | |
|     for (tmp=fields;tmp!=NULL;tmp=tmp->next) {
 | |
| 	if ((tmp->finish)&&(!(*tmp->finish)(tmp,xkb,rtrn,XkbCF_Check)))
 | |
| 	    goto BAILOUT;
 | |
|     }
 | |
|     return True;
 | |
| BAILOUT:
 | |
|     for (tmp=fields;tmp!=NULL;tmp=tmp->next) {
 | |
| 	if (tmp->finish)
 | |
| 	    (*tmp->finish)(tmp,xkb,rtrn,XkbCF_CleanUp);
 | |
|     }
 | |
|     return False;
 | |
| }
 | |
| 
 | |
| /*ARGSUSED*/
 | |
| void
 | |
| XkbCFReportError(FILE *file,char *name,int error,int line)
 | |
| {
 | |
| char *	msg;
 | |
| 
 | |
|     switch(error) {
 | |
| 	case XkbCF_BadAlloc:
 | |
| 	    msg= "allocation failed\n"; break;
 | |
| 	case XkbCF_UnterminatedString:
 | |
| 	    msg= "unterminated string on line %d"; break;
 | |
| 	case XkbCF_MissingIdent:
 | |
| 	    msg= "expected identifier on line %d"; break;
 | |
| 	case XkbCF_MissingEquals:
 | |
| 	    msg= "expected '=' on line %d"; break;
 | |
| 	case XkbCF_ExpectedEOS:
 | |
| 	    msg= "expected ';' or newline on line %d"; break;
 | |
| 	case XkbCF_ExpectedBoolean:
 | |
| 	    msg= "expected a boolean value on line %d"; break;
 | |
| 	case XkbCF_ExpectedInteger:
 | |
| 	    msg= "expected a numeric value on line %d"; break;
 | |
| 	case XkbCF_ExpectedString:
 | |
| 	    msg= "expected a string on line %d"; break;
 | |
| 	case XkbCF_ExpectedModifier:
 | |
| 	    msg= "expected a modifier name on line %d"; break;
 | |
| 	case XkbCF_ExpectedControl:
 | |
| 	    msg= "expected a control name on line %d"; break;
 | |
| 	case XkbCF_ExpectedAXOption:
 | |
| 	    msg= "expected an AccessX option on line %d"; break;
 | |
| 	case XkbCF_ExpectedOperator:
 | |
| 	    msg= "expected '+' or '-' on line %d"; break;
 | |
| 	case XkbCF_ExpectedOORGroupBehavior:
 | |
| 	    msg= "expected wrap, clamp or group number on line %d"; break;
 | |
| 	default:
 | |
| 	    msg= "unknown error on line %d"; break;
 | |
|     }
 | |
| #ifndef XKB_IN_SERVER
 | |
|     fprintf(file,msg,line);
 | |
|     if (name)	fprintf(file," of %s\n",name);
 | |
|     else	fprintf(file,"\n");
 | |
| #else
 | |
|     ErrorF(msg,line);
 | |
|     if (name)	ErrorF(" of %s\n",name);
 | |
|     else	ErrorF("\n");
 | |
| #endif
 | |
|     return;
 | |
| }
 |