1 #include "messagebuffer.hpp"
3 messagebuffer::update_handler::~update_handler() throw()
7 messagebuffer::messagebuffer(size_t maxmessages
, size_t windowsize
) throw(std::bad_alloc
, std::logic_error
)
9 if(windowsize
> maxmessages
)
10 throw std::logic_error("Invalid window size");
12 throw std::logic_error("Invalid max message count");
13 first_present_message
= 0;
14 next_message_number
= 0;
16 max_messages
= maxmessages
;
17 window_size
= windowsize
;
18 scroll_frozen
= false;
19 updates_frozen
= false;
20 window_start_at_freeze
= 0;
21 window_size_at_freeze
= 0;
22 next_message_number_at_freeze
= 0;
25 void messagebuffer::add_message(const std::string
& msg
) throw(std::bad_alloc
, std::runtime_error
)
27 messages_buf
[next_message_number
++] = msg
;
28 //If too many messages, erase one.
29 if(messages_buf
.size() > max_messages
)
30 messages_buf
.erase(first_present_message
++);
31 //Force scrolling if message in window got erased.
32 if(window_start
< first_present_message
) {
33 window_start
= first_present_message
;
36 //Autoscrolling at the end.
37 if(!scroll_frozen
&& window_start
+ window_size
+ 1 == next_message_number
) {
44 const std::string
& messagebuffer::get_message(size_t msgnum
) throw(std::bad_alloc
, std::logic_error
)
46 if(!messages_buf
.count(msgnum
))
47 throw std::logic_error("Invalid message number");
48 return messages_buf
[msgnum
];
51 size_t messagebuffer::get_msg_first() throw()
53 return first_present_message
;
56 size_t messagebuffer::get_msg_count() throw()
58 return next_message_number
- first_present_message
;
61 size_t messagebuffer::get_visible_first() throw()
66 size_t messagebuffer::get_visible_count() throw()
68 if(window_start
+ window_size
> next_message_number
)
69 return next_message_number
- window_start
;
74 bool messagebuffer::is_more_messages() throw()
76 return (window_start
+ window_size
< next_message_number
);
79 void messagebuffer::freeze_scrolling() throw()
84 void messagebuffer::unfreeze_scrolling() throw()
86 scroll_frozen
= false;
89 void messagebuffer::freeze_updates() throw()
91 updates_frozen
= true;
92 window_size_at_freeze
= window_size
;
93 window_start_at_freeze
= window_start
;
94 next_message_number_at_freeze
= next_message_number
;
97 bool messagebuffer::unfreeze_updates() throw()
99 updates_frozen
= false;
100 if(window_start_at_freeze
< first_present_message
)
102 uint64_t messages_visible_at_freeze
;
103 uint64_t messages_visible_now
;
104 if(window_start_at_freeze
+ window_size_at_freeze
>= next_message_number_at_freeze
)
105 messages_visible_at_freeze
= next_message_number_at_freeze
- window_start_at_freeze
;
107 messages_visible_at_freeze
= window_size_at_freeze
;
108 messages_visible_now
= get_visible_count();
109 if(messages_visible_now
!= messages_visible_at_freeze
)
111 if(window_start_at_freeze
!= window_start
)
116 void messagebuffer::scroll_beginning() throw(std::bad_alloc
, std::runtime_error
)
118 if(window_start
== first_present_message
)
120 window_start
= first_present_message
;
121 send_notifications();
124 void messagebuffer::scroll_up_page() throw(std::bad_alloc
, std::runtime_error
)
126 if(window_start
== first_present_message
)
128 if(window_start
< first_present_message
+ window_size
)
129 window_start
= first_present_message
;
131 window_start
-= window_size
;
132 send_notifications();
135 void messagebuffer::scroll_up_line() throw(std::bad_alloc
, std::runtime_error
)
137 if(window_start
== first_present_message
)
140 send_notifications();
143 void messagebuffer::scroll_down_line() throw(std::bad_alloc
, std::runtime_error
)
145 if(window_start
+ window_size
>= next_message_number
)
148 send_notifications();
151 void messagebuffer::scroll_down_page() throw(std::bad_alloc
, std::runtime_error
)
153 if(window_start
+ window_size
>= next_message_number
)
155 window_start
+= window_size
;
156 if(window_start
+ window_size
>= next_message_number
)
157 window_start
= next_message_number
- window_size
;
158 send_notifications();
161 void messagebuffer::scroll_end() throw(std::bad_alloc
, std::runtime_error
)
163 if(first_present_message
+ window_size
> next_message_number
)
165 window_start
= next_message_number
- window_size
;
166 send_notifications();
169 void messagebuffer::register_handler(messagebuffer::update_handler
& handler
) throw(std::bad_alloc
)
171 handlers
.insert(&handler
);
174 void messagebuffer::unregister_handler(messagebuffer::update_handler
& handler
) throw()
176 handlers
.erase(&handler
);
179 void messagebuffer::set_max_window_size(size_t windowsize
) throw(std::bad_alloc
, std::logic_error
)
181 if(windowsize
> max_messages
)
182 throw std::logic_error("Invalid window size");
183 if(window_size
> windowsize
) {
185 bool autoscrolling
= !scroll_frozen
&& (window_start
+ window_size
>= next_message_number
);
186 if(autoscrolling
&& window_start
+ windowsize
< next_message_number
)
187 window_start
= next_message_number
- windowsize
;
188 window_size
= windowsize
;
189 send_notifications();
190 } else if(window_size
< windowsize
) {
192 if(first_present_message
+ windowsize
>= next_message_number
)
193 window_start
= first_present_message
;
194 else if(window_start
+ windowsize
>= next_message_number
)
195 window_start
= next_message_number
- windowsize
;
196 window_size
= windowsize
;
197 send_notifications();
201 size_t messagebuffer::get_max_window_size() throw()
206 void messagebuffer::send_notifications()
210 for(auto i
: handlers
)
211 i
->messagebuffer_update();
214 std::string
messagebuffer::get_last_message()
216 if(messages_buf
.empty())
218 return messages_buf
.rbegin()->second
;