2 Copyright © 1995-2015, The AROS Development Team. All rights reserved.
5 Desc: Support functions for console handler.
9 /****************************************************************************************/
11 #define CYCLIC_HISTORY_WALK 0
13 /****************************************************************************************/
15 #include <proto/exec.h>
16 #include <exec/libraries.h>
17 #include <exec/resident.h>
18 #include <exec/memory.h>
20 #include <exec/errors.h>
21 #include <exec/alerts.h>
22 #include <utility/tagitem.h>
23 #include <dos/exall.h>
24 #include <dos/dosasl.h>
25 #include <intuition/intuition.h>
26 #include <intuition/sghooks.h>
27 #include <proto/dos.h>
28 #include <proto/intuition.h>
29 #include <proto/input.h>
30 #include <devices/conunit.h>
34 #include <aros/debug.h>
40 #include "con_handler_intern.h"
42 #include "completion.h"
44 #define ioReq(x) ((struct IORequest *)x)
46 void replypkt(struct DosPacket
*dp
, SIPTR res1
)
53 mn
->mn_Node
.ln_Name
= (char*) dp
;
54 dp
->dp_Port
= &((struct Process
*) FindTask(NULL
))->pr_MsgPort
;
58 void replypkt2(struct DosPacket
*dp
, SIPTR res1
, SIPTR res2
)
65 /******************************************************************************************/
67 static const UBYTE up_seq
[] = { 'A' };
68 static const UBYTE down_seq
[] = { 'B' };
69 static const UBYTE right_seq
[] = { 'C' };
70 static const UBYTE left_seq
[] = { 'D' };
71 static const UBYTE shift_up_seq
[] = { 'T' };
72 static const UBYTE shift_down_seq
[] = { 'S' };
73 static const UBYTE shift_right_seq
[] = { ' ', '@' };
74 static const UBYTE shift_left_seq
[] = { ' ', 'A' };
75 static const UBYTE shift_tab_seq
[] = { 'Z' };
76 static const UBYTE help_seq
[] = { '?', '~' };
77 static const UBYTE f1_seq
[] = { '0', '~' };
78 static const UBYTE f2_seq
[] = { '1', '~' };
79 static const UBYTE f3_seq
[] = { '2', '~' };
80 static const UBYTE f4_seq
[] = { '3', '~' };
81 static const UBYTE f5_seq
[] = { '4', '~' };
82 static const UBYTE f6_seq
[] = { '5', '~' };
83 static const UBYTE f7_seq
[] = { '6', '~' };
84 static const UBYTE f8_seq
[] = { '7', '~' };
85 static const UBYTE f9_seq
[] = { '8', '~' };
86 static const UBYTE f10_seq
[] = { '9', '~' };
87 static const UBYTE paste_seq
[] = { '0', ' ', 'v' };
88 static const UBYTE f11_seq
[] = { '2', '0', '~' };
89 static const UBYTE f12_seq
[] = { '2', '1', '~' };
90 static const UBYTE shift_f1_seq
[] = { '1', '0', '~' };
91 static const UBYTE shift_f2_seq
[] = { '1', '1', '~' };
92 static const UBYTE shift_f3_seq
[] = { '1', '2', '~' };
93 static const UBYTE shift_f4_seq
[] = { '1', '3', '~' };
94 static const UBYTE shift_f5_seq
[] = { '1', '4', '~' };
95 static const UBYTE shift_f6_seq
[] = { '1', '5', '~' };
96 static const UBYTE shift_f7_seq
[] = { '1', '6', '~' };
97 static const UBYTE shift_f8_seq
[] = { '1', '7', '~' };
98 static const UBYTE shift_f9_seq
[] = { '1', '8', '~' };
99 static const UBYTE shift_f10_seq
[] = { '1', '9', '~' };
100 static const UBYTE shift_f11_seq
[] = { '3', '0', '~' };
101 static const UBYTE shift_f12_seq
[] = { '3', '1', '~' };
102 static const UBYTE insert_seq
[] = { '4', '0', '~' };
103 static const UBYTE pageup_seq
[] = { '4', '1', '~' };
104 static const UBYTE pagedown_seq
[] = { '4', '2', '~' };
105 static const UBYTE pause_seq
[] = { '4', '3', '~' };
106 static const UBYTE break_seq
[] = { '5', '3', '~' };
107 static const UBYTE home_seq
[] = { '4', '4', '~' };
108 static const UBYTE end_seq
[] = { '4', '5', '~' };
109 static const UBYTE shift_insert_seq
[] = { '5', '0', '~' };
110 static const UBYTE shift_pageup_seq
[] = { '5', '1', '~' };
111 static const UBYTE shift_pagedown_seq
[] = { '5', '2', '~' };
112 static const UBYTE shift_home_seq
[] = { '5', '4', '~' };
113 static const UBYTE shift_end_seq
[] = { '5', '5', '~' };
115 /* F11, F12, insert, pageup, pagedown, ... seq taken from
116 RKRM: Devices/Console/Reading from the Console Device/Information about the Input Stream */
118 static CONST
struct csimatch
126 {up_seq
, 1, INP_CURSORUP
},
127 {down_seq
, 1, INP_CURSORDOWN
},
128 {right_seq
, 1, INP_CURSORRIGHT
},
129 {left_seq
, 1, INP_CURSORLEFT
},
130 {shift_up_seq
, 1, INP_SHIFT_CURSORUP
},
131 {shift_down_seq
, 1, INP_SHIFT_CURSORDOWN
},
132 {shift_right_seq
, 2, INP_SHIFT_CURSORRIGHT
},
133 {shift_left_seq
, 2, INP_SHIFT_CURSORLEFT
},
134 {shift_tab_seq
, 1, INP_SHIFT_TAB
},
135 {help_seq
, 2, INP_HELP
},
136 {f1_seq
, 2, INP_F1
},
137 {f2_seq
, 2, INP_F2
},
138 {f3_seq
, 2, INP_F3
},
139 {f4_seq
, 2, INP_F4
},
140 {f5_seq
, 2, INP_F5
},
141 {f6_seq
, 2, INP_F6
},
142 {f7_seq
, 2, INP_F7
},
143 {f8_seq
, 2, INP_F8
},
144 {f9_seq
, 2, INP_F9
},
145 {f10_seq
, 2, INP_F10
},
146 {f11_seq
, 3, INP_F11
},
147 {f12_seq
, 3, INP_F12
},
148 {shift_f1_seq
, 3, INP_SHIFT_F1
},
149 {shift_f2_seq
, 3, INP_SHIFT_F2
},
150 {shift_f3_seq
, 3, INP_SHIFT_F3
},
151 {shift_f4_seq
, 3, INP_SHIFT_F4
},
152 {shift_f5_seq
, 3, INP_SHIFT_F5
},
153 {shift_f6_seq
, 3, INP_SHIFT_F6
},
154 {shift_f7_seq
, 3, INP_SHIFT_F7
},
155 {shift_f8_seq
, 3, INP_SHIFT_F8
},
156 {shift_f9_seq
, 3, INP_SHIFT_F9
},
157 {shift_f10_seq
, 3, INP_SHIFT_F10
},
158 {shift_f11_seq
, 3, INP_SHIFT_F11
},
159 {shift_f12_seq
, 3, INP_SHIFT_F12
},
160 {insert_seq
, 3, INP_INSERT
},
161 {pageup_seq
, 3, INP_PAGEUP
},
162 {pagedown_seq
, 3, INP_PAGEDOWN
},
163 {pause_seq
, 3, INP_PAUSE
},
164 {break_seq
, 3, INP_BREAK
},
165 {home_seq
, 3, INP_HOME
},
166 {end_seq
, 3, INP_END
},
167 {shift_insert_seq
, 3, INP_SHIFT_INSERT
},
168 {shift_pageup_seq
, 3, INP_SHIFT_PAGEUP
},
169 {shift_pagedown_seq
, 3, INP_SHIFT_PAGEDOWN
},
170 {shift_home_seq
, 3, INP_SHIFT_HOME
},
171 {shift_end_seq
, 3, INP_SHIFT_END
},
172 {paste_seq
, 3, INP_PASTE
},
177 /******************************************************************************************/
179 static UBYTE
hex2val(char c
)
181 if (c
>= '0' && c
<= '9')
186 /* strtoul() not used because it is much larger and uses .bss
187 * TODO: Sanity checks. */
188 static IPTR
string2val(const char *s
, WORD len
)
192 if (s
[0] == '0' && (s
[1] == 'x' || s
[1] == 'X'))
195 while (len
-- > 0 && *s
)
204 while (len
-- > 0 && *s
)
214 BOOL
parse_filename(struct filehandle
*fh
, char *filename
, struct NewWindow
*nw
)
220 BOOL ok
= TRUE
, done
= FALSE
, paramok
= FALSE
;
222 ASSERT_VALID_PTR(fh
);
223 ASSERT_VALID_PTR(nw
);
226 ASSERT_VALID_PTR(param
);
259 UWORD paramlen
= filename
- param
- 1;
264 nw
->LeftEdge
= paramval
;
268 nw
->TopEdge
= paramval
;
272 nw
->Width
= paramval
;
276 nw
->Height
= paramval
;
280 if ((fh
->wintitle
= AllocVec(paramlen
+ 1, MEMF_PUBLIC
)))
282 CopyMem(param
, fh
->wintitle
, paramlen
);
283 fh
->wintitle
[paramlen
] = '\0';
284 nw
->Title
= fh
->wintitle
;
289 if (!strnicmp(param
, "WAIT", paramlen
))
291 fh
->flags
|= FHFLG_WAIT
;
293 else if (!strnicmp(param
, "CLOSE", paramlen
))
295 nw
->Flags
|= WFLG_CLOSEGADGET
;
297 else if (!strnicmp(param
, "NOCLOSE", paramlen
))
299 nw
->Flags
&= ~WFLG_CLOSEGADGET
;
301 else if (!strnicmp(param
, "AUTO", paramlen
))
303 fh
->flags
|= FHFLG_AUTO
;
305 else if (!strnicmp(param
, "INACTIVE", paramlen
))
307 nw
->Flags
&= ~WFLG_ACTIVATE
;
309 else if (!strnicmp(param
, "NODEPTH", paramlen
))
311 nw
->Flags
&= ~WFLG_DEPTHGADGET
;
313 else if (!strnicmp(param
, "NOSIZE", paramlen
))
315 nw
->Flags
&= ~WFLG_SIZEGADGET
;
317 else if (!strnicmp(param
, "NODRAG", paramlen
))
319 nw
->Flags
&= ~WFLG_DRAGBAR
;
321 else if (!strnicmp(param
, "NOBORDER", paramlen
))
323 nw
->Flags
|= WFLG_BORDERLESS
;
325 else if (!strnicmp(param
, "BACKDROP", paramlen
))
327 nw
->Flags
|= WFLG_BACKDROP
;
328 nw
->Flags
&= ~(WFLG_DRAGBAR
| WFLG_SIZEGADGET
);
330 else if (!strnicmp(param
, "SIMPLE", paramlen
))
334 else if (!strnicmp(param
, "SMART", paramlen
))
338 else if (!strnicmp(param
, "ALT", paramlen
))
340 /* TODO: style "ALT30/30/200/200" */
342 else if (!strnicmp(param
, "WINDOW", 6))
344 /* Do we need some sanity checks here? */
345 fh
->otherwindow
= (struct Window
*) string2val(param
+ 6, paramlen
- 6);
347 else if (!strnicmp(param
, "SCREEN", 6))
349 if ((fh
->screenname
= AllocVec(paramlen
- 5, MEMF_PUBLIC
)))
351 CopyMem(param
+ 6, fh
->screenname
, paramlen
- 6);
352 fh
->screenname
[paramlen
- 6] = '\0';
355 else if (!strnicmp(param
, "BOOT", paramlen
)) /* Private parameter */
357 fh
->flags
|= FHFLG_BOOTCON
;
361 } /* switch(paramid) */
384 } /* while (!done) */
389 /******************************************************************************************/
391 void do_write(struct filehandle
*fh
, APTR data
, ULONG length
)
393 fh
->conwriteio
.io_Command
= CMD_WRITE
;
394 fh
->conwriteio
.io_Data
= data
;
395 fh
->conwriteio
.io_Length
= length
;
397 DoIO((struct IORequest
*) &fh
->conwriteio
);
400 /******************************************************************************************/
402 void do_movecursor(struct filehandle
*fh
, UBYTE direction
, UBYTE howmuch
)
404 UBYTE seq
[6]; /* 9B <N> <N> <N> <dir> <0> */
418 sprintf(&seq
[1], "%d%c", howmuch
, direction
);
422 do_write(fh
, seq
, size
);
426 /******************************************************************************************/
428 void do_cursorvisible(struct filehandle
*fh
, BOOL on
)
439 do_write(fh
, seq
, size
);
442 /******************************************************************************************/
444 void do_deletechar(struct filehandle
*fh
)
449 do_write(fh
, seq
, 2);
452 /******************************************************************************************/
454 void do_eraseinline(struct filehandle
*fh
)
459 do_write(fh
, seq
, 2);
462 /******************************************************************************************/
464 void do_eraseindisplay(struct filehandle
*fh
)
469 do_write(fh
, seq
, 2);
471 /******************************************************************************************/
472 static void copy_from_pastebuf(struct filehandle
* fh
)
474 if (fh
->conbufferpos
>= fh
->conbuffersize
&& fh
->pastebuffer
&& fh
->pastebufferpos
< fh
->pastebuffersize
)
476 ULONG len
= CONSOLEBUFFER_SIZE
;
477 ULONG pastelen
= fh
->pastebuffersize
- fh
->pastebufferpos
;
481 D(bug("Copying %d bytes from paste buffer\n", len
));
483 fh
->conbufferpos
= 0;
484 CopyMem(fh
->pastebuffer
+ fh
->pastebufferpos
, &fh
->consolebuffer
, len
);
485 fh
->conbuffersize
= len
;
486 fh
->pastebufferpos
+= len
;
487 if (fh
->pastebufferpos
>= fh
->pastebuffersize
)
489 FreeMem(fh
->pastebuffer
, PASTEBUFSIZE
);
495 WORD
scan_input(struct filehandle
*fh
, UBYTE
*buffer
)
498 struct csimatch
*match
;
500 WORD result
= INP_DONE
;
502 copy_from_pastebuf(fh
);
504 if (fh
->conbufferpos
< fh
->conbuffersize
)
506 c
= fh
->consolebuffer
[fh
->conbufferpos
++];
507 D(bug("scan_input: check char %d\n", c
));
514 result
= INP_CTRL_C
- 3 + (WORD
) c
;
518 /* FIXME: Ugh... Race condition, anyone? The qualifier might
519 have changed between the keypress and the time we do this */
520 if (PeekQualifier() & (IEQUALIFIER_LSHIFT
| IEQUALIFIER_RSHIFT
))
522 result
= INP_SHIFT_BACKSPACE
;
526 result
= INP_BACKSPACE
;
535 result
= INP_LINEFEED
;
538 case 12: /* CTRL-L */
540 result
= INP_ECHO_STRING
;
548 if (PeekQualifier() & (IEQUALIFIER_LSHIFT
| IEQUALIFIER_RSHIFT
))
550 result
= INP_SHIFT_DELETE
;
559 result
= INP_CONTROL_X
;
562 case 28: /* CTRL-\ */
567 result
= INP_UNKNOWN
;
569 match
= csimatchtable
;
570 for (; match
->seq
; match
++)
572 if (!strncmp(match
->seq
, &(fh
->consolebuffer
[fh
->conbufferpos
]), match
->len
))
575 fh
->conbufferpos
+= match
->len
;
589 } /* if (fh->conbufferpos < fh->conbuffersize) */
591 D(bug("scan_input: result %d\n", result
));
596 /******************************************************************************************/
598 void add_to_history(struct filehandle
*fh
)
600 BOOL add_to_history
= FALSE
;
602 fh
->inputbuffer
[fh
->inputsize
] = '\0';
604 /* Don't add emptry strings */
605 if (fh
->inputbuffer
[fh
->inputstart
] == '\0')
608 if (fh
->historysize
== 0)
610 add_to_history
= TRUE
;
616 old_historypos
= fh
->historypos
- 1;
617 if (old_historypos
< 0)
618 old_historypos
= fh
->historysize
- 1;
620 if (strcmp(&fh
->inputbuffer
[fh
->inputstart
], fh
->historybuffer
[old_historypos
]))
622 /* add to history only if different from last history entry */
624 add_to_history
= TRUE
;
630 if (fh
->historysize
< CMD_HISTORY_SIZE
)
633 strcpy(fh
->historybuffer
[fh
->historypos
], &fh
->inputbuffer
[fh
->inputstart
]);
636 if (fh
->historypos
>= CMD_HISTORY_SIZE
)
640 fh
->historyviewpos
= fh
->historypos
;
643 /******************************************************************************************/
645 void history_walk(struct filehandle
*fh
, WORD inp
)
649 #if !CYCLIC_HISTORY_WALK
650 BOOL walk_to_empty_string
= FALSE
;
656 case INP_SHIFT_CURSORUP
:
657 fh
->historyviewpos
= 0;
660 case INP_SHIFT_CURSORDOWN
:
661 fh
->historyviewpos
= fh
->historysize
- 1;
666 #if CYCLIC_HISTORY_WALK
667 fh
->historyviewpos
--;
668 if (fh
->historyviewpos
< 0) fh
->historyviewpos
= fh
->historysize
- 1;
670 if (fh
->historyviewpos
!= -1)
672 fh
->historyviewpos
--;
673 if (fh
->historyviewpos
< 0 && fh
->historysize
== CMD_HISTORY_SIZE
)
674 fh
->historyviewpos
= CMD_HISTORY_SIZE
- 1;
675 if (fh
->historyviewpos
== fh
->historypos
)
676 fh
->historyviewpos
= -1;
678 if (fh
->historyviewpos
== -1)
679 walk_to_empty_string
= TRUE
;
684 #if CYCLIC_HISTORY_WALK
685 fh
->historyviewpos
++;
686 if (fh
->historyviewpos
>= fh
->historysize
) fh
->historyviewpos
= 0;
688 if (fh
->historyviewpos
!= fh
->historypos
)
690 if (fh
->historyviewpos
== -1 && fh
->historysize
== CMD_HISTORY_SIZE
)
691 fh
->historyviewpos
= fh
->historypos
;
692 fh
->historyviewpos
= (fh
->historyviewpos
+ 1) % CMD_HISTORY_SIZE
;
694 if (fh
->historyviewpos
== fh
->historypos
)
695 walk_to_empty_string
= TRUE
;
700 if (fh
->inputpos
> fh
->inputstart
)
702 do_movecursor(fh
, CUR_LEFT
, fh
->inputpos
- fh
->inputstart
);
707 fh
->inputsize
= fh
->inputstart
;
708 fh
->inputpos
= fh
->inputstart
;
710 #if !CYCLIC_HISTORY_WALK
711 if (!walk_to_empty_string
)
714 len
= strlen(fh
->historybuffer
[fh
->historyviewpos
]);
715 if (len
> (INPUTBUFFER_SIZE
- fh
->inputstart
))
717 len
= INPUTBUFFER_SIZE
- fh
->inputstart
;
722 CopyMem(fh
->historybuffer
[fh
->historyviewpos
], &fh
->inputbuffer
[fh
->inputstart
], len
);
724 fh
->inputsize
+= len
;
727 do_write(fh
, &fh
->inputbuffer
[fh
->inputstart
], len
);
730 #if !CYCLIC_HISTORY_WALK
731 } /* if (!walk_to_empty_string) */
734 } /* if (fh->historysize) */
737 /****************************************************************************************/
739 static const STRPTR CONCLIP_PORTNAME
= "ConClip.rendezvous";
748 static void do_paste(struct filehandle
* fh
)
750 struct MsgPort replyport
, *port
;
752 struct MyEditHookMsg msg
;
753 struct StringInfo sinfo
;
755 if (!(port
= FindPort(CONCLIP_PORTNAME
)))
757 D(bug("ConClip not running, but we got a ConClip paste request"));
761 D(bug("PASTE REQUEST!\n"));
763 replyport
.mp_Node
.ln_Type
= NT_MSGPORT
;
764 replyport
.mp_Node
.ln_Name
= NULL
;
765 replyport
.mp_Node
.ln_Pri
= 0;
766 replyport
.mp_Flags
= PA_SIGNAL
;
767 replyport
.mp_SigBit
= SIGB_SINGLE
;
768 replyport
.mp_SigTask
= FindTask(NULL
);
769 NEWLIST(&replyport
.mp_MsgList
);
771 msg
.msg
.mn_Node
.ln_Type
= NT_MESSAGE
;
772 msg
.msg
.mn_ReplyPort
= &replyport
;
773 msg
.msg
.mn_Length
= sizeof(msg
);
778 /* FIXME: Ensure no fields are left uninitialized */
781 sgw
.WorkBuffer
= AllocMem(PASTEBUFSIZE
, MEMF_CLEAR
| MEMF_ANY
);
788 sgw
.EditOp
= EO_BIGCHANGE
;
792 /* ConClip only ever looks at MaxChars in StringInfo */
793 sinfo
.MaxChars
= PASTEBUFSIZE
;
794 sgw
.StringInfo
= &sinfo
;
796 SetSignal(0, SIGF_SINGLE
);
797 PutMsg(port
, &msg
.msg
);
798 WaitPort(&replyport
);
800 D(bug("Pasting %d bytes\n", sgw
.BufferPos
));
803 FreeMem(fh
->pastebuffer
, PASTEBUFSIZE
);
804 fh
->pastebuffer
= sgw
.WorkBuffer
;
805 fh
->pastebuffersize
= sgw
.BufferPos
;
806 fh
->pastebufferpos
= 0;
809 /****************************************************************************************/
811 BOOL
process_input(struct filehandle
*fh
)
815 while ((inp
= scan_input(fh
, &c
)) != INP_DONE
)
817 D(bug("Input Code: %d\n", inp
));
822 if (fh
->inputpos
> fh
->inputstart
)
825 do_movecursor(fh
, CUR_LEFT
, 1);
829 case INP_SHIFT_CURSORLEFT
: /* move to beginning of line */
831 if (fh
->inputpos
> fh
->inputstart
)
833 do_movecursor(fh
, CUR_LEFT
, fh
->inputpos
- fh
->inputstart
);
834 fh
->inputpos
= fh
->inputstart
;
838 case INP_CURSORRIGHT
:
839 if (fh
->inputpos
< fh
->inputsize
)
842 do_movecursor(fh
, CUR_RIGHT
, 1);
846 case INP_SHIFT_CURSORRIGHT
: /* move to end of line */
848 if (fh
->inputpos
!= fh
->inputsize
)
850 do_movecursor(fh
, CUR_RIGHT
, fh
->inputsize
- fh
->inputpos
);
851 fh
->inputpos
= fh
->inputsize
;
855 case INP_CURSORUP
: /* walk through cmd history */
857 case INP_SHIFT_CURSORUP
:
858 case INP_SHIFT_CURSORDOWN
:
859 history_walk(fh
, inp
);
863 if (fh
->inputpos
> fh
->inputstart
)
865 do_movecursor(fh
, CUR_LEFT
, 1);
867 if (fh
->inputpos
== fh
->inputsize
)
876 WORD chars_right
= fh
->inputsize
- fh
->inputpos
;
881 do_cursorvisible(fh
, FALSE
);
882 do_write(fh
, &fh
->inputbuffer
[fh
->inputpos
+ 1], chars_right
);
884 do_movecursor(fh
, CUR_LEFT
, chars_right
);
885 do_cursorvisible(fh
, TRUE
);
887 memmove(&fh
->inputbuffer
[fh
->inputpos
], &fh
->inputbuffer
[fh
->inputpos
+ 1], chars_right
);
893 case INP_SHIFT_BACKSPACE
:
894 if (fh
->inputpos
> fh
->inputstart
)
896 do_movecursor(fh
, CUR_LEFT
, fh
->inputpos
- fh
->inputstart
);
897 if (fh
->inputpos
== fh
->inputsize
)
901 fh
->inputpos
= fh
->inputsize
= fh
->inputstart
;
905 WORD chars_right
= fh
->inputsize
- fh
->inputpos
;
907 do_cursorvisible(fh
, FALSE
);
908 do_write(fh
, &fh
->inputbuffer
[fh
->inputpos
], chars_right
);
910 do_movecursor(fh
, CUR_LEFT
, chars_right
);
911 do_cursorvisible(fh
, TRUE
);
913 memmove(&fh
->inputbuffer
[fh
->inputstart
], &fh
->inputbuffer
[fh
->inputpos
], chars_right
);
915 fh
->inputsize
-= (fh
->inputpos
- fh
->inputstart
);
916 fh
->inputpos
= fh
->inputstart
;
922 if (fh
->inputpos
< fh
->inputsize
)
926 if (fh
->inputpos
== fh
->inputsize
)
932 WORD chars_right
= fh
->inputsize
- fh
->inputpos
;
934 do_cursorvisible(fh
, FALSE
);
935 do_write(fh
, &fh
->inputbuffer
[fh
->inputpos
+ 1], chars_right
);
937 do_movecursor(fh
, CUR_LEFT
, chars_right
);
938 do_cursorvisible(fh
, TRUE
);
940 memmove(&fh
->inputbuffer
[fh
->inputpos
], &fh
->inputbuffer
[fh
->inputpos
+ 1], chars_right
);
945 case INP_SHIFT_DELETE
:
946 if (fh
->inputpos
< fh
->inputsize
)
948 fh
->inputsize
= fh
->inputpos
;
954 if ((fh
->inputsize
- fh
->inputstart
) > 0)
956 if (fh
->inputpos
> fh
->inputstart
)
958 do_movecursor(fh
, CUR_LEFT
, fh
->inputpos
- fh
->inputstart
);
962 fh
->inputpos
= fh
->inputsize
= fh
->inputstart
;
966 case INP_ECHO_STRING
:
971 if (fh
->inputsize
< INPUTBUFFER_SIZE
)
975 if (fh
->inputpos
== fh
->inputsize
)
977 fh
->inputbuffer
[fh
->inputpos
++] = c
;
982 WORD chars_right
= fh
->inputsize
- fh
->inputpos
;
984 do_cursorvisible(fh
, FALSE
);
985 do_write(fh
, &fh
->inputbuffer
[fh
->inputpos
], chars_right
);
986 do_movecursor(fh
, CUR_LEFT
, chars_right
);
987 do_cursorvisible(fh
, TRUE
);
989 memmove(&fh
->inputbuffer
[fh
->inputpos
+ 1], &fh
->inputbuffer
[fh
->inputpos
], chars_right
);
990 fh
->inputbuffer
[fh
->inputpos
++] = c
;
997 D(bug("[CON] Read EOF (window closing)\n"));
999 if (fh
->flags
& FHFLG_WAITFORCLOSE
)
1002 fh
->flags
|= FHFLG_EOF
;
1003 if (fh
->flags
& FHFLG_AUTO
&& fh
->window
)
1005 if (fh
->flags
& FHFLG_CONSOLEDEVICEOPEN
)
1007 /* Close the device, it will be re-opened if needed */
1008 CloseDevice((struct IORequest
*) fh
->conreadio
);
1009 fh
->flags
&= ~FHFLG_CONSOLEDEVICEOPEN
;
1011 /* Only now close the window itself */
1012 CloseWindow(fh
->window
);
1019 if (fh
->inputsize
< INPUTBUFFER_SIZE
)
1024 do_write(fh
, &c
, 1);
1027 fh
->inputbuffer
[fh
->inputsize
++] = '\n';
1030 fh
->inputstart
= fh
->inputsize
;
1031 fh
->inputpos
= fh
->inputstart
;
1034 HandlePendingReads(fh
);
1036 if ((fh
->flags
& FHFLG_EOF
) && (fh
->flags
& FHFLG_READPENDING
))
1038 struct Message
*msg
= (struct Message
*) RemHead((struct List
*) &fh
->pendingReads
);
1039 struct DosPacket
*dp
= (struct DosPacket
*) msg
->mn_Node
.ln_Name
;
1043 replypkt2(dp
, 0, 0);
1044 fh
->flags
&= ~FHFLG_EOF
;
1047 if (IsListEmpty(&fh
->pendingReads
))
1048 fh
->flags
&= ~FHFLG_READPENDING
;
1051 } /* if (fh->inputsize < INPUTBUFFER_SIZE) */
1055 if (fh
->inputsize
< INPUTBUFFER_SIZE
)
1058 do_write(fh
, &c
, 1);
1061 fh
->inputbuffer
[fh
->inputsize
++] = c
;
1062 fh
->inputstart
= fh
->inputsize
;
1063 fh
->inputpos
= fh
->inputsize
;
1073 Signal(fh
->breaktask
, 1L << (12 + inp
- INP_CTRL_C
));
1078 Completion(fh
, FALSE
);
1082 Completion(fh
, TRUE
);
1091 } /* while((inp = scan_input(fh, &c)) != INP_DONE) */
1096 BOOL
answer_write_request(struct filehandle
*fh
, struct DosPacket
*dp
)
1098 UBYTE
*buffer
= (UBYTE
*) dp
->dp_Arg2
;
1099 LONG length
= dp
->dp_Arg3
;
1101 #if RMB_FREEZES_OUTPUT
1102 struct Window
*conwindow
;
1104 conwindow
= ((struct ConUnit
*) fh
->conwriteio
.io_Unit
)->cu_Window
;
1106 while ((PeekQualifier() & IEQUALIFIER_RBUTTON
) && conwindow
&& (conwindow
== IntuitionBase
->ActiveWindow
))
1112 if ((dp
->dp_Port
->mp_Flags
& PF_ACTION
) == PA_SIGNAL
&& dp
->dp_Port
->mp_SigTask
)
1114 fh
->lastwritetask
= dp
->dp_Port
->mp_SigTask
;
1117 do_write(fh
, buffer
, length
);
1118 replypkt2(dp
, length
, 0);
1123 void answer_read_request(struct filehandle
*fh
, struct DosPacket
*dp
, ULONG dp_Arg3
)
1127 readlen
= (fh
->inputsize
< dp_Arg3
) ? fh
->inputsize
: dp_Arg3
;
1129 CopyMem(fh
->inputbuffer
, (UBYTE
*) dp
->dp_Arg2
, readlen
);
1130 CopyMem(fh
->inputbuffer
+ readlen
, fh
->inputbuffer
, fh
->inputsize
- readlen
);
1132 fh
->inputsize
-= readlen
;
1133 fh
->inputpos
-= readlen
;
1134 fh
->inputstart
-= readlen
;
1136 replypkt2(dp
, readlen
, 0);
1139 void HandlePendingReads(struct filehandle
*fh
)
1141 if (fh
->flags
& FHFLG_READPENDING
)
1143 struct DosPacket
*dp
;
1144 struct Message
*msg
, *next_msg
;
1146 ForeachNodeSafe(&fh
->pendingReads
, msg
, next_msg
)
1148 Remove((struct Node
*) msg
);
1149 dp
= (struct DosPacket
*) msg
->mn_Node
.ln_Name
;
1150 answer_read_request(fh
, dp
, dp
->dp_Arg3
);
1152 if (fh
->inputsize
== 0)
1156 if (IsListEmpty(&fh
->pendingReads
))
1157 fh
->flags
&= ~FHFLG_READPENDING
;
1162 fh
->flags
|= FHFLG_CANREAD
;
1163 fh
->canreadsize
= fh
->inputsize
;
1167 void con_read(struct filehandle
*fh
, struct DosPacket
*dp
)
1169 if (fh
->flags
& FHFLG_CANREAD
)
1171 ULONG readlen
= (fh
->canreadsize
< dp
->dp_Arg3
) ? fh
->canreadsize
: dp
->dp_Arg3
;
1173 answer_read_request(fh
, dp
, readlen
);
1175 fh
->canreadsize
-= readlen
;
1176 if (fh
->canreadsize
== 0)
1177 fh
->flags
&= ~FHFLG_CANREAD
;
1182 if (fh
->flags
& FHFLG_EOF
)
1184 replypkt2(dp
, 0, 0);
1185 fh
->flags
&= ~FHFLG_EOF
;
1189 AddTail((struct List
*) &fh
->pendingReads
, (struct Node
*) dp
->dp_Link
);
1190 fh
->flags
|= FHFLG_READPENDING
;