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