2 Copyright © 1995-2014, 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
,
30 UBYTE
*numparams_ptr
, LONG toparse
, IPTR
*p_tab
, Object
*unit
,
31 struct ConsoleBase
*ConsoleDevice
);
32 static BOOL
string2command(BYTE
*cmd_ptr
, UBYTE
** writestr_ptr
,
33 UBYTE
*numparams_ptr
, LONG toparse
, IPTR
*p_tab
, Object
*unit
,
34 struct ConsoleBase
*ConsoleDevice
);
41 #define BACKSPACE 0x08
46 #define CARRIAGE_RETURN 0x0D
47 #define SHIFT_OUT 0x0E
50 #define NEXT_LINE 0x85
51 #define H_TAB_SET 0x88
52 #define REVERSE_INDEX 0x8D
55 #define FIRST_CSI_CMD 0x40
57 /***********************
58 ** writeToConsole() **
59 ***********************/
62 ** SGR is the command with most params: 4
63 ** stegerg: RKRMs say it can have any number of parameters in any order. So instead of 4
64 ** we assume and hope that there will never be more than 16 params :-\
67 #define MAX_COMMAND_PARAMS 16
70 ULONG
writeToConsole(struct ConUnit
*unit
, STRPTR buf
, ULONG towrite
,
71 struct ConsoleBase
*ConsoleDevice
)
73 IPTR param_tab
[MAX_COMMAND_PARAMS
];
77 UBYTE
*orig_write_str
, *write_str
;
78 LONG written
, orig_towrite
;
80 write_str
= orig_write_str
= (UBYTE
*) buf
;
82 EnterFunc(bug("WriteToConsole(ioreq=%p)\n"));
84 orig_towrite
= towrite
;
86 D(bug("Number of chars to write %d\n", towrite
));
88 /* Interpret string into a command and execute command */
95 for (i
= 0; i
< towrite
; i
++)
96 kprintf("%x", write_str
[i
]);
106 if (!string2command(&command
, &write_str
, &numparams
, towrite
,
107 param_tab
, (Object
*) unit
, ConsoleDevice
))
110 Console_UnRenderCursor((Object
*) unit
);
111 Console_DoCommand((Object
*) unit
, command
, numparams
, param_tab
);
112 Console_RenderCursor((Object
*) unit
);
114 towrite
= orig_towrite
- (write_str
- orig_write_str
);
115 } /* while (characters left to interpret) */
117 written
= write_str
- orig_write_str
;
119 ReturnInt("WriteToConsole", LONG
, written
);
123 /**********************
124 ** string2command() **
125 **********************/
128 static const UBYTE str_slm
[] = {0x32, 0x30, 0x68}; /* Set linefeed mode */
129 static const UBYTE str_rnm
[] = {0x32, 0x30, 0x6C}; /* Reset linefeed mode */
130 static const UBYTE str_ssm
[] = {0x3E, 0x31, 0x68}; /* Set autoscroll mode */
131 static const UBYTE str_rsm
[] = {0x3E, 0x31, 0x6C}; /* Reset autoscroll mode */
132 static const UBYTE str_swm
[] = {0x3E, 0x37, 0x68}; /* Set autowrap mode */
133 static const UBYTE str_rwm
[] = {0x3E, 0x37, 0x6C}; /* Reset autowrap mode */
134 static const UBYTE str_dsr
[] = {0x36, 0x6E}; /* device status report */
135 static const UBYTE str_con
[] = {' ', 'p'}; /* cursor visible */
136 static const UBYTE str_con2
[] = {'1', ' ', 'p'}; /* cursor visible */
137 static const UBYTE str_cof
[] = {'0', ' ', 'p'}; /* cursor invisible */
138 static const UBYTE str_srq1
[] = {' ', 'q'}; /* window status request */
139 static const UBYTE str_srq2
[] = {'0', ' ', 'q'}; /* window status request */
141 #define NUM_SPECIAL_COMMANDS 12
142 static const struct special_cmd_descr
147 } scd_tab
[NUM_SPECIAL_COMMANDS
] =
149 {C_SET_LF_MODE
, (STRPTR
) str_slm
, 3},
150 {C_RESET_LF_MODE
, (STRPTR
) str_rnm
, 3},
151 {C_SET_AUTOSCROLL_MODE
, (STRPTR
) str_ssm
, 3},
152 {C_RESET_AUTOSCROLL_MODE
, (STRPTR
) str_rsm
, 3},
153 {C_SET_AUTOWRAP_MODE
, (STRPTR
) str_swm
, 3},
154 {C_RESET_AUTOWRAP_MODE
, (STRPTR
) str_rwm
, 3},
155 {C_DEVICE_STATUS_REPORT
, (STRPTR
) str_dsr
, 2},
156 {C_CURSOR_VISIBLE
, (STRPTR
) str_con
, 2},
157 {C_CURSOR_VISIBLE
, (STRPTR
) str_con2
, 3},
158 {C_CURSOR_INVISIBLE
, (STRPTR
) str_cof
, 3},
159 {C_WINDOW_STATUS_REQUEST
, (STRPTR
) str_srq1
, 2},
160 {C_WINDOW_STATUS_REQUEST
, (STRPTR
) str_srq2
, 3}
164 static UBYTE
*cmd_names
[NUM_CONSOLE_COMMANDS
] = {
166 "Ascii", /* C_ASCII = 0 */
169 "Bell", /* C_BELL, */
170 "Backspace", /* C_BACKSPACE, */
171 "HTab", /* C_HTAB, */
172 "Linefeed", /* C_LINEFEED, */
173 "VTab", /* C_VTAB, */
174 "Formefeed", /* C_FORMFEED, */
175 "Carriage return", /* C_CARRIAGE_RETURN, */
176 "Shift In", /* C_SHIFT_IN, */
177 "Shift Out", /* C_SHIFT_OUT, */
178 "Index", /* C_INDEX, */
179 "Nex Line", /* C_NEXT_LINE, */
180 "Tab set", /* C_H_TAB_SET, */
181 "Reverse Idx", /* C_REVERSE_IDX, */
182 "Set LF Mode", /* C_SET_LF_MODE, */
183 "Reset LF Mode", /* C_RESET_lF_MODE, */
184 "Device Status Report", /* C_DEVICE_STATUS_REPORT, */
186 "Insert Char", /* C_INSERT_CHAR, */
187 "Cursor Up", /* C_CURSOR_UP, */
188 "Cursor Down", /* C_CURSOR_DOWN, */
189 "Cursor Forward", /* C_CURSOR_FORWARD, */
190 "Cursor Backward", /* C_CURSOR_BACKWARD, */
191 "Cursor Next Line", /* C_CURSOR_NEXT_LINE, */
192 "Cursor Prev Line", /* C_CURSOR_PREV_LINE, */
193 "Cursor Pos", /* C_CURSOR_POS, */
194 "Cursor HTab", /* C_CURSOR_HTAB, */
195 "Erase In Display", /* C_ERASE_IN_DISPLAY, */
196 "Erase In Line", /* C_ERASE_IN_LINE, */
197 "Insert Line", /* C_INSERT_LINE, */
198 "Delete Line", /* C_DELETE_LINE, */
199 "Delete Char", /* C_DELETE_CHAR, */
200 "Scroll Up", /* C_SCROLL_UP, */
201 "Scroll Down", /* C_SCROLL_DOWN, */
202 "Cursor Tab Ctrl", /* C_CURSOR_TAB_CTRL, */
203 "Cursor Backtab", /* C_CURSOR_BACKTAB, */
204 "Select Graphic Rendition", /* C_SELECT_GRAPHIC_RENDITION */
205 "Window Status Request", /* C_WINDOW_STATUS_REQUEST */
206 "Cursor Visible", /* C_CURSOR_VISIBLE, */
207 "Cursor Invisible", /* C_CURSOR_INVISIBLE, */
208 "Set Raw Events", /* C_SET_RAWEVENTS, */
209 "Reset Raw Events", /* C_RESET_RAWEVENTS */
210 "Set Auto Wrap Mode", /* C_SET_AUTOWRAP_MODE */
211 "Reset Auto Wrap Mode", /* C_RESET_AUTOWRAP_MODE */
212 "Set Auto Scroll Mode", /* C_SET_AUTOSCROLL_MODE */
213 "Reset Auto Scroll Mode", /* C_RESET_AUTOSCROLL_MODE */
214 "Set Page Length", /* C_SET_PAGE_LENGTH */
215 "Set Line Length", /* C_SET_LINE_LENGTH */
216 "Set Left Offset", /* C_SET_LEFT_OFFSET */
217 "Set Top Offset" /* C_SET_TOP_OFFSET */
221 static BOOL
check_special(STRPTR string
, LONG toparse
)
223 return ((*string
== CSI
) ||
224 (toparse
>= 2 && (string
[0] == ESC
) && (string
[1] == '[')) || /* CSI */
227 (*string
== BACKSPACE
) ||
229 (*string
== LINEFEED
) ||
230 (*string
== FORMFEED
) ||
231 (*string
== CARRIAGE_RETURN
) ||
232 (*string
== SHIFT_OUT
) ||
233 (*string
== SHIFT_IN
) ||
235 (*string
== INDEX
) ||
236 (*string
== H_TAB_SET
) || (*string
== REVERSE_INDEX
));
239 static BOOL
string2command(BYTE
*cmd_ptr
, UBYTE
** writestr_ptr
,
240 UBYTE
*numparams_ptr
, LONG toparse
, IPTR
*p_tab
, Object
*unit
,
241 struct ConsoleBase
*ConsoleDevice
)
243 UBYTE
*write_str
= *writestr_ptr
;
244 UBYTE
*csi_str
= write_str
;
245 LONG csi_toparse
= 0;
247 BOOL found
= FALSE
, csi
= FALSE
;
249 EnterFunc(bug("StringToCommand(toparse=%d)\n", toparse
));
252 if (*write_str
== CSI
)
256 csi_toparse
= toparse
- 1;
258 else if (toparse
>= 2)
260 if ((write_str
[0] == ESC
) && (write_str
[1] == '['))
263 csi_toparse
= toparse
- 2;
270 D(bug("CSI found, getting command\n"));
272 /* Search for the longest commands first */
277 /* Look for some special commands */
278 for (i
= 0; ((i
< NUM_SPECIAL_COMMANDS
) && (!found
)); i
++)
280 /* Check whether command sequence is longer than input */
281 if (scd_tab
[i
].Length
> csi_toparse
)
282 continue; /* if so, check next command sequence */
285 ("Comparing for special command %d, idx %d, cmdstr %p, len %d, csistr %p \n",
286 scd_tab
[i
].Command
, i
, scd_tab
[i
].CommandStr
,
287 scd_tab
[i
].Length
, csi_str
));
288 /* Command match ? */
289 if (0 == strncmp(csi_str
, scd_tab
[i
].CommandStr
,
292 D(bug("Special command found\n"));
293 csi_str
+= scd_tab
[i
].Length
;
294 *cmd_ptr
= scd_tab
[i
].Command
;
298 } /* for (each special command) */
301 /* A parameter command? (I.e. one of the commands that take
305 getparamcommand(cmd_ptr
, &csi_str
, numparams_ptr
,
306 csi_toparse
, p_tab
, unit
, ConsoleDevice
);
308 } /* if (CSI was found) */
314 /* Look for standalone codes */
328 *cmd_ptr
= C_BACKSPACE
;
338 *cmd_ptr
= C_LINEFEED
;
348 *cmd_ptr
= C_FORMFEED
;
352 case CARRIAGE_RETURN
:
353 *cmd_ptr
= C_CARRIAGE_RETURN
;
358 *cmd_ptr
= C_SHIFT_OUT
;
363 *cmd_ptr
= C_SHIFT_IN
;
378 *cmd_ptr
= C_NEXT_LINE
;
383 *cmd_ptr
= C_H_TAB_SET
;
388 *cmd_ptr
= C_REVERSE_IDX
;
395 /* Found special char. Increase pointer */
401 if (!found
) /* Still not any found? Try to print as plain ASCII */
403 *cmd_ptr
= C_ASCII_STRING
;
405 p_tab
[0] = (IPTR
) write_str
;
414 while (toparse
&& !check_special(write_str
, toparse
));
416 /* store the string length */
417 p_tab
[1] = (IPTR
) (write_str
- (UBYTE
*) p_tab
[0]);
420 D(bug("FOUND CMD: %s\n", cmd_names
[*cmd_ptr
]));
422 /* Return pointer to first character AFTER last interpreted char */
423 *writestr_ptr
= write_str
;
425 ReturnBool("StringToCommand", found
);
429 /************************
430 ** getparamcommand() **
431 ************************/
434 If you add a command here, you should also add default values for
435 its parameters in Console::GetDefaultParams()
437 static const struct Command
444 {C_INSERT_CHAR
, 1}, /* 0x40 @ */
445 {C_CURSOR_UP
, 1}, /* 0x41 A */
446 {C_CURSOR_DOWN
, 1}, /* 0x42 B */
447 {C_CURSOR_FORWARD
, 1}, /* 0x43 C */
448 {C_CURSOR_BACKWARD
, 1}, /* 0x44 D */
449 {C_CURSOR_NEXT_LINE
, 1}, /* 0x45 E */
450 {C_CURSOR_PREV_LINE
, 1}, /* 0x46 F */
452 {C_CURSOR_POS
, 2}, /* 0x48 H */
453 {C_CURSOR_HTAB
, 1}, /* 0x49 I */
454 {C_ERASE_IN_DISPLAY
, 0}, /* 0x4A J */
455 {C_ERASE_IN_LINE
, 0}, /* 0x4B K */
456 {C_INSERT_LINE
, 0}, /* 0x4C L */
457 {C_DELETE_LINE
, 0}, /* 0x4D M */
460 {C_DELETE_CHAR
, 1}, /* 0x50 P */
463 {C_SCROLL_UP
, 1}, /* 0x53 S */
464 {C_SCROLL_DOWN
, 1}, /* 0x54 T */
467 {C_CURSOR_TAB_CTRL
, 1}, /* 0x57 W */
470 {C_CURSOR_BACKTAB
, 1}, /* 0x5A Z */
489 {C_SELECT_GRAPHIC_RENDITION
, MAX_COMMAND_PARAMS
}, /* 0x6D m */
496 {C_SET_PAGE_LENGTH
, 1}, /* 0x74 t */
497 {C_SET_LINE_LENGTH
, }, /* 0x75 u */
500 {C_SET_LEFT_OFFSET
, 1}, /* 0x78 x */
501 {C_SET_TOP_OFFSET
, 1}, /* 0x79 y */
503 {C_SET_RAWEVENTS
, MAX_COMMAND_PARAMS
}, /* 0x7B { */
505 {C_RESET_RAWEVENTS
, MAX_COMMAND_PARAMS
}, /* 0x7D } */
509 #define PARAM_BUF_SIZE MAX_COMMAND_PARAMS
510 /* Parameters for commands are parsed and filled into this one */
513 UBYTE numparams
; /* Parameters stored */
515 /* Since parameters may be optional, only supplied parameters
516 are saved, along with their number. For example
517 for the command CURSOR POSITION, if only the second parameter
518 (column) is specified in the write stream, then
519 numparams will be 1 and for the one entry, paramno will be 1
520 (C counting) and val will be <column>.
521 Row will have to be set to some default value.
525 UBYTE paramno
; /* Starts counting at 0 */
527 } tab
[PARAM_BUF_SIZE
];
531 static BOOL
getparamcommand(BYTE
*cmd_ptr
, UBYTE
** writestr_ptr
,
532 UBYTE
*numparams_ptr
, LONG toparse
, IPTR
*p_tab
, Object
*unit
,
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
= { };
546 BYTE cmd_next_idx
= 0; /* Index to byte after the command */
548 /* write_str points to first character after <CSI> */
549 UBYTE
*write_str
= *writestr_ptr
;
551 UBYTE num_params
= 0;
552 BOOL done
= FALSE
, found
= FALSE
;
553 BOOL next_can_be_separator
= TRUE
,
554 next_can_be_param
= TRUE
,
555 next_can_be_commandid
= TRUE
, last_was_param
= FALSE
;
556 UBYTE num_separators_found
= 0;
560 /* In case it's a parameter */
598 UBYTE idx
= *write_str
- FIRST_CSI_CMD
;
599 UBYTE maxparams
= csi2command
[idx
].MaxParams
;
601 if (next_can_be_commandid
)
603 /* FIXME: Should also do a MinParams compare */
604 if (num_params
<= maxparams
) /* Valid command? */
607 /* Assure that there are not too many separators in
609 if ((num_separators_found
< maxparams
)
610 /* FIXME: 0-param commands can be moved to special-command-handlin in string2command() */
611 || ((num_separators_found
== 0)
612 && (maxparams
== 0)))
614 cmd
= csi2command
[idx
].Command
;
616 /* Save index to where the next command will
618 cmd_next_idx
= write_str
- *writestr_ptr
+ 1;
620 params
.numparams
= num_params
;
630 case ';': /* parameter separator, skip it */
632 if (!next_can_be_separator
)
639 next_can_be_separator
= FALSE
;
640 next_can_be_param
= TRUE
;
641 next_can_be_commandid
= FALSE
;
642 last_was_param
= FALSE
;
644 num_separators_found
++;
658 case '>': /* because of SGR background color param :-( */
659 if (!next_can_be_param
)
669 if (num_params
> MAX_COMMAND_PARAMS
)
674 params
.tab
[num_params
- 1].paramno
= num_params
- 1;
675 params
.tab
[num_params
- 1].val
= 0;
677 last_was_param
= TRUE
;
680 params
.tab
[num_params
- 1].val
*= 10;
681 if (*write_str
== '>')
683 params
.tab
[num_params
- 1].val
+= 5;
687 params
.tab
[num_params
- 1].val
+= (*write_str
) - '0';
690 next_can_be_separator
= TRUE
;
691 next_can_be_commandid
= TRUE
;
702 } /* while (!done) */
709 /* Continue parsing on the first byte after the command */
710 *writestr_ptr
+= cmd_next_idx
;
716 /* First fill in some default values in p_tab */
717 Console_GetDefaultParams(unit
, *cmd_ptr
, p_tab
);
719 for (i
= 0; i
< params
.numparams
; i
++)
721 /* Override with parsed values */
722 D(bug("CMD %s: Setting param %d to %d\n", cmd_names
[*cmd_ptr
],
723 params
.tab
[i
].paramno
, params
.tab
[i
].val
));
725 p_tab
[params
.tab
[i
].paramno
] = params
.tab
[i
].val
;
728 *numparams_ptr
= params
.numparams
;
734 VOID
printstring(STRPTR string
, ULONG len
,
735 struct ConsoleBase
*ConsoleDevice
)
739 kprintf("%d/%c ", *string
, *string
);