2 Copyright © 1995-2011, The AROS Development Team. All rights reserved.
5 Desc: Support functions for console handler.
9 /****************************************************************************************/
11 #define CYCLIC_HISTORY_WALK 0
13 /****************************************************************************************/
16 #include <proto/exec.h>
17 #include <exec/libraries.h>
18 #include <exec/resident.h>
19 #include <exec/memory.h>
21 #include <exec/errors.h>
22 #include <exec/alerts.h>
23 #include <utility/tagitem.h>
24 #include <dos/exall.h>
25 #include <dos/dosasl.h>
26 #include <intuition/intuition.h>
27 #include <intuition/sghooks.h>
28 #include <proto/dos.h>
29 #include <proto/intuition.h>
30 #include <proto/input.h>
31 #include <devices/conunit.h>
35 #include <aros/debug.h>
41 #include "con_handler_intern.h"
43 #include "completion.h"
45 #define ioReq(x) ((struct IORequest *)x)
47 void replypkt(struct DosPacket
*dp
, SIPTR res1
)
54 mn
->mn_Node
.ln_Name
= (char*)dp
;
55 dp
->dp_Port
= &((struct Process
*)FindTask(NULL
))->pr_MsgPort
;
59 void replypkt2(struct DosPacket
*dp
, SIPTR res1
, SIPTR res2
)
66 /******************************************************************************************/
68 static const UBYTE up_seq
[] = {'A'};
69 static const UBYTE down_seq
[] = {'B'};
70 static const UBYTE right_seq
[] = {'C'};
71 static const UBYTE left_seq
[] = {'D'};
72 static const UBYTE shift_up_seq
[] = {'T'};
73 static const UBYTE shift_down_seq
[] = {'S'};
74 static const UBYTE shift_right_seq
[] = {' ', '@'};
75 static const UBYTE shift_left_seq
[] = {' ', 'A'};
76 static const UBYTE shift_tab_seq
[] = {'Z'};
77 static const UBYTE help_seq
[] = {'?', '~'};
78 static const UBYTE f1_seq
[] = {'0', '~'};
79 static const UBYTE f2_seq
[] = {'1', '~'};
80 static const UBYTE f3_seq
[] = {'2', '~'};
81 static const UBYTE f4_seq
[] = {'3', '~'};
82 static const UBYTE f5_seq
[] = {'4', '~'};
83 static const UBYTE f6_seq
[] = {'5', '~'};
84 static const UBYTE f7_seq
[] = {'6', '~'};
85 static const UBYTE f8_seq
[] = {'7', '~'};
86 static const UBYTE f9_seq
[] = {'8', '~'};
87 static const UBYTE f10_seq
[] = {'9', '~'};
88 static const UBYTE paste_seq
[] = {'0', ' ', 'v'};
89 static const UBYTE f11_seq
[] = {'2', '0', '~'};
90 static const UBYTE f12_seq
[] = {'2', '1', '~'};
91 static const UBYTE shift_f1_seq
[] = {'1', '0', '~'};
92 static const UBYTE shift_f2_seq
[] = {'1', '1', '~'};
93 static const UBYTE shift_f3_seq
[] = {'1', '2', '~'};
94 static const UBYTE shift_f4_seq
[] = {'1', '3', '~'};
95 static const UBYTE shift_f5_seq
[] = {'1', '4', '~'};
96 static const UBYTE shift_f6_seq
[] = {'1', '5', '~'};
97 static const UBYTE shift_f7_seq
[] = {'1', '6', '~'};
98 static const UBYTE shift_f8_seq
[] = {'1', '7', '~'};
99 static const UBYTE shift_f9_seq
[] = {'1', '8', '~'};
100 static const UBYTE shift_f10_seq
[] = {'1', '9', '~'};
101 static const UBYTE shift_f11_seq
[] = {'3', '0', '~'};
102 static const UBYTE shift_f12_seq
[] = {'3', '1', '~'};
103 static const UBYTE insert_seq
[] = {'4', '0', '~'};
104 static const UBYTE pageup_seq
[] = {'4', '1', '~'};
105 static const UBYTE pagedown_seq
[] = {'4', '2', '~'};
106 static const UBYTE pause_seq
[] = {'4', '3', '~'};
107 static const UBYTE break_seq
[] = {'5', '3', '~'};
108 static const UBYTE home_seq
[] = {'4', '4', '~'};
109 static const UBYTE end_seq
[] = {'4', '5', '~'};
110 static const UBYTE shift_insert_seq
[] = {'5', '0', '~'};
111 static const UBYTE shift_pageup_seq
[] = {'5', '1', '~'};
112 static const UBYTE shift_pagedown_seq
[] = {'5', '2', '~'};
113 static const UBYTE shift_home_seq
[] = {'5', '4', '~'};
114 static const UBYTE shift_end_seq
[] = {'5', '5', '~'};
116 /* F11, F12, insert, pageup, pagedown, ... seq taken from
117 RKRM: Devices/Console/Reading from the Console Device/Information about the Input Stream */
119 static CONST
struct csimatch
127 {up_seq
, 1, INP_CURSORUP
},
128 {down_seq
, 1, INP_CURSORDOWN
},
129 {right_seq
, 1, INP_CURSORRIGHT
},
130 {left_seq
, 1, INP_CURSORLEFT
},
131 {shift_up_seq
, 1, INP_SHIFT_CURSORUP
},
132 {shift_down_seq
, 1, INP_SHIFT_CURSORDOWN
},
133 {shift_right_seq
, 2, INP_SHIFT_CURSORRIGHT
},
134 {shift_left_seq
, 2, INP_SHIFT_CURSORLEFT
},
135 {shift_tab_seq
, 1, INP_SHIFT_TAB
},
136 {help_seq
, 2, INP_HELP
},
137 {f1_seq
, 2, INP_F1
},
138 {f2_seq
, 2, INP_F2
},
139 {f3_seq
, 2, INP_F3
},
140 {f4_seq
, 2, INP_F4
},
141 {f5_seq
, 2, INP_F5
},
142 {f6_seq
, 2, INP_F6
},
143 {f7_seq
, 2, INP_F7
},
144 {f8_seq
, 2, INP_F8
},
145 {f9_seq
, 2, INP_F9
},
146 {f10_seq
, 2, INP_F10
},
147 {f11_seq
, 3, INP_F11
},
148 {f12_seq
, 3, INP_F12
},
149 {shift_f1_seq
, 3, INP_SHIFT_F1
},
150 {shift_f2_seq
, 3, INP_SHIFT_F2
},
151 {shift_f3_seq
, 3, INP_SHIFT_F3
},
152 {shift_f4_seq
, 3, INP_SHIFT_F4
},
153 {shift_f5_seq
, 3, INP_SHIFT_F5
},
154 {shift_f6_seq
, 3, INP_SHIFT_F6
},
155 {shift_f7_seq
, 3, INP_SHIFT_F7
},
156 {shift_f8_seq
, 3, INP_SHIFT_F8
},
157 {shift_f9_seq
, 3, INP_SHIFT_F9
},
158 {shift_f10_seq
, 3, INP_SHIFT_F10
},
159 {shift_f11_seq
, 3, INP_SHIFT_F11
},
160 {shift_f12_seq
, 3, INP_SHIFT_F12
},
161 {insert_seq
, 3, INP_INSERT
},
162 {pageup_seq
, 3, INP_PAGEUP
},
163 {pagedown_seq
, 3, INP_PAGEDOWN
},
164 {pause_seq
, 3, INP_PAUSE
},
165 {break_seq
, 3, INP_BREAK
},
166 {home_seq
, 3, INP_HOME
},
167 {end_seq
, 3, INP_END
},
168 {shift_insert_seq
, 3, INP_SHIFT_INSERT
},
169 {shift_pageup_seq
, 3, INP_SHIFT_PAGEUP
},
170 {shift_pagedown_seq
, 3, INP_SHIFT_PAGEDOWN
},
171 {shift_home_seq
, 3, INP_SHIFT_HOME
},
172 {shift_end_seq
, 3, INP_SHIFT_END
},
173 {paste_seq
, 3, INP_PASTE
},
178 /******************************************************************************************/
180 static UBYTE
hex2val(char c
)
182 if (c
>= '0' && c
<= '9')
187 /* strtoul() not used because it is much larger and uses .bss
188 * TODO: Sanity checks. */
189 static IPTR
string2val(const char *s
, WORD len
)
193 if (s
[0] == '0' && (s
[1] == 'x' || s
[1] == 'X')) {
195 while (len
-- > 0 && *s
) {
201 while (len
-- > 0 && *s
) {
210 BOOL
parse_filename(struct filehandle
*fh
, char *filename
, struct NewWindow
*nw
)
216 BOOL ok
= TRUE
, done
= FALSE
, paramok
= FALSE
;
218 ASSERT_VALID_PTR(fh
);
219 ASSERT_VALID_PTR(nw
);
222 ASSERT_VALID_PTR(param
);
255 UWORD paramlen
= filename
- param
- 1;
260 nw
->LeftEdge
= paramval
;
264 nw
->TopEdge
= paramval
;
268 nw
->Width
= paramval
;
272 nw
->Height
= paramval
;
276 if ((fh
->wintitle
= AllocVec(paramlen
+ 1, MEMF_PUBLIC
)))
278 CopyMem(param
, fh
->wintitle
, paramlen
);
279 fh
->wintitle
[paramlen
] = '\0';
280 nw
->Title
= fh
->wintitle
;
285 if (!strnicmp(param
, "WAIT", paramlen
))
287 fh
->flags
|= FHFLG_WAIT
;
289 else if (!strnicmp(param
, "CLOSE", paramlen
))
291 nw
->Flags
|= WFLG_CLOSEGADGET
;
293 else if (!strnicmp(param
, "NOCLOSE", paramlen
))
295 nw
->Flags
&= ~WFLG_CLOSEGADGET
;
297 else if (!strnicmp(param
, "AUTO", paramlen
))
299 fh
->flags
|= FHFLG_AUTO
;
301 else if (!strnicmp(param
, "INACTIVE", paramlen
))
303 nw
->Flags
&= ~WFLG_ACTIVATE
;
305 else if (!strnicmp(param
, "NODEPTH", paramlen
))
307 nw
->Flags
&= ~WFLG_DEPTHGADGET
;
309 else if (!strnicmp(param
, "NOSIZE", paramlen
))
311 nw
->Flags
&= ~WFLG_SIZEGADGET
;
313 else if (!strnicmp(param
, "NODRAG", paramlen
))
315 nw
->Flags
&= ~WFLG_DRAGBAR
;
317 else if (!strnicmp(param
, "NOBORDER", paramlen
))
319 nw
->Flags
|= WFLG_BORDERLESS
;
321 else if (!strnicmp(param
, "BACKDROP", paramlen
))
323 nw
->Flags
|= WFLG_BACKDROP
;
324 nw
->Flags
&= ~(WFLG_DRAGBAR
| WFLG_SIZEGADGET
);
326 else if (!strnicmp(param
, "SIMPLE", paramlen
))
330 else if (!strnicmp(param
, "SMART", paramlen
))
334 else if (!strnicmp(param
, "ALT", paramlen
))
336 /* TODO: style "ALT30/30/200/200" */
338 else if (!strnicmp(param
, "WINDOW", 6))
340 /* Do we need some sanity checks here? */
341 fh
->otherwindow
= (struct Window
*)string2val(param
+ 6, paramlen
- 6);
343 else if (!strnicmp(param
, "SCREEN", 6))
345 if ((fh
->screenname
= AllocVec(paramlen
- 5, MEMF_PUBLIC
)))
347 CopyMem(param
+ 6, fh
->screenname
, paramlen
- 6);
348 fh
->screenname
[paramlen
- 6] = '\0';
353 } /* switch(paramid) */
376 } /* while (!done) */
381 /******************************************************************************************/
384 void do_write(struct filehandle
*fh
, APTR data
, ULONG length
)
386 fh
->conwriteio
.io_Command
= CMD_WRITE
;
387 fh
->conwriteio
.io_Data
= data
;
388 fh
->conwriteio
.io_Length
= length
;
390 DoIO((struct IORequest
*)&fh
->conwriteio
);
393 /******************************************************************************************/
395 void do_movecursor(struct filehandle
*fh
, UBYTE direction
, UBYTE howmuch
)
397 UBYTE seq
[6]; /* 9B <N> <N> <N> <dir> <0> */
409 sprintf(&seq
[1],"%d%c", howmuch
, direction
);
413 do_write(fh
, seq
, size
);
417 /******************************************************************************************/
419 void do_cursorvisible(struct filehandle
*fh
, BOOL on
)
425 if (!on
) seq
[size
++] = '0';
429 do_write(fh
, seq
, size
);
432 /******************************************************************************************/
434 void do_deletechar(struct filehandle
*fh
)
436 UBYTE seq
[] = {0x9B, 'P'};
438 do_write(fh
, seq
, 2);
441 /******************************************************************************************/
443 void do_eraseinline(struct filehandle
*fh
)
445 UBYTE seq
[] = {0x9B, 'K'};
447 do_write(fh
, seq
, 2);
450 /******************************************************************************************/
452 void do_eraseindisplay(struct filehandle
*fh
)
454 UBYTE seq
[] = {0x9B, 'J'};
456 do_write(fh
, seq
, 2);
458 /******************************************************************************************/
459 static void copy_from_pastebuf(struct filehandle
* fh
)
461 if (fh
->conbufferpos
>= fh
->conbuffersize
&&
463 fh
->pastebufferpos
< fh
->pastebuffersize
)
465 ULONG len
= CONSOLEBUFFER_SIZE
;
466 ULONG pastelen
= fh
->pastebuffersize
- fh
->pastebufferpos
;
467 if (pastelen
< len
) len
= pastelen
;
469 D(bug("Copying %d bytes from paste buffer\n",len
));
471 fh
->conbufferpos
= 0;
472 CopyMem(fh
->pastebuffer
+ fh
->pastebufferpos
,
475 fh
->conbuffersize
= len
;
476 fh
->pastebufferpos
+= len
;
477 if (fh
->pastebufferpos
>= fh
->pastebuffersize
) {
478 FreeMem(fh
->pastebuffer
,PASTEBUFSIZE
);
484 WORD
scan_input(struct filehandle
*fh
, UBYTE
*buffer
)
486 CONST
struct csimatch
*match
;
488 WORD result
= INP_DONE
;
490 copy_from_pastebuf(fh
);
492 if (fh
->conbufferpos
< fh
->conbuffersize
)
494 c
= fh
->consolebuffer
[fh
->conbufferpos
++];
495 D(bug("scan_input: check char %d\n",c
));
502 result
= INP_CTRL_C
- 3 + (WORD
)c
;
506 /* FIXME: Ugh... Race condition, anyone? The qualifier might
507 have changed between the keypress and the time we do this */
508 if (PeekQualifier() & (IEQUALIFIER_LSHIFT
| IEQUALIFIER_RSHIFT
))
510 result
= INP_SHIFT_BACKSPACE
;
512 result
= INP_BACKSPACE
;
521 result
= INP_LINEFEED
;
524 case 12: /* CTRL-L */
526 result
= INP_ECHO_STRING
;
534 if (PeekQualifier() & (IEQUALIFIER_LSHIFT
| IEQUALIFIER_RSHIFT
))
536 result
= INP_SHIFT_DELETE
;
543 result
= INP_CONTROL_X
;
546 case 28: /* CTRL-\ */
551 result
= INP_UNKNOWN
;
553 match
= csimatchtable
;
554 for(;match
->seq
;match
++)
556 if (!strncmp(match
->seq
, &(fh
->consolebuffer
[fh
->conbufferpos
]), match
->len
))
559 fh
->conbufferpos
+= match
->len
;
573 } /* if (fh->conbufferpos < fh->conbuffersize) */
575 D(bug("scan_input: result %d\n",result
));
580 /******************************************************************************************/
582 void add_to_history(struct filehandle
*fh
)
584 BOOL add_to_history
= FALSE
;
586 fh
->inputbuffer
[fh
->inputsize
] = '\0';
588 /* Don't add emptry strings */
589 if (fh
->inputbuffer
[fh
->inputstart
] == '\0') return;
591 if (fh
->historysize
== 0)
593 add_to_history
= TRUE
;
599 old_historypos
= fh
->historypos
- 1;
600 if (old_historypos
< 0) old_historypos
= fh
->historysize
- 1;
602 if (strcmp(&fh
->inputbuffer
[fh
->inputstart
], fh
->historybuffer
[old_historypos
]))
604 /* add to history only if different from last history entry */
606 add_to_history
= TRUE
;
612 if (fh
->historysize
< CMD_HISTORY_SIZE
) fh
->historysize
++;
614 strcpy(fh
->historybuffer
[fh
->historypos
], &fh
->inputbuffer
[fh
->inputstart
]);
617 if (fh
->historypos
>= CMD_HISTORY_SIZE
) fh
->historypos
= 0;
620 fh
->historyviewpos
= fh
->historypos
;
623 /******************************************************************************************/
625 void history_walk(struct filehandle
*fh
, WORD inp
)
629 #if !CYCLIC_HISTORY_WALK
630 BOOL walk_to_empty_string
= FALSE
;
636 case INP_SHIFT_CURSORUP
:
637 fh
->historyviewpos
= 0;
640 case INP_SHIFT_CURSORDOWN
:
641 fh
->historyviewpos
= fh
->historysize
- 1;;
645 #if CYCLIC_HISTORY_WALK
646 fh
->historyviewpos
--;
647 if (fh
->historyviewpos
< 0) fh
->historyviewpos
= fh
->historysize
- 1;
649 if (fh
->historyviewpos
!= -1)
651 fh
->historyviewpos
--;
652 if (fh
->historyviewpos
< 0
653 && fh
->historysize
== CMD_HISTORY_SIZE
)
654 fh
->historyviewpos
= CMD_HISTORY_SIZE
- 1;
655 if (fh
->historyviewpos
== fh
->historypos
)
656 fh
->historyviewpos
= -1;
658 if (fh
->historyviewpos
== -1)
659 walk_to_empty_string
= TRUE
;
664 #if CYCLIC_HISTORY_WALK
665 fh
->historyviewpos
++;
666 if (fh
->historyviewpos
>= fh
->historysize
) fh
->historyviewpos
= 0;
668 if (fh
->historyviewpos
!= fh
->historypos
)
670 if (fh
->historyviewpos
== -1
671 && fh
->historysize
== CMD_HISTORY_SIZE
)
672 fh
->historyviewpos
= fh
->historypos
;
673 fh
->historyviewpos
= (fh
->historyviewpos
+ 1)
676 if (fh
->historyviewpos
== fh
->historypos
)
677 walk_to_empty_string
= TRUE
;
682 if (fh
->inputpos
> fh
->inputstart
)
684 do_movecursor(fh
, CUR_LEFT
, fh
->inputpos
- fh
->inputstart
);
689 fh
->inputsize
= fh
->inputstart
;
690 fh
->inputpos
= fh
->inputstart
;
692 #if !CYCLIC_HISTORY_WALK
693 if (!walk_to_empty_string
)
696 len
= strlen(fh
->historybuffer
[fh
->historyviewpos
]);
697 if (len
> (INPUTBUFFER_SIZE
- fh
->inputstart
))
699 len
= INPUTBUFFER_SIZE
- fh
->inputstart
;
704 CopyMem(fh
->historybuffer
[fh
->historyviewpos
],
705 &fh
->inputbuffer
[fh
->inputstart
],
708 fh
->inputsize
+= len
;
711 do_write(fh
, &fh
->inputbuffer
[fh
->inputstart
], len
);
714 #if !CYCLIC_HISTORY_WALK
715 } /* if (!walk_to_empty_string) */
718 } /* if (fh->historysize) */
721 /****************************************************************************************/
723 static const STRPTR CONCLIP_PORTNAME
= "ConClip.rendezvous";
732 static void do_paste(struct filehandle
* fh
)
734 struct MsgPort replyport
, *port
;
736 struct MyEditHookMsg msg
;
737 struct StringInfo sinfo
;
739 if (!(port
= FindPort(CONCLIP_PORTNAME
))) {
740 D(bug("ConClip not running, but we got a ConClip paste request"));
744 D(bug("PASTE REQUEST!\n"));
746 replyport
.mp_Node
.ln_Type
= NT_MSGPORT
;
747 replyport
.mp_Node
.ln_Name
= NULL
;
748 replyport
.mp_Node
.ln_Pri
= 0;
749 replyport
.mp_Flags
= PA_SIGNAL
;
750 replyport
.mp_SigBit
= SIGB_SINGLE
;
751 replyport
.mp_SigTask
= FindTask(NULL
);
752 NEWLIST(&replyport
.mp_MsgList
);
754 msg
.msg
.mn_Node
.ln_Type
= NT_MESSAGE
;
755 msg
.msg
.mn_ReplyPort
= &replyport
;
756 msg
.msg
.mn_Length
= sizeof(msg
);
761 /* FIXME: Ensure no fields are left uninitialized */
764 sgw
.WorkBuffer
= AllocMem(PASTEBUFSIZE
,MEMF_CLEAR
| MEMF_ANY
);
771 sgw
.EditOp
= EO_BIGCHANGE
;
775 /* ConClip only ever looks at MaxChars in StringInfo */
776 sinfo
.MaxChars
= PASTEBUFSIZE
;
777 sgw
.StringInfo
= &sinfo
;
779 SetSignal(0, SIGF_SINGLE
);
780 PutMsg(port
, &msg
.msg
);
781 WaitPort(&replyport
);
783 D(bug("Pasting %d bytes\n",sgw
.BufferPos
));
785 if (fh
->pastebuffer
) FreeMem(fh
->pastebuffer
,PASTEBUFSIZE
);
786 fh
->pastebuffer
= sgw
.WorkBuffer
;
787 fh
->pastebuffersize
= sgw
.BufferPos
;
788 fh
->pastebufferpos
= 0;
792 /****************************************************************************************/
794 BOOL
process_input(struct filehandle
*fh
)
798 while((inp
= scan_input(fh
, &c
)) != INP_DONE
)
800 D(bug("Input Code: %d\n",inp
));
805 if (fh
->inputpos
> fh
->inputstart
)
808 do_movecursor(fh
, CUR_LEFT
, 1);
812 case INP_SHIFT_CURSORLEFT
: /* move to beginning of line */
814 if (fh
->inputpos
> fh
->inputstart
)
816 do_movecursor(fh
, CUR_LEFT
, fh
->inputpos
- fh
->inputstart
);
817 fh
->inputpos
= fh
->inputstart
;
821 case INP_CURSORRIGHT
:
822 if (fh
->inputpos
< fh
->inputsize
)
825 do_movecursor(fh
, CUR_RIGHT
, 1);
829 case INP_SHIFT_CURSORRIGHT
: /* move to end of line */
831 if (fh
->inputpos
!= fh
->inputsize
)
833 do_movecursor(fh
, CUR_RIGHT
, fh
->inputsize
- fh
->inputpos
);
834 fh
->inputpos
= fh
->inputsize
;
838 case INP_CURSORUP
: /* walk through cmd history */
840 case INP_SHIFT_CURSORUP
:
841 case INP_SHIFT_CURSORDOWN
:
842 history_walk(fh
, inp
);
846 if (fh
->inputpos
> fh
->inputstart
)
848 do_movecursor(fh
, CUR_LEFT
, 1);
850 if (fh
->inputpos
== fh
->inputsize
)
857 WORD chars_right
= fh
->inputsize
- fh
->inputpos
;
862 do_cursorvisible(fh
, FALSE
);
863 do_write(fh
, &fh
->inputbuffer
[fh
->inputpos
+ 1], chars_right
);
865 do_movecursor(fh
, CUR_LEFT
, chars_right
);
866 do_cursorvisible(fh
, TRUE
);
868 memmove(&fh
->inputbuffer
[fh
->inputpos
], &fh
->inputbuffer
[fh
->inputpos
+ 1], chars_right
);
874 case INP_SHIFT_BACKSPACE
:
875 if (fh
->inputpos
> fh
->inputstart
)
877 do_movecursor(fh
, CUR_LEFT
, fh
->inputpos
- fh
->inputstart
);
878 if (fh
->inputpos
== fh
->inputsize
)
882 fh
->inputpos
= fh
->inputsize
= fh
->inputstart
;
884 WORD chars_right
= fh
->inputsize
- fh
->inputpos
;
886 do_cursorvisible(fh
, FALSE
);
887 do_write(fh
, &fh
->inputbuffer
[fh
->inputpos
], chars_right
);
889 do_movecursor(fh
, CUR_LEFT
, chars_right
);
890 do_cursorvisible(fh
, TRUE
);
892 memmove(&fh
->inputbuffer
[fh
->inputstart
], &fh
->inputbuffer
[fh
->inputpos
], chars_right
);
894 fh
->inputsize
-= (fh
->inputpos
- fh
->inputstart
);
895 fh
->inputpos
= fh
->inputstart
;
901 if (fh
->inputpos
< fh
->inputsize
)
905 if (fh
->inputpos
== fh
->inputsize
)
909 WORD chars_right
= fh
->inputsize
- fh
->inputpos
;
911 do_cursorvisible(fh
, FALSE
);
912 do_write(fh
, &fh
->inputbuffer
[fh
->inputpos
+ 1], chars_right
);
914 do_movecursor(fh
, CUR_LEFT
, chars_right
);
915 do_cursorvisible(fh
, TRUE
);
917 memmove(&fh
->inputbuffer
[fh
->inputpos
], &fh
->inputbuffer
[fh
->inputpos
+ 1], chars_right
);
922 case INP_SHIFT_DELETE
:
923 if (fh
->inputpos
< fh
->inputsize
)
925 fh
->inputsize
= fh
->inputpos
;
931 if ((fh
->inputsize
- fh
->inputstart
) > 0)
933 if (fh
->inputpos
> fh
->inputstart
)
935 do_movecursor(fh
, CUR_LEFT
, fh
->inputpos
- fh
->inputstart
);
939 fh
->inputpos
= fh
->inputsize
= fh
->inputstart
;
943 case INP_ECHO_STRING
:
948 if (fh
->inputsize
< INPUTBUFFER_SIZE
)
952 if (fh
->inputpos
== fh
->inputsize
)
954 fh
->inputbuffer
[fh
->inputpos
++] = c
;
957 WORD chars_right
= fh
->inputsize
- fh
->inputpos
;
959 do_cursorvisible(fh
, FALSE
);
960 do_write(fh
, &fh
->inputbuffer
[fh
->inputpos
], chars_right
);
961 do_movecursor(fh
, CUR_LEFT
, chars_right
);
962 do_cursorvisible(fh
, TRUE
);
964 memmove(&fh
->inputbuffer
[fh
->inputpos
+ 1], &fh
->inputbuffer
[fh
->inputpos
], chars_right
);
965 fh
->inputbuffer
[fh
->inputpos
++] = c
;
972 D(bug("[CON] Read EOF (window closing)\n"));
974 if (fh
->flags
& FHFLG_WAITFORCLOSE
)
977 fh
->flags
|= FHFLG_EOF
;
978 if (fh
->flags
& FHFLG_AUTO
&& fh
->window
)
980 CloseWindow(fh
->window
);
987 if (fh
->inputsize
< INPUTBUFFER_SIZE
)
995 fh
->inputbuffer
[fh
->inputsize
++] = '\n';
998 fh
->inputstart
= fh
->inputsize
;
999 fh
->inputpos
= fh
->inputstart
;
1002 HandlePendingReads(fh
);
1004 if ((fh
->flags
& FHFLG_EOF
) && (fh
->flags
& FHFLG_READPENDING
))
1006 struct Message
*msg
= (struct Message
*)RemHead((struct List
*)&fh
->pendingReads
);
1007 struct DosPacket
*dp
= (struct DosPacket
*)msg
->mn_Node
.ln_Name
;
1011 replypkt2(dp
, 0, 0);
1012 fh
->flags
&= ~FHFLG_EOF
;
1015 if (IsListEmpty(&fh
->pendingReads
))
1016 fh
->flags
&= ~FHFLG_READPENDING
;
1019 } /* if (fh->inputsize < INPUTBUFFER_SIZE) */
1023 if (fh
->inputsize
< INPUTBUFFER_SIZE
)
1026 do_write(fh
, &c
, 1);
1029 fh
->inputbuffer
[fh
->inputsize
++] = c
;
1030 fh
->inputstart
= fh
->inputsize
;
1031 fh
->inputpos
= fh
->inputsize
;
1041 Signal(fh
->breaktask
, 1L << (12 + inp
- INP_CTRL_C
));
1055 } /* while((inp = scan_input(fh, &c)) != INP_DONE) */
1061 BOOL
answer_write_request(struct filehandle
*fh
, struct DosPacket
*dp
)
1063 UBYTE
*buffer
= (UBYTE
*)dp
->dp_Arg2
;
1064 LONG length
= dp
->dp_Arg3
;
1066 #if RMB_FREEZES_OUTPUT
1067 struct Window
*conwindow
;
1069 conwindow
= ((struct ConUnit
*)fh
->conwriteio
.io_Unit
)->cu_Window
;
1071 while((PeekQualifier() & IEQUALIFIER_RBUTTON
) &&
1072 conwindow
&& (conwindow
== IntuitionBase
->ActiveWindow
))
1078 if ((dp
->dp_Port
->mp_Flags
& PF_ACTION
) == PA_SIGNAL
&&
1079 dp
->dp_Port
->mp_SigTask
)
1081 fh
->lastwritetask
= dp
->dp_Port
->mp_SigTask
;
1085 do_write(fh
, buffer
, length
);
1086 replypkt2(dp
, length
, 0);
1091 void answer_read_request(struct filehandle
*fh
, struct DosPacket
*dp
, ULONG dp_Arg3
)
1095 readlen
= (fh
->inputsize
< dp_Arg3
) ? fh
->inputsize
: dp_Arg3
;
1097 CopyMem(fh
->inputbuffer
, (UBYTE
*)dp
->dp_Arg2
, readlen
);
1098 CopyMem(fh
->inputbuffer
+ readlen
, fh
->inputbuffer
, fh
->inputsize
- readlen
);
1100 fh
->inputsize
-= readlen
;
1101 fh
->inputpos
-= readlen
;
1102 fh
->inputstart
-= readlen
;
1104 replypkt2(dp
, readlen
, 0);
1107 void HandlePendingReads(struct filehandle
*fh
)
1109 if (fh
->flags
& FHFLG_READPENDING
)
1111 struct DosPacket
*dp
;
1112 struct Message
*msg
, *next_msg
;
1114 ForeachNodeSafe(&fh
->pendingReads
, msg
, next_msg
)
1116 Remove((struct Node
*)msg
);
1117 dp
= (struct DosPacket
*)msg
->mn_Node
.ln_Name
;
1118 answer_read_request(fh
, dp
, dp
->dp_Arg3
);
1120 if (fh
->inputsize
== 0)
1124 if (IsListEmpty(&fh
->pendingReads
))
1125 fh
->flags
&= ~FHFLG_READPENDING
;
1130 fh
->flags
|= FHFLG_CANREAD
;
1131 fh
->canreadsize
= fh
->inputsize
;
1135 void con_read(struct filehandle
*fh
, struct DosPacket
*dp
)
1137 if (fh
->flags
& FHFLG_CANREAD
)
1139 ULONG readlen
= (fh
->canreadsize
< dp
->dp_Arg3
) ? fh
->canreadsize
: dp
->dp_Arg3
;
1141 answer_read_request(fh
, dp
, readlen
);
1143 fh
->canreadsize
-= readlen
;
1144 if (fh
->canreadsize
== 0)
1145 fh
->flags
&= ~FHFLG_CANREAD
;
1150 if (fh
->flags
& FHFLG_EOF
)
1152 replypkt2(dp
, 0, 0);
1153 fh
->flags
&= ~FHFLG_EOF
;
1155 else if (fh
->flags
& FHFLG_RAW
)
1157 replypkt2(dp
, 0, 0);
1161 AddTail((struct List
*)&fh
->pendingReads
, (struct Node
*)dp
->dp_Link
);
1162 fh
->flags
|= FHFLG_READPENDING
;