Only temporarily display keyboard shortcuts
[texmacs.git] / src / src / Edit / Interface / edit_footer.cpp
blob8ce3ad8f613eef7f87afbca0e7959d9d97571a2c
2 /******************************************************************************
3 * MODULE : edit_footer.cpp
4 * DESCRIPTION: display interesting information for the user in the footer
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 ******************************************************************************/
12 #include "edit_interface.hpp"
13 #include "convert.hpp"
14 #include "connect.hpp"
16 /******************************************************************************
17 * Set left footer with information about environment variables
18 ******************************************************************************/
20 void
21 edit_interface_rep::set_left_footer (string s) {
22 SERVER (set_left_footer (s));
25 void
26 edit_interface_rep::append_left_footer (string& s, string env_var) {
27 string i= get_init_string (env_var);
28 string c= get_env_string (env_var);
29 if (c != i) s= s * "#" * c;
32 void
33 edit_interface_rep::set_left_footer () {
34 int i;
35 string s, r, e;
36 double base_sz= get_env_int (FONT_BASE_SIZE);
37 double sz= get_env_double (FONT_SIZE);
38 tree the_style= get_style ();
39 for (i=0; i<arity (the_style); i++)
40 s= s * "#" * as_string (the_style[i]);
41 string mode= get_env_string (MODE);
42 string lan = get_env_string (MODE_LANGUAGE (mode));
43 if (mode == "prog") s= s * "#program";
44 else if (as_string (get_init_value (MODE_LANGUAGE (mode))) != lan)
45 s= s * "#" * lan;
46 else s= s * "#" * mode;
47 if ((mode == "text") || (mode == "src")) {
48 s= s * "#" * get_env_string (FONT);
49 append_left_footer (s, FONT_FAMILY);
50 s= s * "#" * as_string ((int) ((base_sz+0.5)*sz));
51 append_left_footer (s, FONT_SERIES);
52 append_left_footer (s, FONT_SHAPE);
54 else if (mode == "math") {
55 s= s * "#" * get_env_string (MATH_FONT);
56 append_left_footer (s, MATH_FONT_FAMILY);
57 s= s * "#" * as_string ((int) ((base_sz+0.5)*sz));
58 append_left_footer (s, MATH_FONT_SERIES);
59 append_left_footer (s, MATH_FONT_SHAPE);
61 else if (mode == "prog") {
62 string session_name= get_env_string (PROG_SESSION);
63 if (session_name != "default") s= s * "-" * session_name;
64 s= s * "#" * get_env_string (PROG_FONT);
65 append_left_footer (s, PROG_FONT_FAMILY);
66 s= s * "#" * as_string ((int) ((base_sz+0.5)*sz));
67 append_left_footer (s, PROG_FONT_SERIES);
68 append_left_footer (s, PROG_FONT_SHAPE);
70 r= get_env_string (COLOR);
71 if (r != "black") s= s * "#" * r;
72 if ((N(s)>0) && (s[0] == '#')) s= s (1, N(s));
73 if (inside ("session") && (lan != "scheme")) {
74 string lan = get_env_string (PROG_LANGUAGE);
75 string session= get_env_string (PROG_SESSION);
76 switch (connection_status (lan, session)) {
77 case CONNECTION_DEAD:
78 s= s * "#[dead]";
79 break;
80 case CONNECTION_DYING:
81 case WAITING_FOR_OUTPUT:
82 s= s * "#[busy]";
83 break;
84 case WAITING_FOR_INPUT:
85 s= s * "#[idle]";
86 break;
89 s= as_string (call ("footer-hook", object (s)));
90 set_left_footer (s);
93 /******************************************************************************
94 * Set right footer with information about cursor position
95 ******************************************************************************/
97 void
98 edit_interface_rep::set_right_footer (string s) {
99 SERVER (set_right_footer (s));
102 string
103 edit_interface_rep::compute_text_footer (tree st) {
104 string r;
105 language lan= get_env_language ();
106 int end = last_item (tp);
107 int start= end;
108 tm_char_backwards (st->label, start);
109 r= st->label (start, end);
110 if (r == "") r= "start";
111 if (r == " ") r= "space";
112 if (r == "#") r= "sharp";
113 return r;
116 static string
117 get_accent_type (string s) {
118 if (s == "^") return "hat";
119 if (s == "~") return "tilde";
120 if ((N(s)>=2) && (s[0]=='<') && (s[N(s)-1]=='>')) return s (1, N(s)-1);
121 return "unknown accent";
124 inline string
125 as_symbol (tree t) {
126 string s= as_string (t);
127 if (N(s)<=1) return s;
128 else return "<" * s * ">";
131 static string
132 get_with_text (tree t) {
133 int i, n=N(t), k=(n-1)/2;
134 if ((n&1)!=1) return "";
135 string s;
136 for (i=0; i<k; i++)
137 if (is_atomic (t[2*i]) && (t[2*i]!="") && is_atomic (t[2*i+1])) {
138 if (i>0) s << "#";
139 string var= t[2*i]->label;
140 if ((var!=MODE) && (var!=COLOR) && (var!=PAR_MODE) &&
141 (var!=LANGUAGE) && (var!=FONT) &&
142 (var!=FONT_FAMILY) && (var!=FONT_SHAPE) && (var!=FONT_SERIES) &&
143 (var!=MATH_LANGUAGE) && (var!=MATH_FONT) &&
144 (var!=MATH_FONT_FAMILY) && (var!=MATH_FONT_SHAPE) &&
145 (var!=MATH_FONT_SERIES) &&
146 (var!=PROG_LANGUAGE) && (var!=PROG_FONT) &&
147 (var!=PROG_FONT_FAMILY) && (var!=PROG_FONT_SHAPE) &&
148 (var!=PROG_FONT_SERIES) &&
149 (var!=PROG_SESSION))
150 s << var << "=";
151 s << t[2*i+1]->label;
153 return s;
156 string
157 edit_interface_rep::compute_operation_footer (tree st) {
158 string r;
159 switch (L (st)) {
160 case _FLOAT: r= (is_atomic (st[0])? st[0]->label: string ("float")); break;
161 case MID: r= "separator#" * as_symbol (st[0]); break;
162 case RIGHT: r= "close#" * as_symbol (st[0]); break;
163 case BIG: r= "big#" * as_symbol (st[0]); break;
164 case LPRIME: r= "left prime#" * as_string (st[0]); break;
165 case RPRIME: r= "prime#" * as_string (st[0]); break;
166 case SQRT: r= (char*) ((N(st)==1)? "square root": "n-th root"); break;
167 case WIDE: r= get_accent_type (as_string (st[1])); break;
168 case VAR_WIDE: r= "under#" * get_accent_type (as_string (st[1])); break;
169 case TFORMAT: r= "table"; break;
170 case ASSIGN: r= "assign#" * as_string (st[0]); break;
171 case WITH: r= "with#" * get_with_text (st); break;
172 case PROVIDES: r= "provides#" * as_string (st[0]); break;
173 case VALUE: r= "value#" * as_string (st[0]); break;
174 case QUOTE_VALUE: r= "quoted value#" * as_string (st[0]); break;
175 case ARG: r= "argument#" * as_string (st[0]); break;
176 case QUOTE_ARG: r= "quoted argument#" * as_string (st[0]); break;
177 case COMPOUND:
178 if (is_atomic (st[0])) r= as_string (st[0]);
179 else r= "compound";
180 break;
181 case INCLUDE: r= "include#" * as_string (st[0]); break;
182 case INACTIVE: r= "inactive#" * drd->get_name (L(st[0])); break;
183 case VAR_INACTIVE: r= "inactive#" * drd->get_name (L(st[0])); break;
184 case LABEL: r= "label: " * as_string (st[0]); break;
185 case REFERENCE: r= "reference: " * as_string (st[0]); break;
186 case PAGEREF: r= "page reference: " * as_string (st[0]); break;
187 case WRITE: r= "write to " * as_string (st[0]); break;
188 case SPECIFIC: r= "specific " * as_string (st[0]); break;
189 case POSTSCRIPT: r= "postscript image"; break;
190 default: r= drd->get_name (L(st));
192 if (last_item (tp) == 0) r= "before#" * r;
193 return r;
196 string
197 edit_interface_rep::compute_compound_footer (tree t, path p) {
198 if (!(rp < p)) return "";
199 string up= compute_compound_footer (t, path_up (p));
200 tree st= subtree (t, path_up (p));
201 int l = last_item (p);
202 switch (L (st)) {
203 case DOCUMENT:
204 case PARA:
205 return up;
206 case SURROUND:
207 if (l == 0) return up * "left surrounding#";
208 if (l == 1) return up * "right surrounding#";
209 return up;
210 case CONCAT:
211 return up;
212 case MOVE:
213 if (l==0) return up * "move#";
214 else return up;
215 case RESIZE:
216 if (l==0) return up * "resize#";
217 else return up;
218 case _FLOAT:
219 if (is_atomic (st[0])) return up * st[0]->label * "#";
220 else return up * "float#";
221 case BELOW:
222 if (l==0) return up * "body#";
223 else return up * "script below#";
224 case ABOVE:
225 if (l==0) return up * "body#";
226 else return up * "script above#";
227 case FRAC:
228 if (l==0) return up * "numerator#";
229 else return up * "denominator#";
230 case SQRT:
231 if (N(st)==1) return up * "square root#";
232 if (l==0) return up * "root#";
233 else return up * "index#";
234 case WIDE:
235 return up * get_accent_type (as_string (st[1])) * "#";
236 case VAR_WIDE:
237 return up * "under#" * get_accent_type (as_string (st[1])) * "#";
238 case TREE:
239 if (l==0) return up * "root#";
240 else return up * "branch(" * as_string (l) * ")#";
241 case TFORMAT:
242 return up;
243 case TABLE:
244 return up * "(" * as_string (l+1) * ",";
245 case ROW:
246 return up * as_string (l+1) * ")#";
247 case CELL:
248 return up;
249 case WITH:
250 return up * get_with_text (st) * "#";
251 case DRD_PROPS:
252 if (l == 0) return up * "drd property(variable)" * "#";
253 if ((l&1) == 1) return up * "drd property(" * as_string (l/2+1) * ")#";
254 return up * "value(" * as_string (l/2) * ")#";
255 case COMPOUND:
256 if (is_atomic (st[0])) return up * as_string (st[0]) * "#";
257 else return up * "compound#";
258 case HLINK:
259 return up * "hyperlink(" * as_string (st[1]) * ")#";
260 case TUPLE:
261 return up * "tuple(" * as_string (l+1) * ")#";
262 case ATTR:
263 if ((l&1) == 0) return up * "variable(" * as_string (l/2+1) * ")#";
264 else return up * "value(" * as_string (l/2+1) * ")#";
265 case SPECIFIC:
266 return up * "texmacs#";
267 default:
268 return up * drd->get_name (L(st)) * "#";
272 void
273 edit_interface_rep::set_right_footer () {
274 string s, r;
275 tree st= subtree (et, path_up (tp));
276 if (is_atomic (st)) r= compute_text_footer (st);
277 else r= compute_operation_footer (st);
278 r= compute_compound_footer (et, path_up (tp)) * r;
279 set_right_footer (r);
282 /******************************************************************************
283 * Set footer with information about execution of latex command
284 ******************************************************************************/
286 bool
287 edit_interface_rep::set_latex_footer (tree st) {
288 if (is_atomic (st))
289 if (is_func (subtree (et, path_up (tp, 2)), LATEX, 1) ||
290 is_func (subtree (et, path_up (tp, 2)), HYBRID, 1)) {
291 string s= st->label;
292 string help;
293 command cmd;
294 if (sv->kbd_get_command (s, help, cmd)) {
295 set_left_footer ("return:#" * help);
296 set_right_footer ("latex command");
297 return true;
300 return false;
303 bool
304 edit_interface_rep::set_hybrid_footer (tree st) {
305 // WARNING: update edit_dynamic_rep::activate_hybrid when updating this
306 if (is_atomic (st))
307 if (is_func (subtree (et, path_up (tp, 2)), HYBRID, 1)) {
308 string msg;
309 // macro argument
310 string name= st->label;
311 path mp= search_upwards (MACRO);
312 if (!is_nil (mp)) {
313 tree mt= subtree (et, mp);
314 int i, n= N(mt)-1;
315 for (i=0; i<n; i++)
316 if (mt[i] == name) {
317 set_message ("return:#insert argument#" * name, "hybrid command");
318 return true;
321 // macro application
322 tree f= get_env_value (name);
323 if (drd->contains (name) && (f == UNINIT))
324 set_message("return:#insert primitive#" * name, "hybrid command");
325 else if (is_func (f, MACRO) || is_func (f, XMACRO))
326 set_message("return:#insert macro#" * name, "hybrid command");
327 else if (f != UNINIT)
328 set_message("return:#insert value#" * name, "hybrid command");
329 else return false;
330 return true;
332 return false;
335 /******************************************************************************
336 * Update footer
337 ******************************************************************************/
339 TM_DEBUG
341 int concrete_count = 0;
342 int abstract_count = 0;
343 int box_count = 0;
344 int event_count = 0;
345 int widget_count = 0;
346 int line_item_count= 0;
347 int list_count = 0;
348 int command_count = 0;
349 int observer_count = 0;
350 int iterator_count = 0;
351 int function_count = 0;
352 int instance_count = 0;
355 void
356 edit_interface_rep::set_footer () {
357 TM_DEBUG
359 cout << "--------------------------------------------------------------\n";
360 cout << "concrete " << concrete_count << "\n";
361 cout << "abstract " << abstract_count << "\n";
362 cout << "widget " << widget_count << "\n";
363 cout << "box " << box_count << "\n";
364 cout << "event " << event_count << "\n";
365 cout << "line item " << line_item_count << "\n";
366 cout << "list " << list_count << "\n";
367 cout << "command " << command_count << "\n";
368 cout << "observer " << observer_count << "\n";
369 cout << "iterator " << iterator_count << "\n";
370 cout << "function " << function_count << "\n";
371 cout << "instance " << instance_count << "\n";
374 if ((N(message_l) == 0) && (N(message_r) == 0)) {
375 last_l= ""; last_r= "";
376 tree st= subtree (et, path_up (tp));
377 if (set_latex_footer (st)) return;
378 if (set_hybrid_footer (st)) return;
379 set_left_footer();
380 set_right_footer();
382 else {
383 if (message_l == "") set_left_footer ();
384 else set_left_footer (message_l);
385 if (message_r == "") set_right_footer ();
386 else set_right_footer (message_r);
387 message_l= message_r= "";
391 /******************************************************************************
392 * Exported routines
393 ******************************************************************************/
395 void
396 edit_interface_rep::set_message (string l, string r, bool temp) {
397 eval ("(set-message-notify)");
398 message_l= l;
399 message_r= r;
400 if (!temp) {
401 last_l= l;
402 last_r= r;
404 notify_change (THE_DECORATIONS);
407 void
408 edit_interface_rep::recall_message () {
409 set_message (last_l, last_r);