1 // Key binding interface
2 // Copyright (C) 2000 Core Technologies.
3 
4 // This file is part of e93.
5 //
6 // e93 is free software; you can redistribute it and/or modify
7 // it under the terms of the e93 LICENSE AGREEMENT.
8 //
9 // e93 is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 // e93 LICENSE AGREEMENT for more details.
13 //
14 // You should have received a copy of the e93 LICENSE AGREEMENT
15 // along with e93; see the file "LICENSE.TXT".
16 
17 #include	"includes.h"
18 
19 typedef struct keyBinding
20 {
21 	UINT32
22 		keyCode,
23 		modifierMask,
24 		modifierValue;
25 	struct keyBinding
26 		*previousBinding,					// pointer to previous binding in the global binding list
27 		*nextBinding,						// pointer to next binding in the global binding list (in user defined order)
28 		*nextHashBinding;					// pointer to next binding in local hash list
29 	char
30 		dataText[1];						// variable length array of characters of data (would like to declare as dataText[0] but some compilers complain)
31 } EDITOR_KEY_BINDING;
32 
GetBindingHashListHead(UINT32 keyCode)33 static EDITOR_KEY_BINDING **GetBindingHashListHead(UINT32 keyCode)
34 // perform hashing function on keyCode, return pointer to list head
35 // for bindings
36 {
37 	return(&(keyBindingTable[keyCode&0xFF]));
38 }
39 
GetKeyBindingText(EDITOR_KEY_BINDING * binding)40 char *GetKeyBindingText(EDITOR_KEY_BINDING *binding)
41 // return a pointer to the key binding text for binding
42 {
43 	return(binding->dataText);
44 }
45 
GetKeyBindingCodeAndModifiers(EDITOR_KEY_BINDING * binding,UINT32 * keyCode,UINT32 * modifierMask,UINT32 * modifierValue)46 void GetKeyBindingCodeAndModifiers(EDITOR_KEY_BINDING *binding,UINT32 *keyCode,UINT32 *modifierMask,UINT32 *modifierValue)
47 // return the key binding information
48 {
49 	*keyCode=binding->keyCode;
50 	*modifierMask=binding->modifierMask;
51 	*modifierValue=binding->modifierValue;
52 }
53 
LocateKeyBinding(UINT32 keyCode,UINT32 modifierMask,UINT32 modifierValue,EDITOR_KEY_BINDING *** hashListHead,EDITOR_KEY_BINDING ** previousHashEntry,EDITOR_KEY_BINDING ** entry)54 static bool LocateKeyBinding(UINT32 keyCode,UINT32 modifierMask,UINT32 modifierValue,EDITOR_KEY_BINDING ***hashListHead,EDITOR_KEY_BINDING **previousHashEntry,EDITOR_KEY_BINDING **entry)
55 // locate a key binding in the binding table, return pointers to important entries
56 {
57 	bool
58 		found;
59 	EDITOR_KEY_BINDING
60 		*currentEntry;
61 
62 	*entry=NULL;													// keep gcc quiet
63 	currentEntry=*(*hashListHead=GetBindingHashListHead(keyCode));	// point to the head of the linked list at this hash entry
64 	*previousHashEntry=NULL;
65 	found=false;
66 	while(currentEntry&&!found)
67 	{
68 		if((currentEntry->keyCode==keyCode)&&(currentEntry->modifierMask==modifierMask)&&(currentEntry->modifierValue==modifierValue))
69 		{
70 			found=true;
71 			*entry=currentEntry;
72 		}
73 		else
74 		{
75 			*previousHashEntry=currentEntry;
76 			currentEntry=currentEntry->nextHashBinding;
77 		}
78 	}
79 	return(found);
80 }
81 
LocateNextKeyBinding(EDITOR_KEY_BINDING * currentBinding)82 EDITOR_KEY_BINDING *LocateNextKeyBinding(EDITOR_KEY_BINDING *currentBinding)
83 // return the next key binding from the current one
84 // if there is none, return NULL
85 {
86 	return(currentBinding->nextBinding);
87 }
88 
LocateKeyBindingMatch(UINT32 keyCode,UINT32 modifierValue)89 EDITOR_KEY_BINDING *LocateKeyBindingMatch(UINT32 keyCode,UINT32 modifierValue)
90 // find a key binding that matches the keyCode, and modifierValue, and return it
91 // if there is none, return NULL
92 {
93 	bool
94 		found;
95 	EDITOR_KEY_BINDING
96 		*currentEntry;
97 
98 	currentEntry=*GetBindingHashListHead(keyCode);	// point to the head of the linked list at this hash entry
99 	found=false;
100 	while(currentEntry&&!found)
101 	{
102 		if((currentEntry->keyCode==keyCode)&&((currentEntry->modifierMask&modifierValue)==currentEntry->modifierValue))
103 		{
104 			found=true;
105 		}
106 		else
107 		{
108 			currentEntry=currentEntry->nextHashBinding;
109 		}
110 	}
111 	return(currentEntry);
112 }
113 
DeleteEditorKeyBinding(UINT32 keyCode,UINT32 modifierMask,UINT32 modifierValue)114 bool DeleteEditorKeyBinding(UINT32 keyCode,UINT32 modifierMask,UINT32 modifierValue)
115 // attempt to locate the given binding in the key bindings table, and
116 // remove it if it is found
117 // if it is not located, return false
118 {
119 	EDITOR_KEY_BINDING
120 		**hashListHead,
121 		*previousHashEntry,
122 		*entry;
123 
124 	if(LocateKeyBinding(keyCode,modifierMask,modifierValue,&hashListHead,&previousHashEntry,&entry))
125 	{
126 		if(previousHashEntry)
127 		{
128 			previousHashEntry->nextHashBinding=entry->nextHashBinding;		// unlink the located entry
129 		}
130 		else
131 		{
132 			*hashListHead=entry->nextHashBinding;
133 		}
134 		if(entry->previousBinding)
135 		{
136 			if((entry->previousBinding->nextBinding=entry->nextBinding))
137 			{
138 				entry->nextBinding->previousBinding=entry->previousBinding;
139 			}
140 		}
141 		else
142 		{
143 			if((keyBindingListHead=entry->nextBinding))
144 			{
145 				keyBindingListHead->previousBinding=NULL;
146 			}
147 		}
148 		MDisposePtr(entry);
149 		return(true);
150 	}
151 	return(false);
152 }
153 
CreateEditorKeyBinding(UINT32 keyCode,UINT32 modifierMask,UINT32 modifierValue,char * dataText)154 bool CreateEditorKeyBinding(UINT32 keyCode,UINT32 modifierMask,UINT32 modifierValue,char *dataText)
155 // search the key binding table for an entry that matches the one given, and delete it if
156 // it exists. Then add this entry to the table
157 // if there is a problem, SetError, and return false
158 {
159 	EDITOR_KEY_BINDING
160 		**hashListHead,
161 		*newEntry;
162 
163 	DeleteEditorKeyBinding(keyCode,modifierMask,modifierValue);	// try to delete one if it exists
164 	hashListHead=GetBindingHashListHead(keyCode);						// point to head of list in hash table where this binding will go
165 	if((newEntry=(EDITOR_KEY_BINDING *)MNewPtr(sizeof(EDITOR_KEY_BINDING)+strlen(dataText)+1)))
166 	{
167 		newEntry->keyCode=keyCode;
168 		newEntry->modifierMask=modifierMask;
169 		newEntry->modifierValue=modifierValue;
170 		newEntry->nextHashBinding=*hashListHead;
171 		strcpy(&(newEntry->dataText[0]),dataText);				// copy in the data
172 		*hashListHead=newEntry;									// link to head of hash list
173 		newEntry->previousBinding=NULL;
174 		if((newEntry->nextBinding=keyBindingListHead))			// point to the next entry
175 		{
176 			keyBindingListHead->previousBinding=newEntry;
177 		}
178 		keyBindingListHead=newEntry;
179 		return(true);
180 	}
181 	return(false);
182 }
183 
InitKeyBindingTable()184 bool InitKeyBindingTable()
185 // clear the key binding table so that there are no bindings present
186 // if there is a problem, SetError, and return false
187 {
188 	int
189 		i;
190 
191 	for(i=0;i<256;i++)
192 	{
193 		keyBindingTable[i]=NULL;
194 	}
195 	keyBindingListHead=NULL;
196 	return(true);
197 }
198 
UnInitKeyBindingTable()199 void UnInitKeyBindingTable()
200 // remove all key bindings from the bindings table
201 {
202 	int
203 		i;
204 	EDITOR_KEY_BINDING
205 		*currentEntry,
206 		*nextEntry;
207 
208 	for(i=0;i<256;i++)
209 	{
210 		currentEntry=keyBindingTable[i];
211 		while(currentEntry)
212 		{
213 			nextEntry=currentEntry->nextHashBinding;
214 			MDisposePtr(currentEntry);
215 			currentEntry=nextEntry;
216 		}
217 		keyBindingTable[i]=NULL;
218 	}
219 	keyBindingListHead=NULL;
220 }
221