1 // -*- mode:C++ ; compile-command: "g++-3.4 -I. -I.. -g -c Equation.cc -DHAVE_CONFIG_H -DIN_GIAC -Wall" -*-
2 /*
3 * Copyright (C) 2005,2014 B. Parisse, Institut Fourier, 38402 St Martin d'Heres
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18 #include "config.h"
19 #include "giacPCH.h"
20 #ifdef NSPIRE_NEWLIB
21 #include <sys/stat.h>
22 #include <sys/types.h>
23 #include <os.h>
24 #include <syscall.h>
25 #endif
26 #ifdef KHICAS
27 #include "kdisplay.h"
28 #include <string.h>
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <math.h>
32 #include <ctype.h>
33 #include "input_lexer.h"
34 #include "input_parser.h"
35 //giac::context * contextptr=0;
36 int clip_ymin=0;
37 int lang=1;
38 bool warn_nr=true;
39 bool xthetat=false;
40 bool freezeturtle=false;
41 int esc_flag=0;
42 int xcas_python_eval=0;
43 using namespace std;
44 using namespace giac;
45 const int LCD_WIDTH_PX=320;
46 const int LCD_HEIGHT_PX=222;
47 char* fmenu_cfg=0;
48 int khicas_addins_menu(GIAC_CONTEXT); // in kadd.cc
49 #ifdef MICROPY_LIB
50 extern "C" const char * const * mp_vars();
51 #endif
52
53 // Numworks Logo commands
54 #ifndef NO_NAMESPACE_GIAC
55 namespace giac {
56 #endif // ndef NO_NAMESPACE_GIAC
Bdisp_PutDisp_DD()57 void Bdisp_PutDisp_DD(){
58 sync_screen();
59 }
Bdisp_AllClr_VRAM()60 void Bdisp_AllClr_VRAM(){
61 waitforvblank();
62 drawRectangle(0,0,LCD_WIDTH_PX,LCD_HEIGHT_PX,_WHITE);
63 }
drawLine(int x1,int y1,int x2,int y2,int c)64 void drawLine(int x1,int y1,int x2,int y2,int c){
65 draw_line(x1,y1,x2,y2,c,context0);
66 }
stroke_rectangle(int x,int y,int w,int h,int c)67 void stroke_rectangle(int x,int y,int w,int h,int c){
68 drawLine(x,y,x+w,y,c);
69 drawLine(x,y+h,x+w,y+h,c);
70 drawLine(x,y,x,y+h,c);
71 drawLine(x+w,y,x+w,y+h,c);
72 }
DefineStatusMessage(const char * s,int a,int b,int c)73 void DefineStatusMessage(const char * s,int a,int b,int c){
74 statuslinemsg(s);
75 }
76
DisplayStatusArea()77 void DisplayStatusArea(){
78 sync_screen();
79 }
80
set_xcas_status()81 void set_xcas_status(){
82 statusline(1);
83 }
GetSetupSetting(int mode)84 int GetSetupSetting(int mode){
85 return 0;
86 }
87
SetSetupSetting(int mode,int)88 void SetSetupSetting(int mode,int){
89 }
90
handle_f5()91 void handle_f5(){
92 lock_alpha();
93 }
94
delete_clipboard()95 void delete_clipboard(){}
96
97 bool clip_pasted=true;
98
clipboard()99 string * clipboard(){
100 static string * ptr=0;
101 if (!ptr)
102 ptr=new string;
103 return ptr;
104 }
105
copy_clipboard(const string & s,bool status)106 void copy_clipboard(const string & s,bool status){
107 if (1 || clip_pasted) // adding to clipboard is sometimes annoying
108 *clipboard()=s;
109 else
110 *clipboard()+=s;
111 clip_pasted=false;
112 if (status){
113 DefineStatusMessage((char*)((lang==1)?"Selection copiee vers presse-papiers.":"Selection copied to clipboard"), 1, 0, 0);
114 DisplayStatusArea();
115 }
116 }
117
paste_clipboard()118 const char * paste_clipboard(){
119 clip_pasted=true;
120 return clipboard()->c_str();
121 }
122
print_msg12(const char * msg1,const char * msg2,int textY=40)123 int print_msg12(const char * msg1,const char * msg2,int textY=40){
124 drawRectangle(0, textY+10, LCD_WIDTH_PX, 44, COLOR_WHITE);
125 drawRectangle(3,textY+10,316,3, COLOR_BLACK);
126 drawRectangle(3,textY+10,3,44, COLOR_BLACK);
127 drawRectangle(316,textY+10,3,44, COLOR_BLACK);
128 drawRectangle(3,textY+54,316,3, COLOR_BLACK);
129 int textX=30;
130 if (msg1){
131 if (strlen(msg1)>=30)
132 os_draw_string_small_(textX,textY+15,msg1);
133 else
134 os_draw_string_(textX,textY+15,msg1);
135 }
136 textX=10;
137 textY+=33;
138 if (msg2){
139 if (strlen(msg2)>=30)
140 os_draw_string_small_(textX,textY,msg2);
141 else
142 textX=os_draw_string_(textX,textY,msg2);
143 }
144 return textX;
145 }
146
insert(string & s,int pos,const char * add)147 void insert(string & s,int pos,const char * add){
148 if (pos>s.size())
149 pos=s.size();
150 if (pos<0)
151 pos=0;
152 s=s.substr(0,pos)+add+s.substr(pos,s.size()-pos);
153 }
154
do_confirm(const char * s)155 bool do_confirm(const char * s){
156 #ifdef NSPIRE_NEWLIB
157 return confirm(s,((lang==1)?"enter: oui, esc:annuler":"enter: yes, esc: cancel"))==KEY_CTRL_F1;
158 #else
159 return confirm(s,((lang==1)?"OK: oui, Back:annuler":"OK: yes, Back: cancel"))==KEY_CTRL_F1;
160 #endif
161 }
162
confirm(const char * msg1,const char * msg2,bool acexit,int y)163 int confirm(const char * msg1,const char * msg2,bool acexit,int y){
164 int key=0;
165 print_msg12(msg1,msg2,y);
166 while (key!=KEY_CTRL_F1 && key!=KEY_CTRL_F6){
167 GetKey(&key);
168 if (key==KEY_SHUTDOWN)
169 return key;
170 if (key==KEY_CTRL_EXE || key==KEY_CTRL_OK)
171 key=KEY_CTRL_F1;
172 if (key==KEY_CTRL_AC || key==KEY_CTRL_EXIT || key==KEY_CTRL_MENU){
173 if (acexit) return -1;
174 key=KEY_CTRL_F6;
175 }
176 set_xcas_status();
177 }
178 return key;
179 }
180
confirm_overwrite()181 bool confirm_overwrite(){
182 #ifdef NSPIRE_NEWLIB
183 return do_confirm((lang==1)?"enter: oui, esc:annuler":"enter: yes, esc: cancel")==KEY_CTRL_F1;
184 #else
185 return do_confirm((lang==1)?"OK: oui, Back:annuler":"OK: yes, Back: cancel")==KEY_CTRL_F1;
186 #endif
187 }
188
invalid_varname()189 void invalid_varname(){
190 confirm((lang==1)?"Nom de variable incorrect":"Invalid variable name",
191 #ifdef NSPIRE_NEWLIB
192 (lang==1)?"enter: ok":"enter: ok"
193 #else
194 (lang==1)?"OK: ok":"OK: ok"
195 #endif
196 );
197 }
198
199
200 #ifdef SCROLLBAR
201 typedef scrollbar TScrollbar;
202 #endif
203
204 #define C24 18 // 24 on 90
205 #define C18 18 // 18
206 #define C10 10 // 18
207 #define C6 6 // 6
208
MB_ElementCount(const char * s)209 int MB_ElementCount(const char * s){
210 return strlen(s); // FIXME for UTF8
211 }
212
PrintXY(int x,int y,const char * s,int mode,int c=giac::_BLACK,int bg=giac::_WHITE)213 void PrintXY(int x,int y,const char * s,int mode,int c=giac::_BLACK,int bg=giac::_WHITE){
214 if (mode==TEXT_MODE_NORMAL)
215 os_draw_string(x,y,c,bg,s);
216 else
217 os_draw_string(x,y,bg,c,s);
218 }
219
PrintMiniMini(int x,int y,const char * s,int mode,int c=giac::_BLACK,int bg=giac::_WHITE,bool fake=false)220 int PrintMiniMini(int x,int y,const char * s,int mode,int c=giac::_BLACK,int bg=giac::_WHITE,bool fake=false){
221 if (mode==TEXT_MODE_NORMAL)
222 return os_draw_string_small(x,y,c,bg,s,fake);
223 else
224 return os_draw_string_small(x,y,bg,c,s,fake);
225 }
226
PrintMini(int x,int y,const char * s,int mode,int c=giac::_BLACK,int bg=giac::_WHITE,bool fake=false)227 int PrintMini(int x,int y,const char * s,int mode,int c=giac::_BLACK,int bg=giac::_WHITE,bool fake=false){
228 if (mode==TEXT_MODE_NORMAL)
229 return os_draw_string(x,y,c,bg,s,fake);
230 else
231 return os_draw_string(x,y,bg,c,s,fake);
232 }
233
printCentered(const char * text,int y)234 void printCentered(const char* text, int y) {
235 int len = strlen(text);
236 int x = LCD_WIDTH_PX/2-(len*6)/2;
237 PrintXY(x,y,text,0);
238 }
239
doMenu(Menu * menu,MenuItemIcon * icontable)240 int doMenu(Menu* menu, MenuItemIcon* icontable) { // returns code telling what user did. selection is on menu->selection. menu->selection starts at 1!
241 int itemsStartY=menu->startY; // char Y where to start drawing the menu items. Having a title increases this by one
242 int itemsHeight=menu->height;
243 int showtitle = menu->title != NULL;
244 if (showtitle) {
245 itemsStartY++;
246 itemsHeight--;
247 }
248 char keyword[5];
249 keyword[0]=0;
250 if(menu->selection > menu->scroll+(menu->numitems>itemsHeight ? itemsHeight : menu->numitems))
251 menu->scroll = menu->selection -(menu->numitems>itemsHeight ? itemsHeight : menu->numitems);
252 if(menu->selection-1 < menu->scroll)
253 menu->scroll = menu->selection -1;
254
255 while(1) {
256 // Cursor_SetFlashOff();
257 if (menu->selection <=1)
258 menu->selection=1;
259 if (menu->selection > menu->scroll+(menu->numitems>itemsHeight ? itemsHeight : menu->numitems))
260 menu->scroll = menu->selection -(menu->numitems>itemsHeight ? itemsHeight : menu->numitems);
261 if (menu->selection-1 < menu->scroll)
262 menu->scroll = menu->selection -1;
263 if(menu->statusText != NULL) DefineStatusMessage(menu->statusText, 1, 0, 0);
264 // Clear the area of the screen we are going to draw on
265 if(0 == menu->pBaRtR) {
266 int x=C10*menu->startX-1,
267 y=C24*(menu->miniMiniTitle ? itemsStartY:menu->startY)-1,
268 w=2+C10*menu->width /* + ((menu->scrollbar && menu->scrollout)?C10:0) */,
269 h=2+C24*menu->height-(menu->miniMiniTitle ? C24:0);
270 // drawRectangle(x, y, w, h, COLOR_WHITE);
271 draw_line(x,y,x+w,y,COLOR_BLACK,context0);
272 draw_line(x,y+h,x+w,y+h,COLOR_BLACK,context0);
273 draw_line(x,y,x,y+h,COLOR_BLACK,context0);
274 draw_line(x+w,y,x+w,y+h,COLOR_BLACK,context0);
275 }
276 if (menu->numitems>0) {
277 for(int curitem=0; curitem < menu->numitems; curitem++) {
278 // print the menu item only when appropriate
279 if(menu->scroll <= curitem && menu->scroll > curitem-itemsHeight) {
280 if ((curitem-menu->scroll) % 6==0)
281 waitforvblank();
282 char menuitem[256] = "";
283 if(menu->numitems>=100 || menu->type == MENUTYPE_MULTISELECT){
284 strcpy(menuitem, " "); //allow for the folder and selection icons on MULTISELECT menus (e.g. file browser)
285 strcpy(menuitem+2,menu->items[curitem].text);
286 }
287 else {
288 int cur=curitem+1;
289 if (menu->numitems<10){
290 menuitem[0]='0'+cur;
291 menuitem[1]=' ';
292 menuitem[2]=0;
293 strcpy(menuitem+2,menu->items[curitem].text);
294 }
295 else {
296 menuitem[0]=cur>=10?('0'+(cur/10)):' ';
297 menuitem[1]='0'+(cur%10);
298 menuitem[2]=' ';
299 menuitem[3]=0;
300 strcpy(menuitem+3,menu->items[curitem].text);
301 }
302 }
303 //strncat(menuitem, menu->items[curitem].text, 68);
304 if(menu->items[curitem].type != MENUITEM_SEPARATOR) {
305 //make sure we have a string big enough to have background when item is selected:
306 // MB_ElementCount is used instead of strlen because multibyte chars count as two with strlen, while graphically they are just one char, making fillerRequired become wrong
307 int fillerRequired = menu->width - MB_ElementCount(menu->items[curitem].text) - (menu->type == MENUTYPE_MULTISELECT ? 2 : 3);
308 for(int i = 0; i < fillerRequired; i++)
309 strcat(menuitem, " ");
310 drawRectangle(C10*menu->startX,C18*(curitem+itemsStartY-menu->scroll),C10*menu->width,C24,(menu->selection == curitem+1 ? _BLACK : _WHITE));
311 PrintXY(C10*menu->startX,C18*(curitem+itemsStartY-menu->scroll),menuitem, (menu->selection == curitem+1 ? TEXT_MODE_INVERT : TEXT_MODE_NORMAL));
312 } else {
313 /*int textX = (menu->startX-1) * C18;
314 int textY = curitem*C24+itemsStartY*C24-menu->scroll*C24-C24+C10;
315 clearLine(menu->startX, curitem+itemsStartY-menu->scroll, (menu->selection == curitem+1 ? textColorToFullColor(menu->items[curitem].color) : COLOR_WHITE));
316 drawLine(textX, textY+C24-4, LCD_WIDTH_PX-2, textY+C24-4, COLOR_GRAY);
317 PrintMini(&textX, &textY, (unsigned char*)menuitem, 0, 0xFFFFFFFF, 0, 0, (menu->selection == curitem+1 ? COLOR_WHITE : textColorToFullColor(menu->items[curitem].color)), (menu->selection == curitem+1 ? textColorToFullColor(menu->items[curitem].color) : COLOR_WHITE), 1, 0);*/
318 }
319 // deal with menu items of type MENUITEM_CHECKBOX
320 if(menu->items[curitem].type == MENUITEM_CHECKBOX) {
321 PrintXY(C10*(menu->startX+menu->width-4),C18*(curitem+itemsStartY-menu->scroll),
322 (menu->items[curitem].value == MENUITEM_VALUE_CHECKED ? " [+]" : " [-]"),
323 (menu->selection == curitem+1 ? TEXT_MODE_INVERT : (menu->pBaRtR == 1? TEXT_MODE_NORMAL : TEXT_MODE_NORMAL)));
324 }
325 // deal with multiselect menus
326 if(menu->type == MENUTYPE_MULTISELECT) {
327 if((curitem+itemsStartY-menu->scroll)>=itemsStartY &&
328 (curitem+itemsStartY-menu->scroll)<=(itemsStartY+itemsHeight) &&
329 icontable != NULL
330 ) {
331 #if 0
332 if (menu->items[curitem].isfolder == 1) {
333 // assumes first icon in icontable is the folder icon
334 CopySpriteMasked(icontable[0].data, (menu->startX)*C18, (curitem+itemsStartY-menu->scroll)*C24, 0x12, 0x18, 0xf81f );
335 } else {
336 if(menu->items[curitem].icon >= 0) CopySpriteMasked(icontable[menu->items[curitem].icon].data, (menu->startX)*C18, (curitem+itemsStartY-menu->scroll)*C24, 0x12, 0x18, 0xf81f );
337 }
338 #endif
339 }
340 if (menu->items[curitem].isselected) {
341 if (menu->selection == curitem+1) {
342 PrintXY(C10*menu->startX,C18*(curitem+itemsStartY-menu->scroll),"\xe6\x9b", TEXT_MODE_NORMAL);
343 } else {
344 PrintXY(C10*menu->startX,C18*(curitem+itemsStartY-menu->scroll),"\xe6\x9b", TEXT_MODE_NORMAL);
345 }
346 }
347 }
348 }
349 } // end for curitem<menu->numitem
350 int dh=menu->height-menu->numitems-(showtitle?1:0);
351 if (dh>0)
352 drawRectangle(C10*menu->startX,C24*(menu->numitems+(showtitle?1:0)),C10*menu->width,C24*dh,_WHITE);
353 if (menu->scrollbar) {
354 #ifdef SCROLLBAR
355 TScrollbar sb;
356 sb.I1 = 0;
357 sb.I5 = 0;
358 sb.indicatormaximum = menu->numitems;
359 sb.indicatorheight = itemsHeight;
360 sb.indicatorpos = menu->scroll;
361 sb.barheight = itemsHeight*C24;
362 sb.bartop = (itemsStartY-1)*C24;
363 sb.barleft = menu->startX*C18+menu->width*C18 - C18 - (menu->scrollout ? 0 : 5);
364 sb.barwidth = C10;
365 Scrollbar(&sb);
366 #endif
367 }
368 //if(menu->type==MENUTYPE_MULTISELECT && menu->fkeypage == 0) drawFkeyLabels(0x0037); // SELECT (white)
369 } else {
370 giac::printCentered(menu->nodatamsg, (itemsStartY*C24)+(itemsHeight*C24)/2-12);
371 }
372 if(showtitle) {
373 int textX = C10*menu->startX, textY=menu->startY*C24;
374 drawRectangle(textX,textY,C10*menu->width,C24,_WHITE);
375 if (menu->miniMiniTitle)
376 PrintMini( textX, textY, menu->title, 0 );
377 else
378 PrintXY(textX, textY, menu->title, TEXT_MODE_NORMAL);
379 if(menu->subtitle != NULL) {
380 int textX=(MB_ElementCount(menu->title)+menu->startX-1)*C18+C10, textY=C10;
381 PrintMini(textX, textY, menu->subtitle, 0);
382 }
383 PrintXY(textX+C10*(menu->width-5), 1, "____", 0);
384 PrintXY(textX+C10*(menu->width-5), 1, keyword, 0);
385 }
386 /*if(menu->darken) {
387 DrawFrame(COLOR_BLACK);
388 VRAMInvertArea(menu->startX*C18-C18, menu->startY*C24, menu->width*C18-(menu->scrollout || !menu->scrollbar ? 0 : 5), menu->height*C24);
389 }*/
390 if(menu->type == MENUTYPE_NO_KEY_HANDLING) return MENU_RETURN_INSTANT; // we don't want to handle keys
391 int key;
392 GetKey(&key);
393 if (key==KEY_SHUTDOWN)
394 return key;
395 if (key==KEY_CTRL_MENU){
396 menu->selection=menu->numitems;
397 return MENU_RETURN_SELECTION;
398 }
399 if (key<256 && isalpha(key)){
400 key=tolower(key);
401 int pos=strlen(keyword);
402 if (pos>=4)
403 pos=0;
404 keyword[pos]=key;
405 keyword[pos+1]=0;
406 int cur=0;
407 for (;cur<menu->numitems;++cur){
408 #if 1
409 if (strcmp(menu->items[cur].text,keyword)>=0)
410 break;
411 #else
412 char c=menu->items[cur].text[0];
413 if (key<=c)
414 break;
415 #endif
416 }
417 if (cur<menu->numitems){
418 menu->selection=cur+1;
419 if(menu->selection > menu->scroll+(menu->numitems>itemsHeight ? itemsHeight : menu->numitems))
420 menu->scroll = menu->selection -(menu->numitems>itemsHeight ? itemsHeight : menu->numitems);
421 if(menu->selection-1 < menu->scroll)
422 menu->scroll = menu->selection -1;
423 }
424 continue;
425 }
426 switch(key) {
427 case KEY_CTRL_PAGEDOWN:
428 menu->selection+=6;
429 if (menu->selection >= menu->numitems)
430 menu->selection=menu->numitems;
431 if(menu->selection > menu->scroll+(menu->numitems>itemsHeight ? itemsHeight : menu->numitems))
432 menu->scroll = menu->selection -(menu->numitems>itemsHeight ? itemsHeight : menu->numitems);
433 break;
434 case KEY_CTRL_DOWN:
435 if(menu->selection == menu->numitems)
436 {
437 if(menu->returnOnInfiniteScrolling) {
438 return MENU_RETURN_SCROLLING;
439 } else {
440 menu->selection = 1;
441 menu->scroll = 0;
442 }
443 }
444 else
445 {
446 menu->selection++;
447 if(menu->selection > menu->scroll+(menu->numitems>itemsHeight ? itemsHeight : menu->numitems))
448 menu->scroll = menu->selection -(menu->numitems>itemsHeight ? itemsHeight : menu->numitems);
449 }
450 if(menu->pBaRtR==1) return MENU_RETURN_INSTANT;
451 break;
452 case KEY_CTRL_PAGEUP:
453 menu->selection-=6;
454 if (menu->selection <=1)
455 menu->selection=1;
456 if(menu->selection-1 < menu->scroll)
457 menu->scroll = menu->selection -1;
458 break;
459 case KEY_CTRL_UP:
460 if(menu->selection == 1)
461 {
462 if(menu->returnOnInfiniteScrolling) {
463 return MENU_RETURN_SCROLLING;
464 } else {
465 menu->selection = menu->numitems;
466 menu->scroll = menu->selection-(menu->numitems>itemsHeight ? itemsHeight : menu->numitems);
467 }
468 }
469 else
470 {
471 menu->selection--;
472 if(menu->selection-1 < menu->scroll)
473 menu->scroll = menu->selection -1;
474 }
475 if(menu->pBaRtR==1) return MENU_RETURN_INSTANT;
476 break;
477 case KEY_CTRL_F1:
478 if(menu->type==MENUTYPE_MULTISELECT && menu->fkeypage == 0 && menu->numitems > 0) {
479 /*if(menu->items[menu->selection-1].isselected) {
480 menu->items[menu->selection-1].isselected=0;
481 menu->numselitems = menu->numselitems-1;
482 } else {
483 menu->items[menu->selection-1].isselected=1;
484 menu->numselitems = menu->numselitems+1;
485 }
486 return key; //return on F1 too so that parent subroutines have a chance to e.g. redraw fkeys*/
487 } else if (menu->type == MENUTYPE_FKEYS) {
488 return key;
489 }
490 break;
491 case KEY_CTRL_F2:
492 case KEY_CTRL_F3:
493 case KEY_CTRL_F4:
494 case KEY_CTRL_F5:
495 case KEY_CTRL_F6: case KEY_CTRL_CATALOG: case KEY_BOOK: case '\t':
496 case KEY_CHAR_ANS:
497 if (menu->type == MENUTYPE_FKEYS || menu->type==MENUTYPE_MULTISELECT) return key; // MULTISELECT also returns on Fkeys
498 break;
499 case KEY_CTRL_PASTE:
500 if (menu->type==MENUTYPE_MULTISELECT) return key; // MULTISELECT also returns on paste
501 case KEY_CTRL_OPTN:
502 if (menu->type==MENUTYPE_FKEYS || menu->type==MENUTYPE_MULTISELECT) return key;
503 break;
504 case KEY_CTRL_FORMAT:
505 if (menu->type==MENUTYPE_FKEYS) return key; // return on the Format key so that event lists can prompt to change event category
506 break;
507 case KEY_CTRL_RIGHT:
508 if(menu->type != MENUTYPE_MULTISELECT) return KEY_BOOK; // break;
509 // else fallthrough
510 case KEY_CTRL_EXE: case KEY_CTRL_OK:
511 if(menu->numitems>0) return key==KEY_CTRL_OK?MENU_RETURN_SELECTION:key;
512 break;
513 case KEY_CTRL_LEFT:
514 if(menu->type != MENUTYPE_MULTISELECT) break;
515 // else fallthrough
516 case KEY_CTRL_DEL:
517 if (strlen(keyword))
518 keyword[strlen(keyword)-1]=0;
519 else {
520 if (strcmp(menu->title,"Variables")==0)
521 return key;
522 }
523 break;
524 case KEY_CTRL_AC:
525 if (strlen(keyword)){
526 keyword[0]=0;
527 lock_alpha();//SetSetupSetting( (unsigned int)0x14, 0x88);
528 //DisplayStatusArea();
529 break;
530 }
531 case KEY_CTRL_EXIT:
532 return MENU_RETURN_EXIT;
533 break;
534 case KEY_CHAR_1:
535 case KEY_CHAR_2:
536 case KEY_CHAR_3:
537 case KEY_CHAR_4:
538 case KEY_CHAR_5:
539 case KEY_CHAR_6:
540 case KEY_CHAR_7:
541 case KEY_CHAR_8:
542 case KEY_CHAR_9:
543 if(menu->numitems>=(key-0x30)) {
544 menu->selection = (key-0x30);
545 if (menu->type != MENUTYPE_FKEYS) return MENU_RETURN_SELECTION;
546 }
547 break;
548 case KEY_CHAR_0:
549 if(menu->numitems>=10) {
550 menu->selection = 10;
551 if (menu->type != MENUTYPE_FKEYS) return MENU_RETURN_SELECTION;
552 }
553 break;
554 case KEY_CHAR_EXPN:
555 if(menu->numitems>=11) {
556 menu->selection = 11;
557 if (menu->type != MENUTYPE_FKEYS) return MENU_RETURN_SELECTION;
558 }
559 break;
560 case KEY_CHAR_LN:
561 if(menu->numitems>=12) {
562 menu->selection = 12;
563 if (menu->type != MENUTYPE_FKEYS) return MENU_RETURN_SELECTION;
564 }
565 break;
566 case KEY_CHAR_LOG:
567 if(menu->numitems>=13) {
568 menu->selection = 13;
569 if (menu->type != MENUTYPE_FKEYS) return MENU_RETURN_SELECTION;
570 }
571 break;
572 case KEY_CHAR_IMGNRY:
573 if(menu->numitems>=14) {
574 menu->selection = 14;
575 if (menu->type != MENUTYPE_FKEYS) return MENU_RETURN_SELECTION;
576 }
577 break;
578 case KEY_CHAR_COMMA:
579 if(menu->numitems>=15) {
580 menu->selection = 15;
581 if (menu->type != MENUTYPE_FKEYS) return MENU_RETURN_SELECTION;
582 }
583 break;
584 case KEY_CHAR_POW:
585 if(menu->numitems>=16) {
586 menu->selection = 16;
587 if (menu->type != MENUTYPE_FKEYS) return MENU_RETURN_SELECTION;
588 }
589 break;
590 case KEY_CHAR_SIN:
591 case KEY_CHAR_COS:
592 case KEY_CHAR_TAN:
593 if(menu->numitems>=(key-112)) {
594 menu->selection = (key-112);
595 if (menu->type != MENUTYPE_FKEYS) return MENU_RETURN_SELECTION;
596 }
597 break;
598 case KEY_CHAR_PI:
599 if(menu->numitems>=20) {
600 menu->selection = 20;
601 if (menu->type != MENUTYPE_FKEYS) return MENU_RETURN_SELECTION;
602 }
603 break;
604 case KEY_CHAR_ROOT:
605 if(menu->numitems>=21) {
606 menu->selection = 21;
607 if (menu->type != MENUTYPE_FKEYS) return MENU_RETURN_SELECTION;
608 }
609 break;
610 case KEY_CHAR_SQUARE:
611 if(menu->numitems>=22) {
612 menu->selection = 22;
613 if (menu->type != MENUTYPE_FKEYS) return MENU_RETURN_SELECTION;
614 }
615 break;
616 case KEY_CHAR_LPAR:
617 case KEY_CHAR_RPAR:
618 if(menu->numitems>=(key-21)) {
619 menu->selection = (key-21);
620 if (menu->type != MENUTYPE_FKEYS) return MENU_RETURN_SELECTION;
621 }
622 break;
623 }
624 }
625 return MENU_RETURN_EXIT;
626 }
627
628 #define CAT_CATEGORY_ALL 0
629 #define CAT_CATEGORY_ALGEBRA 1
630 #define CAT_CATEGORY_LINALG 2
631 #define CAT_CATEGORY_CALCULUS 3
632 #define CAT_CATEGORY_ARIT 4
633 #define CAT_CATEGORY_COMPLEXNUM 5
634 #define CAT_CATEGORY_PLOT 6
635 #define CAT_CATEGORY_POLYNOMIAL 7
636 #define CAT_CATEGORY_PROBA 8
637 #define CAT_CATEGORY_PROGCMD 9
638 #define CAT_CATEGORY_REAL 10
639 #define CAT_CATEGORY_SOLVE 11
640 #define CAT_CATEGORY_STATS 12
641 #define CAT_CATEGORY_TRIG 13
642 #define CAT_CATEGORY_OPTIONS 14
643 #define CAT_CATEGORY_LIST 15
644 #define CAT_CATEGORY_MATRIX 16
645 #define CAT_CATEGORY_PROG 17
646 #define CAT_CATEGORY_SOFUS 18
647 #define CAT_CATEGORY_PHYS 19
648 #define CAT_CATEGORY_UNIT 20
649 #define CAT_CATEGORY_LOGO 21 // should be the last one
650
init_locale()651 void init_locale(){
652 lang=1;
653 }
654
655 const catalogFunc completeCatfr[] = { // list of all functions (including some not in any category)
656 // {"cosh(x)", 0, "Hyperbolic cosine of x.", 0, 0, CAT_CATEGORY_TRIG},
657 // {"exp(x)", 0, "Renvoie e^x.", "1.2", 0, CAT_CATEGORY_REAL},
658 // {"log(x)", 0, "Logarithme naturel de x.", 0, 0, CAT_CATEGORY_REAL},
659 // {"sinh(x)", 0, "Hyperbolic sine of x.", 0, 0, CAT_CATEGORY_TRIG},
660 // {"tanh(x)", 0, "Hyperbolic tangent of x.", 0, 0, CAT_CATEGORY_TRIG},
661 {" boucle for (pour)", "for ", "Boucle definie pour un indice variant entre 2 valeurs fixees", "#\nfor ", 0, CAT_CATEGORY_PROG},
662 {" boucle liste", "for in", "Boucle sur tous les elements d'une liste.", "#\nfor in", 0, CAT_CATEGORY_PROG},
663 {" boucle while (tantque)", "while ", "Boucle indefinie tantque.", "#\nwhile ", 0, CAT_CATEGORY_PROG},
664 {" test si alors", "if ", "Test", "#\nif ", 0, CAT_CATEGORY_PROG},
665 {" test sinon", "else ", "Clause fausse du test", 0, 0, CAT_CATEGORY_PROG},
666 {" fonction def.", "f(x):=", "Definition de fonction.", "#\nf(x):=", 0, CAT_CATEGORY_PROG},
667 {" local j,k;", "local ", "Declaration de variables locales Xcas", 0, 0, CAT_CATEGORY_PROG},
668 {" range(a,b)", "in range(", "Dans l'intervalle [a,b[ (a inclus, b exclus)", "# in range(1,10)", 0, CAT_CATEGORY_PROG},
669 {" return res;", "return ", "return ou retourne quitte la fonction et renvoie le resultat res", 0, 0, CAT_CATEGORY_PROG},
670 {" edit list ", "list ", "Assistant creation de liste.", 0, 0, CAT_CATEGORY_LIST},
671 {" edit matrix ", "matrix ", "Assistant creation de matrice.", 0, 0, CAT_CATEGORY_MATRIX},
672 {" mksa(x)", 0, "Conversion en unites MKSA", 0, 0, CAT_CATEGORY_PHYS | (CAT_CATEGORY_UNIT << 8)},
673 {" ufactor(a,b)", 0, "Factorise l'unite b dans a", "100_J,1_kW", 0, CAT_CATEGORY_PHYS | (CAT_CATEGORY_UNIT << 8)},
674 {" usimplify(a)", 0, "Simplifie l'unite dans a", "100_l/10_cm^2", 0, CAT_CATEGORY_PHYS | (CAT_CATEGORY_UNIT << 8)},
675 //{"fonction def Xcas", "fonction f(x) local y; ffonction:;", "Definition de fonction.", "#fonction f(x) local y; y:=x^2; return y; ffonction:;", 0, CAT_CATEGORY_PROG},
676 {"!", "!", "Non logique (prefixe) ou factorielle de n (suffixe).", "#7!", "#!b", CAT_CATEGORY_PROGCMD},
677 {"#", "#", "Commentaire Python, en Xcas taper //. Raccourci ALPHA F2", 0, 0, CAT_CATEGORY_PROG},
678 {"%", "%", "a % b signifie a modulo b", 0, 0, CAT_CATEGORY_ARIT | (CAT_CATEGORY_PROGCMD << 8)},
679 {"&", "&", "Et logique ou +", "#1&2", 0, CAT_CATEGORY_PROGCMD},
680 {":=", ":=", "Affectation vers la gauche (inverse de =>).", "#a:=3", 0, CAT_CATEGORY_PROGCMD|(CAT_CATEGORY_SOFUS<<8)},
681 {"<", "<", "Inferieur strict. Raccourci SHIFT F2", 0, 0, CAT_CATEGORY_PROGCMD},
682 {"=>", "=>", "Affectation vers la droite ou conversion en (touche ->). Par exemple 5=>a ou x^4-1=>* ou (x+1)^2=>+ ou sin(x)^2=>cos.", "#5=>a", "#15_m=>_cm", CAT_CATEGORY_PROGCMD | (CAT_CATEGORY_PHYS <<8) | (CAT_CATEGORY_UNIT << 16)},
683 {">", ">", "Superieur strict. Raccourci F2.", 0, 0, CAT_CATEGORY_PROGCMD},
684 {"\\", "\\", "Caractere \\", 0, 0, CAT_CATEGORY_PROGCMD},
685 {"_", "_", "Caractere _. Prefixe d'unites.", 0, 0, CAT_CATEGORY_PROGCMD},
686 {"_(km/h)", "_(km/h)", "Vitesse en kilometre/heure", 0, 0, CAT_CATEGORY_UNIT},
687 {"_(m/s)", "_(m/s)", "Vitesse en metre/seconde", 0, 0, CAT_CATEGORY_UNIT},
688 {"_(m/s^2)", "_(m/s^2)", "Acceleration en metre par seconde au carre", 0, 0, CAT_CATEGORY_UNIT},
689 {"_(m^2/s)", "_(m^2/s)", "Viscosite", 0, 0, CAT_CATEGORY_UNIT},
690 {"_A", 0, "Intensite electrique en Ampere", 0, 0, CAT_CATEGORY_UNIT},
691 {"_Bq", 0, "Radioactivite: Becquerel", 0, 0, CAT_CATEGORY_UNIT},
692 {"_C", 0, "Charge electrique en Coulomb", 0, 0, CAT_CATEGORY_UNIT},
693 {"_Ci", 0, "Radioactivite: Curie", 0, 0, CAT_CATEGORY_UNIT},
694 {"_F", 0, "Farad", 0, 0, CAT_CATEGORY_UNIT},
695 {"_F_", 0, "constante de Faraday (charge globale d'une mole de charges élémentaires).", 0, 0, CAT_CATEGORY_PHYS},
696 {"_G_", 0, "constante de gravitation universelle. Force=_G_*m1*m2/r^2", 0, 0, CAT_CATEGORY_PHYS},
697 {"_H", 0, "Henry", 0, 0, CAT_CATEGORY_UNIT},
698 {"_Hz", 0, "Hertz", 0, 0, CAT_CATEGORY_UNIT},
699 {"_J", 0, "Energie en Joule=kg*m^2/s^2", 0, 0, CAT_CATEGORY_UNIT},
700 {"_K", 0, "Temperature en Kelvin", 0, 0, CAT_CATEGORY_UNIT},
701 {"_Kcal", 0, "Energie en kilo-calorier", 0, 0, CAT_CATEGORY_UNIT},
702 {"_MeV", 0, "Energie en mega-electron-Volt", 0, 0, CAT_CATEGORY_UNIT},
703 {"_N", 0, "Force en Newton=kg*m/s^2", 0, 0, CAT_CATEGORY_UNIT},
704 {"_NA_", 0, "Avogadro", 0, 0, CAT_CATEGORY_PHYS},
705 {"_Ohm", 0, "Resistance electrique en Ohm", 0, 0, CAT_CATEGORY_UNIT},
706 {"_PSun_", 0, "puissance du Soleil", 0, 0, CAT_CATEGORY_PHYS},
707 {"_Pa", 0, "Pression en Pascal=kg/m/s^2", 0, 0, CAT_CATEGORY_UNIT},
708 {"_REarth_", 0, "Rayon de la Terre", 0, 0, CAT_CATEGORY_PHYS},
709 {"_RSun_", 0, "rayon du Soleil", 0, 0, CAT_CATEGORY_PHYS},
710 {"_R_", 0, "constante des gaz (de Boltzmann par mole)", 0, 0, CAT_CATEGORY_PHYS},
711 {"_S", 0, "", 0, 0, CAT_CATEGORY_UNIT},
712 {"_StdP_", 0, "Pression standard (au niveau de la mer)", 0, 0, CAT_CATEGORY_PHYS},
713 {"_StdT_", 0, "temperature standard (0 degre Celsius exprimes en Kelvins)", 0, 0, CAT_CATEGORY_PHYS},
714 {"_Sv", 0, "Radioactivite: Sievert", 0, 0, CAT_CATEGORY_UNIT},
715 {"_T", 0, "Tesla", 0, 0, CAT_CATEGORY_UNIT},
716 {"_V", 0, "Tension electrique en Volt", 0, 0, CAT_CATEGORY_UNIT},
717 {"_Vm_", 0, "Volume molaire", 0, 0, CAT_CATEGORY_PHYS},
718 {"_W", 0, "Puissance en Watt=kg*m^2/s^3", 0, 0, CAT_CATEGORY_UNIT},
719 {"_Wb", 0, "Weber", 0, 0, CAT_CATEGORY_UNIT},
720 {"_alpha_", 0, "constante de structure fine", 0, 0, CAT_CATEGORY_PHYS},
721 {"_c_", 0, "vitesse de la lumiere", 0, 0, CAT_CATEGORY_PHYS},
722 {"_cd", 0, "Luminosite en candela", 0, 0, CAT_CATEGORY_UNIT},
723 {"_cdf", "_cdf", "Suffixe pour obtenir une distribution cumulee. Taper F2 pour la distribution cumulee inverse.", "#_icdf", 0, CAT_CATEGORY_PROBA},
724 {"_d", 0, "Temps: jour", 0, 0, CAT_CATEGORY_UNIT},
725 {"_deg", 0, "Angle en degres", 0, 0, CAT_CATEGORY_UNIT},
726 {"_eV", 0, "Energie en electron-Volt", 0, 0, CAT_CATEGORY_UNIT},
727 {"_epsilon0_", 0, "permittivite du vide", 0, 0, CAT_CATEGORY_PHYS},
728 {"_ft", 0, "Longueur en pieds", 0, 0, CAT_CATEGORY_UNIT},
729 {"_g_", 0, "gravite au sol", 0, 0, CAT_CATEGORY_PHYS},
730 {"_grad", 0, "Angle en grades", 0, 0, CAT_CATEGORY_UNIT},
731 {"_h", 0, "Heure", 0, 0, CAT_CATEGORY_UNIT},
732 {"_h_", 0, "constante de Planck", 0, 0, CAT_CATEGORY_PHYS},
733 {"_ha", 0, "Aire en hectare", 0, 0, CAT_CATEGORY_UNIT},
734 {"_hbar_", 0, "constante de Planck/(2*pi)", 0, 0, CAT_CATEGORY_PHYS},
735 {"_inch", 0, "Longueur en pouces", 0, 0, CAT_CATEGORY_UNIT},
736 {"_kWh", 0, "Energie en kWh", 0, 0, CAT_CATEGORY_UNIT},
737 {"_k_", 0, "constante de Boltzmann", 0, 0, CAT_CATEGORY_PHYS},
738 {"_kg", 0, "Masse en kilogramme", 0, 0, CAT_CATEGORY_UNIT},
739 {"_l", 0, "Volume en litre", 0, 0, CAT_CATEGORY_UNIT},
740 {"_m", 0, "Longueur en metre", 0, 0, CAT_CATEGORY_UNIT},
741 {"_mEarth_", 0, "masse de la Terre", 0, 0, CAT_CATEGORY_PHYS},
742 {"_m^2", 0, "Aire en m^2", 0, 0, CAT_CATEGORY_UNIT},
743 {"_m^3", 0, "Volume en m^3", 0, 0, CAT_CATEGORY_UNIT},
744 {"_me_", 0, "masse electron", 0, 0, CAT_CATEGORY_PHYS},
745 {"_miUS", 0, "Longueur en miles US", 0, 0, CAT_CATEGORY_UNIT},
746 {"_mn", 0, "Temps: minute", 0, 0, CAT_CATEGORY_UNIT},
747 {"_mp_", 0, "masse proton", 0, 0, CAT_CATEGORY_PHYS},
748 {"_mpme_", 0, "ratio de masse proton/electron", 0, 0, CAT_CATEGORY_PHYS},
749 {"_mu0_", 0, "permeabilite du vide", 0, 0, CAT_CATEGORY_PHYS},
750 {"_phi_", 0, "quantum flux magnetique", 0, 0, CAT_CATEGORY_PHYS},
751 {"_plot", "_plot", "Suffixe pour obtenir le graphe d'une regression.", "#X,Y:=[1,2,3,4,5],[0,1,3,4,4];polynomial_regression_plot(X,Y,2);scatterplot(X,Y)", 0, CAT_CATEGORY_STATS},
752 {"_qe_", 0, "charge de l'electron", 0, 0, CAT_CATEGORY_PHYS},
753 {"_qme_", 0, "_q_/_me_", 0, 0, CAT_CATEGORY_PHYS},
754 {"_rad", 0, "Angle en radians", 0, 0, CAT_CATEGORY_UNIT},
755 {"_rem", 0, "Radioactivite: rem", 0, 0, CAT_CATEGORY_UNIT},
756 {"_s", 0, "Temps: seconde", 0, 0, CAT_CATEGORY_UNIT},
757 {"_sd_", 0, "Jour sideral", 0, 0, CAT_CATEGORY_PHYS},
758 {"_syr_", 0, "Annee siderale", 0, 0, CAT_CATEGORY_PHYS},
759 {"_tr", 0, "Angle en tours", 0, 0, CAT_CATEGORY_UNIT},
760 {"_yd", 0, "Longueur en yards", 0, 0, CAT_CATEGORY_UNIT},
761 {"a and b", " and ", "Et logique", 0, 0, CAT_CATEGORY_PROGCMD},
762 {"a or b", " or ", "Ou logique", 0, 0, CAT_CATEGORY_PROGCMD},
763 {"abcuv(a,b,c)", 0, "Cherche 2 polynomes u,v tels que a*u+b*v=c","x+1,x^2-2,x", 0, CAT_CATEGORY_POLYNOMIAL},
764 {"abs(x)", 0, "Valeur absolue, module ou norme de x", "-3", "[1,2,3]", CAT_CATEGORY_COMPLEXNUM | (CAT_CATEGORY_REAL<<8)},
765 {"append", 0, "Ajoute un element en fin de liste l","#l.append(x)", 0, CAT_CATEGORY_LIST},
766 {"approx(x)", 0, "Valeur approchee de x. Raccourci S-D", "pi", 0, CAT_CATEGORY_REAL},
767 {"arg(z)", 0, "Argument du complexe z.", "1+i", 0, CAT_CATEGORY_COMPLEXNUM},
768 {"asc(string)", 0, "Liste des codes ASCII d'une chaine", "\"Bonjour\"", 0, CAT_CATEGORY_ARIT},
769 {"assume(hyp)", 0, "Hypothese sur une variable.", "x>1", "x>-1 and x<1", CAT_CATEGORY_PROGCMD | (CAT_CATEGORY_SOFUS<<8)},
770 {"avance n", "avance ", "La tortue avance de n pas, par defaut n=10", "#avance 40", 0, CAT_CATEGORY_LOGO},
771 {"axes", "axes", "Axes visibles ou non axes=1 ou 0", "#axes=0", "#axes=1", CAT_CATEGORY_PROGCMD << 8},
772 {"baisse_crayon ", "baisse_crayon ", "La tortue se deplace en marquant son passage.", 0, 0, CAT_CATEGORY_LOGO},
773 {"barplot(list)", 0, "Diagramme en batons d'une serie statistique 1d.", "[3/2,2,1,1/2,3,2,3/2]", 0, CAT_CATEGORY_STATS},
774 {"binomial(n,p,k)", 0, "binomial(n,p,k) probabilite de k succes avec n essais ou p est la proba de succes d'un essai. binomial_cdf(n,p,k) est la probabilite d'obtenir au plus k succes avec n essais. binomial_icdf(n,p,t) renvoie le plus petit k tel que binomial_cdf(n,p,k)>=t", "10,.5,4", 0, CAT_CATEGORY_PROBA},
775 {"bitxor", "bitxor", "Ou exclusif", "#bitxor(1,2)", 0, CAT_CATEGORY_PROGCMD},
776 {"black", "black", "Option d'affichage", "#display=black", 0, CAT_CATEGORY_PROGCMD},
777 {"blue", "blue", "Option d'affichage", "#display=blue", 0, CAT_CATEGORY_PROGCMD},
778 {"cache_tortue ", "cache_tortue ", "Cache la tortue apres avoir trace le dessin.", 0, 0, CAT_CATEGORY_LOGO},
779 {"camembert(list)", 0, "Diagramme en camembert d'une serie statistique 1d.", "[[\"France\",6],[\"Allemagne\",12],[\"Suisse\",5]]", 0, CAT_CATEGORY_STATS},
780 {"ceiling(x)", 0, "Partie entiere superieure", "1.2", 0, CAT_CATEGORY_REAL},
781 {"cercle(centre,rayon)", 0, "Cercle donne par centre et rayon ou par un diametre", "2+i,3", "1-i,1+i", CAT_CATEGORY_PROGCMD},
782 {"cfactor(p)", 0, "Factorisation sur C.", "x^4-1", 0, CAT_CATEGORY_ALGEBRA | (CAT_CATEGORY_COMPLEXNUM << 8)},
783 {"char(liste)", 0, "Chaine donnee par une liste de code ASCII", "[97,98,99]", 0, CAT_CATEGORY_ARIT},
784 {"charpoly(M,x)", 0, "Polynome caracteristique de la matrice M en la variable x.", "[[1,2],[3,4]],x", 0, CAT_CATEGORY_MATRIX},
785 {"clearscreen()", "clearscreen()", "Efface l'ecran.", 0, 0, CAT_CATEGORY_PROGCMD},
786 {"coeff(p,x,n)", 0, "Coefficient de x^n dans le polynome p.", "(1+x)^6,x,3", 0, CAT_CATEGORY_POLYNOMIAL},
787 {"comb(n,k)", 0, "Renvoie k parmi n.", "10,4", 0, CAT_CATEGORY_PROBA},
788 {"cond(A,[1,2,inf])", 0, "Nombre de condition d'une matrice par rapport a la norme specifiee (par defaut 1)", "[[1,2],[3,4]]", 0, CAT_CATEGORY_MATRIX},
789 {"conj(z)", 0, "Conjugue complexe de z.", "1+i", 0, CAT_CATEGORY_COMPLEXNUM},
790 {"correlation(l1,l2)", 0, "Correlation listes l1 et l2", "[1,2,3,4,5],[0,1,3,4,4]", 0, CAT_CATEGORY_STATS},
791 {"covariance(l1,l2)", 0, "Covariance listes l1 et l2", "[1,2,3,4,5],[0,1,3,4,4]", 0, CAT_CATEGORY_STATS},
792 {"cpartfrac(p,x)", 0, "Decomposition en elements simples sur C.", "1/(x^4-1)", 0, CAT_CATEGORY_ALGEBRA | (CAT_CATEGORY_COMPLEXNUM << 8)},
793 {"crayon ", "crayon ", "Couleur de trace de la tortue", "#crayon rouge", 0, CAT_CATEGORY_LOGO},
794 {"cross(u,v)", 0, "Produit vectoriel de u et v.","[1,2,3],[0,1,3]", 0, CAT_CATEGORY_LINALG},
795 {"csolve(equation,x)", 0, "Resolution exacte dans C d'une equation en x (ou d'un systeme polynomial).","x^2+x+1=0", 0, CAT_CATEGORY_SOLVE | (CAT_CATEGORY_COMPLEXNUM << 8)},
796 {"curl(u,vars)", 0, "Rotationnel du vecteur u.", "[2*x*y,x*z,y*z],[x,y,z]", 0, CAT_CATEGORY_LINALG},
797 {"cyan", "cyan", "Option d'affichage", "#display=cyan", 0, CAT_CATEGORY_PROGCMD},
798 {"debug(f(args))", 0, "Execute la fonction f en mode pas a pas.", 0, 0, CAT_CATEGORY_PROG},
799 {"degree(p,x)", 0, "Degre du polynome p en x.", "x^4-1", 0, CAT_CATEGORY_POLYNOMIAL},
800 {"denom(x)", 0, "Denominateur de l'expression x.", "3/4", 0, CAT_CATEGORY_POLYNOMIAL},
801 {"desolve(equation,t,y)", 0, "Resolution exacte d'equation differentielle ou de systeme differentiel lineaire a coefficients constants.", "[y'+y=exp(x),y(0)=1]", "[y'=[[1,2],[2,1]]*y+[x,x+1],y(0)=[1,2]]", CAT_CATEGORY_SOLVE | (CAT_CATEGORY_CALCULUS << 8)},
802 {"det(A)", 0, "Determinant de la matrice A.", "[[1,2],[3,4]]", 0, CAT_CATEGORY_MATRIX},
803 {"diff(f,var,[n])", 0, "Derivee de l'expression f par rapport a var (a l'ordre n, n=1 par defaut), par exemple diff(sin(x),x) ou diff(x^3,x,2). Pour deriver f par rapport a x, utiliser f' (raccourci F3). Pour le gradient de f, var est la liste des variables.", "sin(x),x", "sin(x^2),x,3", CAT_CATEGORY_CALCULUS},
804 {"display", "display", "Option d'affichage", "#display=red", 0, CAT_CATEGORY_PROGCMD},
805 {"disque n", "disque ", "Cercle rempli tangent a la tortue, de rayon n. Utiliser disque n,theta pour remplir un morceau de camembert ou disque n,theta,segment pour remplir un segment de disque", "#disque 30", "#disque(30,90)", CAT_CATEGORY_LOGO},
806 {"dot(a,b)", 0, "Produit scalaire de 2 vecteurs. Raccourci: *", "[1,2,3,4,5],[0,1,3,4,4]", 0, CAT_CATEGORY_LINALG},
807 {"draw_arc(x1,y1,rx,ry,theta1,theta2,c)", 0, "Arc d'ellipse pixelise.", "100,100,60,80,0,pi,magenta", 0, CAT_CATEGORY_PROGCMD},
808 {"draw_circle(x1,y1,r,c)", 0, "Cercle pixelise. Option filled pour le remplir.", "100,100,60,cyan+filled", 0, CAT_CATEGORY_PROGCMD},
809 {"draw_line(x1,y1,x2,y2,c)", 0, "Droite pixelisee.", "100,50,300,200,blue", 0, CAT_CATEGORY_PROGCMD},
810 {"draw_pixel(x,y,color)", 0, "Colorie le pixel x,y. Faire draw_pixel() pour synchroniser l'ecran.", 0, 0, CAT_CATEGORY_PROGCMD},
811 {"draw_polygon([[x1,y1],...],c)", 0, "Polygone pixelise.", "[[100,50],[30,20],[60,70]],red+filled", 0, CAT_CATEGORY_PROGCMD},
812 {"draw_rectangle(x,y,w,h,c)", 0, "Rectangle pixelise.", "100,50,30,20,red+filled", 0, CAT_CATEGORY_PROGCMD},
813 {"draw_string(s,x,y,c)", 0, "Affiche la chaine s en x,y", "\"Bonjour\",80,60", 0, CAT_CATEGORY_PROGCMD},
814 {"droite(equation)", 0, "Droite donnee par une equation ou 2 points", "y=2x+1", "1+i,2-i", CAT_CATEGORY_PROGCMD},
815 {"ecris ", "ecris ", "Ecrire a la position de la tortue", "#ecris \"coucou\"", 0, CAT_CATEGORY_LOGO},
816 {"efface", "efface", "Remise a zero de la tortue", 0, 0, CAT_CATEGORY_LOGO},
817 {"egcd(A,B)", 0, "Cherche des polynomes U,V,D tels que A*U+B*V=D=gcd(A,B)","x^2+3x+1,x^2-5x-1", 0, CAT_CATEGORY_POLYNOMIAL},
818 {"eigenvals(A)", 0, "Valeurs propres de la matrice A.", "[[1,2],[3,4]]", 0, CAT_CATEGORY_MATRIX},
819 {"eigenvects(A)", 0, "Vecteurs propres de la matrice A.", "[[1,2],[3,4]]", 0, CAT_CATEGORY_MATRIX},
820 {"elif (test)", "elif", "Tests en cascade", 0, 0, CAT_CATEGORY_PROG},
821 //{"end", "end", "Fin de bloc", 0, 0, CAT_CATEGORY_PROG},
822 {"erf(x)", 0, "Fonction erreur en x.", "1.2", 0, CAT_CATEGORY_PROBA},
823 {"erfc(x)", 0, "Fonction erreur complementaire en x.", "1.2", 0, CAT_CATEGORY_PROBA},
824 {"euler(n)",0,"Indicatrice d'Euler: nombre d'entiers < n premiers avec n","25",0,CAT_CATEGORY_ARIT},
825 {"eval(f)", 0, "Evalue f.", 0, 0, CAT_CATEGORY_PROGCMD},
826 {"evalc(z)", 0, "Ecrit z=x+i*y.", "1/(1+i*sqrt(3))", 0, CAT_CATEGORY_COMPLEXNUM},
827 {"exact(x)", 0, "Convertit x en rationnel. Raccourci shift S-D", "1.2", 0, CAT_CATEGORY_REAL},
828 {"exp2trig(expr)", 0, "Conversion d'exponentielles complexes en sin/cos", "exp(i*x)", 0, CAT_CATEGORY_TRIG},
829 {"exponential_regression(Xlist,Ylist)", 0, "Regression exponentielle.", "[1,2,3,4,5],[0,1,3,4,4]", 0, CAT_CATEGORY_STATS},
830 {"exponential_regression_plot(Xlist,Ylist)", 0, "Graphe d'une regression exponentielle.", "#X,Y:=[1,2,3,4,5],[1,3,4,6,8];exponential_regression_plot(X,Y);", 0, CAT_CATEGORY_STATS},
831 {"exponentiald(lambda,x)", 0, "Loi exponentielle de parametre lambda. exponentiald_cdf(lambda,x) probabilite que \"loi exponentielle <=x\" par ex. exponentiald_cdf(2,3). exponentiald_icdf(lambda,t) renvoie x tel que \"loi exponentielle <=x\" vaut t, par ex. exponentiald_icdf(2,0.95) ", "5.1,3.4", 0, CAT_CATEGORY_PROBA},
832 {"extend", 0, "Concatene 2 listes. Attention a ne pas utiliser + qui effectue l'addition de 2 vecteurs.","#l1.extend(l2)", 0, CAT_CATEGORY_LIST},
833 {"factor(p,[x])", 0, "Factorisation du polynome p (utiliser ifactor pour un entier). Raccourci: p=>*", "x^4-1", "x^6+1,sqrt(3)", CAT_CATEGORY_ALGEBRA | (CAT_CATEGORY_POLYNOMIAL << 8)},
834 {"filled", "filled", "Option d'affichage", 0, 0, CAT_CATEGORY_PROGCMD},
835 {"float(x)", 0, "Convertit x en nombre approche (flottant).", "pi", 0, CAT_CATEGORY_REAL},
836 {"floor(x)", 0, "Partie entiere de x", "pi", 0, CAT_CATEGORY_REAL},
837 {"fonction f(x)", "fonction", "Definition de fonction (Xcas). Par exemple\nfonction f(x)\n local y;\ny:=x*x;\nreturn y;\nffonction", 0, 0, CAT_CATEGORY_PROG},
838 {"from math/... import *", "from math import *", "Instruction pour utiliser les fonctions de maths ou des fonctions aleatoires [random] ou la tortue en anglais [turtle]. Importer math n'est pas necessaire dans KhiCAS", "#from random import *", "#from turtle import *", CAT_CATEGORY_PROG},
839 {"fsolve(equation,x=a[..b])", 0, "Resolution approchee de equation pour x dans l'intervalle a..b ou en partant de x=a.","cos(x)=x,x=0..1", "cos(x)-x,x=0.0", CAT_CATEGORY_SOLVE},
840 {"gauss(q)", 0, "Reduction de Gauss d'une forme quadratique q", "x^2+x*y+x*z,[x,y,z]", "x^2+4*x*y,[]", CAT_CATEGORY_LINALG },
841 {"gcd(a,b,...)", 0, "Plus grand commun diviseur. Voir iegcd ou egcd pour Bezout.", "23,13", "x^2-1,x^3-1", CAT_CATEGORY_ARIT | (CAT_CATEGORY_POLYNOMIAL << 8)},
842 {"gl_x", "gl_x", "Reglage graphique X gl_x=xmin..xmax", "#gl_x=0..2", 0, CAT_CATEGORY_PROGCMD << 8},
843 {"gl_y", "gl_y", "Reglage graphique Y gl_y=ymin..ymax", "#gl_y=-1..1", 0, CAT_CATEGORY_PROGCMD << 8},
844 {"green", "green", "Option d'affichage", "#display=green", 0, CAT_CATEGORY_PROGCMD},
845 {"halftan(expr)", 0, "Exprime cos, sin, tan avec tan(angle/2).","cos(x)", 0, CAT_CATEGORY_TRIG},
846 {"hermite(n)", 0, "n-ieme polynome de Hermite", "10", "10,t", CAT_CATEGORY_POLYNOMIAL},
847 {"hilbert(n)", 0, "Matrice de Hilbert de taille n.", "4", 0, CAT_CATEGORY_MATRIX},
848 {"histogram(list,min,size)", 0, "Histogramme d'une liste de donneees, classes commencant a min de taille size.","ranv(100,uniformd,0,1),0,0.1", 0, CAT_CATEGORY_STATS},
849 {"iabcuv(a,b,c)", 0, "Cherche 2 entiers u,v tels que a*u+b*v=c","23,13,15", 0, CAT_CATEGORY_ARIT},
850 {"ichinrem([a,m],[b,n])", 0,"Restes chinois entiers de a mod m et b mod n.", "[3,13],[2,7]", 0, CAT_CATEGORY_ARIT},
851 {"idivis(n)", 0, "Liste des diviseurs d'un entier n.", "10", 0, CAT_CATEGORY_ARIT},
852 {"idn(n)", 0, "matrice identite n * n", "4", 0, CAT_CATEGORY_MATRIX},
853 {"iegcd(a,b)", 0, "Determine les entiers u,v,d tels que a*u+b*v=d=gcd(a,b)","23,13", 0, CAT_CATEGORY_ARIT},
854 {"ifactor(n)", 0, "Factorisation d'un entier (pas trop grand!). Raccourci n=>*", "1234", 0, CAT_CATEGORY_ARIT},
855 {"ilaplace(f,s,x)", 0, "Transformee inverse de Laplace de f", "s/(s^2+1),s,x", 0, CAT_CATEGORY_CALCULUS},
856 {"im(z)", 0, "Partie imaginaire.", "1+i", 0, CAT_CATEGORY_COMPLEXNUM},
857 {"inf", "inf", "Plus l'infini. Utiliser -inf pour moins l'infini ou infinity pour l'infini complexe. Raccourci shift INS.", "-inf", "infinity", CAT_CATEGORY_CALCULUS},
858 {"input()", "input()", "Lire une chaine au clavier", "\"Valeur ?\"", 0, CAT_CATEGORY_PROG},
859 {"integrate(f,x,[,a,b])", 0, "Primitive de f par rapport a la variable x, par ex. integrate(x*sin(x),x). Pour calculer une integrale definie, entrer les arguments optionnels a et b, par ex. integrate(x*sin(x),x,0,pi). Raccourci SHIFT F3.", "x*sin(x),x", "cos(x)/(1+x^4),x,0,inf", CAT_CATEGORY_CALCULUS},
860 {"interp(X,Y[,interp])", 0, "Interpolation de Lagrange aux points (xi,yi) avec X la liste des xi et Y des yi. Renvoie la liste des differences divisees si interp est passe en parametre.", "[1,2,3,4,5],[0,1,3,4,4]", "[1,2,3,4,5],[0,1,3,4,4],interp", CAT_CATEGORY_POLYNOMIAL},
861 {"inv(A)", 0, "Inverse de A.", "[[1,2],[3,4]]", 0, CAT_CATEGORY_MATRIX},
862 {"inverser(v)", "inverser ", "La variable v est remplacee par son inverse", "#v:=3; inverser v", 0, CAT_CATEGORY_SOFUS},
863 {"iquo(a,b)", 0, "Quotient euclidien de deux entiers.", "23,13", 0, CAT_CATEGORY_ARIT},
864 {"irem(a,b)", 0,"Reste euclidien de deux entiers", "23,13", 0, CAT_CATEGORY_ARIT},
865 {"isprime(n)", 0, "Renvoie 1 si n est premier, 0 sinon.", "11", "10", CAT_CATEGORY_ARIT},
866 {"jordan(A)", 0, "Forme normale de Jordan de la matrice A, renvoie P et D tels que P^-1*A*P=D", "[[1,2],[3,4]]", "[[1,1,-1,2,-1],[2,0,1,-4,-1],[0,1,1,1,1],[0,1,2,0,1],[0,0,-3,3,-1]]", CAT_CATEGORY_MATRIX},
867 {"laguerre(n,a,x)", 0, "n-ieme polynome de Laguerre (a=0 par defaut).", "10", 0, CAT_CATEGORY_POLYNOMIAL},
868 {"laplace(f,x,s)", 0, "Transformee de Laplace de f","sin(x),x,s", 0, CAT_CATEGORY_CALCULUS},
869 {"lcm(a,b,...)", 0, "Plus petit commun multiple.", "23,13", "x^2-1,x^3-1", CAT_CATEGORY_ARIT | (CAT_CATEGORY_POLYNOMIAL << 8)},
870 {"lcoeff(p,x)", 0, "Coefficient dominant du polynome p.", "x^4-1", 0, CAT_CATEGORY_POLYNOMIAL},
871 {"legendre(n)", 0, "n-ieme polynome de Legendre.", "10", "10,t", CAT_CATEGORY_POLYNOMIAL},
872 #ifdef RELEASE
873 {"len(l)", 0, "Taille d'une liste.", "[3/2,2,1,1/2,3,2,3/2]", 0, CAT_CATEGORY_LIST},
874 #endif
875 {"leve_crayon ", "leve_crayon ", "La tortue se deplace sans marquer son passage", 0, 0, CAT_CATEGORY_LOGO},
876 {"limit(f,x=a)", 0, "Limite de f en x = a. Ajouter 1 ou -1 pour une limite a droite ou a gauche, limit(sin(x)/x,x=0) ou limit(abs(x)/x,x=0,1). Raccourci: SHIFT MIXEDFRAC", "sin(x)/x,x=0", "exp(-1/x),x=0,1", CAT_CATEGORY_CALCULUS},
877 {"line_width_", "line_width_", "Prefixe d'epaisseur (2 a 8)", 0, 0, CAT_CATEGORY_PROGCMD},
878 {"linear_regression(Xlist,Ylist)", 0, "Regression lineaire.", "[1,2,3,4,5],[0,1,3,4,4]", 0, CAT_CATEGORY_STATS},
879 {"linear_regression_plot(Xlist,Ylist)", 0, "Graphe d'une regression lineaire.", "#X,Y:=[1,2,3,4,5],[0,1,3,4,4];linear_regression_plot(X,Y);", 0, CAT_CATEGORY_STATS },
880 {"linetan(expr,x,x0)", 0, "Tangente au graphe en x=x0.", "sin(x),x,pi/2", 0, CAT_CATEGORY_PLOT},
881 {"linsolve([eq1,eq2,..],[x,y,..])", 0, "Resolution de systeme lineaire. Peut utiliser le resultat de lu pour resolution en O(n^2).","[x+y=1,x-y=2],[x,y]", "#p,l,u:=lu([[1,2],[3,4]]); linsolve(p,l,u,[5,6])", CAT_CATEGORY_SOLVE | (CAT_CATEGORY_LINALG <<8) | (CAT_CATEGORY_MATRIX << 16)},
882 {"logarithmic_regression(Xlist,Ylist)", 0, "Regression logarithmique.", "[1,2,3,4,5],[0,1,3,4,4]", 0, CAT_CATEGORY_STATS},
883 {"logarithmic_regression_plot(Xlist,Ylist)", 0, "Graphe d'une regression logarithmique.", "#X,Y:=[1,2,3,4,5],[0,1,3,4,4];logarithmic_regression_plot(X,Y);", 0, CAT_CATEGORY_STATS},
884 {"lu(A)", 0, "decomposition LU de la matrice A, P*A=L*U, renvoie P permutation, L et U triangulaires inferieure et superieure", "[[1,2],[3,4]]", 0, CAT_CATEGORY_MATRIX},
885 {"magenta", "magenta", "Option d'affichage", "#display=magenta", 0, CAT_CATEGORY_PROGCMD},
886 {"map(l,f)", 0, "Applique f aux elements de la liste l.","[1,2,3],x->x^2", 0, CAT_CATEGORY_LIST},
887 {"matpow(A,n)", 0, "Renvoie A^n, la matrice A la puissance n", "[[1,2],[3,4]],n","#assume(n>=1);matpow([[0,2],[0,4]],n)", CAT_CATEGORY_MATRIX},
888 {"matrix(l,c,func)", 0, "Matrice de terme general donne.", "2,3,(j,k)->j^k", 0, CAT_CATEGORY_MATRIX},
889 {"mean(l)", 0, "Moyenne arithmetique liste l", "[3/2,2,1,1/2,3,2,3/2]", 0, CAT_CATEGORY_STATS},
890 {"median(l)", 0, "Mediane", "[3/2,2,1,1/2,3,2,3/2]", 0, CAT_CATEGORY_STATS},
891 {"montre_tortue ", "montre_tortue ", "Affiche la tortue", 0, 0, CAT_CATEGORY_LOGO},
892 {"mult_c_conjugate", 0, "Multiplier par le conjugue complexe.", "1+2*i", 0, (CAT_CATEGORY_COMPLEXNUM << 8)},
893 {"mult_conjugate", 0, "Multiplier par le conjugue (sqrt).", "sqrt(2)-sqrt(3)", 0, CAT_CATEGORY_ALGEBRA},
894 {"normald([mu,sigma],x)", 0, "Loi normale, par defaut mu=0 et sigma=1. normald_cdf([mu,sigma],x) probabilite que \"loi normale <=x\" par ex. normald_cdf(1.96). normald_icdf([mu,sigma],t) renvoie x tel que \"loi normale <=x\" vaut t, par ex. normald_icdf(0.975) ", "1.2", 0, CAT_CATEGORY_PROBA},
895 {"not(x)", 0, "Non logique.", 0, 0, CAT_CATEGORY_PROGCMD},
896 {"numer(x)", 0, "Numerateur de x.", "3/4", 0, CAT_CATEGORY_POLYNOMIAL},
897 {"odesolve(f(t,y),[t,y],[t0,y0],t1)", 0, "Solution approchee d'equation differentielle y'=f(t,y) et y(t0)=y0, valeur en t1 (ajouter curve pour les valeurs intermediaires de y)", "sin(t*y),[t,y],[0,1],2", "0..pi,(t,v)->{[-v[1],v[0]]},[0,1]", CAT_CATEGORY_SOLVE},
898 {"partfrac(p,x)", 0, "Decomposition en elements simples. Raccourci p=>+", "1/(x^4-1)", 0, CAT_CATEGORY_ALGEBRA},
899 {"pas_de_cote n", "pas_de_cote ", "Saut lateral de la tortue, par defaut n=10", "#pas_de_cote 30", 0, CAT_CATEGORY_LOGO},
900 {"plot(expr,x)", 0, "Graphe de fonction. Par exemple plot(sin(x)), plot(ln(x),x.0,5)", "ln(x),x=0..5", "1/x,x=1..5,xstep=1", CAT_CATEGORY_PLOT},
901 {"plotarea(expr,x=a..b,[n,meth])", 0, "Aire sous la courbe selon une methode d'integration.", "1/x,x=1..5,4,rectangle_gauche", 0, CAT_CATEGORY_PLOT},
902 {"plotcontour(expr,[x=xm..xM,y=ym..yM],niveaux)", 0, "Lignes de niveau de expr.", "x^2+2y^2, [x=-2..2,y=-2..2],[1,2]", 0, CAT_CATEGORY_PLOT},
903 {"plotdensity(expr,[x=xm..xM,y=ym..yM])", 0, "Representation en niveaux de couleurs d'une expression de 2 variables.", "x^2-y^2,[x=-3..3,y=-2..2]", 0, CAT_CATEGORY_PLOT},
904 {"plotfield(f(t,y), [t=tmin..tmax,y=ymin..ymax])", 0, "Champ des tangentes de y'=f(t,y), optionnellement graphe avec plotode=[t0,y0]", "sin(t*y), [t=-3..3,y=-3..3],plotode=[0,1]", "5*[-y,x], [x=-1..1,y=-1..1]", CAT_CATEGORY_PLOT},
905 {"plotlist(list)", 0, "Graphe d'une liste", "[3/2,2,1,1/2,3,2,3/2]", "[1,13],[2,10],[3,15],[4,16]", CAT_CATEGORY_PLOT},
906 {"plotode(f(t,y), [t=tmin..tmax,y],[t0,y0])", 0, "Graphe de solution d'equation differentielle y'=f(t,y), y(t0)=y0.", "sin(t*y),[t=-3..3,y],[0,1]", 0, CAT_CATEGORY_PLOT},
907 {"plotparam([x,y],t)", 0, "Graphe en parametriques. Par exemple plotparam([sin(3t),cos(2t)],t,0,pi) ou plotparam(exp(i*t),t,0,pi)", "[sin(3t),cos(2t)],t,0,pi", "[t^2,t^3],t=-1..1,tstep=0.1", CAT_CATEGORY_PLOT},
908 {"plotpolar(r,theta)", 0, "Graphe en polaire.","cos(3*x),x,0,pi", "1/(1+cos(x)),x=0..pi,xstep=0.05", CAT_CATEGORY_PLOT},
909 {"plotseq(f(x),x=[u0,m,M],n)", 0, "Trace f(x) sur [m,M] et n termes de la suite recurrente u_{n+1}=f(u_n) de 1er terme u0.","sqrt(2+x),x=[6,0,7],5", 0, CAT_CATEGORY_PLOT},
910 {"plus_point", "plus_point", "Option d'affichage", "#display=blue+plus_point", 0, CAT_CATEGORY_PROGCMD },
911 {"point(x,y)", 0, "Point", "1,2", 0, CAT_CATEGORY_PROGCMD},
912 {"polygon(list)", 0, "Polygone ferme.", "1-i,2+i,3", 0, CAT_CATEGORY_PROGCMD},
913 {"polygonscatterplot(Xlist,Ylist)", 0, "Nuage de points relies.", "[1,2,3,4,5],[0,1,3,4,4]", 0, CAT_CATEGORY_STATS},
914 {"polynomial_regression(Xlist,Ylist,n)", 0, "Regression polynomiale de degre <= n.", "[1,2,3,4,5],[0,1,3,4,4],2", 0, CAT_CATEGORY_STATS},
915 {"polynomial_regression_plot(Xlist,Ylist,n)", 0, "Graphe d'une regression polynomiale de degre <= n.", "#X,Y:=[1,2,3,4,5],[0,1,3,4,4];polynomial_regression_plot(X,Y,2);scatterplot(X,Y);", 0, CAT_CATEGORY_STATS},
916 {"pour (boucle Xcas)", "pour de to faire fpour;", "Boucle definie.","#pour j de 1 to 10 faire print(j,j^2); fpour;", 0, CAT_CATEGORY_PROG},
917 {"power_regression(Xlist,Ylist,n)", 0, "Regression puissance.", "[1,2,3,4,5],[0,1,3,4,4]", 0, CAT_CATEGORY_STATS},
918 {"power_regression_plot(Xlist,Ylist,n)", 0, "Graphe d'une regression puissance.", "#X,Y:=[1,2,3,4,5],[1,1,3,4,4];power_regression_plot(X,Y);", 0, CAT_CATEGORY_STATS},
919 {"powmod(a,n,p[,P,x])", 0, "Renvoie a^n mod p, ou a^n mod un entier p et un polynome P en x.","123,456,789", "x+1,452,19,x^4+x+1,x", CAT_CATEGORY_ARIT},
920 {"print(expr)", 0, "Afficher dans la console", 0, 0, CAT_CATEGORY_PROG},
921 {"proot(p)", 0, "Racines reelles et complexes approchees d'un polynome. Exemple proot([1,2.1,3,4.2]) ou proot(x^3+2.1*x^2+3x+4.2)", "x^3+2.1*x^2+3x+4.2", 0, CAT_CATEGORY_POLYNOMIAL},
922 {"purge(x)", 0, "Purge le contenu de la variable x. Raccourci SHIFT-FORMAT", 0, 0, CAT_CATEGORY_PROGCMD | (CAT_CATEGORY_SOFUS<<8)},
923 {"python(f)", 0, "Affiche la fonction f en syntaxe Python.", 0, 0, CAT_CATEGORY_PROGCMD},
924 {"python_compat(0|1|2)", 0, "python_compat(0) syntaxe Xcas, python_compat(1) syntaxe Python avec ^ interprete comme puissance, python_compat(2) ^ interprete comme ou exclusif bit a bit", "0", "1", CAT_CATEGORY_PROG},
925 {"qr(A)", 0, "Factorisation A=Q*R avec Q orthogonale et R triangulaire superieure", "[[1,2],[3,4]]", 0, CAT_CATEGORY_MATRIX},
926 {"quartile1(l)", 0, "1er quartile", "[3/2,2,1,1/2,3,2,3/2]", 0, CAT_CATEGORY_STATS},
927 {"quartile3(l)", 0, "3eme quartile", "[3/2,2,1,1/2,3,2,3/2]", 0, CAT_CATEGORY_STATS},
928 {"quo(p,q,x)", 0, "Quotient de division euclidienne polynomiale en x.", 0, 0, CAT_CATEGORY_POLYNOMIAL},
929 {"quote(x)", 0, "Renvoie l'expression x non evaluee.", 0, 0, CAT_CATEGORY_ALGEBRA},
930 {"rand()", "rand()", "Reel aleatoire entre 0 et 1", 0, 0, CAT_CATEGORY_PROBA},
931 {"randint(n)", 0, "Entier aleatoire entre 1 et n ou entre a et b si on fournit 2 arguments", "6", "5,20", CAT_CATEGORY_PROBA},
932 {"ranm(n,m,[loi,parametres])", 0, "Matrice aleatoire a coefficients entiers ou selon une loi de probabilites (ranv pour un vecteur). Exemples ranm(2,3), ranm(3,2,binomial,20,.3), ranm(4,2,normald,0,1)", "4,2,normald,0,1", "3,3,10", CAT_CATEGORY_MATRIX},
933 {"ranv(n,[loi,parametres])", 0, "Vecteur aleatoire", "4,normald,0,1", "10,30", CAT_CATEGORY_LINALG},
934 {"ratnormal(x)", 0, "Ecrit sous forme d'une fraction irreductible.", "(x+1)/(x^2-1)^2", 0, CAT_CATEGORY_ALGEBRA},
935 {"re(z)", 0, "Partie reelle.", "1+i", 0, CAT_CATEGORY_COMPLEXNUM},
936 {"read(\"filename\")", "read(\"", "Lire un fichier. Voir aussi write", 0, 0, CAT_CATEGORY_PROGCMD},
937 {"rectangle_plein a,b", "rectangle_plein ", "Rectangle direct rempli depuis la tortue de cotes a et b (si b est omis, la tortue remplit un carre)", "#rectangle_plein 30", "#rectangle_plein(20,40)", CAT_CATEGORY_LOGO},
938 {"recule n", "recule ", "La tortue recule de n pas, par defaut n=10", "#recule 30", 0, CAT_CATEGORY_LOGO},
939 {"red", "red", "Option d'affichage", "#display=red", 0, CAT_CATEGORY_PROGCMD},
940 {"rem(p,q,x)", 0, "Reste de division euclidienne polynomiale en x", 0, 0, CAT_CATEGORY_POLYNOMIAL},
941 {"repete(n,...)", "repete( ", "Repete plusieurs fois les instructions", "#repete(4,avance,tourne_gauche)", 0, CAT_CATEGORY_LOGO},
942 #ifdef RELEASE
943 {"residue(f(z),z,z0)", 0, "Residu de l'expression en z0.", "1/(x^2+1),x,i", 0, CAT_CATEGORY_COMPLEXNUM},
944 #endif
945 {"resultant(p,q,x)", 0, "Resultant en x des polynomes p et q.", "#P:=x^3+p*x+q;resultant(P,P',x);", 0, CAT_CATEGORY_POLYNOMIAL},
946 {"revert(p[,x])", 0, "Developpement de Taylor reciproque, p doit etre nul en 0","x+x^2+x^4", 0, CAT_CATEGORY_CALCULUS},
947 {"rgb(r,g,b)", 0, "couleur definie par niveau de rouge, vert, bleu entre 0 et 255", "255,0,255", 0, CAT_CATEGORY_PROGCMD},
948 {"rhombus_point", "rhombus_point", "Option d'affichage", "#display=magenta+rhombus_point", 0, CAT_CATEGORY_PROGCMD },
949 {"rond n", "rond ", "Cercle tangent a la tortue de rayon n. Utiliser rond n,theta pour un arc de cercle.", "#rond 30", "#rond(30,90)", CAT_CATEGORY_LOGO},
950 {"rsolve(equation,u(n),[init])", 0, "Expression d'une suite donnee par une recurrence.","u(n+1)=2*u(n)+3,u(n),u(0)=1", "([u(n+1)=3*v(n)+u(n),v(n+1)=v(n)+u(n)],[u(n),v(n)],[u(0)=1,v(0)=2]", CAT_CATEGORY_SOLVE},
951 {"saute n", "saute ", "La tortue fait un saut de n pas, par defaut n=10", "#saute 30", 0, CAT_CATEGORY_LOGO},
952 {"scatterplot(Xlist,Ylist)", 0, "Nuage de points.", "[1,2,3,4,5],[0,1,3,4,4]", 0, CAT_CATEGORY_STATS},
953 {"segment(A,B)", 0, "Segment", "1,2+i", 0, CAT_CATEGORY_PROGCMD},
954 {"seq(expr,var,a,b[,pas])", 0, "Liste de terme general donne.","j^2,j,1,10", "j^2,j,1,10,2", CAT_CATEGORY_LIST},
955 {"si (test Xcas)", "si alors sinon fsi;", "Test.", "#f(x):=si x>0 alors x; sinon -x; fsi;", 0, CAT_CATEGORY_PROG},
956 {"sign(x)", 0, "Renvoie -1 si x est negatif, 0 si x est nul et 1 si x est positif.", 0, 0, CAT_CATEGORY_REAL},
957 {"simplify(expr)", 0, "Renvoie en general expr sous forme simplifiee. Raccourci expr=>/", "sin(3x)/sin(x)", "ln(4)-ln(2)", CAT_CATEGORY_ALGEBRA},
958 {"sin_regression(Xlist,Ylist)", 0, "Regression trigonometrique.", "[1,2,3,4,5,6,7,8,9,10,11,12,13,14],[0.1,0.5,0.8,1,0.7,0.5,0.05,-.5,-.75,-1,-.7,-.4,0.1,.5]", 0, CAT_CATEGORY_STATS},
959 {"sin_regression_plot(Xlist,Ylist)", 0, "Graphe d'une regression trigonometrique.", "#X,Y:=[1,2,3,4,5,6,7,8,9,10,11,12,13,14],[0.1,0.5,0.8,1,0.7,0.5,0.05,-.5,-.75,-1,-.7,-.4,0.1,.5];sin_regression_plot(X,Y);", 0, CAT_CATEGORY_STATS },
960 {"solve(equation,x)", 0, "Resolution exacte d'une equation en x (ou d'un systeme polynomial). Utiliser csolve pour les solutions complexes, linsolve pour un systeme lineaire. Raccourci SHIFT XthetaT", "x^2-x-1=0,x", "[x^2-y^2=0,x^2-z^2=0],[x,y,z]", CAT_CATEGORY_SOLVE},
961 {"sort(l)", 0, "Trie une liste.","[3/2,2,1,1/2,3,2,3/2]", "[[1,2],[2,3],[4,3]],(x,y)->when(x[1]==y[1],x[0]>y[0],x[1]>y[1]", CAT_CATEGORY_LIST},
962 {"square_point", "square_point", "Option d'affichage", "#display=cyan+square_point", 0, CAT_CATEGORY_PROGCMD },
963 {"star_point", "star_point", "Option d'affichage", "#display=magenta+star_point", 0, CAT_CATEGORY_PROGCMD },
964 {"stddev(l)", 0, "Ecart-type d'une liste l", "[3/2,2,1,1/2,3,2,3/2]", 0, CAT_CATEGORY_STATS},
965 {"subst(a,b=c)", 0, "Remplace b par c dans a. Raccourci a(b=c). Pour faire plusieurs remplacements, saisir subst(expr,[b1,b2...],[c1,c2...])", "x^2,x=3", "x+y^2,[x,y],[1,2]", CAT_CATEGORY_ALGEBRA},
966 {"sum(f,k,m,M)", 0, "Somme de l'expression f dependant de k pour k variant de m a M. Exemple sum(k^2,k,1,n)=>*. Raccourci ALPHA F3", "k,k,1,n", "k^2,k", CAT_CATEGORY_CALCULUS},
967 {"svd(A)", 0, "Singular Value Decomposition, renvoie U orthogonale, S vecteur des valeurs singulières, Q orthogonale tels que A=U*diag(S)*tran(Q).", "[[1,2],[3,4]]", 0, CAT_CATEGORY_MATRIX},
968 {"tabvar(f,[x=a..b])", 0, "Tableau de variations de l'expression f, avec arguments optionnels la variable x dans l'intervalle a..b.", "sqrt(x^2+x+1)", "[cos(2t),sin(3t)],t", CAT_CATEGORY_CALCULUS},
969 {"tantque (boucle Xcas)", "tantque faire ftantque;", "Boucle indefinie.", "#j:=13; tantque j!=1 faire j:=ifte(even(j),j/2,3j+1); print(j); ftantque;", 0, CAT_CATEGORY_PROG},
970 {"taylor(f,x=a,n,[polynom])", 0, "Developpement de Taylor de l'expression f en x=a a l'ordre n, ajouter le parametre polynom pour enlever le terme de reste.","sin(x),x=0,5", "sin(x),x=0,5,polynom", CAT_CATEGORY_CALCULUS},
971 {"tchebyshev1(n)", 0, "Polynome de Tchebyshev de 1ere espece: cos(n*x)=T_n(cos(x))", "10", 0, CAT_CATEGORY_POLYNOMIAL},
972 {"tchebyshev2(n)", 0, "Polynome de Tchebyshev de 2eme espece: sin((n+1)*x)=sin(x)*U_n(cos(x))", "10", 0, CAT_CATEGORY_POLYNOMIAL},
973 {"tcollect(expr)", 0, "Linearisation trigonometrique et regroupement.","sin(x)+cos(x)", 0, CAT_CATEGORY_TRIG},
974 {"texpand(expr)", 0, "Developpe les fonctions trigonometriques, exp et ln.","sin(3x)", "ln(x*y)", CAT_CATEGORY_TRIG},
975 {"time(cmd)", 0, "Temps pour effectuer une commande ou mise a l'heure de horloge","int(1/(x^4+1),x)","8,0", CAT_CATEGORY_PROG},
976 {"tlin(expr)", 0, "Linearisation trigonometrique de l'expression.","sin(x)^3", 0, CAT_CATEGORY_TRIG},
977 {"tourne_droite n", "tourne_droite ", "La tortue tourne de n degres, par defaut n=90", "#tourne_droite 45", 0, CAT_CATEGORY_LOGO},
978 {"tourne_gauche n", "tourne_gauche ", "La tortue tourne de n degres, par defaut n=90", "#tourne_gauche 45", 0, CAT_CATEGORY_LOGO},
979 {"trace(A)", 0, "Trace de la matrice A.", "[[1,2],[3,4]]", 0, CAT_CATEGORY_MATRIX},
980 {"tran(A)", 0, "Transposee de la matrice A. Pour la transconjuguee utiliser trn(A) ou A^*.", "[[1,2],[3,4]]", 0, CAT_CATEGORY_MATRIX},
981 {"triangle_point", "triangle_point", "Option d'affichage", "#display=yellow+triangle_point", 0, CAT_CATEGORY_PROGCMD},
982 {"trig2exp(expr)", 0, "Convertit les fonctions trigonometriques en exponentielles.","cos(x)^3", 0, CAT_CATEGORY_TRIG},
983 {"trigcos(expr)", 0, "Exprime sin^2 et tan^2 avec cos^2.","sin(x)^4", 0, CAT_CATEGORY_TRIG},
984 {"trigsin(expr)", 0, "Exprime cos^2 et tan^2 avec sin^2.","cos(x)^4", 0, CAT_CATEGORY_TRIG},
985 {"trigtan(expr)", 0, "Exprime cos^2 et sin^2 avec tan^2.","cos(x)^4", 0, CAT_CATEGORY_TRIG},
986 {"uniformd(a,b,x)", 0, "loi uniforme sur [a,b] de densite 1/(b-a)", 0, 0, CAT_CATEGORY_PROBA},
987 {"v augmente_de n", " augmente_de ", "La variable v augmente de n, ou de n %", "#v:=3; v augmente_de 1", 0, CAT_CATEGORY_SOFUS},
988 {"v diminue_de n", " diminue_de ", "La variable v diminue de n, ou de n %", "#v:=3; v diminue_de 1", 0, CAT_CATEGORY_SOFUS},
989 {"v est_divise_par n", " est_divise_par ", "La variable v est divisee par n", "#v:=3; v est_divise_par 2", 0, CAT_CATEGORY_SOFUS},
990 {"v est_eleve_puissance n", " est_eleve_puissance ", "La variable v est eleveee a la puissance n", "#v:=3; v est_eleve_puissance 2", 0, CAT_CATEGORY_SOFUS},
991 {"v est_multiplie_par n", " est_multiplie_par ", "La variable v est multipliee par n", "#v:=3; v est_multiplie_par 2", 0, CAT_CATEGORY_SOFUS},
992 //{"version", "version()", "Khicas 1.5.0, (c) B. Parisse et al. www-fourier.ujf-grenoble.fr/~parisse. License GPL version 2. Interface adaptee d'Eigenmath pour Casio, G. Maia, http://gbl08ma.com", 0, 0, CAT_CATEGORY_PROGCMD},
993 {"write(\"filename\",var)", "write(\"", "Sauvegarde une ou plusieurs variables dans un fichier. Par exemple f(x):=x^2; write(\"func_f\",f).", 0, 0, CAT_CATEGORY_PROGCMD},
994 {"yellow", "yellow", "Option d'affichage", "#display=yellow", 0, CAT_CATEGORY_PROGCMD},
995 {"|", "|", "Ou logique", "#1|2", 0, CAT_CATEGORY_PROGCMD},
996 {"~", "~", "Complement", "#~7", 0, CAT_CATEGORY_PROGCMD},
997 };
998
999 const catalogFunc completeCaten[] = { // list of all functions (including some not in any category)
1000 {" loop for", "for ", "Defined loop.", "#\nfor ", 0, CAT_CATEGORY_PROG},
1001 {" loop in list", "for in", "Loop on all elements of a list.", "#\nfor in", 0, CAT_CATEGORY_PROG},
1002 {" loop while", "while ", "Undefined loop.", "#\nwhile ", 0, CAT_CATEGORY_PROG},
1003 {" test if", "if ", "Test", "#\nif ", 0, CAT_CATEGORY_PROG},
1004 {" test else", "else ", "Test false case", 0, 0, CAT_CATEGORY_PROG},
1005 {" function def", "f(x):=", "Definition of function.", "#\nf(x):=", 0, CAT_CATEGORY_PROG},
1006 {" local j,k;", "local ", "Local variables declaration (Xcas)", 0, 0, CAT_CATEGORY_PROG},
1007 {" range(a,b)", 0, "In range [a,b) (a included, b excluded)", "# in range(1,10)", 0, CAT_CATEGORY_PROG},
1008 {" return res", "return ", "Leaves current function and returns res.", 0, 0, CAT_CATEGORY_PROG},
1009 {" edit list ", "list ", "List creation wizzard.", 0, 0, CAT_CATEGORY_LIST},
1010 {" edit matrix ", "matrix ", "Matrix creation wizzard.", 0, 0, CAT_CATEGORY_MATRIX},
1011 {" mksa(x)", 0, "Conversion to MKSA units", 0, 0, CAT_CATEGORY_PHYS | (CAT_CATEGORY_UNIT << 8)},
1012 {" ufactor(a,b)", 0, "Factorize unit b in a", "100_J,1_kW", 0, CAT_CATEGORY_PHYS | (CAT_CATEGORY_UNIT << 8)},
1013 {" usimplify(a)", 0, "Simplify unit", "100_l/10_cm^2", 0, CAT_CATEGORY_PHYS | (CAT_CATEGORY_UNIT << 8)},
1014 {"!", "!", "Logical not (prefix) or factorial of n (suffix).", "#7!", "~!b", CAT_CATEGORY_PROGCMD},
1015 {"#", "#", "Python comment, for Xcas comment type //. Shortcut ALPHA F2", 0, 0, CAT_CATEGORY_PROG},
1016 {"%", "%", "a % b means a modulo b", 0, 0, CAT_CATEGORY_ARIT | (CAT_CATEGORY_PROGCMD << 8)},
1017 {"&", "&", "Logical and or +", "#1&2", 0, CAT_CATEGORY_PROGCMD},
1018 {":=", ":=", "Set variable value. Shortcut SHIFT F1", "#a:=3", 0, CAT_CATEGORY_PROGCMD|(CAT_CATEGORY_SOFUS<<8)},
1019 {"<", "<", "Shortcut SHIFT F2", 0, 0, CAT_CATEGORY_PROGCMD},
1020 {"=>", "=>", "Store value in variable or conversion (touche ->). For example 5=>a or x^4-1=>* or (x+1)^2=>+ or sin(x)^2=>cos.", "#5=>a", "#15_ft=>_cm", CAT_CATEGORY_PROGCMD | (CAT_CATEGORY_PHYS <<8) | (CAT_CATEGORY_UNIT << 16)},
1021 {">", ">", "Shortcut F2.", 0, 0, CAT_CATEGORY_PROGCMD},
1022 {"\\", "\\", "\\ char", 0, 0, CAT_CATEGORY_PROGCMD},
1023 {"_", "_", "_ char, shortcut (-).", 0, 0, CAT_CATEGORY_PROGCMD},
1024 {"_(km/h)", "_(km/h)", "Speed kilometer per hour", 0, 0, CAT_CATEGORY_UNIT},
1025 {"_(m/s)", "_(m/s)", "Speed meter/second", 0, 0, CAT_CATEGORY_UNIT},
1026 {"_(m/s^2)", "_(m/s^2)", "Acceleration", 0, 0, CAT_CATEGORY_UNIT},
1027 {"_(m^2/s)", "_(m^2/s)", "Viscosity", 0, 0, CAT_CATEGORY_UNIT},
1028 {"_A", 0, "Ampere", 0, 0, CAT_CATEGORY_UNIT},
1029 {"_Bq", 0, "Becquerel", 0, 0, CAT_CATEGORY_UNIT},
1030 {"_C", 0, "Coulomb", 0, 0, CAT_CATEGORY_UNIT},
1031 {"_Ci", 0, "Curie", 0, 0, CAT_CATEGORY_UNIT},
1032 {"_F", 0, "Farad", 0, 0, CAT_CATEGORY_UNIT},
1033 {"_F_", 0, "Faraday constant", 0, 0, CAT_CATEGORY_PHYS},
1034 {"_G_", 0, "Gravitation force=_G_*m1*m2/r^2", 0, 0, CAT_CATEGORY_PHYS},
1035 {"_H", 0, "Henry", 0, 0, CAT_CATEGORY_UNIT},
1036 {"_Hz", 0, "Hertz", 0, 0, CAT_CATEGORY_UNIT},
1037 {"_J", 0, "Joule=kg*m^2/s^2", 0, 0, CAT_CATEGORY_UNIT},
1038 {"_K", 0, "Temperature in Kelvin", 0, 0, CAT_CATEGORY_UNIT},
1039 {"_Kcal", 0, "Energy kilo-calorie", 0, 0, CAT_CATEGORY_UNIT},
1040 {"_MeV", 0, "Energy mega-electron-Volt", 0, 0, CAT_CATEGORY_UNIT},
1041 {"_N", 0, "Force Newton=kg*m/s^2", 0, 0, CAT_CATEGORY_UNIT},
1042 {"_NA_", 0, "Avogadro constant", 0, 0, CAT_CATEGORY_PHYS},
1043 {"_Ohm", 0, "Ohm", 0, 0, CAT_CATEGORY_UNIT},
1044 {"_PSun_", 0, "Sun power", 0, 0, CAT_CATEGORY_PHYS},
1045 {"_Pa", 0, "Pressure in Pascal=kg/m/s^2", 0, 0, CAT_CATEGORY_UNIT},
1046 {"_REarth_", 0, "Earth radius", 0, 0, CAT_CATEGORY_PHYS},
1047 {"_RSun_", 0, "Sun radius", 0, 0, CAT_CATEGORY_PHYS},
1048 {"_R_", 0, "Boltzmann constant (per mol)", 0, 0, CAT_CATEGORY_PHYS},
1049 {"_S", 0, "", 0, 0, CAT_CATEGORY_UNIT},
1050 {"_StdP_", 0, "Standard pressure", 0, 0, CAT_CATEGORY_PHYS},
1051 {"_StdT_", 0, "Standard temperature (0 degre Celsius in Kelvins)", 0, 0, CAT_CATEGORY_PHYS},
1052 {"_Sv", 0, "Sievert", 0, 0, CAT_CATEGORY_UNIT},
1053 {"_T", 0, "Tesla", 0, 0, CAT_CATEGORY_UNIT},
1054 {"_V", 0, "Volt", 0, 0, CAT_CATEGORY_UNIT},
1055 {"_Vm_", 0, "Volume molaire", 0, 0, CAT_CATEGORY_PHYS},
1056 {"_W", 0, "Watt=kg*m^2/s^3", 0, 0, CAT_CATEGORY_UNIT},
1057 {"_Wb", 0, "Weber", 0, 0, CAT_CATEGORY_UNIT},
1058 {"_alpha_", 0, "fine structure constant", 0, 0, CAT_CATEGORY_PHYS},
1059 {"_c_", 0, "speed of light", 0, 0, CAT_CATEGORY_PHYS},
1060 {"_cd", 0, "candela", 0, 0, CAT_CATEGORY_UNIT},
1061 {"_cdf", "_cdf", "Suffix to get a cumulative distribution function. Type F2 for inverse cumulative distribution function _icdf suffix.", "#_icdf", 0, CAT_CATEGORY_PROBA},
1062 {"_d", 0, "day", 0, 0, CAT_CATEGORY_UNIT},
1063 {"_deg", 0, "degree", 0, 0, CAT_CATEGORY_UNIT},
1064 {"_eV", 0, "electron-Volt", 0, 0, CAT_CATEGORY_UNIT},
1065 {"_epsilon0_", 0, "vacuum permittivity", 0, 0, CAT_CATEGORY_PHYS},
1066 {"_ft", 0, "feet", 0, 0, CAT_CATEGORY_UNIT},
1067 {"_g_", 0, "Earth gravity (ground)", 0, 0, CAT_CATEGORY_PHYS},
1068 {"_grad", 0, "grades (angle unit(", 0, 0, CAT_CATEGORY_UNIT},
1069 {"_h", 0, "Hour", 0, 0, CAT_CATEGORY_UNIT},
1070 {"_h_", 0, "Planck constant", 0, 0, CAT_CATEGORY_PHYS},
1071 {"_ha", 0, "hectare", 0, 0, CAT_CATEGORY_UNIT},
1072 {"_hbar_", 0, "Planck constant/(2*pi)", 0, 0, CAT_CATEGORY_PHYS},
1073 {"_inch", 0, "inches", 0, 0, CAT_CATEGORY_UNIT},
1074 {"_kWh", 0, "kWh", 0, 0, CAT_CATEGORY_UNIT},
1075 {"_k_", 0, "Boltzmann constant", 0, 0, CAT_CATEGORY_PHYS},
1076 {"_kg", 0, "kilogram", 0, 0, CAT_CATEGORY_UNIT},
1077 {"_l", 0, "liter", 0, 0, CAT_CATEGORY_UNIT},
1078 {"_m", 0, "meter", 0, 0, CAT_CATEGORY_UNIT},
1079 {"_mEarth_", 0, "Earth mass", 0, 0, CAT_CATEGORY_PHYS},
1080 {"_m^2", 0, "Area in m^2", 0, 0, CAT_CATEGORY_UNIT},
1081 {"_m^3", 0, "Volume in m^3", 0, 0, CAT_CATEGORY_UNIT},
1082 {"_me_", 0, "electron mass", 0, 0, CAT_CATEGORY_PHYS},
1083 {"_miUS", 0, "US miles", 0, 0, CAT_CATEGORY_UNIT},
1084 {"_mn", 0, "minute", 0, 0, CAT_CATEGORY_UNIT},
1085 {"_mp_", 0, "proton mass", 0, 0, CAT_CATEGORY_PHYS},
1086 {"_mpme_", 0, "proton/electron mass-ratio", 0, 0, CAT_CATEGORY_PHYS},
1087 {"_mu0_", 0, "", 0, 0, CAT_CATEGORY_PHYS},
1088 {"_phi_", 0, "magnetic flux quantum", 0, 0, CAT_CATEGORY_PHYS},
1089 {"_plot", "_plot", "Suffix for a regression graph.", "#X,Y:=[1,2,3,4,5],[0,1,3,4,4];polynomial_regression_plot(X,Y,2);scatterplot(X,Y)", 0, CAT_CATEGORY_STATS},
1090 {"_qe_", 0, "electron charge", 0, 0, CAT_CATEGORY_PHYS},
1091 {"_qme_", 0, "_q_/_me_", 0, 0, CAT_CATEGORY_PHYS},
1092 {"_rad", 0, "radians", 0, 0, CAT_CATEGORY_UNIT},
1093 {"_rem", 0, "rem", 0, 0, CAT_CATEGORY_UNIT},
1094 {"_s", 0, "second", 0, 0, CAT_CATEGORY_UNIT},
1095 {"_sd_", 0, "Sideral day", 0, 0, CAT_CATEGORY_PHYS},
1096 {"_syr_", 0, "Siderale year", 0, 0, CAT_CATEGORY_PHYS},
1097 {"_tr", 0, "tour (angle unit)", 0, 0, CAT_CATEGORY_UNIT},
1098 {"_yd", 0, "yards", 0, 0, CAT_CATEGORY_UNIT},
1099 {"a and b", " and ", "Logical and", 0, 0, CAT_CATEGORY_PROGCMD},
1100 {"a or b", " or ", "Logical or", 0, 0, CAT_CATEGORY_PROGCMD},
1101 {"abcuv(a,b,c)", 0, "Find 2 polynomial u,v such that a*u+b*v=c","x+1,x^2-2,x", 0, CAT_CATEGORY_POLYNOMIAL},
1102 {"abs(x)", 0, "Absolute value or norm of x x", "-3", "[1,2,3]", CAT_CATEGORY_COMPLEXNUM | (CAT_CATEGORY_REAL<<8)},
1103 {"append", 0, "Adds an element at the end of a list","#l.append(x)", 0, CAT_CATEGORY_LIST},
1104 {"approx(x)", 0, "Approx. value x. Shortcut S-D", "pi", 0, CAT_CATEGORY_REAL},
1105 {"arg(z)", 0, "Angle of complex z.", "1+i", 0, CAT_CATEGORY_COMPLEXNUM},
1106 {"asc(string)", 0, "List of ASCII codes os a string", "\"Hello\"", 0, CAT_CATEGORY_ARIT},
1107 {"assume(hyp)", 0, "Assumption on variable.", "x>1", "x>-1 and x<1", CAT_CATEGORY_PROGCMD|(CAT_CATEGORY_SOFUS<<8)},
1108 {"avance n", "avance ", "Turtle forward n steps, default n=10", "#avance 30", 0, CAT_CATEGORY_LOGO},
1109 {"axes", "axes", "Axes visible or not axes=1 or 0", "#axes=0", 0, CAT_CATEGORY_PROGCMD << 8},
1110 {"baisse_crayon ", "baisse_crayon ", "Turtle moves with the pen writing.", 0, 0, CAT_CATEGORY_LOGO},
1111 {"barplot(list)", 0, "Bar plot of 1-d statistic serie data in list.", "[3/2,2,1,1/2,3,2,3/2]", 0, CAT_CATEGORY_STATS},
1112 {"binomial(n,p,k)", 0, "binomial(n,p,k) probability to get k success with n trials where p is the probability of success of 1 trial. binomial_cdf(n,p,k) is the probability to get at most k successes. binomial_icdf(n,p,t) returns the smallest k such that binomial_cdf(n,p,k)>=t", "10,.5,4", 0, CAT_CATEGORY_PROBA},
1113 {"bitxor", "bitxor", "Exclusive or", "#bitxor(1,2)", 0, CAT_CATEGORY_PROGCMD},
1114 {"black", "black", "Display option", "#display=black", 0, CAT_CATEGORY_PROGCMD},
1115 {"blue", "blue", "Display option", "#display=blue", 0, CAT_CATEGORY_PROGCMD},
1116 {"camembert(list)", 0, "Camembert pie-chart of a 1-d statistical serie.", "[[\"France\",6],[\"Germany\",12],[\"Switzerland\",5]]", 0, CAT_CATEGORY_STATS},
1117 {"cache_tortue ", "cache_tortue ", "Hide turtle (once the picture has been drawn).", 0, 0, CAT_CATEGORY_LOGO},
1118 {"ceiling(x)", 0, "Smallest integer not less than x", "1.2", 0, CAT_CATEGORY_REAL},
1119 {"cfactor(p)", 0, "Factorization over C.", "x^4-1", 0, CAT_CATEGORY_ALGEBRA | (CAT_CATEGORY_COMPLEXNUM << 8)},
1120 {"char(liste)", 0, "Converts a list of ASCII codes to a string.", "[97,98,99]", 0, CAT_CATEGORY_ARIT},
1121 {"charpoly(M,x)", 0, "Characteristic polynomial of matrix M in variable x.", "[[1,2],[3,4]],x", 0, CAT_CATEGORY_MATRIX},
1122 {"circle(center,radius)", 0, "Circle", "2+i,3", "1-i,1+i", CAT_CATEGORY_PROGCMD},
1123 {"clearscreen()", "clearscreen()", "Clear screen.", 0, 0, CAT_CATEGORY_PROGCMD},
1124 {"coeff(p,x,n)", 0, "Coefficient of x^n in polynomial p.", 0, 0, CAT_CATEGORY_POLYNOMIAL},
1125 {"comb(n,k)", 0, "Returns nCk", "10,4", 0, CAT_CATEGORY_PROBA},
1126 {"cond(A,[1,2,inf])", 0, "Nombre de condition d'une matrice par rapport a la norme specifiee (par defaut 1)", "[[1,2],[3,4]]", 0, CAT_CATEGORY_MATRIX},
1127 {"conj(z)", 0, "Complex conjugate of z.", "1+i", 0, CAT_CATEGORY_COMPLEXNUM},
1128 {"correlation(l1,l2)", 0, "Correlation of lists l1 and l2", "[1,2,3,4,5],[0,1,3,4,4]", 0, CAT_CATEGORY_STATS},
1129 {"covariance(l1,l2)", 0, "Covariance of lists l1 and l2", "[1,2,3,4,5],[0,1,3,4,4]", 0, CAT_CATEGORY_STATS},
1130 {"cpartfrac(p,x)", 0, "Partial fraction decomposition over C.", "1/(x^4-1)", 0, CAT_CATEGORY_ALGEBRA | (CAT_CATEGORY_COMPLEXNUM << 8)},
1131 {"crayon ", "crayon ", "Turtle drawing color", "#crayon red", 0, CAT_CATEGORY_LOGO},
1132 {"cross(u,v)", 0, "Cross product of vectors u and v.","[1,2,3],[0,1,3]", 0, CAT_CATEGORY_LINALG},
1133 {"csolve(equation,x)", 0, "Solve equation (or polynomial system) in exact mode over the complex numbers.","x^2+x+1=0", 0, CAT_CATEGORY_SOLVE| (CAT_CATEGORY_COMPLEXNUM << 8)},
1134 {"curl(u,vars)", 0, "Curl of vector u.", "[2*x*y,x*z,y*z],[x,y,z]", 0, CAT_CATEGORY_LINALG},
1135 {"cyan", "cyan", "Display option", "#display=cyan", 0, CAT_CATEGORY_PROGCMD},
1136 {"debug(f(args))", 0, "Runs user function f in step by step mode.", 0, 0, CAT_CATEGORY_PROG},
1137 {"degree(p,x)", 0, "Degre of polynomial p in x.", "x^4-1", 0, CAT_CATEGORY_POLYNOMIAL},
1138 {"denom(x)", 0, "Denominator of expression x.", "3/4", 0, CAT_CATEGORY_POLYNOMIAL},
1139 {"desolve(equation,t,y)", 0, "Exact differential equation solving.", "desolve([y'+y=exp(x),y(0)=1])", "[y'=[[1,2],[2,1]]*y+[x,x+1],y(0)=[1,2]]", CAT_CATEGORY_SOLVE | (CAT_CATEGORY_CALCULUS << 8)},
1140 {"det(A)", 0, "Determinant of matrix A.", "[[1,2],[3,4]]", 0, CAT_CATEGORY_MATRIX},
1141 {"diff(f,var,[n])", 0, "Derivative of expression f with respect to var (order n, n=1 by default), for example diff(sin(x),x) or diff(x^3,x,2). For derivation with respect to x, run f' (shortcut F3). For the gradient of f, var is the list of variables.", "sin(x),x", "sin(x^2),x,3", CAT_CATEGORY_CALCULUS},
1142 {"display", "display", "Display option", "#display=red", 0, CAT_CATEGORY_PROGCMD},
1143 {"disque n", "disque ", "Filled circle tangent to the turtle, radius n. Run disque n,theta for a filled arc of circle, theta in degrees, or disque n,theta,segment for a segment of circle.", "#disque 30", "#disque(30,90)", CAT_CATEGORY_LOGO},
1144 {"dot(a,b)", 0, "Dot product of 2 vectors. Shortcut: *", "[1,2,3,4,5],[0,1,3,4,4]", 0, CAT_CATEGORY_LINALG},
1145 {"draw_arc(x1,y1,rx,ry,theta1,theta2,c)", 0, "Pixelised arc of ellipse.", "100,100,60,80,0,pi,magenta", 0, CAT_CATEGORY_PROGCMD},
1146 {"draw_circle(x1,y1,r,c)", 0, "Pixelised circle. Option: filled", "100,100,60,cyan+filled", 0, CAT_CATEGORY_PROGCMD},
1147 {"draw_line(x1,y1,x2,y2,c)", 0, "Pixelised line.", "100,50,300,200,blue", 0, CAT_CATEGORY_PROGCMD},
1148 {"draw_pixel(x,y,color)", 0, "Colors pixel x,y. Run draw_pixel() to synchronise screen.", 0, 0, CAT_CATEGORY_PROGCMD},
1149 {"draw_polygon([[x1,y1],...],c)", 0, "Pixelised polygon.", "[[100,50],[30,20],[60,70]],red+filled", 0, CAT_CATEGORY_PROGCMD},
1150 {"draw_rectangle(x,y,w,h,c)", 0, "Rectangle.", "100,50,30,20,red+filled", 0, CAT_CATEGORY_PROGCMD},
1151 {"draw_string(s,x,y,c)", 0, "Draw string s at pixel x,y", "\"Bonjour\",80,60", 0, CAT_CATEGORY_PROGCMD},
1152 #ifndef TURTLETAB
1153 {"ecris ", "ecris ", "Write at turtle position", "#ecris \"hello\"", 0, CAT_CATEGORY_LOGO},
1154 #endif
1155 {"efface", "efface", "Reset turtle", 0, 0, CAT_CATEGORY_LOGO},
1156 {"egcd(A,B)", 0, "Find polynomials U,V,D such that A*U+B*V=D=gcd(A,B)","x^2+3x+1,x^2-5x-1", 0, CAT_CATEGORY_POLYNOMIAL},
1157 {"elif test", "elif ", "Test cascade", 0, 0, CAT_CATEGORY_PROG},
1158 {"eigenvals(A)", 0, "Eigenvalues of matrix A.", "[[1,2],[3,4]]", 0, CAT_CATEGORY_MATRIX},
1159 {"eigenvects(A)", 0, "Eigenvectors of matrix A.", "[[1,2],[3,4]]", 0, CAT_CATEGORY_MATRIX},
1160 {"erf(x)", 0, "Error function of x.", "1.2", 0, CAT_CATEGORY_PROBA},
1161 {"erfc(x)", 0, "Complementary error function of x.", "1.2", 0, CAT_CATEGORY_PROBA},
1162 {"euler(n)",0,"Euler indicatrix: number of integers < n coprime with n","25",0,CAT_CATEGORY_ARIT},
1163 {"eval(f)", 0, "Evals f.", 0, 0, CAT_CATEGORY_PROGCMD},
1164 {"evalc(z)", 0, "Write z=x+i*y.", "1/(1+i*sqrt(3))", 0, CAT_CATEGORY_COMPLEXNUM},
1165 {"exact(x)", 0, "Converts x to a rational. Shortcut shift S-D", "1.2", 0, CAT_CATEGORY_REAL},
1166 {"exp2trig(expr)", 0, "Convert complex exponentials to sin/cos", "exp(i*x)", 0, CAT_CATEGORY_TRIG},
1167 {"exponential_regression(Xlist,Ylist)", 0, "Exponential regression.", "[1,2,3,4,5],[0,1,3,4,4]", 0, CAT_CATEGORY_STATS},
1168 {"exponential_regression_plot(Xlist,Ylist)", 0, "Exponential regression plot.", "#X,Y:=[1,2,3,4,5],[0,1,3,4,4];exponential_regression_plot(X,Y);scatterplot(X,Y)", 0, CAT_CATEGORY_STATS},
1169 {"exponentiald(lambda,x)", 0, "Exponential distribution law of parameter lambda. exponentiald_cdf(lambda,x) probability that \"exponential distribution <=x\" e.g. exponentiald_cdf(2,3). exponentiald_icdf(lambda,t) returns x such that \"exponential distribution <=x\" has probability t, e.g, exponentiald_icdf(2,0.95) ", "5.1,3.4", 0, CAT_CATEGORY_PROBA},
1170 {"extend", 0, "Merge 2 lists. Note that + does not merge lists, it adds vectors","#l1.extend(l2)", 0, CAT_CATEGORY_LIST},
1171 {"factor(p,[x])", 0, "Factors polynomial p (run ifactor for an integer). Shortcut: p=>*", "x^4-1", "x^6+1,sqrt(3)", CAT_CATEGORY_ALGEBRA| (CAT_CATEGORY_POLYNOMIAL << 8)},
1172 {"filled", "filled", "Display option", 0, 0, CAT_CATEGORY_PROGCMD},
1173 {"float(x)", 0, "Converts x to a floating point value.", "pi", 0, CAT_CATEGORY_REAL},
1174 {"floor(x)", 0, "Largest integer not greater than x", "pi", 0, CAT_CATEGORY_REAL},
1175 {"fourier_an(f,x,T,n,a)", 0, "Cosine Fourier coefficients of f", "x^2,x,2*pi,n,-pi", 0, CAT_CATEGORY_CALCULUS},
1176 {"fourier_bn(f,x,T,n,a)", 0, "Sine Fourier coefficients of f", "x^2,x,2*pi,n,-pi", 0, CAT_CATEGORY_CALCULUS},
1177 {"fourier_cn(f,x,T,n,a)", 0, "Exponential Fourier coefficients of f", "x^2,x,2*pi,n,-pi", 0, CAT_CATEGORY_CALCULUS},
1178 {"from math/... import *", "from math import *", "Access to math or to random functions ([random]) or turtle with English commandnames [turtle]. Math import is not required in KhiCAS", "#from random import *", "#from turtle import *", CAT_CATEGORY_PROG},
1179 {"fsolve(equation,x=a..b)", 0, "Approx equation solving in interval a..b.","cos(x)=x,x=0..1", "cos(x)-x,x=0.0", CAT_CATEGORY_SOLVE},
1180 // {"function f(x):...", "function f(x) local y; ffunction:;", "Function definition.", "#function f(x) local y; y:=x^2; return y; ffunction:;", 0, CAT_CATEGORY_PROG},
1181 {"gauss(q)", 0, "Quadratic form reduction", "x^2+x*y+x*z+y^2+z^2,[x,y,z]", 0, CAT_CATEGORY_LINALG},
1182 {"gcd(a,b,...)", 0, "Greatest common divisor. See also iegcd and egcd for extended GCD.", "23,13", "x^2-1,x^3-1", CAT_CATEGORY_ARIT | (CAT_CATEGORY_POLYNOMIAL << 8)},
1183 {"gl_x", "gl_x", "Display settings X gl_x=xmin..xmax", "#gl_x=0..2", 0, CAT_CATEGORY_PROGCMD},
1184 {"gl_y", "gl_y", "Display settings Y gl_y=ymin..ymax", "#gl_y=-1..1", 0, CAT_CATEGORY_PROGCMD},
1185 {"gramschmidt(M)", 0, "Gram-Schmidt orthonormalization (line vectors or linearly independant set of vectors)", "[[1,2,3],[4,5,6]]", "[1,1+x],(p,q)->integrate(p*q,x,-1,1)", CAT_CATEGORY_LINALG},
1186 {"green", "green", "Display option", "#display=green", 0, CAT_CATEGORY_PROGCMD},
1187 {"halftan(expr)", 0, "Convert cos, sin, tan with tan(angle/2).","cos(x)", 0, CAT_CATEGORY_TRIG},
1188 {"hermite(n)", 0, "n-th Hermite polynomial", "10", 0, CAT_CATEGORY_POLYNOMIAL},
1189 {"hilbert(n)", 0, "Hilbert matrix of order n.", "4", 0, CAT_CATEGORY_MATRIX},
1190 {"histogram(list,min,size)", 0, "Histogram of data in list, classes begin at min of size size.","ranv(100,uniformd,0,1),0,0.1", 0, CAT_CATEGORY_STATS},
1191 {"iabcuv(a,b,c)", 0, "Find 2 integers u,v such that a*u+b*v=c","23,13,15", 0, CAT_CATEGORY_ARIT},
1192 {"ichinrem([a,m],[b,n])", 0,"Integer chinese remainder of a mod m and b mod n.", "[3,13],[2,7]", 0, CAT_CATEGORY_ARIT},
1193 {"idivis(n)", 0, "Returns the list of divisors of an integer n.", "10", 0, CAT_CATEGORY_ARIT},
1194 {"idn(n)", 0, "Identity matrix of order n", "4", 0, CAT_CATEGORY_MATRIX},
1195 {"iegcd(a,b)", 0, "Find integers u,v,d such that a*u+b*v=d=gcd(a,b)","23,13", 0, CAT_CATEGORY_ARIT},
1196 {"ifactor(n)", 0, "Factorization of an integer (not too large!). Shortcut n=>*", 0, 0, CAT_CATEGORY_ARIT},
1197 {"ilaplace(f,s,x)", 0, "Inverse Laplace transform of f", "s/(s^2+1),s,x", 0, CAT_CATEGORY_CALCULUS},
1198 {"im(z)", 0, "Imaginary part.", "1+i", 0, CAT_CATEGORY_COMPLEXNUM},
1199 {"inf", "inf", "Plus infinity. -inf for minus infinity and infinity for unsigned/complex infinity. Shortcut shift INS.", "oo", 0, CAT_CATEGORY_CALCULUS},
1200 {"input()", "input()", "Read a string from keyboard", 0, 0, CAT_CATEGORY_PROG},
1201 {"integrate(f,x,[a,b])", 0, "Antiderivative of f with respect to x, like integrate(x*sin(x),x). For definite integral enter optional arguments a and b, like integrate(x*sin(x),x,0,pi). Shortcut SHIFT F3.", "x*sin(x),x", "cos(x)/(1+x^4),x,0,inf", CAT_CATEGORY_CALCULUS},
1202 {"interp(X,Y)", 0, "Lagrange interpolation at points (xi,yi) where X is the list of xi and Y of yi. If interp is passed as 3rd argument, returns the divided differences list.", "[1,2,3,4,5],[0,1,3,4,4]", "[1,2,3,4,5],[0,1,3,4,4],interp", CAT_CATEGORY_POLYNOMIAL},
1203 {"inv(A)", 0, "Inverse of A.", "[[1,2],[3,4]]", 0, CAT_CATEGORY_MATRIX},
1204 {"iquo(a,b)", 0, "Integer quotient of a and b.", "23,13", 0, CAT_CATEGORY_ARIT},
1205 {"irem(a,b)", 0,"Integer remainder of a and b.", "23,13", 0, CAT_CATEGORY_ARIT},
1206 {"isprime(n)", 0, "Returns 1 if n is prime, 0 otherwise.", "11", "10", CAT_CATEGORY_ARIT},
1207 {"jordan(A)", 0, "Jordan normal form of matrix A, returns P and D such that P^-1*A*P=D", "[[1,2],[3,4]]", "[[1,1,-1,2,-1],[2,0,1,-4,-1],[0,1,1,1,1],[0,1,2,0,1],[0,0,-3,3,-1]]", CAT_CATEGORY_MATRIX},
1208 {"laguerre(n,a,x)", 0, "n-ieme Laguerre polynomial (default a=0).", "10", 0, CAT_CATEGORY_POLYNOMIAL},
1209 {"laplace(f,x,s)", 0, "Laplace transform of f","sin(x),x,s", 0, CAT_CATEGORY_CALCULUS},
1210 {"lcm(a,b,...)", 0, "Least common multiple.", "23,13", "x^2-1,x^3-1", CAT_CATEGORY_ARIT | (CAT_CATEGORY_POLYNOMIAL << 8)},
1211 {"lcoeff(p,x)", 0, "Leading coefficient of polynomial p in x.", "x^4-1", 0, CAT_CATEGORY_POLYNOMIAL},
1212 {"legendre(n)", 0, "n-the Legendre polynomial.", "10", "10,t", CAT_CATEGORY_POLYNOMIAL},
1213 #ifdef RELEASE
1214 {"len(l)", 0, "Size of a list.", "[3/2,2,1,1/2,3,2,3/2]", 0, CAT_CATEGORY_LIST},
1215 #endif
1216 {"leve_crayon ", "leve_crayon ", "Turtle moves without trace.", 0, 0, CAT_CATEGORY_LOGO},
1217 {"limit(f,x=a)", 0, "Limit of f at x = a. Add 1 or -1 for unidirectional limits, e.g. limit(sin(x)/x,x=0) or limit(abs(x)/x,x=0,1). Shortcut: SHIFT MIXEDFRAC", "sin(x)/x,x=0", "exp(-1/x),x=0,1", CAT_CATEGORY_CALCULUS},
1218 {"line(equation)", 0, "Line of equation", "y=2x+1", 0, CAT_CATEGORY_PROGCMD},
1219 {"line_width_", "line_width_", "Width prefix (2 to 8)", 0, 0, CAT_CATEGORY_PROGCMD},
1220 {"linear_regression(Xlist,Ylist)", 0, "Linear regression.", "[1,2,3,4,5],[0,1,3,4,4]", 0, CAT_CATEGORY_STATS},
1221 {"linear_regression_plot(Xlist,Ylist)", 0, "Linear regression plot.", "#X,Y:=[1,2,3,4,5],[0,1,3,4,4];linear_regression_plot(X,Y);scatterplot(X,Y)", 0, CAT_CATEGORY_STATS},
1222 {"linetan(expr,x,x0)", 0, "Tangent to the graph at x=x0.", "sin(x),x,pi/2", 0, CAT_CATEGORY_PLOT},
1223 {"linsolve([eq1,eq2,..],[x,y,..])", 0, "Linear system solving. May use the output of lu for O(n^2) solving (see example 2).","[x+y=1,x-y=2],[x,y]", "#p,l,u:=lu([[1,2],[3,4]]); linsolve(p,l,u,[5,6])", CAT_CATEGORY_SOLVE | (CAT_CATEGORY_LINALG <<8) | (CAT_CATEGORY_MATRIX << 16)},
1224 {"logarithmic_regression(Xlist,Ylist)", 0, "Logarithmic egression.", "[1,2,3,4,5],[0,1,3,4,4]", 0, CAT_CATEGORY_STATS},
1225 {"logarithmic_regression_plot(Xlist,Ylist)", 0, "Logarithmic regression plot.", "#X,Y:=[1,2,3,4,5],[0,1,3,4,4];logarithmic_regression_plot(X,Y);scatterplot(X,Y)", 0, CAT_CATEGORY_STATS},
1226 {"lu(A)", 0, "LU decomposition LU of matrix A, P*A=L*U", "[[1,2],[3,4]]", 0, CAT_CATEGORY_MATRIX},
1227 {"magenta", "magenta", "Display option", "#display=magenta", 0, CAT_CATEGORY_PROGCMD},
1228 {"map(l,f)", 0, "Maps f on element of list l.","[1,2,3],x->x^2", 0, CAT_CATEGORY_LIST},
1229 {"matpow(A,n)", 0, "Returns matrix A^n", "[[1,2],[3,4]],n","#assume(n>=1);matpow([[0,2],[0,4]],n)", CAT_CATEGORY_MATRIX},
1230 {"matrix(r,c,func)", 0, "Matrix from a defining function.", "2,3,(j,k)->j^k", 0, CAT_CATEGORY_MATRIX},
1231 {"mean(l)", 0, "Arithmetic mean of list l", "[3/2,2,1,1/2,3,2,3/2]", 0, CAT_CATEGORY_STATS},
1232 {"median(l)", 0, "Median", "[3/2,2,1,1/2,3,2,3/2]", 0, CAT_CATEGORY_STATS},
1233 {"montre_tortue ", "montre_tortue ", "Displays the turtle", 0, 0, CAT_CATEGORY_LOGO},
1234 {"mult_c_conjugate", 0, "Multiplier par le conjugue complexe.", "1+2*i", 0, (CAT_CATEGORY_COMPLEXNUM << 8)},
1235 {"mult_conjugate", 0, "Multiplier par le conjugue (sqrt).", "sqrt(2)-sqrt(3)", 0, CAT_CATEGORY_ALGEBRA},
1236 {"normald([mu,sigma],x)", 0, "Normal distribution probability density, by default mu=0 and sigma=1. normald_cdf([mu,sigma],x) probability that \"normal distribution <=x\" e.g. normald_cdf(1.96). normald_icdf([mu,sigma],t) returns x such that \"normal distribution <=x\" has probability t, e.g. normald_icdf(0.975) ", "1.2", 0, CAT_CATEGORY_PROBA},
1237 {"not(x)", 0, "Logical not.", 0, 0, CAT_CATEGORY_PROGCMD},
1238 {"numer(x)", 0, "Numerator of x.", "3/4", 0, CAT_CATEGORY_POLYNOMIAL},
1239 {"odesolve(f(t,y),[t,y],[t0,y0],t1)", 0, "Approx. solution of differential equation y'=f(t,y) and y(t0)=y0, value for t=t1 (add curve to get intermediate values of y)", "sin(t*y),[t,y],[0,1],2", "0..pi,(t,v)->{[-v[1],v[0]]},[0,1]", CAT_CATEGORY_SOLVE},
1240 {"partfrac(p,x)", 0, "Partial fraction expansion. Shortcut p=>+", "1/(x^4-1)", 0, CAT_CATEGORY_ALGEBRA},
1241 {"pas_de_cote n", "pas_de_cote ", "Turtle side jump from n steps, by default n=10", "#pas_de_cote 30", 0, CAT_CATEGORY_LOGO},
1242 {"plot(expr,x)", 0, "Plot an expression. For example plot(sin(x)), plot(ln(x),x.0,5)", "ln(x),x,0,5", "1/x,x=1..5,xstep=1", CAT_CATEGORY_PLOT},
1243 #ifdef RELEASE
1244 {"plotarea(expr,x=a..b,[n,meth])", 0, "Area under curve with specified quadrature.", "1/x,x=1..3,2,trapezoid", 0, CAT_CATEGORY_PLOT},
1245 #endif
1246 {"plotcontour(expr,[x=xm..xM,y=ym..yM],levels)", 0, "Levels of expr.", "x^2+2y^2,[x=-2..2,y=-2..2],[1,2]", 0, CAT_CATEGORY_PLOT},
1247 {"plotfield(f(t,y),[t=tmin..tmax,y=ymin..ymax])", 0, "Plot field of differential equation y'=f(t,y), an optionnally one solution by adding plotode=[t0,y0]", "sin(t*y),[t=-3..3,y=-3..3],plotode=[0,1]", 0, CAT_CATEGORY_PLOT},
1248 {"plotlist(list)", 0, "Plot a list", "[3/2,2,1,1/2,3,2,3/2]", 0, CAT_CATEGORY_PLOT},
1249 {"plotode(f(t,y),[t=tmin..tmax,y],[t0,y0])", 0, "Plot solution of differential equation y'=f(t,y), y(t0)=y0.", "sin(t*y),[t=-3..3,y],[0,1]", 0, CAT_CATEGORY_PLOT},
1250 {"plotparam([x,y],t)", 0, "Parametric plot. For example plotparam([sin(3t),cos(2t)],t,0,pi) or plotparam(exp(i*t),t,0,pi)", "[sin(3t),cos(2t)],t,0,pi", "[t^2,t^3],t=-1..1,tstep=0.1", CAT_CATEGORY_PLOT},
1251 {"plotpolar(r,theta)", 0, "Polar plot.","cos(3*x),x,0,pi", "1/(1+cos(x)),x=0..pi,xstep=0.05", CAT_CATEGORY_PLOT},
1252 {"plotseq(f(x),x=[u0,m,M],n)", 0, "Plot f(x) on [m,M] and n terms of the sequence defined by u_{n+1}=f(u_n) and u0.","sqrt(2+x),x=[6,0,7],5", 0, CAT_CATEGORY_PLOT},
1253 {"plus_point", "plus_point", "Display option", "#display=blue+plus_point", 0, CAT_CATEGORY_PROGCMD},
1254 {"point(x,y)", 0, "Point", "1,2", 0, CAT_CATEGORY_PLOT},
1255 {"polygon(list)", 0, "Closed polygon.", "1-i,2+i,3", 0, CAT_CATEGORY_PROGCMD},
1256 {"polygonscatterplot(Xlist,Ylist)", 0, "Plot points and polygonal line.", "[1,2,3,4,5],[0,1,3,4,4]", 0, CAT_CATEGORY_STATS},
1257 {"polynomial_regression(Xlist,Ylist,n)", 0, "Polynomial regression, degree <= n.", "[1,2,3,4,5],[0,1,3,4,4],2", 0, CAT_CATEGORY_STATS},
1258 {"polynomial_regression_plot(Xlist,Ylist,n)", 0, "Polynomial regression plot, degree <= n.", "#X,Y:=[1,2,3,4,5],[0,1,3,4,4];polynomial_regression_plot(X,Y,2);scatterplot(X,Y)", 0, CAT_CATEGORY_STATS},
1259 //{"pour", "pour j de 1 jusque faire fpour;", "For loop.","#pour j de 1 jusque 10 faire print(j,j^2); fpour;", 0, CAT_CATEGORY_PROG},
1260 {"power_regression(Xlist,Ylist,n)", 0, "Power regression.", "[1,2,3,4,5],[0,1,3,4,4]", 0, CAT_CATEGORY_STATS},
1261 {"power_regression_plot(Xlist,Ylist,n)", 0, "Power regression graph", "#X,Y:=[1,2,3,4,5],[0,1,3,4,4];power_regression_plot(X,Y);scatterplot(X,Y)", 0, CAT_CATEGORY_STATS},
1262 {"powmod(a,n,p)", 0, "Returns a^n mod p.","123,456,789", 0, CAT_CATEGORY_ARIT},
1263 {"print(expr)", 0, "Print expr in console", 0, 0, CAT_CATEGORY_PROG},
1264 {"proot(p)", 0, "Returns real and complex roots, of polynomial p. Exemple proot([1,2.1,3,4.2]) or proot(x^3+2.1*x^2+3x+4.2)", "x^3+2.1*x^2+3x+4.2", 0, CAT_CATEGORY_POLYNOMIAL},
1265 {"purge(x)", 0, "Clear assigned variable x. Shortcut SHIFT-FORMAT", 0, 0, CAT_CATEGORY_PROGCMD|(CAT_CATEGORY_SOFUS<<8)},
1266 {"python(f)", 0, "Displays f in Python syntax.", 0, 0, CAT_CATEGORY_PROGCMD},
1267 {"python_compat(0|1|2)", 0, "python_compat(0) Xcas syntax, python_compat(1) Python syntax with ^ interpreted as power, python_compat(2) ^ as bit xor", "0", "1", CAT_CATEGORY_PROG},
1268 {"qr(A)", 0, "A=Q*R factorization with Q orthogonal and R upper triangular", "[[1,2],[3,4]]", 0, CAT_CATEGORY_MATRIX},
1269 {"quartile1(l)", 0, "1st quartile", "[3/2,2,1,1/2,3,2,3/2]", 0, CAT_CATEGORY_STATS},
1270 {"quartile3(l)", 0, "3rd quartile", "[3/2,2,1,1/2,3,2,3/2]", 0, CAT_CATEGORY_STATS},
1271 {"quo(p,q,x)", 0, "Quotient of synthetic division of polynomials p and q (variable x).", 0, 0, CAT_CATEGORY_POLYNOMIAL},
1272 {"quote(x)", 0, "Returns expression x unevaluated.", 0, 0, CAT_CATEGORY_ALGEBRA},
1273 {"rand()", "rand()", "Random real between 0 and 1", 0, 0, CAT_CATEGORY_PROBA},
1274 {"randint(n)", 0, "Random integer between 1 and n", "6", 0, CAT_CATEGORY_PROBA},
1275 {"ranm(n,m,[loi,parametres])", 0, "Random matrix with integer coefficients or according to a probability law (ranv for a vector). Examples ranm(2,3), ranm(3,2,binomial,20,.3), ranm(4,2,normald,0,1)", "4,2,normald,0,1", "3,3,10", CAT_CATEGORY_MATRIX},
1276 {"ranv(n,[loi,parametres])", 0, "Random vector.", "4,normald,0,1", "10,30", CAT_CATEGORY_LINALG},
1277 {"ratnormal(x)", 0, "Puts everything over a common denominator.", 0, 0, CAT_CATEGORY_ALGEBRA},
1278 {"re(z)", 0, "Real part.", "1+i", 0, CAT_CATEGORY_COMPLEXNUM},
1279 {"read(\"filename\")", "read(\"", "Read a file.", 0, 0, CAT_CATEGORY_PROGCMD},
1280 {"rectangle_plein a,b", "rectangle_plein ", "Direct filled rectangle from turtle position, if b is omitted b==a", "#rectangle_plein 30","#rectangle_plein 20,40", CAT_CATEGORY_LOGO},
1281 {"recule n", "recule ", "Turtle backward n steps, n=10 by default", "#recule 30", 0, CAT_CATEGORY_LOGO},
1282 {"red", "red", "Display option", "#display=red", 0, CAT_CATEGORY_PROGCMD},
1283 {"rem(p,q,x)", 0, "Remainder of synthetic division of polynomials p and q (variable x)", 0, 0, CAT_CATEGORY_POLYNOMIAL},
1284 #ifdef RELEASE
1285 {"residue(f(z),z,z0)", 0, "Residue of an expression at z0.", "1/(x^2+1),x,i", 0, CAT_CATEGORY_COMPLEXNUM},
1286 #endif
1287 {"resultant(p,q,x)", 0, "Resultant in x of polynomials p and q.", "#P:=x^3+p*x+q;resultant(P,P',x);", 0, CAT_CATEGORY_POLYNOMIAL},
1288 {"revert(p[,x])", 0, "Revert Taylor series","x+x^2+x^4", 0, CAT_CATEGORY_CALCULUS},
1289 {"rgb(r,g,b)", 0, "color defined from red, green, blue from 0 to 255", "255,0,255", 0, CAT_CATEGORY_PROGCMD},
1290 {"rhombus_point", "rhombus_point", "Display option", "#display=magenta+rhombus_point", 0, CAT_CATEGORY_PROGCMD},
1291 {"rond n", "rond ", "Circle tangent to the turtle, radius n. Run rond n,theta for an arc of circle of theta degrees", 0, 0, CAT_CATEGORY_LOGO},
1292 {"rsolve(equation,u(n),[init])", 0, "Solve a recurrence relation.","u(n+1)=2*u(n)+3,u(n),u(0)=1", "([u(n+1)=3*v(n)+u(n),v(n+1)=v(n)+u(n)],[u(n),v(n)],[u(0)=1,v(0)=2]", CAT_CATEGORY_SOLVE},
1293 {"saute n", "saute ", "Turtle jumps n steps, by default n=10", "#saute 30", 0, CAT_CATEGORY_LOGO},
1294 {"scatterplot(Xlist,Ylist)", 0, "Draws points", "[1,2,3,4,5],[0,1,3,4,4]", 0, CAT_CATEGORY_STATS},
1295 {"segment(A,B)", 0, "Segment", "1,2+i", 0, CAT_CATEGORY_PROGCMD},
1296 {"seq(expr,var,a,b)", 0, "Generates a list from an expression.","j^2,j,1,10", 0, CAT_CATEGORY_PROGCMD},
1297 //{"si", "si alors sinon fsi;", "Test.", "#f(x):=si x>0 alors x; sinon -x; fsi;// valeur absolue", 0, CAT_CATEGORY_PROG},
1298 {"sign(x)", 0, "Returns -1 if x is negative, 0 if x is zero and 1 if x is positive.", 0, 0, CAT_CATEGORY_REAL},
1299 {"simplify(expr)", 0, "Returns x in a simpler form. Shortcut expr=>/", "sin(3x)/sin(x)", 0, CAT_CATEGORY_ALGEBRA},
1300 {"solve(equation,x)", 0, "Exact solving of equation w.r.t. x (or of a polynomial system). Run csolve for complex solutions, linsolve for a linear system. Shortcut SHIFT XthetaT", "x^2-x-1=0,x", "[x^2-y^2=0,x^2-z^2=0],[x,y,z]", CAT_CATEGORY_SOLVE},
1301 {"sort(l)", 0, "Sorts a list.","[3/2,2,1,1/2,3,2,3/2]", "[[1,2],[2,3],[4,3]],(x,y)->when(x[1]==y[1],x[0]>y[0],x[1]>y[1]", CAT_CATEGORY_LIST},
1302 {"square_point", "square_point", "Display option", "#display=cyan+square_point", 0, CAT_CATEGORY_PROGCMD},
1303 {"star_point", "star_point", "Display option", "#display=magenta+star_point", 0, CAT_CATEGORY_PROGCMD},
1304 {"stddev(l)", 0, "Standard deviation of list l", "[3/2,2,1,1/2,3,2,3/2]", 0, CAT_CATEGORY_STATS},
1305 {"subst(a,b=c)", 0, "Substitutes b for c in a. Shortcut a(b=c).", "x^2,x=3", 0, CAT_CATEGORY_ALGEBRA},
1306 {"sum(f,k,m,M)", 0, "Summation of expression f for k from m to M. Exemple sum(k^2,k,1,n)=>*. Shortcut ALPHA F3", "k,k,1,n", 0, CAT_CATEGORY_CALCULUS},
1307 {"svd(A)", 0, "Singular Value Decomposition, returns U orthogonal, S vector of singular values, Q orthogonal such that A=U*diag(S)*tran(Q).", "[[1,2],[3,4]]", 0, CAT_CATEGORY_MATRIX},
1308 {"tabvar(f,[x=a..b])", 0, "Table of variations of expression f, optional arguments variable x in interval a..b", "sqrt(x^2+x+1)", "[cos(t),sin(3t)],t", CAT_CATEGORY_CALCULUS},
1309 //{"tantque", "tantque faire ftantque;", "While loop.", "#j:=13; tantque j!=1 faire j:=when(even(j),j/2,3j+1); print(j); ftantque;", 0, CAT_CATEGORY_PROG},
1310 {"taylor(f,x=a,n,[polynom])", 0, "Taylor expansion of f of x at a order n, add parameter polynom to remove remainder term.","sin(x),x=0,5", "sin(x),x=0,5,polynom", CAT_CATEGORY_CALCULUS},
1311 {"tchebyshev1(n)", 0, "Tchebyshev polynomial 1st kind: cos(n*x)=T_n(cos(x))", "10", 0, CAT_CATEGORY_POLYNOMIAL},
1312 {"tchebyshev2(n)", 0, "Tchebyshev polynomial 2nd kind: sin((n+1)*x)=sin(x)*U_n(cos(x))", "10", 0, CAT_CATEGORY_POLYNOMIAL},
1313 {"tcollect(expr)", 0, "Linearize and collect trig functions.","sin(x)+cos(x)", 0, CAT_CATEGORY_TRIG},
1314 {"texpand(expr)", 0, "Expand trigonometric, exp and ln functions.","sin(3x)", 0, CAT_CATEGORY_TRIG},
1315 {"time(cmd)", 0, "Time to run a command or set the clock","int(1/(x^4+1),x)","8,0", CAT_CATEGORY_PROG},
1316 {"tlin(expr)", 0, "Trigonometric linearization of expr.","sin(x)^3", 0, CAT_CATEGORY_TRIG},
1317 {"tourne_droite n", "tourne_droite ", "Turtle turns right n degrees, n=90 by default", 0, 0, CAT_CATEGORY_LOGO},
1318 {"tourne_gauche n", "tourne_gauche ", "Turtle turns left n degrees, n=90 by default", 0, 0, CAT_CATEGORY_LOGO},
1319 {"trace(A)", 0, "Trace of the matrix A.", "[[1,2],[3,4]]", 0, CAT_CATEGORY_MATRIX},
1320 {"tran(A)", 0, "Transposes matrix A. Transconjugate command is trn(A) or A^*.", "[[1,2],[3,4]]", 0, CAT_CATEGORY_MATRIX},
1321 {"triangle_point", "triangle_point", "Display option", "#display=yellow+triangle_point", 0, CAT_CATEGORY_PROGCMD},
1322 {"trig2exp(expr)", 0, "Convert complex exponentials to trigonometric functions","cos(x)^3", 0, CAT_CATEGORY_TRIG},
1323 {"trigcos(expr)", 0, "Convert sin^2 and tan^2 to cos^2.","sin(x)^4", 0, CAT_CATEGORY_TRIG},
1324 {"trigsin(expr)", 0, "Convert cos^2 and tan^2 to sin^2.","cos(x)^4", 0, CAT_CATEGORY_TRIG},
1325 {"trigtan(expr)", 0, "Convert cos^2 and sin^2 to tan^2.","cos(x)^4", 0, CAT_CATEGORY_TRIG},
1326 {"uniformd(a,b,x)", "uniformd", "uniform law on [a,b] of density 1/(b-a)", 0, 0, CAT_CATEGORY_PROBA},
1327 //{"version", "version()", "Khicas 1.5.0, (c) B. Parisse et al. www-fourier.ujf-grenoble.fr/~parisse\nLicense GPL version 2. Interface adapted from Eigenmath for Casio, G. Maia, http://gbl08ma.com. Do not use if CAS calculators are forbidden.", 0, 0, CAT_CATEGORY_PROGCMD},
1328 {"write(\"filename\",var)", "write(\"", "Save 1 or more variables in a file. For example f(x):=x^2; write(\"func_f\",f).", 0, 0, CAT_CATEGORY_PROGCMD},
1329 {"yellow", "yellow", "Display option", "#display=yellow", 0, CAT_CATEGORY_PROGCMD},
1330 {"|", "|", "Logical or", "#1|2", 0, CAT_CATEGORY_PROGCMD},
1331 {"~", "~", "Complement", "#~7", 0, CAT_CATEGORY_PROGCMD},
1332 };
1333
1334 const char aide_khicas_string[]="Aide Khicas";
1335 #ifdef NUMWORKS
1336 const char shortcuts_fr_string[]="Raccourcis clavier (shell et editeur)\nshift-/: %\nalpha shift \": '\nshift--: \\\nshift-*: factor\nshift-+: normal\nshift-1 a 6: selon bandeau en bas\nshift-7: matrices\nshift-8: listes\nshift-9:arithmetique\nshift-0: polynomes\nshift-.: reels\nshift-10^: programme\nvar: liste des variables (shell) ou dessin tortue (editeur)\n\nshift-x^y (sto) renvoie =>\n=>+: partfrac\n=>*: factor\n=>sin/cos/tan\n=>=>: solve\n\nShell:\nshift-5: Editeur 2d ou graphique ou texte selon objet\nshift-6: editeur texte\n+ ou - modifie un parametre en surbrillance\n\nEditeur d'expressions\nshift-cut: defaire/refaire (1 fois)\npave directionnel: deplace la selection dans l'arborescence de l'expression\nshift-droit/gauche echange selection avec argument a droite ou a gauche\nalpha-droit/gauche dans une somme ou un produit: augmente la selection avec argument droit ou gauche\nshift-4: Editer selection, shift-5: taille police + ou - grande\nEXE: evaluer la selection\nshift-6: valeur approchee\nBackspace: supprime l'operateur racine de la selection\n\nEditeur de scripts\nEXE: passage a la ligne\nshift-CUT: defaire/refaire (1 fois)\nshift-COPY: marque le debut de la selection, deplacer le curseur vers la fin puis Backspace pour effacer ou shift-COPY pour copier sans effacer. shift-PASTE pour coller.\nHome-6 recherche seule: entrer un mot puis EXE puis EXE. Taper EXE pour l'occurence suivante, Back pour annuler.\nHome-6 remplacer: entrer un mot puis EXE puis le remplacement et EXE. Taper EXE ou Back pour remplacer ou non et passer a l'occurence suivante, AC pour annuler\nOK: tester syntaxe\n\nRaccourcis Graphes:\n+ - zoom\n(-): zoomout selon y\n*: autoscale\n/: orthonormalisation\nOPTN: axes on/off";
1337 const char shortcuts_en_string[]="Keyboard shortcuts (shell and editor)\nshift-/: %\nalpha shift \": '\nshift--: \\\nshift-*: factor\nshift-+: normal\nshift-1 to 6: cf. screen bottom\nshift-7: matrices\nshift-8: lists\nshift-9:arithmetic\nshift-0: polynomials\nshift-.: reals\nshift-10^: programs\nvar: variables list (shell) or turtle screen (editor)\n\nshift-x^y (sto) returns =>\n=>+: partfrac\n=>*: factor\n=>sin/cos/tan\n=>=>: solve\n\nShell:\nshift-5: 2d editor or graph or text\nshift-6: text edit\n+ ou - modifies selected slider\n\nExpressions editor\nshift-cut: undo/redo (1 fois)\nkeypad: move selection inside expression tree\nshift-right/left exchange selection with right or left argument\nalpha-right/left: inside a sum or product: increase selection with right or left argument\nshift-4: Edit selection, shift-5: change fontsize\nEXE: eval selection\nshift-6: approx value\nBackspace: suppress selection's rootnode operator\n\nScript Editor\nEXE: newline\nshift-CUT: undo/redo (1 time)\nshift-COPY: marks selection begin, move the cursor to the end, then hit Backspace to erase or shift-COPY to copy (no erase). shift-PASTE to paste.\nHome-6 search: enter a word then EXE then again EXE. Type EXE for next occurence, Back to cancel.\nHome-6 replace: enter a word then EXE then replacement word then EXE. Type EXE or Back to replace or ignore and go to next occurence, AC to cancel\nOK: test syntax\n\nGraph shortcuts:\n+ - zoom\n(-): zoomout along y\n*: autoscale\n/: orthonormalization\nOPTN: axes on/off";
1338 #else
1339 const char shortcuts_fr_string[]="Raccourcis clavier (shell et editeur)\nlivre: aide/complete\ntab: complete (shell)/indente (editeur)\nshift-/: %\nshift *: '\nctrl-/: \\\nshift-1 a 6: selon bandeau en bas\nshift-7: matrices\nshift-8: listes\nshift-9:arithmetique\nshift-0: complexes\nshift-.: reels\nctrl P: programme\nvar: liste des variables (shell) ou dessin tortue (editeur)\n\nctrl-var (sto) renvoie =>\n=>+: partfrac\n=>*: factor\n=>sin/cos/tan\n=>=>: solve\n\nShell:\nshift-5: Editeur 2d ou graphique ou texte selon objet\nshift-4: editeur texte\n+ ou - modifie un parametre en surbrillance\n\nEditeur d'expressions\nctrl z: defaire/refaire (1 fois)\npave directionnel: deplace la selection dans l'arborescence de l'expression\nshift-droit/gauche echange selection avec argument a droite ou a gauche\nctrl droit/gauche dans une somme ou un produit: augmente la selection avec argument droit ou gauche\nshift-4: Editer selection, shift-5: taille police + ou - grande\nenter: evaluer la selection\nshift-6: valeur approchee\nDel: supprime l'operateur racine de la selection\n\nEditeur de scripts\nenter: passage a la ligne\nctrl z: defaire/refaire (1 fois)\nctrl c: marque le debut de la selection, deplacer le curseur vers la fin puis Del pour effacer ou ctrl c pour copier sans effacer. ctrl v pour coller.\nMenu-6 recherche seule: entrer un mot puis enter puis enter. Taper enter pour l'occurence suivante, esc pour annuler.\nMenu-6 remplacer: entrer un mot puis enter puis le remplacement et enter. Taper enter ou esc pour remplacer ou non et passer a l'occurence suivante, ctrl del pour annuler\nvalidation (a droite de U): tester syntaxe\n\nRaccourcis Graphes:\n+ - zoom\n(-): zoomout selon y\n*: autoscale\n/: orthonormalisation\nOPTN: axes on/off";
1340 const char shortcuts_en_string[]="Keyboard shortcuts (shell and editor)\nbook: help or completion\ntab: completion (shell), indent (editor)\nshift-/: %\nalpha shift *: '\nctrl-/: \\\nshift-1 a 6: see at bottom\nshift-7: matrices\nshift-8: listes\nshift-9:arithmetic\nshift-0: complexes\nshift-.: reals\nctrl P: program\nvar: variables list (shell) or turtle screen (editor)\n\nctrl var (sto) returns =>\n=>+: partfrac\n=>*: factor\n=>sin/cos/tan\n=>=>: solve\n\nShell:\nshift-5: 2d editor or graph or text\nshift-4: text edit\n+ ou - modifies selected slider\n\nExpressions editor\nctrl z: undo/redo (1 fois)\nkeypad: move selection inside expression tree\nshift-right/left exchange selection with right or left argument\nalpha-right/left: inside a sum or product: increase selection with right or left argument\nshift-4: Edit selection, shift-5: change fontsize\nenter: eval selection\nshift-6: approx value\nDel: suppress selection's rootnode operator\n\nScript Editor\nenter: newline\nctrl z: undo/redo (1 time)\nctrl c: marks selection begin, move the cursor to the end, then hit Del to erase or ctrl c to copy (no erase). ctrl v to paste.\nMenu-6 search: enter a word then enter then again enter. Type enter for next occurence, esc to cancel.\nMenu-6 replace: enter a word then enter then replacement word then enter. Type enter or esc to replace or ignore and go to next occurence, AC to cancel\nOK: test syntax\n\nGraph shortcuts:\n+ - zoom\n(-): zoomout along y\n*: autoscale\n/: orthonormalization\nOPTN: axes on/off";
1341 #endif
1342
1343 const char apropos_fr_string[]="Giac/Xcas 1.6.0, (c) 2020 B. Parisse et R. De Graeve, www-fourier.univ-grenoble-alpes.fr/~parisse.\nKhicas, interface pour calculatrices par B. Parisse, license GPL version 2, adaptee de l'interface d'Eigenmath pour Casio, G. Maia (http://gbl08ma.com), Mike Smith, Nemhardy, LePhenixNoir, ...\nPortage sur Numworks par Damien Nicolet. Remerciements a Jean-Baptiste Boric et Maxime Friess\nPortage sur Nspire grace a Fabian Vogt (firebird-emu, ndless...).\nTable periodique d'apres Maxime Friess\nRemerciements au site tiplanet, en particulier Xavier Andreani, Adrien Bertrand, Lionel Debroux";
1344
1345 const char apropos_en_string[]="Giac/Xcas 1.6.0, (c) 2020 B. Parisse et R. De Graeve, www-fourier.univ-grenoble-alpes.fr/~parisse.\nKhicas, calculators interface by B. Parisse, GPL license version 2, adapted from Eigenmath for Casio, G. Maia (http://gbl08ma.com), Mike Smith, Nemhardy, LePhenixNoir, ...\nPorted on Numworks by Damien Nicolet. Thanks to Jean-Baptiste Boric and Maxime Friess\nPorted on Nspire thanks to Fabian Vogt (firebird-emu, ndless...)\nPeriodic table by Maxime Friess\nThanks to tiplanet, especially Xavier Andreani, Adrien Bertrand, Lionel Debroux";
1346
1347 const int CAT_COMPLETE_COUNT_FR=sizeof(completeCatfr)/sizeof(catalogFunc);
1348 const int CAT_COMPLETE_COUNT_EN=sizeof(completeCaten)/sizeof(catalogFunc);
1349
insert_string(int index)1350 std::string insert_string(int index){
1351 std::string s;
1352 const catalogFunc * completeCat=(lang==1)?completeCatfr:completeCaten;
1353 if (completeCat[index].insert)
1354 s=completeCat[index].insert;
1355 else {
1356 s=completeCat[index].name;
1357 int pos=s.find('(');
1358 if (pos>=0 && pos<s.size())
1359 s=s.substr(0,pos+1);
1360 }
1361 return s;//s+' ';
1362 }
1363
1364 // not tested
aide2catalogFunc(const giac::aide & a,catalogFunc & c)1365 void aide2catalogFunc(const giac::aide & a,catalogFunc & c){
1366 static aide as=a;
1367 static string desc;
1368 string descrip;
1369 c.name=as.cmd_name.c_str();
1370 c.insert=c.name;
1371 desc=as.syntax+'\n';
1372 for (int i=0;i<as.blabla.size();++i){
1373 localized_string & ls=as.blabla[i];
1374 if (ls.language==lang){ // exact match
1375 descrip=as.blabla[i].chaine.c_str();
1376 break;
1377 }
1378 if (ls.language==0) // default
1379 descrip=as.blabla[i].chaine.c_str();
1380 }
1381 desc += descrip;
1382 c.desc=desc.c_str();
1383 c.example=as.examples.size()?as.examples[0].c_str():0;
1384 c.example2=as.examples.size()>=2?as.examples[1].c_str():0;
1385 c.category=-1;
1386 }
showCatalog(char * insertText,int preselect,int menupos,GIAC_CONTEXT)1387 int showCatalog(char* insertText,int preselect,int menupos,GIAC_CONTEXT) {
1388 // returns 0 on failure (user exit) and 1 on success (user chose a option)
1389 MenuItem menuitems[CAT_CATEGORY_LOGO+1];
1390 menuitems[CAT_CATEGORY_ALL].text = (char*)((lang==1)?"Tout":"All");
1391 menuitems[CAT_CATEGORY_ALGEBRA].text = (char*)((lang==1)?"Algebre":"Algebra");
1392 menuitems[CAT_CATEGORY_LINALG].text = (char*)((lang==1)?"Algebre lineaire":"Linear algebra");
1393 menuitems[CAT_CATEGORY_CALCULUS].text = (char*)((lang==1)?"Analyse":"Calculus");
1394 menuitems[CAT_CATEGORY_ARIT].text = (char*)"Arithmetic, crypto";
1395 menuitems[CAT_CATEGORY_COMPLEXNUM].text = (char*)"Complexes";
1396 menuitems[CAT_CATEGORY_PLOT].text = (char*)((lang==1)?"Courbes":"Curves");
1397 menuitems[CAT_CATEGORY_POLYNOMIAL].text = (char*)((lang==1)?"Polynomes":"Polynomials");
1398 menuitems[CAT_CATEGORY_PROBA].text = (char*)((lang==1)?"Probabilites":"Probabilities");
1399 menuitems[CAT_CATEGORY_PROGCMD].text = (char*)((lang==1)?"Programmes cmds (0)":"Program cmds (0)");
1400 menuitems[CAT_CATEGORY_REAL].text = (char*)((lang==1)?"Reels (e^)":"Reals");
1401 menuitems[CAT_CATEGORY_SOLVE].text = (char*)((lang==1)?"Resoudre (ln)":"Solve (ln)");
1402 menuitems[CAT_CATEGORY_STATS].text = (char*)((lang==1)?"Statistiques (log)":"Statistics (log)");
1403 menuitems[CAT_CATEGORY_TRIG].text = (char*)((lang==1)?"Trigonometrie (i)":"Trigonometry (i)");
1404 menuitems[CAT_CATEGORY_OPTIONS].text = (char*)"Options (,)";
1405 menuitems[CAT_CATEGORY_LIST].text = (char*)((lang==1)?"Listes (x^y)":"Lists (x^y)");
1406 menuitems[CAT_CATEGORY_MATRIX].text = (char*)"Matrices (sin)";
1407 menuitems[CAT_CATEGORY_PROG].text = (char*)((lang==1)?"Programmes (cos)":"Programs");
1408 menuitems[CAT_CATEGORY_SOFUS].text = (char*)((lang==1)?"Modifier variables (tan)":"Change variables (tan)");
1409 menuitems[CAT_CATEGORY_PHYS].text = (char*)((lang==1)?"Constantes physique (pi)":"Physics constants (pi)");
1410 menuitems[CAT_CATEGORY_UNIT].text = (char*)((lang==1)?"Unites physiques (sqrt)":"Units (sqrt)");
1411 menuitems[CAT_CATEGORY_LOGO].text = (char*)((lang==1)?"Tortue (x^2)":"Turtle (x^2)");
1412
1413 Menu menu;
1414 menu.items=menuitems;
1415 menu.numitems=sizeof(menuitems)/sizeof(MenuItem);
1416 menu.scrollout=1;
1417 menu.title = (char*)((lang==1)?"Liste de commandes":"Commands list");
1418 //puts("catalog 1");
1419 while(1) {
1420 if (preselect)
1421 menu.selection=preselect;
1422 else {
1423 if (menupos>0)
1424 menu.selection=menupos;
1425 int sres = doMenu(&menu);
1426 if (sres != MENU_RETURN_SELECTION && sres!=KEY_CTRL_EXE)
1427 return 0;
1428 }
1429 // puts("catalog 3");
1430 if(doCatalogMenu(insertText, menuitems[menu.selection-1].text, menu.selection-1,contextptr))
1431 return 1;
1432 if (preselect)
1433 return 0;
1434 }
1435 return 0;
1436 }
1437
showCatalog(char * text,int nmenu,GIAC_CONTEXT)1438 int showCatalog(char * text,int nmenu,GIAC_CONTEXT){
1439 return showCatalog(text,0,nmenu,contextptr);
1440 }
1441
isalphanum(char c)1442 bool isalphanum(char c){
1443 return (c>='a' && c<='z') || (c>='A' && c<='Z') || (c>='0' && c<='9');
1444 }
1445
help_insert(const char * cmdline,GIAC_CONTEXT)1446 string help_insert(const char * cmdline,GIAC_CONTEXT){
1447 int l=strlen(cmdline);
1448 char buf[l+1];
1449 strcpy(buf,cmdline);
1450 bool openpar=l && buf[l-1]=='(';
1451 if (openpar){
1452 buf[l-1]=0;
1453 --l;
1454 }
1455 for (;l>0;--l){
1456 if (!isalphanum(buf[l-1]) && buf[l-1]!='_')
1457 break;
1458 }
1459 // cmdname in buf+l
1460 const char * cmdname=buf+l,*cmdnameorig=cmdname;
1461 l=strlen(cmdname);
1462 // search in catalog: dichotomy would be more efficient
1463 // but leading spaces cmdnames would be missed
1464 int nfunc=(lang==1)?CAT_COMPLETE_COUNT_FR:CAT_COMPLETE_COUNT_EN;//sizeof(completeCat)/sizeof(catalogFunc);
1465 #ifdef NSPIRE_NEWLIB
1466 int iii=nfunc; // no search in completeCat, directly in static_help.h
1467 #else
1468 int iii=0;
1469 #endif
1470 const catalogFunc * completeCat=(lang==1)?completeCatfr:completeCaten;
1471 for (;iii<nfunc;++iii){
1472 const char * name=completeCat[iii].name;
1473 while (*name==' ')
1474 ++name;
1475 int j=0;
1476 for (;j<l;++j){
1477 if (name[j]!=cmdname[j])
1478 break;
1479 }
1480 if (j==l)
1481 break;
1482 }
1483 const catalogFunc * catf=iii==nfunc?0:completeCat+iii;
1484 const char * fhowto=0,* fsyntax=0,* frelated=0,* fexamples=0;
1485 char fbuf[1024];
1486 if (iii==nfunc){
1487 if (!has_static_help(cmdname,lang,fhowto,fsyntax,fexamples,frelated)){
1488 confirm("Pas d'aide disponible pour",cmdname,true);
1489 return "";
1490 }
1491 if (fexamples && fexamples[0]==0){
1492 fexamples=frelated;
1493 frelated=0;
1494 }
1495 // cut example at ; if there is one
1496 for (int i=0;i<sizeof(fbuf);++i){
1497 if (fexamples[i]==0)
1498 break;
1499 if (fexamples[i]==';'){
1500 strcpy(fbuf,fexamples);
1501 fbuf[i]=0;
1502 fexamples=fbuf;
1503 frelated=fbuf+i+1;
1504 while (*frelated==' ')
1505 ++frelated;
1506 for (++i;i<sizeof(fbuf);++i){
1507 if (fbuf[i]==0)
1508 break;
1509 if (fbuf[i]==';'){
1510 fbuf[i]=0;
1511 break;
1512 }
1513 }
1514 break;
1515 }
1516 }
1517 }
1518 const char * example=catf?catf->example:fexamples;
1519 const char * example2=catf?catf->example2:frelated;
1520 xcas::textArea text;
1521 text.editable=false;
1522 text.clipline=-1;
1523 text.title = (char*)((lang==1)?"Aide sur la commande":"Help on command");
1524 text.allowF1=true;
1525 text.python=false;
1526 std::vector<xcas::textElement> & elem=text.elements;
1527 elem = std::vector<xcas::textElement> (example2?4:3);
1528 elem[0].s = catf?catf->name:cmdname;
1529 elem[0].newLine = 0;
1530 //elem[0].color = COLOR_BLUE;
1531 elem[1].newLine = 1;
1532 elem[1].lineSpacing = 1;
1533 elem[1].minimini=1;
1534 std::string autoexample;
1535 if (catf && catf->desc==0){
1536 // if (token==T_UNARY_OP || token==T_UNARY_OP_38)
1537 elem[1].s=elem[0].s+"(args)";
1538 }
1539 else
1540 elem[1].s = catf?catf->desc:fhowto;
1541 #ifdef NSPIRE_NEWLIB
1542 std::string ex("tab: ");
1543 #else
1544 std::string ex("Ans: ");
1545 #endif
1546 elem[2].newLine = 1;
1547 elem[2].lineSpacing = 0;
1548 //elem[2].minimini=1;
1549 if (example){
1550 if (example[0]=='#')
1551 ex += example+1;
1552 else {
1553 if (iii==nfunc)
1554 ex += fexamples;
1555 else {
1556 ex += insert_string(iii);
1557 ex += example;
1558 ex += ")";
1559 }
1560 }
1561 elem[2].s = ex;
1562 if (example2){
1563 #ifdef NSPIRE_NEWLIB
1564 string ex2="ret: ";
1565 #else
1566 string ex2="EXE: ";
1567 #endif
1568 if (example2[0]=='#')
1569 ex2 += example2+1;
1570 else {
1571 if (iii==nfunc)
1572 ex2 += example2;
1573 else {
1574 ex2 += insert_string(iii);
1575 ex2 += example2;
1576 ex2 += ")";
1577 }
1578 }
1579 elem[3].newLine = 1;
1580 // elem[3].lineSpacing = 0;
1581 //elem[3].minimini=1;
1582 elem[3].s=ex2;
1583 }
1584 }
1585 else {
1586 if (autoexample.size())
1587 elem[2].s=ex+autoexample;
1588 else
1589 elem.pop_back();
1590 }
1591 int sres=doTextArea(&text,contextptr);
1592 if (sres==KEY_SHUTDOWN)
1593 return "";
1594 if (sres==MENU_RETURN_SELECTION){
1595 while (*cmdname && *cmdname==*cmdnameorig){
1596 ++cmdname; ++cmdnameorig;
1597 }
1598 return cmdname;
1599 }
1600 if (sres == KEY_CHAR_ANS || sres==KEY_BOOK || sres=='\t' || sres==KEY_CTRL_EXE) {
1601 reset_kbd();
1602 std::string s;
1603 const char * example=0;
1604 if (sres==KEY_CHAR_ANS || sres==KEY_BOOK || sres=='\t')
1605 example=catf?catf->example:fexamples;
1606 else
1607 example=catf?catf->example2:frelated;
1608 if (example){
1609 while (*example && *example==*cmdnameorig){
1610 ++example; ++cmdnameorig;
1611 }
1612 if (openpar && example[0]=='(')
1613 ++example;
1614 if (example[0]=='#')
1615 s=example+1;
1616 else {
1617 s += example;
1618 //if (catf && s[s.size()-1]!=')') s += ")";
1619 }
1620 }
1621 return s;
1622 }
1623 return "";
1624 }
1625
1626 // 0 on exit, 1 on success
doCatalogMenu(char * insertText,const char * title,int category,GIAC_CONTEXT)1627 int doCatalogMenu(char* insertText, const char* title, int category,GIAC_CONTEXT) {
1628 const catalogFunc * completeCat=(lang==1)?completeCatfr:completeCaten;
1629 for (;;){
1630 int allcmds=builtin_lexer_functions_end()-builtin_lexer_functions_begin();
1631 int allopts=lexer_tab_int_values_end-lexer_tab_int_values_begin;
1632 bool isall=category==CAT_CATEGORY_ALL;
1633 bool isopt=category==CAT_CATEGORY_OPTIONS;
1634 const int CAT_COMPLETE_COUNT=((lang==1)?CAT_COMPLETE_COUNT_FR:CAT_COMPLETE_COUNT_EN);
1635 int nitems = isall? allcmds:(isopt?allopts:CAT_COMPLETE_COUNT);
1636 #ifdef MENUITEM_MALLOC
1637 MenuItem *menuitems=(MenuItem *) malloc(sizeof(MenuItem)*nitems);
1638 if (!menuitems)
1639 return 0;
1640 #else
1641 MenuItem menuitems[nitems];
1642 #endif
1643 int cur = 0,curmi = 0,i=0;
1644 gen g;
1645 while(cur<nitems) {
1646 menuitems[curmi].type = MENUITEM_NORMAL;
1647 menuitems[curmi].color = _BLACK;
1648 if (isall || isopt) {
1649 const char * text=isall?(builtin_lexer_functions_begin()+curmi)->first:(lexer_tab_int_values_begin+curmi)->keyword;
1650 menuitems[curmi].text = (char*) text;
1651 menuitems[curmi].isfolder = allcmds; // assumes allcmds>allopts
1652 menuitems[curmi].token=isall?((builtin_lexer_functions_begin()+curmi)->second.subtype+256):((lexer_tab_int_values_begin+curmi)->subtype+(lexer_tab_int_values_begin+curmi)->return_value*256);
1653 // menuitems[curmi].token=isall?find_or_make_symbol(text,g,0,false,contextptr):((lexer_tab_int_values_begin+curmi)->subtype+(lexer_tab_int_values_begin+curmi)->return_value*256);
1654 for (;i<CAT_COMPLETE_COUNT;++i){
1655 const char * catname=completeCat[i].name;
1656 int tmp=strcmp(catname,text);
1657 if (tmp>=0){
1658 size_t st=strlen(text),j=tmp?0:st;
1659 for (;j<st;++j){
1660 if (catname[j]!=text[j])
1661 break;
1662 }
1663 if (j==st && (!isalphanum(catname[j]))){
1664 menuitems[curmi].isfolder = i;
1665 ++i;
1666 }
1667 break;
1668 }
1669 }
1670 // compare text with completeCat
1671 ++curmi;
1672 }
1673 else {
1674 int cat=completeCat[cur].category;
1675 if ( (cat & 0xff) == category ||
1676 (cat & 0xff00) == (category<<8) ||
1677 (cat & 0xff0000) == (category <<16)
1678 ){
1679 menuitems[curmi].isfolder = cur; // little hack: store index of the command in the full list in the isfolder property (unused by the menu system in this case)
1680 menuitems[curmi].text = (char *) completeCat[cur].name;
1681 curmi++;
1682 }
1683 }
1684 cur++;
1685 }
1686
1687 Menu menu;
1688 menu.items=menuitems;
1689 menu.numitems=curmi;
1690 if (isopt){ menu.selection=5; menu.scroll=4; }
1691 if (curmi>=100)
1692 lock_alpha(); //SetSetupSetting( (unsigned int)0x14, 0x88);
1693 // DisplayStatusArea();
1694 menu.scrollout=1;
1695 menu.title = (char *) title;
1696 menu.type = MENUTYPE_FKEYS;
1697 menu.height = 11;
1698 while(1) {
1699 drawRectangle(0,200,LCD_WIDTH_PX,22,giac::_WHITE);
1700 #ifdef NSPIRE_NEWLIB
1701 PrintMini(0,200,(category==CAT_CATEGORY_ALL?"doc: help | tab: ex1 | enter: ex2":"doc: help | tab: ex1 | enter ex2"),4,33333,giac::_WHITE);
1702 #else
1703 PrintMini(0,200,(category==CAT_CATEGORY_ALL?"Toolbox help | Ans ex1 | EXE ex2":"Toolbox help | Ans ex1 | EXE ex2"),4,33333,giac::_WHITE);
1704 #endif
1705 int sres = doMenu(&menu);
1706 if (sres==KEY_CTRL_F4 && category!=CAT_CATEGORY_ALL){
1707 break;
1708 }
1709 if(sres == MENU_RETURN_EXIT){
1710 reset_kbd();
1711 #ifdef MENUITEM_MALLOC
1712 free(menuitems);
1713 #endif
1714 return sres;
1715 }
1716 int index=menuitems[menu.selection-1].isfolder;
1717 if(sres == KEY_CTRL_CATALOG || sres==KEY_BOOK) {
1718 const char * example=index<allcmds?completeCat[index].example:0;
1719 const char * example2=index<allcmds?completeCat[index].example2:0;
1720 xcas::textArea text;
1721 text.editable=false;
1722 text.clipline=-1;
1723 text.title = (char*)((lang==1)?"Aide sur la commande":"Help on command");
1724 text.allowF1=true;
1725 text.python=python_compat(contextptr);
1726 std::vector<xcas::textElement> & elem=text.elements;
1727 elem = std::vector<xcas::textElement> (example2?4:3);
1728 elem[0].s = index<allcmds?completeCat[index].name:menuitems[menu.selection-1].text;
1729 elem[0].newLine = 0;
1730 //elem[0].color = COLOR_BLUE;
1731 elem[1].newLine = 1;
1732 elem[1].lineSpacing = 1;
1733 elem[1].minimini=1;
1734 std::string autoexample;
1735 if (index<allcmds)
1736 elem[1].s = completeCat[index].desc;
1737 else {
1738 int token=menuitems[menu.selection-1].token;
1739 elem[1].s="Desole, pas d'aide disponible...";
1740 const char *fcmdname=menuitems[menu.selection-1].text,* fhowto=0,*fsyntax=0,*fexamples=0,*frelated=0;
1741 if (has_static_help(fcmdname,lang,fhowto,fsyntax,fexamples,frelated)){
1742 elem[1].s=fhowto;
1743 example=fexamples;
1744 }
1745 else {
1746 // *logptr(contextptr) << token << endl;
1747 if (isopt){
1748 if (token==_INT_PLOT+T_NUMBER*256){
1749 autoexample="display="+elem[0].s;
1750 elem[1].s ="Option d'affichage: "+ autoexample;
1751 }
1752 if (token==_INT_COLOR+T_NUMBER*256){
1753 autoexample="display="+elem[0].s;
1754 elem[1].s="Option de couleur: "+ autoexample;
1755 }
1756 if (token==_INT_SOLVER+T_NUMBER*256){
1757 autoexample=elem[0].s;
1758 elem[1].s="Option de fsolve: " + autoexample;
1759 }
1760 if (token==_INT_TYPE+T_TYPE_ID*256){
1761 autoexample=elem[0].s;
1762 elem[1].s="Type d'objet: " + autoexample;
1763 }
1764 }
1765 if (isall){
1766 if (token==T_UNARY_OP || token==T_UNARY_OP_38)
1767 elem[1].s=elem[0].s+"(args)";
1768 }
1769 }
1770 }
1771 #ifdef NSPIRE_NEWLIB
1772 std::string ex("tab: ");
1773 #else
1774 std::string ex("Ans: ");
1775 #endif
1776 elem[2].newLine = 1;
1777 elem[2].lineSpacing = 0;
1778 //elem[2].minimini=1;
1779 if (example){
1780 if (example[0]=='#')
1781 ex += example+1;
1782 else {
1783 if (index<allcmds){
1784 ex += insert_string(index);
1785 ex += example;
1786 ex += ")";
1787 }
1788 else ex+=example;
1789 }
1790 elem[2].s = ex;
1791 if (example2){
1792 #ifdef NSPIRE_NEWLIB
1793 string ex2="enter: ";
1794 #else
1795 string ex2="EXE: ";
1796 #endif
1797 if (example2[0]=='#')
1798 ex2 += example2+1;
1799 else {
1800 if (index<allcmds){
1801 ex2 += insert_string(index);
1802 ex2 += example2;
1803 ex2 += ")";
1804 }
1805 else
1806 ex2 += example2;
1807 }
1808 elem[3].newLine = 1;
1809 // elem[3].lineSpacing = 0;
1810 //elem[3].minimini=1;
1811 elem[3].s=ex2;
1812 }
1813 }
1814 else {
1815 if (autoexample.size())
1816 elem[2].s=ex+autoexample;
1817 else
1818 elem.pop_back();
1819 }
1820 sres=doTextArea(&text,contextptr);
1821 }
1822 if (sres == KEY_CHAR_ANS || sres=='\t' ||sres==KEY_BOOK || sres==KEY_CTRL_EXE) {
1823 reset_kbd();
1824 const char * example=0;
1825 std::string s;
1826 if (index<allcmds ){
1827 s=insert_string(index);
1828 if (sres==KEY_CHAR_ANS || sres=='\t' || sres==KEY_BOOK)
1829 example=completeCat[index].example;
1830 else
1831 example=completeCat[index].example2;
1832 }
1833 else {
1834 const char *fcmdname=menuitems[menu.selection-1].text,* fhowto=0,*fsyntax=0,*fexamples=0,*frelated=0;
1835 if (has_static_help(fcmdname,lang,fhowto,fsyntax,fexamples,frelated)){
1836 example=fexamples;
1837 }
1838 }
1839 if (example){
1840 if (example[0]=='#')
1841 s=example+1;
1842 else {
1843 s += example;
1844 if (s[s.size()-1]!=')')
1845 s += ")";
1846 }
1847 strcpy(insertText, s.c_str());
1848 #ifdef MENUITEM_MALLOC
1849 free(menuitems);
1850 #endif
1851 return 1;
1852 }
1853 else {
1854 if (isopt){
1855 int token=menuitems[menu.selection-1].token;
1856 if (token==_INT_PLOT+T_NUMBER*256 || token==_INT_COLOR+T_NUMBER*256)
1857 strcpy(insertText,"display=");
1858 else
1859 *insertText=0;
1860 strcat(insertText,menuitems[menu.selection-1].text);
1861 #ifdef MENUITEM_MALLOC
1862 free(menuitems);
1863 #endif
1864 return 1;
1865 }
1866 }
1867 sres=KEY_CTRL_OK;
1868 }
1869 if(sres == MENU_RETURN_SELECTION || sres == KEY_CTRL_OK) {
1870 reset_kbd();
1871 strcpy(insertText,index<allcmds?insert_string(index).c_str():menuitems[menu.selection-1].text);
1872 #ifdef MENUITEM_MALLOC
1873 free(menuitems);
1874 #endif
1875 return 1;
1876 }
1877 }
1878 title="CATALOG";
1879 category=0;
1880 } // end endless for
1881 return 0;
1882 }
1883
select_var(GIAC_CONTEXT)1884 gen select_var(GIAC_CONTEXT){
1885 kbd_interrupted=giac::ctrl_c=giac::interrupted=false;
1886 #ifdef MICROPY_LIB
1887 if (xcas_python_eval==1){
1888 const char ** tab=(const char **)mp_vars();
1889 if (tab){
1890 int i=select_item(tab,"VARS",true);
1891 gen g=undef;
1892 if (i>=0 && tab[i])
1893 g=gen(tab[i],contextptr);
1894 free(tab);
1895 return g;
1896 }
1897 }
1898 #endif
1899 gen g(_VARS(0,contextptr));
1900 if (g.type!=_VECT || g._VECTptr->empty()){
1901 confirm((lang==1)?"Pas de variables. Exemples pour en creer":"No variables. Examples to create",(lang==1)?"a=1 ou f(x):=sin(x^2)":"a=1 or f(x):=sin(x^2)",true);
1902 return undef;
1903 }
1904 vecteur & v=*g._VECTptr;
1905 MenuItem smallmenuitems[v.size()+3];
1906 vector<std::string> vs(v.size()+1);
1907 int i,total=0;
1908 const char typ[]="idzDcpiveSfEsFRmuMwgPF";
1909 for (i=0;i<v.size();++i){
1910 vs[i]=v[i].print(contextptr);
1911 if (v[i].type==giac::_IDNT){
1912 giac::gen w;
1913 v[i]._IDNTptr->in_eval(0,v[i],w,contextptr,true);
1914 #if 1
1915 vector<int> vi(9);
1916 tailles(w,vi);
1917 total += vi[8];
1918 if (vi[8]<400)
1919 vs[i]+=":="+w.print(contextptr);
1920 else {
1921 vs[i] += " ~";
1922 vs[i] += giac::print_INT_(vi[8]);
1923 vs[i] += ',';
1924 vs[i] += typ[w.type];
1925 }
1926 #else
1927 if (taille(w,50)<50)
1928 vs[i]+=": "+w.print(contextptr);
1929 #endif
1930 }
1931 smallmenuitems[i].text=(char *) vs[i].c_str();
1932 }
1933 total +=
1934 // giac::syms().capacity()*(sizeof(string)+sizeof(giac::gen)+8)+sizeof(giac::sym_string_tab) +
1935 giac::turtle_stack().capacity()*sizeof(giac::logo_turtle) +
1936 // sizeof(giac::context)+contextptr->tabptr->capacity()*(sizeof(const char *)+sizeof(giac::gen)+8)+
1937 bytesize(giac::history_in(contextptr))+bytesize(giac::history_out(contextptr));
1938 vs[i]="purge(~"+giac::print_INT_(total)+')';
1939 smallmenuitems[i].text=(char *)vs[i].c_str();
1940 smallmenuitems[i+1].text=(char *)"assume(";
1941 smallmenuitems[i+2].text=(char *)"restart";
1942 Menu smallmenu;
1943 smallmenu.numitems=v.size()+3;
1944 smallmenu.items=smallmenuitems;
1945 smallmenu.height=12;
1946 smallmenu.scrollbar=1;
1947 smallmenu.scrollout=1;
1948 smallmenu.title = (char*)"Variables";
1949 //MsgBoxPush(5);
1950 int sres = doMenu(&smallmenu);
1951 //MsgBoxPop();
1952 if (sres==KEY_CTRL_DEL && smallmenu.selection<=v.size())
1953 return symbolic(at_purge,v[smallmenu.selection-1]);
1954 if (sres!=MENU_RETURN_SELECTION && sres!=KEY_CTRL_EXE)
1955 return undef;
1956 if (smallmenu.selection==1+v.size())
1957 return string2gen("purge(",false);
1958 if (smallmenu.selection==2+v.size())
1959 return string2gen("assume(",false);
1960 if (smallmenu.selection==3+v.size())
1961 return string2gen("restart",false);
1962 return v[smallmenu.selection-1];
1963 }
1964
keytostring(int key,int keyflag,bool py,const giac::context * contextptr)1965 const char * keytostring(int key,int keyflag,bool py,const giac::context * contextptr){
1966 const int textsize=512;
1967 static char text[textsize];
1968 if (key>=0x20 && key<=0x7e){
1969 text[0]=key;
1970 text[1]=0;
1971 return text;
1972 }
1973 switch (key){
1974 case KEY_CHAR_PLUS:
1975 return "+";
1976 case KEY_CHAR_MINUS:
1977 return "-";
1978 case KEY_CHAR_PMINUS:
1979 return "_";
1980 case KEY_CHAR_MULT:
1981 return "*";
1982 case KEY_CHAR_FRAC:
1983 return py?"\\":"solve(";
1984 case KEY_CHAR_DIV:
1985 return "/";
1986 case KEY_CHAR_POW:
1987 return "^";
1988 case KEY_CHAR_ROOT:
1989 return "sqrt(";
1990 case KEY_CHAR_SQUARE:
1991 return py?"**2":"^2";
1992 case KEY_CHAR_CUBEROOT:
1993 return py?"**(1/3)":"^(1/3)";
1994 case KEY_CHAR_POWROOT:
1995 return py?"**(1/":"^(1/";
1996 case KEY_CHAR_RECIP:
1997 return py?"**-1":"^-1";
1998 case KEY_CHAR_THETA:
1999 return "arg(";
2000 case KEY_CHAR_VALR:
2001 return "abs(";
2002 case KEY_CHAR_ANGLE:
2003 return "polar_complex(";
2004 case KEY_CTRL_XTT:
2005 return xthetat?"t":"x";
2006 case KEY_CHAR_LN:
2007 return "ln(";
2008 case KEY_CHAR_LOG:
2009 return "log10(";
2010 case KEY_CHAR_EXPN10:
2011 return "10^";
2012 case KEY_CHAR_EXPN:
2013 return "exp(";
2014 case KEY_CHAR_SIN:
2015 return "sin(";
2016 case KEY_CHAR_COS:
2017 return "cos(";
2018 case KEY_CHAR_TAN:
2019 return "tan(";
2020 case KEY_CHAR_ASIN:
2021 return "asin(";
2022 case KEY_CHAR_ACOS:
2023 return "acos(";
2024 case KEY_CHAR_ATAN:
2025 return "atan(";
2026 case KEY_CTRL_MIXEDFRAC:
2027 return "limit(";
2028 case KEY_CTRL_FRACCNVRT:
2029 return "exact(";
2030 // case KEY_CTRL_FORMAT: return "purge(";
2031 case KEY_CTRL_FD:
2032 return "approx(";
2033 case KEY_CHAR_STORE:
2034 // if (keyflag==1) return "inf";
2035 return "=>";
2036 case KEY_CHAR_IMGNRY:
2037 return "i";
2038 case KEY_CHAR_PI:
2039 return "pi";
2040 case KEY_CTRL_VARS: {
2041 giac::gen var=select_var(contextptr);
2042 if (!giac::is_undef(var)){
2043 strcpy(text,(var.type==giac::_STRNG?*var._STRNGptr:var.print(contextptr)).c_str());
2044 return text;
2045 }
2046 return "";//"VARS()";
2047 }
2048 case KEY_CHAR_EXP:
2049 return "e";
2050 case KEY_CHAR_ANS:
2051 return "ans()";
2052 case KEY_CTRL_INS:
2053 return ":=";
2054 case KEY_CHAR_MAT:{
2055 const char * ptr=xcas::input_matrix(false,contextptr); if (ptr) return ptr;
2056 if (showCatalog(text,17,contextptr)) return text;
2057 return "";
2058 }
2059 case KEY_CHAR_LIST: {
2060 const char * ptr=xcas::input_matrix(true,contextptr); if (ptr) return ptr;
2061 if (showCatalog(text,16,contextptr)) return text;
2062 return "";
2063 }
2064 case KEY_CTRL_PRGM:
2065 // open functions catalog, prgm submenu
2066 if(showCatalog(text,18,contextptr))
2067 return text;
2068 return "";
2069 case KEY_CTRL_CATALOG: case KEY_BOOK:
2070 if(showCatalog(text,0,contextptr))
2071 return text;
2072 return "";
2073 case KEY_CTRL_F4:
2074 if(showCatalog(text,0,contextptr))
2075 return text;
2076 return "";
2077 case KEY_CTRL_OPTN:
2078 if(showCatalog(text,15,contextptr))
2079 return text;
2080 return "";
2081 case KEY_CTRL_QUIT:
2082 if(showCatalog(text,20,contextptr))
2083 return text;
2084 return "";
2085 case KEY_CTRL_PASTE:
2086 return paste_clipboard();
2087 case KEY_CHAR_DQUATE:
2088 return "\"";
2089 case KEY_CHAR_FACTOR:
2090 return "factor(";
2091 case KEY_CHAR_NORMAL:
2092 return "normal(";
2093 }
2094 return 0;
2095 }
2096
keytostring(int key,int keyflag,GIAC_CONTEXT)2097 const char * keytostring(int key,int keyflag,GIAC_CONTEXT){
2098 return keytostring(key,keyflag,python_compat(contextptr),contextptr);
2099 }
2100
stringtodouble(const string & s1,double & d)2101 bool stringtodouble(const string & s1,double & d){
2102 gen g(s1,context0);
2103 g=evalf(g,1,context0);
2104 if (g.type!=_DOUBLE_){
2105 confirm("Invalid value",s1.c_str());
2106 return false;
2107 }
2108 d=g._DOUBLE_val;
2109 return true;
2110 }
2111
inputdouble(const char * msg1,double & d,GIAC_CONTEXT)2112 bool inputdouble(const char * msg1,double & d,GIAC_CONTEXT){
2113 int di=d;
2114 string s1;
2115 if (di==d)
2116 s1=print_INT_(di);
2117 else
2118 s1=print_DOUBLE_(d,3);
2119 inputline(msg1,((lang==1)?"Nouvelle valeur? ":"New value? "),s1,false,65,contextptr);
2120 return stringtodouble(s1,d);
2121 }
2122
inputline(const char * msg1,const char * msg2,string & s,bool numeric,int ypos,GIAC_CONTEXT)2123 int inputline(const char * msg1,const char * msg2,string & s,bool numeric,int ypos,GIAC_CONTEXT){
2124 //s=msg2;
2125 int pos=s.size(),beg=0;
2126 for (;;){
2127 int X1=print_msg12(msg1,msg2,ypos-30);
2128 int textX=X1,textY=ypos;
2129 drawRectangle(textX,textY,LCD_WIDTH_PX-textX-4,18,COLOR_WHITE);
2130 if (pos-beg>36)
2131 beg=pos-12;
2132 if (int(s.size())-beg<36)
2133 beg=giac::giacmax(0,int(s.size())-36);
2134 textX=X1;
2135 #if 0
2136 os_draw_string_(textX,textY,(s.substr(beg,pos-beg)+"|"+s.substr(pos,s.size()-pos)).c_str());
2137 #else
2138 textX=os_draw_string_(textX,textY+2,s.substr(beg,pos-beg).c_str());
2139 os_draw_string_(textX,textY+2,s.substr(pos,s.size()-pos).c_str());
2140 drawRectangle(textX,textY+4,2,13,COLOR_BLACK); // cursor
2141 // PrintMini(0,58," | | | | A<>a | ",4);
2142 #endif
2143 int key;
2144 GetKey(&key);
2145 if (key==KEY_SHUTDOWN)
2146 return key;
2147 // if (!giac::freeze) set_xcas_status();
2148 if (key==KEY_CTRL_EXE || key==KEY_CTRL_OK)
2149 return KEY_CTRL_EXE;
2150 if (key>=32 && key<128){
2151 if (!numeric || key=='-' || (key>='0' && key<='9')){
2152 s.insert(s.begin()+pos,char(key));
2153 ++pos;
2154 }
2155 continue;
2156 }
2157 if (key==KEY_CTRL_DEL){
2158 if (pos){
2159 s.erase(s.begin()+pos-1);
2160 --pos;
2161 }
2162 continue;
2163 }
2164 if (key==KEY_CTRL_AC){
2165 if (s=="")
2166 return KEY_CTRL_EXIT;
2167 s="";
2168 pos=0;
2169 continue;
2170 }
2171 if (key==KEY_CTRL_EXIT)
2172 return key;
2173 if (key==KEY_CTRL_RIGHT){
2174 if (pos<s.size())
2175 ++pos;
2176 continue;
2177 }
2178 if (key==KEY_SHIFT_RIGHT){
2179 pos=s.size();
2180 continue;
2181 }
2182 if (key==KEY_CTRL_LEFT){
2183 if (pos)
2184 --pos;
2185 continue;
2186 }
2187 if (key==KEY_SHIFT_LEFT){
2188 pos=0;
2189 continue;
2190 }
2191 if (const char * ans=keytostring(key,0,false,contextptr)){
2192 insert(s,pos,ans);
2193 pos+=strlen(ans);
2194 continue;
2195 }
2196 }
2197 }
2198
2199 logo_turtle * turtleptr=0;
2200
turtle()2201 logo_turtle & turtle(){
2202 if (!turtleptr)
2203 turtleptr=new logo_turtle;
2204 return * turtleptr;
2205 }
2206
2207 #ifdef NSPIRE_NEWLIB
2208 const int MAX_LOGO=2048;
2209 #else
2210 const int MAX_LOGO=368; // 512;
2211 #endif
2212
turtle_stack()2213 std::vector<logo_turtle> & turtle_stack(){
2214 static std::vector<logo_turtle> * ans = 0;
2215 if (!ans){
2216 // initialize from python app storage
2217 ans=new std::vector<logo_turtle>(1,(*turtleptr));
2218
2219 }
2220 return *ans;
2221 }
2222
vecteur2turtle(const vecteur & v)2223 logo_turtle vecteur2turtle(const vecteur & v){
2224 int s=int(v.size());
2225 if (s>=5 && v[0].type==_DOUBLE_ && v[1].type==_DOUBLE_ && v[2].type==_DOUBLE_ && v[3].type==_INT_ && v[4].type==_INT_ ){
2226 logo_turtle t;
2227 t.x=v[0]._DOUBLE_val;
2228 t.y=v[1]._DOUBLE_val;
2229 t.theta=v[2]._DOUBLE_val;
2230 int i=v[3].val;
2231 t.mark=(i%2)!=0;
2232 i=i >> 1;
2233 t.visible=(i%2)!=0;
2234 i=i >> 1;
2235 t.direct = (i%2)!=0;
2236 i=i >> 1;
2237 t.turtle_length = i & 0xff;
2238 i=i >> 8;
2239 t.color = i;
2240 t.radius = v[4].val;
2241 if (s>5 && v[5].type==_INT_)
2242 t.s=v[5].val;
2243 else
2244 t.s=-1;
2245 return t;
2246 }
2247 #ifndef NO_STDEXCEPT
2248 setsizeerr(gettext("vecteur2turtle")); // FIXME
2249 #endif
2250 return logo_turtle();
2251 }
2252
turtle_status(const logo_turtle & turtle)2253 static int turtle_status(const logo_turtle & turtle){
2254 int status= (turtle.color << 11) | ( (turtle.turtle_length & 0xff) << 3) ;
2255 if (turtle.direct)
2256 status += 4;
2257 if (turtle.visible)
2258 status += 2;
2259 if (turtle.mark)
2260 status += 1;
2261 return status;
2262 }
2263
set_turtle_state(const vecteur & v,GIAC_CONTEXT)2264 bool set_turtle_state(const vecteur & v,GIAC_CONTEXT){
2265 if (v.size()>=2 && v[0].type==_DOUBLE_ && v[1].type==_DOUBLE_){
2266 vecteur w(v);
2267 int s=int(w.size());
2268 if (s==2)
2269 w.push_back(double((*turtleptr).theta));
2270 if (s<4)
2271 w.push_back(turtle_status((*turtleptr)));
2272 if (s<5)
2273 w.push_back(0);
2274 if (w[2].type==_DOUBLE_ && w[3].type==_INT_ && w[4].type==_INT_){
2275 (*turtleptr)=vecteur2turtle(w);
2276 #ifdef TURTLETAB
2277 turtle_stack_push_back(*turtleptr);
2278 #else
2279 turtle_stack().push_back((*turtleptr));
2280 #endif
2281 return true;
2282 }
2283 }
2284 return false;
2285 }
2286
turtle2gen(const logo_turtle & turtle)2287 gen turtle2gen(const logo_turtle & turtle){
2288 return gen(makevecteur(turtle.x,turtle.y,double(turtle.theta),turtle_status(turtle),turtle.radius,turtle.s),_LOGO__VECT);
2289 }
2290
turtle_state(GIAC_CONTEXT)2291 gen turtle_state(GIAC_CONTEXT){
2292 return turtle2gen((*turtleptr));
2293 }
2294
update_turtle_state(bool clrstring,GIAC_CONTEXT)2295 static gen update_turtle_state(bool clrstring,GIAC_CONTEXT){
2296 #ifdef TURTLETAB
2297 if (turtle_stack_size>=MAX_LOGO)
2298 return gensizeerr("Not enough memory");
2299 #else
2300 if (turtle_stack().size()>=MAX_LOGO){
2301 ctrl_c=true; interrupted=true;
2302 return gensizeerr("Not enough memory");
2303 }
2304 #endif
2305 if (clrstring)
2306 (*turtleptr).s=-1;
2307 (*turtleptr).theta = (*turtleptr).theta - floor((*turtleptr).theta/360)*360;
2308 #ifdef TURTLETAB
2309 turtle_stack_push_back((*turtleptr));
2310 #else
2311 turtle_stack().push_back((*turtleptr));
2312 #endif
2313 gen res=turtle_state(contextptr);
2314 #ifdef EMCC // should directly interact with canvas
2315 return gen(turtlevect2vecteur(turtle_stack()),_LOGO__VECT);
2316 #endif
2317 return res;
2318 }
2319
2320 int turtle_speed=0;
_speed(const gen & g,GIAC_CONTEXT)2321 gen _speed(const gen & g,GIAC_CONTEXT){
2322 if ( g.type==_STRNG && g.subtype==-1) return g;
2323 if (g.type==_VECT && g._VECTptr->empty())
2324 return turtle_speed;
2325 if (g.type!=_INT_)
2326 return gensizeerr(contextptr);
2327 int i=g.val;
2328 if (i<0) i=0;
2329 if (i>1000) i=1000;
2330 turtle_speed=i;
2331 return i;
2332 }
2333 static const char _speed_s []="speed";
2334 static define_unary_function_eval2 (__speed,&_speed,_speed_s,&printastifunction);
2335 define_unary_function_ptr5( at_speed ,alias_at_speed,&__speed,0,T_LOGO);
2336
_avance(const gen & g,GIAC_CONTEXT)2337 gen _avance(const gen & g,GIAC_CONTEXT){
2338 if ( g.type==_STRNG && g.subtype==-1) return g;
2339 // logo instruction
2340 double i;
2341 if (g.type!=_INT_){
2342 if (g.type==_VECT)
2343 i=(*turtleptr).turtle_length;
2344 else {
2345 gen g1=evalf_double(g,1,contextptr);
2346 if (g1.type==_DOUBLE_)
2347 i=g1._DOUBLE_val;
2348 else
2349 return gensizeerr(contextptr);
2350 }
2351 }
2352 else
2353 i=g.val;
2354 (*turtleptr).x += i * std::cos((*turtleptr).theta*deg2rad_d);
2355 (*turtleptr).y += i * std::sin((*turtleptr).theta*deg2rad_d) ;
2356 (*turtleptr).radius = 0;
2357 return update_turtle_state(true,contextptr);
2358 }
2359 static const char _avance_s []="avance";
2360 static define_unary_function_eval2 (__avance,&_avance,_avance_s,&printastifunction);
2361 define_unary_function_ptr5( at_avance ,alias_at_avance,&__avance,0,T_LOGO);
2362
2363 static const char _forward_s []="forward";
2364 static define_unary_function_eval (__forward,&_avance,_forward_s);
2365 define_unary_function_ptr5( at_forward ,alias_at_forward,&__forward,0,true);
2366
_recule(const gen & g,GIAC_CONTEXT)2367 gen _recule(const gen & g,GIAC_CONTEXT){
2368 if ( g.type==_STRNG && g.subtype==-1) return g;
2369 // logo instruction
2370 if (g.type==_VECT)
2371 return _avance(-(*turtleptr).turtle_length,contextptr);
2372 return _avance(-g,contextptr);
2373 }
2374 static const char _recule_s []="recule";
2375 static define_unary_function_eval2 (__recule,&_recule,_recule_s,&printastifunction);
2376 define_unary_function_ptr5( at_recule ,alias_at_recule,&__recule,0,T_LOGO);
2377
2378 static const char _backward_s []="backward";
2379 static define_unary_function_eval (__backward,&_recule,_backward_s);
2380 define_unary_function_ptr5( at_backward ,alias_at_backward,&__backward,0,true);
2381
_position(const gen & g,GIAC_CONTEXT)2382 gen _position(const gen & g,GIAC_CONTEXT){
2383 if ( g.type==_STRNG && g.subtype==-1) return g;
2384 // logo instruction
2385 if (g.type!=_VECT)
2386 return makevecteur((*turtleptr).x,(*turtleptr).y);
2387 // return turtle_state();
2388 vecteur v = *g._VECTptr;
2389 int s=int(v.size());
2390 if (!s)
2391 return makevecteur((*turtleptr).x,(*turtleptr).y);
2392 v[0]=evalf_double(v[0],1,contextptr);
2393 if (s>1)
2394 v[1]=evalf_double(v[1],1,contextptr);
2395 if (s>2)
2396 v[2]=evalf_double(v[2],1,contextptr);
2397 if (set_turtle_state(v,contextptr))
2398 return update_turtle_state(true,contextptr);
2399 return zero;
2400 }
2401 static const char _position_s []="position";
2402 static define_unary_function_eval2 (__position,&_position,_position_s,&printastifunction);
2403 define_unary_function_ptr5( at_position ,alias_at_position,&__position,0,T_LOGO);
2404
_cap(const gen & g,GIAC_CONTEXT)2405 gen _cap(const gen & g,GIAC_CONTEXT){
2406 if ( g.type==_STRNG && g.subtype==-1) return g;
2407 // logo instruction
2408 gen gg=evalf_double(g,1,contextptr);
2409 if (gg.type!=_DOUBLE_)
2410 return double((*turtleptr).theta);
2411 (*turtleptr).theta=gg._DOUBLE_val;
2412 (*turtleptr).radius = 0;
2413 return update_turtle_state(true,contextptr);
2414 }
2415 static const char _cap_s []="cap";
2416 static define_unary_function_eval2 (__cap,&_cap,_cap_s,&printastifunction);
2417 define_unary_function_ptr5( at_cap ,alias_at_cap,&__cap,0,T_LOGO);
2418
2419 static const char _heading_s []="heading";
2420 static define_unary_function_eval (__heading,&_cap,_heading_s);
2421 define_unary_function_ptr5( at_heading ,alias_at_heading,&__heading,0,true);
2422
2423
_tourne_droite(const gen & g,GIAC_CONTEXT)2424 gen _tourne_droite(const gen & g,GIAC_CONTEXT){
2425 if ( g.type==_STRNG && g.subtype==-1) return g;
2426 // logo instruction
2427 if (g.type!=_INT_){
2428 if (g.type==_VECT)
2429 (*turtleptr).theta -= 90;
2430 else {
2431 gen g1=evalf_double(g,1,contextptr);
2432 if (g1.type==_DOUBLE_)
2433 (*turtleptr).theta -= g1._DOUBLE_val;
2434 else
2435 return gensizeerr(contextptr);
2436 }
2437 }
2438 else
2439 (*turtleptr).theta -= g.val;
2440 (*turtleptr).radius = 0;
2441 return update_turtle_state(true,contextptr);
2442 }
2443 static const char _tourne_droite_s []="tourne_droite";
2444 static define_unary_function_eval2 (__tourne_droite,&_tourne_droite,_tourne_droite_s,&printastifunction);
2445 define_unary_function_ptr5( at_tourne_droite ,alias_at_tourne_droite,&__tourne_droite,0,T_LOGO);
2446
_tourne_gauche(const gen & g,GIAC_CONTEXT)2447 gen _tourne_gauche(const gen & g,GIAC_CONTEXT){
2448 if ( g.type==_STRNG && g.subtype==-1) return g;
2449 // logo instruction
2450 if (g.type==_VECT){
2451 (*turtleptr).theta += 90;
2452 (*turtleptr).radius = 0;
2453 return update_turtle_state(true,contextptr);
2454 }
2455 return _tourne_droite(-g,contextptr);
2456 }
2457 static const char _tourne_gauche_s []="tourne_gauche";
2458 static define_unary_function_eval2 (__tourne_gauche,&_tourne_gauche,_tourne_gauche_s,&printastifunction);
2459 define_unary_function_ptr5( at_tourne_gauche ,alias_at_tourne_gauche,&__tourne_gauche,0,T_LOGO);
2460
_leve_crayon(const gen & g,GIAC_CONTEXT)2461 gen _leve_crayon(const gen & g,GIAC_CONTEXT){
2462 if ( g.type==_STRNG && g.subtype==-1) return g;
2463 // logo instruction
2464 (*turtleptr).mark = false;
2465 (*turtleptr).radius = 0;
2466 return update_turtle_state(true,contextptr);
2467 }
2468 static const char _leve_crayon_s []="leve_crayon";
2469 static define_unary_function_eval2 (__leve_crayon,&_leve_crayon,_leve_crayon_s,&printastifunction);
2470 define_unary_function_ptr5( at_leve_crayon ,alias_at_leve_crayon,&__leve_crayon,0,T_LOGO);
2471
2472 static const char _penup_s []="penup";
2473 static define_unary_function_eval (__penup,&_leve_crayon,_penup_s);
2474 define_unary_function_ptr5( at_penup ,alias_at_penup,&__penup,0,T_LOGO);
2475
_baisse_crayon(const gen & g,GIAC_CONTEXT)2476 gen _baisse_crayon(const gen & g,GIAC_CONTEXT){
2477 if ( g.type==_STRNG && g.subtype==-1) return g;
2478 // logo instruction
2479 (*turtleptr).mark = true;
2480 (*turtleptr).radius = 0;
2481 return update_turtle_state(true,contextptr);
2482 }
2483 static const char _baisse_crayon_s []="baisse_crayon";
2484 static define_unary_function_eval2 (__baisse_crayon,&_baisse_crayon,_baisse_crayon_s,&printastifunction);
2485 define_unary_function_ptr5( at_baisse_crayon ,alias_at_baisse_crayon,&__baisse_crayon,0,T_LOGO);
2486
2487 static const char _pendown_s []="pendown";
2488 static define_unary_function_eval (__pendown,&_baisse_crayon,_pendown_s);
2489 define_unary_function_ptr5( at_pendown ,alias_at_pendown,&__pendown,0,T_LOGO);
2490
2491 vector<string> * ecrisptr=0;
ecristab()2492 vector<string> & ecristab(){
2493 if (!ecrisptr)
2494 ecrisptr=new vector<string>;
2495 return * ecrisptr;
2496 }
_ecris(const gen & g,GIAC_CONTEXT)2497 gen _ecris(const gen & g,GIAC_CONTEXT){
2498 if ( g.type==_STRNG && g.subtype==-1) return g;
2499 #if 0 //def TURTLETAB
2500 return gensizeerr("String support does not work with static turtle table");
2501 #endif
2502 // logo instruction
2503 (*turtleptr).radius=14;
2504 if (g.type==_VECT){
2505 vecteur & v =*g._VECTptr;
2506 int s=int(v.size());
2507 if (s==2 && v[1].type==_INT_){
2508 (*turtleptr).radius=absint(v[1].val);
2509 (*turtleptr).s=ecristab().size();
2510 ecristab().push_back(gen2string(v.front()));
2511 return update_turtle_state(false,contextptr);
2512 }
2513 if (s==4 && v[1].type==_INT_ && v[2].type==_INT_ && v[3].type==_INT_){
2514 logo_turtle t=(*turtleptr);
2515 _leve_crayon(0,contextptr);
2516 _position(makevecteur(v[2],v[3]),contextptr);
2517 (*turtleptr).radius=absint(v[1].val);
2518 (*turtleptr).s=ecristab().size();
2519 ecristab().push_back(gen2string(v.front()));
2520 update_turtle_state(false,contextptr);
2521 (*turtleptr)=t;
2522 return update_turtle_state(true,contextptr);
2523 }
2524 }
2525 (*turtleptr).s=ecristab().size();
2526 ecristab().push_back(gen2string(g));
2527 return update_turtle_state(false,contextptr);
2528 }
2529 static const char _ecris_s []="ecris";
2530 static define_unary_function_eval2 (__ecris,&_ecris,_ecris_s,&printastifunction);
2531 define_unary_function_ptr5( at_ecris ,alias_at_ecris,&__ecris,0,T_LOGO);
2532
_signe(const gen & g,GIAC_CONTEXT)2533 gen _signe(const gen & g,GIAC_CONTEXT){
2534 if ( g.type==_STRNG && g.subtype==-1) return g;
2535 // logo instruction
2536 return _ecris(makevecteur(g,20,10,10),contextptr);
2537 }
2538 static const char _signe_s []="signe";
2539 static define_unary_function_eval2 (__signe,&_signe,_signe_s,&printastifunction);
2540 define_unary_function_ptr5( at_signe ,alias_at_signe,&__signe,0,T_LOGO);
2541
_saute(const gen & g,GIAC_CONTEXT)2542 gen _saute(const gen & g,GIAC_CONTEXT){
2543 if ( g.type==_STRNG && g.subtype==-1) return g;
2544 _leve_crayon(0,contextptr);
2545 _avance(g,contextptr);
2546 return _baisse_crayon(0,contextptr);
2547 }
2548 static const char _saute_s []="saute";
2549 static define_unary_function_eval2 (__saute,&_saute,_saute_s,&printastifunction);
2550 define_unary_function_ptr5( at_saute ,alias_at_saute,&__saute,0,T_LOGO);
2551
2552 static const char _jump_s []="jump";
2553 static define_unary_function_eval2 (__jump,&_saute,_jump_s,&printastifunction);
2554 define_unary_function_ptr5( at_jump ,alias_at_jump,&__jump,0,T_LOGO);
2555
_pas_de_cote(const gen & g,GIAC_CONTEXT)2556 gen _pas_de_cote(const gen & g,GIAC_CONTEXT){
2557 if ( g.type==_STRNG && g.subtype==-1) return g;
2558 _leve_crayon(0,contextptr);
2559 _tourne_droite(-90,contextptr);
2560 _avance(g,contextptr);
2561 _tourne_droite(90,contextptr);
2562 return _baisse_crayon(0,contextptr);
2563 }
2564 static const char _pas_de_cote_s []="pas_de_cote";
2565 static define_unary_function_eval2 (__pas_de_cote,&_pas_de_cote,_pas_de_cote_s,&printastifunction);
2566 define_unary_function_ptr5( at_pas_de_cote ,alias_at_pas_de_cote,&__pas_de_cote,0,T_LOGO);
2567
2568 static const char _skip_s []="skip";
2569 static define_unary_function_eval2 (__skip,&_pas_de_cote,_skip_s,&printastifunction);
2570 define_unary_function_ptr5( at_skip ,alias_at_skip,&__skip,0,T_LOGO);
2571
_cache_tortue(const gen & g,GIAC_CONTEXT)2572 gen _cache_tortue(const gen & g,GIAC_CONTEXT){
2573 if ( g.type==_STRNG && g.subtype==-1) return g;
2574 // logo instruction
2575 (*turtleptr).visible=false;
2576 (*turtleptr).radius = 0;
2577 return update_turtle_state(true,contextptr);
2578 }
2579 static const char _cache_tortue_s []="cache_tortue";
2580 static define_unary_function_eval2 (__cache_tortue,&_cache_tortue,_cache_tortue_s,&printastifunction);
2581 define_unary_function_ptr5( at_cache_tortue ,alias_at_cache_tortue,&__cache_tortue,0,T_LOGO);
2582
2583 static const char _hideturtle_s []="hideturtle";
2584 static define_unary_function_eval (__hideturtle,&_cache_tortue,_hideturtle_s);
2585 define_unary_function_ptr5( at_hideturtle ,alias_at_hideturtle,&__hideturtle,0,true);
2586
_montre_tortue(const gen & g,GIAC_CONTEXT)2587 gen _montre_tortue(const gen & g,GIAC_CONTEXT){
2588 if ( g.type==_STRNG && g.subtype==-1) return g;
2589 // logo instruction
2590 (*turtleptr).visible=true;
2591 (*turtleptr).radius = 0;
2592 return update_turtle_state(true,contextptr);
2593 }
2594 static const char _montre_tortue_s []="montre_tortue";
2595 static define_unary_function_eval2 (__montre_tortue,&_montre_tortue,_montre_tortue_s,&printastifunction);
2596 define_unary_function_ptr5( at_montre_tortue ,alias_at_montre_tortue,&__montre_tortue,0,T_LOGO);
2597
2598 static const char _showturtle_s []="showturtle";
2599 static define_unary_function_eval (__showturtle,&_montre_tortue,_showturtle_s);
2600 define_unary_function_ptr5( at_showturtle ,alias_at_showturtle,&__showturtle,0,true);
2601
2602
_repete(const gen & g,GIAC_CONTEXT)2603 gen _repete(const gen & g,GIAC_CONTEXT){
2604 if ( g.type==_STRNG && g.subtype==-1) return g;
2605 if (g.type!=_VECT || g._VECTptr->size()<2)
2606 return gensizeerr(contextptr);
2607 // logo instruction
2608 vecteur v = *g._VECTptr;
2609 v[0]=eval(v[0],contextptr);
2610 if (v.front().type!=_INT_)
2611 return gentypeerr(contextptr);
2612 gen prog=vecteur(v.begin()+1,v.end());
2613 int i=absint(v.front().val);
2614 gen res;
2615 for (int j=0;j<i;++j){
2616 res=eval(prog,contextptr);
2617 }
2618 return res;
2619 }
2620 static const char _repete_s []="repete";
2621 static define_unary_function_eval_quoted (__repete,&_repete,_repete_s);
2622 define_unary_function_ptr5( at_repete ,alias_at_repete,&__repete,_QUOTE_ARGUMENTS,T_RETURN);
2623
_crayon(const gen & g,GIAC_CONTEXT)2624 gen _crayon(const gen & g,GIAC_CONTEXT){
2625 if ( g.type==_STRNG && g.subtype==-1) return g;
2626 if (g.type==_STRNG) return _crayon(gen(*g._STRNGptr,contextptr),contextptr);
2627 // logo instruction
2628 if (g.type==_VECT && g._VECTptr->size()==3)
2629 return _crayon(_rgb(g,contextptr),contextptr);
2630 if (g.type!=_INT_){
2631 gen res=(*turtleptr).color;
2632 res.subtype=_INT_COLOR;
2633 return res;
2634 }
2635 (*turtleptr).color=g.val;
2636 (*turtleptr).radius = 0;
2637 return update_turtle_state(true,contextptr);
2638 }
2639 static const char _crayon_s []="crayon";
2640 static define_unary_function_eval2 (__crayon,&_crayon,_crayon_s,&printastifunction);
2641 define_unary_function_ptr5( at_crayon ,alias_at_crayon,&__crayon,0,T_LOGO);
2642
2643 static const char _pencolor_s []="pencolor";
2644 static define_unary_function_eval (__pencolor,&_crayon,_pencolor_s);
2645 define_unary_function_ptr5( at_pencolor ,alias_at_pencolor,&__pencolor,0,T_LOGO);
2646
_efface_logo(const gen & g,GIAC_CONTEXT)2647 gen _efface_logo(const gen & g,GIAC_CONTEXT){
2648 if ( g.type==_STRNG && g.subtype==-1) return g;
2649 if (g.type==_INT_){
2650 _crayon(int(FL_WHITE),contextptr);
2651 _recule(g,contextptr);
2652 return _crayon(0,contextptr);
2653 }
2654 // logo instruction
2655 (*turtleptr) = logo_turtle();
2656 #ifdef TURTLETAB
2657 turtle_stack_size=0;
2658 #else
2659 turtle_stack().clear();
2660 #endif
2661 ecristab().clear();
2662 if (g.type==_VECT && g._VECTptr->size()==2){
2663 vecteur v = *g._VECTptr;
2664 int s=int(v.size());
2665 v[0]=evalf_double(v[0],1,contextptr);
2666 if (s>1)
2667 v[1]=evalf_double(v[1],1,contextptr);
2668 (*turtleptr).mark = false; // leve_crayon
2669 (*turtleptr).radius = 0;
2670 update_turtle_state(true,contextptr);
2671 set_turtle_state(v,contextptr); // baisse_crayon
2672 update_turtle_state(true,contextptr);
2673 (*turtleptr).mark = true;
2674 (*turtleptr).radius = 0;
2675 }
2676 return update_turtle_state(true,contextptr);
2677 }
2678 static const char _efface_logo_s []="efface";
2679 static define_unary_function_eval2 (__efface_logo,&_efface_logo,_efface_logo_s,&printastifunction);
2680 define_unary_function_ptr5( at_efface_logo ,alias_at_efface_logo,&__efface_logo,0,T_LOGO);
2681
2682 static const char _efface_s []="efface";
2683 static define_unary_function_eval2 (__efface,&_efface_logo,_efface_s,&printastifunction);
2684 define_unary_function_ptr5( at_efface ,alias_at_efface,&__efface,0,T_LOGO);
2685
2686 static const char _reset_s []="reset";
2687 static define_unary_function_eval2 (__reset,&_efface_logo,_reset_s,&printastifunction);
2688 define_unary_function_ptr5( at_reset ,alias_at_reset,&__reset,0,T_LOGO);
2689
2690 static const char _clearscreen_s []="clearscreen";
2691 static define_unary_function_eval2 (__clearscreen,&_efface_logo,_clearscreen_s,&printastifunction);
2692 define_unary_function_ptr5( at_clearscreen ,alias_at_clearscreen,&__clearscreen,0,T_LOGO);
2693
_debut_enregistrement(const gen & g,GIAC_CONTEXT)2694 gen _debut_enregistrement(const gen &g,GIAC_CONTEXT){
2695 return undef;
2696 }
2697 static const char _debut_enregistrement_s []="debut_enregistrement";
2698 static define_unary_function_eval2 (__debut_enregistrement,&_debut_enregistrement,_debut_enregistrement_s,&printastifunction);
2699 define_unary_function_ptr5( at_debut_enregistrement ,alias_at_debut_enregistrement,&__debut_enregistrement,0,T_LOGO);
2700
2701 static const char _fin_enregistrement_s []="fin_enregistrement";
2702 static define_unary_function_eval2 (__fin_enregistrement,&_debut_enregistrement,_fin_enregistrement_s,&printastifunction);
2703 define_unary_function_ptr5( at_fin_enregistrement ,alias_at_fin_enregistrement,&__fin_enregistrement,0,T_LOGO);
2704
2705 static const char _turtle_stack_s []="turtle_stack";
2706 static define_unary_function_eval2 (__turtle_stack,&_debut_enregistrement,_turtle_stack_s,&printastifunction);
2707 define_unary_function_ptr5( at_turtle_stack ,alias_at_turtle_stack,&__turtle_stack,0,T_LOGO);
2708
_vers(const gen & g,GIAC_CONTEXT)2709 gen _vers(const gen & g,GIAC_CONTEXT){
2710 if ( g.type==_STRNG && g.subtype==-1) return g;
2711 // logo instruction
2712 if (g.type!=_VECT || g._VECTptr->size()!=2)
2713 return gensizeerr(contextptr);
2714 gen x=evalf_double(g._VECTptr->front(),1,contextptr),
2715 y=evalf_double(g._VECTptr->back(),1,contextptr);
2716 if (x.type!=_DOUBLE_ || y.type!=_DOUBLE_)
2717 return gensizeerr(contextptr);
2718 double xv=x._DOUBLE_val,yv=y._DOUBLE_val,xt=(*turtleptr).x,yt=(*turtleptr).y;
2719 double theta=atan2(yv-yt,xv-xt);
2720 return _cap(theta*180/M_PI,contextptr);
2721 }
2722 static const char _vers_s []="vers";
2723 static define_unary_function_eval2 (__vers,&_vers,_vers_s,&printastifunction);
2724 define_unary_function_ptr5( at_vers ,alias_at_vers,&__vers,0,T_LOGO);
2725
find_radius(const gen & g,int & r,int & theta2,bool & direct)2726 static int find_radius(const gen & g,int & r,int & theta2,bool & direct){
2727 int radius;
2728 direct=true;
2729 theta2 = 360 ;
2730 // logo instruction
2731 if (g.type==_VECT && !g._VECTptr->empty()){
2732 vecteur v = *g._VECTptr;
2733 bool seg=false;
2734 if (v.back()==at_segment){
2735 v.pop_back();
2736 seg=true;
2737 }
2738 if (v.size()<2)
2739 return RAND_MAX; // setdimerr(contextptr);
2740 if (v[0].type==_INT_)
2741 r=v[0].val;
2742 else {
2743 gen v0=evalf_double(v[0],1,context0);
2744 if (v0.type==_DOUBLE_)
2745 r=int(v0._DOUBLE_val+0.5);
2746 else
2747 return RAND_MAX; // setsizeerr(contextptr);
2748 }
2749 if (r<0){
2750 r=-r;
2751 direct=false;
2752 }
2753 int theta1;
2754 if (v[1].type==_DOUBLE_)
2755 theta1=int(v[1]._DOUBLE_val+0.5);
2756 else {
2757 if (v[1].type==_INT_)
2758 theta1=v[1].val;
2759 else return RAND_MAX; // setsizeerr(contextptr);
2760 }
2761 while (theta1<0)
2762 theta1 += 360;
2763 if (v.size()>=3){
2764 if (v[2].type==_DOUBLE_)
2765 theta2 = int(v[2]._DOUBLE_val+0.5);
2766 else {
2767 if (v[2].type==_INT_)
2768 theta2 = v[2].val;
2769 else return RAND_MAX; // setsizeerr(contextptr);
2770 }
2771 while (theta2<0)
2772 theta2 += 360;
2773 radius = giacmin(r,512) | (giacmin(theta1,360) << 9) | (giacmin(theta2,360) << 18 ) | (seg?(1<<28):0);
2774 }
2775 else {// angle 1=0
2776 theta2 = theta1;
2777 if (theta2<0)
2778 theta2 += 360;
2779 radius = giacmin(r,512) | (giacmin(theta2,360) << 18 ) | (seg?(1<<28):0);
2780 }
2781 return radius;
2782 }
2783 radius = 10;
2784 if (g.type==_INT_)
2785 radius= (r=g.val);
2786 if (g.type==_DOUBLE_)
2787 radius= (r=int(g._DOUBLE_val));
2788 if (radius<=0){
2789 radius = -radius;
2790 direct=false;
2791 }
2792 radius = giacmin(radius,512 )+(360 << 18) ; // 2nd angle = 360 degrees
2793 return radius;
2794 }
2795
turtle_move(int r,int theta2,GIAC_CONTEXT)2796 static void turtle_move(int r,int theta2,GIAC_CONTEXT){
2797 double theta0;
2798 if ((*turtleptr).direct)
2799 theta0=(*turtleptr).theta-90;
2800 else {
2801 theta0=(*turtleptr).theta+90;
2802 theta2=-theta2;
2803 }
2804 (*turtleptr).x += r*(std::cos(M_PI/180*(theta2+theta0))-std::cos(M_PI/180*theta0));
2805 (*turtleptr).y += r*(std::sin(M_PI/180*(theta2+theta0))-std::sin(M_PI/180*theta0));
2806 (*turtleptr).theta = (*turtleptr).theta+theta2 ;
2807 if ((*turtleptr).theta<0)
2808 (*turtleptr).theta += 360;
2809 if ((*turtleptr).theta>360)
2810 (*turtleptr).theta -= 360;
2811 }
2812
_rond(const gen & g,GIAC_CONTEXT)2813 gen _rond(const gen & g,GIAC_CONTEXT){
2814 if ( g.type==_STRNG && g.subtype==-1) return g;
2815 int r,theta2,tmpr;
2816 tmpr=find_radius(g,r,theta2,(*turtleptr).direct);
2817 if (tmpr==RAND_MAX)
2818 return gensizeerr(contextptr);
2819 (*turtleptr).radius=tmpr;
2820 turtle_move(r,theta2,contextptr);
2821 return update_turtle_state(true,contextptr);
2822 }
2823 static const char _rond_s []="rond";
2824 static define_unary_function_eval2 (__rond,&_rond,_rond_s,&printastifunction);
2825 define_unary_function_ptr5( at_rond ,alias_at_rond,&__rond,0,T_LOGO);
2826
_disque(const gen & g,GIAC_CONTEXT)2827 gen _disque(const gen & g,GIAC_CONTEXT){
2828 if ( g.type==_STRNG && g.subtype==-1) return g;
2829 int r,theta2,tmpr=find_radius(g,r,theta2,(*turtleptr).direct);
2830 if (tmpr==RAND_MAX)
2831 return gensizeerr(contextptr);
2832 (*turtleptr).radius=tmpr;
2833 turtle_move(r,theta2,contextptr);
2834 (*turtleptr).radius += 1 << 27;
2835 return update_turtle_state(true,contextptr);
2836 }
2837 static const char _disque_s []="disque";
2838 static define_unary_function_eval2 (__disque,&_disque,_disque_s,&printastifunction);
2839 define_unary_function_ptr5( at_disque ,alias_at_disque,&__disque,0,T_LOGO);
2840
_disque_centre(const gen & g,GIAC_CONTEXT)2841 gen _disque_centre(const gen & g,GIAC_CONTEXT){
2842 if ( g.type==_STRNG && g.subtype==-1) return g;
2843 int r,theta2;
2844 bool direct;
2845 int radius=find_radius(g,r,theta2,direct);
2846 if (radius==RAND_MAX)
2847 return gensizeerr(contextptr);
2848 r=absint(r);
2849 _saute(r,contextptr);
2850 _tourne_gauche(direct?90:-90,contextptr);
2851 (*turtleptr).radius = radius;
2852 (*turtleptr).direct=direct;
2853 turtle_move(r,theta2,contextptr);
2854 (*turtleptr).radius += 1 << 27;
2855 update_turtle_state(true,contextptr);
2856 _tourne_droite(direct?90:-90,contextptr);
2857 return _saute(-r,contextptr);
2858 }
2859 static const char _disque_centre_s []="disque_centre";
2860 static define_unary_function_eval2 (__disque_centre,&_disque_centre,_disque_centre_s,&printastifunction);
2861 define_unary_function_ptr5( at_disque_centre ,alias_at_disque_centre,&__disque_centre,0,T_LOGO);
2862
_polygone_rempli(const gen & g,GIAC_CONTEXT)2863 gen _polygone_rempli(const gen & g,GIAC_CONTEXT){
2864 if ( g.type==_STRNG && g.subtype==-1) return g;
2865 if (g.type==_INT_){
2866 (*turtleptr).radius=-absint(g.val);
2867 if ((*turtleptr).radius<-1)
2868 return update_turtle_state(true,contextptr);
2869 }
2870 return gensizeerr(gettext("Integer argument >= 2"));
2871 }
2872 static const char _polygone_rempli_s []="polygone_rempli";
2873 static define_unary_function_eval2 (__polygone_rempli,&_polygone_rempli,_polygone_rempli_s,&printastifunction);
2874 define_unary_function_ptr5( at_polygone_rempli ,alias_at_polygone_rempli,&__polygone_rempli,0,T_LOGO);
2875
_rectangle_plein(const gen & g,GIAC_CONTEXT)2876 gen _rectangle_plein(const gen & g,GIAC_CONTEXT){
2877 if ( g.type==_STRNG && g.subtype==-1) return g;
2878 gen gx=g,gy=g;
2879 if (g.type==_VECT && g._VECTptr->size()==2){
2880 gx=g._VECTptr->front();
2881 gy=g._VECTptr->back();
2882 }
2883 for (int i=0;i<2;++i){
2884 _avance(gx,contextptr);
2885 _tourne_droite(-90,contextptr);
2886 _avance(gy,contextptr);
2887 _tourne_droite(-90,contextptr);
2888 }
2889 //for (int i=0;i<turtle_stack().size();++i){ *logptr(contextptr) << turtle2gen(turtle_stack()[i]) <<endl;}
2890 return _polygone_rempli(-8,contextptr);
2891 }
2892 static const char _rectangle_plein_s []="rectangle_plein";
2893 static define_unary_function_eval2 (__rectangle_plein,&_rectangle_plein,_rectangle_plein_s,&printastifunction);
2894 define_unary_function_ptr5( at_rectangle_plein ,alias_at_rectangle_plein,&__rectangle_plein,0,T_LOGO);
2895
_triangle_plein(const gen & g,GIAC_CONTEXT)2896 gen _triangle_plein(const gen & g,GIAC_CONTEXT){
2897 if ( g.type==_STRNG && g.subtype==-1) return g;
2898 gen gx=g,gy=g,gtheta=60;
2899 if (g.type==_VECT && g._VECTptr->size()>=2){
2900 vecteur & v=*g._VECTptr;
2901 gx=v.front();
2902 gy=v[1];
2903 gtheta=90;
2904 if (v.size()>2)
2905 gtheta=v[2];
2906 }
2907 logo_turtle t=(*turtleptr);
2908 _avance(gx,contextptr);
2909 double save_x=(*turtleptr).x,save_y=(*turtleptr).y;
2910 _recule(gx,contextptr);
2911 _tourne_gauche(gtheta,contextptr);
2912 _avance(gy,contextptr);
2913 (*turtleptr).x=save_x;
2914 (*turtleptr).y=save_y;
2915 update_turtle_state(true,contextptr);
2916 (*turtleptr)=t;
2917 (*turtleptr).radius=0;
2918 update_turtle_state(true,contextptr);
2919 return _polygone_rempli(-3,contextptr);
2920 }
2921 static const char _triangle_plein_s []="triangle_plein";
2922 static define_unary_function_eval2 (__triangle_plein,&_triangle_plein,_triangle_plein_s,&printastifunction);
2923 define_unary_function_ptr5( at_triangle_plein ,alias_at_triangle_plein,&__triangle_plein,0,T_LOGO);
2924
_dessine_tortue(const gen & g,GIAC_CONTEXT)2925 gen _dessine_tortue(const gen & g,GIAC_CONTEXT){
2926 if ( g.type==_STRNG && g.subtype==-1) return g;
2927 // logo instruction
2928 /*
2929 _triangle_plein(makevecteur(17,5));
2930 _tourne_droite(90);
2931 _triangle_plein(makevecteur(5,17));
2932 return _tourne_droite(-90);
2933 */
2934 double save_x=(*turtleptr).x,save_y=(*turtleptr).y;
2935 _tourne_droite(90,contextptr);
2936 _avance(5,contextptr);
2937 _tourne_gauche(106,contextptr);
2938 _avance(18,contextptr);
2939 _tourne_gauche(148,contextptr);
2940 _avance(18,contextptr);
2941 _tourne_gauche(106,contextptr);
2942 _avance(5,contextptr);
2943 (*turtleptr).x=save_x; (*turtleptr).y=save_y;
2944 gen res(_tourne_gauche(90,contextptr));
2945 if (is_one(g))
2946 return res;
2947 return _polygone_rempli(-9,contextptr);
2948 }
2949 static const char _dessine_tortue_s []="dessine_tortue";
2950 static define_unary_function_eval2 (__dessine_tortue,&_dessine_tortue,_dessine_tortue_s,&printastifunction);
2951 define_unary_function_ptr5( at_dessine_tortue ,alias_at_dessine_tortue,&__dessine_tortue,0,T_LOGO);
2952
2953 #ifndef NO_NAMESPACE_GIAC
2954 } // namespace giac
2955 #endif // ndef NO_NAMESPACE_GIAC
2956
2957
2958 #ifndef NO_NAMESPACE_XCAS
2959 namespace xcas {
2960 #endif // ndef NO_NAMESPACE_XCAS
drawRectangle(int x,int y,int w,int h,int c)2961 void drawRectangle(int x,int y,int w,int h,int c){
2962 draw_rectangle(x,y,w,h,c,context0);
2963 }
draw_rectangle(int x,int y,int w,int h,int c)2964 void draw_rectangle(int x,int y,int w,int h,int c){
2965 draw_rectangle(x,y,w,h,c,context0);
2966 }
draw_line(int x0,int y0,int x1,int y1,int c)2967 void draw_line(int x0,int y0,int x1,int y1,int c){
2968 draw_line(x0,y0,x1,y1,c,context0);
2969 }
draw_circle(int xc,int yc,int r,int color,bool q1,bool q2,bool q3,bool q4)2970 void draw_circle(int xc,int yc,int r,int color,bool q1,bool q2,bool q3,bool q4){
2971 draw_circle(xc,yc,r,color,q1,q2,q3,q4,context0);
2972 }
draw_filled_circle(int xc,int yc,int r,int color,bool left,bool right)2973 void draw_filled_circle(int xc,int yc,int r,int color,bool left,bool right){
2974 draw_filled_circle(xc,yc,r,color,left,right,context0);
2975 }
draw_polygon(std::vector<std::vector<int>> & v1,int color)2976 void draw_polygon(std::vector< std::vector<int> > & v1,int color){
2977 draw_polygon(v1,color,context0);
2978 }
draw_filled_polygon(std::vector<vector<int>> & L,int xmin,int xmax,int ymin,int ymax,int color)2979 void draw_filled_polygon(std::vector< vector<int> > &L,int xmin,int xmax,int ymin,int ymax,int color){
2980 draw_filled_polygon(L,xmin,xmax,ymin,ymax,color,context0);
2981 }
draw_arc(int xc,int yc,int rx,int ry,int color,double theta1,double theta2)2982 void draw_arc(int xc,int yc,int rx,int ry,int color,double theta1, double theta2){
2983 draw_arc(xc,yc,rx,ry,color,theta1,theta2,giac::context0);
2984 }
draw_filled_arc(int x,int y,int rx,int ry,int theta1_deg,int theta2_deg,int color,int xmin,int xmax,int ymin,int ymax,bool segment)2985 void draw_filled_arc(int x,int y,int rx,int ry,int theta1_deg,int theta2_deg,int color,int xmin,int xmax,int ymin,int ymax,bool segment){
2986 draw_filled_arc(x,y,rx,ry,theta1_deg,theta2_deg,color,xmin,xmax,ymin,ymax,segment,context0);
2987 }
2988
2989
2990 unsigned max_prettyprint_equation=256;
2991
2992 // make a free copy of g
Equation_copy(const gen & g)2993 gen Equation_copy(const gen & g){
2994 if (g.type==_EQW)
2995 return *g._EQWptr;
2996 if (g.type!=_VECT)
2997 return g;
2998 vecteur & v = *g._VECTptr;
2999 const_iterateur it=v.begin(),itend=v.end();
3000 vecteur res;
3001 res.reserve(itend-it);
3002 for (;it!=itend;++it)
3003 res.push_back(Equation_copy(*it));
3004 return gen(res,g.subtype);
3005 }
3006
3007 // matrix/list select
do_select(gen & eql,bool select,gen & value)3008 bool do_select(gen & eql,bool select,gen & value){
3009 if (eql.type==_VECT && !eql._VECTptr->empty()){
3010 vecteur & v=*eql._VECTptr;
3011 size_t s=v.size();
3012 if (v[s-1].type!=_EQW)
3013 return false;
3014 v[s-1]._EQWptr->selected=select;
3015 gen sommet=v[s-1]._EQWptr->g;
3016 --s;
3017 vecteur args(s);
3018 for (size_t i=0;i<s;++i){
3019 if (!do_select(v[i],select,args[i]))
3020 return false;
3021 if (args[i].type==_EQW)
3022 args[i]=args[i]._EQWptr->g;
3023 }
3024 gen va=s==1?args[0]:gen(args,_SEQ__VECT);
3025 if (sommet.type==_FUNC)
3026 va=symbolic(*sommet._FUNCptr,va);
3027 else
3028 va=sommet(va,context0);
3029 //cout << "va " << va << endl;
3030 value=*v[s]._EQWptr;
3031 value._EQWptr->g=va;
3032 //cout << "value " << value << endl;
3033 return true;
3034 }
3035 if (eql.type!=_EQW)
3036 return false;
3037 eql._EQWptr->selected=select;
3038 value=eql;
3039 return true;
3040 }
3041
Equation_box_sizes(const gen & g,int & l,int & h,int & x,int & y,attributs & attr,bool & selected)3042 bool Equation_box_sizes(const gen & g,int & l,int & h,int & x,int & y,attributs & attr,bool & selected){
3043 if (g.type==_EQW){
3044 eqwdata & w=*g._EQWptr;
3045 x=w.x;
3046 y=w.y;
3047 l=w.dx;
3048 h=w.dy;
3049 selected=w.selected;
3050 attr=w.eqw_attributs;
3051 //cout << g << endl;
3052 return true;
3053 }
3054 else {
3055 if (g.type!=_VECT || g._VECTptr->empty() ){
3056 l=0;
3057 h=0;
3058 x=0;
3059 y=0;
3060 attr=attributs(0,0,0);
3061 selected=false;
3062 return true;
3063 }
3064 gen & g1=g._VECTptr->back();
3065 Equation_box_sizes(g1,l,h,x,y,attr,selected);
3066 return false;
3067 }
3068 }
3069
3070 // return true if g has some selection inside, gsel points to the selection
Equation_adjust_xy(gen & g,int & xleft,int & ytop,int & xright,int & ybottom,gen * & gsel,gen * & gselparent,int & gselpos,std::vector<int> * goto_ptr)3071 bool Equation_adjust_xy(gen & g,int & xleft,int & ytop,int & xright,int & ybottom,gen * & gsel,gen * & gselparent,int &gselpos,std::vector<int> * goto_ptr){
3072 gsel=0;
3073 gselparent=0;
3074 gselpos=0;
3075 int x,y,w,h;
3076 attributs f(0,0,0);
3077 bool selected;
3078 Equation_box_sizes(g,w,h,x,y,f,selected);
3079 if ( (g.type==_EQW__VECT) || selected ){ // terminal or selected
3080 xleft=x;
3081 ybottom=y;
3082 if (selected){ // g is selected
3083 ytop=y+h;
3084 xright=x+w;
3085 gsel = &g;
3086 //cout << "adjust " << *gsel << endl;
3087 return true;
3088 }
3089 else { // no selection
3090 xright=x;
3091 ytop=y;
3092 return false;
3093 }
3094 }
3095 if (g.type!=_VECT)
3096 return false;
3097 // last not selected, recurse
3098 iterateur it=g._VECTptr->begin(),itend=g._VECTptr->end()-1;
3099 for (;it!=itend;++it){
3100 if (Equation_adjust_xy(*it,xleft,ytop,xright,ybottom,gsel,gselparent,gselpos,goto_ptr)){
3101 if (goto_ptr){
3102 goto_ptr->push_back(it-g._VECTptr->begin());
3103 //cout << g << ":" << *goto_ptr << endl;
3104 }
3105 if (gsel==&*it){
3106 // check next siblings
3107
3108 gselparent= &g;
3109 gselpos=it-g._VECTptr->begin();
3110 //cout << "gselparent " << g << endl;
3111 }
3112 return true;
3113 }
3114 }
3115 return false;
3116 }
3117
3118 // select or deselect part of the current eqution
3119 // This is done *in place*
Equation_select(gen & g,bool select)3120 void Equation_select(gen & g,bool select){
3121 if (g.type==_EQW){
3122 eqwdata & e=*g._EQWptr;
3123 e.selected=select;
3124 }
3125 if (g.type!=_VECT)
3126 return;
3127 vecteur & v=*g._VECTptr;
3128 iterateur it=v.begin(),itend=v.end();
3129 for (;it!=itend;++it)
3130 Equation_select(*it,select);
3131 }
3132
3133 // decrease selection (like HP49 eqw Down key)
eqw_select_down(gen & g)3134 int eqw_select_down(gen & g){
3135 int xleft,ytop,xright,ybottom,gselpos;
3136 int newxleft,newytop,newxright,newybottom;
3137 gen * gsel,*gselparent;
3138 if (Equation_adjust_xy(g,xleft,ytop,xright,ybottom,gsel,gselparent,gselpos)){
3139 //cout << "select down before " << *gsel << endl;
3140 if (gsel->type==_VECT && !gsel->_VECTptr->empty()){
3141 Equation_select(*gsel,false);
3142 Equation_select(gsel->_VECTptr->front(),true);
3143 //cout << "select down after " << *gsel << endl;
3144 Equation_adjust_xy(g,newxleft,newytop,newxright,newybottom,gsel,gselparent,gselpos);
3145 return newytop-ytop;
3146 }
3147 }
3148 return 0;
3149 }
3150
eqw_select_up(gen & g)3151 int eqw_select_up(gen & g){
3152 int xleft,ytop,xright,ybottom,gselpos;
3153 int newxleft,newytop,newxright,newybottom;
3154 gen * gsel,*gselparent;
3155 if (Equation_adjust_xy(g,xleft,ytop,xright,ybottom,gsel,gselparent,gselpos) && gselparent){
3156 Equation_select(*gselparent,true);
3157 //cout << "gselparent " << *gselparent << endl;
3158 Equation_adjust_xy(g,newxleft,newytop,newxright,newybottom,gsel,gselparent,gselpos);
3159 return newytop-ytop;
3160 }
3161 return false;
3162 }
3163
3164 // exchange==0 move selection to left or right sibling, ==2 add left or right
3165 // sibling, ==1 exchange selection with left or right sibling
eqw_select_leftright(Equation & eq,bool left,int exchange,GIAC_CONTEXT)3166 int eqw_select_leftright(Equation & eq,bool left,int exchange,GIAC_CONTEXT){
3167 gen & g=eq.data;
3168 int xleft,ytop,xright,ybottom,gselpos;
3169 int newxleft,newytop,newxright,newybottom;
3170 gen * gsel,*gselparent;
3171 vector<int> goto_sel;
3172 if (Equation_adjust_xy(g,xleft,ytop,xright,ybottom,gsel,gselparent,gselpos,&goto_sel) && gselparent && gselparent->type==_VECT){
3173 vecteur & gselv=*gselparent->_VECTptr;
3174 int n=gselv.size()-1,gselpos_orig=gselpos;
3175 if (n<1) return 0;
3176 if (left) {
3177 if (gselpos==0)
3178 gselpos=n-1;
3179 else
3180 gselpos--;
3181 }
3182 else {
3183 if (gselpos==n-1)
3184 gselpos=0;
3185 else
3186 gselpos++;
3187 }
3188 if (exchange==1){ // exchange gselpos_orig and gselpos
3189 swapgen(gselv[gselpos],gselv[gselpos_orig]);
3190 gsel=&gselv[gselpos_orig];
3191 gen value;
3192 if (xcas::do_select(*gsel,true,value) && value.type==_EQW)
3193 replace_selection(eq,value._EQWptr->g,gsel,&goto_sel,contextptr);
3194 }
3195 else {
3196 // increase selection to next sibling possible for + and * only
3197 if (n>2 && exchange==2 && gselv[n].type==_EQW && (gselv[n]._EQWptr->g==at_plus || gselv[n]._EQWptr->g==at_prod)){
3198 gen value1, value2,tmp;
3199 if (gselpos_orig<gselpos)
3200 swapint(gselpos_orig,gselpos);
3201 // now gselpos<gselpos_orig
3202 xcas::do_select(gselv[gselpos_orig],true,value1);
3203 xcas::do_select(gselv[gselpos],true,value2);
3204 if (value1.type==_EQW && value2.type==_EQW){
3205 tmp=gselv[n]._EQWptr->g==at_plus?value1._EQWptr->g+value2._EQWptr->g:value1._EQWptr->g*value2._EQWptr->g;
3206 gselv.erase(gselv.begin()+gselpos_orig);
3207 replace_selection(eq,tmp,&gselv[gselpos],&goto_sel,contextptr);
3208 }
3209 }
3210 else {
3211 Equation_select(*gselparent,false);
3212 gen & tmp=(*gselparent->_VECTptr)[gselpos];
3213 Equation_select(tmp,true);
3214 }
3215 }
3216 Equation_adjust_xy(g,newxleft,newytop,newxright,newybottom,gsel,gselparent,gselpos);
3217 return newxleft-xleft;
3218 }
3219 return 0;
3220 }
3221
eqw_select(const gen & eq,int l,int c,bool select,gen & value)3222 bool eqw_select(const gen & eq,int l,int c,bool select,gen & value){
3223 value=undef;
3224 if (l<0 || eq.type!=_VECT || eq._VECTptr->size()<=l)
3225 return false;
3226 gen & eql=(*eq._VECTptr)[l];
3227 if (c<0)
3228 return do_select(eql,select,value);
3229 if (eql.type!=_VECT || eql._VECTptr->size()<=c)
3230 return false;
3231 gen & eqlc=(*eql._VECTptr)[c];
3232 return do_select(eqlc,select,value);
3233 }
3234
3235 gen Equation_compute_size(const gen & g,const attributs & a,int windowhsize,GIAC_CONTEXT);
3236
3237 // void Bdisp_MMPrint(int x, int y, const char* string, int mode_flags, int xlimit, int P6, int P7, int color, int back_color, int writeflag, int P11);
3238 // void PrintCXY(int x, int y, const char *cptr, int mode_flags, int P5, int color, int back_color, int P8, int P9)
3239 // void PrintMini( int* x, int* y, const char* string, int mode_flags, unsigned int xlimit, int P6, int P7, int color, int back_color, int writeflag, int P11)
text_print(int fontsize,const char * s,int x,int y,int c=COLOR_BLACK,int bg=COLOR_WHITE,int mode=0)3240 void text_print(int fontsize,const char * s,int x,int y,int c=COLOR_BLACK,int bg=COLOR_WHITE,int mode=0){
3241 // *logptr(contextptr) << x << " " << y << " " << fontsize << " " << s << endl; return;
3242 c=(unsigned short) c;
3243 if (x>LCD_WIDTH_PX) return;
3244 int ss=strlen(s);
3245 if (ss==1 && s[0]==0x1e){ // arrow for limit
3246 if (mode==4)
3247 c=bg;
3248 draw_line(x,y-4,x+fontsize/2,y-4,c);
3249 draw_line(x,y-3,x+fontsize/2,y-3,c);
3250 draw_line(x+fontsize/2-4,y,x+fontsize/2,y-4,c);
3251 draw_line(x+fontsize/2-3,y,x+fontsize/2+1,y-4,c);
3252 draw_line(x+fontsize/2-4,y-7,x+fontsize/2,y-3,c);
3253 draw_line(x+fontsize/2-3,y-7,x+fontsize/2+1,y-3,c);
3254 return;
3255 }
3256 if (ss==2 && strcmp(s,"pi")==0){
3257 if (mode==4){
3258 drawRectangle(x,y+2-fontsize,fontsize,fontsize,c);
3259 c=bg;
3260 }
3261 draw_line(x+fontsize/3-1,y+1,x+fontsize/3,y+6-fontsize,c);
3262 draw_line(x+fontsize/3-2,y+1,x+fontsize/3-1,y+6-fontsize,c);
3263 draw_line(x+2*fontsize/3,y+1,x+2*fontsize/3,y+6-fontsize,c);
3264 draw_line(x+2*fontsize/3+1,y+1,x+2*fontsize/3+1,y+6-fontsize,c);
3265 draw_line(x+2,y+6-fontsize,x+fontsize,y+6-fontsize,c);
3266 draw_line(x+2,y+5-fontsize,x+fontsize,y+5-fontsize,c);
3267 return;
3268 }
3269 if (fontsize>=16 && ss==2 && s[0]==char(0xe5) && (s[1]==char(0xea) || s[1]==char(0xeb))) // special handling for increasing and decreasing in tabvar output
3270 fontsize=18;
3271 if (fontsize>=18){
3272 y -= 16;// status area shift
3273 os_draw_string(x,y,mode==4?bg:c,mode==4?c:bg,s);
3274 // PrintMini(&x,&y,(unsigned char *)s,mode,0xffffffff,0,0,c,bg,1,0);
3275 return;
3276 }
3277 y -= 12;
3278 x=os_draw_string_small(x,y,mode==4?bg:c,mode==4?c:bg,s);// PrintMiniMini( &x, &y, (unsigned char *)s, mode,c, 0 );
3279 return;
3280 }
3281
text_width(int fontsize,const char * s)3282 int text_width(int fontsize,const char * s){
3283 #ifdef NSPIRE_NEWLIB
3284 int x=0;
3285 if (fontsize>=18)
3286 x=os_draw_string(0,0,0,1,s,true);
3287 else
3288 x=os_draw_string_small(0,0,0,1,s,true);
3289 return x;
3290 #else
3291 if (fontsize>=18)
3292 return strlen(s)*11;
3293 return strlen(s)*7;
3294 #endif
3295 }
3296
fl_arc(int x,int y,int rx,int ry,int theta1_deg,int theta2_deg,int c=COLOR_BLACK)3297 void fl_arc(int x,int y,int rx,int ry,int theta1_deg,int theta2_deg,int c=COLOR_BLACK){
3298 rx/=2;
3299 ry/=2;
3300 // *logptr(contextptr) << "theta " << theta1_deg << " " << theta2_deg << endl;
3301 if (ry==rx){
3302 if (theta2_deg-theta1_deg==360){
3303 draw_circle(x+rx,y+rx,rx,c);
3304 return;
3305 }
3306 if (theta1_deg==0 && theta2_deg==180){
3307 draw_circle(x+rx,y+rx,rx,c,true,true,false,false);
3308 return;
3309 }
3310 if (theta1_deg==180 && theta2_deg==360){
3311 draw_circle(x+rx,y+rx,rx,c,false,false,true,true);
3312 return;
3313 }
3314 }
3315 // *logptr(contextptr) << "draw_arc" << theta1_deg*M_PI/180. << " " << theta2_deg*M_PI/180. << endl;
3316 draw_arc(x+rx,y+ry,rx,ry,c,theta1_deg*M_PI/180.,theta2_deg*M_PI/180.,context0);
3317 }
3318
fl_pie(int x,int y,int rx,int ry,int theta1_deg,int theta2_deg,int c=COLOR_BLACK,bool segment=false)3319 void fl_pie(int x,int y,int rx,int ry,int theta1_deg,int theta2_deg,int c=COLOR_BLACK,bool segment=false){
3320 //cout << "fl_pie " << theta1_deg << " " << theta2_deg << " " << c << endl;
3321 if (!segment && ry==rx){
3322 if (theta2_deg-theta1_deg>=360){
3323 rx/=2;
3324 draw_filled_circle(x+rx,y+rx,rx,c);
3325 return;
3326 }
3327 if (theta1_deg==-90 && theta2_deg==90){
3328 rx/=2;
3329 draw_filled_circle(x+rx,y+rx,rx,c,false,true);
3330 return;
3331 }
3332 if (theta1_deg==90 && theta2_deg==270){
3333 rx/=2;
3334 draw_filled_circle(x+rx,y+rx,rx,c,true,false);
3335 return;
3336 }
3337 }
3338 // approximation by a filled polygon
3339 // points: (x,y), (x+rx*cos(theta)/2,y+ry*sin(theta)/2) theta=theta1..theta2
3340 while (theta2_deg<theta1_deg)
3341 theta2_deg+=360;
3342 if (theta2_deg-theta1_deg>=360){
3343 theta1_deg=0;
3344 theta2_deg=360;
3345 }
3346 int N0=theta2_deg-theta1_deg+1;
3347 // reduce N if rx or ry is small
3348 double red=double(rx)/LCD_WIDTH_PX*double(ry)/LCD_HEIGHT_PX;
3349 if (red>1) red=1;
3350 if (red<0.1) red=0.1;
3351 int N=red*N0;
3352 if (N<5)
3353 N=N0>5?5:N0;
3354 if (N<2)
3355 N=2;
3356 vector< vector<int> > v(segment?N+1:N+2,vector<int>(2));
3357 x += rx/2;
3358 y += ry/2;
3359 int i=0;
3360 if (!segment){
3361 v[0][0]=x;
3362 v[0][1]=y;
3363 ++i;
3364 }
3365 double theta=theta1_deg*M_PI/180;
3366 double thetastep=(theta2_deg-theta1_deg)*M_PI/(180*(N-1));
3367 for (;i<v.size()-1;++i){
3368 v[i][0]=int(x+rx*std::cos(theta)/2+.5);
3369 v[i][1]=int(y-ry*std::sin(theta)/2+.5); // y is inverted
3370 theta += thetastep;
3371 }
3372 v.back()=v.front();
3373 draw_filled_polygon(v,0,LCD_WIDTH_PX,24,LCD_HEIGHT_PX,c);
3374 }
3375
binary_op(const unary_function_ptr & u)3376 bool binary_op(const unary_function_ptr & u){
3377 const unary_function_ptr binary_op_tab_ptr []={*at_plus,*at_prod,*at_pow,*at_and,*at_ou,*at_xor,*at_different,*at_same,*at_equal,*at_unit,*at_compose,*at_composepow,*at_deuxpoints,*at_tilocal,*at_pointprod,*at_pointdivision,*at_pointpow,*at_division,*at_normalmod,*at_minus,*at_intersect,*at_union,*at_interval,*at_inferieur_egal,*at_inferieur_strict,*at_superieur_egal,*at_superieur_strict,*at_equal2,0};
3378 return equalposcomp(binary_op_tab_ptr,u);
3379 }
3380
Equation_total_size(const gen & g)3381 eqwdata Equation_total_size(const gen & g){
3382 if (g.type==_EQW)
3383 return *g._EQWptr;
3384 if (g.type!=_VECT || g._VECTptr->empty())
3385 return eqwdata(0,0,0,0,attributs(0,0,0),undef);
3386 return Equation_total_size(g._VECTptr->back());
3387 }
3388
3389 // find smallest value of y and height
Equation_y_dy(const gen & g,int & y,int & dy)3390 void Equation_y_dy(const gen & g,int & y,int & dy){
3391 y=0; dy=0;
3392 if (g.type==_EQW){
3393 y=g._EQWptr->y;
3394 dy=g._EQWptr->dy;
3395 }
3396 if (g.type==_VECT){
3397 iterateur it=g._VECTptr->begin(),itend=g._VECTptr->end();
3398 for (;it!=itend;++it){
3399 int Y,dY;
3400 Equation_y_dy(*it,Y,dY);
3401 // Y, Y+dY and y,y+dy
3402 int ymax=giacmax(y+dy,Y+dY);
3403 if (Y<y)
3404 y=Y;
3405 dy=ymax-y;
3406 }
3407 }
3408 }
3409
Equation_translate(gen & g,int deltax,int deltay)3410 void Equation_translate(gen & g,int deltax,int deltay){
3411 if (g.type==_EQW){
3412 g._EQWptr->x += deltax;
3413 g._EQWptr->y += deltay;
3414 g._EQWptr->baseline += deltay;
3415 return ;
3416 }
3417 if (g.type!=_VECT)
3418 setsizeerr();
3419 vecteur & v=*g._VECTptr;
3420 iterateur it=v.begin(),itend=v.end();
3421 for (;it!=itend;++it)
3422 Equation_translate(*it,deltax,deltay);
3423 }
3424
Equation_change_attributs(const gen & g,const attributs & newa)3425 gen Equation_change_attributs(const gen & g,const attributs & newa){
3426 if (g.type==_EQW){
3427 gen res(*g._EQWptr);
3428 res._EQWptr->eqw_attributs = newa;
3429 return res;
3430 }
3431 if (g.type!=_VECT)
3432 return gensizeerr();
3433 vecteur v=*g._VECTptr;
3434 iterateur it=v.begin(),itend=v.end();
3435 for (;it!=itend;++it)
3436 *it=Equation_change_attributs(*it,newa);
3437 return gen(v,g.subtype);
3438 }
3439
Equation_subsizes(const gen & arg,const attributs & a,int windowhsize,GIAC_CONTEXT)3440 vecteur Equation_subsizes(const gen & arg,const attributs & a,int windowhsize,GIAC_CONTEXT){
3441 vecteur v;
3442 if ( (arg.type==_VECT) && ( (arg.subtype==_SEQ__VECT)
3443 // || (!ckmatrix(arg))
3444 ) ){
3445 const_iterateur it=arg._VECTptr->begin(),itend=arg._VECTptr->end();
3446 for (;it!=itend;++it)
3447 v.push_back(Equation_compute_size(*it,a,windowhsize,contextptr));
3448 }
3449 else {
3450 v.push_back(Equation_compute_size(arg,a,windowhsize,contextptr));
3451 }
3452 return v;
3453 }
3454
3455 // vertical merge with same baseline
3456 // for vertical merge of hp,yp at top (like ^) add fontsize to yp
3457 // at bottom (like lower bound of int) substract fontsize from yp
Equation_vertical_adjust(int hp,int yp,int & h,int & y)3458 void Equation_vertical_adjust(int hp,int yp,int & h,int & y){
3459 int yf=min(y,yp);
3460 h=max(y+h,yp+hp)-yf;
3461 y=yf;
3462 }
3463
Equation_compute_symb_size(const gen & g,const attributs & a,int windowhsize,GIAC_CONTEXT)3464 gen Equation_compute_symb_size(const gen & g,const attributs & a,int windowhsize,GIAC_CONTEXT){
3465 if (g.type!=_SYMB)
3466 return Equation_compute_size(g,a,windowhsize,contextptr);
3467 unary_function_ptr & u=g._SYMBptr->sommet;
3468 gen arg=g._SYMBptr->feuille,rootof_value;
3469 if (u==at_makevector){
3470 vecteur v(1,arg);
3471 if (arg.type==_VECT)
3472 v=*arg._VECTptr;
3473 iterateur it=v.begin(),itend=v.end();
3474 for (;it!=itend;++it){
3475 if ( (it->type==_SYMB) && (it->_SYMBptr->sommet==at_makevector) )
3476 *it=_makevector(it->_SYMBptr->feuille,contextptr);
3477 }
3478 return Equation_compute_size(v,a,windowhsize,contextptr);
3479 }
3480 if (u==at_makesuite){
3481 if (arg.type==_VECT)
3482 return Equation_compute_size(gen(*arg._VECTptr,_SEQ__VECT),a,windowhsize,contextptr);
3483 else
3484 return Equation_compute_size(arg,a,windowhsize,contextptr);
3485 }
3486 if (u==at_sqrt)
3487 return Equation_compute_size(symb_pow(arg,plus_one_half),a,windowhsize,contextptr);
3488 if (u==at_division){
3489 if (arg.type!=_VECT || arg._VECTptr->size()!=2)
3490 return Equation_compute_size(arg,a,windowhsize,contextptr);
3491 gen tmp=Tfraction<gen>(arg._VECTptr->front(),arg._VECTptr->back());
3492 return Equation_compute_size(tmp,a,windowhsize,contextptr);
3493 }
3494 if (u==at_prod){
3495 gen n,d;
3496 if (rewrite_prod_inv(arg,n,d)){
3497 if (n.is_symb_of_sommet(at_neg))
3498 return Equation_compute_size(symbolic(at_neg,Tfraction<gen>(-n,d)),a,windowhsize,contextptr);
3499 return Equation_compute_size(Tfraction<gen>(n,d),a,windowhsize,contextptr);
3500 }
3501 }
3502 if (u==at_inv){
3503 if ( (is_integer(arg) && is_positive(-arg,contextptr))
3504 || (arg.is_symb_of_sommet(at_neg)))
3505 return Equation_compute_size(symbolic(at_neg,Tfraction<gen>(plus_one,-arg)),a,windowhsize,contextptr);
3506 return Equation_compute_size(Tfraction<gen>(plus_one,arg),a,windowhsize,contextptr);
3507 }
3508 if (u==at_expr && arg.type==_VECT && arg.subtype==_SEQ__VECT && arg._VECTptr->size()==2 && arg._VECTptr->back().type==_INT_){
3509 gen varg1=Equation_compute_size(arg._VECTptr->front(),a,windowhsize,contextptr);
3510 eqwdata vv(Equation_total_size(varg1));
3511 gen varg2=eqwdata(0,0,0,0,a,arg._VECTptr->back());
3512 vecteur v12(makevecteur(varg1,varg2));
3513 v12.push_back(eqwdata(vv.dx,vv.dy,0,vv.y,a,at_expr,0));
3514 return gen(v12,_SEQ__VECT);
3515 }
3516 int llp=int(text_width(a.fontsize,("(")))-1;
3517 int lrp=llp;
3518 int lc=int(text_width(a.fontsize,(",")));
3519 string us=u.ptr()->s;
3520 int ls=int(text_width(a.fontsize,(us.c_str())));
3521 // if (isalpha(u.ptr()->s[0])) ls += 1;
3522 if (u==at_abs)
3523 ls = 2;
3524 // special cases first int, sigma, /, ^
3525 // and if printed as printsommetasoperator
3526 // otherwise print with usual functional notation
3527 int x=0;
3528 int h=a.fontsize;
3529 int y=0;
3530 #if 1
3531 if ((u==at_integrate) || (u==at_sum) ){ // Int
3532 int s=1;
3533 if (arg.type==_VECT)
3534 s=arg._VECTptr->size();
3535 else
3536 arg=vecteur(1,arg);
3537 // s==1 -> general case
3538 if ( (s==1) || (s==2) ){ // int f(x) dx and sum f(n) n
3539 vecteur v(Equation_subsizes(gen(*arg._VECTptr,_SEQ__VECT),a,windowhsize,contextptr));
3540 eqwdata vv(Equation_total_size(v[0]));
3541 if (s==1){
3542 x=a.fontsize;
3543 Equation_translate(v[0],x,0);
3544 x += int(text_width(a.fontsize,(" dx")));
3545 }
3546 if (s==2){
3547 if (u==at_integrate){
3548 x=a.fontsize;
3549 Equation_translate(v[0],x,0);
3550 x += vv.dx+int(text_width(a.fontsize,(" d")));
3551 Equation_vertical_adjust(vv.dy,vv.y,h,y);
3552 vv=Equation_total_size(v[1]);
3553 Equation_translate(v[1],x,0);
3554 Equation_vertical_adjust(vv.dy,vv.y,h,y);
3555 }
3556 else {
3557 Equation_vertical_adjust(vv.dy,vv.y,h,y);
3558 eqwdata v1=Equation_total_size(v[1]);
3559 x=max((int)a.fontsize,(int)v1.dx)+2*a.fontsize/3; // var name size
3560 Equation_translate(v[1],0,-v1.dy-v1.y);
3561 Equation_vertical_adjust(v1.dy,-v1.dy,h,y);
3562 Equation_translate(v[0],x,0);
3563 x += vv.dx; // add function size
3564 }
3565 }
3566 if (u==at_integrate){
3567 x += vv.dx;
3568 if (h==a.fontsize)
3569 h+=2*a.fontsize/3;
3570 if (y==0){
3571 y=-2*a.fontsize/3;
3572 h+=2*a.fontsize/3;
3573 }
3574 }
3575 v.push_back(eqwdata(x,h,0,y,a,u,0));
3576 return gen(v,_SEQ__VECT);
3577 }
3578 if (s>=3){ // int _a^b f(x) dx
3579 vecteur & intarg=*arg._VECTptr;
3580 gen tmp_l,tmp_u,tmp_f,tmp_x;
3581 attributs aa(a);
3582 if (a.fontsize>=10)
3583 aa.fontsize -= 2;
3584 tmp_f=Equation_compute_size(intarg[0],a,windowhsize,contextptr);
3585 tmp_x=Equation_compute_size(intarg[1],a,windowhsize,contextptr);
3586 tmp_l=Equation_compute_size(intarg[2],aa,windowhsize,contextptr);
3587 if (s==4)
3588 tmp_u=Equation_compute_size(intarg[3],aa,windowhsize,contextptr);
3589 x=a.fontsize+(u==at_integrate?-2:+4);
3590 eqwdata vv(Equation_total_size(tmp_l));
3591 Equation_translate(tmp_l,x,-vv.y-vv.dy);
3592 vv=Equation_total_size(tmp_l);
3593 Equation_vertical_adjust(vv.dy,vv.y,h,y);
3594 int lx = vv.dx;
3595 if (s==4){
3596 vv=Equation_total_size(tmp_u);
3597 Equation_translate(tmp_u,x,a.fontsize-3-vv.y);
3598 vv=Equation_total_size(tmp_u);
3599 Equation_vertical_adjust(vv.dy,vv.y,h,y);
3600 }
3601 x += max(lx,(int)vv.dx);
3602 Equation_translate(tmp_f,x,0);
3603 vv=Equation_total_size(tmp_f);
3604 Equation_vertical_adjust(vv.dy,vv.y,h,y);
3605 if (u==at_integrate){
3606 x += vv.dx+int(text_width(a.fontsize,(" d")));
3607 Equation_translate(tmp_x,x,0);
3608 vv=Equation_total_size(tmp_x);
3609 Equation_vertical_adjust(vv.dy,vv.y,h,y);
3610 x += vv.dx;
3611 }
3612 else {
3613 x += vv.dx;
3614 Equation_vertical_adjust(vv.dy,vv.y,h,y);
3615 vv=Equation_total_size(tmp_x);
3616 x=max(x,(int)vv.dx)+a.fontsize/3;
3617 Equation_translate(tmp_x,0,-vv.dy-vv.y);
3618 //Equation_translate(tmp_l,0,-1);
3619 if (s==4) Equation_translate(tmp_u,-2,0);
3620 Equation_vertical_adjust(vv.dy,-vv.dy,h,y);
3621 }
3622 vecteur res(makevecteur(tmp_f,tmp_x,tmp_l));
3623 if (s==4)
3624 res.push_back(tmp_u);
3625 res.push_back(eqwdata(x,h,0,y,a,u,0));
3626 return gen(res,_SEQ__VECT);
3627 }
3628 }
3629 if (u==at_limit && arg.type==_VECT){ // limit
3630 vecteur limarg=*arg._VECTptr;
3631 int s=limarg.size();
3632 if (s==2 && limarg[1].is_symb_of_sommet(at_equal)){
3633 limarg.push_back(limarg[1]._SYMBptr->feuille[1]);
3634 limarg[1]=limarg[1]._SYMBptr->feuille[0];
3635 ++s;
3636 }
3637 if (s>=3){
3638 gen tmp_l,tmp_f,tmp_x,tmp_dir;
3639 attributs aa(a);
3640 if (a.fontsize>=10)
3641 aa.fontsize -= 2;
3642 tmp_f=Equation_compute_size(limarg[0],a,windowhsize,contextptr);
3643 tmp_x=Equation_compute_size(limarg[1],aa,windowhsize,contextptr);
3644 tmp_l=Equation_compute_size(limarg[2],aa,windowhsize,contextptr);
3645 if (s==4)
3646 tmp_dir=Equation_compute_size(limarg[3],aa,windowhsize,contextptr);
3647 eqwdata vf(Equation_total_size(tmp_f));
3648 eqwdata vx(Equation_total_size(tmp_x));
3649 eqwdata vl(Equation_total_size(tmp_l));
3650 eqwdata vdir(Equation_total_size(tmp_dir));
3651 int sous=max(vx.dy,vl.dy);
3652 if (s==4)
3653 Equation_translate(tmp_f,vx.dx+vl.dx+vdir.dx+a.fontsize+4,0);
3654 else
3655 Equation_translate(tmp_f,vx.dx+vl.dx+a.fontsize+2,0);
3656 Equation_translate(tmp_x,0,-sous-vl.y);
3657 Equation_translate(tmp_l,vx.dx+a.fontsize+2,-sous-vl.y);
3658 if (s==4)
3659 Equation_translate(tmp_dir,vx.dx+vl.dx+a.fontsize+4,-sous-vl.y);
3660 h=vf.dy;
3661 y=vf.y;
3662 vl=Equation_total_size(tmp_l);
3663 Equation_vertical_adjust(vl.dy,vl.y,h,y);
3664 vecteur res(makevecteur(tmp_f,tmp_x,tmp_l));
3665 if (s==4){
3666 res.push_back(tmp_dir);
3667 res.push_back(eqwdata(vf.dx+vx.dx+a.fontsize+4+vl.dx+vdir.dx,h,0,y,a,u,0));
3668 }
3669 else
3670 res.push_back(eqwdata(vf.dx+vx.dx+a.fontsize+2+vl.dx,h,0,y,a,u,0));
3671 return gen(res,_SEQ__VECT);
3672 }
3673 }
3674 #endif
3675 if ( (u==at_of || u==at_at) && arg.type==_VECT && arg._VECTptr->size()==2 ){
3676 // user function, function in 1st arg, arguments in 2nd arg
3677 gen varg1=Equation_compute_size(arg._VECTptr->front(),a,windowhsize,contextptr);
3678 eqwdata vv=Equation_total_size(varg1);
3679 Equation_vertical_adjust(vv.dy,vv.y,h,y);
3680 gen arg2=arg._VECTptr->back();
3681 if (u==at_at && xcas_mode(contextptr)!=0){
3682 if (arg2.type==_VECT)
3683 arg2=gen(addvecteur(*arg2._VECTptr,vecteur(arg2._VECTptr->size(),plus_one)),_SEQ__VECT);
3684 else
3685 arg2=arg2+plus_one;
3686 }
3687 gen varg2=Equation_compute_size(arg2,a,windowhsize,contextptr);
3688 Equation_translate(varg2,vv.dx+llp,0);
3689 vv=Equation_total_size(varg2);
3690 Equation_vertical_adjust(vv.dy,vv.y,h,y);
3691 vecteur res(makevecteur(varg1,varg2));
3692 res.push_back(eqwdata(vv.dx+vv.x+lrp,h,0,y,a,u,0));
3693 return gen(res,_SEQ__VECT);
3694 }
3695 if (u==at_pow){
3696 // first arg not translated
3697 gen varg=Equation_compute_size(arg._VECTptr->front(),a,windowhsize,contextptr);
3698 eqwdata vv=Equation_total_size(varg);
3699 // 1/2 ->sqrt, otherwise as exponent
3700 if (arg._VECTptr->back()==plus_one_half){
3701 Equation_translate(varg,a.fontsize,0);
3702 vecteur res(1,varg);
3703 res.push_back(eqwdata(vv.dx+a.fontsize,vv.dy+4,vv.x,vv.y,a,at_sqrt,0));
3704 return gen(res,_SEQ__VECT);
3705 }
3706 bool needpar=vv.g.type==_FUNC || vv.g.is_symb_of_sommet(at_pow) || need_parenthesis(vv.g);
3707 if (needpar)
3708 x=llp;
3709 Equation_translate(varg,x,0);
3710 Equation_vertical_adjust(vv.dy,vv.y,h,y);
3711 vecteur res(1,varg);
3712 // 2nd arg translated
3713 if (needpar)
3714 x+=vv.dx+lrp;
3715 else
3716 x+=vv.dx+1;
3717 int arg1dy=vv.dy,arg1y=vv.y;
3718 if (a.fontsize>=16){
3719 attributs aa(a);
3720 aa.fontsize -= 2;
3721 varg=Equation_compute_size(arg._VECTptr->back(),aa,windowhsize,contextptr);
3722 }
3723 else
3724 varg=Equation_compute_size(arg._VECTptr->back(),a,windowhsize,contextptr);
3725 vv=Equation_total_size(varg);
3726 Equation_translate(varg,x,arg1y+(3*arg1dy)/4-vv.y);
3727 res.push_back(varg);
3728 vv=Equation_total_size(varg);
3729 Equation_vertical_adjust(vv.dy,vv.y,h,y);
3730 x += vv.dx;
3731 res.push_back(eqwdata(x,h,0,y,a,u,0));
3732 return gen(res,_SEQ__VECT);
3733 }
3734 if (u==at_factorial){
3735 vecteur v;
3736 gen varg=Equation_compute_size(arg,a,windowhsize,contextptr);
3737 eqwdata vv=Equation_total_size(varg);
3738 bool paren=need_parenthesis(vv.g) || vv.g==at_prod || vv.g==at_division || vv.g==at_pow;
3739 if (paren)
3740 x+=llp;
3741 Equation_translate(varg,x,0);
3742 Equation_vertical_adjust(vv.dy,vv.y,h,y);
3743 v.push_back(varg);
3744 x += vv.dx;
3745 if (paren)
3746 x+=lrp;
3747 varg=eqwdata(x+4,h,0,y,a,u,0);
3748 v.push_back(varg);
3749 return gen(v,_SEQ__VECT);
3750 }
3751 if (u==at_sto){ // A:=B, *it -> B
3752 gen varg=Equation_compute_size(arg._VECTptr->back(),a,windowhsize,contextptr);
3753 eqwdata vv=Equation_total_size(varg);
3754 Equation_vertical_adjust(vv.dy,vv.y,h,y);
3755 Equation_translate(varg,x,0);
3756 vecteur v(2);
3757 v[1]=varg;
3758 x+=vv.dx;
3759 x+=ls+3;
3760 // first arg not translated
3761 varg=Equation_compute_size(arg._VECTptr->front(),a,windowhsize,contextptr);
3762 vv=Equation_total_size(varg);
3763 if (need_parenthesis(vv.g))
3764 x+=llp;
3765 Equation_translate(varg,x,0);
3766 Equation_vertical_adjust(vv.dy,vv.y,h,y);
3767 v[0]=varg;
3768 x += vv.dx;
3769 if (need_parenthesis(vv.g))
3770 x+=lrp;
3771 v.push_back(eqwdata(x,h,0,y,a,u,0));
3772 return gen(v,_SEQ__VECT);
3773 }
3774 if (u==at_program && arg._VECTptr->back().type!=_VECT && !arg._VECTptr->back().is_symb_of_sommet(at_local) ){
3775 gen varg=Equation_compute_size(arg._VECTptr->front(),a,windowhsize,contextptr);
3776 eqwdata vv=Equation_total_size(varg);
3777 Equation_vertical_adjust(vv.dy,vv.y,h,y);
3778 Equation_translate(varg,x,0);
3779 vecteur v(2);
3780 v[0]=varg;
3781 x+=vv.dx;
3782 x+=int(text_width(a.fontsize,("->")))+3;
3783 varg=Equation_compute_size(arg._VECTptr->back(),a,windowhsize,contextptr);
3784 vv=Equation_total_size(varg);
3785 Equation_translate(varg,x,0);
3786 Equation_vertical_adjust(vv.dy,vv.y,h,y);
3787 v[1]=varg;
3788 x += vv.dx;
3789 v.push_back(eqwdata(x,h,0,y,a,u,0));
3790 return gen(v,_SEQ__VECT);
3791 }
3792 bool binaryop= (u.ptr()->printsommet==&printsommetasoperator) || binary_op(u);
3793 if ( u!=at_sto && u.ptr()->printsommet!=NULL && !binaryop ){
3794 gen tmp=string2gen(g.print(contextptr),false);
3795 return Equation_compute_size(symbolic(at_expr,makesequence(tmp,xcas_mode(contextptr))),a,windowhsize,contextptr);
3796 }
3797 vecteur v;
3798 if (!binaryop || arg.type!=_VECT)
3799 v=Equation_subsizes(arg,a,windowhsize,contextptr);
3800 else
3801 v=Equation_subsizes(gen(*arg._VECTptr,_SEQ__VECT),a,windowhsize,contextptr);
3802 iterateur it=v.begin(),itend=v.end();
3803 if ( it==itend || (itend-it==1) ){
3804 gen gtmp;
3805 if (it==itend)
3806 gtmp=Equation_compute_size(gen(vecteur(0),_SEQ__VECT),a,windowhsize,contextptr);
3807 else
3808 gtmp=*it;
3809 // unary op, shift arg position horizontally
3810 eqwdata vv=Equation_total_size(gtmp);
3811 bool paren = u!=at_neg || (vv.g!=at_prod && need_parenthesis(vv.g)) ;
3812 x=ls+(paren?llp:0);
3813 gen tmp=gtmp; Equation_translate(tmp,x,0);
3814 x=x+vv.dx+(paren?lrp:0);
3815 Equation_vertical_adjust(vv.dy,vv.y,h,y);
3816 return gen(makevecteur(tmp,eqwdata(x,h,0,y,a,u,0)),_EQW__VECT);
3817 }
3818 if (binaryop){ // op (default with par)
3819 int currenth=h,largeur=0;
3820 iterateur itprec=v.begin();
3821 h=0;
3822 if (u==at_plus){ // op without parenthesis
3823 if (it->type==_VECT && !it->_VECTptr->empty() && it->_VECTptr->back().type==_EQW && it->_VECTptr->back()._EQWptr->g==at_equal)
3824 ;
3825 else {
3826 llp=0;
3827 lrp=0;
3828 }
3829 }
3830 for (;;){
3831 eqwdata vv=Equation_total_size(*it);
3832 if (need_parenthesis(vv.g))
3833 x+=llp;
3834 if (u==at_plus && it!=v.begin() &&
3835 (
3836 (it->type==_VECT && it->_VECTptr->back().type==_EQW && it->_VECTptr->back()._EQWptr->g==at_neg)
3837 ||
3838 ( it->type==_EQW && (is_integer(it->_EQWptr->g) || it->_EQWptr->g.type==_DOUBLE_) && is_strictly_positive(-it->_EQWptr->g,contextptr) )
3839 )
3840 )
3841 x -= ls;
3842 #if 0 //
3843 if (x>windowhsize-vv.dx && x>windowhsize/2 && (itend-it)*vv.dx>windowhsize/2){
3844 largeur=max(x,largeur);
3845 x=0;
3846 if (need_parenthesis(vv.g))
3847 x+=llp;
3848 h+=currenth;
3849 Equation_translate(*it,x,0);
3850 for (iterateur kt=v.begin();kt!=itprec;++kt)
3851 Equation_translate(*kt,0,currenth);
3852 if (y){
3853 for (iterateur kt=itprec;kt!=it;++kt)
3854 Equation_translate(*kt,0,-y);
3855 }
3856 itprec=it;
3857 currenth=vv.dy;
3858 y=vv.y;
3859 }
3860 else
3861 #endif
3862 {
3863 Equation_translate(*it,x,0);
3864 vv=Equation_total_size(*it);
3865 Equation_vertical_adjust(vv.dy,vv.y,currenth,y);
3866 }
3867 x+=vv.dx;
3868 if (need_parenthesis(vv.g))
3869 x+=lrp;
3870 ++it;
3871 if (it==itend){
3872 for (iterateur kt=v.begin();kt!=itprec;++kt)
3873 Equation_translate(*kt,0,currenth+y);
3874 h+=currenth;
3875 v.push_back(eqwdata(max(x,largeur),h,0,y,a,u,0));
3876 //cout << v << endl;
3877 return gen(v,_SEQ__VECT);
3878 }
3879 x += ls+3;
3880 }
3881 }
3882 // normal printing
3883 x=ls+llp;
3884 for (;;){
3885 eqwdata vv=Equation_total_size(*it);
3886 Equation_translate(*it,x,0);
3887 Equation_vertical_adjust(vv.dy,vv.y,h,y);
3888 x+=vv.dx;
3889 ++it;
3890 if (it==itend){
3891 x+=lrp;
3892 v.push_back(eqwdata(x,h,0,y,a,u,0));
3893 return gen(v,_SEQ__VECT);
3894 }
3895 x+=lc;
3896 }
3897 }
3898
3899 // windowhsize is used for g of type HIST__VECT (history) right justify answers
3900 // Returns either a eqwdata type object (terminal) or a vector
3901 // (of subtype _EQW__VECT or _HIST__VECT)
Equation_compute_size(const gen & g,const attributs & a,int windowhsize,GIAC_CONTEXT)3902 gen Equation_compute_size(const gen & g,const attributs & a,int windowhsize,GIAC_CONTEXT){
3903 /*****************
3904 * FRACTIONS *
3905 *****************/
3906 if (g.type==_FRAC){
3907 if (is_integer(g._FRACptr->num) && is_positive(-g._FRACptr->num,contextptr))
3908 return Equation_compute_size(symbolic(at_neg,fraction(-g._FRACptr->num,g._FRACptr->den)),a,windowhsize,contextptr);
3909 gen v1=Equation_compute_size(g._FRACptr->num,a,windowhsize,contextptr);
3910 eqwdata vv1=Equation_total_size(v1);
3911 gen v2=Equation_compute_size(g._FRACptr->den,a,windowhsize,contextptr);
3912 eqwdata vv2=Equation_total_size(v2);
3913 // Center the fraction
3914 int w1=vv1.dx,w2=vv2.dx;
3915 int w=max(w1,w2)+6;
3916 vecteur v(3);
3917 v[0]=v1; Equation_translate(v[0],(w-w1)/2,11-vv1.y);
3918 v[1]=v2; Equation_translate(v[1],(w-w2)/2,5-vv2.dy-vv2.y);
3919 v[2]=eqwdata(w,a.fontsize/2+vv1.dy+vv2.dy+1,0,(a.fontsize<=14?4:3)-vv2.dy,a,at_division,0);
3920 return gen(v,_SEQ__VECT);
3921 }
3922 /***************
3923 * VECTORS *
3924 ***************/
3925 if ( (g.type==_VECT) && !g._VECTptr->empty() ){
3926 vecteur v;
3927 const_iterateur it=g._VECTptr->begin(),itend=g._VECTptr->end();
3928 int x=0,y=0,h=a.fontsize;
3929 /***************
3930 * MATRICE *
3931 ***************/
3932 bool gmat=ckmatrix(g);
3933 vector<int> V; int p=0;
3934 if (!gmat && is_mod_vecteur(*g._VECTptr,V,p) && p!=0){
3935 gen gm=makemodquoted(unmod(g),p);
3936 return Equation_compute_size(gm,a,windowhsize,contextptr);
3937 }
3938 vector< vector<int> > M;
3939 if (gmat && is_mod_matrice(*g._VECTptr,M,p) && p!=0){
3940 gen gm=makemodquoted(unmod(g),p);
3941 return Equation_compute_size(gm,a,windowhsize,contextptr);
3942 }
3943 if (gmat && g.subtype!=_SEQ__VECT && g.subtype!=_SET__VECT && g.subtype!=_POLY1__VECT && g._VECTptr->front().subtype!=_SEQ__VECT){
3944 gen mkvect(at_makevector);
3945 mkvect.subtype=_SEQ__VECT;
3946 gen mkmat(at_makevector);
3947 mkmat.subtype=_MATRIX__VECT;
3948 int nrows,ncols;
3949 mdims(*g._VECTptr,nrows,ncols);
3950 if (ncols){
3951 vecteur all_sizes;
3952 all_sizes.reserve(nrows);
3953 vector<int> row_heights(nrows),row_bases(nrows),col_widths(ncols);
3954 // vertical gluing
3955 for (int i=0;it!=itend;++it,++i){
3956 gen tmpg=*it;
3957 tmpg.subtype=_SEQ__VECT;
3958 vecteur tmp(Equation_subsizes(tmpg,a,max(windowhsize/ncols-a.fontsize,230),contextptr));
3959 int h=a.fontsize,y=0;
3960 const_iterateur jt=tmp.begin(),jtend=tmp.end();
3961 for (int j=0;jt!=jtend;++jt,++j){
3962 eqwdata w(Equation_total_size(*jt));
3963 Equation_vertical_adjust(w.dy,w.y,h,y);
3964 col_widths[j]=max(col_widths[j],(int)w.dx);
3965 }
3966 if (i)
3967 row_heights[i]=row_heights[i-1]+h+a.fontsize/2;
3968 else
3969 row_heights[i]=h;
3970 row_bases[i]=y;
3971 all_sizes.push_back(tmp);
3972 }
3973 // accumulate col widths
3974 col_widths.front() +=(3*a.fontsize)/2;
3975 vector<int>::iterator iit=col_widths.begin()+1,iitend=col_widths.end();
3976 for (;iit!=iitend;++iit)
3977 *iit += *(iit-1)+a.fontsize;
3978 // translate each cell
3979 it=all_sizes.begin();
3980 itend=all_sizes.end();
3981 int h,y,prev_h=0;
3982 for (int i=0;it!=itend;++it,++i){
3983 h=row_heights[i];
3984 y=row_bases[i];
3985 iterateur jt=it->_VECTptr->begin(),jtend=it->_VECTptr->end();
3986 for (int j=0;jt!=jtend;++jt,++j){
3987 eqwdata w(Equation_total_size(*jt));
3988 if (j)
3989 Equation_translate(*jt,col_widths[j-1]-w.x,-h-y);
3990 else
3991 Equation_translate(*jt,-w.x+a.fontsize/2,-h-y);
3992 }
3993 it->_VECTptr->push_back(eqwdata(col_widths.back(),h-prev_h,0,-h,a,mkvect,0));
3994 prev_h=h;
3995 }
3996 all_sizes.push_back(eqwdata(col_widths.back(),row_heights.back(),0,-row_heights.back(),a,mkmat,-row_heights.back()/2));
3997 gen all_sizesg=all_sizes; Equation_translate(all_sizesg,0,row_heights.back()/2); return all_sizesg;
3998 }
3999 } // end matrices
4000 /*************************
4001 * SEQUENCES/VECTORS *
4002 *************************/
4003 // horizontal gluing
4004 if (g.subtype!=_PRINT__VECT) x += a.fontsize/2;
4005 int ncols=itend-it;
4006 //ncols=min(ncols,5);
4007 for (;it!=itend;++it){
4008 gen cur_size=Equation_compute_size(*it,a,
4009 max(windowhsize/ncols-a.fontsize,
4010 #ifdef IPAQ
4011 200
4012 #else
4013 480
4014 #endif
4015 ),contextptr);
4016 eqwdata tmp=Equation_total_size(cur_size);
4017 Equation_translate(cur_size,x-tmp.x,0); v.push_back(cur_size);
4018 x=x+tmp.dx+((g.subtype==_PRINT__VECT)?2:a.fontsize);
4019 Equation_vertical_adjust(tmp.dy,tmp.y,h,y);
4020 }
4021 gen mkvect(at_makevector);
4022 if (g.subtype==_SEQ__VECT)
4023 mkvect=at_makesuite;
4024 else
4025 mkvect.subtype=g.subtype;
4026 v.push_back(eqwdata(x,h,0,y,a,mkvect,0));
4027 return gen(v,_EQW__VECT);
4028 } // end sequences
4029 if (g.type==_MOD){
4030 int x=0;
4031 int h=a.fontsize;
4032 int y=0;
4033 bool py=python_compat(contextptr);
4034 int modsize=int(text_width(a.fontsize,(py?" mod":"%")))+4;
4035 bool paren=is_positive(-*g._MODptr,contextptr);
4036 int llp=int(text_width(a.fontsize,("(")));
4037 int lrp=int(text_width(a.fontsize,(")")));
4038 gen varg1=Equation_compute_size(*g._MODptr,a,windowhsize,contextptr);
4039 if (paren) Equation_translate(varg1,llp,0);
4040 eqwdata vv=Equation_total_size(varg1);
4041 Equation_vertical_adjust(vv.dy,vv.y,h,y);
4042 gen arg2=*(g._MODptr+1);
4043 gen varg2=Equation_compute_size(arg2,a,windowhsize,contextptr);
4044 if (paren)
4045 Equation_translate(varg2,vv.dx+modsize+lrp,0);
4046 else
4047 Equation_translate(varg2,vv.dx+modsize,0);
4048 vv=Equation_total_size(varg2);
4049 Equation_vertical_adjust(vv.dy,vv.y,h,y);
4050 vecteur res(makevecteur(varg1,varg2));
4051 res.push_back(eqwdata(vv.dx+vv.x,h,0,y,a,at_normalmod,0));
4052 return gen(res,_SEQ__VECT);
4053 }
4054 if (g.type!=_SYMB){
4055 string s=g.type==_STRNG?*g._STRNGptr:g.print(contextptr);
4056 //if (g==cst_pi) s=char(129);
4057 if (s.size()>2000)
4058 s=s.substr(0,2000)+"...";
4059 int i=int(text_width(a.fontsize,(s.c_str())));
4060 gen tmp=eqwdata(i,a.fontsize,0,0,a,g);
4061 return tmp;
4062 }
4063 /**********************
4064 * SYMBOLIC HANDLING *
4065 **********************/
4066 return Equation_compute_symb_size(g,a,windowhsize,contextptr);
4067 // return Equation_compute_symb_size(aplatir_fois_plus(g),a,windowhsize,contextptr);
4068 // aplatir_fois_plus is a problem for Equation_replace_selection
4069 // because it will modify the structure of the data
4070 }
4071
Equation_draw(const eqwdata & e,int x,int y,int rightx,int lowery,Equation * eq,GIAC_CONTEXT)4072 void Equation_draw(const eqwdata & e,int x,int y,int rightx,int lowery,Equation * eq,GIAC_CONTEXT){
4073 if ( (e.dx+e.x<x) || (e.x>rightx) || (e.y>y) || e.y+e.dy<lowery)
4074 ; // return; // nothing to draw, out of window
4075 gen gg=e.g;
4076 int fontsize=e.eqw_attributs.fontsize;
4077 int text_color=COLOR_BLACK;
4078 int background=COLOR_WHITE;
4079 string s=gg.type==_STRNG?*gg._STRNGptr:gg.print(contextptr);
4080 if (gg.type==_IDNT && !s.empty() && s[0]=='_')
4081 s=s.substr(1,s.size()-1);
4082 // if (gg==cst_pi){ s="p"; s[0]=(unsigned char)129; }
4083 if (s.size()>2000)
4084 s=s.substr(0,2000)+"...";
4085 // cerr << s.size() << endl;
4086 text_print(fontsize,s.c_str(),eq->x()+e.x-x,eq->y()+y-e.y,text_color,background,e.selected?4:0);
4087 return;
4088 }
4089
check_fl_rectf(int x,int y,int w,int h,int imin,int jmin,int di,int dj,int delta_i,int delta_j,int c)4090 inline void check_fl_rectf(int x,int y,int w,int h,int imin,int jmin,int di,int dj,int delta_i,int delta_j,int c){
4091 drawRectangle(x+delta_i,y+delta_j,w,h,c);
4092 //fl_rectf(x+delta_i,y+delta_j,w,h,c);
4093 }
4094
Equation_draw(const gen & g,int x,int y,int rightx,int lowery,Equation * equat,GIAC_CONTEXT)4095 void Equation_draw(const gen & g,int x,int y,int rightx,int lowery,Equation * equat,GIAC_CONTEXT){
4096 int eqx=equat->x(),eqy=equat->y();
4097 if (g.type==_EQW){ // terminal
4098 eqwdata & e=*g._EQWptr;
4099 Equation_draw(e,x,y,rightx,lowery,equat,contextptr);
4100 }
4101 if (g.type!=_VECT)
4102 return;
4103 vecteur & v=*g._VECTptr;
4104 if (v.empty())
4105 return;
4106 gen tmp=v.back();
4107 if (tmp.type!=_EQW){
4108 cout << "EQW error:" << v << endl;
4109 return;
4110 }
4111 eqwdata & w=*tmp._EQWptr;
4112 if ( (w.dx+w.x-x<0) || (w.x>rightx) || (w.y>y) || (w.y+w.dy<lowery) )
4113 ; // return; // nothing to draw, out of window
4114 /*******************
4115 * draw the vector *
4116 *******************/
4117 // v is the vector, w the master operator eqwdata
4118 gen oper=w.g;
4119 bool selected=w.selected ;
4120 int fontsize=w.eqw_attributs.fontsize;
4121 int background=w.eqw_attributs.background;
4122 int text_color=w.eqw_attributs.text_color;
4123 int mode=selected?4:0;
4124 int draw_line_color=selected?background:text_color;
4125 int x0=w.x;
4126 int y0=w.y; // lower coordinate of the master vector
4127 int y1=y0+w.dy; // upper coordinate of the master vector
4128 if (selected)
4129 drawRectangle(eqx+w.x-x,eqy+y-w.y-w.dy+1,w.dx,w.dy+1,text_color);
4130 // draw arguments of v
4131 const_iterateur it=v.begin(),itend=v.end()-1;
4132 if (oper==at_expr && v.size()==3){
4133 Equation_draw(*it,x,y,rightx,lowery,equat,contextptr);
4134 return;
4135 }
4136 for (;it!=itend;++it)
4137 Equation_draw(*it,x,y,rightx,lowery,equat,contextptr);
4138 if (oper==at_multistring)
4139 return;
4140 string s;
4141 if (oper.type==_FUNC){
4142 // catch here special cases user function, vect/matr, ^, int, sqrt, etc.
4143 unary_function_ptr & u=*oper._FUNCptr;
4144 if (u==at_at){ // draw brackets around 2nd arg
4145 gen arg2=v[1]; // 2nd arg of at_of, i.e. what's inside the parenth.
4146 eqwdata varg2=Equation_total_size(arg2);
4147 x0=varg2.x;
4148 y0=varg2.y;
4149 y1=y0+varg2.dy;
4150 fontsize=varg2.eqw_attributs.fontsize;
4151 if (x0<rightx)
4152 text_print(fontsize,"[",eqx+x0-x-int(text_width(fontsize,("["))),eqy+y-varg2.baseline,text_color,background,mode);
4153 x0 += varg2.dx ;
4154 if (x0<rightx)
4155 text_print(fontsize,"]",eqx+x0-x,eqy+y-varg2.baseline,text_color,background,mode);
4156 return;
4157 }
4158 if (u==at_of){ // do we need to draw some parenthesis?
4159 gen arg2=v[1]; // 2nd arg of at_of, i.e. what's inside the parenth.
4160 if (arg2.type!=_VECT || arg2._VECTptr->back().type !=_EQW || arg2._VECTptr->back()._EQWptr->g!=at_makesuite){ // Yes (if not _EQW it's a sequence with parent)
4161 eqwdata varg2=Equation_total_size(arg2);
4162 x0=varg2.x;
4163 y0=varg2.y;
4164 y1=y0+varg2.dy;
4165 fontsize=varg2.eqw_attributs.fontsize;
4166 int pfontsize=max(fontsize,(fontsize+(varg2.baseline-varg2.y))/2);
4167 if (x0<rightx)
4168 text_print(pfontsize,"(",eqx+x0-x-int(text_width(fontsize,("("))),eqy+y-varg2.baseline,text_color,background,mode);
4169 x0 += varg2.dx ;
4170 if (x0<rightx)
4171 text_print(pfontsize,")",eqx+x0-x,eqy+y-varg2.baseline,text_color,background,mode);
4172 }
4173 return;
4174 }
4175 if (u==at_makesuite){
4176 bool paren=v.size()!=2; // Sequences with 1 arg don't show parenthesis
4177 int pfontsize=max(fontsize,(fontsize+(w.baseline-w.y))/2);
4178 if (paren && x0<rightx)
4179 text_print(pfontsize,"(",eqx+x0-x-int(text_width(fontsize,("(")))/2,eqy+y-w.baseline,text_color,background,mode);
4180 x0 += w.dx;
4181 if (paren && x0<rightx)
4182 text_print(pfontsize,")",eqx+x0-x-int(text_width(fontsize,("(")))/2,eqy+y-w.baseline,text_color,background,mode);
4183 // print commas between args
4184 it=v.begin(),itend=v.end()-2;
4185 for (;it!=itend;++it){
4186 eqwdata varg2=Equation_total_size(*it);
4187 fontsize=varg2.eqw_attributs.fontsize;
4188 if (varg2.x+varg2.dx<rightx)
4189 text_print(fontsize,",",eqx+varg2.x+varg2.dx-x+1,eqy+y-varg2.baseline,text_color,background,mode);
4190 }
4191 return;
4192 }
4193 if (u==at_makevector){ // draw [] delimiters for vector/matrices
4194 if (oper.subtype!=_SEQ__VECT && oper.subtype!=_PRINT__VECT){
4195 int decal=1;
4196 switch (oper.subtype){
4197 case _MATRIX__VECT: decal=2; break;
4198 case _SET__VECT: decal=4; break;
4199 case _POLY1__VECT: decal=6; break;
4200 }
4201 if (eqx+x0-x+1>=0){
4202 draw_line(eqx+x0-x+1,eqy+y-y0+1,eqx+x0-x+1,eqy+y-y1+1,draw_line_color);
4203 draw_line(eqx+x0-x+decal,eqy+y-y0+1,eqx+x0-x+decal,eqy+y-y1+1,draw_line_color);
4204 draw_line(eqx+x0-x+1,eqy+y-y0+1,eqx+x0-x+fontsize/4,eqy+y-y0+1,draw_line_color);
4205 draw_line(eqx+x0-x+1,eqy+y-y1+1,eqx+x0-x+fontsize/4,eqy+y-y1+1,draw_line_color);
4206 }
4207 x0 += w.dx ;
4208 if (eqx+x0-x-1<LCD_WIDTH_PX){
4209 draw_line(eqx+x0-x-1,eqy+y-y0+1,eqx+x0-x-1,eqy+y-y1+1,draw_line_color);
4210 draw_line(eqx+x0-x-decal,eqy+y-y0+1,eqx+x0-x-decal,eqy+y-y1+1,draw_line_color);
4211 draw_line(eqx+x0-x-1,eqy+y-y0+1,eqx+x0-x-fontsize/4,eqy+y-y0+1,draw_line_color);
4212 draw_line(eqx+x0-x-1,eqy+y-y1+1,eqx+x0-x-fontsize/4,eqy+y-y1+1,draw_line_color);
4213 }
4214 } // end if oper.subtype!=SEQ__VECT
4215 if (oper.subtype!=_MATRIX__VECT && oper.subtype!=_PRINT__VECT){
4216 // print commas between args
4217 it=v.begin(),itend=v.end()-2;
4218 for (;it!=itend;++it){
4219 eqwdata varg2=Equation_total_size(*it);
4220 fontsize=varg2.eqw_attributs.fontsize;
4221 if (varg2.x+varg2.dx<rightx)
4222 text_print(fontsize,",",eqx+varg2.x+varg2.dx-x+1,eqy+y-varg2.baseline,text_color,background,mode);
4223 }
4224 }
4225 return;
4226 }
4227 int lpsize=int(text_width(fontsize,("(")));
4228 int rpsize=int(text_width(fontsize,(")")));
4229 eqwdata tmp=Equation_total_size(v.front()); // tmp= 1st arg eqwdata
4230 if (u==at_sto)
4231 tmp=Equation_total_size(v[1]);
4232 x0=w.x-x;
4233 y0=y-w.baseline;
4234 if (u==at_pow){
4235 if (!need_parenthesis(tmp.g)&& tmp.g!=at_pow && tmp.g!=at_prod && tmp.g!=at_division)
4236 return;
4237 if (tmp.g==at_pow){
4238 fontsize=tmp.eqw_attributs.fontsize+2;
4239 }
4240 if (tmp.x-lpsize<rightx)
4241 text_print(fontsize,"(",eqx+tmp.x-x-lpsize,eqy+y-tmp.baseline,text_color,background,mode);
4242 if (tmp.x+tmp.dx<rightx)
4243 text_print(fontsize,")",eqx+tmp.x+tmp.dx-x,eqy+y-tmp.baseline,text_color,background,mode);
4244 return;
4245 }
4246 if (u==at_program){
4247 if (tmp.x+tmp.dx<rightx)
4248 text_print(fontsize,"->",eqx+tmp.x+tmp.dx-x,eqy+y-tmp.baseline,text_color,background,mode);
4249 return;
4250 }
4251 #if 1
4252 if (u==at_sum){
4253 if (x0<rightx){
4254 draw_line(eqx+x0,eqy+y0,eqx+x0+(2*fontsize)/3,eqy+y0,draw_line_color);
4255 draw_line(eqx+x0,eqy+y0-fontsize,eqx+x0+(2*fontsize)/3,eqy+y0-fontsize,draw_line_color);
4256 draw_line(eqx+x0,eqy+y0,eqx+x0+fontsize/2,eqy+y0-fontsize/2,draw_line_color);
4257 draw_line(eqx+x0+fontsize/2,eqy+y0-fontsize/2,eqx+x0,eqy+y0-fontsize,draw_line_color);
4258 if (v.size()>2){ // draw the =
4259 eqwdata ptmp=Equation_total_size(v[1]);
4260 if (ptmp.x+ptmp.dx<rightx)
4261 text_print(fontsize,"=",eqx+ptmp.x+ptmp.dx-x-2,eqy+y-ptmp.baseline,text_color,background,mode);
4262 }
4263 }
4264 return;
4265 }
4266 #endif
4267 if (u==at_abs){
4268 y0 =1+y-w.y;
4269 int h=w.dy;
4270 if (x0<rightx){
4271 draw_line(eqx+x0+2,eqy+y0-1,eqx+x0+2,eqy+y0-h+3,draw_line_color);
4272 draw_line(eqx+x0+1,eqy+y0-1,eqx+x0+1,eqy+y0-h+3,draw_line_color);
4273 draw_line(eqx+x0+w.dx-1,eqy+y0-1,eqx+x0+w.dx-1,eqy+y0-h+3,draw_line_color);
4274 draw_line(eqx+x0+w.dx,eqy+y0-1,eqx+x0+w.dx,eqy+y0-h+3,draw_line_color);
4275 }
4276 return;
4277 }
4278 if (u==at_sqrt){
4279 y0 =1+y-w.y;
4280 int h=w.dy;
4281 if (x0<rightx){
4282 draw_line(eqx+x0+2,eqy+y0-h/2,eqx+x0+fontsize/2,eqy+y0-1,draw_line_color);
4283 draw_line(eqx+x0+fontsize/2,eqy+y0-1,eqx+x0+fontsize,eqy+y0-h+3,draw_line_color);
4284 draw_line(eqx+x0+fontsize,eqy+y0-h+3,eqx+x0+w.dx-1,eqy+y0-h+3,draw_line_color);
4285 ++y0;
4286 draw_line(eqx+x0+2,eqy+y0-h/2,eqx+x0+fontsize/2,eqy+y0-1,draw_line_color);
4287 draw_line(eqx+x0+fontsize/2,eqy+y0-1,eqx+x0+fontsize,eqy+y0-h+3,draw_line_color);
4288 draw_line(eqx+x0+fontsize,eqy+y0-h+3,eqx+x0+w.dx-1,eqy+y0-h+3,draw_line_color);
4289 }
4290 return;
4291 }
4292 if (u==at_factorial){
4293 text_print(fontsize,"!",eqx+w.x+w.dx-4-x,eqy+y-w.baseline,text_color,background,mode);
4294 if (!need_parenthesis(tmp.g)
4295 && tmp.g!=at_pow && tmp.g!=at_prod && tmp.g!=at_division
4296 )
4297 return;
4298 if (tmp.x-lpsize<rightx)
4299 text_print(fontsize,"(",eqx+tmp.x-x-lpsize,eqy+y-tmp.baseline,text_color,background,mode);
4300 if (tmp.x+tmp.dx<rightx)
4301 text_print(fontsize,")",eqx+tmp.x+tmp.dx-x,eqy+y-tmp.baseline,text_color,background,mode);
4302 return;
4303 }
4304 #if 1
4305 if (u==at_integrate){
4306 x0+=2;
4307 y0+=fontsize/2;
4308 if (x0<rightx){
4309 fl_arc(eqx+x0,eqy+y0,fontsize/3,fontsize/3,180,360,draw_line_color);
4310 draw_line(eqx+x0+fontsize/3,eqy+y0,eqx+x0+fontsize/3,eqy+y0-2*fontsize+4,draw_line_color);
4311 fl_arc(eqx+x0+fontsize/3,eqy+y0-2*fontsize+3,fontsize/3,fontsize/3,0,180,draw_line_color);
4312 }
4313 if (v.size()!=2){ // if arg has size > 1 draw the d
4314 eqwdata ptmp=Equation_total_size(v[1]);
4315 if (ptmp.x<rightx)
4316 text_print(fontsize," d",eqx+ptmp.x-x-int(text_width(fontsize,(" d"))),eqy+y-ptmp.baseline,text_color,background,mode);
4317 }
4318 else {
4319 eqwdata ptmp=Equation_total_size(v[0]);
4320 if (ptmp.x+ptmp.dx<rightx)
4321 text_print(fontsize," dx",eqx+ptmp.x+ptmp.dx-x,eqy+y-ptmp.baseline,text_color,background,mode);
4322 }
4323 return;
4324 }
4325 #endif
4326 if (u==at_division){
4327 if (x0<rightx){
4328 int yy=eqy+y0-8;
4329 draw_line(eqx+x0+2,yy,eqx+x0+w.dx-2,yy,draw_line_color);
4330 ++yy;
4331 draw_line(eqx+x0+2,yy,eqx+x0+w.dx-2,yy,draw_line_color);
4332 }
4333 return;
4334 }
4335 #if 1
4336 if (u==at_limit && v.size()>=4){
4337 if (x0<rightx)
4338 text_print(fontsize,"lim",eqx+w.x-x,eqy+y-w.baseline,text_color,background,mode);
4339 gen arg2=v[1]; // 2nd arg of limit, i.e. the variable
4340 if (arg2.type==_EQW){
4341 eqwdata & varg2=*arg2._EQWptr;
4342 if (varg2.x+varg2.dx+2<rightx)
4343 text_print(fontsize,"\x1e",eqx+varg2.x+varg2.dx+2-x,eqy+y-varg2.y,text_color,background,mode);
4344 }
4345 if (v.size()>=5){
4346 arg2=v[2]; // 3rd arg of lim, the point, draw a comma after if dir.
4347 if (arg2.type==_EQW){
4348 eqwdata & varg2=*arg2._EQWptr;
4349 if (varg2.x+varg2.dx<rightx)
4350 text_print(fontsize,",",eqx+varg2.x+varg2.dx-x,eqy+y-varg2.baseline,text_color,background,mode);
4351 }
4352 }
4353 return;
4354 } // limit
4355 #endif
4356 bool parenthesis=true;
4357 string opstring(",");
4358 if (u.ptr()->printsommet==&printsommetasoperator || binary_op(u) ){
4359 if (u==at_normalmod && python_compat(contextptr))
4360 opstring=" mod";
4361 else
4362 opstring=u.ptr()->s;
4363 }
4364 else {
4365 if (u==at_sto)
4366 opstring=":=";
4367 parenthesis=false;
4368 }
4369 // int yy=y0; // y0 is the lower coordinate of the whole eqwdata
4370 // int opsize=int(text_width(fontsize,(opstring.c_str())))+3;
4371 it=v.begin();
4372 itend=v.end()-1;
4373 // Reminder: here tmp is the 1st arg eqwdata, w the whole eqwdata
4374 if ( (itend-it==1) && ( (u==at_neg)
4375 || (u==at_plus) // uncommented for +infinity
4376 ) ){
4377 if ( (u==at_neg &&need_parenthesis(tmp.g) && tmp.g!=at_prod)){
4378 if (tmp.x-lpsize<rightx)
4379 text_print(fontsize,"(",eqx+tmp.x-x-lpsize,eqy+y-tmp.baseline,text_color,background,mode);
4380 if (tmp.x+tmp.dx<rightx)
4381 text_print(fontsize,")",eqx+tmp.x-x+tmp.dx,eqy+y-tmp.baseline,text_color,background,mode);
4382 }
4383 if (w.x<rightx){
4384 text_print(fontsize,u.ptr()->s,eqx+w.x-x,eqy+y-w.baseline,text_color,background,mode);
4385 }
4386 return;
4387 }
4388 // write first open parenthesis
4389 if (u==at_plus && tmp.g!=at_equal)
4390 parenthesis=false;
4391 else {
4392 if (parenthesis && need_parenthesis(tmp.g)){
4393 if (w.x<rightx){
4394 int pfontsize=max(fontsize,(fontsize+(tmp.baseline-tmp.y))/2);
4395 text_print(pfontsize,"(",eqx+w.x-x,eqy+y-tmp.baseline,text_color,background,mode);
4396 }
4397 }
4398 }
4399 for (;;){
4400 // write close parenthesis at end
4401 int xx=tmp.dx+tmp.x-x;
4402 if (parenthesis && need_parenthesis(tmp.g)){
4403 if (xx<rightx){
4404 int pfontsize=min(max(fontsize,(fontsize+(tmp.baseline-tmp.y))/2),fontsize*2);
4405 int deltapary=(2*(pfontsize-fontsize))/3;
4406 text_print(pfontsize,")",eqx+xx,eqy+y-tmp.baseline+deltapary,text_color,background,mode);
4407 }
4408 xx +=rpsize;
4409 }
4410 ++it;
4411 if (it==itend){
4412 if (u.ptr()->printsommet==&printsommetasoperator || u==at_sto || binary_op(u))
4413 return;
4414 else
4415 break;
4416 }
4417 // write operator
4418 if (u==at_prod){
4419 // text_print(fontsize,".",eqx+xx+3,eqy+y-tmp.baseline-fontsize/3);
4420 text_print(fontsize,opstring.c_str(),eqx+xx+1,eqy+y-tmp.baseline,text_color,background,mode);
4421 }
4422 else {
4423 gen tmpgen;
4424 if (u==at_plus && (
4425 (it->type==_VECT && it->_VECTptr->back().type==_EQW && it->_VECTptr->back()._EQWptr->g==at_neg)
4426 ||
4427 ( it->type==_EQW && (is_integer(it->_EQWptr->g) || it->_EQWptr->g.type==_DOUBLE_) && is_strictly_positive(-it->_EQWptr->g,contextptr) )
4428 )
4429 )
4430 ;
4431 else {
4432 if (xx+1<rightx)
4433 // fl_draw(opstring.c_str(),xx+1,y-tmp.y-tmp.dy/2+fontsize/2);
4434 text_print(fontsize,opstring.c_str(),eqx+xx+1,eqy+y-tmp.baseline,text_color,background,mode);
4435 }
4436 }
4437 // write right parent, update tmp
4438 tmp=Equation_total_size(*it);
4439 if (parenthesis && (need_parenthesis(tmp.g)) ){
4440 if (tmp.x-lpsize<rightx){
4441 int pfontsize=min(max(fontsize,(fontsize+(tmp.baseline-tmp.y))/2),fontsize*2);
4442 int deltapary=(2*(pfontsize-fontsize))/3;
4443 text_print(pfontsize,"(",eqx+tmp.x-pfontsize*lpsize/fontsize-x,eqy+y-tmp.baseline+deltapary,text_color,background,mode);
4444 }
4445 }
4446 } // end for (;;)
4447 if (w.x<rightx){
4448 s = u.ptr()->s;
4449 s += '(';
4450 text_print(fontsize,s.c_str(),eqx+w.x-x,eqy+y-w.baseline,text_color,background,mode);
4451 }
4452 if (w.x+w.dx-rpsize<rightx)
4453 text_print(fontsize,")",eqx+w.x+w.dx-x-rpsize+2,eqy+y-w.baseline,text_color,background,mode);
4454 return;
4455 }
4456 s=oper.print(contextptr);
4457 if (w.x<rightx){
4458 text_print(fontsize,s.c_str(),eqx+w.x-x,eqy+y-w.baseline,text_color,background,mode);
4459 }
4460 }
4461
Equation(int x_,int y_,const gen & g,const giac::context * cptr)4462 Equation::Equation(int x_, int y_, const gen & g,const giac::context * cptr){
4463 _x=x_;
4464 _y=y_;
4465 attr=attributs(18,COLOR_WHITE,COLOR_BLACK);
4466 contextptr=cptr;
4467 if (taille(g,max_prettyprint_equation)<max_prettyprint_equation)
4468 data=Equation_compute_size(g,attr,LCD_WIDTH_PX,contextptr);
4469 else
4470 data=Equation_compute_size(string2gen("Object_too_large",false),attr,LCD_WIDTH_PX,contextptr);
4471 undodata=Equation_copy(data);
4472 }
4473
replace_selection(Equation & eq,const gen & tmp,gen * gsel,const vector<int> * gotoptr,GIAC_CONTEXT)4474 void replace_selection(Equation & eq,const gen & tmp,gen * gsel,const vector<int> * gotoptr,GIAC_CONTEXT){
4475 int xleft,ytop,xright,ybottom,gselpos; gen *gselparent;
4476 vector<int> goto_sel;
4477 eq.undodata=Equation_copy(eq.data);
4478 if (gotoptr==0){
4479 if (xcas::Equation_adjust_xy(eq.data,xleft,ytop,xright,ybottom,gsel,gselparent,gselpos,&goto_sel) && gsel)
4480 gotoptr=&goto_sel;
4481 else
4482 return;
4483 }
4484 *gsel=xcas::Equation_compute_size(tmp,eq.attr,LCD_WIDTH_PX,contextptr);
4485 gen value;
4486 xcas::do_select(eq.data,true,value);
4487 if (value.type==_EQW)
4488 eq.data=xcas::Equation_compute_size(value._EQWptr->g,eq.attr,LCD_WIDTH_PX,contextptr);
4489 //cout << "new value " << value << " " << eq.data << " " << *gotoptr << endl;
4490 xcas::Equation_select(eq.data,false);
4491 gen * gptr=&eq.data;
4492 for (int i=gotoptr->size()-1;i>=0;--i){
4493 int pos=(*gotoptr)[i];
4494 if (gptr->type==_VECT &&gptr->_VECTptr->size()>pos)
4495 gptr=&(*gptr->_VECTptr)[pos];
4496 }
4497 xcas::Equation_select(*gptr,true);
4498 //cout << "new sel " << *gptr << endl;
4499 }
4500
display(Equation & eq,int x,int y,GIAC_CONTEXT)4501 void display(Equation & eq,int x,int y,GIAC_CONTEXT){
4502 // Equation_draw(eq.data,x,y,LCD_WIDTH_PX,0,&eq,contextptr);
4503 int xleft,ytop,xright,ybottom,gselpos; gen * gsel,*gselparent;
4504 eqwdata eqdata=Equation_total_size(eq.data);
4505 if ( (eqdata.dx>LCD_WIDTH_PX || eqdata.dy>LCD_HEIGHT_PX-STATUS_AREA_PX) && Equation_adjust_xy(eq.data,xleft,ytop,xright,ybottom,gsel,gselparent,gselpos)){
4506 if (x<xleft){
4507 if (x+LCD_WIDTH_PX<xright)
4508 x=giacmin(xleft,xright-LCD_WIDTH_PX);
4509 }
4510 if (x>=xleft && x+LCD_WIDTH_PX>=xright){
4511 if (xright-x<LCD_WIDTH_PX)
4512 x=giacmax(xright-LCD_WIDTH_PX,0);
4513 }
4514 #if 0
4515 cout << "avant " << y << " " << ytop << " " << ybottom << endl;
4516 if (y<ytop){
4517 if (y+LCD_HEIGHT_PX<ybottom)
4518 y=giacmin(ytop,ybottom-LCD_HEIGHT_PX);
4519 }
4520 if (y>=ytop && y+LCD_HEIGHT_PX>=ybottom){
4521 if (ybottom-y<LCD_HEIGHT_PX)
4522 y=giacmax(ybottom-LCD_HEIGHT_PX,0);
4523 }
4524 cout << "apres " << y << " " << ytop << " " << ybottom << endl;
4525 #endif
4526 }
4527 int save_ymin_clip=clip_ymin;
4528 clip_ymin=STATUS_AREA_PX;
4529 Equation_draw(eq.data,x,y,RAND_MAX,0,&eq,contextptr);
4530 clip_ymin=save_ymin_clip;
4531 }
4532
4533 /* ******************* *
4534 * GRAPH *
4535 * ******************* *
4536 */
4537 #if 1
4538
find_tick(double dx)4539 double find_tick(double dx){
4540 double d=std::pow(10.0,std::floor(std::log10(absdouble(dx))));
4541 if (dx<2*d)
4542 d=d/5;
4543 else {
4544 if (dx<5*d)
4545 d=d/2;
4546 }
4547 return d;
4548 }
4549
Graph2d(const giac::gen & g_,const giac::context * cptr)4550 Graph2d::Graph2d(const giac::gen & g_,const giac::context * cptr):window_xmin(gnuplot_xmin),window_xmax(gnuplot_xmax),window_ymin(gnuplot_ymin),window_ymax(gnuplot_ymax),g(g_),display_mode(0x45),show_axes(1),show_names(1),labelsize(16),contextptr(cptr) {
4551 update();
4552 autoscale();
4553 }
4554
zoomx(double d,bool round)4555 void Graph2d::zoomx(double d,bool round){
4556 double x_center=(window_xmin+window_xmax)/2;
4557 double dx=(window_xmax-window_xmin);
4558 if (dx==0)
4559 dx=gnuplot_xmax-gnuplot_xmin;
4560 dx *= d/2;
4561 x_tick = find_tick(dx);
4562 window_xmin = x_center - dx;
4563 if (round)
4564 window_xmin=int( window_xmin/x_tick -1)*x_tick;
4565 window_xmax = x_center + dx;
4566 if (round)
4567 window_xmax=int( window_xmax/x_tick +1)*x_tick;
4568 update();
4569 }
4570
zoomy(double d,bool round)4571 void Graph2d::zoomy(double d,bool round){
4572 double y_center=(window_ymin+window_ymax)/2;
4573 double dy=(window_ymax-window_ymin);
4574 if (dy==0)
4575 dy=gnuplot_ymax-gnuplot_ymin;
4576 dy *= d/2;
4577 y_tick = find_tick(dy);
4578 window_ymin = y_center - dy;
4579 if (round)
4580 window_ymin=int( window_ymin/y_tick -1)*y_tick;
4581 window_ymax = y_center + dy;
4582 if (round)
4583 window_ymax=int( window_ymax/y_tick +1)*y_tick;
4584 update();
4585 }
4586
zoom(double d)4587 void Graph2d::zoom(double d){
4588 zoomx(d);
4589 zoomy(d);
4590 }
4591
autoscale(bool fullview)4592 void Graph2d::autoscale(bool fullview){
4593 // Find the largest and lowest x/y/z in objects (except lines/plans)
4594 vector<double> vx,vy,vz;
4595 int s;
4596 bool ortho=autoscaleg(g,vx,vy,vz,contextptr);
4597 autoscaleminmax(vx,window_xmin,window_xmax,fullview);
4598 zoomx(1.0);
4599 autoscaleminmax(vy,window_ymin,window_ymax,fullview);
4600 zoomy(1.0);
4601 if (window_xmax-window_xmin<1e-100){
4602 window_xmax=gnuplot_xmax;
4603 window_xmin=gnuplot_xmin;
4604 }
4605 if (window_ymax-window_ymin<1e-100){
4606 window_ymax=gnuplot_ymax;
4607 window_ymin=gnuplot_ymin;
4608 }
4609 bool do_ortho=ortho;
4610 if (!do_ortho){
4611 double w=LCD_WIDTH_PX;
4612 double h=LCD_HEIGHT_PX-STATUS_AREA_PX;
4613 double window_w=window_xmax-window_xmin,window_h=window_ymax-window_ymin;
4614 double tst=h/w*window_w/window_h;
4615 if (tst>0.7 && tst<1.4)
4616 do_ortho=true;
4617 }
4618 if (do_ortho )
4619 orthonormalize();
4620 y_tick=find_tick(window_ymax-window_ymin);
4621 update();
4622 }
4623
orthonormalize()4624 void Graph2d::orthonormalize(){
4625 // Center of the directions, orthonormalize
4626 double w=LCD_WIDTH_PX;
4627 double h=LCD_HEIGHT_PX-STATUS_AREA_PX;
4628 double window_w=window_xmax-window_xmin,window_h=window_ymax-window_ymin;
4629 double window_hsize=h/w*window_w;
4630 if (window_h > window_hsize*1.01){ // enlarge horizontally
4631 double window_xcenter=(window_xmin+window_xmax)/2;
4632 double window_wsize=w/h*window_h;
4633 window_xmin=window_xcenter-window_wsize/2;
4634 window_xmax=window_xcenter+window_wsize/2;
4635 }
4636 if (window_h < window_hsize*0.99) { // enlarge vertically
4637 double window_ycenter=(window_ymin+window_ymax)/2;
4638 window_ymin=window_ycenter-window_hsize/2;
4639 window_ymax=window_ycenter+window_hsize/2;
4640 }
4641 x_tick=find_tick(window_xmax-window_xmin);
4642 y_tick=find_tick(window_ymax-window_ymin);
4643 update();
4644 }
4645
update()4646 void Graph2d::update(){
4647 x_scale=LCD_WIDTH_PX/(window_xmax-window_xmin);
4648 y_scale=(LCD_HEIGHT_PX-STATUS_AREA_PX)/(window_ymax-window_ymin);
4649 }
4650
findij(const gen & e0,double x_scale,double y_scale,double & i0,double & j0,GIAC_CONTEXT) const4651 bool Graph2d::findij(const gen & e0,double x_scale,double y_scale,double & i0,double & j0,GIAC_CONTEXT) const {
4652 gen e,f0,f1;
4653 evalfdouble2reim(e0,e,f0,f1,contextptr);
4654 if ((f0.type==_DOUBLE_) && (f1.type==_DOUBLE_)){
4655 if (display_mode & 0x400){
4656 if (f0._DOUBLE_val<=0)
4657 return false;
4658 f0=std::log10(f0._DOUBLE_val);
4659 }
4660 i0=(f0._DOUBLE_val-window_xmin)*x_scale;
4661 if (display_mode & 0x800){
4662 if (f1._DOUBLE_val<=0)
4663 return false;
4664 f1=std::log10(f1._DOUBLE_val);
4665 }
4666 j0=(window_ymax-f1._DOUBLE_val)*y_scale;
4667 return true;
4668 }
4669 // cerr << "Invalid drawing data" << endl;
4670 return false;
4671 }
4672
swapint(int & i0,int & i1)4673 inline void swapint(int & i0,int & i1){
4674 int tmp=i0;
4675 i0=i1;
4676 i1=tmp;
4677 }
4678
check_fl_draw(int fontsize,const char * ch,int i0,int j0,int imin,int jmin,int di,int dj,int delta_i,int delta_j,int c)4679 void check_fl_draw(int fontsize,const char * ch,int i0,int j0,int imin,int jmin,int di,int dj,int delta_i,int delta_j,int c){
4680 /* int n=fl_size();
4681 if (j0>=jmin-n && j0<=jmin+dj+n) */
4682 // cerr << i0 << " " << j0 << endl;
4683 if (strlen(ch)>200)
4684 text_print(fontsize,"String too long",i0+delta_i,j0+delta_j,c);
4685 else
4686 text_print(fontsize,ch,i0+delta_i,j0+delta_j,c);
4687 }
4688
check_fl_point(int i0,int j0,int imin,int jmin,int di,int dj,int delta_i,int delta_j,int c)4689 inline void check_fl_point(int i0,int j0,int imin,int jmin,int di,int dj,int delta_i,int delta_j,int c){
4690 /* if (i0>=imin && i0<=imin+di && j0>=jmin && j0<=jmin+dj) */
4691 os_set_pixel(i0+delta_i,j0+delta_j,c);
4692 }
4693
fl_line(int x0,int y0,int x1,int y1,int c)4694 inline void fl_line(int x0,int y0,int x1,int y1,int c){
4695 draw_line(x0,y0,x1,y1,c);
4696 }
4697
fl_polygon(int x0,int y0,int x1,int y1,int x2,int y2,int c)4698 inline void fl_polygon(int x0,int y0,int x1,int y1,int x2,int y2,int c){
4699 draw_line(x0,y0,x1,y1,c);
4700 draw_line(x1,y1,x2,y2,c);
4701 }
4702
check_fl_line(int i0,int j0,int i1,int j1,int imin,int jmin,int di,int dj,int delta_i,int delta_j,int c)4703 inline void check_fl_line(int i0,int j0,int i1,int j1,int imin,int jmin,int di,int dj,int delta_i,int delta_j,int c){
4704 fl_line(i0+delta_i,j0+delta_j,i1+delta_i,j1+delta_j,c);
4705 }
4706
4707 int logplot_points=20;
4708
checklog_fl_line(double i0,double j0,double i1,double j1,double deltax,double deltay,bool logx,bool logy,double window_xmin,double x_scale,double window_ymax,double y_scale,int c)4709 void checklog_fl_line(double i0,double j0,double i1,double j1,double deltax,double deltay,bool logx,bool logy,double window_xmin,double x_scale,double window_ymax,double y_scale,int c){
4710 if (!logx && !logy){
4711 fl_line(round(i0+deltax),round(j0+deltay),round(i1+deltax),round(j1+deltay),c);
4712 return;
4713 }
4714 }
4715
find_dxdy(const string & legendes,int labelpos,int labelsize,int & dx,int & dy)4716 void find_dxdy(const string & legendes,int labelpos,int labelsize,int & dx,int & dy){
4717 int l=text_width(labelsize,legendes.c_str());
4718 dx=3;
4719 dy=1;
4720 switch (labelpos){
4721 case 1:
4722 dx=-l-3;
4723 break;
4724 case 2:
4725 dx=-l-3;
4726 dy=labelsize-2;
4727 break;
4728 case 3:
4729 dy=labelsize-2;
4730 break;
4731 }
4732 //dy += labelsize;
4733 }
4734
draw_legende(const vecteur & f,int i0,int j0,int labelpos,const Graph2d * iptr,int clip_x,int clip_y,int clip_w,int clip_h,int deltax,int deltay,int c,GIAC_CONTEXT)4735 void draw_legende(const vecteur & f,int i0,int j0,int labelpos,const Graph2d * iptr,int clip_x,int clip_y,int clip_w,int clip_h,int deltax,int deltay,int c,GIAC_CONTEXT){
4736 if (f.empty() ||!iptr->show_names )
4737 return;
4738 string legendes;
4739 if (f[0].is_symb_of_sommet(at_curve)){
4740 gen & f0=f[0]._SYMBptr->feuille;
4741 if (f0.type==_VECT && !f0._VECTptr->empty()){
4742 gen & f1 = f0._VECTptr->front();
4743 if (f1.type==_VECT && f1._VECTptr->size()>4 && (!is_zero((*f1._VECTptr)[4]) || (iptr->show_names & 2)) ){
4744 gen legende=f1._VECTptr->front();
4745 gen var=(*f1._VECTptr)[1];
4746 gen r=re(legende,contextptr),i=im(legende,contextptr),a,b;
4747 if (var.type==_IDNT && is_linear_wrt(r,*var._IDNTptr,a,b,contextptr)){
4748 i=subst(i,var,(var-b)/a,false,contextptr);
4749 legendes=i.print(contextptr);
4750 }
4751 else
4752 legendes=r.print(contextptr)+","+i.print(contextptr);
4753 if (legendes.size()>18){
4754 if (legendes.size()>30)
4755 legendes="";
4756 else
4757 legendes=legendes.substr(0,16)+"...";
4758 }
4759 }
4760 }
4761 }
4762 if (f.size()>2)
4763 legendes=gen2string(f[2])+(legendes.empty()?"":":")+legendes;
4764 if (legendes.empty())
4765 return;
4766 int fontsize=iptr->labelsize;
4767 int dx=3,dy=1;
4768 find_dxdy(legendes,labelpos,fontsize,dx,dy);
4769 check_fl_draw(fontsize,legendes.c_str(),i0+dx,j0+dy,clip_x,clip_y,clip_w,clip_h,deltax,deltay,c);
4770 }
4771
petite_fleche(double i1,double j1,double dx,double dy,int deltax,int deltay,int width,int c)4772 void petite_fleche(double i1,double j1,double dx,double dy,int deltax,int deltay,int width,int c){
4773 double dxy=std::sqrt(dx*dx+dy*dy);
4774 if (dxy){
4775 dxy/=max(2,min(5,int(dxy/10)))+width;
4776 dx/=dxy;
4777 dy/=dxy;
4778 double dxp=-dy,dyp=dx; // perpendicular
4779 dx*=std::sqrt(3.0);
4780 dy*=sqrt(3.0);
4781 fl_polygon(round(i1)+deltax,round(j1)+deltay,round(i1+dx+dxp)+deltax,round(j1+dy+dyp)+deltay,round(i1+dx-dxp)+deltax,round(j1+dy-dyp)+deltay,c);
4782 }
4783 }
4784
fltk_point(int deltax,int deltay,int i0,int j0,int epaisseur_point,int type_point,int c)4785 void fltk_point(int deltax,int deltay,int i0,int j0,int epaisseur_point,int type_point,int c){
4786 switch (type_point){
4787 case 1: // losange
4788 fl_line(deltax+i0-epaisseur_point,deltay+j0,deltax+i0,deltay+j0-epaisseur_point,c);
4789 fl_line(deltax+i0,deltay+j0-epaisseur_point,deltax+i0+epaisseur_point,deltay+j0,c);
4790 fl_line(deltax+i0-epaisseur_point,deltay+j0,deltax+i0,deltay+j0+epaisseur_point,c);
4791 fl_line(deltax+i0,deltay+j0+epaisseur_point,deltax+i0+epaisseur_point,deltay+j0,c);
4792 break;
4793 case 2: // croix verticale
4794 fl_line(deltax+i0,deltay+j0-epaisseur_point,deltax+i0,deltay+j0+epaisseur_point,c);
4795 fl_line(deltax+i0-epaisseur_point,deltay+j0,deltax+i0+epaisseur_point,deltay+j0,c);
4796 break;
4797 case 3: // carre
4798 fl_line(deltax+i0-epaisseur_point,deltay+j0-epaisseur_point,deltax+i0-epaisseur_point,deltay+j0+epaisseur_point,c);
4799 fl_line(deltax+i0+epaisseur_point,deltay+j0-epaisseur_point,deltax+i0+epaisseur_point,deltay+j0+epaisseur_point,c);
4800 fl_line(deltax+i0-epaisseur_point,deltay+j0-epaisseur_point,deltax+i0+epaisseur_point,deltay+j0-epaisseur_point,c);
4801 fl_line(deltax+i0-epaisseur_point,deltay+j0+epaisseur_point,deltax+i0+epaisseur_point,deltay+j0+epaisseur_point,c);
4802 break;
4803 case 5: // triangle
4804 fl_line(deltax+i0-epaisseur_point,deltay+j0,deltax+i0,deltay+j0-epaisseur_point,c);
4805 fl_line(deltax+i0,deltay+j0-epaisseur_point,deltax+i0+epaisseur_point,deltay+j0,c);
4806 fl_line(deltax+i0-epaisseur_point,deltay+j0,deltax+i0+epaisseur_point,deltay+j0,c);
4807 break;
4808 case 7: // point
4809 if (epaisseur_point>2)
4810 fl_arc(deltax+i0-(epaisseur_point-1),deltay+j0-(epaisseur_point-1),2*(epaisseur_point-1),2*(epaisseur_point-1),0,360,c);
4811 else
4812 fl_line(deltax+i0,deltay+j0,deltax+i0+1,deltay+j0,c);
4813 break;
4814 case 6: // etoile
4815 fl_line(deltax+i0-epaisseur_point,deltay+j0,deltax+i0+epaisseur_point,deltay+j0,c);
4816 // no break to add the following lines
4817 case 0: // 0 croix diagonale
4818 fl_line(deltax+i0-epaisseur_point,deltay+j0-epaisseur_point,deltax+i0+epaisseur_point,deltay+j0+epaisseur_point,c);
4819 fl_line(deltax+i0-epaisseur_point,deltay+j0+epaisseur_point,deltax+i0+epaisseur_point,deltay+j0-epaisseur_point,c);
4820 break;
4821 default: // 4 nothing drawn
4822 break;
4823 }
4824 }
4825
horiz_or_vert(const_iterateur jt,GIAC_CONTEXT)4826 int horiz_or_vert(const_iterateur jt,GIAC_CONTEXT){
4827 gen tmp(*(jt+1)-*jt),r,i;
4828 reim(tmp,r,i,contextptr);
4829 if (is_zero(r,contextptr)) return 1;
4830 if (is_zero(i,contextptr)) return 2;
4831 return 0;
4832 }
4833
fltk_draw(Graph2d & Mon_image,const gen & g,double x_scale,double y_scale,int clip_x,int clip_y,int clip_w,int clip_h,GIAC_CONTEXT)4834 void fltk_draw(Graph2d & Mon_image,const gen & g,double x_scale,double y_scale,int clip_x,int clip_y,int clip_w,int clip_h,GIAC_CONTEXT){
4835 int deltax=0,deltay=STATUS_AREA_PX,fontsize=Mon_image.labelsize;
4836 if (g.type==_VECT){
4837 const vecteur & v=*g._VECTptr;
4838 const_iterateur it=v.begin(),itend=v.end();
4839 for (;it!=itend;++it)
4840 fltk_draw(Mon_image,*it,x_scale,y_scale,clip_x,clip_y,clip_w,clip_h,contextptr);
4841 }
4842 if (g.type!=_SYMB)
4843 return;
4844 unary_function_ptr s=g._SYMBptr->sommet;
4845 if (g._SYMBptr->feuille.type!=_VECT)
4846 return;
4847 vecteur f=*g._SYMBptr->feuille._VECTptr;
4848 int mxw=LCD_WIDTH_PX,myw=LCD_HEIGHT_PX-STATUS_AREA_PX;
4849 double i0,j0,i0save,j0save,i1,j1;
4850 int fs=f.size();
4851 if ((fs==4) && (s==at_parameter)){
4852 return ;
4853 }
4854 string the_legend;
4855 vecteur style(get_style(f,the_legend));
4856 int styles=style.size();
4857 // color
4858 int ensemble_attributs = style.front().val;
4859 bool hidden_name = false;
4860 if (style.front().type==_ZINT){
4861 ensemble_attributs = mpz_get_si(*style.front()._ZINTptr);
4862 hidden_name=true;
4863 }
4864 else
4865 hidden_name=ensemble_attributs<0;
4866 int width =(ensemble_attributs & 0x00070000) >> 16; // 3 bits
4867 int epaisseur_point =(ensemble_attributs & 0x00380000) >> 19; // 3 bits
4868 int type_line =(ensemble_attributs & 0x01c00000) >> 22; // 3 bits
4869 if (type_line>4)
4870 type_line=(type_line-4)<<8;
4871 int type_point =(ensemble_attributs & 0x0e000000) >> 25; // 3 bits
4872 int labelpos =(ensemble_attributs & 0x30000000) >> 28; // 2 bits
4873 bool fill_polygon =(ensemble_attributs & 0x40000000) >> 30;
4874 int couleur =(ensemble_attributs & 0x0007ffff);
4875 epaisseur_point += 2;
4876 if (s==at_pnt){
4877 // f[0]=complex pnt or vector of complex pnts or symbolic
4878 // f[1] -> style
4879 // f[2] optional=label
4880 gen point=f[0];
4881 if (point.type==_VECT && point.subtype==_POINT__VECT)
4882 return;
4883 if ( (f[0].type==_SYMB) && (f[0]._SYMBptr->sommet==at_curve) && (f[0]._SYMBptr->feuille.type==_VECT) && (f[0]._SYMBptr->feuille._VECTptr->size()) ){
4884 // Mon_image.show_mouse_on_object=false;
4885 point=f[0]._SYMBptr->feuille._VECTptr->back();
4886 if (type_line>=4 && point.type==_VECT && point._VECTptr->size()>2){
4887 vecteur v=*point._VECTptr;
4888 int vs=v.size()/2; // 3 -> 1
4889 if (Mon_image.findij(v[vs],x_scale,y_scale,i0,j0,contextptr) && Mon_image.findij(v[vs+1],x_scale,y_scale,i1,j1,contextptr)){
4890 bool logx=Mon_image.display_mode & 0x400,logy=Mon_image.display_mode & 0x800;
4891 checklog_fl_line(i0,j0,i1,j1,deltax,deltay,logx,logy,Mon_image.window_xmin,x_scale,Mon_image.window_ymax,y_scale,couleur);
4892 double dx=i0-i1,dy=j0-j1;
4893 petite_fleche(i1,j1,dx,dy,deltax,deltay,width+3,couleur);
4894 }
4895 }
4896 }
4897 if (is_undef(point))
4898 return;
4899 // fl_line_style(type_line,width+1,0);
4900 if (point.type==_SYMB) {
4901 if (point._SYMBptr->sommet==at_cercle){
4902 vecteur v=*point._SYMBptr->feuille._VECTptr;
4903 gen diametre=remove_at_pnt(v[0]);
4904 gen e1=diametre._VECTptr->front().evalf_double(1,contextptr),e2=diametre._VECTptr->back().evalf_double(1,contextptr);
4905 gen centre=rdiv(e1+e2,2.0,contextptr);
4906 gen e12=e2-e1;
4907 double ex=evalf_double(re(e12,contextptr),1,contextptr)._DOUBLE_val,ey=evalf_double(im(e12,contextptr),1,contextptr)._DOUBLE_val;
4908 if (!Mon_image.findij(centre,x_scale,y_scale,i0,j0,contextptr))
4909 return;
4910 gen diam=std::sqrt(ex*ex+ey*ey);
4911 gen angle=std::atan2(ey,ex);
4912 gen a1=v[1].evalf_double(1,contextptr),a2=v[2].evalf_double(1,contextptr);
4913 bool full=v[1]==0 && v[2]==cst_two_pi;
4914 if ( (diam.type==_DOUBLE_) && (a1.type==_DOUBLE_) && (a2.type==_DOUBLE_) ){
4915 i1=diam._DOUBLE_val*x_scale/2.0;
4916 j1=diam._DOUBLE_val*y_scale/2.0;
4917 double a1d=a1._DOUBLE_val,a2d=a2._DOUBLE_val,angled=angle._DOUBLE_val;
4918 bool changer_sens=a1d>a2d;
4919 if (changer_sens){
4920 double tmp=a1d;
4921 a1d=a2d;
4922 a2d=tmp;
4923 }
4924 double anglei=(angled+a1d),anglef=(angled+a2d),anglem=(anglei+anglef)/2;
4925 if (fill_polygon)
4926 fl_pie(deltax+round(i0-i1),deltay+round(j0-j1),round(2*i1),round(2*j1),full?0:anglei*180/M_PI+.5,full?360:anglef*180/M_PI+.5,couleur,false);
4927 else {
4928 fl_arc(deltax+round(i0-i1),deltay+round(j0-j1),round(2*i1),round(2*j1),full?0:anglei*180/M_PI+.5,full?360:anglef*180/M_PI+.5,couleur);
4929 if (v.size()>=4){ // if cercle has the optionnal 5th arg
4930 if (v[3]==2)
4931 petite_fleche(i0+i1*std::cos(anglem),j0-j1*std::sin(anglem),-i1*std::sin(anglem),-j1*std::cos(anglem),deltax,deltay,width,couleur);
4932 else {
4933 if (changer_sens)
4934 petite_fleche(i0+i1*std::cos(anglei),j0-j1*std::sin(anglei),-i1*std::sin(anglei),-j1*std::cos(anglei),deltax,deltay,width,couleur);
4935 else
4936 petite_fleche(i0+i1*std::cos(anglef),j0-j1*std::sin(anglef),i1*std::sin(anglef),j1*std::cos(anglef),deltax,deltay,width,couleur);
4937 }
4938 }
4939 }
4940 // Label a few degrees from the start angle,
4941 // FIXME should use labelpos
4942 double anglel=angled+a1d+0.3;
4943 if (v.size()>=4 && v[3]==2)
4944 anglel=angled+(0.45*a1d+0.55*a2d);
4945 i0=i0+i1*std::cos(anglel);
4946 j0=j0-j1*std::sin(anglel);
4947 if (!hidden_name)
4948 draw_legende(f,round(i0),round(j0),labelpos,&Mon_image,clip_x,clip_y,clip_w,clip_h,0,0,couleur,contextptr);
4949 return;
4950 }
4951 } // end circle
4952 #if 0
4953 if (point._SYMBptr->sommet==at_legende){
4954 gen & f=point._SYMBptr->feuille;
4955 if (f.type==_VECT && f._VECTptr->size()==3){
4956 vecteur & fv=*f._VECTptr;
4957 if (fv[0].type==_VECT && fv[0]._VECTptr->size()>=2 && fv[1].type==_STRNG && fv[2].type==_INT_){
4958 vecteur & fvv=*fv[0]._VECTptr;
4959 if (fvv[0].type==_INT_ && fvv[1].type==_INT_){
4960 int dx=0,dy=0;
4961 string legendes(*fv[1]._STRNGptr);
4962 find_dxdy(legendes,labelpos,fontsize,dx,dy);
4963 text_print(fontsize,legendes.c_str(),deltax+fvv[0].val+dx,deltay+fvv[1].val+dy,fv[2].val);
4964 }
4965 }
4966 }
4967 }
4968 #endif
4969 } // end point.type==_SYMB
4970 if (point.type!=_VECT || (point.type==_VECT && (point.subtype==_GROUP__VECT || point.subtype==_VECTOR__VECT) && point._VECTptr->size()==2 && is_zero(point._VECTptr->back()-point._VECTptr->front())) ){ // single point
4971 if (!Mon_image.findij((point.type==_VECT?point._VECTptr->front():point),x_scale,y_scale,i0,j0,contextptr))
4972 return;
4973 if (i0>0 && i0<mxw && j0>0 && j0<myw)
4974 fltk_point(deltax,deltay,round(i0),round(j0),epaisseur_point,type_point,couleur);
4975 if (!hidden_name)
4976 draw_legende(f,round(i0),round(j0),labelpos,&Mon_image,clip_x,clip_y,clip_w,clip_h,0,0,couleur,contextptr);
4977 return;
4978 }
4979 // path
4980 const_iterateur jt=point._VECTptr->begin(),jtend=point._VECTptr->end();
4981 if (jt==jtend)
4982 return;
4983 bool logx=Mon_image.display_mode & 0x400,logy=Mon_image.display_mode & 0x800;
4984 if (jt->type==_VECT)
4985 return;
4986 if ( (type_point || epaisseur_point>2) && type_line==0 && width==0){
4987 for (;jt!=jtend;++jt){
4988 if (!Mon_image.findij(*jt,x_scale,y_scale,i0,j0,contextptr))
4989 return;
4990 if (i0>0 && i0<mxw && j0>0 && j0<myw)
4991 fltk_point(deltax,deltay,round(i0),round(j0),epaisseur_point,type_point,couleur);
4992 }
4993 if (!hidden_name)
4994 draw_legende(f,round(i0),round(j0),labelpos,&Mon_image,clip_x,clip_y,clip_w,clip_h,0,0,couleur,contextptr);
4995 return;
4996 }
4997 // initial point
4998 if (!Mon_image.findij(*jt,x_scale,y_scale,i0,j0,contextptr))
4999 return;
5000 i0save=i0;
5001 j0save=j0;
5002 if (fill_polygon){
5003 if (jtend-jt==5 && *(jt+4)==*jt){
5004 // check rectangle parallel to axes -> draw_rectangle (filled)
5005 int cote1=horiz_or_vert(jt,contextptr);
5006 if (cote1 && horiz_or_vert(jt+1,contextptr)==3-cote1 && horiz_or_vert(jt+2,contextptr)==cote1 && horiz_or_vert(jt+3,contextptr)==3-cote1){
5007 if (!Mon_image.findij(*(jt+2),x_scale,y_scale,i0,j0,contextptr))
5008 return;
5009 int x,y,w,h;
5010 if (i0<i0save){
5011 x=i0;
5012 w=i0save-i0;
5013 }
5014 else {
5015 x=i0save;
5016 w=i0-i0save;
5017 }
5018 if (j0<j0save){
5019 y=j0;
5020 h=j0save-j0;
5021 }
5022 else {
5023 y=j0save;
5024 h=j0-j0save;
5025 }
5026 draw_rectangle(deltax+x,deltay+y,w,h,couleur);
5027 if (!hidden_name)
5028 draw_legende(f,deltax+x,deltay+y,labelpos,&Mon_image,clip_x,clip_y,clip_w,clip_h,0,0,couleur,contextptr);
5029 return;
5030 }
5031 } // end rectangle check
5032 bool closed=*jt==*(jtend-1);
5033 vector< vector<int> > vi(jtend-jt+(closed?0:1),vector<int>(2));
5034 for (int pos=0;jt!=jtend;++pos,++jt){
5035 if (!Mon_image.findij(*jt,x_scale,y_scale,i0,j0,contextptr))
5036 return;
5037 vi[pos][0]=i0+deltax;
5038 vi[pos][1]=j0+deltay;
5039 }
5040 if (!closed)
5041 vi.back()=vi.front();
5042 draw_filled_polygon(vi,0,LCD_WIDTH_PX,0,LCD_HEIGHT_PX,couleur);
5043 if (!hidden_name)
5044 draw_legende(f,round(i0),round(j0),labelpos,&Mon_image,clip_x,clip_y,clip_w,clip_h,0,0,couleur,contextptr);
5045 return;
5046 }
5047 ++jt;
5048 if (jt==jtend){
5049 if (i0>0 && i0<mxw && j0>0 && j0<myw)
5050 check_fl_point(deltax+round(i0),deltay+round(j0),clip_x,clip_y,clip_w,clip_h,0,0,couleur);
5051 if (!hidden_name)
5052 draw_legende(f,round(i0),round(j0),labelpos,&Mon_image,clip_x,clip_y,clip_w,clip_h,0,0,couleur,contextptr);
5053 return;
5054 }
5055 bool seghalfline=( point.subtype==_LINE__VECT || point.subtype==_HALFLINE__VECT ) && (point._VECTptr->size()==2);
5056 // rest of the path
5057 for (;;){
5058 if (!Mon_image.findij(*jt,x_scale,y_scale,i1,j1,contextptr))
5059 return;
5060 if (!seghalfline){
5061 checklog_fl_line(i0,j0,i1,j1,deltax,deltay,logx,logy,Mon_image.window_xmin,x_scale,Mon_image.window_ymax,y_scale,couleur);
5062 if (point.subtype==_VECTOR__VECT){
5063 double dx=i0-i1,dy=j0-j1;
5064 petite_fleche(i1,j1,dx,dy,deltax,deltay,width,couleur);
5065 }
5066 }
5067 ++jt;
5068 if (jt==jtend){ // label of line at midpoint
5069 if (point.subtype==_LINE__VECT){
5070 i0=(6*i1-i0)/5-8;
5071 j0=(6*j1-j0)/5-8;
5072 }
5073 else {
5074 i0=(i0+i1)/2-8;
5075 j0=(j0+j1)/2;
5076 }
5077 break;
5078 }
5079 i0=i1;
5080 j0=j1;
5081 }
5082 // check for a segment/halfline/line
5083 if ( seghalfline){
5084 double deltai=i1-i0save,adeltai=absdouble(deltai);
5085 double deltaj=j1-j0save,adeltaj=absdouble(deltaj);
5086 if (point.subtype==_LINE__VECT){
5087 if (deltai==0)
5088 checklog_fl_line(i1,0,i1,clip_h,deltax,deltay,logx,logy,Mon_image.window_xmin,x_scale,Mon_image.window_ymax,y_scale,couleur);
5089 else {
5090 if (deltaj==0)
5091 checklog_fl_line(0,j1,clip_w,j1,deltax,deltay,Mon_image.display_mode & 0x400,Mon_image.display_mode & 0x800,Mon_image.window_xmin,x_scale,Mon_image.window_ymax,y_scale,couleur);
5092 else {
5093 // Find the intersections with the 4 rectangle segments
5094 // Horizontal x=0 or w =i1+t*deltai: y=j1+t*deltaj
5095 vector< complex<double> > pts;
5096 double y0=j1-i1/deltai*deltaj,tol=clip_h*1e-6;
5097 if (y0>=-tol && y0<=clip_h+tol)
5098 pts.push_back(complex<double>(0.0,y0));
5099 double yw=j1+(clip_w-i1)/deltai*deltaj;
5100 if (yw>=-tol && yw<=clip_h+tol)
5101 pts.push_back(complex<double>(clip_w,yw));
5102 // Vertical y=0 or h=j1+t*deltaj, x=i1+t*deltai
5103 double x0=i1-j1/deltaj*deltai;
5104 tol=clip_w*1e-6;
5105 if (x0>=-tol && x0<=clip_w+tol)
5106 pts.push_back(complex<double>(x0,0.0));
5107 double xh=i1+(clip_h-j1)/deltaj*deltai;
5108 if (xh>=-tol && xh<=clip_w+tol)
5109 pts.push_back(complex<double>(xh,clip_h));
5110 if (pts.size()>=2)
5111 checklog_fl_line(pts[0].real(),pts[0].imag(),pts[1].real(),pts[1].imag(),deltax,deltay,Mon_image.display_mode & 0x400,Mon_image.display_mode & 0x800,Mon_image.window_xmin,x_scale,Mon_image.window_ymax,y_scale,couleur);
5112 } // end else adeltai==0 , adeltaj==0
5113 } // end else adeltai==0
5114 } // end LINE_VECT
5115 else {
5116 double N=1;
5117 if (adeltai){
5118 N=clip_w/adeltai+1;
5119 if (adeltaj)
5120 N=max(N,clip_h/adeltaj+1);
5121 }
5122 else {
5123 if (adeltaj)
5124 N=clip_h/adeltaj+1;
5125 }
5126 N *= 2; // increase N since rounding might introduce too small clipping
5127 while (fabs(N*deltai)>10000)
5128 N /= 2;
5129 while (fabs(N*deltaj)>10000)
5130 N /= 2;
5131 checklog_fl_line(i0save,j0save,i1+N*deltai,j1+N*deltaj,deltax,deltay,Mon_image.display_mode & 0x400,Mon_image.display_mode & 0x800,Mon_image.window_xmin,x_scale,Mon_image.window_ymax,y_scale,couleur);
5132 }
5133 } // end seghalfline
5134 if ( (point.subtype==_GROUP__VECT) && (point._VECTptr->size()==2))
5135 ; // no legend for segment
5136 else {
5137 if (!hidden_name)
5138 draw_legende(f,round(i0),round(j0),labelpos,&Mon_image,clip_x,clip_y,clip_w,clip_h,0,0,couleur,contextptr);
5139 }
5140 } // end pnt subcase
5141 }
5142 #endif
5143
5144 // return a vector of values with simple decimal representation
5145 // between xmin/xmax or including xmin/xmax (if bounds is true)
ticks(double xmin,double xmax,bool bounds)5146 vecteur ticks(double xmin,double xmax,bool bounds){
5147 if (xmax<xmin)
5148 swapdouble(xmin,xmax);
5149 double dx=xmax-xmin;
5150 vecteur res;
5151 if (dx==0)
5152 return res;
5153 double d=std::pow(10.0,std::floor(std::log10(dx)));
5154 if (dx<2*d)
5155 d=d/5;
5156 else {
5157 if (dx<5*d)
5158 d=d/2;
5159 }
5160 double x1=std::floor(xmin/d)*d;
5161 double x2=(bounds?std::ceil(xmax/d):std::floor(xmax/d))*d;
5162 for (double x=x1+(bounds?0:d);x<=x2;x+=d){
5163 if (absdouble(x-int(x+.5))<1e-6*d)
5164 res.push_back(int(x+.5));
5165 else
5166 res.push_back(x);
5167 }
5168 return res;
5169 }
5170
draw()5171 void Graph2d::draw(){
5172 int save_clip_ymin=clip_ymin;
5173 clip_ymin=STATUS_AREA_PX;
5174 int horizontal_pixels=LCD_WIDTH_PX,vertical_pixels=LCD_HEIGHT_PX-STATUS_AREA_PX,deltax=0,deltay=STATUS_AREA_PX,clip_x=0,clip_y=0,clip_w=horizontal_pixels,clip_h=vertical_pixels;
5175 drawRectangle(0, STATUS_AREA_PX, horizontal_pixels, vertical_pixels,COLOR_WHITE);
5176 // Draw axis
5177 double I0,J0;
5178 findij(zero,x_scale,y_scale,I0,J0,contextptr); // origin
5179 int i_0=round(I0),j_0=round(J0);
5180 if (show_axes && (window_ymax>=0) && (window_ymin<=0)){ // X-axis
5181 vecteur aff; int affs;
5182 char ch[256];
5183 check_fl_line(deltax,deltay+j_0,deltax+horizontal_pixels,deltay+j_0,clip_x,clip_y,clip_w,clip_h,0,0,_GREEN);
5184 check_fl_line(deltax+i_0,deltay+j_0,deltax+i_0+int(x_scale),deltay+j_0,clip_x,clip_y,clip_w,clip_h,0,0,_CYAN);
5185 aff=ticks(window_xmin,window_xmax,true);
5186 affs=aff.size();
5187 for (int i=0;i<affs;++i){
5188 double d=evalf_double(aff[i],1,contextptr)._DOUBLE_val;
5189 if (fabs(d)<1e-6) strcpy(ch,"0"); else sprint_double(ch,d);
5190 int delta=int(horizontal_pixels*(d-window_xmin)/(window_xmax-window_xmin));
5191 int taille=strlen(ch)*9;
5192 fl_line(delta,deltay+j_0,delta,deltay+j_0-4,_GREEN);
5193 }
5194 check_fl_draw(labelsize,"x",deltax+horizontal_pixels-40,deltay+j_0-4,clip_x,clip_y,clip_w,clip_h,0,0,_GREEN);
5195 }
5196 if ( show_axes && (window_xmax>=0) && (window_xmin<=0) ) {// Y-axis
5197 vecteur aff; int affs;
5198 char ch[256];
5199 check_fl_line(deltax+i_0,deltay,deltax+i_0,deltay+vertical_pixels,clip_x,clip_y,clip_w,clip_h,0,0,_RED);
5200 check_fl_line(deltax+i_0,deltay+j_0,deltax+i_0,deltay+j_0-int(y_scale),clip_x,clip_y,clip_w,clip_h,0,0,_CYAN);
5201 aff=ticks(window_ymin,window_ymax,true);
5202 affs=aff.size();
5203 int taille=5;
5204 for (int j=0;j<affs;++j){
5205 double d=evalf_double(aff[j],1,contextptr)._DOUBLE_val;
5206 if (fabs(d)<1e-6) strcpy(ch,"0"); else sprint_double(ch,d);
5207 int delta=int(vertical_pixels*(window_ymax-d)/(window_ymax-window_ymin));
5208 if (delta>=taille && delta<=vertical_pixels-taille){
5209 fl_line(deltax+i_0,STATUS_AREA_PX+delta,deltax+i_0+4,STATUS_AREA_PX+delta,_RED);
5210 }
5211 }
5212 check_fl_draw(labelsize,"y",deltax+i_0+2,deltay+labelsize,clip_x,clip_y,clip_w,clip_h,0,0,_RED);
5213 }
5214 #if 0 // if ticks are enabled, don't forget to set freeze to false
5215 // Ticks
5216 if (show_axes && (horizontal_pixels)/(x_scale*x_tick) < 40 && vertical_pixels/(y_tick*y_scale) <40 ){
5217 if (x_tick>0 && y_tick>0 ){
5218 double nticks=(horizontal_pixels-I0)/(x_scale*x_tick);
5219 double mticks=(vertical_pixels-J0)/(y_tick*y_scale);
5220 int count=0;
5221 for (int ii=int(-I0/(x_tick*x_scale));ii<=nticks;++ii){
5222 int iii=int(I0+ii*x_scale*x_tick+.5);
5223 for (int jj=int(-J0/(y_tick*y_scale));jj<=mticks && count<1600;++jj,++count){
5224 int jjj=int(J0+jj*y_scale*y_tick+.5);
5225 check_fl_point(deltax+iii,deltay+jjj,clip_x,clip_y,clip_w,clip_h,0,0,COLOR_BLACK);
5226 }
5227 }
5228 }
5229 }
5230 #endif
5231 if (show_axes){
5232 int taille,affs,delta;
5233 vecteur aff;
5234 char ch[256];
5235 // X
5236 aff=ticks(window_xmin,window_xmax,true);
5237 affs=aff.size();
5238 for (int i=0;i<affs;++i){
5239 double d=evalf_double(aff[i],1,contextptr)._DOUBLE_val;
5240 sprint_double(ch,d);
5241 delta=int(horizontal_pixels*(d-window_xmin)/(window_xmax-window_xmin));
5242 taille=strlen(ch)*9;
5243 fl_line(delta,vertical_pixels+STATUS_AREA_PX-6,delta,vertical_pixels+STATUS_AREA_PX-1,_GREEN);
5244 if (delta>=taille/2 && delta<=horizontal_pixels){
5245 text_print(10,ch,delta-taille/2,vertical_pixels+STATUS_AREA_PX-7,_GREEN);
5246 }
5247 }
5248 // Y
5249 aff=ticks(window_ymin,window_ymax,true);
5250 affs=aff.size();
5251 taille=5;
5252 for (int j=0;j<affs;++j){
5253 double d=evalf_double(aff[j],1,contextptr)._DOUBLE_val;
5254 sprint_double(ch,d);
5255 delta=int(vertical_pixels*(window_ymax-d)/(window_ymax-window_ymin));
5256 if (delta>=taille && delta<=vertical_pixels-taille){
5257 fl_line(horizontal_pixels-5,STATUS_AREA_PX+delta,horizontal_pixels-1,STATUS_AREA_PX+delta,_RED);
5258 text_print(10,ch,horizontal_pixels-strlen(ch)*9,STATUS_AREA_PX+delta+taille,_RED);
5259 }
5260 }
5261 }
5262
5263 // draw
5264 fltk_draw(*this,g,x_scale,y_scale,clip_x,clip_y,clip_w,clip_h,contextptr);
5265 clip_ymin=save_clip_ymin;
5266 }
5267
left(double d)5268 void Graph2d::left(double d){
5269 window_xmin -= d;
5270 window_xmax -= d;
5271 }
5272
right(double d)5273 void Graph2d::right(double d){
5274 window_xmin += d;
5275 window_xmax += d;
5276 }
5277
up(double d)5278 void Graph2d::up(double d){
5279 window_ymin += d;
5280 window_ymax += d;
5281 }
5282
down(double d)5283 void Graph2d::down(double d){
5284 window_ymin -= d;
5285 window_ymax -= d;
5286 }
5287
draw()5288 void Turtle::draw(){
5289 const int deltax=0,deltay=0;
5290 int horizontal_pixels=LCD_WIDTH_PX-2*giac::COORD_SIZE;
5291 // Check for fast redraw
5292 // Then redraw the background
5293 drawRectangle(deltax, deltay, LCD_WIDTH_PX, LCD_HEIGHT_PX,COLOR_WHITE);
5294 if (turtleptr &&
5295 #ifdef TURTLETAB
5296 turtle_stack_size
5297 #else
5298 !turtleptr->empty()
5299 #endif
5300 ){
5301 if (turtlezoom>8)
5302 turtlezoom=8;
5303 if (turtlezoom<0.125)
5304 turtlezoom=0.125;
5305 // check that position is not out of screen
5306 #ifdef TURTLETAB
5307 logo_turtle t=turtleptr[turtle_stack_size-1];
5308 #else
5309 logo_turtle t=turtleptr->back();
5310 #endif
5311 double x=turtlezoom*(t.x-turtlex);
5312 if (x<0)
5313 turtlex += int(x/turtlezoom);
5314 if (x>=LCD_WIDTH_PX-10)
5315 turtlex += int((x-LCD_WIDTH_PX+10)/turtlezoom);
5316 double y=turtlezoom*(t.y-turtley);
5317 if (y<0)
5318 turtley += int(y/turtlezoom);
5319 if (y>LCD_HEIGHT_PX-10)
5320 turtley += int((y-LCD_HEIGHT_PX+10)/turtlezoom);
5321 }
5322 #if 0
5323 if (maillage & 0x3){
5324 fl_color(FL_BLACK);
5325 double xdecal=std::floor(turtlex/10.0)*10;
5326 double ydecal=std::floor(turtley/10.0)*10;
5327 if ( (maillage & 0x3)==1){
5328 for (double i=xdecal;i<LCD_WIDTH_PX+xdecal;i+=10){
5329 for (double j=ydecal;j<LCD_HEIGHT_PX+ydecal;j+=10){
5330 fl_point(deltax+int((i-turtlex)*turtlezoom+.5),deltay+LCD_HEIGHT_PX-int((j-turtley)*turtlezoom+.5));
5331 }
5332 }
5333 }
5334 else {
5335 double dj=std::sqrt(3.0)*10,i0=xdecal;
5336 for (double j=ydecal;j<LCD_HEIGHT_PX+ydecal;j+=dj){
5337 int J=deltay+int(LCD_HEIGHT_PX-(j-turtley)*turtlezoom);
5338 for (double i=i0;i<LCD_WIDTH_PX+xdecal;i+=10){
5339 fl_point(deltax+int((i-turtlex)*turtlezoom+.5),J);
5340 }
5341 i0 += dj;
5342 while (i0>=10)
5343 i0 -= 10;
5344 }
5345 }
5346 }
5347 #endif
5348 // Show turtle position/cap
5349 if (turtleptr &&
5350 #ifdef TURTLETAB
5351 turtle_stack_size &&
5352 #else
5353 !turtleptr->empty() &&
5354 #endif
5355 !(maillage & 0x4)){
5356 #ifdef TURTLETAB
5357 logo_turtle turtle=turtleptr[turtle_stack_size-1];
5358 #else
5359 logo_turtle turtle=turtleptr->back();
5360 #endif
5361 drawRectangle(deltax+horizontal_pixels,deltay,LCD_WIDTH_PX-horizontal_pixels,2*COORD_SIZE,_YELLOW);
5362 // drawRectangle(deltax, deltay, LCD_WIDTH_PX, LCD_HEIGHT_PX,COLOR_BLACK);
5363 char buf[32];
5364 sprintf(buf,"x %i ",int(turtle.x+.5));
5365 text_print(18,buf,deltax+horizontal_pixels,deltay+(2*COORD_SIZE)/3-2,COLOR_BLACK,_YELLOW);
5366 sprintf(buf,"y %i ",int(turtle.y+.5));
5367 text_print(18,buf,deltax+horizontal_pixels,deltay+(4*COORD_SIZE)/3-3,COLOR_BLACK,_YELLOW);
5368 sprintf(buf,"t %i ",int(turtle.theta+.5));
5369 text_print(18,buf,deltax+horizontal_pixels,deltay+2*COORD_SIZE-4,COLOR_BLACK,_YELLOW);
5370 }
5371 // draw turtle Logo
5372 if (turtleptr){
5373 #ifdef TURTLETAB
5374 int l=turtle_stack_size;
5375 #else
5376 int l=turtleptr->size();
5377 #endif
5378 if (l>0){
5379 #ifdef TURTLETAB
5380 logo_turtle prec =turtleptr[0];
5381 #else
5382 logo_turtle prec =(*turtleptr)[0];
5383 #endif
5384 int sp=speed;
5385 for (int k=1;k<l;++k){
5386 if (k>=2 && sp){
5387 sync_screen();
5388 for (int i=0;i<speed;++i){
5389 for (int j=0;j<1000;++j){
5390 if (iskeydown(5) || iskeydown(4) || iskeydown(22)){
5391 sp=0;
5392 break;
5393 }
5394 }
5395 }
5396 }
5397 #ifdef TURTLETAB
5398 logo_turtle current =(turtleptr)[k];
5399 #else
5400 logo_turtle current =(*turtleptr)[k];
5401 #endif
5402 #if 1
5403 if (current.s>=0){ // Write a string
5404 //cout << current.radius << " " << current.s << endl;
5405 if (current.s<ecristab().size())
5406 text_print(current.radius,ecristab()[current.s].c_str(),int(deltax+turtlezoom*(current.x-turtlex)),int(deltay+LCD_HEIGHT_PX-turtlezoom*(current.y-turtley)),current.color);
5407 }
5408 else
5409 #endif
5410 {
5411 if (current.radius>0){
5412 int r=current.radius & 0x1ff; // bit 0-8
5413 double theta1,theta2;
5414 if (current.direct){
5415 theta1=prec.theta+double((current.radius >> 9) & 0x1ff); // bit 9-17
5416 theta2=prec.theta+double((current.radius >> 18) & 0x1ff); // bit 18-26
5417 }
5418 else {
5419 theta1=prec.theta-double((current.radius >> 9) & 0x1ff); // bit 9-17
5420 theta2=prec.theta-double((current.radius >> 18) & 0x1ff); // bit 18-26
5421 }
5422 bool rempli=(current.radius >> 27) & 0x1;
5423 bool seg=(current.radius >> 28) & 0x1;
5424 double angle;
5425 int x,y,R;
5426 R=int(2*turtlezoom*r+.5);
5427 angle = M_PI/180*(theta2-90);
5428 if (current.direct){
5429 x=int(turtlezoom*(current.x-turtlex-r*std::cos(angle) - r)+.5);
5430 y=int(turtlezoom*(current.y-turtley-r*std::sin(angle) + r)+.5);
5431 }
5432 else {
5433 x=int(turtlezoom*(current.x-turtlex+r*std::cos(angle) -r)+.5);
5434 y=int(turtlezoom*(current.y-turtley+r*std::sin(angle) +r)+.5);
5435 }
5436 if (current.direct){
5437 if (rempli)
5438 fl_pie(deltax+x,deltay+LCD_HEIGHT_PX-y,R,R,theta1-90,theta2-90,current.color,seg);
5439 else
5440 fl_arc(deltax+x,deltay+LCD_HEIGHT_PX-y,R,R,theta1-90,theta2-90,current.color);
5441 }
5442 else {
5443 if (rempli)
5444 fl_pie(deltax+x,deltay+LCD_HEIGHT_PX-y,R,R,90+theta2,90+theta1,current.color,seg);
5445 else
5446 fl_arc(deltax+x,deltay+LCD_HEIGHT_PX-y,R,R,90+theta2,90+theta1,current.color);
5447 }
5448 } // end radius>0
5449 else {
5450 if (prec.mark){
5451 fl_line(deltax+int(turtlezoom*(prec.x-turtlex)+.5),deltay+int(LCD_HEIGHT_PX+turtlezoom*(turtley-prec.y)+.5),deltax+int(turtlezoom*(current.x-turtlex)+.5),deltay+int(LCD_HEIGHT_PX+turtlezoom*(turtley-current.y)+.5),prec.color);
5452 }
5453 }
5454 if (current.radius<-1 && k+current.radius>=0){
5455 // poly-line from (*turtleptr)[k+current.radius] to (*turtleptr)[k]
5456 vector< vector<int> > vi(1-current.radius,vector<int>(2));
5457 for (int i=0;i>=current.radius;--i){
5458 #ifdef TURTLETAB
5459 logo_turtle & t=(turtleptr)[k+i];
5460 #else
5461 logo_turtle & t=(*turtleptr)[k+i];
5462 #endif
5463 vi[-i][0]=deltax+turtlezoom*(t.x-turtlex);
5464 vi[-i][1]=deltay+LCD_HEIGHT_PX+turtlezoom*(turtley-t.y);
5465 //*logptr(contextptr) << i << " " << vi[-i][0] << " " << vi[-i][1] << endl;
5466 }
5467 //vi.back()=vi.front();
5468 draw_filled_polygon(vi,0,LCD_WIDTH_PX,24,LCD_HEIGHT_PX,current.color);
5469 }
5470 } // end else (non-string turtle record)
5471 prec=current;
5472 } // end for (all turtle records)
5473 #ifdef TURTLETAB
5474 logo_turtle & t = (turtleptr)[l-1];
5475 #else
5476 logo_turtle & t = (*turtleptr)[l-1];
5477 #endif
5478 int x=int(turtlezoom*(t.x-turtlex)+.5);
5479 int y=int(turtlezoom*(t.y-turtley)+.5);
5480 double cost=std::cos(t.theta*deg2rad_d);
5481 double sint=std::sin(t.theta*deg2rad_d);
5482 int Dx=int(turtlezoom*t.turtle_length*cost/2+.5);
5483 int Dy=int(turtlezoom*t.turtle_length*sint/2+.5);
5484 if (t.visible){
5485 fl_line(deltax+x+Dy,deltay+LCD_HEIGHT_PX-(y-Dx),deltax+x-Dy,deltay+LCD_HEIGHT_PX-(y+Dx),t.color);
5486 int c=t.color;
5487 if (!t.mark)
5488 c=t.color ^ 0x7777;
5489 fl_line(deltax+x+Dy,deltay+LCD_HEIGHT_PX-(y-Dx),deltax+x+3*Dx,deltay+LCD_HEIGHT_PX-(y+3*Dy),c);
5490 fl_line(deltax+x-Dy,deltay+LCD_HEIGHT_PX-(y+Dx),deltax+x+3*Dx,deltay+LCD_HEIGHT_PX-(y+3*Dy),c);
5491 }
5492 }
5493 return;
5494 } // End logo mode
5495 }
5496
5497
displaygraph(const giac::gen & ge,GIAC_CONTEXT)5498 int displaygraph(const giac::gen & ge,GIAC_CONTEXT){
5499 // graph display
5500 //if (aborttimer > 0) { Timer_Stop(aborttimer); Timer_Deinstall(aborttimer);}
5501 xcas::Graph2d gr(ge,contextptr);
5502 gr.show_axes=true;
5503 // initial setting for x and y
5504 if (ge.type==_VECT){
5505 const_iterateur it=ge._VECTptr->begin(),itend=ge._VECTptr->end();
5506 for (;it!=itend;++it){
5507 if (it->is_symb_of_sommet(at_equal)){
5508 const gen & f=it->_SYMBptr->feuille;
5509 gen & optname = f._VECTptr->front();
5510 gen & optvalue= f._VECTptr->back();
5511 if (optname.val==_AXES && optvalue.type==_INT_)
5512 gr.show_axes=optvalue.val;
5513 if (optname.type==_INT_ && optname.subtype == _INT_PLOT && optname.val>=_GL_X && optname.val<=_GL_Z && optvalue.is_symb_of_sommet(at_interval)){
5514 //*logptr(contextptr) << optname << " " << optvalue << endl;
5515 gen optvf=evalf_double(optvalue._SYMBptr->feuille,1,contextptr);
5516 if (optvf.type==_VECT && optvf._VECTptr->size()==2){
5517 gen a=optvf._VECTptr->front();
5518 gen b=optvf._VECTptr->back();
5519 if (a.type==_DOUBLE_ && b.type==_DOUBLE_){
5520 switch (optname.val){
5521 case _GL_X:
5522 gr.window_xmin=a._DOUBLE_val;
5523 gr.window_xmax=b._DOUBLE_val;
5524 gr.update();
5525 break;
5526 case _GL_Y:
5527 gr.window_ymin=a._DOUBLE_val;
5528 gr.window_ymax=b._DOUBLE_val;
5529 gr.update();
5530 break;
5531 }
5532 }
5533 }
5534 }
5535 }
5536 }
5537 }
5538 // UI
5539 #ifdef NSPIRE_NEWLIB
5540 DefineStatusMessage((char*)"+-: zoom, pad: move, esc: quit", 1, 0, 0);
5541 #else
5542 DefineStatusMessage((char*)"+-: zoom, pad: move, EXIT: quit", 1, 0, 0);
5543 #endif
5544 // EnableStatusArea(2);
5545 for (;;){
5546 gr.draw();
5547 DisplayStatusArea();
5548 // int x=0,y=LCD_HEIGHT_PX-STATUS_AREA_PX-17;
5549 // PrintMini(&x,&y,(unsigned char *)"menu",0x04,0xffffffff,0,0,COLOR_BLACK,COLOR_WHITE,1,0);
5550 int key=-1;
5551 GetKey(&key);
5552 if (key==KEY_SHUTDOWN)
5553 return key;
5554 #if 1
5555 if (key==KEY_CTRL_CATALOG || key==KEY_BOOK){
5556 char menu_xmin[32],menu_xmax[32],menu_ymin[32],menu_ymax[32];
5557 string s;
5558 s="xmin "+print_DOUBLE_(gr.window_xmin,contextptr);
5559 strcpy(menu_xmin,s.c_str());
5560 s="xmax "+print_DOUBLE_(gr.window_xmax,contextptr);
5561 strcpy(menu_xmax,s.c_str());
5562 s="ymin "+print_DOUBLE_(gr.window_ymin,contextptr);
5563 strcpy(menu_ymin,s.c_str());
5564 s="ymax "+print_DOUBLE_(gr.window_ymax,contextptr);
5565 strcpy(menu_ymax,s.c_str());
5566 Menu smallmenu;
5567 smallmenu.numitems=12;
5568 MenuItem smallmenuitems[smallmenu.numitems];
5569 smallmenu.items=smallmenuitems;
5570 smallmenu.height=12;
5571 //smallmenu.title = "KhiCAS";
5572 smallmenuitems[0].text = (char *) menu_xmin;
5573 smallmenuitems[1].text = (char *) menu_xmax;
5574 smallmenuitems[2].text = (char *) menu_ymin;
5575 smallmenuitems[3].text = (char *) menu_ymax;
5576 smallmenuitems[4].text = (char*) "Orthonormalize /";
5577 smallmenuitems[5].text = (char*) "Autoscale *";
5578 smallmenuitems[6].text = (char *) ("Zoom in +");
5579 smallmenuitems[7].text = (char *) ("Zoom out -");
5580 smallmenuitems[8].text = (char *) ("Y-Zoom out (-)");
5581 smallmenuitems[9].text = (char*) ((lang==1)?"Voir axes":"Show axes");
5582 smallmenuitems[10].text = (char*) ((lang==1)?"Cacher axes":"Hide axes");
5583 smallmenuitems[11].text = (char*)((lang==1)?"Quitter":"Quit");
5584 int sres = doMenu(&smallmenu);
5585 if(sres == MENU_RETURN_SELECTION || sres==KEY_CTRL_EXE) {
5586 const char * ptr=0;
5587 string s1; double d;
5588 if (smallmenu.selection==1){
5589 if (inputdouble(menu_xmin,d,contextptr)){
5590 gr.window_xmin=d;
5591 gr.update();
5592 }
5593 }
5594 if (smallmenu.selection==2){
5595 if (inputdouble(menu_xmax,d,contextptr)){
5596 gr.window_xmax=d;
5597 gr.update();
5598 }
5599 }
5600 if (smallmenu.selection==3){
5601 if (inputdouble(menu_ymin,d,contextptr)){
5602 gr.window_ymin=d;
5603 gr.update();
5604 }
5605 }
5606 if (smallmenu.selection==4){
5607 if (inputdouble(menu_ymax,d,contextptr)){
5608 gr.window_ymax=d;
5609 gr.update();
5610 }
5611 }
5612 if (smallmenu.selection==5)
5613 gr.orthonormalize();
5614 if (smallmenu.selection==6)
5615 gr.autoscale();
5616 if (smallmenu.selection==7)
5617 gr.zoom(0.7);
5618 if (smallmenu.selection==8)
5619 gr.zoom(1/0.7);
5620 if (smallmenu.selection==9)
5621 gr.zoomy(1/0.7);
5622 if (smallmenu.selection==10)
5623 gr.show_axes=true;
5624 if (smallmenu.selection==11)
5625 gr.show_axes=false;
5626 if (smallmenu.selection==12)
5627 break;
5628 }
5629 }
5630 #endif
5631 if (key==KEY_CTRL_EXIT || key==KEY_CTRL_OK){
5632 os_hide_graph();
5633 break;
5634 }
5635 if (key==KEY_CTRL_UP){ gr.up((gr.window_ymax-gr.window_ymin)/5); }
5636 if (key==KEY_CTRL_PAGEUP) { gr.up((gr.window_ymax-gr.window_ymin)/2); }
5637 if (key==KEY_CTRL_DOWN) { gr.down((gr.window_ymax-gr.window_ymin)/5); }
5638 if (key==KEY_CTRL_PAGEDOWN) { gr.down((gr.window_ymax-gr.window_ymin)/2);}
5639 if (key==KEY_CTRL_LEFT) { gr.left((gr.window_xmax-gr.window_xmin)/5); }
5640 if (key==KEY_SHIFT_LEFT) { gr.left((gr.window_xmax-gr.window_xmin)/2); }
5641 if (key==KEY_CTRL_RIGHT) { gr.right((gr.window_xmax-gr.window_xmin)/5); }
5642 if (key==KEY_SHIFT_RIGHT) { gr.right((gr.window_xmax-gr.window_xmin)/5); }
5643 if (key==KEY_CHAR_PLUS) {
5644 gr.zoom(0.7);
5645 }
5646 if (key==KEY_CHAR_MINUS){
5647 gr.zoom(1/0.7);
5648 }
5649 if (key==KEY_CHAR_PMINUS){
5650 gr.zoomy(1/0.7);
5651 }
5652 if (key==KEY_CHAR_MULT){
5653 gr.autoscale();
5654 }
5655 if (key==KEY_CHAR_DIV) {
5656 gr.orthonormalize();
5657 }
5658 if (key==KEY_CTRL_VARS) {
5659 gr.show_axes=!gr.show_axes;
5660 }
5661 }
5662 // aborttimer = Timer_Install(0, check_execution_abort, 100); if (aborttimer > 0) { Timer_Start(aborttimer); }
5663 return 0;
5664 }
5665
displaylogo()5666 int displaylogo(){
5667 #ifdef TURTLETAB
5668 xcas::Turtle t={tablogo,0,0,1,1,(short) turtle_speed};
5669 #else
5670 xcas::Turtle t={&turtle_stack(),0,0,1,1,(short) turtle_speed};
5671 #endif
5672 #ifdef NSPIRE_NEWLIB
5673 DefineStatusMessage((char*)"+-: zoom, pad: move, esc: quit", 1, 0, 0);
5674 #else
5675 DefineStatusMessage((char*)"+-: zoom, pad: move, EXIT: quit", 1, 0, 0);
5676 #endif
5677 DisplayStatusArea();
5678 bool redraw=true;
5679 while (1){
5680 int save_ymin=clip_ymin;
5681 clip_ymin=24;
5682 if (redraw)
5683 t.draw();
5684 redraw=false;
5685 clip_ymin=save_ymin;
5686 int key;
5687 GetKey(&key);
5688 if (key==KEY_SHUTDOWN)
5689 return key;
5690 if (key==KEY_CTRL_EXIT || key==KEY_CTRL_OK || key==KEY_PRGM_ACON || key==KEY_CTRL_MENU || key==KEY_CTRL_EXE || key==KEY_CTRL_VARS)
5691 break;
5692 if (key==KEY_CTRL_UP){ t.turtley += 10; redraw=true; }
5693 if (key==KEY_CTRL_PAGEUP) { t.turtley += 100; redraw=true;}
5694 if (key==KEY_CTRL_DOWN) { t.turtley -= 10; redraw=true;}
5695 if (key==KEY_CTRL_PAGEDOWN) { t.turtley -= 100;redraw=true;}
5696 if (key==KEY_CTRL_LEFT) { t.turtlex -= 10; redraw=true;}
5697 if (key==KEY_SHIFT_LEFT) { t.turtlex -= 100; redraw=true;}
5698 if (key==KEY_CTRL_RIGHT) { t.turtlex += 10; redraw=true;}
5699 if (key==KEY_SHIFT_RIGHT) { t.turtlex += 100;redraw=true;}
5700 if (key==KEY_CHAR_PLUS) { t.turtlezoom *= 2;redraw=true;}
5701 if (key==KEY_CHAR_MINUS){ t.turtlezoom /= 2; redraw=true; }
5702 if (key==KEY_CHAR_MULT){ if (t.speed) t.speed *=2; else t.speed=10; redraw=true; }
5703 if (key==KEY_CHAR_DIV){ t.speed /=2; redraw=true; }
5704 if (key=='='){ redraw=true; }
5705 }
5706 os_hide_graph();
5707 return 0;
5708 }
5709
ispnt(const gen & g)5710 bool ispnt(const gen & g){
5711 if (g.is_symb_of_sommet(giac::at_pnt))
5712 return true;
5713 if (g.type!=_VECT || g._VECTptr->empty())
5714 return false;
5715 return ispnt(g._VECTptr->back());
5716 }
5717
translate_fkey(int & input_key)5718 void translate_fkey(int & input_key){
5719 if (input_key==KEY_CTRL_MIXEDFRAC) input_key=KEY_CTRL_F10;
5720 if (input_key==KEY_CTRL_FRACCNVRT) input_key=KEY_CTRL_F7;
5721 if (input_key==KEY_CHAR_LIST) input_key=KEY_CTRL_F9;
5722 if (input_key==KEY_CHAR_MAT) input_key=KEY_CTRL_F8;
5723 if (input_key==KEY_CTRL_PRGM) input_key=KEY_CTRL_F12;
5724 if (input_key==KEY_CTRL_FD) input_key=KEY_CTRL_F11;
5725 if (input_key==KEY_CHAR_ANGLE) input_key=KEY_CTRL_F13;
5726 if (input_key==KEY_CHAR_FRAC) input_key=KEY_CTRL_F14;
5727 }
5728
eqw(const giac::gen & ge,bool editable,GIAC_CONTEXT)5729 giac::gen eqw(const giac::gen & ge,bool editable,GIAC_CONTEXT){
5730 bool edited=false;
5731 const int margin=16;
5732 #ifdef CURSOR
5733 Cursor_SetFlashOff();
5734 #endif
5735 giac::gen geq(_copy(ge,contextptr));
5736 // if (ge.type!=giac::_DOUBLE_ && giac::has_evalf(ge,geq,1,contextptr)) geq=giac::symb_equal(ge,geq);
5737 int line=-1,col=-1,nlines=0,ncols=0,listormat=0;
5738 xcas::Equation eq(0,0,geq,contextptr);
5739 giac::eqwdata eqdata=xcas::Equation_total_size(eq.data);
5740 if (eqdata.dx>1.5*LCD_WIDTH_PX || eqdata.dy>1.5*LCD_HEIGHT_PX){
5741 if (eqdata.dx>2.25*LCD_WIDTH_PX || eqdata.dy>2.25*LCD_HEIGHT_PX)
5742 eq.attr=giac::attributs(14,COLOR_WHITE,COLOR_BLACK);
5743 else
5744 eq.attr=giac::attributs(16,COLOR_WHITE,COLOR_BLACK);
5745 eq.data=0; // clear memory
5746 eq.data=xcas::Equation_compute_size(geq,eq.attr,LCD_WIDTH_PX,contextptr);
5747 eqdata=xcas::Equation_total_size(eq.data);
5748 }
5749 int dx=(eqdata.dx-LCD_WIDTH_PX)/2,dy=LCD_HEIGHT_PX-2*margin+eqdata.y;
5750 if (geq.type==_VECT){
5751 nlines=geq._VECTptr->size();
5752 if (eqdata.dx>=LCD_WIDTH_PX)
5753 dx=-20; // line=nlines/2;
5754 //else
5755 if (geq.subtype!=_SEQ__VECT){
5756 line=0;
5757 listormat=1;
5758 if (ckmatrix(geq)){
5759 ncols=geq._VECTptr->front()._VECTptr->size();
5760 if (eqdata.dy>=LCD_HEIGHT_PX-margin)
5761 dy=eqdata.y+eqdata.dy+32;// col=ncols/2;
5762 // else
5763 col=0;
5764 listormat=2;
5765 }
5766 }
5767 }
5768 if (!listormat){
5769 xcas::Equation_select(eq.data,true);
5770 xcas::eqw_select_down(eq.data);
5771 }
5772 //cout << eq.data << endl;
5773 int firstrun=2;
5774 for (;;){
5775 #if 1
5776 if (firstrun==2){
5777 #ifdef NSPIRE_NEWLIB
5778 DefineStatusMessage((char*)((lang==1)?"ctrl enter: eval, esc: quitte, ":"ctrl enter: eval, esc: exit"), 1, 0, 0);
5779 #else
5780 DefineStatusMessage((char*)((lang==1)?"EXE: quitte, resultat dans last":"EXE: quit, result stored in last"), 1, 0, 0);
5781 #endif
5782 DisplayStatusArea();
5783 firstrun=1;
5784 }
5785 else
5786 set_xcas_status();
5787 #else
5788 DefineStatusMessage((char*)"+-: zoom, pad: move, EXIT: quit", 1, 0, 0);
5789 EnableStatusArea(2);
5790 DisplayStatusArea();
5791 #endif
5792 gen value;
5793 if (listormat) // select line l, col c
5794 xcas::eqw_select(eq.data,line,col,true,value);
5795 if (eqdata.dx>LCD_WIDTH_PX){
5796 if (dx<-20)
5797 dx=-20;
5798 if (dx>eqdata.dx-LCD_WIDTH_PX+20)
5799 dx=eqdata.dx-LCD_WIDTH_PX+20;
5800 }
5801 #define EQW_TAILLE 18
5802 if (eqdata.dy>LCD_HEIGHT_PX-2*EQW_TAILLE){
5803 if (dy-eqdata.y<LCD_HEIGHT_PX-2*EQW_TAILLE)
5804 dy=eqdata.y+LCD_HEIGHT_PX-2*EQW_TAILLE;
5805 if (dy-eqdata.y>eqdata.dy+32)
5806 dy=eqdata.y+eqdata.dy+32;
5807 }
5808 waitforvblank();
5809 drawRectangle(0, 0, LCD_WIDTH_PX, 205,COLOR_WHITE);
5810 // Bdisp_AllClr_VRAM();
5811 int save_clip_ymin=clip_ymin;
5812 clip_ymin=STATUS_AREA_PX;
5813 xcas::display(eq,dx,dy,contextptr);
5814 #if 1
5815 string menu("shift-1 ");
5816 menu += string(menu_f1);
5817 menu += "|2 ";
5818 menu += string(menu_f2);
5819 menu += "|3 undo|4 edt|5 +-|6 approx";
5820 drawRectangle(0,205,LCD_WIDTH_PX,17,22222);
5821 PrintMiniMini(0,205,menu.c_str(),4,22222,giac::_BLACK);
5822 #endif
5823 //draw_menu(2);
5824 clip_ymin=save_clip_ymin;
5825 int keyflag = GetSetupSetting( (unsigned int)0x14);
5826 if (firstrun){ // workaround for e.g. 1+x/2 partly not displayed
5827 firstrun=0;
5828 continue;
5829 }
5830 int key;
5831 //cout << eq.data << endl;
5832 GetKey(&key);
5833 if (key==KEY_SHUTDOWN)
5834 return undef;
5835 bool alph=alphawasactive(&key);
5836 if (key==KEY_CTRL_OK || key==KEY_CTRL_MENU){
5837 os_hide_graph();
5838 if (edited && xcas::do_select(eq.data,true,value) && value.type==_EQW){
5839 //cout << "ok " << value._EQWptr->g << endl;
5840 DefineStatusMessage(((lang==1)?"resultat stocke dans last":"result stored in last"), 1, 0, 0);
5841 //DisplayStatusArea();
5842 giac::sto(value._EQWptr->g,giac::gen("last",contextptr),contextptr);
5843 return value._EQWptr->g;
5844 }
5845 //cout << "no " << eq.data << endl; if (value.type==_EQW) cout << value._EQWptr->g << endl ;
5846 return geq;
5847 }
5848 if (key==KEY_CTRL_EXIT || key==KEY_CTRL_AC ){
5849 if (!edited){
5850 os_hide_graph();
5851 return geq;
5852 }
5853 if (confirm(
5854 #ifdef NSPIRE_NEWLIB
5855 (lang==1)?"Vraiment abandonner?":"Really leave",(lang==1)?"esc: editeur, enter: confirmer":"esc: editor, enter: confirm"
5856 #else
5857 (lang==1)?"Vraiment abandonner?":"Really leave",(lang==1)?"Back: editeur, OK: confirmer":"Back: editor, OK: confirm"
5858 #endif
5859 )==KEY_CTRL_F1){
5860 os_hide_graph();
5861 return geq;
5862 }
5863 }
5864 if (key==KEY_CTRL_F3)
5865 key=KEY_CTRL_UNDO;
5866 if (key==KEY_CTRL_UNDO){
5867 giac::swapgen(eq.undodata,eq.data);
5868 if (listormat){
5869 xcas::do_select(eq.data,true,value);
5870 if (value.type==_EQW){
5871 gen g=eval(value._EQWptr->g,1,contextptr);
5872 if (g.type==_VECT){
5873 const vecteur & v=*g._VECTptr;
5874 nlines=v.size();
5875 if (line >= nlines)
5876 line=nlines-1;
5877 if (col!=-1 &&v.front().type==_VECT){
5878 ncols=v.front()._VECTptr->size();
5879 if (col>=ncols)
5880 col=ncols-1;
5881 }
5882 xcas::do_select(eq.data,false,value);
5883 xcas::eqw_select(eq.data,line,col,true,value);
5884 }
5885 }
5886 }
5887 continue;
5888 }
5889 int redo=0;
5890 if (listormat){
5891 if (key==KEY_CHAR_COMMA || key==KEY_CTRL_DEL ){
5892 xcas::do_select(eq.data,true,value);
5893 if (value.type==_EQW){
5894 gen g=eval(value._EQWptr->g,1,contextptr);
5895 if (g.type==_VECT){
5896 edited=true; eq.undodata=Equation_copy(eq.data);
5897 vecteur v=*g._VECTptr;
5898 if (key==KEY_CHAR_COMMA){
5899 if (col==-1 || (line>0 && line==nlines-1)){
5900 v.insert(v.begin()+line+1,0*v.front());
5901 ++line; ++nlines;
5902 }
5903 else {
5904 v=mtran(v);
5905 v.insert(v.begin()+col+1,0*v.front());
5906 v=mtran(v);
5907 ++col; ++ncols;
5908 }
5909 }
5910 else {
5911 if (col==-1 || (nlines>=3 && line==nlines-1)){
5912 if (nlines>=(col==-1?2:3)){
5913 v.erase(v.begin()+line,v.begin()+line+1);
5914 if (line) --line;
5915 --nlines;
5916 }
5917 }
5918 else {
5919 if (ncols>=2){
5920 v=mtran(v);
5921 v.erase(v.begin()+col,v.begin()+col+1);
5922 v=mtran(v);
5923 if (col) --col; --ncols;
5924 }
5925 }
5926 }
5927 geq=gen(v,g.subtype);
5928 key=0; redo=1;
5929 // continue;
5930 }
5931 }
5932 }
5933 }
5934 bool ins=key==KEY_CHAR_STORE || key==KEY_CHAR_RPAR || key==KEY_CHAR_LPAR || key==KEY_CHAR_COMMA || key==KEY_CTRL_PASTE || key==KEY_CTRL_F4;
5935 int xleft,ytop,xright,ybottom,gselpos; gen * gsel=0,*gselparent=0;
5936 if (key==KEY_CTRL_CLIP){
5937 xcas::Equation_adjust_xy(eq.data,xleft,ytop,xright,ybottom,gsel,gselparent,gselpos,0);
5938 if (gsel==0)
5939 gsel==&eq.data;
5940 // cout << "var " << g << " " << eq.data << endl;
5941 if (xcas::do_select(*gsel,true,value) && value.type==_EQW){
5942 //cout << g << ":=" << value._EQWptr->g << endl;
5943 copy_clipboard(value._EQWptr->g.print(contextptr),true);
5944 continue;
5945 }
5946 }
5947 if (key==KEY_CHAR_STORE){
5948 int keyflag = GetSetupSetting( (unsigned int)0x14);
5949 if (keyflag==0)
5950 handle_f5();
5951 std::string varname;
5952 if (inputline(((lang==1)?"Stocker la selection dans":"Save selection in",(lang==1)?"Nom de variable: ":"Variable name: "),0,varname,false,65,contextptr) && !varname.empty() && isalpha(varname[0])){
5953 giac::gen g(varname,contextptr);
5954 giac::gen ge(protecteval(g,1,contextptr));
5955 if (g.type!=_IDNT){
5956 invalid_varname();
5957 continue;
5958 }
5959 if (ge==g || confirm_overwrite()){
5960 vector<int> goto_sel;
5961 xcas::Equation_adjust_xy(eq.data,xleft,ytop,xright,ybottom,gsel,gselparent,gselpos,&goto_sel);
5962 if (gsel==0)
5963 gsel==&eq.data;
5964 // cout << "var " << g << " " << eq.data << endl;
5965 if (xcas::do_select(*gsel,true,value) && value.type==_EQW){
5966 //cout << g << ":=" << value._EQWptr->g << endl;
5967 giac::gen gg(value._EQWptr->g);
5968 if (gg.is_symb_of_sommet(at_makevector))
5969 gg=giac::eval(gg,1,contextptr);
5970 giac::sto(gg,g,contextptr);
5971 }
5972 }
5973 }
5974 continue;
5975 }
5976 if (key==KEY_CTRL_DEL){
5977 vector<int> goto_sel;
5978 if (xcas::Equation_adjust_xy(eq.data,xleft,ytop,xright,ybottom,gsel,gselparent,gselpos,&goto_sel) && gsel && xcas::do_select(*gsel,true,value) && value.type==_EQW){
5979 value=value._EQWptr->g;
5980 if (value.type==_SYMB){
5981 gen tmp=value._SYMBptr->feuille;
5982 if (tmp.type!=_VECT || tmp.subtype!=_SEQ__VECT){
5983 xcas::replace_selection(eq,tmp,gsel,&goto_sel,contextptr);
5984 continue;
5985 }
5986 }
5987 if (!goto_sel.empty() && gselparent && gselparent->type==_VECT && !gselparent->_VECTptr->empty()){
5988 vecteur & v=*gselparent->_VECTptr;
5989 if (v.back().type==_EQW){
5990 gen opg=v.back()._EQWptr->g;
5991 if (opg.type==_FUNC){
5992 int i=0;
5993 for (;i<v.size()-1;++i){
5994 if (&v[i]==gsel)
5995 break;
5996 }
5997 if (i<v.size()-1){
5998 if (v.size()==5 && (opg==at_integrate || opg==at_sum) && i>=2)
5999 v.erase(v.begin()+2,v.begin()+4);
6000 else
6001 v.erase(v.begin()+i);
6002 xcas::do_select(*gselparent,true,value);
6003 if (value.type==_EQW){
6004 value=value._EQWptr->g;
6005 // cout << goto_sel << " " << value << endl; continue;
6006 if (v.size()==2 && (opg==at_plus || opg==at_prod))
6007 value=protecteval(value,1,contextptr);
6008 goto_sel.erase(goto_sel.begin());
6009 xcas::replace_selection(eq,value,gselparent,&goto_sel,contextptr);
6010 continue;
6011 }
6012 }
6013 }
6014 }
6015 }
6016 }
6017 }
6018 if (key=='\\' || key==KEY_CTRL_F5){
6019 xcas::do_select(eq.data,true,value);
6020 if (value.type==_EQW)
6021 geq=value._EQWptr->g;
6022 if (eq.attr.fontsize<=14)
6023 eq.attr.fontsize=18;
6024 else
6025 eq.attr.fontsize=14;
6026 redo=1;
6027 }
6028 if (key==KEY_CHAR_IMGNRY)
6029 key='i';
6030 const char keybuf[2]={(key==KEY_CHAR_PMINUS?'-':char(key)),0};
6031 const char * adds=(key==KEY_CTRL_F4 || key==KEY_CHAR_PMINUS ||
6032 (key==char(key) && (isalphanum(key)|| key=='.' ))
6033 )?keybuf:keytostring(key,keyflag,contextptr);
6034 if (adds && !strcmp(adds,"VARS()"))
6035 continue;
6036 translate_fkey(key);
6037 if ( key==KEY_CTRL_F1 || key==KEY_CTRL_F2 ||
6038 (key>=KEY_CTRL_F7 && key<=KEY_CTRL_F14)){
6039 adds=console_menu(key,fmenu_cfg,1);//alph?"simplify":(keyflag==1?"factor":"partfrac");
6040 // workaround for infinitiy
6041 if (!adds) continue;
6042 if (strlen(adds)>=2 && adds[0]=='o' && adds[1]=='o')
6043 key=KEY_CTRL_F3;
6044 }
6045 if (key==KEY_CTRL_F6 || key==KEY_CTRL_EXE){
6046 adds= (key==KEY_CTRL_F6?"evalf":"eval");
6047 }
6048 if (key==KEY_CHAR_MINUS)
6049 adds="-";
6050 if (key==KEY_CHAR_EQUAL)
6051 adds="=";
6052 if (key==KEY_CHAR_RECIP)
6053 adds="inv";
6054 if (key==KEY_CHAR_SQUARE)
6055 adds="sq";
6056 if (key==KEY_CHAR_POWROOT)
6057 adds="surd";
6058 if (key==KEY_CHAR_CUBEROOT)
6059 adds="surd";
6060 if (key==KEY_CHAR_FACTOR)
6061 adds="factor";
6062 if (key==KEY_CHAR_NORMAL)
6063 adds="normal";
6064 int addssize=adds?strlen(adds):0;
6065 // cout << addssize << " " << adds << endl;
6066 if (0 && key==KEY_CTRL_EXE){
6067 if (xcas::do_select(eq.data,true,value) && value.type==_EQW){
6068 //cout << "ok " << value._EQWptr->g << endl;
6069 DefineStatusMessage(((lang==1)?"resultat stocke dans last":"result stored in last"), 1, 0, 0);
6070 //DisplayStatusArea();
6071 giac::sto(value._EQWptr->g,giac::gen("last",contextptr),contextptr);
6072 return value._EQWptr->g;
6073 }
6074 //cout << "no " << eq.data << endl; if (value.type==_EQW) cout << value._EQWptr->g << endl ;
6075 return geq;
6076 }
6077 if ( key!=KEY_CHAR_MINUS && key!=KEY_CHAR_EQUAL && key!=0 &&
6078 (ins || key==KEY_CHAR_PI || key==KEY_CTRL_VARS || key==KEY_CTRL_F3 || (addssize==1 && (isalphanum(adds[0])|| adds[0]=='.' || adds[0]=='-') ) )
6079 ){
6080 edited=true;
6081 if (line>=0 && xcas::eqw_select(eq.data,line,col,true,value)){
6082 string s;
6083 if (ins){
6084 if (key==KEY_CTRL_PASTE)
6085 s=paste_clipboard();
6086 else {
6087 if (value.type==_EQW){
6088 s=value._EQWptr->g.print(contextptr);
6089 }
6090 else
6091 s=value.print(contextptr);
6092 }
6093 }
6094 else
6095 s = adds;
6096 string msg("Line ");
6097 msg += print_INT_(line+1);
6098 msg += " Col ";
6099 msg += print_INT_(col+1);
6100 if (inputline(msg.c_str(),0,s,false,65,contextptr)==KEY_CTRL_EXE){
6101 value=gen(s,contextptr);
6102 if (col<0)
6103 (*geq._VECTptr)[line]=value;
6104 else
6105 (*((*geq._VECTptr)[line]._VECTptr))[col]=value;
6106 redo=2;
6107 key=KEY_SHIFT_RIGHT;
6108 }
6109 else
6110 continue;
6111 }
6112 else {
6113 vector<int> goto_sel;
6114 if (xcas::Equation_adjust_xy(eq.data,xleft,ytop,xright,ybottom,gsel,gselparent,gselpos,&goto_sel) && gsel && xcas::do_select(*gsel,true,value) && value.type==_EQW){
6115 string s;
6116 if (ins){
6117 if (key==KEY_CTRL_PASTE)
6118 s=paste_clipboard();
6119 else {
6120 s = value._EQWptr->g.print(contextptr);
6121 if (key==KEY_CHAR_COMMA)
6122 s += ',';
6123 }
6124 }
6125 else
6126 s = adds;
6127 if (inputline(value._EQWptr->g.print(contextptr).c_str(),0,s,false)==KEY_CTRL_EXE){
6128 value=gen(s,contextptr);
6129 //cout << value << " goto " << goto_sel << endl;
6130 xcas::replace_selection(eq,value,gsel,&goto_sel,contextptr);
6131 firstrun=-1; // workaround, force 2 times display
6132 }
6133 continue;
6134 }
6135 }
6136 }
6137 if (redo){
6138 eq.data=0; // clear memory
6139 eq.data=xcas::Equation_compute_size(geq,eq.attr,LCD_WIDTH_PX,contextptr);
6140 eqdata=xcas::Equation_total_size(eq.data);
6141 if (redo==1){
6142 dx=(eqdata.dx-LCD_WIDTH_PX)/2;
6143 dy=LCD_HEIGHT_PX-2*margin+eqdata.y;
6144 if (listormat) // select line l, col c
6145 xcas::eqw_select(eq.data,line,col,true,value);
6146 else {
6147 xcas::Equation_select(eq.data,true);
6148 xcas::eqw_select_down(eq.data);
6149 }
6150 continue;
6151 }
6152 }
6153 bool doit=eqdata.dx>=LCD_WIDTH_PX;
6154 int delta=0;
6155 if (listormat){
6156 if (key==KEY_CTRL_LEFT || (!doit && key==KEY_SHIFT_LEFT)){
6157 if (line>=0 && xcas::eqw_select(eq.data,line,col,false,value)){
6158 if (col>=0){
6159 --col;
6160 if (col<0){
6161 col=ncols-1;
6162 if (line>0){
6163 --line;
6164 dy += value._EQWptr->dy+eq.attr.fontsize/2;
6165 }
6166 }
6167 }
6168 else {
6169 if (line>0)
6170 --line;
6171 }
6172 xcas::eqw_select(eq.data,line,col,true,value);
6173 if (doit) dx -= value._EQWptr->dx;
6174 }
6175 continue;
6176 }
6177 if (doit && key==KEY_SHIFT_LEFT){
6178 dx -= 20;
6179 continue;
6180 }
6181 if (key==KEY_CTRL_RIGHT || (!doit && key==KEY_SHIFT_RIGHT)) {
6182 if (line>=0 && xcas::eqw_select(eq.data,line,col,false,value)){
6183 if (doit)
6184 dx += value._EQWptr->dx;
6185 if (col>=0){
6186 ++col;
6187 if (col==ncols){
6188 col=0;
6189 if (line<nlines-1){
6190 ++line;
6191 dy -= value._EQWptr->dy+eq.attr.fontsize/2;
6192 }
6193 }
6194 } else {
6195 if (line<nlines-1)
6196 ++line;
6197 }
6198 xcas::eqw_select(eq.data,line,col,true,value);
6199 }
6200 continue;
6201 }
6202 if (key==KEY_SHIFT_RIGHT && doit){
6203 dx += 20;
6204 continue;
6205 }
6206 doit=eqdata.dy>=LCD_HEIGHT_PX-2*margin;
6207 if (key==KEY_CTRL_UP || (!doit && key==KEY_CTRL_PAGEUP)){
6208 if (line>0 && col>=0 && xcas::eqw_select(eq.data,line,col,false,value)){
6209 --line;
6210 xcas::eqw_select(eq.data,line,col,true,value);
6211 if (doit)
6212 dy += value._EQWptr->dy+eq.attr.fontsize/2;
6213 }
6214 continue;
6215 }
6216 if (key==KEY_CTRL_PAGEUP && doit){
6217 dy += 10;
6218 continue;
6219 }
6220 if (key==KEY_CTRL_DOWN || (!doit && key==KEY_CTRL_PAGEDOWN)){
6221 if (line<nlines-1 && col>=0 && xcas::eqw_select(eq.data,line,col,false,value)){
6222 if (doit)
6223 dy -= value._EQWptr->dy+eq.attr.fontsize/2;
6224 ++line;
6225 xcas::eqw_select(eq.data,line,col,true,value);
6226 }
6227 continue;
6228 }
6229 if ( key==KEY_CTRL_PAGEDOWN && doit){
6230 dy -= 10;
6231 continue;
6232 }
6233 }
6234 else { // else listormat
6235 if (key==KEY_CTRL_LEFT){
6236 delta=xcas::eqw_select_leftright(eq,true,alph?2:0,contextptr);
6237 // cout << "left " << delta << endl;
6238 if (doit) dx += (delta?delta:-20);
6239 continue;
6240 }
6241 if (key==KEY_SHIFT_LEFT){
6242 delta=xcas::eqw_select_leftright(eq,true,1,contextptr);
6243 vector<int> goto_sel;
6244 if (doit) dx += (delta?delta:-20);
6245 continue;
6246 }
6247 if (key==KEY_CTRL_RIGHT){
6248 delta=xcas::eqw_select_leftright(eq,false,alph?2:0,contextptr);
6249 // cout << "right " << delta << endl;
6250 if (doit)
6251 dx += (delta?delta:20);
6252 continue;
6253 }
6254 if (key==KEY_SHIFT_RIGHT){
6255 delta=xcas::eqw_select_leftright(eq,false,1,contextptr);
6256 // cout << "right " << delta << endl;
6257 if (doit)
6258 dx += (delta?delta:20);
6259 // dx=eqdata.dx-LCD_WIDTH_PX+20;
6260 continue;
6261 }
6262 doit=eqdata.dy>=LCD_HEIGHT_PX-2*margin;
6263 if (key==KEY_CTRL_UP){
6264 delta=xcas::eqw_select_up(eq.data);
6265 // cout << "up " << delta << endl;
6266 continue;
6267 }
6268 //cout << "up " << eq.data << endl;
6269 if (key==KEY_CTRL_PAGEUP && doit){
6270 dy=eqdata.y+eqdata.dy+20;
6271 continue;
6272 }
6273 if (key==KEY_CTRL_DOWN){
6274 delta=xcas::eqw_select_down(eq.data);
6275 // cout << "down " << delta << endl;
6276 continue;
6277 }
6278 //cout << "down " << eq.data << endl;
6279 if ( key==KEY_CTRL_PAGEDOWN && doit){
6280 dy=eqdata.y+LCD_HEIGHT_PX-margin;
6281 continue;
6282 }
6283 }
6284 if (adds){
6285 edited=true;
6286 if (strcmp(adds,"'")==0)
6287 adds="diff";
6288 if (strcmp(adds,"^2")==0)
6289 adds="sq";
6290 if (strcmp(adds,">")==0)
6291 adds="simplify";
6292 if (strcmp(adds,"<")==0)
6293 adds="factor";
6294 if (strcmp(adds,"#")==0)
6295 adds="partfrac";
6296 string cmd(adds);
6297 if (cmd.size() && cmd[cmd.size()-1]=='(')
6298 cmd ='\''+cmd.substr(0,cmd.size()-1)+'\'';
6299 vector<int> goto_sel;
6300 if (xcas::Equation_adjust_xy(eq.data,xleft,ytop,xright,ybottom,gsel,gselparent,gselpos,&goto_sel) && gsel){
6301 gen op;
6302 int addarg=0;
6303 if (addssize==1){
6304 switch (adds[0]){
6305 case '+':
6306 addarg=1;
6307 op=at_plus;
6308 break;
6309 case '^':
6310 addarg=1;
6311 op=at_pow;
6312 break;
6313 case '=':
6314 addarg=1;
6315 op=at_equal;
6316 break;
6317 case '-':
6318 addarg=1;
6319 op=at_binary_minus;
6320 break;
6321 case '*':
6322 addarg=1;
6323 op=at_prod;
6324 break;
6325 case '/':
6326 addarg=1;
6327 op=at_division;
6328 break;
6329 case '\'':
6330 addarg=1;
6331 op=at_derive;
6332 break;
6333 }
6334 }
6335 if (op==0)
6336 op=gen(cmd,contextptr);
6337 if (op.type==_SYMB)
6338 op=op._SYMBptr->sommet;
6339 // cout << "keyed " << adds << " " << op << " " << op.type << endl;
6340 if (op.type==_FUNC){
6341 edited=true;
6342 // execute command on selection
6343 gen tmp,value;
6344 if (xcas::do_select(*gsel,true,value) && value.type==_EQW){
6345 if (op==at_integrate || op==at_sum)
6346 addarg=3;
6347 if (op==at_limit)
6348 addarg=2;
6349 gen args=protecteval(value._EQWptr->g,1,contextptr);
6350 gen vx=xthetat?t__IDNT_e:x__IDNT_e;
6351 if (addarg==1)
6352 args=makesequence(args,0);
6353 if (addarg==2)
6354 args=makesequence(args,vx_var,0);
6355 if (addarg==3)
6356 args=makesequence(args,vx_var,0,1);
6357 if (op==at_surd)
6358 args=makesequence(args,key==KEY_CHAR_CUBEROOT?3:4);
6359 if (op==at_subst)
6360 args=makesequence(args,giac::symb_equal(vx_var,0));
6361 unary_function_ptr immediate_op[]={*at_eval,*at_evalf,*at_evalc,*at_regrouper,*at_simplify,*at_normal,*at_ratnormal,*at_factor,*at_cfactor,*at_partfrac,*at_cpartfrac,*at_expand,*at_canonical_form,*at_exp2trig,*at_trig2exp,*at_sincos,*at_lin,*at_tlin,*at_tcollect,*at_texpand,*at_trigexpand,*at_trigcos,*at_trigsin,*at_trigtan,*at_halftan};
6362 if (equalposcomp(immediate_op,*op._FUNCptr)){
6363 set_abort();
6364 tmp=(*op._FUNCptr)(args,contextptr);
6365 clear_abort();
6366 esc_flag=0;
6367 giac::ctrl_c=false;
6368 kbd_interrupted=giac::interrupted=false;
6369 }
6370 else
6371 tmp=symbolic(*op._FUNCptr,args);
6372 //cout << "sel " << value._EQWptr->g << " " << tmp << " " << goto_sel << endl;
6373 esc_flag=0;
6374 giac::ctrl_c=false;
6375 kbd_interrupted=giac::interrupted=false;
6376 if (!is_undef(tmp)){
6377 xcas::replace_selection(eq,tmp,gsel,&goto_sel,contextptr);
6378 if (addarg){
6379 xcas::eqw_select_down(eq.data);
6380 xcas::eqw_select_leftright(eq,false,0,contextptr);
6381 }
6382 eqdata=xcas::Equation_total_size(eq.data);
6383 dx=(eqdata.dx-LCD_WIDTH_PX)/2;
6384 dy=LCD_HEIGHT_PX-2*margin+eqdata.y;
6385 firstrun=-1; // workaround, force 2 times display
6386 }
6387 }
6388 } // if (op.type==_FUNC)
6389
6390 } // if adjust_xy
6391 } // if (adds)
6392 }
6393 //*logptr(contextptr) << eq.data << endl;
6394 }
6395
clear_turtle_history(GIAC_CONTEXT)6396 void clear_turtle_history(GIAC_CONTEXT){
6397 history_in(contextptr).clear();
6398 history_out(contextptr).clear();
6399 turtle_stack()=vector<logo_turtle>(1,logo_turtle());
6400 }
6401
do_restart(GIAC_CONTEXT)6402 void do_restart(GIAC_CONTEXT){
6403 if (contextptr){
6404 if (contextptr->globalcontextptr && contextptr->globalcontextptr->tabptr)
6405 contextptr->globalcontextptr->tabptr->clear();
6406 }
6407 else
6408 _restart(0,contextptr);
6409 }
do_run(const char * s,gen & g,gen & ge,const context * & contextptr)6410 void do_run(const char * s,gen & g,gen & ge,const context * & contextptr){
6411 warn_nr=os_shell=true;
6412 if (!contextptr)
6413 contextptr=new giac::context;
6414 if (!strcmp(s,"restart")){
6415 clear_turtle_history(contextptr);
6416 do_restart(contextptr);
6417 return;
6418 }
6419 int S=strlen(s);
6420 char buf[S+1];
6421 buf[S]=0;
6422 for (int i=0;i<S;++i){
6423 char c=s[i];
6424 if (c==0x1e || c==char(0x9c))
6425 buf[i]='\n';
6426 else {
6427 if (c==0x0d)
6428 buf[i]=' ';
6429 else
6430 buf[i]=c;
6431 }
6432 }
6433 g=gen(buf,contextptr);
6434 //Console_Output(g.print(contextptr).c_str()); return ;
6435 giac::freeze=false;
6436 // execution_in_progress = 1;
6437 set_abort();
6438 ge=protecteval(equaltosto(g,contextptr),1,contextptr);
6439 clear_abort();
6440 // execution_in_progress = 0;
6441 if (esc_flag || ctrl_c){
6442 esc_flag=ctrl_c=interrupted=false;
6443 while (confirm("Interrupted","OK",true)==-1)
6444 ; // insure ON has been removed from keyboard buffer
6445 ge=string2gen("Interrupted",false);
6446 // memory full?
6447 if (!kbd_interrupted){
6448 // clear turtle, display msg
6449 clear_turtle_history(contextptr);
6450 int res=confirm((lang==1)?"Memoire remplie! Purger":"Memory full. Purge",
6451 #ifdef NSPIRE_NEWLIB
6452 (lang==1)?"enter: variable, esc: tout.":"enter: variables, esc: all",
6453 #else
6454 (lang==1)?"EXE variable, Back: tout.":"EXE variables, Back: all",
6455 #endif
6456 false);
6457 if (res==KEY_CTRL_F1 && select_var(contextptr).type==_IDNT){
6458 size_t savestackptr = stackptr;
6459 #ifdef x86_64
6460 stackptr=0xffffffffffffffff;
6461 #else
6462 stackptr=0xffffffff;
6463 #endif
6464 _purge(g,contextptr);
6465 stackptr=savestackptr;
6466 }
6467 else
6468 do_restart(contextptr);
6469 }
6470 }
6471 //Console_Output("Done"); return ;
6472 esc_flag=0;
6473 giac::ctrl_c=false;
6474 giac::kbd_interrupted=giac::interrupted=false;
6475 }
6476
6477 #ifdef NSPIRE_LED
6478 #include "kled.cc"
6479 #else
set_exam_mode(int i,GIAC_CONTEXT)6480 void set_exam_mode(int i,GIAC_CONTEXT){
6481 exam_mode=i;
6482 }
6483 #endif
print_duration(double & duration)6484 string print_duration(double & duration){
6485 if (duration<=0)
6486 return "";
6487 int s=std::floor(duration+.5);
6488 int h=s/3600;
6489 int m=((s+30)%3600)/60;
6490 char ch[6]="00h00";
6491 ch[0] += h/10;
6492 ch[1] += h%10;
6493 ch[3] += m/10;
6494 ch[4] += m%10;
6495 duration=h+m/100.0;
6496 return ch;
6497 }
islogo(const gen & g)6498 bool islogo(const gen & g){
6499 if (g.type!=_VECT || g._VECTptr->empty()) return false;
6500 if (g.subtype==_LOGO__VECT) return true;
6501 const vecteur & v=*g._VECTptr;
6502 if (islogo(v.back()))
6503 return true;
6504 for (size_t i=0;i<v.size();++i){
6505 if (v[i].type==_VECT && v[i].subtype==_LOGO__VECT)
6506 return true;
6507 }
6508 return false;
6509 }
6510
6511
eqws(char * s,bool eval,GIAC_CONTEXT)6512 int eqws(char * s,bool eval,GIAC_CONTEXT){ // s buffer must be at least 512 char
6513 gen g,ge;
6514 int dconsole_save=dconsole_mode;
6515 int ss=strlen(s);
6516 for (int i=0;i<ss;++i){
6517 if (s[i]==char(0x9c))
6518 s[i]='\n';
6519 }
6520 if (ss>=2 && (s[0]=='#' || s[0]=='"' ||
6521 (s[0]=='/' && (s[1]=='/' || s[1]=='*'))
6522 ))
6523 return textedit(s,giacmax(512,ss),contextptr);
6524 dconsole_mode=0;
6525 if (eval)
6526 do_run(s,g,ge,contextptr);
6527 else {
6528 if (s[0]==0)
6529 ge=0;
6530 else
6531 ge=gen(s,contextptr);
6532 }
6533 dconsole_mode=dconsole_save;
6534 if (is_undef(ge))
6535 return textedit(s,giacmax(512,ss),contextptr);
6536 if (ge.type==giac::_SYMB || (ge.type==giac::_VECT && !ge._VECTptr->empty() && !is_numericv(*ge._VECTptr)) ){
6537 if (islogo(ge)){
6538 if (displaylogo()==KEY_SHUTDOWN)
6539 return KEY_SHUTDOWN;
6540 return 0;
6541 }
6542 if (ispnt(ge)){
6543 if (displaygraph(ge,contextptr)==KEY_SHUTDOWN)
6544 return KEY_SHUTDOWN;
6545 // aborttimer = Timer_Install(0, check_execution_abort, 100); if (aborttimer > 0) { Timer_Start(aborttimer); }
6546 return 0;
6547 }
6548 if (ge.is_symb_of_sommet(at_program))
6549 return textedit(s,giacmax(ss,512),contextptr);
6550 if (taille(ge,256)>=256)
6551 return 0;
6552 }
6553 gen tmp=eqw(ge,true,contextptr);
6554 if (is_undef(tmp) || tmp==ge || taille(ge,64)>=64)
6555 return 0;
6556 string S(tmp.print(contextptr));
6557 if (S.size()>=512)
6558 return 0;
6559 strcpy(s,S.c_str());
6560 return 1;
6561 }
6562
6563
6564 #define GIAC_TEXTAREA 1
6565 #if GIAC_TEXTAREA
6566 textArea * edptr=0;
6567 #ifdef SCROLLBAR
6568 typedef scrollbar TScrollbar;
6569 #endif
6570
get_line_number(const char * msg1,const char * msg2)6571 int get_line_number(const char * msg1,const char * msg2){
6572 string s;
6573 int res=inputline(msg1,msg2,s,false);
6574 if (res==KEY_CTRL_EXIT)
6575 return 0;
6576 res=strtol(s.c_str(),0,10);
6577 return res;
6578 }
6579
warn_python(int mode,bool autochange)6580 void warn_python(int mode,bool autochange){
6581 if (mode==0)
6582 confirm(autochange?((lang==1)?"Source en syntaxe Xcas detecte.":"Xcas syntax source code detected."):((lang==1)?"Syntaxe Xcas.":"Xcas syntax."),
6583 #ifdef NSPIRE_NEWLIB
6584 "enter: ok"
6585 #else
6586 "OK: ok"
6587 #endif
6588 );
6589 if (mode==1)
6590 if (autochange)
6591 confirm((lang==1)?"Source en syntaxe Python. Passage":"Python syntax source detected. Setting",
6592 #ifdef NSPIRE_NEWLIB
6593 (lang==1)?"en Python avec ^=**, enter: ok":"Python mode with ^=**, enter:ok"
6594 #else
6595 (lang==1)?"en Python avec ^=**, OK: ok":"Python mode with ^=**, OK:ok"
6596 #endif
6597 );
6598 else
6599 confirm((lang==1)?"Syntaxe Python avec ^==**, tapez":"Python syntax with ^==**, type",
6600 #ifdef NSPIRE_NEWLIB
6601 (lang==1)?"python_compat(2) pour xor. enter: ok":"python_compat(2) for xor. enter: ok"
6602 #else
6603 (lang==1)?"python_compat(2) pour xor. OK: ok":"python_compat(2) for xor. OK: ok"
6604 #endif
6605 );
6606 if (mode==2){
6607 confirm((lang==1)?"Syntaxe Python avec ^==xor":"Python syntax with ^==xor",
6608 #ifdef NSPIRE_NEWLIB
6609 (lang==1)?"python_compat(1) pour **. enter: ok":"python_compat(1) for **. enter: ok"
6610 #else
6611 (lang==1)?"python_compat(1) pour **. OK: ok":"python_compat(1) for **. OK: ok"
6612 #endif
6613 );
6614 }
6615 if (mode & 4){
6616 confirm((lang==1)?"Interpreteur MicroPython":"MicroPython interpreter",
6617 #ifdef NSPIRE_NEWLIB
6618 (lang==1)?"enter: ok":"enter: ok"
6619 #else
6620 (lang==1)?"OK: ok":"OK: ok"
6621 #endif
6622 );
6623 }
6624 }
6625
check_do_graph(giac::gen & ge,int do_logo_graph_eqw,GIAC_CONTEXT)6626 int check_do_graph(giac::gen & ge,int do_logo_graph_eqw,GIAC_CONTEXT) {
6627 if (ge.type==giac::_SYMB || (ge.type==giac::_VECT && !ge._VECTptr->empty() && !is_numericv(*ge._VECTptr)) ){
6628 if (islogo(ge)){
6629 if (do_logo_graph_eqw & 4){
6630 if (displaylogo()==KEY_SHUTDOWN)
6631 return KEY_SHUTDOWN;
6632 }
6633 return 0;
6634 }
6635 if (ispnt(ge)){
6636 if (do_logo_graph_eqw & 2){
6637 if (displaygraph(ge,contextptr)==KEY_SHUTDOWN)
6638 return KEY_SHUTDOWN;
6639 }
6640 // aborttimer = Timer_Install(0, check_execution_abort, 100); if (aborttimer > 0) { Timer_Start(aborttimer); }
6641 return 0;
6642 }
6643 if ( do_logo_graph_eqw % 2 ==0)
6644 return 0;
6645 if (taille(ge,256)>=256 || ge.is_symb_of_sommet(at_program))
6646 return 0; // sizeof(eqwdata)=44
6647 gen tmp=eqw(ge,false,contextptr);
6648 if (!is_undef(tmp) && tmp!=ge){
6649 //dConsolePutChar(147);
6650 *giac::logptr(contextptr) << ge.print(contextptr) << '\n';
6651 ge=tmp;
6652 }
6653 }
6654 return 0;
6655 }
6656
process_freeze()6657 void process_freeze(){
6658 if (freezeturtle){
6659 displaylogo();
6660 freezeturtle=false;
6661 return;
6662 }
6663 if (giac::freeze){
6664 giac::freeze=false;
6665 #ifdef NSPIRE_NEWLIB
6666 DefineStatusMessage((char*)((lang==1)?"Ecran fige. Taper esc":"Screen freezed. Press esc."), 1, 0, 0);
6667 #else
6668 DefineStatusMessage((char*)((lang==1)?"Ecran fige. Taper EXIT":"Screen freezed. Press EXIT."), 1, 0, 0);
6669 #endif
6670 DisplayStatusArea();
6671 for (;;){
6672 int key;
6673 GetKey(&key);
6674 if (key==KEY_CTRL_EXIT)
6675 break;
6676 }
6677 }
6678 }
6679
6680 // called from editor, return
check_parse(textArea * text,const std::vector<textElement> & v,int python,GIAC_CONTEXT)6681 int check_parse(textArea * text,const std::vector<textElement> & v,int python,GIAC_CONTEXT){
6682 if (v.empty())
6683 return 0;
6684 char status[256];
6685 for (int i=0;i<sizeof(status);++i)
6686 status[i]=0;
6687 int shift=0;
6688 #ifdef MICROPY_LIB
6689 if (xcas_python_eval==1){
6690 #if 0
6691 if (text->changed){
6692 std::string tmp=text->filename;
6693 tmp += (lang==1)?" a ete modifie!":" was modified!";
6694 if (confirm(tmp.c_str(),
6695 #ifdef NSPIRE_NEWLIB
6696 (lang==1)?"enter: sauvegarder, esc: tant pis":"enter: save, esc: discard changes"
6697 #else
6698 (lang==1)?"OK: sauvegarder, Back: tant pis":"OK: save, Back: discard changes"
6699 #endif
6700 )==KEY_CTRL_F1){
6701 save_script(text->filename.c_str(),merge_area(text->elements));
6702 text->changed=false;
6703 }
6704 }
6705 string tmp="from "+remove_extension(text->filename)+" import *"; // os error 2 ??
6706 micropy_eval(tmp.c_str());
6707 #else
6708 freezeturtle=false;
6709 // newlines do not work correctly unless we cut the input
6710 for (int i=0;i<=v.size();++i){
6711 if (i==v.size() || (v[i].s.size() && v[i].s[0]!=' ')){
6712 string s=merge_area(vector<textElement>(v.begin()+shift,v.begin()+i));
6713 micropy_eval(s.c_str());
6714 if (parser_errorline>0){
6715 parser_errorline += shift;
6716 break;
6717 }
6718 shift=i;
6719 }
6720 }
6721 #endif
6722 // should detect syntax errors here and return line number
6723 if (parser_errorline>0){
6724 //--parser_errorline; // ?? something strange
6725 sprintf(status,(lang==1)?"Erreur ligne %i (esc + d'info avec no de ligne decale de %i)":"Error line %i (esc more details with linenumber shifted by %i)",parser_errorline,shift);
6726 }
6727 else {
6728 process_freeze();
6729 sprintf(status,"%s",(lang==1)?"Syntaxe correcte":"Parse OK");
6730 }
6731 DefineStatusMessage(status,1,0,0);
6732 return parser_errorline;
6733 }
6734 #endif
6735 std::string s=merge_area(v);
6736 giac::python_compat(python,contextptr);
6737 if (python) s="@@"+s; // force Python translation
6738 freeze=true;
6739 giac::gen g(s,contextptr);
6740 freeze=false;
6741 int lineerr=giac::first_error_line(contextptr);
6742 if (lineerr){
6743 std::string tok=giac::error_token_name(contextptr);
6744 int pos=-1;
6745 if (lineerr>=1 && lineerr<=v.size()){
6746 pos=v[lineerr-1].s.find(tok);
6747 const std::string & err=v[lineerr-1].s;
6748 if (pos>=err.size())
6749 pos=-1;
6750 if (python){
6751 // find 1st token, check if it's def/if/elseif/for/while
6752 size_t i=0,j=0;
6753 for (;i<err.size();++i){
6754 if (err[i]!=' ')
6755 break;
6756 }
6757 std::string firsterr;
6758 for (j=i;j<err.size();++j){
6759 if (!isalpha(err[j]))
6760 break;
6761 firsterr += err[j];
6762 }
6763 // if there is no : at end set pos=-2
6764 if (firsterr=="for" || firsterr=="def" || firsterr=="if" || firsterr=="elseif" || firsterr=="while"){
6765 for (i=err.size()-1;i>0;--i){
6766 if (err[i]!=' ')
6767 break;
6768 }
6769 if (err[i]!=':')
6770 pos=-2;
6771 }
6772 }
6773 }
6774 else {
6775 lineerr=v.size();
6776 tok=(lang==1)?"la fin":"end";
6777 pos=0;
6778 }
6779 if (pos>=0)
6780 sprintf(status,(lang==1)?"Erreur ligne %i a %s":"Error line %i at %s",lineerr,tok.c_str());
6781 else
6782 sprintf(status,(lang==1)?"Erreur ligne %i %s":"Error line %i %s",lineerr,(pos==-2?((lang==1)?", : manquant ?":", missing :?"):""));
6783 DefineStatusMessage(status,1,0,0);
6784 }
6785 else {
6786 set_abort();
6787 g=protecteval(g,1,contextptr);
6788 clear_abort();
6789 giac::ctrl_c=false;
6790 kbd_interrupted=giac::interrupted=false;
6791 // define the function
6792 if (check_do_graph(g,7,contextptr)==KEY_SHUTDOWN)
6793 return KEY_SHUTDOWN;
6794 DefineStatusMessage((char *)((lang==1)?"Syntaxe correcte":"Parse OK"),1,0,0);
6795 }
6796 DisplayStatusArea();
6797 return lineerr;
6798 }
6799
fix_newlines(textArea * edptr)6800 void fix_newlines(textArea * edptr){
6801 edptr->elements[0].newLine=0;
6802 for (size_t i=1;i<edptr->elements.size();++i){
6803 edptr->elements[i].newLine=1;
6804 }
6805 }
6806
fix_mini(textArea * edptr)6807 void fix_mini(textArea * edptr){
6808 bool minimini=edptr->elements[0].minimini;
6809 for (size_t i=1;i<edptr->elements.size();++i){
6810 edptr->elements[i].minimini=minimini;
6811 }
6812 }
6813
end_do_then(const std::string & s)6814 int end_do_then(const std::string & s){
6815 // skip spaces from end
6816 int l=s.size(),i,i0;
6817 const char * ptr=s.c_str();
6818 for (i=l-1;i>0;--i){
6819 if (ptr[i]!=' '){
6820 if (ptr[i]==':' || ptr[i]=='{')
6821 return 1;
6822 if (ptr[i]=='}')
6823 return -1;
6824 break;
6825 }
6826 }
6827 if (i>0){
6828 for (i0=i;i0>=0;--i0){
6829 if (!isalphanum(ptr[i0]) && ptr[i0]!=';' && ptr[i0]!=':')
6830 break;
6831 }
6832 if (i>i0+2){
6833 if (ptr[i]==';')
6834 --i;
6835 if (ptr[i]==':')
6836 --i;
6837 }
6838 std::string keyw(ptr+i0+1,ptr+i+1);
6839 const char * ptr=keyw.c_str();
6840 if (strcmp(ptr,"faire")==0 || strcmp(ptr,"do")==0 || strcmp(ptr,"alors")==0 || strcmp(ptr,"then")==0)
6841 return 1;
6842 if (strcmp(ptr,"fsi")==0 || strcmp(ptr,"end")==0 || strcmp(ptr,"fi")==0 || strcmp(ptr,"od")==0 || strcmp(ptr,"ftantque")==0 || strcmp(ptr,"fpour")==0 || strcmp(ptr,"ffonction")==0 || strcmp(ptr,"ffunction")==0)
6843 return -1;
6844 }
6845 return 0;
6846 }
6847
add(textArea * edptr,const std::string & s)6848 void add(textArea *edptr,const std::string & s){
6849 int r=1;
6850 for (size_t i=0;i<s.size();++i){
6851 if (s[i]=='\n' || s[i]==char(0x9c))
6852 ++r;
6853 }
6854 edptr->elements.reserve(edptr->elements.size()+r);
6855 textElement cur;
6856 cur.lineSpacing=2;
6857 for (size_t i=0;i<s.size();++i){
6858 char c=s[i];
6859 if (c!='\n' && c!=char(0x9c)){
6860 if (c!=char(0x0d))
6861 cur.s += c;
6862 continue;
6863 }
6864 string tmp=string(cur.s.begin(),cur.s.end());
6865 cur.s.swap(tmp);
6866 edptr->elements.push_back(cur);
6867 ++edptr->line;
6868 cur.s="";
6869 }
6870 if (cur.s.size()){
6871 edptr->elements.push_back(cur);
6872 ++edptr->line;
6873 }
6874 fix_newlines(edptr);
6875 }
6876
find_indentation(const std::string & s)6877 int find_indentation(const std::string & s){
6878 size_t indent=0;
6879 for (;indent<s.size();++indent){
6880 if (s[indent]!=' ')
6881 break;
6882 }
6883 return indent;
6884 }
6885
add_indented_line(std::vector<textElement> & v,int & textline,int & textpos)6886 void add_indented_line(std::vector<textElement> & v,int & textline,int & textpos){
6887 // add line
6888 v.insert(v.begin()+textline+1,v[textline]);
6889 std::string & s=v[textline].s;
6890 int indent=find_indentation(s);
6891 if (!s.empty())
6892 indent += 2*end_do_then(s);
6893 //cout << indent << s << ":" << endl;
6894 if (indent<0)
6895 indent=0;
6896 v[textline+1].s=std::string(indent,' ')+s.substr(textpos,s.size()-textpos);
6897 v[textline+1].newLine=1;
6898 v[textline].s=s.substr(0,textpos);
6899 ++textline;
6900 v[textline].nlines=1; // will be recomputed by cursor moves
6901 textpos=indent;
6902 }
6903
undo(textArea * text)6904 void undo(textArea * text){
6905 if (text->undoelements.empty())
6906 return;
6907 giac::swapint(text->line,text->undoline);
6908 giac::swapint(text->pos,text->undopos);
6909 giac::swapint(text->clipline,text->undoclipline);
6910 giac::swapint(text->clippos,text->undoclippos);
6911 swap(text->elements,text->undoelements);
6912 }
6913
set_undo(textArea * text)6914 void set_undo(textArea * text){
6915 text->changed=true;
6916 text->undoelements=text->elements;
6917 text->undopos=text->pos;
6918 text->undoline=text->line;
6919 text->undoclippos=text->clippos;
6920 text->undoclipline=text->clipline;
6921 }
6922
add_nl(textArea * text,const std::string & ins)6923 void add_nl(textArea * text,const std::string & ins){
6924 std::vector<textElement> & v=text->elements;
6925 std::vector<textElement> w(v.begin()+text->line+1,v.end());
6926 v.erase(v.begin()+text->line+1,v.end());
6927 add(text,ins);
6928 for (size_t i=0;i<w.size();++i)
6929 v.push_back(w[i]);
6930 fix_newlines(text);
6931 text->changed=true;
6932 }
6933
insert(textArea * text,const char * adds,bool indent)6934 void insert(textArea * text,const char * adds,bool indent){
6935 size_t n=strlen(adds),i=0;
6936 if (!n)
6937 return;
6938 set_undo(text);
6939 int l=text->line;
6940 if (l<0 || l>=text->elements.size())
6941 return; // invalid line number
6942 std::string & s=text->elements[l].s;
6943 int ss=int(s.size());
6944 int & pos=text->pos;
6945 if (pos>ss)
6946 pos=ss;
6947 std::string ins=s.substr(0,pos);
6948 for (;i<n;++i){
6949 if (adds[i]=='\n' || adds[i]==0x1e) {
6950 break;
6951 }
6952 else {
6953 if (adds[i]!=char(0x0d))
6954 ins += adds[i];
6955 }
6956 }
6957 if (i==n){ // no newline in inserted string
6958 s=ins+s.substr(pos,ss-pos);
6959 pos += n;
6960 return;
6961 }
6962 std::string S(adds+i+1);
6963 int decal=ss-pos;
6964 S += s.substr(pos,decal);
6965 // cout << S << " " << ins << endl;
6966 s=ins;
6967 if (indent){
6968 pos=s.size();
6969 int debut=0;
6970 for (i=0;i<S.size();++i){
6971 if (S[i]=='\n' || S[i]==0x1e){
6972 add_indented_line(text->elements,text->line,pos);
6973 // cout << S.substr(debut,i-debut) << endl;
6974 text->elements[text->line].s += S.substr(debut,i-debut);
6975 pos = text->elements[text->line].s.size();
6976 debut=i+1;
6977 }
6978 }
6979 //cout << S << " " << debut << " " << i << S.c_str()+debut << endl;
6980 add_indented_line(text->elements,text->line,pos);
6981 text->elements[text->line].s += (S.c_str()+debut);
6982 fix_newlines(text);
6983 }
6984 else
6985 add_nl(text,S);
6986 pos = text->elements[text->line].s.size()-decal;
6987 fix_mini(text);
6988 }
6989
merge_area(const std::vector<textElement> & v)6990 std::string merge_area(const std::vector<textElement> & v){
6991 std::string s;
6992 size_t l=0;
6993 for (size_t i=0;i<v.size();++i)
6994 l += v[i].s.size()+1;
6995 s.reserve(l);
6996 for (size_t i=0;i<v.size();++i){
6997 s += v[i].s;
6998 s += '\n';
6999 }
7000 return s;
7001 }
7002
isalphanum(char c)7003 bool isalphanum(char c){
7004 return isalpha(c) || (c>='0' && c<='9');
7005 }
7006
search_msg()7007 void search_msg(){
7008 #ifdef NSPIRE_NEWLIB
7009 DefineStatusMessage((char *)((lang==1)?"enter: suivant, DEL: annuler":"enter: next, DEL: cancel"),1,0,0);
7010 #else
7011 DefineStatusMessage((char *)((lang==1)?"enter: suivant, DEL: annuler":"enter: next, DEL: cancel"),1,0,0);
7012 #endif
7013 DisplayStatusArea();
7014 }
7015
7016
show_status(textArea * text,const std::string & search,const std::string & replace)7017 void show_status(textArea * text,const std::string & search,const std::string & replace){
7018 if (text->editable && text->clipline>=0)
7019 DefineStatusMessage((char *)"PAD: select, COPY: copy, DEL: cut",1,0,0);
7020 else {
7021 std::string status;
7022 #ifdef GIAC_SHOWTIME
7023 int d=(int(millis()/60000) +time_shift) % (24*60); // minutes
7024 int heure=d/60;
7025 int minute=d%60;
7026 status += char('0'+heure/10);
7027 status += char('0'+(heure%10));
7028 status += ':';
7029 status += char('0'+(minute/10));
7030 status += char('0'+(minute%10));
7031 #endif
7032 if (text->editable){
7033 #ifndef NSPIRE_NEWLIB
7034 status += (xthetat?" t":" x");
7035 #endif
7036 if (text->python & 4)
7037 status += " MicroPython ";
7038 else
7039 status += text->python?(text->python==2?" Py ^xor ":" Py ^=** "):" Xcas ";
7040 status += giac::remove_extension(text->filename.c_str());
7041 status += text->changed?" * ":" - ";
7042 status += giac::printint(text->line+1);
7043 status += '/';
7044 status += giac::printint(text->elements.size());
7045 }
7046 if (search.size()){
7047 #ifdef NSPIRE_NEWLIB
7048 status += " enter: " + search;
7049 #else
7050 status += " EXE: " + search;
7051 #endif
7052 if (replace.size())
7053 status += "->"+replace;
7054 }
7055 DefineStatusMessage((char *)status.c_str(), 1, 0, 0);
7056 }
7057 DisplayStatusArea();
7058 }
7059
chk_replace(textArea * text,const std::string & search,const std::string & replace)7060 bool chk_replace(textArea * text,const std::string & search,const std::string & replace){
7061 if (replace.size()){
7062 #ifdef NSPIRE_NEWLIB
7063 DefineStatusMessage((char *)((lang==1)?"Remplacer? enter: Oui, 8 ou N: Non":"Replace? enter: Yes, 8 or N: No"),1,0,0);
7064 #else
7065 DefineStatusMessage((char *)((lang==1)?"Remplacer? EXE: Oui, 8 ou N: Non":"Replace? EXE: Yes, 8 or N: No"),1,0,0);
7066 #endif
7067 }
7068 else
7069 search_msg();
7070 DisplayStatusArea();
7071 for (;;){
7072 int key;
7073 GetKey(&key);
7074 if (key==KEY_CHAR_MINUS || key==KEY_CHAR_Y || key==KEY_CHAR_9 || key==KEY_CHAR_O || key==KEY_CTRL_EXE || key==KEY_CTRL_OK){
7075 if (replace.size()){
7076 set_undo(text);
7077 std::string & s = text->elements[text->line].s;
7078 s=s.substr(0,text->pos-search.size())+replace+s.substr(text->pos,s.size()-text->pos);
7079 search_msg();
7080 }
7081 return true;
7082 }
7083 if (key==KEY_CTRL_DEL || (replace.empty() && key==KEY_CTRL_EXIT) || key==KEY_CTRL_LEFT || key==KEY_CTRL_RIGHT || key==KEY_CTRL_UP || key==KEY_CTRL_DOWN){
7084 show_status(text,search,replace);
7085 return false;
7086 }
7087 if (key==KEY_CHAR_8 || key==KEY_CHAR_N || key==KEY_CTRL_EXIT){
7088 search_msg();
7089 return true;
7090 }
7091 }
7092 }
7093
check_leave(textArea * text)7094 int check_leave(textArea * text){
7095 if (text->editable && text->filename.size()){
7096 if (text->changed){
7097 // save or cancel?
7098 std::string tmp=text->filename;
7099 if (strcmp(tmp.c_str(),"temp.py")==0){
7100 if (confirm((lang==1)?"Les modifications seront perdues":"Changes will be lost",
7101 #ifdef NSPIRE_NEWLIB
7102 (lang==1)?"enter: annuler, esc: tant pis":"enter: cancel, esc: confirm"
7103 #else
7104 (lang==1)?"OK: annuler, Back: tant pis":"OK: cancel, Back: confirm"
7105 #endif
7106 )==KEY_CTRL_F1)
7107 return 2;
7108 else {
7109 return 0;
7110 }
7111 }
7112 tmp += (lang==1)?" a ete modifie!":" was modified!";
7113 if (confirm(tmp.c_str(),
7114 #ifdef NSPIRE_NEWLIB
7115 (lang==1)?"enter: sauvegarder, esc: tant pis":"enter: save, esc: discard changes"
7116 #else
7117 (lang==1)?"OK: sauvegarder, Back: tant pis":"OK: save, Back: discard changes"
7118 #endif
7119 )==KEY_CTRL_F1){
7120 save_script(text->filename.c_str(),merge_area(text->elements));
7121 text->changed=false;
7122 return 1;
7123 }
7124 return 0;
7125 }
7126 return 1;
7127 }
7128 return 0;
7129 }
7130
print(int & X,int & Y,const char * buf,int color,bool revert,bool fake,bool minimini)7131 void print(int &X,int&Y,const char * buf,int color,bool revert,bool fake,bool minimini){
7132 if(minimini)
7133 X=PrintMiniMini(X, Y, buf, revert?4:0, color, COLOR_WHITE,fake);
7134 else
7135 X=PrintMini(X, Y, buf, revert?4:0, color, COLOR_WHITE, fake);
7136 }
7137
match_print(char * singleword,int delta,int X,int Y,bool match,bool minimini)7138 void match_print(char * singleword,int delta,int X,int Y,bool match,bool minimini){
7139 // char buflog[128];sprintf(buflog,"%i %i %s ",delta,(int)match,singleword);puts(buflog);
7140 char ch=singleword[delta];
7141 singleword[delta]=0;
7142 print(X,Y,singleword,0,false,/* fake*/true,minimini);
7143 singleword[delta]=ch;
7144 char buf[4];
7145 buf[0]=ch;
7146 buf[1]=0;
7147 // inverted print: colors are reverted too!
7148 int color;
7149 if (minimini)
7150 color=match?TEXT_COLOR_GREEN:TEXT_COLOR_RED;
7151 else
7152 color=match?COLOR_GREEN:COLOR_RED;
7153 print(X,Y,buf,color,true,/*fake*/false,minimini);
7154 }
7155
match(textArea * text,int pos,int & line1,int & pos1,int & line2,int & pos2)7156 bool match(textArea * text,int pos,int & line1,int & pos1,int & line2,int & pos2){
7157 line2=-1;line1=-1;
7158 int linepos=text->line;
7159 const std::vector<textElement> & v=text->elements;
7160 if (linepos<0 || linepos>=v.size()) return false;
7161 const std::string * s=&v[linepos].s;
7162 int ss=s->size();
7163 if (pos<0 || pos>=ss) return false;
7164 char ch=(*s)[pos];
7165 int open1=0,open2=0,open3=0,inc=0;
7166 if (ch=='(' || ch=='['
7167 || ch=='{'
7168 ){
7169 line1=linepos;
7170 pos1=pos;
7171 inc=1;
7172 }
7173 if (
7174 ch=='}' ||
7175 ch==']' || ch==')'
7176 ){
7177 line2=linepos;
7178 pos2=pos;
7179 inc=-1;
7180 }
7181 if (!inc) return false;
7182 bool instring=false;
7183 for (;;){
7184 for (;pos>=0 && pos<ss;pos+=inc){
7185 if ((*s)[pos]=='"' && (pos==0 || (*s)[pos-1]!='\\'))
7186 instring=!instring;
7187 if (instring)
7188 continue;
7189 switch ((*s)[pos]){
7190 case '(':
7191 open1++;
7192 break;
7193 case '[':
7194 open2++;
7195 break;
7196 case '{':
7197 open3++;
7198 break;
7199 case ')':
7200 open1--;
7201 break;
7202 case ']':
7203 open2--;
7204 break;
7205 case '}':
7206 open3--;
7207 break;
7208 }
7209 if (open1==0 && open2==0 && open3==0){
7210 //char buf[128];sprintf(buf,"%i %i",pos_orig,pos);puts(buf);
7211 if (inc>0){
7212 line2=linepos; pos2=pos;
7213 }
7214 else {
7215 line1=linepos; pos1=pos;
7216 }
7217 return true;
7218 } // end if
7219 } // end for pos
7220 linepos+=inc;
7221 if (linepos<0 || linepos>=v.size())
7222 return false;
7223 s=&v[linepos].s;
7224 ss=s->size();
7225 pos=inc>0?0:ss-1;
7226 } // end for linepos
7227 return false;
7228 }
7229
get_selection(textArea * text,bool erase)7230 std::string get_selection(textArea * text,bool erase){
7231 int sel_line1,sel_line2,sel_pos1,sel_pos2;
7232 int clipline=text->clipline,clippos=text->clippos,textline=text->line,textpos=text->pos;
7233 if (clipline>=0){
7234 if (clipline<textline || (clipline==textline && clippos<textpos)){
7235 sel_line1=clipline;
7236 sel_line2=textline;
7237 sel_pos1=clippos;
7238 sel_pos2=textpos;
7239 }
7240 else {
7241 sel_line1=textline;
7242 sel_line2=clipline;
7243 sel_pos1=textpos;
7244 sel_pos2=clippos;
7245 }
7246 }
7247 std::string s(text->elements[sel_line1].s);
7248 if (erase){
7249 set_undo(text);
7250 text->line=sel_line1;
7251 text->pos=sel_pos1;
7252 text->elements[sel_line1].s=s.substr(0,sel_pos1)+text->elements[sel_line2].s.substr(sel_pos2,text->elements[sel_line2].s.size()-sel_pos2);
7253 }
7254 if (sel_line1==sel_line2){
7255 return s.substr(sel_pos1,sel_pos2-sel_pos1);
7256 }
7257 s=s.substr(sel_pos1,s.size()-sel_pos1)+'\n';
7258 int sel_line1_=sel_line1;
7259 for (sel_line1++;sel_line1<sel_line2;sel_line1++){
7260 s += text->elements[sel_line1].s;
7261 s += '\n';
7262 }
7263 s += text->elements[sel_line2].s.substr(0,sel_pos2);
7264 if (erase)
7265 text->elements.erase(text->elements.begin()+sel_line1_+1,text->elements.begin()+sel_line2+1);
7266 return s;
7267 }
7268
change_mode(textArea * text,int flag,GIAC_CONTEXT)7269 void change_mode(textArea * text,int flag,GIAC_CONTEXT){
7270 if (bool(text->python)!=bool(flag)){
7271 text->python=flag;
7272 python_compat(text->python,contextptr);
7273 show_status(text,"","");
7274 warn_python(flag,true);
7275 }
7276 }
7277
clearLine(int x,int y,color_t color=_WHITE)7278 void clearLine(int x, int y, color_t color=_WHITE) {
7279 // clear text line. x and y are text cursor coordinates
7280 // this is meant to achieve the same effect as using PrintXY with a line full of spaces (except it doesn't waste strings).
7281 int width=LCD_WIDTH_PX;
7282 if(x>1) width = 24*(21-x);
7283 drawRectangle((x-1)*18, y*24, width, 24, color);
7284 }
7285
mPrintXY(int x,int y,char * msg,int mode,int color)7286 void mPrintXY(int x, int y, char*msg, int mode, int color) {
7287 char nmsg[50];
7288 nmsg[0] = 0x20;
7289 nmsg[1] = 0x20;
7290 nmsg[2] = '\0';
7291 strncat(nmsg, msg, 48);
7292 PrintXY(x, y, nmsg, mode ,color);
7293 }
7294
drawScreenTitle(char * title,char * subtitle=0)7295 void drawScreenTitle(char* title, char* subtitle=0) {
7296 if(title != NULL) mPrintXY(1, 1, title, TEXT_MODE_NORMAL, TEXT_COLOR_BLUE);
7297 if(subtitle != NULL) mPrintXY(1, 2, subtitle, TEXT_MODE_NORMAL, TEXT_COLOR_BLACK);
7298 }
7299
find_color(const char * s,GIAC_CONTEXT)7300 int find_color(const char * s,GIAC_CONTEXT){
7301 if (s[0]=='"')
7302 return 4;
7303 if (!isalpha(s[0]))
7304 return 0;
7305 char buf[256];
7306 const char * ptr=s;
7307 for (int i=0;i<255 && (isalphanum(*ptr) || *ptr=='_'); ++i){
7308 ++ptr;
7309 }
7310 strncpy(buf,s,ptr-s);
7311 buf[ptr-s]=0;
7312 if (strcmp(buf,"def")==0)
7313 return 1;
7314 //int pos=dichotomic_search(keywords,sizeof(keywords),buf);
7315 //if (pos>=0) return 1;
7316 gen g;
7317 int token=find_or_make_symbol(buf,g,0,false,contextptr);
7318 //*logptr(contextptr) << s << " " << buf << " " << token << " " << g << endl;
7319 if (token==T_UNARY_OP || token==T_UNARY_OP_38 || token==T_LOGO)
7320 return 3;
7321 if (token==T_NUMBER)
7322 return 2;
7323 if (token!=T_SYMBOL)
7324 return 1;
7325 return 0;
7326 }
7327
strncasecmp_duplicate(const char * s1,const char * s2,size_t n)7328 int strncasecmp_duplicate(const char *s1, const char *s2, size_t n)
7329 {
7330 if (n != 0) {
7331 const unsigned char *us1 = (const unsigned char *)s1;
7332 const unsigned char *us2 = (const unsigned char *)s2;
7333
7334 do {
7335 if (tolower(*us1) != tolower(*us2++))
7336 return (tolower(*us1) - tolower(*--us2));
7337 if (*us1++ == '\0')
7338 break;
7339 } while (--n != 0);
7340 }
7341 return (0);
7342 }
strcasestr_duplicate(const char * s,const char * find)7343 char *strcasestr_duplicate(const char *s, const char *find)
7344 {
7345 char c;
7346
7347 if ((c = *find++) != 0) {
7348 c = tolower((unsigned char)c);
7349 size_t len = strlen(find);
7350 do {
7351 char sc;
7352 do {
7353 if ((sc = *s++) == 0)
7354 return (NULL);
7355 } while ((char)tolower((unsigned char)sc) != c);
7356 } while (strncasecmp(s, find, len) != 0);
7357 s--;
7358 }
7359 return ((char *)s);
7360 }
7361
7362
7363 /* copy over the next token from an input string, WITHOUT
7364 skipping leading blanks. The token is terminated by the
7365 first appearance of tokchar, or by the end of the source
7366 string.
7367
7368 The caller must supply sufficient space in token to
7369 receive any token, Otherwise tokens will be truncated.
7370
7371 Returns: a pointer past the terminating tokchar.
7372
7373 This will happily return an infinity of empty tokens if
7374 called with src pointing to the end of a string. Tokens
7375 will never include a copy of tokchar.
7376
7377 A better name would be "strtkn", except that is reserved
7378 for the system namespace. Change to that at your risk.
7379
7380 released to Public Domain, by C.B. Falconer.
7381 Published 2006-02-20. Attribution appreciated.
7382 Modified by gbl08ma not to skip blanks at the beginning.
7383 */
7384
toksplit(const unsigned char * src,char tokchar,unsigned char * token,int lgh)7385 const unsigned char *toksplit(const unsigned char *src, /* Source of tokens */
7386 char tokchar, /* token delimiting char */
7387 unsigned char *token, /* receiver of parsed token */
7388 int lgh) /* length token can receive */
7389 /* not including final '\0' */
7390 {
7391 if (src) {
7392 while (*src && (tokchar != *src)) {
7393 if (lgh) {
7394 *token++ = *src;
7395 --lgh;
7396 }
7397 src++;
7398 }
7399 if (*src && (tokchar == *src)) src++;
7400 }
7401 *token = '\0';
7402 return src;
7403 } /* toksplit */
7404
7405
display(textArea * text,int & isFirstDraw,int & totalTextY,int & scroll,int & textY,GIAC_CONTEXT)7406 void display(textArea * text,int & isFirstDraw,int & totalTextY,int & scroll,int & textY,GIAC_CONTEXT){
7407 #ifdef CURSOR
7408 Cursor_SetFlashOff();
7409 #endif
7410 drawRectangle(text->x, text->y, LCD_WIDTH_PX, LCD_HEIGHT_PX-text->y, COLOR_WHITE);
7411 bool editable=text->editable;
7412 int showtitle = !editable && (text->title != NULL);
7413 std::vector<textElement> & v=text->elements;
7414 //drawRectangle(text->x, text->y+24, text->width, LCD_HEIGHT_PX-24, COLOR_WHITE);
7415 // insure cursor is visible
7416 if (editable && !isFirstDraw){
7417 int linesbefore=0,cur;
7418 for (cur=0;cur<text->line;++cur){
7419 linesbefore += (v[cur].newLine+(v[cur].nlines-1))*(text->lineHeight+v[cur].lineSpacing); //*logptr(contextptr) << cur << "," << v[cur].nlines << " ";
7420 }
7421 // line begin Y is at scroll+linesbefore*17, must be positive
7422 if (linesbefore+scroll<0)
7423 scroll = -linesbefore;
7424 linesbefore += (v[cur].newLine+(v[cur].nlines-1))*(text->lineHeight+v[cur].lineSpacing); //*logptr(contextptr) << '\n';
7425 // after line Y is at scroll+linesbefore*17
7426 if (linesbefore+scroll>148)
7427 scroll = 148-linesbefore;
7428 }
7429 textY = scroll+(showtitle ? 24 : 0)+text->y; // 24 pixels for title (or not)
7430 int deltax=0;
7431 if (editable){
7432 if (v.size()<10){
7433 deltax=9;
7434 }
7435 else {
7436 if (v.size()<100)
7437 deltax=18;
7438 else
7439 deltax=27;
7440 }
7441 }
7442 int & clipline=text->clipline;
7443 int & clippos=text->clippos;
7444 int & textline=text->line;
7445 int & textpos=text->pos;
7446 if (textline<0) textline=0;
7447 if (textline>=text->elements.size())
7448 textline=text->elements.size()-1;
7449 if (textpos<0) textpos=0;
7450 if (textpos>text->elements[textline].s.size())
7451 textpos=text->elements[textline].s.size();
7452 //char bufpos[512]; sprintf(bufpos,"%i,%i:%i,%i ",textpos,textline,text->elements[textline].s.size(),text->elements.size()); puts(bufpos);
7453 if (clipline>=0){
7454 if (clipline>=v.size())
7455 clipline=-1;
7456 else {
7457 if (clippos<0)
7458 clippos=0;
7459 if (clippos>=v[clipline].s.size())
7460 clippos=v[clipline].s.size()-1;
7461 }
7462 }
7463 int line1,line2,pos1=0,pos2=0;
7464 if (!match(text,text->pos,line1,pos1,line2,pos2) && line1==-1 && line2==-1)
7465 match(text,text->pos-1,line1,pos1,line2,pos2);
7466 //char bufpos[512]; sprintf(bufpos,"%i,%i:%i,%i ",line1,pos1,line2,pos2); puts(bufpos);
7467 for (int cur=0;cur < v.size();++cur) {
7468 const char* src = v[cur].s.c_str();
7469 if (cur==0){
7470 int l=v[cur].s.size();
7471 if (l>=1 && src[0]=='#')
7472 change_mode(text,1,contextptr); // text->python=true;
7473 if (l>=2 && src[0]=='/' && src[1]=='/')
7474 change_mode(text,0,contextptr); // text->python=false;
7475 if (l>=8 && src[0]=='f' && (src[1]=='o' || src[1]=='u') && src[2]=='n' && src[3]=='c' && src[4]=='t' && src[5]=='i' && src[6]=='o' && src[7]=='n')
7476 change_mode(text,0,contextptr); // text->python=false;
7477 if (l>=4 && src[0]=='d' && src[1]=='e' && src[2]=='f' && src[3]==' ')
7478 change_mode(text,1,contextptr); // text->python=true;
7479 //drawRectangle(text->x, text->y, text->width, LCD_HEIGHT_PX-(editable?17:0), COLOR_WHITE);
7480 }
7481 if (cur%4==0 && textY>=(showtitle?24:0))
7482 waitforvblank();
7483 int textX=text->x,saveY=textY;
7484 if(v[cur].newLine) {
7485 textY=textY+text->lineHeight+v[cur].lineSpacing;
7486 }
7487 if (!isFirstDraw && clipline==-1){
7488 // check if we can skip directly to the next line
7489 int y=textY+(v[cur].nlines-1)*(text->lineHeight+v[cur].lineSpacing);
7490 if (y<-text->lineHeight){
7491 textY=y;
7492 continue;
7493 }
7494 }
7495 int dh=18+v[cur].lineSpacing;
7496 if (textY+dh+(editable?17:0)>LCD_HEIGHT_PX){
7497 if (isFirstDraw)
7498 dh -= textY+dh+(editable?17:0)-LCD_HEIGHT_PX;
7499 else {
7500 textY = saveY;
7501 break;
7502 }
7503 }
7504 //if (dh>0 && textY>=(showtitle?24:0))
7505 //drawRectangle(textX, textY, LCD_WIDTH_PX, dh, COLOR_WHITE);
7506 if (editable && textY>=(showtitle?24:0)){
7507 char line_s[16];
7508 sprint_int(line_s,cur+1);
7509 os_draw_string_small(textX,textY,COLOR_MAGENTA,_WHITE,line_s);
7510 }
7511 textX=text->x+deltax;
7512 int tlen = v[cur].s.size();
7513 char singleword[tlen+32];
7514 // char* singleword = (char*)malloc(tlen+1); // because of this, a single text element can't have more bytes than malloc can provide
7515 if (cur==textline){
7516 if (textpos<0 || textpos>tlen)
7517 textpos=tlen;
7518 if (tlen==0 && text->editable){ // cursor on empty line
7519 drawRectangle(textX,textY,3,16,COLOR_BLACK);
7520 }
7521 }
7522 bool chksel=false;
7523 int sel_line1,sel_line2,sel_pos1,sel_pos2;
7524 if (clipline>=0){
7525 if (clipline<textline || (clipline==textline && clippos<textpos)){
7526 sel_line1=clipline;
7527 sel_line2=textline;
7528 sel_pos1=clippos;
7529 sel_pos2=textpos;
7530 }
7531 else {
7532 sel_line1=textline;
7533 sel_line2=clipline;
7534 sel_pos1=textpos;
7535 sel_pos2=clippos;
7536 }
7537 chksel=(sel_line1<=cur && cur<=sel_line2);
7538 }
7539 const char * match1=0; // matching parenthesis (or brackets?)
7540 const char * match2=0;
7541 if (cur==line1)
7542 match1=v[cur].s.c_str()+pos1;
7543 else
7544 match1=0;
7545 if (cur==line2)
7546 match2=v[cur].s.c_str()+pos2;
7547 else
7548 match2=0;
7549 // if (cur==textline && !match(v[cur].s.c_str(),textpos,match1,match2) && !match1 && !match2) match(v[cur].s.c_str(),textpos-1,match1,match2);
7550 // char buf[128];sprintf(buf,"%i %i %i ",cur,(int)match1,(int)match2);puts(buf);
7551 const char * srcpos=src+textpos;
7552 bool minimini=v[cur].minimini;
7553 int couleur=v[cur].color;
7554 int nlines=1;
7555 bool linecomment=false;
7556 while (*src){
7557 const char * oldsrc=src;
7558 if ( (text->python && *src=='#') ||
7559 (!text->python && *src=='/' && *(src+1)=='/')){
7560 linecomment=true;
7561 couleur=4;
7562 }
7563 if (linecomment || !text->editable)
7564 src = (char*)toksplit((unsigned char*)src, ' ', (unsigned char*)singleword, minimini?50:35); //break into words; next word
7565 else { // skip string (only with delimiters " ")
7566 if (*src=='"'){
7567 for (++src;*src;++src){
7568 if (*src=='"' && *(src-1)!='\\')
7569 break;
7570 }
7571 if (*src=='"')
7572 ++src;
7573 int i=src-oldsrc;
7574 strncpy(singleword,oldsrc,i);
7575 singleword[i]=0;
7576 }
7577 else {
7578 size_t i=0;
7579 for (;*src==' ';++src){ // skip initial whitespaces
7580 ++i;
7581 }
7582 if (i==0){
7583 if (isalpha(*src)){ // skip keyword
7584 for (;isalphanum(*src) || *src=='_';++src){
7585 ++i;
7586 }
7587 }
7588 // go to next space or alphabetic char
7589 for (;*src;++i,++src){
7590 if (*src==' ' || (i && *src>=' ' && *src<='/') || (text->python && *src=='#') || (!text->python && *src=='/' && *(src+1)=='/')|| *src=='"' || isalpha(*src))
7591 break;
7592 }
7593 }
7594 strncpy(singleword,oldsrc,i);
7595 singleword[i]=0;
7596 if (i==0){
7597 puts(src); // free(singleword);
7598 return ; // FIXME KEY_CTRL_F2;
7599 }
7600 } // end normal case
7601 } // end else linecomment case
7602 // take care of selection
7603 bool invert=false;
7604 if (chksel){
7605 if (cur<sel_line1 || cur>sel_line2)
7606 invert=false;
7607 else {
7608 int printpos1=oldsrc-v[cur].s.c_str();
7609 int printpos2=src-v[cur].s.c_str();
7610 if (cur==sel_line1 && printpos1<sel_pos1 && printpos2>sel_pos1){
7611 // cut word in 2 parts: first part not selected
7612 src=oldsrc+sel_pos1-printpos1;
7613 singleword[sel_pos1-printpos1]=0;
7614 printpos2=sel_pos1;
7615 }
7616 if (cur==sel_line2 && printpos1<sel_pos2 && printpos2>sel_pos2){
7617 src=oldsrc+sel_pos2-printpos1;
7618 singleword[sel_pos2-printpos1]=0;
7619 printpos2=sel_pos2;
7620 }
7621 // now singleword is totally unselected or totally selected
7622 // which one?
7623 if (cur==sel_line1){
7624 if (cur==sel_line2)
7625 invert=printpos1>=sel_pos1 && printpos2<=sel_pos2;
7626 else
7627 invert=printpos1>=sel_pos1;
7628 }
7629 else {
7630 if (cur==sel_line2)
7631 invert=printpos2<=sel_pos2;
7632 else
7633 invert=true;
7634 }
7635 }
7636 }
7637 //check if printing this word would go off the screen, with fake PrintMini drawing:
7638 int temptextX = 0,temptextY=0;
7639 print(temptextX,temptextY,singleword,couleur,false,/*fake*/true,minimini);
7640 if(temptextX<text->width && temptextX + textX > text->width-6) {
7641 if (editable)
7642 textX=PrintMini(textX, textY, ">", 4, COLOR_MAGENTA, COLOR_WHITE);
7643 //time for a new line
7644 textX=text->x+deltax;
7645 textY=textY+text->lineHeight+v[cur].lineSpacing;
7646 //if (textY>=(showtitle?24:0))
7647 // drawRectangle(0, textY, LCD_WIDTH_PX, 18+v[cur].lineSpacing, COLOR_WHITE);
7648 ++nlines;
7649 } //else still fits, print new word normally (or just increment textX, if we are not "on stage" yet)
7650 if(textY >= (showtitle?24:0) && textY < LCD_HEIGHT_PX) {
7651 temptextX=textX;
7652 if (editable){
7653 couleur=linecomment?5:find_color(singleword,contextptr);
7654 if (couleur==1) couleur=COLOR_BLUE;
7655 if (couleur==2) couleur=COLOR_YELLOWDARK;
7656 if (couleur==3) couleur=33024;
7657 if (couleur==4) couleur=COLOR_MAGENTA;
7658 if (couleur==5) couleur=COLOR_GREEN;
7659 //char ch[32];
7660 //sprint_int(ch,couleur);
7661 //puts(singleword); puts(ch);
7662 }
7663 if (linecomment || !text->editable || singleword[0]=='"')
7664 print(textX,textY,singleword,couleur,invert,/*fake*/false,minimini);
7665 else { // print two parts, commandname in color and remain in black
7666 char * ptr=singleword;
7667 if (isalpha(*ptr)){
7668 while (isalphanum(*ptr) || *ptr=='_')
7669 ++ptr;
7670 }
7671 char ch=*ptr;
7672 *ptr=0;
7673 print(textX,textY,singleword,couleur,invert,/*fake*/false,minimini);
7674 *ptr=ch;
7675 print(textX,textY,ptr,COLOR_BLACK,invert,/*fake*/false,minimini);
7676 }
7677 // ?add a space removed from token
7678 if( ((linecomment || !text->editable)?*src:*src==' ') || v[cur].spaceAtEnd){
7679 if (*src==' ')
7680 ++src;
7681 print(textX,textY," ",COLOR_BLACK,invert,false,minimini);
7682 }
7683 // ?print cursor, and par. matching
7684 if (editable){
7685 if (match1 && oldsrc<=match1 && match1<src)
7686 match_print(singleword,match1-oldsrc,temptextX,textY,
7687 line2!=-1,
7688 // match2,
7689 minimini);
7690 if (match2 && oldsrc<=match2 && match2<src)
7691 match_print(singleword,match2-oldsrc,temptextX,textY,
7692 line1!=-1,
7693 //match1,
7694 minimini);
7695 }
7696 if (editable && cur==textline){
7697 if (oldsrc<=srcpos && (srcpos<src || (srcpos==src && textpos==tlen))){
7698 if (textpos>=2 && v[cur].s[textpos-1]==' ' && v[cur].s[textpos-2]!=' ' && srcpos-oldsrc==strlen(singleword)+1){ // fix cursor position after space
7699 //char ch[512];
7700 //sprintf(ch,"%s %i %i %i %i",singleword,strlen(singleword),srcpos-oldsrc,textpos,v[cur].s[textpos-2]);
7701 //puts(ch);
7702 singleword[srcpos-oldsrc-1]=' ';
7703 }
7704 singleword[srcpos-oldsrc]=0;
7705 print(temptextX,temptextY,singleword,couleur,false,/*fake*/true,minimini);
7706 //drawLine(temptextX, textY+14, temptextX, textY-14, COLOR_BLACK);
7707 //drawLine(temptextX+1, textY+14, temptextX+1, textY-14, COLOR_BLACK);
7708 drawRectangle(temptextX-1,textY,3,16,COLOR_BLACK);
7709 }
7710 }
7711 } // end if testY visible
7712 else {
7713 textX += temptextX;
7714 if(*src || v[cur].spaceAtEnd) textX += 7; // size of a PrintMini space
7715 }
7716 } // end while (*src)
7717 // free(singleword);
7718 v[cur].nlines=nlines; //if (cur<6) *logptr(contextptr) << cur << ":" << src << nlines << '\n';
7719 if (isFirstDraw)
7720 totalTextY = textY+(showtitle ? 0 : 24);
7721 } // end main draw loop (for cur<v.size())
7722 int dh=LCD_HEIGHT_PX-textY-text->lineHeight-(editable?17:0);
7723 if (dh>0)
7724 drawRectangle(0, textY+text->lineHeight, LCD_WIDTH_PX, dh, COLOR_WHITE);
7725 isFirstDraw=0;
7726 if(showtitle) {
7727 waitforvblank();
7728 drawRectangle(0, 0, LCD_WIDTH_PX, 24, _WHITE);
7729 drawScreenTitle((char*)text->title);
7730 }
7731 //if (editable)
7732 if (editable){
7733 // waitforvblank();
7734 drawRectangle(0,205,LCD_WIDTH_PX,17,44444);
7735 PrintMiniMini(0,205,text->python?"shift-1 test|2 loop|3 undo|4 misc|5 +-|6 logo|7 lin|8 list|9plot":"shift-1 test|2 loop|3 undo|4 misc|5 +-|6 logo|7 matr|8 list",4,44444,giac::_BLACK);
7736 //draw_menu(1);
7737 }
7738 #ifdef SCROLLBAR
7739 int scrollableHeight = LCD_HEIGHT_PX-24*(showtitle ? 2 : 1)-text->y;
7740 //draw a scrollbar:
7741 if(text->scrollbar) {
7742 TScrollbar sb;
7743 sb.I1 = 0;
7744 sb.I5 = 0;
7745 sb.indicatormaximum = totalTextY;
7746 sb.indicatorheight = scrollableHeight;
7747 sb.indicatorpos = -scroll;
7748 sb.barheight = scrollableHeight;
7749 sb.bartop = (showtitle ? 24 : 0)+text->y;
7750 sb.barleft = text->width - 6;
7751 sb.barwidth = 6;
7752
7753 Scrollbar(&sb);
7754 }
7755 #endif
7756 }
7757
move_to_word(textArea * text,const std::string & s,const std::string & replace,int & isFirstDraw,int & totalTextY,int & scroll,int & textY,GIAC_CONTEXT)7758 bool move_to_word(textArea * text,const std::string & s,const std::string & replace,int & isFirstDraw,int & totalTextY,int & scroll,int & textY,GIAC_CONTEXT){
7759 if (!s.size())
7760 return false;
7761 int line=text->line,pos=text->pos;
7762 if (line>=text->elements.size())
7763 line=0;
7764 if (pos>=text->elements[line].s.size())
7765 pos=0;
7766 for (;line<text->elements.size();++line){
7767 int p=text->elements[line].s.find(s,pos);
7768 if (p>=0 && p<text->elements[line].s.size()){
7769 text->line=line;
7770 text->clipline=line;
7771 text->clippos=p;
7772 text->pos=p+s.size();
7773 display(text,isFirstDraw,totalTextY,scroll,textY,contextptr); // this modifies text->elements[].nlines (no idea why), 2 calls insure scrolling is adequate
7774 display(text,isFirstDraw,totalTextY,scroll,textY,contextptr);
7775 text->clipline=-1;
7776 return chk_replace(text,s,replace);
7777 }
7778 pos=0;
7779 }
7780 for (line=0;line<text->line;++line){
7781 int p=text->elements[line].s.find(s,0);
7782 if (p>=0 && p<text->elements[line].s.size()){
7783 text->line=line;
7784 text->clipline=line;
7785 text->clippos=p;
7786 text->pos=p+s.size();
7787 display(text,isFirstDraw,totalTextY,scroll,textY,contextptr);
7788 display(text,isFirstDraw,totalTextY,scroll,textY,contextptr); // 2 callslike above
7789 text->clipline=-1;
7790 return chk_replace(text,s,replace);
7791 }
7792 }
7793 return false;
7794 }
7795
load_script(const char * filename,std::string & s)7796 int load_script(const char * filename,std::string & s){
7797 const char * ch =read_file(filename);
7798 s=ch?ch:"";
7799 return 1;
7800 }
7801
save_script(const char * filename,const string & s)7802 void save_script(const char * filename,const string & s){
7803 #ifdef NUMWORKS
7804 char buf[s.size()+2];
7805 buf[0]=1;
7806 strcpy(buf+1,s.c_str());
7807 #else
7808 char buf[s.size()+1];
7809 strcpy(buf,s.c_str());
7810 #endif
7811 #ifdef NSPIRE_NEWLIB
7812 char filenametns[strlen(filename)+5];
7813 strcpy(filenametns,filename);
7814 strcpy(filenametns+strlen(filename),".tns");
7815 write_file(filenametns,buf);
7816 #else
7817 write_file(filename,buf);
7818 #endif
7819 }
7820
textedit(char * s,int bufsize,bool OKparse,const giac::context * contextptr)7821 bool textedit(char * s,int bufsize,bool OKparse,const giac::context * contextptr){
7822 if (!s)
7823 return false;
7824 int ss=strlen(s);
7825 if (ss==0){
7826 *s=' ';
7827 s[1]=0;
7828 ss=1;
7829 }
7830 textArea ta;
7831 ta.elements.clear();
7832 ta.editable=true;
7833 ta.clipline=-1;
7834 ta.changed=false;
7835 ta.filename="temp.py";
7836 ta.y=0;
7837 ta.python=true;
7838 ta.allowEXE=false;//true; // set back to true later
7839 ta.OKparse=OKparse;
7840 bool str=s[0]=='"' && s[ss-1]=='"';
7841 if (str){
7842 s[ss-1]=0;
7843 add(&ta,s+1);
7844 }
7845 else
7846 add(&ta,s);
7847 ta.line=0;
7848 ta.pos=ta.elements[ta.line].s.size();
7849 int res=doTextArea(&ta,contextptr);
7850 drawRectangle(0,0,LCD_WIDTH_PX,LCD_HEIGHT_PX,_WHITE);
7851 os_hide_graph();
7852 if (res==TEXTAREA_RETURN_EXIT)
7853 return false;
7854 string S(merge_area(ta.elements));
7855 if (str)
7856 S='"'+S+'"';
7857 int Ssize=S.size();
7858 if (Ssize<bufsize){
7859 strcpy(s,S.c_str());
7860 for (--Ssize;Ssize>=0;--Ssize){
7861 if ((unsigned char)s[Ssize]==0x9c || s[Ssize]=='\n')
7862 s[Ssize]=0;
7863 if (s[Ssize]!=' ')
7864 break;
7865 }
7866 return true;
7867 }
7868 return false;
7869 }
7870
textedit(char * s,int bufsize,const giac::context * contextptr)7871 bool textedit(char * s,int bufsize,const giac::context * contextptr){
7872 return textedit(s,bufsize,false,contextptr);
7873 }
7874
7875 #if 0
7876 int get_filename(char * filename,const char * extension){
7877 return 0;
7878 }
7879 #else
get_filename(char * filename,const char * extension)7880 int get_filename(char * filename,const char * extension){
7881 handle_f5();
7882 string str;
7883 #ifdef NSPIRE_NEWLIB
7884 int res=inputline((lang==1)?"esc ou chaine vide: annulation":"esc or empty string: cancel",(lang==1)?"Nom de fichier:":"Filename:",str,false);
7885 #else
7886 int res=inputline((lang==1)?"EXIT ou chaine vide: annulation":"EXIT or empty string: cancel",(lang==1)?"Nom de fichier:":"Filename:",str,false);
7887 #endif
7888 if (res==KEY_CTRL_EXIT || str.empty())
7889 return 0;
7890 strcpy(filename,str.c_str());
7891 int s=strlen(filename);
7892 if (strcmp(filename+s-3,extension))
7893 strcpy(filename+s,extension);
7894 // if file already exists, warn, otherwise create
7895 if (!file_exists(filename))
7896 return 1;
7897 if (confirm((lang==1)?" Le fichier existe!":" File exists!",
7898 #ifdef NSPIRE_NEWLIB
7899 (lang==1)?"enter: ecraser, esc: annuler":"enter:overwrite, esc: cancel"
7900 #else
7901 (lang==1)?"OK: ecraser,Back: annuler":"OK:overwrite, Back: cancel"
7902 #endif
7903 )==KEY_CTRL_F1)
7904 return 1;
7905 return 0;
7906 }
7907 #endif
7908
input_matrix(const gen & g,gen & ge,GIAC_CONTEXT)7909 const char * input_matrix(const gen &g,gen & ge,GIAC_CONTEXT){
7910 #ifdef MICROPY_LIB
7911 if (xcas_python_eval==1){
7912 if (ge.type==_VECT)
7913 ge.subtype=0;
7914 static string input_matrix_s=g.print(contextptr)+'='+ge.print(contextptr);
7915 return input_matrix_s.c_str();
7916 }
7917 #endif
7918 if (ge.type==giac::_VECT)
7919 sto(ge,g,contextptr);
7920 return "";
7921 }
7922
input_matrix(bool list,GIAC_CONTEXT)7923 const char * input_matrix(bool list,GIAC_CONTEXT){
7924 static std::string * sptr=0;
7925 if (!sptr)
7926 sptr=new std::string;
7927 *sptr="";
7928 giac::gen v(giac::_VARS(0,contextptr));
7929 giac::vecteur w;
7930 if (v.type==giac::_VECT){
7931 for (size_t i=0;i<v._VECTptr->size();++i){
7932 giac::gen & tmp = (*v._VECTptr)[i];
7933 if (tmp.type==giac::_IDNT){
7934 giac::gen tmpe(protecteval(tmp,1,contextptr));
7935 if (list){
7936 if (tmpe.type==giac::_VECT && !ckmatrix(tmpe))
7937 w.push_back(tmp);
7938 }
7939 else {
7940 if (ckmatrix(tmpe))
7941 w.push_back(tmp);
7942 }
7943 }
7944 }
7945 }
7946 std::string msg;
7947 if (w.empty())
7948 msg=(lang==1)?(list?"Creer nouvelle liste":"Creer nouvelle matrice"):(list?"Create new list":"Create new matrix");
7949 else
7950 msg=(((lang==1)?"Creer nouveau ou editer ":"Create new or edit ")+(w.size()==1?w.front():giac::gen(w,giac::_SEQ__VECT)).print(contextptr));
7951 handle_f5();
7952 if (inputline(msg.c_str(),((lang==1)?"Nom de variable:":"Variable name:"),*sptr,false) && !sptr->empty() && isalpha((*sptr)[0])){
7953 giac::gen g(*sptr,contextptr);
7954 giac::gen ge(protecteval(g,1,contextptr));
7955 if (g.type==giac::_IDNT){
7956 if (ge.type==giac::_VECT){
7957 ge=eqw(ge,true,contextptr);
7958 ge=protecteval(ge,1,contextptr);
7959 return input_matrix(g,ge,contextptr);
7960 if (ge.type==giac::_VECT)
7961 sto(ge,g,contextptr);
7962 else
7963 cout << "edited " << ge << endl;
7964 return ""; // return sptr->c_str();
7965 }
7966 if (ge==g || confirm_overwrite()){
7967 *sptr="";
7968 if (inputline(((lang==1)?(list?"Nombre d'elements":"Nombre de lignes"):(list?"Elements number":"Line number")),"",*sptr,true)){
7969 int l=strtol(sptr->c_str(),0,10);
7970 if (l>0 && l<256){
7971 int c;
7972 if (list)
7973 c=0;
7974 else {
7975 std::string tmp(*sptr+((lang==1)?" lignes.":" lines."));
7976 *sptr="";
7977 inputline(tmp.c_str(),(lang==1)?"Colonnes:":"Columns:",*sptr,true);
7978 c=strtol(sptr->c_str(),0,10);
7979 }
7980 if (c==0){
7981 ge=giac::vecteur(l);
7982 }
7983 else {
7984 if (c>0 && l*c<256)
7985 ge=giac::_matrix(giac::makesequence(l,c),contextptr);
7986 }
7987 ge=eqw(ge,true,contextptr);
7988 ge=protecteval(ge,1,contextptr);
7989 return input_matrix(g,ge,contextptr);
7990 } // l<256
7991 }
7992 } // ge==g || overwrite confirmed
7993 } // g.type==_IDNT
7994 else {
7995 invalid_varname();
7996 }
7997 } // isalpha
7998 return 0;
7999 }
8000
get_searchitem(std::string & replace)8001 std::string get_searchitem(std::string & replace){
8002 replace="";
8003 std::string search;
8004 handle_f5();
8005 #ifdef NSPIRE_NEWLIB
8006 int res=inputline((lang==1)?"esc ou chaine vide: annulation":"esc or empty string: cancel",(lang==1)?"Chercher:":"Search:",search,false);
8007 if (search.empty() || res==KEY_CTRL_EXIT)
8008 return "";
8009 replace="";
8010 std::string tmp=((lang==1)?"esc: recherche seule de ":"esc: search only ")+search;
8011 #else
8012 int res=inputline((lang==1)?"EXIT ou chaine vide: annulation":"EXIT or empty string: cancel",(lang==1)?"Chercher:":"Search:",search,false);
8013 if (search.empty() || res==KEY_CTRL_EXIT)
8014 return "";
8015 replace="";
8016 std::string tmp=((lang==1)?"EXIT: recherche seule de ":"EXIT: search only ")+search;
8017 #endif
8018 handle_f5();
8019 res=inputline(tmp.c_str(),(lang==1)?"Remplacer par:":"Replace by:",replace,false);
8020 if (res==KEY_CTRL_EXIT)
8021 replace="";
8022 return search;
8023 }
8024
doTextArea(textArea * text,GIAC_CONTEXT)8025 int doTextArea(textArea* text,GIAC_CONTEXT) {
8026 int scroll = 0;
8027 int isFirstDraw = 1;
8028 int totalTextY = 0,textY=0;
8029 bool editable=text->editable;
8030 int showtitle = !editable && (text->title != NULL);
8031 int scrollableHeight = LCD_HEIGHT_PX-24*(showtitle ? 2 : 1)-text->y;
8032 std::vector<textElement> & v=text->elements;
8033 std::string search,replace;
8034 show_status(text,search,replace);
8035 if (text->line>=v.size())
8036 text->line=0;
8037 display(text,isFirstDraw,totalTextY,scroll,textY,contextptr);
8038 while(1) {
8039 if (text->line>=v.size())
8040 text->line=0;
8041 display(text,isFirstDraw,totalTextY,scroll,textY,contextptr);
8042 if(text->type == TEXTAREATYPE_INSTANT_RETURN) return 0;
8043 int keyflag = GetSetupSetting( (unsigned int)0x14);
8044 int key;
8045 GetKey(&key);
8046 if (key==KEY_SHUTDOWN)
8047 return key;
8048 if (key==KEY_CTRL_F3) // Numworks has no UNDO key
8049 key=KEY_CTRL_UNDO;
8050 #if 1
8051 if (key == KEY_CTRL_SETUP) {
8052 menu_setup(contextptr);
8053 continue;
8054 }
8055 #endif
8056 if (key!=KEY_CTRL_PRGM && key!=KEY_CHAR_FRAC)
8057 translate_fkey(key);
8058 //char keylog[32];sprint_int(keylog,key); puts(keylog);
8059 show_status(text,search,replace);
8060 int & clipline=text->clipline;
8061 int & clippos=text->clippos;
8062 int & textline=text->line;
8063 int & textpos=text->pos;
8064 if (key==KEY_CTRL_CUT && clipline<0) // if no selection, CUT -> pixel menu
8065 key=KEY_CTRL_F3;
8066 if (!editable && (key==KEY_CHAR_ANS || key==KEY_BOOK || key=='\t' || key==KEY_CTRL_EXE))
8067 return key;
8068 if (editable){
8069 if (key=='\t'){
8070 int indent=0; // indent deduced from prev line
8071 if (textline!=0){
8072 std::string & s=v[textline-1].s;
8073 indent=find_indentation(s);
8074 if (!s.empty())
8075 indent+=2*end_do_then(s);
8076 }
8077 std::string & s=v[textline].s;
8078 int curindent=find_indentation(s);
8079 int diff=curindent-indent;
8080 if (diff>0){
8081 s=s.substr(diff,s.size()-diff);
8082 if (textpos>diff)
8083 textpos -= diff;
8084 else
8085 textpos = 0;
8086 continue;
8087 }
8088 if (diff<0){
8089 s=string(-diff,' ')+s;
8090 textpos += -diff;
8091 continue;
8092 }
8093 key=KEY_BOOK;
8094 }
8095 if (key==KEY_BOOK){
8096 string curs=v[textline].s.substr(0,textpos);
8097 if (!curs.empty()){
8098 string adds=help_insert(curs.c_str(),contextptr);
8099 if (!adds.empty())
8100 insert(text,adds.c_str(),false);
8101 }
8102 continue;
8103 }
8104 if (key==KEY_CHAR_FRAC && clipline<0){
8105 if (textline==0) continue;
8106 std::string & s=v[textline].s;
8107 std::string & prev_s=v[textline-1].s;
8108 int indent=find_indentation(s),prev_indent=find_indentation(prev_s);
8109 if (!prev_s.empty())
8110 prev_indent += 2*end_do_then(prev_s);
8111 int diff=indent-prev_indent;
8112 if (diff>0 && diff<=s.size())
8113 s=s.substr(diff,s.size()-diff);
8114 if (diff<0)
8115 s=string(-diff,' ')+s;
8116 textpos -= diff;
8117 continue;
8118 }
8119 if (key==KEY_CTRL_VARS){
8120 displaylogo();
8121 continue;
8122 }
8123 if (0 && key==KEY_CHAR_ANS){ // lack of keys, ANS -> menu
8124 int err=check_parse(text,v,text->python,contextptr);
8125 if (err==KEY_SHUTDOWN)
8126 return err;
8127 if (err) // move cursor to the error line
8128 textline=err-1;
8129 continue;
8130 }
8131 if (key>=KEY_SELECT_LEFT && key<=KEY_SELECT_RIGHT){
8132 if (clipline<0){
8133 clipline=textline;
8134 clippos=textpos;
8135 show_status(text,search,replace);
8136 }
8137 if (key==KEY_SELECT_LEFT){
8138 if (textpos)
8139 --textpos;
8140 else {
8141 if (textline){
8142 --textline;
8143 textpos=v[textline].s.size();
8144 }
8145 }
8146 }
8147 if (key==KEY_SELECT_RIGHT){
8148 if (textpos<v[textline].s.size())
8149 ++textpos;
8150 else {
8151 if (textline<v.size()){
8152 ++textline;
8153 textpos=0;
8154 }
8155 }
8156 }
8157 if (key==KEY_SELECT_UP){
8158 if (textline){
8159 --textline;
8160 textpos=giacmin(textpos,v[textline].s.size());
8161 }
8162 }
8163 if (key==KEY_SELECT_DOWN){
8164 if (textline<v.size()){
8165 ++textline;
8166 textpos=giacmin(textpos,v[textline].s.size());
8167 }
8168 }
8169 }
8170 if (key==KEY_CTRL_CLIP) {
8171 #if 1
8172 if (clipline>=0){
8173 copy_clipboard(get_selection(text,false),true);
8174 clipline=-1;
8175 }
8176 else {
8177 clipline=textline;
8178 clippos=textpos;
8179 show_status(text,search,replace);
8180 }
8181 #else
8182 copy_clipboard(v[textline].s,false);
8183 DefineStatusMessage((char*)"Line copied to clipboard", 1, 0, 0);
8184 DisplayStatusArea();
8185 #endif
8186 continue;
8187 }
8188 if (key==KEY_CTRL_F5){
8189 bool minimini=!v[0].minimini;
8190 for (int i=0;i<v.size();++i)
8191 v[i].minimini=minimini;
8192 text->lineHeight=minimini?13:17;
8193 isFirstDraw=1;
8194 display(text,isFirstDraw,totalTextY,scroll,textY,contextptr);
8195 continue;
8196 }
8197 if (clipline<0){
8198 const char * adds;
8199 #if 1
8200 if ( (key>=KEY_CTRL_F1 && key<=KEY_CTRL_F4) ||
8201 (key >= KEY_CTRL_F6 && key <= KEY_CTRL_F14)
8202 ){
8203 string le_menu=text->python?
8204 "F1 test\nif \nelse \n<\n>\n==\n!=\n&&\n||\nF2 loop\nfor \nfor in\nrange(\nwhile \nbreak\ndef\nreturn \n#\nF4 misc\n:\n;\n_\n!\n%\nfrom import *\nprint(\ninput(\nF6 tortue\nforward(\nbackward(\nleft(\nright(\npencolor(\ncircle(\nreset()\nfrom turtle import *\nF9 plot\nplot(\ntext(\narrow(\nlinear_regression_plot(\nscatter(\naxis(\nbar(\nfrom matplotl import *\nF7 linalg\nadd(\nsub(\nmul(\ninv(\ndet(\nrref(\ntranspose(\nfrom linalg import *\nF: color\nred\nblue\ngreen\ncyan\nyellow\nmagenta\nblack\nwhite\nF= draw\nset_pixel(\ndraw_line(\ndraw_rectangle(\nfill_rect(\ndraw_polygon(\ndraw_circle(\ndraw_string(\nfrom graphic import *\nF> cplx\nabs(\narg(\nre(\nim(\nconj(\npolar(\nrect(\nfrom cmath import *\n":
8205 "F1 test\nif \nelse \n<\n>\n==\n!=\nand\nor\nF2 loop\nfor \nfor in\nrange(\nwhile \nbreak\nf(x):=\nreturn \nlocal\nF4 misc\n;\n:\n_\n!\n%\n&\nprint(\ninput(\nF6 tortue\navance\nrecule\ntourne_gauche\ntourne_droite\nrond\ndisque\nrepete\nefface\nF7 lin\nmatrix(\ndet(\nmatpow(\nranm(\nrref(\ntran(\negvl(\negv(\nF: arit\n mod \nirem(\nifactor(\ngcd(\nisprime(\nnextprime(\npowmod(\niegcd(\nF9 plot\nplot(\nplotseq(\nplotlist(\nplotparam(\nplotpolar(\nplotfield(\nhistogram(\nbarplot(\nF= misc\n<\n>\n_\n!\n % \nrand(\nbinomial(\nnormald(\nF> cplx\nabs(\narg(\nre(\nim(\nconj(\ncsolve(\ncfactor(\ncpartfrac(\n";
8206 le_menu += "F8 list\nmakelist(\nrange(\nseq(\nlen(\nappend(\nranv(\nsort(\napply(\nF; real\nexact(\napprox(\nfloor(\nceil(\nround(\nsign(\nmax(\nmin(\nF< prog\n;\n:\n\\\n&\n?\n!\ndebug(\npython(\n";
8207 const char * ptr=console_menu(key,(char*)(le_menu.c_str()),2);
8208 if (!ptr){
8209 show_status(text,search,replace);
8210 continue;
8211 }
8212 adds=ptr;
8213 }
8214 else
8215 #endif
8216 adds=keytostring(key,keyflag,text->python,contextptr);
8217 if (key!=KEY_CHAR_ANS && adds){
8218 bool isex=adds[0]=='\n';
8219 if (isex)
8220 ++adds;
8221 bool isif=strcmp(adds,"if ")==0,
8222 iselse=strcmp(adds,"else ")==0,
8223 isfor=strcmp(adds,"for ")==0,
8224 isforin=strcmp(adds,"for in")==0,
8225 isdef=strcmp(adds,"f(x):=")==0 || strcmp(adds,"def")==0,
8226 iswhile=strcmp(adds,"while ")==0,
8227 islist=strcmp(adds,"list ")==0,
8228 ismat=strcmp(adds,"matrix ")==0;
8229 if (islist){
8230 input_matrix(true,contextptr);
8231 continue;
8232 }
8233 if (ismat){
8234 input_matrix(false,contextptr);
8235 continue;
8236 }
8237 if (text->python){
8238 if (isif)
8239 adds=isex?"if x<0:\nx=-x":"if :\n";
8240 if (iselse)
8241 adds="else:\n";
8242 if (isfor)
8243 adds=isex?"for j in range(10):\nprint(j*j)":"for in range():\n";
8244 if (isforin)
8245 adds=isex?"for j in [1,4,9,16]:\nprint(j)":"for in :\n";
8246 if (iswhile && isex)
8247 adds="a,b=25,15\nwhile b!=0:\na,b=b,a%b";
8248 if (isdef)
8249 adds=isex?"def f(x):\nreturn x*x*x\n":"def f(x):\n\nreturn\n";
8250 } else {
8251 if (isif)
8252 adds=(lang==1)?(isex?"si x<0 alors x:=-x; fsi;":"si alors\n\nsinon\n\nfsi;"):(isex?"if x<0 then x:=-x; fi;":"if then\n\nelse\n\nfi;");
8253 if (lang && iselse)
8254 adds="sinon ";
8255 if (isfor)
8256 adds=(lang==1)?(isex?"pour j de 1 jusque 10 faire\nprint(j*j);\nfpour;":"pour de jusque faire\n\nfpour;"):(isex?"for j from 1 to 10 do\nprint(j*j);\nod;":"for from to do\n\nod;");
8257 if (isforin)
8258 adds=(lang==1)?(isex?"pour j in [1,4,9,16] faire\nprint(j)\nfpour;":"pour in faire\n\nfpour;"):(isex?"for j in [1,4,9,16] do\nprint(j);od;":"for in do\n\nod;");
8259 if (iswhile)
8260 adds=(lang==1)?(isex?"a,b:=25,15;\ntantque b!=0 faire\na,b:=b,irem(a,b);\nftantque;a;":"tantque faire\n\nftantque;"):(isex?"a,b:=25,15;\nwhile b!=0 do\na,b:=b,irem(a,b);\nod;a;":"while do\n\nod;");
8261 if (isdef)
8262 adds=(lang==1)?(isex?"fonction f(x)\nlocal j;\nj:=x*x;\nreturn j;\nffonction:;\n":"fonction f(x)\nlocal j;\n\nreturn ;\nffonction:;"):(isex?"function f(x)\nlocal j;\nj:=x*x;\nreturn j;\nffunction:;\n":"function f(x)\n local j;\n\n return ;\nffunction:;");
8263 }
8264 insert(text,adds,key!=KEY_CTRL_PASTE); // was true, but we should not indent when pasting
8265 show_status(text,search,replace);
8266 continue;
8267 }
8268 }
8269 }
8270 textElement * ptr=& v[textline];
8271 const int interligne=16;
8272 switch(key){
8273 case KEY_CTRL_DEL:
8274 if (clipline>=0){
8275 copy_clipboard(get_selection(text,true),true);
8276 // erase selection
8277 clipline=-1;
8278 }
8279 else {
8280 if (editable){
8281 if (textpos){
8282 set_undo(text);
8283 std::string & s=v[textline].s;
8284 int nextpos=textpos-1;
8285 if (textpos==find_indentation(s)){
8286 for (int line=textline-1;line>=0;--line){
8287 int ind=find_indentation(v[line].s);
8288 if (textpos>ind){
8289 nextpos=ind;
8290 break;
8291 }
8292 }
8293 }
8294 s.erase(s.begin()+nextpos,s.begin()+textpos);
8295 textpos=nextpos;
8296 }
8297 else {
8298 if (textline){
8299 set_undo(text);
8300 --textline;
8301 textpos=v[textline].s.size();
8302 v[textline].s += v[textline+1].s;
8303 v[textline].nlines += v[textline+1].nlines;
8304 v.erase(v.begin()+textline+1);
8305 }
8306 }
8307 }
8308 show_status(text,search,replace);
8309 }
8310 break;
8311 case KEY_CTRL_S:
8312 display(text,isFirstDraw,totalTextY,scroll,textY,contextptr);
8313 search=get_searchitem(replace);
8314 if (!search.empty()){
8315 for (;;){
8316 if (!move_to_word(text,search,replace,isFirstDraw,totalTextY,scroll,textY,contextptr)){
8317 break;
8318 }
8319 }
8320 show_status(text,search,replace);
8321 }
8322 continue;
8323 case KEY_CTRL_OK:
8324 if (text->allowEXE || !text->editable) return TEXTAREA_RETURN_EXE;
8325 if (search.size()){
8326 for (;;){
8327 if (!move_to_word(text,search,replace,isFirstDraw,totalTextY,scroll,textY,contextptr))
8328 break;
8329 }
8330 show_status(text,search,replace);
8331 continue;
8332 }
8333 else {
8334 if (!text->OKparse) return TEXTAREA_RETURN_EXE;
8335 int err=check_parse(text,v,text->python,contextptr);
8336 if (err==KEY_SHUTDOWN)
8337 return err;
8338 if (err) // move cursor to the error line
8339 textline=err-1;
8340 continue;
8341 }
8342 break;
8343 case KEY_CTRL_EXE:
8344 if (search.size()){
8345 for (;;){
8346 if (!move_to_word(text,search,replace,isFirstDraw,totalTextY,scroll,textY,contextptr))
8347 break;
8348 }
8349 show_status(text,search,replace);
8350 continue;
8351 }
8352 if (clipline<0 && editable){
8353 set_undo(text);
8354 add_indented_line(v,textline,textpos);
8355 show_status(text,search,replace);
8356 }
8357 break;
8358 case KEY_CTRL_UNDO:
8359 undo(text);
8360 break;
8361 case KEY_SHIFT_LEFT:
8362 textpos=0;
8363 break;
8364 case KEY_SHIFT_RIGHT:
8365 textpos=v[textline].s.size();
8366 break;
8367 case KEY_CTRL_LEFT:
8368 if (editable){
8369 --textpos;
8370 if (textpos<0){
8371 if (textline==0)
8372 textpos=0;
8373 else {
8374 --textline;
8375 show_status(text,search,replace);
8376 textpos=v[textline].s.size();
8377 }
8378 }
8379 if (textpos>=0)
8380 break;
8381 }
8382 case KEY_CTRL_UP:
8383 if (editable){
8384 if (textline>0){
8385 --textline;
8386 show_status(text,search,replace);
8387 }
8388 else {
8389 textline=0;
8390 textpos=0;
8391 }
8392 } else {
8393 if (scroll < 0) {
8394 scroll = scroll + interligne;
8395 if(scroll > 0) scroll = 0;
8396 }
8397 }
8398 break;
8399 case KEY_CTRL_RIGHT:
8400 ++textpos;
8401 if (textpos<=ptr->s.size())
8402 break;
8403 if (textline==v.size()-1){
8404 textpos=ptr->s.size();
8405 break;
8406 }
8407 textpos=0;
8408 case KEY_CTRL_DOWN:
8409 if (editable){
8410 if (textline<v.size()-1)
8411 ++textline;
8412 else {
8413 textline=v.size()-1;
8414 textpos=v[textline].s.size();
8415 }
8416 show_status(text,search,replace);
8417 }
8418 else {
8419 if (textY > scrollableHeight-(showtitle ? 0 : interligne)) {
8420 scroll = scroll - interligne;
8421 if(scroll < -totalTextY+scrollableHeight-(showtitle ? 0 : interligne)) scroll = -totalTextY+scrollableHeight-(showtitle ? 0 : interligne);
8422 }
8423 }
8424 break;
8425 case KEY_CTRL_PAGEDOWN:
8426 if (editable){
8427 textline=v.size()-1;
8428 textpos=v[textline].s.size();
8429 }
8430 else {
8431 if (textY > scrollableHeight-(showtitle ? 0 : interligne)) {
8432 scroll = scroll - scrollableHeight;
8433 if(scroll < -totalTextY+scrollableHeight-(showtitle ? 0 : interligne)) scroll = -totalTextY+scrollableHeight-(showtitle ? 0 : interligne);
8434 }
8435 }
8436 break;
8437 case KEY_CTRL_PAGEUP:
8438 if (editable)
8439 textline=0;
8440 else {
8441 if (scroll < 0) {
8442 scroll = scroll + scrollableHeight;
8443 if(scroll > 0) scroll = 0;
8444 }
8445 }
8446 break;
8447 case KEY_SAVE:
8448 save_script(text->filename.c_str(),merge_area(v));
8449 text->changed=false;
8450 char status[256];
8451 sprintf(status,(lang==1)?"%s sauvegarde":"%s saved",text->filename.c_str());
8452 DefineStatusMessage(status, 1, 0, 0);
8453 DisplayStatusArea();
8454 continue;
8455 case KEY_CTRL_F1:
8456 if(text->allowF1) return KEY_CTRL_F1;
8457 break;
8458 case KEY_CTRL_MENU: case KEY_CTRL_F6:
8459 // case KEY_CHAR_ANS:
8460 if (!text->editable) return TEXTAREA_RETURN_EXIT;
8461 if (clipline<0 && text->editable && text->filename.size()){
8462 Menu smallmenu;
8463 smallmenu.numitems=12;
8464 MenuItem smallmenuitems[smallmenu.numitems];
8465 smallmenu.items=smallmenuitems;
8466 smallmenu.height=12;
8467 smallmenu.scrollbar=0;
8468 //smallmenu.title = "KhiCAS";
8469 smallmenuitems[0].text = (char*)((lang==1)?"Tester syntaxe":"Check syntax");
8470 smallmenuitems[1].text = (char*)((lang==1)?"Sauvegarder":"Save");
8471 smallmenuitems[2].text = (char*)((lang==1)?"Sauvegarder comme":"Save as");
8472 if (exam_mode) smallmenuitems[2].text = (char*)"";
8473 smallmenuitems[3].text = (char*)((lang==1)?"Inserer":"Insert");
8474 smallmenuitems[4].text = (char*)((lang==1)?"Effacer":"Clear");
8475 smallmenuitems[5].text = (char*)((lang==1)?"Chercher,remplacer":"Search, replace");
8476 smallmenuitems[6].text = (char*)((lang==1)?"Aller a la ligne":"Goto line");
8477 int p=python_compat(contextptr);
8478 if (p&4)
8479 smallmenuitems[7].text = (char*)"Change syntax (MicroPython)";
8480 else {
8481 if (p==0)
8482 smallmenuitems[7].text = (char*)"Change syntax (Xcas)";
8483 if (p==1)
8484 smallmenuitems[7].text = (char*)"Change syntax (Xcas comp Python ^=**)";
8485 if (p==2)
8486 smallmenuitems[7].text = (char*)"Change syntax (Xcas comp Python ^=xor)";
8487 }
8488 smallmenuitems[8].text = (char *)((lang==1)?"Changer taille caracteres":"Change fontsize");
8489 smallmenuitems[9].text = (char *)aide_khicas_string;
8490 smallmenuitems[10].text = (char *)((lang==1)?"A propos":"About");
8491 smallmenuitems[11].text = (char*)((lang==1)?"Quitter":"Quit");
8492 int sres = doMenu(&smallmenu);
8493 if(sres == MENU_RETURN_SELECTION || sres==KEY_CTRL_EXE) {
8494 sres=smallmenu.selection;
8495 if (sres==12){
8496 int res=check_leave(text);
8497 if (res==2)
8498 continue;
8499 return TEXTAREA_RETURN_EXIT;
8500 }
8501 if(sres >= 10) {
8502 textArea text;
8503 text.editable=false;
8504 text.clipline=-1;
8505 text.title = smallmenuitems[sres-1].text;
8506 add(&text,smallmenu.selection==10?((lang==1)?shortcuts_fr_string:shortcuts_en_string):((lang==1)?apropos_fr_string:apropos_en_string));
8507 if (doTextArea(&text,contextptr)==KEY_SHUTDOWN)
8508 return KEY_SHUTDOWN;
8509 continue;
8510 }
8511 if (sres==9 && editable){
8512 bool minimini=!v[0].minimini;
8513 for (int i=0;i<v.size();++i)
8514 v[i].minimini=minimini;
8515 text->lineHeight=minimini?13:17;
8516 continue;
8517 }
8518 if (sres==1){
8519 int err=check_parse(text,v,text->python,contextptr);
8520 if (err==KEY_SHUTDOWN)
8521 return err;
8522 if (err) // move cursor to the error line
8523 textline=err-1;
8524 }
8525 if (sres==3 && exam_mode==0){
8526 char filename[MAX_FILENAME_SIZE+1];
8527 if (get_filename(filename,".py")){
8528 text->filename=filename;
8529 sres=2;
8530 }
8531 }
8532 if(sres == 2) {
8533 save_script(text->filename.c_str(),merge_area(v));
8534 text->changed=false;
8535 char status[256];
8536 sprintf(status,(lang==1)?"%s sauvegarde":"%s saved",text->filename.c_str());
8537 DefineStatusMessage(status, 1, 0, 0);
8538 DisplayStatusArea();
8539 }
8540 if (sres==4){
8541 char filename[MAX_FILENAME_SIZE+1];
8542 std::string ins;
8543 if (giac_filebrowser(filename, "py", "Scripts") && load_script(filename,ins))
8544 insert(text,ins.c_str(),false);//add_nl(text,ins);
8545 }
8546 if (sres==5){
8547 std::string s(merge_area(v));
8548 #if 0
8549 for (size_t i=0;i<s.size();++i){
8550 if (s[i]=='\n')
8551 s[i]=0x1e;
8552 }
8553 CLIP_Store(s.c_str(),s.size()+1);
8554 #endif
8555 copy_clipboard(s,false);
8556 set_undo(text);
8557 v.resize(1);
8558 v[0].s="";
8559 textline=0;
8560 }
8561 if (sres==6){
8562 display(text,isFirstDraw,totalTextY,scroll,textY,contextptr);
8563 search=get_searchitem(replace);
8564 if (!search.empty()){
8565 for (;;){
8566 if (!move_to_word(text,search,replace,isFirstDraw,totalTextY,scroll,textY,contextptr)){
8567 break;
8568 }
8569 }
8570 show_status(text,search,replace);
8571 }
8572 }
8573 if (sres==7){
8574 display(text,isFirstDraw,totalTextY,scroll,textY,contextptr);
8575 int l=get_line_number((lang==1)?"Negatif: en partant de la fin":"Negative: counted from the end",(lang==1)?"Numero de ligne:":"Line number:");
8576 if (l>0)
8577 text->line=l-1;
8578 if (l<0)
8579 text->line=v.size()+l;
8580 }
8581 if (sres==8){
8582 int c=select_interpreter();
8583 if (c>=0){
8584 int p=text->python;
8585 if (c==3)
8586 p |= 0x4;
8587 else
8588 p=c;
8589 giac::python_compat(p,contextptr);
8590 text->python=p;
8591 xcas_python_eval=c==3;
8592 show_status(text,search,replace);
8593 warn_python(text->python,false);
8594 drawRectangle(0,205,LCD_WIDTH_PX,17,44444);
8595 PrintMiniMini(0,205,"shift-1 test|2 loop|3 undo|4 misc|5 +- | ",4,44444,giac::_BLACK);
8596 }
8597 }
8598 }
8599 }
8600 break;
8601 case KEY_CTRL_SETUP: // inactive
8602 text->python=text->python?0:1;
8603 show_status(text,search,replace);
8604 python_compat(text->python,contextptr);
8605 warn_python(text->python,false);
8606 drawRectangle(0,205,LCD_WIDTH_PX,17,44444);
8607 PrintMiniMini(0,205,"shift-1 test|2 loop|3 undo|4 misc|5 +- | ",4,44444,giac::_BLACK);
8608 continue;
8609 case KEY_CTRL_F2:
8610 if (clipline<0)
8611 return KEY_CTRL_F2;
8612 case KEY_CTRL_EXIT:
8613 if (clipline>=0){
8614 clipline=-1;
8615 show_status(text,search,replace);
8616 continue;
8617 }
8618 if (!search.empty()){
8619 search="";
8620 show_status(text,search,replace);
8621 continue;
8622 }
8623 if (check_leave(text)==2)
8624 continue;
8625 return TEXTAREA_RETURN_EXIT;
8626 case KEY_CTRL_INS:
8627 break;
8628 default:
8629 if (clipline<0 && key>=32 && key<128 && editable){
8630 char buf[2]={char(key),0};
8631 insert(text,buf,false);
8632 show_status(text,search,replace);
8633 }
8634 if (key==KEY_CTRL_AC){
8635 if (clipline>=0){
8636 clipline=-1;
8637 show_status(text,search,replace);
8638 }
8639 else {
8640 if (search.size()){
8641 search="";
8642 show_status(text,search,replace);
8643 }
8644 else {
8645 copy_clipboard(v[textline].s+'\n',true);
8646 if (v.size()==1)
8647 v[0].s="";
8648 else {
8649 v.erase(v.begin()+textline);
8650 if (textline>=v.size())
8651 --textline;
8652 }
8653 DefineStatusMessage((char*)"Line cut and copied to clipboard", 1, 0, 0);
8654 DisplayStatusArea();
8655 }
8656 }
8657 }
8658 }
8659 }
8660 }
8661
reload_edptr(const char * filename,textArea * edptr,GIAC_CONTEXT)8662 void reload_edptr(const char * filename,textArea *edptr,GIAC_CONTEXT){
8663 if (edptr){
8664 std::string s(merge_area(edptr->elements));
8665 copy_clipboard(s,true);
8666 s="\n";
8667 edptr->elements.clear();
8668 edptr->clipline=-1;
8669 edptr->filename=remove_path(giac::remove_extension(filename))+".py";
8670 load_script((char *)edptr->filename.c_str(),s);
8671 if (s.empty())
8672 s="\n";
8673 // cout << "script " << edptr->filename << endl;
8674 edptr->editable=true;
8675 edptr->changed=false;
8676 edptr->python=python_compat(contextptr);
8677 edptr->elements.clear();
8678 edptr->y=7;
8679 add(edptr,s);
8680 edptr->line=0;
8681 edptr->pos=0;
8682 }
8683 }
8684
8685 console_line * Line=0;//[_LINE_MAX];//={data_line};
8686 char menu_f1[8]={0},menu_f2[8]={0},menu_f3[8]={0},menu_f4[8]={0},menu_f5[8]={0},menu_f6[8];
8687 char session_filename[MAX_FILENAME_SIZE+1]="session";
8688 char * FMenu_entries_name[6]={menu_f1,menu_f2,menu_f3,menu_f4,menu_f5,menu_f6};
8689 location Cursor;
8690 char *Edit_Line=0;
8691 int Start_Line, Last_Line,editline_cursor;
8692 int Case;
8693 int console_changed=0; // 1 if something new in history
8694 int dconsole_mode=1; // 0 disables dConsole commands
8695
8696 #define Current_Line (Start_Line + Cursor.y)
8697 #define Current_Col (Line[Cursor.y + Start_Line].start_col + Cursor.x)
8698
console_disp_status(GIAC_CONTEXT)8699 void console_disp_status(GIAC_CONTEXT){
8700 int i=python_compat(contextptr);
8701 string msg;
8702 if (i&4)
8703 msg="MicroPython";
8704 else {
8705 if (i==0)
8706 msg="Xcas";
8707 else {
8708 if (i==1)
8709 msg="Py ^=**";
8710 else
8711 msg="Py ^=xor";
8712 }
8713 }
8714 if (angle_radian(contextptr))
8715 msg += " RAD ";
8716 else
8717 msg += " DEG ";
8718 msg += session_filename;
8719 if (console_changed)
8720 msg += " *";
8721 statuslinemsg(msg.c_str());
8722 set_xcas_status();
8723 Bdisp_PutDisp_DD();
8724 }
8725
leave_exam_mode(GIAC_CONTEXT)8726 void leave_exam_mode(GIAC_CONTEXT){
8727 #ifdef NSPIRE_NEWLIB
8728 // FIXME test USB connection instead
8729 unsigned NSPIRE_RTC_ADDR=0x90090000;
8730 unsigned t1= * (volatile unsigned *) NSPIRE_RTC_ADDR;
8731 int chk=0;
8732 if (exam_duration<=0 || (t1-exam_start<exam_duration)){
8733 chk=-1;
8734 #if 1 // checkin the power management addresses range
8735 unsigned poweraddr=0x900b0028;
8736 unsigned u=*(unsigned *)poweraddr;
8737 //*logptr(contextptr) << "power " << u << '\n';
8738 if ( (u&0xff0000)==0x070000) // connected 0x11070114, disconnected 0x11110114
8739 chk=0;
8740 #endif
8741 #if 0 /// check connection, works only if graph link connection before
8742 unsigned powermanagement_lockaddr=0x900b0018;
8743 // Bit 5: #B0000000 - USB OTG controller
8744 // Bit 6: #B4000000 - USB HOST controller
8745 *(unsigned *)powermanagement_lockaddr=0x8400a5d;
8746 unsigned HW_USBCTRL_PORTSC1=0xb0000184;
8747 unsigned u=*(unsigned *) HW_USBCTRL_PORTSC1;
8748 if ( (u&0xff000000)==0x11000000) // 0x11000805 vs 0x1d000004
8749 chk=0;
8750 // B00001A4 might be used as well: HW_USBCTRL_OTGSC 1f202d20 vs 1f3c1120
8751 #endif
8752 #if 0 // check USB does not work
8753 nn_ch_t ch = NULL;
8754 nn_oh_t oh = NULL;
8755 nn_nh_t nh = NULL;
8756 oh = TI_NN_CreateOperationHandle();
8757 int ans=TI_NN_NodeEnumInit((nn_ch_t) oh);//(ch);
8758 *logptr(contextptr) << "enuminit" << ans << '\n';
8759 if (ans>=0){
8760 ans=TI_NN_NodeEnumNext(oh, &nh);
8761 *logptr(contextptr) << "enumnext" << ans << '\n';
8762 if (ans>=0){
8763 ans=TI_NN_Connect(nh, 0x4060, &ch);
8764 *logptr(contextptr) << "connect" << ans << '\n';
8765 if (ans>=0){
8766 if(ch){
8767 TI_NN_Disconnect(ch);
8768 chk=0;
8769 }
8770 }
8771 }
8772 TI_NN_NodeEnumDone(oh);
8773 TI_NN_DestroyOperationHandle(oh);
8774 }
8775 #endif
8776 }
8777 #else
8778 int chk=0;
8779 #endif
8780 if (chk>=0){
8781 set_exam_mode(0,contextptr);
8782 }
8783 if (exam_mode)
8784 confirm((lang==1)?"Pour arreter le mode examen":"To stop exam mode",(lang==1)?"branchez la calculatrice puis menu menu":"plug in the calculator then menu menu");
8785 else
8786 confirm((lang==1)?"Fin du mode examen":"End exam mode","enter: OK");
8787 }
8788
menu_setup(GIAC_CONTEXT)8789 void menu_setup(GIAC_CONTEXT){
8790 Menu smallmenu;
8791 smallmenu.numitems=13;
8792 MenuItem smallmenuitems[smallmenu.numitems];
8793 smallmenu.items=smallmenuitems;
8794 smallmenu.height=12;
8795 smallmenu.scrollbar=1;
8796 smallmenu.scrollout=1;
8797 smallmenu.title = (char*)"Config";
8798 #ifdef NUMWORKS
8799 smallmenuitems[0].type = MENUITEM_CHECKBOX;
8800 smallmenuitems[0].text = (char*)"x,n,t -> t";
8801 #endif
8802 smallmenuitems[1].text = (char*)"Syntaxe (Xcas/Python)";
8803 smallmenuitems[2].type = MENUITEM_CHECKBOX;
8804 smallmenuitems[2].text = (char*)"Radians (in Xcas)";
8805 smallmenuitems[3].type = MENUITEM_CHECKBOX;
8806 smallmenuitems[3].text = (char*)"Sqrt (in Xcas)";
8807 smallmenuitems[4].text = (char*)"Francais";
8808 smallmenuitems[5].text = (char*)"English";
8809 smallmenuitems[6].text = (char*)"Spanish&English";
8810 smallmenuitems[7].text = (char*)"Greek&English";
8811 smallmenuitems[8].text = (char*)"Deutsch&English";
8812 smallmenuitems[9].text = (char *) ((lang==1)?"Raccourcis clavier (0)":"Shortcuts (0)");
8813 smallmenuitems[10].text = (char*) ((lang==1)?"Mode examen (e^x)":"Exam mode (e^x)");
8814 smallmenuitems[11].text = (char*) ((lang==1)?"A propos":"About");
8815 smallmenuitems[12].text = (char*) "Quit";
8816 if (exam_mode)
8817 smallmenuitems[12].text = (char*)((lang==1)?"Quitter le mode examen":"Quit exam mode");
8818
8819 // smallmenuitems[2].text = (char*)(isRecording ? "Stop Recording" : "Record Script");
8820 while(1) {
8821 #ifdef NUMWORKS
8822 smallmenuitems[0].value = xthetat;
8823 #else
8824 string dig("Digits (in Xcas): ");
8825 dig += print_INT_(decimal_digits(contextptr));
8826 smallmenuitems[0].text = (char*)dig.c_str();
8827 #endif
8828 int p=python_compat(contextptr);
8829 if (p&4)
8830 smallmenuitems[1].text = (char*)"Change syntax (MicroPython)";
8831 else {
8832 if (p==0)
8833 smallmenuitems[1].text = (char*)"Change syntax (Xcas)";
8834 if (p==1)
8835 smallmenuitems[1].text = (char*)"Change syntax (Xcas comp Python ^=**)";
8836 if (p==2)
8837 smallmenuitems[1].text = (char*)"Change syntax (Xcas comp Python ^=xor)";
8838 }
8839 smallmenuitems[2].value = giac::angle_radian(contextptr);
8840 smallmenuitems[3].value = giac::withsqrt(contextptr);
8841 int sres = doMenu(&smallmenu);
8842 if (sres==MENU_RETURN_EXIT)
8843 break;
8844 if (sres == MENU_RETURN_SELECTION || sres==KEY_CTRL_EXE) {
8845 if (smallmenu.selection == 1){
8846 #ifdef NUMWORKS
8847 xthetat=1-xthetat;
8848 #else
8849 double d=decimal_digits(contextptr);
8850 if (inputdouble("Nombre de digits?",d,contextptr) && d==int(d) && d>0){
8851 decimal_digits(d,contextptr);
8852 }
8853 #endif
8854 continue;
8855 }
8856 if (smallmenu.selection == 2){
8857 int c=select_interpreter();
8858 if (c>=0){
8859 int p=giac::python_compat(contextptr);
8860 if (c==3)
8861 p |= 0x4;
8862 else
8863 p=c;
8864 xcas_python_eval=c==3;
8865 giac::python_compat(p,contextptr);
8866 warn_python(p,false);
8867 if (edptr)
8868 edptr->python=p;
8869 Console_FMenu_Init(contextptr);
8870 console_disp_status(contextptr);
8871 break;
8872 }
8873 }
8874 if (smallmenu.selection == 3){
8875 giac::angle_radian(!giac::angle_radian(contextptr),contextptr);
8876 os_set_angle_unit(giac::angle_radian(contextptr)?0:1);
8877 statusline();
8878 continue;
8879 }
8880 if (smallmenu.selection == 4){
8881 giac::withsqrt(!giac::withsqrt(contextptr),contextptr);
8882 continue;
8883 }
8884 if (smallmenu.selection>=5 && smallmenu.selection<=9){
8885 lang=smallmenu.selection-4;
8886 giac::language(lang,contextptr);
8887 break;
8888 }
8889 if (smallmenu.selection == 11){
8890 if (!exam_mode && confirm((lang==1?"Verifiez que le calcul formel est autorise.":"Please check that the CAS is allowed."),(lang==1?"France: autorise au bac. Enter: ok, esc: annul":"enter: yes, esc: no"))!=KEY_CTRL_F1)
8891 break;
8892 // confirmation, duree (>=0 French indicative, else not indicative)
8893 double duration=exam_mode?absint(exam_duration):0;
8894 string msg=(lang==1)?"Compte a rebours en h.min ou 0 pour horloge":"Exam duration in h.min (0: end by pluging)";
8895 msg += print_duration(duration);
8896 if (inputdouble(msg.c_str(),duration,contextptr)){
8897 bool indicative=lang==1?duration>=0:duration<=0;
8898 if (exam_mode)
8899 indicative=exam_duration<=0;
8900 else {
8901 if (lang==1 && !indicative && confirm("Attention, mode non conforme au bac en France","enter: corriger, esc: tant pis")!=KEY_CTRL_F6)
8902 indicative=true;
8903 }
8904 if (duration<0)
8905 duration=-duration;
8906 if (duration>10)
8907 duration=duration/60;
8908 else
8909 duration=std::floor(duration)+100.0/60*(duration-std::floor(duration));
8910 if (duration){
8911 msg=lang==1?"Duree compte a rebours ":"Exam duration ";
8912 double d=giacmax(duration*3600,absint(exam_duration));
8913 msg += print_duration(d);
8914 }
8915 else
8916 msg="Mode examen.";
8917 if (indicative)
8918 msg += lang==1?" Fin par branchement":" Exit by pluging";
8919 if (confirm(msg.c_str(),(lang==1?"!Blocage dans Xcas en mode exam! enter OK, esc annul":"!Trapped in Xcas in exam mode! enter OK, esc cancel."))==KEY_CTRL_F1){
8920 #ifdef NSPIRE_NEWLIB
8921 if (exam_mode)
8922 exam_duration=duration?giacmax(absint(exam_duration),duration*3600+30):0;
8923 else {
8924 unsigned NSPIRE_RTC_ADDR=0x90090000;
8925 exam_start= * (volatile unsigned *) NSPIRE_RTC_ADDR;
8926 exam_duration = duration?duration*3600+30:0;
8927 }
8928 if (indicative)
8929 exam_duration=-absint(exam_duration);
8930 #else
8931 exam_start=0;
8932 exam_duration=1;
8933 #endif
8934 set_exam_mode(1,contextptr);
8935 do_restart(contextptr);
8936 clear_turtle_history(contextptr);
8937 Console_Init(contextptr);
8938 Console_Clear_EditLine();
8939 console_changed=0;
8940 strcpy(session_filename,"session.xw");
8941 save_session(contextptr);
8942 if (edptr){
8943 edptr->elements.resize(1);
8944 edptr->elements[0].s="";
8945 edptr->undoelements=edptr->elements;
8946 edptr->line=0;
8947 edptr->pos=0;
8948 }
8949 save_script("session.py","");
8950 }
8951 }
8952 break;
8953 }
8954 if (smallmenu.selection == 13){
8955 if (exam_mode)
8956 leave_exam_mode(contextptr);
8957 break;
8958 }
8959 if (smallmenu.selection >= 10) {
8960 textArea text;
8961 text.editable=false;
8962 text.clipline=-1;
8963 text.title = smallmenuitems[smallmenu.selection-1].text;
8964 add(&text,smallmenu.selection==10?((lang==1)?shortcuts_fr_string:shortcuts_en_string):((lang==1)?apropos_fr_string:apropos_en_string));
8965 if (doTextArea(&text,contextptr)==KEY_SHUTDOWN)
8966 return ;
8967 continue;
8968 }
8969 }
8970 }
8971 }
8972
console_malloc(unsigned s)8973 void * console_malloc(unsigned s){
8974 return new char [s];
8975 // return malloc(s);
8976 }
8977
console_free(void * ptr)8978 void console_free(void * ptr){
8979 delete [] (char *) ptr;
8980 // free(ptr);
8981 }
8982
cleanup(std::string & s)8983 void cleanup(std::string & s){
8984 for (size_t i=0;i<s.size();++i){
8985 if (s[i]=='\n')
8986 s[i]=' ';
8987 }
8988 }
8989
8990 const int max_lines_saved=50;
8991
run(const char * s,int do_logo_graph_eqw,GIAC_CONTEXT)8992 int run(const char * s,int do_logo_graph_eqw,GIAC_CONTEXT){
8993 if (strlen(s)>=2 && (s[0]=='#' ||
8994 (s[0]=='/' && (s[1]=='/' || s[1]=='*'))
8995 ))
8996 return 0;
8997 if (strcmp(s,"xcas")==0){
8998 xcas_python_eval=0;
8999 python_compat(python_compat(contextptr)&3,contextptr);
9000 if (edptr)
9001 edptr->python=0;
9002 *logptr(contextptr) << "Xcas interpreter\n";
9003 Console_FMenu_Init(contextptr);
9004 return 0;
9005 }
9006 if (strcmp(s,"python")==0){
9007 xcas_python_eval=1;
9008 python_compat(4|python_compat(contextptr),contextptr);
9009 if (edptr)
9010 edptr->python=1;
9011 *logptr(contextptr) << "Micropython interpreter\n";
9012 Console_FMenu_Init(contextptr);
9013 return 0;
9014 }
9015 gen g,ge;
9016 #ifdef MICROPY_LIB
9017 if (xcas_python_eval==1){
9018 freezeturtle=false;
9019 micropy_eval(s);
9020 }
9021 else
9022 do_run(s,g,ge,contextptr);
9023 #else
9024 do_run(s,g,ge,contextptr);
9025 #endif
9026 process_freeze();
9027 #ifdef MICROPY_LIB
9028 if (xcas_python_eval==1)
9029 return 0;
9030 #endif
9031 int t=giac::taille(g,GIAC_HISTORY_MAX_TAILLE);
9032 int te=giac::taille(ge,GIAC_HISTORY_MAX_TAILLE);
9033 bool do_tex=false;
9034 if (t<GIAC_HISTORY_MAX_TAILLE && te<GIAC_HISTORY_MAX_TAILLE){
9035 giac::vecteur &vin=history_in(contextptr);
9036 giac::vecteur &vout=history_out(contextptr);
9037 if (vin.size()>GIAC_HISTORY_SIZE)
9038 vin.erase(vin.begin());
9039 vin.push_back(g);
9040 if (vout.size()>GIAC_HISTORY_SIZE)
9041 vout.erase(vout.begin());
9042 vout.push_back(ge);
9043 }
9044 if (check_do_graph(ge,do_logo_graph_eqw,contextptr)==KEY_SHUTDOWN)
9045 return KEY_SHUTDOWN;
9046 string s_;
9047 if (ge.type==giac::_STRNG)
9048 s_='"'+*ge._STRNGptr+'"';
9049 else {
9050 if (te>256)
9051 s_="Object too large";
9052 else {
9053 if (ge.is_symb_of_sommet(giac::at_pnt) || (ge.type==giac::_VECT && !ge._VECTptr->empty() && ge._VECTptr->back().is_symb_of_sommet(giac::at_pnt)))
9054 s_="Graphic object";
9055 else {
9056 //do_tex=ge.type==giac::_SYMB && has_op(ge,*giac::at_inv);
9057 // tex support has been disabled!
9058 s_=ge.print(contextptr);
9059 // translate to tex? set do_tex to true
9060 }
9061 }
9062 }
9063 #ifdef NUMWORKS
9064 if (s_.size()>512)
9065 s_=s_.substr(0,509)+"...";
9066 #else
9067 if (s_.size()>8192)
9068 s_=s_.substr(0,8189)+"...";
9069 #endif
9070 char* edit_line = (char*)Console_GetEditLine();
9071 Console_Output((const char*)s_.c_str());
9072 return 0;
9073 }
9074
run_session(int start,GIAC_CONTEXT)9075 int run_session(int start,GIAC_CONTEXT){
9076 std::vector<std::string> v;
9077 for (int i=start;i<Last_Line;++i){
9078 if (Line[i].type==LINE_TYPE_INPUT)
9079 v.push_back((const char *)Line[i].str);
9080 console_free(Line[i].str);
9081 Line[i].str=0;
9082 Line[i].readonly = 0;
9083 Line[i].type = LINE_TYPE_INPUT;
9084 Line[i].start_col = 0;
9085 Line[i].disp_len = 0;
9086 }
9087 Line[Last_Line].str=0;
9088 Last_Line=start;
9089 Start_Line=Last_Line>LINE_DISP_MAX?Last_Line-LINE_DISP_MAX:0;
9090 Cursor.x=0;
9091 Cursor.y=start;
9092 Line[start].str=Edit_Line;
9093 Edit_Line[0]=0;
9094 if (v.empty()) return 0;
9095 //Console_Init(contextptr);
9096 for (int i=0;i<v.size();++i){
9097 Console_Output((const char *)v[i].c_str());
9098 //int j=Last_Line;
9099 Console_NewLine(LINE_TYPE_INPUT, 1);
9100 // Line[j].type=LINE_TYPE_INPUT;
9101 run(v[i].c_str(),6,contextptr); /* show logo and graph but not eqw */
9102 // j=Last_Line;
9103 Console_NewLine(LINE_TYPE_OUTPUT, 1);
9104 // Line[j].type=LINE_TYPE_OUTPUT;
9105 Console_Disp(1,contextptr);
9106 Bdisp_PutDisp_DD();
9107 }
9108 return 0;
9109 }
9110
9111
khicas_state(GIAC_CONTEXT)9112 string khicas_state(GIAC_CONTEXT){
9113 giac::gen g(giac::_VARS(-1,contextptr));
9114 int b=python_compat(contextptr);
9115 python_compat(0,contextptr);
9116 #if 1
9117 #ifdef NSPIRE_NEWLIB
9118 char *buf=nspire_filebuf;
9119 buf[0]=0;
9120 int bufsize=NSPIRE_FILEBUFFER;
9121 #else
9122 char buf[6144]="";
9123 int bufsize=sizeof(buf);
9124 #endif
9125 if (g.type==giac::_VECT){
9126 bool ok=true;
9127 for (int i=0;i<g._VECTptr->size();++i){
9128 string s((*g._VECTptr)[i].print(contextptr));
9129 if (strlen(buf)+s.size()+128<bufsize){
9130 strcat(buf,s.c_str());
9131 strcat(buf,":;");
9132 }
9133 else
9134 ok=false;
9135 }
9136 if (!ok){
9137 confirm((lang==1)?"Contexte trop lourd, non sauvegarde":"Context too havy, not saved.",(lang==1)?"Re-executez scripts au chargement (esc enter)":"Re-run scripts at load time (esc enter)",true,64);
9138 buf[0]=0;
9139 }
9140 }
9141 python_compat(b,contextptr);
9142 if (strlen(buf)+128<bufsize){
9143 strcat(buf,"python_compat(");
9144 strcat(buf,giac::print_INT_(b).c_str());
9145 strcat(buf,");angle_radian(");
9146 strcat(buf,angle_radian(contextptr)?"1":"0");
9147 strcat(buf,");with_sqrt(");
9148 strcat(buf,withsqrt(contextptr)?"1":"0");
9149 strcat(buf,");integer_format(");
9150 strcat(buf,integer_format(contextptr)==16?"16":"10");
9151 strcat(buf,");set_language(");
9152 char l[]="0";
9153 l[0]+=lang;
9154 strcat(buf,l);
9155 strcat(buf,");");
9156 }
9157 if (sheetptr){
9158 string s(current_sheet(vecteur(0),contextptr).print(contextptr));
9159 if (strlen(buf)+s.size()+20<bufsize){
9160 strcat(buf,"current_sheet(");
9161 strcat(buf,s.c_str());
9162 strcat(buf,");");
9163 }
9164 }
9165 return buf;
9166 #else
9167 string s(g.print(contextptr));
9168 python_compat(b,contextptr);
9169 s += "; python_compat(";
9170 s += giac::print_INT_(b);
9171 s += ");angle_radian(";
9172 s += angle_radian(contextptr)?'1':'0';
9173 s += ");with_sqrt(";
9174 s += withsqrt(contextptr)?'1':'0';
9175 s += ");";
9176 return s;
9177 #endif
9178 }
Bfile_WriteFile_OS(char * & buf,const void * ptr,size_t len)9179 void Bfile_WriteFile_OS(char * & buf,const void * ptr,size_t len){
9180 memcpy(buf,ptr,len);
9181 buf += len;
9182 }
Bfile_WriteFile_OS4(char * & buf,size_t n)9183 void Bfile_WriteFile_OS4(char * & buf,size_t n){
9184 buf[0]= n>>24;
9185 buf[1]= (n>>16) & 0xff;
9186 buf[2]= (n & 0xffff)>>8;
9187 buf[3]= n & 0xff;
9188 buf += 4;
9189 }
Bfile_WriteFile_OS2(char * & buf,unsigned short n)9190 void Bfile_WriteFile_OS2(char * & buf,unsigned short n){
9191 buf[0]= n>>8;
9192 buf[1]= n & 0xff;
9193 buf += 2;
9194 }
save_console_state_smem(const char * filename,GIAC_CONTEXT)9195 void save_console_state_smem(const char * filename,GIAC_CONTEXT){
9196 console_changed=0;
9197 string state(khicas_state(contextptr));
9198 int statesize=state.size();
9199 string script;
9200 if (edptr)
9201 script=merge_area(edptr->elements);
9202 int scriptsize=script.size();
9203 // save format: line_size (2), start_col(2), line_type (1), readonly (1), line
9204 int size=2*sizeof(int)+statesize+scriptsize;
9205 int start_row=Last_Line-max_lines_saved;
9206 if (start_row<0) start_row=0;
9207 for (int i=start_row;i<=Last_Line;++i){
9208 size += 2*sizeof(short)+2*sizeof(char)+strlen((const char *)Line[i].str);
9209 }
9210 char savebuf[size+4];
9211 #ifdef NUMWORKS
9212 char * hFile=savebuf+1;
9213 #else
9214 char * hFile=savebuf;
9215 #endif
9216 // save variables and modes
9217 Bfile_WriteFile_OS4(hFile, statesize);
9218 Bfile_WriteFile_OS(hFile, state.c_str(), statesize);
9219 // save script
9220 Bfile_WriteFile_OS4(hFile, scriptsize);
9221 Bfile_WriteFile_OS(hFile, script.c_str(), scriptsize);
9222 // save console state
9223 // save console state
9224 for (int i=start_row;i<=Last_Line;++i){
9225 console_line & cur=Line[i];
9226 unsigned short l=strlen((const char *)cur.str);
9227 Bfile_WriteFile_OS2(hFile, l);
9228 unsigned short s=cur.start_col;
9229 Bfile_WriteFile_OS2(hFile, s);
9230 unsigned char c=cur.type;
9231 Bfile_WriteFile_OS(hFile, &c, sizeof(c));
9232 c=1;//cur.readonly;
9233 Bfile_WriteFile_OS(hFile, &c, sizeof(c));
9234 unsigned char buf[l+1];
9235 buf[l]=0;
9236 strcpy((char *)buf,(const char*)cur.str);
9237 unsigned char *ptr=buf,*strend=ptr+l;
9238 for (;ptr<strend;++ptr){
9239 if (*ptr==0x9c)
9240 *ptr='\n';
9241 }
9242 Bfile_WriteFile_OS(hFile, buf, l);
9243 }
9244 char BUF[2]={0,0};
9245 Bfile_WriteFile_OS(hFile, BUF, sizeof(BUF));
9246 #ifdef NUMWORKS
9247 savebuf[0]=1;
9248 #endif
9249 int len=hFile-savebuf;
9250 write_file(filename,savebuf,len);
9251 }
9252
Bfile_ReadFile_OS4(const char * & hf)9253 size_t Bfile_ReadFile_OS4(const char * & hf){
9254 size_t n=(((((hf[0]<<8)+hf[1])<<8)+hf[2])<<8)+hf[3];
9255 hf += 4;
9256 return n;
9257 }
9258
Bfile_ReadFile_OS2(const char * & hf)9259 size_t Bfile_ReadFile_OS2(const char * & hf){
9260 size_t n=(hf[0]<<8)+hf[1];
9261 hf += 2;
9262 return n;
9263 }
9264
Bfile_ReadFile_OS(const char * & hf,char * dest,size_t len)9265 void Bfile_ReadFile_OS(const char * &hf,char * dest,size_t len){
9266 memcpy(dest,hf,len);
9267 hf += len;
9268 }
9269
load_console_state_smem(const char * filename,GIAC_CONTEXT)9270 bool load_console_state_smem(const char * filename,GIAC_CONTEXT){
9271 const char * hf=read_file(filename);
9272 if (!hf) return false;
9273 size_t L=Bfile_ReadFile_OS4(hf);
9274 char BUF[L+4];
9275 BUF[1]=BUF[0]='/'; // avoid trying python compat.
9276 BUF[2]='\n';
9277 Bfile_ReadFile_OS(hf,BUF+3,L);
9278 BUF[L+3]=0;
9279 giac::gen g,ge;
9280 dconsole_mode=0; python_compat(contextptr)=0; xcas_mode(contextptr)=0;
9281 bool bi=try_parse_i(contextptr);
9282 try_parse_i(false,contextptr);
9283 do_run((char*)BUF,g,ge,contextptr);
9284 try_parse_i(bi,contextptr);
9285 dconsole_mode=1;
9286 // read script
9287 L=Bfile_ReadFile_OS4(hf);
9288 if (L>0){
9289 char bufscript[L+1];
9290 Bfile_ReadFile_OS(hf,bufscript,L);
9291 bufscript[L]=0;
9292 if (edptr==0)
9293 edptr=new textArea;
9294 if (edptr){
9295 edptr->elements.clear();
9296 edptr->clipline=-1;
9297 edptr->filename=remove_path(giac::remove_extension(filename))+".py";
9298 //cout << "script " << edptr->filename << endl;
9299 edptr->editable=true;
9300 edptr->changed=false;
9301 edptr->python=python_compat(contextptr);
9302 edptr->elements.clear();
9303 edptr->y=0;
9304 add(edptr,bufscript);
9305 edptr->line=0;
9306 //edptr->line=edptr->elements.size()-1;
9307 edptr->pos=0;
9308 }
9309 }
9310 // read console state
9311 // insure parse messages are cleared
9312 Console_Init(contextptr);
9313 Console_Clear_EditLine();
9314 for (int pos=0;;++pos){
9315 unsigned short int l,curs;
9316 unsigned char type,readonly;
9317 if ( (l=Bfile_ReadFile_OS2(hf))==0) break;
9318 curs=Bfile_ReadFile_OS2(hf);
9319 type = *hf; ++hf;
9320 readonly=*hf; ++hf;
9321 char buf[l+1];
9322 Bfile_ReadFile_OS(hf,buf,l);
9323 buf[l]=0;
9324 // ok line ready in buf
9325 while (Line[Current_Line].readonly)
9326 Console_MoveCursor(CURSOR_DOWN);
9327 Console_Input(buf);
9328 Console_NewLine(LINE_TYPE_INPUT, 1);
9329 #if 1
9330 if (Current_Line>0){
9331 console_line & cur=Line[Current_Line-1];
9332 cur.type=type;
9333 cur.readonly=readonly;
9334 cur.start_col+=curs;
9335 }
9336 #endif
9337 }
9338 console_changed=0;
9339 if (python_compat(contextptr)&4)
9340 xcas_python_eval=1;
9341 Console_FMenu_Init(contextptr); // insure the menus are sync-ed
9342 return true;
9343 }
9344
9345 /*
9346
9347 The following functions will be used to specify the location before deleting a string of n characters altogether. Among them, a wide character (2 bytes) will be counted as a character.
9348
9349 For example, we have the following string str:
9350
9351 Location | 0 | 1 | 2 | 3 | 4 | 5 | 6 |
9352 Character | 'a' | 'b' | 'c' | 'd' | 'e' | 'f' | 0 |
9353
9354 After the call Console_DelStr (str, 3, 2), position 1 and 2 characters will be deleted, then the characters will be in advance.
9355
9356 Results are as follows:
9357
9358 Location | 0 | 1 | 2 | 3 | 4 | 5 | 6 |
9359 Character | 'a' | 'd' | 'e' | 'f' | 0 | 'f' | 0 |
9360
9361 (Note: the extra positions will not be filled with '\ 0', but '\ 0' will be a copy of the original end of the string.)
9362
9363 */
9364
Console_DelStr(char * str,int end_pos,int n)9365 int Console_DelStr(char *str, int end_pos, int n)
9366 {
9367 int str_len, actual_end_pos, start_pos, actual_start_pos, del_len, i;
9368
9369 str_len = strlen((const char *)str);
9370 if ((start_pos = end_pos - n) < 0) return CONSOLE_ARG_ERR;
9371
9372 if ((actual_end_pos = Console_GetActualPos(str, end_pos)) == CONSOLE_ARG_ERR) return CONSOLE_ARG_ERR;
9373 if ((actual_start_pos = Console_GetActualPos(str, start_pos)) == CONSOLE_ARG_ERR) return CONSOLE_ARG_ERR;
9374
9375 del_len = actual_end_pos - actual_start_pos;
9376
9377 for (i = actual_start_pos; i < str_len; i++)
9378 {
9379 str[i] = str[i + del_len];
9380 }
9381
9382 return CONSOLE_SUCCEEDED;
9383 }
9384
9385 /*
9386
9387 The following functions are used to specify the location of the insertion in the specified string.
9388 (Note: This refers to the position of the printing position when, rather than the actual position.)
9389 */
9390
Console_InsStr(char * dest,const char * src,int disp_pos)9391 int Console_InsStr(char *dest, const char *src, int disp_pos)
9392 {
9393 int i, ins_len, str_len, actual_pos;
9394
9395 ins_len = strlen((const char *)src);
9396 str_len = strlen((const char *)dest);
9397
9398 actual_pos = Console_GetActualPos(dest, disp_pos);
9399
9400 if (ins_len + str_len >= EDIT_LINE_MAX) return CONSOLE_MEM_ERR;
9401 if (actual_pos > str_len) return CONSOLE_ARG_ERR;
9402
9403 for (i = str_len; i >= actual_pos; i--)
9404 {
9405 dest[i + ins_len] = dest[i];
9406 }
9407
9408 for (i = 0; i < ins_len; i++)
9409 {
9410 char c=src[i];
9411 if (c=='\n') c=0x9c;
9412 dest[actual_pos + i] = (c==0x0a?' ':c);
9413 }
9414
9415 return CONSOLE_SUCCEEDED;
9416 }
9417
9418 /*
9419
9420 The following function is used to determine the true position of the string corresponding to the printing position.
9421 For example, in the following this string str contains wide characters, the location of the print is as follows:
9422
9423 Location | 00 | 01 | 02 | 03 | 04 | 05 | 06 |
9424 Character | one | two | three | four | five | six | \ 0 |
9425
9426 The actual storage location is as follows:
9427
9428 Location | 00 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 |
9429 Value | 0xD2 | 0xBB | 0xB6 | 0xFE | 0xC8 | 0xFD | 0xCB | 0xC4 | 0xCE | 0xE5 | 0xC1 | 0xF9 |
9430
9431 You can find the first four characters 'five' is actually stored in the eighth position.
9432 So, when you call Console_GetActualPos (str, 4), it will return 8.
9433 */
9434
Console_GetActualPos(const char * str,int disp_pos)9435 int Console_GetActualPos(const char *str, int disp_pos)
9436 {
9437 int actual_pos, count;
9438
9439 for (actual_pos = count = 0; count < disp_pos; count++)
9440 {
9441 if (str[actual_pos] == '\0') return CONSOLE_ARG_ERR;
9442
9443 if (is_wchar(str[actual_pos]))
9444 {
9445 actual_pos += 2;
9446 }
9447 else
9448 {
9449 actual_pos++;
9450 }
9451 }
9452
9453 return actual_pos;
9454 }
9455
9456 /*
9457 The following functions are used to obtain a string of print length, ie, a wide character (2 bytes) recorded as a character.
9458 */
9459
Console_GetDispLen(const char * str)9460 int Console_GetDispLen(const char *str)
9461 {
9462 int i, len;
9463
9464 for (i = len = 0; str[i]!='\0'; len++)
9465 {
9466 if (is_wchar(str[i]))
9467 {
9468 i += 2;
9469 }
9470 else
9471 {
9472 i++;
9473 }
9474 }
9475
9476 return len;
9477 }
9478
9479 /*
9480 The following functions are used to move the cursor.
9481 */
9482
Console_MoveCursor(int direction)9483 int Console_MoveCursor(int direction)
9484 {
9485 switch (direction)
9486 {
9487 case CURSOR_UP:
9488 if (Current_Line==Last_Line)
9489 editline_cursor=Cursor.x;
9490 //If you need to operate.
9491 if ((Cursor.y > 0) || (Start_Line > 0)){
9492 //If the current line is not read-only, then Edit_Line copy to the current line.
9493 if (!Line[Current_Line].readonly){
9494 if ((Line[Current_Line].str = (char *)console_malloc(strlen((const char *)Edit_Line) + 1)) == NULL) return CONSOLE_MEM_ERR;
9495 strcpy((char *)Line[Current_Line].str, (const char *)Edit_Line);
9496 Line[Current_Line].disp_len = Console_GetDispLen(Line[Current_Line].str);
9497 Line[Current_Line].type = LINE_TYPE_INPUT;
9498 }
9499 //If the cursor does not move to the top of, directly move the cursor upward.
9500 if (Cursor.y > 0)
9501 Cursor.y--;
9502 //Otherwise, the number of rows, if the screen's first line is not the first line, then began to show minus one.
9503 else {
9504 if (Start_Line > 0)
9505 Start_Line--;
9506 }
9507 //End if the horizontal position after moving the cursor over the line, then move the cursor to the end of the line.
9508 if (Cursor.x > Line[Current_Line].disp_len){
9509 Cursor.x = Line[Current_Line].disp_len;
9510 }
9511 else {
9512 if (Line[Current_Line].disp_len - Line[Current_Line].start_col > COL_DISP_MAX){
9513 if (Cursor.x == COL_DISP_MAX)
9514 Cursor.x = COL_DISP_MAX - 1;
9515 }
9516 }
9517 //If you move the cursor to the line after the first, and the front of the line there is a character does not appear, then move the cursor to position 1.
9518 if (Cursor.x == 0 && Line[Current_Line].start_col > 0)
9519 Cursor.x = 1;
9520 //If the current cursor line is not read-only, then it is a string copy to Edit_Line for editing.
9521 if (!Line[Current_Line].readonly){
9522 strcpy((char *)Edit_Line, (const char *)Line[Current_Line].str);
9523 console_free(Line[Current_Line].str);
9524 Line[Current_Line].str = Edit_Line;
9525 }
9526 }
9527 break;
9528 case CURSOR_ALPHA_UP:{
9529 int pos1=Start_Line+Cursor.y;
9530 Console_MoveCursor(CURSOR_UP);
9531 int pos2=Start_Line+Cursor.y;
9532 if (pos1<Last_Line && pos2<Last_Line && pos1!=pos2){
9533 console_line curline=Line[pos1];
9534 Line[pos1]=Line[pos2];
9535 Line[pos2]=curline;
9536 }
9537 break;
9538 }
9539 case CURSOR_ALPHA_DOWN: {
9540 int pos1=Start_Line+Cursor.y;
9541 Console_MoveCursor(CURSOR_DOWN);
9542 int pos2=Start_Line+Cursor.y;
9543 if (pos1<Last_Line && pos2<Last_Line && pos1!=pos2){
9544 console_line curline=Line[pos1];
9545 Line[pos1]=Line[pos2];
9546 Line[pos2]=curline;
9547 }
9548 break;
9549 }
9550 case CURSOR_DOWN:
9551 if (Current_Line==Last_Line)
9552 editline_cursor=Cursor.x;
9553 //If you need to operate.
9554 if ((Cursor.y < LINE_DISP_MAX - 1) && (Current_Line < Last_Line) || (Start_Line + LINE_DISP_MAX - 1 < Last_Line))
9555 {
9556 //If the current line is not read-only, then Edit_Line copy to the current line.
9557 if (!Line[Current_Line].readonly)
9558 {
9559 if ((Line[Current_Line].str = (char *)console_malloc(strlen((const char *)Edit_Line) + 1)) == NULL) return CONSOLE_MEM_ERR;
9560 strcpy((char *)Line[Current_Line].str, (const char *)Edit_Line);
9561 Line[Current_Line].disp_len = Console_GetDispLen(Line[Current_Line].str);
9562 Line[Current_Line].type = LINE_TYPE_INPUT;
9563 }
9564
9565 //If the cursor does not move to the bottom, the cursor moves down directly.
9566 if (Cursor.y < LINE_DISP_MAX - 1 && Current_Line < Last_Line)
9567 {
9568 Cursor.y++;
9569 }
9570 //The number of rows Otherwise, if the last line is not the last line on the screen, it will begin to show a plus.
9571 else if (Start_Line + LINE_DISP_MAX - 1 < Last_Line)
9572 {
9573 Start_Line++;
9574 }
9575
9576 //If you move the cursor after the end of the horizontal position over the line, then move the cursor to the end of the line.
9577 if (Cursor.x > Line[Current_Line].disp_len)
9578 {
9579 Cursor.x = Line[Current_Line].disp_len;
9580 }
9581 else if (Line[Current_Line].disp_len - Line[Current_Line].start_col >= COL_DISP_MAX)
9582 {
9583 if (Cursor.x == COL_DISP_MAX) Cursor.x = COL_DISP_MAX - 1;
9584 }
9585
9586 //If you move the cursor to the line after the first, and the front of the line there is a character does not appear, then move the cursor to position 1.
9587 if (Cursor.x == 0 && Line[Current_Line].start_col > 0) Cursor.x = 1;
9588
9589 //If the current cursor line is not read-only, then it is a string copy to Edit_Line for editing.
9590 if (!Line[Current_Line].readonly)
9591 {
9592 strcpy((char *)Edit_Line, (const char *)Line[Current_Line].str);
9593 console_free(Line[Current_Line].str);
9594 Line[Current_Line].str = Edit_Line;
9595 }
9596 }
9597 break;
9598 case CURSOR_LEFT:
9599 if (Line[Current_Line].readonly){
9600 if (Line[Current_Line].start_col > 0){
9601 Line[Current_Line].start_col--;
9602 }
9603 break;
9604 }
9605 else {
9606 if (Line[Current_Line].start_col > 0){
9607 if (Cursor.x > 1)
9608 Cursor.x--;
9609 else
9610 Line[Current_Line].start_col--;
9611 break;
9612 }
9613 if (Cursor.x > 0){
9614 Cursor.x--;
9615 break;
9616 }
9617 }
9618 case CURSOR_SHIFT_RIGHT:
9619 if (!Line[Current_Line].readonly)
9620 Cursor.x=giacmin(Line[Current_Line].disp_len,COL_DISP_MAX);
9621 if (Line[Current_Line].disp_len > COL_DISP_MAX)
9622 Line[Current_Line].start_col = Line[Current_Line].disp_len - COL_DISP_MAX;
9623 break;
9624 case CURSOR_RIGHT:
9625 if (Line[Current_Line].readonly){
9626 if (Line[Current_Line].disp_len - Line[Current_Line].start_col > COL_DISP_MAX){
9627 Line[Current_Line].start_col++;
9628 }
9629 break;
9630 }
9631 else {
9632 if (Line[Current_Line].disp_len - Line[Current_Line].start_col > COL_DISP_MAX){
9633 if (Cursor.x < COL_DISP_MAX - 1)
9634 Cursor.x++;
9635 else
9636 Line[Current_Line].start_col++;
9637 break;
9638 }
9639 if (Cursor.x < Line[Current_Line].disp_len - Line[Current_Line].start_col){
9640 Cursor.x++;
9641 break;
9642 }
9643 }
9644 case CURSOR_SHIFT_LEFT:
9645 if (!Line[Current_Line].readonly)
9646 Cursor.x=0;
9647 Line[Current_Line].start_col=0;
9648 break;
9649 default:
9650 return CONSOLE_ARG_ERR;
9651 break;
9652 }
9653 return CONSOLE_SUCCEEDED;
9654 }
9655
9656 /*
9657 The following function is used for input.
9658 String input to the cursor, the cursor will automatically move.
9659 */
9660
Console_Input(const char * str)9661 int Console_Input(const char *str)
9662 {
9663 console_changed=1;
9664 int old_len,i,return_val;
9665
9666 if (!Line[Current_Line].readonly)
9667 {
9668 old_len = Line[Current_Line].disp_len;
9669 return_val = Console_InsStr(Edit_Line, str, Current_Col);
9670 if (return_val != CONSOLE_SUCCEEDED) return return_val;
9671 if ((Line[Current_Line].disp_len = Console_GetDispLen(Edit_Line)) == CONSOLE_ARG_ERR) return CONSOLE_ARG_ERR;
9672 for (i = 0; i < Line[Current_Line].disp_len - old_len; i++)
9673 {
9674 Console_MoveCursor(CURSOR_RIGHT);
9675 }
9676 return CONSOLE_SUCCEEDED;
9677 }
9678 else
9679 {
9680 return CONSOLE_ARG_ERR;
9681 }
9682 }
9683
9684 /*
9685 The following functions are used to output the string to the current line.
9686 */
9687
Console_Output(const char * str)9688 int Console_Output(const char *str) {
9689 if (!Line) return 0;
9690 console_changed=1;
9691 int return_val, old_len, i;
9692
9693 if (!Line[Current_Line].readonly)
9694 {
9695 old_len = Line[Current_Line].disp_len;
9696
9697 return_val = Console_InsStr(Edit_Line, str, Current_Col);
9698 if (return_val != CONSOLE_SUCCEEDED) return return_val;
9699 if ((Line[Current_Line].disp_len = Console_GetDispLen(Edit_Line)) == CONSOLE_ARG_ERR) return CONSOLE_ARG_ERR;
9700 Line[Current_Line].type = LINE_TYPE_OUTPUT;
9701
9702 for (i = 0; i < Line[Current_Line].disp_len - old_len; i++)
9703 {
9704 Console_MoveCursor(CURSOR_RIGHT);
9705 }
9706 return CONSOLE_SUCCEEDED;
9707 }
9708 else
9709 {
9710 return CONSOLE_ARG_ERR;
9711 }
9712 }
9713
dConsolePut(const char * S)9714 void dConsolePut(const char * S){
9715 if (!dconsole_mode)
9716 return;
9717 int l=strlen(S);
9718 char s[l+1];
9719 strcpy(s,S);
9720 for (int i=0;i<l;++i){
9721 if (s[i]=='\n' ||
9722 s[i]==10)
9723 s[i]=' ';
9724 }
9725 Console_Output((const char *)s);
9726 if (l && S[l-1]=='\n'){
9727 Console_NewLine(LINE_TYPE_OUTPUT, 1);
9728 if (!freeze)
9729 Console_Disp(1,0);
9730 }
9731 }
9732
dPuts(const char * s)9733 void dPuts(const char * s){
9734 dConsolePut(s);
9735 }
9736
9737 #define PUTCHAR_LEN 35
9738 static char putchar_buf[PUTCHAR_LEN+2];
9739 static int putchar_pos=0;
dConsolePutChar(const char ch)9740 void dConsolePutChar(const char ch){
9741 if (!dconsole_mode)
9742 return;
9743 if (putchar_pos==PUTCHAR_LEN)
9744 dConsolePutChar('\n');
9745 if (ch=='\n'){
9746 putchar_buf[putchar_pos]='\n';
9747 putchar_buf[putchar_pos+1]=0;
9748 putchar_pos=0;
9749 dConsolePut(putchar_buf);
9750 }
9751 else {
9752 putchar_buf[putchar_pos]=ch;
9753 ++putchar_pos;
9754 }
9755 }
9756
9757 /*
9758 Clear the current output line
9759 */
9760
Console_Clear_EditLine()9761 void Console_Clear_EditLine()
9762 {
9763 if(!Line[Current_Line].readonly) {
9764 Edit_Line[0] = '\0';
9765 Line[Current_Line].start_col = 0;
9766 Line[Current_Line].disp_len = 0;
9767 Cursor.x = 0;
9768 }
9769 }
9770
9771 /*
9772
9773 The following functions are used to create a new line.
9774 Pre_line_type type parameter is used to specify the line, pre_line_readonly parameter is used to specify the line is read-only.
9775 New_line_type parameter is used to specify the type of the next line, new_line_readonly parameter is used to specify the next line is read-only.
9776 */
9777
Console_NewLine(int pre_line_type,int pre_line_readonly)9778 int Console_NewLine(int pre_line_type, int pre_line_readonly)
9779 {
9780 if (!Line) return 0;
9781 console_changed=1;
9782 int i;
9783
9784 if (strlen((const char *)Edit_Line)||Line[Current_Line].type==LINE_TYPE_OUTPUT)
9785 {
9786 //Èç¹ûÒѾÊÇËùÄÜ´æ´¢µÄ×îºóÒ»ÐУ¬Ôòɾ³ýµÚÒ»ÐС£
9787 //If this is the last line we can store, delete the first line.
9788 if (Last_Line == _LINE_MAX - 1)
9789 {
9790 for (i = 0; i < Last_Line; i++)
9791 {
9792 Line[i].disp_len = Line[i + 1].disp_len;
9793 Line[i].readonly = Line[i + 1].readonly;
9794 Line[i].start_col = Line[i + 1].start_col;
9795 Line[i].str = Line[i + 1].str;
9796 Line[i].type = Line[i + 1].type;
9797 }
9798 Last_Line--;
9799
9800 if (Start_Line > 0) Start_Line--;
9801 }
9802
9803 if (Line[Last_Line].type == LINE_TYPE_OUTPUT && strlen((const char *)Edit_Line) == 0) Console_Output((const char *)"Done");
9804
9805 //Edit_Line copy the contents to the last line.
9806
9807 if ((Line[Last_Line].str = (char *)console_malloc(strlen((const char *)Edit_Line) + 1)) == NULL) return CONSOLE_MEM_ERR;
9808 strcpy((char *)Line[Last_Line].str, (const char *)Edit_Line);
9809
9810 if ((Line[Last_Line].disp_len = Console_GetDispLen(Line[Last_Line].str)) == CONSOLE_ARG_ERR) return CONSOLE_ARG_ERR;
9811 Line[Last_Line].type = pre_line_type;
9812 Line[Last_Line].readonly = pre_line_readonly;
9813 Line[Last_Line].start_col = 0;
9814
9815 Edit_Line[0] = '\0';
9816
9817 Last_Line++;
9818
9819 Cursor.x = 0;
9820
9821 if ((Last_Line - Start_Line) == LINE_DISP_MAX)
9822 {
9823 Start_Line++;
9824 }
9825 else
9826 {
9827 Cursor.y++;
9828 }
9829
9830 Line[Last_Line].str = Edit_Line;
9831 Line[Last_Line].readonly = 0;
9832 Line[Last_Line].type = LINE_TYPE_INPUT;
9833 Line[Last_Line].start_col = 0;
9834 Line[Last_Line].disp_len = 0;
9835
9836 return CONSOLE_NEW_LINE_SET;
9837 }
9838 else
9839 {
9840 return CONSOLE_NO_EVENT;
9841 }
9842 }
9843
Console_Insert_Line()9844 void Console_Insert_Line(){
9845 if (Last_Line>=_LINE_MAX-1)
9846 return;
9847 for (int i=Last_Line;i>=Current_Line;--i){
9848 Line[i+1]=Line[i];
9849 }
9850 ++Last_Line;
9851 int i=Current_Line;
9852 console_line & l=Line[i];
9853 l.str=(char *)console_malloc(2);
9854 strcpy((char *)l.str,"0");
9855 l.type=Line[i+1].type==LINE_TYPE_INPUT?LINE_TYPE_OUTPUT:LINE_TYPE_INPUT;
9856 l.start_col=0;
9857 l.readonly=1;
9858 l.disp_len=Console_GetDispLen(l.str);
9859 }
9860
9861 /*
9862 The following function is used to delete a character before the cursor.
9863 */
9864
Console_Backspace(GIAC_CONTEXT)9865 int Console_Backspace(GIAC_CONTEXT){
9866 console_changed=1;
9867 if (Last_Line>0 && Current_Line<Last_Line){
9868 int i=Current_Line;
9869 if (Edit_Line==Line[i].str)
9870 Edit_Line=Line[i+1].str;
9871 if (Line[i].str){
9872 copy_clipboard((const char *)Line[i].str,true);
9873 console_free(Line[i].str);
9874 }
9875 for (;i<Last_Line;++i){
9876 Line[i]=Line[i+1];
9877 }
9878 Line[i].readonly = 0;
9879 Line[i].type = LINE_TYPE_INPUT;
9880 Line[i].start_col = 0;
9881 Line[i].disp_len = 0;
9882 Line[i].str=0;
9883 --Last_Line;
9884 if (Start_Line>0)
9885 --Start_Line;
9886 else {
9887 if (Cursor.y>0)
9888 --Cursor.y;
9889 }
9890 #if 1
9891 if (Last_Line==0 && Current_Line==0){ // workaround
9892 char buf[strlen((const char*)Edit_Line)+1];
9893 strcpy(buf,(const char*)Edit_Line);
9894 Console_Init(contextptr);
9895 Console_Clear_EditLine();
9896 if (buf[0])
9897 Console_Input((const char *)buf);
9898 //std::string status(giac::print_INT_(Last_Line)+" "+(giac::print_INT_(Current_Line)+" ")+giac::print_INT_(Line[Current_Line].str)+" "+(const char*)Line[Current_Line].str);
9899 //DefineStatusMessage(status.c_str(),1,0,0);
9900 //DisplayStatusArea();
9901 }
9902 #endif
9903 Console_Disp(1,0);
9904 return CONSOLE_SUCCEEDED;
9905 }
9906 int return_val;
9907 return_val = Console_DelStr(Edit_Line, Current_Col, 1);
9908 if (return_val != CONSOLE_SUCCEEDED) return return_val;
9909 Line[Current_Line].disp_len = Console_GetDispLen(Edit_Line);
9910 return Console_MoveCursor(CURSOR_LEFT);
9911 }
9912
9913 /*
9914 The following functions are used to deal with the key.
9915 */
9916
chk_clearscreen(GIAC_CONTEXT)9917 void chk_clearscreen(GIAC_CONTEXT){
9918 drawRectangle(0, 24, LCD_WIDTH_PX, LCD_HEIGHT_PX-24, COLOR_WHITE);
9919 if (confirm((lang==1)?"Effacer l'historique?":"Clear history?",
9920 #ifdef NSPIRE_NEWLIB
9921 (lang==1)?"enter: oui, esc: conserver":"enter: yes, esc: keep",
9922 #else
9923 (lang==1)?"OK: oui, Back: conserver":"OK: yes, Back: keep",
9924 #endif
9925 false)==KEY_CTRL_F1){
9926 Console_Init(contextptr);
9927 Console_Clear_EditLine();
9928 }
9929 Console_Disp(1,0);
9930 }
9931
9932
9933 /*
9934 int handle_f5(){
9935 int keyflag = GetSetupSetting( (unsigned int)0x14);
9936 if (keyflag == 0x04 || keyflag == 0x08 || keyflag == 0x84 || keyflag == 0x88) {
9937 // ^only applies if some sort of alpha (not locked) is already on
9938 if (keyflag == 0x08 || keyflag == 0x88) { //if lowercase
9939 SetSetupSetting( (unsigned int)0x14, keyflag-0x04);
9940 DisplayStatusArea();
9941 return 1; //do not process the key, because otherwise we will leave alpha status
9942 } else {
9943 SetSetupSetting( (unsigned int)0x14, keyflag+0x04);
9944 DisplayStatusArea();
9945 return 1; //do not process the key, because otherwise we will leave alpha status
9946 }
9947 }
9948 if (keyflag==0) {
9949 SetSetupSetting( (unsigned int)0x14, 0x88);
9950 DisplayStatusArea();
9951 }
9952 return 0;
9953 }
9954 */
9955
Console_Eval(const char * buf,GIAC_CONTEXT)9956 int Console_Eval(const char * buf,GIAC_CONTEXT){
9957 int start=Current_Line;
9958 console_free(Line[start].str);
9959 Line[start].str=(char *)console_malloc(strlen(buf)+1);
9960 strcpy((char *)Line[start].str,buf);
9961 run_session(start,contextptr);
9962 int move_line = Last_Line - start;
9963 for (int i = 0; i < move_line; i++)
9964 Console_MoveCursor(CURSOR_UP);
9965 return CONSOLE_SUCCEEDED;
9966 }
9967
9968
save(const char * fname,GIAC_CONTEXT)9969 void save(const char * fname,GIAC_CONTEXT){
9970 clear_abort();
9971 #if 0
9972 return;
9973 #else
9974 string filename(remove_path(remove_extension(fname)));
9975 filename+=".xw";
9976 #ifdef NSPIRE_NEWLIB
9977 filename+=".tns";
9978 #endif
9979 save_console_state_smem(filename.c_str(),contextptr); // call before save_khicas_symbols_smem(), because this calls create_data_folder if necessary!
9980 // save_khicas_symbols_smem(("\\\\fls0\\"+filename+".xw").c_str());
9981 if (edptr)
9982 check_leave(edptr);
9983 #endif
9984 }
9985
restore_session(const char * fname,GIAC_CONTEXT)9986 int restore_session(const char * fname,GIAC_CONTEXT){
9987 #if 0
9988 return 0;
9989 #else
9990 // cout << "0" << fname << endl; Console_Disp(1); GetKey(&key);
9991 string filename(remove_path(remove_extension(fname)));
9992 filename+=string(".xw");
9993 #ifdef NSPIRE_NEWLIB
9994 filename+=string(".tns");
9995 #endif
9996 if (!load_console_state_smem(filename.c_str(),contextptr)){
9997 int x=0,y=0;
9998 PrintMini(x,y,"KhiCAS 1.6 (c) 2020 B. Parisse",TEXT_MODE_NORMAL, COLOR_BLACK, COLOR_WHITE);
9999 y +=18;
10000 PrintMini(x,y,"et al, License GPL 2",TEXT_MODE_NORMAL,COLOR_BLACK, COLOR_WHITE);
10001 y += 18;
10002 #ifdef NSPIRE_NEWLIB
10003 PrintMini(x,y,((lang==1)?"Taper menu plusieurs fois":"Type menu several times"),TEXT_MODE_NORMAL,COLOR_BLACK, COLOR_WHITE);
10004 #else
10005 PrintMini(x,y,((lang==1)?"Taper HOME plusieurs fois":"Type HOME several times"),TEXT_MODE_NORMAL,COLOR_BLACK, COLOR_WHITE);
10006 #endif
10007 y += 18;
10008 PrintMini(x,y,((lang==1)?"pour quitter KhiCAS.":"to leave KhiCAS."),TEXT_MODE_NORMAL,COLOR_BLACK, COLOR_WHITE);
10009 y += 18;
10010 PrintMini(x,y,(lang==1)?"Si le calcul formel est interdit":"If CAS is forbidden!",TEXT_MODE_NORMAL, COLOR_RED, COLOR_WHITE);
10011 y += 18;
10012 #ifdef NSPIRE_NEWLIB
10013 PrintMini(x,y,(lang==1)?"quittez Khicas (menu menu menu)":"Leave Khicas (menu menu menu)",TEXT_MODE_NORMAL, COLOR_RED, COLOR_WHITE);
10014 if (confirm("Interpreter? enter: Xcas, esc: MicroPython",(lang==1?"Peut se modifier depuis menu configuration":"May be changed later from menu configuration"),false,130)==KEY_CTRL_F6){
10015 python_compat(4,contextptr);
10016 xcas_python_eval=1;
10017 *logptr(contextptr) << "Micropython interpreter\n";
10018 Console_FMenu_Init(contextptr);
10019 }
10020 else {
10021 python_compat(1,contextptr);
10022 *logptr(contextptr) << "Xcas interpreter, Python compatible mode\n";
10023 }
10024 #else
10025 PrintMini(x,y,(lang==1)?"quittez Khicas (HOME HOME HOME)":"Leave Khicas (HOME HOME HOME)",TEXT_MODE_NORMAL, COLOR_RED, COLOR_WHITE);
10026 if (confirm("Interpreter? OK: Xcas, Back: MicroPython",(lang==1?"Peut se modifier depuis menu configuration":"May be changed later from menu configuration"),false,130)==KEY_CTRL_F6){
10027 python_compat(4,contextptr);
10028 xcas_python_eval=1;
10029 *logptr(contextptr) << "Micropython interpreter\n";
10030 Console_FMenu_Init(contextptr);
10031 }
10032 else {
10033 python_compat(1,contextptr);
10034 *logptr(contextptr) << "Xcas interpreter, Python compatible mode\n";
10035 }
10036 #endif
10037 Bdisp_AllClr_VRAM();
10038 #ifdef GIAC_SHOWTIME
10039 Console_Output("Reglage de l'heure, exemple");
10040 Console_NewLine(LINE_TYPE_OUTPUT, 1);
10041 Console_Output("12,37=>,");
10042 Console_NewLine(LINE_TYPE_OUTPUT, 1);
10043 #endif
10044 //menu_about();
10045 return 0;
10046 }
10047 return 1;
10048 #endif
10049 }
10050
extract_name(const char * s)10051 string extract_name(const char * s){
10052 int l=strlen(s),i,j;
10053 for (i=l-1;i>=0;--i){
10054 if (s[i]=='.')
10055 break;
10056 }
10057 if (i<=0)
10058 return "f";
10059 for (j=i-1;j>=0;--j){
10060 if (s[j]=='\\')
10061 break;
10062 }
10063 if (j<0)
10064 return "f";
10065 return string(s+j+1).substr(0,i-j-1);
10066 }
10067
giac_filebrowser(char * filename,const char * extension,const char * title)10068 int giac_filebrowser(char * filename,const char * extension,const char * title){
10069 const char * filenames[MAX_NUMBER_OF_FILENAMES+1];
10070 int n=os_file_browser(filenames,MAX_NUMBER_OF_FILENAMES,extension);
10071 if (n==0) return 0;
10072 int choix=select_item(filenames,title?title:"Scripts");
10073 if (choix<0 || choix>=n) return 0;
10074 strcpy(filename,filenames[choix]);
10075 return choix+1;
10076 }
10077
erase_script()10078 void erase_script(){
10079 char filename[MAX_FILENAME_SIZE+1];
10080 int res=giac_filebrowser(filename, "py", "Scripts");
10081 if (res && do_confirm((lang==1)?"Vraiment effacer":"Really erase?")){
10082 erase_file(filename);
10083 }
10084 }
10085
run_script(const char * filename,GIAC_CONTEXT)10086 int run_script(const char* filename,GIAC_CONTEXT) {
10087 #if 0
10088 return 1;
10089 #else
10090 string s;
10091 load_script(filename,s);
10092 // execution_in_progress = 1;
10093 run(s.c_str(),7,contextptr);
10094 // execution_in_progress = 0;
10095 if (s.size()>=4){
10096 if (s[0]=='#' || (s[0]=='d' && s[1]=='e' && s[2]=='f' && s[3]==' '))
10097 return 2;
10098 if ( (s[0]=='/' && s[1]=='/') ||
10099 (s.size()>8 && s[0]=='f' && (s[1]=='o' || s[1]=='u') && s[2]=='n' && s[3]=='c' && s[4]=='t' && s[5]=='i' && s[6]=='o' && s[7]=='n' && s[8]==' ')
10100 )
10101 return 3;
10102 }
10103 return 1;
10104 #endif
10105 }
10106
edit_script(char * fname,GIAC_CONTEXT)10107 int edit_script(char * fname,GIAC_CONTEXT){
10108 char fname_[MAX_FILENAME_SIZE+1];
10109 char * filename=0;
10110 int res=1;
10111 if (fname)
10112 filename=fname;
10113 else {
10114 res=giac_filebrowser(fname_, "py", "Scripts");
10115 filename=fname_;
10116 }
10117 if(res) {
10118 string s;
10119 load_script(filename,s);
10120 if (s.empty()){
10121 s=python_compat(contextptr)?((lang==1)?"Prog. Python, sinon taper":"Python prog., for Xcas"):((lang==1)?"Prog. Xcas, sinon taper":"Xcas prog., for Python");
10122 s += " AC F6 12";
10123 int k=confirm(s.c_str(),
10124 #ifdef NSPIRE_NEWLIB
10125 "enter: Prog, esc: Tortue"
10126 #else
10127 "OK: Prog, Back: Tortue"
10128 #endif
10129 );
10130 if (k==-1)
10131 return 0;
10132 if (k==KEY_CTRL_F6)
10133 s=python_compat(contextptr)?"from turtle import *\nreset()\n":"\nefface;\n ";
10134 else
10135 s=python_compat(contextptr)?"def "+extract_name(filename)+"(x):\n \n return x":"function "+extract_name(filename)+"(x)\nlocal j;\n \n return x;\nffunction";
10136 }
10137 // split s at newlines
10138 if (edptr==0)
10139 edptr=new textArea;
10140 if (!edptr) return -1;
10141 edptr->elements.clear();
10142 edptr->clipline=-1;
10143 edptr->filename=filename;
10144 edptr->editable=true;
10145 edptr->changed=false;
10146 edptr->python=python_compat(contextptr);
10147 edptr->elements.clear();
10148 add(edptr,s);
10149 s.clear();
10150 edptr->line=0;
10151 //edptr->line=edptr->elements.size()-1;
10152 edptr->pos=0;
10153 int res=doTextArea(edptr,contextptr);
10154 if (res==KEY_SHUTDOWN)
10155 return res;
10156 if (res==-1)
10157 python_compat(edptr->python,contextptr);
10158 dConsolePutChar('\x1e');
10159 }
10160 return 0;
10161 }
10162
chk_restart(GIAC_CONTEXT)10163 void chk_restart(GIAC_CONTEXT){
10164 drawRectangle(0, 24, LCD_WIDTH_PX, LCD_HEIGHT_PX-24, COLOR_WHITE);
10165 if (confirm((lang==1)?"Conserver les variables?":"Keep variables?",
10166 #ifdef NSPIRE_NEWLIB
10167 (lang==1)?"enter: conserver, esc: effacer":"enter: keep, esc: erase"
10168 #else
10169 (lang==1)?"OK: conserver, Back: effacer":"OK: keep, Back: erase"
10170 #endif
10171 )==KEY_CTRL_F6)
10172 do_restart(contextptr);
10173 }
10174
load(GIAC_CONTEXT)10175 void load(GIAC_CONTEXT){
10176 char filename[MAX_FILENAME_SIZE+1];
10177 if (giac_filebrowser(filename, "xw", "Sessions")){
10178 if (console_changed==0 ||
10179 strcmp(session_filename,"session")==0 ||
10180 confirm((lang==1)?"Session courante perdue?":"Current session will be lost",
10181 #ifdef NSPIRE_NEWLIB
10182 (lang==1)?"enter: annul, esc: ok":"enter: cancel, esc: ok"
10183 #else
10184 (lang==1)?"OK: annul, Back: ok":"OK: cancel, Back: ok"
10185 #endif
10186 )==KEY_CTRL_F6){
10187 giac::_restart(giac::gen(giac::vecteur(0),giac::_SEQ__VECT),contextptr);
10188 restore_session(filename,contextptr);
10189 clip_pasted=true;
10190 strcpy(session_filename,remove_path(giac::remove_extension(filename)).c_str());
10191 #ifdef NSPIRE_NEWLIB
10192 static bool ctrl_r=true;
10193 if (ctrl_r){
10194 confirm((lang==1)?"Taper ctrl puis r pour executer session ":"Type ctrl then r to run session","Enter: OK");
10195 ctrl_r=false;
10196 }
10197 #endif
10198 Console_Disp(0,contextptr);
10199 // reload_edptr(session_filename,edptr);
10200 }
10201 }
10202 }
10203
Console_GetKey(GIAC_CONTEXT)10204 int Console_GetKey(GIAC_CONTEXT){
10205 int key;
10206 unsigned int i, move_line, move_col;
10207 char tmp_str[2];
10208 char *tmp;
10209 for (;;){
10210 int keyflag = GetSetupSetting(0x14);
10211 GetKey(&key);
10212 if (key==KEY_SHUTDOWN)
10213 return key;
10214 bool alph=alphawasactive(&key);
10215 if (key==KEY_PRGM_ACON)
10216 Console_Disp(1,contextptr);
10217 translate_fkey(key);
10218 if (key==KEY_CTRL_PASTE)
10219 return Console_Input((const char*) paste_clipboard());
10220 if ( (key==KEY_CHAR_PLUS || key==KEY_CHAR_MINUS || key==KEY_CHAR_MULT || key==KEY_CHAR_DIV) && Current_Line<Last_Line-1){
10221 console_line * nxt=&Line[Current_Line];
10222 if (strncmp((const char *)nxt->str,"parameter([",11)==0)
10223 Console_MoveCursor(CURSOR_UP);
10224 nxt=&Line[Current_Line+1];
10225 if (strncmp((const char *)nxt->str,"parameter([",11)==0){
10226 giac::gen g((const char *)nxt->str,contextptr);
10227 if (g.is_symb_of_sommet(giac::at_parameter)){
10228 g=g._SYMBptr->feuille;
10229 if (g.type==giac::_VECT && g._VECTptr->size()>=5){
10230 giac::vecteur & v=*g._VECTptr;
10231 for (int i=1;i<v.size();++i)
10232 v[i]=evalf_double(v[i],1,contextptr);
10233 if (v[0].type==giac::_IDNT && v[1].type==giac::_DOUBLE_ && v[2].type==giac::_DOUBLE_ && v[3].type==giac::_DOUBLE_ && v[4].type==giac::_DOUBLE_){
10234 std::string s("assume(");
10235 s += v[0]._IDNTptr->id_name;
10236 s += "=[";
10237 int val=1;
10238 if (key==KEY_CHAR_MINUS) val=-1;
10239 if (key==KEY_CHAR_MULT) val=5;
10240 if (key==KEY_CHAR_DIV) val=-5;
10241 s += giac::print_DOUBLE_(v[3]._DOUBLE_val + val*v[4]._DOUBLE_val,contextptr);
10242 s += ',';
10243 s += giac::print_DOUBLE_(v[1]._DOUBLE_val,contextptr);
10244 s += ',';
10245 s += giac::print_DOUBLE_(v[2]._DOUBLE_val,contextptr);
10246 s += ',';
10247 s += giac::print_DOUBLE_(v[4]._DOUBLE_val,contextptr);
10248 s += "])";
10249 return Console_Eval(s.c_str(),contextptr);
10250 }
10251 }
10252 }
10253 }
10254 }
10255 if ( (key >= ' ' && key <= '~' )
10256 // (key>='0' && key<='9')|| (key >= 'A' && key <= 'Z') || (key >= 'a' && key <= 'z')
10257 ){
10258 tmp_str[0] = key;
10259 tmp_str[1] = '\0';
10260 Console_Input(tmp_str);
10261 Console_Disp(1,contextptr);
10262 continue;
10263 }
10264 if (key == KEY_CTRL_F5 || key==KEY_EQW_TEMPLATE || key==KEY_CTRL_F4 || ( (key==KEY_CTRL_RIGHT || key==KEY_CTRL_LEFT) && Current_Line<Last_Line) ){
10265 int l=Current_Line;
10266 bool graph=strcmp((const char *)Line[l].str,"Graphic object")==0;
10267 if (graph && l>0) --l;
10268 char buf[giacmax(512,strlen((const char *)Line[l].str+1))];
10269 strcpy(buf,(const char *)Line[l].str);
10270 int ret=(alph || key==KEY_CTRL_RIGHT || key==KEY_CTRL_F4) ?textedit(buf,512,false,contextptr):eqws(buf,graph,contextptr);
10271 if (ret==KEY_SHUTDOWN)
10272 return ret;
10273 if (ret){
10274 if (Current_Line==Last_Line){
10275 Console_Clear_EditLine();
10276 return Console_Input((const char *)buf);
10277 }
10278 else {
10279 #if 1
10280 if (Line[l].type==LINE_TYPE_INPUT && l<Last_Line-1 && Line[l+1].type==LINE_TYPE_OUTPUT)
10281 return Console_Eval(buf,contextptr);
10282 else {
10283 console_free(Line[l].str);
10284 Line[l].str=(char*)console_malloc(strlen(buf)+1);
10285 Line[l].disp_len = Console_GetDispLen(Line[l].str);
10286 strcpy((char *)Line[l].str,buf);
10287 }
10288 #else
10289 int x=editline_cursor;
10290 move_line = Last_Line - Current_Line;
10291 for (i = 0; i <=move_line; i++) Console_MoveCursor(CURSOR_DOWN);
10292 Cursor.x=x;
10293 return Console_Input((const char *)buf);
10294 #endif
10295 }
10296 }
10297 Console_Disp(1,contextptr);
10298 continue;
10299 }
10300 if (0 &&key==KEY_CTRL_F6){
10301 char buf[512];
10302 if (!showCatalog(buf,0,0))
10303 buf[0]=0;
10304 return Console_Input((const char*)buf);
10305 }
10306 if (key==KEY_CTRL_S || key==KEY_CTRL_T){
10307 giac::gen g=sheet(contextptr);
10308 if (g.type==_INT_ && g.val==KEY_SHUTDOWN)
10309 return KEY_SHUTDOWN;
10310 if (g.type==_VECT)
10311 return Console_Input(g.print(contextptr).c_str());
10312 Console_Disp(1,contextptr);
10313 continue;
10314 }
10315 if (key==KEY_SAVE){
10316 save(session_filename,contextptr);
10317 console_changed=false;
10318 console_disp_status(contextptr);
10319 continue;
10320 }
10321 if (key==KEY_LOAD){
10322 load(contextptr);
10323 Console_Disp(1,contextptr);
10324 continue;
10325 }
10326 if (key==KEY_CTRL_MENU){
10327 #if 1
10328 Menu smallmenu;
10329 smallmenu.numitems=17;
10330 MenuItem smallmenuitems[smallmenu.numitems];
10331
10332 smallmenu.items=smallmenuitems;
10333 smallmenu.height=12;
10334 smallmenu.scrollbar=1;
10335 smallmenu.scrollout=1;
10336 //smallmenu.title = "KhiCAS";
10337 // smallmenuitems[2].text = (char*)(isRecording ? "Stop Recording" : "Record Script");
10338 while(1) {
10339 // moved inside the loop because lang might change
10340 smallmenuitems[0].text = (char*)"Applications (shift ANS)";
10341 smallmenuitems[1].text = (char *) ((lang==1)?"Enregistrer session":"Save session ");
10342 smallmenuitems[2].text = (char *) ((lang==1)?"Enregistrer sous":"Save session as");
10343 if (exam_mode)
10344 smallmenuitems[2].text = (char *) "";
10345 smallmenuitems[3].text = (char*) ((lang==1)?"Charger session":"Load session");
10346 smallmenuitems[4].text = (char*)((lang==1)?"Nouvelle session":"New session");
10347 smallmenuitems[5].text = (char*)((lang==1)?"Executer session":"Run session");
10348 smallmenuitems[6].text = (char*)((lang==1)?"Editeur script":"Script editor");
10349 smallmenuitems[7].text = (char*)((lang==1)?"Ouvrir script":"Open script");
10350 smallmenuitems[8].text = (char*)((lang==1)?"Executer script":"Run script");
10351 smallmenuitems[9].text = (char*)((lang==1)?"Effacer historique (0)":"Clear history");
10352 smallmenuitems[10].text = (char*)((lang==1)?"Effacer script (e^)":"Clear script");
10353 smallmenuitems[11].text = (char*)"Configuration/examen (ln)";
10354 smallmenuitems[12].text = (char *) ((lang==1)?"Aide interface (log)":"Shortcuts");
10355 smallmenuitems[13].text = (char*)((lang==1)?"Editer matrice (i)":"Matrix editor");
10356 smallmenuitems[14].text = (char*) ((lang==1)?"Creer parametre (,)":"Create slider (,)");
10357 smallmenuitems[15].text = (char*) ((lang==1)?"A propos (x^y)":"About");
10358 #ifdef NSPIRE_NEWLIB
10359 smallmenuitems[16].text = (char*) ((lang==1)?"Quitter (menu)":"Quit");
10360 #else
10361 smallmenuitems[16].text = (char*) ((lang==1)?"Quitter (HOME)":"Quit");
10362 #endif
10363 if (exam_mode)
10364 smallmenuitems[16].text = (char*)((lang==1)?"Quitter le mode examen":"Quit exam mode");
10365 int sres = doMenu(&smallmenu);
10366 if(sres == MENU_RETURN_SELECTION || sres==KEY_CTRL_EXE) {
10367 if (smallmenu.selection==smallmenu.numitems){
10368 if (!exam_mode)
10369 return KEY_CTRL_MENU;
10370 leave_exam_mode(contextptr);
10371 break;
10372 }
10373 const char * ptr=0;
10374 if (smallmenu.selection==1){
10375 key=KEY_SHIFT_ANS;
10376 break;
10377 }
10378 if (smallmenu.selection==2){
10379 if (strcmp(session_filename,"session")==0)
10380 smallmenu.selection=3;
10381 else {
10382 save(session_filename,contextptr);
10383 break;
10384 }
10385 }
10386 if (smallmenu.selection==3 && !exam_mode){
10387 char buf[270];
10388 if (get_filename(buf,".xw")){
10389 save(buf,contextptr);
10390 string fname(remove_path(giac::remove_extension(buf)));
10391 strcpy(session_filename,fname.c_str());
10392 if (edptr)
10393 edptr->filename=fname+".py";
10394 }
10395 break;
10396 }
10397 if (smallmenu.selection==4){
10398 load(contextptr);
10399 break;
10400 }
10401 if (0 && smallmenu.selection==5) {
10402 // FIXME: make a menu catalog?
10403 char buf[512];
10404 if (doCatalogMenu(buf,(char*)"CATALOG",0,contextptr))
10405 return Console_Input((const char *)buf);
10406 break;
10407 }
10408 if (smallmenu.selection==5) {
10409 if (exam_mode){
10410 if (do_confirm((lang==1)?"Tout effacer?":"Really clear?")){
10411 Console_Init(contextptr);
10412 Console_Clear_EditLine();
10413 giac::_restart(giac::gen(giac::vecteur(0),giac::_SEQ__VECT),contextptr);
10414 }
10415 }
10416 else {
10417 char filename[MAX_FILENAME_SIZE+1];
10418 drawRectangle(0, 0, LCD_WIDTH_PX, LCD_HEIGHT_PX, COLOR_WHITE);
10419 if (get_filename(filename,".xw")){
10420 if (console_changed==0 ||
10421 strcmp(session_filename,"session")==0 ||
10422 confirm((lang==1)?"Session courante perdue?":"Current session will be lost",
10423 #ifdef NSPIRE_NEWLIB
10424 (lang==1)?"enter: annul, esc: ok":"enter: cancel, esc: ok"
10425 #else
10426 (lang==1)?"OK: annul, Back: ok":"OK: cancel, Back: ok"
10427 #endif
10428 )==KEY_CTRL_F6){
10429 clip_pasted=true;
10430 Console_Init(contextptr);
10431 Console_Clear_EditLine();
10432 giac::_restart(giac::gen(giac::vecteur(0),giac::_SEQ__VECT),contextptr);
10433 std::string s(remove_path(giac::remove_extension(filename)));
10434 strcpy(session_filename,s.c_str());
10435 reload_edptr(session_filename,edptr,contextptr);
10436 }
10437 }
10438 }
10439 break;
10440 }
10441 if (smallmenu.selection==6) {
10442 run_session(0,contextptr);
10443 break;
10444 }
10445 if (smallmenu.selection==7) {
10446 if (!edptr || merge_area(edptr->elements).size()<2)
10447 edit_script((char *)(giac::remove_extension(session_filename)+".py").c_str(),contextptr);
10448 else
10449 doTextArea(edptr,contextptr);
10450 break;
10451 }
10452 if (smallmenu.selection==8) {
10453 char filename[MAX_FILENAME_SIZE+1];
10454 drawRectangle(0, 0, LCD_WIDTH_PX, LCD_HEIGHT_PX-8, COLOR_WHITE);
10455 if (giac_filebrowser(filename, "py", "Scripts"))
10456 edit_script(filename,contextptr);
10457 break;
10458 }
10459 if (smallmenu.selection==9) {
10460 char filename[MAX_FILENAME_SIZE+1];
10461 drawRectangle(0, 0, LCD_WIDTH_PX, LCD_HEIGHT_PX-8, COLOR_WHITE);
10462 if (giac_filebrowser(filename, "py", "Scripts"))
10463 run_script(filename,contextptr);
10464 Console_Clear_EditLine();
10465 break;
10466 }
10467 if(smallmenu.selection == 10) {
10468 chk_restart(contextptr);
10469 Console_Init(contextptr);
10470 Console_Clear_EditLine();
10471 break;
10472 }
10473 if (smallmenu.selection==11){
10474 erase_script();
10475 break;
10476 }
10477 if (smallmenu.selection == 12){
10478 menu_setup(contextptr);
10479 continue;
10480 }
10481 if(smallmenu.selection == 13 ||smallmenu.selection == 16 ) {
10482 textArea text;
10483 text.editable=false;
10484 text.clipline=-1;
10485 text.title = smallmenuitems[smallmenu.selection-1].text;
10486 add(&text,smallmenu.selection==13?((lang==1)?shortcuts_fr_string:shortcuts_en_string):((lang==1)?apropos_fr_string:apropos_en_string));
10487 doTextArea(&text,contextptr);
10488 continue;
10489 }
10490 if (smallmenu.selection==14){
10491 drawRectangle(0, 0, LCD_WIDTH_PX, LCD_HEIGHT_PX-8, COLOR_WHITE);
10492 if (ptr=input_matrix(false,contextptr)) {
10493 return Console_Input((const char *)ptr);
10494 }
10495 break;
10496 }
10497 if (smallmenu.selection == 15){
10498 Menu paramenu;
10499 paramenu.numitems=6;
10500 MenuItem paramenuitems[paramenu.numitems];
10501 paramenu.items=paramenuitems;
10502 paramenu.height=12;
10503 paramenu.title = (char *)"Parameter";
10504 char menu_xcur[32],menu_xmin[32],menu_xmax[32],menu_xstep[32],menu_name[16]="name a";
10505 static char curname='a';
10506 menu_name[5]=curname;
10507 ++curname;
10508 double pcur=0,pmin=-5,pmax=5,pstep=0.1;
10509 std::string s;
10510 bool doit;
10511 for (;;){
10512 s="cur "+giac::print_DOUBLE_(pcur,contextptr);
10513 strcpy(menu_xcur,s.c_str());
10514 s="min "+giac::print_DOUBLE_(pmin,contextptr);
10515 strcpy(menu_xmin,s.c_str());
10516 s="max "+giac::print_DOUBLE_(pmax,contextptr);
10517 strcpy(menu_xmax,s.c_str());
10518 s="step "+giac::print_DOUBLE_(pstep,contextptr);
10519 strcpy(menu_xstep,s.c_str());
10520 paramenuitems[0].text = (char *) "OK";
10521 paramenuitems[1].text = (char *) menu_name;
10522 paramenuitems[2].text = (char *) menu_xcur;
10523 paramenuitems[3].text = (char *) menu_xmin;
10524 paramenuitems[4].text = (char *) menu_xmax;
10525 paramenuitems[5].text = (char *) menu_xstep;
10526 int sres = doMenu(¶menu);
10527 doit = sres==MENU_RETURN_SELECTION || sres==KEY_CTRL_EXE;
10528 if (doit) {
10529 std::string s1; double d;
10530 if (paramenu.selection==2){
10531 handle_f5();
10532 if (inputline(menu_name,(lang==1)?"Nouvelle valeur?":"New value?",s1,false)==KEY_CTRL_EXE && s1.size()>0 && isalpha(s1[0])){
10533 if (s1.size()>10)
10534 s1=s1.substr(0,10);
10535 strcpy(menu_name,("name "+s1).c_str());
10536 }
10537 continue;
10538 }
10539 if (paramenu.selection==3){
10540 inputdouble(menu_xcur,pcur,contextptr);
10541 continue;
10542 }
10543 if (paramenu.selection==4){
10544 inputdouble(menu_xmin,pmin,contextptr);
10545 continue;
10546 }
10547 if (paramenu.selection==5){
10548 inputdouble(menu_xmax,pmax,contextptr);
10549 continue;
10550 }
10551 if (paramenu.selection==6){
10552 inputdouble(menu_xstep,pstep,contextptr);
10553 pstep=fabs(pstep);
10554 continue;
10555 }
10556 // if (paramenu.selection==6) break;
10557 } // end menu
10558 break;
10559 } // end for (;;)
10560 if (doit && pmin<pmax && pstep>0){
10561 s="assume(";
10562 s += (menu_name+5);
10563 s += "=[";
10564 s += (menu_xcur+4);
10565 s += ',';
10566 s += (menu_xmin+4);
10567 s += ',';
10568 s += (menu_xmax+4);
10569 s += ',';
10570 s += (menu_xstep+5);
10571 s += "])";
10572 return Console_Input((const char *)s.c_str());
10573 }
10574 continue;
10575 }
10576 }
10577 break;
10578 } // end while(1)
10579 if (key!=KEY_SHIFT_ANS){
10580 Console_Disp(1,contextptr);
10581 return CONSOLE_SUCCEEDED;
10582 }
10583 #else
10584 char filename[MAX_FILENAME_SIZE+1];
10585 //drawRectangle(0, 24, LCD_WIDTH_PX, LCD_HEIGHT_PX-24, COLOR_WHITE);
10586 if (get_filename(filename))
10587 edit_script(filename,contextptr);
10588 //edit_script(0);
10589 return CONSOLE_SUCCEEDED;
10590 #endif
10591 }
10592 if (key==KEY_SHIFT_ANS){ // 3rd party app
10593 int res=khicas_addins_menu(contextptr);
10594 if (res==KEY_CTRL_MENU)
10595 return res;
10596 Console_Disp(1,contextptr);
10597 return CONSOLE_SUCCEEDED;
10598 }
10599 if ( (key >= KEY_CTRL_F1 && key <= KEY_CTRL_F6) ||
10600 (key >= KEY_CTRL_F7 && key <= KEY_CTRL_F14)
10601 ){
10602 return Console_FMenu(key,contextptr);
10603 }
10604 if (key == KEY_CTRL_UP)
10605 return Console_MoveCursor(alph?CURSOR_ALPHA_UP:CURSOR_UP);
10606 if (key == KEY_CTRL_DOWN || key=='\t'
10607 // FIREBIRDEMU
10608 || key==KEY_BOOK
10609 ){
10610 if (Current_Line==Last_Line && !Line[Current_Line].readonly && Current_Col>0){
10611 char buf[strlen(Edit_Line)+1];
10612 strcpy(buf,Edit_Line);
10613 buf[Cursor.x]=0;
10614 string s=help_insert(buf,contextptr);
10615 Console_Input(s.c_str());
10616 Console_Disp(1,contextptr);
10617 Console_MoveCursor(CURSOR_SHIFT_RIGHT);
10618 continue;
10619 }
10620 return Console_MoveCursor(alph?CURSOR_ALPHA_DOWN:CURSOR_DOWN);
10621 }
10622 //if (key == KEY_CTRL_PAGEUP) return Console_MoveCursor(CURSOR_ALPHA_UP);
10623 //if (key == KEY_CTRL_PAGEDOWN) return Console_MoveCursor(CURSOR_ALPHA_DOWN);
10624 if (key == KEY_CTRL_LEFT)
10625 Console_MoveCursor(CURSOR_LEFT);
10626 if (key == KEY_CTRL_RIGHT)
10627 Console_MoveCursor(CURSOR_RIGHT);
10628 if (key == KEY_SHIFT_LEFT)
10629 Console_MoveCursor(CURSOR_SHIFT_LEFT);
10630 if (key == KEY_SHIFT_RIGHT)
10631 Console_MoveCursor(CURSOR_SHIFT_RIGHT);
10632 if (key == KEY_SHIFT_RIGHT || key == KEY_SHIFT_LEFT ||
10633 key == KEY_CTRL_RIGHT || key == KEY_CTRL_LEFT){
10634 Console_Disp(0,contextptr);
10635 continue;
10636 }
10637 if (key == KEY_CTRL_EXIT){
10638 if (Last_Line==Current_Line){
10639 if (!edptr)
10640 edit_script((char *)(giac::remove_extension(session_filename)+".py").c_str(),contextptr);
10641 else {
10642 edptr->y=0;
10643 doTextArea(edptr,contextptr);
10644 }
10645 Console_Disp(1,contextptr);
10646 }
10647 else {
10648 move_line = Last_Line - Current_Line;
10649 for (i = 0; i <= move_line; i++) Console_MoveCursor(CURSOR_DOWN);
10650 }
10651 return CONSOLE_SUCCEEDED;
10652 }
10653 if (key == KEY_CTRL_AC)
10654 {
10655 if (Line[Current_Line].readonly){
10656 move_line = Last_Line - Current_Line;
10657 for (i = 0; i <= move_line; i++) Console_MoveCursor(CURSOR_DOWN);
10658 return CONSOLE_SUCCEEDED;
10659 }
10660 if (Edit_Line[0]=='\0'){
10661 //return Console_Input((const char *)"restart");
10662 chk_clearscreen(contextptr);
10663 continue;
10664 }
10665 Edit_Line[0] = '\0';
10666 Line[Current_Line].start_col = 0;
10667 Line[Current_Line].type = LINE_TYPE_INPUT;
10668 Line[Current_Line].disp_len = 0;
10669 Cursor.x = 0;
10670 return CONSOLE_SUCCEEDED;
10671 }
10672
10673 if (key == KEY_CTRL_INS) {
10674 if (Current_Line<Last_Line){
10675 Console_Insert_Line();
10676 Console_Insert_Line();
10677 }
10678 else
10679 Console_Input((const char*)":=");
10680 Console_Disp(1,contextptr);
10681 continue;
10682 }
10683 if (key==KEY_AFFECT){
10684 Console_Input((const char*)":=");
10685 Console_Disp(1,contextptr);
10686 continue;
10687 }
10688 if (key==KEY_CTRL_D){
10689 Console_Input((const char*)"debug(");
10690 Console_Disp(1,contextptr);
10691 continue;
10692 }
10693 if (key == KEY_CTRL_SETUP) {
10694 menu_setup(contextptr);
10695 Console_Disp(1,contextptr);
10696 continue;
10697 }
10698
10699 if (key == KEY_CTRL_EXE || key==KEY_CTRL_OK){
10700 if (Current_Line == Last_Line)
10701 {
10702 return Console_NewLine(LINE_TYPE_INPUT, 1);
10703 }
10704 }
10705 if (key == KEY_CTRL_DEL)
10706 return Console_Backspace(contextptr);
10707 if (key == KEY_CTRL_R){
10708 run_session(0,contextptr);
10709 return 0;
10710 }
10711 if (key == KEY_CTRL_CLIP){
10712 copy_clipboard((const char *)Line[Current_Line].str,true);
10713 }
10714 if (key==KEY_CTRL_EXE || key==KEY_CTRL_OK){
10715 tmp = Line[Current_Line].str;
10716
10717 #if 1
10718 int x=editline_cursor;
10719 move_line = Last_Line - Current_Line;
10720 for (i = 0; i <= move_line; i++) Console_MoveCursor(CURSOR_DOWN);
10721 Cursor.x=x;
10722 if (Cursor.x>COL_DISP_MAX)
10723 Line[Last_Line].start_col=Cursor.x-COL_DISP_MAX;
10724 #else
10725 move_line = Last_Line - Current_Line;
10726 for (i = 0; i <= move_line; i++) Console_MoveCursor(CURSOR_DOWN);
10727 move_col = Line[Current_Line].disp_len - Current_Col;
10728 for (i = 0; i <= move_col; i++) Console_MoveCursor(CURSOR_RIGHT);
10729 #endif
10730 return Console_Input(tmp);
10731 }
10732 const char * ptr=keytostring(key,keyflag,0,contextptr);
10733 if (ptr)
10734 return Console_Input((const char *)ptr);
10735
10736 }
10737 return CONSOLE_NO_EVENT;
10738 }
10739
Console_FMenu(int key,GIAC_CONTEXT)10740 int Console_FMenu(int key,GIAC_CONTEXT){
10741 const char * s=console_menu(key,fmenu_cfg,0),*ptr=0;
10742 if (!s){
10743 //cout << "console " << unsigned(s) << endl;
10744 return CONSOLE_NO_EVENT;
10745 }
10746 if (strcmp("matrix(",s)==0 && (ptr=input_matrix(false,contextptr)) )
10747 s=ptr;
10748 if (strcmp("makelist(",s)==0 && (ptr=input_matrix(true,contextptr)) )
10749 s=ptr;
10750 return Console_Input((const char *)s);
10751 }
10752
console_menu(int key,int active_app)10753 const char * console_menu(int key,int active_app){
10754 return console_menu(key,fmenu_cfg,active_app);
10755 }
10756
console_menu(int key,char * cfg_,int active_app)10757 const char * console_menu(int key,char* cfg_,int active_app){
10758 char * cfg=cfg_;
10759 int i, matched = 0;
10760 const char * ret=0;
10761 const int maxentry_size=64;
10762 static char console_buf[maxentry_size];
10763 char temp[maxentry_size],menu1[maxentry_size],menu2[maxentry_size],menu3[maxentry_size],menu4[maxentry_size],menu5[maxentry_size],menu6[maxentry_size],menu7[maxentry_size],menu8[maxentry_size];
10764 char * tabmenu[8]={menu1,menu2,menu3,menu4,menu5,menu6,menu7,menu8};
10765 struct FMenu entry = {0,tabmenu,0};
10766 // char* cfg = (char *)memory_load((char *)"\\\\fls0\\FMENU.cfg");
10767
10768 while (*cfg) {
10769 //Get each line
10770 for(i=0; i<maxentry_size-1 && *cfg && *cfg!='\r' && *cfg!='\n'; i++, cfg++) {
10771 temp[i] = *cfg;
10772 }
10773 temp[i]=0;
10774 //If starting by 'F' followed by the right number, start filling the structure.
10775 if (temp[0] == 'F' && temp[1]==(key-KEY_CTRL_F1)+'1'){
10776 matched = 1;
10777 continue;
10778 }
10779 if (temp[0] == 'F' && temp[1]!=(key-KEY_CTRL_F1)+'0'){
10780 matched = 0;
10781 continue;
10782 }
10783 //Fill the structure
10784 if (matched && temp[0] && entry.count<8) {
10785 strcpy(tabmenu[entry.count], temp);
10786 entry.count++;
10787 }
10788 cfg++;
10789 }
10790 if(entry.count > 0) {
10791 ret = Console_Draw_FMenu(key, &entry,cfg,active_app);
10792 // cout << "console0 " << (unsigned) ret << endl;
10793 if (!ret) return ret;
10794 if (!strcmp("periodic_table",ret)){
10795 const char * name,*symbol;
10796 char protons[32],nucleons[32],mass[32],electroneg[32];
10797 int res=periodic_table(name,symbol,protons,nucleons,mass,electroneg);
10798 if (!res)
10799 return 0;
10800 char * ptr=console_buf;
10801 if (res & 1)
10802 ptr=strcpy(ptr,name)+strlen(ptr);
10803 if (res & 2){
10804 if (res & 1)
10805 ptr=strcpy(ptr,",")+strlen(ptr);
10806 ptr=strcpy(ptr,symbol)+strlen(ptr);
10807 }
10808 if (res & 4){
10809 if (res&3)
10810 ptr=strcpy(ptr,",")+strlen(ptr);
10811 ptr=strcpy(ptr,protons)+strlen(ptr);
10812 }
10813 if (res & 8){
10814 if (res&7)
10815 ptr=strcpy(ptr,",")+strlen(ptr);
10816 ptr=strcpy(ptr,nucleons)+strlen(ptr);
10817 }
10818 if (res & 16){
10819 if (res&15)
10820 ptr=strcpy(ptr,",")+strlen(ptr);
10821 ptr=strcpy(ptr,mass+2)+strlen(ptr);
10822 }
10823 if (res & 32){
10824 if (res&31)
10825 ptr=strcpy(ptr,",")+strlen(ptr);
10826 ptr=strcpy(ptr,electroneg+4)+strlen(ptr);
10827 }
10828 }
10829 else
10830 strcpy(console_buf,ret);
10831 return console_buf;
10832 }
10833 return 0;
10834 }
10835
Console_Make_Entry(const char * str)10836 char *Console_Make_Entry(const char* str)
10837 {
10838 char* entry = NULL;
10839 entry = (char*)calloc((strlen((const char *)str)+1), sizeof(char*));
10840 if(entry) memcpy(entry, (const char *)str, strlen((const char *)str)+1);
10841
10842 return entry;
10843 }
10844
PrintMini(int x,int y,const char * s,int mode)10845 void PrintMini(int x,int y,const char * s,int mode){
10846 x *=3;
10847 y *=3;
10848 PrintMini(x,y,(char *)s,mode,COLOR_BLACK, COLOR_WHITE);
10849 }
10850
10851 //Draws and runs the asked for menu.
Console_Draw_FMenu(int key,struct FMenu * menu,char * cfg,int active_app)10852 const char * Console_Draw_FMenu(int key, struct FMenu* menu,char * cfg,int active_app)
10853 {
10854 int i, nb_entries = 0, selector = 0, position_number, position_x, ret, longest = 0;
10855 int input_key;
10856 char quick[] = "*: ";
10857 int quick_len = 2;
10858 char **entries;
10859 DISPBOX box,box3;
10860
10861 position_number = key - KEY_CTRL_F1;
10862 if (position_number<0 || position_number>=5)
10863 position_number=4;
10864
10865 entries = menu->str;
10866 nb_entries = menu->count;
10867
10868 for(i=0; i<nb_entries; i++)
10869 if(strlen(entries[i]) > longest) longest = strlen(entries[i]);
10870 if (longest>15)
10871 longest=15;
10872 // screen resolution Graph90 384x(216-24), Graph35 128x64
10873 // factor 3x3
10874 position_x = 17*position_number;
10875 if(position_x + longest*4 + quick_len*4 > 115) position_x = 115 - longest*4 - quick_len*4;
10876
10877 box.left = position_x;
10878 box.right = position_x + longest*4 + quick_len*4 + 6;
10879 box.bottom = 63-7;
10880 box.top = 63-7-nb_entries*7;
10881 box3.left=3*box.left;
10882 box3.right=3*box.right;
10883 box3.bottom=3*box.bottom+22;
10884 box3.top=3*box.top+20;
10885
10886 drawRectangle(box3.left,box3.top,box3.right-box3.left,box3.bottom-box3.top,COLOR_WHITE);
10887 drawLine(box3.left, box3.top, box3.right, box3.top,COLOR_BLACK);
10888 drawLine(box3.left, box3.bottom, box3.left, box3.top,COLOR_BLACK);
10889 drawLine(box3.right, box3.bottom, box3.right, box3.top,COLOR_BLACK);
10890 drawLine(box3.left, box3.bottom, box3.right, box3.bottom,COLOR_BLACK);
10891
10892 // Cursor_SetFlashOff();
10893
10894 for (;;){
10895 for(i=0; i<nb_entries; i++) {
10896 quick[0] = '0'+(i+1);
10897 PrintMini(3+position_x, box.bottom-7*i, quick, 0);
10898 PrintMini(3+position_x+quick_len*4, box.bottom-7*i, entries[i], 0);
10899 }
10900 PrintMini(3+position_x+quick_len*4,box.bottom-7*selector, entries[selector], 4);
10901 GetKey(&input_key);
10902 if (input_key==KEY_PRGM_ACON) Console_Disp(1,0);
10903 if (input_key == KEY_CTRL_EXIT || input_key==KEY_CTRL_AC) return 0;
10904 if (input_key == KEY_CTRL_UP && selector < nb_entries-1) selector++;
10905 if (input_key == KEY_CTRL_DOWN && selector > 0) selector--;
10906
10907 if (input_key == KEY_CTRL_EXE || input_key==KEY_CTRL_OK) return entries[selector];
10908
10909 if (input_key >= KEY_CHAR_1 && input_key < KEY_CHAR_1 + nb_entries) return entries[input_key-KEY_CHAR_1];
10910
10911 translate_fkey(input_key);
10912
10913 if ( active_app==0 &&
10914 ((input_key >= KEY_CTRL_F1 && input_key <= KEY_CTRL_F6) ||
10915 (input_key >= KEY_CTRL_F7 && input_key <= KEY_CTRL_F12) )
10916 ){
10917 Console_Disp(1,0);
10918 key=input_key;
10919 return console_menu(key,cfg,active_app);
10920 }
10921 } // end while input_key!=EXE/EXIT
10922
10923 return 0; // never reached
10924 }
10925
Console_Free()10926 void Console_Free(){
10927 for (int i = 0; i < _LINE_MAX; i++){
10928 if (Line[i].str){
10929 if (Line[i].str==Edit_Line)
10930 Edit_Line=0;
10931 console_free(Line[i].str);
10932 Line[i].str=0;
10933 }
10934 }
10935 if (Edit_Line)
10936 console_free(Edit_Line);
10937 if (Line){
10938 delete [] Line;
10939 Line = 0;
10940 }
10941 }
10942
Console_Init(GIAC_CONTEXT)10943 int Console_Init(GIAC_CONTEXT){
10944 console_changed=1;
10945 int i;
10946 if (!Line){
10947 Line=new console_line[_LINE_MAX];
10948 for (i = 0; i < _LINE_MAX; i++){
10949 Line[i].str=0;
10950 }
10951 }
10952 Start_Line = 0;
10953 Last_Line = 0;
10954
10955 for (i = 0; i < _LINE_MAX; i++){
10956 if (Line[i].str){
10957 if (Line[i].str==Edit_Line)
10958 Edit_Line=0;
10959 console_free(Line[i].str);
10960 Line[i].str=0;
10961 }
10962 Line[i].readonly = 0;
10963 Line[i].type = LINE_TYPE_INPUT;
10964 Line[i].start_col = 0;
10965 Line[i].disp_len = 0;
10966 }
10967 if (Edit_Line)
10968 console_free(Edit_Line);
10969 if ((Edit_Line = (char *)console_malloc(EDIT_LINE_MAX + 1)) == NULL) return CONSOLE_MEM_ERR;
10970 Edit_Line[0]=0;
10971 Line[0].str = Edit_Line;
10972
10973 Cursor.x = 0;
10974 Cursor.y = 0;
10975
10976 Case = LOWER_CASE;
10977
10978 /*for(i = 0; i < 6; i++) {
10979 FMenu_entries[i].name = NULL;
10980 FMenu_entries[i].count = 0;
10981 }*/
10982
10983 Console_FMenu_Init(contextptr);
10984
10985 return CONSOLE_SUCCEEDED;
10986 }
10987
10988 const char conf_standard[] = "F1 algb\nsimplify(\nfactor(\npartfrac(\ntcollect(\ntexpand(\nsum(\noo\nproduct(\nF2 calc\n'\ndiff(\nintegrate(\nlimit(\nseries(\nsolve(\ndesolve(\nrsolve(\nF5 2d \nreserved\nF4 menu\nreserved\nF6 reg\nlinear_regression_plot(\nlogarithmic_regression_plot(\nexponential_regression_plot(\npower_regression_plot(\npolynomial_regression_plot(\nsin_regression_plot(\nscatterplot(\nmatrix(\nF= poly\nproot(\npcoeff(\nquo(\nrem(\ngcd(\negcd(\nresultant(\nGF(\nF9 arit\n mod \nirem(\nifactor(\ngcd(\nisprime(\nnextprime(\npowmod(\niegcd(\nF7 lin\nmatrix(\ndet(\nmatpow(\nranm(\nrref(\ntran(\negvl(\negv(\nF8 list\nmakelist(\nrange(\nseq(\nlen(\nappend(\nranv(\nsort(\napply(\nF3 plot\nplot(\nplotseq(\nplotlist(\nplotparam(\nplotpolar(\nplotfield(\nhistogram(\nbarplot(\nF; 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 % \nperiodic_table\n";
10989
10990 const char python_conf_standard[] = "F1 misc\n\"\n\'\n;\n:\n[]\ndef f(x):return\ncaseval(\"\nfrom cas import *\nF2 math\nfloor(\nceil(\nround(\nmin(\nmax(\nsign(\nsqrt(\nfrom math import *\nF3 rand\nrandint(\nrandom()\nchoice(\nfrom random import *\nF4 menu\nreserved\nF5 2d\nreserved\nF; color\n\nF6 tortue\nforward(\nbackward(\nleft(\nright(\npencolor(\ncircle(\nreset()\nfrom turtle import *\nF9 plot\nplot(\ntext(\narrow(\nlinear_regression_plot(\nscatter(\naxis(\nbar(\nfrom matplotl import *\nF7 linalg\nmatrix(\nadd(\nsub(\nmul(\ninv(\nrref(\ntranspose(\nfrom linalg import *\nF8 list\nlist(\nrange(\nlen(\nappend(\nhead(\nsort(\napply(\nF: color\nred\nblue\ngreen\ncyan\nyellow\nmagenta\nblack\nwhite\nF< prog\n:\n&\n#\nhexprint(\nbinprint(\nf(x):=\ndebug(\npython(\nF> cplx\nabs(\narg(\nre(\nim(\nconj(\npolar(\nrect(\nfrom cmath import *\nF= draw\nclear_screen();\nshow_screen();\nset_pixel(\ndraw_line(\ndraw_rectangle(\n\ndraw_circle(\ndraw_string(\nfrom graphic import *\n";
10991
10992 // Loads the FMenus' data into memory, from a cfg file
Console_FMenu_Init(GIAC_CONTEXT)10993 void Console_FMenu_Init(GIAC_CONTEXT)
10994 {
10995 char temp[32] = {'\0'};
10996 #if 0
10997 if (!fmenu_cfg){
10998 fmenu_cfg = (char *)conf_standard;
10999 std::string cfg_s;
11000 // Does the file exists ?
11001 if (load_script((char*)"FMENU.cfg",cfg_s)){
11002 char * ptr=new char[cfg_s.size()+1];
11003 strcpy(ptr,cfg_s.c_str());
11004 fmenu_cfg=(char *)ptr;
11005 }
11006 if(!fmenu_cfg) {
11007 save_script((const char *)"FMENU.cfg",conf_standard);
11008 fmenu_cfg = (char *)conf_standard;
11009 }
11010 }
11011 #else
11012 if (xcas_python_eval==1){
11013 fmenu_cfg=(char *)python_conf_standard;
11014 }
11015 else {
11016 fmenu_cfg=(char *)conf_standard;
11017 }
11018 #endif
11019 const char *cfg=fmenu_cfg;
11020 while(*cfg) {
11021 //Get each line
11022 int i;
11023 for(i=0; i<20 && *cfg && *cfg!='\r' && *cfg!='\n'; i++, cfg++) {
11024 temp[i] = *cfg;
11025 }
11026 temp[i]=0;
11027 //If starting by 'F', adjust the number and eventually set the name of the menu
11028 if(temp[0] == 'F' && temp[1]>='1' && temp[1]<='6') {
11029 int number = temp[1]-'0' - 1;
11030 if(temp[3] && number<6) {
11031 strcpy(FMenu_entries_name[number], (char*)temp+3);
11032 //FMenu_entries[number].name[4] = '\0';
11033 }
11034 }
11035
11036 memset(temp, '\0', 20);
11037 cfg++;
11038 }
11039 //free(fmenu_cfg);
11040 }
11041
11042 /*
11043 The following functions are used to display all lines.
11044 Note: After calling this function, the first clear the memory.
11045 */
11046
11047 #ifndef CURSOR
11048 int print_x=0,print_y=0,vfontsize=18,hfontsize=12;
11049 #endif
11050
locate(int x,int y)11051 void locate(int x,int y){
11052 #ifdef CURSOR
11053 return locate_OS(x,y);
11054 #else
11055 print_x=(x-1)*hfontsize;
11056 print_y=(y-1)*vfontsize;
11057 #endif
11058 }
11059
Cursor_SetPosition(int x,int y)11060 void Cursor_SetPosition(int x,int y){
11061 return locate(x+1,y+1);
11062 }
11063
PrintRev(const char * s,int color=TEXT_COLOR_BLACK)11064 void PrintRev(const char * s,int color=TEXT_COLOR_BLACK){
11065 #ifdef CURSOR
11066 Print_OS((char *)s,TEXT_MODE_INVERT,0);
11067 #else
11068 print(print_x,print_y,(const char *)s,color,true/* revert*/,false,false);
11069 #endif
11070 }
11071
Print(const char * s,int color=TEXT_COLOR_BLACK)11072 void Print(const char * s,int color=TEXT_COLOR_BLACK){
11073 #ifdef CURSOR
11074 Print_OS((char *)s,TEXT_MODE_NORMAL,0);
11075 #else
11076 print(print_x,print_y,(const char *)s,color,false,false,false);
11077 #endif
11078 }
11079
11080 // redraw_mode=1 clear area
Console_Disp(int redraw_mode,GIAC_CONTEXT)11081 int Console_Disp(int redraw_mode,GIAC_CONTEXT){
11082 unsigned int* pBitmap;
11083 int i, alpha_shift_status;
11084 DISPBOX ficon;
11085 int print_y = 0; //pixel y cursor
11086 int print_y_locate;
11087
11088 // if (redraw_mode & 1) Bdisp_AllClr_VRAM();
11089
11090 //GetFKeyIconPointer( 0x01BE, &ficon );
11091 //DisplayFKeyIcon( i, ficon);
11092
11093 //Reading each "line" that will be printed
11094 for (i = 0; (i < LINE_DISP_MAX) && (i + Start_Line <= Last_Line); i++){
11095 console_line & curline=Line[i+Start_Line];
11096 if (i == Cursor.y){
11097 // cursor line
11098 //if ((redraw_mode & 1)==0)
11099 drawRectangle(0,i*vfontsize,LCD_WIDTH_PX,vfontsize,_WHITE);
11100 if (curline.type == LINE_TYPE_INPUT || curline.type == LINE_TYPE_OUTPUT && curline.disp_len >= COL_DISP_MAX){
11101 locate(1, i + 1);
11102 if (curline.readonly){
11103 #ifdef CURSOR
11104 Cursor_SetFlashOff();
11105 #endif
11106 PrintRev(curline.str + curline.start_col);
11107 }
11108 else
11109 Print(curline.str+curline.start_col+(Cursor.x>COL_DISP_MAX-1?1:0));
11110 }
11111 else {
11112 locate(1, i + 1);
11113 print(print_x,print_y,(const char *)curline.str,TEXT_COLOR_BLACK,false,true/*fake*/,false);
11114 print_x=LCD_WIDTH_PX-print_x;
11115 if (curline.readonly){
11116 #ifdef CURSOR
11117 Cursor_SetFlashOff();
11118 #endif
11119 PrintRev(curline.str);
11120 }
11121 else
11122 Print(curline.str);
11123 }
11124
11125 if (
11126 #if 1 //def CURSOR
11127 curline.disp_len - curline.start_col > COL_DISP_MAX-1
11128 #else
11129 print_x>LCD_WIDTH_PX-hfontsize
11130 #endif
11131 ){
11132 #ifdef CURSOR
11133 locate(COL_DISP_MAX, i + 1);
11134 #else
11135 print_y=i*vfontsize;
11136 print_x=LCD_WIDTH_PX+2-hfontsize;
11137 #endif
11138 if (curline.readonly){
11139 if(curline.disp_len - curline.start_col != COL_DISP_MAX) {
11140 #ifdef CURSOR
11141 Cursor_SetFlashOff();
11142 #endif
11143 PrintRev((char *)">",COLOR_MAGENTA);
11144 }
11145 }
11146 else if (Cursor.x < COL_DISP_MAX-1){
11147 Print((char *)">",COLOR_MAGENTA);
11148 }
11149 }
11150
11151 if (curline.start_col > 0){
11152 locate(1, i + 1);
11153 if (curline.readonly){
11154 #ifdef CURSOR
11155 Cursor_SetFlashOff();
11156 #endif
11157 PrintRev((char *)"<",COLOR_MAGENTA);
11158 }
11159 else {
11160 Print((char *)"<",COLOR_MAGENTA);
11161 }
11162 }
11163
11164 if (!curline.readonly){
11165 #ifdef CURSOR
11166 switch(GetSetupSetting( (unsigned int)0x14)) {
11167 case 0:
11168 alpha_shift_status = 0;
11169 break;
11170 case 1: //Shift enabled
11171 alpha_shift_status = 1;
11172 break;
11173 case 4: case 0x84: //Alpha enabled
11174 alpha_shift_status = 2;
11175 break;
11176 case 8: case 0x88:
11177 alpha_shift_status = 4;
11178 break;
11179 default:
11180 alpha_shift_status = 0;
11181 break;
11182 }
11183 Cursor_SetPosition(Cursor.x, Cursor.y);
11184 Cursor_SetFlashOn(alpha_shift_status);
11185 //Cursor_SetFlashStyle(alpha_shift_status); //Potential 2.00 OS incompatibilty (cf Simon's doc)
11186 #else
11187 //locate(Cursor.x+1,Cursor.y+1);
11188 //DefineStatusMessage((giac::print_DOUBLE_(Cursor.y,6)+","+giac::print_DOUBLE_(print_y,6)).c_str(),1,0,0);
11189 //DisplayStatusArea();
11190 int fakestart=curline.start_col+(Cursor.x > COL_DISP_MAX-1?1:0);
11191 string fakes=string((const char *)curline.str).substr(fakestart,Cursor.x);
11192 int fakex=0,fakey=Cursor.y*vfontsize;
11193 print(fakex,fakey,fakes.c_str(),TEXT_COLOR_BLACK,false,true/* fake*/,false);
11194 drawRectangle(fakex,fakey,2,vfontsize,COLOR_BLACK);
11195 //drawRectangle(Cursor.x*hfontsize,24+Cursor.y*vfontsize,2,vfontsize,COLOR_BLACK);
11196 #endif
11197 }
11198 } // end cursor line
11199 else {
11200 if ((redraw_mode & 1)==0)
11201 continue;
11202 drawRectangle(0,i*vfontsize,LCD_WIDTH_PX,vfontsize,_WHITE);
11203 bool bigoutput = curline.type==LINE_TYPE_OUTPUT && curline.disp_len>=COL_DISP_MAX-3;
11204 locate(bigoutput?3:1,i+1);
11205 if (curline.type==LINE_TYPE_INPUT || bigoutput)
11206 Print(curline.str + curline.start_col);
11207 else {
11208 #ifdef CURSOR
11209 locate(COL_DISP_MAX - Line[i + Start_Line].disp_len + 1, i + 1);
11210 #else
11211 print(print_x,print_y,(const char *)curline.str,TEXT_COLOR_BLACK,false,true/*fake*/,false);
11212 print_x=LCD_WIDTH_PX-print_x;
11213 #endif
11214 Print(curline.str);
11215 }
11216 if (curline.disp_len - curline.start_col > COL_DISP_MAX){
11217 #ifdef CURSOR
11218 locate(COL_DISP_MAX, i + 1);
11219 #else
11220 print_x=LCD_WIDTH_PX+2-hfontsize;
11221 #endif
11222 Print((char *)">",COLOR_BLUE);
11223 }
11224 if (curline.start_col > 0){
11225 #ifdef CURSOR
11226 locate(1, i + 1);
11227 #else
11228 print_x=0;
11229 #endif
11230 Print((char *)"<",COLOR_BLUE);
11231 }
11232 } // end non cursor line
11233 } // end loop on all lines
11234 drawRectangle(0,i*vfontsize,LCD_WIDTH_PX,205-i*vfontsize,_WHITE);
11235
11236 if ((redraw_mode & 1)==1){
11237 for (; (i < LINE_DISP_MAX) ; i++)
11238 drawRectangle(0,i*vfontsize,LCD_WIDTH_PX,vfontsize,_WHITE);
11239 string menu("shift-1 ");
11240 menu += string(menu_f1);
11241 menu += "|2 ";
11242 menu += string(menu_f2);
11243 menu += "|3 ";
11244 menu += string(menu_f3);
11245 menu += xcas_python_eval==1?"|4 edt|5 2d|6 logo|7 lin|8 list|9plot|0 C":"|4 edt|5 2d|6 regr|7 matr|8 list|9 arit|0 C";
11246 drawRectangle(0,205,LCD_WIDTH_PX,17,_BLACK);
11247 PrintMiniMini(0,205,menu.c_str(),4);
11248 }
11249
11250 // status, clock,
11251 console_disp_status(contextptr);
11252 return CONSOLE_SUCCEEDED;
11253 }
11254
dConsoleRedraw()11255 void dConsoleRedraw(){
11256 Console_Disp(1,0);
11257 }
11258
Console_GetLine(GIAC_CONTEXT)11259 char *Console_GetLine(GIAC_CONTEXT)
11260 {
11261 int return_val;
11262
11263 do
11264 {
11265 return_val = Console_GetKey(contextptr);
11266 if (return_val==KEY_SHUTDOWN)
11267 return 0;
11268 Console_Disp(1,contextptr);
11269 if (return_val == KEY_CTRL_MENU) return 0;
11270 if (return_val == CONSOLE_MEM_ERR) return NULL;
11271 } while (return_val != CONSOLE_NEW_LINE_SET);
11272
11273 return Line[Current_Line - 1].str;
11274 }
11275
11276 /*
11277 Simple accessor to the Edit_Line buffer.
11278 */
Console_GetEditLine()11279 char* Console_GetEditLine()
11280 {
11281 return Edit_Line;
11282 }
11283
save_session(GIAC_CONTEXT)11284 void save_session(GIAC_CONTEXT){
11285 if (strcmp(session_filename,"session") && console_changed){
11286 string tmp(session_filename);
11287 tmp += (lang==1)?" a ete modifie!":" was modified!";
11288 if (confirm(tmp.c_str(),
11289 #ifdef NSPIRE_NEWLIB
11290 (lang==1)?"enter: sauve, esc: tant pis":"enter: save, esc: discard changes"
11291 #else
11292 (lang==1)?"OK: sauve, Back: tant pis":"OK: save, Back: discard changes"
11293 #endif
11294 )==KEY_CTRL_F1){
11295 save(session_filename,contextptr);
11296 console_changed=0;
11297 }
11298 }
11299 save("session",contextptr);
11300 // this is only called on exit, no need to reinstall the check_execution_abort timer.
11301 if (edptr && edptr->changed && edptr->filename!="session.py"){
11302 if (!check_leave(edptr)){
11303 save_script("lastprg.py",merge_area(edptr->elements));
11304 }
11305 }
11306 }
11307
11308 #ifdef NSPIRE_NEWLIB
nspire_fr()11309 bool nspire_fr(){
11310 char16_t input_w[] = u"getLangInfo()";
11311 void *math_expr = nullptr;
11312 int str_offset = 0;
11313
11314 int error = TI_MS_evaluateExpr_ACBER(NULL, NULL, (const uint16_t*)input_w, &math_expr, &str_offset);
11315 if (error)
11316 return false;
11317
11318 char16_t *output_w;
11319 error = TI_MS_MathExprToStr(math_expr, NULL, (uint16_t**)&output_w);
11320 syscall<e_free, void>(math_expr); // Should be TI_MS_DeleteMathExpr
11321
11322 if (error)
11323 return false;
11324 int l=0;
11325 for (l=0;l<64;++l){
11326 if (output_w[l]==0)
11327 break;
11328 }
11329 bool b=l==4 && output_w[1]=='f' && output_w[2]=='r';
11330 // Do something with output_w, it's u"42." here
11331
11332 syscall<e_free, void>(output_w);
11333 return b;
11334 }
11335 #endif
11336
11337 tableur * sheetptr=0;
console_main(GIAC_CONTEXT)11338 int console_main(GIAC_CONTEXT){
11339 #if defined NUMWORKS && defined MICROPY_LIB
11340 mp_stack_ctrl_init();
11341 char * heap=micropy_init();
11342 if (!heap)
11343 return 1;
11344 #endif
11345 sheetptr=0;
11346 shutdown=do_shutdown;
11347 #ifdef NSPIRE_NEWLIB
11348 // try to detect emulator or real calc
11349 unsigned NSPIRE_SPEED=0x900B0000;
11350 unsigned speed=*(unsigned *)NSPIRE_SPEED;
11351 nspireemu= (speed==1445890);
11352 mkdir("Xcas",0755);
11353 //mkdir("/Xcas",0755);
11354 //mkdir("A:/Xcas",0755);
11355 //mkdir("A:\\Xcas",0755);
11356 int err=chdir("Xcas");
11357 if (err)
11358 err=chdir("ndless");
11359 bool b=nspire_fr();
11360 lang=b?1:0;
11361 #endif
11362 // SetQuitHandler(save_session); // automatically save session when exiting
11363 if (!turtleptr){
11364 turtle();
11365 _efface_logo(vecteur(0),contextptr);
11366 }
11367 int key;
11368 Console_Init(contextptr);
11369 Bdisp_AllClr_VRAM();
11370 rand_seed(millis(),contextptr);
11371 restore_session("session",contextptr);
11372 giac::angle_radian(os_get_angle_unit()==0,contextptr);
11373 //GetKey(&key);
11374 Console_Disp(1,contextptr);
11375 // GetKey(&key);
11376 char *expr=0;
11377 #ifndef NO_STDEXCEPT
11378 try {
11379 #endif
11380 while(1){
11381 if ((expr=Console_GetLine(contextptr))==NULL){
11382 save_session(contextptr);
11383 #ifdef NUMWORKS
11384 return 0;
11385 #endif
11386 #ifdef MICROPY_LIB
11387 mp_deinit(); free(heap);
11388 #endif
11389 Console_Free();
11390 release_globals();
11391 if (sheetptr){
11392 // sheetptr->m.clear();
11393 delete sheetptr;
11394 sheetptr=0;
11395 }
11396 return 0;
11397 }
11398 if (strcmp((const char *)expr,"restart")==0){
11399 if (confirm((lang==1)?"Effacer variables?":"Clear variables?",
11400 #ifdef NSPIRE_NEWLIB
11401 (lang==1)?"enter: annul, esc: confirmer":"enter: cancel, esc: confirm"
11402 #else
11403 (lang==1)?"OK: annul, Back: confirmer":"OK: cancel, Back: confirm"
11404 #endif
11405 )!=KEY_CTRL_F6){
11406 Console_Output(" cancelled");
11407 Console_NewLine(LINE_TYPE_OUTPUT,1);
11408 //GetKey(&key);
11409 Console_Disp(1,contextptr);
11410 continue;
11411 }
11412 }
11413 // should save in another file
11414 if (strcmp((const char *)expr,"=>")==0 || strcmp((const char *)expr,"=>\n")==0){
11415 save_session(contextptr);
11416 Console_Output("Session saved");
11417 }
11418 else
11419 run(expr,7,contextptr);
11420 //print_mem_info();
11421 Console_NewLine(LINE_TYPE_OUTPUT,1);
11422 //GetKey(&key);
11423 Console_Disp(1,contextptr);
11424 }
11425 #ifndef NO_STDEXCEPT
11426 } catch(autoshutdown & e) {
11427 }
11428 #endif
11429 #ifdef NUMWORKS
11430 return 0;
11431 #endif
11432 Console_Free();
11433 release_globals();
11434 #ifdef MICROPY_LIB
11435 mp_deinit(); free(heap);
11436 #endif
11437 if (sheetptr){
11438 // sheetptr->m.clear();
11439 delete sheetptr;
11440 sheetptr=0;
11441 }
11442 return 0;
11443 }
11444
11445
11446 #endif // TEXTAREA
11447
rgb24to16(int c)11448 int rgb24to16(int c){
11449 int r=(c>>16)&0xff,g=(c>>8)&0xff,b=c&0xff;
11450 return (((r*32)/256)<<11) | (((g*64)/256)<<5) | (b*32/256);
11451 }
11452
11453 // table periodique, code adapte de https://github.com/M4xi1m3/nw-atom
11454 // avec l'aimable autorisation de diffusion sous licence GPL de Maxime Friess
11455 // https://tiplanet.org/forum/viewtopic.php?f=97&t=23094&p=247471#p247471
11456 enum AtomType {
11457 ALKALI_METAL,
11458 ALKALI_EARTH_METAL,
11459 LANTHANIDE,
11460 ACTINIDE,
11461 TRANSITION_METAL,
11462 POST_TRANSITION_METAL,
11463 METALLOID,
11464 HALOGEN,
11465 REACTIVE_NONMETAL,
11466 NOBLE_GAS,
11467 UNKNOWN
11468 };
11469
11470 struct AtomDef {
11471 uint8_t num;
11472 uint8_t x;
11473 uint8_t y;
11474 AtomType type;
11475 const char* name;
11476 const char* symbol;
11477 uint8_t neutrons;
11478 double mass;
11479 double electroneg;
11480 };
11481
11482 const AtomDef atomsdefs[] = {
11483 { 1, 0, 0, REACTIVE_NONMETAL , "Hydrogen" , "H" , 0, 1.00784 , 2.2 },
11484 { 2, 17, 0, NOBLE_GAS , "Helium" , "He" , 2, 4.002602 , -1 },
11485
11486
11487 { 3, 0, 1, ALKALI_METAL , "Lithium" , "Li" , 4, 6.938 , 0.98 },
11488 { 4, 1, 1, ALKALI_EARTH_METAL , "Beryllium" , "Be" , 5, 9.012182 , 1.57 },
11489 { 5, 12, 1, METALLOID , "Boron" , "B" , 6, 10.806 , 2.04 },
11490 { 6, 13, 1, REACTIVE_NONMETAL , "Carbon" , "C" , 6, 12.0096 , 2.55 },
11491 { 7, 14, 1, REACTIVE_NONMETAL , "Nitrogen" , "N" , 7, 14.00643 , 3.04 },
11492 { 8, 15, 1, REACTIVE_NONMETAL , "Oxygen" , "O" , 8, 15.99903 , 3.44 },
11493 { 9, 16, 1, HALOGEN , "Fluorine" , "F" , 10, 18.9984032 , 3.98 },
11494 { 10, 17, 1, NOBLE_GAS , "Neon" , "Ne" , 10, 20.1797 , -1 },
11495
11496
11497 { 11, 0, 2, ALKALI_METAL , "Sodium" , "Na" , 12, 22.9897693 , 0.93 },
11498 { 12, 1, 2, ALKALI_EARTH_METAL , "Magnesium" , "Mg" , 12, 24.3050 , 1.31 },
11499 { 13, 12, 2, POST_TRANSITION_METAL , "Aluminium" , "Al" , 14, 26.9815386 , 1.61 },
11500 { 14, 13, 2, METALLOID , "Silicon" , "Si" , 14, 28.084 , 1.9 },
11501 { 15, 14, 2, REACTIVE_NONMETAL , "Phosphorus" , "P" , 16, 30.973762 , 2.19 },
11502 { 16, 15, 2, REACTIVE_NONMETAL , "Sulfur" , "S" , 16, 32.059 , 2.58 },
11503 { 17, 16, 2, HALOGEN , "Chlorine" , "Cl" , 18, 35.446 , 3.16 },
11504 { 18, 17, 2, NOBLE_GAS , "Argon" , "Ar" , 22, 39.948 , -1 },
11505
11506
11507 { 19, 0, 3, ALKALI_METAL , "Potassium" , "K" , 20, 39.0983 , 0.82 },
11508 { 20, 1, 3, ALKALI_EARTH_METAL , "Calcium" , "Ca" , 20, 40.078 , 1 },
11509 { 21, 2, 3, TRANSITION_METAL , "Scandium" , "Sc" , 24, 44.955912 , 1.36 },
11510 { 22, 3, 3, TRANSITION_METAL , "Titanium" , "Ti" , 26, 47.867 , 1.54 },
11511 { 23, 4, 3, TRANSITION_METAL , "Vanadium" , "V" , 28, 50.9415 , 1.63 },
11512 { 24, 5, 3, TRANSITION_METAL , "Chromium" , "Cr" , 28, 51.9961 , 1.66 },
11513 { 25, 6, 3, TRANSITION_METAL , "Manganese" , "Mn" , 30, 54.938045 , 1.55 },
11514 { 26, 7, 3, TRANSITION_METAL , "Iron" , "Fe" , 30, 55.845 , 1.83 },
11515 { 27, 8, 3, TRANSITION_METAL , "Cobalt" , "Co" , 32, 58.933195 , 1.88 },
11516 { 28, 9, 3, TRANSITION_METAL , "Nickel" , "Ni" , 30, 58.6934 , 1.91 },
11517 { 29, 10, 3, TRANSITION_METAL , "Copper" , "Cu" , 34, 63.546 , 1.9 },
11518 { 30, 11, 3, POST_TRANSITION_METAL , "Zinc" , "Zn" , 34, 65.38 , 1.65 },
11519 { 31, 12, 3, POST_TRANSITION_METAL , "Gallium" , "Ga" , 38, 69.723 , 1.81 },
11520 { 32, 13, 3, METALLOID , "Germanium" , "Ge" , 42, 72.63 , 2.01 },
11521 { 33, 14, 3, METALLOID , "Arsenic" , "As" , 42, 74.92160 , 2.18 },
11522 { 34, 15, 3, REACTIVE_NONMETAL , "Selenium" , "Se" , 46, 78.96 , 2.55 },
11523 { 35, 16, 3, HALOGEN , "Bromine" , "Br" , 44, 79.904 , 2.96 },
11524 { 36, 17, 3, NOBLE_GAS , "Krypton" , "Kr" , 48, 83.798 , -1 },
11525
11526 { 37, 0, 4, ALKALI_METAL , "Rubidium" , "Rb" , 48, 85.4678 , 0.82 },
11527 { 38, 1, 4, ALKALI_EARTH_METAL , "Strontium" , "Sr" , 50, 87.62 , 0.95 },
11528 { 39, 2, 4, TRANSITION_METAL , "Yttrium" , "Y" , 50, 88.90585 , 1.22 },
11529 { 40, 3, 4, TRANSITION_METAL , "Zirconium" , "Zr" , 50, 91.224 , 1.33 },
11530 { 41, 4, 4, TRANSITION_METAL , "Niobium" , "Nb" , 52, 92.90638 , 1.6 },
11531 { 42, 5, 4, TRANSITION_METAL , "Molybdenum" , "Mo" , 56, 95.96 , 2.16 },
11532 { 43, 6, 4, TRANSITION_METAL , "Technetium" , "Tc" , 55, 98 , 2.10 },
11533 { 44, 7, 4, TRANSITION_METAL , "Ruthemium" , "Ru" , 58, 101.07 , 2.2 },
11534 { 45, 8, 4, TRANSITION_METAL , "Rhodium" , "Rh" , 58, 102.90550 , 2.28 },
11535 { 46, 9, 4, TRANSITION_METAL , "Palladium" , "Pd" , 60, 106.42 , 2.20 },
11536 { 47, 10, 4, TRANSITION_METAL , "Silver" , "Ag" , 60, 107.8682 , 1.93 },
11537 { 48, 11, 4, POST_TRANSITION_METAL , "Cadmium" , "Cd" , 66, 112.411 , 1.69 },
11538 { 49, 12, 4, POST_TRANSITION_METAL , "Indium" , "In" , 66, 114.818 , 1.78 },
11539 { 50, 13, 4, POST_TRANSITION_METAL , "Tin" , "Sn" , 70, 118.710 , 1.96 },
11540 { 51, 14, 4, METALLOID , "Antimony" , "Sb" , 70, 121.760 , 2.05 },
11541 { 52, 15, 4, METALLOID , "Tellurium" , "Te" , 78, 127.60 , 2.1 },
11542 { 53, 16, 4, HALOGEN , "Indine" , "I" , 74, 126.90447 , 2.66 },
11543 { 54, 17, 4, NOBLE_GAS , "Xenon" , "Xe" , 78, 131.293 , 2.60 },
11544
11545
11546 { 55, 0, 5, ALKALI_METAL , "Caesium" , "Cs" , 78, 132.905452 , 0.79 },
11547 { 56, 1, 5, ALKALI_EARTH_METAL , "Barium" , "Ba" , 82, 137.327 , 0.89 },
11548
11549 { 57, 3, 7, LANTHANIDE , "Lanthanum" , "La" , 82, 138.90547 , 1.10 },
11550 { 58, 4, 7, LANTHANIDE , "Cerium" , "Ce" , 82, 140.116 , 1.12 },
11551 { 59, 5, 7, LANTHANIDE , "Praseodymium" , "Pr" , 82, 140.90765 , 1.13 },
11552 { 60, 6, 7, LANTHANIDE , "Neodymium" , "Nd" , 82, 144.242 , 1.14 },
11553 { 61, 7, 7, LANTHANIDE , "Promethium" , "Pm" , 84, 145 , 1.13 },
11554 { 62, 8, 7, LANTHANIDE , "Samarium" , "Sm" , 90, 150.36 , 1.17 },
11555 { 63, 9, 7, LANTHANIDE , "Europium" , "Eu" , 90, 151.964 , 1.12 },
11556 { 64, 10, 7, LANTHANIDE , "Gadolinium" , "Gd" , 94, 157.25 , 1.20 },
11557 { 65, 11, 7, LANTHANIDE , "Terbium" , "Tb" , 94, 158.92535 , 1.12 },
11558 { 66, 12, 7, LANTHANIDE , "Dyxprosium" , "Dy" , 98, 162.500 , 1.22 },
11559 { 67, 13, 7, LANTHANIDE , "Holmium" , "Ho" , 98, 164.93032 , 1.23 },
11560 { 68, 14, 7, LANTHANIDE , "Erbium" , "Er" , 98, 167.259 , 1.24 },
11561 { 69, 15, 7, LANTHANIDE , "Thulium" , "Tm" , 100, 168.93421 , 1.25 },
11562 { 70, 16, 7, LANTHANIDE , "Ytterbium" , "Yb" , 104, 173.054 , 1.1 },
11563 { 71, 17, 7, LANTHANIDE , "Lutetium" , "Lu" , 104, 174.9668 , 1.0 },
11564
11565 { 72, 3, 5, TRANSITION_METAL , "Hafnium" , "Hf" , 108, 178.49 , 1.3 },
11566 { 73, 4, 5, TRANSITION_METAL , "Tantalum" , "Ta" , 108, 180.94788 , 1.5 },
11567 { 74, 5, 5, TRANSITION_METAL , "Tungsten" , "W" , 110, 183.84 , 1.7 },
11568 { 75, 6, 5, TRANSITION_METAL , "Rhenium" , "Re" , 112, 186.207 , 1.9 },
11569 { 76, 7, 5, TRANSITION_METAL , "Osmium" , "Os" , 116, 190.23 , 2.2 },
11570 { 77, 8, 5, TRANSITION_METAL , "Iridium" , "Ir" , 116, 192.217 , 2.2 },
11571 { 78, 9, 5, TRANSITION_METAL , "Platinum" , "Pt" , 117, 195.084 , 2.2 },
11572 { 79, 10, 5, TRANSITION_METAL , "Gold" , "Au" , 118, 196.966569 , 2.4 },
11573 { 80, 11, 5, POST_TRANSITION_METAL , "Mercury" , "Hg" , 122, 200.59 , 1.9 },
11574 { 81, 12, 5, POST_TRANSITION_METAL , "Thalium" , "Tl" , 124, 204.382 , 1.8 },
11575 { 82, 13, 5, POST_TRANSITION_METAL , "Lead" , "Pb" , 126, 207.2 , 1.8 },
11576 { 83, 14, 5, POST_TRANSITION_METAL , "Bismuth" , "Bi" , 126, 208.98040 , 1.9 },
11577 { 84, 15, 5, POST_TRANSITION_METAL , "Polonium" , "Po" , 126, 209 , 2.0 },
11578 { 85, 16, 5, HALOGEN , "Astatine" , "At" , 125, 210 , 2.2 },
11579 { 86, 17, 5, NOBLE_GAS , "Radon" , "Rn" , 136, 222 , 2.2 },
11580
11581
11582 { 87, 0, 6, ALKALI_METAL , "Francium" , "Fr" , 136, 223 , 0.7 },
11583 { 88, 1, 6, ALKALI_EARTH_METAL , "Radium" , "Ra" , 138, 226 , 0.9 },
11584
11585 { 89, 3, 8, ACTINIDE , "Actinium" , "Ac" , 138, 227 , 1.1 },
11586 { 90, 4, 8, ACTINIDE , "Thorium" , "Th" , 142, 232.03806 , 1.3 },
11587 { 91, 5, 8, ACTINIDE , "Protactinium" , "Pa" , 140, 231.03588 , 1.5 },
11588 { 92, 6, 8, ACTINIDE , "Uranium" , "U" , 146, 238.02891 , 1.38 },
11589 { 93, 7, 8, ACTINIDE , "Neptunium" , "Np" , 144, 237 , 1.36 },
11590 { 94, 8, 8, ACTINIDE , "Plutonium" , "Pu" , 150, 244 , 1.28 },
11591 { 95, 9, 8, ACTINIDE , "Americium" , "Am" , 148, 243 , 1.13 },
11592 { 96, 10, 8, ACTINIDE , "Curium" , "Cm" , 151, 247 , 1.28 },
11593 { 97, 11, 8, ACTINIDE , "Berkellum" , "Bk" , 150, 247 , 1.3 },
11594 { 98, 12, 8, ACTINIDE , "Californium" , "Cf" , 153, 251 , 1.3 },
11595 { 99, 13, 8, ACTINIDE , "Einsteinium" , "Es" , 153, 252 , 1.3 },
11596 {100, 14, 8, ACTINIDE , "Fermium" , "Fm" , 157, 257 , 1.3 },
11597 {101, 15, 8, ACTINIDE , "Mendelevium" , "Md" , 157, 258 , 1.3 },
11598 {102, 16, 8, ACTINIDE , "Nobelium" , "No" , 157, 259 , 1.3 },
11599 {103, 17, 8, ACTINIDE , "Lawrencium" , "Lr" , 163, 262 , 1.3 },
11600
11601 {104, 3, 6, TRANSITION_METAL , "Rutherfordium", "Rf" , 163, 261 , -1 },
11602 {105, 4, 6, TRANSITION_METAL , "Dubnium" , "Db" , 163, 262 , -1 },
11603 {106, 5, 6, TRANSITION_METAL , "Seaborgium" , "Sg" , 163, 263 , -1 },
11604 {107, 6, 6, TRANSITION_METAL , "Bohrium" , "Bh" , 163, 264 , -1 },
11605 {108, 7, 6, TRANSITION_METAL , "Hassium" , "Hs" , 169, 265 , -1 },
11606 {109, 8, 6, UNKNOWN , "Meitnerium" , "Mt" , 169, 268 , -1 },
11607 {110, 9, 6, UNKNOWN , "Damstadtium" , "Ds" , 171, 281 , -1 },
11608 {111, 10, 6, UNKNOWN , "Roentgenium" , "Rg" , 171, 273 , -1 },
11609 {112, 11, 6, POST_TRANSITION_METAL , "Coppernicium" , "Cn" , 173, 277 , -1 },
11610 {113, 12, 6, UNKNOWN , "Nihonium" , "Nh" , 173, 283 , -1 },
11611 {114, 13, 6, UNKNOWN , "Flerovium" , "Fl" , 175, 285 , -1 },
11612 {115, 14, 6, UNKNOWN , "Moscovium" , "Mv" , 174, 287 , -1 },
11613 {116, 15, 6, UNKNOWN , "Livermorium" , "Lv" , 177, 289 , -1 },
11614 {117, 16, 6, UNKNOWN , "Tennessine" , "Ts" , 177, 294 , -1 },
11615 {118, 17, 6, NOBLE_GAS , "Oganesson" , "Og" , 176, 293 , -1 },
11616
11617 };
11618
drawAtom(uint8_t id)11619 void drawAtom(uint8_t id) {
11620 int fill = rgb24to16(0xeeeeee);
11621
11622 switch(atomsdefs[id].type) {
11623 case ALKALI_METAL:
11624 fill = rgb24to16(0xffaa00);
11625 break;
11626 case ALKALI_EARTH_METAL:
11627 fill = rgb24to16(0xf6f200);
11628 break;
11629 case LANTHANIDE:
11630 fill = rgb24to16(0xffaa8b);
11631 break;
11632 case ACTINIDE:
11633 fill = rgb24to16(0xdeaacd);
11634 break;
11635 case TRANSITION_METAL:
11636 fill = rgb24to16(0xde999c);
11637 break;
11638 case POST_TRANSITION_METAL:
11639 fill = rgb24to16(0x9cbaac);
11640 break;
11641 case METALLOID:
11642 fill = rgb24to16(0x52ce8b);
11643 break;
11644 case REACTIVE_NONMETAL:
11645 fill = rgb24to16(0x00ee00);
11646 break;
11647 case NOBLE_GAS:
11648 fill = rgb24to16(0x8baaff);
11649 break;
11650 case HALOGEN:
11651 fill = rgb24to16(0x00debd);
11652 break;
11653 default:
11654 break;
11655 }
11656
11657 if (atomsdefs[id].y >= 7) {
11658 drawRectangle(6 + atomsdefs[id].x * 17, 15 + atomsdefs[id].y * 17, 18, 18, fill);
11659 stroke_rectangle(6 + atomsdefs[id].x * 17, 15 + atomsdefs[id].y * 17, 18, 18, rgb24to16(0x525552));
11660 os_draw_string_small(8 + atomsdefs[id].x * 17, 17 + atomsdefs[id].y * 17, _BLACK, fill, atomsdefs[id].symbol);
11661 } else {
11662 drawRectangle(6 + atomsdefs[id].x * 17, 6 + atomsdefs[id].y * 17, 18, 18, fill);
11663 stroke_rectangle(6 + atomsdefs[id].x * 17, 6 + atomsdefs[id].y * 17, 18, 18, rgb24to16(0x525552));
11664 os_draw_string_small(8 + atomsdefs[id].x * 17, 8 + atomsdefs[id].y * 17, _BLACK, fill, atomsdefs[id].symbol);
11665 }
11666 }
11667
periodic_table(const char * & name,const char * & symbol,char * protons,char * nucleons,char * mass,char * electroneg)11668 int periodic_table(const char * & name,const char * & symbol,char * protons,char * nucleons,char * mass,char * electroneg){
11669 bool partial_draw=false,redraw=true;
11670 int cursor_pos=0;
11671 const int ATOM_NUMS=sizeof(atomsdefs)/sizeof(AtomDef);
11672 for (;;){
11673 if (redraw){
11674 if (partial_draw) {
11675 partial_draw = false;
11676 drawRectangle(50, 0, 169, 57, _WHITE);
11677 drawRectangle(0, 185, LCD_WIDTH_PX, 15, _WHITE);
11678 } else {
11679 drawRectangle(0,0,LCD_WIDTH_PX,LCD_HEIGHT_PX,_WHITE);
11680 }
11681 #ifdef NSPIRE_NEWLIB
11682 os_draw_string_small_(0,200,gettext("enter: tout, P:protons, N:nucleons, M:mass, E:khi"));
11683 #else
11684 os_draw_string_small_(0,200,gettext("OK: tout, P:protons, N:nucleons, M:mass, E:khi"));
11685 #endif
11686 for(int i = 0; i < ATOM_NUMS; i++) {
11687 drawAtom(i);
11688 }
11689 if (atomsdefs[cursor_pos].y >= 7) {
11690 stroke_rectangle(6 + atomsdefs[cursor_pos].x * 17, 15 + atomsdefs[cursor_pos].y * 17, 18, 18, 0x000000);
11691 stroke_rectangle(7 + atomsdefs[cursor_pos].x * 17, 16 + atomsdefs[cursor_pos].y * 17, 16, 16, 0x000000);
11692 } else {
11693 stroke_rectangle(6 + atomsdefs[cursor_pos].x * 17, 6 + atomsdefs[cursor_pos].y * 17, 18, 18, 0x000000);
11694 stroke_rectangle(7 + atomsdefs[cursor_pos].x * 17, 7 + atomsdefs[cursor_pos].y * 17, 16, 16, 0x000000);
11695 }
11696
11697 drawRectangle(48, 99, 2, 61,rgb24to16(0x525552));
11698 drawRectangle(48, 141, 9, 2, rgb24to16(0x525552));
11699 drawRectangle(48, 158, 9, 2, rgb24to16(0x525552));
11700
11701 int prot=atomsdefs[cursor_pos].num;
11702 sprint_int(protons,prot);
11703 int nuc=atomsdefs[cursor_pos].neutrons+atomsdefs[cursor_pos].num;
11704 sprint_int(nucleons,nuc);
11705
11706 symbol=atomsdefs[cursor_pos].symbol;
11707 os_draw_string_(73,23,symbol);
11708 name=atomsdefs[cursor_pos].name;
11709 os_draw_string_small_(110,27,gettext(name));
11710 os_draw_string_small_(50,18,nucleons);
11711 os_draw_string_small_(50,31,protons);
11712 strcpy(mass,"M:");
11713 strcpy(electroneg,"khi:");
11714 sprint_double(mass+2,atomsdefs[cursor_pos].mass);
11715 os_draw_string_small_(0,186,mass);
11716 sprint_double(electroneg+4,atomsdefs[cursor_pos].electroneg);
11717 os_draw_string_small_(160,186,electroneg);
11718 }
11719 redraw=false;
11720 int key;
11721 GetKey(&key);
11722 if (key==KEY_SHUTDOWN)
11723 return key;
11724 if (key==KEY_PRGM_ACON)
11725 redraw=true;
11726 if (key==KEY_CTRL_EXIT)
11727 return 0;
11728 if (key==KEY_CTRL_EXE || key==KEY_CTRL_OK)
11729 return 1|4|8|16|32;
11730 if (key=='s' || key==KEY_CHAR_5)
11731 return 2;
11732 if (key=='p' || key==KEY_CHAR_LPAR)
11733 return 4;
11734 if (key=='n' || key==KEY_CHAR_8)
11735 return 8;
11736 if (key=='m' || key==KEY_CHAR_7)
11737 return 16;
11738 if (key=='e' || key==KEY_CHAR_COMMA)
11739 return 32;
11740 if (key==KEY_CTRL_LEFT){
11741 if (cursor_pos>0)
11742 --cursor_pos;
11743 redraw=partial_draw=true;
11744 }
11745 if (key==KEY_CTRL_RIGHT){
11746 if (cursor_pos< ATOM_NUMS-1)
11747 ++cursor_pos;
11748 redraw=partial_draw=true;
11749 }
11750 if (key==KEY_CTRL_UP){
11751 uint8_t curr_x = atomsdefs[cursor_pos].x;
11752 uint8_t curr_y = atomsdefs[cursor_pos].y;
11753 bool updated = false;
11754
11755 if (curr_y > 0 && curr_y <= 9) {
11756 for(uint8_t i = 0; i < ATOM_NUMS; i++) {
11757 if (atomsdefs[i].x == curr_x && atomsdefs[i].y == curr_y - 1) {
11758 cursor_pos = i;
11759 redraw=partial_draw = true;
11760 }
11761 }
11762 }
11763
11764 }
11765 if (key==KEY_CTRL_DOWN){
11766 uint8_t curr_x = atomsdefs[cursor_pos].x;
11767 uint8_t curr_y = atomsdefs[cursor_pos].y;
11768 bool updated = false;
11769
11770 if (curr_y >= 0 && curr_y < 9) {
11771 for (uint8_t i = 0; i < ATOM_NUMS; i++) {
11772 if (atomsdefs[i].x == curr_x && atomsdefs[i].y == curr_y + 1) {
11773 cursor_pos = i;
11774 redraw=partial_draw = true;
11775 break;
11776 }
11777 }
11778 }
11779 }
11780 } // end endless for
11781 } // end periodic_table
11782
11783 #ifndef NO_NAMESPACE_XCAS
11784 } // namespace xcas
11785 #endif // ndef NO_NAMESPACE_XCAS
11786
console_output(const char * s,int l)11787 void console_output(const char * s,int l){
11788 char buf[l+1];
11789 strncpy(buf,s,l);
11790 buf[l]=0;
11791 xcas::dConsolePut(buf);
11792 }
11793
console_input(const char * msg1,const char * msg2,bool numeric,int ypos)11794 const char * console_input(const char * msg1,const char * msg2,bool numeric,int ypos){
11795 static string str;
11796 if (!giac::inputline(msg1,msg2,str,numeric,ypos,context0))
11797 return 0;
11798 return str.c_str();
11799 }
11800
c_draw_rectangle(int x,int y,int w,int h,int c)11801 void c_draw_rectangle(int x,int y,int w,int h,int c){
11802 giac::freeze=true;
11803 xcas::draw_line(x,y,x+w,y,c);
11804 xcas::draw_line(x+w,y,x+w,y+h,c);
11805 xcas::draw_line(x,y+h,x+w,y+h,c);
11806 xcas::draw_line(x,y,x,y+h,c);
11807 }
c_draw_line(int x0,int y0,int x1,int y1,int c)11808 void c_draw_line(int x0,int y0,int x1,int y1,int c){
11809 giac::freeze=true;
11810 xcas::draw_line(x0,y0,x1,y1,c);
11811 }
c_draw_circle(int xc,int yc,int r,int color,bool q1,bool q2,bool q3,bool q4)11812 void c_draw_circle(int xc,int yc,int r,int color,bool q1,bool q2,bool q3,bool q4){
11813 giac::freeze=true;
11814 xcas::draw_circle(xc,yc,r,color,q1,q2,q3,q4);
11815 }
c_draw_filled_circle(int xc,int yc,int r,int color,bool left,bool right)11816 void c_draw_filled_circle(int xc,int yc,int r,int color,bool left,bool right){
11817 giac::freeze=true;
11818 xcas::draw_filled_circle(xc,yc,r,color,left,right);
11819 }
c_convert(int * x,int * y,vector<vector<int>> & v)11820 void c_convert(int *x,int*y,vector< vector<int> > & v){
11821 for (int i=0;i<v.size();++i,++x,++y){
11822 v[i].push_back(*x);
11823 v[i].push_back(*y);
11824 }
11825 }
c_draw_polygon(int * x,int * y,int n,int color)11826 void c_draw_polygon(int * x,int *y ,int n,int color){
11827 giac::freeze=true;
11828 vector< vector<int> > v(n);
11829 c_convert(x,y,v);
11830 xcas::draw_polygon(v,color);
11831 }
c_draw_filled_polygon(int * x,int * y,int n,int xmin,int xmax,int ymin,int ymax,int color)11832 void c_draw_filled_polygon(int * x,int *y, int n,int xmin,int xmax,int ymin,int ymax,int color){
11833 giac::freeze=true;
11834 vector< vector<int> > v(n);
11835 c_convert(x,y,v);
11836 xcas::draw_filled_polygon(v,xmin,xmax,ymin,ymax,color);
11837 }
c_draw_arc(int xc,int yc,int rx,int ry,int color,double theta1,double theta2)11838 void c_draw_arc(int xc,int yc,int rx,int ry,int color,double theta1, double theta2){
11839 giac::freeze=true;
11840 xcas::draw_arc(xc,yc,rx,ry,color,theta1,theta2);
11841 }
c_draw_filled_arc(int x,int y,int rx,int ry,int theta1_deg,int theta2_deg,int color,int xmin,int xmax,int ymin,int ymax,bool segment)11842 void c_draw_filled_arc(int x,int y,int rx,int ry,int theta1_deg,int theta2_deg,int color,int xmin,int xmax,int ymin,int ymax,bool segment){
11843 giac::freeze=true;
11844 xcas::draw_filled_arc(x,y,rx,ry,theta1_deg,theta2_deg,color,xmin,xmax,ymin,ymax,segment);
11845 }
c_set_pixel(int x,int y,int c)11846 void c_set_pixel(int x,int y,int c){
11847 giac::freeze=true;
11848 os_set_pixel(x,y,c);
11849 }
c_fill_rect(int x,int y,int w,int h,int c)11850 void c_fill_rect(int x,int y,int w,int h,int c){
11851 giac::freeze=true;
11852 os_fill_rect(x,y,w,h,c);
11853 }
c_draw_string(int x,int y,int c,int bg,const char * s,bool fake)11854 int c_draw_string(int x,int y,int c,int bg,const char * s,bool fake){
11855 giac::freeze=true;
11856 return os_draw_string(x,y,c,bg,s,fake);
11857 }
c_draw_string_small(int x,int y,int c,int bg,const char * s,bool fake)11858 int c_draw_string_small(int x,int y,int c,int bg,const char * s,bool fake){
11859 giac::freeze=true;
11860 return os_draw_string_small(x,y,c,bg,s,fake);
11861 }
c_draw_string_medium(int x,int y,int c,int bg,const char * s,bool fake)11862 int c_draw_string_medium(int x,int y,int c,int bg,const char * s,bool fake){
11863 giac::freeze=true;
11864 return os_draw_string_medium(x,y,c,bg,s,fake);
11865 }
11866
select_item(const char ** ptr,const char * title,bool askfor1)11867 int select_item(const char ** ptr,const char * title,bool askfor1){
11868 int nitems=0;
11869 for (const char ** p=ptr;*p;++p)
11870 ++nitems;
11871 if (nitems==0 || nitems>=256)
11872 return -1;
11873 if (!askfor1 && nitems==1)
11874 return 0;
11875 MenuItem smallmenuitems[nitems];
11876 for (int i=0;i<nitems;++i){
11877 smallmenuitems[i].text=(char *) ptr[i];
11878 }
11879 Menu smallmenu;
11880 smallmenu.numitems=nitems;
11881 smallmenu.items=smallmenuitems;
11882 smallmenu.height=12;
11883 smallmenu.scrollbar=1;
11884 smallmenu.scrollout=1;
11885 smallmenu.title = (char*) title;
11886 //MsgBoxPush(5);
11887 int sres = doMenu(&smallmenu);
11888 //MsgBoxPop();
11889 if (sres!=MENU_RETURN_SELECTION && sres!=KEY_CTRL_EXE)
11890 return -1;
11891 return smallmenu.selection-1;
11892 }
11893
select_interpreter()11894 int select_interpreter(){
11895 const char * choix[]={"Xcas interpreter","Xcas compat Python ^=**","Xcas compat Python ^=xor","MicroPython interpreter",0};
11896 return select_item(choix,"Syntax",false);
11897 }
11898
double2gen(double d)11899 ulonglong double2gen(double d){
11900 giac::gen g(d);
11901 return *(ulonglong *) &g;
11902 }
11903
int2gen(int d)11904 ulonglong int2gen(int d){
11905 giac::gen g(d);
11906 return *(ulonglong *) &g;
11907 }
11908
turtle_freeze()11909 void turtle_freeze(){
11910 freezeturtle=true;
11911 }
11912
doubleptr2matrice(double * x,int n,int m,giac::matrice & M)11913 void doubleptr2matrice(double * x,int n,int m,giac::matrice & M){
11914 M.resize(n);
11915 for (int i=0;i<n;++i){
11916 M[i]=giac::vecteur(m);
11917 giac::vecteur & w=*M[i]._VECTptr;
11918 for (int j=0;j<m;++j){
11919 w[j]=*x;
11920 ++x;
11921 }
11922 }
11923 }
11924
11925 // x must have enough space!
matrice2doubleptr(const giac::matrice & M,double * x)11926 bool matrice2doubleptr(const giac::matrice &M,double *x){
11927 int n=M.size();
11928 if (n==0 || M.front().type!=giac::_VECT)
11929 return false;
11930 int m=M.front()._VECTptr->size();
11931 for (int i=0;i<n;++i){
11932 if (M[i].type!=giac::_VECT || M[i]._VECTptr->size()!=m)
11933 return false;
11934 giac::vecteur & w=*M[i]._VECTptr;
11935 for (int j=0;j<m;++j){
11936 giac::gen g =giac::evalf_double(w[j],1,giac::context0);
11937 if (g.type!=giac::_DOUBLE_)
11938 return false;
11939 *x=g._DOUBLE_val;
11940 ++x;
11941 }
11942 }
11943 return true;
11944 }
11945
r_inv(double * x,int n)11946 bool r_inv(double * x,int n){
11947 giac::matrice M(n);
11948 doubleptr2matrice(x,n,n,M);
11949 M=giac::minv(M,giac::context0);
11950 return matrice2doubleptr(M,x);
11951 }
11952
11953
r_rref(double * x,int n,int m)11954 bool r_rref(double * x,int n,int m){
11955 giac::matrice M(n);
11956 doubleptr2matrice(x,n,m,M);
11957 giac::gen g=giac::_rref(M,giac::context0);
11958 if (g.type!=giac::_VECT)
11959 return false;
11960 return matrice2doubleptr(*g._VECTptr,x);
11961 }
11962
r_det(double * x,int n)11963 double r_det(double *x,int n){
11964 giac::matrice M(n);
11965 doubleptr2matrice(x,n,n,M);
11966 giac::gen g=giac::mdet(M,giac::context0);
11967 g=giac::evalf_double(g,1,giac::context0);
11968 double d=1.0,e=1.0;
11969 if (g.type!=_DOUBLE_)
11970 return 0.0/(d-e);
11971 return g._DOUBLE_val;
11972 }
11973
c_complexptr2matrice(c_complex * x,int n,int m,giac::matrice & M)11974 void c_complexptr2matrice(c_complex * x,int n,int m,giac::matrice & M){
11975 M.resize(n);
11976 for (int i=0;i<n;++i){
11977 if (m==0){
11978 M[i]=gen(x->r,x->i);
11979 ++x;
11980 continue;
11981 }
11982 M[i]=giac::vecteur(m);
11983 giac::vecteur & w=*M[i]._VECTptr;
11984 for (int j=0;j<m;++j){
11985 w[j]=gen(x->r,x->i);
11986 ++x;
11987 }
11988 }
11989 }
11990
gen2c_complex(giac::gen & g)11991 c_complex gen2c_complex(giac::gen & g){
11992 double d=1.0,e=1.0;
11993 c_complex c={0,0};
11994 if (g.type!=giac::_DOUBLE_ && g.type!=giac::_CPLX)
11995 c.r=c.i=0.0/(d-e);
11996 else {
11997 if (g.type==giac::_DOUBLE_)
11998 c.r=g._DOUBLE_val;
11999 else {
12000 if (g.subtype!=3)
12001 c.r=c.i=0.0/(d-e);
12002 c.r=g._CPLXptr->_DOUBLE_val;
12003 c.i=(g._CPLXptr+1)->_DOUBLE_val;
12004 }
12005 }
12006 return c;
12007 }
12008
12009 // x must have enough space!
matrice2c_complexptr(const giac::matrice & M,c_complex * x)12010 bool matrice2c_complexptr(const giac::matrice &M,c_complex *x){
12011 int n=M.size();
12012 if (n==0)
12013 return false;
12014 if (M.front().type!=giac::_VECT){
12015 for (int i=0;i<n;++i){
12016 giac::gen g =giac::evalf_double(M[i],1,giac::context0);
12017 if (g.type!=giac::_DOUBLE_ && g.type!=giac::_CPLX)
12018 return false;
12019 *x=gen2c_complex(g);
12020 ++x;
12021 }
12022 return true;
12023 }
12024 int m=M.front()._VECTptr->size();
12025 for (int i=0;i<n;++i){
12026 if (M[i].type!=giac::_VECT || M[i]._VECTptr->size()!=m)
12027 return false;
12028 giac::vecteur & w=*M[i]._VECTptr;
12029 for (int j=0;j<m;++j){
12030 giac::gen g =giac::evalf_double(w[j],1,giac::context0);
12031 if (g.type!=giac::_DOUBLE_ && g.type!=giac::_CPLX)
12032 return false;
12033 *x=gen2c_complex(g);
12034 ++x;
12035 }
12036 }
12037 return true;
12038 }
12039
c_inv(c_complex * x,int n)12040 bool c_inv(c_complex * x,int n){
12041 giac::matrice M(n);
12042 c_complexptr2matrice(x,n,n,M);
12043 M=giac::minv(M,giac::context0);
12044 return matrice2c_complexptr(M,x);
12045 }
12046
c_proot(c_complex * x,int n)12047 bool c_proot(c_complex * x,int n){
12048 giac::matrice M(n);
12049 c_complexptr2matrice(x,n,0,M);
12050 M=giac::proot(M);
12051 return matrice2c_complexptr(M,x);
12052 }
12053
c_pcoeff(c_complex * x,int n)12054 bool c_pcoeff(c_complex * x,int n){
12055 giac::matrice M(n);
12056 c_complexptr2matrice(x,n,0,M);
12057 M=giac::pcoeff(M);
12058 return matrice2c_complexptr(M,x);
12059 }
12060
c_fft(c_complex * x,int n,bool inverse)12061 bool c_fft(c_complex * x,int n,bool inverse){
12062 #if 1
12063 complex<double> * X=(complex<double> *) x;
12064 double theta=2*M_PI/n;
12065 if (!inverse)
12066 theta=-theta;
12067 fft2(X,n,theta);
12068 if (inverse){
12069 for (int i=0;i<n;++i)
12070 X[i]=X[i]/double(n);
12071 }
12072 return true;
12073 #else
12074 giac::matrice M(n);
12075 c_complexptr2matrice(x,n,0,M);
12076 gen g=inverse?giac::_ifft(M,giac::context0):giac::_fft(M,giac::context0);
12077 if (g.type!=_VECT)
12078 return false;
12079 return matrice2c_complexptr(*g._VECTptr,x);
12080 #endif
12081 }
12082
c_egv(c_complex * x,int n)12083 bool c_egv(c_complex * x,int n){
12084 giac::matrice M(n);
12085 c_complexptr2matrice(x,n,n,M);
12086 gen g=giac::_egv(M,giac::context0);
12087 if (!ckmatrix(g))
12088 return false;
12089 return matrice2c_complexptr(*g._VECTptr,x);
12090 }
12091
c_eig(c_complex * x,c_complex * d,int n)12092 bool c_eig(c_complex * x,c_complex * d,int n){
12093 giac::matrice M(n);
12094 c_complexptr2matrice(x,n,n,M);
12095 gen g=giac::_jordan(M,giac::context0);
12096 if (g.type!=_VECT || g._VECTptr->size()!=2 || !ckmatrix(g[0]) || !ckmatrix(g[1]))
12097 return false;
12098 return matrice2c_complexptr(*g[0]._VECTptr,x) && matrice2c_complexptr(*g[1]._VECTptr,d);
12099 }
12100
c_rref(c_complex * x,int n,int m)12101 bool c_rref(c_complex * x,int n,int m){
12102 giac::matrice M(n);
12103 c_complexptr2matrice(x,n,m,M);
12104 giac::gen g=giac::_rref(M,giac::context0);
12105 if (g.type!=giac::_VECT)
12106 return false;
12107 return matrice2c_complexptr(*g._VECTptr,x);
12108 }
12109
c_det(c_complex * x,int n)12110 c_complex c_det(c_complex *x,int n){
12111 giac::matrice M(n);
12112 c_complexptr2matrice(x,n,n,M);
12113 giac::gen g=giac::mdet(M,giac::context0);
12114 g=giac::evalf_double(g,1,giac::context0);
12115 return gen2c_complex(g);
12116 }
12117
c_sprint_double(char * s,double d)12118 void c_sprint_double(char * s,double d){
12119 giac::sprint_double(s,d);
12120 }
12121
12122 // auto-shutdown
do_shutdown()12123 int do_shutdown(){
12124 xcas::save_console_state_smem("session.xw.tns",giac::context0);
12125 #ifdef NO_STDEXCEPT
12126 return 1;
12127 #else
12128 throw autoshutdown();
12129 #endif
12130 }
12131
12132 // string translations
12133 #ifdef NUMWORKS
12134 #include "numworks_translate.h"
12135 #else
12136 #include "aspen_translate.h"
12137 #endif
tri2(const char4 & a,const char4 & b)12138 bool tri2(const char4 & a,const char4 & b){
12139 int res= strcmp(a[0],b[0]);
12140 return res<0;
12141 }
12142
giac2aspen(int lang)12143 int giac2aspen(int lang){
12144 switch (lang){
12145 case 0: case 2:
12146 return 1;
12147 case 1:
12148 return 3;
12149 case 3:
12150 return 5;
12151 case 6:
12152 return 7;
12153 case 8:
12154 return 2;
12155 case 5:
12156 return 4;
12157 }
12158 return 0;
12159 }
12160
gettext(const char * s)12161 const char * gettext(const char * s) {
12162 // 0 and 2 english 1 french 3 sp 4 el 5 de 6 it 7 tr 8 zh 9 pt
12163 int aspenlang=giac2aspen(lang);
12164 char4 s4={s};
12165 std::pair<char4 * const,char4 *const> pp=equal_range(aspen_giac_translations,aspen_giac_translations+aspen_giac_records,s4,tri2);
12166 if (pp.first!=pp.second &&
12167 pp.second!=aspen_giac_translations+aspen_giac_records &&
12168 (*pp.first)[aspenlang]){
12169 return (*pp.first)[aspenlang];
12170 }
12171 return s;
12172 }
12173
12174 #endif // KHICAS
12175