/* --- Copyright University of Sussex 1998. All rights reserved. --------- > File: C.x/x/ved/src/xvedrawin.p > Purpose: Multi Window VED - raw input "device" > Author: Jonathan Meyer, 20 July 1990 (see revisions) > Documentation: SYSDOC *XVED > Related Files: xved.p xvedoutput.p xvedevent.p xveddeclare.p */ #_INCLUDE 'xved_declare.ph' include sigdefs.ph; section $-xved; /************************************************************************ * Xved Raw Input ************************************************************************/ /* The procedure xved_rawin_add_string adds a string of characters to the input stream. xved_rawin_add_event adds a new event to the input stream. */ lconstant input_buffer = writeable initv(128), ;;; 128 character/event typeahead buf_size = 128, ; vars xvedcurrinputwin = false, ; lvars write_pos = 0, read_pos = 0, num_inputs = 0, in_read = false, ; define :inline lconstant ADVANCE_POS(pos); (pos fi_+ 1) fi_mod buf_size enddefine; define :inline lconstant BUF_ENTRY(pos); subscrv(pos fi_+ 1, input_buffer) enddefine; ;;; INTERNAL PROCEDURES ;;; Flush_in - ensure that input device events are up to date. define lconstant Flush_in; if xvedappcontext and num_inputs /== 0 then fast_XptAppTryEvents(xvedappcontext); endif; enddefine; ;;; Splices an event name and data into the device input stream define xved_rawin_add_event(window, name, data); lvars name, data, event_unit, next_pos, window; returnif((ADVANCE_POS(write_pos) ->> next_pos) == read_pos); false -> xvedcurrinputwin; ;;; set input at write position conspair(name, conspair(window, data)) -> BUF_ENTRY(write_pos); ;;; advance write position next_pos -> write_pos; ;;; increate char count - an event will also generate a single ;;; character output num_inputs fi_+ 1 -> num_inputs; unless in_read then if xvedisasynchronous then external_defer_apply(vedprocess_try_input) else XptSetXtWakeup() endif endunless; enddefine; ;;; Splices a string of characters into the device input stream. define xved_rawin_add_string(window, string); lvars n, string, next_pos, window, m; if window /== xvedcurrinputwin and window then ;;; change of window returnif((ADVANCE_POS(write_pos) ->> next_pos) == read_pos); window ->> xvedcurrinputwin -> BUF_ENTRY(write_pos); next_pos -> write_pos; num_inputs fi_+ 1 -> num_inputs; endif; unless string then ;;; n chars and n on the stack if (() ->> n) fi_> 16 then consstring(n) -> string endif endunless; if string and datalength(string) fi_> 16 then ;;; make a character 'repeater' returnif((ADVANCE_POS(write_pos) ->> next_pos) == read_pos); consvector(1, string, 2) -> BUF_ENTRY(write_pos); next_pos -> write_pos; num_inputs fi_+ 1 -> num_inputs else if string then deststring(string) -> n endif; ;;; n chars now on stack n -> m; until n == 0 do ;;; set character at write position and advance write position. quitif((ADVANCE_POS(write_pos) ->> next_pos) == read_pos); subscr_stack(n) -> BUF_ENTRY(write_pos); next_pos -> write_pos; num_inputs fi_+ 1 -> num_inputs; n fi_- 1 -> n enduntil; erasenum(m); endif; unless in_read then if xvedisasynchronous then external_defer_apply(vedprocess_try_input) else XptSetXtWakeup() endif endunless; enddefine; /* ======== Ved Screen Input Hooks ============================ */ ;;; returns true if the next input is an event for window of specified type define xved_is_next_event(window, type); lvars window, type, input; num_inputs /== 0 and ved_char_in_stream == [] and (BUF_ENTRY(read_pos) ->> input).ispair and type == fast_front(input) and window == fast_front(fast_back(input)); enddefine; ;;; returns true if input waiting define :XVED_FOR vedscr_input_waiting() /* -> bool */; returnif(in_read)(false); Flush_in(); num_inputs /== 0 and num_inputs; enddefine; ;;; clears any stuff on input buffer define :XVED_FOR vedscr_clear_input(); Flush_in(); 0 ->> write_pos ->> read_pos -> num_inputs; false -> xvedcurrinputwin enddefine; ;;; read char/proc input, blocking until characters are available define lconstant Read_input(allow_events) -> input; lvars allow_events, input = false, event, n, string, save_busy; define lconstant raise_timeout = xved_rawin_add_event(%false, "readTimeout", false%) enddefine; define lconstant block_input(); wvedwindow -> xvedblockinput; XptBusyCursorOn -> save_busy; false -> XptBusyCursorFeedback(wvedwindow.xvedwin_shell); true -> XptBusyCursorOn; enddefine; define lconstant exit_action(); if xvedblockinput then false -> xvedblockinput; true -> XptBusyCursorFeedback(wvedwindow.xvedwin_shell); save_busy -> XptBusyCursorOn endif; false -> sys_timer(raise_timeout) enddefine; dlocal 0 % , if dlocal_context fi_<= 2 then ;;; not suspend/resume exit_action() endif%; ;;; flush output first - then flush input buffer vedscr_flush_output(); Flush_in(); dlocal in_read = true; false -> fast_subscrv(1, xvedrawdevindata); ;;; reset event vector if isinteger(pop_timeout_secs) then pop_timeout_secs * 1e6 -> sys_timer(raise_timeout) endif; repeat ;;; until we've got something to return while num_inputs == 0 do if ved_char_in_stream /== [] and (allow_events or isinteger(hd(ved_char_in_stream)->>input) or isstring(input)) then return(vedgetinput() -> input) endif; ;;; wait for inputs unless allow_events or xvedblockinput then block_input() endunless; xved_rawin_read_trap() endwhile; BUF_ENTRY(read_pos) -> input; if input.isvector then ;;; character repeater fast_subscrv(1,input) -> n; fast_subscrv(2,input) -> string; n fi_+ 1 -> fast_subscrv(1,input); fast_subscrs(n,string) -> input; returnunless(n == datalength(string)) endif; ADVANCE_POS(read_pos) -> read_pos; num_inputs fi_- 1 -> num_inputs; returnif(input.isinteger); if input.ispair then ;;; event sys_grbg_destpair(input) -> (fast_subscrv(1, xvedrawdevindata), fast_subscrv(2, xvedrawdevindata)); fast_subscrv(1, xvedrawdevindata) -> event; if event == "readTimeout" then ;;; test still an integer, just in case if pop_timeout_secs.isinteger then pop_timeout() endif; elseif event == "userInterrupt" then sys_raise_ast(SIG_INT); elseif allow_events then return(xved_process_event -> input) else unless xvedblockinput then block_input() endunless; ;;; when xvedblockinput is set, only events whose handlers ;;; have a pair in the pdprops are actioned xved_process_event() endif else ;;; window change for character input ;;; (next test stops xved_select_window being called when ;;; wvedwindow is set temporarily to some window) if input /== wvedwindow then xved_select_window(input) endif endif endrepeat enddefine; define :XVED_FOR vedscr_read_input(); Read_input(true) enddefine; define :XVED_FOR vedscr_read_ascii(); Read_input(false) enddefine; endsection; /* --- Revision History --------------------------------------------------- --- John Gibson, Sep 28 1998 Added guard test input /== wvedwindow around call of xved_select_window in Read_input. --- John Gibson, Apr 14 1994 Xpt*DeferApply -> external_defer_apply --- John Gibson, Jan 15 1994 Allowed xved_rawin_add_string to take false for ______string arg meaning n chars ... n on the stack --- John Gibson, Jan 13 1994 Merged vedscr_read_input and vedscr_read_ascii so that the latter doesn't set the busy cursor if input is already waiting --- John Gibson, Dec 12 1991 Moved initialisation of -save_busy- to dlocal entry action --- John Gibson, Dec 1 1991 Got rid of unnecessary procedures --- Jonathan Meyer, Sep 3 1991 Added xved_is_next_event --- Jonathan Meyer, Sep 2 1991 vedscr_read_ascii now changes to busy cursor in all but the wvedwindow --- John Gibson, Aug 29 1991 Uses system vedprocess_try_input instead of Xved_try_input --- John Gibson, Aug 26 1991 Made xved_rawin_add_string deal with long strings by constructing character repeaters --- John Gibson, Aug 10 1991 Made input_buffer writeable --- John Gibson, Aug 3 1991 Altered to handle window changes directly in input queue. --- John Gibson, Aug 3 1991 --- Jonathan Meyer, Jul 27 1991 advance_pos -> ADVANCE_POS, buf_entry -> BUF_ENTRY --- Jonathan Meyer, Jul 5 1991 Made read loop test num_inputs rather than xved*hasinputwaiting Removed xved*hasinputwaiting --- Jonathan Meyer, Jul 5 1991 Added Xved_try_input and test of xvedisasynchronous --- John Gibson, Jun 26 1991 Undid last change ... --- Jonathan Meyer, Jun 25 1991 Changed vedscr_read_ascii to set rawin_read_trap to syshibernate --- John Gibson, Jun 18 1991 Fixed timeout processing --- Jonathan Meyer, Jun 5 1991 Added dlocal to xvedblockinput --- Jonathan Meyer, Jun 4 1991 Added vedscr_read_ascii --- Jonathan Meyer, Jun 4 1991 Made pop_timeout clear as an exit action --- Jonathan Meyer, Jun 4 1991 Added pop_timeout check --- Jonathan Meyer, May 31 1991 Added in_read local --- Jonathan Meyer, Apr 9 1991 Made device only return one character at a time. Re-instated switching to old device when not(iscaller(vedprocess)) --- Jonathan Meyer, Apr 7 1991 Tidied --- Jonathan Meyer, Apr 5 1991 Incorporated johng's XptSetXtWakeup. Rewrote Read to process inputs in the buffer one at a time. --- Jonathan Meyer, Apr 4 1991 Added called_by_ved to stop rawcharin from returning event chars. Modified xved_rawin_read_trap for <14.02 poplog so that it calls XptAppTryEvents. --- Jonathan Meyer, Mar 30 1991 Changed representation of input buffer from list to vector. Added BUF_ENTRY and ADVANCE_POS macros. Made buffer 128 entries long. --- Jonathan Meyer, Mar 29 1991 Fixed call to xvedoldrawdevin device when not editing. --- Jonathan Meyer, Mar 8 1991 Modified so that the device returns XV_EVENT_CHAR as a character when there is an event that needs dealing with. This character is dealt with by ved by calling xved_handle_event, which unpacks the event and calls xved_raw_dispatch_event. --- Jonathan Meyer, Feb 17 1991 Revised handling of interrupts --- Jonathan Meyer, Dec 12 1990 Added events to user input queue. Added dispatcher and other event Management routines --- Jonathan Meyer, Dec 2 1990 Rewrote in terms of user device - added xved_raw_read_trap, and renamed xved_select_window wved_select_window. --- Jonathan Meyer, Nov 16 1990 Removed rawcharin - can be written in terms of vedinascii. Used xved_select_window to check event window is current window --- Jonathan Meyer, Oct 9 1990 Removed uses keysym.p - defined used keysyms locally instead. */