| @@ -1,344 +1,344 @@ | |||
| /* | |||
| ============================================================================== | |||
| This file is part of the JUCE library - "Jules' Utility Class Extensions" | |||
| Copyright 2004-7 by Raw Material Software ltd. | |||
| ------------------------------------------------------------------------------ | |||
| JUCE can be redistributed and/or modified 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. | |||
| JUCE 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 JUCE; if not, visit www.gnu.org/licenses or write to the | |||
| Free Software Foundation, Inc., 59 Temple Place, Suite 330, | |||
| Boston, MA 02111-1307 USA | |||
| ------------------------------------------------------------------------------ | |||
| If you'd like to release a closed-source product which uses JUCE, commercial | |||
| licenses are also available: visit www.rawmaterialsoftware.com/juce for | |||
| more information. | |||
| ============================================================================== | |||
| */ | |||
| #include "../../../src/juce_core/basics/juce_StandardHeader.h" | |||
| #include <Carbon/Carbon.h> | |||
| BEGIN_JUCE_NAMESPACE | |||
| #include "../../../src/juce_appframework/events/juce_MessageManager.h" | |||
| #include "../../../src/juce_appframework/application/juce_Application.h" | |||
| #include "../../../src/juce_appframework/gui/components/juce_Desktop.h" | |||
| #include "../../../src/juce_core/text/juce_StringArray.h" | |||
| #include "../../../src/juce_core/threads/juce_Thread.h" | |||
| #include "../../../src/juce_core/misc/juce_PlatformUtilities.h" | |||
| #undef Point | |||
| static int kJUCEClass = FOUR_CHAR_CODE ('JUCE'); | |||
| const int kJUCEKind = 1; | |||
| const int kCallbackKind = 2; | |||
| extern void juce_HandleProcessFocusChange(); | |||
| extern void juce_maximiseAllMinimisedWindows(); | |||
| extern void juce_InvokeMainMenuCommand (const HICommand& command); | |||
| extern void juce_MainMenuAboutToBeUsed(); | |||
| static pascal OSStatus EventHandlerProc (EventHandlerCallRef, EventRef theEvent, void* userData) | |||
| { | |||
| void* event = 0; | |||
| GetEventParameter (theEvent, 'mess', typeVoidPtr, 0, sizeof (void*), 0, &event); | |||
| if (event != 0) | |||
| MessageManager::getInstance()->deliverMessage (event); | |||
| return noErr; | |||
| } | |||
| struct CallbackMessagePayload | |||
| { | |||
| MessageCallbackFunction* function; | |||
| void* parameter; | |||
| void* volatile result; | |||
| bool volatile hasBeenExecuted; | |||
| }; | |||
| static pascal OSStatus CallbackHandlerProc (EventHandlerCallRef, EventRef theEvent, void* userData) | |||
| { | |||
| CallbackMessagePayload* pl = 0; | |||
| GetEventParameter (theEvent, 'mess', typeVoidPtr, 0, sizeof(pl), 0, &pl); | |||
| if (pl != 0) | |||
| { | |||
| pl->result = (*pl->function) (pl->parameter); | |||
| pl->hasBeenExecuted = true; | |||
| } | |||
| return noErr; | |||
| } | |||
| static pascal OSStatus MouseClickHandlerProc (EventHandlerCallRef, EventRef theEvent, void* userData) | |||
| { | |||
| ::Point where; | |||
| GetEventParameter (theEvent, kEventParamMouseLocation, typeQDPoint, 0, sizeof(::Point), 0, &where); | |||
| WindowRef window; | |||
| if (FindWindow (where, &window) == inMenuBar) | |||
| { | |||
| // turn off the wait cursor before going in here.. | |||
| const int oldTimeBeforeWaitCursor = MessageManager::getInstance()->getTimeBeforeShowingWaitCursor(); | |||
| MessageManager::getInstance()->setTimeBeforeShowingWaitCursor (0); | |||
| if (Component::getCurrentlyModalComponent() != 0) | |||
| Component::getCurrentlyModalComponent()->inputAttemptWhenModal(); | |||
| juce_MainMenuAboutToBeUsed(); | |||
| MenuSelect (where); | |||
| HiliteMenu (0); | |||
| MessageManager::getInstance()->setTimeBeforeShowingWaitCursor (oldTimeBeforeWaitCursor); | |||
| return noErr; | |||
| } | |||
| return eventNotHandledErr; | |||
| } | |||
| static pascal OSErr QuitAppleEventHandler (const AppleEvent *appleEvt, AppleEvent* reply, long refcon) | |||
| { | |||
| if (JUCEApplication::getInstance() != 0) | |||
| JUCEApplication::getInstance()->systemRequestedQuit(); | |||
| return noErr; | |||
| } | |||
| static pascal OSErr OpenDocEventHandler (const AppleEvent *appleEvt, AppleEvent* reply, long refcon) | |||
| { | |||
| AEDescList docs; | |||
| StringArray files; | |||
| if (AEGetParamDesc (appleEvt, keyDirectObject, typeAEList, &docs) == noErr) | |||
| { | |||
| long num; | |||
| if (AECountItems (&docs, &num) == noErr) | |||
| { | |||
| for (int i = 1; i <= num; ++i) | |||
| { | |||
| FSRef file; | |||
| AEKeyword keyword; | |||
| DescType type; | |||
| Size size; | |||
| if (AEGetNthPtr (&docs, i, typeFSRef, &keyword, &type, | |||
| &file, sizeof (file), &size) == noErr) | |||
| { | |||
| const String path (PlatformUtilities::makePathFromFSRef (&file)); | |||
| if (path.isNotEmpty()) | |||
| files.add (path.quoted()); | |||
| } | |||
| } | |||
| if (files.size() > 0 | |||
| && JUCEApplication::getInstance() != 0) | |||
| { | |||
| JUCE_TRY | |||
| { | |||
| JUCEApplication::getInstance() | |||
| ->anotherInstanceStarted (files.joinIntoString (T(" "))); | |||
| } | |||
| JUCE_CATCH_ALL | |||
| } | |||
| } | |||
| AEDisposeDesc (&docs); | |||
| }; | |||
| return noErr; | |||
| } | |||
| static pascal OSStatus AppEventHandlerProc (EventHandlerCallRef, EventRef theEvent, void* userData) | |||
| { | |||
| const UInt32 eventClass = GetEventClass (theEvent); | |||
| if (eventClass == kEventClassCommand) | |||
| { | |||
| HICommand command; | |||
| if (GetEventParameter (theEvent, kEventParamHICommand, typeHICommand, 0, sizeof (command), 0, &command) == noErr | |||
| || GetEventParameter (theEvent, kEventParamDirectObject, typeHICommand, 0, sizeof (command), 0, &command) == noErr) | |||
| { | |||
| if (command.commandID == kHICommandQuit) | |||
| { | |||
| if (JUCEApplication::getInstance() != 0) | |||
| JUCEApplication::getInstance()->systemRequestedQuit(); | |||
| return noErr; | |||
| } | |||
| else if (command.commandID == kHICommandMaximizeAll | |||
| || command.commandID == kHICommandMaximizeWindow | |||
| || command.commandID == kHICommandBringAllToFront) | |||
| { | |||
| juce_maximiseAllMinimisedWindows(); | |||
| return noErr; | |||
| } | |||
| else | |||
| { | |||
| juce_InvokeMainMenuCommand (command); | |||
| } | |||
| } | |||
| } | |||
| else if (eventClass == kEventClassApplication) | |||
| { | |||
| if (GetEventKind (theEvent) == kEventAppFrontSwitched) | |||
| { | |||
| juce_HandleProcessFocusChange(); | |||
| } | |||
| else if (GetEventKind (theEvent) == kEventAppShown) | |||
| { | |||
| // this seems to blank the windows, so we need to do a repaint.. | |||
| for (int i = Desktop::getInstance().getNumComponents(); --i >= 0;) | |||
| { | |||
| Component* const c = Desktop::getInstance().getComponent (i); | |||
| if (c != 0) | |||
| c->repaint(); | |||
| } | |||
| } | |||
| } | |||
| return eventNotHandledErr; | |||
| } | |||
| static EventQueueRef mainQueue; | |||
| static EventHandlerRef juceEventHandler = 0; | |||
| static EventHandlerRef callbackEventHandler = 0; | |||
| //============================================================================== | |||
| void MessageManager::doPlatformSpecificInitialisation() | |||
| { | |||
| static bool initialised = false; | |||
| if (! initialised) | |||
| { | |||
| initialised = true; | |||
| #if MACOS_10_3_OR_EARLIER | |||
| // work-around for a bug in MacOS 10.2.. | |||
| ProcessSerialNumber junkPSN; | |||
| (void) GetCurrentProcess (&junkPSN); | |||
| #endif | |||
| mainQueue = GetMainEventQueue(); | |||
| // if we're linking a Juce app to one or more dynamic libraries, we'll need different values | |||
| // for this so each module doesn't interfere with the others. | |||
| UnsignedWide t; | |||
| Microseconds (&t); | |||
| kJUCEClass ^= t.lo; | |||
| } | |||
| const EventTypeSpec type1 = { kJUCEClass, kJUCEKind }; | |||
| InstallApplicationEventHandler (NewEventHandlerUPP (EventHandlerProc), 1, &type1, 0, &juceEventHandler); | |||
| const EventTypeSpec type2 = { kJUCEClass, kCallbackKind }; | |||
| InstallApplicationEventHandler (NewEventHandlerUPP (CallbackHandlerProc), 1, &type2, 0, &callbackEventHandler); | |||
| // only do this stuff if we're running as an application rather than a library.. | |||
| if (JUCEApplication::getInstance() != 0) | |||
| { | |||
| const EventTypeSpec type3 = { kEventClassMouse, kEventMouseDown }; | |||
| InstallApplicationEventHandler (NewEventHandlerUPP (MouseClickHandlerProc), 1, &type3, 0, 0); | |||
| const EventTypeSpec type4[] = { { kEventClassApplication, kEventAppShown }, | |||
| { kEventClassApplication, kEventAppFrontSwitched }, | |||
| { kEventClassCommand, kEventProcessCommand } }; | |||
| InstallApplicationEventHandler (NewEventHandlerUPP (AppEventHandlerProc), 3, type4, 0, 0); | |||
| AEInstallEventHandler (kCoreEventClass, kAEQuitApplication, | |||
| NewAEEventHandlerUPP (QuitAppleEventHandler), 0, false); | |||
| AEInstallEventHandler (kCoreEventClass, kAEOpenDocuments, | |||
| NewAEEventHandlerUPP (OpenDocEventHandler), 0, false); | |||
| } | |||
| } | |||
| void MessageManager::doPlatformSpecificShutdown() | |||
| { | |||
| if (juceEventHandler != 0) | |||
| { | |||
| RemoveEventHandler (juceEventHandler); | |||
| juceEventHandler = 0; | |||
| } | |||
| if (callbackEventHandler != 0) | |||
| { | |||
| RemoveEventHandler (callbackEventHandler); | |||
| callbackEventHandler = 0; | |||
| } | |||
| } | |||
| bool juce_postMessageToSystemQueue (void* message) | |||
| { | |||
| jassert (mainQueue == GetMainEventQueue()); | |||
| EventRef event; | |||
| if (CreateEvent (0, kJUCEClass, kJUCEKind, 0, kEventAttributeUserEvent, &event) == noErr) | |||
| { | |||
| SetEventParameter (event, 'mess', typeVoidPtr, sizeof (void*), &message); | |||
| const bool ok = PostEventToQueue (mainQueue, event, kEventPriorityStandard) == noErr; | |||
| ReleaseEvent (event); | |||
| return ok; | |||
| } | |||
| return false; | |||
| } | |||
| void MessageManager::broadcastMessage (const String& value) throw() | |||
| { | |||
| } | |||
| void* MessageManager::callFunctionOnMessageThread (MessageCallbackFunction* callback, | |||
| void* data) | |||
| { | |||
| if (isThisTheMessageThread()) | |||
| { | |||
| return (*callback) (data); | |||
| } | |||
| else | |||
| { | |||
| jassert (mainQueue == GetMainEventQueue()); | |||
| CallbackMessagePayload cmp; | |||
| cmp.function = callback; | |||
| cmp.parameter = data; | |||
| cmp.result = 0; | |||
| cmp.hasBeenExecuted = false; | |||
| EventRef event; | |||
| if (CreateEvent (0, kJUCEClass, kCallbackKind, 0, kEventAttributeUserEvent, &event) == noErr) | |||
| { | |||
| void* v = &cmp; | |||
| SetEventParameter (event, 'mess', typeVoidPtr, sizeof (void*), &v); | |||
| if (PostEventToQueue (mainQueue, event, kEventPriorityStandard) == noErr) | |||
| { | |||
| while (! cmp.hasBeenExecuted) | |||
| Thread::yield(); | |||
| return cmp.result; | |||
| } | |||
| } | |||
| return 0; | |||
| } | |||
| } | |||
| END_JUCE_NAMESPACE | |||
| /* | |||
| ============================================================================== | |||
| This file is part of the JUCE library - "Jules' Utility Class Extensions" | |||
| Copyright 2004-7 by Raw Material Software ltd. | |||
| ------------------------------------------------------------------------------ | |||
| JUCE can be redistributed and/or modified 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. | |||
| JUCE 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 JUCE; if not, visit www.gnu.org/licenses or write to the | |||
| Free Software Foundation, Inc., 59 Temple Place, Suite 330, | |||
| Boston, MA 02111-1307 USA | |||
| ------------------------------------------------------------------------------ | |||
| If you'd like to release a closed-source product which uses JUCE, commercial | |||
| licenses are also available: visit www.rawmaterialsoftware.com/juce for | |||
| more information. | |||
| ============================================================================== | |||
| */ | |||
| #include "../../../src/juce_core/basics/juce_StandardHeader.h" | |||
| #include <Carbon/Carbon.h> | |||
| BEGIN_JUCE_NAMESPACE | |||
| #include "../../../src/juce_appframework/events/juce_MessageManager.h" | |||
| #include "../../../src/juce_appframework/application/juce_Application.h" | |||
| #include "../../../src/juce_appframework/gui/components/juce_Desktop.h" | |||
| #include "../../../src/juce_core/text/juce_StringArray.h" | |||
| #include "../../../src/juce_core/threads/juce_Thread.h" | |||
| #include "../../../src/juce_core/misc/juce_PlatformUtilities.h" | |||
| #undef Point | |||
| static int kJUCEClass = FOUR_CHAR_CODE ('JUCE'); | |||
| const int kJUCEKind = 1; | |||
| const int kCallbackKind = 2; | |||
| extern void juce_HandleProcessFocusChange(); | |||
| extern void juce_maximiseAllMinimisedWindows(); | |||
| extern void juce_InvokeMainMenuCommand (const HICommand& command); | |||
| extern void juce_MainMenuAboutToBeUsed(); | |||
| static pascal OSStatus EventHandlerProc (EventHandlerCallRef, EventRef theEvent, void* userData) | |||
| { | |||
| void* event = 0; | |||
| GetEventParameter (theEvent, 'mess', typeVoidPtr, 0, sizeof (void*), 0, &event); | |||
| if (event != 0) | |||
| MessageManager::getInstance()->deliverMessage (event); | |||
| return noErr; | |||
| } | |||
| struct CallbackMessagePayload | |||
| { | |||
| MessageCallbackFunction* function; | |||
| void* parameter; | |||
| void* volatile result; | |||
| bool volatile hasBeenExecuted; | |||
| }; | |||
| static pascal OSStatus CallbackHandlerProc (EventHandlerCallRef, EventRef theEvent, void* userData) | |||
| { | |||
| CallbackMessagePayload* pl = 0; | |||
| GetEventParameter (theEvent, 'mess', typeVoidPtr, 0, sizeof(pl), 0, &pl); | |||
| if (pl != 0) | |||
| { | |||
| pl->result = (*pl->function) (pl->parameter); | |||
| pl->hasBeenExecuted = true; | |||
| } | |||
| return noErr; | |||
| } | |||
| static pascal OSStatus MouseClickHandlerProc (EventHandlerCallRef, EventRef theEvent, void* userData) | |||
| { | |||
| ::Point where; | |||
| GetEventParameter (theEvent, kEventParamMouseLocation, typeQDPoint, 0, sizeof(::Point), 0, &where); | |||
| WindowRef window; | |||
| if (FindWindow (where, &window) == inMenuBar) | |||
| { | |||
| // turn off the wait cursor before going in here.. | |||
| const int oldTimeBeforeWaitCursor = MessageManager::getInstance()->getTimeBeforeShowingWaitCursor(); | |||
| MessageManager::getInstance()->setTimeBeforeShowingWaitCursor (0); | |||
| if (Component::getCurrentlyModalComponent() != 0) | |||
| Component::getCurrentlyModalComponent()->inputAttemptWhenModal(); | |||
| juce_MainMenuAboutToBeUsed(); | |||
| MenuSelect (where); | |||
| HiliteMenu (0); | |||
| MessageManager::getInstance()->setTimeBeforeShowingWaitCursor (oldTimeBeforeWaitCursor); | |||
| return noErr; | |||
| } | |||
| return eventNotHandledErr; | |||
| } | |||
| static pascal OSErr QuitAppleEventHandler (const AppleEvent *appleEvt, AppleEvent* reply, long refcon) | |||
| { | |||
| if (JUCEApplication::getInstance() != 0) | |||
| JUCEApplication::getInstance()->systemRequestedQuit(); | |||
| return noErr; | |||
| } | |||
| static pascal OSErr OpenDocEventHandler (const AppleEvent *appleEvt, AppleEvent* reply, long refcon) | |||
| { | |||
| AEDescList docs; | |||
| StringArray files; | |||
| if (AEGetParamDesc (appleEvt, keyDirectObject, typeAEList, &docs) == noErr) | |||
| { | |||
| long num; | |||
| if (AECountItems (&docs, &num) == noErr) | |||
| { | |||
| for (int i = 1; i <= num; ++i) | |||
| { | |||
| FSRef file; | |||
| AEKeyword keyword; | |||
| DescType type; | |||
| Size size; | |||
| if (AEGetNthPtr (&docs, i, typeFSRef, &keyword, &type, | |||
| &file, sizeof (file), &size) == noErr) | |||
| { | |||
| const String path (PlatformUtilities::makePathFromFSRef (&file)); | |||
| if (path.isNotEmpty()) | |||
| files.add (path.quoted()); | |||
| } | |||
| } | |||
| if (files.size() > 0 | |||
| && JUCEApplication::getInstance() != 0) | |||
| { | |||
| JUCE_TRY | |||
| { | |||
| JUCEApplication::getInstance() | |||
| ->anotherInstanceStarted (files.joinIntoString (T(" "))); | |||
| } | |||
| JUCE_CATCH_ALL | |||
| } | |||
| } | |||
| AEDisposeDesc (&docs); | |||
| }; | |||
| return noErr; | |||
| } | |||
| static pascal OSStatus AppEventHandlerProc (EventHandlerCallRef, EventRef theEvent, void* userData) | |||
| { | |||
| const UInt32 eventClass = GetEventClass (theEvent); | |||
| if (eventClass == kEventClassCommand) | |||
| { | |||
| HICommand command; | |||
| if (GetEventParameter (theEvent, kEventParamHICommand, typeHICommand, 0, sizeof (command), 0, &command) == noErr | |||
| || GetEventParameter (theEvent, kEventParamDirectObject, typeHICommand, 0, sizeof (command), 0, &command) == noErr) | |||
| { | |||
| if (command.commandID == kHICommandQuit) | |||
| { | |||
| if (JUCEApplication::getInstance() != 0) | |||
| JUCEApplication::getInstance()->systemRequestedQuit(); | |||
| return noErr; | |||
| } | |||
| else if (command.commandID == kHICommandMaximizeAll | |||
| || command.commandID == kHICommandMaximizeWindow | |||
| || command.commandID == kHICommandBringAllToFront) | |||
| { | |||
| juce_maximiseAllMinimisedWindows(); | |||
| return noErr; | |||
| } | |||
| else | |||
| { | |||
| juce_InvokeMainMenuCommand (command); | |||
| } | |||
| } | |||
| } | |||
| else if (eventClass == kEventClassApplication) | |||
| { | |||
| if (GetEventKind (theEvent) == kEventAppFrontSwitched) | |||
| { | |||
| juce_HandleProcessFocusChange(); | |||
| } | |||
| else if (GetEventKind (theEvent) == kEventAppShown) | |||
| { | |||
| // this seems to blank the windows, so we need to do a repaint.. | |||
| for (int i = Desktop::getInstance().getNumComponents(); --i >= 0;) | |||
| { | |||
| Component* const c = Desktop::getInstance().getComponent (i); | |||
| if (c != 0) | |||
| c->repaint(); | |||
| } | |||
| } | |||
| } | |||
| return eventNotHandledErr; | |||
| } | |||
| static EventQueueRef mainQueue; | |||
| static EventHandlerRef juceEventHandler = 0; | |||
| static EventHandlerRef callbackEventHandler = 0; | |||
| //============================================================================== | |||
| void MessageManager::doPlatformSpecificInitialisation() | |||
| { | |||
| static bool initialised = false; | |||
| if (! initialised) | |||
| { | |||
| initialised = true; | |||
| #if MACOS_10_3_OR_EARLIER | |||
| // work-around for a bug in MacOS 10.2.. | |||
| ProcessSerialNumber junkPSN; | |||
| (void) GetCurrentProcess (&junkPSN); | |||
| #endif | |||
| mainQueue = GetMainEventQueue(); | |||
| // if we're linking a Juce app to one or more dynamic libraries, we'll need different values | |||
| // for this so each module doesn't interfere with the others. | |||
| UnsignedWide t; | |||
| Microseconds (&t); | |||
| kJUCEClass ^= t.lo; | |||
| } | |||
| const EventTypeSpec type1 = { kJUCEClass, kJUCEKind }; | |||
| InstallApplicationEventHandler (NewEventHandlerUPP (EventHandlerProc), 1, &type1, 0, &juceEventHandler); | |||
| const EventTypeSpec type2 = { kJUCEClass, kCallbackKind }; | |||
| InstallApplicationEventHandler (NewEventHandlerUPP (CallbackHandlerProc), 1, &type2, 0, &callbackEventHandler); | |||
| // only do this stuff if we're running as an application rather than a library.. | |||
| if (JUCEApplication::getInstance() != 0) | |||
| { | |||
| const EventTypeSpec type3 = { kEventClassMouse, kEventMouseDown }; | |||
| InstallApplicationEventHandler (NewEventHandlerUPP (MouseClickHandlerProc), 1, &type3, 0, 0); | |||
| const EventTypeSpec type4[] = { { kEventClassApplication, kEventAppShown }, | |||
| { kEventClassApplication, kEventAppFrontSwitched }, | |||
| { kEventClassCommand, kEventProcessCommand } }; | |||
| InstallApplicationEventHandler (NewEventHandlerUPP (AppEventHandlerProc), 3, type4, 0, 0); | |||
| AEInstallEventHandler (kCoreEventClass, kAEQuitApplication, | |||
| NewAEEventHandlerUPP (QuitAppleEventHandler), 0, false); | |||
| AEInstallEventHandler (kCoreEventClass, kAEOpenDocuments, | |||
| NewAEEventHandlerUPP (OpenDocEventHandler), 0, false); | |||
| } | |||
| } | |||
| void MessageManager::doPlatformSpecificShutdown() | |||
| { | |||
| if (juceEventHandler != 0) | |||
| { | |||
| RemoveEventHandler (juceEventHandler); | |||
| juceEventHandler = 0; | |||
| } | |||
| if (callbackEventHandler != 0) | |||
| { | |||
| RemoveEventHandler (callbackEventHandler); | |||
| callbackEventHandler = 0; | |||
| } | |||
| } | |||
| bool juce_postMessageToSystemQueue (void* message) | |||
| { | |||
| jassert (mainQueue == GetMainEventQueue()); | |||
| EventRef event; | |||
| if (CreateEvent (0, kJUCEClass, kJUCEKind, 0, kEventAttributeUserEvent, &event) == noErr) | |||
| { | |||
| SetEventParameter (event, 'mess', typeVoidPtr, sizeof (void*), &message); | |||
| const bool ok = PostEventToQueue (mainQueue, event, kEventPriorityStandard) == noErr; | |||
| ReleaseEvent (event); | |||
| return ok; | |||
| } | |||
| return false; | |||
| } | |||
| void MessageManager::broadcastMessage (const String& value) throw() | |||
| { | |||
| } | |||
| void* MessageManager::callFunctionOnMessageThread (MessageCallbackFunction* callback, | |||
| void* data) | |||
| { | |||
| if (isThisTheMessageThread()) | |||
| { | |||
| return (*callback) (data); | |||
| } | |||
| else | |||
| { | |||
| jassert (mainQueue == GetMainEventQueue()); | |||
| CallbackMessagePayload cmp; | |||
| cmp.function = callback; | |||
| cmp.parameter = data; | |||
| cmp.result = 0; | |||
| cmp.hasBeenExecuted = false; | |||
| EventRef event; | |||
| if (CreateEvent (0, kJUCEClass, kCallbackKind, 0, kEventAttributeUserEvent, &event) == noErr) | |||
| { | |||
| void* v = &cmp; | |||
| SetEventParameter (event, 'mess', typeVoidPtr, sizeof (void*), &v); | |||
| if (PostEventToQueue (mainQueue, event, kEventPriorityStandard) == noErr) | |||
| { | |||
| while (! cmp.hasBeenExecuted) | |||
| Thread::yield(); | |||
| return cmp.result; | |||
| } | |||
| } | |||
| return 0; | |||
| } | |||
| } | |||
| END_JUCE_NAMESPACE | |||
| @@ -1722,7 +1722,7 @@ public: | |||
| peer->doDragDropMove (theEvent); | |||
| return noErr; | |||
| case kEventControlDragLeave: | |||
| case kEventControlDragLeave: | |||
| peer->doDragDropExit (theEvent); | |||
| return noErr; | |||
| @@ -791,7 +791,7 @@ public: | |||
| { | |||
| case kVstSmpte24fps: | |||
| rate = AudioPlayHead::fps24; | |||
| fps = 24.0; | |||
| fps = 24.0; | |||
| break; | |||
| case kVstSmpte25fps: | |||
| @@ -806,22 +806,22 @@ public: | |||
| case kVstSmpte30fps: | |||
| rate = AudioPlayHead::fps30; | |||
| fps = 30.0; | |||
| fps = 30.0; | |||
| break; | |||
| case kVstSmpte2997dfps: | |||
| case kVstSmpte2997dfps: | |||
| rate = AudioPlayHead::fps2997drop; | |||
| fps = 29.97; | |||
| fps = 29.97; | |||
| break; | |||
| case kVstSmpte30dfps: | |||
| rate = AudioPlayHead::fps30drop; | |||
| fps = 30.0; | |||
| fps = 30.0; | |||
| break; | |||
| case kVstSmpteFilm16mm: | |||
| case kVstSmpteFilm35mm: | |||
| fps = 24.0; | |||
| fps = 24.0; | |||
| break; | |||
| case kVstSmpte239fps: fps = 23.976; break; | |||
| @@ -1019,7 +1019,7 @@ public: | |||
| void doIdleCallback() | |||
| { | |||
| // (wavelab calls this on a separate thread and causes a deadlock).. | |||
| if (MessageManager::getInstance()->isThisTheMessageThread() | |||
| if (MessageManager::getInstance()->isThisTheMessageThread() | |||
| && ! recursionCheck) | |||
| { | |||
| const MessageManagerLock mml; | |||
| @@ -7961,4 +7961,3 @@ static const unsigned char temp17[] = {47,42,13,10,32,32,61,61,61,61,61,61,61,61 | |||
| 110,100,77,97,110,97,103,101,114,42,32,99,111,109,109,97,110,100,77,97,110,97,103,101,114,41,13,10,123,13,10,32,32,32,32,114,101,116,117,114, | |||
| 110,32,110,101,119,32,87,105,100,103,101,116,115,68,101,109,111,32,40,99,111,109,109,97,110,100,77,97,110,97,103,101,114,41,59,13,10,125,13,10,0,0}; | |||
| const char* BinaryData::widgetsdemo_cpp = (const char*) temp17; | |||
| @@ -911,4 +911,3 @@ static const unsigned char temp4[] = {137,80,78,71,13,10,26,10,0,0,0,13,73,72,68 | |||
| 0,98,28,9,155,95,0,2,104,68,236,11,1,8,160,17,225,73,128,0,3,0,120,52,172,151,198,78,252,63,0,0,0,0,73,69,78,68,174,66, | |||
| 96,130,0,0}; | |||
| const char* BinaryData::prefs_misc_png = (const char*) temp4; | |||
| @@ -1,373 +1,373 @@ | |||
| /* | |||
| ============================================================================== | |||
| This file is part of the JUCE library - "Jules' Utility Class Extensions" | |||
| Copyright 2004-7 by Raw Material Software ltd. | |||
| ------------------------------------------------------------------------------ | |||
| JUCE can be redistributed and/or modified 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. | |||
| JUCE 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 JUCE; if not, visit www.gnu.org/licenses or write to the | |||
| Free Software Foundation, Inc., 59 Temple Place, Suite 330, | |||
| Boston, MA 02111-1307 USA | |||
| ------------------------------------------------------------------------------ | |||
| If you'd like to release a closed-source product which uses JUCE, commercial | |||
| licenses are also available: visit www.rawmaterialsoftware.com/juce for | |||
| more information. | |||
| ============================================================================== | |||
| */ | |||
| #include "../../juce_core/basics/juce_StandardHeader.h" | |||
| BEGIN_JUCE_NAMESPACE | |||
| #include "juce_MessageManager.h" | |||
| #include "juce_ActionListenerList.h" | |||
| #include "../application/juce_Application.h" | |||
| #include "../gui/components/juce_Component.h" | |||
| #include "../../juce_core/threads/juce_Thread.h" | |||
| #include "../../juce_core/basics/juce_Time.h" | |||
| //============================================================================== | |||
| // platform-specific functions.. | |||
| bool juce_dispatchNextMessageOnSystemQueue (bool returnIfNoPendingMessages); | |||
| bool juce_postMessageToSystemQueue (void* message); | |||
| //============================================================================== | |||
| MessageManager* MessageManager::instance = 0; | |||
| static const int quitMessageId = 0xfffff321; | |||
| MessageManager::MessageManager() throw() | |||
| : broadcastListeners (0), | |||
| quitMessagePosted (false), | |||
| quitMessageReceived (false), | |||
| useMaximumForceWhenQuitting (true), | |||
| messageCounter (0), | |||
| lastMessageCounter (-1), | |||
| isInMessageDispatcher (0), | |||
| needToGetRidOfWaitCursor (false), | |||
| timeBeforeWaitCursor (0), | |||
| lastActivityCheckOkTime (0) | |||
| { | |||
| currentLockingThreadId = messageThreadId = Thread::getCurrentThreadId(); | |||
| } | |||
| MessageManager::~MessageManager() throw() | |||
| { | |||
| jassert (instance == this); | |||
| instance = 0; | |||
| deleteAndZero (broadcastListeners); | |||
| doPlatformSpecificShutdown(); | |||
| } | |||
| MessageManager* MessageManager::getInstance() throw() | |||
| { | |||
| if (instance == 0) | |||
| { | |||
| instance = new MessageManager(); | |||
| doPlatformSpecificInitialisation(); | |||
| instance->setTimeBeforeShowingWaitCursor (500); | |||
| } | |||
| return instance; | |||
| } | |||
| void MessageManager::postMessageToQueue (Message* const message) | |||
| { | |||
| if (quitMessagePosted || ! juce_postMessageToSystemQueue (message)) | |||
| delete message; | |||
| } | |||
| //============================================================================== | |||
| // not for public use.. | |||
| void MessageManager::deliverMessage (void* message) | |||
| { | |||
| const MessageManagerLock lock; | |||
| Message* const m = (Message*) message; | |||
| MessageListener* const recipient = m->messageRecipient; | |||
| if (messageListeners.contains (recipient)) | |||
| { | |||
| JUCE_TRY | |||
| { | |||
| recipient->handleMessage (*m); | |||
| } | |||
| JUCE_CATCH_EXCEPTION | |||
| if (needToGetRidOfWaitCursor) | |||
| { | |||
| needToGetRidOfWaitCursor = false; | |||
| MouseCursor::hideWaitCursor(); | |||
| } | |||
| ++messageCounter; | |||
| } | |||
| else if (recipient == 0 && m->intParameter1 == quitMessageId) | |||
| { | |||
| quitMessageReceived = true; | |||
| useMaximumForceWhenQuitting = (m->intParameter2 != 0); | |||
| } | |||
| delete m; | |||
| } | |||
| //============================================================================== | |||
| bool MessageManager::dispatchNextMessage (const bool returnImmediatelyIfNoMessages, | |||
| bool* const wasAMessageDispatched) | |||
| { | |||
| if (quitMessageReceived) | |||
| { | |||
| if (wasAMessageDispatched != 0) | |||
| *wasAMessageDispatched = false; | |||
| return false; | |||
| } | |||
| ++isInMessageDispatcher; | |||
| bool result = false; | |||
| JUCE_TRY | |||
| { | |||
| result = juce_dispatchNextMessageOnSystemQueue (returnImmediatelyIfNoMessages); | |||
| if (wasAMessageDispatched != 0) | |||
| *wasAMessageDispatched = result; | |||
| if (instance == 0) | |||
| return false; | |||
| } | |||
| JUCE_CATCH_EXCEPTION | |||
| --isInMessageDispatcher; | |||
| ++messageCounter; | |||
| return result || ! returnImmediatelyIfNoMessages; | |||
| } | |||
| void MessageManager::dispatchPendingMessages (int maxNumberOfMessagesToDispatch) | |||
| { | |||
| jassert (isThisTheMessageThread()); // must only be called by the message thread | |||
| while (--maxNumberOfMessagesToDispatch >= 0 && ! quitMessageReceived) | |||
| { | |||
| ++isInMessageDispatcher; | |||
| bool carryOn = false; | |||
| JUCE_TRY | |||
| { | |||
| carryOn = juce_dispatchNextMessageOnSystemQueue (true); | |||
| } | |||
| JUCE_CATCH_EXCEPTION | |||
| --isInMessageDispatcher; | |||
| ++messageCounter; | |||
| if (! carryOn) | |||
| break; | |||
| } | |||
| } | |||
| bool MessageManager::runDispatchLoop() | |||
| { | |||
| jassert (isThisTheMessageThread()); // must only be called by the message thread | |||
| while (dispatchNextMessage()) | |||
| { | |||
| } | |||
| return useMaximumForceWhenQuitting; | |||
| } | |||
| //============================================================================== | |||
| void MessageManager::postQuitMessage (const bool useMaximumForce) | |||
| { | |||
| Message* const m = new Message (quitMessageId, (useMaximumForce) ? 1 : 0, 0, 0); | |||
| m->messageRecipient = 0; | |||
| postMessageToQueue (m); | |||
| quitMessagePosted = true; | |||
| } | |||
| bool MessageManager::hasQuitMessageBeenPosted() const throw() | |||
| { | |||
| return quitMessagePosted; | |||
| } | |||
| //============================================================================== | |||
| void MessageManager::deliverBroadcastMessage (const String& value) | |||
| { | |||
| if (broadcastListeners != 0) | |||
| broadcastListeners->sendActionMessage (value); | |||
| } | |||
| void MessageManager::registerBroadcastListener (ActionListener* const listener) throw() | |||
| { | |||
| if (broadcastListeners == 0) | |||
| broadcastListeners = new ActionListenerList(); | |||
| broadcastListeners->addActionListener (listener); | |||
| } | |||
| void MessageManager::deregisterBroadcastListener (ActionListener* const listener) throw() | |||
| { | |||
| if (broadcastListeners != 0) | |||
| broadcastListeners->removeActionListener (listener); | |||
| } | |||
| //============================================================================== | |||
| // This gets called occasionally by the timer thread (to save using an extra thread | |||
| // for it). | |||
| void MessageManager::inactivityCheckCallback() throw() | |||
| { | |||
| if (instance != 0) | |||
| instance->inactivityCheckCallbackInt(); | |||
| } | |||
| void MessageManager::inactivityCheckCallbackInt() throw() | |||
| { | |||
| const unsigned int now = Time::getApproximateMillisecondCounter(); | |||
| if (isInMessageDispatcher > 0 | |||
| && lastMessageCounter == messageCounter | |||
| && timeBeforeWaitCursor > 0 | |||
| && lastActivityCheckOkTime > 0 | |||
| && ! ModifierKeys::getCurrentModifiersRealtime().isAnyMouseButtonDown()) | |||
| { | |||
| if (now >= lastActivityCheckOkTime + timeBeforeWaitCursor | |||
| && ! needToGetRidOfWaitCursor) | |||
| { | |||
| // been in the same message call too long.. | |||
| MouseCursor::showWaitCursor(); | |||
| needToGetRidOfWaitCursor = true; | |||
| } | |||
| } | |||
| else | |||
| { | |||
| lastActivityCheckOkTime = now; | |||
| lastMessageCounter = messageCounter; | |||
| } | |||
| } | |||
| void MessageManager::delayWaitCursor() throw() | |||
| { | |||
| if (instance != 0) | |||
| { | |||
| instance->messageCounter++; | |||
| if (instance->needToGetRidOfWaitCursor) | |||
| { | |||
| instance->needToGetRidOfWaitCursor = false; | |||
| MouseCursor::hideWaitCursor(); | |||
| } | |||
| } | |||
| } | |||
| void MessageManager::setTimeBeforeShowingWaitCursor (const int millisecs) throw() | |||
| { | |||
| // if this is a bit too small you'll get a lot of unwanted hourglass cursors.. | |||
| jassert (millisecs <= 0 || millisecs > 200); | |||
| timeBeforeWaitCursor = millisecs; | |||
| if (millisecs > 0) | |||
| startTimer (millisecs / 2); // (see timerCallback() for explanation of this) | |||
| else | |||
| stopTimer(); | |||
| } | |||
| void MessageManager::timerCallback() | |||
| { | |||
| // dummy callback - the message manager is just a Timer to ensure that there are always | |||
| // some events coming in - otherwise it'll show the egg-timer/beachball-of-death. | |||
| ++messageCounter; | |||
| } | |||
| int MessageManager::getTimeBeforeShowingWaitCursor() const throw() | |||
| { | |||
| return timeBeforeWaitCursor; | |||
| } | |||
| bool MessageManager::isThisTheMessageThread() const throw() | |||
| { | |||
| return Thread::getCurrentThreadId() == messageThreadId; | |||
| } | |||
| void MessageManager::setCurrentMessageThread (const int threadId) throw() | |||
| { | |||
| messageThreadId = threadId; | |||
| } | |||
| bool MessageManager::currentThreadHasLockedMessageManager() const throw() | |||
| { | |||
| return Thread::getCurrentThreadId() == currentLockingThreadId; | |||
| } | |||
| //============================================================================== | |||
| MessageManagerLock::MessageManagerLock() throw() | |||
| : locked (false) | |||
| { | |||
| if (MessageManager::instance != 0) | |||
| { | |||
| MessageManager::instance->messageDispatchLock.enter(); | |||
| lastLockingThreadId = MessageManager::instance->currentLockingThreadId; | |||
| MessageManager::instance->currentLockingThreadId = Thread::getCurrentThreadId(); | |||
| locked = true; | |||
| } | |||
| } | |||
| MessageManagerLock::MessageManagerLock (Thread* const thread) throw() | |||
| : locked (false) | |||
| { | |||
| jassert (thread != 0); // This will only work if you give it a valid thread! | |||
| if (MessageManager::instance != 0) | |||
| { | |||
| for (;;) | |||
| { | |||
| if (MessageManager::instance->messageDispatchLock.tryEnter()) | |||
| { | |||
| locked = true; | |||
| lastLockingThreadId = MessageManager::instance->currentLockingThreadId; | |||
| MessageManager::instance->currentLockingThreadId = Thread::getCurrentThreadId(); | |||
| break; | |||
| } | |||
| if (thread != 0 && thread->threadShouldExit()) | |||
| break; | |||
| Thread::sleep (1); | |||
| } | |||
| } | |||
| } | |||
| MessageManagerLock::~MessageManagerLock() throw() | |||
| { | |||
| if (locked && MessageManager::instance != 0) | |||
| { | |||
| MessageManager::instance->currentLockingThreadId = lastLockingThreadId; | |||
| MessageManager::instance->messageDispatchLock.exit(); | |||
| } | |||
| } | |||
| END_JUCE_NAMESPACE | |||
| /* | |||
| ============================================================================== | |||
| This file is part of the JUCE library - "Jules' Utility Class Extensions" | |||
| Copyright 2004-7 by Raw Material Software ltd. | |||
| ------------------------------------------------------------------------------ | |||
| JUCE can be redistributed and/or modified 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. | |||
| JUCE 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 JUCE; if not, visit www.gnu.org/licenses or write to the | |||
| Free Software Foundation, Inc., 59 Temple Place, Suite 330, | |||
| Boston, MA 02111-1307 USA | |||
| ------------------------------------------------------------------------------ | |||
| If you'd like to release a closed-source product which uses JUCE, commercial | |||
| licenses are also available: visit www.rawmaterialsoftware.com/juce for | |||
| more information. | |||
| ============================================================================== | |||
| */ | |||
| #include "../../juce_core/basics/juce_StandardHeader.h" | |||
| BEGIN_JUCE_NAMESPACE | |||
| #include "juce_MessageManager.h" | |||
| #include "juce_ActionListenerList.h" | |||
| #include "../application/juce_Application.h" | |||
| #include "../gui/components/juce_Component.h" | |||
| #include "../../juce_core/threads/juce_Thread.h" | |||
| #include "../../juce_core/basics/juce_Time.h" | |||
| //============================================================================== | |||
| // platform-specific functions.. | |||
| bool juce_dispatchNextMessageOnSystemQueue (bool returnIfNoPendingMessages); | |||
| bool juce_postMessageToSystemQueue (void* message); | |||
| //============================================================================== | |||
| MessageManager* MessageManager::instance = 0; | |||
| static const int quitMessageId = 0xfffff321; | |||
| MessageManager::MessageManager() throw() | |||
| : broadcastListeners (0), | |||
| quitMessagePosted (false), | |||
| quitMessageReceived (false), | |||
| useMaximumForceWhenQuitting (true), | |||
| messageCounter (0), | |||
| lastMessageCounter (-1), | |||
| isInMessageDispatcher (0), | |||
| needToGetRidOfWaitCursor (false), | |||
| timeBeforeWaitCursor (0), | |||
| lastActivityCheckOkTime (0) | |||
| { | |||
| currentLockingThreadId = messageThreadId = Thread::getCurrentThreadId(); | |||
| } | |||
| MessageManager::~MessageManager() throw() | |||
| { | |||
| jassert (instance == this); | |||
| instance = 0; | |||
| deleteAndZero (broadcastListeners); | |||
| doPlatformSpecificShutdown(); | |||
| } | |||
| MessageManager* MessageManager::getInstance() throw() | |||
| { | |||
| if (instance == 0) | |||
| { | |||
| instance = new MessageManager(); | |||
| doPlatformSpecificInitialisation(); | |||
| instance->setTimeBeforeShowingWaitCursor (500); | |||
| } | |||
| return instance; | |||
| } | |||
| void MessageManager::postMessageToQueue (Message* const message) | |||
| { | |||
| if (quitMessagePosted || ! juce_postMessageToSystemQueue (message)) | |||
| delete message; | |||
| } | |||
| //============================================================================== | |||
| // not for public use.. | |||
| void MessageManager::deliverMessage (void* message) | |||
| { | |||
| const MessageManagerLock lock; | |||
| Message* const m = (Message*) message; | |||
| MessageListener* const recipient = m->messageRecipient; | |||
| if (messageListeners.contains (recipient)) | |||
| { | |||
| JUCE_TRY | |||
| { | |||
| recipient->handleMessage (*m); | |||
| } | |||
| JUCE_CATCH_EXCEPTION | |||
| if (needToGetRidOfWaitCursor) | |||
| { | |||
| needToGetRidOfWaitCursor = false; | |||
| MouseCursor::hideWaitCursor(); | |||
| } | |||
| ++messageCounter; | |||
| } | |||
| else if (recipient == 0 && m->intParameter1 == quitMessageId) | |||
| { | |||
| quitMessageReceived = true; | |||
| useMaximumForceWhenQuitting = (m->intParameter2 != 0); | |||
| } | |||
| delete m; | |||
| } | |||
| //============================================================================== | |||
| bool MessageManager::dispatchNextMessage (const bool returnImmediatelyIfNoMessages, | |||
| bool* const wasAMessageDispatched) | |||
| { | |||
| if (quitMessageReceived) | |||
| { | |||
| if (wasAMessageDispatched != 0) | |||
| *wasAMessageDispatched = false; | |||
| return false; | |||
| } | |||
| ++isInMessageDispatcher; | |||
| bool result = false; | |||
| JUCE_TRY | |||
| { | |||
| result = juce_dispatchNextMessageOnSystemQueue (returnImmediatelyIfNoMessages); | |||
| if (wasAMessageDispatched != 0) | |||
| *wasAMessageDispatched = result; | |||
| if (instance == 0) | |||
| return false; | |||
| } | |||
| JUCE_CATCH_EXCEPTION | |||
| --isInMessageDispatcher; | |||
| ++messageCounter; | |||
| return result || ! returnImmediatelyIfNoMessages; | |||
| } | |||
| void MessageManager::dispatchPendingMessages (int maxNumberOfMessagesToDispatch) | |||
| { | |||
| jassert (isThisTheMessageThread()); // must only be called by the message thread | |||
| while (--maxNumberOfMessagesToDispatch >= 0 && ! quitMessageReceived) | |||
| { | |||
| ++isInMessageDispatcher; | |||
| bool carryOn = false; | |||
| JUCE_TRY | |||
| { | |||
| carryOn = juce_dispatchNextMessageOnSystemQueue (true); | |||
| } | |||
| JUCE_CATCH_EXCEPTION | |||
| --isInMessageDispatcher; | |||
| ++messageCounter; | |||
| if (! carryOn) | |||
| break; | |||
| } | |||
| } | |||
| bool MessageManager::runDispatchLoop() | |||
| { | |||
| jassert (isThisTheMessageThread()); // must only be called by the message thread | |||
| while (dispatchNextMessage()) | |||
| { | |||
| } | |||
| return useMaximumForceWhenQuitting; | |||
| } | |||
| //============================================================================== | |||
| void MessageManager::postQuitMessage (const bool useMaximumForce) | |||
| { | |||
| Message* const m = new Message (quitMessageId, (useMaximumForce) ? 1 : 0, 0, 0); | |||
| m->messageRecipient = 0; | |||
| postMessageToQueue (m); | |||
| quitMessagePosted = true; | |||
| } | |||
| bool MessageManager::hasQuitMessageBeenPosted() const throw() | |||
| { | |||
| return quitMessagePosted; | |||
| } | |||
| //============================================================================== | |||
| void MessageManager::deliverBroadcastMessage (const String& value) | |||
| { | |||
| if (broadcastListeners != 0) | |||
| broadcastListeners->sendActionMessage (value); | |||
| } | |||
| void MessageManager::registerBroadcastListener (ActionListener* const listener) throw() | |||
| { | |||
| if (broadcastListeners == 0) | |||
| broadcastListeners = new ActionListenerList(); | |||
| broadcastListeners->addActionListener (listener); | |||
| } | |||
| void MessageManager::deregisterBroadcastListener (ActionListener* const listener) throw() | |||
| { | |||
| if (broadcastListeners != 0) | |||
| broadcastListeners->removeActionListener (listener); | |||
| } | |||
| //============================================================================== | |||
| // This gets called occasionally by the timer thread (to save using an extra thread | |||
| // for it). | |||
| void MessageManager::inactivityCheckCallback() throw() | |||
| { | |||
| if (instance != 0) | |||
| instance->inactivityCheckCallbackInt(); | |||
| } | |||
| void MessageManager::inactivityCheckCallbackInt() throw() | |||
| { | |||
| const unsigned int now = Time::getApproximateMillisecondCounter(); | |||
| if (isInMessageDispatcher > 0 | |||
| && lastMessageCounter == messageCounter | |||
| && timeBeforeWaitCursor > 0 | |||
| && lastActivityCheckOkTime > 0 | |||
| && ! ModifierKeys::getCurrentModifiersRealtime().isAnyMouseButtonDown()) | |||
| { | |||
| if (now >= lastActivityCheckOkTime + timeBeforeWaitCursor | |||
| && ! needToGetRidOfWaitCursor) | |||
| { | |||
| // been in the same message call too long.. | |||
| MouseCursor::showWaitCursor(); | |||
| needToGetRidOfWaitCursor = true; | |||
| } | |||
| } | |||
| else | |||
| { | |||
| lastActivityCheckOkTime = now; | |||
| lastMessageCounter = messageCounter; | |||
| } | |||
| } | |||
| void MessageManager::delayWaitCursor() throw() | |||
| { | |||
| if (instance != 0) | |||
| { | |||
| instance->messageCounter++; | |||
| if (instance->needToGetRidOfWaitCursor) | |||
| { | |||
| instance->needToGetRidOfWaitCursor = false; | |||
| MouseCursor::hideWaitCursor(); | |||
| } | |||
| } | |||
| } | |||
| void MessageManager::setTimeBeforeShowingWaitCursor (const int millisecs) throw() | |||
| { | |||
| // if this is a bit too small you'll get a lot of unwanted hourglass cursors.. | |||
| jassert (millisecs <= 0 || millisecs > 200); | |||
| timeBeforeWaitCursor = millisecs; | |||
| if (millisecs > 0) | |||
| startTimer (millisecs / 2); // (see timerCallback() for explanation of this) | |||
| else | |||
| stopTimer(); | |||
| } | |||
| void MessageManager::timerCallback() | |||
| { | |||
| // dummy callback - the message manager is just a Timer to ensure that there are always | |||
| // some events coming in - otherwise it'll show the egg-timer/beachball-of-death. | |||
| ++messageCounter; | |||
| } | |||
| int MessageManager::getTimeBeforeShowingWaitCursor() const throw() | |||
| { | |||
| return timeBeforeWaitCursor; | |||
| } | |||
| bool MessageManager::isThisTheMessageThread() const throw() | |||
| { | |||
| return Thread::getCurrentThreadId() == messageThreadId; | |||
| } | |||
| void MessageManager::setCurrentMessageThread (const int threadId) throw() | |||
| { | |||
| messageThreadId = threadId; | |||
| } | |||
| bool MessageManager::currentThreadHasLockedMessageManager() const throw() | |||
| { | |||
| return Thread::getCurrentThreadId() == currentLockingThreadId; | |||
| } | |||
| //============================================================================== | |||
| MessageManagerLock::MessageManagerLock() throw() | |||
| : locked (false) | |||
| { | |||
| if (MessageManager::instance != 0) | |||
| { | |||
| MessageManager::instance->messageDispatchLock.enter(); | |||
| lastLockingThreadId = MessageManager::instance->currentLockingThreadId; | |||
| MessageManager::instance->currentLockingThreadId = Thread::getCurrentThreadId(); | |||
| locked = true; | |||
| } | |||
| } | |||
| MessageManagerLock::MessageManagerLock (Thread* const thread) throw() | |||
| : locked (false) | |||
| { | |||
| jassert (thread != 0); // This will only work if you give it a valid thread! | |||
| if (MessageManager::instance != 0) | |||
| { | |||
| for (;;) | |||
| { | |||
| if (MessageManager::instance->messageDispatchLock.tryEnter()) | |||
| { | |||
| locked = true; | |||
| lastLockingThreadId = MessageManager::instance->currentLockingThreadId; | |||
| MessageManager::instance->currentLockingThreadId = Thread::getCurrentThreadId(); | |||
| break; | |||
| } | |||
| if (thread != 0 && thread->threadShouldExit()) | |||
| break; | |||
| Thread::sleep (1); | |||
| } | |||
| } | |||
| } | |||
| MessageManagerLock::~MessageManagerLock() throw() | |||
| { | |||
| if (locked && MessageManager::instance != 0) | |||
| { | |||
| MessageManager::instance->currentLockingThreadId = lastLockingThreadId; | |||
| MessageManager::instance->messageDispatchLock.exit(); | |||
| } | |||
| } | |||
| END_JUCE_NAMESPACE | |||
| @@ -1,397 +1,397 @@ | |||
| /* | |||
| ============================================================================== | |||
| This file is part of the JUCE library - "Jules' Utility Class Extensions" | |||
| Copyright 2004-7 by Raw Material Software ltd. | |||
| ------------------------------------------------------------------------------ | |||
| JUCE can be redistributed and/or modified 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. | |||
| JUCE 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 JUCE; if not, visit www.gnu.org/licenses or write to the | |||
| Free Software Foundation, Inc., 59 Temple Place, Suite 330, | |||
| Boston, MA 02111-1307 USA | |||
| ------------------------------------------------------------------------------ | |||
| If you'd like to release a closed-source product which uses JUCE, commercial | |||
| licenses are also available: visit www.rawmaterialsoftware.com/juce for | |||
| more information. | |||
| ============================================================================== | |||
| */ | |||
| #include "../../juce_core/basics/juce_StandardHeader.h" | |||
| BEGIN_JUCE_NAMESPACE | |||
| #include "juce_Timer.h" | |||
| #include "juce_MessageManager.h" | |||
| #include "juce_AsyncUpdater.h" | |||
| #include "../application/juce_Application.h" | |||
| #include "../application/juce_DeletedAtShutdown.h" | |||
| #include "../../juce_core/basics/juce_Time.h" | |||
| #include "../../juce_core/threads/juce_Thread.h" | |||
| #include "../../juce_core/threads/juce_ScopedLock.h" | |||
| #include "../../juce_core/containers/juce_VoidArray.h" | |||
| //============================================================================== | |||
| class InternalTimerThread : private Thread, | |||
| private MessageListener, | |||
| private DeletedAtShutdown, | |||
| private AsyncUpdater | |||
| { | |||
| private: | |||
| friend class Timer; | |||
| static InternalTimerThread* instance; | |||
| static CriticalSection lock; | |||
| Timer* volatile firstTimer; | |||
| bool volatile callbackNeeded; | |||
| InternalTimerThread (const InternalTimerThread&); | |||
| const InternalTimerThread& operator= (const InternalTimerThread&); | |||
| void addTimer (Timer* const t) throw() | |||
| { | |||
| #ifdef JUCE_DEBUG | |||
| Timer* tt = firstTimer; | |||
| while (tt != 0) | |||
| { | |||
| // trying to add a timer that's already here - shouldn't get to this point, | |||
| // so if you get this assertion, let me know! | |||
| jassert (tt != t); | |||
| tt = tt->next; | |||
| } | |||
| jassert (t->previous == 0 && t->next == 0); | |||
| #endif | |||
| Timer* i = firstTimer; | |||
| if (i == 0 || i->countdownMs > t->countdownMs) | |||
| { | |||
| t->next = firstTimer; | |||
| firstTimer = t; | |||
| } | |||
| else | |||
| { | |||
| while (i->next != 0 && i->next->countdownMs <= t->countdownMs) | |||
| i = i->next; | |||
| jassert (i != 0); | |||
| t->next = i->next; | |||
| t->previous = i; | |||
| i->next = t; | |||
| } | |||
| if (t->next != 0) | |||
| t->next->previous = t; | |||
| jassert ((t->next == 0 || t->next->countdownMs >= t->countdownMs) | |||
| && (t->previous == 0 || t->previous->countdownMs <= t->countdownMs)); | |||
| notify(); | |||
| } | |||
| void removeTimer (Timer* const t) throw() | |||
| { | |||
| #ifdef JUCE_DEBUG | |||
| Timer* tt = firstTimer; | |||
| bool found = false; | |||
| while (tt != 0) | |||
| { | |||
| if (tt == t) | |||
| { | |||
| found = true; | |||
| break; | |||
| } | |||
| tt = tt->next; | |||
| } | |||
| // trying to remove a timer that's not here - shouldn't get to this point, | |||
| // so if you get this assertion, let me know! | |||
| jassert (found); | |||
| #endif | |||
| if (t->previous != 0) | |||
| { | |||
| jassert (firstTimer != t); | |||
| t->previous->next = t->next; | |||
| } | |||
| else | |||
| { | |||
| jassert (firstTimer == t); | |||
| firstTimer = t->next; | |||
| } | |||
| if (t->next != 0) | |||
| t->next->previous = t->previous; | |||
| t->next = 0; | |||
| t->previous = 0; | |||
| } | |||
| void decrementAllCounters (const int numMillisecs) const | |||
| { | |||
| Timer* t = firstTimer; | |||
| while (t != 0) | |||
| { | |||
| t->countdownMs -= numMillisecs; | |||
| t = t->next; | |||
| } | |||
| } | |||
| void handleAsyncUpdate() | |||
| { | |||
| startThread (7); | |||
| } | |||
| public: | |||
| InternalTimerThread() | |||
| : Thread ("Juce Timer"), | |||
| firstTimer (0), | |||
| callbackNeeded (false) | |||
| { | |||
| triggerAsyncUpdate(); | |||
| } | |||
| ~InternalTimerThread() throw() | |||
| { | |||
| stopThread (4000); | |||
| jassert (instance == this || instance == 0); | |||
| if (instance == this) | |||
| instance = 0; | |||
| } | |||
| void run() | |||
| { | |||
| uint32 lastTime = Time::getMillisecondCounter(); | |||
| uint32 lastMessageManagerCallback = lastTime; | |||
| while (! threadShouldExit()) | |||
| { | |||
| uint32 now = Time::getMillisecondCounter(); | |||
| if (now <= lastTime) | |||
| { | |||
| wait (2); | |||
| continue; | |||
| } | |||
| const int elapsed = now - lastTime; | |||
| lastTime = now; | |||
| lock.enter(); | |||
| decrementAllCounters (elapsed); | |||
| const int timeUntilFirstTimer = (firstTimer != 0) ? firstTimer->countdownMs | |||
| : 1000; | |||
| lock.exit(); | |||
| if (timeUntilFirstTimer <= 0) | |||
| { | |||
| callbackNeeded = true; | |||
| postMessage (new Message()); | |||
| // sometimes, our message could get discarded by the OS (particularly when running as an RTAS when the app has a modal loop), | |||
| // so this is how long to wait before assuming the message has been lost and trying again. | |||
| const uint32 messageDeliveryTimeout = now + 2000; | |||
| while (callbackNeeded) | |||
| { | |||
| wait (4); | |||
| if (threadShouldExit()) | |||
| return; | |||
| now = Time::getMillisecondCounter(); | |||
| if (now > lastMessageManagerCallback + 200) | |||
| { | |||
| lastMessageManagerCallback = now; | |||
| MessageManager::inactivityCheckCallback(); | |||
| } | |||
| if (now > messageDeliveryTimeout) | |||
| break; | |||
| } | |||
| } | |||
| else | |||
| { | |||
| // don't wait for too long because running this loop also helps keep the | |||
| // Time::getApproximateMillisecondTimer value stay up-to-date | |||
| wait (jlimit (1, 50, timeUntilFirstTimer)); | |||
| } | |||
| if (now > lastMessageManagerCallback + 200) | |||
| { | |||
| lastMessageManagerCallback = now; | |||
| MessageManager::inactivityCheckCallback(); | |||
| } | |||
| } | |||
| } | |||
| void handleMessage (const Message&) | |||
| { | |||
| const ScopedLock sl (lock); | |||
| while (firstTimer != 0 && firstTimer->countdownMs <= 0) | |||
| { | |||
| Timer* const t = firstTimer; | |||
| t->countdownMs = t->periodMs; | |||
| removeTimer (t); | |||
| addTimer (t); | |||
| const ScopedUnlock ul (lock); | |||
| callbackNeeded = false; | |||
| JUCE_TRY | |||
| { | |||
| t->timerCallback(); | |||
| } | |||
| JUCE_CATCH_EXCEPTION | |||
| } | |||
| callbackNeeded = false; | |||
| } | |||
| static void callAnyTimersSynchronously() | |||
| { | |||
| if (InternalTimerThread::instance != 0) | |||
| { | |||
| const Message m; | |||
| InternalTimerThread::instance->handleMessage (m); | |||
| } | |||
| } | |||
| static inline void add (Timer* const tim) throw() | |||
| { | |||
| if (instance == 0) | |||
| instance = new InternalTimerThread(); | |||
| instance->addTimer (tim); | |||
| } | |||
| static inline void remove (Timer* const tim) throw() | |||
| { | |||
| if (instance != 0) | |||
| instance->removeTimer (tim); | |||
| } | |||
| static inline void resetCounter (Timer* const tim, | |||
| const int newCounter) throw() | |||
| { | |||
| if (instance != 0) | |||
| { | |||
| tim->countdownMs = newCounter; | |||
| tim->periodMs = newCounter; | |||
| if ((tim->next != 0 && tim->next->countdownMs < tim->countdownMs) | |||
| || (tim->previous != 0 && tim->previous->countdownMs > tim->countdownMs)) | |||
| { | |||
| instance->removeTimer (tim); | |||
| instance->addTimer (tim); | |||
| } | |||
| } | |||
| } | |||
| }; | |||
| InternalTimerThread* InternalTimerThread::instance = 0; | |||
| CriticalSection InternalTimerThread::lock; | |||
| void juce_callAnyTimersSynchronously() | |||
| { | |||
| InternalTimerThread::callAnyTimersSynchronously(); | |||
| } | |||
| //============================================================================== | |||
| #ifdef JUCE_DEBUG | |||
| static SortedSet <Timer*> activeTimers; | |||
| #endif | |||
| Timer::Timer() throw() | |||
| : countdownMs (0), | |||
| periodMs (0), | |||
| previous (0), | |||
| next (0) | |||
| { | |||
| #ifdef JUCE_DEBUG | |||
| activeTimers.add (this); | |||
| #endif | |||
| } | |||
| Timer::Timer (const Timer&) throw() | |||
| : countdownMs (0), | |||
| periodMs (0), | |||
| previous (0), | |||
| next (0) | |||
| { | |||
| #ifdef JUCE_DEBUG | |||
| activeTimers.add (this); | |||
| #endif | |||
| } | |||
| Timer::~Timer() | |||
| { | |||
| stopTimer(); | |||
| #ifdef JUCE_DEBUG | |||
| activeTimers.removeValue (this); | |||
| #endif | |||
| } | |||
| void Timer::startTimer (const int interval) throw() | |||
| { | |||
| const ScopedLock sl (InternalTimerThread::lock); | |||
| #ifdef JUCE_DEBUG | |||
| // this isn't a valid object! Your timer might be a dangling pointer or something.. | |||
| jassert (activeTimers.contains (this)); | |||
| #endif | |||
| if (periodMs == 0) | |||
| { | |||
| countdownMs = interval; | |||
| periodMs = jmax (1, interval); | |||
| InternalTimerThread::add (this); | |||
| } | |||
| else | |||
| { | |||
| InternalTimerThread::resetCounter (this, interval); | |||
| } | |||
| } | |||
| void Timer::stopTimer() throw() | |||
| { | |||
| const ScopedLock sl (InternalTimerThread::lock); | |||
| #ifdef JUCE_DEBUG | |||
| // this isn't a valid object! Your timer might be a dangling pointer or something.. | |||
| jassert (activeTimers.contains (this)); | |||
| #endif | |||
| if (periodMs > 0) | |||
| { | |||
| InternalTimerThread::remove (this); | |||
| periodMs = 0; | |||
| } | |||
| } | |||
| END_JUCE_NAMESPACE | |||
| /* | |||
| ============================================================================== | |||
| This file is part of the JUCE library - "Jules' Utility Class Extensions" | |||
| Copyright 2004-7 by Raw Material Software ltd. | |||
| ------------------------------------------------------------------------------ | |||
| JUCE can be redistributed and/or modified 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. | |||
| JUCE 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 JUCE; if not, visit www.gnu.org/licenses or write to the | |||
| Free Software Foundation, Inc., 59 Temple Place, Suite 330, | |||
| Boston, MA 02111-1307 USA | |||
| ------------------------------------------------------------------------------ | |||
| If you'd like to release a closed-source product which uses JUCE, commercial | |||
| licenses are also available: visit www.rawmaterialsoftware.com/juce for | |||
| more information. | |||
| ============================================================================== | |||
| */ | |||
| #include "../../juce_core/basics/juce_StandardHeader.h" | |||
| BEGIN_JUCE_NAMESPACE | |||
| #include "juce_Timer.h" | |||
| #include "juce_MessageManager.h" | |||
| #include "juce_AsyncUpdater.h" | |||
| #include "../application/juce_Application.h" | |||
| #include "../application/juce_DeletedAtShutdown.h" | |||
| #include "../../juce_core/basics/juce_Time.h" | |||
| #include "../../juce_core/threads/juce_Thread.h" | |||
| #include "../../juce_core/threads/juce_ScopedLock.h" | |||
| #include "../../juce_core/containers/juce_VoidArray.h" | |||
| //============================================================================== | |||
| class InternalTimerThread : private Thread, | |||
| private MessageListener, | |||
| private DeletedAtShutdown, | |||
| private AsyncUpdater | |||
| { | |||
| private: | |||
| friend class Timer; | |||
| static InternalTimerThread* instance; | |||
| static CriticalSection lock; | |||
| Timer* volatile firstTimer; | |||
| bool volatile callbackNeeded; | |||
| InternalTimerThread (const InternalTimerThread&); | |||
| const InternalTimerThread& operator= (const InternalTimerThread&); | |||
| void addTimer (Timer* const t) throw() | |||
| { | |||
| #ifdef JUCE_DEBUG | |||
| Timer* tt = firstTimer; | |||
| while (tt != 0) | |||
| { | |||
| // trying to add a timer that's already here - shouldn't get to this point, | |||
| // so if you get this assertion, let me know! | |||
| jassert (tt != t); | |||
| tt = tt->next; | |||
| } | |||
| jassert (t->previous == 0 && t->next == 0); | |||
| #endif | |||
| Timer* i = firstTimer; | |||
| if (i == 0 || i->countdownMs > t->countdownMs) | |||
| { | |||
| t->next = firstTimer; | |||
| firstTimer = t; | |||
| } | |||
| else | |||
| { | |||
| while (i->next != 0 && i->next->countdownMs <= t->countdownMs) | |||
| i = i->next; | |||
| jassert (i != 0); | |||
| t->next = i->next; | |||
| t->previous = i; | |||
| i->next = t; | |||
| } | |||
| if (t->next != 0) | |||
| t->next->previous = t; | |||
| jassert ((t->next == 0 || t->next->countdownMs >= t->countdownMs) | |||
| && (t->previous == 0 || t->previous->countdownMs <= t->countdownMs)); | |||
| notify(); | |||
| } | |||
| void removeTimer (Timer* const t) throw() | |||
| { | |||
| #ifdef JUCE_DEBUG | |||
| Timer* tt = firstTimer; | |||
| bool found = false; | |||
| while (tt != 0) | |||
| { | |||
| if (tt == t) | |||
| { | |||
| found = true; | |||
| break; | |||
| } | |||
| tt = tt->next; | |||
| } | |||
| // trying to remove a timer that's not here - shouldn't get to this point, | |||
| // so if you get this assertion, let me know! | |||
| jassert (found); | |||
| #endif | |||
| if (t->previous != 0) | |||
| { | |||
| jassert (firstTimer != t); | |||
| t->previous->next = t->next; | |||
| } | |||
| else | |||
| { | |||
| jassert (firstTimer == t); | |||
| firstTimer = t->next; | |||
| } | |||
| if (t->next != 0) | |||
| t->next->previous = t->previous; | |||
| t->next = 0; | |||
| t->previous = 0; | |||
| } | |||
| void decrementAllCounters (const int numMillisecs) const | |||
| { | |||
| Timer* t = firstTimer; | |||
| while (t != 0) | |||
| { | |||
| t->countdownMs -= numMillisecs; | |||
| t = t->next; | |||
| } | |||
| } | |||
| void handleAsyncUpdate() | |||
| { | |||
| startThread (7); | |||
| } | |||
| public: | |||
| InternalTimerThread() | |||
| : Thread ("Juce Timer"), | |||
| firstTimer (0), | |||
| callbackNeeded (false) | |||
| { | |||
| triggerAsyncUpdate(); | |||
| } | |||
| ~InternalTimerThread() throw() | |||
| { | |||
| stopThread (4000); | |||
| jassert (instance == this || instance == 0); | |||
| if (instance == this) | |||
| instance = 0; | |||
| } | |||
| void run() | |||
| { | |||
| uint32 lastTime = Time::getMillisecondCounter(); | |||
| uint32 lastMessageManagerCallback = lastTime; | |||
| while (! threadShouldExit()) | |||
| { | |||
| uint32 now = Time::getMillisecondCounter(); | |||
| if (now <= lastTime) | |||
| { | |||
| wait (2); | |||
| continue; | |||
| } | |||
| const int elapsed = now - lastTime; | |||
| lastTime = now; | |||
| lock.enter(); | |||
| decrementAllCounters (elapsed); | |||
| const int timeUntilFirstTimer = (firstTimer != 0) ? firstTimer->countdownMs | |||
| : 1000; | |||
| lock.exit(); | |||
| if (timeUntilFirstTimer <= 0) | |||
| { | |||
| callbackNeeded = true; | |||
| postMessage (new Message()); | |||
| // sometimes, our message could get discarded by the OS (particularly when running as an RTAS when the app has a modal loop), | |||
| // so this is how long to wait before assuming the message has been lost and trying again. | |||
| const uint32 messageDeliveryTimeout = now + 2000; | |||
| while (callbackNeeded) | |||
| { | |||
| wait (4); | |||
| if (threadShouldExit()) | |||
| return; | |||
| now = Time::getMillisecondCounter(); | |||
| if (now > lastMessageManagerCallback + 200) | |||
| { | |||
| lastMessageManagerCallback = now; | |||
| MessageManager::inactivityCheckCallback(); | |||
| } | |||
| if (now > messageDeliveryTimeout) | |||
| break; | |||
| } | |||
| } | |||
| else | |||
| { | |||
| // don't wait for too long because running this loop also helps keep the | |||
| // Time::getApproximateMillisecondTimer value stay up-to-date | |||
| wait (jlimit (1, 50, timeUntilFirstTimer)); | |||
| } | |||
| if (now > lastMessageManagerCallback + 200) | |||
| { | |||
| lastMessageManagerCallback = now; | |||
| MessageManager::inactivityCheckCallback(); | |||
| } | |||
| } | |||
| } | |||
| void handleMessage (const Message&) | |||
| { | |||
| const ScopedLock sl (lock); | |||
| while (firstTimer != 0 && firstTimer->countdownMs <= 0) | |||
| { | |||
| Timer* const t = firstTimer; | |||
| t->countdownMs = t->periodMs; | |||
| removeTimer (t); | |||
| addTimer (t); | |||
| const ScopedUnlock ul (lock); | |||
| callbackNeeded = false; | |||
| JUCE_TRY | |||
| { | |||
| t->timerCallback(); | |||
| } | |||
| JUCE_CATCH_EXCEPTION | |||
| } | |||
| callbackNeeded = false; | |||
| } | |||
| static void callAnyTimersSynchronously() | |||
| { | |||
| if (InternalTimerThread::instance != 0) | |||
| { | |||
| const Message m; | |||
| InternalTimerThread::instance->handleMessage (m); | |||
| } | |||
| } | |||
| static inline void add (Timer* const tim) throw() | |||
| { | |||
| if (instance == 0) | |||
| instance = new InternalTimerThread(); | |||
| instance->addTimer (tim); | |||
| } | |||
| static inline void remove (Timer* const tim) throw() | |||
| { | |||
| if (instance != 0) | |||
| instance->removeTimer (tim); | |||
| } | |||
| static inline void resetCounter (Timer* const tim, | |||
| const int newCounter) throw() | |||
| { | |||
| if (instance != 0) | |||
| { | |||
| tim->countdownMs = newCounter; | |||
| tim->periodMs = newCounter; | |||
| if ((tim->next != 0 && tim->next->countdownMs < tim->countdownMs) | |||
| || (tim->previous != 0 && tim->previous->countdownMs > tim->countdownMs)) | |||
| { | |||
| instance->removeTimer (tim); | |||
| instance->addTimer (tim); | |||
| } | |||
| } | |||
| } | |||
| }; | |||
| InternalTimerThread* InternalTimerThread::instance = 0; | |||
| CriticalSection InternalTimerThread::lock; | |||
| void juce_callAnyTimersSynchronously() | |||
| { | |||
| InternalTimerThread::callAnyTimersSynchronously(); | |||
| } | |||
| //============================================================================== | |||
| #ifdef JUCE_DEBUG | |||
| static SortedSet <Timer*> activeTimers; | |||
| #endif | |||
| Timer::Timer() throw() | |||
| : countdownMs (0), | |||
| periodMs (0), | |||
| previous (0), | |||
| next (0) | |||
| { | |||
| #ifdef JUCE_DEBUG | |||
| activeTimers.add (this); | |||
| #endif | |||
| } | |||
| Timer::Timer (const Timer&) throw() | |||
| : countdownMs (0), | |||
| periodMs (0), | |||
| previous (0), | |||
| next (0) | |||
| { | |||
| #ifdef JUCE_DEBUG | |||
| activeTimers.add (this); | |||
| #endif | |||
| } | |||
| Timer::~Timer() | |||
| { | |||
| stopTimer(); | |||
| #ifdef JUCE_DEBUG | |||
| activeTimers.removeValue (this); | |||
| #endif | |||
| } | |||
| void Timer::startTimer (const int interval) throw() | |||
| { | |||
| const ScopedLock sl (InternalTimerThread::lock); | |||
| #ifdef JUCE_DEBUG | |||
| // this isn't a valid object! Your timer might be a dangling pointer or something.. | |||
| jassert (activeTimers.contains (this)); | |||
| #endif | |||
| if (periodMs == 0) | |||
| { | |||
| countdownMs = interval; | |||
| periodMs = jmax (1, interval); | |||
| InternalTimerThread::add (this); | |||
| } | |||
| else | |||
| { | |||
| InternalTimerThread::resetCounter (this, interval); | |||
| } | |||
| } | |||
| void Timer::stopTimer() throw() | |||
| { | |||
| const ScopedLock sl (InternalTimerThread::lock); | |||
| #ifdef JUCE_DEBUG | |||
| // this isn't a valid object! Your timer might be a dangling pointer or something.. | |||
| jassert (activeTimers.contains (this)); | |||
| #endif | |||
| if (periodMs > 0) | |||
| { | |||
| InternalTimerThread::remove (this); | |||
| periodMs = 0; | |||
| } | |||
| } | |||
| END_JUCE_NAMESPACE | |||
| @@ -308,7 +308,7 @@ void LookAndFeel::drawButtonBackground (Graphics& g, | |||
| button.isConnectedOnBottom()); | |||
| } | |||
| void LookAndFeel::drawButtonText (Graphics& g, TextButton& button, | |||
| void LookAndFeel::drawButtonText (Graphics& g, TextButton& button, | |||
| bool /*isMouseOverButton*/, bool /*isButtonDown*/) | |||
| { | |||
| g.setFont (button.getFont()); | |||
| @@ -132,7 +132,7 @@ public: | |||
| bool isButtonDown); | |||
| /** Draws the text for a TextButton. */ | |||
| virtual void drawButtonText (Graphics& g, | |||
| virtual void drawButtonText (Graphics& g, | |||
| TextButton& button, | |||
| bool isMouseOverButton, | |||
| bool isButtonDown); | |||
| @@ -389,7 +389,7 @@ | |||
| #define PNG_LIBPNG_BUILD_RC 3 | |||
| #define PNG_LIBPNG_BUILD_STABLE 4 | |||
| #define PNG_LIBPNG_BUILD_RELEASE_STATUS_MASK 7 | |||
| /* Release-Specific Flags */ | |||
| #define PNG_LIBPNG_BUILD_PATCH 8 /* Can be OR'ed with | |||
| PNG_LIBPNG_BUILD_STABLE only */ | |||
| @@ -424,12 +424,12 @@ | |||
| /* Ref MSDN: Private as priority over Special | |||
| * VS_FF_PRIVATEBUILD File *was not* built using standard release | |||
| * procedures. If this value is given, the StringFileInfo block must | |||
| * contain a PrivateBuild string. | |||
| * contain a PrivateBuild string. | |||
| * | |||
| * VS_FF_SPECIALBUILD File *was* built by the original company using | |||
| * standard release procedures but is a variation of the standard | |||
| * file of the same version number. If this value is given, the | |||
| * StringFileInfo block must contain a SpecialBuild string. | |||
| * StringFileInfo block must contain a SpecialBuild string. | |||
| */ | |||
| #if defined(PNG_USER_PRIVATEBUILD) | |||
| @@ -42,7 +42,7 @@ | |||
| //============================================================================== | |||
| /* | |||
| /* | |||
| * PNG_USER_CONFIG has to be defined on the compiler command line. This | |||
| * includes the resource compiler for Windows DLL configurations. | |||
| */ | |||
| @@ -62,7 +62,7 @@ | |||
| /* | |||
| * Added at libpng-1.2.8 | |||
| * | |||
| * | |||
| * If you create a private DLL you need to define in "pngusr.h" the followings: | |||
| * #define PNG_USER_PRIVATEBUILD <Describes by whom and why this version of | |||
| * the DLL was built> | |||
| @@ -73,8 +73,8 @@ | |||
| * number and must match your private DLL name> | |||
| * e.g. // private DLL "libpng13gx.dll" | |||
| * #define PNG_USER_DLLFNAME_POSTFIX "gx" | |||
| * | |||
| * The following macros are also at your disposal if you want to complete the | |||
| * | |||
| * The following macros are also at your disposal if you want to complete the | |||
| * DLL VERSIONINFO structure. | |||
| * - PNG_USER_VERSIONINFO_COMMENTS | |||
| * - PNG_USER_VERSIONINFO_COMPANYNAME | |||
| @@ -167,9 +167,9 @@ | |||
| * 'Cygwin' defines/defaults: | |||
| * PNG_BUILD_DLL -- (ignored) building the dll | |||
| * (no define) -- (ignored) building an application, linking to the dll | |||
| * PNG_STATIC -- (ignored) building the static lib, or building an | |||
| * PNG_STATIC -- (ignored) building the static lib, or building an | |||
| * application that links to the static lib. | |||
| * ALL_STATIC -- (ignored) building various static libs, or building an | |||
| * ALL_STATIC -- (ignored) building various static libs, or building an | |||
| * application that links to the static libs. | |||
| * Thus, | |||
| * a cygwin user should define either PNG_BUILD_DLL or PNG_STATIC, and | |||
| @@ -182,12 +182,12 @@ | |||
| * PNG_BUILD_DLL | |||
| * PNG_STATIC | |||
| * (nothing) == PNG_USE_DLL | |||
| * | |||
| * | |||
| * CYGWIN (2002-01-20): The preceding is now obsolete. With the advent | |||
| * of auto-import in binutils, we no longer need to worry about | |||
| * of auto-import in binutils, we no longer need to worry about | |||
| * __declspec(dllexport) / __declspec(dllimport) and friends. Therefore, | |||
| * we don't need to worry about PNG_STATIC or ALL_STATIC when it comes | |||
| * to __declspec() stuff. However, we DO need to worry about | |||
| * to __declspec() stuff. However, we DO need to worry about | |||
| * PNG_BUILD_DLL and PNG_STATIC because those change some defaults | |||
| * such as CONSOLE_IO and whether GLOBAL_ARRAYS are allowed. | |||
| */ | |||
| @@ -231,8 +231,8 @@ | |||
| # if !defined(PNG_DLL) | |||
| # define PNG_DLL | |||
| # endif | |||
| # endif | |||
| # endif | |||
| # endif | |||
| # endif | |||
| # endif | |||
| #endif | |||
| @@ -749,7 +749,7 @@ | |||
| # define PNG_EASY_ACCESS_SUPPORTED | |||
| #endif | |||
| /* PNG_ASSEMBLER_CODE was enabled by default in version 1.2.0 | |||
| /* PNG_ASSEMBLER_CODE was enabled by default in version 1.2.0 | |||
| * and removed from version 1.2.20. The following will be removed | |||
| * from libpng-1.4.0 | |||
| */ | |||
| @@ -1324,7 +1324,7 @@ typedef z_stream FAR * png_zstreamp; | |||
| # define PNGAPI __cdecl | |||
| # undef PNG_IMPEXP | |||
| # define PNG_IMPEXP | |||
| #endif | |||
| #endif | |||
| /* If you define PNGAPI, e.g., with compiler option "-DPNGAPI=__stdcall", | |||
| * you may get warnings regarding the linkage of png_zalloc and png_zfree. | |||
| @@ -1,341 +1,341 @@ | |||
| /* pngerror.c - stub functions for i/o and memory allocation | |||
| * | |||
| * Last changed in libpng 1.2.20 October 4, 2007 | |||
| * For conditions of distribution and use, see copyright notice in png.h | |||
| * Copyright (c) 1998-2007 Glenn Randers-Pehrson | |||
| * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) | |||
| * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) | |||
| * | |||
| * This file provides a location for all error handling. Users who | |||
| * need special error handling are expected to write replacement functions | |||
| * and use png_set_error_fn() to use those functions. See the instructions | |||
| * at each function. | |||
| */ | |||
| #define PNG_INTERNAL | |||
| #include "png.h" | |||
| #if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) | |||
| static void /* PRIVATE */ | |||
| png_default_error PNGARG((png_structp png_ptr, | |||
| png_const_charp error_message)); | |||
| #ifndef PNG_NO_WARNINGS | |||
| static void /* PRIVATE */ | |||
| png_default_warning PNGARG((png_structp png_ptr, | |||
| png_const_charp warning_message)); | |||
| #endif /* PNG_NO_WARNINGS */ | |||
| /* This function is called whenever there is a fatal error. This function | |||
| * should not be changed. If there is a need to handle errors differently, | |||
| * you should supply a replacement error function and use png_set_error_fn() | |||
| * to replace the error function at run-time. | |||
| */ | |||
| #ifndef PNG_NO_ERROR_TEXT | |||
| void PNGAPI | |||
| png_error(png_structp png_ptr, png_const_charp error_message) | |||
| { | |||
| #ifdef PNG_ERROR_NUMBERS_SUPPORTED | |||
| char msg[16]; | |||
| if (png_ptr != NULL) | |||
| { | |||
| if (png_ptr->flags& | |||
| (PNG_FLAG_STRIP_ERROR_NUMBERS|PNG_FLAG_STRIP_ERROR_TEXT)) | |||
| { | |||
| if (*error_message == '#') | |||
| { | |||
| int offset; | |||
| for (offset=1; offset<15; offset++) | |||
| if (*(error_message+offset) == ' ') | |||
| break; | |||
| if (png_ptr->flags&PNG_FLAG_STRIP_ERROR_TEXT) | |||
| { | |||
| int i; | |||
| for (i=0; i<offset-1; i++) | |||
| msg[i]=error_message[i+1]; | |||
| msg[i]='\0'; | |||
| error_message=msg; | |||
| } | |||
| else | |||
| error_message+=offset; | |||
| } | |||
| else | |||
| { | |||
| if (png_ptr->flags&PNG_FLAG_STRIP_ERROR_TEXT) | |||
| { | |||
| msg[0]='0'; | |||
| msg[1]='\0'; | |||
| error_message=msg; | |||
| } | |||
| } | |||
| } | |||
| } | |||
| #endif | |||
| if (png_ptr != NULL && png_ptr->error_fn != NULL) | |||
| (*(png_ptr->error_fn))(png_ptr, error_message); | |||
| /* If the custom handler doesn't exist, or if it returns, | |||
| use the default handler, which will not return. */ | |||
| png_default_error(png_ptr, error_message); | |||
| } | |||
| #else | |||
| void PNGAPI | |||
| png_err(png_structp png_ptr) | |||
| { | |||
| if (png_ptr != NULL && png_ptr->error_fn != NULL) | |||
| (*(png_ptr->error_fn))(png_ptr, '\0'); | |||
| /* If the custom handler doesn't exist, or if it returns, | |||
| use the default handler, which will not return. */ | |||
| png_default_error(png_ptr, '\0'); | |||
| } | |||
| #endif /* PNG_NO_ERROR_TEXT */ | |||
| #ifndef PNG_NO_WARNINGS | |||
| /* This function is called whenever there is a non-fatal error. This function | |||
| * should not be changed. If there is a need to handle warnings differently, | |||
| * you should supply a replacement warning function and use | |||
| * png_set_error_fn() to replace the warning function at run-time. | |||
| */ | |||
| void PNGAPI | |||
| png_warning(png_structp png_ptr, png_const_charp warning_message) | |||
| { | |||
| int offset = 0; | |||
| if (png_ptr != NULL) | |||
| { | |||
| #ifdef PNG_ERROR_NUMBERS_SUPPORTED | |||
| if (png_ptr->flags& | |||
| (PNG_FLAG_STRIP_ERROR_NUMBERS|PNG_FLAG_STRIP_ERROR_TEXT)) | |||
| #endif | |||
| { | |||
| if (*warning_message == '#') | |||
| { | |||
| for (offset=1; offset<15; offset++) | |||
| if (*(warning_message+offset) == ' ') | |||
| break; | |||
| } | |||
| } | |||
| if (png_ptr != NULL && png_ptr->warning_fn != NULL) | |||
| (*(png_ptr->warning_fn))(png_ptr, warning_message+offset); | |||
| } | |||
| else | |||
| png_default_warning(png_ptr, warning_message+offset); | |||
| } | |||
| #endif /* PNG_NO_WARNINGS */ | |||
| /* These utilities are used internally to build an error message that relates | |||
| * to the current chunk. The chunk name comes from png_ptr->chunk_name, | |||
| * this is used to prefix the message. The message is limited in length | |||
| * to 63 bytes, the name characters are output as hex digits wrapped in [] | |||
| * if the character is invalid. | |||
| */ | |||
| #define isnonalpha(c) ((c) < 65 || (c) > 122 || ((c) > 90 && (c) < 97)) | |||
| static PNG_CONST char png_digit[16] = { | |||
| '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', | |||
| 'A', 'B', 'C', 'D', 'E', 'F' | |||
| }; | |||
| #if !defined(PNG_NO_WARNINGS) || !defined(PNG_NO_ERROR_TEXT) | |||
| static void /* PRIVATE */ | |||
| png_format_buffer(png_structp png_ptr, png_charp buffer, png_const_charp | |||
| error_message) | |||
| { | |||
| int iout = 0, iin = 0; | |||
| while (iin < 4) | |||
| { | |||
| int c = png_ptr->chunk_name[iin++]; | |||
| if (isnonalpha(c)) | |||
| { | |||
| buffer[iout++] = '['; | |||
| buffer[iout++] = png_digit[(c & 0xf0) >> 4]; | |||
| buffer[iout++] = png_digit[c & 0x0f]; | |||
| buffer[iout++] = ']'; | |||
| } | |||
| else | |||
| { | |||
| buffer[iout++] = (png_byte)c; | |||
| } | |||
| } | |||
| if (error_message == NULL) | |||
| buffer[iout] = 0; | |||
| else | |||
| { | |||
| buffer[iout++] = ':'; | |||
| buffer[iout++] = ' '; | |||
| png_strncpy(buffer+iout, error_message, 63); | |||
| buffer[iout+63] = 0; | |||
| } | |||
| } | |||
| #ifdef PNG_READ_SUPPORTED | |||
| void PNGAPI | |||
| png_chunk_error(png_structp png_ptr, png_const_charp error_message) | |||
| { | |||
| char msg[18+64]; | |||
| if (png_ptr == NULL) | |||
| png_error(png_ptr, error_message); | |||
| else | |||
| { | |||
| png_format_buffer(png_ptr, msg, error_message); | |||
| png_error(png_ptr, msg); | |||
| } | |||
| } | |||
| #endif /* PNG_READ_SUPPORTED */ | |||
| #endif /* !defined(PNG_NO_WARNINGS) || !defined(PNG_NO_ERROR_TEXT) */ | |||
| #ifndef PNG_NO_WARNINGS | |||
| void PNGAPI | |||
| png_chunk_warning(png_structp png_ptr, png_const_charp warning_message) | |||
| { | |||
| char msg[18+64]; | |||
| if (png_ptr == NULL) | |||
| png_warning(png_ptr, warning_message); | |||
| else | |||
| { | |||
| png_format_buffer(png_ptr, msg, warning_message); | |||
| png_warning(png_ptr, msg); | |||
| } | |||
| } | |||
| #endif /* PNG_NO_WARNINGS */ | |||
| /* This is the default error handling function. Note that replacements for | |||
| * this function MUST NOT RETURN, or the program will likely crash. This | |||
| * function is used by default, or if the program supplies NULL for the | |||
| * error function pointer in png_set_error_fn(). | |||
| */ | |||
| static void /* PRIVATE */ | |||
| png_default_error(png_structp png_ptr, png_const_charp error_message) | |||
| { | |||
| #ifndef PNG_NO_CONSOLE_IO | |||
| #ifdef PNG_ERROR_NUMBERS_SUPPORTED | |||
| if (*error_message == '#') | |||
| { | |||
| int offset; | |||
| char error_number[16]; | |||
| for (offset=0; offset<15; offset++) | |||
| { | |||
| error_number[offset] = *(error_message+offset+1); | |||
| if (*(error_message+offset) == ' ') | |||
| break; | |||
| } | |||
| if((offset > 1) && (offset < 15)) | |||
| { | |||
| error_number[offset-1]='\0'; | |||
| fprintf(stderr, "libpng error no. %s: %s\n", error_number, | |||
| error_message+offset); | |||
| } | |||
| else | |||
| fprintf(stderr, "libpng error: %s, offset=%d\n", error_message,offset); | |||
| } | |||
| else | |||
| #endif | |||
| fprintf(stderr, "libpng error: %s\n", error_message); | |||
| #endif | |||
| #ifdef PNG_SETJMP_SUPPORTED | |||
| if (png_ptr) | |||
| { | |||
| # ifdef USE_FAR_KEYWORD | |||
| { | |||
| jmp_buf jmpbuf; | |||
| png_memcpy(jmpbuf, png_ptr->jmpbuf, png_sizeof(jmp_buf)); | |||
| longjmp(jmpbuf, 1); | |||
| } | |||
| # else | |||
| longjmp(png_ptr->jmpbuf, 1); | |||
| # endif | |||
| } | |||
| #else | |||
| PNG_ABORT(); | |||
| #endif | |||
| #ifdef PNG_NO_CONSOLE_IO | |||
| error_message = error_message; /* make compiler happy */ | |||
| #endif | |||
| } | |||
| #ifndef PNG_NO_WARNINGS | |||
| /* This function is called when there is a warning, but the library thinks | |||
| * it can continue anyway. Replacement functions don't have to do anything | |||
| * here if you don't want them to. In the default configuration, png_ptr is | |||
| * not used, but it is passed in case it may be useful. | |||
| */ | |||
| static void /* PRIVATE */ | |||
| png_default_warning(png_structp png_ptr, png_const_charp warning_message) | |||
| { | |||
| #ifndef PNG_NO_CONSOLE_IO | |||
| # ifdef PNG_ERROR_NUMBERS_SUPPORTED | |||
| if (*warning_message == '#') | |||
| { | |||
| int offset; | |||
| char warning_number[16]; | |||
| for (offset=0; offset<15; offset++) | |||
| { | |||
| warning_number[offset]=*(warning_message+offset+1); | |||
| if (*(warning_message+offset) == ' ') | |||
| break; | |||
| } | |||
| if((offset > 1) && (offset < 15)) | |||
| { | |||
| warning_number[offset-1]='\0'; | |||
| fprintf(stderr, "libpng warning no. %s: %s\n", warning_number, | |||
| warning_message+offset); | |||
| } | |||
| else | |||
| fprintf(stderr, "libpng warning: %s\n", warning_message); | |||
| } | |||
| else | |||
| # endif | |||
| fprintf(stderr, "libpng warning: %s\n", warning_message); | |||
| #else | |||
| warning_message = warning_message; /* make compiler happy */ | |||
| #endif | |||
| png_ptr = png_ptr; /* make compiler happy */ | |||
| } | |||
| #endif /* PNG_NO_WARNINGS */ | |||
| /* This function is called when the application wants to use another method | |||
| * of handling errors and warnings. Note that the error function MUST NOT | |||
| * return to the calling routine or serious problems will occur. The return | |||
| * method used in the default routine calls longjmp(png_ptr->jmpbuf, 1) | |||
| */ | |||
| void PNGAPI | |||
| png_set_error_fn(png_structp png_ptr, png_voidp error_ptr, | |||
| png_error_ptr error_fn, png_error_ptr warning_fn) | |||
| { | |||
| if (png_ptr == NULL) | |||
| return; | |||
| png_ptr->error_ptr = error_ptr; | |||
| png_ptr->error_fn = error_fn; | |||
| png_ptr->warning_fn = warning_fn; | |||
| } | |||
| /* This function returns a pointer to the error_ptr associated with the user | |||
| * functions. The application should free any memory associated with this | |||
| * pointer before png_write_destroy and png_read_destroy are called. | |||
| */ | |||
| png_voidp PNGAPI | |||
| png_get_error_ptr(png_structp png_ptr) | |||
| { | |||
| if (png_ptr == NULL) | |||
| return NULL; | |||
| return ((png_voidp)png_ptr->error_ptr); | |||
| } | |||
| #ifdef PNG_ERROR_NUMBERS_SUPPORTED | |||
| void PNGAPI | |||
| png_set_strip_error_numbers(png_structp png_ptr, png_uint_32 strip_mode) | |||
| { | |||
| if(png_ptr != NULL) | |||
| { | |||
| png_ptr->flags &= | |||
| ((~(PNG_FLAG_STRIP_ERROR_NUMBERS|PNG_FLAG_STRIP_ERROR_TEXT))&strip_mode); | |||
| } | |||
| } | |||
| #endif | |||
| #endif /* PNG_READ_SUPPORTED || PNG_WRITE_SUPPORTED */ | |||
| /* pngerror.c - stub functions for i/o and memory allocation | |||
| * | |||
| * Last changed in libpng 1.2.20 October 4, 2007 | |||
| * For conditions of distribution and use, see copyright notice in png.h | |||
| * Copyright (c) 1998-2007 Glenn Randers-Pehrson | |||
| * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) | |||
| * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) | |||
| * | |||
| * This file provides a location for all error handling. Users who | |||
| * need special error handling are expected to write replacement functions | |||
| * and use png_set_error_fn() to use those functions. See the instructions | |||
| * at each function. | |||
| */ | |||
| #define PNG_INTERNAL | |||
| #include "png.h" | |||
| #if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) | |||
| static void /* PRIVATE */ | |||
| png_default_error PNGARG((png_structp png_ptr, | |||
| png_const_charp error_message)); | |||
| #ifndef PNG_NO_WARNINGS | |||
| static void /* PRIVATE */ | |||
| png_default_warning PNGARG((png_structp png_ptr, | |||
| png_const_charp warning_message)); | |||
| #endif /* PNG_NO_WARNINGS */ | |||
| /* This function is called whenever there is a fatal error. This function | |||
| * should not be changed. If there is a need to handle errors differently, | |||
| * you should supply a replacement error function and use png_set_error_fn() | |||
| * to replace the error function at run-time. | |||
| */ | |||
| #ifndef PNG_NO_ERROR_TEXT | |||
| void PNGAPI | |||
| png_error(png_structp png_ptr, png_const_charp error_message) | |||
| { | |||
| #ifdef PNG_ERROR_NUMBERS_SUPPORTED | |||
| char msg[16]; | |||
| if (png_ptr != NULL) | |||
| { | |||
| if (png_ptr->flags& | |||
| (PNG_FLAG_STRIP_ERROR_NUMBERS|PNG_FLAG_STRIP_ERROR_TEXT)) | |||
| { | |||
| if (*error_message == '#') | |||
| { | |||
| int offset; | |||
| for (offset=1; offset<15; offset++) | |||
| if (*(error_message+offset) == ' ') | |||
| break; | |||
| if (png_ptr->flags&PNG_FLAG_STRIP_ERROR_TEXT) | |||
| { | |||
| int i; | |||
| for (i=0; i<offset-1; i++) | |||
| msg[i]=error_message[i+1]; | |||
| msg[i]='\0'; | |||
| error_message=msg; | |||
| } | |||
| else | |||
| error_message+=offset; | |||
| } | |||
| else | |||
| { | |||
| if (png_ptr->flags&PNG_FLAG_STRIP_ERROR_TEXT) | |||
| { | |||
| msg[0]='0'; | |||
| msg[1]='\0'; | |||
| error_message=msg; | |||
| } | |||
| } | |||
| } | |||
| } | |||
| #endif | |||
| if (png_ptr != NULL && png_ptr->error_fn != NULL) | |||
| (*(png_ptr->error_fn))(png_ptr, error_message); | |||
| /* If the custom handler doesn't exist, or if it returns, | |||
| use the default handler, which will not return. */ | |||
| png_default_error(png_ptr, error_message); | |||
| } | |||
| #else | |||
| void PNGAPI | |||
| png_err(png_structp png_ptr) | |||
| { | |||
| if (png_ptr != NULL && png_ptr->error_fn != NULL) | |||
| (*(png_ptr->error_fn))(png_ptr, '\0'); | |||
| /* If the custom handler doesn't exist, or if it returns, | |||
| use the default handler, which will not return. */ | |||
| png_default_error(png_ptr, '\0'); | |||
| } | |||
| #endif /* PNG_NO_ERROR_TEXT */ | |||
| #ifndef PNG_NO_WARNINGS | |||
| /* This function is called whenever there is a non-fatal error. This function | |||
| * should not be changed. If there is a need to handle warnings differently, | |||
| * you should supply a replacement warning function and use | |||
| * png_set_error_fn() to replace the warning function at run-time. | |||
| */ | |||
| void PNGAPI | |||
| png_warning(png_structp png_ptr, png_const_charp warning_message) | |||
| { | |||
| int offset = 0; | |||
| if (png_ptr != NULL) | |||
| { | |||
| #ifdef PNG_ERROR_NUMBERS_SUPPORTED | |||
| if (png_ptr->flags& | |||
| (PNG_FLAG_STRIP_ERROR_NUMBERS|PNG_FLAG_STRIP_ERROR_TEXT)) | |||
| #endif | |||
| { | |||
| if (*warning_message == '#') | |||
| { | |||
| for (offset=1; offset<15; offset++) | |||
| if (*(warning_message+offset) == ' ') | |||
| break; | |||
| } | |||
| } | |||
| if (png_ptr != NULL && png_ptr->warning_fn != NULL) | |||
| (*(png_ptr->warning_fn))(png_ptr, warning_message+offset); | |||
| } | |||
| else | |||
| png_default_warning(png_ptr, warning_message+offset); | |||
| } | |||
| #endif /* PNG_NO_WARNINGS */ | |||
| /* These utilities are used internally to build an error message that relates | |||
| * to the current chunk. The chunk name comes from png_ptr->chunk_name, | |||
| * this is used to prefix the message. The message is limited in length | |||
| * to 63 bytes, the name characters are output as hex digits wrapped in [] | |||
| * if the character is invalid. | |||
| */ | |||
| #define isnonalpha(c) ((c) < 65 || (c) > 122 || ((c) > 90 && (c) < 97)) | |||
| static PNG_CONST char png_digit[16] = { | |||
| '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', | |||
| 'A', 'B', 'C', 'D', 'E', 'F' | |||
| }; | |||
| #if !defined(PNG_NO_WARNINGS) || !defined(PNG_NO_ERROR_TEXT) | |||
| static void /* PRIVATE */ | |||
| png_format_buffer(png_structp png_ptr, png_charp buffer, png_const_charp | |||
| error_message) | |||
| { | |||
| int iout = 0, iin = 0; | |||
| while (iin < 4) | |||
| { | |||
| int c = png_ptr->chunk_name[iin++]; | |||
| if (isnonalpha(c)) | |||
| { | |||
| buffer[iout++] = '['; | |||
| buffer[iout++] = png_digit[(c & 0xf0) >> 4]; | |||
| buffer[iout++] = png_digit[c & 0x0f]; | |||
| buffer[iout++] = ']'; | |||
| } | |||
| else | |||
| { | |||
| buffer[iout++] = (png_byte)c; | |||
| } | |||
| } | |||
| if (error_message == NULL) | |||
| buffer[iout] = 0; | |||
| else | |||
| { | |||
| buffer[iout++] = ':'; | |||
| buffer[iout++] = ' '; | |||
| png_strncpy(buffer+iout, error_message, 63); | |||
| buffer[iout+63] = 0; | |||
| } | |||
| } | |||
| #ifdef PNG_READ_SUPPORTED | |||
| void PNGAPI | |||
| png_chunk_error(png_structp png_ptr, png_const_charp error_message) | |||
| { | |||
| char msg[18+64]; | |||
| if (png_ptr == NULL) | |||
| png_error(png_ptr, error_message); | |||
| else | |||
| { | |||
| png_format_buffer(png_ptr, msg, error_message); | |||
| png_error(png_ptr, msg); | |||
| } | |||
| } | |||
| #endif /* PNG_READ_SUPPORTED */ | |||
| #endif /* !defined(PNG_NO_WARNINGS) || !defined(PNG_NO_ERROR_TEXT) */ | |||
| #ifndef PNG_NO_WARNINGS | |||
| void PNGAPI | |||
| png_chunk_warning(png_structp png_ptr, png_const_charp warning_message) | |||
| { | |||
| char msg[18+64]; | |||
| if (png_ptr == NULL) | |||
| png_warning(png_ptr, warning_message); | |||
| else | |||
| { | |||
| png_format_buffer(png_ptr, msg, warning_message); | |||
| png_warning(png_ptr, msg); | |||
| } | |||
| } | |||
| #endif /* PNG_NO_WARNINGS */ | |||
| /* This is the default error handling function. Note that replacements for | |||
| * this function MUST NOT RETURN, or the program will likely crash. This | |||
| * function is used by default, or if the program supplies NULL for the | |||
| * error function pointer in png_set_error_fn(). | |||
| */ | |||
| static void /* PRIVATE */ | |||
| png_default_error(png_structp png_ptr, png_const_charp error_message) | |||
| { | |||
| #ifndef PNG_NO_CONSOLE_IO | |||
| #ifdef PNG_ERROR_NUMBERS_SUPPORTED | |||
| if (*error_message == '#') | |||
| { | |||
| int offset; | |||
| char error_number[16]; | |||
| for (offset=0; offset<15; offset++) | |||
| { | |||
| error_number[offset] = *(error_message+offset+1); | |||
| if (*(error_message+offset) == ' ') | |||
| break; | |||
| } | |||
| if((offset > 1) && (offset < 15)) | |||
| { | |||
| error_number[offset-1]='\0'; | |||
| fprintf(stderr, "libpng error no. %s: %s\n", error_number, | |||
| error_message+offset); | |||
| } | |||
| else | |||
| fprintf(stderr, "libpng error: %s, offset=%d\n", error_message,offset); | |||
| } | |||
| else | |||
| #endif | |||
| fprintf(stderr, "libpng error: %s\n", error_message); | |||
| #endif | |||
| #ifdef PNG_SETJMP_SUPPORTED | |||
| if (png_ptr) | |||
| { | |||
| # ifdef USE_FAR_KEYWORD | |||
| { | |||
| jmp_buf jmpbuf; | |||
| png_memcpy(jmpbuf, png_ptr->jmpbuf, png_sizeof(jmp_buf)); | |||
| longjmp(jmpbuf, 1); | |||
| } | |||
| # else | |||
| longjmp(png_ptr->jmpbuf, 1); | |||
| # endif | |||
| } | |||
| #else | |||
| PNG_ABORT(); | |||
| #endif | |||
| #ifdef PNG_NO_CONSOLE_IO | |||
| error_message = error_message; /* make compiler happy */ | |||
| #endif | |||
| } | |||
| #ifndef PNG_NO_WARNINGS | |||
| /* This function is called when there is a warning, but the library thinks | |||
| * it can continue anyway. Replacement functions don't have to do anything | |||
| * here if you don't want them to. In the default configuration, png_ptr is | |||
| * not used, but it is passed in case it may be useful. | |||
| */ | |||
| static void /* PRIVATE */ | |||
| png_default_warning(png_structp png_ptr, png_const_charp warning_message) | |||
| { | |||
| #ifndef PNG_NO_CONSOLE_IO | |||
| # ifdef PNG_ERROR_NUMBERS_SUPPORTED | |||
| if (*warning_message == '#') | |||
| { | |||
| int offset; | |||
| char warning_number[16]; | |||
| for (offset=0; offset<15; offset++) | |||
| { | |||
| warning_number[offset]=*(warning_message+offset+1); | |||
| if (*(warning_message+offset) == ' ') | |||
| break; | |||
| } | |||
| if((offset > 1) && (offset < 15)) | |||
| { | |||
| warning_number[offset-1]='\0'; | |||
| fprintf(stderr, "libpng warning no. %s: %s\n", warning_number, | |||
| warning_message+offset); | |||
| } | |||
| else | |||
| fprintf(stderr, "libpng warning: %s\n", warning_message); | |||
| } | |||
| else | |||
| # endif | |||
| fprintf(stderr, "libpng warning: %s\n", warning_message); | |||
| #else | |||
| warning_message = warning_message; /* make compiler happy */ | |||
| #endif | |||
| png_ptr = png_ptr; /* make compiler happy */ | |||
| } | |||
| #endif /* PNG_NO_WARNINGS */ | |||
| /* This function is called when the application wants to use another method | |||
| * of handling errors and warnings. Note that the error function MUST NOT | |||
| * return to the calling routine or serious problems will occur. The return | |||
| * method used in the default routine calls longjmp(png_ptr->jmpbuf, 1) | |||
| */ | |||
| void PNGAPI | |||
| png_set_error_fn(png_structp png_ptr, png_voidp error_ptr, | |||
| png_error_ptr error_fn, png_error_ptr warning_fn) | |||
| { | |||
| if (png_ptr == NULL) | |||
| return; | |||
| png_ptr->error_ptr = error_ptr; | |||
| png_ptr->error_fn = error_fn; | |||
| png_ptr->warning_fn = warning_fn; | |||
| } | |||
| /* This function returns a pointer to the error_ptr associated with the user | |||
| * functions. The application should free any memory associated with this | |||
| * pointer before png_write_destroy and png_read_destroy are called. | |||
| */ | |||
| png_voidp PNGAPI | |||
| png_get_error_ptr(png_structp png_ptr) | |||
| { | |||
| if (png_ptr == NULL) | |||
| return NULL; | |||
| return ((png_voidp)png_ptr->error_ptr); | |||
| } | |||
| #ifdef PNG_ERROR_NUMBERS_SUPPORTED | |||
| void PNGAPI | |||
| png_set_strip_error_numbers(png_structp png_ptr, png_uint_32 strip_mode) | |||
| { | |||
| if(png_ptr != NULL) | |||
| { | |||
| png_ptr->flags &= | |||
| ((~(PNG_FLAG_STRIP_ERROR_NUMBERS|PNG_FLAG_STRIP_ERROR_TEXT))&strip_mode); | |||
| } | |||
| } | |||
| #endif | |||
| #endif /* PNG_READ_SUPPORTED || PNG_WRITE_SUPPORTED */ | |||
| @@ -1,167 +1,167 @@ | |||
| /* pngrio.c - functions for data input | |||
| * | |||
| * Last changed in libpng 1.2.13 November 13, 2006 | |||
| * For conditions of distribution and use, see copyright notice in png.h | |||
| * Copyright (c) 1998-2006 Glenn Randers-Pehrson | |||
| * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) | |||
| * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) | |||
| * | |||
| * This file provides a location for all input. Users who need | |||
| * special handling are expected to write a function that has the same | |||
| * arguments as this and performs a similar function, but that possibly | |||
| * has a different input method. Note that you shouldn't change this | |||
| * function, but rather write a replacement function and then make | |||
| * libpng use it at run time with png_set_read_fn(...). | |||
| */ | |||
| #define PNG_INTERNAL | |||
| #include "png.h" | |||
| #if defined(PNG_READ_SUPPORTED) | |||
| /* Read the data from whatever input you are using. The default routine | |||
| reads from a file pointer. Note that this routine sometimes gets called | |||
| with very small lengths, so you should implement some kind of simple | |||
| buffering if you are using unbuffered reads. This should never be asked | |||
| to read more then 64K on a 16 bit machine. */ | |||
| void /* PRIVATE */ | |||
| png_read_data(png_structp png_ptr, png_bytep data, png_size_t length) | |||
| { | |||
| png_debug1(4,"reading %d bytes\n", (int)length); | |||
| if (png_ptr->read_data_fn != NULL) | |||
| (*(png_ptr->read_data_fn))(png_ptr, data, length); | |||
| else | |||
| png_error(png_ptr, "Call to NULL read function"); | |||
| } | |||
| #if !defined(PNG_NO_STDIO) | |||
| /* This is the function that does the actual reading of data. If you are | |||
| not reading from a standard C stream, you should create a replacement | |||
| read_data function and use it at run time with png_set_read_fn(), rather | |||
| than changing the library. */ | |||
| #ifndef USE_FAR_KEYWORD | |||
| void PNGAPI | |||
| png_default_read_data(png_structp png_ptr, png_bytep data, png_size_t length) | |||
| { | |||
| png_size_t check; | |||
| if(png_ptr == NULL) return; | |||
| /* fread() returns 0 on error, so it is OK to store this in a png_size_t | |||
| * instead of an int, which is what fread() actually returns. | |||
| */ | |||
| #if defined(_WIN32_WCE) | |||
| if ( !ReadFile((HANDLE)(png_ptr->io_ptr), data, length, &check, NULL) ) | |||
| check = 0; | |||
| #else | |||
| check = (png_size_t)fread(data, (png_size_t)1, length, | |||
| (png_FILE_p)png_ptr->io_ptr); | |||
| #endif | |||
| if (check != length) | |||
| png_error(png_ptr, "Read Error"); | |||
| } | |||
| #else | |||
| /* this is the model-independent version. Since the standard I/O library | |||
| can't handle far buffers in the medium and small models, we have to copy | |||
| the data. | |||
| */ | |||
| #define NEAR_BUF_SIZE 1024 | |||
| #define MIN(a,b) (a <= b ? a : b) | |||
| static void PNGAPI | |||
| png_default_read_data(png_structp png_ptr, png_bytep data, png_size_t length) | |||
| { | |||
| int check; | |||
| png_byte *n_data; | |||
| png_FILE_p io_ptr; | |||
| if(png_ptr == NULL) return; | |||
| /* Check if data really is near. If so, use usual code. */ | |||
| n_data = (png_byte *)CVT_PTR_NOCHECK(data); | |||
| io_ptr = (png_FILE_p)CVT_PTR(png_ptr->io_ptr); | |||
| if ((png_bytep)n_data == data) | |||
| { | |||
| #if defined(_WIN32_WCE) | |||
| if ( !ReadFile((HANDLE)(png_ptr->io_ptr), data, length, &check, NULL) ) | |||
| check = 0; | |||
| #else | |||
| check = fread(n_data, 1, length, io_ptr); | |||
| #endif | |||
| } | |||
| else | |||
| { | |||
| png_byte buf[NEAR_BUF_SIZE]; | |||
| png_size_t read, remaining, err; | |||
| check = 0; | |||
| remaining = length; | |||
| do | |||
| { | |||
| read = MIN(NEAR_BUF_SIZE, remaining); | |||
| #if defined(_WIN32_WCE) | |||
| if ( !ReadFile((HANDLE)(io_ptr), buf, read, &err, NULL) ) | |||
| err = 0; | |||
| #else | |||
| err = fread(buf, (png_size_t)1, read, io_ptr); | |||
| #endif | |||
| png_memcpy(data, buf, read); /* copy far buffer to near buffer */ | |||
| if(err != read) | |||
| break; | |||
| else | |||
| check += err; | |||
| data += read; | |||
| remaining -= read; | |||
| } | |||
| while (remaining != 0); | |||
| } | |||
| if ((png_uint_32)check != (png_uint_32)length) | |||
| png_error(png_ptr, "read Error"); | |||
| } | |||
| #endif | |||
| #endif | |||
| /* This function allows the application to supply a new input function | |||
| for libpng if standard C streams aren't being used. | |||
| This function takes as its arguments: | |||
| png_ptr - pointer to a png input data structure | |||
| io_ptr - pointer to user supplied structure containing info about | |||
| the input functions. May be NULL. | |||
| read_data_fn - pointer to a new input function that takes as its | |||
| arguments a pointer to a png_struct, a pointer to | |||
| a location where input data can be stored, and a 32-bit | |||
| unsigned int that is the number of bytes to be read. | |||
| To exit and output any fatal error messages the new write | |||
| function should call png_error(png_ptr, "Error msg"). */ | |||
| void PNGAPI | |||
| png_set_read_fn(png_structp png_ptr, png_voidp io_ptr, | |||
| png_rw_ptr read_data_fn) | |||
| { | |||
| if(png_ptr == NULL) return; | |||
| png_ptr->io_ptr = io_ptr; | |||
| #if !defined(PNG_NO_STDIO) | |||
| if (read_data_fn != NULL) | |||
| png_ptr->read_data_fn = read_data_fn; | |||
| else | |||
| png_ptr->read_data_fn = png_default_read_data; | |||
| #else | |||
| png_ptr->read_data_fn = read_data_fn; | |||
| #endif | |||
| /* It is an error to write to a read device */ | |||
| if (png_ptr->write_data_fn != NULL) | |||
| { | |||
| png_ptr->write_data_fn = NULL; | |||
| png_warning(png_ptr, | |||
| "It's an error to set both read_data_fn and write_data_fn in the "); | |||
| png_warning(png_ptr, | |||
| "same structure. Resetting write_data_fn to NULL."); | |||
| } | |||
| #if defined(PNG_WRITE_FLUSH_SUPPORTED) | |||
| png_ptr->output_flush_fn = NULL; | |||
| #endif | |||
| } | |||
| #endif /* PNG_READ_SUPPORTED */ | |||
| /* pngrio.c - functions for data input | |||
| * | |||
| * Last changed in libpng 1.2.13 November 13, 2006 | |||
| * For conditions of distribution and use, see copyright notice in png.h | |||
| * Copyright (c) 1998-2006 Glenn Randers-Pehrson | |||
| * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) | |||
| * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) | |||
| * | |||
| * This file provides a location for all input. Users who need | |||
| * special handling are expected to write a function that has the same | |||
| * arguments as this and performs a similar function, but that possibly | |||
| * has a different input method. Note that you shouldn't change this | |||
| * function, but rather write a replacement function and then make | |||
| * libpng use it at run time with png_set_read_fn(...). | |||
| */ | |||
| #define PNG_INTERNAL | |||
| #include "png.h" | |||
| #if defined(PNG_READ_SUPPORTED) | |||
| /* Read the data from whatever input you are using. The default routine | |||
| reads from a file pointer. Note that this routine sometimes gets called | |||
| with very small lengths, so you should implement some kind of simple | |||
| buffering if you are using unbuffered reads. This should never be asked | |||
| to read more then 64K on a 16 bit machine. */ | |||
| void /* PRIVATE */ | |||
| png_read_data(png_structp png_ptr, png_bytep data, png_size_t length) | |||
| { | |||
| png_debug1(4,"reading %d bytes\n", (int)length); | |||
| if (png_ptr->read_data_fn != NULL) | |||
| (*(png_ptr->read_data_fn))(png_ptr, data, length); | |||
| else | |||
| png_error(png_ptr, "Call to NULL read function"); | |||
| } | |||
| #if !defined(PNG_NO_STDIO) | |||
| /* This is the function that does the actual reading of data. If you are | |||
| not reading from a standard C stream, you should create a replacement | |||
| read_data function and use it at run time with png_set_read_fn(), rather | |||
| than changing the library. */ | |||
| #ifndef USE_FAR_KEYWORD | |||
| void PNGAPI | |||
| png_default_read_data(png_structp png_ptr, png_bytep data, png_size_t length) | |||
| { | |||
| png_size_t check; | |||
| if(png_ptr == NULL) return; | |||
| /* fread() returns 0 on error, so it is OK to store this in a png_size_t | |||
| * instead of an int, which is what fread() actually returns. | |||
| */ | |||
| #if defined(_WIN32_WCE) | |||
| if ( !ReadFile((HANDLE)(png_ptr->io_ptr), data, length, &check, NULL) ) | |||
| check = 0; | |||
| #else | |||
| check = (png_size_t)fread(data, (png_size_t)1, length, | |||
| (png_FILE_p)png_ptr->io_ptr); | |||
| #endif | |||
| if (check != length) | |||
| png_error(png_ptr, "Read Error"); | |||
| } | |||
| #else | |||
| /* this is the model-independent version. Since the standard I/O library | |||
| can't handle far buffers in the medium and small models, we have to copy | |||
| the data. | |||
| */ | |||
| #define NEAR_BUF_SIZE 1024 | |||
| #define MIN(a,b) (a <= b ? a : b) | |||
| static void PNGAPI | |||
| png_default_read_data(png_structp png_ptr, png_bytep data, png_size_t length) | |||
| { | |||
| int check; | |||
| png_byte *n_data; | |||
| png_FILE_p io_ptr; | |||
| if(png_ptr == NULL) return; | |||
| /* Check if data really is near. If so, use usual code. */ | |||
| n_data = (png_byte *)CVT_PTR_NOCHECK(data); | |||
| io_ptr = (png_FILE_p)CVT_PTR(png_ptr->io_ptr); | |||
| if ((png_bytep)n_data == data) | |||
| { | |||
| #if defined(_WIN32_WCE) | |||
| if ( !ReadFile((HANDLE)(png_ptr->io_ptr), data, length, &check, NULL) ) | |||
| check = 0; | |||
| #else | |||
| check = fread(n_data, 1, length, io_ptr); | |||
| #endif | |||
| } | |||
| else | |||
| { | |||
| png_byte buf[NEAR_BUF_SIZE]; | |||
| png_size_t read, remaining, err; | |||
| check = 0; | |||
| remaining = length; | |||
| do | |||
| { | |||
| read = MIN(NEAR_BUF_SIZE, remaining); | |||
| #if defined(_WIN32_WCE) | |||
| if ( !ReadFile((HANDLE)(io_ptr), buf, read, &err, NULL) ) | |||
| err = 0; | |||
| #else | |||
| err = fread(buf, (png_size_t)1, read, io_ptr); | |||
| #endif | |||
| png_memcpy(data, buf, read); /* copy far buffer to near buffer */ | |||
| if(err != read) | |||
| break; | |||
| else | |||
| check += err; | |||
| data += read; | |||
| remaining -= read; | |||
| } | |||
| while (remaining != 0); | |||
| } | |||
| if ((png_uint_32)check != (png_uint_32)length) | |||
| png_error(png_ptr, "read Error"); | |||
| } | |||
| #endif | |||
| #endif | |||
| /* This function allows the application to supply a new input function | |||
| for libpng if standard C streams aren't being used. | |||
| This function takes as its arguments: | |||
| png_ptr - pointer to a png input data structure | |||
| io_ptr - pointer to user supplied structure containing info about | |||
| the input functions. May be NULL. | |||
| read_data_fn - pointer to a new input function that takes as its | |||
| arguments a pointer to a png_struct, a pointer to | |||
| a location where input data can be stored, and a 32-bit | |||
| unsigned int that is the number of bytes to be read. | |||
| To exit and output any fatal error messages the new write | |||
| function should call png_error(png_ptr, "Error msg"). */ | |||
| void PNGAPI | |||
| png_set_read_fn(png_structp png_ptr, png_voidp io_ptr, | |||
| png_rw_ptr read_data_fn) | |||
| { | |||
| if(png_ptr == NULL) return; | |||
| png_ptr->io_ptr = io_ptr; | |||
| #if !defined(PNG_NO_STDIO) | |||
| if (read_data_fn != NULL) | |||
| png_ptr->read_data_fn = read_data_fn; | |||
| else | |||
| png_ptr->read_data_fn = png_default_read_data; | |||
| #else | |||
| png_ptr->read_data_fn = read_data_fn; | |||
| #endif | |||
| /* It is an error to write to a read device */ | |||
| if (png_ptr->write_data_fn != NULL) | |||
| { | |||
| png_ptr->write_data_fn = NULL; | |||
| png_warning(png_ptr, | |||
| "It's an error to set both read_data_fn and write_data_fn in the "); | |||
| png_warning(png_ptr, | |||
| "same structure. Resetting write_data_fn to NULL."); | |||
| } | |||
| #if defined(PNG_WRITE_FLUSH_SUPPORTED) | |||
| png_ptr->output_flush_fn = NULL; | |||
| #endif | |||
| } | |||
| #endif /* PNG_READ_SUPPORTED */ | |||
| @@ -1,234 +1,234 @@ | |||
| /* pngwio.c - functions for data output | |||
| * | |||
| * Last changed in libpng 1.2.13 November 13, 2006 | |||
| * For conditions of distribution and use, see copyright notice in png.h | |||
| * Copyright (c) 1998-2006 Glenn Randers-Pehrson | |||
| * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) | |||
| * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) | |||
| * | |||
| * This file provides a location for all output. Users who need | |||
| * special handling are expected to write functions that have the same | |||
| * arguments as these and perform similar functions, but that possibly | |||
| * use different output methods. Note that you shouldn't change these | |||
| * functions, but rather write replacement functions and then change | |||
| * them at run time with png_set_write_fn(...). | |||
| */ | |||
| #define PNG_INTERNAL | |||
| #include "png.h" | |||
| #ifdef PNG_WRITE_SUPPORTED | |||
| /* Write the data to whatever output you are using. The default routine | |||
| writes to a file pointer. Note that this routine sometimes gets called | |||
| with very small lengths, so you should implement some kind of simple | |||
| buffering if you are using unbuffered writes. This should never be asked | |||
| to write more than 64K on a 16 bit machine. */ | |||
| void /* PRIVATE */ | |||
| png_write_data(png_structp png_ptr, png_bytep data, png_size_t length) | |||
| { | |||
| if (png_ptr->write_data_fn != NULL ) | |||
| (*(png_ptr->write_data_fn))(png_ptr, data, length); | |||
| else | |||
| png_error(png_ptr, "Call to NULL write function"); | |||
| } | |||
| #if !defined(PNG_NO_STDIO) | |||
| /* This is the function that does the actual writing of data. If you are | |||
| not writing to a standard C stream, you should create a replacement | |||
| write_data function and use it at run time with png_set_write_fn(), rather | |||
| than changing the library. */ | |||
| #ifndef USE_FAR_KEYWORD | |||
| void PNGAPI | |||
| png_default_write_data(png_structp png_ptr, png_bytep data, png_size_t length) | |||
| { | |||
| png_uint_32 check; | |||
| if(png_ptr == NULL) return; | |||
| #if defined(_WIN32_WCE) | |||
| if ( !WriteFile((HANDLE)(png_ptr->io_ptr), data, length, &check, NULL) ) | |||
| check = 0; | |||
| #else | |||
| check = fwrite(data, 1, length, (png_FILE_p)(png_ptr->io_ptr)); | |||
| #endif | |||
| if (check != length) | |||
| png_error(png_ptr, "Write Error"); | |||
| } | |||
| #else | |||
| /* this is the model-independent version. Since the standard I/O library | |||
| can't handle far buffers in the medium and small models, we have to copy | |||
| the data. | |||
| */ | |||
| #define NEAR_BUF_SIZE 1024 | |||
| #define MIN(a,b) (a <= b ? a : b) | |||
| void PNGAPI | |||
| png_default_write_data(png_structp png_ptr, png_bytep data, png_size_t length) | |||
| { | |||
| png_uint_32 check; | |||
| png_byte *near_data; /* Needs to be "png_byte *" instead of "png_bytep" */ | |||
| png_FILE_p io_ptr; | |||
| if(png_ptr == NULL) return; | |||
| /* Check if data really is near. If so, use usual code. */ | |||
| near_data = (png_byte *)CVT_PTR_NOCHECK(data); | |||
| io_ptr = (png_FILE_p)CVT_PTR(png_ptr->io_ptr); | |||
| if ((png_bytep)near_data == data) | |||
| { | |||
| #if defined(_WIN32_WCE) | |||
| if ( !WriteFile(io_ptr, near_data, length, &check, NULL) ) | |||
| check = 0; | |||
| #else | |||
| check = fwrite(near_data, 1, length, io_ptr); | |||
| #endif | |||
| } | |||
| else | |||
| { | |||
| png_byte buf[NEAR_BUF_SIZE]; | |||
| png_size_t written, remaining, err; | |||
| check = 0; | |||
| remaining = length; | |||
| do | |||
| { | |||
| written = MIN(NEAR_BUF_SIZE, remaining); | |||
| png_memcpy(buf, data, written); /* copy far buffer to near buffer */ | |||
| #if defined(_WIN32_WCE) | |||
| if ( !WriteFile(io_ptr, buf, written, &err, NULL) ) | |||
| err = 0; | |||
| #else | |||
| err = fwrite(buf, 1, written, io_ptr); | |||
| #endif | |||
| if (err != written) | |||
| break; | |||
| else | |||
| check += err; | |||
| data += written; | |||
| remaining -= written; | |||
| } | |||
| while (remaining != 0); | |||
| } | |||
| if (check != length) | |||
| png_error(png_ptr, "Write Error"); | |||
| } | |||
| #endif | |||
| #endif | |||
| /* This function is called to output any data pending writing (normally | |||
| to disk). After png_flush is called, there should be no data pending | |||
| writing in any buffers. */ | |||
| #if defined(PNG_WRITE_FLUSH_SUPPORTED) | |||
| void /* PRIVATE */ | |||
| png_flush(png_structp png_ptr) | |||
| { | |||
| if (png_ptr->output_flush_fn != NULL) | |||
| (*(png_ptr->output_flush_fn))(png_ptr); | |||
| } | |||
| #if !defined(PNG_NO_STDIO) | |||
| void PNGAPI | |||
| png_default_flush(png_structp png_ptr) | |||
| { | |||
| #if !defined(_WIN32_WCE) | |||
| png_FILE_p io_ptr; | |||
| #endif | |||
| if(png_ptr == NULL) return; | |||
| #if !defined(_WIN32_WCE) | |||
| io_ptr = (png_FILE_p)CVT_PTR((png_ptr->io_ptr)); | |||
| if (io_ptr != NULL) | |||
| fflush(io_ptr); | |||
| #endif | |||
| } | |||
| #endif | |||
| #endif | |||
| /* This function allows the application to supply new output functions for | |||
| libpng if standard C streams aren't being used. | |||
| This function takes as its arguments: | |||
| png_ptr - pointer to a png output data structure | |||
| io_ptr - pointer to user supplied structure containing info about | |||
| the output functions. May be NULL. | |||
| write_data_fn - pointer to a new output function that takes as its | |||
| arguments a pointer to a png_struct, a pointer to | |||
| data to be written, and a 32-bit unsigned int that is | |||
| the number of bytes to be written. The new write | |||
| function should call png_error(png_ptr, "Error msg") | |||
| to exit and output any fatal error messages. | |||
| flush_data_fn - pointer to a new flush function that takes as its | |||
| arguments a pointer to a png_struct. After a call to | |||
| the flush function, there should be no data in any buffers | |||
| or pending transmission. If the output method doesn't do | |||
| any buffering of ouput, a function prototype must still be | |||
| supplied although it doesn't have to do anything. If | |||
| PNG_WRITE_FLUSH_SUPPORTED is not defined at libpng compile | |||
| time, output_flush_fn will be ignored, although it must be | |||
| supplied for compatibility. */ | |||
| void PNGAPI | |||
| png_set_write_fn(png_structp png_ptr, png_voidp io_ptr, | |||
| png_rw_ptr write_data_fn, png_flush_ptr output_flush_fn) | |||
| { | |||
| if(png_ptr == NULL) return; | |||
| png_ptr->io_ptr = io_ptr; | |||
| #if !defined(PNG_NO_STDIO) | |||
| if (write_data_fn != NULL) | |||
| png_ptr->write_data_fn = write_data_fn; | |||
| else | |||
| png_ptr->write_data_fn = png_default_write_data; | |||
| #else | |||
| png_ptr->write_data_fn = write_data_fn; | |||
| #endif | |||
| #if defined(PNG_WRITE_FLUSH_SUPPORTED) | |||
| #if !defined(PNG_NO_STDIO) | |||
| if (output_flush_fn != NULL) | |||
| png_ptr->output_flush_fn = output_flush_fn; | |||
| else | |||
| png_ptr->output_flush_fn = png_default_flush; | |||
| #else | |||
| png_ptr->output_flush_fn = output_flush_fn; | |||
| #endif | |||
| #endif /* PNG_WRITE_FLUSH_SUPPORTED */ | |||
| /* It is an error to read while writing a png file */ | |||
| if (png_ptr->read_data_fn != NULL) | |||
| { | |||
| png_ptr->read_data_fn = NULL; | |||
| png_warning(png_ptr, | |||
| "Attempted to set both read_data_fn and write_data_fn in"); | |||
| png_warning(png_ptr, | |||
| "the same structure. Resetting read_data_fn to NULL."); | |||
| } | |||
| } | |||
| #if defined(USE_FAR_KEYWORD) | |||
| #if defined(_MSC_VER) | |||
| void *png_far_to_near(png_structp png_ptr,png_voidp ptr, int check) | |||
| { | |||
| void *near_ptr; | |||
| void FAR *far_ptr; | |||
| FP_OFF(near_ptr) = FP_OFF(ptr); | |||
| far_ptr = (void FAR *)near_ptr; | |||
| if(check != 0) | |||
| if(FP_SEG(ptr) != FP_SEG(far_ptr)) | |||
| png_error(png_ptr,"segment lost in conversion"); | |||
| return(near_ptr); | |||
| } | |||
| # else | |||
| void *png_far_to_near(png_structp png_ptr,png_voidp ptr, int check) | |||
| { | |||
| void *near_ptr; | |||
| void FAR *far_ptr; | |||
| near_ptr = (void FAR *)ptr; | |||
| far_ptr = (void FAR *)near_ptr; | |||
| if(check != 0) | |||
| if(far_ptr != ptr) | |||
| png_error(png_ptr,"segment lost in conversion"); | |||
| return(near_ptr); | |||
| } | |||
| # endif | |||
| # endif | |||
| #endif /* PNG_WRITE_SUPPORTED */ | |||
| /* pngwio.c - functions for data output | |||
| * | |||
| * Last changed in libpng 1.2.13 November 13, 2006 | |||
| * For conditions of distribution and use, see copyright notice in png.h | |||
| * Copyright (c) 1998-2006 Glenn Randers-Pehrson | |||
| * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) | |||
| * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) | |||
| * | |||
| * This file provides a location for all output. Users who need | |||
| * special handling are expected to write functions that have the same | |||
| * arguments as these and perform similar functions, but that possibly | |||
| * use different output methods. Note that you shouldn't change these | |||
| * functions, but rather write replacement functions and then change | |||
| * them at run time with png_set_write_fn(...). | |||
| */ | |||
| #define PNG_INTERNAL | |||
| #include "png.h" | |||
| #ifdef PNG_WRITE_SUPPORTED | |||
| /* Write the data to whatever output you are using. The default routine | |||
| writes to a file pointer. Note that this routine sometimes gets called | |||
| with very small lengths, so you should implement some kind of simple | |||
| buffering if you are using unbuffered writes. This should never be asked | |||
| to write more than 64K on a 16 bit machine. */ | |||
| void /* PRIVATE */ | |||
| png_write_data(png_structp png_ptr, png_bytep data, png_size_t length) | |||
| { | |||
| if (png_ptr->write_data_fn != NULL ) | |||
| (*(png_ptr->write_data_fn))(png_ptr, data, length); | |||
| else | |||
| png_error(png_ptr, "Call to NULL write function"); | |||
| } | |||
| #if !defined(PNG_NO_STDIO) | |||
| /* This is the function that does the actual writing of data. If you are | |||
| not writing to a standard C stream, you should create a replacement | |||
| write_data function and use it at run time with png_set_write_fn(), rather | |||
| than changing the library. */ | |||
| #ifndef USE_FAR_KEYWORD | |||
| void PNGAPI | |||
| png_default_write_data(png_structp png_ptr, png_bytep data, png_size_t length) | |||
| { | |||
| png_uint_32 check; | |||
| if(png_ptr == NULL) return; | |||
| #if defined(_WIN32_WCE) | |||
| if ( !WriteFile((HANDLE)(png_ptr->io_ptr), data, length, &check, NULL) ) | |||
| check = 0; | |||
| #else | |||
| check = fwrite(data, 1, length, (png_FILE_p)(png_ptr->io_ptr)); | |||
| #endif | |||
| if (check != length) | |||
| png_error(png_ptr, "Write Error"); | |||
| } | |||
| #else | |||
| /* this is the model-independent version. Since the standard I/O library | |||
| can't handle far buffers in the medium and small models, we have to copy | |||
| the data. | |||
| */ | |||
| #define NEAR_BUF_SIZE 1024 | |||
| #define MIN(a,b) (a <= b ? a : b) | |||
| void PNGAPI | |||
| png_default_write_data(png_structp png_ptr, png_bytep data, png_size_t length) | |||
| { | |||
| png_uint_32 check; | |||
| png_byte *near_data; /* Needs to be "png_byte *" instead of "png_bytep" */ | |||
| png_FILE_p io_ptr; | |||
| if(png_ptr == NULL) return; | |||
| /* Check if data really is near. If so, use usual code. */ | |||
| near_data = (png_byte *)CVT_PTR_NOCHECK(data); | |||
| io_ptr = (png_FILE_p)CVT_PTR(png_ptr->io_ptr); | |||
| if ((png_bytep)near_data == data) | |||
| { | |||
| #if defined(_WIN32_WCE) | |||
| if ( !WriteFile(io_ptr, near_data, length, &check, NULL) ) | |||
| check = 0; | |||
| #else | |||
| check = fwrite(near_data, 1, length, io_ptr); | |||
| #endif | |||
| } | |||
| else | |||
| { | |||
| png_byte buf[NEAR_BUF_SIZE]; | |||
| png_size_t written, remaining, err; | |||
| check = 0; | |||
| remaining = length; | |||
| do | |||
| { | |||
| written = MIN(NEAR_BUF_SIZE, remaining); | |||
| png_memcpy(buf, data, written); /* copy far buffer to near buffer */ | |||
| #if defined(_WIN32_WCE) | |||
| if ( !WriteFile(io_ptr, buf, written, &err, NULL) ) | |||
| err = 0; | |||
| #else | |||
| err = fwrite(buf, 1, written, io_ptr); | |||
| #endif | |||
| if (err != written) | |||
| break; | |||
| else | |||
| check += err; | |||
| data += written; | |||
| remaining -= written; | |||
| } | |||
| while (remaining != 0); | |||
| } | |||
| if (check != length) | |||
| png_error(png_ptr, "Write Error"); | |||
| } | |||
| #endif | |||
| #endif | |||
| /* This function is called to output any data pending writing (normally | |||
| to disk). After png_flush is called, there should be no data pending | |||
| writing in any buffers. */ | |||
| #if defined(PNG_WRITE_FLUSH_SUPPORTED) | |||
| void /* PRIVATE */ | |||
| png_flush(png_structp png_ptr) | |||
| { | |||
| if (png_ptr->output_flush_fn != NULL) | |||
| (*(png_ptr->output_flush_fn))(png_ptr); | |||
| } | |||
| #if !defined(PNG_NO_STDIO) | |||
| void PNGAPI | |||
| png_default_flush(png_structp png_ptr) | |||
| { | |||
| #if !defined(_WIN32_WCE) | |||
| png_FILE_p io_ptr; | |||
| #endif | |||
| if(png_ptr == NULL) return; | |||
| #if !defined(_WIN32_WCE) | |||
| io_ptr = (png_FILE_p)CVT_PTR((png_ptr->io_ptr)); | |||
| if (io_ptr != NULL) | |||
| fflush(io_ptr); | |||
| #endif | |||
| } | |||
| #endif | |||
| #endif | |||
| /* This function allows the application to supply new output functions for | |||
| libpng if standard C streams aren't being used. | |||
| This function takes as its arguments: | |||
| png_ptr - pointer to a png output data structure | |||
| io_ptr - pointer to user supplied structure containing info about | |||
| the output functions. May be NULL. | |||
| write_data_fn - pointer to a new output function that takes as its | |||
| arguments a pointer to a png_struct, a pointer to | |||
| data to be written, and a 32-bit unsigned int that is | |||
| the number of bytes to be written. The new write | |||
| function should call png_error(png_ptr, "Error msg") | |||
| to exit and output any fatal error messages. | |||
| flush_data_fn - pointer to a new flush function that takes as its | |||
| arguments a pointer to a png_struct. After a call to | |||
| the flush function, there should be no data in any buffers | |||
| or pending transmission. If the output method doesn't do | |||
| any buffering of ouput, a function prototype must still be | |||
| supplied although it doesn't have to do anything. If | |||
| PNG_WRITE_FLUSH_SUPPORTED is not defined at libpng compile | |||
| time, output_flush_fn will be ignored, although it must be | |||
| supplied for compatibility. */ | |||
| void PNGAPI | |||
| png_set_write_fn(png_structp png_ptr, png_voidp io_ptr, | |||
| png_rw_ptr write_data_fn, png_flush_ptr output_flush_fn) | |||
| { | |||
| if(png_ptr == NULL) return; | |||
| png_ptr->io_ptr = io_ptr; | |||
| #if !defined(PNG_NO_STDIO) | |||
| if (write_data_fn != NULL) | |||
| png_ptr->write_data_fn = write_data_fn; | |||
| else | |||
| png_ptr->write_data_fn = png_default_write_data; | |||
| #else | |||
| png_ptr->write_data_fn = write_data_fn; | |||
| #endif | |||
| #if defined(PNG_WRITE_FLUSH_SUPPORTED) | |||
| #if !defined(PNG_NO_STDIO) | |||
| if (output_flush_fn != NULL) | |||
| png_ptr->output_flush_fn = output_flush_fn; | |||
| else | |||
| png_ptr->output_flush_fn = png_default_flush; | |||
| #else | |||
| png_ptr->output_flush_fn = output_flush_fn; | |||
| #endif | |||
| #endif /* PNG_WRITE_FLUSH_SUPPORTED */ | |||
| /* It is an error to read while writing a png file */ | |||
| if (png_ptr->read_data_fn != NULL) | |||
| { | |||
| png_ptr->read_data_fn = NULL; | |||
| png_warning(png_ptr, | |||
| "Attempted to set both read_data_fn and write_data_fn in"); | |||
| png_warning(png_ptr, | |||
| "the same structure. Resetting read_data_fn to NULL."); | |||
| } | |||
| } | |||
| #if defined(USE_FAR_KEYWORD) | |||
| #if defined(_MSC_VER) | |||
| void *png_far_to_near(png_structp png_ptr,png_voidp ptr, int check) | |||
| { | |||
| void *near_ptr; | |||
| void FAR *far_ptr; | |||
| FP_OFF(near_ptr) = FP_OFF(ptr); | |||
| far_ptr = (void FAR *)near_ptr; | |||
| if(check != 0) | |||
| if(FP_SEG(ptr) != FP_SEG(far_ptr)) | |||
| png_error(png_ptr,"segment lost in conversion"); | |||
| return(near_ptr); | |||
| } | |||
| # else | |||
| void *png_far_to_near(png_structp png_ptr,png_voidp ptr, int check) | |||
| { | |||
| void *near_ptr; | |||
| void FAR *far_ptr; | |||
| near_ptr = (void FAR *)ptr; | |||
| far_ptr = (void FAR *)near_ptr; | |||
| if(check != 0) | |||
| if(far_ptr != ptr) | |||
| png_error(png_ptr,"segment lost in conversion"); | |||
| return(near_ptr); | |||
| } | |||
| # endif | |||
| # endif | |||
| #endif /* PNG_WRITE_SUPPORTED */ | |||
| @@ -64,7 +64,7 @@ BEGIN_JUCE_NAMESPACE | |||
| static void millisToLocal (const int64 millis, struct tm& result) throw() | |||
| { | |||
| const int64 seconds = millis / 1000; | |||
| if (seconds < literal64bit (86400) || seconds >= literal64bit (2145916800)) | |||
| { | |||
| // use extended maths for dates beyond 1970 to 2037.. | |||
| @@ -144,7 +144,7 @@ Time::Time (const int year, | |||
| const int timeZoneAdjustment = 31536000 - (int) (Time (1971, 0, 1, 0, 0).toMilliseconds() / 1000); | |||
| const int a = (13 - month) / 12; | |||
| const int y = year + 4800 - a; | |||
| const int jd = day + (153 * (month + 12 * a - 2) + 2) / 5 | |||
| const int jd = day + (153 * (month + 12 * a - 2) + 2) / 5 | |||
| + (y * 365) + (y / 4) - (y / 100) + (y / 400) | |||
| - 32045; | |||
| @@ -116,7 +116,7 @@ int InputStream::readCompressedInt() | |||
| int64 InputStream::readInt64() | |||
| { | |||
| char temp [8]; | |||
| if (read (temp, 8) == 8) | |||
| return (int64) swapIfBigEndian (*(uint64*)temp); | |||
| else | |||
| @@ -126,7 +126,7 @@ int64 InputStream::readInt64() | |||
| int64 InputStream::readInt64BigEndian() | |||
| { | |||
| char temp [8]; | |||
| if (read (temp, 8) == 8) | |||
| return (int64) swapIfLittleEndian (*(uint64*)temp); | |||
| else | |||