Back to index

texmacs  1.0.7.15
tm_dialogue.cpp
Go to the documentation of this file.
00001 
00002 /******************************************************************************
00003 * MODULE     : tm_dialogue.cpp
00004 * DESCRIPTION: Dialogues
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 "tm_frame.hpp"
00013 #include "tm_window.hpp"
00014 #include "convert.hpp"
00015 #include "file.hpp"
00016 #include "analyze.hpp"
00017 #include "message.hpp"
00018 #include "dictionary.hpp"
00019 
00020 /******************************************************************************
00021 * Dialogues
00022 ******************************************************************************/
00023 
00024 class dialogue_command_rep: public command_rep {
00025   server_rep* sv;
00026   object      fun;
00027   int         nr_args;
00028 
00029 public:
00030   dialogue_command_rep (server_rep* sv2, object fun2, int nr_args2):
00031     sv (sv2), fun (fun2), nr_args (nr_args2) {}
00032   void apply ();
00033   tm_ostream& print (tm_ostream& out) {
00034     return out << "Dialogue"; }
00035 };
00036 
00037 void
00038 dialogue_command_rep::apply () {
00039   int i;
00040   object cmd  = null_object ();
00041   object learn= null_object ();
00042   for (i=nr_args-1; i>=0; i--) {
00043     string s_arg;
00044     sv->dialogue_inquire (i, s_arg);
00045     if (s_arg == "#f") {
00046       exec_delayed (scheme_cmd ("(dialogue-end)"));
00047       return;
00048     }
00049     object arg= string_to_object (s_arg);
00050     learn= cons (cons (object (as_string (i)), arg), learn);
00051     cmd= cons (arg, cmd);
00052     //call ("learn-interactive-arg", fun, object (i), arg);
00053   }
00054   call ("learn-interactive", fun, learn);
00055   cmd= cons (fun, cmd);
00056   exec_delayed (scheme_cmd ("(dialogue-end)"));
00057   exec_delayed (scheme_cmd (cmd));
00058 }
00059 
00060 command
00061 dialogue_command (server_rep* sv, object fun, int nr_args) {
00062   return tm_new<dialogue_command_rep> (sv, fun, nr_args);
00063 }
00064 
00065 void
00066 tm_frame_rep::dialogue_start (string name, widget wid) {
00067   if (is_nil (dialogue_win)) {
00068     string lan= get_output_language ();
00069     if (lan == "russian") lan= "english";
00070     name= translate (name, "english", lan);
00071     dialogue_wid= wid;
00072     dialogue_win= plain_window_widget (dialogue_wid, name);
00073 
00074     widget win= get_window () -> win;
00075     SI ox, oy, dx, dy, ex= 0, ey= 0;
00076     get_position (win, ox, oy);
00077     get_size (win, dx, dy);
00078     get_size (dialogue_win, ex, ey);
00079     ox += (dx - ex) >> 1;
00080     oy -= (dy - ey) >> 1;
00081     set_position (dialogue_win, ox, oy);
00082     set_visibility (dialogue_win, true);
00083   }
00084 }
00085 
00086 void
00087 tm_frame_rep::dialogue_inquire (int i, string& arg) {
00088   if (i == 0) arg= get_string_input (dialogue_wid);
00089   else {
00090     widget field_i= get_form_field (dialogue_wid, i);
00091     arg= get_string_input (field_i);
00092   }
00093 }
00094 
00095 void
00096 tm_frame_rep::dialogue_end () {
00097   if (!is_nil (dialogue_win)) {
00098     set_visibility (dialogue_win, false);
00099     destroy_window_widget (dialogue_win);
00100     dialogue_win= widget ();
00101     dialogue_wid= widget ();
00102   }
00103 }
00104 
00105 static int
00106 gcd (int i, int j) {
00107   if (i<j)  return gcd (j, i);
00108   if (j==0) return i;
00109   return gcd (j, i%j);
00110 }
00111 
00112 void
00113 tm_frame_rep::choose_file (object fun, string title, string type) {
00114   url      name= get_name_buffer ();
00115   command  cb  = dialogue_command (get_server(), fun, 1);
00116   bool     save= starts (title, "Save") || starts (title, "Export");
00117   widget   wid = file_chooser_widget (cb, type, save);
00118   if (!is_scratch (name)) {
00119     set_directory (wid, as_string (head (name)));
00120     if ((type != "image") && (type != "")) {
00121       url u= tail (name);
00122       string old_suf= suffix (u);
00123       string new_suf= format_to_suffix (type);
00124       if ((suffix_to_format (suffix (u)) != type) &&
00125          (old_suf != "") && (new_suf != ""))
00126        {
00127          u= unglue (u, N(old_suf) + 1);
00128          u= glue (u, "." * new_suf);
00129        }
00130       set_file (wid, as_string (u));
00131     }
00132   }
00133   else set_directory (wid, ".");
00134   dialogue_start (title, wid);
00135   if (type == "directory") send_keyboard_focus (get_directory (dialogue_wid));
00136   else send_keyboard_focus (get_file (dialogue_wid));
00137 }
00138 
00139 /******************************************************************************
00140 * Interactive commands
00141 ******************************************************************************/
00142 
00143 static string
00144 get_prompt (scheme_tree p, int i) {
00145   if (is_atomic (p[i]) && is_quoted (p[i]->label))
00146     return translate (scm_unquote (p[i]->label));
00147   else if (is_tuple (p[i]) && N(p[i])>0) {
00148     if (is_atomic (p[i][0]) && is_quoted (p[i][0]->label))
00149       return translate (scm_unquote (p[i][0]->label));
00150     return translate (scheme_tree_to_tree (p[i][0]));
00151   }
00152   return translate ("Input:");
00153 }
00154 
00155 static string
00156 get_type (scheme_tree p, int i) {
00157   if (is_tuple (p[i]) && N(p[i])>1 &&
00158       is_atomic (p[i][1]) && is_quoted (p[i][1]->label))
00159     return scm_unquote (p[i][1]->label);
00160   return "string";
00161 }
00162 
00163 static array<string>
00164 get_proposals (scheme_tree p, int i) {
00165   array<string> a;
00166   if (is_tuple (p[i]) && N(p[i]) >= 2) {
00167     int j, n= N(p[i]);
00168     for (j=2; j<n; j++)
00169       if (is_atomic (p[i][j]) && is_quoted (p[i][j]->label))
00170        a << scm_unquote (p[i][j]->label);
00171   }
00172   return a;
00173 }
00174 
00175 class interactive_command_rep: public command_rep {
00176   server_rep*   sv;   // the underlying server
00177   tm_window     win;  // the underlying TeXmacs window
00178   object        fun;  // the function which is applied to the arguments
00179   scheme_tree   p;    // the interactive arguments
00180   int           i;    // counter where we are
00181   array<string> s;    // feedback from interaction with user
00182 
00183 public:
00184   interactive_command_rep (
00185     server_rep* sv2, tm_window win2, object fun2, scheme_tree p2):
00186       sv (sv2), win (win2), fun (fun2), p (p2), i (0), s (N(p)) {}
00187   void apply ();
00188   tm_ostream& print (tm_ostream& out) {
00189     return out << "interactive command " << p; }
00190 };
00191 
00192 void
00193 interactive_command_rep::apply () {
00194   if ((i>0) && (s[i-1] == "#f")) return;
00195   if (i == N(p)) {
00196     object learn= null_object ();
00197     array<object> params (N(p));
00198     for (i=N(p)-1; i>=0; i--) {
00199       params[i]= string_to_object (s[i]);
00200       learn= cons (cons (object (as_string (i)), params[i]), learn);
00201     }
00202     call ("learn-interactive", fun, learn);
00203     string ret= object_to_string (call (fun, params));
00204     if (ret != "" && ret != "<unspecified>" && ret != "#<unspecified>")
00205       sv->set_message (verbatim (ret), "interactive command");
00206   }
00207   else {
00208     s[i]= string ("");
00209     string prompt= get_prompt (p, i);
00210     string type  = get_type (p, i);
00211     array<string> proposals= get_proposals (p, i);
00212     win->interactive (prompt, type, proposals, s[i], this);
00213     i++;
00214   }
00215 }
00216 
00217 void
00218 tm_frame_rep::interactive (object fun, scheme_tree p) {
00219   ASSERT (is_tuple (p), "tuple expected");
00220   if (get_preference ("interactive questions") == "popup") {
00221     int i, n= N(p);
00222     array<string> prompts (n);
00223     for (i=0; i<n; i++)
00224       prompts[i]= get_prompt (p, i);
00225     command cb= dialogue_command (get_server(), fun, n);
00226     widget wid= inputs_list_widget (cb, prompts);
00227     for (i=0; i<n; i++) {
00228       widget input_wid= get_form_field (wid, i);
00229       set_input_type (input_wid, get_type (p, i));
00230       array<string> proposals= get_proposals (p, i);
00231       int j, k= N(proposals);
00232       if (k > 0) set_string_input (input_wid, proposals[0]);
00233       for (j=0; j<k; j++) add_input_proposal (input_wid, proposals[j]);
00234     }
00235     string title= translate ("Enter data");
00236     if (ends (prompts[0], "?")) title= translate ("Question");
00237     dialogue_start (title, wid);
00238     send_keyboard_focus (get_form_field (dialogue_wid, 0));
00239   }
00240   else {
00241     if (get_window () -> get_interactive_mode ()) beep ();
00242     else {
00243       command interactive_cmd=
00244        tm_new<interactive_command_rep> (this, get_window (), fun, p);
00245       interactive_cmd ();
00246     }
00247   }
00248 }