00001 00005 /* 00006 Copyright (C) 2002-2010 UFO: Alien Invasion. 00007 00008 This program is free software; you can redistribute it and/or 00009 modify it under the terms of the GNU General Public License 00010 as published by the Free Software Foundation; either version 2 00011 of the License, or (at your option) any later version. 00012 00013 This program is distributed in the hope that it will be useful, 00014 but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 00016 00017 See the GNU General Public License for more details. 00018 00019 You should have received a copy of the GNU General Public License 00020 along with this program; if not, write to the Free Software 00021 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 00022 00023 */ 00024 00025 #include "../client.h" 00026 #include "ui_nodes.h" 00027 #include "ui_timer.h" 00028 00032 #define UI_TIMER_SLOT_NUMBER 10 00033 00037 static uiTimer_t mn_timerSlots[UI_TIMER_SLOT_NUMBER]; 00038 00043 static uiTimer_t *mn_firstTimer; 00044 00049 static inline void UI_RemoveTimerFromActiveList (uiTimer_t *timer) 00050 { 00051 assert(timer >= mn_timerSlots && timer < mn_timerSlots + UI_TIMER_SLOT_NUMBER); 00052 if (timer->prev) { 00053 timer->prev->next = timer->next; 00054 } else { 00055 mn_firstTimer = timer->next; 00056 } 00057 if (timer->next) { 00058 timer->next->prev = timer->prev; 00059 } 00060 } 00061 00066 static void UI_InsertTimerInActiveList (uiTimer_t* first, uiTimer_t* newTimer) 00067 { 00068 uiTimer_t* current = first; 00069 uiTimer_t* prev = NULL; 00070 00071 /* find insert position */ 00072 if (current != NULL) { 00073 prev = current->prev; 00074 } 00075 while (current) { 00076 if (newTimer->nextTime < current->nextTime) 00077 break; 00078 prev = current; 00079 current = current->next; 00080 } 00081 00082 /* insert between previous and current */ 00083 newTimer->prev = prev; 00084 newTimer->next = current; 00085 if (current != NULL) { 00086 current->prev = newTimer; 00087 } 00088 if (prev != NULL) { 00089 prev->next = newTimer; 00090 } else { 00091 mn_firstTimer = newTimer; 00092 } 00093 } 00094 00098 void UI_HandleTimers (void) 00099 { 00100 /* is first element is out of date? */ 00101 while (mn_firstTimer && mn_firstTimer->nextTime <= CL_Milliseconds()) { 00102 uiTimer_t *timer = mn_firstTimer; 00103 00104 /* throw event */ 00105 timer->calledTime++; 00106 timer->callback(timer->owner, timer); 00107 00108 /* update the sorted list */ 00109 if (timer->isRunning) { 00110 UI_RemoveTimerFromActiveList(timer); 00111 timer->nextTime += timer->delay; 00112 UI_InsertTimerInActiveList(timer->next, timer); 00113 } 00114 } 00115 } 00116 00123 uiTimer_t* UI_AllocTimer (uiNode_t *node, int firstDelay, timerCallback_t callback) 00124 { 00125 uiTimer_t *timer = NULL; 00126 int i; 00127 00128 /* search empty slot */ 00129 for (i = 0; i < UI_TIMER_SLOT_NUMBER; i++) { 00130 if (mn_timerSlots[i].callback != NULL) 00131 continue; 00132 timer = mn_timerSlots + i; 00133 break; 00134 } 00135 if (timer == NULL) 00136 Com_Error(ERR_FATAL, "UI_AllocTimer: No more timer slot"); 00137 00138 timer->owner = node; 00139 timer->delay = firstDelay; 00140 timer->callback = callback; 00141 timer->calledTime = 0; 00142 timer->prev = NULL; 00143 timer->next = NULL; 00144 timer->isRunning = qfalse; 00145 return timer; 00146 } 00147 00151 void UI_TimerStart (uiTimer_t *timer) 00152 { 00153 if (timer->isRunning) 00154 return; 00155 assert(mn_firstTimer != timer && timer->prev == NULL && timer->next == NULL); 00156 timer->nextTime = CL_Milliseconds() + timer->delay; 00157 timer->isRunning = qtrue; 00158 UI_InsertTimerInActiveList(mn_firstTimer, timer); 00159 } 00160 00164 void UI_TimerStop (uiTimer_t *timer) 00165 { 00166 if (!timer->isRunning) 00167 return; 00168 UI_RemoveTimerFromActiveList(timer); 00169 timer->prev = NULL; 00170 timer->next = NULL; 00171 timer->isRunning = qfalse; 00172 } 00173 00177 void UI_TimerRelease (uiTimer_t *timer) 00178 { 00179 UI_RemoveTimerFromActiveList(timer); 00180 timer->prev = NULL; 00181 timer->next = NULL; 00182 timer->owner = NULL; 00183 timer->callback = NULL; 00184 } 00185 00186 #ifdef COMPILE_UNITTESTS 00187 00192 uiTimer_t *UI_GetFirstTimer (void) 00193 { 00194 return mn_firstTimer; 00195 } 00196 00197 void UI_PrivateInsertTimerInActiveList (uiTimer_t* first, uiTimer_t* newTimer) 00198 { 00199 UI_InsertTimerInActiveList(first, newTimer); 00200 } 00201 00202 #endif