| @@ -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); | peer->doDragDropMove (theEvent); | ||||
| return noErr; | return noErr; | ||||
| case kEventControlDragLeave: | |||||
| case kEventControlDragLeave: | |||||
| peer->doDragDropExit (theEvent); | peer->doDragDropExit (theEvent); | ||||
| return noErr; | return noErr; | ||||
| @@ -791,7 +791,7 @@ public: | |||||
| { | { | ||||
| case kVstSmpte24fps: | case kVstSmpte24fps: | ||||
| rate = AudioPlayHead::fps24; | rate = AudioPlayHead::fps24; | ||||
| fps = 24.0; | |||||
| fps = 24.0; | |||||
| break; | break; | ||||
| case kVstSmpte25fps: | case kVstSmpte25fps: | ||||
| @@ -806,22 +806,22 @@ public: | |||||
| case kVstSmpte30fps: | case kVstSmpte30fps: | ||||
| rate = AudioPlayHead::fps30; | rate = AudioPlayHead::fps30; | ||||
| fps = 30.0; | |||||
| fps = 30.0; | |||||
| break; | break; | ||||
| case kVstSmpte2997dfps: | |||||
| case kVstSmpte2997dfps: | |||||
| rate = AudioPlayHead::fps2997drop; | rate = AudioPlayHead::fps2997drop; | ||||
| fps = 29.97; | |||||
| fps = 29.97; | |||||
| break; | break; | ||||
| case kVstSmpte30dfps: | case kVstSmpte30dfps: | ||||
| rate = AudioPlayHead::fps30drop; | rate = AudioPlayHead::fps30drop; | ||||
| fps = 30.0; | |||||
| fps = 30.0; | |||||
| break; | break; | ||||
| case kVstSmpteFilm16mm: | case kVstSmpteFilm16mm: | ||||
| case kVstSmpteFilm35mm: | case kVstSmpteFilm35mm: | ||||
| fps = 24.0; | |||||
| fps = 24.0; | |||||
| break; | break; | ||||
| case kVstSmpte239fps: fps = 23.976; break; | case kVstSmpte239fps: fps = 23.976; break; | ||||
| @@ -1019,7 +1019,7 @@ public: | |||||
| void doIdleCallback() | void doIdleCallback() | ||||
| { | { | ||||
| // (wavelab calls this on a separate thread and causes a deadlock).. | // (wavelab calls this on a separate thread and causes a deadlock).. | ||||
| if (MessageManager::getInstance()->isThisTheMessageThread() | |||||
| if (MessageManager::getInstance()->isThisTheMessageThread() | |||||
| && ! recursionCheck) | && ! recursionCheck) | ||||
| { | { | ||||
| const MessageManagerLock mml; | 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,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}; | 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; | 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, | 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}; | 96,130,0,0}; | ||||
| const char* BinaryData::prefs_misc_png = (const char*) temp4; | 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()); | button.isConnectedOnBottom()); | ||||
| } | } | ||||
| void LookAndFeel::drawButtonText (Graphics& g, TextButton& button, | |||||
| void LookAndFeel::drawButtonText (Graphics& g, TextButton& button, | |||||
| bool /*isMouseOverButton*/, bool /*isButtonDown*/) | bool /*isMouseOverButton*/, bool /*isButtonDown*/) | ||||
| { | { | ||||
| g.setFont (button.getFont()); | g.setFont (button.getFont()); | ||||
| @@ -132,7 +132,7 @@ public: | |||||
| bool isButtonDown); | bool isButtonDown); | ||||
| /** Draws the text for a TextButton. */ | /** Draws the text for a TextButton. */ | ||||
| virtual void drawButtonText (Graphics& g, | |||||
| virtual void drawButtonText (Graphics& g, | |||||
| TextButton& button, | TextButton& button, | ||||
| bool isMouseOverButton, | bool isMouseOverButton, | ||||
| bool isButtonDown); | bool isButtonDown); | ||||
| @@ -389,7 +389,7 @@ | |||||
| #define PNG_LIBPNG_BUILD_RC 3 | #define PNG_LIBPNG_BUILD_RC 3 | ||||
| #define PNG_LIBPNG_BUILD_STABLE 4 | #define PNG_LIBPNG_BUILD_STABLE 4 | ||||
| #define PNG_LIBPNG_BUILD_RELEASE_STATUS_MASK 7 | #define PNG_LIBPNG_BUILD_RELEASE_STATUS_MASK 7 | ||||
| /* Release-Specific Flags */ | /* Release-Specific Flags */ | ||||
| #define PNG_LIBPNG_BUILD_PATCH 8 /* Can be OR'ed with | #define PNG_LIBPNG_BUILD_PATCH 8 /* Can be OR'ed with | ||||
| PNG_LIBPNG_BUILD_STABLE only */ | PNG_LIBPNG_BUILD_STABLE only */ | ||||
| @@ -424,12 +424,12 @@ | |||||
| /* Ref MSDN: Private as priority over Special | /* Ref MSDN: Private as priority over Special | ||||
| * VS_FF_PRIVATEBUILD File *was not* built using standard release | * VS_FF_PRIVATEBUILD File *was not* built using standard release | ||||
| * procedures. If this value is given, the StringFileInfo block must | * 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 | * VS_FF_SPECIALBUILD File *was* built by the original company using | ||||
| * standard release procedures but is a variation of the standard | * standard release procedures but is a variation of the standard | ||||
| * file of the same version number. If this value is given, the | * 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) | #if defined(PNG_USER_PRIVATEBUILD) | ||||
| @@ -42,7 +42,7 @@ | |||||
| //============================================================================== | //============================================================================== | ||||
| /* | |||||
| /* | |||||
| * PNG_USER_CONFIG has to be defined on the compiler command line. This | * PNG_USER_CONFIG has to be defined on the compiler command line. This | ||||
| * includes the resource compiler for Windows DLL configurations. | * includes the resource compiler for Windows DLL configurations. | ||||
| */ | */ | ||||
| @@ -62,7 +62,7 @@ | |||||
| /* | /* | ||||
| * Added at libpng-1.2.8 | * Added at libpng-1.2.8 | ||||
| * | |||||
| * | |||||
| * If you create a private DLL you need to define in "pngusr.h" the followings: | * 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 | * #define PNG_USER_PRIVATEBUILD <Describes by whom and why this version of | ||||
| * the DLL was built> | * the DLL was built> | ||||
| @@ -73,8 +73,8 @@ | |||||
| * number and must match your private DLL name> | * number and must match your private DLL name> | ||||
| * e.g. // private DLL "libpng13gx.dll" | * e.g. // private DLL "libpng13gx.dll" | ||||
| * #define PNG_USER_DLLFNAME_POSTFIX "gx" | * #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. | * DLL VERSIONINFO structure. | ||||
| * - PNG_USER_VERSIONINFO_COMMENTS | * - PNG_USER_VERSIONINFO_COMMENTS | ||||
| * - PNG_USER_VERSIONINFO_COMPANYNAME | * - PNG_USER_VERSIONINFO_COMPANYNAME | ||||
| @@ -167,9 +167,9 @@ | |||||
| * 'Cygwin' defines/defaults: | * 'Cygwin' defines/defaults: | ||||
| * PNG_BUILD_DLL -- (ignored) building the dll | * PNG_BUILD_DLL -- (ignored) building the dll | ||||
| * (no define) -- (ignored) building an application, linking to 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. | * 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. | * application that links to the static libs. | ||||
| * Thus, | * Thus, | ||||
| * a cygwin user should define either PNG_BUILD_DLL or PNG_STATIC, and | * a cygwin user should define either PNG_BUILD_DLL or PNG_STATIC, and | ||||
| @@ -182,12 +182,12 @@ | |||||
| * PNG_BUILD_DLL | * PNG_BUILD_DLL | ||||
| * PNG_STATIC | * PNG_STATIC | ||||
| * (nothing) == PNG_USE_DLL | * (nothing) == PNG_USE_DLL | ||||
| * | |||||
| * | |||||
| * CYGWIN (2002-01-20): The preceding is now obsolete. With the advent | * 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, | * __declspec(dllexport) / __declspec(dllimport) and friends. Therefore, | ||||
| * we don't need to worry about PNG_STATIC or ALL_STATIC when it comes | * 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 | * PNG_BUILD_DLL and PNG_STATIC because those change some defaults | ||||
| * such as CONSOLE_IO and whether GLOBAL_ARRAYS are allowed. | * such as CONSOLE_IO and whether GLOBAL_ARRAYS are allowed. | ||||
| */ | */ | ||||
| @@ -231,8 +231,8 @@ | |||||
| # if !defined(PNG_DLL) | # if !defined(PNG_DLL) | ||||
| # define PNG_DLL | # define PNG_DLL | ||||
| # endif | # endif | ||||
| # endif | |||||
| # endif | |||||
| # endif | |||||
| # endif | |||||
| # endif | # endif | ||||
| #endif | #endif | ||||
| @@ -749,7 +749,7 @@ | |||||
| # define PNG_EASY_ACCESS_SUPPORTED | # define PNG_EASY_ACCESS_SUPPORTED | ||||
| #endif | #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 | * and removed from version 1.2.20. The following will be removed | ||||
| * from libpng-1.4.0 | * from libpng-1.4.0 | ||||
| */ | */ | ||||
| @@ -1324,7 +1324,7 @@ typedef z_stream FAR * png_zstreamp; | |||||
| # define PNGAPI __cdecl | # define PNGAPI __cdecl | ||||
| # undef PNG_IMPEXP | # undef PNG_IMPEXP | ||||
| # define PNG_IMPEXP | # define PNG_IMPEXP | ||||
| #endif | |||||
| #endif | |||||
| /* If you define PNGAPI, e.g., with compiler option "-DPNGAPI=__stdcall", | /* If you define PNGAPI, e.g., with compiler option "-DPNGAPI=__stdcall", | ||||
| * you may get warnings regarding the linkage of png_zalloc and png_zfree. | * 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() | static void millisToLocal (const int64 millis, struct tm& result) throw() | ||||
| { | { | ||||
| const int64 seconds = millis / 1000; | const int64 seconds = millis / 1000; | ||||
| if (seconds < literal64bit (86400) || seconds >= literal64bit (2145916800)) | if (seconds < literal64bit (86400) || seconds >= literal64bit (2145916800)) | ||||
| { | { | ||||
| // use extended maths for dates beyond 1970 to 2037.. | // 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 timeZoneAdjustment = 31536000 - (int) (Time (1971, 0, 1, 0, 0).toMilliseconds() / 1000); | ||||
| const int a = (13 - month) / 12; | const int a = (13 - month) / 12; | ||||
| const int y = year + 4800 - a; | 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) | + (y * 365) + (y / 4) - (y / 100) + (y / 400) | ||||
| - 32045; | - 32045; | ||||
| @@ -116,7 +116,7 @@ int InputStream::readCompressedInt() | |||||
| int64 InputStream::readInt64() | int64 InputStream::readInt64() | ||||
| { | { | ||||
| char temp [8]; | char temp [8]; | ||||
| if (read (temp, 8) == 8) | if (read (temp, 8) == 8) | ||||
| return (int64) swapIfBigEndian (*(uint64*)temp); | return (int64) swapIfBigEndian (*(uint64*)temp); | ||||
| else | else | ||||
| @@ -126,7 +126,7 @@ int64 InputStream::readInt64() | |||||
| int64 InputStream::readInt64BigEndian() | int64 InputStream::readInt64BigEndian() | ||||
| { | { | ||||
| char temp [8]; | char temp [8]; | ||||
| if (read (temp, 8) == 8) | if (read (temp, 8) == 8) | ||||
| return (int64) swapIfLittleEndian (*(uint64*)temp); | return (int64) swapIfLittleEndian (*(uint64*)temp); | ||||
| else | else | ||||