Funny IO.select behaviour

I've been debugging my full screen console ruby editor.

Suddenly, for no apparent reason, I'm starting to get

(a) random quits while typing. espically when pressing "t".

(b) Select:Interrupt while typing.

This didn't used to happen. The line it is dying at is...

if select(@in_io],nil,nil,1)

very strange, and frustrating! This is on linux...

ruby version...

1.8.6 (2007-09-24 patchlevel 111) [i686-linux]

I'm willing to post the whole thing, as long as I don't get too much
abuse for it not being very well coded. It's a work in progress.

Hi,

···

In message "Re: Funny IO.select behaviour" on Tue, 25 May 2010 22:15:45 +0900, Dennis Nedry <dennis@cortex-media.info> writes:

This didn't used to happen. The line it is dying at is...

if select(@in_io],nil,nil,1)

very strange, and frustrating! This is on linux...

I feel sympathy, but above code snippet help us nothing. If you need
help from the list, you'd better disclose everything, to reproduce the
problem, no matter how bad your code is right now.

              matz.

Dennis Nedry wrote:

1.8.6 (2007-09-24 patchlevel 111) [i686-linux]

Can you try upgrading to the latest 1.8.6 or 1.8.7? IIRC there were a lot of changes to threading somewhere in the 1.8.6 patchlevels. Or it could be something else...

But Matz, my Ruby is real bad. It looks like my Pascal did. I never
did manage to get my head around this new fangled stuff. I'm 41, and
i learned to program when i was about 10, on a pdp 11. Anyway, I'm
getting off topic. Did I thank you for this wonderful language.
Anyway, here goes... these are the two main files...

fsed.rb (Poor Dossy)

···

On Tue, May 25, 2010 at 2:23 PM, Yukihiro Matsumoto <matz@ruby-lang.org> wrote:

I feel sympathy, but above code snippet help us nothing. If you need
help from the list, you'd better disclose everything, to reproduce the
problem, no matter how bad your code is right now.

#
# Full Screen EDitor (FSED) for QUARKware QBBS.
#
# Copyright (C) 2002, Dossy <dossy@panoptic.com>
# All rights reserved.
#
# $Id: fsed.rb,v 1.1 2002/09/12 12:27:16 dossy Exp $
#

module Editors
  module FSED
    VERSION = "0.75"
    ESC = 27.chr
    RETURN = 10.chr

    class Buffer
      def initialize(max_lines,in_file)
        @buffer = getfile(in_file)
        @max_lines = max_lines
      end

      def =(x, y, value)
        if @buffer[y - 1] == nil
          @buffer[y - 1] =
        end
        @buffer[y - 1][x - 1] = value
      end

      def (x, y)
        if @buffer[y - 1].nil?
          nil
        else
          @buffer[y - 1][x - 1]
        end
      end

      def clear
        @buffer =
      end

def length
  @buffer.length
end

      def delete_at(x, y)
        unless @buffer[y - 1].nil?
   @buffer[y - 1].slice!(x - 1) # used to use delete_at but that
didn't always work.
        end
      end

      def insert_at_line(y,x,in_str)
       inthing = nil
       if !in_str.nil? then
        in_str.each_with_index {|c,i| @buffer[y-1].insert(x+ i,c)}
       end
      end

      def insert_line_at(y,ln)
       @buffer[y] = if @buffer[y] == nil
       @buffer.insert(y,ln)
     end

     def delete_line_at(y)
       @buffer.delete_at(y - 1)
     end

     def buffer_length

      return @buffer.length
     end

     def length_y(y)
       if !@buffer[y - 1].nil?
        return @buffer[y - 1].length
       else
        return 0
       end
     end

    def del_range(y,x1,x2)
     total = x2 - x1
     str = @buffer[y-1].slice!(-(total),total)
     return str
    end

      def insert_char(x, y, value)
       @buffer[y - 1] = if @buffer[y - 1] == nil
        if (x-1) > @buffer[y-1].length then
    @buffer[y-1] << value
  else
        @buffer[y - 1].insert(x-1,value)
  end
      end

    def find_first_space(y)
       return @buffer[y-1].index(" ")
    end

    def find_nearest_space(y,space)
       result = nil
       @buffer[y - 1] = if @buffer[y - 1].nil?
       highest = 0
      @buffer[y-1].each_with_index {|c,i|
               highest = i
               result = i if (c == " ") and (i <= space)
               }
       result= highest if highest <= space
      return result
    end

     def paragraph_up(start_y,width)

       for i in start_y..@buffer.length #- 1
   break if @buffer[i,0].nil?
   pos = length_y(i-1)
   space = width - pos #how much space on the line above?
   unwrap_space = find_nearest_space(i,space)
         break if unwrap_space.nil? or unwrap_space == 0
   unwrap_str = del_range(i,0,unwrap_space+1)
   insert_at_line(i - 1,pos,unwrap_str)
  end
     end

    def detect_and_wrap(y,x,width)
      l_space = 0; wrap = nil
      @buffer[y - 1] = if @buffer[y - 1].nil?
      l = @buffer[y-1].length - 1
      test = @buffer[y-1]

      if !@buffer[y-1][width].nil? then #is there now a character past max_width
       test.slice!(-1) if test.last == " "
       l_space = test.rindex(' ')
       wrap = @buffer[y-1][l_space..l]
       del_range(y,l_space+1,l+1)
       return [l_space,wrap]
      end
    end

      def line(line)
        if !@buffer[line - 1].nil? then #protect against backspace on
an empty line -- produces a nil
        @buffer[line - 1].collect { |char|
          if char.nil?
            " "
          else
            char
          end
        }.to_s.chomp
       end
     end

     def buff_out
          @buffer.collect { |line|
          if line.nil?
            "\n"
          else
            [ line.collect { |char|
              if char.nil?
                " "
              else
                char
              end
            }, "\n" ].to_s
          end
        }
      end

     def dump
          @buffer.collect { |line|
          if line.nil?
            "\n"
          else
            [ line.collect { |char|
              if char.nil?
                " "
              else
                char
              end
            }, "\n" ].to_s
          end
        }.to_s.chomp
      end

   # def display
# i = 0
  # @buffer.collect { |line| i = i + 1
    # if line.nil?
      # "#{i}: \n"
        # else
         # "#{i}: " << [ line.collect { |char|
          # if char.nil?
           # " "
           # else
          # char
          # end
         # }, "\n" ].to_s
       # end
      # }.to_s.chomp
#end

     def to_s(top_start,vp_height)

     out = String.new
     top_stop = @buffer.length - 1
     top_stop = vp_height + top_start - 1 if @buffer.length - 1 >=
vp_height + top_start

       for i in top_start..top_stop
        one_line = @buffer[i].to_s
        out = out+ one_line + "\n"
        end
        out
      end

def room_on_line(y,str,width)

room = false

if !@buffer[y].nil?

if !str.nil? then
   room = true if (@buffer[y].length - 1) + str.length < width
end
end
return room
end

    def getfile(filename)
   file_array =
   if !filename.nil? then
   #this used to use chars.to_a but it didn't always work right
    if File.exists?(filename)
     IO.foreach(filename) { |line|
     line.gsub!("\n","")
     line.gsub!("\r","")
     build =
     for i in 0..line.length-1
      build << line[i].chr
     end
     file_array << build}
    end
   end
    puts
    file_array
   end

end

    class EditorState
      attr_reader :current_cursor_position, :previous_cursor_position
      attr_reader :screen_width, :screen_height
      attr_reader :viewport_width, :viewport_height
      attr_reader :header_height
      attr_reader :buffer

      def initialize(width, height,in_file)
        @dirty = true
        @current_cursor_position = [1, 1]
        @previous_cursor_position = [1, 1]
        @screen_width = width
        @screen_height = height
        @buffer = Buffer.new(500,in_file)
        @buffer_top = 0

        @header_height = 2
        @viewport_width = @screen_width
        @viewport_height = @screen_height - @header_height
        @wrapped = false
  @insert = true

        open_error_log
      end

      require "windows.rb"

      def open_error_log
        $lf = File.new("debug.txt", File::CREAT|File::TRUNC|File::RDWR, 0644)
      end

      def current_x
        @current_cursor_position[0]
      end

      def current_y
        @current_cursor_position[1]
      end

      def place_cursor(x, y)
        @previous_cursor_position = @current_cursor_position
        @current_cursor_position = [x, y]
        @dirty = true
      end

      def move_cursor_up(x)
       result = NO_REDRAW
       new_y = current_y - x
       if new_y < 1 then
        new_y = 1
         @buffer_top -=x if @buffer_top > 0
        result = REDRAW
       end
        place_cursor(current_x, new_y)
        return result
      end

      def page_up
       redraw = move_cursor_up(@viewport_height)
       return redraw
      end

      def move_cursor_down(x)
        result = NO_REDRAW
        new_y = current_y + x
        @wrapped = false
        if new_y >=@viewport_height then
         new_y = (current_y)
         @buffer_top += x
         result = REDRAW
        end
        place_cursor(current_x, new_y)
       return result
      end

      def page_down
       down = @buffer.buffer_length - (current_y+ @buffer_top)
       if down > @viewport_height then
        redraw = move_cursor_down(@viewport_height)
        return redraw
       else
        return NO_REDRAW
       end
      end

      def move_cursor_left(x)
        new_x = current_x - x
        new_x = 1 if new_x < 1
        place_cursor(new_x, current_y)
      end

      def home_cursor
        place_cursor(1,current_y)
      end

      def move_cursor_right(x)
        new_x = current_x + x
        new_x = @viewport_width if new_x > @viewport_width
        place_cursor(new_x, current_y)
      end

  def end_cursor
   end_line = @buffer.length_y(current_y)+1
   end_line = @viewport_width if end_line > @viewport_width
   place_cursor(end_line,current_y)
  end

  def clear_screen
   "#{ESC}[2J#{ESC}[H#{ESC}[00m"
  end

  def toggle_ins
   @insert = !@insert
  end

  def parse_c(line)
   COLORTABLE.each_pair {|color, result| line.gsub!(color,result) }
         return line
  end
  
  def header
   out_str = "INS"
   out_str = "OVR" if !@insert
   out = String.new
   out << parse_c("%WQuark%YEDIT #{VERSION}%W".fit(79)) +"\n"
   out << parse_c("%YCTRL + e%YX%Wit %Y|%W %YG%W Help %Y|%W %YS%Wave
%Y|%W %YN%Wewline %Y|%W %YY%W Delete %Y|%W #{out_str} %Y|%W Line:
#{current_y + @buffer_top}".fit(79)) << "\n"
   out << bg("black") << fg("WHITE")
   return out
  end

      def redraw(force)
        @dirty = true if force
        if @dirty
          @dirty = false
          if force
            [clear_screen,
            header,
            buffer.to_s(@buffer_top,@viewport_height),
            update_cursor_position].to_s
          else
            ""
          end
        else
          ""
        end
      end

      def clear
        @buffer.clear
      end

# this is complicated... too complicated...

      def input_char_at_cursor(c)
       if @insert then #we are
in insert mode
  @buffer.insert_char(current_x,(current_y) + @buffer_top,c)
   l_space,wrap = @buffer.detect_and_wrap(current_y,current_x,@screen_width - 1)
   if !wrap.nil? then
          if !(current_x < @buffer.length_y(current_y) - 1) then
#no wrap... insert a character
           if (current_x + wrap.length) < @screen_width then
            move_cursor_right(1)
           return [c,NO_REDRAW]
           else
   #wrap at insert at end of line
            @buffer.insert_line_at(current_y,wrap.to_s.strip!)
            home_cursor
      move_cursor_right(wrap.length - 1)
            move_cursor_down(1)
          end
          $lf.print "I'm here...wrap line\n"
          return [nil,REDRAW] #we don't want a character
printed because we are in overflow
        end

      $lf.print "@buffer.length + wrap.length:
#{@buffer.length_y(current_y) +(wrap.length + 2)}\n"
      $lf.print "@screen_width: #{@screen_width}\n"
      $lf.print "room on line: #{@buffer.room_on_line(current_y +
1,wrap,@screen_width)}\n"
      $lf.print "@buffer.length: #{@buffer.length}\n"
          if (@buffer.length_y(current_y) + (wrap.length + 2)) >=
@screen_width then #wrap for insert not at end of line
       $lf.print "in insert not at end of line...\n"
     if @buffer.room_on_line(current_y + 1,wrap,@screen_width) then

      @buffer.insert_at_line(current_y+1,0,wrap) #subsequent words go
to next line

      $lf.print "on next existing line...\n"
     else

       @buffer.insert_line_at(current_y,wrap) #out of room so make a new line

       $lf.print "on a new line...\n"
     end
            move_cursor_right(1)
            $lf.print "done with insert before line\n"
            return [c,REDRAW]
          end
         end
        move_cursor_right(1) #redraw because we are inserting...
        if (@buffer.length_y(current_y)+1) == current_x then
         return [c,NO_REDRAW] #insert mode at eol so no redraw
        else
       return [c,REDRAW] #insert mode not at eol, so redraw
      end

  else
    if current_x < @screen_width then
     @buffer[current_x,(current_y) + @buffer_top] = c #we are in
over-write mode....
     move_cursor_right(1)
     $lf.print "Overwrite Mode\n"
     return [c,NO_REDRAW]
    else
      $lf.print "I'm here...sixth return\n"
     return [nil,NO_REDRAW]
    end
   end
  end

  def newline
  
  if @buffer.length_y(current_y) == 0 then
     @buffer.insert_line_at(current_y,nil)
     move_cursor_down(1)
  else
    str = @buffer.del_range(current_y,current_x-1,@buffer.length_y(current_y))
    @buffer.insert_line_at(current_y,str)
    move_cursor_left(current_x)
    move_cursor_down(1)
   end
    @dirty = true
  end

  def deleteline
    @buffer.delete_line_at(current_y)
  end

   def backspace
     if current_x > 1 then #normal delete, not at BOL
       move_cursor_left(1)
       @buffer.delete_at(current_x, current_y)
     else
       if current_y > 1 then # delete at BOL
  if @buffer.length_y(current_y-1) == 0 then #blank line above
   @buffer.delete_line_at(current_y-1)
   move_cursor_up(1)
  else
    @buffer.paragraph_up(current_y,@screen_width) #move up until you
hit a blank line...
     move_cursor_up(1)
     home_cursor
     move_cursor_right(@buffer.length_y(current_y))
    end
         return REDRAW
  end
      end
  return REDRAW
end

   def update_cursor_position
    "#{ESC}[#{current_y + @header_height};#{current_x}H"
   end

  def w_update_cursor(x,y)
   "#{ESC}[#{y + @header_height};#{x}H"
  end

  def w_clear
   return @c.reset
  end

  def fg(forground)

    out = String.new

    case forground
      when "red"
       out = "e[31m"
      when "RED"
       out = "e[;1;31m"
      when "green"
       out << "e[32m"
      when "GREEN"
       out = "e[;1;32m"
      when "blue"
       out = "e[34m"
      when "BLUE"
       out = "e[;1;34m"
      when "cyan"
       out = "e[36m"
      when "CYAN"
       out = "e[;1;36m"
      when "magenta"
       out = "e[35m"
      when "MAGENTA"
       out = "e[;1;35m"
      when "yellow"
       out = "e[33m"
      when "YELLOW"
       out = "e[;1;33m"
      when "black"
       out = "e[30m"
      when "BLACK"
       out = "e[;1;30m"
       when "hide"
        out = "e[?25l"
       when "show"
        out = "e[?25h"
       when "reset"
        out = "e[0m"

      end
  return out
end

   def bg(background)

    out = String.new

    case background
      when "red"
       out = "e[41m"
      when "green"
       out = "e[42m"
      when "blue"
       out = "e[44m"
      when "cyan"
       out = "e[46m"
      when "magenta"
       out = "e[45m"
      when "yellow"
       out = "e[43m"
      when "black"
       out = "e[40m"
      when "white"
       out = "e[47m"
      end
  return out
end

  def center(string,width,color)
   result = String.new
   outdash = ((width / 2 ) - (string.length / 2))
   outdash.times {result << " "}
   result << color if !color.nil?
   result << string
   (width - (outdash + string.length)).times {result << " "}
   return result
end

  def make_window(startx,starty,width,height,forground,background,border,title)

   f_color = fg(forground)
   b_color = bg(background)
   bdr_color = bg(border)
   window = String.new

   window << w_update_cursor(startx,starty)
   window << bdr_color
   window << center(title,width,nil)
  for i in 1..height do
      window << w_update_cursor(startx,starty+i)
      window << bdr_color << " " << b_color
      (width - 2).times {window << " "}
      window << bdr_color << " "
      window << bg("white") << " "
    end
     window << w_update_cursor(startx,starty+height) << bdr_color
     width.times {window << " "}
     window << w_update_cursor(startx+1,starty+height+1) << bg("white")
     width.times {window << " "}
     window << w_update_cursor(startx,starty)

   return window
  end

def help_window

   idt = 16
   str = 5
   width=58
   out = make_window(str,2,60,12,"BLACK","cyan","blue","Help Window")
   out << w_update_cursor(idt,str) << fg("yellow") << bg("cyan")
   out << "CTRL-A" << fg("white") << " Abort Message"
   out << w_update_cursor(idt,str+1) << fg("yellow")
   out << "CTRL-L" << fg("white") << " Refresh Screen"
   out << w_update_cursor(idt,str+2) << fg("yellow")
   out << "CTRL-N" << fg("white") << " New Line"
   out << w_update_cursor(idt,str+3) << fg("yellow")
   out << "CTRL-X" << fg("white") << " Save (Post) Message"
   out << w_update_cursor(idt,str+4) << fg("yellow")
   out << "CTRL-Y" << fg("white") << " Delete Line"
   out << w_update_cursor(idt,str+6) << fg("yellow")
   out << "INSERT" << fg("white") << " Toggle Insert/Overwrite"
   out << w_update_cursor(idt,str+8)
   out << "ESC to exit this window." << fg("white")
end

def splash_window

   idt = 15
   str = 8
   width = 38
   out = make_window(idt-1,str-1,40,8,"WHITE","magenta","cyan","About")
   out << w_update_cursor(idt,str+1) <<fg("yellow") << bg("magenta")
   out << center("QUARKedit #{VERSION}",width,fg("white"))
   out << w_update_cursor(idt,str+3)
   out << center("By Dossy and Mark Firestone",width,fg("white"))
   out <<w_update_cursor(idt+36,str+7)
   #out << fg("hide")
end

def yes_no_window(question)
   idt = 11
   str = 10
   w_width = question.length + 14
   width = w_width - 2
   out = make_window(idt-2,str-1,w_width,4,"WHITE","red","yellow","Confirm")
   out << w_update_cursor(idt+1,str+1)
   out << fg("WHITE") << bg("red")
   out << question << "(Y,n): "
end

def screen_clear # I don't know why. Needs two redraws or the
background color is wrong....
   out = redraw(true)
   out << redraw(true)
   return out
end

end #of class

    class Editor

      #Window Constants
      MESSAGE = 1
      ABORT = 2
      SAVE = 3
      SPELL = 4

      def initialize(width, height, in_io, out_io,in_file,bbs_mode)
        @state = EditorState.new(width, height,in_file)
        @in_io = in_io
        @out_io = out_io
  @w_mode = false
        @w_type = MESSAGE
  @supress = false
  @bbs_mode = bbs_mode
      end

      def run
        @out_io.sync = true
        @in_io.sync = false
  @out_io.print @state.screen_clear
        @out_io.print @state.redraw(true)
  @out_io.print @state.splash_window
  sleep(1)
        @out_io.print @state.redraw(true)
  @out_io.print @state.redraw(true)
        buf = nil

        while true

        if select([@in_io], nil, nil, 1)
         $lf.print "I made it"
  
        c = @in_io.sysread(1)
  $lf.print "after sysread"
        #c = @in_io.getc
     # $lf.print"c: #{c}\n"
       # $lf.print"c-chr: #{c[0]}\n"
  # if @supress then # if we are suppressing the mysterious
extra linefeed... we do that here.
     # @supress = false
  # c = 0.chr if c.bytes.to_a[0] = 10
  # end
  
         if @w_mode then #We are in window mode, not edit mode...
           # $lf.print "in wmode\n"
            #$lf.print "c: #{c.upcase}"

          case c
           when "\e" #effectively, esc this is cancel for everything
            @w_mode = false
            @out_io.print @state.screen_clear
          else
      
           case @w_type
              when ABORT,SAVE
                if c.upcase == "Y" or c == RETURN then
     print "Y"
                 @state.clear if @w_type == ABORT
                 @state.clear_screen
                sleep(2)
                 break
                else
                 @out_io.print @state.screen_clear
                 @w_mode = false
               end
            end
          end

    else
      case c
      when "\cX" # exit
   @out_io.print @state.yes_no_window("Post message... Are you sure?")
        @w_type = SAVE
  @w_mode = true
      when "\cG","\eOP"
  @out_io.print @state.help_window
        @w_type = MESSAGE
  @w_mode = true
      when "\cA"
   @out_io.print @state.yes_no_window("Abort message... Are you sure?")
        @w_type = ABORT
  @w_mode = true
      when "\cN" #insert line
  @state.newline
  @out_io.print @state.redraw(true)
       when "\cY" #delete line
  @state.deleteline
  @out_io.print @state.redraw(true)
       when "\cL" # refresh
  @out_io.print @state.redraw(true)
       when "\r","\n"
        @state.newline
        @supress = true if @bbs_mode #telnet seems to like to echo
linefeeds. lets supress this ...
  @out_io.print @state.redraw(true)
      when "\010", "\177"
        redraw = @state.backspace
        @out_io.print "\e[#{@state.current_y + @state.header_height};1H\e[K"
        @out_io.print @state.buffer.line(@state.current_y)
        @out_io.print @state.update_cursor_position
  @out_io.print @state.redraw(true) if redraw
       when "\e" # escape
        buf = c
           else
              if buf.nil?
                chr = c.unpack("c")[0]
                if (chr >= 32 && chr <= 127)
                 out_c,redraw = @state.input_char_at_cursor(c)
                 @out_io.putc(out_c) if !out_c.nil?
     @out_io.print @state.redraw(true) if redraw
                end
              else
                buf << c
              # $lf.print "buf: #{buf}\n"
                case buf
      when "\e[H","\e[1"
        @state.home_cursor
        @out_io.print @state.update_cursor_position
      when "\e[F","\e[4"
        @state.end_cursor
         @out_io.print @state.update_cursor_position
      when "\e[6"
                     redraw = @state.page_down
         @out_io.print @state.redraw(true) if redraw
      when "\e[5"
        redraw = @state.page_up
        @out_io.print @state.redraw(true) if redraw
      when "\e[2"
            @state.toggle_ins
                  @out_io.print @state.redraw(true)
                 when "\e[A"
                   redraw = @state.move_cursor_up(1)
                   if redraw
                    @out_io.print @state.redraw(true)
                   else
                    @out_io.print @state.update_cursor_position
                   end
                   buf = nil
                  when "\e[B"
       redraw = @state.move_cursor_down(1)
       if redraw
                    @out_io.print @state.redraw(true)
                   else
                    @out_io.print @state.update_cursor_position
       end
                   buf = nil
                  when "\e[D"
                   @state.move_cursor_left(1)
                   @out_io.print @state.update_cursor_position
                   buf = nil
                  when "\e[C"
                  @state.move_cursor_right(1)
                  @out_io.print @state.update_cursor_position
                  buf = nil
                else
                  if buf.size >= 3
                    buf = nil
      end
      end
                end
              end
            end
          end
  end
        @state.buffer
  
end

    end

  end

end

file edit.rb:

require 'fsed'
require "tools.rb"
#require "raspell"

#Consts

SPELL_CHECK = true #if you don't want raspell, comment out the
require above.

COLORTABLE = {
  '%R' => "\e[;1;31;44m", '%G' => "\e[;1;32;44m",
  '%Y' => "\e[;1;33;44m", '%B' => "\e[;1;34;44m",
  '%M' => "\e[;1;35;44m", '%C' => "\e[;1;36;44m",
  '%W' => "\e[;1;37;44m", '%r' => "\e[;31;44m",
  '%g' => "\e[;32;44m", '%y' => "\e[;33;44m",
  '%b' => "\e[;34;44m", '%m' => "\e[;35;44m",
  '%c' => "\e[;36;44m", '%w' => "\e[;31;44m"
}

REDRAW = true
NO_REDRAW = false

def tcgetattr(io)
  _TCGETA = 0x5405
  attr = [0, 0, 0, 0].pack("SSSS")
  io.ioctl(_TCGETA, attr)
  attr
end

def tcsetattr(io, attr)
  _TCSETA = 0x5406
  io.ioctl(_TCSETA, attr)
end

def writefile (filename,array)

  lf = File.new(filename, File::WRONLY|File::TRUNC|File::CREAT, 0644)
  array.each {|x|
                    print "."
                    lf.puts x}
  lf.close
  puts
  end

def pull_apart_args(args)

  bbs_mode = false
  filename = nil
  if !args.nil then
   filename = args.last
   args.each {|arg| bbs_mode = true if arg == "-L"
                           #put more switches here
                           }
  end
  return [bbs_mode,filename]
end

begin
  unless RUBY_PLATFORM =~ /mswin32/
    # turn off stdin buffering and echo

    # c_iflag bits
    INLCR = "0000100".to_i
    IGNCR = "0000200".to_i
    ICRNL = "0000400".to_i

    # c_oflag bits
    OPOST = "0000001".to_i

    # c_lflag bits
    ISIG = "0000001".to_i
    ICANON = "0000002".to_i
    ECHO = "0000010".to_i

    old_attr = tcgetattr($stdin)
    input, output, control, local = old_attr.unpack("SSSS")
    # input &= ~(INLCR | IGNCR | ICRNL)
    # output &= ~OPOST
    #local &= ~(ECHO | ICANON | ISIG)
    local &= ~(ECHO)
    new_attr = [input, output, control, local].pack("SSSS")
    tcsetattr($stdin, new_attr)
  end

  bbs_mode,in_file = pull_apart_args(ARGV)
  puts "bbsmode: #{bbs_mode}"
  sleep(2)
  editor = Editors::FSED::Editor.new(80, 23, STDIN.to_io,
$>.to_io,in_file,bbs_mode)

  buffer = editor.run
# if bbs_mode then
   $lf.print "writing file...\n"
   writefile(in_file,buffer.buff_out)
   $lf.print "file written...\n"
  #end
ensure
  unless RUBY_PLATFORM =~ /mswin32/
    tcsetattr($stdin, old_attr)
  end
end

--
I know a mouse
And he hasn't got a house
I don't know why
I call him Gerald
He's getting rather old
But he's a good mouse

- Syd Barrett

I thought about that. I'm kind of nervous about doing that, because
the ruby BBS I wrote didn't like 1.8.7. It used to get segfaults.

I think you might be on to something. I don't think I'm doing
something wrong, it just ain't pretty.

···

On Tue, May 25, 2010 at 5:23 PM, Joel VanderWerf <joelvanderwerf@gmail.com> wrote:

Dennis Nedry wrote:

1.8.6 (2007-09-24 patchlevel 111) [i686-linux]

Can you try upgrading to the latest 1.8.6 or 1.8.7? IIRC there were a lot of
changes to threading somewhere in the 1.8.6 patchlevels. Or it could be
something else...

--
I know a mouse
And he hasn't got a house
I don't know why
I call him Gerald
He's getting rather old
But he's a good mouse

- Syd Barrett

Martin (my partner in crime) has tried it for me on 1.8.7 and 1.9.1
and it doesn't work right on those either.

What's odd is, I haven't changed that part of the program, and it
worked fine before.

···

On Tue, May 25, 2010 at 8:57 PM, Dennis Nedry <dennis@cortex-media.info> wrote:

On Tue, May 25, 2010 at 5:23 PM, Joel VanderWerf

Can you try upgrading to the latest 1.8.6 or 1.8.7? IIRC there were a lot of
changes to threading somewhere in the 1.8.6 patchlevels. Or it could be
something else...

--
I know a mouse
And he hasn't got a house
I don't know why
I call him Gerald
He's getting rather old
But he's a good mouse

- Syd Barrett

No takers I guess. Code must be worse than I thought... (;

···

--
I know a mouse
And he hasn't got a house
I don't know why
I call him Gerald
He's getting rather old
But he's a good mouse

- Syd Barrett

Hi,

···

In message "Re: Funny IO.select behaviour" on Thu, 27 May 2010 22:26:16 +0900, Dennis Nedry <dennis@cortex-media.info> writes:

No takers I guess. Code must be worse than I thought... (;

I think the problem was ill indented (and wrongly wrapped) code. It's
quite tough to re-indent the whole lines of code. I was too busy.
Also, the instruction to reproduce the error is sought.

              matz.

What can I do to help? I'm certianly not demanding... just asking. (;

···

On Thu, May 27, 2010 at 3:23 PM, Yukihiro Matsumoto <matz@ruby-lang.org> wrote:

Hi,

In message "Re: Funny IO.select behaviour" > on Thu, 27 May 2010 22:26:16 +0900, Dennis Nedry <dennis@cortex-media.info> writes:

>No takers I guess. Code must be worse than I thought... (;

I think the problem was ill indented (and wrongly wrapped) code. It's
quite tough to re-indent the whole lines of code. I was too busy.
Also, the instruction to reproduce the error is sought.

--
I know a mouse
And he hasn't got a house
I don't know why
I call him Gerald
He's getting rather old
But he's a good mouse

- Syd Barrett

Hi,

···

In message "Re: Funny IO.select behaviour" on Thu, 27 May 2010 23:24:33 +0900, Dennis Nedry <dennis@cortex-media.info> writes:

On Thu, May 27, 2010 at 3:23 PM, Yukihiro Matsumoto <matz@ruby-lang.org> wrote:

Hi,

In message "Re: Funny IO.select behaviour" >> on Thu, 27 May 2010 22:26:16 +0900, Dennis Nedry <dennis@cortex-media.info> writes:

>No takers I guess. Code must be worse than I thought... (;

I think the problem was ill indented (and wrongly wrapped) code. It's
quite tough to re-indent the whole lines of code. I was too busy.
Also, the instruction to reproduce the error is sought.

What can I do to help? I'm certianly not demanding... just asking. (;

Probably your MUA wraps lines and modifies indentation, so attach the
code to your mail. Plus, instruction to reproduce the error is
preferable (command line options, key strokes, etc).

              matz.

If you can boil the problem down to 10 lines of code or less, I'm sure
that would help too. I know this isn't always easy....

···

On 5/27/10, Dennis Nedry <dennis@cortex-media.info> wrote:

What can I do to help? I'm certianly not demanding... just asking. (;

That is one of the issues. I can't. Getting random QUITs doesn't
help, and getting an error on the select doesn't tell me much either.
I can't see any reason for the issue. It used to work fine, until I
started cleaning up some of the horrible bits, and fixed (well mostly)
the word wrapping routines.

Very odd. I'm baffled.

···

On Thu, May 27, 2010 at 3:54 PM, Caleb Clausen <vikkous@gmail.com> wrote:

On 5/27/10, Dennis Nedry <dennis@cortex-media.info> wrote:

If you can boil the problem down to 10 lines of code or less, I'm sure
that would help too. I know this isn't always easy....

--
I know a mouse
And he hasn't got a house
I don't know why
I call him Gerald
He's getting rather old
But he's a good mouse

- Syd Barrett

I've pushed the code to github, and am updating it to run on ruby
1.9.1. There's a good chance that will clear up any weird issues.

martin

···

On Thu, May 27, 2010 at 8:29 PM, Dennis Nedry <dennis@cortex-media.info> wrote:

That is one of the issues. I can't. Getting random QUITs doesn't
help, and getting an error on the select doesn't tell me much either.
I can't see any reason for the issue. It used to work fine, until I
started cleaning up some of the horrible bits, and fixed (well mostly)
the word wrapping routines.