1
2 /******************************************************************************
3 * MODULE : tm_config.cpp
4 * DESCRIPTION: Configuration routines for TeXmacs server
5 * COPYRIGHT : (C) 1999 Joris van der Hoeven
6 *******************************************************************************
7 * This software falls under the GNU general public license version 3 or later.
8 * It comes WITHOUT ANY WARRANTY WHATSOEVER. For details, see the file LICENSE
9 * in the root directory or <http://www.gnu.org/licenses/gpl-3.0.html>.
10 ******************************************************************************/
11
12 #include "tm_config.hpp"
13 #include "analyze.hpp"
14
15 /******************************************************************************
16 * Constructor and destructor
17 ******************************************************************************/
18
tm_config_rep()19 tm_config_rep::tm_config_rep ():
20 var_suffix (" tab"), unvar_suffix (" S-tab") {}
21
~tm_config_rep()22 tm_config_rep::~tm_config_rep () {}
23
24 /******************************************************************************
25 * Setup TeXmacs fonts
26 ******************************************************************************/
27
28 void
set_font_rules(scheme_tree rules)29 tm_config_rep::set_font_rules (scheme_tree rules) {
30 int i, n= arity (rules);
31 for (i=0; i<n; i++)
32 if (arity (rules [i]) == 2) {
33 tree l= (tree) rules[i][0];
34 tree r= (tree) rules[i][1];
35 font_rule (l, r);
36 }
37 }
38
39 /******************************************************************************
40 * Latex and user commands
41 ******************************************************************************/
42
43 bool
kbd_get_command(string which,string & help,command & cmd)44 tm_config_rep::kbd_get_command (string which, string& help, command& cmd) {
45 object im= call ("kbd-get-command", which);
46 if (im == object (false)) return false;
47 help= as_string (car (im));
48 cmd = as_command (cdr (im));
49 return true;
50 }
51
52 /******************************************************************************
53 * Wildcards for keyboard bindings
54 ******************************************************************************/
55
56 static string
apply_wildcards(string s,hashmap<string,tree> w)57 apply_wildcards (string s, hashmap<string,tree> w) {
58 int len, start, end, n= N(s);
59 for (len=n; len>0; len--) {
60 for (start=0; start <= (n-len); start++) {
61 end= start+ len;
62 if ((start>0) && (s[start-1] != ' ') && (s[start-1] != '-')) continue;
63 if ((end<n) && (s[end-1] != ' ') && (s[end-1] != '-')) continue;
64 string ss= s (start, end);
65 if (s[end-1] == ' ') ss= s (start, end-1);
66
67 // cout << " " << ss << " => " << w[ss] << LF;
68 if (w->contains (ss)) {
69 tree t= w[ss];
70 string rr= t[0]->label;
71 bool lflag= (t[1]->label != "") || (start == 0);
72 bool rflag= (t[2]->label != "") || (end == n);
73 if (lflag && rflag) {
74 if ((end<n) && (rr != "") && (rr[N(rr)-1] != '-')) rr= rr * " ";
75 string r= s (0, start) * rr * s (end, n);
76 return apply_wildcards (r, w);
77 }
78 }
79 }
80 }
81 return s;
82 }
83
84 void
insert_kbd_wildcard(string key,string im,bool post,bool l,bool r)85 tm_config_rep::insert_kbd_wildcard (
86 string key, string im, bool post, bool l, bool r)
87 {
88 //cout << "Wildcard " << key << " -> " << im << "\n";
89 tree t= tuple (im,
90 l? string ("*"): string (""),
91 r? string ("*"): string (""));
92 if (post) post_kbd_wildcards (key)= t;
93 else pre_kbd_wildcards (key)= t;
94 }
95
96 /******************************************************************************
97 * Variants
98 ******************************************************************************/
99
100 void
set_variant_keys(string var,string unvar)101 tm_config_rep::set_variant_keys (string var, string unvar) {
102 var_suffix= " " * var;
103 unvar_suffix= " " * unvar;
104 }
105
106 #define rewrite_find_key_binding(s) \
107 find_key_binding (apply_wildcards (s, post_kbd_wildcards))
108
109 void
variant_simplification(string & which)110 tm_config_rep::variant_simplification (string& which) {
111 if (ends (which, var_suffix)) {
112 object obj= rewrite_find_key_binding (which);
113 // cout << which << " => " << obj << LF;
114 if (obj == object (false))
115 while (ends (which, var_suffix))
116 which= which (0, N(which) - N(var_suffix));
117 }
118 if (ends (which, unvar_suffix)) {
119 if (ends (which, var_suffix * unvar_suffix))
120 which= which (0, N(which) - N(var_suffix) - N(unvar_suffix));
121 else {
122 which= which (0, N(which) - N(unvar_suffix));
123 while (true) {
124 if (rewrite_find_key_binding (which * var_suffix) == object (false))
125 break;
126 which= which * var_suffix;
127 }
128 }
129 }
130 }
131
132 /******************************************************************************
133 * Server keyboard mappings and shorthands
134 ******************************************************************************/
135
136 object
find_key_binding(string key)137 tm_config_rep::find_key_binding (string key) {
138 return call ("kbd-find-key-binding", key);
139 }
140
141 string
kbd_pre_rewrite(string s)142 tm_config_rep::kbd_pre_rewrite (string s) {
143 return apply_wildcards (s, pre_kbd_wildcards);
144 }
145
146 string
kbd_post_rewrite(string s,bool var_flag)147 tm_config_rep::kbd_post_rewrite (string s, bool var_flag) {
148 if (var_flag) variant_simplification (s);
149 return apply_wildcards (s, post_kbd_wildcards);
150 }
151
152 void
get_keycomb(string & which,int & status,command & cmd,string & shorth,string & help)153 tm_config_rep::get_keycomb (
154 string& which, int& status, command& cmd, string& shorth, string& help)
155 {
156 string orig= which;
157 if (DEBUG_KEYBOARD) debug_keyboard << which;
158 variant_simplification (which);
159 if (DEBUG_KEYBOARD) debug_keyboard << " -> " << which;
160 string rew= apply_wildcards (which, post_kbd_wildcards);
161 bool no_var= false;
162 if (rew * var_suffix == orig) {
163 no_var= true;
164 rew= var_suffix (1, N(var_suffix));
165 }
166 if (rew * unvar_suffix == orig) {
167 no_var= true;
168 rew= unvar_suffix (1, N(unvar_suffix));
169 }
170 if (DEBUG_KEYBOARD) debug_keyboard << " -> " << rew << LF;
171 object obj= find_key_binding (rew);
172 //cout << rew << " => " << obj << LF;
173 //if (obj == object (false) || (orig != which && !is_string (car (obj)))) {
174 if (obj == object (false)) {
175 status= 0;
176 cmd = command ();
177 shorth= copy (rew);
178 help = "";
179 }
180 else if (!is_string (car (obj))) {
181 status= 1;
182 cmd = as_command (car (obj));
183 shorth= copy (rew);
184 help = as_string (cadr (obj));
185 }
186 else {
187 status= 2;
188 cmd = command ();
189 shorth= as_string (car (obj));
190 help = as_string (cadr (obj));
191 }
192 if (no_var) status += 3;
193 }
194
195 /******************************************************************************
196 * System dependent rendering of keyboard shortcuts
197 ******************************************************************************/
198
199 static tree
localize(string s,bool mod_flag=false)200 localize (string s, bool mod_flag= false) {
201 if (mod_flag) return tree (CONCAT, localize (s), "+");
202 else return compound ("localize", s);
203 }
204
205 tree
mathop(string s)206 mathop (string s) {
207 return compound ("math", compound ("op", s));
208 }
209
210 static void
system_kbd_initialize(hashmap<string,tree> & h)211 system_kbd_initialize (hashmap<string,tree>& h) {
212 if (N(h) != 0);
213 else if (use_macos_fonts ()) {
214 h ("S-")= "<#21E7>";
215 h ("C-")= "<#2303>";
216 h ("A-")= "<#2325>";
217 h ("M-")= "<#2318>";
218 h ("H-")= localize ("Hyper");
219 h ("windows")= localize ("Windows");
220 h ("capslock")= "<#21EA>";
221 h ("return")= "<#21A9>";
222 h ("delete")= "<#2326>";
223 h ("backspace")= "<#232B>";
224 h ("clear")= "<#2327>";
225 h ("escape")= "<#238B>";
226 h ("space")= "Space";
227 h ("var")= "<#21E5>";
228 h ("tab")= "<#21E5>";
229 h ("left")= "<#2190>";
230 h ("right")= "<#2192>";
231 h ("up")= "<#2191>";
232 h ("down")= "<#2193>";
233 h ("home")= "<#2196>";
234 h ("end")= "<#2198>";
235 h ("pageup")= "<#21DE>";
236 h ("pagedown")= "<#21DF>";
237 h ("<less>")= "<#3C>";
238 h ("<gtr>")= "<#3E>";
239 }
240 else if (gui_is_qt ()) {
241 h ("S-")= localize ("Shift", true);
242 h ("C-")= localize ("Ctrl", true);
243 h ("A-")= localize ("Alt", true);
244 h ("M-")= localize ("Meta", true);
245 h ("H-")= localize ("Hyper", true);
246 h ("windows")= localize ("Windows");
247 h ("capslock")= localize ("Capslock");
248 h ("return")= localize ("Return");
249 h ("delete")= localize ("Delete");
250 h ("backspace")= localize ("Backspace");
251 h ("escape")= localize ("Escape");
252 h ("space")= localize ("Space");
253 h ("var")= localize ("Tab");
254 h ("tab")= localize ("Tab");
255 h ("left")= mathop ("<leftarrow>");
256 h ("right")= mathop ("<rightarrow>");
257 h ("up")= mathop ("<uparrow>");
258 h ("down")= mathop ("<downarrow>");
259 h ("home")= localize ("Home");
260 h ("end")= localize ("End");
261 h ("pageup")= localize ("PageUp");
262 h ("pagedown")= localize ("PageDown");
263 }
264 else {
265 h ("S-")= "S-";
266 h ("C-")= "C-";
267 h ("A-")= "A-";
268 h ("M-")= "M-";
269 h ("H-")= "H-";
270 h ("windows")= localize ("windows");
271 h ("capslock")= localize ("capslock");
272 h ("return")= localize ("return");
273 h ("delete")= localize ("delete");
274 h ("backspace")= localize ("backspace");
275 h ("escape")= localize ("escape");
276 h ("space")= localize ("space");
277 h ("var")= localize ("tab");
278 h ("tab")= localize ("tab");
279 h ("left")= mathop ("<leftarrow>");
280 h ("right")= mathop ("<rightarrow>");
281 h ("up")= mathop ("<uparrow>");
282 h ("down")= mathop ("<downarrow>");
283 h ("home")= localize ("home");
284 h ("end")= localize ("end");
285 h ("pageup")= localize ("pageup");
286 h ("pagedown")= localize ("pagedown");
287 }
288 }
289
290 static tree
kbd_render(tree t)291 kbd_render (tree t) {
292 if (use_macos_fonts ())
293 t= tree (WITH, "font", "apple-lucida", t);
294 return compound ("render-key", t);
295 }
296
297 static string
kbd_system_prevails(string s)298 kbd_system_prevails (string s) {
299 string laf= get_preference ("look and feel");
300 bool mac= os_macos () && (laf == "default" || laf == "macos");
301 if (mac && starts (s, "A-")) {
302 string ss= s (2, N(s));
303 string r = "escape " * ss;
304 if (starts (ss, "S-")) ss= ss (2, N(ss));
305 if (N(ss) == 1) return r;
306 else return s;
307 }
308 else return s;
309 }
310
311 tree
kbd_system_rewrite(string s)312 tm_config_rep::kbd_system_rewrite (string s) {
313 system_kbd_initialize (system_kbd_decode);
314 int start= 0, i;
315 for (i=0; i <= N(s); i++)
316 if (i == N(s) || s[i] == ' ') {
317 string ss= s (start, i);
318 string rr= kbd_system_prevails (ss);
319 if (rr != ss)
320 return kbd_system_rewrite (s (0, start) * rr * s (i, N(s)));
321 start= i+1;
322 }
323
324 tree k (CONCAT);
325 tree r (CONCAT);
326 start= i= 0;
327 while (true)
328 if (i == N(s) || s[i] == '-' || s[i] == ' ') {
329 if (i < N(s) && s[i] == '-') i++;
330 string ss= s (start, i);
331 if (system_kbd_decode->contains (ss)) r << system_kbd_decode[ss];
332 else if (N(ss) == 1 && (use_macos_fonts () || gui_is_qt ())) {
333 if (is_locase (ss[0])) r << upcase_all (ss);
334 else if (is_upcase (ss[0])) r << system_kbd_decode ("S-") << ss;
335 else r << ss;
336 }
337 else r << ss;
338 if (i == N(s) || s[i] == ' ') {
339 k << kbd_render (simplify_concat (r));
340 r= tree (CONCAT);
341 if (i == N(s)) break;
342 i++;
343 }
344 start= i;
345 }
346 else i++;
347 return simplify_concat (k);
348 }
349