/* AbiSource Program Utilities * Copyright (C) 1998 AbiSource, Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. */ #include "ut_qnxTimer.h" #include "ut_assert.h" #include "ut_debugmsg.h" #include #include /*****************************************************************/ extern PtWidget_t *gTimerWidget; UT_Timer* UT_Timer::static_constructor(UT_TimerCallback pCallback, void* pData, GR_Graphics * /*pG*/) { UT_ASSERT(pCallback); UT_QNXTimer * p = new UT_QNXTimer(pCallback, pData); return p; } UT_QNXTimer::UT_QNXTimer(UT_TimerCallback pCallback, void* pData) { setCallback(pCallback); setInstanceData(pData); m_bStarted = false; m_iMilliseconds = 0; } UT_QNXTimer::~UT_QNXTimer() { stop(); } /*****************************************************************/ static int _Timer_Proc(PtWidget_t *w, void *p, PtCallbackInfo_t *info) { UT_QNXTimer *pTimer; /* We need to look up the timer because the widget might have been deleted. Note that this is not entirely foolproof since a new timer might have been created which re-used the widget's address and so we could pre-maturely fire someone elses timer. It would be better if we could do the lookup based on a large increasing number, but alas that would mean that we couldn't store our widget pointer in the Identifier field (which might not be entirely a bad thing). */ pTimer = (UT_QNXTimer *)UT_Timer::findTimer((UT_uint32)w); if (!pTimer) { printf("*** Saved ourselves a timer segfault *** \n"); } else { pTimer->fire(); } return Pt_CONTINUE; } void UT_QNXTimer::resetIfStarted(void) { if (m_bStarted) set(m_iMilliseconds); } /* The goal here is to set this timer to go off after iMilliseconds have passed. This method should not block. It should call some OS routine which provides timing facilities. It is assumed that this routine requires a C callback. That callback, when it is called, must look up the UT_Timer object which corresponds to it, and call its fire() method. The lookup of the UT_Timer object should be done in a manner such that if the timer is deleted and then the event is fired it will not segfault by referencing the now invalid timer object. This can be done by using the calls setIdentifier/getIdentifier and the static findTimer() calls. See ut_Win32Timer.cpp for an example of how it's done on Windows. We're hoping that something similar will work for other platforms. */ UT_sint32 UT_QNXTimer::set(UT_uint32 iMilliseconds) { PtArg_t args[5]; PtWidget_t *idTimer; int n; if (!gTimerWidget || !PtWidgetIsRealized(gTimerWidget)) { UT_DEBUGMSG(("TIMER: Can't access global timer widget ")); UT_ASSERT(0); return 1; } //Clear the identifier while we are doing this processing setIdentifier(0); //Set up and create the timer n = 0; PtSetArg(&args[n++], Pt_ARG_TIMER_INITIAL, iMilliseconds, 0); PtSetArg(&args[n++], Pt_ARG_TIMER_REPEAT, iMilliseconds, 0); if (!(idTimer = PtCreateWidget(PtTimer, gTimerWidget, n, args))) { UT_DEBUGMSG(("TIMER: Can't create local timer ")); UT_ASSERT(0); return 1; } //We get our reference to the timer object by querying the id of the widget PtAddCallback(idTimer, Pt_CB_TIMER_ACTIVATE, _Timer_Proc, NULL); setIdentifier((UT_sint32)idTimer); //The timer only starts when we realize the timer widget. PtRealizeWidget(idTimer); m_iMilliseconds = iMilliseconds; m_bStarted = true; return 0; } /* Stop the delivery of timer events and stop the OS timer from firing, but do not delete the class. */ void UT_QNXTimer::stop(void) { PtWidget_t *timer; timer = (PtWidget_t *)getIdentifier(); setIdentifier(0); if (timer && PtWidgetIsRealized(timer)) { PtDestroyWidget(timer); } m_bStarted = false; } /* Resume the delivery of timer events but only if they have not already been started. */ void UT_QNXTimer::start(void) { UT_ASSERT(m_iMilliseconds > 0); if (!m_bStarted) set(m_iMilliseconds); }