1 #include "config.h"
2 #include "giacPCH.h"
3 #ifdef KHICAS
4 #include "kdisplay.h"
5 #include <string.h>
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <math.h>
9 #include <ctype.h>
10 
11 #ifndef NO_NAMESPACE_GIAC
12 namespace giac {
13 #endif // ndef NO_NAMESPACE_GIAC
new_tableur(GIAC_CONTEXT)14   xcas::tableur * new_tableur(GIAC_CONTEXT){
15     xcas::tableur * sheetptr=new xcas::tableur;
16 #ifdef NUMWORKS
17     sheetptr->nrows=14; sheetptr->ncols=4;
18 #else
19     sheetptr->nrows=20; sheetptr->ncols=5;
20 #endif
21     gen g=vecteur(sheetptr->ncols);
22     sheetptr->m=makefreematrice(vecteur(sheetptr->nrows,g));
23     makespreadsheetmatrice(sheetptr->m,contextptr);
24     sheetptr->cur_row=sheetptr->cur_col=sheetptr->disp_row_begin=sheetptr->disp_col_begin=0;
25     sheetptr->sel_row_begin=sheetptr->sel_col_begin=-1;
26     sheetptr->cmd_pos=sheetptr->cmd_row=sheetptr->cmd_col=-1;
27     sheetptr->changed=false;
28     sheetptr->recompute=true;
29     sheetptr->matrix_fill_cells=true;
30     sheetptr->movedown=true;
31     sheetptr->filename="session";
32     return sheetptr;
33   }
current_sheet(const gen & g,GIAC_CONTEXT)34   gen current_sheet(const gen & g,GIAC_CONTEXT){
35     if (!xcas::sheetptr)
36       xcas::sheetptr=new_tableur(contextptr);
37     xcas::tableur & t=*xcas::sheetptr;
38     if (ckmatrix(g,true)){
39       t.m=*g._VECTptr;
40       //makespreadsheetmatrice(t.m,contextptr);
41       t.cur_row=t.cur_col=0;
42       t.nrows=t.m.size();
43       t.ncols=t.m.front()._VECTptr->size();
44       t.sel_row_begin=-1;
45       t.cmd_row=t.cmd_pos=-1;
46       return 1;
47     }
48     int r,c;
49     if (iscell(g,c,r,contextptr)){
50       if (r>=t.nrows||c>=t.ncols)
51 	return undef;
52       gen tmp=t.m[r];
53       tmp=tmp[c];
54       return tmp[1];
55     }
56     if (g.type==_VECT && g.subtype==0 && g._VECTptr->empty())
57       return gen(extractmatricefromsheet(t.m,false),_SPREAD__VECT);
58     gen m(extractmatricefromsheet(t.m),_MATRIX__VECT);
59     if (g.type==_VECT && g._VECTptr->empty())
60       return m;
61     return m[g];
62   }
63   static const char _current_sheet_s []="current_sheet";
64   static define_unary_function_eval(__current_sheet,&current_sheet,_current_sheet_s);
65   define_unary_function_ptr5( at_current_sheet ,alias_at_current_sheet,&__current_sheet,_QUOTE_ARGUMENTS,true);
66 
67 #ifndef NO_NAMESPACE_GIAC
68 }
69 #endif // ndef NO_NAMESPACE_GIAC
70 
71 
72 using namespace std;
73 using namespace giac;
74 using namespace xcas;
75 
76 #if 0
77 int ext_main(){
78   while (1){
79     statuslinemsg("Numworks loader");
80     drawRectangle(0,0,LCD_WITH_PX,LCD_HEIGHT_PX,_BLACK);
81     os_draw_string(0,20,_WHITE,_BLACK,"1. Khicas shell");
82     os_draw_string(0,40,_WHITE,_BLACK,"2. Epsilon (Numworks HOME)");
83     int k=getkey(1);
84     if (k=='1' ) run_epsilon();
85     if (k=='2') caseval("*");
86   }
87 }
88 #else
ext_main()89 int ext_main(){
90   caseval("*");
91   return 0;
92 }
93 #endif
94 
95 unsigned short mmind_col[]={COLOR_BLUE,COLOR_RED,COLOR_MAGENTA,COLOR_GREEN,COLOR_CYAN,COLOR_YELLOW};
96 
mastermind_disp(const vector<int> & solution,const vector<vector<int>> & essais,const vector<int> & essai,bool fulldisp,GIAC_CONTEXT)97 void mastermind_disp(const vector<int> & solution,const vector< vector<int> > & essais,const vector<int> & essai,bool fulldisp,GIAC_CONTEXT){
98   int x0=30,y0=30;
99   if (fulldisp)
100     drawRectangle(0,0,LCD_WIDTH_PX,LCD_HEIGHT_PX,_WHITE);
101   else
102     drawRectangle(0,y0+6*20,LCD_WIDTH_PX,LCD_HEIGHT_PX-(y0+4*20),_WHITE);
103   if (fulldisp){
104     // grille
105     for (int i=y0;i<=y0+4*20;i+=20)
106       draw_line(x0,i,x0+12*20,i,_BLACK);
107     for (int j=x0;j<=x0+12*20;j+=20)
108       draw_line(j,y0,j,y0+4*20,_BLACK);
109     // affichage des coups precedents et resultats
110     for (int c=0;c<essais.size();++c){
111       const vector<int> & essai=essais[c];
112       for (int i=0;i<4;++i){
113 	draw_filled_circle(x0+20*c+10,y0+20*i+10,10,mmind_col[essai[i]],true,true,contextptr);
114       }
115       // resultats
116       vector<int> S(solution),E(essai);
117       // bien places
118       int bien=0;
119       for (int i=0;i<S.size();++i){
120 	if (S[i]==E[i]){
121 	  ++bien;
122 	  S.erase(S.begin()+i);
123 	  E.erase(E.begin()+i);
124 	  --i;
125 	}
126       }
127       // mal places
128       int mal=0;
129       sort(S.begin(),S.end());
130       sort(E.begin(),E.end());
131       int s=0,e=0;
132       for (;;){
133 	if (s>=S.size() || e>=E.size())
134 	  break;
135 	if (S[s]==E[e]){
136 	  ++mal;
137 	  ++s; ++e;
138 	  continue;
139 	}
140 	if (S[s]<E[e])
141 	  ++s;
142 	else
143 	  ++e;
144       }
145       char buf[2]={0,0};
146       buf[0]='0'+bien;
147       os_draw_string(x0+20*c+3,y0+20*4+2,COLOR_GREEN,_WHITE,buf);
148       buf[0]='0'+mal;
149       os_draw_string(x0+20*c+3,y0+20*5+2,COLOR_MAGENTA,_WHITE,buf);
150       //CERR << solution << " " << essai << " " << bien << " " << mal << endl;
151     }
152   }
153   int y=170;
154   int x=os_draw_string_small_(x0,y,"0");
155   draw_filled_circle(x+10,y+10,10,COLOR_BLUE);
156   x=os_draw_string_small_(x+30,y,"1");
157   draw_filled_circle(x+10,y+10,10,COLOR_RED);
158   x=os_draw_string_small_(x+30,y,"2");
159   draw_filled_circle(x+10,y+10,10,COLOR_MAGENTA);
160   x=os_draw_string_small_(x+30,y,"3");
161   draw_filled_circle(x+10,y+10,10,COLOR_GREEN);
162   x=os_draw_string_small_(x+30,y,"4");
163   draw_filled_circle(x+10,y+10,10,COLOR_CYAN);
164   x=os_draw_string_small_(x+30,y,"5");
165   draw_filled_circle(x+10,y+10,10,COLOR_YELLOW);
166   y += 20;
167   // affichage du coup actuel
168   for (int i=0;i<essai.size();++i)
169     draw_filled_circle(x0+20*i+10,y+10,10,mmind_col[essai[i]],true,true,contextptr);
170 }
171 
mastermind(GIAC_CONTEXT)172 int mastermind(GIAC_CONTEXT){
173   // Mastermind
174   vector<int> solution(4),essai;
175   vector< vector<int> > essais;
176   const int nbcouleurs=6;
177   const int nbessais=12;
178   for (int i=0;i<4;++i)
179     solution[i]=giac_rand(contextptr) % nbcouleurs;
180   int i=0,j=0;
181   bool fulldisp=true;
182   for (;;){
183     mastermind_disp(solution,essais,essai,fulldisp,contextptr);
184     // saisie du prochain coup
185     int key=getkey(1);
186     if (key==KEY_SHUTDOWN)
187       return key;
188     fulldisp=false;
189     if (key==KEY_CTRL_MENU)
190       return key;
191     if (key==KEY_PRGM_ACON){
192       fulldisp=true;
193       continue;
194     }
195     if (key>='0' && key<='5'){
196       if (essai.size()==4)
197 	continue;
198       essai.push_back(key-'0');
199     }
200     if (key==KEY_CTRL_EXE || key==KEY_CTRL_OK){
201       if (essai.size()==4){
202 	if (essai==solution){
203 	  char buf[16]; sprint_int(buf,essais.size());
204 	  confirm("Vous avez trouve. Essais:",buf);
205 	  return i;
206 	}
207 	fulldisp=true;
208 	essais.push_back(essai);
209 	essai.clear();
210 	if (essais.size()==nbessais){
211 	  mastermind_disp(solution,essais,essai,true,contextptr);
212 	  for (int i=0;i<solution.size();++i)
213 	    draw_filled_circle(30+20*i+10,190+20,10,mmind_col[solution[i]],true,true,contextptr);
214 	  confirm("Vous avez perdu.","La solution etait",false,140);
215 	  return -1;
216 	}
217       }
218     }
219     if (key==KEY_CTRL_DEL){
220       if (!essai.empty())
221 	essai.pop_back();
222       continue;
223     }
224   }
225   return 0;
226 }
227 
fractale(GIAC_CONTEXT)228 int fractale(GIAC_CONTEXT){
229   freeze=true;
230   int X=320,Y=222,Nmax=10;
231   double d=10;
232   if (inputdouble(lang?"Number of iterations? (default 10)":"Nombre d'iterations? (defaut 10)",d,contextptr) && d>=1 && d<=20)
233     Nmax=d;
234   double w=2.7/X;
235   double h=-1.87/Y;
236   for (int y=0;y<=Y/2;++y){
237     complex<double> c(-2.1,h*y+0.935);
238     for (int x=0;x<X;++x){
239       complex<double> z(0);
240       int j;
241       for (j=0;j<Nmax;++j){
242 	z=z*z+c;
243 	if (abs(z)>2)
244 	  break;
245       }
246       int color=126*j+2079;
247       os_set_pixel(x,y,color);
248       os_set_pixel(x,(Y-y),color);
249       c = c+w;
250     }
251     sync_screen();
252   }
253   statuslinemsg("Ecran fige. Taper EXIT");
254   getkey(1);
255   return 0;
256 }
257 
258 
khicas_addins_menu(GIAC_CONTEXT)259 int khicas_addins_menu(GIAC_CONTEXT){
260   Menu smallmenu;
261   smallmenu.numitems=7; // INCREMENT IF YOU ADD AN APPLICATION
262   // and uncomment first smallmenuitems[app_number].text="Reserved"
263   // replace by your application name
264   // and add if (smallmenu.selection==app_number-1){ call your code }
265   MenuItem smallmenuitems[smallmenu.numitems];
266   smallmenu.items=smallmenuitems;
267   smallmenu.height=12;
268   smallmenu.scrollbar=1;
269   smallmenu.scrollout=1;
270   smallmenuitems[0].text = (char*)(lang?"Tableur":"Spreadsheet");
271   smallmenuitems[1].text = (char*)(lang?"Table periodique":"Periodic table");
272   smallmenuitems[2].text = (char*)(lang?"Exemple simple: Syracuse":"Simple example; Syracuse");
273   smallmenuitems[3].text = (char*)(lang?"Exemple de jeu: Mastermind":"Game example: Mastermind");
274   smallmenuitems[4].text = (char*)(lang?"Fractale de Mandelbrot":"Mandelbrot fractal");
275   // smallmenuitems[4].text = (char*)"Reserverd";
276   // smallmenuitems[5].text = (char*)"Reserverd";
277   // smallmenuitems[6].text = (char*)"Reserverd";
278   // smallmenuitems[7].text = (char*)"Reserverd";
279   // smallmenuitems[8].text = (char*)"Reserverd";
280   // smallmenuitems[9].text = (char*)"Reserverd";
281   // smallmenuitems[10].text = (char*)"Reserverd";
282   smallmenuitems[smallmenu.numitems-2].text = (char*)(lang?"Quitter le menu":"Leave menu");
283   smallmenuitems[smallmenu.numitems-1].text = (char*)(lang?"Quitter KhiCAS":"Leave KhiCAS");
284   while(1) {
285     int sres = doMenu(&smallmenu);
286     if(sres == MENU_RETURN_SELECTION || sres==KEY_CTRL_EXE) {
287       if (smallmenu.selection==smallmenu.numitems){
288 	return KEY_CTRL_MENU;
289       }
290       if (smallmenu.selection==1)
291 	sheet(contextptr);
292       if (smallmenu.selection==4)
293 	mastermind(contextptr);
294       if (smallmenu.selection==5)
295 	fractale(contextptr);
296       if (smallmenu.selection==3){
297 	// Exemple simple d'application tierce: la suite de Syracuse
298 	// on entre la valeur de u0
299 	double d; int i;
300 	for (;;){
301 	  inputdouble(gettext("Suite de Syracuse. u0?"),d,contextptr);
302 	  i=(d);
303 	  if (i==d)
304 	    break;
305 	  confirm(gettext("u0 doit etre entier!"),gettext("Recommencez"));
306 	}
307 	i=max(i,1);
308 	vecteur v(1,i); // initialise une liste avec u0
309 	while (i!=1){
310 	  if (i%2)
311 	    i=3*i+1;
312 	  else
313 	    i=i/2;
314 	  v.push_back(i);
315 	}
316 	// representation graphique de la liste
317 	displaygraph(_listplot(v,contextptr),contextptr);
318 	// on entre la liste en ligne de commande
319 	Console_Input(gen(v).print(contextptr).c_str());
320       }
321       if (smallmenu.selection==2){
322 	const char * name,*symbol;
323 	char protons[32],nucleons[32],mass[32],electroneg[32];
324 	int res=periodic_table(name,symbol,protons,nucleons,mass,electroneg);
325 	if (!res)
326 	  continue;
327 	char console_buf[64]={0};
328 	char * ptr=console_buf;
329 	if (res & 1)
330 	  ptr=strcpy(ptr,name)+strlen(ptr);
331 	if (res & 2){
332 	  if (res & 1)
333 	    ptr=strcpy(ptr,",")+strlen(ptr);
334 	  ptr=strcpy(ptr,symbol)+strlen(ptr);
335 	}
336 	if (res & 4){
337 	  if (res&3)
338 	    ptr=strcpy(ptr,",")+strlen(ptr);
339 	  ptr=strcpy(ptr,protons)+strlen(ptr);
340 	}
341 	if (res & 8){
342 	  if (res&7)
343 	    ptr=strcpy(ptr,",")+strlen(ptr);
344 	  ptr=strcpy(ptr,nucleons)+strlen(ptr);
345 	}
346 	if (res & 16){
347 	  if (res&15)
348 	    ptr=strcpy(ptr,",")+strlen(ptr);
349 	  ptr=strcpy(ptr,mass+2)+strlen(ptr);
350 	  ptr=strcpy(ptr,"_(g/mol)")+8;
351 	}
352 	if (res & 32){
353 	  if (res&31)
354 	    ptr=strcpy(ptr,",")+strlen(ptr);
355 	  ptr=strcpy(ptr,electroneg+4)+strlen(ptr);
356 	}
357 	return Console_Input(console_buf);
358       }
359     } // end sres==menu_selection
360     Console_Disp(1,contextptr);
361     break;
362   } // end endless while
363   return CONSOLE_SUCCEEDED;
364 }
365 
366 /* **************************
367    * SPREADSHEET CODE       *
368    ************************** */
369 const int row_height=20;
370 const int col_width=60;
printcell(int i,int j)371 string printcell(int i,int j){
372   string s="";
373   s+=('A'+j);
374   s+=print_INT_(i);
375   return s;
376 }
printsel(int r,int c,int R,int C)377 string printsel(int r,int c,int R,int C){
378   return printcell(r,c)+":"+printcell(R,C);
379 }
380 
change_undo(tableur & t)381 void change_undo(tableur & t){
382   t.undo=t.m;
383   t.changed=true;
384 }
385 
save_sheet(tableur & t,GIAC_CONTEXT)386 void save_sheet(tableur & t,GIAC_CONTEXT){
387   string s=gen(extractmatricefromsheet(t.m,false),_SPREAD__VECT).print(contextptr);
388   string filename(remove_path(remove_extension(t.filename)));
389   filename+=".tab";
390 #ifdef NSPIRE_NEWLIB
391   filename+=".tns";
392 #endif
393   write_file(filename.c_str(),s.c_str(),s.size());
394 }
sheet_status(tableur & t,GIAC_CONTEXT)395 void sheet_status(tableur & t,GIAC_CONTEXT){
396   string st;
397   if (python_compat(contextptr))
398     st="Py ";
399   else
400     st="Xcas ";
401   if (t.var.type==_IDNT)
402     st += t.var.print(contextptr);
403   else
404     st += "<>";
405   st += ' ';
406   st += t.filename ;
407   st += " R";
408   st += print_INT_(t.nrows);
409   st += " C";
410   st += print_INT_(t.ncols);
411   if (t.changed)
412     st += " *";
413   else
414     st += " -";
415   if (t.sel_row_begin>=0)
416     st += (lang==1)?" esc: annule selection":" esc: cancel selection";
417   else {
418     if (t.cmd_row>=0)
419       st += (lang==1)?" esc: annule ligne cmd":" esc: cancel cmdline";
420   }
421   statuslinemsg(st.c_str());
422 }
sheet_display(tableur & t,GIAC_CONTEXT)423 bool sheet_display(tableur &t,GIAC_CONTEXT){
424   drawRectangle(0,0,LCD_WIDTH_PX,LCD_HEIGHT_PX,_WHITE);
425   int y=0;
426   draw_line(0,y,LCD_WIDTH_PX,y,_BLACK);
427   y+=row_height;
428   int disp_rows=LCD_HEIGHT_PX/row_height-3;
429   int disp_cols=LCD_WIDTH_PX/(col_width+4)-1;
430   if (t.disp_row_begin>t.cur_row)
431     t.disp_row_begin=t.cur_row;
432   if (t.disp_row_begin<t.cur_row-disp_rows+1)
433     t.disp_row_begin=t.cur_row-disp_rows+1;
434   if (t.disp_col_begin>t.cur_col)
435     t.disp_col_begin=t.cur_col;
436   if (t.disp_col_begin<t.cur_col-disp_cols+1)
437     t.disp_col_begin=t.cur_col-disp_cols+1;
438   int I=giacmin(giacmin(t.nrows,t.m.size()),t.disp_row_begin+disp_rows);
439   bool has_sel=t.sel_row_begin>=0 && t.sel_row_begin<t.nrows;
440   int sel_r=t.sel_row_begin,sel_R=t.cur_row,sel_c=t.sel_col_begin,sel_C=t.cur_col;
441   if (sel_r>sel_R)
442     swapint(sel_r,sel_R);
443   if (sel_c>sel_C)
444     swapint(sel_c,sel_C);
445   bool has_cmd=t.cmd_row>=0 && t.cmd_row<t.nrows;
446   for (int i=t.disp_row_begin;i<I;++i){
447     os_draw_string(4,y,_BLACK,_WHITE,print_INT_(i).c_str());
448     gen g=t.m[i];
449     if (g.type!=_VECT)
450       return false;
451     vecteur & v=*g._VECTptr;
452     int J=giacmin(t.ncols,v.size());
453     J=giacmin(J,t.disp_col_begin+disp_cols);
454     int x=col_width;
455     bool drawcol=i==t.disp_row_begin;
456     for (int j=t.disp_col_begin;j<J;++j){
457       if (drawcol){
458 	draw_line(x,0,x,(1+disp_rows)*row_height,_BLACK);
459 	char colname[3]="A";
460 	colname[0]+=j;
461 	os_draw_string(x+col_width/2-4,2,_BLACK,_WHITE,colname);
462       }
463       gen vj=v[j];
464       if (vj.type==_VECT && vj._VECTptr->size()==3){
465 	bool iscur=i==t.cur_row && j==t.cur_col;
466 	string s;
467 	if (iscur){
468 	  if (!has_cmd)
469 	    t.cmdline=(*vj._VECTptr)[0].print(contextptr);
470 	}
471 	bool rev=has_sel?(sel_r<=i && i<=sel_R && sel_c<=j && j<=sel_C):iscur;
472 	if (rev)
473 	  drawRectangle(x,y,col_width+4,row_height,_BLACK);
474 	s=(*vj._VECTptr)[1].print(contextptr);
475 	int dx=os_draw_string(0,0,0,0,s.c_str(),true); // find width
476 	if (dx<col_width)
477 	  os_draw_string(x+2,y,rev?_WHITE:_BLACK,rev?_BLACK:_WHITE,s.c_str(),false); // draw
478 	else {
479 	  if (iscur && !has_sel && t.cmd_row<0)
480 	    statuslinemsg(s.c_str());
481 	  s=s.substr(0,8)+"...";
482 	  os_draw_string_small(x+2,y,rev?_WHITE:_BLACK,rev?_BLACK:_WHITE,s.c_str(),false); // draw
483 	}
484       }
485       x+=col_width+4;
486     }
487     draw_line(0,y,LCD_WIDTH_PX,y,_BLACK);
488     y+=row_height;
489   }
490   draw_line(0,y,LCD_WIDTH_PX,y,_BLACK);
491   string s;
492   if (has_sel)
493     s=printsel(sel_r,sel_c,sel_R,sel_C);
494   else
495     s=printcell(t.cur_row,t.cur_col);
496   os_draw_string(2,1,_BLACK,_WHITE,s.c_str(),false);
497   // commandline
498   s=t.cmdline;
499   int dx=os_draw_string(0,0,0,0,s.c_str(),true),xend=2; // find width
500   bool small=dx>=LCD_WIDTH_PX-50;
501   if (t.cmd_row>=0 && t.cmd_pos>=0 && t.cmd_pos<=s.size()){
502     xend=os_draw_string(xend,LCD_HEIGHT_PX-2*row_height,_BLUE,_WHITE,printcell(t.cmd_row,t.cmd_col).c_str())+5;
503     string s1=s.substr(0,t.cmd_pos)+"|";
504     if (small)
505       xend=os_draw_string_small(xend,LCD_HEIGHT_PX-2*row_height,_BLACK,_WHITE,s1.c_str(),false);
506     else
507       xend=os_draw_string(xend,LCD_HEIGHT_PX-2*row_height,_BLACK,_WHITE,s1.c_str(),false);
508     s=s.substr(t.cmd_pos,s.size()-t.cmd_pos);
509     if (has_sel){
510       s1=printsel(sel_r,sel_c,sel_R,sel_C);
511       xend=os_draw_string_small(xend,LCD_HEIGHT_PX+2-2*row_height,_WHITE,_BLACK,s1.c_str(),false);
512     }
513     else {
514       if (t.cmd_row!=t.cur_row || t.cmd_col!=t.cur_col)
515 	xend=os_draw_string_small(xend,LCD_HEIGHT_PX+2-2*row_height,_WHITE,_BLACK,printcell(t.cur_row,t.cur_col).c_str(),false);
516     }
517   } // end cmdline active
518   else
519     xend=os_draw_string(xend,LCD_HEIGHT_PX-2*row_height,_BLACK,_WHITE,printcell(t.cur_row,t.cur_col).c_str())+5;
520   int bg=t.cmd_row>=0?_WHITE:57051;
521   if (small)
522     xend=os_draw_string_small(xend,LCD_HEIGHT_PX-2*row_height,_BLACK,bg,s.c_str(),false);
523   else
524     xend=os_draw_string(xend,LCD_HEIGHT_PX-2*row_height,_BLACK,bg,s.c_str(),false);
525   // fast menus
526   string menu("shift-1 stat1d|2 stat2d|3 seq|4 edit|5 view|6 graph|7 R|8 list| ");
527   bg=52832;
528   drawRectangle(0,205,LCD_WIDTH_PX,17,bg);
529   os_draw_string_small(0,205,_BLACK,bg,menu.c_str());
530   return true;
531 }
532 
activate_cmdline(tableur & t)533 void activate_cmdline(tableur & t){
534   if (t.cmd_row==-1){
535     t.cmd_row=t.cur_row;
536     t.cmd_col=t.cur_col;
537     t.cmd_pos=t.cmdline.size();
538   }
539 }
540 
sheet_eval(tableur & t,GIAC_CONTEXT,bool ckrecompute=true)541 bool sheet_eval(tableur & t,GIAC_CONTEXT,bool ckrecompute=true){
542   t.changed=true;
543   if (!ckrecompute || t.recompute)
544     spread_eval(t.m,contextptr);
545   return true;
546 }
547 
copy_right(tableur & t,GIAC_CONTEXT)548 void copy_right(tableur & t,GIAC_CONTEXT){
549   int R=t.cur_row,C=t.cur_col,c=t.ncols;
550   vecteur v=*t.m[R]._VECTptr;
551   gen g=v[C];
552   for (int i=C+1;i<c;++i){
553     v[i]=freecopy(g);
554   }
555   t.m[R]=v;
556   sheet_eval(t,contextptr,true);
557 }
558 
copy_down(tableur & t,GIAC_CONTEXT)559 void copy_down(tableur & t,GIAC_CONTEXT){
560   int R=t.cur_row,C=t.cur_col,r=giacmin(t.nrows,t.m.size());
561   gen g=t.m[R][C];
562   for (int i=R+1;i<r;++i){
563     vecteur v=*t.m[i]._VECTptr;
564     v[C]=freecopy(g);
565     t.m[i]=v;
566   }
567   sheet_eval(t,contextptr,true);
568 }
569 
paste(tableur & t,const matrice & m,GIAC_CONTEXT)570 void paste(tableur & t,const matrice & m,GIAC_CONTEXT){
571   int r=t.cur_row,c=t.cur_col,R=t.nrows,C=t.ncols;
572   int dr=t.clip.size(),dc=0;
573   if (r+dr>R)
574     dr=R-r;
575   if (dr && ckmatrix(m,true)){
576     dc=m.front()._VECTptr->size();
577     if (c+dc>C)
578       dc=C-c;
579     if (dc){
580       for (int i=0;i<dr;++i){
581 	const vecteur & w=*m[i]._VECTptr;
582 	vecteur v=*t.m[r+i]._VECTptr;
583 	for (int j=0;j<dc;++j)
584 	  v[c+j]=w[j];
585 	t.m[r+i]=v;
586       }
587     }
588   }
589   sheet_eval(t,contextptr,true);
590 }
591 
paste(tableur & t,GIAC_CONTEXT)592 void paste(tableur & t,GIAC_CONTEXT){
593   paste(t,t.clip,contextptr);
594 }
595 
596 void sheet_pntv(const vecteur & v,vecteur & res);
sheet_pnt(const gen & g,vecteur & res)597 void sheet_pnt(const gen & g,vecteur & res){
598   if (g.type==_VECT)
599     sheet_pntv(*g._VECTptr,res);
600   if (g.is_symb_of_sommet(at_pnt))
601     res.push_back(g);
602 }
603 
sheet_pntv(const vecteur & v,vecteur & res)604 void sheet_pntv(const vecteur & v,vecteur & res){
605   for (int i=0;i<v.size();++i){
606     sheet_pnt(v[i],res);
607   }
608 }
609 
resizesheet(tableur & t)610 void resizesheet(tableur &t){
611   int cur_r=t.m.size(),cur_c=t.m.front()._VECTptr->size(),nr=t.nrows,nc=t.ncols;
612   if (nr!=cur_r || nc!=cur_c){
613     if (do_confirm(((lang==1?"Redimensionner ":"Resize ")+print_INT_(cur_r)+"x"+print_INT_(cur_c)+"->"+print_INT_(nr)+"x"+print_INT_(nc)).c_str())){
614       vecteur fill(3,0);
615       if (nr<cur_r) // erase rows
616 	t.m.resize(nr);
617       else {
618 	for (;cur_r<nr;++cur_r){
619 	  vecteur tmp;
620 	  for (int j=0;j<nc;++j)
621 	    tmp.push_back(freecopy(fill));
622 	  t.m.push_back(tmp);
623 	}
624       }
625       for (int i=0;i<nr;++i){
626 	vecteur & v=*t.m[i]._VECTptr;
627 	int cur_c=v.size();
628 	if (nc<cur_c){
629 	  t.m[i]=vecteur(v.begin(),v.begin()+nc);
630 	}
631 	else {
632 	  for (;cur_c<nc;++cur_c)
633 	    v.push_back(freecopy(fill));
634 	}
635       }
636       t.cur_row=giacmin(t.cur_row,t.nrows);
637       t.cur_col=giacmin(t.cur_col,t.ncols);
638       t.cmd_pos=t.cmd_row=t.sel_row_begin=-1;
639     } // end confirmed table resize
640     else {
641       t.nrows=cur_r;
642       t.ncols=cur_c;
643     }
644   }
645 }
646 
sheet_menu_setup(tableur & t,GIAC_CONTEXT)647 void sheet_menu_setup(tableur & t,GIAC_CONTEXT){
648   Menu smallmenu;
649   smallmenu.numitems=7;
650   MenuItem smallmenuitems[smallmenu.numitems];
651   smallmenu.items=smallmenuitems;
652   smallmenu.height=12;
653   smallmenu.scrollbar=1;
654   smallmenu.scrollout=1;
655   smallmenu.title = (char*)(lang==1?"Configuration tableur":"Sheet config");
656   smallmenuitems[3].type = MENUITEM_CHECKBOX;
657   smallmenuitems[3].text = (char*)"Reeval";
658   smallmenuitems[4].type = MENUITEM_CHECKBOX;
659   smallmenuitems[4].text = (char*)(lang==1?"Matrice: remplir cellules":"Matrix: fill cells");
660   smallmenuitems[5].type = MENUITEM_CHECKBOX;
661   smallmenuitems[5].text = (char*)(lang==1?"Deplacement vers le bas":"Move down");
662   smallmenuitems[smallmenu.numitems-1].text = (char*) "Quit";
663   while(1) {
664     string dig("Digits (in Xcas): ");
665     dig += print_INT_(decimal_digits(contextptr));
666     smallmenuitems[0].text = (char*)dig.c_str();
667     string nrows((lang==1?"Lignes ":"Rows ")+print_INT_(t.nrows));
668     smallmenuitems[1].text = (char*)nrows.c_str();
669     string ncols((lang==1?"Colonnes ":"Cols ")+print_INT_(t.ncols));
670     smallmenuitems[2].text = (char*)ncols.c_str();
671     smallmenuitems[3].value = t.recompute;
672     smallmenuitems[4].value = t.matrix_fill_cells;
673     smallmenuitems[5].value = t.movedown;
674     int sres = doMenu(&smallmenu);
675     if (sres==MENU_RETURN_EXIT){
676       resizesheet(t);
677       break;
678     }
679     if (sres == MENU_RETURN_SELECTION  || sres==KEY_CTRL_EXE) {
680       if (smallmenu.selection == 1){
681 	double d=decimal_digits(contextptr);
682 	if (inputdouble("Nombre de digits?",d,contextptr) && d==int(d) && d>0){
683 	  decimal_digits(d,contextptr);
684 	}
685 	continue;
686       }
687       if (smallmenu.selection == 2){
688 	double d=t.nrows;
689 	if (inputdouble((lang==1?"Nombre de lignes?":"Rows?"),d,contextptr) && d==int(d) && d>0){
690 	  t.nrows=d;
691 	}
692 	continue;
693       }
694       if (smallmenu.selection == 3){
695 	double d=t.nrows;
696 	if (inputdouble((lang==1?"Nombre de lignes?":"Rows?"),d,contextptr) && d==int(d) && d>0){
697 	  t.nrows=d;
698 	}
699 	continue;
700       }
701       if (smallmenu.selection == 4){
702 	t.recompute=!t.recompute;
703 	continue;
704       }
705       if (smallmenu.selection==5){
706 	t.matrix_fill_cells=!t.matrix_fill_cells;
707 	continue;
708       }
709       if (smallmenu.selection == 6){
710 	t.movedown=!t.movedown;
711 	continue;
712       }
713       if (smallmenu.selection == smallmenu.numitems){
714 	change_undo(t);
715 	resizesheet(t);
716 	break;
717       }
718     }
719   } // end endless while
720 }
721 
sheet_graph(tableur & t,GIAC_CONTEXT)722 void sheet_graph(tableur &t,GIAC_CONTEXT){
723   vecteur v;
724   sheet_pnt(t.m,v);
725   gen g(v);
726   check_do_graph(g,2,contextptr);
727 }
728 
sheet_menu_menu(tableur & t,GIAC_CONTEXT)729 int sheet_menu_menu(tableur & t,GIAC_CONTEXT){
730   t.cmd_row=-1; t.cmd_pos=-1; t.sel_row_begin=-1;
731   Menu smallmenu;
732   smallmenu.numitems=14;
733   MenuItem smallmenuitems[smallmenu.numitems];
734   smallmenu.items=smallmenuitems;
735   smallmenu.height=12;
736   //smallmenu.width=24;
737   smallmenu.scrollbar=1;
738   smallmenu.scrollout=1;
739   smallmenu.title = (char*)(lang==1?"Esc: annule menu tableur":"Esc: cancel sheet menu");
740   smallmenuitems[0].text = (char *)(lang==1?"Sauvegarder tableur":"Save sheet");
741   smallmenuitems[1].text = (char *)(lang==1?"Sauvegarder tableur comme":"Save sheet as");
742   smallmenuitems[2].text = (char*)(lang==1?"Charger":"Load");
743   string cell=(lang==1?"Editer cellule ":"Edit cell ")+printcell(t.cur_row,t.cur_col);
744   smallmenuitems[3].text = (char*)cell.c_str();
745   smallmenuitems[4].text = (char*)(lang==1?"Voir graphique (shift 6)":"View graph (shift 4)");
746   smallmenuitems[5].text = (char*)(lang==1?"Copier vers le bas (ctrl D)":"Copy down (ctrl D)");
747   smallmenuitems[6].text = (char*)(lang==1?"Copier vers la droite (ctrl R)":"Copy right (ctrl R)");
748   smallmenuitems[7].text = (char*)(lang==1?"Inserer une ligne":"Insert row");
749   smallmenuitems[8].text = (char*)(lang==1?"Inserer une colonne":"Insert column");
750   smallmenuitems[9].text = (char*)(lang==1?"Effacer ligne courante":"Remove current row");
751   smallmenuitems[10].text = (char*)(lang==1?"Effacer colonne courante":"Remove current column");
752   smallmenuitems[11].text = (char*)(lang==1?"Remplir le tableau de 0":"Fill sheet with 0");
753   smallmenuitems[smallmenu.numitems-2].text = (char*) "Config";
754   smallmenuitems[smallmenu.numitems-1].text = (char*) (lang==1?"Quitter tableur":"Leave sheet");
755   while(1) {
756     int sres = doMenu(&smallmenu);
757     if (sres==MENU_RETURN_EXIT)
758       return -1;
759     if (sres == MENU_RETURN_SELECTION  || sres==KEY_CTRL_EXE) {
760       if (smallmenu.selection == 1){
761 	// save
762 	save_sheet(t,contextptr);
763 	return -1;
764       }
765       if (smallmenu.selection == 2 ){
766 	// save
767 	char buf[270];
768 	if (get_filename(buf,".tab")){
769 	  t.filename=remove_path(remove_extension(buf));
770 	  save_sheet(t,contextptr);
771 	  return -1;
772 	}
773       }
774       if (smallmenu.selection== 3 && !exam_mode) {
775 	char filename[128];
776 	if (giac_filebrowser(filename,"tab",(lang==1?"Fichiers tableurs":"Sheet files"))){
777 	  if (t.changed && do_confirm(lang==1?"Sauvegarder le tableur actuel?":"Save current sheet?"))
778 	    save_sheet(t,contextptr);
779 	  const char * s=read_file(filename);
780 	  if (s){
781 	    gen g(s,contextptr);
782 	    g=eval(g,1,contextptr);
783 	    if (ckmatrix(g,true)){
784 	      t.filename=filename;
785 	      t.m=*g._VECTptr;
786 	      t.nrows=t.m.size();
787 	      t.ncols=t.m.front()._VECTptr->size();
788 	      t.cur_col=t.cur_row=0;
789 	      t.sel_row_begin=t.cmd_row=-1;
790 	    }
791 	    else
792 	      s=0;
793 	  }
794 	  if (!s)
795 	    do_confirm(lang==1?"Erreur de lecture du fichier":"Error reading file");
796 	}
797 	return -1;
798       } // end load
799       if (smallmenu.selection==4){
800 	activate_cmdline(t);
801 	t.cmd_pos=t.cmdline.size();
802 	return -1;
803       }
804       if (smallmenu.selection==5){
805 	sheet_graph(t,contextptr);
806 	return -1;
807       }
808       if (smallmenu.selection==6){
809 	t.cmd_pos=t.cmd_row=t.sel_row_begin=-1;
810 	copy_down(t,contextptr);
811 	return -1;
812       }
813       if (smallmenu.selection==7){
814 	t.cmd_pos=t.cmd_row=t.sel_row_begin=-1;
815 	copy_right(t,contextptr);
816 	return -1;
817       }
818       if (smallmenu.selection==8){
819 	t.cmd_pos=t.cmd_row=t.sel_row_begin=-1;
820 	change_undo(t);
821 	t.m=matrice_insert(t.m,t.cur_row,t.cur_col,1,0,makevecteur(0,0,2),contextptr);
822 	t.nrows++;
823 	return -1;
824       }
825       if (smallmenu.selection==9){
826 	t.cmd_pos=t.cmd_row=t.sel_row_begin=-1;
827 	change_undo(t);
828 	t.m=matrice_insert(t.m,t.cur_row,t.cur_col,0,1,makevecteur(0,0,2),contextptr);
829 	t.ncols++;
830 	return -1;
831       }
832       if (smallmenu.selection==10 && t.nrows>=2){
833 	t.cmd_pos=t.cmd_row=t.sel_row_begin=-1;
834 	change_undo(t);
835 	t.m=matrice_erase(t.m,t.cur_row,t.cur_col,1,0,contextptr);
836 	--t.nrows;
837 	return -1;
838       }
839       if (smallmenu.selection==11 && t.ncols>=2){
840 	t.cmd_pos=t.cmd_row=t.sel_row_begin=-1;
841 	change_undo(t);
842 	t.m=matrice_erase(t.m,t.cur_row,t.cur_col,0,1,contextptr);
843 	--t.ncols;
844 	return -1;
845       }
846       if (smallmenu.selection==12){
847 	t.cmd_pos=t.cmd_row=t.sel_row_begin=-1;
848 	change_undo(t);
849 	gen g=vecteur(t.ncols);
850 	t.m=makefreematrice(vecteur(t.nrows,g));
851 	makespreadsheetmatrice(t.m,contextptr);
852 	return -1;
853       }
854       if (smallmenu.selection == smallmenu.numitems-1){
855 	sheet_menu_setup(t,contextptr);
856 	continue;
857       }
858       if (smallmenu.selection == smallmenu.numitems){
859 	return 0;
860       }
861     }
862   } // end endless while
863   return 1;
864 }
865 
sheet_cmd(tableur & t,const char * ans)866 void sheet_cmd(tableur & t,const char * ans){
867   string s=ans;
868   if (t.sel_row_begin>=0){
869     t.cmdline="";
870     s="="+s+"matrix("+print_INT_(absint(t.sel_row_begin-t.cur_row)+1)+","+print_INT_(absint(t.sel_col_begin-t.cur_col)+1)+","+printsel(t.sel_row_begin,t.sel_col_begin,t.cur_row,t.cur_col)+")";
871     if (t.cur_row<t.sel_row_begin)
872       t.cur_row=t.sel_row_begin;
873     t.sel_row_begin=-1;
874     if (t.cur_col<t.sel_col_begin)
875       t.cur_col=t.sel_col_begin;
876     int i,j=t.cur_col;
877     // find empty cell in next rows
878     for (i=t.cur_row;i<t.nrows;++i){
879       if (is_zero(t.m[i][t.cur_col][0]))
880 	break;
881     }
882     if (i==t.nrows){
883       // find an empty cell in next columns
884       for (j=t.cur_col+1;j<t.ncols;++j){
885 	for (i=0;i<t.nrows;++i){
886 	  if (is_zero(t.m[i][j][0]))
887 	    break;
888 	}
889 	if (i<t.nrows)
890 	  break;
891       }
892     }
893     if (i<t.nrows && j<t.ncols){
894       t.cur_row=i;
895       t.cur_col=j;
896     }
897     else {
898       do_confirm((lang==1?"Impossible de trouver une cellule libre":"Could not find an empty cell"));
899       return;
900     }
901   }
902   activate_cmdline(t);
903   insert(t.cmdline,t.cmd_pos,s.c_str());
904   t.cmd_pos += s.size();
905 }
906 
sheet_cmdline(tableur & t,GIAC_CONTEXT)907 void sheet_cmdline(tableur &t,GIAC_CONTEXT){
908   gen g(t.cmdline,contextptr);
909   change_undo(t);
910   bool doit=true;
911   bool tableseq=g.is_symb_of_sommet(at_tableseq);
912   bool tablefunc=g.is_symb_of_sommet(at_tablefunc);
913   if (tableseq || t.matrix_fill_cells){
914     set_abort();
915     gen g1=protecteval(g,1,contextptr);
916     clear_abort();
917     if (g1.type==_VECT){
918       doit=false;
919       matrice & m=*g1._VECTptr;
920       if (!ckmatrix(m) && t.movedown)
921 	m=mtran(vecteur(1,m));
922       matrice clip=t.clip;
923       makespreadsheetmatrice(m,contextptr);
924       t.clip=m;
925       paste(t,contextptr);
926       t.clip=clip;
927       if (tableseq && t.cur_row+4<t.nrows){
928 	t.cur_row += 4;
929 	copy_down(t,contextptr);
930       }
931       if (tablefunc && t.cur_row+3<t.nrows && t.cur_col+1<t.ncols){
932 	t.cur_row += 3;
933 	copy_down(t,contextptr);
934 	t.cur_col++;
935 	copy_down(t,contextptr);
936       }
937     }
938   }
939   if (doit) {
940     if (t.cmd_row<t.m.size()){
941       gen v=t.m[t.cmd_row];
942       if (v.type==_VECT && t.cmd_col>=0 && t.cmd_col<v._VECTptr->size()){
943 	vecteur w=*v._VECTptr;
944 	g=spread_convert(g,t.cur_row,t.cur_col,contextptr);
945 	w[t.cmd_col]=makevecteur(g,g,0);
946 	t.m[t.cmd_row]=w;
947 	sheet_eval(t,contextptr,true);
948       }
949     }
950   }
951   t.cur_row=t.cmd_row;
952   t.cur_col=t.cmd_col;
953   t.cmd_row=-1;
954   t.cmd_pos=-1;
955   if (t.movedown){
956     ++t.cur_row;
957     if (t.cur_row>=t.nrows){
958       t.cur_row=0;
959       ++t.cur_col;
960       if (t.cur_col>=t.ncols)
961 	t.cur_col=0;
962     }
963   }
964   else {
965     ++t.cur_col;
966     if (t.cur_col>=t.ncols){
967       t.cur_col=0;
968       ++t.cur_row;
969       if (t.cur_row>=t.nrows){
970 	t.cur_row=0;
971       }
972     }
973   }
974 }
975 
sheet(GIAC_CONTEXT)976 giac::gen sheet(GIAC_CONTEXT){
977   if (!sheetptr)
978     sheetptr=new_tableur(contextptr);
979   tableur & t=*sheetptr;
980   bool status_freeze=false;
981   for (;;){
982     int R=t.cur_row,C=t.cur_col;
983     if (t.cmd_row>=0){
984       R=t.cmd_row;
985       C=t.cmd_col;
986     }
987     printcell_current_row(contextptr)=R;
988     printcell_current_col(contextptr)=C;
989     if (!status_freeze)
990       sheet_status(t,contextptr);
991     sheet_display(t,contextptr);
992     int key=getkey(1);
993     if (key==KEY_SHUTDOWN)
994       return key;
995     status_freeze=false;
996     if (key==KEY_CTRL_SETUP){
997       sheet_menu_setup(t,contextptr);
998       continue;
999     }
1000     if (key==KEY_CTRL_MENU){
1001       if (sheet_menu_menu(t,contextptr)==0)
1002 	return 0;
1003     }
1004     if (key==KEY_CTRL_EXIT){
1005       if (t.sel_row_begin>=0){
1006 	t.sel_row_begin=-1;
1007 	continue;
1008       }
1009       if (t.cmd_row>=0){
1010 	bool b= t.cmd_row==t.cur_row && t.cmd_col==t.cur_col;
1011 	t.cur_row=t.cmd_row;
1012 	t.cur_col=t.cmd_col;
1013 	if (b)
1014 	  t.cmd_row=-1;
1015 	continue;
1016       }
1017       if (!t.changed || do_confirm("Quit?"))
1018 	return 0;
1019     }
1020     switch (key){
1021     case KEY_CTRL_UNDO:
1022       std::swap(t.m,t.undo);
1023       sheet_eval(t,contextptr);
1024       continue;
1025     case KEY_CTRL_CLIP:
1026       if (t.sel_row_begin<0){
1027 	t.sel_row_begin=t.cur_row;
1028 	t.sel_col_begin=t.cur_col;
1029       }
1030       else {
1031 	int r=t.cur_row,R=t.sel_row_begin,c=t.cur_col,C=t.sel_col_begin;
1032 	if (r>R)
1033 	  swapint(r,R);
1034 	if (c>C)
1035 	  swapint(c,C);
1036 	t.clip=matrice_extract(t.m,r,c,R-r+1,C-c+1);
1037 	copy_clipboard(gen(extractmatricefromsheet(t.clip)).print(contextptr).c_str(),true);
1038 	t.sel_row_begin=-1;
1039       }
1040       continue;
1041     case KEY_CTRL_PASTE:
1042       paste(t,contextptr);
1043       status_freeze=true;
1044       continue;
1045     case KEY_SELECT_RIGHT:
1046       if (t.sel_row_begin<0){
1047 	t.sel_row_begin=t.cur_row;
1048 	t.sel_col_begin=t.cur_col;
1049       }
1050     case KEY_CTRL_RIGHT:
1051       if (t.cmd_pos>=0 && t.cmd_row==t.cur_row && t.cmd_col==t.cur_col && t.sel_row_begin==-1){
1052 	++t.cmd_pos;
1053 	if (t.cmd_pos>t.cmdline.size())
1054 	  t.cmd_pos=t.cmdline.size();
1055       }
1056       else {
1057 	++t.cur_col;
1058 	if (t.cur_col>=t.ncols)
1059 	  t.cur_col=0;
1060       }
1061       continue;
1062     case KEY_SHIFT_RIGHT:
1063       if (t.cmd_pos>=0 && t.cmd_row==t.cur_row && t.cmd_col==t.cur_col && t.sel_row_begin==-1){
1064 	t.cmd_pos=t.cmdline.size();
1065       }
1066       else
1067 	t.cur_col=t.ncols-1;
1068       break;
1069     case KEY_SELECT_LEFT:
1070       if (t.sel_row_begin<0){
1071 	t.sel_row_begin=t.cur_row;
1072 	t.sel_col_begin=t.cur_col;
1073       }
1074     case KEY_CTRL_LEFT:
1075       if (t.cmd_pos>=0 && t.cmd_row==t.cur_row && t.cmd_col==t.cur_col && t.sel_row_begin==-1){
1076 	if (t.cmd_pos>0)
1077 	  --t.cmd_pos;
1078       }
1079       else {
1080 	--t.cur_col;
1081 	if (t.cur_col<0)
1082 	  t.cur_col=t.ncols-1;
1083       }
1084       continue;
1085     case KEY_SHIFT_LEFT:
1086       if (t.cmd_pos>=0 && t.cmd_row==t.cur_row && t.cmd_col==t.cur_col && t.sel_row_begin==-1){
1087 	t.cmd_pos=0;
1088       }
1089       else {
1090 	t.cur_col=0;
1091       }
1092       break;
1093     case KEY_SELECT_UP:
1094       if (t.sel_row_begin<0){
1095 	t.sel_row_begin=t.cur_row;
1096 	t.sel_col_begin=t.cur_col;
1097       }
1098     case KEY_CTRL_UP:
1099       --t.cur_row;
1100       if (t.cur_row<0)
1101 	t.cur_row=t.nrows-1;
1102       continue;
1103     case KEY_SELECT_DOWN:
1104       if (t.sel_row_begin<0){
1105 	t.sel_row_begin=t.cur_row;
1106 	t.sel_col_begin=t.cur_col;
1107       }
1108     case KEY_CTRL_DOWN:
1109       ++t.cur_row;
1110       if (t.cur_row>=t.nrows)
1111 	t.cur_row=0;
1112       continue;
1113     case KEY_CTRL_DEL:
1114       if (t.cmd_row>=0){
1115 	if (t.cmd_pos>0){
1116 	  t.cmdline.erase(t.cmdline.begin()+t.cmd_pos-1);
1117 	  --t.cmd_pos;
1118 	}
1119       }
1120       else {
1121 	t.cmdline="";
1122 	t.cmd_row=t.cur_row;
1123 	t.cmd_col=t.cur_col;
1124 	t.cmd_pos=0;
1125       }
1126       continue;
1127     case KEY_CTRL_EXE:
1128 #if 1
1129       if (t.cmd_row<0){
1130 	sheet_eval(t,contextptr);
1131 	continue;
1132       }
1133 #else
1134       if (t.cmd_row<0){
1135 	int r=t.sel_row_begin;
1136 	if (r<0)
1137 	  return extractmatricefromsheet(t.m);
1138 	int R=t.cur_row,c=t.sel_col_begin,C=t.cur_col;
1139 	if (r>R)
1140 	  swapint(r,R);
1141 	if (c>C)
1142 	  swapint(c,C);
1143 	return extractmatricefromsheet(matrice_extract(t.m,r,c,R-r+1,C-c+1));
1144       }
1145 #endif
1146     case KEY_CTRL_OK:
1147       if (t.cmd_row>=0){
1148 	string s;
1149 	if (t.sel_row_begin>=0){
1150 	  s=printsel(t.sel_row_begin,t.sel_col_begin,t.cur_row,t.cur_col);
1151 	  t.cur_row=t.cmd_row;
1152 	  t.cur_col=t.cmd_col;
1153 	  t.sel_row_begin=-1;
1154 	}
1155 	if (t.cmd_row!=t.cur_row || t.cmd_col!=t.cur_col){
1156 	  s=printcell(t.cur_row,t.cur_col);
1157 	  t.cur_row=t.cmd_row;
1158 	  t.cur_col=t.cmd_col;
1159 	}
1160 	if (s.empty())
1161 	  sheet_cmdline(t,contextptr);
1162 	else {
1163 	  insert(t.cmdline,t.cmd_pos,s.c_str());
1164 	  t.cmd_pos+=s.size();
1165 	}
1166       } // if t.cmd_row>=0
1167       else {
1168 	t.cmd_row=t.cur_row;
1169 	t.cmd_col=t.cur_col;
1170 	t.cmd_pos=t.cmdline.size();
1171       }
1172       continue;
1173     case KEY_CTRL_F5: // view
1174       {
1175 	string value((*t.m[t.cur_row]._VECTptr)[t.cur_col][1].print(contextptr));
1176 	char buf[1024];
1177 	strcpy(buf,value.substr(0,1024-1).c_str());
1178 	textedit(buf,1024-1,contextptr );
1179       }
1180       continue;
1181     case KEY_CTRL_F4: // edit
1182       if (t.cmd_row<0 && t.sel_row_begin<0){
1183 	char buf[1024];
1184 	strcpy(buf,t.cmdline.substr(0,1024-1).c_str());
1185 	if (textedit(buf,1024-1,contextptr )){
1186 	  t.cmdline=buf;
1187 	  t.cmd_row=t.cur_row; t.cmd_col=t.cur_col;
1188 	  sheet_cmdline(t,contextptr);
1189 	}
1190       }
1191       continue;
1192     case KEY_CTRL_F6: // view graph
1193       sheet_graph(t,contextptr);
1194       continue;
1195     case KEY_CTRL_D: // copy down
1196       copy_down(t,contextptr);
1197       continue;
1198     case KEY_CTRL_R:
1199       copy_right(t,contextptr);
1200       continue;
1201     case KEY_CTRL_CATALOG: case '\t':
1202       {
1203 	if (t.cmd_pos>=0){
1204 	  string adds=help_insert(t.cmdline.substr(0,t.cmd_pos).c_str(),contextptr);
1205 	  if (!adds.empty())
1206 	    sheet_cmd(t,adds.c_str());
1207 	}
1208       }
1209       continue;
1210     } // end switch
1211     if ( (key >= KEY_CTRL_F1 && key <= KEY_CTRL_F6) ||
1212 	  (key >= KEY_CTRL_F7 && key <= KEY_CTRL_F14)
1213 	 ){
1214       const char tmenu[]= "F1 stat1d\nsum(\nmean(\nstddev(\nmedian(\nhistogram(\nbarplot(\nboxwhisker(\nF2 stat2d\nlinear_regression_plot(\nlogarithmic_regression_plot(\nexponential_regression_plot(\npower_regression_plot(\npolynomial_regression_plot(\nsin_regression_plot(\nscatterplot(\npolygonscatterplot(\nF3 seq\nrange(\nseq(\ntableseq(\nplotseq(\ntablefunc(\nrandvector(\nrandmatrix(\nF4 edt\nreserved\nF6 graph\nreserved\nF= poly\nproot(\npcoeff(\nquo(\nrem(\ngcd(\negcd(\nresultant(\nGF(\nF: arit\n mod \nirem(\nifactor(\ngcd(\nisprime(\nnextprime(\npowmod(\niegcd(\nF8 list\nmakelist(\nrange(\nseq(\nlen(\nappend(\nranv(\nsort(\napply(\nF; plot\nplot(\nplotseq(\nplotlist(\nplotparam(\nplotpolar(\nplotfield(\nhistogram(\nbarplot(\nF7 real\nexact(\napprox(\nfloor(\nceil(\nround(\nsign(\nmax(\nmin(\nF< prog\n:\n&\n#\nhexprint(\nbinprint(\nf(x):=\ndebug(\npython(\nF> cplx\nabs(\narg(\nre(\nim(\nconj(\ncsolve(\ncfactor(\ncpartfrac(\nF= misc\n!\nrand(\nbinomial(\nnormald(\nexponentiald(\n\\\n % \n\n";
1215       const char * s=console_menu(key,(char *)tmenu,0);
1216       if (s && strlen(s)){
1217 	if (t.cmd_row<0)
1218 	  t.cmdline="";
1219 	sheet_cmd(t,s);
1220       }
1221       continue;
1222     }
1223     if (key>=32 && key<128){
1224       if (t.cmd_row<0)
1225 	t.cmdline="";
1226       activate_cmdline(t);
1227       t.cmdline.insert(t.cmdline.begin()+t.cmd_pos,char(key));
1228       ++t.cmd_pos;
1229       continue;
1230     }
1231     if (const char * ans=keytostring(key,0,false,contextptr)){
1232       if (ans && strlen(ans)){
1233 	if (t.cmd_row<0)
1234 	  t.cmdline="";
1235 	sheet_cmd(t,ans);
1236       }
1237       continue;
1238     }
1239     if (key==KEY_CTRL_AC && t.cmd_row>=0){
1240       if (t.cmdline=="")
1241 	t.cmd_row=-1;
1242       t.cmdline="";
1243       t.cmd_pos=0;
1244       continue;
1245     }
1246 
1247   }
1248 }
1249 
1250 
1251 #endif
1252