A (very) few UI improvements
[eigenmath-fx.git] / console.c
blob898ed6564cf1dffa885d0043169ae67419c9fe8a
1 #include <stdio.h>
3 #include "console.h"
4 #include "config.h"
5 #include "tex/TeX.h"
6 #include "syscalls.h"
7 #include "memory.h"
9 #define POPUP_PRETTY 1
10 #define POPUP_PRETTY_STR "Pretty print"
12 extern void run(char *s);
14 static struct line Line[LINE_MAX];
15 static char FMenu_entries_name[6*FMENU_TITLE_LENGHT+1] = {'\0'};
16 static struct location Cursor;
17 static unsigned char *Edit_Line;
18 static int Start_Line, Last_Line;
19 static int Case;
21 #define Current_Line (Start_Line + Cursor.y)
22 #define Current_Col (Line[Cursor.y + Start_Line].start_col + Cursor.x)
25 ÒÔϺ¯Êý½«ÓÃÓÚɾ³ý×Ö·û´®Ö¸¶¨Î»ÖÃ֮ǰ¹²n¸ö×Ö·û¡£ÆäÖУ¬1¸ö¿í×Ö·û£¨Õ¼2×Ö½Ú£©½«Ëã×÷1¸ö×Ö·û¡£
27 ÀýÈ磬ÎÒÃÇÓÐÈçÏÂ×Ö·û´®str£º
29 λÖà | 0 | 1 | 2 | 3 | 4 | 5 | 6 |
30 ×Ö·û |'a'|'b'|'c'|'d'|'e'|'f'| 0 |
32 Ôòµ÷ÓÃConsole_DelStr(str, 3, 2)ºó£¬Î»ÖÃ1¡¢2µÄ×Ö·û½«±»É¾³ý£¬ÆäºóµÄ×Ö·û½«±»ÌáÇ°¡£
33 ½á¹ûÈçÏ£º
35 λÖà | 0 | 1 | 2 | 3 | 4 | 5 | 6 |
36 ×Ö·û |'a'|'d'|'e'|'f'| 0 |'f'| 0 |
38 £¨×¢Ò⣺¶àÓàµÄλÖò¢²»»á±»Ìî³äΪ'\0'£¬µ«ÊÇÔ­×Ö·û´®Ä©Î²µÄ'\0'½«±»¿½±´¡££©
40 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.
42 For example, we have the following string str:
44 Location | 0 | 1 | 2 | 3 | 4 | 5 | 6 |
45 Character | 'a' | 'b' | 'c' | 'd' | 'e' | 'f' | 0 |
47 After the call Console_DelStr (str, 3, 2), position 1 and 2 characters will be deleted, then the characters will be in advance.
49 Results are as follows:
51 Location | 0 | 1 | 2 | 3 | 4 | 5 | 6 |
52 Character | 'a' | 'd' | 'e' | 'f' | 0 | 'f' | 0 |
54 (Note: the extra positions will not be filled with '\ 0', but '\ 0' will be a copy of the original end of the string.)
58 int Console_DelStr(unsigned char *str, int end_pos, int n)
60 int str_len, actual_end_pos, start_pos, actual_start_pos, del_len, i;
62 str_len = strlen((const char *)str);
63 if ((start_pos = end_pos - n) < 0) return CONSOLE_ARG_ERR;
65 if ((actual_end_pos = Console_GetActualPos(str, end_pos)) == CONSOLE_ARG_ERR) return CONSOLE_ARG_ERR;
66 if ((actual_start_pos = Console_GetActualPos(str, start_pos)) == CONSOLE_ARG_ERR) return CONSOLE_ARG_ERR;
68 del_len = actual_end_pos - actual_start_pos;
70 for (i = actual_start_pos; i < str_len; i++)
72 str[i] = str[i + del_len];
75 return CONSOLE_SUCCEEDED;
79 ÒÔϺ¯ÊýÓÃÓÚÔÚÖ¸¶¨Î»ÖòåÈëÖ¸¶¨µÄ×Ö·û´®¡£
81 £¨×¢Ò⣺ÕâÀïµÄλÖÃÖ¸µÄÊÇ´òӡʱµÄλÖ㬶ø²»ÊÇʵ¼ÊµÄλÖᣣ©
83 The following functions are used to specify the location of the insertion in the specified string.
84 (Note: This refers to the position of the printing position when, rather than the actual position.)
87 int Console_InsStr(unsigned char *dest, const unsigned char *src, int disp_pos)
89 int i, ins_len, str_len, actual_pos;
91 ins_len = strlen((const char *)src);
92 str_len = strlen((const char *)dest);
94 actual_pos = Console_GetActualPos(dest, disp_pos);
96 if (ins_len + str_len >= EDIT_LINE_MAX) return CONSOLE_MEM_ERR;
97 if (actual_pos > str_len) return CONSOLE_ARG_ERR;
99 for (i = str_len; i >= actual_pos; i--)
101 dest[i + ins_len] = dest[i];
104 for (i = 0; i < ins_len; i++)
106 dest[actual_pos + i] = src[i];
109 return CONSOLE_SUCCEEDED;
113 ÒÔϺ¯ÊýÓÃÓÚÈ·¶¨¶ÔÓ¦ÓÚ×Ö·û´®´òӡλÖõÄÕæʵλÖá£
115 ÀýÈ磬ÔÚÒÔÏÂÕâÒ»°üº¬¿í×Ö·ûµÄ×Ö·û´®strÖУ¬´òӡʱµÄλÖÃÈçÏ£º
117 λÖà | 00 | 01 | 02 | 03 | 04 | 05 | 06 |
118 ×Ö·û | Ò» | ¶þ | Èý | ËÄ | Îå | Áù | \0 |
120 ¶øÔÚʵ¼Ê´æ´¢Ê±µÄλÖÃÈçÏ£º
122 λÖà | 00 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 |
123 Öµ | 0xD2 | 0xBB | 0xB6 | 0xFE | 0xC8 | 0xFD | 0xCB | 0xC4 | 0xCE | 0xE5 | 0xC1 | 0xF9 |
125 ¿ÉÒÔ·¢ÏÖ£¬µÚ4¸ö×Ö·û¡®Î塯ʵ¼ÊÉÏ´æ´¢ÓÚµÚ8µÄλÖá£
126 Òò´Ë£¬µ±µ÷ÓÃConsole_GetActualPos(str, 4)ʱ£¬½«·µ»Ø8¡£
129 The following function is used to determine the true position of the string corresponding to the printing position.
130 For example, in the following this string str contains wide characters, the location of the print is as follows:
132 Location | 00 | 01 | 02 | 03 | 04 | 05 | 06 |
133 Character | one | two | three | four | five | six | \ 0 |
135 The actual storage location is as follows:
137 Location | 00 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 |
138 Value | 0xD2 | 0xBB | 0xB6 | 0xFE | 0xC8 | 0xFD | 0xCB | 0xC4 | 0xCE | 0xE5 | 0xC1 | 0xF9 |
140 You can find the first four characters 'five' is actually stored in the eighth position.
141 So, when you call Console_GetActualPos (str, 4), it will return 8.
144 int Console_GetActualPos(const unsigned char *str, int disp_pos)
146 int actual_pos, count;
148 for (actual_pos = count = 0; count < disp_pos; count++)
150 if (str[actual_pos] == '\0') return CONSOLE_ARG_ERR;
152 if (is_wchar(str[actual_pos]))
154 actual_pos += 2;
156 else
158 actual_pos++;
162 return actual_pos;
166 ÒÔϺ¯ÊýÓÃÓÚ»ñÈ¡×Ö·û´®µÄ´òÓ¡³¤¶È£¬¼´£¬1¸ö¿í×Ö·û£¨Õ¼ÓÃ2×Ö½Ú£©¼Ç×÷1×Ö·û¡£
167 The following functions are used to obtain a string of print length, ie, a wide character (2 bytes) recorded as a character.
170 int Console_GetDispLen(const unsigned char *str)
172 int i, len;
174 for (i = len = 0; str[i]!='\0'; len++)
176 if (is_wchar(str[i]))
178 i += 2;
180 else
182 i++;
186 return len;
190 ÒÔϺ¯ÊýÓÃÓÚÒƶ¯¹â±ê¡£
191 The following functions are used to move the cursor.
194 int Console_MoveCursor(int direction)
196 switch (direction)
198 case CURSOR_UP:
199 //Èç¹ûÐèÒª²Ù×÷¡£
200 //If you need to operate.
201 if ((Cursor.y > 0) || (Start_Line > 0))
203 //Èç¹ûµ±Ç°Ðв»ÊÇÖ»¶ÁµÄ,Ôò½«Edit_Line¿½±´¸øµ±Ç°ÐС£
204 //If the current line is not read-only, then Edit_Line copy to the current line.
205 if (!Line[Current_Line].readonly)
207 if ((Line[Current_Line].str = (unsigned char *)malloc(strlen((const char *)Edit_Line) + 1)) == NULL) return CONSOLE_MEM_ERR;
208 strcpy((char *)Line[Current_Line].str, (const char *)Edit_Line);
209 Line[Current_Line].disp_len = Console_GetDispLen(Line[Current_Line].str);
210 Line[Current_Line].type = LINE_TYPE_INPUT;
213 //Èç¹û¹â±êδÒƵ½×îÉÏ·½,ÔòÖ±½Ó½«¹â±êÏòÉÏÒÆ¡£
214 //If the cursor does not move to the top of, directly move the cursor upward.
215 if (Cursor.y > 0)
217 Cursor.y--;
219 //·ñÔò£¬Èç¹ûÆÁÄ»ÉÏÊ×Ðв»ÊǵÚÒ»ÐУ¬Ôò½«¿ªÊ¼ÏÔʾµÄÐÐÊý¼õÒ»¡£
220 //Otherwise, the number of rows, if the screen's first line is not the first line, then began to show minus one.
221 else if (Start_Line > 0)
223 Start_Line--;
226 //Èç¹ûÒƶ¯ºó¹â±êˮƽλÖó¬¹ýÐÐÄ©£¬Ôò½«¹â±êÒÆÖÁÐÐÄ©¡£
227 //End if the horizontal position after moving the cursor over the line, then move the cursor to the end of the line.
228 if (Cursor.x > Line[Current_Line].disp_len)
230 Cursor.x = Line[Current_Line].disp_len;
232 else if (Line[Current_Line].disp_len - Line[Current_Line].start_col > COL_DISP_MAX)
234 if (Cursor.x == COL_DISP_MAX) Cursor.x = COL_DISP_MAX - 1;
237 //Èç¹ûÒƶ¯ºó¹â±êÔÚÐÐÊ×£¬ÇÒ¸ÃÐÐÇ°ÃæÓÐ×Ö·ûδÏÔʾ£¬Ôò½«¹â±êÒÆÖÁλÖÃ1¡£
238 //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.
239 if (Cursor.x == 0 && Line[Current_Line].start_col > 0) Cursor.x = 1;
241 //Èç¹ûÏÖÔÚ¹â±êËùÔÚÐв»ÊÇÖ»¶ÁµÄ£¬Ôò½«Æä×Ö·û´®¿½±´¸øEdit_LineÒÔ¹©±à¼­¡£
242 //If the current cursor line is not read-only, then it is a string copy to Edit_Line for editing.
243 if (!Line[Current_Line].readonly)
245 strcpy((char *)Edit_Line, (const char *)Line[Current_Line].str);
246 free(Line[Current_Line].str);
247 Line[Current_Line].str = Edit_Line;
250 break;
251 case CURSOR_DOWN:
252 //Èç¹ûÐèÒª²Ù×÷¡£
253 //If you need to operate.
254 if ((Cursor.y < LINE_DISP_MAX - 1) && (Current_Line < Last_Line) || (Start_Line + LINE_DISP_MAX - 1 < Last_Line))
256 //Èç¹ûµ±Ç°Ðв»ÊÇÖ»¶ÁµÄ,Ôò½«Edit_Line¿½±´¸øµ±Ç°ÐС£
257 //If the current line is not read-only, then Edit_Line copy to the current line.
258 if (!Line[Current_Line].readonly)
260 if ((Line[Current_Line].str = (unsigned char *)malloc(strlen((const char *)Edit_Line) + 1)) == NULL) return CONSOLE_MEM_ERR;
261 strcpy((char *)Line[Current_Line].str, (const char *)Edit_Line);
262 Line[Current_Line].disp_len = Console_GetDispLen(Line[Current_Line].str);
263 Line[Current_Line].type = LINE_TYPE_INPUT;
266 //Èç¹û¹â±êδÒƵ½×îÏ·½,ÔòÖ±½Ó½«¹â±êÏòÏÂÒÆ¡£
267 //If the cursor does not move to the bottom, the cursor moves down directly.
268 if (Cursor.y < LINE_DISP_MAX - 1 && Current_Line < Last_Line)
270 Cursor.y++;
272 //·ñÔò£¬Èç¹ûÆÁÄ»ÉÏÄ©Ðв»ÊÇ×îºóÒ»ÐУ¬Ôò½«¿ªÊ¼ÏÔʾµÄÐÐÊý¼ÓÒ»¡£
273 //The number of rows Otherwise, if the last line is not the last line on the screen, it will begin to show a plus.
274 else if (Start_Line + LINE_DISP_MAX - 1 < Last_Line)
276 Start_Line++;
279 //Èç¹ûÒƶ¯ºó¹â±êˮƽλÖó¬¹ýÐÐÄ©£¬Ôò½«¹â±êÒÆÖÁÐÐÄ©¡£
280 //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.
281 if (Cursor.x > Line[Current_Line].disp_len)
283 Cursor.x = Line[Current_Line].disp_len;
285 else if (Line[Current_Line].disp_len - Line[Current_Line].start_col >= COL_DISP_MAX)
287 if (Cursor.x == COL_DISP_MAX) Cursor.x = COL_DISP_MAX - 1;
290 //Èç¹ûÒƶ¯ºó¹â±êÔÚÐÐÊ×£¬ÇÒ¸ÃÐÐÇ°ÃæÓÐ×Ö·ûδÏÔʾ£¬Ôò½«¹â±êÒÆÖÁλÖÃ1¡£
291 //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.
292 if (Cursor.x == 0 && Line[Current_Line].start_col > 0) Cursor.x = 1;
294 //Èç¹ûÏÖÔÚ¹â±êËùÔÚÐв»ÊÇÖ»¶ÁµÄ£¬Ôò½«Æä×Ö·û´®¿½±´¸øEdit_LineÒÔ¹©±à¼­¡£
295 //If the current cursor line is not read-only, then it is a string copy to Edit_Line for editing.
296 if (!Line[Current_Line].readonly)
298 strcpy((char *)Edit_Line, (const char *)Line[Current_Line].str);
299 free(Line[Current_Line].str);
300 Line[Current_Line].str = Edit_Line;
303 break;
304 case CURSOR_LEFT:
305 if (Line[Current_Line].readonly)
307 if (Line[Current_Line].start_col > 0) Line[Current_Line].start_col--;
309 else if (Line[Current_Line].start_col > 0)
311 if (Cursor.x > 1)
313 Cursor.x--;
315 else
317 Line[Current_Line].start_col--;
320 else if (Cursor.x > 0) Cursor.x--;
321 break;
322 case CURSOR_RIGHT:
323 if (Line[Current_Line].readonly)
325 if (Line[Current_Line].disp_len - Line[Current_Line].start_col > COL_DISP_MAX) Line[Current_Line].start_col++;
327 else if (Line[Current_Line].disp_len - Line[Current_Line].start_col > COL_DISP_MAX)
329 if (Cursor.x < COL_DISP_MAX - 1)
331 Cursor.x++;
333 else
335 Line[Current_Line].start_col++;
338 else if (Cursor.x < Line[Current_Line].disp_len - Line[Current_Line].start_col) Cursor.x++;
339 break;
340 default:
341 return CONSOLE_ARG_ERR;
342 break;
344 return CONSOLE_SUCCEEDED;
348 ÒÔϺ¯ÊýÓÃÓÚÊäÈë¡£
349 ×Ö·û´®½«ÊäÈëµ½¹â±ê´¦£¬¹â±ê½«×Ô¶¯Òƶ¯¡£
351 The following function is used for input.
352 String input to the cursor, the cursor will automatically move.
355 int Console_Input(const unsigned char *str)
357 int old_len,i,return_val;
359 if (!Line[Current_Line].readonly)
361 old_len = Line[Current_Line].disp_len;
362 return_val = Console_InsStr(Edit_Line, str, Current_Col);
363 if (return_val != CONSOLE_SUCCEEDED) return return_val;
364 if ((Line[Current_Line].disp_len = Console_GetDispLen(Edit_Line)) == CONSOLE_ARG_ERR) return CONSOLE_ARG_ERR;
365 for (i = 0; i < Line[Current_Line].disp_len - old_len; i++)
367 Console_MoveCursor(CURSOR_RIGHT);
369 return CONSOLE_SUCCEEDED;
371 else
373 return CONSOLE_ARG_ERR;
378 ÒÔϺ¯ÊýÓÃÓÚÊä³ö×Ö·û´®µ½µ±Ç°ÐС£
379 The following functions are used to output the string to the current line.
382 int Console_Output(const unsigned char *str)
384 int return_val, old_len, i;
386 if (!Line[Current_Line].readonly)
388 old_len = Line[Current_Line].disp_len;
390 return_val = Console_InsStr(Edit_Line, str, Current_Col);
391 if (return_val != CONSOLE_SUCCEEDED) return return_val;
392 if ((Line[Current_Line].disp_len = Console_GetDispLen(Edit_Line)) == CONSOLE_ARG_ERR) return CONSOLE_ARG_ERR;
393 Line[Current_Line].type = LINE_TYPE_OUTPUT;
395 for (i = 0; i < Line[Current_Line].disp_len - old_len; i++)
397 Console_MoveCursor(CURSOR_RIGHT);
399 return CONSOLE_SUCCEEDED;
401 else
403 return CONSOLE_ARG_ERR;
408 Clear the current output line
411 int Console_Clear_EditLine()
413 if(!Line[Current_Line].readonly) {
414 Edit_Line[0] = '\0';
415 Line[Current_Line].start_col = 0;
416 Line[Current_Line].disp_len = 0;
417 Cursor.x = 0;
422 ÒÔϺ¯ÊýÓÃÓÚ´´½¨ÐÂÐС£
423 ²ÎÊýpre_line_typeÓÃÓÚÖ¸¶¨ÉÏÒ»ÐеÄÀàÐÍ£¬²ÎÊýpre_line_readonlyÓÃÓÚÖ¸¶¨ÉÏÒ»ÐÐÊÇ·ñÖ»¶Á¡£
424 ²ÎÊýnew_line_typeÓÃÓÚÖ¸¶¨ÏÂÒ»ÐеÄÀàÐÍ£¬²ÎÊýnew_line_readonlyÓÃÓÚÖ¸¶¨ÏÂÒ»ÐÐÊÇ·ñÖ»¶Á¡£
426 The following functions are used to create a new line.
427 Pre_line_type type parameter is used to specify the line, pre_line_readonly parameter is used to specify the line is read-only.
428 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.
431 int Console_NewLine(int pre_line_type, int pre_line_readonly)
433 int i;
435 if (strlen((const char *)Edit_Line)||Line[Current_Line].type==LINE_TYPE_OUTPUT)
437 //Èç¹ûÒѾ­ÊÇËùÄÜ´æ´¢µÄ×îºóÒ»ÐУ¬Ôòɾ³ýµÚÒ»ÐС£
438 //If this is the last line we can store, delete the first line.
439 if (Last_Line == LINE_MAX - 1)
441 for (i = 0; i < Last_Line; i++)
443 Line[i].disp_len = Line[i + 1].disp_len;
444 Line[i].readonly = Line[i + 1].readonly;
445 Line[i].start_col = Line[i + 1].start_col;
446 Line[i].str = Line[i + 1].str;
447 Line[i].type = Line[i + 1].type;
449 Last_Line--;
451 if (Start_Line > 0) Start_Line--;
454 if (Line[Last_Line].type == LINE_TYPE_OUTPUT && strlen((const char *)Edit_Line) == 0) Console_Output((const unsigned char *)"Done");
456 if (TeX_isTeX((char*)Edit_Line)) Line[Last_Line].tex_flag = 1;
457 if (Line[Last_Line].type == LINE_TYPE_OUTPUT && Line[Last_Line].tex_flag) TeX_sizeComplex ((char*)Edit_Line, &(Line[Last_Line].tex_width), &(Line[Last_Line].tex_height), NULL);
458 else Line[Last_Line].tex_flag = 0;
460 //½«Edit_LineµÄÄÚÈÝ¿½±´¸ø×îºóÒ»ÐС£
461 //Edit_Line copy the contents to the last line.
463 #ifdef POPUP_PRETTY
464 if(Line[Last_Line].tex_flag) {
465 if ((Line[Last_Line].str = (unsigned char *)malloc(strlen(POPUP_PRETTY_STR) + 1)) == NULL) return CONSOLE_MEM_ERR;
466 strcpy((char*)Line[Last_Line].str, (const char*)POPUP_PRETTY_STR);
467 if ((Line[Last_Line].tex_str = (unsigned char *)malloc(strlen((const char *)Edit_Line) + 1)) == NULL) return CONSOLE_MEM_ERR;
468 strcpy((char *)Line[Last_Line].tex_str, (const char *)Edit_Line);
470 else {
471 if ((Line[Last_Line].str = (unsigned char *)malloc(strlen((const char *)Edit_Line) + 1)) == NULL) return CONSOLE_MEM_ERR;
472 strcpy((char *)Line[Last_Line].str, (const char *)Edit_Line);
474 #else
475 if ((Line[Last_Line].str = (unsigned char *)malloc(strlen((const char *)Edit_Line) + 1)) == NULL) return CONSOLE_MEM_ERR;
476 strcpy((char *)Line[Last_Line].str, (const char *)Edit_Line);
477 #endif
479 if ((Line[Last_Line].disp_len = Console_GetDispLen(Line[Last_Line].str)) == CONSOLE_ARG_ERR) return CONSOLE_ARG_ERR;
480 Line[Last_Line].type = pre_line_type;
481 Line[Last_Line].readonly = pre_line_readonly;
482 Line[Last_Line].start_col = 0;
484 Edit_Line[0] = '\0';
486 Last_Line++;
488 Cursor.x = 0;
490 if ((Last_Line - Start_Line) == LINE_DISP_MAX)
492 Start_Line++;
494 else
496 Cursor.y++;
499 Line[Last_Line].str = Edit_Line;
500 Line[Last_Line].readonly = 0;
501 Line[Last_Line].type = LINE_TYPE_INPUT;
502 Line[Last_Line].start_col = 0;
503 Line[Last_Line].disp_len = 0;
505 return CONSOLE_NEW_LINE_SET;
507 else
509 return CONSOLE_NO_EVENT;
514 ÒÔϺ¯ÊýÓÃÓÚɾ³ý¹â±êÇ°µÄÒ»¸ö×Ö·û¡£
515 The following function is used to delete a character before the cursor.
518 int Console_Backspace()
520 int return_val;
522 return_val = Console_DelStr(Edit_Line, Current_Col, 1);
523 if (return_val != CONSOLE_SUCCEEDED) return return_val;
524 Line[Current_Line].disp_len = Console_GetDispLen(Edit_Line);
525 return Console_MoveCursor(CURSOR_LEFT);
529 ÒÔϺ¯ÊýÓÃÓÚ´¦Àí°´¼ü¡£
530 The following functions are used to deal with the key.
533 int Console_GetKey()
535 unsigned int key, i, move_line, move_col;
536 unsigned char tmp_str[2];
537 unsigned char *tmp;
539 GetKey(&key);
541 if (key >= '0' && key <= '9')
543 tmp_str[0] = key;
544 tmp_str[1] = '\0';
545 return Console_Input(tmp_str);
548 if (key >= KEY_CTRL_F1 &&
549 key <= KEY_CTRL_F6) return Console_FMenu(key);
550 if (key == KEY_CHAR_IMGNRY) return Console_Input((const unsigned char *)"i");
551 if (key == KEY_CHAR_MAT) return Console_Input((const unsigned char *)"matrix");
552 if (key == KEY_CHAR_DP) return Console_Input((const unsigned char *)".");
553 if (key == KEY_CHAR_EQUAL) return Console_Input((const unsigned char *)"=");
554 if (key == KEY_CHAR_EXP) return Console_Input((const unsigned char *)"*10^(");
555 if (key == KEY_CHAR_DQUATE) return Console_Input((const unsigned char *)"\"");
556 if (key == KEY_CHAR_SPACE) return Console_Input((const unsigned char *)" ");
557 if (key == KEY_CHAR_PI) return Console_Input((const unsigned char *)"pi");
558 if (key == KEY_CHAR_PMINUS) return Console_Input((const unsigned char *)"-");
559 if (key == KEY_CHAR_MINUS) return Console_Input((const unsigned char *)"-");
560 if (key == KEY_CHAR_ANS) return Console_Input((const unsigned char *)"last");
561 if (key == KEY_CHAR_PLUS) return Console_Input((const unsigned char *)"+");
562 if (key == KEY_CHAR_LBRCKT) return Console_Input((const unsigned char *)"[");
563 if (key == KEY_CHAR_RBRCKT) return Console_Input((const unsigned char *)"]");
564 if (key == KEY_CHAR_MULT) return Console_Input((const unsigned char *)"*");
565 if (key == KEY_CHAR_LBRACE) return Console_Input((const unsigned char *)"{");
566 if (key == KEY_CHAR_DIV) return Console_Input((const unsigned char *)"/");
567 if (key == KEY_CHAR_RBRACE) return Console_Input((const unsigned char *)"}");
568 if (key == KEY_CHAR_FRAC) return Console_Input((const unsigned char *)"/");
569 if (key == KEY_CTRL_MIXEDFRAC) return Console_Input((const unsigned char *)"simplify(");
570 if (key == KEY_CTRL_FD) return Console_Input((const unsigned char *)"float");
571 if (key == KEY_CTRL_FRACCNVRT) return Console_Input((const unsigned char *)"factor(");
572 if (key == KEY_CHAR_LPAR) return Console_Input((const unsigned char *)"(");
573 if (key == KEY_CHAR_RPAR) return Console_Input((const unsigned char *)")");
574 if (key == KEY_CHAR_CUBEROOT) return Console_Input((const unsigned char *)"^(1/3)");
575 if (key == KEY_CHAR_RECIP) return Console_Input((const unsigned char *)"^(-1)");
576 if (key == KEY_CHAR_COMMA) return Console_Input((const unsigned char *)",");
577 if (key == KEY_CHAR_STORE) return Console_Input((const unsigned char *)"!");
578 if (key == KEY_CTRL_XTT) return Console_Input((const unsigned char *)"x");
579 if (key == KEY_CHAR_LOG) return Console_Input((const unsigned char *)"log(");
580 if (key == KEY_CHAR_EXPN10) return Console_Input((const unsigned char *)"10^(");
581 if (key == KEY_CHAR_LN) return Console_Input((const unsigned char *)"ln(");
582 if (key == KEY_CHAR_EXPN) return Console_Input((const unsigned char *)"e^(");
583 if (key == KEY_CHAR_SIN) return Console_Input((const unsigned char *)"sin(");
584 if (key == KEY_CHAR_ASIN) return Console_Input((const unsigned char *)"arcsin(");
585 if (key == KEY_CHAR_COS) return Console_Input((const unsigned char *)"cos(");
586 if (key == KEY_CHAR_ACOS) return Console_Input((const unsigned char *)"arccos(");
587 if (key == KEY_CHAR_TAN) return Console_Input((const unsigned char *)"tan(");
588 if (key == KEY_CHAR_ATAN) return Console_Input((const unsigned char *)"arctan(");
589 if (key == KEY_CHAR_SQUARE) return Console_Input((const unsigned char *)"^2");
590 if (key == KEY_CHAR_ROOT) return Console_Input((const unsigned char *)"sqrt(");
591 if (key == KEY_CHAR_VALR) return Console_Input((const unsigned char *)"r");
592 if (key == KEY_CHAR_POW) return Console_Input((const unsigned char *)"^");
593 if (key == KEY_CHAR_POWROOT) return Console_Input((const unsigned char *)"^(1/");
594 if (key == KEY_CHAR_THETA) return Console_Input((const unsigned char *)"theta");
596 if ((key >= 'A') && (key <= 'Z'))
598 if (Case == LOWER_CASE) key += 'a' - 'A';
599 tmp_str[0] = key;
600 tmp_str[1] = 0;
601 return Console_Input(tmp_str);
604 if (key == KEY_CTRL_UP) return Console_MoveCursor(CURSOR_UP);
605 if (key == KEY_CTRL_DOWN) return Console_MoveCursor(CURSOR_DOWN);
606 if (key == KEY_CTRL_LEFT) return Console_MoveCursor(CURSOR_LEFT);
607 if (key == KEY_CTRL_RIGHT) return Console_MoveCursor(CURSOR_RIGHT);
609 if (key == KEY_CTRL_AC)
611 if (Line[Current_Line].readonly) return CONSOLE_NO_EVENT;
612 Edit_Line[0] = '\0';
613 Line[Current_Line].start_col = 0;
614 Line[Current_Line].type = LINE_TYPE_INPUT;
615 Line[Current_Line].disp_len = 0;
616 Cursor.x = 0;
617 return CONSOLE_SUCCEEDED;
620 /*if (key == KEY_CTRL_INS) {
621 if (!Line[Current_Line].readonly) {
622 Edit_Line[0] = '\0';
623 Line[Current_Line].start_col = 0;
624 Line[Current_Line].type = LINE_TYPE_INPUT;
625 Line[Current_Line].disp_len = 0;
626 Cursor.x = 0;
628 return Console_Init();
631 if (key == KEY_CTRL_SETUP) {
632 menu_setup();
635 if (key == KEY_CTRL_EXE)
637 #ifdef POPUP_PRETTY
638 if(Line[Current_Line].tex_flag) Console_Draw_TeX_Popup(Line[Current_Line].tex_str, Line[Current_Line].tex_width, Line[Current_Line].tex_height);
639 else {
640 #endif
641 if (Current_Line == Last_Line)
643 return Console_NewLine(LINE_TYPE_INPUT, 1);
645 else
647 return CONSOLE_ARG_ERR;
649 #ifdef POPUP_PRETTY
651 #endif
654 if (key == KEY_CTRL_DEL) return Console_Backspace();
656 if (key == KEY_CTRL_CLIP)
658 #ifdef POPUP_PRETTY
659 if(Line[Current_Line].tex_flag) Console_Draw_TeX_Popup(Line[Current_Line].tex_str, Line[Current_Line].tex_width, Line[Current_Line].tex_height);
660 else {
661 #endif
662 tmp = Line[Current_Line].str;
664 move_line = Last_Line - Current_Line;
665 for (i = 0; i <= move_line; i++) Console_MoveCursor(CURSOR_DOWN);
667 move_col = Line[Current_Line].disp_len - Current_Col;
668 for (i = 0; i <= move_col; i++) Console_MoveCursor(CURSOR_RIGHT);
670 Console_Input(tmp);
671 #ifdef POPUP_PRETTY
673 #endif
676 return CONSOLE_NO_EVENT;
679 int Console_FMenu(int key)
681 int i, handle, ret, matched = 0, number=0;
682 unsigned int error_key;
683 struct FMenu entry = {0};
684 char* tmp_realloc = NULL;
685 char temp[30] = {'\0'};
686 char* original_cfg;
687 char* cfg = memory_load("\\\\fls0\\FMENU.cfg");
689 original_cfg = cfg;
691 while(*cfg) {
692 //Get each line
693 for(i=0; i<20, *cfg && *cfg!='\r' && *cfg!='\n'; i++, cfg++) {
694 temp[i] = *cfg;
697 //If starting by 'F' followed by the right number, start filling the structure.
698 if(temp[0] == 'F' && temp[1]==(key-KEY_CTRL_F1)+'1') matched = 1;
699 else if(temp[0] == 'F' && temp[1]!=(key-KEY_CTRL_F1)+'0') matched = 0;
701 //Fill the structure
702 else if(matched && temp[0] && entry.count < MAX_FMENU_ITEMS) {
703 //Alloc a new string a copy current data into it
704 tmp_realloc=(char*)entry.str;
705 entry.str = realloc(tmp_realloc, sizeof(unsigned char*)*(entry.count+1));
707 if(entry.str != NULL) {
708 entry.str[entry.count] = (char*)malloc(strlen(temp)+1);
710 if(entry.str[entry.count] == NULL) {
711 PrintMini(10,40, (unsigned char*)"Error realloc bis -> Console_FMenu()", MINI_OVER);
712 GetKey(&error_key);
713 entry.str = (char*)realloc(entry.str, entry.count); //May never fail.
714 entry.count--;
717 else strcpy(entry.str[entry.count], temp);
719 entry.count++;
721 else {
722 PrintMini(50,40, (unsigned char*)"Error realloc -> Console_FMenu()", MINI_OVER);
723 GetKey(&error_key);
724 entry.str = tmp_realloc;
727 memset(temp, '\0', 30);
728 cfg++;
731 free(original_cfg);
733 if(entry.count > 0) {
734 ret = Console_Draw_FMenu(key, &entry);
735 for(i=0; i < entry.count; i++) {
736 free(entry.str[i]);
738 free(entry.str);
739 free(entry.name);
742 else return 0;
745 char *Console_Make_Entry(const unsigned char* str)
747 char* entry = NULL;
748 entry = (char*)calloc((strlen(str)+1), sizeof(unsigned char*));
749 if(entry) memcpy(entry, str, strlen(str)+1);
751 return entry;
754 //Draws and runs the asked for menu.
755 int Console_Draw_FMenu(int key, struct FMenu* menu)
757 int i, nb_entries = 0, selector = 0, position_number, position_x, ret, longest = 0;
758 unsigned int input_key;
759 char quick[] = "*: ";
760 int quick_len = 2;
761 char **entries;
762 DISPBOX box;
764 position_number = key - KEY_CTRL_F1;
766 entries = menu->str;
767 nb_entries = menu->count;
769 for(i=0; i<nb_entries; i++)
770 if(strlen(entries[i]) > longest) longest = strlen(entries[i]);
772 position_x = 21*position_number;
773 if(position_x + longest*4 + quick_len*4 > 115) position_x = 115 - longest*4 - quick_len*4;
775 box.left = position_x;
776 box.right = position_x + longest*4 + quick_len*4 + 6;
777 box.bottom = 63-9;
778 box.top = 63-9-nb_entries*7;
780 Bdisp_AreaClr_VRAM(&box);
782 Bdisp_DrawLineVRAM(box.left, box.bottom, box.left, box.top);
783 Bdisp_DrawLineVRAM(box.right, box.bottom, box.right, box.top);
785 //If the cursor is flashing on the opening box, disable it.
786 if(((Cursor.x*(128/21)<box.right && Cursor.x*(128/21)>box.left))
787 && ((Cursor.y*(64/8)<box.bottom) && (Cursor.y*(64/8)>box.top))) Cursor_SetFlashOff();
789 while(input_key != KEY_CTRL_EXE || input_key != KEY_CTRL_EXIT) {
790 for(i=0; i<nb_entries; i++) {
791 quick[0] = '0'+(i+1);
792 PrintMini(3+position_x, box.bottom-7*(i+1), (unsigned char*)quick, MINI_OVER);
793 PrintMini(3+position_x+quick_len*4, box.bottom-7*(i+1), (unsigned char*)entries[i], MINI_OVER);
795 PrintMini(3+position_x+quick_len*4,box.bottom-7*(selector+1), (unsigned char*)entries[selector], MINI_REV);
796 GetKey(&input_key);
798 if (input_key == KEY_CTRL_UP && selector < nb_entries-1) selector++;
799 if (input_key == KEY_CTRL_DOWN && selector > 0) selector--;
801 if (input_key == KEY_CTRL_EXE) return Console_Input((unsigned char *)entries[selector]);
803 if (input_key >= KEY_CHAR_1 && input_key < KEY_CHAR_1 + nb_entries) return Console_Input((unsigned char*)entries[input_key-KEY_CHAR_1]);
805 if (input_key == KEY_CTRL_EXIT) return Console_Input((const unsigned char *)"");
807 if (input_key >= KEY_CTRL_F1 && input_key <= KEY_CTRL_F6) {
808 Console_Input((const unsigned char *)"");
809 Console_Disp();
810 return Console_FMenu(input_key);
816 ÒÔϺ¯ÊýÓÃÓÚ³õʼ»¯¡£
819 int Console_Init()
821 int i;
823 Start_Line = 0;
824 Last_Line = 0;
826 for (i = 0; i < LINE_MAX; i++)
828 if(Line[i].str) free(Line[i].str);
829 Line[i].readonly = 0;
830 Line[i].type = LINE_TYPE_INPUT;
831 Line[i].start_col = 0;
832 Line[i].disp_len = 0;
835 if ((Edit_Line = (unsigned char *)malloc(EDIT_LINE_MAX + 1)) == NULL) return CONSOLE_MEM_ERR;
836 Line[0].str = Edit_Line;
838 Cursor.x = 0;
839 Cursor.y = 0;
841 Case = LOWER_CASE;
843 /*for(i = 0; i < 6; i++) {
844 FMenu_entries[i].name = NULL;
845 FMenu_entries[i].count = 0;
848 Console_FMenu_Init();
850 return CONSOLE_SUCCEEDED;
853 // Loads the FMenus' data into memory, from a cfg file
854 void Console_FMenu_Init()
856 int i, number=0, key, handle;
857 unsigned char* tmp_realloc = NULL;
858 unsigned char temp[20] = {'\0'};
859 unsigned char* original_cfg;
860 unsigned char* cfg = memory_load("\\\\fls0\\FMENU.cfg");
863 // Does the file exists ?
864 // Todo : check the error codes...
865 if(!cfg) {
866 unsigned char conf_standard[] = {"F1 calc\nd(\nintegral(\ntaylor(\nsum(\nproduct(\nsimplify(\nfactor(\nF2 trig\ncosh(\narccosh(\nsinh(\narcsinh(\ntanh(\narctanh(\nF3 cplx\nmag(\narg(\nreal(\nimag(\nconj(\npolar(\nrect(\nF4 alge\nabs(\ndet(\nadj(\ncross(\ncurl(\ncontract(\nhilbert(\nF5 poly\nnroots(\ndeg(\ncoeff(\nquotient(\nhermite(\nlaguerre(\nlegendre(\nF6 arit\nmod(\ngcd(\nlcd(\nisprime(\nprime(\nfactor(\n"};
867 memory_createfile("\\\\fls0\\FMENU.cfg", strlen((char*)conf_standard)+1);
868 handle = memory_openfile("\\\\fls0\\FMENU.cfg", _OPENMODE_READWRITE);
869 memory_writefile(handle, conf_standard, strlen((char*)conf_standard)+1);
870 memory_closefile(handle);
872 cfg = memory_load("\\\\fls0\\FMENU.cfg");
875 original_cfg = cfg;
877 while(*cfg) {
878 //Get each line
879 for(i=0; i<20, *cfg && *cfg!='\r' && *cfg!='\n'; i++, cfg++) {
880 temp[i] = *cfg;
883 //If starting by 'F', adjust the number and eventually set the name of the menu
884 if(temp[0] == 'F' && temp[1]>='1' && temp[1]<='6') {
885 number = temp[1]-'0' - 1;
886 if(temp[3]) {
887 strncpy((char*)FMenu_entries_name+(number*FMENU_TITLE_LENGHT), (char*)temp+3, FMENU_TITLE_LENGHT);
888 //FMenu_entries[number].name[4] = '\0';
892 memset(temp, '\0', 20);
893 cfg++;
895 FMenu_entries_name[6*FMENU_TITLE_LENGHT] = '\0';
896 free(original_cfg);
900 ÒÔϺ¯ÊýÓÃÓÚÏÔʾËùÓÐÐС£
901 ×¢Ò⣺µ÷Óøú¯Êýºó£¬½«Ê×ÏÈÇå¿ÕÏÔ´æ¡£
902 The following functions are used to display all lines.
903 Note: After calling this function, the first clear the memory.
906 int Console_Disp()
908 unsigned int* pBitmap;
909 char temp_fkey[FMENU_TITLE_LENGHT] = {'\0'};
910 int i, alpha_shift_status;
911 DISPBOX ficon;
912 int print_y = 0; //pixel y cursor
913 int print_y_locate;
915 Bdisp_AllClr_VRAM();
917 //GetFKeyIconPointer( 0x01BE, &ficon );
918 //DisplayFKeyIcon( i, ficon);
920 //Reading each "line" that will be printed
921 for (i = 0; (i < LINE_DISP_MAX) && (i + Start_Line <= Last_Line); i++)
923 if (i == Cursor.y)
925 if (Line[i + Start_Line].type == LINE_TYPE_INPUT || Line[i + Start_Line].type == LINE_TYPE_OUTPUT && Line[i + Start_Line].disp_len >= COL_DISP_MAX)
927 locate(1, i + 1);
929 if (Line[i + Start_Line].readonly)
931 Cursor_SetFlashMode(0);
932 PrintRev(Line[i + Start_Line].str + Line[i + Start_Line].start_col);
934 else
936 if(Cursor.x > COL_DISP_MAX-1) {
937 Print(Line[i + Start_Line].str + Line[i + Start_Line].start_col + 1);
939 else {
940 Print(Line[i + Start_Line].str + Line[i + Start_Line].start_col);
944 else
946 locate(COL_DISP_MAX - Line[i + Start_Line].disp_len + 1, i + 1);
948 if (Line[i + Start_Line].readonly)
950 Cursor_SetFlashMode(0);
951 if(Line[i+Start_Line].tex_flag) {
952 locate(COL_DISP_MAX - strlen(POPUP_PRETTY_STR) + 1,i+1);
953 PrintRev((unsigned char*)POPUP_PRETTY_STR);
955 else {
956 PrintRev(Line[i + Start_Line].str);
959 else
961 Print(Line[i + Start_Line].str);
965 if (Line[i + Start_Line].start_col > 0)
967 locate(1, i + 1);
969 if (Line[i + Start_Line].readonly)
971 Cursor_SetFlashMode(0);
972 PrintRev((unsigned char *)"\xE6\x9A");
974 else
976 Print((unsigned char *)"\xE6\x9A");
980 if (Line[i + Start_Line].disp_len - Line[i + Start_Line].start_col > COL_DISP_MAX-1)
982 locate(COL_DISP_MAX, i + 1);
983 if (Line[i + Start_Line].readonly)
985 if(Line[i + Start_Line].disp_len - Line[i + Start_Line].start_col != COL_DISP_MAX) {
986 Cursor_SetFlashMode(0);
987 PrintRev((unsigned char *)"\xE6\x9B");
990 else if(Cursor.x < COL_DISP_MAX-1)
992 Print((unsigned char *)"\xE6\x9B");
996 if (!Line[i + Start_Line].readonly)
998 switch(Setup_GetEntry(0x14)) {
999 case 0:
1000 alpha_shift_status = 0;
1001 break;
1002 case 1: //Shift enabled
1003 alpha_shift_status = 1;
1004 break;
1005 case 4: //Alpha enabled
1006 alpha_shift_status = 4;
1007 break;
1008 case 0x84: //both Shift and Alpha enabled, seems to be not working
1009 alpha_shift_status = 4;
1010 break;
1011 default:
1012 alpha_shift_status = 0;
1013 break;
1015 Cursor_SetPosition(Cursor.x, Cursor.y);
1016 Cursor_SetFlashMode(1);
1017 Cursor_SetFlashOn(alpha_shift_status);
1018 //Cursor_SetFlashStyle(alpha_shift_status); //Potential 2.00 OS incompatibilty (cf Simon's doc)
1021 else
1023 if (Line[i + Start_Line].type == LINE_TYPE_INPUT || Line[i + Start_Line].type == LINE_TYPE_OUTPUT && Line[i + Start_Line].disp_len >= COL_DISP_MAX)
1025 locate(1, i + 1);
1026 Print(Line[i + Start_Line].str + Line[i + Start_Line].start_col);
1028 else
1030 if(Line[i+Start_Line].tex_flag) {
1031 locate(COL_DISP_MAX - strlen(POPUP_PRETTY_STR) + 1, i + 1);
1032 Print((unsigned char*)POPUP_PRETTY_STR);
1034 else {
1035 locate(COL_DISP_MAX - Line[i + Start_Line].disp_len + 1, i + 1);
1036 Print(Line[i + Start_Line].str);
1040 if (Line[i + Start_Line].start_col > 0)
1042 locate(1, i + 1);
1043 Print((unsigned char *)"\xE6\xAF");
1046 if (Line[i + Start_Line].disp_len - Line[i + Start_Line].start_col > COL_DISP_MAX)
1048 locate(COL_DISP_MAX, i + 1);
1049 Print((unsigned char *)"\xE6\x9F");
1054 //Draw the "fkeys icons"
1055 for(i=0; i<6; i++) {
1056 ficon.bottom = 64;
1057 ficon.top = 64-8;
1058 if (FMenu_entries_name[i*FMENU_TITLE_LENGHT]!= '\0') {
1059 ficon.left = 1+i*21;
1060 ficon.right = ficon.left + (127-2)/6 - 1;
1061 Bdisp_AreaClr_VRAM(&ficon);
1062 Bdisp_AreaReverseVRAM(ficon.left, ficon.top, ficon.right, ficon.bottom);
1063 memcpy(temp_fkey, FMenu_entries_name+i*FMENU_TITLE_LENGHT, FMENU_TITLE_LENGHT*sizeof(char));
1064 PrintMini(ficon.left + 2, ficon.top +2, (unsigned char*)temp_fkey, MINI_REV);
1065 memset(temp_fkey, '\0', FMENU_TITLE_LENGHT*sizeof(char));
1069 Bdisp_PutDisp_DD();
1070 return CONSOLE_SUCCEEDED;
1074 Draw a popup at the center of the screen containing the str expression drawn in pretty print.
1076 #ifdef POPUP_PRETTY
1077 void Console_Draw_TeX_Popup(unsigned char* str, int width, int height)
1079 DISPBOX popup;
1080 int margin = 2, border = 1;
1081 int key;
1083 popup.left = 64 - width/2 - margin - border;
1084 popup.right = 128 - popup.left;
1086 popup.top = 32 - height/2 - margin - border;
1087 popup.bottom = 64 - popup.top;
1089 Bdisp_AreaClr_VRAM(&popup);
1090 Bdisp_AreaReverseVRAM(popup.left, popup.top, popup.right, popup.bottom);
1092 Bdisp_AreaReverseVRAM(popup.left + border, popup.top + border, popup.right - border, popup.bottom - border);
1094 TeX_drawComplex((char*)str, popup.left+border+margin, popup.top+border+margin);
1096 GetKey(&key);
1098 #endif
1101 ÒÔϺ¯ÊýÓÃÓÚÊäÈëÐУ¬³É¹¦ºó½«·µ»Ø¸ÃÐеÄ×Ö·û´®¡£
1104 unsigned char *Console_GetLine()
1106 int return_val;
1110 return_val = Console_GetKey();
1111 Console_Disp();
1112 if (return_val == CONSOLE_MEM_ERR) return NULL;
1113 } while (return_val != CONSOLE_NEW_LINE_SET);
1115 return Line[Current_Line - 1].str;
1119 Simple accessor to the Edit_Line buffer.
1121 unsigned char* Console_GetEditLine()
1123 return Edit_Line;