6 CURSES_COLORS = [Curses::COLOR_BLACK, Curses::COLOR_RED, Curses::COLOR_GREEN,
7 Curses::COLOR_YELLOW, Curses::COLOR_BLUE,
8 Curses::COLOR_MAGENTA, Curses::COLOR_CYAN,
13 raise "only one instance can be created" if @@instance
16 @color_pairs = {[Curses::COLOR_WHITE, Curses::COLOR_BLACK] => 0}
19 yield self if block_given?
20 @entries[highlight_sym(:none)] = highlight_for(Curses::COLOR_WHITE,
25 def add sym, fg, bg, attr=nil, opts={}
26 raise ArgumentError, "color for #{sym} already defined" if @entries.member? sym
27 raise ArgumentError, "color '#{fg}' unknown" unless CURSES_COLORS.include? fg
28 raise ArgumentError, "color '#{bg}' unknown" unless CURSES_COLORS.include? bg
29 attrs = [attr].flatten.compact
31 @entries[sym] = [fg, bg, attrs, nil]
32 @entries[highlight_sym(sym)] = opts[:highlight] ? @entries[opts[:highlight]] : highlight_for(fg, bg, attrs) + [nil]
36 "#{sym}_highlight".intern
39 def highlight_for fg, bg, attrs
42 when Curses::COLOR_BLUE
44 when Curses::COLOR_YELLOW, Curses::COLOR_GREEN
52 when Curses::COLOR_CYAN
59 if fg == Curses::COLOR_WHITE && attrs.include?(Curses::A_BOLD)
63 when Curses::COLOR_BLACK
72 def color_for sym, highlight=false
73 sym = highlight_sym(sym) if highlight
74 return Curses::COLOR_BLACK if sym == :none
75 raise ArgumentError, "undefined color #{sym}" unless @entries.member? sym
77 ## if this color is cached, return it
78 fg, bg, attrs, color = @entries[sym]
81 if(cp = @color_pairs[[fg, bg]])
83 else ## need to get a new colorpair
84 @next_id = (@next_id + 1) % NUM_COLORS
85 @next_id += 1 if @next_id == 0 # 0 is always white on black
87 Redwood::log "colormap: for color #{sym}, using id #{id} -> #{fg}, #{bg}"
88 Curses.init_pair id, fg, bg or raise ArgumentError,
89 "couldn't initialize curses color pair #{fg}, #{bg} (key #{id})"
91 cp = @color_pairs[[fg, bg]] = Curses.color_pair(id)
92 ## delete the old mapping, if it exists
94 @users[cp].each do |usym|
95 Redwood::log "dropping color #{usym} (#{id})"
96 @entries[usym][3] = nil
102 ## by now we have a color pair
103 color = attrs.inject(cp) { |color, attr| color | attr }
104 @entries[sym][3] = color # fill the cache
105 (@users[cp] ||= []) << sym # record entry as a user of that color pair
109 def self.instance; @@instance; end
110 def self.method_missing meth, *a
111 Colorcolors.new unless @@instance
112 @@instance.send meth, *a