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,¤t_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