MODULE CommObxStreamsClient;

   project   = "BlackBox"
   organization   = ""
   contributors   = "Oberon microsystems"
   version   = "System/Rsrc/About"
   copyright   = "System/Rsrc/About"
   license   = "Docu/BB-License"
   changes   = ""
   issues   = ""


   IMPORT Services, CommStreams, TextModels, TextControllers, StdLog;


      protocol = "CommTCP";         (* driver for TCP/IP communication, over Winsock *)
      remoteAdr = "";   (* 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
                                          "" *)
      localAdr = "";                     (* don't specify an address or port on the client side *)

      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 *)

      senders: Sender;
   PROCEDURE (s: Sender) Do;

      VAR written: INTEGER;
      IF THEN, 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 *)
            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
      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 Do;
   PROCEDURE Start (s: Sender);

      VAR stream: CommStreams.Stream; res: INTEGER;
      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; := stream;
         StdLog.String("client: connection opened"); StdLog.Ln
         StdLog.String("client: error opening the connection ("); StdLog.Int(res); StdLog.Char(")"); StdLog.Ln
   END Start;

      WHILE senders # NIL DO; Services.RemoveAction(senders);
         senders := senders.succ
   END Stop;
   PROCEDURE SendTextSelection*;

      VAR c: TextControllers.Controller; beg, end, i, len: INTEGER; rd: TextModels.Reader; ch: CHAR; s: Sender;
      c := TextControllers.Focus();
      IF (c # NIL) & c.HasSelection() THEN
         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
            IF ch < 100X THEN   (* skip Unicode characters *)
               s.buf[i] := SHORT(SHORT(ORD(ch))); INC(i)
         s.idx := 0; s.len := i;
         StdLog.String("client: no text selection found"); StdLog.Ln
   END SendTextSelection;

   Stop   (* prevent the client from trapping after module unloading *)
END CommObxStreamsClient.