Back to index

texmacs  1.0.7.15
edit_footer.cpp
Go to the documentation of this file.
00001 
00002 /******************************************************************************
00003 * MODULE     : edit_footer.cpp
00004 * DESCRIPTION: display interesting information for the user in the footer
00005 * COPYRIGHT  : (C) 1999  Joris van der Hoeven
00006 *******************************************************************************
00007 * This software falls under the GNU general public license version 3 or later.
00008 * It comes WITHOUT ANY WARRANTY WHATSOEVER. For details, see the file LICENSE
00009 * in the root directory or <http://www.gnu.org/licenses/gpl-3.0.html>.
00010 ******************************************************************************/
00011 
00012 #include "edit_interface.hpp"
00013 #include "convert.hpp"
00014 #include "connect.hpp"
00015 #include "dictionary.hpp"
00016 
00017 /******************************************************************************
00018 * Set left footer with information about environment variables
00019 ******************************************************************************/
00020 
00021 void
00022 edit_interface_rep::set_left_footer (tree l) {
00023   SERVER (set_left_footer (translate (l)));
00024 }
00025 
00026 void
00027 edit_interface_rep::append_left_footer (tree& l, string env_var) {
00028   if (!is_concat (l)) l= concat (l);
00029   string i= get_init_string (env_var);
00030   string c= get_env_string (env_var);
00031   if (c != i) l << (" " * c);
00032 }
00033 
00034 void
00035 edit_interface_rep::set_left_footer () {
00036   tree s= concat ();
00037   double base_sz= get_env_int (FONT_BASE_SIZE);
00038   double sz= get_env_double (FONT_SIZE);
00039   /*
00040   tree the_style= get_style ();
00041   for (int i=0; i<arity (the_style); i++)
00042     s << " " << as_string (the_style[i]);
00043   */
00044   string mode= get_env_string (MODE);
00045   string lan = get_env_string (MODE_LANGUAGE (mode));
00046   if (mode == "prog") s << "program";
00047   else if (as_string (get_init_value (MODE_LANGUAGE (mode))) != lan)
00048     s << " " << lan;
00049   else s << " " << mode;
00050   if ((mode == "text") || (mode == "src")) {
00051     s << " " << get_env_string (FONT);
00052     append_left_footer (s, FONT_FAMILY);
00053     s << " " << as_string ((int) ((base_sz+0.5)*sz));
00054     append_left_footer (s, FONT_SERIES);
00055     append_left_footer (s, FONT_SHAPE);
00056   }
00057   else if (mode == "math") {
00058     s << " " << get_env_string (MATH_FONT);
00059     append_left_footer (s, MATH_FONT_FAMILY);
00060     s << " " << as_string ((int) ((base_sz+0.5)*sz));
00061     append_left_footer (s, MATH_FONT_SERIES);
00062     append_left_footer (s, MATH_FONT_SHAPE);
00063   }
00064   else if (mode == "prog") {
00065     string session_name= get_env_string (PROG_SESSION);
00066     if (session_name != "default") s << "-" << session_name;
00067     s << " " << get_env_string (PROG_FONT);
00068     append_left_footer (s, PROG_FONT_FAMILY);
00069     s << " " << as_string ((int) ((base_sz+0.5)*sz));
00070     append_left_footer (s, PROG_FONT_SERIES);
00071     append_left_footer (s, PROG_FONT_SHAPE);
00072   }
00073   string r= get_env_string (COLOR);
00074   if (r != "black") s << " " << r;
00075   if (N(s) > 0 && s[0] == " ") s= s (1, N(s));
00076   if (inside ("session") && (lan != "scheme")) {
00077     string lan    = get_env_string (PROG_LANGUAGE);
00078     string session= get_env_string (PROG_SESSION);
00079     switch (connection_status (lan, session)) {
00080     case CONNECTION_DEAD:
00081       s= s << " [dead]";
00082       break;
00083     case CONNECTION_DYING:
00084     case WAITING_FOR_OUTPUT:
00085       s= s << " [busy]";
00086       break;
00087     case WAITING_FOR_INPUT:
00088       s= s << " [idle]";
00089       break;
00090     }
00091   }
00092   s= as_tree (call ("footer-hook", object (s)));
00093   set_left_footer (s);
00094 }
00095 
00096 /******************************************************************************
00097 * Set right footer with information about cursor position
00098 ******************************************************************************/
00099 
00100 void
00101 edit_interface_rep::set_right_footer (tree r) {
00102   SERVER (set_right_footer (translate (r)));
00103 }
00104 
00105 tree
00106 edit_interface_rep::compute_text_footer (tree st) {
00107   string r;
00108   language lan= get_env_language ();
00109   int end  = last_item (tp);
00110   int start= end;
00111   tm_char_backwards (st->label, start);
00112   r= st->label (start, end);
00113   if (r == "") r= "start";
00114   if (r == " ") r= "space";
00115   if (r == "space" && get_env_string (MODE) == "math") r= "apply";
00116   return r;
00117 }
00118 
00119 static string
00120 get_accent_type (string s) {
00121   if (s == "^") return "hat";
00122   if (s == "~") return "tilde";
00123   if ((N(s)>=2) && (s[0]=='<') && (s[N(s)-1]=='>')) return s (1, N(s)-1);
00124   return "unknown accent";
00125 }
00126 
00127 inline string
00128 as_symbol (tree t) {
00129   string s= as_string (t);
00130   if (N(s)<=1) return s;
00131   else return "<" * s * ">";
00132 }
00133 
00134 static tree
00135 get_with_text (tree t) {
00136   int i, n=N(t), k=(n-1)/2;
00137   if ((n&1)!=1) return "";
00138   if (is_func (t[n-1], GRAPHICS)) return "";
00139   tree s= concat ();
00140   for (i=0; i<k; i++)
00141     if (is_atomic (t[2*i]) && (t[2*i]!="") && is_atomic (t[2*i+1])) {
00142       if (i>0) s << " ";
00143       string var= t[2*i]->label;
00144       if ((var!=MODE) && (var!=COLOR) && (var!=PAR_MODE) &&
00145          (var!=LANGUAGE) && (var!=FONT) &&
00146          (var!=FONT_FAMILY) && (var!=FONT_SHAPE) && (var!=FONT_SERIES) &&
00147          (var!=MATH_LANGUAGE) && (var!=MATH_FONT) &&
00148          (var!=MATH_FONT_FAMILY) && (var!=MATH_FONT_SHAPE) &&
00149          (var!=MATH_FONT_SERIES) &&
00150          (var!=PROG_LANGUAGE) && (var!=PROG_FONT) &&
00151          (var!=PROG_FONT_FAMILY) && (var!=PROG_FONT_SHAPE) &&
00152          (var!=PROG_FONT_SERIES) &&
00153          (var!=PROG_SESSION))
00154        s << (var * "=" * t[2*i+1]->label);
00155       else s << t[2*i+1]->label;
00156     }
00157   return s;
00158 }
00159 
00160 tree
00161 edit_interface_rep::compute_operation_footer (tree st) {
00162   tree r= "";
00163   if (N(st) >= 2) {
00164     switch (L (st)) {
00165     case VAR_WIDE:
00166       r= concat ("under ", get_accent_type (as_string (st[1]))); break;
00167     default: ;
00168     }
00169   }
00170   if (r == "" && N(st) >= 1) {
00171     switch (L (st)) {
00172     case HSPACE:
00173       r= concat ("space"); break;
00174     case VAR_VSPACE:
00175       r= concat ("vertical space before");
00176       break;
00177     case VSPACE:
00178       r= concat ("vertical space"); break;
00179     case SPACE:
00180       r= concat ("space"); break;
00181     case _FLOAT:
00182       r= (is_atomic (st[0])? st[0]->label: string ("float")); break;
00183     case MID:
00184       r= concat ("middle ", as_symbol (st[0])); break;
00185     case RIGHT:
00186       r= concat ("close ", as_symbol (st[0])); break;
00187     case BIG:
00188       r= concat ("big ", as_symbol (st[0])); break;
00189     case LPRIME:
00190       r= concat ("left prime ", as_string (st[0])); break;
00191     case LONG_ARROW:
00192       r= concat ("long arrow ", as_string (st[0])); break;
00193     case RPRIME:
00194       r= concat ("prime ", as_string (st[0])); break;
00195     case SQRT:
00196       r= tree ((char*) ((N(st)==1)? "square root": "n-th root")); break;
00197     case WIDE:
00198       r= tree (get_accent_type (as_string (st[1]))); break;
00199     case ASSIGN:
00200       r= concat ("assign ", as_string (st[0])); break;
00201     case WITH:
00202       r= concat ("with ", get_with_text (st)); break;
00203     case PROVIDES:
00204       r= concat ("provides ", as_string (st[0])); break;
00205     case VALUE:
00206       r= concat ("value ", as_string (st[0])); break;
00207     case QUOTE_VALUE:
00208       r= concat ("quoted value ", as_string (st[0])); break;
00209     case ARG:
00210       r= concat ("argument ", as_string (st[0])); break;
00211     case QUOTE_ARG:
00212       r= concat ("quoted argument ", as_string (st[0])); break;
00213     case COMPOUND:
00214       if (is_atomic (st[0])) r= as_string (st[0]);
00215       else r= "compound";
00216       break;
00217     case INCLUDE:
00218       r= concat ("include ", as_string (st[0])); break;
00219     case INACTIVE:
00220       r= concat ("inactive ", drd->get_name (L(st[0]))); break;
00221     case VAR_INACTIVE:
00222       r= concat ("inactive ", drd->get_name (L(st[0]))); break;
00223     case LABEL:
00224       r= concat ("label: ", as_string (st[0])); break;
00225     case REFERENCE:
00226       r= concat ("reference: ", as_string (st[0])); break;
00227     case PAGEREF:
00228       r= concat ("page reference: ", as_string (st[0])); break;
00229     case WRITE:
00230       r= concat ("write to ", as_string (st[0])); break;
00231     case SPECIFIC:
00232       r= concat ("specific ", as_string (st[0])); break;
00233     case IMAGE:
00234       r= concat ("image"); break;
00235     default: ;
00236     }
00237   }
00238   if (r == "") {
00239     switch (L (st)) {
00240     case IMAGE: r= "image"; break;
00241     default: r= drd->get_name (L(st));
00242     }
00243   }
00244   if (last_item (tp) == 0) r= concat ("before ", r);
00245   return r;
00246 }
00247 
00248 tree
00249 edit_interface_rep::compute_compound_footer (tree t, path p) {
00250   if (!(rp < p)) return "";
00251   tree up= compute_compound_footer (t, path_up (p));
00252   if (N(focus_get (false))+1 < N(p)) return up;
00253   tree st= subtree (t, path_up (p));
00254   int  l = last_item (p);
00255   switch (L (st)) {
00256   case DOCUMENT:
00257   case PARA:
00258     return up;
00259   case SURROUND:
00260     if (l == 0) return concat (up, "left surrounding ");
00261     if (l == 1) return concat (up, "right surrounding ");
00262     return up;
00263   case CONCAT:
00264     return up;
00265   case MOVE:
00266     if (l == 0) return concat (up, "move ");
00267     else return up;
00268   case SHIFT:
00269     if (l==0) return concat (up, "shift ");
00270     else return up;
00271   case RESIZE:
00272     if (l==0) return concat (up, "resize ");
00273     else return up;
00274   case CLIPPED:
00275     if (l==0) return concat (up, "clipped ");
00276     else return up;
00277   case _FLOAT:
00278     if (N(st) >= 1 && is_atomic (st[0]))
00279       return concat (up, st[0]->label * " ");
00280     else return concat (up, "float ");
00281   case LONG_ARROW:
00282     if (l == 1) return concat (up, "above ");
00283     else if (l == 2) return concat (up, "below ");
00284     else return up;
00285   case BELOW:
00286     if (l==0) return concat (up, "body ");
00287     else return concat (up, "script below ");
00288   case ABOVE:
00289     if (l==0) return concat (up, "body ");
00290     else return concat (up, "script above ");
00291   case FRAC:
00292     if (l==0) return concat (up, "numerator ");
00293     else return concat (up, "denominator ");
00294   case SQRT:
00295     if (N(st)==1) return concat (up, "square root ");
00296     if (l==0) return concat (up, "root ");
00297     else return concat (up, "index ");
00298   case WIDE:
00299     if (N(st) >= 1)
00300       return concat (up, get_accent_type (as_string (st[1])) * " ");
00301     else
00302       return concat (up, "wide ");
00303   case VAR_WIDE:
00304     if (N(st) >= 1)
00305       return concat (up, "under " * get_accent_type (as_string (st[1])) * " ");
00306     else
00307       return concat (up, "var-wide ");
00308   case TREE:
00309     if (l==0) return concat (up, "root ");
00310     else return concat (up, "branch(" * as_string (l) * ") ");
00311   case TFORMAT:
00312     return up;
00313   case TABLE:
00314     return concat (up, "(" * as_string (l+1) * ",");
00315   case ROW:
00316     return concat (up, as_string (l+1) * ") ");
00317   case CELL:
00318     return up;
00319   case WITH:
00320     return concat (up, get_with_text (st), " ");
00321   case DRD_PROPS:
00322     if (l == 0)
00323       return concat (up, "drd property(variable) ");
00324     if ((l&1) == 1)
00325       return concat (up, "drd property(" * as_string (l/2+1) * ") ");
00326     return concat (up, "value(" * as_string (l/2) * ") ");
00327   case COMPOUND:
00328     if (N(st) >= 1 && is_atomic (st[0]))
00329       return concat (up, as_string (st[0]) * " ");
00330     else
00331       return concat (up, "compound ");
00332   case HLINK:
00333     if (N(st) >= 2)
00334       return concat (up, "hyperlink(" * as_string (st[1]) * ") ");
00335     else
00336       return concat (up, "hyperlink ");
00337   case TUPLE:
00338     return concat (up, "tuple(" * as_string (l+1) * ") ");
00339   case ATTR:
00340     if ((l&1) == 0)
00341       return concat (up, "variable(" * as_string (l/2+1) * ") ");
00342     else
00343       return concat (up, "value(" * as_string (l/2+1) * ") ");
00344   case SPECIFIC:
00345     return concat (up, "texmacs ");
00346   case ANIM_CONSTANT:
00347     if (l == 0)
00348       return concat (up, "anim-constant ");
00349     else return up;
00350   case ANIM_TRANSLATE:
00351     if (l == 0)
00352       return concat (up, "anim-translate ");
00353     else return up;
00354   case ANIM_PROGRESSIVE:
00355     if (l == 0)
00356       return concat (up, "anim-progressive ");
00357     else return up;
00358   default:
00359     return concat (up, drd->get_name (L(st)) * " ");
00360   }
00361 }
00362 
00363 void
00364 edit_interface_rep::set_right_footer () {
00365   tree cf= compute_compound_footer (et, path_up (tp));
00366   tree st= subtree (et, path_up (tp));
00367   tree lf;
00368   if (is_atomic (st)) lf= compute_text_footer (st);
00369   else lf= compute_operation_footer (st);
00370   if (N(focus_get (false))+1 >= N(tp)) cf= concat (cf, lf);
00371   set_right_footer (cf);
00372 }
00373 
00374 /******************************************************************************
00375 * Set footer with information about execution of latex command
00376 ******************************************************************************/
00377 
00378 bool
00379 edit_interface_rep::set_latex_footer (tree st) {
00380   if (is_atomic (st)) 
00381     if (is_func (subtree (et, path_up (tp, 2)), LATEX, 1) ||
00382        is_func (subtree (et, path_up (tp, 2)), HYBRID, 1)) {
00383       string s= st->label;
00384       string help;
00385       command cmd;
00386       if (sv->kbd_get_command (s, help, cmd)) {
00387        set_left_footer (concat (kbd ("return"), ": " * help));
00388        set_right_footer ("latex command");
00389        return true;
00390       }
00391     }
00392   return false;
00393 }
00394 
00395 bool
00396 edit_interface_rep::set_hybrid_footer (tree st) {
00397   // WARNING: update edit_dynamic_rep::activate_hybrid when updating this
00398   if (is_atomic (st))
00399     if (is_func (subtree (et, path_up (tp, 2)), HYBRID, 1)) {
00400       string msg;
00401       // macro argument
00402       string name= st->label;
00403       path mp= search_upwards (MACRO);
00404       if (!is_nil (mp)) {
00405        tree mt= subtree (et, mp);
00406        int i, n= N(mt)-1;
00407        for (i=0; i<n; i++)
00408          if (mt[i] == name) {
00409            set_message (concat (kbd ("return"), ": insert argument ", name),
00410                       "hybrid command");
00411            return true;
00412          }
00413       }
00414       // macro application
00415       tree f= get_env_value (name);
00416       if (drd->contains (name) && (f == UNINIT))
00417        set_message (concat (kbd ("return"), ": insert primitive ", name),
00418                    "hybrid command");
00419       else if (is_func (f, MACRO) || is_func (f, XMACRO))
00420        set_message (concat (kbd ("return"), ": insert macro ", name),
00421                    "hybrid command");
00422       else if (f != UNINIT)
00423        set_message (concat (kbd ("return"), ": insert value ", name),
00424                    "hybrid command");
00425       else return false;
00426       return true;
00427     }
00428   return false;
00429 }
00430 
00431 /******************************************************************************
00432 * Update footer
00433 ******************************************************************************/
00434 
00435 TM_DEBUG
00436 (
00437   int concrete_count = 0;
00438   int abstract_count = 0;
00439   int box_count      = 0;
00440   int event_count    = 0;
00441   int widget_count   = 0;
00442   int line_item_count= 0;
00443   int list_count     = 0;
00444   int command_count  = 0;
00445   int observer_count = 0;
00446   int iterator_count = 0;
00447   int function_count = 0;
00448   int instance_count = 0;
00449 )
00450 
00451 void
00452 edit_interface_rep::set_footer () {
00453   TM_DEBUG
00454   (
00455     cout << "--------------------------------------------------------------\n";
00456     cout << "concrete  " << concrete_count << "\n";
00457     cout << "abstract  " << abstract_count << "\n";
00458     cout << "widget    " << widget_count << "\n";
00459     cout << "box       " << box_count << "\n";
00460     cout << "event     " << event_count << "\n";
00461     cout << "line item " << line_item_count << "\n";
00462     cout << "list      " << list_count << "\n";
00463     cout << "command   " << command_count << "\n";
00464     cout << "observer  " << observer_count << "\n";
00465     cout << "iterator  " << iterator_count << "\n";
00466     cout << "function  " << function_count << "\n";
00467     cout << "instance  " << instance_count << "\n";
00468   )
00469 
00470   if ((message_l == "") && (message_r == "")) {
00471     last_l= ""; last_r= "";
00472     tree st= subtree (et, path_up (tp));
00473     if (set_latex_footer (st)) return;
00474     if (set_hybrid_footer (st)) return;
00475     set_left_footer();
00476     set_right_footer();
00477   }
00478   else {
00479     if (message_l == "") set_left_footer ();
00480     else set_left_footer (message_l);
00481     if (message_r == "") set_right_footer ();
00482     else set_right_footer (message_r);
00483     message_l= message_r= "";
00484   }
00485 }
00486 
00487 /******************************************************************************
00488 * Exported routines
00489 ******************************************************************************/
00490 
00491 void
00492 edit_interface_rep::set_message (tree l, tree r, bool temp) {
00493   eval ("(set-message-notify)");
00494   message_l= l;
00495   message_r= r;
00496   if (!temp) {
00497     last_l= l;
00498     last_r= r;
00499   }
00500   notify_change (THE_DECORATIONS);
00501 }
00502 
00503 void
00504 edit_interface_rep::recall_message () {
00505   set_message (last_l, last_r);
00506 }