Browse Source

New TextEditorKeyMapper class added to simplify text navigation key interpretation. Removed a problematic spinlock from the Timer code. Added an error callback to AudioIODeviceCallback.

tags/2021-05-28
Julian Storer 14 years ago
parent
commit
df2526e33b
23 changed files with 1841 additions and 1546 deletions
  1. +2
    -0
      Builds/MacOSX/Juce.xcodeproj/project.pbxproj
  2. +1
    -0
      Builds/VisualStudio2005/Juce.vcproj
  3. +1
    -0
      Builds/VisualStudio2008/Juce.vcproj
  4. +1
    -0
      Builds/VisualStudio2008_DLL/Juce.vcproj
  5. +1
    -0
      Builds/VisualStudio2010/Juce.vcxproj
  6. +3
    -0
      Builds/VisualStudio2010/Juce.vcxproj.filters
  7. +2
    -0
      Builds/iOS/Juce.xcodeproj/project.pbxproj
  8. +2
    -0
      Juce.jucer
  9. +881
    -1039
      juce_amalgamated.cpp
  10. +419
    -42
      juce_amalgamated.h
  11. +2
    -0
      src/audio/devices/juce_AudioIODevice.cpp
  12. +7
    -2
      src/audio/devices/juce_AudioIODevice.h
  13. +1
    -1
      src/core/juce_StandardHeader.h
  14. +2
    -2
      src/events/juce_Timer.cpp
  15. +70
    -129
      src/gui/components/code_editor/juce_CodeEditorComponent.cpp
  16. +23
    -26
      src/gui/components/code_editor/juce_CodeEditorComponent.h
  17. +194
    -173
      src/gui/components/controls/juce_TextEditor.cpp
  18. +24
    -1
      src/gui/components/controls/juce_TextEditor.h
  19. +132
    -0
      src/gui/components/keyboard/juce_TextEditorKeyMapper.h
  20. +8
    -7
      src/gui/graphics/imaging/image_file_formats/juce_GIFLoader.cpp
  21. +1
    -1
      src/io/files/juce_FileOutputStream.cpp
  22. +3
    -0
      src/juce_app_includes.h
  23. +61
    -123
      src/native/mac/juce_mac_CoreAudio.cpp

+ 2
- 0
Builds/MacOSX/Juce.xcodeproj/project.pbxproj View File

@@ -682,6 +682,7 @@
15C6FD019B274AA51B4E2D76 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_KeyPressMappingSet.h; path = ../../src/gui/components/keyboard/juce_KeyPressMappingSet.h; sourceTree = SOURCE_ROOT; }; 15C6FD019B274AA51B4E2D76 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_KeyPressMappingSet.h; path = ../../src/gui/components/keyboard/juce_KeyPressMappingSet.h; sourceTree = SOURCE_ROOT; };
B1E8FF009812F29C2620E6BB = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = juce_ModifierKeys.cpp; path = ../../src/gui/components/keyboard/juce_ModifierKeys.cpp; sourceTree = SOURCE_ROOT; }; B1E8FF009812F29C2620E6BB = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = juce_ModifierKeys.cpp; path = ../../src/gui/components/keyboard/juce_ModifierKeys.cpp; sourceTree = SOURCE_ROOT; };
FAEEA3536AD17B2667A1BB94 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_ModifierKeys.h; path = ../../src/gui/components/keyboard/juce_ModifierKeys.h; sourceTree = SOURCE_ROOT; }; FAEEA3536AD17B2667A1BB94 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_ModifierKeys.h; path = ../../src/gui/components/keyboard/juce_ModifierKeys.h; sourceTree = SOURCE_ROOT; };
D64DD9F41E4598606855DFCF = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_TextEditorKeyMapper.h; path = ../../src/gui/components/keyboard/juce_TextEditorKeyMapper.h; sourceTree = SOURCE_ROOT; };
7356F5E93CEA4D472D83D8E5 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_TextInputTarget.h; path = ../../src/gui/components/keyboard/juce_TextInputTarget.h; sourceTree = SOURCE_ROOT; }; 7356F5E93CEA4D472D83D8E5 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_TextInputTarget.h; path = ../../src/gui/components/keyboard/juce_TextInputTarget.h; sourceTree = SOURCE_ROOT; };
921B616E2229AEB6390D2B57 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = juce_ComponentAnimator.cpp; path = ../../src/gui/components/layout/juce_ComponentAnimator.cpp; sourceTree = SOURCE_ROOT; }; 921B616E2229AEB6390D2B57 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = juce_ComponentAnimator.cpp; path = ../../src/gui/components/layout/juce_ComponentAnimator.cpp; sourceTree = SOURCE_ROOT; };
FE1072B5FB77E8FEE1BEBDFE = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_ComponentAnimator.h; path = ../../src/gui/components/layout/juce_ComponentAnimator.h; sourceTree = SOURCE_ROOT; }; FE1072B5FB77E8FEE1BEBDFE = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_ComponentAnimator.h; path = ../../src/gui/components/layout/juce_ComponentAnimator.h; sourceTree = SOURCE_ROOT; };
@@ -1447,6 +1448,7 @@
15C6FD019B274AA51B4E2D76, 15C6FD019B274AA51B4E2D76,
B1E8FF009812F29C2620E6BB, B1E8FF009812F29C2620E6BB,
FAEEA3536AD17B2667A1BB94, FAEEA3536AD17B2667A1BB94,
D64DD9F41E4598606855DFCF,
7356F5E93CEA4D472D83D8E5 ); name = keyboard; sourceTree = "<group>"; }; 7356F5E93CEA4D472D83D8E5 ); name = keyboard; sourceTree = "<group>"; };
D75AAB3AB61247E962C00692 = { isa = PBXGroup; children = ( D75AAB3AB61247E962C00692 = { isa = PBXGroup; children = (
921B616E2229AEB6390D2B57, 921B616E2229AEB6390D2B57,


+ 1
- 0
Builds/VisualStudio2005/Juce.vcproj View File

@@ -532,6 +532,7 @@
<File RelativePath="..\..\src\gui\components\keyboard\juce_KeyPressMappingSet.h"/> <File RelativePath="..\..\src\gui\components\keyboard\juce_KeyPressMappingSet.h"/>
<File RelativePath="..\..\src\gui\components\keyboard\juce_ModifierKeys.cpp"/> <File RelativePath="..\..\src\gui\components\keyboard\juce_ModifierKeys.cpp"/>
<File RelativePath="..\..\src\gui\components\keyboard\juce_ModifierKeys.h"/> <File RelativePath="..\..\src\gui\components\keyboard\juce_ModifierKeys.h"/>
<File RelativePath="..\..\src\gui\components\keyboard\juce_TextEditorKeyMapper.h"/>
<File RelativePath="..\..\src\gui\components\keyboard\juce_TextInputTarget.h"/> <File RelativePath="..\..\src\gui\components\keyboard\juce_TextInputTarget.h"/>
</Filter> </Filter>
<Filter Name="layout"> <Filter Name="layout">


+ 1
- 0
Builds/VisualStudio2008/Juce.vcproj View File

@@ -532,6 +532,7 @@
<File RelativePath="..\..\src\gui\components\keyboard\juce_KeyPressMappingSet.h"/> <File RelativePath="..\..\src\gui\components\keyboard\juce_KeyPressMappingSet.h"/>
<File RelativePath="..\..\src\gui\components\keyboard\juce_ModifierKeys.cpp"/> <File RelativePath="..\..\src\gui\components\keyboard\juce_ModifierKeys.cpp"/>
<File RelativePath="..\..\src\gui\components\keyboard\juce_ModifierKeys.h"/> <File RelativePath="..\..\src\gui\components\keyboard\juce_ModifierKeys.h"/>
<File RelativePath="..\..\src\gui\components\keyboard\juce_TextEditorKeyMapper.h"/>
<File RelativePath="..\..\src\gui\components\keyboard\juce_TextInputTarget.h"/> <File RelativePath="..\..\src\gui\components\keyboard\juce_TextInputTarget.h"/>
</Filter> </Filter>
<Filter Name="layout"> <Filter Name="layout">


+ 1
- 0
Builds/VisualStudio2008_DLL/Juce.vcproj View File

@@ -534,6 +534,7 @@
<File RelativePath="..\..\src\gui\components\keyboard\juce_KeyPressMappingSet.h"/> <File RelativePath="..\..\src\gui\components\keyboard\juce_KeyPressMappingSet.h"/>
<File RelativePath="..\..\src\gui\components\keyboard\juce_ModifierKeys.cpp"/> <File RelativePath="..\..\src\gui\components\keyboard\juce_ModifierKeys.cpp"/>
<File RelativePath="..\..\src\gui\components\keyboard\juce_ModifierKeys.h"/> <File RelativePath="..\..\src\gui\components\keyboard\juce_ModifierKeys.h"/>
<File RelativePath="..\..\src\gui\components\keyboard\juce_TextEditorKeyMapper.h"/>
<File RelativePath="..\..\src\gui\components\keyboard\juce_TextInputTarget.h"/> <File RelativePath="..\..\src\gui\components\keyboard\juce_TextInputTarget.h"/>
</Filter> </Filter>
<Filter Name="layout"> <Filter Name="layout">


+ 1
- 0
Builds/VisualStudio2010/Juce.vcxproj View File

@@ -626,6 +626,7 @@
<ClInclude Include="..\..\src\gui\components\keyboard\juce_KeyPress.h"/> <ClInclude Include="..\..\src\gui\components\keyboard\juce_KeyPress.h"/>
<ClInclude Include="..\..\src\gui\components\keyboard\juce_KeyPressMappingSet.h"/> <ClInclude Include="..\..\src\gui\components\keyboard\juce_KeyPressMappingSet.h"/>
<ClInclude Include="..\..\src\gui\components\keyboard\juce_ModifierKeys.h"/> <ClInclude Include="..\..\src\gui\components\keyboard\juce_ModifierKeys.h"/>
<ClInclude Include="..\..\src\gui\components\keyboard\juce_TextEditorKeyMapper.h"/>
<ClInclude Include="..\..\src\gui\components\keyboard\juce_TextInputTarget.h"/> <ClInclude Include="..\..\src\gui\components\keyboard\juce_TextInputTarget.h"/>
<ClInclude Include="..\..\src\gui\components\layout\juce_ComponentAnimator.h"/> <ClInclude Include="..\..\src\gui\components\layout\juce_ComponentAnimator.h"/>
<ClInclude Include="..\..\src\gui\components\layout\juce_ComponentBoundsConstrainer.h"/> <ClInclude Include="..\..\src\gui\components\layout\juce_ComponentBoundsConstrainer.h"/>


+ 3
- 0
Builds/VisualStudio2010/Juce.vcxproj.filters View File

@@ -1809,6 +1809,9 @@
<ClInclude Include="..\..\src\gui\components\keyboard\juce_ModifierKeys.h"> <ClInclude Include="..\..\src\gui\components\keyboard\juce_ModifierKeys.h">
<Filter>Juce\Source\gui\components\keyboard</Filter> <Filter>Juce\Source\gui\components\keyboard</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\..\src\gui\components\keyboard\juce_TextEditorKeyMapper.h">
<Filter>Juce\Source\gui\components\keyboard</Filter>
</ClInclude>
<ClInclude Include="..\..\src\gui\components\keyboard\juce_TextInputTarget.h"> <ClInclude Include="..\..\src\gui\components\keyboard\juce_TextInputTarget.h">
<Filter>Juce\Source\gui\components\keyboard</Filter> <Filter>Juce\Source\gui\components\keyboard</Filter>
</ClInclude> </ClInclude>


+ 2
- 0
Builds/iOS/Juce.xcodeproj/project.pbxproj View File

@@ -682,6 +682,7 @@
15C6FD019B274AA51B4E2D76 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_KeyPressMappingSet.h; path = ../../src/gui/components/keyboard/juce_KeyPressMappingSet.h; sourceTree = SOURCE_ROOT; }; 15C6FD019B274AA51B4E2D76 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_KeyPressMappingSet.h; path = ../../src/gui/components/keyboard/juce_KeyPressMappingSet.h; sourceTree = SOURCE_ROOT; };
B1E8FF009812F29C2620E6BB = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = juce_ModifierKeys.cpp; path = ../../src/gui/components/keyboard/juce_ModifierKeys.cpp; sourceTree = SOURCE_ROOT; }; B1E8FF009812F29C2620E6BB = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = juce_ModifierKeys.cpp; path = ../../src/gui/components/keyboard/juce_ModifierKeys.cpp; sourceTree = SOURCE_ROOT; };
FAEEA3536AD17B2667A1BB94 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_ModifierKeys.h; path = ../../src/gui/components/keyboard/juce_ModifierKeys.h; sourceTree = SOURCE_ROOT; }; FAEEA3536AD17B2667A1BB94 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_ModifierKeys.h; path = ../../src/gui/components/keyboard/juce_ModifierKeys.h; sourceTree = SOURCE_ROOT; };
D64DD9F41E4598606855DFCF = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_TextEditorKeyMapper.h; path = ../../src/gui/components/keyboard/juce_TextEditorKeyMapper.h; sourceTree = SOURCE_ROOT; };
7356F5E93CEA4D472D83D8E5 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_TextInputTarget.h; path = ../../src/gui/components/keyboard/juce_TextInputTarget.h; sourceTree = SOURCE_ROOT; }; 7356F5E93CEA4D472D83D8E5 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_TextInputTarget.h; path = ../../src/gui/components/keyboard/juce_TextInputTarget.h; sourceTree = SOURCE_ROOT; };
921B616E2229AEB6390D2B57 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = juce_ComponentAnimator.cpp; path = ../../src/gui/components/layout/juce_ComponentAnimator.cpp; sourceTree = SOURCE_ROOT; }; 921B616E2229AEB6390D2B57 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = juce_ComponentAnimator.cpp; path = ../../src/gui/components/layout/juce_ComponentAnimator.cpp; sourceTree = SOURCE_ROOT; };
FE1072B5FB77E8FEE1BEBDFE = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_ComponentAnimator.h; path = ../../src/gui/components/layout/juce_ComponentAnimator.h; sourceTree = SOURCE_ROOT; }; FE1072B5FB77E8FEE1BEBDFE = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_ComponentAnimator.h; path = ../../src/gui/components/layout/juce_ComponentAnimator.h; sourceTree = SOURCE_ROOT; };
@@ -1447,6 +1448,7 @@
15C6FD019B274AA51B4E2D76, 15C6FD019B274AA51B4E2D76,
B1E8FF009812F29C2620E6BB, B1E8FF009812F29C2620E6BB,
FAEEA3536AD17B2667A1BB94, FAEEA3536AD17B2667A1BB94,
D64DD9F41E4598606855DFCF,
7356F5E93CEA4D472D83D8E5 ); name = keyboard; sourceTree = "<group>"; }; 7356F5E93CEA4D472D83D8E5 ); name = keyboard; sourceTree = "<group>"; };
D75AAB3AB61247E962C00692 = { isa = PBXGroup; children = ( D75AAB3AB61247E962C00692 = { isa = PBXGroup; children = (
921B616E2229AEB6390D2B57, 921B616E2229AEB6390D2B57,


+ 2
- 0
Juce.jucer View File

@@ -713,6 +713,8 @@
file="src/gui/components/keyboard/juce_ModifierKeys.cpp"/> file="src/gui/components/keyboard/juce_ModifierKeys.cpp"/>
<FILE id="sEv20iWws" name="juce_ModifierKeys.h" compile="0" resource="0" <FILE id="sEv20iWws" name="juce_ModifierKeys.h" compile="0" resource="0"
file="src/gui/components/keyboard/juce_ModifierKeys.h"/> file="src/gui/components/keyboard/juce_ModifierKeys.h"/>
<FILE id="ohA4B9" name="juce_TextEditorKeyMapper.h" compile="0" resource="0"
file="src/gui/components/keyboard/juce_TextEditorKeyMapper.h"/>
<FILE id="xafOvZlQw" name="juce_TextInputTarget.h" compile="0" resource="0" <FILE id="xafOvZlQw" name="juce_TextInputTarget.h" compile="0" resource="0"
file="src/gui/components/keyboard/juce_TextInputTarget.h"/> file="src/gui/components/keyboard/juce_TextInputTarget.h"/>
</GROUP> </GROUP>


+ 881
- 1039
juce_amalgamated.cpp
File diff suppressed because it is too large
View File


+ 419
- 42
juce_amalgamated.h View File

@@ -73,7 +73,7 @@ namespace JuceDummyNamespace {}
*/ */
#define JUCE_MAJOR_VERSION 1 #define JUCE_MAJOR_VERSION 1
#define JUCE_MINOR_VERSION 53 #define JUCE_MINOR_VERSION 53
#define JUCE_BUILDNUMBER 89
#define JUCE_BUILDNUMBER 90


/** Current Juce version number. /** Current Juce version number.


@@ -1647,8 +1647,8 @@ public:
template <typename CharPointerType> template <typename CharPointerType>
static double readDoubleValue (CharPointerType& text) noexcept static double readDoubleValue (CharPointerType& text) noexcept
{ {
double result[3] = { 0, 0, 0 }, accumulator[2] = { 0, 0 };
int exponentAdjustment[2] = { 0, 0 }, exponentAccumulator[2] = { -1, -1 };
double result[3] = { 0 }, accumulator[2] = { 0 };
int exponentAdjustment[2] = { 0 }, exponentAccumulator[2] = { -1, -1 };
int exponent = 0, decPointIndex = 0, digit = 0; int exponent = 0, decPointIndex = 0, digit = 0;
int lastDigit = 0, numSignificantDigits = 0; int lastDigit = 0, numSignificantDigits = 0;
bool isNegative = false, digitsFound = false; bool isNegative = false, digitsFound = false;
@@ -8734,16 +8734,16 @@ public:
var (ReferenceCountedObject* object); var (ReferenceCountedObject* object);
var (MethodFunction method) noexcept; var (MethodFunction method) noexcept;


var& operator= (const var& valueToCopy);
var& operator= (int value);
var& operator= (int64 value);
var& operator= (bool value);
var& operator= (double value);
var& operator= (const char* value);
var& operator= (const wchar_t* value);
var& operator= (const String& value);
var& operator= (ReferenceCountedObject* object);
var& operator= (MethodFunction method);
const var& operator= (const var& valueToCopy);
const var& operator= (int value);
const var& operator= (int64 value);
const var& operator= (bool value);
const var& operator= (double value);
const var& operator= (const char* value);
const var& operator= (const wchar_t* value);
const var& operator= (const String& value);
const var& operator= (ReferenceCountedObject* object);
const var& operator= (MethodFunction method);


void swapWith (var& other) noexcept; void swapWith (var& other) noexcept;


@@ -18835,6 +18835,8 @@ private:
bool negative; bool negative;


void ensureSize (int numVals); void ensureSize (int numVals);
void shiftLeft (int bits, int startBit);
void shiftRight (int bits, int startBit);
static const BigInteger simpleGCD (BigInteger* m, BigInteger* n); static const BigInteger simpleGCD (BigInteger* m, BigInteger* n);


static inline int bitToIndex (const int bit) noexcept { return bit >> 5; } static inline int bitToIndex (const int bit) noexcept { return bit >> 5; }
@@ -19258,6 +19260,7 @@ private:
void openHandle(); void openHandle();
void closeHandle(); void closeHandle();
void flushInternal(); void flushInternal();
bool flushBuffer();
int64 setPositionInternal (int64 newPosition); int64 setPositionInternal (int64 newPosition);
int writeInternal (const void* data, int numBytes); int writeInternal (const void* data, int numBytes);


@@ -20835,6 +20838,7 @@ private:
friend class ScopedPointer <GZIPCompressorHelper>; friend class ScopedPointer <GZIPCompressorHelper>;
ScopedPointer <GZIPCompressorHelper> helper; ScopedPointer <GZIPCompressorHelper> helper;
bool doNextBlock(); bool doNextBlock();
void flushInternal();


JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (GZIPCompressorOutputStream); JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (GZIPCompressorOutputStream);
}; };
@@ -21077,6 +21081,8 @@ private:
MemoryBlock internalBlock; MemoryBlock internalBlock;
size_t position, size; size_t position, size;


void trimExternalBlockSize();

JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MemoryOutputStream); JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MemoryOutputStream);
}; };


@@ -38124,9 +38130,14 @@ public:
*/ */
virtual void audioDeviceAboutToStart (AudioIODevice* device) = 0; virtual void audioDeviceAboutToStart (AudioIODevice* device) = 0;


/** Called to indicate that the device has stopped.
*/
/** Called to indicate that the device has stopped. */
virtual void audioDeviceStopped() = 0; virtual void audioDeviceStopped() = 0;

/** This can be overridden to be told if the device generates an error while operating.
Be aware that this could be called by any thread! And not all devices perform
this callback.
*/
virtual void audioDeviceError (const String& errorMessage);
}; };


/** /**
@@ -38728,6 +38739,8 @@ private:
int blockSize, readAheadBufferSize; int blockSize, readAheadBufferSize;
bool isPrepared, inputStreamEOF; bool isPrepared, inputStreamEOF;


void releaseMasterResources();

JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AudioTransportSource); JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AudioTransportSource);
}; };


@@ -42920,6 +42933,27 @@ public:
/** @internal */ /** @internal */
void setTemporaryUnderlining (const Array <Range<int> >&); void setTemporaryUnderlining (const Array <Range<int> >&);


bool moveCaretLeft (bool moveInWholeWordSteps, bool selecting);
bool moveCaretRight (bool moveInWholeWordSteps, bool selecting);
bool moveCaretUp (bool selecting);
bool moveCaretDown (bool selecting);
bool pageUp (bool selecting);
bool pageDown (bool selecting);
bool scrollDown();
bool scrollUp();
bool moveCaretToTop (bool selecting);
bool moveCaretToStartOfLine (bool selecting);
bool moveCaretToEnd (bool selecting);
bool moveCaretToEndOfLine (bool selecting);
bool deleteBackwards (bool moveInWholeWordSteps);
bool deleteForwards (bool moveInWholeWordSteps);
bool copyToClipboard();
bool cutToClipboard();
bool pasteFromClipboard();
bool selectAll();
bool undo();
bool redo();

/** This adds the items to the popup menu. /** This adds the items to the popup menu.


By default it adds the cut/copy/paste items, but you can override this if By default it adds the cut/copy/paste items, but you can override this if
@@ -43052,7 +43086,7 @@ private:
int indexAtPosition (float x, float y); int indexAtPosition (float x, float y);
int findWordBreakAfter (int position) const; int findWordBreakAfter (int position) const;
int findWordBreakBefore (int position) const; int findWordBreakBefore (int position) const;
bool moveCaretWithTransation (int newPos, bool selecting);
friend class TextHolderComponent; friend class TextHolderComponent;
friend class TextEditorViewport; friend class TextEditorViewport;
void drawContent (Graphics& g); void drawContent (Graphics& g);
@@ -43060,6 +43094,8 @@ private:
float getWordWrapWidth() const; float getWordWrapWidth() const;
void timerCallbackInt(); void timerCallbackInt();
void repaintText (const Range<int>& range); void repaintText (const Range<int>& range);
void scrollByLines (int deltaLines);
bool undoOrRedo (bool shouldUndo);
UndoManager* getUndoManager() noexcept; UndoManager* getUndoManager() noexcept;


JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (TextEditor); JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (TextEditor);
@@ -47364,6 +47400,7 @@ private:
void scanFor (AudioPluginFormat* format); void scanFor (AudioPluginFormat* format);
static void optionsMenuStaticCallback (int result, PluginListComponent*); static void optionsMenuStaticCallback (int result, PluginListComponent*);
void optionsMenuCallback (int result); void optionsMenuCallback (int result);
void updateList();


JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (PluginListComponent); JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (PluginListComponent);
}; };
@@ -49522,6 +49559,8 @@ private:
Path path; Path path;
int offset; int offset;


void updateShadowAndOffset();

JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ArrowButton); JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ArrowButton);
}; };


@@ -52238,40 +52277,36 @@ public:
*/ */
const CodeDocument::Position getPositionAt (int x, int y); const CodeDocument::Position getPositionAt (int x, int y);


void cursorLeft (bool moveInWholeWordSteps, bool selecting);
void cursorRight (bool moveInWholeWordSteps, bool selecting);
void cursorDown (bool selecting);
void cursorUp (bool selecting);
bool moveCaretLeft (bool moveInWholeWordSteps, bool selecting);
bool moveCaretRight (bool moveInWholeWordSteps, bool selecting);
bool moveCaretUp (bool selecting);
bool moveCaretDown (bool selecting);
bool scrollDown();
bool scrollUp();
bool pageUp (bool selecting);
bool pageDown (bool selecting);
bool moveCaretToTop (bool selecting);
bool moveCaretToStartOfLine (bool selecting);
bool moveCaretToEnd (bool selecting);
bool moveCaretToEndOfLine (bool selecting);
bool deleteBackwards (bool moveInWholeWordSteps);
bool deleteForwards (bool moveInWholeWordSteps);
bool copyToClipboard();
bool cutToClipboard();
bool pasteFromClipboard();
bool undo();
bool redo();


void pageDown (bool selecting);
void pageUp (bool selecting);
bool selectAll();
void deselectAll();


void scrollDown();
void scrollUp();
void scrollToLine (int newFirstLineOnScreen); void scrollToLine (int newFirstLineOnScreen);
void scrollBy (int deltaLines); void scrollBy (int deltaLines);
void scrollToColumn (int newFirstColumnOnScreen); void scrollToColumn (int newFirstColumnOnScreen);
void scrollToKeepCaretOnScreen(); void scrollToKeepCaretOnScreen();


void goToStartOfDocument (bool selecting);
void goToStartOfLine (bool selecting);
void goToEndOfDocument (bool selecting);
void goToEndOfLine (bool selecting);

void deselectAll();
void selectAll();

void insertTextAtCaret (const String& textToInsert); void insertTextAtCaret (const String& textToInsert);
void insertTabAtCaret(); void insertTabAtCaret();
void cut();
void copy();
void copyThenCut();
void paste();
void backspace (bool moveInWholeWordSteps);
void deleteForward (bool moveInWholeWordSteps);

void undo();
void redo();


const Range<int> getHighlightedRegion() const; const Range<int> getHighlightedRegion() const;
void setHighlightedRegion (const Range<int>& newRange); void setHighlightedRegion (const Range<int>& newRange);
@@ -52422,6 +52457,7 @@ private:
void scrollToLineInternal (int line); void scrollToLineInternal (int line);
void scrollToColumnInternal (double column); void scrollToColumnInternal (double column);
void newTransaction(); void newTransaction();
void cut();


int indexToColumn (int line, int index) const noexcept; int indexToColumn (int line, int index) const noexcept;
int columnToIndex (int line, int column) const noexcept; int columnToIndex (int line, int column) const noexcept;
@@ -53426,7 +53462,8 @@ private:
double velocityModeSensitivity, velocityModeOffset, minMaxDiff; double velocityModeSensitivity, velocityModeOffset, minMaxDiff;
int velocityModeThreshold; int velocityModeThreshold;
float rotaryStart, rotaryEnd; float rotaryStart, rotaryEnd;
int numDecimalPlaces, mouseXWhenLastDragged, mouseYWhenLastDragged;
int numDecimalPlaces;
Point<int> mousePosWhenLastDragged;
int mouseDragStartX, mouseDragStartY; int mouseDragStartX, mouseDragStartY;
int sliderRegionStart, sliderRegionSize; int sliderRegionStart, sliderRegionSize;
int sliderBeingDragged; int sliderBeingDragged;
@@ -55763,6 +55800,9 @@ protected:
*/ */
virtual void getRoots (StringArray& rootNames, StringArray& rootPaths); virtual void getRoots (StringArray& rootNames, StringArray& rootPaths);


/** Updates the items in the dropdown list of recent paths with the values from getRoots(). */
void resetRecentPaths();

private: private:


ScopedPointer <DirectoryContentsList> fileList; ScopedPointer <DirectoryContentsList> fileList;
@@ -56995,6 +57035,7 @@ private:
bool hasBeenResized; bool hasBeenResized;
#endif #endif


void initialise (bool addToDesktop);
void updateLastPos(); void updateLastPos();
void setContent (Component* newComp, bool takeOwnership, bool resizeToFit); void setContent (Component* newComp, bool takeOwnership, bool resizeToFit);


@@ -58863,6 +58904,340 @@ private:
#endif #endif
#ifndef __JUCE_MODIFIERKEYS_JUCEHEADER__ #ifndef __JUCE_MODIFIERKEYS_JUCEHEADER__


#endif
#ifndef __JUCE_TEXTEDITORKEYMAPPER_JUCEHEADER__

/*** Start of inlined file: juce_TextEditorKeyMapper.h ***/
#ifndef __JUCE_TEXTEDITORKEYMAPPER_JUCEHEADER__
#define __JUCE_TEXTEDITORKEYMAPPER_JUCEHEADER__


/*** Start of inlined file: juce_Keypress.h ***/
#ifndef __JUCE_KEYPRESS_JUCEHEADER__
#define __JUCE_KEYPRESS_JUCEHEADER__

/**
Represents a key press, including any modifier keys that are needed.

E.g. a KeyPress might represent CTRL+C, SHIFT+ALT+H, Spacebar, Escape, etc.

@see Component, KeyListener, Button::addShortcut, KeyPressMappingManager
*/
class JUCE_API KeyPress
{
public:

/** Creates an (invalid) KeyPress.

@see isValid
*/
KeyPress() noexcept;

/** Creates a KeyPress for a key and some modifiers.

e.g.
CTRL+C would be: KeyPress ('c', ModifierKeys::ctrlModifier)
SHIFT+Escape would be: KeyPress (KeyPress::escapeKey, ModifierKeys::shiftModifier)

@param keyCode a code that represents the key - this value must be
one of special constants listed in this class, or an
8-bit character code such as a letter (case is ignored),
digit or a simple key like "," or ".". Note that this
isn't the same as the textCharacter parameter, so for example
a keyCode of 'a' and a shift-key modifier should have a
textCharacter value of 'A'.
@param modifiers the modifiers to associate with the keystroke
@param textCharacter the character that would be printed if someone typed
this keypress into a text editor. This value may be
null if the keypress is a non-printing character
@see getKeyCode, isKeyCode, getModifiers
*/
KeyPress (int keyCode,
const ModifierKeys& modifiers,
juce_wchar textCharacter) noexcept;

/** Creates a keypress with a keyCode but no modifiers or text character.
*/
KeyPress (int keyCode) noexcept;

/** Creates a copy of another KeyPress. */
KeyPress (const KeyPress& other) noexcept;

/** Copies this KeyPress from another one. */
KeyPress& operator= (const KeyPress& other) noexcept;

/** Compares two KeyPress objects. */
bool operator== (const KeyPress& other) const noexcept;

/** Compares two KeyPress objects. */
bool operator!= (const KeyPress& other) const noexcept;

/** Returns true if this is a valid KeyPress.

A null keypress can be created by the default constructor, in case it's
needed.
*/
bool isValid() const noexcept { return keyCode != 0; }

/** Returns the key code itself.

This will either be one of the special constants defined in this class,
or an 8-bit character code.
*/
int getKeyCode() const noexcept { return keyCode; }

/** Returns the key modifiers.

@see ModifierKeys
*/
const ModifierKeys getModifiers() const noexcept { return mods; }

/** Returns the character that is associated with this keypress.

This is the character that you'd expect to see printed if you press this
keypress in a text editor or similar component.
*/
juce_wchar getTextCharacter() const noexcept { return textCharacter; }

/** Checks whether the KeyPress's key is the same as the one provided, without checking
the modifiers.

The values for key codes can either be one of the special constants defined in
this class, or an 8-bit character code.

@see getKeyCode
*/
bool isKeyCode (int keyCodeToCompare) const noexcept { return keyCode == keyCodeToCompare; }

/** Converts a textual key description to a KeyPress.

This attempts to decode a textual version of a keypress, e.g. "CTRL + C" or "SPACE".

This isn't designed to cope with any kind of input, but should be given the
strings that are created by the getTextDescription() method.

If the string can't be parsed, the object returned will be invalid.

@see getTextDescription
*/
static const KeyPress createFromDescription (const String& textVersion);

/** Creates a textual description of the key combination.

e.g. "CTRL + C" or "DELETE".

To store a keypress in a file, use this method, along with createFromDescription()
to retrieve it later.
*/
const String getTextDescription() const;

/** Creates a textual description of the key combination, using unicode icon symbols if possible.

On OSX, this uses the Apple symbols for command, option, shift, etc, instead of the textual
modifier key descriptions that are returned by getTextDescription()
*/
const String getTextDescriptionWithIcons() const;

/** Checks whether the user is currently holding down the keys that make up this
KeyPress.

Note that this will return false if any extra modifier keys are
down - e.g. if the keypress is CTRL+X and the user is actually holding CTRL+ALT+x
then it will be false.
*/
bool isCurrentlyDown() const;

/** Checks whether a particular key is held down, irrespective of modifiers.

The values for key codes can either be one of the special constants defined in
this class, or an 8-bit character code.
*/
static bool isKeyCurrentlyDown (int keyCode);

// Key codes
//
// Note that the actual values of these are platform-specific and may change
// without warning, so don't store them anywhere as constants. For persisting/retrieving
// KeyPress objects, use getTextDescription() and createFromDescription() instead.
//

static const int spaceKey; /**< key-code for the space bar */
static const int escapeKey; /**< key-code for the escape key */
static const int returnKey; /**< key-code for the return key*/
static const int tabKey; /**< key-code for the tab key*/

static const int deleteKey; /**< key-code for the delete key (not backspace) */
static const int backspaceKey; /**< key-code for the backspace key */
static const int insertKey; /**< key-code for the insert key */

static const int upKey; /**< key-code for the cursor-up key */
static const int downKey; /**< key-code for the cursor-down key */
static const int leftKey; /**< key-code for the cursor-left key */
static const int rightKey; /**< key-code for the cursor-right key */
static const int pageUpKey; /**< key-code for the page-up key */
static const int pageDownKey; /**< key-code for the page-down key */
static const int homeKey; /**< key-code for the home key */
static const int endKey; /**< key-code for the end key */

static const int F1Key; /**< key-code for the F1 key */
static const int F2Key; /**< key-code for the F2 key */
static const int F3Key; /**< key-code for the F3 key */
static const int F4Key; /**< key-code for the F4 key */
static const int F5Key; /**< key-code for the F5 key */
static const int F6Key; /**< key-code for the F6 key */
static const int F7Key; /**< key-code for the F7 key */
static const int F8Key; /**< key-code for the F8 key */
static const int F9Key; /**< key-code for the F9 key */
static const int F10Key; /**< key-code for the F10 key */
static const int F11Key; /**< key-code for the F11 key */
static const int F12Key; /**< key-code for the F12 key */
static const int F13Key; /**< key-code for the F13 key */
static const int F14Key; /**< key-code for the F14 key */
static const int F15Key; /**< key-code for the F15 key */
static const int F16Key; /**< key-code for the F16 key */

static const int numberPad0; /**< key-code for the 0 on the numeric keypad. */
static const int numberPad1; /**< key-code for the 1 on the numeric keypad. */
static const int numberPad2; /**< key-code for the 2 on the numeric keypad. */
static const int numberPad3; /**< key-code for the 3 on the numeric keypad. */
static const int numberPad4; /**< key-code for the 4 on the numeric keypad. */
static const int numberPad5; /**< key-code for the 5 on the numeric keypad. */
static const int numberPad6; /**< key-code for the 6 on the numeric keypad. */
static const int numberPad7; /**< key-code for the 7 on the numeric keypad. */
static const int numberPad8; /**< key-code for the 8 on the numeric keypad. */
static const int numberPad9; /**< key-code for the 9 on the numeric keypad. */

static const int numberPadAdd; /**< key-code for the add sign on the numeric keypad. */
static const int numberPadSubtract; /**< key-code for the subtract sign on the numeric keypad. */
static const int numberPadMultiply; /**< key-code for the multiply sign on the numeric keypad. */
static const int numberPadDivide; /**< key-code for the divide sign on the numeric keypad. */
static const int numberPadSeparator; /**< key-code for the comma on the numeric keypad. */
static const int numberPadDecimalPoint; /**< key-code for the decimal point sign on the numeric keypad. */
static const int numberPadEquals; /**< key-code for the equals key on the numeric keypad. */
static const int numberPadDelete; /**< key-code for the delete key on the numeric keypad. */

static const int playKey; /**< key-code for a multimedia 'play' key, (not all keyboards will have one) */
static const int stopKey; /**< key-code for a multimedia 'stop' key, (not all keyboards will have one) */
static const int fastForwardKey; /**< key-code for a multimedia 'fast-forward' key, (not all keyboards will have one) */
static const int rewindKey; /**< key-code for a multimedia 'rewind' key, (not all keyboards will have one) */

private:

int keyCode;
ModifierKeys mods;
juce_wchar textCharacter;

JUCE_LEAK_DETECTOR (KeyPress);
};

#endif // __JUCE_KEYPRESS_JUCEHEADER__

/*** End of inlined file: juce_Keypress.h ***/

/** This class is used to invoke a range of text-editor navigation methods on
an object, based upon a keypress event.

It's currently used internally by the TextEditor and CodeEditorComponent.
*/
template <class CallbackClass>
struct TextEditorKeyMapper
{
/** Checks the keypress and invokes one of a range of navigation functions that
the target class must implement, based on the key event.
*/
static bool invokeKeyFunction (CallbackClass& target, const KeyPress& key)
{
const bool isShiftDown = key.getModifiers().isShiftDown();
const bool ctrlOrAltDown = key.getModifiers().isCtrlDown() || key.getModifiers().isAltDown();

if (key == KeyPress (KeyPress::downKey, ModifierKeys::ctrlModifier, 0)
&& target.scrollUp())
return true;

if (key == KeyPress (KeyPress::upKey, ModifierKeys::ctrlModifier, 0)
&& target.scrollDown())
return true;

#if JUCE_MAC
if (key.getModifiers().isCommandDown())
{
if (key.isKeyCode (KeyPress::upKey))
return target.moveCaretToTop (isShiftDown);

if (key.isKeyCode (KeyPress::downKey))
return target.moveCaretToEnd (isShiftDown);

if (key.isKeyCode (KeyPress::leftKey))
return target.moveCaretToStartOfLine (isShiftDown);

if (key.isKeyCode (KeyPress::rightKey))
return target.moveCaretToEndOfLine (isShiftDown);
}
#endif

if (key.isKeyCode (KeyPress::upKey))
return target.moveCaretUp (isShiftDown);

if (key.isKeyCode (KeyPress::downKey))
return target.moveCaretDown (isShiftDown);

if (key.isKeyCode (KeyPress::leftKey))
return target.moveCaretLeft (ctrlOrAltDown, isShiftDown);

if (key.isKeyCode (KeyPress::rightKey))
return target.moveCaretRight (ctrlOrAltDown, isShiftDown);

if (key.isKeyCode (KeyPress::pageUpKey))
return target.pageUp (isShiftDown);

if (key.isKeyCode (KeyPress::pageDownKey))
return target.pageDown (isShiftDown);

if (key.isKeyCode (KeyPress::homeKey))
return ctrlOrAltDown ? target.moveCaretToTop (isShiftDown)
: target.moveCaretToStartOfLine (isShiftDown);

if (key.isKeyCode (KeyPress::endKey))
return ctrlOrAltDown ? target.moveCaretToEnd (isShiftDown)
: target.moveCaretToEndOfLine (isShiftDown);

if (key == KeyPress ('c', ModifierKeys::commandModifier, 0)
|| key == KeyPress (KeyPress::insertKey, ModifierKeys::ctrlModifier, 0))
return target.copyToClipboard();

if (key == KeyPress ('x', ModifierKeys::commandModifier, 0)
|| key == KeyPress (KeyPress::deleteKey, ModifierKeys::shiftModifier, 0))
return target.cutToClipboard();

if (key == KeyPress ('v', ModifierKeys::commandModifier, 0)
|| key == KeyPress (KeyPress::insertKey, ModifierKeys::shiftModifier, 0))
return target.pasteFromClipboard();

if (key.isKeyCode (KeyPress::backspaceKey))
return target.deleteBackwards (ctrlOrAltDown);

if (key.isKeyCode (KeyPress::deleteKey))
return target.deleteForwards (ctrlOrAltDown);

if (key == KeyPress ('a', ModifierKeys::commandModifier, 0))
return target.selectAll();

if (key == KeyPress ('z', ModifierKeys::commandModifier, 0))
return target.undo();

if (key == KeyPress ('y', ModifierKeys::commandModifier, 0)
|| key == KeyPress ('z', ModifierKeys::commandModifier | ModifierKeys::shiftModifier, 0))
return target.redo();

return false;
}
};

#endif // __JUCE_TEXTEDITORKEYMAPPER_JUCEHEADER__

/*** End of inlined file: juce_TextEditorKeyMapper.h ***/


#endif #endif
#ifndef __JUCE_TEXTINPUTTARGET_JUCEHEADER__ #ifndef __JUCE_TEXTINPUTTARGET_JUCEHEADER__


@@ -63088,6 +63463,8 @@ private:
ScopedPointer<ComboBox> midiOutputSelector; ScopedPointer<ComboBox> midiOutputSelector;
ScopedPointer<Label> midiInputsLabel, midiOutputLabel; ScopedPointer<Label> midiInputsLabel, midiOutputLabel;


void updateAllControls();

JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AudioDeviceSelectorComponent); JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AudioDeviceSelectorComponent);
}; };




+ 2
- 0
src/audio/devices/juce_AudioIODevice.cpp View File

@@ -53,6 +53,8 @@ bool AudioIODevice::showControlPanel()
return false; return false;
} }
//==============================================================================
void AudioIODeviceCallback::audioDeviceError (const String&) {}
END_JUCE_NAMESPACE END_JUCE_NAMESPACE

+ 7
- 2
src/audio/devices/juce_AudioIODevice.h View File

@@ -107,9 +107,14 @@ public:
*/ */
virtual void audioDeviceAboutToStart (AudioIODevice* device) = 0; virtual void audioDeviceAboutToStart (AudioIODevice* device) = 0;
/** Called to indicate that the device has stopped.
*/
/** Called to indicate that the device has stopped. */
virtual void audioDeviceStopped() = 0; virtual void audioDeviceStopped() = 0;
/** This can be overridden to be told if the device generates an error while operating.
Be aware that this could be called by any thread! And not all devices perform
this callback.
*/
virtual void audioDeviceError (const String& errorMessage);
}; };


+ 1
- 1
src/core/juce_StandardHeader.h View File

@@ -33,7 +33,7 @@
*/ */
#define JUCE_MAJOR_VERSION 1 #define JUCE_MAJOR_VERSION 1
#define JUCE_MINOR_VERSION 53 #define JUCE_MINOR_VERSION 53
#define JUCE_BUILDNUMBER 89
#define JUCE_BUILDNUMBER 90
/** Current Juce version number. /** Current Juce version number.


+ 2
- 2
src/events/juce_Timer.cpp View File

@@ -44,7 +44,7 @@ class InternalTimerThread : private Thread,
private AsyncUpdater private AsyncUpdater
{ {
public: public:
typedef SpinLock LockType;
typedef CriticalSection LockType; // (mysteriously, using a SpinLock here causes problems on some XP machines..)
InternalTimerThread() InternalTimerThread()
: Thread ("Juce Timer"), : Thread ("Juce Timer"),
@@ -146,7 +146,7 @@ public:
/* This is needed as a memory barrier to make sure all processing of current timers is done /* This is needed as a memory barrier to make sure all processing of current timers is done
before the boolean is set. This set should never fail since if it was false in the first place, before the boolean is set. This set should never fail since if it was false in the first place,
we wouldn't get a message (so it can't be changed from false to true from under us), and if we we wouldn't get a message (so it can't be changed from false to true from under us), and if we
get a message then the value is true and the other thread can only set it to true again and
get a message then the value is true and the other thread can only set it to true again and
we will get another callback to set it to false. we will get another callback to set it to false.
*/ */
callbackNeeded.set (0); callbackNeeded.set (0);


+ 70
- 129
src/gui/components/code_editor/juce_CodeEditorComponent.cpp View File

@@ -29,6 +29,7 @@ BEGIN_JUCE_NAMESPACE
#include "juce_CodeEditorComponent.h" #include "juce_CodeEditorComponent.h"
#include "../lookandfeel/juce_LookAndFeel.h" #include "../lookandfeel/juce_LookAndFeel.h"
#include "../keyboard/juce_TextEditorKeyMapper.h"
#include "../../../utilities/juce_SystemClipboard.h" #include "../../../utilities/juce_SystemClipboard.h"
@@ -628,7 +629,7 @@ void CodeEditorComponent::cut()
insertTextAtCaret (String::empty); insertTextAtCaret (String::empty);
} }
void CodeEditorComponent::copy()
bool CodeEditorComponent::copyToClipboard()
{ {
newTransaction(); newTransaction();
@@ -636,16 +637,19 @@ void CodeEditorComponent::copy()
if (selection.isNotEmpty()) if (selection.isNotEmpty())
SystemClipboard::copyTextToClipboard (selection); SystemClipboard::copyTextToClipboard (selection);
return true;
} }
void CodeEditorComponent::copyThenCut()
bool CodeEditorComponent::cutToClipboard()
{ {
copy();
copyToClipboard();
cut(); cut();
newTransaction(); newTransaction();
return true;
} }
void CodeEditorComponent::paste()
bool CodeEditorComponent::pasteFromClipboard()
{ {
newTransaction(); newTransaction();
const String clip (SystemClipboard::getTextFromClipboard()); const String clip (SystemClipboard::getTextFromClipboard());
@@ -654,9 +658,10 @@ void CodeEditorComponent::paste()
insertTextAtCaret (clip); insertTextAtCaret (clip);
newTransaction(); newTransaction();
return true;
} }
void CodeEditorComponent::cursorLeft (const bool moveInWholeWordSteps, const bool selecting)
bool CodeEditorComponent::moveCaretLeft (const bool moveInWholeWordSteps, const bool selecting)
{ {
newTransaction(); newTransaction();
@@ -664,9 +669,11 @@ void CodeEditorComponent::cursorLeft (const bool moveInWholeWordSteps, const boo
moveCaretTo (document.findWordBreakBefore (caretPos), selecting); moveCaretTo (document.findWordBreakBefore (caretPos), selecting);
else else
moveCaretTo (caretPos.movedBy (-1), selecting); moveCaretTo (caretPos.movedBy (-1), selecting);
return true;
} }
void CodeEditorComponent::cursorRight (const bool moveInWholeWordSteps, const bool selecting)
bool CodeEditorComponent::moveCaretRight (const bool moveInWholeWordSteps, const bool selecting)
{ {
newTransaction(); newTransaction();
@@ -674,6 +681,8 @@ void CodeEditorComponent::cursorRight (const bool moveInWholeWordSteps, const bo
moveCaretTo (document.findWordBreakAfter (caretPos), selecting); moveCaretTo (document.findWordBreakAfter (caretPos), selecting);
else else
moveCaretTo (caretPos.movedBy (1), selecting); moveCaretTo (caretPos.movedBy (1), selecting);
return true;
} }
void CodeEditorComponent::moveLineDelta (const int delta, const bool selecting) void CodeEditorComponent::moveLineDelta (const int delta, const bool selecting)
@@ -691,7 +700,7 @@ void CodeEditorComponent::moveLineDelta (const int delta, const bool selecting)
columnToTryToMaintain = colToMaintain; columnToTryToMaintain = colToMaintain;
} }
void CodeEditorComponent::cursorDown (const bool selecting)
bool CodeEditorComponent::moveCaretDown (const bool selecting)
{ {
newTransaction(); newTransaction();
@@ -699,9 +708,11 @@ void CodeEditorComponent::cursorDown (const bool selecting)
moveCaretTo (CodeDocument::Position (&document, std::numeric_limits<int>::max(), std::numeric_limits<int>::max()), selecting); moveCaretTo (CodeDocument::Position (&document, std::numeric_limits<int>::max(), std::numeric_limits<int>::max()), selecting);
else else
moveLineDelta (1, selecting); moveLineDelta (1, selecting);
return true;
} }
void CodeEditorComponent::cursorUp (const bool selecting)
bool CodeEditorComponent::moveCaretUp (const bool selecting)
{ {
newTransaction(); newTransaction();
@@ -709,46 +720,53 @@ void CodeEditorComponent::cursorUp (const bool selecting)
moveCaretTo (CodeDocument::Position (&document, 0, 0), selecting); moveCaretTo (CodeDocument::Position (&document, 0, 0), selecting);
else else
moveLineDelta (-1, selecting); moveLineDelta (-1, selecting);
return true;
} }
void CodeEditorComponent::pageDown (const bool selecting)
bool CodeEditorComponent::pageDown (const bool selecting)
{ {
newTransaction(); newTransaction();
scrollBy (jlimit (0, linesOnScreen, 1 + document.getNumLines() - firstLineOnScreen - linesOnScreen)); scrollBy (jlimit (0, linesOnScreen, 1 + document.getNumLines() - firstLineOnScreen - linesOnScreen));
moveLineDelta (linesOnScreen, selecting); moveLineDelta (linesOnScreen, selecting);
return true;
} }
void CodeEditorComponent::pageUp (const bool selecting)
bool CodeEditorComponent::pageUp (const bool selecting)
{ {
newTransaction(); newTransaction();
scrollBy (-linesOnScreen); scrollBy (-linesOnScreen);
moveLineDelta (-linesOnScreen, selecting); moveLineDelta (-linesOnScreen, selecting);
return true;
} }
void CodeEditorComponent::scrollUp()
bool CodeEditorComponent::scrollUp()
{ {
newTransaction(); newTransaction();
scrollBy (1); scrollBy (1);
if (caretPos.getLineNumber() < firstLineOnScreen) if (caretPos.getLineNumber() < firstLineOnScreen)
moveLineDelta (1, false); moveLineDelta (1, false);
return true;
} }
void CodeEditorComponent::scrollDown()
bool CodeEditorComponent::scrollDown()
{ {
newTransaction(); newTransaction();
scrollBy (-1); scrollBy (-1);
if (caretPos.getLineNumber() >= firstLineOnScreen + linesOnScreen) if (caretPos.getLineNumber() >= firstLineOnScreen + linesOnScreen)
moveLineDelta (-1, false); moveLineDelta (-1, false);
return true;
} }
void CodeEditorComponent::goToStartOfDocument (const bool selecting)
bool CodeEditorComponent::moveCaretToTop (const bool selecting)
{ {
newTransaction(); newTransaction();
moveCaretTo (CodeDocument::Position (&document, 0, 0), selecting); moveCaretTo (CodeDocument::Position (&document, 0, 0), selecting);
return true;
} }
namespace CodeEditorHelpers namespace CodeEditorHelpers
@@ -771,7 +789,7 @@ namespace CodeEditorHelpers
} }
} }
void CodeEditorComponent::goToStartOfLine (const bool selecting)
bool CodeEditorComponent::moveCaretToStartOfLine (const bool selecting)
{ {
newTransaction(); newTransaction();
@@ -781,21 +799,24 @@ void CodeEditorComponent::goToStartOfLine (const bool selecting)
index = 0; index = 0;
moveCaretTo (CodeDocument::Position (&document, caretPos.getLineNumber(), index), selecting); moveCaretTo (CodeDocument::Position (&document, caretPos.getLineNumber(), index), selecting);
return true;
} }
void CodeEditorComponent::goToEndOfDocument (const bool selecting)
bool CodeEditorComponent::moveCaretToEnd (const bool selecting)
{ {
newTransaction(); newTransaction();
moveCaretTo (CodeDocument::Position (&document, std::numeric_limits<int>::max(), std::numeric_limits<int>::max()), selecting); moveCaretTo (CodeDocument::Position (&document, std::numeric_limits<int>::max(), std::numeric_limits<int>::max()), selecting);
return true;
} }
void CodeEditorComponent::goToEndOfLine (const bool selecting)
bool CodeEditorComponent::moveCaretToEndOfLine (const bool selecting)
{ {
newTransaction(); newTransaction();
moveCaretTo (CodeDocument::Position (&document, caretPos.getLineNumber(), std::numeric_limits<int>::max()), selecting); moveCaretTo (CodeDocument::Position (&document, caretPos.getLineNumber(), std::numeric_limits<int>::max()), selecting);
return true;
} }
void CodeEditorComponent::backspace (const bool moveInWholeWordSteps)
bool CodeEditorComponent::deleteBackwards (const bool moveInWholeWordSteps)
{ {
if (moveInWholeWordSteps) if (moveInWholeWordSteps)
{ {
@@ -809,9 +830,10 @@ void CodeEditorComponent::backspace (const bool moveInWholeWordSteps)
} }
cut(); cut();
return true;
} }
void CodeEditorComponent::deleteForward (const bool moveInWholeWordSteps)
bool CodeEditorComponent::deleteForwards (const bool moveInWholeWordSteps)
{ {
if (moveInWholeWordSteps) if (moveInWholeWordSteps)
{ {
@@ -827,26 +849,30 @@ void CodeEditorComponent::deleteForward (const bool moveInWholeWordSteps)
} }
cut(); cut();
return true;
} }
void CodeEditorComponent::selectAll()
bool CodeEditorComponent::selectAll()
{ {
newTransaction(); newTransaction();
moveCaretTo (CodeDocument::Position (&document, std::numeric_limits<int>::max(), std::numeric_limits<int>::max()), false); moveCaretTo (CodeDocument::Position (&document, std::numeric_limits<int>::max(), std::numeric_limits<int>::max()), false);
moveCaretTo (CodeDocument::Position (&document, 0, 0), true); moveCaretTo (CodeDocument::Position (&document, 0, 0), true);
return true;
} }
//============================================================================== //==============================================================================
void CodeEditorComponent::undo()
bool CodeEditorComponent::undo()
{ {
document.undo(); document.undo();
scrollToKeepCaretOnScreen(); scrollToKeepCaretOnScreen();
return true;
} }
void CodeEditorComponent::redo()
bool CodeEditorComponent::redo()
{ {
document.redo(); document.redo();
scrollToKeepCaretOnScreen(); scrollToKeepCaretOnScreen();
return true;
} }
void CodeEditorComponent::newTransaction() void CodeEditorComponent::newTransaction()
@@ -881,114 +907,29 @@ const String CodeEditorComponent::getTextInRange (const Range<int>& range) const
//============================================================================== //==============================================================================
bool CodeEditorComponent::keyPressed (const KeyPress& key) bool CodeEditorComponent::keyPressed (const KeyPress& key)
{ {
const bool moveInWholeWordSteps = key.getModifiers().isCtrlDown() || key.getModifiers().isAltDown();
const bool shiftDown = key.getModifiers().isShiftDown();
if (key.isKeyCode (KeyPress::leftKey))
{
cursorLeft (moveInWholeWordSteps, shiftDown);
}
else if (key.isKeyCode (KeyPress::rightKey))
{
cursorRight (moveInWholeWordSteps, shiftDown);
}
else if (key.isKeyCode (KeyPress::upKey))
{
if (key.getModifiers().isCtrlDown() && ! shiftDown)
scrollDown();
#if JUCE_MAC
else if (key.getModifiers().isCommandDown())
goToStartOfDocument (shiftDown);
#endif
else
cursorUp (shiftDown);
}
else if (key.isKeyCode (KeyPress::downKey))
{
if (key.getModifiers().isCtrlDown() && ! shiftDown)
scrollUp();
#if JUCE_MAC
else if (key.getModifiers().isCommandDown())
goToEndOfDocument (shiftDown);
#endif
else
cursorDown (shiftDown);
}
else if (key.isKeyCode (KeyPress::pageDownKey))
{
pageDown (shiftDown);
}
else if (key.isKeyCode (KeyPress::pageUpKey))
{
pageUp (shiftDown);
}
else if (key.isKeyCode (KeyPress::homeKey))
{
if (moveInWholeWordSteps)
goToStartOfDocument (shiftDown);
else
goToStartOfLine (shiftDown);
}
else if (key.isKeyCode (KeyPress::endKey))
if (! TextEditorKeyMapper<CodeEditorComponent>::invokeKeyFunction (*this, key))
{ {
if (moveInWholeWordSteps)
goToEndOfDocument (shiftDown);
if (key == KeyPress::tabKey || key.getTextCharacter() == '\t')
{
insertTabAtCaret();
}
else if (key == KeyPress::returnKey)
{
newTransaction();
insertTextAtCaret (document.getNewLineCharacters());
}
else if (key.isKeyCode (KeyPress::escapeKey))
{
newTransaction();
}
else if (key.getTextCharacter() >= ' ')
{
insertTextAtCaret (String::charToString (key.getTextCharacter()));
}
else else
goToEndOfLine (shiftDown);
}
else if (key.isKeyCode (KeyPress::backspaceKey))
{
backspace (moveInWholeWordSteps);
}
else if (key.isKeyCode (KeyPress::deleteKey))
{
deleteForward (moveInWholeWordSteps);
}
else if (key == KeyPress ('c', ModifierKeys::commandModifier, 0))
{
copy();
}
else if (key == KeyPress ('x', ModifierKeys::commandModifier, 0))
{
copyThenCut();
}
else if (key == KeyPress ('v', ModifierKeys::commandModifier, 0))
{
paste();
}
else if (key == KeyPress ('z', ModifierKeys::commandModifier, 0))
{
undo();
}
else if (key == KeyPress ('y', ModifierKeys::commandModifier, 0)
|| key == KeyPress ('z', ModifierKeys::commandModifier | ModifierKeys::shiftModifier, 0))
{
redo();
}
else if (key == KeyPress ('a', ModifierKeys::commandModifier, 0))
{
selectAll();
}
else if (key == KeyPress::tabKey || key.getTextCharacter() == '\t')
{
insertTabAtCaret();
}
else if (key == KeyPress::returnKey)
{
newTransaction();
insertTextAtCaret (document.getNewLineCharacters());
}
else if (key.isKeyCode (KeyPress::escapeKey))
{
newTransaction();
}
else if (key.getTextCharacter() >= ' ')
{
insertTextAtCaret (String::charToString (key.getTextCharacter()));
}
else
{
return false;
{
return false;
}
} }
return true; return true;


+ 23
- 26
src/gui/components/code_editor/juce_CodeEditorComponent.h View File

@@ -116,40 +116,36 @@ public:
const CodeDocument::Position getPositionAt (int x, int y); const CodeDocument::Position getPositionAt (int x, int y);
//============================================================================== //==============================================================================
void cursorLeft (bool moveInWholeWordSteps, bool selecting);
void cursorRight (bool moveInWholeWordSteps, bool selecting);
void cursorDown (bool selecting);
void cursorUp (bool selecting);
void pageDown (bool selecting);
void pageUp (bool selecting);
bool moveCaretLeft (bool moveInWholeWordSteps, bool selecting);
bool moveCaretRight (bool moveInWholeWordSteps, bool selecting);
bool moveCaretUp (bool selecting);
bool moveCaretDown (bool selecting);
bool scrollDown();
bool scrollUp();
bool pageUp (bool selecting);
bool pageDown (bool selecting);
bool moveCaretToTop (bool selecting);
bool moveCaretToStartOfLine (bool selecting);
bool moveCaretToEnd (bool selecting);
bool moveCaretToEndOfLine (bool selecting);
bool deleteBackwards (bool moveInWholeWordSteps);
bool deleteForwards (bool moveInWholeWordSteps);
bool copyToClipboard();
bool cutToClipboard();
bool pasteFromClipboard();
bool undo();
bool redo();
bool selectAll();
void deselectAll();
void scrollDown();
void scrollUp();
void scrollToLine (int newFirstLineOnScreen); void scrollToLine (int newFirstLineOnScreen);
void scrollBy (int deltaLines); void scrollBy (int deltaLines);
void scrollToColumn (int newFirstColumnOnScreen); void scrollToColumn (int newFirstColumnOnScreen);
void scrollToKeepCaretOnScreen(); void scrollToKeepCaretOnScreen();
void goToStartOfDocument (bool selecting);
void goToStartOfLine (bool selecting);
void goToEndOfDocument (bool selecting);
void goToEndOfLine (bool selecting);
void deselectAll();
void selectAll();
void insertTextAtCaret (const String& textToInsert); void insertTextAtCaret (const String& textToInsert);
void insertTabAtCaret(); void insertTabAtCaret();
void cut();
void copy();
void copyThenCut();
void paste();
void backspace (bool moveInWholeWordSteps);
void deleteForward (bool moveInWholeWordSteps);
void undo();
void redo();
//============================================================================== //==============================================================================
const Range<int> getHighlightedRegion() const; const Range<int> getHighlightedRegion() const;
@@ -307,6 +303,7 @@ private:
void scrollToLineInternal (int line); void scrollToLineInternal (int line);
void scrollToColumnInternal (double column); void scrollToColumnInternal (double column);
void newTransaction(); void newTransaction();
void cut();
int indexToColumn (int line, int index) const noexcept; int indexToColumn (int line, int index) const noexcept;
int columnToIndex (int line, int column) const noexcept; int columnToIndex (int line, int column) const noexcept;


+ 194
- 173
src/gui/components/controls/juce_TextEditor.cpp View File

@@ -35,6 +35,7 @@ BEGIN_JUCE_NAMESPACE
#include "../../../text/juce_LocalisedStrings.h" #include "../../../text/juce_LocalisedStrings.h"
#include "../../../io/streams/juce_MemoryOutputStream.h" #include "../../../io/streams/juce_MemoryOutputStream.h"
#include "../lookandfeel/juce_LookAndFeel.h" #include "../lookandfeel/juce_LookAndFeel.h"
#include "../keyboard/juce_TextEditorKeyMapper.h"
//============================================================================== //==============================================================================
@@ -1032,20 +1033,28 @@ void TextEditor::newTransaction()
undoManager.beginNewTransaction(); undoManager.beginNewTransaction();
} }
void TextEditor::doUndoRedo (const bool isRedo)
bool TextEditor::undoOrRedo (const bool shouldUndo)
{ {
if (! isReadOnly()) if (! isReadOnly())
{ {
if (isRedo ? undoManager.redo()
: undoManager.undo())
newTransaction();
if (shouldUndo ? undoManager.undo()
: undoManager.redo())
{ {
scrollToMakeSureCursorIsVisible(); scrollToMakeSureCursorIsVisible();
repaint(); repaint();
textChanged(); textChanged();
return true;
} }
} }
return false;
} }
bool TextEditor::undo() { return undoOrRedo (true); }
bool TextEditor::redo() { return undoOrRedo (false); }
//============================================================================== //==============================================================================
void TextEditor::setMultiLine (const bool shouldBeMultiLine, void TextEditor::setMultiLine (const bool shouldBeMultiLine,
const bool shouldWordWrap) const bool shouldWordWrap)
@@ -1885,163 +1894,199 @@ void TextEditor::mouseWheelMove (const MouseEvent& e, float wheelIncrementX, flo
} }
//============================================================================== //==============================================================================
bool TextEditor::keyPressed (const KeyPress& key)
bool TextEditor::moveCaretWithTransation (const int newPos, const bool selecting)
{ {
if (isReadOnly() && key != KeyPress ('c', ModifierKeys::commandModifier, 0))
return false;
newTransaction();
moveCaretTo (newPos, selecting);
return true;
}
bool TextEditor::moveCaretLeft (bool moveInWholeWordSteps, bool selecting)
{
int pos = getCaretPosition();
if (moveInWholeWordSteps)
pos = findWordBreakBefore (pos);
else
--pos;
return moveCaretWithTransation (pos, selecting);
}
bool TextEditor::moveCaretRight (bool moveInWholeWordSteps, bool selecting)
{
int pos = getCaretPosition();
if (moveInWholeWordSteps)
pos = findWordBreakAfter (pos);
else
++pos;
return moveCaretWithTransation (pos, selecting);
}
bool TextEditor::moveCaretUp (bool selecting)
{
if (! isMultiLine())
return moveCaretToStartOfLine (selecting);
const bool moveInWholeWordSteps = key.getModifiers().isCtrlDown() || key.getModifiers().isAltDown();
const Rectangle<float> caretPos (getCaretRectangle().toFloat()); const Rectangle<float> caretPos (getCaretRectangle().toFloat());
return moveCaretWithTransation (indexAtPosition (caretPos.getX(), caretPos.getY() - 1.0f), selecting);
}
if (key.isKeyCode (KeyPress::leftKey)
|| key.isKeyCode (KeyPress::upKey))
{
newTransaction();
bool TextEditor::moveCaretDown (bool selecting)
{
if (! isMultiLine())
return moveCaretToEndOfLine (selecting);
int newPos;
const Rectangle<float> caretPos (getCaretRectangle().toFloat());
return moveCaretWithTransation (indexAtPosition (caretPos.getX(), caretPos.getBottom() + 1.0f), selecting);
}
if (isMultiLine() && key.isKeyCode (KeyPress::upKey))
newPos = indexAtPosition (caretPos.getX(), caretPos.getY() - 1.0f);
else if (moveInWholeWordSteps)
newPos = findWordBreakBefore (getCaretPosition());
else
newPos = getCaretPosition() - 1;
bool TextEditor::pageUp (bool selecting)
{
if (! isMultiLine())
return moveCaretToStartOfLine (selecting);
moveCaretTo (newPos, key.getModifiers().isShiftDown());
}
else if (key.isKeyCode (KeyPress::rightKey)
|| key.isKeyCode (KeyPress::downKey))
{
newTransaction();
const Rectangle<float> caretPos (getCaretRectangle().toFloat());
return moveCaretWithTransation (indexAtPosition (caretPos.getX(), caretPos.getY() - viewport->getViewHeight()), selecting);
}
int newPos;
bool TextEditor::pageDown (bool selecting)
{
if (! isMultiLine())
return moveCaretToEndOfLine (selecting);
if (isMultiLine() && key.isKeyCode (KeyPress::downKey))
newPos = indexAtPosition (caretPos.getX(), caretPos.getBottom() + 1.0f);
else if (moveInWholeWordSteps)
newPos = findWordBreakAfter (getCaretPosition());
else
newPos = getCaretPosition() + 1;
const Rectangle<float> caretPos (getCaretRectangle().toFloat());
return moveCaretWithTransation (indexAtPosition (caretPos.getX(), caretPos.getBottom() + viewport->getViewHeight()), selecting);
}
moveCaretTo (newPos, key.getModifiers().isShiftDown());
}
else if (key.isKeyCode (KeyPress::pageDownKey) && isMultiLine())
{
newTransaction();
void TextEditor::scrollByLines (int deltaLines)
{
ScrollBar* scrollbar = viewport->getVerticalScrollBar();
moveCaretTo (indexAtPosition (caretPos.getX(), caretPos.getBottom() + viewport->getViewHeight()),
key.getModifiers().isShiftDown());
}
else if (key.isKeyCode (KeyPress::pageUpKey) && isMultiLine())
{
newTransaction();
if (scrollbar != nullptr)
scrollbar->moveScrollbarInSteps (deltaLines);
}
moveCaretTo (indexAtPosition (caretPos.getX(), caretPos.getY() - viewport->getViewHeight()),
key.getModifiers().isShiftDown());
}
else if (key.isKeyCode (KeyPress::homeKey))
{
newTransaction();
bool TextEditor::scrollDown()
{
scrollByLines (-1);
return true;
}
if (isMultiLine() && ! moveInWholeWordSteps)
moveCaretTo (indexAtPosition (0.0f, caretPos.getY()),
key.getModifiers().isShiftDown());
else
moveCaretTo (0, key.getModifiers().isShiftDown());
}
else if (key.isKeyCode (KeyPress::endKey))
{
newTransaction();
bool TextEditor::scrollUp()
{
scrollByLines (1);
return true;
}
if (isMultiLine() && ! moveInWholeWordSteps)
moveCaretTo (indexAtPosition ((float) textHolder->getWidth(), caretPos.getY()),
key.getModifiers().isShiftDown());
else
moveCaretTo (getTotalNumChars(), key.getModifiers().isShiftDown());
}
else if (key.isKeyCode (KeyPress::backspaceKey))
bool TextEditor::moveCaretToTop (bool selecting)
{
return moveCaretWithTransation (0, selecting);
}
bool TextEditor::moveCaretToStartOfLine (bool selecting)
{
const Rectangle<float> caretPos (getCaretRectangle().toFloat());
return moveCaretWithTransation (indexAtPosition (0.0f, caretPos.getY()), selecting);
}
bool TextEditor::moveCaretToEnd (bool selecting)
{
return moveCaretWithTransation (getTotalNumChars(), selecting);
}
bool TextEditor::moveCaretToEndOfLine (bool selecting)
{
const Rectangle<float> caretPos (getCaretRectangle().toFloat());
return moveCaretWithTransation (indexAtPosition ((float) textHolder->getWidth(), caretPos.getY()), selecting);
}
bool TextEditor::deleteBackwards (bool moveInWholeWordSteps)
{
if (moveInWholeWordSteps)
moveCaretTo (findWordBreakBefore (getCaretPosition()), true);
else if (selection.isEmpty() && selection.getStart() > 0)
selection.setStart (selection.getEnd() - 1);
cut();
return true;
}
bool TextEditor::deleteForwards (bool /*moveInWholeWordSteps*/)
{
if (selection.isEmpty() && selection.getStart() < getTotalNumChars())
selection.setEnd (selection.getStart() + 1);
cut();
return true;
}
bool TextEditor::copyToClipboard()
{
newTransaction();
copy();
return true;
}
bool TextEditor::cutToClipboard()
{
newTransaction();
copy();
cut();
return true;
}
bool TextEditor::pasteFromClipboard()
{
newTransaction();
paste();
return true;
}
bool TextEditor::selectAll()
{
newTransaction();
moveCaretTo (getTotalNumChars(), false);
moveCaretTo (0, true);
return true;
}
//==============================================================================
bool TextEditor::keyPressed (const KeyPress& key)
{
if (isReadOnly() && key != KeyPress ('c', ModifierKeys::commandModifier, 0))
return false;
if (! TextEditorKeyMapper<TextEditor>::invokeKeyFunction (*this, key))
{ {
if (moveInWholeWordSteps)
if (key == KeyPress::returnKey)
{ {
moveCaretTo (findWordBreakBefore (getCaretPosition()), true);
newTransaction();
if (returnKeyStartsNewLine)
insertTextAtCaret ("\n");
else
returnPressed();
} }
else
else if (key.isKeyCode (KeyPress::escapeKey))
{ {
if (selection.isEmpty() && selection.getStart() > 0)
selection.setStart (selection.getEnd() - 1);
newTransaction();
moveCaretTo (getCaretPosition(), false);
escapePressed();
} }
else if (key.getTextCharacter() >= ' '
|| (tabKeyUsed && (key.getTextCharacter() == '\t')))
{
insertTextAtCaret (String::charToString (key.getTextCharacter()));
cut();
}
else if (key.isKeyCode (KeyPress::deleteKey))
{
if (key.getModifiers().isShiftDown())
copy();
if (selection.isEmpty() && selection.getStart() < getTotalNumChars())
selection.setEnd (selection.getStart() + 1);
cut();
}
else if (key == KeyPress ('c', ModifierKeys::commandModifier, 0)
|| key == KeyPress (KeyPress::insertKey, ModifierKeys::ctrlModifier, 0))
{
newTransaction();
copy();
}
else if (key == KeyPress ('x', ModifierKeys::commandModifier, 0))
{
newTransaction();
copy();
cut();
}
else if (key == KeyPress ('v', ModifierKeys::commandModifier, 0)
|| key == KeyPress (KeyPress::insertKey, ModifierKeys::shiftModifier, 0))
{
newTransaction();
paste();
}
else if (key == KeyPress ('z', ModifierKeys::commandModifier, 0))
{
newTransaction();
doUndoRedo (false);
}
else if (key == KeyPress ('y', ModifierKeys::commandModifier, 0))
{
newTransaction();
doUndoRedo (true);
}
else if (key == KeyPress ('a', ModifierKeys::commandModifier, 0))
{
newTransaction();
moveCaretTo (getTotalNumChars(), false);
moveCaretTo (0, true);
}
else if (key == KeyPress::returnKey)
{
newTransaction();
if (returnKeyStartsNewLine)
insertTextAtCaret ("\n");
lastTransactionTime = Time::getApproximateMillisecondCounter();
}
else else
returnPressed();
}
else if (key.isKeyCode (KeyPress::escapeKey))
{
newTransaction();
moveCaretTo (getCaretPosition(), false);
escapePressed();
}
else if (key.getTextCharacter() >= ' '
|| (tabKeyUsed && (key.getTextCharacter() == '\t')))
{
insertTextAtCaret (String::charToString (key.getTextCharacter()));
lastTransactionTime = Time::getApproximateMillisecondCounter();
}
else
{
return false;
{
return false;
}
} }
return true; return true;
@@ -2052,10 +2097,10 @@ bool TextEditor::keyStateChanged (const bool isKeyDown)
if (! isKeyDown) if (! isKeyDown)
return false; return false;
#if JUCE_WINDOWS
#if JUCE_WINDOWS
if (KeyPress (KeyPress::F4Key, ModifierKeys::altModifier, 0).isCurrentlyDown()) if (KeyPress (KeyPress::F4Key, ModifierKeys::altModifier, 0).isCurrentlyDown())
return false; // We need to explicitly allow alt-F4 to pass through on Windows return false; // We need to explicitly allow alt-F4 to pass through on Windows
#endif
#endif
// (overridden to avoid forwarding key events to the parent) // (overridden to avoid forwarding key events to the parent)
return ! ModifierKeys::getCurrentModifiers().isCommandDown(); return ! ModifierKeys::getCurrentModifiers().isCommandDown();
@@ -2091,38 +2136,14 @@ void TextEditor::performPopupMenuAction (const int menuItemID)
{ {
switch (menuItemID) switch (menuItemID)
{ {
case baseMenuItemID + 1:
copy();
cut();
break;
case baseMenuItemID + 2:
copy();
break;
case baseMenuItemID + 3:
paste();
break;
case baseMenuItemID + 4:
cut();
break;
case baseMenuItemID + 5:
moveCaretTo (getTotalNumChars(), false);
moveCaretTo (0, true);
break;
case baseMenuItemID + 6:
doUndoRedo (false);
break;
case baseMenuItemID + 7:
doUndoRedo (true);
break;
default:
break;
case baseMenuItemID + 1: cutToClipboard(); break;
case baseMenuItemID + 2: copyToClipboard(); break;
case baseMenuItemID + 3: pasteFromClipboard(); break;
case baseMenuItemID + 4: cut(); break;
case baseMenuItemID + 5: selectAll(); break;
case baseMenuItemID + 6: undo(); break;
case baseMenuItemID + 7: redo(); break;
default: break;
} }
} }


+ 24
- 1
src/gui/components/controls/juce_TextEditor.h View File

@@ -534,6 +534,27 @@ public:
/** @internal */ /** @internal */
void setTemporaryUnderlining (const Array <Range<int> >&); void setTemporaryUnderlining (const Array <Range<int> >&);
bool moveCaretLeft (bool moveInWholeWordSteps, bool selecting);
bool moveCaretRight (bool moveInWholeWordSteps, bool selecting);
bool moveCaretUp (bool selecting);
bool moveCaretDown (bool selecting);
bool pageUp (bool selecting);
bool pageDown (bool selecting);
bool scrollDown();
bool scrollUp();
bool moveCaretToTop (bool selecting);
bool moveCaretToStartOfLine (bool selecting);
bool moveCaretToEnd (bool selecting);
bool moveCaretToEndOfLine (bool selecting);
bool deleteBackwards (bool moveInWholeWordSteps);
bool deleteForwards (bool moveInWholeWordSteps);
bool copyToClipboard();
bool cutToClipboard();
bool pasteFromClipboard();
bool selectAll();
bool undo();
bool redo();
//============================================================================== //==============================================================================
/** This adds the items to the popup menu. /** This adds the items to the popup menu.
@@ -668,7 +689,7 @@ private:
int indexAtPosition (float x, float y); int indexAtPosition (float x, float y);
int findWordBreakAfter (int position) const; int findWordBreakAfter (int position) const;
int findWordBreakBefore (int position) const; int findWordBreakBefore (int position) const;
bool moveCaretWithTransation (int newPos, bool selecting);
friend class TextHolderComponent; friend class TextHolderComponent;
friend class TextEditorViewport; friend class TextEditorViewport;
void drawContent (Graphics& g); void drawContent (Graphics& g);
@@ -676,6 +697,8 @@ private:
float getWordWrapWidth() const; float getWordWrapWidth() const;
void timerCallbackInt(); void timerCallbackInt();
void repaintText (const Range<int>& range); void repaintText (const Range<int>& range);
void scrollByLines (int deltaLines);
bool undoOrRedo (bool shouldUndo);
UndoManager* getUndoManager() noexcept; UndoManager* getUndoManager() noexcept;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (TextEditor); JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (TextEditor);


+ 132
- 0
src/gui/components/keyboard/juce_TextEditorKeyMapper.h View File

@@ -0,0 +1,132 @@
/*
==============================================================================
This file is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright 2004-11 by Raw Material Software Ltd.
------------------------------------------------------------------------------
JUCE can be redistributed and/or modified under the terms of the GNU General
Public License (Version 2), as published by the Free Software Foundation.
A copy of the license is included in the JUCE distribution, or can be found
online at www.gnu.org/licenses.
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.
------------------------------------------------------------------------------
To release a closed-source product which uses JUCE, commercial licenses are
available: visit www.rawmaterialsoftware.com/juce for more information.
==============================================================================
*/
#ifndef __JUCE_TEXTEDITORKEYMAPPER_JUCEHEADER__
#define __JUCE_TEXTEDITORKEYMAPPER_JUCEHEADER__
#include "juce_Keypress.h"
//==============================================================================
/** This class is used to invoke a range of text-editor navigation methods on
an object, based upon a keypress event.
It's currently used internally by the TextEditor and CodeEditorComponent.
*/
template <class CallbackClass>
struct TextEditorKeyMapper
{
/** Checks the keypress and invokes one of a range of navigation functions that
the target class must implement, based on the key event.
*/
static bool invokeKeyFunction (CallbackClass& target, const KeyPress& key)
{
const bool isShiftDown = key.getModifiers().isShiftDown();
const bool ctrlOrAltDown = key.getModifiers().isCtrlDown() || key.getModifiers().isAltDown();
if (key == KeyPress (KeyPress::downKey, ModifierKeys::ctrlModifier, 0)
&& target.scrollUp())
return true;
if (key == KeyPress (KeyPress::upKey, ModifierKeys::ctrlModifier, 0)
&& target.scrollDown())
return true;
#if JUCE_MAC
if (key.getModifiers().isCommandDown())
{
if (key.isKeyCode (KeyPress::upKey))
return target.moveCaretToTop (isShiftDown);
if (key.isKeyCode (KeyPress::downKey))
return target.moveCaretToEnd (isShiftDown);
if (key.isKeyCode (KeyPress::leftKey))
return target.moveCaretToStartOfLine (isShiftDown);
if (key.isKeyCode (KeyPress::rightKey))
return target.moveCaretToEndOfLine (isShiftDown);
}
#endif
if (key.isKeyCode (KeyPress::upKey))
return target.moveCaretUp (isShiftDown);
if (key.isKeyCode (KeyPress::downKey))
return target.moveCaretDown (isShiftDown);
if (key.isKeyCode (KeyPress::leftKey))
return target.moveCaretLeft (ctrlOrAltDown, isShiftDown);
if (key.isKeyCode (KeyPress::rightKey))
return target.moveCaretRight (ctrlOrAltDown, isShiftDown);
if (key.isKeyCode (KeyPress::pageUpKey))
return target.pageUp (isShiftDown);
if (key.isKeyCode (KeyPress::pageDownKey))
return target.pageDown (isShiftDown);
if (key.isKeyCode (KeyPress::homeKey))
return ctrlOrAltDown ? target.moveCaretToTop (isShiftDown)
: target.moveCaretToStartOfLine (isShiftDown);
if (key.isKeyCode (KeyPress::endKey))
return ctrlOrAltDown ? target.moveCaretToEnd (isShiftDown)
: target.moveCaretToEndOfLine (isShiftDown);
if (key == KeyPress ('c', ModifierKeys::commandModifier, 0)
|| key == KeyPress (KeyPress::insertKey, ModifierKeys::ctrlModifier, 0))
return target.copyToClipboard();
if (key == KeyPress ('x', ModifierKeys::commandModifier, 0)
|| key == KeyPress (KeyPress::deleteKey, ModifierKeys::shiftModifier, 0))
return target.cutToClipboard();
if (key == KeyPress ('v', ModifierKeys::commandModifier, 0)
|| key == KeyPress (KeyPress::insertKey, ModifierKeys::shiftModifier, 0))
return target.pasteFromClipboard();
if (key.isKeyCode (KeyPress::backspaceKey))
return target.deleteBackwards (ctrlOrAltDown);
if (key.isKeyCode (KeyPress::deleteKey))
return target.deleteForwards (ctrlOrAltDown);
if (key == KeyPress ('a', ModifierKeys::commandModifier, 0))
return target.selectAll();
if (key == KeyPress ('z', ModifierKeys::commandModifier, 0))
return target.undo();
if (key == KeyPress ('y', ModifierKeys::commandModifier, 0)
|| key == KeyPress ('z', ModifierKeys::commandModifier | ModifierKeys::shiftModifier, 0))
return target.redo();
return false;
}
};
#endif // __JUCE_TEXTEDITORKEYMAPPER_JUCEHEADER__

+ 8
- 7
src/gui/graphics/imaging/image_file_formats/juce_GIFLoader.cpp View File

@@ -233,7 +233,7 @@ private:
sp = stack; sp = stack;
} }
int readLZWByte (const int inputCodeSize)
int readLZWByte()
{ {
if (fresh) if (fresh)
{ {
@@ -367,12 +367,13 @@ private:
bool readImage (const int interlace, const int transparent) bool readImage (const int interlace, const int transparent)
{ {
unsigned char c;
if (input.read (&c, 1) != 1)
return false;
{
unsigned char c;
if (input.read (&c, 1) != 1)
return false;
initialise (c);
initialise (c);
}
if (transparent >= 0) if (transparent >= 0)
{ {
@@ -389,7 +390,7 @@ private:
uint8* p = destData.data; uint8* p = destData.data;
const bool hasAlpha = image.hasAlphaChannel(); const bool hasAlpha = image.hasAlphaChannel();
while ((index = readLZWByte (c)) >= 0)
while ((index = readLZWByte()) >= 0)
{ {
const uint8* const paletteEntry = palette [index]; const uint8* const paletteEntry = palette [index];


+ 1
- 1
src/io/files/juce_FileOutputStream.cpp View File

@@ -74,7 +74,7 @@ bool FileOutputStream::flushBuffer()
if (bytesInBuffer > 0) if (bytesInBuffer > 0)
{ {
ok = writeInternal (buffer, bytesInBuffer);
ok = (writeInternal (buffer, bytesInBuffer) == bytesInBuffer);
bytesInBuffer = 0; bytesInBuffer = 0;
} }


+ 3
- 0
src/juce_app_includes.h View File

@@ -425,6 +425,9 @@
#ifndef __JUCE_MODIFIERKEYS_JUCEHEADER__ #ifndef __JUCE_MODIFIERKEYS_JUCEHEADER__
#include "gui/components/keyboard/juce_ModifierKeys.h" #include "gui/components/keyboard/juce_ModifierKeys.h"
#endif #endif
#ifndef __JUCE_TEXTEDITORKEYMAPPER_JUCEHEADER__
#include "gui/components/keyboard/juce_TextEditorKeyMapper.h"
#endif
#ifndef __JUCE_TEXTINPUTTARGET_JUCEHEADER__ #ifndef __JUCE_TEXTINPUTTARGET_JUCEHEADER__
#include "gui/components/keyboard/juce_TextInputTarget.h" #include "gui/components/keyboard/juce_TextInputTarget.h"
#endif #endif


+ 61
- 123
src/native/mac/juce_mac_CoreAudio.cpp View File

@@ -29,35 +29,12 @@
//============================================================================== //==============================================================================
#ifndef JUCE_COREAUDIO_ERROR_LOGGING_ENABLED
#define JUCE_COREAUDIO_ERROR_LOGGING_ENABLED 1
#endif
//==============================================================================
#undef log
#if JUCE_COREAUDIO_LOGGING_ENABLED
#define log(a) Logger::writeToLog (a)
#else
#define log(a)
#endif
#undef OK
#if JUCE_COREAUDIO_ERROR_LOGGING_ENABLED
static bool logAnyErrors_CoreAudio (const OSStatus err, const int lineNum)
{
if (err == noErr)
return true;
Logger::writeToLog ("CoreAudio error: " + String (lineNum) + " - " + String::toHexString ((int) err));
return false;
}
#define OK(a) logAnyErrors_CoreAudio (a, __LINE__)
#if JUCE_COREAUDIO_LOGGING_ENABLED //|| ! defined (JUCE_COREAUDIO_LOGGING_ENABLED)
#define JUCE_COREAUDIOLOG(a) Logger::writeToLog (a)
#else #else
#define OK(a) (a == noErr)
#define JUCE_COREAUDIOLOG(a)
#endif #endif
//============================================================================== //==============================================================================
class CoreAudioInternal : public Timer class CoreAudioInternal : public Timer
{ {
@@ -296,7 +273,7 @@ public:
rates << sampleRate; rates << sampleRate;
} }
log ("sr: " + rates);
JUCE_COREAUDIOLOG ("sr: " + rates);
inputLatency = 0; inputLatency = 0;
outputLatency = 0; outputLatency = 0;
@@ -313,7 +290,7 @@ public:
if (AudioObjectGetPropertyData (deviceID, &pa, 0, 0, &size, &lat) == noErr) if (AudioObjectGetPropertyData (deviceID, &pa, 0, 0, &size, &lat) == noErr)
outputLatency = (int) lat; outputLatency = (int) lat;
log ("lat: " + String (inputLatency) + " " + String (outputLatency));
JUCE_COREAUDIOLOG ("lat: " + String (inputLatency) + " " + String (outputLatency));
inChanNames.clear(); inChanNames.clear();
outChanNames.clear(); outChanNames.clear();
@@ -422,7 +399,7 @@ public:
int bufferSizeSamples) int bufferSizeSamples)
{ {
String error; String error;
log ("CoreAudio reopen");
JUCE_COREAUDIOLOG ("CoreAudio reopen");
callbacksAllowed = false; callbacksAllowed = false;
stopTimer(); stopTimer();
@@ -496,11 +473,11 @@ public:
if (deviceID != 0) if (deviceID != 0)
{ {
#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5
#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5
if (OK (AudioDeviceAddIOProc (deviceID, audioIOProc, this))) if (OK (AudioDeviceAddIOProc (deviceID, audioIOProc, this)))
#else
#else
if (OK (AudioDeviceCreateIOProcID (deviceID, audioIOProc, this, &audioProcID))) if (OK (AudioDeviceCreateIOProcID (deviceID, audioIOProc, this, &audioProcID)))
#endif
#endif
{ {
if (OK (AudioDeviceStart (deviceID, audioIOProc))) if (OK (AudioDeviceStart (deviceID, audioIOProc)))
{ {
@@ -508,12 +485,12 @@ public:
} }
else else
{ {
#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5
#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5
OK (AudioDeviceRemoveIOProc (deviceID, audioIOProc)); OK (AudioDeviceRemoveIOProc (deviceID, audioIOProc));
#else
#else
OK (AudioDeviceDestroyIOProcID (deviceID, audioProcID)); OK (AudioDeviceDestroyIOProcID (deviceID, audioProcID));
audioProcID = 0; audioProcID = 0;
#endif
#endif
} }
} }
} }
@@ -525,10 +502,7 @@ public:
callback = cb; callback = cb;
} }
if (inputDevice != nullptr)
return started && inputDevice->start (cb);
else
return started;
return started && (inputDevice == nullptr || inputDevice->start (cb));
} }
void stop (bool leaveInterruptRunning) void stop (bool leaveInterruptRunning)
@@ -544,12 +518,13 @@ public:
{ {
OK (AudioDeviceStop (deviceID, audioIOProc)); OK (AudioDeviceStop (deviceID, audioIOProc));
#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5
#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5
OK (AudioDeviceRemoveIOProc (deviceID, audioIOProc)); OK (AudioDeviceRemoveIOProc (deviceID, audioIOProc));
#else
#else
OK (AudioDeviceDestroyIOProcID (deviceID, audioProcID)); OK (AudioDeviceDestroyIOProcID (deviceID, audioProcID));
audioProcID = 0; audioProcID = 0;
#endif
#endif
started = false; started = false;
{ const ScopedLock sl (callbackLock); } { const ScopedLock sl (callbackLock); }
@@ -580,15 +555,8 @@ public:
inputDevice->stop (leaveInterruptRunning); inputDevice->stop (leaveInterruptRunning);
} }
double getSampleRate() const
{
return sampleRate;
}
int getBufferSize() const
{
return bufferSize;
}
double getSampleRate() const { return sampleRate; }
int getBufferSize() const { return bufferSize; }
void audioCallback (const AudioBufferList* inInputData, void audioCallback (const AudioBufferList* inInputData,
AudioBufferList* outOutputData) AudioBufferList* outOutputData)
@@ -695,7 +663,7 @@ public:
void timerCallback() void timerCallback()
{ {
stopTimer(); stopTimer();
log ("CoreAudio device changed callback");
JUCE_COREAUDIOLOG ("CoreAudio device changed callback");
const double oldSampleRate = sampleRate; const double oldSampleRate = sampleRate;
const int oldBufferSize = bufferSize; const int oldBufferSize = bufferSize;
@@ -759,9 +727,9 @@ public:
Array <double> sampleRates; Array <double> sampleRates;
Array <int> bufferSizes; Array <int> bufferSizes;
AudioIODeviceCallback* callback; AudioIODeviceCallback* callback;
#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5
#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5
AudioDeviceIOProcID audioProcID; AudioDeviceIOProcID audioProcID;
#endif
#endif
ScopedPointer<CoreAudioInternal> inputDevice; ScopedPointer<CoreAudioInternal> inputDevice;
bool isSlaveDevice; bool isSlaveDevice;
@@ -836,17 +804,31 @@ private:
UInt32 size = 0; UInt32 size = 0;
if (deviceID != 0 if (deviceID != 0
&& OK (AudioObjectGetPropertyDataSize (deviceID, &pa, 0, 0, &size)))
&& AudioObjectGetPropertyDataSize (deviceID, &pa, 0, 0, &size) == noErr)
{ {
types.calloc (size, 1); types.calloc (size, 1);
if (OK (AudioObjectGetPropertyData (deviceID, &pa, 0, 0, &size, types)))
if (AudioObjectGetPropertyData (deviceID, &pa, 0, 0, &size, types) == noErr)
return size / (int) sizeof (OSType); return size / (int) sizeof (OSType);
} }
return 0; return 0;
} }
bool OK (const OSStatus errorCode) const
{
if (errorCode == noErr)
return true;
const String errorMessage ("CoreAudio error: " + String::toHexString ((int) errorCode));
JUCE_COREAUDIOLOG (errorMessage);
if (callback != nullptr)
callback->audioDeviceError (errorMessage);
return false;
}
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (CoreAudioInternal); JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (CoreAudioInternal);
}; };
@@ -888,6 +870,7 @@ public:
} }
internal = device; internal = device;
jassert (device != nullptr);
AudioObjectPropertyAddress pa; AudioObjectPropertyAddress pa;
pa.mSelector = kAudioObjectPropertySelectorWildcard; pa.mSelector = kAudioObjectPropertySelectorWildcard;
@@ -922,25 +905,17 @@ public:
return internal->inChanNames; return internal->inChanNames;
} }
int getNumSampleRates()
{
return internal->sampleRates.size();
}
bool isOpen() { return isOpen_; }
double getSampleRate (int index)
{
return internal->sampleRates [index];
}
int getNumSampleRates() { return internal->sampleRates.size(); }
double getSampleRate (int index) { return internal->sampleRates [index]; }
double getCurrentSampleRate() { return internal->getSampleRate(); }
int getNumBufferSizesAvailable()
{
return internal->bufferSizes.size();
}
int getCurrentBitDepth() { return 32; } // no way to find out, so just assume it's high..
int getBufferSizeSamples (int index)
{
return internal->bufferSizes [index];
}
int getNumBufferSizesAvailable() { return internal->bufferSizes.size(); }
int getBufferSizeSamples (int index) { return internal->bufferSizes [index]; }
int getCurrentBufferSizeSamples() { return internal->getBufferSize(); }
int getDefaultBufferSize() int getDefaultBufferSize()
{ {
@@ -972,51 +947,23 @@ public:
internal->stop (false); internal->stop (false);
} }
bool isOpen()
{
return isOpen_;
}
int getCurrentBufferSizeSamples()
{
return internal != nullptr ? internal->getBufferSize() : 512;
}
double getCurrentSampleRate()
{
return internal != nullptr ? internal->getSampleRate() : 0;
}
int getCurrentBitDepth()
{
return 32; // no way to find out, so just assume it's high..
}
const BigInteger getActiveOutputChannels() const const BigInteger getActiveOutputChannels() const
{ {
return internal != nullptr ? internal->activeOutputChans : BigInteger();
return internal->activeOutputChans;
} }
const BigInteger getActiveInputChannels() const const BigInteger getActiveInputChannels() const
{ {
BigInteger chans;
BigInteger chans (internal->activeInputChans);
if (internal != nullptr)
{
chans = internal->activeInputChans;
if (internal->inputDevice != 0)
chans |= internal->inputDevice->activeInputChans;
}
if (internal->inputDevice != nullptr)
chans |= internal->inputDevice->activeInputChans;
return chans; return chans;
} }
int getOutputLatencyInSamples() int getOutputLatencyInSamples()
{ {
if (internal == nullptr)
return 0;
// this seems like a good guess at getting the latency right - comparing // this seems like a good guess at getting the latency right - comparing
// this with a round-trip measurement, it gets it to within a few millisecs // this with a round-trip measurement, it gets it to within a few millisecs
// for the built-in mac soundcard // for the built-in mac soundcard
@@ -1025,15 +972,12 @@ public:
int getInputLatencyInSamples() int getInputLatencyInSamples()
{ {
if (internal == nullptr)
return 0;
return internal->inputLatency + internal->getBufferSize() * 2; return internal->inputLatency + internal->getBufferSize() * 2;
} }
void start (AudioIODeviceCallback* callback) void start (AudioIODeviceCallback* callback)
{ {
if (internal != nullptr && ! isStarted)
if (! isStarted)
{ {
if (callback != nullptr) if (callback != nullptr)
callback->audioDeviceAboutToStart (this); callback->audioDeviceAboutToStart (this);
@@ -1045,7 +989,7 @@ public:
void stop() void stop()
{ {
if (isStarted && internal != nullptr)
if (isStarted)
{ {
AudioIODeviceCallback* const lastCallback = internal->callback; AudioIODeviceCallback* const lastCallback = internal->callback;
@@ -1110,10 +1054,6 @@ public:
{ {
} }
~CoreAudioIODeviceType()
{
}
//============================================================================== //==============================================================================
void scanForDevices() void scanForDevices()
{ {
@@ -1131,12 +1071,12 @@ public:
pa.mScope = kAudioObjectPropertyScopeWildcard; pa.mScope = kAudioObjectPropertyScopeWildcard;
pa.mElement = kAudioObjectPropertyElementMaster; pa.mElement = kAudioObjectPropertyElementMaster;
if (OK (AudioObjectGetPropertyDataSize (kAudioObjectSystemObject, &pa, 0, 0, &size)))
if (AudioObjectGetPropertyDataSize (kAudioObjectSystemObject, &pa, 0, 0, &size) == noErr)
{ {
HeapBlock <AudioDeviceID> devs; HeapBlock <AudioDeviceID> devs;
devs.calloc (size, 1); devs.calloc (size, 1);
if (OK (AudioObjectGetPropertyData (kAudioObjectSystemObject, &pa, 0, 0, &size, devs)))
if (AudioObjectGetPropertyData (kAudioObjectSystemObject, &pa, 0, 0, &size, devs) == noErr)
{ {
const int num = size / (int) sizeof (AudioDeviceID); const int num = size / (int) sizeof (AudioDeviceID);
for (int i = 0; i < num; ++i) for (int i = 0; i < num; ++i)
@@ -1145,7 +1085,7 @@ public:
size = sizeof (name); size = sizeof (name);
pa.mSelector = kAudioDevicePropertyDeviceName; pa.mSelector = kAudioDevicePropertyDeviceName;
if (OK (AudioObjectGetPropertyData (devs[i], &pa, 0, 0, &size, name)))
if (AudioObjectGetPropertyData (devs[i], &pa, 0, 0, &size, name) == noErr)
{ {
const String nameString (String::fromUTF8 (name, (int) strlen (name))); const String nameString (String::fromUTF8 (name, (int) strlen (name)));
const int numIns = getNumChannels (devs[i], true); const int numIns = getNumChannels (devs[i], true);
@@ -1175,10 +1115,8 @@ public:
{ {
jassert (hasScanned); // need to call scanForDevices() before doing this jassert (hasScanned); // need to call scanForDevices() before doing this
if (wantInputNames)
return inputDeviceNames;
else
return outputDeviceNames;
return wantInputNames ? inputDeviceNames
: outputDeviceNames;
} }
int getDefaultDeviceIndex (bool forInput) const int getDefaultDeviceIndex (bool forInput) const
@@ -1268,12 +1206,12 @@ private:
pa.mScope = input ? kAudioDevicePropertyScopeInput : kAudioDevicePropertyScopeOutput; pa.mScope = input ? kAudioDevicePropertyScopeInput : kAudioDevicePropertyScopeOutput;
pa.mElement = kAudioObjectPropertyElementMaster; pa.mElement = kAudioObjectPropertyElementMaster;
if (OK (AudioObjectGetPropertyDataSize (deviceID, &pa, 0, 0, &size)))
if (AudioObjectGetPropertyDataSize (deviceID, &pa, 0, 0, &size) == noErr)
{ {
HeapBlock <AudioBufferList> bufList; HeapBlock <AudioBufferList> bufList;
bufList.calloc (size, 1); bufList.calloc (size, 1);
if (OK (AudioObjectGetPropertyData (deviceID, &pa, 0, 0, &size, bufList)))
if (AudioObjectGetPropertyData (deviceID, &pa, 0, 0, &size, bufList) == noErr)
{ {
const int numStreams = bufList->mNumberBuffers; const int numStreams = bufList->mNumberBuffers;
@@ -1297,6 +1235,6 @@ AudioIODeviceType* AudioIODeviceType::createAudioIODeviceType_CoreAudio()
return new CoreAudioIODeviceType(); return new CoreAudioIODeviceType();
} }
#undef log
#undef JUCE_COREAUDIOLOG
#endif #endif

Loading…
Cancel
Save