aboutsummaryrefslogtreecommitdiffstats
path: root/lib/reline/terminfo.rb
blob: 9c1615cc2bf24529d1494bb673a23b4ce141ded9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
require 'fiddle'
require 'fiddle/import'

module Reline::Terminfo
  extend Fiddle::Importer

  class TerminfoError < StandardError; end

  @curses_dl = nil
  def self.curses_dl
    return @curses_dl if @curses_dl
    if Gem::Version.create(Fiddle::VERSION) >= Gem::Version.create('1.0.1')
      # Fiddle::TYPE_VARIADIC is supported from Fiddle 1.0.1.
      %w[libncursesw.so libcursesw.so libncurses.so libcurses.so].each do |curses_name|
        result = Fiddle::Handle.new(curses_name)
      rescue Fiddle::DLError
        next
      else
        @curses_dl = result
        break
      end
    end
    @curses_dl
  end
end

module Reline::Terminfo
  dlload curses_dl
  #extern 'int setupterm(char *term, int fildes, int *errret)'
  @setupterm = Fiddle::Function.new(curses_dl['setupterm'], [Fiddle::TYPE_VOIDP, Fiddle::TYPE_INT, Fiddle::TYPE_VOIDP], Fiddle::TYPE_INT)
  #extern 'char *tigetstr(char *capname)'
  @tigetstr = Fiddle::Function.new(curses_dl['tigetstr'], [Fiddle::TYPE_VOIDP], Fiddle::TYPE_VOIDP)
  #extern 'char *tiparm(const char *str, ...)'
  @tiparm = Fiddle::Function.new(curses_dl['tiparm'], [Fiddle::TYPE_VOIDP, Fiddle::TYPE_VARIADIC], Fiddle::TYPE_VOIDP)

  def self.setupterm(term, fildes)
    errret_int = String.new("\x00" * 8, encoding: 'ASCII-8BIT')
    ret = @setupterm.(term, fildes, errret_int)
    errret = errret_int.unpack('i')[0]
    case ret
    when 0 # OK
      0
    when -1 # ERR
      case errret
      when 1
        raise TerminfoError.new('The terminal is hardcopy, cannot be used for curses applications.')
      when 0
        raise TerminfoError.new('The terminal could not be found, or that it is a generic type, having too little information for curses applications to run.')
      when -1
        raise TerminfoError.new('The terminfo database could not be found.')
      else # unknown
        -1
      end
    else # unknown
      -2
    end
  end

  def self.tigetstr(capname)
    @tigetstr.(capname)
  end

  def self.tiparm(str, *args)
    new_args = []
    args.each do |a|
      new_args << Fiddle::TYPE_INT << a
    end
    @tiparm.(str, *new_args)
  end

  def self.enabled?
    true
  end
end if Reline::Terminfo.curses_dl

module Reline::Terminfo
  def self.enabled?
    false
  end
end unless Reline::Terminfo.curses_dl