1 /*
2 * This file is part of Licq, an instant messaging client for UNIX.
3 * Copyright (C) 2003-2005 Martin Maurer (martinmaurer@gmx.at)
4 * Copyright (C) 2007-2010, 2013 Licq developers <licq-dev@googlegroups.com>
5 *
6 * Licq is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * Licq is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with Licq; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21 #include "my_xosd.h"
22
23 #include <iostream>
24 #include <libintl.h>
25 #include <sstream>
26 #include <string>
27 #include <unistd.h>
28 #define _(String) gettext (String)
29
30 using std::string;
31
32 extern void log(int mode, const char *message);
33
34 xosd *osd=0;
35 unsigned long Lines=0, Linelen=0;
36 unsigned long Timeout, DelayPerCharacter;
37 bool Wait=true;
38
toString(int number)39 std::string toString(int number)
40 {
41 std::ostringstream os;
42 os << number;
43 return os.str();
44 }
45
46 // one time setup of the xosd display
47 // warning: xosd lib functions give 0 on success !!!
my_xosd_init(string font=FONT,string colour=COLOUR,unsigned long hoffset=HORIZONTAL_OFFSET,unsigned long voffset=VERTICAL_OFFSET,string vpos=VPOS,string hpos=HPOS,unsigned long timeout=DISPLAYTIMEOUT,unsigned long delaypercharacter=DELAYPERCHARACTER,unsigned long lines=LINES,unsigned long linelen=LINELEN,bool wait=WAIT,unsigned long shadowoffset=SHADOW_OFFSET,unsigned long outlineoffset=OUTLINE_OFFSET,string shadowcolour=SHADOW_COLOUR,string outlinecolour=OUTLINE_COLOUR)48 int my_xosd_init(string font=FONT,
49 string colour=COLOUR,
50 unsigned long hoffset=HORIZONTAL_OFFSET,
51 unsigned long voffset=VERTICAL_OFFSET,
52 string vpos=VPOS,
53 string hpos=HPOS,
54 unsigned long timeout=DISPLAYTIMEOUT,
55 unsigned long delaypercharacter=DELAYPERCHARACTER,
56 unsigned long lines=LINES,
57 unsigned long linelen=LINELEN,
58 bool wait=WAIT,
59 unsigned long shadowoffset=SHADOW_OFFSET,
60 unsigned long outlineoffset=OUTLINE_OFFSET,
61 string shadowcolour=SHADOW_COLOUR,
62 string outlinecolour=OUTLINE_COLOUR
63 )
64 {
65 // two global variables storing these values
66 Lines=lines;
67 Linelen=linelen;
68 Wait=wait;
69 xosd_pos osd_vpos=XOSD_bottom;
70 xosd_align osd_hpos=XOSD_left;
71
72 // osd is the global osd structure
73 osd=xosd_create(lines);
74 if (!osd)
75 {
76 string msg="Unable to create xosd object: ";
77 msg+=toString(lines);
78 msg+=" lines: ";
79 msg+=xosd_error;
80 log(1, msg.c_str());
81 return 0;
82 }
83 if (xosd_set_timeout(osd, 1))
84 {
85 log(1, string("Unable to set timeout ").append(xosd_error).c_str());
86 return 0;
87 }
88 Timeout=timeout;
89 DelayPerCharacter=delaypercharacter;
90
91
92 if (xosd_set_shadow_offset(osd, shadowoffset))
93 {
94 log(1, string("Unable to set shadow offset ").append(xosd_error).c_str());
95 return 0;
96 }
97
98 if (xosd_set_outline_offset(osd, outlineoffset))
99 {
100 log(1, string("Unable to set outline offset ").append(xosd_error).c_str());
101 return 0;
102 }
103
104 if (xosd_set_shadow_colour(osd, shadowcolour.c_str()))
105 {
106 log(1, string("Unable to set shadow colour ").append(xosd_error).c_str());
107 return 0;
108 }
109
110 if (xosd_set_outline_colour(osd, outlinecolour.c_str()))
111 {
112 log(1, string("Unable to set outline colour ").append(xosd_error).c_str());
113 return 0;
114 }
115 if (xosd_set_font(osd, font.c_str()))
116 {
117 log(1, string("Unable to set configured font ").append(xosd_error).c_str());
118 if (xosd_set_font(osd, FONT))
119 {
120 log(1, string("Unable to set default font ").append(xosd_error).c_str());
121 return 0;
122 }
123 }
124
125 if (vpos=="top")
126 osd_vpos=XOSD_top;
127 else if (vpos=="bottom")
128 osd_vpos=XOSD_bottom;
129 else if (vpos=="middle")
130 osd_vpos=XOSD_middle;
131 else
132 {
133 log(0, "invalid vertical position");
134 osd_vpos=XOSD_bottom;
135 }
136 if (xosd_set_pos(osd, osd_vpos))
137 {
138 log (1, string("unable to set vertical position").append(xosd_error).c_str());
139 return 0;
140 }
141
142 if (hpos=="left")
143 osd_hpos=XOSD_left;
144 else if (hpos=="right")
145 osd_hpos=XOSD_right;
146 else if (hpos=="center")
147 osd_hpos=XOSD_center;
148 else
149 {
150 log(0, "invalid horizontal position");
151 osd_hpos=XOSD_left;
152 }
153 if (xosd_set_align(osd, osd_hpos))
154 {
155 log (1, string("Unable to set specified alignment").append(xosd_error).c_str());
156 return 0;
157 }
158
159 if (xosd_set_vertical_offset(osd, voffset))
160 {
161 log (1, string("Unable to set vertical offset ").append(xosd_error).c_str());
162 return 0;
163 }
164 if (xosd_set_horizontal_offset(osd, hoffset))
165 {
166 log (1, string("Unable to set horizontal offset ").append(xosd_error).c_str());
167 return 0;
168 }
169 if (xosd_set_colour(osd, colour.c_str()))
170 {
171 log (1, string("Unable to set colour ").append(colour).append(xosd_error).c_str());
172 return 0;
173 }
174 #ifdef NEWXOSD
175 xosd_set_linetimeout(osd, 1);
176 xosd_set_autoscroll(osd, 1);
177 #endif // NEWXOSD
178
179 // necessary because otherwise the xosd_wait_until_no_display
180 // will cause a lock of timeout seconds in the my_xosd_display call
181 // if (xosd_hide(osd))
182 // {
183 // log (1, "Unable to hide osd display");
184 // return 0;
185 // }
186 my_xosd_display(_("System"), _("XOSD plugin initialized"));
187 return 1;
188 }
189
my_xosd_settimeout(unsigned long timeout)190 int my_xosd_settimeout(unsigned long timeout)
191 {
192 if (timeout>120)
193 timeout=120;
194 return !xosd_set_timeout(osd, timeout);
195 }
196
197 // free ressources
my_xosd_exit()198 int my_xosd_exit()
199 {
200 if (osd)
201 return !xosd_destroy(osd);
202 return 0;
203 }
204
205 #ifndef NEWXOSD
getWord(string message,unsigned int & pos,unsigned int maxlen)206 string getWord(string message, unsigned int &pos, unsigned int maxlen)
207 {
208 string word;
209 word="";
210 while ((pos<message.length()) && (((unsigned char)message.at(pos))>' ')) // as long as we are on the same word
211 {
212 word+=message.at(pos++); // add character to word
213 }
214 if ((pos<message.length()) && (word.length()==0) && (message.at(pos)=='\n')) // newline detected
215 {
216 word=" ";
217 pos++;
218 }
219 else if ((pos<message.length()) && (message.at(pos)!='\n')) // we are at word boundary
220 pos++;
221 if (word.length()>maxlen) // if word is too long
222 {
223 pos-=(word.length()-maxlen);
224 word=word.substr(0, maxlen);
225 }
226 return word;
227 }
228 #endif // !NEWXOSD
229
my_xosd_display(string username,string message,string colour)230 int my_xosd_display(string username, string message, string colour)
231 {
232 #ifndef NEWXOSD
233 string *text;
234 string word;
235 unsigned int i;
236 unsigned int line=1;
237 #endif // !NEWXOSD
238
239 if (!osd)
240 return 0;
241
242 if (Lines==0)
243 return 0;
244
245 // hard limit of 50 - more doesnt seems to make sense
246 // change this if you need more.
247 if (Lines>50)
248 {
249 log (1, "More than 50 lines not allowed - see my_xosd.cpp");
250 return 0;
251 }
252
253 if (Linelen==0)
254 return 0;
255
256 // hard limit of 500 - more doesnt seems to make sense
257 // change this if you need more.
258 if (Linelen>500)
259 {
260 log (1, "More than 500 characters per line not allowed - see my_xosd.cpp");
261 return 0;
262 }
263
264 if (Linelen<=username.length()+2) // Linelen is too short
265 return 0;
266
267 // let the old message time out
268 if (Wait && xosd_wait_until_no_display(osd))
269 return 0;
270
271 if (colour.length()) {
272 if (xosd_set_colour(osd, colour.c_str()))
273 {
274 log (1, "Unable to set colour ");
275 return 0;
276 }
277 }
278
279 #ifdef NEWXOSD
280 username += ": ";
281 xosd_set_message_indention_string(osd, (char *) username.c_str());
282 xosd_display(osd, xosd_get_number_lines(osd), XOSD_message,
283 message.c_str());
284
285 #else // !NEWXOSD
286 // scroll the current lines out of osd display
287 // otherwise we get artefacts when called second time
288 xosd_scroll(osd, Lines);
289
290 text=new string[Lines];
291
292 try {
293 if ((username!="") && (username!="autoresponse"))
294 {
295 // create output lines
296 text[0]=username;
297 text[0]+=": ";
298 for (i=1;i<Lines;i++) // indent second and following lines
299 for(unsigned int j=0;j<username.length()+2;j++)
300 text[i]+=" ";
301 i=0;
302 line=0;
303 while ((line<Lines) && (i<message.length()))
304 {
305 word=getWord(message, i, Linelen-username.length()-2);
306 if (word==" ") // " " is code for newline (see getWord)
307 {
308 line++;
309 }
310 else if (text[line].length()+word.length()<Linelen) // valid word and line long enough
311 {
312 text[line]+=word;
313 text[line]+=' ';
314 }
315 else // line too short --> start new line
316 {
317 line++;
318 if (line<Lines) // further lines available?
319 {
320 text[line]+=word;
321 text[line]+=' ';
322 }
323 }
324 }
325 unsigned long timeout_msg=0;
326 for (i=0;i<Lines;i++)
327 timeout_msg+=text[i].length();
328 // if (DelayPerCharacter!=0)
329 my_xosd_settimeout(Timeout+(DelayPerCharacter*timeout_msg)/1000);
330 // else
331 // my_xosd_settimeout(Timeout);
332
333 }
334 else
335 {
336 text[0]=message;
337 // if (username=="autoresponse")
338 my_xosd_settimeout(Timeout+(DelayPerCharacter*text[0].length())/1000);
339 // else
340 // my_xosd_settimeout(Timeout+(DelayPerCharacter*timeout_msg)/1000);
341 }
342 }
343 catch (...) // some error occurred in message parsing - skip message
344 {
345 return 0;
346 }
347 // display the output lines
348 for (i=0;i<Lines;i++)
349 xosd_display(osd, i, XOSD_string, text[i].c_str());
350 delete[] text;
351 #endif // NEWXOSD
352 return 1;
353 }
354