diff --git a/mewny.rb b/mewny.rb old mode 100644 new mode 100755 index 3b0c08c..6dd35e6 --- a/mewny.rb +++ b/mewny.rb @@ -68,7 +68,11 @@ PORT = options[:port] ROWS = options[:rows] COLS = options[:cols] -VERSION = 0.01 +VERSION = { + :SRV_TXT => '0.01', + :CLN_TXT => '0.01', + :CLN_ARO => '0.02', +} def do_server server = TCPServer.new(SRV_HOST, PORT) @@ -82,28 +86,44 @@ def do_server buffer = pre.ljust(ROWS*COLS)[0...ROWS*COLS] windex = pre.length # Wipe your buffer clean with your write index windex %= buffer.length + motions = [] - def new_buf_wi_out(buf, wi, newtext) + def new_buf_wi_out(buf, wi, newtext, motions: []) buf = buf.dup out = '' nti = 0 # New Text Index - while nti < newtext.length - out << "#{VERSION}|" + while (nti < newtext.length) || (motions.length > 0) + if motions.length > 0 && nti >= motions[0][:nti] + case motions[0][:dir] + when 'u' + wi -= COLS + when 'd' + wi += COLS + when 'l' + wi -= 1 + when 'r' + wi += 1 + end + wi %= ROWS*COLS + motions.shift # remove first motion + end + out << "#{VERSION[:SRV_TXT]}|" out << ((wi/COLS)+1).to_s + '|' out << ((wi%COLS)+1).to_s + '|' + next if nti >= newtext.length loop do out << newtext[nti] buf[wi] = newtext[nti] wi += 1 nti += 1 + break if motions.length > 0 && nti >= motions[0][:nti] break if nti >= newtext.length break if wi%COLS == 0 end - wi = 0 if wi >= (ROWS*COLS) wi %= ROWS*COLS out << "\n" end - [buf, wi, out] # << Implicit return + [buf, wi, out] end loop do @@ -130,17 +150,47 @@ def do_server next end ver, msg = msg.chomp.split('|',2) - next unless ver.to_f <= VERSION - next unless msg != nil - newtext << msg + case ver + when VERSION[:CLN_TXT] + next unless msg != nil + newtext << clean_chars(msg) + when VERSION[:CLN_ARO] + next unless msg != nil + dir = 'l' + case msg + when 'A' + dir = 'u' + when 'B' + dir = 'd' + when 'C' + dir = 'r' + when 'D' + dir = 'l' + else + next + end + motions << { + :nti => newtext.length - 1, + :dir => dir + } + end rescue Errno::ECONNRESET, Errno::EPIPE puts "Disconnect (err): #{sck.peeraddr}" sck.close sockets.delete(sck) end - buffer, windex, out = new_buf_wi_out(buffer,windex,newtext) + buffer, windex, out = new_buf_wi_out(buffer,windex,newtext,motions:motions) + motions = [] clients = sockets - [server] - clients.each { |c| c.puts out } + clients.each do |c| + begin + c.puts out + rescue Errno::ECONNRESET, Errno::EPIPE + puts "Disconnect (err): #{c.peeraddr}" + c.close + sockets.delete(c) + end + end #if out != '' # puts "#{windex}: (#{(windex/COLS)+1},#{(windex%COLS)+1})" #end @@ -148,6 +198,20 @@ def do_server end end +def clean_chars(chars) + out = '' + chars.each_char do |char| + if char.ord < 0x20 # Non printing + out << '^'+(char.ord + 0x40).chr + elsif char.ord == 0x7F # DEL (Non print) + out << '^?' + else + out << char + end + end + out +end + def do_client socket = TCPSocket.new(HOST, PORT) @@ -163,24 +227,31 @@ def do_client msg = socket.gets exit 0 unless msg ver, msg = msg.split('|',2) - next unless ver.to_f <= VERSION + next unless ver == VERSION[:SRV_TXT] next unless msg != nil # In message version 0.01 and lower, # all messages are in an assumed format... row,col,chars = msg.split('|',3) - print "\x1b[#{row};#{col}H#{chars}\x1b[A" + print "\x1b[#{row};#{col}H#{chars.chomp}" end end while (char = STDIN.noecho(&:getch)) exit unless char != "\x04" # ^D - if char.ord < 0x20 # Non printing - char = '^'+(char.ord + 0x40).chr - elsif char.ord == 0x7F # DEL (Non print) - char = '^?' + if char == "\x1b" # Detect arrows + char2 = STDIN.noecho(&:getch) + if /[A-D]/.match? (char3 = STDIN.noecho(&:getch).upcase) + socket.puts "#{VERSION[:CLN_ARO]}|#{char3}" + next + else + char << char2+char3 + end + elsif (char == "\x08" || # backspace + char == "\x7F" ) # delete + socket.puts "#{VERSION[:CLN_ARO]}|D" + next end - next unless - socket.puts "#{VERSION}|#{char}" + socket.puts "#{VERSION[:CLN_TXT]}|#{clean_chars(char)}" end ensure print "\x1b[?1049l" # Back to regular buffer