summaryrefslogtreecommitdiff
Unidiff
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--library/alarmserver.cpp23
-rw-r--r--library/global.cpp6
2 files changed, 17 insertions, 12 deletions
diff --git a/library/alarmserver.cpp b/library/alarmserver.cpp
index 2ea4025..a75fc7e 100644
--- a/library/alarmserver.cpp
+++ b/library/alarmserver.cpp
@@ -1,449 +1,452 @@
1/********************************************************************** 1/**********************************************************************
2** Copyright (C) 2000-2002 Trolltech AS. All rights reserved. 2** Copyright (C) 2000-2002 Trolltech AS. All rights reserved.
3** 3**
4** This file is part of the Qtopia Environment. 4** This file is part of the Qtopia Environment.
5** 5**
6** This file may be distributed and/or modified under the terms of the 6** This file may be distributed and/or modified under the terms of the
7** GNU General Public License version 2 as published by the Free Software 7** GNU General Public License version 2 as published by the Free Software
8** Foundation and appearing in the file LICENSE.GPL included in the 8** Foundation and appearing in the file LICENSE.GPL included in the
9** packaging of this file. 9** packaging of this file.
10** 10**
11** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE 11** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
12** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 12** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
13** 13**
14** See http://www.trolltech.com/gpl/ for GPL licensing information. 14** See http://www.trolltech.com/gpl/ for GPL licensing information.
15** 15**
16** Contact info@trolltech.com if any conditions of this licensing are 16** Contact info@trolltech.com if any conditions of this licensing are
17** not clear to you. 17** not clear to you.
18** 18**
19**********************************************************************/ 19**********************************************************************/
20 20
21#include <qdir.h> 21#include <qdir.h>
22#include <qfile.h> 22#include <qfile.h>
23#include <qmessagebox.h> 23#include <qmessagebox.h>
24#include <qtextstream.h> 24#include <qtextstream.h>
25 25
26 26
27#include <qpe/qpeapplication.h> 27#include <qpe/qpeapplication.h>
28#include "global.h" 28#include "global.h"
29#include "resource.h" 29#include "resource.h"
30 30
31#include <qpe/qcopenvelope_qws.h> 31#include <qpe/qcopenvelope_qws.h>
32#include "alarmserver.h" 32#include "alarmserver.h"
33#include <qpe/timeconversion.h> 33#include <qpe/timeconversion.h>
34 34
35#include <sys/types.h> 35#include <sys/types.h>
36#include <sys/stat.h> 36#include <sys/stat.h>
37 37
38#include <stdlib.h> 38#include <stdlib.h>
39#include <unistd.h> 39#include <unistd.h>
40 40
41 41
42#undef USE_ATD // not used anymore -- we run opie-alarm on suspend/resume 42#undef USE_ATD // not used anymore -- we run opie-alarm on suspend/resume
43 43
44 44
45struct timerEventItem 45struct timerEventItem
46{ 46{
47 time_t UTCtime; 47 time_t UTCtime;
48 QCString channel, message; 48 QCString channel, message;
49 int data; 49 int data;
50 bool operator==( const timerEventItem &right ) const 50 bool operator==( const timerEventItem &right ) const
51 { 51 {
52 return ( UTCtime == right.UTCtime 52 return ( UTCtime == right.UTCtime
53 && channel == right.channel 53 && channel == right.channel
54 && message == right.message 54 && message == right.message
55 && data == right.data ); 55 && data == right.data );
56 } 56 }
57}; 57};
58 58
59class TimerReceiverObject : public QObject 59class TimerReceiverObject : public QObject
60{ 60{
61public: 61public:
62 TimerReceiverObject() 62 TimerReceiverObject()
63 { } 63 { }
64 ~TimerReceiverObject() 64 ~TimerReceiverObject()
65 { } 65 { }
66 void resetTimer(); 66 void resetTimer();
67 void setTimerEventItem(); 67 void setTimerEventItem();
68 void deleteTimer(); 68 void deleteTimer();
69protected: 69protected:
70 void timerEvent( QTimerEvent *te ); 70 void timerEvent( QTimerEvent *te );
71 71
72#ifdef USE_ATD 72#ifdef USE_ATD
73private: 73private:
74 QString atfilename; 74 QString atfilename;
75#endif 75#endif
76}; 76};
77 77
78TimerReceiverObject *timerEventReceiver = NULL; 78TimerReceiverObject *timerEventReceiver = NULL;
79QList<timerEventItem> timerEventList; 79QList<timerEventItem> timerEventList;
80timerEventItem *nearestTimerEvent = NULL; 80timerEventItem *nearestTimerEvent = NULL;
81 81
82 82
83// set the timer to go off on the next event in the list 83// set the timer to go off on the next event in the list
84void setNearestTimerEvent() 84void setNearestTimerEvent()
85{ 85{
86 nearestTimerEvent = NULL; 86 nearestTimerEvent = NULL;
87 QListIterator<timerEventItem> it( timerEventList ); 87 QListIterator<timerEventItem> it( timerEventList );
88 if ( *it ) 88 if ( *it )
89 nearestTimerEvent = *it; 89 nearestTimerEvent = *it;
90 for ( ; *it; ++it ) 90 for ( ; *it; ++it )
91 if ( (*it)->UTCtime < nearestTimerEvent->UTCtime ) 91 if ( (*it)->UTCtime < nearestTimerEvent->UTCtime )
92 nearestTimerEvent = *it; 92 nearestTimerEvent = *it;
93 if (nearestTimerEvent) 93 if (nearestTimerEvent)
94 timerEventReceiver->resetTimer(); 94 timerEventReceiver->resetTimer();
95 else 95 else
96 timerEventReceiver->deleteTimer(); 96 timerEventReceiver->deleteTimer();
97} 97}
98 98
99 99
100//store current state to file 100//store current state to file
101//Simple implementation. Should run on a timer. 101//Simple implementation. Should run on a timer.
102 102
103static void saveState() 103static void saveState()
104{ 104{
105 QString savefilename = Global::applicationFileName( "AlarmServer", "saveFile" ); 105 QString savefilename = Global::applicationFileName( "AlarmServer", "saveFile" );
106 if ( timerEventList.isEmpty() ) { 106 if ( timerEventList.isEmpty() ) {
107 unlink( savefilename ); 107 unlink( savefilename );
108 return ; 108 return ;
109 } 109 }
110 110
111 QFile savefile(savefilename + ".new"); 111 QFile savefile(savefilename + ".new");
112 if ( savefile.open(IO_WriteOnly) ) { 112 if ( savefile.open(IO_WriteOnly) ) {
113 QDataStream ds( &savefile ); 113 QDataStream ds( &savefile );
114 114
115 //save 115 //save
116 116
117 QListIterator<timerEventItem> it( timerEventList ); 117 QListIterator<timerEventItem> it( timerEventList );
118 for ( ; *it; ++it ) { 118 for ( ; *it; ++it ) {
119 ds << it.current()->UTCtime; 119 ds << it.current()->UTCtime;
120 ds << it.current()->channel; 120 ds << it.current()->channel;
121 ds << it.current()->message; 121 ds << it.current()->message;
122 ds << it.current()->data; 122 ds << it.current()->data;
123 } 123 }
124 124
125 125
126 savefile.close(); 126 savefile.close();
127 unlink( savefilename ); 127 unlink( savefilename );
128 QDir d; 128 QDir d;
129 d.rename(savefilename + ".new", savefilename); 129 d.rename(savefilename + ".new", savefilename);
130 130
131 } 131 }
132} 132}
133 133
134/*! 134/*!
135 Sets up the alarm server. Restoring to previous state (session management). 135 Sets up the alarm server. Restoring to previous state (session management).
136 */ 136 */
137void AlarmServer::initialize() 137void AlarmServer::initialize()
138{ 138{
139 //read autosave file and put events in timerEventList 139 //read autosave file and put events in timerEventList
140 140
141 QString savefilename = Global::applicationFileName( "AlarmServer", "saveFile" ); 141 QString savefilename = Global::applicationFileName( "AlarmServer", "saveFile" );
142 142
143 QFile savefile(savefilename); 143 QFile savefile(savefilename);
144 if ( savefile.open(IO_ReadOnly) ) { 144 if ( savefile.open(IO_ReadOnly) ) {
145 QDataStream ds( &savefile ); 145 QDataStream ds( &savefile );
146 while ( !ds.atEnd() ) { 146 while ( !ds.atEnd() ) {
147 timerEventItem *newTimerEventItem = new timerEventItem; 147 timerEventItem *newTimerEventItem = new timerEventItem;
148 ds >> newTimerEventItem->UTCtime; 148 ds >> newTimerEventItem->UTCtime;
149 ds >> newTimerEventItem->channel; 149 ds >> newTimerEventItem->channel;
150 ds >> newTimerEventItem->message; 150 ds >> newTimerEventItem->message;
151 ds >> newTimerEventItem->data; 151 ds >> newTimerEventItem->data;
152 timerEventList.append( newTimerEventItem ); 152 timerEventList.append( newTimerEventItem );
153 } 153 }
154 savefile.close(); 154 savefile.close();
155 if (!timerEventReceiver) 155 if (!timerEventReceiver)
156 timerEventReceiver = new TimerReceiverObject; 156 timerEventReceiver = new TimerReceiverObject;
157 setNearestTimerEvent(); 157 setNearestTimerEvent();
158 } 158 }
159} 159}
160 160
161 161
162#ifdef USE_ATD 162#ifdef USE_ATD
163 163
164static const char* atdir = "/var/spool/at/"; 164static const char* atdir = "/var/spool/at/";
165 165
166static bool triggerAtd( bool writeHWClock = FALSE ) 166static bool triggerAtd( bool writeHWClock = FALSE )
167{ 167{
168 QFile trigger(QString(atdir) + "trigger"); 168 QFile trigger(QString(atdir) + "trigger");
169 if ( trigger.open(IO_WriteOnly | IO_Raw) ) { 169 if ( trigger.open(IO_WriteOnly | IO_Raw) ) {
170 if ( trigger.writeBlock("\n", 2) != 2 ) { 170 if ( trigger.writeBlock("\n", 2) != 2 ) {
171 QMessageBox::critical( 0, QObject::tr( "Out of Space" ), 171 QMessageBox::critical( 0, QObject::tr( "Out of Space" ),
172 QObject::tr( "Unable to schedule alarm.\nFree some memory and try again." ) ); 172 QObject::tr( "Unable to schedule alarm.\nFree some memory and try again." ) );
173 trigger.close(); 173 trigger.close();
174 QFile::remove 174 QFile::remove
175 ( trigger.name() ); 175 ( trigger.name() );
176 return FALSE; 176 return FALSE;
177 } 177 }
178 return TRUE; 178 return TRUE;
179 } 179 }
180 return FALSE; 180 return FALSE;
181} 181}
182 182
183#else 183#else
184 184
185static bool writeResumeAt ( time_t wakeup ) 185static bool writeResumeAt ( time_t wakeup )
186{ 186{
187 FILE *fp = ::fopen ( "/var/run/resumeat", "w" ); 187 FILE *fp = ::fopen ( "/var/run/resumeat", "w" );
188 188
189 if ( fp ) { 189 if ( fp ) {
190 ::fprintf ( fp, "%d\n", (int) wakeup ); 190 ::fprintf ( fp, "%d\n", (int) wakeup );
191 ::fclose ( fp ); 191 ::fclose ( fp );
192 } 192 }
193 else 193 else
194 qWarning ( "Failed to write wakeup time to /var/run/resumeat" ); 194 qWarning ( "Failed to write wakeup time to /var/run/resumeat" );
195 195
196 return ( fp ); 196 return ( fp );
197} 197}
198 198
199#endif 199#endif
200 200
201void TimerReceiverObject::deleteTimer() 201void TimerReceiverObject::deleteTimer()
202{ 202{
203#ifdef USE_ATD 203#ifdef USE_ATD
204 if ( !atfilename.isEmpty() ) { 204 if ( !atfilename.isEmpty() ) {
205 unlink( atfilename ); 205 unlink( atfilename );
206 atfilename = QString::null; 206 atfilename = QString::null;
207 triggerAtd( FALSE ); 207 triggerAtd( FALSE );
208 } 208 }
209#else 209#else
210 writeResumeAt ( 0 ); 210 writeResumeAt ( 0 );
211#endif 211#endif
212} 212}
213 213
214void TimerReceiverObject::resetTimer() 214void TimerReceiverObject::resetTimer()
215{ 215{
216 const int maxsecs = 2147000; 216 const int maxsecs = 2147000;
217 QDateTime nearest = TimeConversion::fromUTC(nearestTimerEvent->UTCtime); 217 QDateTime nearest = TimeConversion::fromUTC(nearestTimerEvent->UTCtime);
218 QDateTime now = QDateTime::currentDateTime(); 218 QDateTime now = QDateTime::currentDateTime();
219 if ( nearest < now ) 219 if ( nearest < now )
220 nearest = now; 220 nearest = now;
221 int secs = TimeConversion::secsTo( now, nearest ); 221 int secs = TimeConversion::secsTo( now, nearest );
222 if ( secs > maxsecs ) { 222 if ( secs > maxsecs ) {
223 // too far for millisecond timing 223 // too far for millisecond timing
224 secs = maxsecs; 224 secs = maxsecs;
225 } 225 }
226 226
227 // System timer (needed so that we wake from deep sleep), 227 // System timer (needed so that we wake from deep sleep),
228 // from the Epoch in seconds. 228 // from the Epoch in seconds.
229 // 229 //
230 int at_secs = TimeConversion::toUTC(nearest); 230 int at_secs = TimeConversion::toUTC(nearest);
231 // qDebug("reset timer to %d seconds from Epoch",at_secs); 231 // qDebug("reset timer to %d seconds from Epoch",at_secs);
232 232
233#ifdef USE_ATD 233#ifdef USE_ATD
234 234
235 QString fn = atdir + QString::number(at_secs) + "." 235 QString fn = atdir + QString::number(at_secs) + "."
236 + QString::number(getpid()); 236 + QString::number(getpid());
237 if ( fn != atfilename ) { 237 if ( fn != atfilename ) {
238 QFile atfile(fn + ".new"); 238 QFile atfile(fn + ".new");
239 if ( atfile.open(IO_WriteOnly | IO_Raw) ) { 239 if ( atfile.open(IO_WriteOnly | IO_Raw) ) {
240 int total_written; 240 int total_written;
241 241
242 // just wake up and delete the at file 242 // just wake up and delete the at file
243 QString cmd = "#!/bin/sh\nrm " + fn; 243 QString cmd = "#!/bin/sh\nrm " + fn;
244 total_written = atfile.writeBlock(cmd.latin1(), cmd.length()); 244 total_written = atfile.writeBlock(cmd.latin1(), cmd.length());
245 if ( total_written != int(cmd.length()) ) { 245 if ( total_written != int(cmd.length()) ) {
246 QMessageBox::critical( 0, tr("Out of Space"), 246 QMessageBox::critical( 0, tr("Out of Space"),
247 tr("Unable to schedule alarm.\n" 247 tr("Unable to schedule alarm.\n"
248 "Please free up space and try again") ); 248 "Please free up space and try again") );
249 atfile.close(); 249 atfile.close();
250 QFile::remove 250 QFile::remove
251 ( atfile.name() ); 251 ( atfile.name() );
252 return ; 252 return ;
253 } 253 }
254 atfile.close(); 254 atfile.close();
255 unlink( atfilename ); 255 unlink( atfilename );
256 QDir d; 256 QDir d;
257 d.rename(fn + ".new", fn); 257 d.rename(fn + ".new", fn);
258 chmod(fn.latin1(), 0755); 258 chmod(fn.latin1(), 0755);
259 atfilename = fn; 259 atfilename = fn;
260 triggerAtd( FALSE ); 260 triggerAtd( FALSE );
261 } 261 }
262 else { 262 else {
263 qWarning("Cannot open atd file %s", fn.latin1()); 263 qWarning("Cannot open atd file %s", fn.latin1());
264 } 264 }
265 } 265 }
266#else 266#else
267 writeResumeAt ( at_secs ); 267 writeResumeAt ( at_secs );
268 268
269#endif 269#endif
270 270
271 // Qt timers (does the actual alarm) 271 // Qt timers (does the actual alarm)
272 // from now in milliseconds 272 // from now in milliseconds
273 // 273 //
274 qDebug("AlarmServer waiting %d seconds", secs); 274 qDebug("AlarmServer waiting %d seconds", secs);
275 startTimer( 1000 * secs + 500 ); 275 startTimer( 1000 * secs + 500 );
276} 276}
277 277
278void TimerReceiverObject::timerEvent( QTimerEvent * ) 278void TimerReceiverObject::timerEvent( QTimerEvent * )
279{ 279{
280 bool needSave = FALSE; 280 bool needSave = FALSE;
281 killTimers(); 281 killTimers();
282 if (nearestTimerEvent) { 282 if (nearestTimerEvent) {
283 if ( nearestTimerEvent->UTCtime 283 if ( nearestTimerEvent->UTCtime
284 <= TimeConversion::toUTC(QDateTime::currentDateTime()) ) { 284 <= TimeConversion::toUTC(QDateTime::currentDateTime()) ) {
285#ifndef QT_NO_COP 285#ifndef QT_NO_COP
286 QCopEnvelope e( nearestTimerEvent->channel, 286 QCopEnvelope e( nearestTimerEvent->channel,
287 nearestTimerEvent->message ); 287 nearestTimerEvent->message );
288 e << TimeConversion::fromUTC( nearestTimerEvent->UTCtime ) 288 e << TimeConversion::fromUTC( nearestTimerEvent->UTCtime )
289 << nearestTimerEvent->data; 289 << nearestTimerEvent->data;
290#endif 290#endif
291 291
292 timerEventList.remove( nearestTimerEvent ); 292 timerEventList.remove( nearestTimerEvent );
293 needSave = TRUE; 293 needSave = TRUE;
294 } 294 }
295 setNearestTimerEvent(); 295 setNearestTimerEvent();
296 } 296 }
297 else { 297 else {
298 resetTimer(); 298 resetTimer();
299 } 299 }
300 if ( needSave ) 300 if ( needSave )
301 saveState(); 301 saveState();
302} 302}
303 303
304/*! 304/*!
305 \class AlarmServer alarmserver.h 305 \class AlarmServer alarmserver.h
306 \brief The AlarmServer class allows alarms to be scheduled and unscheduled. 306 \brief The AlarmServer class allows alarms to be scheduled and unscheduled.
307 307
308 Applications can schedule alarms with addAlarm() and can 308 Applications can schedule alarms with addAlarm() and can
309 unschedule alarms with deleteAlarm(). When the time for an alarm 309 unschedule alarms with deleteAlarm(). When the time for an alarm
310 to go off is reached the specified \link qcop.html QCop\endlink 310 to go off is reached the specified \link qcop.html QCop\endlink
311 message is sent on the specified channel (optionally with 311 message is sent on the specified channel (optionally with
312 additional data). 312 additional data).
313 313
314 Scheduling an alarm using this class is important (rather just using 314 Scheduling an alarm using this class is important (rather just using
315 a QTimer) since the machine may be asleep and needs to get woken up using 315 a QTimer) since the machine may be asleep and needs to get woken up using
316 the Linux kernel which implements this at the kernel level to minimize 316 the Linux kernel which implements this at the kernel level to minimize
317 battery usage while asleep. 317 battery usage while asleep.
318 318
319 \ingroup qtopiaemb 319 \ingroup qtopiaemb
320 \sa QCopEnvelope 320 \sa QCopEnvelope
321*/ 321*/
322 322
323/*! 323/*!
324 Schedules an alarm to go off at (or soon after) time \a when. When 324 Schedules an alarm to go off at (or soon after) time \a when. When
325 the alarm goes off, the \link qcop.html QCop\endlink \a message will 325 the alarm goes off, the \link qcop.html QCop\endlink \a message will
326 be sent to \a channel, with \a data as a parameter. 326 be sent to \a channel, with \a data as a parameter.
327 327
328 If this function is called with exactly the same data as a previous 328 If this function is called with exactly the same data as a previous
329 call the subsequent call is ignored, so there is only ever one alarm 329 call the subsequent call is ignored, so there is only ever one alarm
330 with a given set of parameters. 330 with a given set of parameters.
331 331
332 \sa deleteAlarm() 332 \sa deleteAlarm()
333*/ 333*/
334void AlarmServer::addAlarm ( QDateTime when, const QCString& channel, 334void AlarmServer::addAlarm ( QDateTime when, const QCString& channel,
335 const QCString& message, int data) 335 const QCString& message, int data)
336{ 336{
337 if ( qApp->type() == QApplication::GuiServer ) { 337 if ( qApp->type() == QApplication::GuiServer ) {
338 bool needSave = FALSE; 338 bool needSave = FALSE;
339 // Here we are the server so either it has been directly called from 339 // Here we are the server so either it has been directly called from
340 // within the server or it has been sent to us from a client via QCop 340 // within the server or it has been sent to us from a client via QCop
341 if (!timerEventReceiver) 341 if (!timerEventReceiver)
342 timerEventReceiver = new TimerReceiverObject; 342 timerEventReceiver = new TimerReceiverObject;
343 343
344 timerEventItem *newTimerEventItem = new timerEventItem; 344 timerEventItem *newTimerEventItem = new timerEventItem;
345 newTimerEventItem->UTCtime = TimeConversion::toUTC( when ); 345 newTimerEventItem->UTCtime = TimeConversion::toUTC( when );
346 newTimerEventItem->channel = channel; 346 newTimerEventItem->channel = channel;
347 newTimerEventItem->message = message; 347 newTimerEventItem->message = message;
348 newTimerEventItem->data = data; 348 newTimerEventItem->data = data;
349 // explore the case of already having the event in here... 349 // explore the case of already having the event in here...
350 QListIterator<timerEventItem> it( timerEventList ); 350 QListIterator<timerEventItem> it( timerEventList );
351 for ( ; *it; ++it ) 351 for ( ; *it; ++it )
352 if ( *(*it) == *newTimerEventItem ) 352 if ( *(*it) == *newTimerEventItem )
353 return ; 353 return ;
354 // if we made it here, it is okay to add the item... 354 // if we made it here, it is okay to add the item...
355 timerEventList.append( newTimerEventItem ); 355 timerEventList.append( newTimerEventItem );
356 needSave = TRUE; 356 needSave = TRUE;
357 // quicker than using setNearestTimerEvent() 357 // quicker than using setNearestTimerEvent()
358 if ( nearestTimerEvent ) { 358 if ( nearestTimerEvent ) {
359 if (newTimerEventItem->UTCtime < nearestTimerEvent->UTCtime) { 359 if (newTimerEventItem->UTCtime < nearestTimerEvent->UTCtime) {
360 nearestTimerEvent = newTimerEventItem; 360 nearestTimerEvent = newTimerEventItem;
361 timerEventReceiver->killTimers(); 361 timerEventReceiver->killTimers();
362 timerEventReceiver->resetTimer(); 362 timerEventReceiver->resetTimer();
363 } 363 }
364 } 364 }
365 else { 365 else {
366 nearestTimerEvent = newTimerEventItem; 366 nearestTimerEvent = newTimerEventItem;
367 timerEventReceiver->resetTimer(); 367 timerEventReceiver->resetTimer();
368 } 368 }
369 if ( needSave ) 369 if ( needSave )
370 saveState(); 370 saveState();
371 } 371 }
372 else { 372 else {
373#ifndef QT_NO_COP 373#ifndef QT_NO_COP
374 QCopEnvelope e( "QPE/System", "addAlarm(QDateTime,QCString,QCString,int)" ); 374 QCopEnvelope e( "QPE/System", "addAlarm(QDateTime,QCString,QCString,int)" );
375 e << when << channel << message << data; 375 e << when << channel << message << data;
376#endif 376#endif
377 377
378 } 378 }
379} 379}
380 380
381/*! 381/*!
382 Deletes previously scheduled alarms which match \a when, \a channel, 382 Deletes previously scheduled alarms which match \a when, \a channel,
383 \a message, and \a data. 383 \a message, and \a data.
384 384
385 Passing null values for \a when, \a channel, or for the \link 385 Passing null values for \a when, \a channel, or for the \link
386 qcop.html QCop\endlink \a message, acts as a wildcard meaning "any". 386 qcop.html QCop\endlink \a message, acts as a wildcard meaning "any".
387 Similarly, passing -1 for \a data indicates "any". 387 Similarly, passing -1 for \a data indicates "any".
388 388
389 If there is no matching alarm, nothing happens. 389 If there is no matching alarm, nothing happens.
390 390
391 \sa addAlarm() 391 \sa addAlarm()
392 392
393*/ 393*/
394void AlarmServer::deleteAlarm (QDateTime when, const QCString& channel, const QCString& message, int data) 394void AlarmServer::deleteAlarm (QDateTime when, const QCString& channel, const QCString& message, int data)
395{ 395{
396 if ( qApp->type() == QApplication::GuiServer) { 396 if ( qApp->type() == QApplication::GuiServer) {
397 bool needSave = FALSE; 397 bool needSave = FALSE;
398 if ( timerEventReceiver != NULL ) { 398 if ( timerEventReceiver != NULL ) {
399 timerEventReceiver->killTimers(); 399 timerEventReceiver->killTimers();
400 400
401 // iterate over the list of events 401 // iterate over the list of events
402 QListIterator<timerEventItem> it( timerEventList ); 402 QListIterator<timerEventItem> it( timerEventList );
403 time_t deleteTime = TimeConversion::toUTC( when ); 403 time_t deleteTime = TimeConversion::toUTC( when );
404 for ( ; *it; ++it ) { 404 for ( ; *it; ++it ) {
405 // if its a match, delete it 405 // if its a match, delete it
406 if ( ( (*it)->UTCtime == deleteTime || when.isNull() ) 406 if ( ( (*it)->UTCtime == deleteTime || when.isNull() )
407 && ( channel.isNull() || (*it)->channel == channel ) 407 && ( channel.isNull() || (*it)->channel == channel )
408 && ( message.isNull() || (*it)->message == message ) 408 && ( message.isNull() || (*it)->message == message )
409 && ( data == -1 || (*it)->data == data ) ) { 409 && ( data == -1 || (*it)->data == data ) ) {
410 // if it's first, then we need to update the timer 410 // if it's first, then we need to update the timer
411 if ( (*it) == nearestTimerEvent ) { 411 if ( (*it) == nearestTimerEvent ) {
412 timerEventList.remove(*it); 412 timerEventList.remove(*it);
413 setNearestTimerEvent(); 413 setNearestTimerEvent();
414 } 414 }
415 else { 415 else {
416 timerEventList.remove(*it); 416 timerEventList.remove(*it);
417 } 417 }
418 needSave = TRUE; 418 needSave = TRUE;
419 } 419 }
420 } 420 }
421 if ( nearestTimerEvent ) 421 if ( nearestTimerEvent )
422 timerEventReceiver->resetTimer(); 422 timerEventReceiver->resetTimer();
423 } 423 }
424 if ( needSave ) 424 if ( needSave )
425 saveState(); 425 saveState();
426 } 426 }
427 else { 427 else {
428#ifndef QT_NO_COP 428#ifndef QT_NO_COP
429 QCopEnvelope e( "QPE/System", "deleteAlarm(QDateTime,QCString,QCString,int)" ); 429 QCopEnvelope e( "QPE/System", "deleteAlarm(QDateTime,QCString,QCString,int)" );
430 e << when << channel << message << data; 430 e << when << channel << message << data;
431#endif 431#endif
432 432
433 } 433 }
434} 434}
435 435
436/*! 436/*!
437 Writes the system clock to the hardware clock. 437 The implementation depends on the mode of AlarmServer. If the AlarmServer
438 uses atd the current system time will be written to the hardware clock.
439 If the AlarmServer relies on opie-alarm the time will be written once the
440 device gets suspended. opie-alarm is used by the Zaurus, iPAQs and SIMpad
438*/ 441*/
439void Global::writeHWClock() 442void Global::writeHWClock()
440{ 443{
441#ifdef USE_ATD 444#ifdef USE_ATD
442 if ( !triggerAtd( TRUE ) ) { 445 if ( !triggerAtd( TRUE ) ) {
443 // atd not running? set it ourselves 446 // atd not running? set it ourselves
444 system("/sbin/hwclock --systohc"); // ##### UTC? 447 system("/sbin/hwclock --systohc"); // ##### UTC?
445 } 448 }
446#else 449#else
447 // hwclock is written on suspend 450 // hwclock is written on suspend
448#endif 451#endif
449} 452}
diff --git a/library/global.cpp b/library/global.cpp
index 5c89430..90954fe 100644
--- a/library/global.cpp
+++ b/library/global.cpp
@@ -1,729 +1,731 @@
1/********************************************************************** 1/**********************************************************************
2** Copyright (C) 2000-2002 Trolltech AS. All rights reserved. 2** Copyright (C) 2000-2002 Trolltech AS. All rights reserved.
3** 3**
4** This file is part of the Qtopia Environment. 4** This file is part of the Qtopia Environment.
5** 5**
6** This file may be distributed and/or modified under the terms of the 6** This file may be distributed and/or modified under the terms of the
7** GNU General Public License version 2 as published by the Free Software 7** GNU General Public License version 2 as published by the Free Software
8** Foundation and appearing in the file LICENSE.GPL included in the 8** Foundation and appearing in the file LICENSE.GPL included in the
9** packaging of this file. 9** packaging of this file.
10** 10**
11** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE 11** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
12** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 12** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
13** 13**
14** See http://www.trolltech.com/gpl/ for GPL licensing information. 14** See http://www.trolltech.com/gpl/ for GPL licensing information.
15** 15**
16** Contact info@trolltech.com if any conditions of this licensing are 16** Contact info@trolltech.com if any conditions of this licensing are
17** not clear to you. 17** not clear to you.
18** 18**
19**********************************************************************/ 19**********************************************************************/
20#define QTOPIA_INTERNAL_LANGLIST 20#define QTOPIA_INTERNAL_LANGLIST
21#include <qpe/qpedebug.h> 21#include <qpe/qpedebug.h>
22#include <qpe/global.h> 22#include <qpe/global.h>
23#include <qpe/qdawg.h> 23#include <qpe/qdawg.h>
24#include <qpe/qpeapplication.h> 24#include <qpe/qpeapplication.h>
25#include <qpe/resource.h> 25#include <qpe/resource.h>
26#include <qpe/storage.h> 26#include <qpe/storage.h>
27#include <qpe/applnk.h> 27#include <qpe/applnk.h>
28#include <qpe/qcopenvelope_qws.h> 28#include <qpe/qcopenvelope_qws.h>
29 29
30#include <qfile.h> 30#include <qfile.h>
31#include <qlabel.h> 31#include <qlabel.h>
32#include <qtimer.h> 32#include <qtimer.h>
33#include <qmap.h> 33#include <qmap.h>
34#include <qdict.h> 34#include <qdict.h>
35#include <qdir.h> 35#include <qdir.h>
36#include <qmessagebox.h> 36#include <qmessagebox.h>
37#include <qregexp.h> 37#include <qregexp.h>
38 38
39#include <stdlib.h> 39#include <stdlib.h>
40#include <sys/stat.h> 40#include <sys/stat.h>
41#include <sys/wait.h> 41#include <sys/wait.h>
42#include <sys/types.h> 42#include <sys/types.h>
43#include <fcntl.h> 43#include <fcntl.h>
44#include <unistd.h> 44#include <unistd.h>
45#include <errno.h> 45#include <errno.h>
46 46
47#include <qwindowsystem_qws.h> // for qwsServer 47#include <qwindowsystem_qws.h> // for qwsServer
48#include <qdatetime.h> 48#include <qdatetime.h>
49 49
50#include <qfile.h> 50#include <qfile.h>
51 51
52namespace { 52namespace {
53 // checks if the storage should be searched 53 // checks if the storage should be searched
54 bool checkStorage(const QString &path ){ // this is a small Config replacement cause config is too limited -zecke 54 bool checkStorage(const QString &path ){ // this is a small Config replacement cause config is too limited -zecke
55 QFile file(path ); 55 QFile file(path );
56 if(!file.open(IO_ReadOnly ) ) 56 if(!file.open(IO_ReadOnly ) )
57 return true; 57 return true;
58 58
59 QByteArray array = file.readAll(); 59 QByteArray array = file.readAll();
60 QStringList list = QStringList::split('\n', QString( array ) ); 60 QStringList list = QStringList::split('\n', QString( array ) );
61 for(QStringList::Iterator it = list.begin(); it != list.end(); ++it ){ 61 for(QStringList::Iterator it = list.begin(); it != list.end(); ++it ){
62 if( (*it).startsWith("autocheck = 0" ) ){ 62 if( (*it).startsWith("autocheck = 0" ) ){
63 return false; 63 return false;
64 }else if( (*it).startsWith("autocheck = 1" ) ){ 64 }else if( (*it).startsWith("autocheck = 1" ) ){
65 return true; 65 return true;
66 } 66 }
67 } 67 }
68 return true; 68 return true;
69 } 69 }
70} 70}
71 71
72//#include "quickexec_p.h" 72//#include "quickexec_p.h"
73 73
74class Emitter : public QObject { 74class Emitter : public QObject {
75 Q_OBJECT 75 Q_OBJECT
76public: 76public:
77 Emitter( QWidget* receiver, const QString& document ) 77 Emitter( QWidget* receiver, const QString& document )
78 { 78 {
79 connect(this, SIGNAL(setDocument(const QString&)), 79 connect(this, SIGNAL(setDocument(const QString&)),
80 receiver, SLOT(setDocument(const QString&))); 80 receiver, SLOT(setDocument(const QString&)));
81 emit setDocument(document); 81 emit setDocument(document);
82 disconnect(this, SIGNAL(setDocument(const QString&)), 82 disconnect(this, SIGNAL(setDocument(const QString&)),
83 receiver, SLOT(setDocument(const QString&))); 83 receiver, SLOT(setDocument(const QString&)));
84 } 84 }
85 85
86signals: 86signals:
87 void setDocument(const QString&); 87 void setDocument(const QString&);
88}; 88};
89 89
90 90
91class StartingAppList : public QObject { 91class StartingAppList : public QObject {
92 Q_OBJECT 92 Q_OBJECT
93public: 93public:
94 static void add( const QString& name ); 94 static void add( const QString& name );
95 static bool isStarting( const QString name ); 95 static bool isStarting( const QString name );
96private slots: 96private slots:
97 void handleNewChannel( const QString &); 97 void handleNewChannel( const QString &);
98private: 98private:
99 StartingAppList( QObject *parent=0, const char* name=0 ) ; 99 StartingAppList( QObject *parent=0, const char* name=0 ) ;
100 100
101 QDict<QTime> dict; 101 QDict<QTime> dict;
102 static StartingAppList *appl; 102 static StartingAppList *appl;
103}; 103};
104 104
105StartingAppList* StartingAppList::appl = 0; 105StartingAppList* StartingAppList::appl = 0;
106 106
107StartingAppList::StartingAppList( QObject *parent, const char* name ) 107StartingAppList::StartingAppList( QObject *parent, const char* name )
108 :QObject( parent, name ) 108 :QObject( parent, name )
109{ 109{
110#if QT_VERSION >= 232 && defined(QWS) 110#if QT_VERSION >= 232 && defined(QWS)
111 connect( qwsServer, SIGNAL( newChannel(const QString&)), 111 connect( qwsServer, SIGNAL( newChannel(const QString&)),
112 this, SLOT( handleNewChannel(const QString&)) ); 112 this, SLOT( handleNewChannel(const QString&)) );
113#endif 113#endif
114 dict.setAutoDelete( TRUE ); 114 dict.setAutoDelete( TRUE );
115} 115}
116 116
117void StartingAppList::add( const QString& name ) 117void StartingAppList::add( const QString& name )
118{ 118{
119#if QT_VERSION >= 232 && !defined(QT_NO_COP) 119#if QT_VERSION >= 232 && !defined(QT_NO_COP)
120 if ( !appl ) 120 if ( !appl )
121 appl = new StartingAppList; 121 appl = new StartingAppList;
122 QTime *t = new QTime; 122 QTime *t = new QTime;
123 t->start(); 123 t->start();
124 appl->dict.insert( "QPE/Application/" + name, t ); 124 appl->dict.insert( "QPE/Application/" + name, t );
125#endif 125#endif
126} 126}
127 127
128bool StartingAppList::isStarting( const QString name ) 128bool StartingAppList::isStarting( const QString name )
129{ 129{
130#if QT_VERSION >= 232 && !defined(QT_NO_COP) 130#if QT_VERSION >= 232 && !defined(QT_NO_COP)
131 if ( appl ) { 131 if ( appl ) {
132 QTime *t = appl->dict.find( "QPE/Application/" + name ); 132 QTime *t = appl->dict.find( "QPE/Application/" + name );
133 if ( !t ) 133 if ( !t )
134 return FALSE; 134 return FALSE;
135 if ( t->elapsed() > 10000 ) { 135 if ( t->elapsed() > 10000 ) {
136 // timeout in case of crash or something 136 // timeout in case of crash or something
137 appl->dict.remove( "QPE/Application/" + name ); 137 appl->dict.remove( "QPE/Application/" + name );
138 return FALSE; 138 return FALSE;
139 } 139 }
140 return TRUE; 140 return TRUE;
141 } 141 }
142#endif 142#endif
143 return FALSE; 143 return FALSE;
144} 144}
145 145
146void StartingAppList::handleNewChannel( const QString & name ) 146void StartingAppList::handleNewChannel( const QString & name )
147{ 147{
148#if QT_VERSION >= 232 && !defined(QT_NO_COP) 148#if QT_VERSION >= 232 && !defined(QT_NO_COP)
149 dict.remove( name ); 149 dict.remove( name );
150#endif 150#endif
151} 151}
152 152
153static bool docDirCreated = FALSE; 153static bool docDirCreated = FALSE;
154static QDawg* fixed_dawg = 0; 154static QDawg* fixed_dawg = 0;
155static QDict<QDawg> *named_dawg = 0; 155static QDict<QDawg> *named_dawg = 0;
156 156
157static QString qpeDir() 157static QString qpeDir()
158{ 158{
159 QString dir = getenv("OPIEDIR"); 159 QString dir = getenv("OPIEDIR");
160 if ( dir.isEmpty() ) dir = ".."; 160 if ( dir.isEmpty() ) dir = "..";
161 return dir; 161 return dir;
162} 162}
163 163
164static QString dictDir() 164static QString dictDir()
165{ 165{
166 return qpeDir() + "/etc/dict"; 166 return qpeDir() + "/etc/dict";
167} 167}
168 168
169/*! 169/*!
170 \class Global global.h 170 \class Global global.h
171 \brief The Global class provides application-wide global functions. 171 \brief The Global class provides application-wide global functions.
172 172
173 The Global functions are grouped as follows: 173 The Global functions are grouped as follows:
174 \tableofcontents 174 \tableofcontents
175 175
176 \section1 User Interface 176 \section1 User Interface
177 177
178 The statusMessage() function provides short-duration messages to the 178 The statusMessage() function provides short-duration messages to the
179 user. The showInputMethod() function shows the current input method, 179 user. The showInputMethod() function shows the current input method,
180 and hideInputMethod() hides the input method. 180 and hideInputMethod() hides the input method.
181 181
182 \section1 Document related 182 \section1 Document related
183 183
184 The findDocuments() function creates a set of \link doclnk.html 184 The findDocuments() function creates a set of \link doclnk.html
185 DocLnk\endlink objects in a particular folder. 185 DocLnk\endlink objects in a particular folder.
186 186
187 \section1 Filesystem related 187 \section1 Filesystem related
188 188
189 Global provides an applicationFileName() function that returns the 189 Global provides an applicationFileName() function that returns the
190 full path of an application-specific file. 190 full path of an application-specific file.
191 191
192 The execute() function runs an application. 192 The execute() function runs an application.
193 193
194 \section1 Word list related 194 \section1 Word list related
195 195
196 A list of words relevant to the current locale is maintained by the 196 A list of words relevant to the current locale is maintained by the
197 system. The list is held in a \link qdawg.html DAWG\endlink 197 system. The list is held in a \link qdawg.html DAWG\endlink
198 (implemented by the QDawg class). This list is used, for example, by 198 (implemented by the QDawg class). This list is used, for example, by
199 the pickboard input method. 199 the pickboard input method.
200 200
201 The global QDawg is returned by fixedDawg(); this cannot be updated. 201 The global QDawg is returned by fixedDawg(); this cannot be updated.
202 An updatable copy of the global QDawg is returned by addedDawg(). 202 An updatable copy of the global QDawg is returned by addedDawg().
203 Applications may have their own word lists stored in \l{QDawg}s 203 Applications may have their own word lists stored in \l{QDawg}s
204 which are returned by dawg(). Use addWords() to add words to the 204 which are returned by dawg(). Use addWords() to add words to the
205 updateable copy of the global QDawg or to named application 205 updateable copy of the global QDawg or to named application
206 \l{QDawg}s. 206 \l{QDawg}s.
207 207
208 \section1 Quoting 208 \section1 Quoting
209 209
210 The shellQuote() function quotes a string suitable for passing to a 210 The shellQuote() function quotes a string suitable for passing to a
211 shell. The stringQuote() function backslash escapes '\' and '"' 211 shell. The stringQuote() function backslash escapes '\' and '"'
212 characters. 212 characters.
213 213
214 \section1 Hardware 214 \section1 Hardware
215 215
216 The writeHWClock() function sets the hardware clock to the system 216 The implementation of the writeHWClock() function depends on the AlarmServer
217 clock's date and time. 217 implementation. If the AlarmServer is using atd the clock will be synced to
218 hardware. If opie-alarm is used the hardware clock will be synced before
219 suspending the device. opie-alarm is used by iPAQ and Zaurii implementation
218 220
219 \ingroup qtopiaemb 221 \ingroup qtopiaemb
220*/ 222*/
221 223
222/*! 224/*!
223 \internal 225 \internal
224*/ 226*/
225Global::Global() 227Global::Global()
226{ 228{
227} 229}
228 230
229/*! 231/*!
230 Returns the unchangeable QDawg that contains general 232 Returns the unchangeable QDawg that contains general
231 words for the current locale. 233 words for the current locale.
232 234
233 \sa addedDawg() 235 \sa addedDawg()
234*/ 236*/
235const QDawg& Global::fixedDawg() 237const QDawg& Global::fixedDawg()
236{ 238{
237 if ( !fixed_dawg ) { 239 if ( !fixed_dawg ) {
238 if ( !docDirCreated ) 240 if ( !docDirCreated )
239 createDocDir(); 241 createDocDir();
240 242
241 fixed_dawg = new QDawg; 243 fixed_dawg = new QDawg;
242 QString dawgfilename = dictDir() + "/dawg"; 244 QString dawgfilename = dictDir() + "/dawg";
243 QString words_lang; 245 QString words_lang;
244 QStringList langs = Global::languageList(); 246 QStringList langs = Global::languageList();
245 for (QStringList::ConstIterator it = langs.begin(); it!=langs.end(); ++it) { 247 for (QStringList::ConstIterator it = langs.begin(); it!=langs.end(); ++it) {
246 QString lang = *it; 248 QString lang = *it;
247 words_lang = dictDir() + "/words." + lang; 249 words_lang = dictDir() + "/words." + lang;
248 QString dawgfilename_lang = dawgfilename + "." + lang; 250 QString dawgfilename_lang = dawgfilename + "." + lang;
249 if ( QFile::exists(dawgfilename_lang) || 251 if ( QFile::exists(dawgfilename_lang) ||
250 QFile::exists(words_lang) ) { 252 QFile::exists(words_lang) ) {
251 dawgfilename = dawgfilename_lang; 253 dawgfilename = dawgfilename_lang;
252 break; 254 break;
253 } 255 }
254 } 256 }
255 QFile dawgfile(dawgfilename); 257 QFile dawgfile(dawgfilename);
256 258
257 if ( !dawgfile.exists() ) { 259 if ( !dawgfile.exists() ) {
258 QString fn = dictDir() + "/words"; 260 QString fn = dictDir() + "/words";
259 if ( QFile::exists(words_lang) ) 261 if ( QFile::exists(words_lang) )
260 fn = words_lang; 262 fn = words_lang;
261 QFile in(fn); 263 QFile in(fn);
262 if ( in.open(IO_ReadOnly) ) { 264 if ( in.open(IO_ReadOnly) ) {
263 fixed_dawg->createFromWords(&in); 265 fixed_dawg->createFromWords(&in);
264 dawgfile.open(IO_WriteOnly); 266 dawgfile.open(IO_WriteOnly);
265 fixed_dawg->write(&dawgfile); 267 fixed_dawg->write(&dawgfile);
266 dawgfile.close(); 268 dawgfile.close();
267 } 269 }
268 } else { 270 } else {
269 fixed_dawg->readFile(dawgfilename); 271 fixed_dawg->readFile(dawgfilename);
270 } 272 }
271 } 273 }
272 274
273 return *fixed_dawg; 275 return *fixed_dawg;
274} 276}
275 277
276/*! 278/*!
277 Returns the changeable QDawg that contains general 279 Returns the changeable QDawg that contains general
278 words for the current locale. 280 words for the current locale.
279 281
280 \sa fixedDawg() 282 \sa fixedDawg()
281*/ 283*/
282const QDawg& Global::addedDawg() 284const QDawg& Global::addedDawg()
283{ 285{
284 return dawg("local"); 286 return dawg("local");
285} 287}
286 288
287/*! 289/*!
288 Returns the QDawg with the given \a name. 290 Returns the QDawg with the given \a name.
289 This is an application-specific word list. 291 This is an application-specific word list.
290 292
291 \a name should not contain "/". 293 \a name should not contain "/".
292*/ 294*/
293const QDawg& Global::dawg(const QString& name) 295const QDawg& Global::dawg(const QString& name)
294{ 296{
295 createDocDir(); 297 createDocDir();
296 if ( !named_dawg ) 298 if ( !named_dawg )
297 named_dawg = new QDict<QDawg>; 299 named_dawg = new QDict<QDawg>;
298 QDawg* r = named_dawg->find(name); 300 QDawg* r = named_dawg->find(name);
299 if ( !r ) { 301 if ( !r ) {
300 r = new QDawg; 302 r = new QDawg;
301 named_dawg->insert(name,r); 303 named_dawg->insert(name,r);
302 QString dawgfilename = applicationFileName("Dictionary", name ) + ".dawg"; 304 QString dawgfilename = applicationFileName("Dictionary", name ) + ".dawg";
303 QFile dawgfile(dawgfilename); 305 QFile dawgfile(dawgfilename);
304 if ( dawgfile.open(IO_ReadOnly) ) 306 if ( dawgfile.open(IO_ReadOnly) )
305 r->readFile(dawgfilename); 307 r->readFile(dawgfilename);
306 } 308 }
307 return *r; 309 return *r;
308} 310}
309 311
310/*! 312/*!
311 \overload 313 \overload
312 Adds \a wordlist to the addedDawg(). 314 Adds \a wordlist to the addedDawg().
313 315
314 Note that the addition of words persists between program executions 316 Note that the addition of words persists between program executions
315 (they are saved in the dictionary files), so you should confirm the 317 (they are saved in the dictionary files), so you should confirm the
316 words with the user before adding them. 318 words with the user before adding them.
317*/ 319*/
318void Global::addWords(const QStringList& wordlist) 320void Global::addWords(const QStringList& wordlist)
319{ 321{
320 addWords("local",wordlist); 322 addWords("local",wordlist);
321} 323}
322 324
323/*! 325/*!
324 \overload 326 \overload
325 Adds \a wordlist to the addedDawg(). 327 Adds \a wordlist to the addedDawg().
326 328
327 Note that the addition of words persists between program executions 329 Note that the addition of words persists between program executions
328 (they are saved in the dictionary files), so you should confirm the 330 (they are saved in the dictionary files), so you should confirm the
329 words with the user before adding them. 331 words with the user before adding them.
330*/ 332*/
331void Global::addWords(const QString& dictname, const QStringList& wordlist) 333void Global::addWords(const QString& dictname, const QStringList& wordlist)
332{ 334{
333 QDawg& d = (QDawg&)dawg(dictname); 335 QDawg& d = (QDawg&)dawg(dictname);
334 QStringList all = d.allWords() + wordlist; 336 QStringList all = d.allWords() + wordlist;
335 d.createFromWords(all); 337 d.createFromWords(all);
336 338
337 QString dawgfilename = applicationFileName("Dictionary", dictname) + ".dawg"; 339 QString dawgfilename = applicationFileName("Dictionary", dictname) + ".dawg";
338 QFile dawgfile(dawgfilename); 340 QFile dawgfile(dawgfilename);
339 if ( dawgfile.open(IO_WriteOnly) ) { 341 if ( dawgfile.open(IO_WriteOnly) ) {
340 d.write(&dawgfile); 342 d.write(&dawgfile);
341 dawgfile.close(); 343 dawgfile.close();
342 } 344 }
343 345
344 // #### Re-read the dawg here if we use mmap(). 346 // #### Re-read the dawg here if we use mmap().
345 347
346 // #### Signal other processes to re-read. 348 // #### Signal other processes to re-read.
347} 349}
348 350
349 351
350/*! 352/*!
351 Returns the full path for the application called \a appname, with the 353 Returns the full path for the application called \a appname, with the
352 given \a filename. Returns QString::null if there was a problem creating 354 given \a filename. Returns QString::null if there was a problem creating
353 the directory tree for \a appname. 355 the directory tree for \a appname.
354 If \a filename contains "/", it is the caller's responsibility to 356 If \a filename contains "/", it is the caller's responsibility to
355 ensure that those directories exist. 357 ensure that those directories exist.
356*/ 358*/
357QString Global::applicationFileName(const QString& appname, const QString& filename) 359QString Global::applicationFileName(const QString& appname, const QString& filename)
358{ 360{
359 QDir d; 361 QDir d;
360 QString r = getenv("HOME"); 362 QString r = getenv("HOME");
361 r += "/Applications/"; 363 r += "/Applications/";
362 if ( !QFile::exists( r ) ) 364 if ( !QFile::exists( r ) )
363 if ( d.mkdir(r) == false ) 365 if ( d.mkdir(r) == false )
364 return QString::null; 366 return QString::null;
365 r += appname; 367 r += appname;
366 if ( !QFile::exists( r ) ) 368 if ( !QFile::exists( r ) )
367 if ( d.mkdir(r) == false ) 369 if ( d.mkdir(r) == false )
368 return QString::null; 370 return QString::null;
369 r += "/"; r += filename; 371 r += "/"; r += filename;
370 return r; 372 return r;
371} 373}
372 374
373/*! 375/*!
374 \internal 376 \internal
375*/ 377*/
376void Global::createDocDir() 378void Global::createDocDir()
377{ 379{
378 if ( !docDirCreated ) { 380 if ( !docDirCreated ) {
379 docDirCreated = TRUE; 381 docDirCreated = TRUE;
380 mkdir( QPEApplication::documentDir().latin1(), 0755 ); 382 mkdir( QPEApplication::documentDir().latin1(), 0755 );
381 } 383 }
382} 384}
383 385
384 386
385/*! 387/*!
386 Displays a status \a message to the user. This usually appears 388 Displays a status \a message to the user. This usually appears
387 in the taskbar for a short amount of time, then disappears. 389 in the taskbar for a short amount of time, then disappears.
388*/ 390*/
389void Global::statusMessage(const QString& message) 391void Global::statusMessage(const QString& message)
390{ 392{
391#if !defined(QT_NO_COP) 393#if !defined(QT_NO_COP)
392 QCopEnvelope e( "QPE/TaskBar", "message(QString)" ); 394 QCopEnvelope e( "QPE/TaskBar", "message(QString)" );
393 e << message; 395 e << message;
394#endif 396#endif
395} 397}
396 398
397/*! 399/*!
398 \internal 400 \internal
399*/ 401*/
400void Global::applyStyle() 402void Global::applyStyle()
401{ 403{
402#if !defined(QT_NO_COP) 404#if !defined(QT_NO_COP)
403 QCopChannel::send( "QPE/System", "applyStyle()" ); 405 QCopChannel::send( "QPE/System", "applyStyle()" );
404#else 406#else
405 ((QPEApplication *)qApp)->applyStyle(); // apply without needing QCop for floppy version 407 ((QPEApplication *)qApp)->applyStyle(); // apply without needing QCop for floppy version
406#endif 408#endif
407} 409}
408 410
409/*! 411/*!
410 \internal 412 \internal
411*/ 413*/
412QWidget *Global::shutdown( bool ) 414QWidget *Global::shutdown( bool )
413{ 415{
414#if !defined(QT_NO_COP) 416#if !defined(QT_NO_COP)
415 QCopChannel::send( "QPE/System", "shutdown()" ); 417 QCopChannel::send( "QPE/System", "shutdown()" );
416#endif 418#endif
417 return 0; 419 return 0;
418} 420}
419 421
420/*! 422/*!
421 \internal 423 \internal
422*/ 424*/
423QWidget *Global::restart( bool ) 425QWidget *Global::restart( bool )
424{ 426{
425#if !defined(QT_NO_COP) 427#if !defined(QT_NO_COP)
426 QCopChannel::send( "QPE/System", "restart()" ); 428 QCopChannel::send( "QPE/System", "restart()" );
427#endif 429#endif
428 return 0; 430 return 0;
429} 431}
430 432
431/*! 433/*!
432 Explicitly show the current input method. 434 Explicitly show the current input method.
433 435
434 Input methods are indicated in the taskbar by a small icon. If the 436 Input methods are indicated in the taskbar by a small icon. If the
435 input method is activated (shown) then it takes up some proportion 437 input method is activated (shown) then it takes up some proportion
436 of the bottom of the screen, to allow the user to interact (input 438 of the bottom of the screen, to allow the user to interact (input
437 characters) with it. 439 characters) with it.
438 440
439 \sa hideInputMethod() 441 \sa hideInputMethod()
440*/ 442*/
441void Global::showInputMethod() 443void Global::showInputMethod()
442{ 444{
443#if !defined(QT_NO_COP) 445#if !defined(QT_NO_COP)
444 QCopChannel::send( "QPE/TaskBar", "showInputMethod()" ); 446 QCopChannel::send( "QPE/TaskBar", "showInputMethod()" );
445#endif 447#endif
446} 448}
447 449
448/*! 450/*!
449 Explicitly hide the current input method. 451 Explicitly hide the current input method.
450 452
451 The current input method is still indicated in the taskbar, but no 453 The current input method is still indicated in the taskbar, but no
452 longer takes up screen space, and can no longer be interacted with. 454 longer takes up screen space, and can no longer be interacted with.
453 455
454 \sa showInputMethod() 456 \sa showInputMethod()
455*/ 457*/
456void Global::hideInputMethod() 458void Global::hideInputMethod()
457{ 459{
458#if !defined(QT_NO_COP) 460#if !defined(QT_NO_COP)
459 QCopChannel::send( "QPE/TaskBar", "hideInputMethod()" ); 461 QCopChannel::send( "QPE/TaskBar", "hideInputMethod()" );
460#endif 462#endif
461} 463}
462 464
463 465
464/*! 466/*!
465 \internal 467 \internal
466*/ 468*/
467bool Global::isBuiltinCommand( const QString &name ) 469bool Global::isBuiltinCommand( const QString &name )
468{ 470{
469 if(!builtin) 471 if(!builtin)
470 return FALSE; // yes, it can happen 472 return FALSE; // yes, it can happen
471 for (int i = 0; builtin[i].file; i++) { 473 for (int i = 0; builtin[i].file; i++) {
472 if ( builtin[i].file == name ) { 474 if ( builtin[i].file == name ) {
473 return TRUE; 475 return TRUE;
474 } 476 }
475 } 477 }
476 return FALSE; 478 return FALSE;
477} 479}
478 480
479Global::Command* Global::builtin=0; 481Global::Command* Global::builtin=0;
480QGuardedPtr<QWidget> *Global::running=0; 482QGuardedPtr<QWidget> *Global::running=0;
481 483
482/*! 484/*!
483 \class Global::Command 485 \class Global::Command
484 \brief The Global::Command class is internal. 486 \brief The Global::Command class is internal.
485 \internal 487 \internal
486*/ 488*/
487 489
488/*! 490/*!
489 \internal 491 \internal
490*/ 492*/
491void Global::setBuiltinCommands( Command* list ) 493void Global::setBuiltinCommands( Command* list )
492{ 494{
493 if ( running ) 495 if ( running )
494 delete [] running; 496 delete [] running;
495 497
496 builtin = list; 498 builtin = list;
497 int count = 0; 499 int count = 0;
498 if (!builtin) 500 if (!builtin)
499 return; 501 return;
500 while ( builtin[count].file ) 502 while ( builtin[count].file )
501 count++; 503 count++;
502 504
503 running = new QGuardedPtr<QWidget> [ count ]; 505 running = new QGuardedPtr<QWidget> [ count ];
504} 506}
505 507
506/*! 508/*!
507 \internal 509 \internal
508*/ 510*/
509void Global::setDocument( QWidget* receiver, const QString& document ) 511void Global::setDocument( QWidget* receiver, const QString& document )
510{ 512{
511 Emitter emitter(receiver,document); 513 Emitter emitter(receiver,document);
512} 514}
513 515
514/*! 516/*!
515 \internal 517 \internal
516*/ 518*/
517bool Global::terminateBuiltin( const QString& n ) 519bool Global::terminateBuiltin( const QString& n )
518{ 520{
519 if (!builtin) 521 if (!builtin)
520 return FALSE; 522 return FALSE;
521 for (int i = 0; builtin[i].file; i++) { 523 for (int i = 0; builtin[i].file; i++) {
522 if ( builtin[i].file == n ) { 524 if ( builtin[i].file == n ) {
523 delete running[i]; 525 delete running[i];
524 return TRUE; 526 return TRUE;
525 } 527 }
526 } 528 }
527 return FALSE; 529 return FALSE;
528} 530}
529 531
530/*! 532/*!
531 \internal 533 \internal
532*/ 534*/
533void Global::terminate( const AppLnk* app ) 535void Global::terminate( const AppLnk* app )
534{ 536{
535 //if ( terminateBuiltin(app->exec()) ) return; // maybe? haven't tried this 537 //if ( terminateBuiltin(app->exec()) ) return; // maybe? haven't tried this
536 538
537#ifndef QT_NO_COP 539#ifndef QT_NO_COP
538 QCString channel = "QPE/Application/" + app->exec().utf8(); 540 QCString channel = "QPE/Application/" + app->exec().utf8();
539 if ( QCopChannel::isRegistered(channel) ) { 541 if ( QCopChannel::isRegistered(channel) ) {
540 QCopEnvelope e(channel, "quit()"); 542 QCopEnvelope e(channel, "quit()");
541 } 543 }
542#endif 544#endif
543} 545}
544 546
545/*! 547/*!
546 Low-level function to run command \a c. 548 Low-level function to run command \a c.
547 549
548 \warning Do not use this function. Use execute instead. 550 \warning Do not use this function. Use execute instead.
549 551
550 \sa execute() 552 \sa execute()
551*/ 553*/
552void Global::invoke(const QString &c) 554void Global::invoke(const QString &c)
553{ 555{
554 // Convert the command line in to a list of arguments 556 // Convert the command line in to a list of arguments
555 QStringList list = QStringList::split(QRegExp(" *"),c); 557 QStringList list = QStringList::split(QRegExp(" *"),c);
556 558
557#if !defined(QT_NO_COP) 559#if !defined(QT_NO_COP)
558 QString ap=list[0]; 560 QString ap=list[0];
559 // see if the application is already running 561 // see if the application is already running
560 // XXX should lock file /tmp/qcop-msg-ap 562 // XXX should lock file /tmp/qcop-msg-ap
561 if ( QCopChannel::isRegistered( ("QPE/Application/" + ap).latin1() ) ) { 563 if ( QCopChannel::isRegistered( ("QPE/Application/" + ap).latin1() ) ) {
562 // If the channel is already register, the app is already running, so show it. 564 // If the channel is already register, the app is already running, so show it.
563 { QCopEnvelope env( ("QPE/Application/" + ap).latin1(), "raise()" ); } 565 { QCopEnvelope env( ("QPE/Application/" + ap).latin1(), "raise()" ); }
564 566
565 //QCopEnvelope e("QPE/System", "notBusy(QString)" ); 567 //QCopEnvelope e("QPE/System", "notBusy(QString)" );
566 //e << ap; 568 //e << ap;
567 return; 569 return;
568 } 570 }
569 // XXX should unlock file /tmp/qcop-msg-ap 571 // XXX should unlock file /tmp/qcop-msg-ap
570 //see if it is being started 572 //see if it is being started
571 if ( StartingAppList::isStarting( ap ) ) { 573 if ( StartingAppList::isStarting( ap ) ) {
572 // FIXME take it out for now, since it leads to a much to short showing of wait if 574 // FIXME take it out for now, since it leads to a much to short showing of wait if
573 // some entry is clicked. 575 // some entry is clicked.
574 // Real cause is that ::execute is called twice for document tab. But it would need some larger changes 576 // Real cause is that ::execute is called twice for document tab. But it would need some larger changes
575 // to fix that, and with future syncs with qtopia 1.6 it will change anyway big time since somebody there 577 // to fix that, and with future syncs with qtopia 1.6 it will change anyway big time since somebody there
576 // had the idea that an apploader belongs to the launcher ... 578 // had the idea that an apploader belongs to the launcher ...
577 //QCopEnvelope e("QPE/System", "notBusy(QString)" ); 579 //QCopEnvelope e("QPE/System", "notBusy(QString)" );
578 //e << ap; 580 //e << ap;
579 return; 581 return;
580 } 582 }
581 583
582#endif 584#endif
583 585
584#ifdef QT_NO_QWS_MULTIPROCESS 586#ifdef QT_NO_QWS_MULTIPROCESS
585 QMessageBox::warning( 0, "Error", "Could not find the application " + c, "Ok", 0, 0, 0, 1 ); 587 QMessageBox::warning( 0, "Error", "Could not find the application " + c, "Ok", 0, 0, 0, 1 );
586#else 588#else
587 589
588 QStrList slist; 590 QStrList slist;
589 unsigned int j; 591 unsigned int j;
590 for ( j = 0; j < list.count(); j++ ) 592 for ( j = 0; j < list.count(); j++ )
591 slist.append( list[j].utf8() ); 593 slist.append( list[j].utf8() );
592 594
593 const char **args = new (const char *)[slist.count() + 1]; 595 const char **args = new (const char *)[slist.count() + 1];
594 for ( j = 0; j < slist.count(); j++ ) 596 for ( j = 0; j < slist.count(); j++ )
595 args[j] = slist.at(j); 597 args[j] = slist.at(j);
596 args[j] = NULL; 598 args[j] = NULL;
597 599
598#if !defined(QT_NO_COP) 600#if !defined(QT_NO_COP)
599 // an attempt to show a wait... 601 // an attempt to show a wait...
600 // more logic should be used, but this will be fine for the moment... 602 // more logic should be used, but this will be fine for the moment...
601 QCopEnvelope ( "QPE/System", "busy()" ); 603 QCopEnvelope ( "QPE/System", "busy()" );
602#endif 604#endif
603 605
604#ifdef HAVE_QUICKEXEC 606#ifdef HAVE_QUICKEXEC
605 QString libexe = qpeDir()+"/binlib/lib"+args[0] + ".so"; 607 QString libexe = qpeDir()+"/binlib/lib"+args[0] + ".so";
606 qDebug("libfile = %s", libexe.latin1() ); 608 qDebug("libfile = %s", libexe.latin1() );
607 if ( QFile::exists( libexe ) ) { 609 if ( QFile::exists( libexe ) ) {
608 qDebug("calling quickexec %s", libexe.latin1() ); 610 qDebug("calling quickexec %s", libexe.latin1() );
609 quickexecv( libexe.utf8().data(), (const char **)args ); 611 quickexecv( libexe.utf8().data(), (const char **)args );
610 } else 612 } else
611#endif 613#endif
612 { 614 {
613 bool success = false; 615 bool success = false;
614 int pfd [2]; 616 int pfd [2];
615 if ( ::pipe ( pfd ) < 0 ) 617 if ( ::pipe ( pfd ) < 0 )
616 pfd [0] = pfd [1] = -1; 618 pfd [0] = pfd [1] = -1;
617 619
618 pid_t pid = ::fork ( ); 620 pid_t pid = ::fork ( );
619 621
620 if ( pid == 0 ) { // child 622 if ( pid == 0 ) { // child
621 for ( int fd = 3; fd < 100; fd++ ) { 623 for ( int fd = 3; fd < 100; fd++ ) {
622 if ( fd != pfd [1] ) 624 if ( fd != pfd [1] )
623 ::close ( fd ); 625 ::close ( fd );
624 } 626 }
625 ::setpgid ( ::getpid ( ), ::getppid ( )); 627 ::setpgid ( ::getpid ( ), ::getppid ( ));
626 628
627 // Closing of fd[1] indicates that the execvp succeeded! 629 // Closing of fd[1] indicates that the execvp succeeded!
628 if ( pfd [1] >= 0 ) 630 if ( pfd [1] >= 0 )
629 ::fcntl ( pfd [1], F_SETFD, FD_CLOEXEC ); 631 ::fcntl ( pfd [1], F_SETFD, FD_CLOEXEC );
630 632
631 // Try bindir first, so that foo/bar works too 633 // Try bindir first, so that foo/bar works too
632 ::execv ( qpeDir ( ) + "/bin/" + args [0], (char * const *) args ); 634 ::execv ( qpeDir ( ) + "/bin/" + args [0], (char * const *) args );
633 ::execvp ( args [0], (char * const *) args ); 635 ::execvp ( args [0], (char * const *) args );
634 636
635 char resultByte = 1; 637 char resultByte = 1;
636 if ( pfd [1] >= 0 ) 638 if ( pfd [1] >= 0 )
637 ::write ( pfd [1], &resultByte, 1 ); 639 ::write ( pfd [1], &resultByte, 1 );
638 ::_exit ( -1 ); 640 ::_exit ( -1 );
639 } 641 }
640 else if ( pid > 0 ) { 642 else if ( pid > 0 ) {
641 success = true; 643 success = true;
642 644
643 if ( pfd [1] >= 0 ) 645 if ( pfd [1] >= 0 )
644 ::close ( pfd [1] ); 646 ::close ( pfd [1] );
645 if ( pfd [0] >= 0 ) { 647 if ( pfd [0] >= 0 ) {
646 while ( true ) { 648 while ( true ) {
647 char resultByte; 649 char resultByte;
648 int n = ::read ( pfd [0], &resultByte, 1 ); 650 int n = ::read ( pfd [0], &resultByte, 1 );
649 if ( n == 1 ) { 651 if ( n == 1 ) {
650 success = false; 652 success = false;
651 break; 653 break;
652 } 654 }
653 if (( n == -1 ) && (( errno == ECHILD ) || ( errno == EINTR ))) 655 if (( n == -1 ) && (( errno == ECHILD ) || ( errno == EINTR )))
654 continue; 656 continue;
655 657
656 break; // success 658 break; // success
657 } 659 }
658 ::close ( pfd [0] ); 660 ::close ( pfd [0] );
659 } 661 }
660 } 662 }
661 if ( success ) 663 if ( success )
662 StartingAppList::add( list[0] ); 664 StartingAppList::add( list[0] );
663 else 665 else
664 QMessageBox::warning( 0, "Error", "Could not start the application " + c, "Ok", 0, 0, 0, 1 ); 666 QMessageBox::warning( 0, "Error", "Could not start the application " + c, "Ok", 0, 0, 0, 1 );
665 } 667 }
666#endif //QT_NO_QWS_MULTIPROCESS 668#endif //QT_NO_QWS_MULTIPROCESS
667} 669}
668 670
669 671
670/*! 672/*!
671 Executes the application identfied by \a c, passing \a 673 Executes the application identfied by \a c, passing \a
672 document if it isn't null. 674 document if it isn't null.
673 675
674 Note that a better approach might be to send a QCop message to the 676 Note that a better approach might be to send a QCop message to the
675 application's QPE/Application/\e{appname} channel. 677 application's QPE/Application/\e{appname} channel.
676*/ 678*/
677void Global::execute( const QString &c, const QString& document ) 679void Global::execute( const QString &c, const QString& document )
678{ 680{
679 // ask the server to do the work 681 // ask the server to do the work
680#if !defined(QT_NO_COP) 682#if !defined(QT_NO_COP)
681 if ( document.isNull() ) { 683 if ( document.isNull() ) {
682 QCopEnvelope e( "QPE/System", "execute(QString)" ); 684 QCopEnvelope e( "QPE/System", "execute(QString)" );
683 e << c; 685 e << c;
684 } else { 686 } else {
685 QCopEnvelope e( "QPE/System", "execute(QString,QString)" ); 687 QCopEnvelope e( "QPE/System", "execute(QString,QString)" );
686 e << c << document; 688 e << c << document;
687 } 689 }
688#endif 690#endif
689 return; 691 return;
690} 692}
691 693
692/*! 694/*!
693 Returns the string \a s with the characters '\', '"', and '$' quoted 695 Returns the string \a s with the characters '\', '"', and '$' quoted
694 by a preceeding '\'. 696 by a preceeding '\'.
695 697
696 \sa stringQuote() 698 \sa stringQuote()
697*/ 699*/
698QString Global::shellQuote(const QString& s) 700QString Global::shellQuote(const QString& s)
699{ 701{
700 QString r="\""; 702 QString r="\"";
701 for (int i=0; i<(int)s.length(); i++) { 703 for (int i=0; i<(int)s.length(); i++) {
702 char c = s[i].latin1(); 704 char c = s[i].latin1();
703 switch (c) { 705 switch (c) {
704 case '\\': case '"': case '$': 706 case '\\': case '"': case '$':
705 r+="\\"; 707 r+="\\";
706 } 708 }
707 r += s[i]; 709 r += s[i];
708 } 710 }
709 r += "\""; 711 r += "\"";
710 return r; 712 return r;
711} 713}
712 714
713/*! 715/*!
714 Returns the string \a s with the characters '\' and '"' quoted by a 716 Returns the string \a s with the characters '\' and '"' quoted by a
715 preceeding '\'. 717 preceeding '\'.
716 718
717 \sa shellQuote() 719 \sa shellQuote()
718*/ 720*/
719QString Global::stringQuote(const QString& s) 721QString Global::stringQuote(const QString& s)
720{ 722{
721 QString r="\""; 723 QString r="\"";
722 for (int i=0; i<(int)s.length(); i++) { 724 for (int i=0; i<(int)s.length(); i++) {
723 char c = s[i].latin1(); 725 char c = s[i].latin1();
724 switch (c) { 726 switch (c) {
725 case '\\': case '"': 727 case '\\': case '"':
726 r+="\\"; 728 r+="\\";
727 } 729 }
728 r += s[i]; 730 r += s[i];
729 } 731 }