MODULE CommObxStreamsClient;
(**
project = "BlackBox"
organization = "www.oberon.ch"
contributors = "Oberon microsystems"
version = "System/Rsrc/About"
copyright = "System/Rsrc/About"
license = "Docu/BB-License"
changes = ""
issues = ""
**)
IMPORT Services, CommStreams, TextModels, TextControllers, StdLog;
CONST
protocol = "CommTCP"; (* driver for TCP/IP communication, over Winsock *)
remoteAdr = "127.0.0.1:900"; (* loopback address, so you can test on your local machine;
choose a port number that is not used yet (here: 900).
You could also specify an IP address in the form
"mymachine.mydomain.com:900" *)
localAdr = ""; (* don't specify an address or port on the client side *)
TYPE
Sender = POINTER TO RECORD (Services.Action)
prev, succ: Sender; (* linked to allow stopping upon module unloading *)
stream: CommStreams.Stream; (* during sending, the communicates through this object *)
idx, len: INTEGER; (* index for start of data into the buf array, and length remaining to be sent *)
buf: ARRAY 256 OF BYTE (* data to be sent *)
END;
VAR
senders: Sender;
PROCEDURE (s: Sender) Do;
VAR written: INTEGER;
BEGIN
IF s.stream.IsConnected() THEN
s.stream.WriteBytes(s.buf, s.idx, s.len, written); (* poll for outgoing data *)
INC(s.idx, written); DEC(s.len, written);
IF s.len > 0 THEN (* keep action alive if there remains further data to send *)
Services.DoLater(s, Services.now)
ELSE
s.stream.Close;
IF s.prev # NIL THEN s.prev.succ := s.succ ELSE senders := s.succ END;
IF s.succ # NIL THEN s.succ.prev := s.prev END
END
ELSE (* connection was closed by server *)
IF s.prev # NIL THEN s.prev.succ := s.succ ELSE senders := s.succ END;
IF s.succ # NIL THEN s.succ.prev := s.prev END;
IF s.idx = 0 THEN StdLog.String("client: connection was not accepted by server")
ELSE StdLog.String("client: connection was closed by server")
END;
StdLog.Ln
END
END Do;
PROCEDURE Start (s: Sender);
VAR stream: CommStreams.Stream; res: INTEGER;
BEGIN
CommStreams.NewStream(protocol, localAdr, remoteAdr, stream, res);
IF stream # NIL THEN
s.prev := NIL; s.succ := senders; senders := s;
IF s.succ # NIL THEN s.succ.prev := s END;
s.stream := stream;
Services.DoLater(s, Services.now);
StdLog.String("client: connection opened"); StdLog.Ln
ELSE
StdLog.String("client: error opening the connection ("); StdLog.Int(res); StdLog.Char(")"); StdLog.Ln
END
END Start;
PROCEDURE Stop;
BEGIN
WHILE senders # NIL DO
senders.stream.Close; Services.RemoveAction(senders);
senders := senders.succ
END
END Stop;
PROCEDURE SendTextSelection*;
VAR c: TextControllers.Controller; beg, end, i, len: INTEGER; rd: TextModels.Reader; ch: CHAR; s: Sender;
BEGIN
c := TextControllers.Focus();
IF (c # NIL) & c.HasSelection() THEN
NEW(s);
c.GetSelection(beg, end);
rd := c.text.NewReader(NIL); rd.SetPos(beg);
i := 0; len := end - beg;
IF len >= LEN(s.buf) - 1 THEN len := LEN(s.buf) - 1 END; (* clip string if necessary *)
WHILE len # 0 DO
rd.ReadChar(ch);
IF ch < 100X THEN (* skip Unicode characters *)
s.buf[i] := SHORT(SHORT(ORD(ch))); INC(i)
END;
DEC(len)
END;
s.idx := 0; s.len := i;
Start(s)
ELSE
StdLog.String("client: no text selection found"); StdLog.Ln
END
END SendTextSelection;
CLOSE
Stop (* prevent the client from trapping after module unloading *)
END CommObxStreamsClient.
CommObxStreamsClient.SendTextSelection