8 CURSES_COLORS = [Curses::COLOR_BLACK, Curses::COLOR_RED, Curses::COLOR_GREEN,
9 Curses::COLOR_YELLOW, Curses::COLOR_BLUE,
10 Curses::COLOR_MAGENTA, Curses::COLOR_CYAN,
15 raise "only one instance can be created" if @@instance
18 @color_pairs = {[Curses::COLOR_WHITE, Curses::COLOR_BLACK] => 0}
21 yield self if block_given?
22 @entries[highlight_sym(:none)] = highlight_for(Curses::COLOR_WHITE,
27 def add sym, fg, bg, *attrs
28 raise ArgumentError, "color for #{sym} already defined" if
30 raise ArgumentError, "color '#{fg}' unknown" unless CURSES_COLORS.include? fg
31 raise ArgumentError, "color '#{bg}' unknown" unless CURSES_COLORS.include? bg
33 @entries[sym] = [fg, bg, attrs, nil]
34 @entries[highlight_sym(sym)] = highlight_for(fg, bg, attrs) + [nil]
38 "#{sym}_highlight".intern
41 def highlight_for fg, bg, attrs
44 when Curses::COLOR_BLUE
46 when Curses::COLOR_YELLOW, Curses::COLOR_GREEN
54 when Curses::COLOR_CYAN
61 if fg == Curses::COLOR_WHITE && attrs.include?(Curses::A_BOLD)
65 when Curses::COLOR_BLACK
74 def color_for sym, highlight=false
75 sym = highlight_sym(sym) if highlight
76 return Curses::COLOR_BLACK if sym == :none
77 raise ArgumentError, "undefined color #{sym}" unless @entries.member? sym
79 ## if this color is cached, return it
80 fg, bg, attrs, color = @entries[sym]
83 if(cp = @color_pairs[[fg, bg]])
85 else ## need to get a new colorpair
86 @next_id = (@next_id + 1) % NUM_COLORS
87 @next_id += 1 if @next_id == 0 # 0 is always white on black
89 Redwood::log "colormap: for color #{sym}, using id #{id} -> #{fg}, #{bg}"
90 Curses.init_pair id, fg, bg or raise ArgumentError,
91 "couldn't initialize curses color pair #{fg}, #{bg} (key #{id})"
93 cp = @color_pairs[[fg, bg]] = Curses.color_pair(id)
94 ## delete the old mapping, if it exists
96 @users[cp].each do |usym|
97 Redwood::log "dropping color #{usym} (#{id})"
98 @entries[usym][3] = nil
104 ## by now we have a color pair
105 color = attrs.inject(cp) { |color, attr| color | attr }
106 @entries[sym][3] = color # fill the cache
107 (@users[cp] ||= []) << sym # record entry as a user of that color pair
111 def self.instance; @@instance; end
112 def self.method_missing meth, *a
113 Colorcolors.new unless @@instance
114 @@instance.send meth, *a