2 Copyright © 1995-2001, The AROS Development Team. All rights reserved.
5 Desc: Support functions for console.device
9 #include <proto/exec.h>
10 #include <exec/lists.h>
12 #include <exec/memory.h>
14 #include <proto/intuition.h>
15 #include <intuition/classes.h>
17 #include <devices/conunit.h>
21 #include "console_gcc.h"
23 #include "consoleif.h"
27 #include <aros/debug.h>
29 static BOOL
getparamcommand(BYTE
*cmd_ptr
, UBYTE
**writestr_ptr
, UBYTE
*numparams_ptr
, LONG toparse
, IPTR
*p_tab
, Object
*unit
, struct ConsoleBase
*ConsoleDevice
);
30 static BOOL
string2command(BYTE
*cmd_ptr
, UBYTE
**writestr_ptr
, UBYTE
*numparams_ptr
, LONG toparse
, IPTR
*p_tab
, Object
*unit
, struct ConsoleBase
*ConsoleDevice
);
36 #define BACKSPACE 0x08
41 #define CARRIAGE_RETURN 0x0D
42 #define SHIFT_OUT 0x0E
45 #define NEXT_LINE 0x85
46 #define H_TAB_SET 0x88
47 #define REVERSE_INDEX 0x8D
50 #define FIRST_CSI_CMD 0x40
52 /***********************
53 ** writeToConsole() **
54 ***********************/
57 ** SGR is the command with most params: 4
58 ** stegerg: RKRMs say it can have any number of parameters in any order. So instead of 4
59 ** we assume and hope that there will never be more than 16 params :-\
62 #define MAX_COMMAND_PARAMS 16
65 ULONG
writeToConsole(struct ConUnit
*unit
, STRPTR buf
, ULONG towrite
, struct ConsoleBase
*ConsoleDevice
)
67 IPTR param_tab
[MAX_COMMAND_PARAMS
];
71 UBYTE
*orig_write_str
, *write_str
;
72 LONG written
, orig_towrite
;
74 write_str
= orig_write_str
= (UBYTE
*)buf
;
77 EnterFunc(bug("WriteToConsole(ioreq=%p)\n"));
80 orig_towrite
= towrite
;
82 D(bug("Number of chars to write %d\n", towrite
));
85 /* Interpret string into a command and execute command */
92 for (i
= 0; i
< towrite
; i
++)
93 kprintf("%x", write_str
[i
]);
103 if (!string2command(&command
, &write_str
, &numparams
, towrite
, param_tab
, (Object
*)unit
, ConsoleDevice
))
107 Console_DoCommand((Object
*)unit
, command
, numparams
, param_tab
);
109 towrite
= orig_towrite
- (write_str
- orig_write_str
);
111 } /* while (characters left to interpret) */
113 written
= write_str
- orig_write_str
;
115 ReturnInt("WriteToConsole", LONG
, written
);
119 /**********************
120 ** string2command() **
121 **********************/
124 static const UBYTE str_slm
[] = {0x32, 0x30, 0x68 }; /* Set linefeed mode */
125 static const UBYTE str_rnm
[] = {0x32, 0x30, 0x6C }; /* Reset linefeed mode */
126 static const UBYTE str_ssm
[] = {0x3E, 0x31, 0x68 }; /* Set autoscroll mode */
127 static const UBYTE str_rsm
[] = {0x3E, 0x31, 0x6C }; /* Reset autoscroll mode */
128 static const UBYTE str_swm
[] = {0x3E, 0x37, 0x68 }; /* Set autowrap mode */
129 static const UBYTE str_rwm
[] = {0x3E, 0x37, 0x6C }; /* Reset autowrap mode */
130 static const UBYTE str_dsr
[] = {0x36, 0x6E }; /* device status report */
131 static const UBYTE str_con
[] = {' ', 'p'}; /* cursor visible */
132 static const UBYTE str_con2
[] = {'1', ' ', 'p'}; /* cursor visible */
133 static const UBYTE str_cof
[] = {'0', ' ', 'p'}; /* cursor invisible */
135 #define NUM_SPECIAL_COMMANDS 10
136 static const struct special_cmd_descr
141 } scd_tab
[NUM_SPECIAL_COMMANDS
] = {
143 {C_SET_LF_MODE
, (STRPTR
)str_slm
, 3 },
144 {C_RESET_LF_MODE
, (STRPTR
)str_rnm
, 3 },
145 {C_SET_AUTOSCROLL_MODE
, (STRPTR
)str_ssm
, 3 },
146 {C_RESET_AUTOSCROLL_MODE
, (STRPTR
)str_rsm
, 3 },
147 {C_SET_AUTOWRAP_MODE
, (STRPTR
)str_swm
, 3 },
148 {C_RESET_AUTOWRAP_MODE
, (STRPTR
)str_rwm
, 3 },
149 {C_DEVICE_STATUS_REPORT
, (STRPTR
)str_dsr
, 2 },
150 {C_CURSOR_VISIBLE
, (STRPTR
)str_con
, 2 },
151 {C_CURSOR_VISIBLE
, (STRPTR
)str_con2
, 3 },
152 {C_CURSOR_INVISIBLE
, (STRPTR
)str_cof
, 3 }
157 static UBYTE
*cmd_names
[NUM_CONSOLE_COMMANDS
] =
160 "Ascii", /* C_ASCII = 0 */
163 "Bell", /* C_BELL, */
164 "Backspace", /* C_BACKSPACE, */
165 "HTab", /* C_HTAB, */
166 "Linefeed", /* C_LINEFEED, */
167 "VTab", /* C_VTAB, */
168 "Formefeed", /* C_FORMFEED, */
169 "Carriage return", /* C_CARRIAGE_RETURN, */
170 "Shift In", /* C_SHIFT_IN, */
171 "Shift Out", /* C_SHIFT_OUT, */
172 "Index", /* C_INDEX, */
173 "Nex Line", /* C_NEXT_LINE, */
174 "Tab set", /* C_H_TAB_SET, */
175 "Reverse Idx", /* C_REVERSE_IDX, */
176 "Set LF Mode", /* C_SET_LF_MODE, */
177 "Reset LF Mode", /* C_RESET_lF_MODE, */
178 "Device Status Report", /* C_DEVICE_STATUS_REPORT, */
180 "Insert Char", /* C_INSERT_CHAR, */
181 "Cursor Up", /* C_CURSOR_UP, */
182 "Cursor Down", /* C_CURSOR_DOWN, */
183 "Cursor Forward", /* C_CURSOR_FORWARD, */
184 "Cursor Backward", /* C_CURSOR_BACKWARD, */
185 "Cursor Next Line", /* C_CURSOR_NEXT_LINE, */
186 "Cursor Prev Line", /* C_CURSOR_PREV_LINE, */
187 "Cursor Pos", /* C_CURSOR_POS, */
188 "Cursor HTab", /* C_CURSOR_HTAB, */
189 "Erase In Display", /* C_ERASE_IN_DISPLAY, */
190 "Erase In Line", /* C_ERASE_IN_LINE, */
191 "Insert Line", /* C_INSERT_LINE, */
192 "Delete Line", /* C_DELETE_LINE, */
193 "Delete Char", /* C_DELETE_CHAR, */
194 "Scroll Up", /* C_SCROLL_UP, */
195 "Scroll Down", /* C_SCROLL_DOWN, */
196 "Cursor Tab Ctrl", /* C_CURSOR_TAB_CTRL, */
197 "Cursor Backtab", /* C_CURSOR_BACKTAB, */
198 "Select Graphic Rendition", /* C_SELECT_GRAPHIC_RENDITION */
199 "Cursor Visible", /* C_CURSOR_VISIBLE, */
200 "Cursor Invisible", /* C_CURSOR_INVISIBLE, */
201 "Set Raw Events", /* C_SET_RAWEVENTS, */
202 "Reset Raw Events", /* C_RESET_RAWEVENTS */
203 "Set Auto Wrap Mode", /* C_SET_AUTOWRAP_MODE */
204 "Reset Auto Wrap Mode", /* C_RESET_AUTOWRAP_MODE */
205 "Set Auto Scroll Mode", /* C_SET_AUTOSCROLL_MODE */
206 "Reset Auto Scroll Mode", /* C_RESET_AUTOSCROLL_MODE */
207 "Set Page Length", /* C_SET_PAGE_LENGTH */
208 "Set Line Length", /* C_SET_LINE_LENGTH */
209 "Set Left Offset", /* C_SET_LEFT_OFFSET */
210 "Set Top Offset" /* C_SET_TOP_OFFSET */
214 static BOOL
check_special(STRPTR string
, LONG toparse
)
218 (*string
== CSI
) || (toparse
>= 2 && (string
[0] == ESC
) && (string
[1] == '[')) || /* CSI */
220 (*string
== BACKSPACE
) ||
222 (*string
== LINEFEED
) ||
223 (*string
== FORMFEED
) ||
224 (*string
== CARRIAGE_RETURN
) ||
225 (*string
== SHIFT_OUT
) ||
226 (*string
== SHIFT_IN
) ||
228 (*string
== INDEX
) ||
229 (*string
== H_TAB_SET
) ||
230 (*string
== REVERSE_INDEX
)
234 static BOOL
string2command( BYTE
*cmd_ptr
235 , UBYTE
**writestr_ptr
236 , UBYTE
*numparams_ptr
240 , struct ConsoleBase
*ConsoleDevice
)
242 UBYTE
*write_str
= *writestr_ptr
;
244 UBYTE
*csi_str
= write_str
;
245 LONG csi_toparse
= 0;
251 EnterFunc(bug("StringToCommand(toparse=%d)\n", toparse
));
255 if (*write_str
== CSI
)
260 csi_toparse
= toparse
- 1;
262 else if (toparse
>= 2)
264 if ( (write_str
[0] == ESC
) && (write_str
[1] == '[') )
267 csi_toparse
= toparse
- 2;
274 D(bug("CSI found, getting command\n"));
276 /* Search for the longest commands first */
281 /* Look for some special commands */
282 for (i
= 0; ((i
< NUM_SPECIAL_COMMANDS
) && (!found
)) ; i
++ )
284 /* Check whether command sequence is longer than input */
285 if (scd_tab
[i
].Length
> csi_toparse
)
286 continue; /* if so, check next command sequence */
288 D(bug("Comparing for special command %d, idx %d, cmdstr %p, len %d, csistr %p \n",
289 scd_tab
[i
].Command
, i
, scd_tab
[i
].CommandStr
, scd_tab
[i
].Length
, csi_str
));
290 /* Command match ? */
291 if (0 == strncmp(csi_str
, scd_tab
[i
].CommandStr
, scd_tab
[i
].Length
))
293 D(bug("Special command found\n"));
294 csi_str
+= scd_tab
[i
].Length
;
295 *cmd_ptr
= scd_tab
[i
].Command
;
300 } /* for (each special command) */
304 /* A parameter command ? (Ie. one of the commands that takes parameters) */
306 found
= getparamcommand(cmd_ptr
, &csi_str
, numparams_ptr
, csi_toparse
, p_tab
, unit
, ConsoleDevice
);
308 } /* if (CSI was found) */
314 /* Look for standalone codes */
323 *cmd_ptr
= C_BACKSPACE
;
333 *cmd_ptr
= C_LINEFEED
;
343 *cmd_ptr
= C_FORMFEED
;
347 case CARRIAGE_RETURN
:
348 *cmd_ptr
= C_CARRIAGE_RETURN
;
353 *cmd_ptr
= C_SHIFT_OUT
;
358 *cmd_ptr
= C_SHIFT_IN
;
373 *cmd_ptr
= C_NEXT_LINE
;
378 *cmd_ptr
= C_H_TAB_SET
;
383 *cmd_ptr
= C_REVERSE_IDX
;
391 /* Found special char. Increase pointer */
398 if (!found
) /* Still not any found ? Try to print as plain ASCII */
400 *cmd_ptr
= C_ASCII_STRING
;
402 p_tab
[0] = (IPTR
)write_str
;
410 } while (toparse
&& !check_special(write_str
, toparse
));
412 p_tab
[1] = (IPTR
)(write_str
- (UBYTE
*)p_tab
[0]); /* store the string length */
415 D(bug("FOUND CMD: %s\n", cmd_names
[*cmd_ptr
]));
417 /* Return pointer to first character AFTER last interpreted char */
418 *writestr_ptr
= write_str
;
420 ReturnBool ("StringToCommand", found
);
424 /************************
425 ** getparamcommand() **
426 ************************/
429 If you add a command here, you should also add default values for
430 its parameters in Console::GetDefaultParams()
432 static const struct Command
439 { C_INSERT_CHAR
, 1 }, /* 0x40 @ */
440 { C_CURSOR_UP
, 1 }, /* 0x41 A */
441 { C_CURSOR_DOWN
, 1 }, /* 0x42 B */
442 { C_CURSOR_FORWARD
, 1 }, /* 0x43 C */
443 { C_CURSOR_BACKWARD
, 1 }, /* 0x44 D */
444 { C_CURSOR_NEXT_LINE
, 1 }, /* 0x45 E */
445 { C_CURSOR_PREV_LINE
, 1 }, /* 0x46 F */
446 { -1 , }, /* 0x47 G */
447 { C_CURSOR_POS
, 2 }, /* 0x48 H */
448 { C_CURSOR_HTAB
, 1 }, /* 0x49 I */
450 { C_ERASE_IN_DISPLAY
, 0 }, /* 0x4A J */
451 { C_ERASE_IN_LINE
, 0 }, /* 0x4B K */
452 { C_INSERT_LINE
, 0 }, /* 0x4C L */
453 { C_DELETE_LINE
, 0 }, /* 0x4D M */
454 { -1 , }, /* 0x4E N */
455 { -1 , }, /* 0x4F O */
456 { C_DELETE_CHAR
, 1 }, /* 0x50 P */
457 { -1 , }, /* 0x51 Q */
458 { -1 , }, /* 0x52 R */
459 { C_SCROLL_UP
, 1 }, /* 0x53 S */
460 { C_SCROLL_DOWN
, 1 }, /* 0x54 T */
461 { -1 , }, /* 0x55 U */
462 { -1 , }, /* 0x56 V */
463 { C_CURSOR_TAB_CTRL
, 1 }, /* 0x57 W */
464 { -1 , }, /* 0x58 X */
465 { -1 , }, /* 0x59 Y */
466 { C_CURSOR_BACKTAB
, 1 }, /* 0x5A Z */
467 { -1 , }, /* 0x5B [ */
468 { -1 , }, /* 0x5C \ */
469 { -1 , }, /* 0x5D ] */
470 { -1 , }, /* 0x5E ^ */
471 { -1 , }, /* 0x5F _ */
472 { -1 , }, /* 0x60 ` */
473 { -1 , }, /* 0x61 a */
474 { -1 , }, /* 0x62 b */
475 { -1 , }, /* 0x63 c */
476 { -1 , }, /* 0x64 d */
477 { -1 , }, /* 0x65 e */
478 { -1 , }, /* 0x66 f */
479 { -1 , }, /* 0x67 g */
480 { -1 , }, /* 0x68 h */
481 { -1 , }, /* 0x69 i */
482 { -1 , }, /* 0x6A j */
483 { -1 , }, /* 0x6B k */
484 { -1 , }, /* 0x6C l */
485 { C_SELECT_GRAPHIC_RENDITION
, MAX_COMMAND_PARAMS
}, /* 0x6D m */
486 { -1 , }, /* 0x6E n */
487 { -1 , }, /* 0x6F o */
488 { -1 , }, /* 0x70 p */
489 { -1 , }, /* 0x71 q */
490 { -1 , }, /* 0x72 r */
491 { -1 , }, /* 0x73 s */
492 { C_SET_PAGE_LENGTH
, }, /* 0x74 t */
493 { C_SET_LINE_LENGTH
, }, /* 0x75 u */
494 { -1 , }, /* 0x76 v */
495 { -1 , }, /* 0x77 w */
496 { C_SET_LEFT_OFFSET
, }, /* 0x78 x */
497 { C_SET_TOP_OFFSET
, }, /* 0x79 y */
498 { -1 , }, /* 0x7A z */
499 { C_SET_RAWEVENTS
, MAX_COMMAND_PARAMS
}, /* 0x7B { */
500 { -1 , }, /* 0x7C | */
501 { C_RESET_RAWEVENTS
, MAX_COMMAND_PARAMS
}, /* 0x7D } */
505 #define PARAM_BUF_SIZE MAX_COMMAND_PARAMS
506 /* Parameters for commands are parsed and filled into this one */
509 UBYTE numparams
; /* Parameters stored */
511 /* Since parameters may be optional, only supplied parameters
512 are saved, along with their number. For example
513 for the command CURSOR POSITION, if only the sencond parameter
514 (column) is specified in the write stream, then
515 numparams will be 1 and for the one entry, paramno will be 1 (C counting)
516 and val will be <column>.
517 Row will have to be set to some default value.
521 UBYTE paramno
; /* Starts counting at 0 */
523 } tab
[PARAM_BUF_SIZE
];
527 static BOOL
getparamcommand(BYTE
*cmd_ptr
528 , UBYTE
**writestr_ptr
529 , UBYTE
*numparams_ptr
533 , struct ConsoleBase
*ConsoleDevice
)
535 /* This function checks for a command with parameters in
536 ** the string. The problem is that the parameters come
537 ** before the comand ID, and the parameters are optional.
538 ** This means that a parameter which has the same value
539 ** as a command ID may be mistakenly taken for being
540 ** end of the command. Therefore we must continue scanning
541 ** even if we found a command ID.
544 struct cmd_params params
;
547 BYTE cmd_next_idx
= 0; /* Index to byte after the command */
549 /* write_str points to first character after <CSI> */
550 UBYTE
*write_str
= *writestr_ptr
;
552 UBYTE num_params
= 0;
557 BOOL next_can_be_separator
= TRUE
,
558 next_can_be_param
= TRUE
,
559 next_can_be_commandid
= TRUE
,
560 last_was_param
= FALSE
;
562 UBYTE num_separators_found
= 0;
566 /* In case it's a parameter */
604 UBYTE idx
= *write_str
- FIRST_CSI_CMD
;
605 UBYTE maxparams
= csi2command
[idx
].MaxParams
;
607 if (next_can_be_commandid
)
609 #warning Should also do a MinParams compare
610 if (num_params
<= maxparams
) /* Valid command ? */
613 /* Assure that there are not to many separators in a command */
614 if ((num_separators_found
< maxparams
)
615 #warning 0-param commands can be moved to special-command-handlin in string2command()
616 || ((num_separators_found
== 0) && (maxparams
== 0)))
618 cmd
= csi2command
[idx
].Command
;
620 /* Save index to where the next command will start */
621 cmd_next_idx
= write_str
- *writestr_ptr
+ 1;
623 params
.numparams
= num_params
;
633 case ';': /* parameter separator, skip it */
635 if (!next_can_be_separator
)
642 next_can_be_separator
= FALSE
;
643 next_can_be_param
= TRUE
;
644 next_can_be_commandid
= FALSE
;
645 last_was_param
= FALSE
;
647 num_separators_found
++;
661 case '>': /* because of SGR background color param :-( */
662 if (!next_can_be_param
)
672 if (num_params
> MAX_COMMAND_PARAMS
)
677 params
.tab
[num_params
- 1].paramno
= num_params
- 1;
678 params
.tab
[num_params
- 1].val
= 0;
680 last_was_param
= TRUE
;
683 params
.tab
[num_params
- 1].val
*= 10;
684 if (*write_str
== '>')
686 params
.tab
[num_params
- 1].val
+= 5;
688 params
.tab
[num_params
- 1].val
+= (*write_str
) - '0';
691 next_can_be_separator
= TRUE
;
692 next_can_be_commandid
= TRUE
;
706 } /* while (!done) */
713 /* Continue parsing on the first byte after the command */
714 *writestr_ptr
+= cmd_next_idx
;
720 /* First fill in some default values in p_tab */
721 Console_GetDefaultParams(unit
, *cmd_ptr
, p_tab
);
723 for (i
= 0; i
< params
.numparams
; i
++)
725 /* Override with parsed values */
726 D(bug("CMD %s: Setting param %d to %d\n"
727 , cmd_names
[*cmd_ptr
]
728 , params
.tab
[i
].paramno
729 , params
.tab
[i
].val
));
731 p_tab
[params
.tab
[i
].paramno
] = params
.tab
[i
].val
;
734 *numparams_ptr
= params
.numparams
;
740 VOID
printstring(STRPTR string
, ULONG len
, struct ConsoleBase
*ConsoleDevice
)
744 kprintf("%d/%c ", *string
, *string
);