work save: use SimpleIni.h to read/save project
This commit is contained in:
parent
702124bdb0
commit
276c56e270
|
@ -0,0 +1,539 @@
|
|||
/*
|
||||
* Copyright 2001-2004 Unicode, Inc.
|
||||
*
|
||||
* Disclaimer
|
||||
*
|
||||
* This source code is provided as is by Unicode, Inc. No claims are
|
||||
* made as to fitness for any particular purpose. No warranties of any
|
||||
* kind are expressed or implied. The recipient agrees to determine
|
||||
* applicability of information provided. If this file has been
|
||||
* purchased on magnetic or optical media from Unicode, Inc., the
|
||||
* sole remedy for any claim will be exchange of defective media
|
||||
* within 90 days of receipt.
|
||||
*
|
||||
* Limitations on Rights to Redistribute This Code
|
||||
*
|
||||
* Unicode, Inc. hereby grants the right to freely use the information
|
||||
* supplied in this file in the creation of products supporting the
|
||||
* Unicode Standard, and to make copies of this file in any form
|
||||
* for internal or external distribution as long as this notice
|
||||
* remains attached.
|
||||
*/
|
||||
|
||||
/* ---------------------------------------------------------------------
|
||||
|
||||
Conversions between UTF32, UTF-16, and UTF-8. Source code file.
|
||||
Author: Mark E. Davis, 1994.
|
||||
Rev History: Rick McGowan, fixes & updates May 2001.
|
||||
Sept 2001: fixed const & error conditions per
|
||||
mods suggested by S. Parent & A. Lillich.
|
||||
June 2002: Tim Dodd added detection and handling of incomplete
|
||||
source sequences, enhanced error detection, added casts
|
||||
to eliminate compiler warnings.
|
||||
July 2003: slight mods to back out aggressive FFFE detection.
|
||||
Jan 2004: updated switches in from-UTF8 conversions.
|
||||
Oct 2004: updated to use UNI_MAX_LEGAL_UTF32 in UTF-32 conversions.
|
||||
|
||||
See the header file "ConvertUTF.h" for complete documentation.
|
||||
|
||||
------------------------------------------------------------------------ */
|
||||
|
||||
|
||||
#include "ConvertUTF.h"
|
||||
#ifdef CVTUTF_DEBUG
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
|
||||
static const int halfShift = 10; /* used for shifting by 10 bits */
|
||||
|
||||
static const UTF32 halfBase = 0x0010000UL;
|
||||
static const UTF32 halfMask = 0x3FFUL;
|
||||
|
||||
#define UNI_SUR_HIGH_START (UTF32)0xD800
|
||||
#define UNI_SUR_HIGH_END (UTF32)0xDBFF
|
||||
#define UNI_SUR_LOW_START (UTF32)0xDC00
|
||||
#define UNI_SUR_LOW_END (UTF32)0xDFFF
|
||||
#define false 0
|
||||
#define true 1
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
ConversionResult ConvertUTF32toUTF16 (
|
||||
const UTF32** sourceStart, const UTF32* sourceEnd,
|
||||
UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags) {
|
||||
ConversionResult result = conversionOK;
|
||||
const UTF32* source = *sourceStart;
|
||||
UTF16* target = *targetStart;
|
||||
while (source < sourceEnd) {
|
||||
UTF32 ch;
|
||||
if (target >= targetEnd) {
|
||||
result = targetExhausted; break;
|
||||
}
|
||||
ch = *source++;
|
||||
if (ch <= UNI_MAX_BMP) { /* Target is a character <= 0xFFFF */
|
||||
/* UTF-16 surrogate values are illegal in UTF-32; 0xffff or 0xfffe are both reserved values */
|
||||
if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) {
|
||||
if (flags == strictConversion) {
|
||||
--source; /* return to the illegal value itself */
|
||||
result = sourceIllegal;
|
||||
break;
|
||||
} else {
|
||||
*target++ = UNI_REPLACEMENT_CHAR;
|
||||
}
|
||||
} else {
|
||||
*target++ = (UTF16)ch; /* normal case */
|
||||
}
|
||||
} else if (ch > UNI_MAX_LEGAL_UTF32) {
|
||||
if (flags == strictConversion) {
|
||||
result = sourceIllegal;
|
||||
} else {
|
||||
*target++ = UNI_REPLACEMENT_CHAR;
|
||||
}
|
||||
} else {
|
||||
/* target is a character in range 0xFFFF - 0x10FFFF. */
|
||||
if (target + 1 >= targetEnd) {
|
||||
--source; /* Back up source pointer! */
|
||||
result = targetExhausted; break;
|
||||
}
|
||||
ch -= halfBase;
|
||||
*target++ = (UTF16)((ch >> halfShift) + UNI_SUR_HIGH_START);
|
||||
*target++ = (UTF16)((ch & halfMask) + UNI_SUR_LOW_START);
|
||||
}
|
||||
}
|
||||
*sourceStart = source;
|
||||
*targetStart = target;
|
||||
return result;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
ConversionResult ConvertUTF16toUTF32 (
|
||||
const UTF16** sourceStart, const UTF16* sourceEnd,
|
||||
UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags) {
|
||||
ConversionResult result = conversionOK;
|
||||
const UTF16* source = *sourceStart;
|
||||
UTF32* target = *targetStart;
|
||||
UTF32 ch, ch2;
|
||||
while (source < sourceEnd) {
|
||||
const UTF16* oldSource = source; /* In case we have to back up because of target overflow. */
|
||||
ch = *source++;
|
||||
/* If we have a surrogate pair, convert to UTF32 first. */
|
||||
if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_HIGH_END) {
|
||||
/* If the 16 bits following the high surrogate are in the source buffer... */
|
||||
if (source < sourceEnd) {
|
||||
ch2 = *source;
|
||||
/* If it's a low surrogate, convert to UTF32. */
|
||||
if (ch2 >= UNI_SUR_LOW_START && ch2 <= UNI_SUR_LOW_END) {
|
||||
ch = ((ch - UNI_SUR_HIGH_START) << halfShift)
|
||||
+ (ch2 - UNI_SUR_LOW_START) + halfBase;
|
||||
++source;
|
||||
} else if (flags == strictConversion) { /* it's an unpaired high surrogate */
|
||||
--source; /* return to the illegal value itself */
|
||||
result = sourceIllegal;
|
||||
break;
|
||||
}
|
||||
} else { /* We don't have the 16 bits following the high surrogate. */
|
||||
--source; /* return to the high surrogate */
|
||||
result = sourceExhausted;
|
||||
break;
|
||||
}
|
||||
} else if (flags == strictConversion) {
|
||||
/* UTF-16 surrogate values are illegal in UTF-32 */
|
||||
if (ch >= UNI_SUR_LOW_START && ch <= UNI_SUR_LOW_END) {
|
||||
--source; /* return to the illegal value itself */
|
||||
result = sourceIllegal;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (target >= targetEnd) {
|
||||
source = oldSource; /* Back up source pointer! */
|
||||
result = targetExhausted; break;
|
||||
}
|
||||
*target++ = ch;
|
||||
}
|
||||
*sourceStart = source;
|
||||
*targetStart = target;
|
||||
#ifdef CVTUTF_DEBUG
|
||||
if (result == sourceIllegal) {
|
||||
fprintf(stderr, "ConvertUTF16toUTF32 illegal seq 0x%04x,%04x\n", ch, ch2);
|
||||
fflush(stderr);
|
||||
}
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
/*
|
||||
* Index into the table below with the first byte of a UTF-8 sequence to
|
||||
* get the number of trailing bytes that are supposed to follow it.
|
||||
* Note that *legal* UTF-8 values can't have 4 or 5-bytes. The table is
|
||||
* left as-is for anyone who may want to do such conversion, which was
|
||||
* allowed in earlier algorithms.
|
||||
*/
|
||||
static const char trailingBytesForUTF8[256] = {
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
||||
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 3,3,3,3,3,3,3,3,4,4,4,4,5,5,5,5
|
||||
};
|
||||
|
||||
/*
|
||||
* Magic values subtracted from a buffer value during UTF8 conversion.
|
||||
* This table contains as many values as there might be trailing bytes
|
||||
* in a UTF-8 sequence.
|
||||
*/
|
||||
static const UTF32 offsetsFromUTF8[6] = { 0x00000000UL, 0x00003080UL, 0x000E2080UL,
|
||||
0x03C82080UL, 0xFA082080UL, 0x82082080UL };
|
||||
|
||||
/*
|
||||
* Once the bits are split out into bytes of UTF-8, this is a mask OR-ed
|
||||
* into the first byte, depending on how many bytes follow. There are
|
||||
* as many entries in this table as there are UTF-8 sequence types.
|
||||
* (I.e., one byte sequence, two byte... etc.). Remember that sequencs
|
||||
* for *legal* UTF-8 will be 4 or fewer bytes total.
|
||||
*/
|
||||
static const UTF8 firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
/* The interface converts a whole buffer to avoid function-call overhead.
|
||||
* Constants have been gathered. Loops & conditionals have been removed as
|
||||
* much as possible for efficiency, in favor of drop-through switches.
|
||||
* (See "Note A" at the bottom of the file for equivalent code.)
|
||||
* If your compiler supports it, the "isLegalUTF8" call can be turned
|
||||
* into an inline function.
|
||||
*/
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
ConversionResult ConvertUTF16toUTF8 (
|
||||
const UTF16** sourceStart, const UTF16* sourceEnd,
|
||||
UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags) {
|
||||
ConversionResult result = conversionOK;
|
||||
const UTF16* source = *sourceStart;
|
||||
UTF8* target = *targetStart;
|
||||
while (source < sourceEnd) {
|
||||
UTF32 ch;
|
||||
unsigned short bytesToWrite = 0;
|
||||
const UTF32 byteMask = 0xBF;
|
||||
const UTF32 byteMark = 0x80;
|
||||
const UTF16* oldSource = source; /* In case we have to back up because of target overflow. */
|
||||
ch = *source++;
|
||||
/* If we have a surrogate pair, convert to UTF32 first. */
|
||||
if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_HIGH_END) {
|
||||
/* If the 16 bits following the high surrogate are in the source buffer... */
|
||||
if (source < sourceEnd) {
|
||||
UTF32 ch2 = *source;
|
||||
/* If it's a low surrogate, convert to UTF32. */
|
||||
if (ch2 >= UNI_SUR_LOW_START && ch2 <= UNI_SUR_LOW_END) {
|
||||
ch = ((ch - UNI_SUR_HIGH_START) << halfShift)
|
||||
+ (ch2 - UNI_SUR_LOW_START) + halfBase;
|
||||
++source;
|
||||
} else if (flags == strictConversion) { /* it's an unpaired high surrogate */
|
||||
--source; /* return to the illegal value itself */
|
||||
result = sourceIllegal;
|
||||
break;
|
||||
}
|
||||
} else { /* We don't have the 16 bits following the high surrogate. */
|
||||
--source; /* return to the high surrogate */
|
||||
result = sourceExhausted;
|
||||
break;
|
||||
}
|
||||
} else if (flags == strictConversion) {
|
||||
/* UTF-16 surrogate values are illegal in UTF-32 */
|
||||
if (ch >= UNI_SUR_LOW_START && ch <= UNI_SUR_LOW_END) {
|
||||
--source; /* return to the illegal value itself */
|
||||
result = sourceIllegal;
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* Figure out how many bytes the result will require */
|
||||
if (ch < (UTF32)0x80) { bytesToWrite = 1;
|
||||
} else if (ch < (UTF32)0x800) { bytesToWrite = 2;
|
||||
} else if (ch < (UTF32)0x10000) { bytesToWrite = 3;
|
||||
} else if (ch < (UTF32)0x110000) { bytesToWrite = 4;
|
||||
} else { bytesToWrite = 3;
|
||||
ch = UNI_REPLACEMENT_CHAR;
|
||||
}
|
||||
|
||||
target += bytesToWrite;
|
||||
if (target > targetEnd) {
|
||||
source = oldSource; /* Back up source pointer! */
|
||||
target -= bytesToWrite; result = targetExhausted; break;
|
||||
}
|
||||
switch (bytesToWrite) { /* note: everything falls through. */
|
||||
case 4: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6;
|
||||
case 3: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6;
|
||||
case 2: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6;
|
||||
case 1: *--target = (UTF8)(ch | firstByteMark[bytesToWrite]);
|
||||
}
|
||||
target += bytesToWrite;
|
||||
}
|
||||
*sourceStart = source;
|
||||
*targetStart = target;
|
||||
return result;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
/*
|
||||
* Utility routine to tell whether a sequence of bytes is legal UTF-8.
|
||||
* This must be called with the length pre-determined by the first byte.
|
||||
* If not calling this from ConvertUTF8to*, then the length can be set by:
|
||||
* length = trailingBytesForUTF8[*source]+1;
|
||||
* and the sequence is illegal right away if there aren't that many bytes
|
||||
* available.
|
||||
* If presented with a length > 4, this returns false. The Unicode
|
||||
* definition of UTF-8 goes up to 4-byte sequences.
|
||||
*/
|
||||
|
||||
static Boolean isLegalUTF8(const UTF8 *source, int length) {
|
||||
UTF8 a;
|
||||
const UTF8 *srcptr = source+length;
|
||||
switch (length) {
|
||||
default: return false;
|
||||
/* Everything else falls through when "true"... */
|
||||
case 4: if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return false;
|
||||
case 3: if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return false;
|
||||
case 2: if ((a = (*--srcptr)) > 0xBF) return false;
|
||||
|
||||
switch (*source) {
|
||||
/* no fall-through in this inner switch */
|
||||
case 0xE0: if (a < 0xA0) return false; break;
|
||||
case 0xED: if (a > 0x9F) return false; break;
|
||||
case 0xF0: if (a < 0x90) return false; break;
|
||||
case 0xF4: if (a > 0x8F) return false; break;
|
||||
default: if (a < 0x80) return false;
|
||||
}
|
||||
|
||||
case 1: if (*source >= 0x80 && *source < 0xC2) return false;
|
||||
}
|
||||
if (*source > 0xF4) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
/*
|
||||
* Exported function to return whether a UTF-8 sequence is legal or not.
|
||||
* This is not used here; it's just exported.
|
||||
*/
|
||||
Boolean isLegalUTF8Sequence(const UTF8 *source, const UTF8 *sourceEnd) {
|
||||
int length = trailingBytesForUTF8[*source]+1;
|
||||
if (source+length > sourceEnd) {
|
||||
return false;
|
||||
}
|
||||
return isLegalUTF8(source, length);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
ConversionResult ConvertUTF8toUTF16 (
|
||||
const UTF8** sourceStart, const UTF8* sourceEnd,
|
||||
UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags) {
|
||||
ConversionResult result = conversionOK;
|
||||
const UTF8* source = *sourceStart;
|
||||
UTF16* target = *targetStart;
|
||||
while (source < sourceEnd) {
|
||||
UTF32 ch = 0;
|
||||
unsigned short extraBytesToRead = trailingBytesForUTF8[*source];
|
||||
if (source + extraBytesToRead >= sourceEnd) {
|
||||
result = sourceExhausted; break;
|
||||
}
|
||||
/* Do this check whether lenient or strict */
|
||||
if (! isLegalUTF8(source, extraBytesToRead+1)) {
|
||||
result = sourceIllegal;
|
||||
break;
|
||||
}
|
||||
/*
|
||||
* The cases all fall through. See "Note A" below.
|
||||
*/
|
||||
switch (extraBytesToRead) {
|
||||
case 5: ch += *source++; ch <<= 6; /* remember, illegal UTF-8 */
|
||||
case 4: ch += *source++; ch <<= 6; /* remember, illegal UTF-8 */
|
||||
case 3: ch += *source++; ch <<= 6;
|
||||
case 2: ch += *source++; ch <<= 6;
|
||||
case 1: ch += *source++; ch <<= 6;
|
||||
case 0: ch += *source++;
|
||||
}
|
||||
ch -= offsetsFromUTF8[extraBytesToRead];
|
||||
|
||||
if (target >= targetEnd) {
|
||||
source -= (extraBytesToRead+1); /* Back up source pointer! */
|
||||
result = targetExhausted; break;
|
||||
}
|
||||
if (ch <= UNI_MAX_BMP) { /* Target is a character <= 0xFFFF */
|
||||
/* UTF-16 surrogate values are illegal in UTF-32 */
|
||||
if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) {
|
||||
if (flags == strictConversion) {
|
||||
source -= (extraBytesToRead+1); /* return to the illegal value itself */
|
||||
result = sourceIllegal;
|
||||
break;
|
||||
} else {
|
||||
*target++ = UNI_REPLACEMENT_CHAR;
|
||||
}
|
||||
} else {
|
||||
*target++ = (UTF16)ch; /* normal case */
|
||||
}
|
||||
} else if (ch > UNI_MAX_UTF16) {
|
||||
if (flags == strictConversion) {
|
||||
result = sourceIllegal;
|
||||
source -= (extraBytesToRead+1); /* return to the start */
|
||||
break; /* Bail out; shouldn't continue */
|
||||
} else {
|
||||
*target++ = UNI_REPLACEMENT_CHAR;
|
||||
}
|
||||
} else {
|
||||
/* target is a character in range 0xFFFF - 0x10FFFF. */
|
||||
if (target + 1 >= targetEnd) {
|
||||
source -= (extraBytesToRead+1); /* Back up source pointer! */
|
||||
result = targetExhausted; break;
|
||||
}
|
||||
ch -= halfBase;
|
||||
*target++ = (UTF16)((ch >> halfShift) + UNI_SUR_HIGH_START);
|
||||
*target++ = (UTF16)((ch & halfMask) + UNI_SUR_LOW_START);
|
||||
}
|
||||
}
|
||||
*sourceStart = source;
|
||||
*targetStart = target;
|
||||
return result;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
ConversionResult ConvertUTF32toUTF8 (
|
||||
const UTF32** sourceStart, const UTF32* sourceEnd,
|
||||
UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags) {
|
||||
ConversionResult result = conversionOK;
|
||||
const UTF32* source = *sourceStart;
|
||||
UTF8* target = *targetStart;
|
||||
while (source < sourceEnd) {
|
||||
UTF32 ch;
|
||||
unsigned short bytesToWrite = 0;
|
||||
const UTF32 byteMask = 0xBF;
|
||||
const UTF32 byteMark = 0x80;
|
||||
ch = *source++;
|
||||
if (flags == strictConversion ) {
|
||||
/* UTF-16 surrogate values are illegal in UTF-32 */
|
||||
if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) {
|
||||
--source; /* return to the illegal value itself */
|
||||
result = sourceIllegal;
|
||||
break;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Figure out how many bytes the result will require. Turn any
|
||||
* illegally large UTF32 things (> Plane 17) into replacement chars.
|
||||
*/
|
||||
if (ch < (UTF32)0x80) { bytesToWrite = 1;
|
||||
} else if (ch < (UTF32)0x800) { bytesToWrite = 2;
|
||||
} else if (ch < (UTF32)0x10000) { bytesToWrite = 3;
|
||||
} else if (ch <= UNI_MAX_LEGAL_UTF32) { bytesToWrite = 4;
|
||||
} else { bytesToWrite = 3;
|
||||
ch = UNI_REPLACEMENT_CHAR;
|
||||
result = sourceIllegal;
|
||||
}
|
||||
|
||||
target += bytesToWrite;
|
||||
if (target > targetEnd) {
|
||||
--source; /* Back up source pointer! */
|
||||
target -= bytesToWrite; result = targetExhausted; break;
|
||||
}
|
||||
switch (bytesToWrite) { /* note: everything falls through. */
|
||||
case 4: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6;
|
||||
case 3: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6;
|
||||
case 2: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6;
|
||||
case 1: *--target = (UTF8) (ch | firstByteMark[bytesToWrite]);
|
||||
}
|
||||
target += bytesToWrite;
|
||||
}
|
||||
*sourceStart = source;
|
||||
*targetStart = target;
|
||||
return result;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
ConversionResult ConvertUTF8toUTF32 (
|
||||
const UTF8** sourceStart, const UTF8* sourceEnd,
|
||||
UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags) {
|
||||
ConversionResult result = conversionOK;
|
||||
const UTF8* source = *sourceStart;
|
||||
UTF32* target = *targetStart;
|
||||
while (source < sourceEnd) {
|
||||
UTF32 ch = 0;
|
||||
unsigned short extraBytesToRead = trailingBytesForUTF8[*source];
|
||||
if (source + extraBytesToRead >= sourceEnd) {
|
||||
result = sourceExhausted; break;
|
||||
}
|
||||
/* Do this check whether lenient or strict */
|
||||
if (! isLegalUTF8(source, extraBytesToRead+1)) {
|
||||
result = sourceIllegal;
|
||||
break;
|
||||
}
|
||||
/*
|
||||
* The cases all fall through. See "Note A" below.
|
||||
*/
|
||||
switch (extraBytesToRead) {
|
||||
case 5: ch += *source++; ch <<= 6;
|
||||
case 4: ch += *source++; ch <<= 6;
|
||||
case 3: ch += *source++; ch <<= 6;
|
||||
case 2: ch += *source++; ch <<= 6;
|
||||
case 1: ch += *source++; ch <<= 6;
|
||||
case 0: ch += *source++;
|
||||
}
|
||||
ch -= offsetsFromUTF8[extraBytesToRead];
|
||||
|
||||
if (target >= targetEnd) {
|
||||
source -= (extraBytesToRead+1); /* Back up the source pointer! */
|
||||
result = targetExhausted; break;
|
||||
}
|
||||
if (ch <= UNI_MAX_LEGAL_UTF32) {
|
||||
/*
|
||||
* UTF-16 surrogate values are illegal in UTF-32, and anything
|
||||
* over Plane 17 (> 0x10FFFF) is illegal.
|
||||
*/
|
||||
if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) {
|
||||
if (flags == strictConversion) {
|
||||
source -= (extraBytesToRead+1); /* return to the illegal value itself */
|
||||
result = sourceIllegal;
|
||||
break;
|
||||
} else {
|
||||
*target++ = UNI_REPLACEMENT_CHAR;
|
||||
}
|
||||
} else {
|
||||
*target++ = ch;
|
||||
}
|
||||
} else { /* i.e., ch > UNI_MAX_LEGAL_UTF32 */
|
||||
result = sourceIllegal;
|
||||
*target++ = UNI_REPLACEMENT_CHAR;
|
||||
}
|
||||
}
|
||||
*sourceStart = source;
|
||||
*targetStart = target;
|
||||
return result;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------
|
||||
|
||||
Note A.
|
||||
The fall-through switches in UTF-8 reading code save a
|
||||
temp variable, some decrements & conditionals. The switches
|
||||
are equivalent to the following loop:
|
||||
{
|
||||
int tmpBytesToRead = extraBytesToRead+1;
|
||||
do {
|
||||
ch += *source++;
|
||||
--tmpBytesToRead;
|
||||
if (tmpBytesToRead) ch <<= 6;
|
||||
} while (tmpBytesToRead > 0);
|
||||
}
|
||||
In UTF-8 writing code, the switches on "bytesToWrite" are
|
||||
similarly unrolled loops.
|
||||
|
||||
--------------------------------------------------------------------- */
|
|
@ -0,0 +1,149 @@
|
|||
/*
|
||||
* Copyright 2001-2004 Unicode, Inc.
|
||||
*
|
||||
* Disclaimer
|
||||
*
|
||||
* This source code is provided as is by Unicode, Inc. No claims are
|
||||
* made as to fitness for any particular purpose. No warranties of any
|
||||
* kind are expressed or implied. The recipient agrees to determine
|
||||
* applicability of information provided. If this file has been
|
||||
* purchased on magnetic or optical media from Unicode, Inc., the
|
||||
* sole remedy for any claim will be exchange of defective media
|
||||
* within 90 days of receipt.
|
||||
*
|
||||
* Limitations on Rights to Redistribute This Code
|
||||
*
|
||||
* Unicode, Inc. hereby grants the right to freely use the information
|
||||
* supplied in this file in the creation of products supporting the
|
||||
* Unicode Standard, and to make copies of this file in any form
|
||||
* for internal or external distribution as long as this notice
|
||||
* remains attached.
|
||||
*/
|
||||
|
||||
/* ---------------------------------------------------------------------
|
||||
|
||||
Conversions between UTF32, UTF-16, and UTF-8. Header file.
|
||||
|
||||
Several funtions are included here, forming a complete set of
|
||||
conversions between the three formats. UTF-7 is not included
|
||||
here, but is handled in a separate source file.
|
||||
|
||||
Each of these routines takes pointers to input buffers and output
|
||||
buffers. The input buffers are const.
|
||||
|
||||
Each routine converts the text between *sourceStart and sourceEnd,
|
||||
putting the result into the buffer between *targetStart and
|
||||
targetEnd. Note: the end pointers are *after* the last item: e.g.
|
||||
*(sourceEnd - 1) is the last item.
|
||||
|
||||
The return result indicates whether the conversion was successful,
|
||||
and if not, whether the problem was in the source or target buffers.
|
||||
(Only the first encountered problem is indicated.)
|
||||
|
||||
After the conversion, *sourceStart and *targetStart are both
|
||||
updated to point to the end of last text successfully converted in
|
||||
the respective buffers.
|
||||
|
||||
Input parameters:
|
||||
sourceStart - pointer to a pointer to the source buffer.
|
||||
The contents of this are modified on return so that
|
||||
it points at the next thing to be converted.
|
||||
targetStart - similarly, pointer to pointer to the target buffer.
|
||||
sourceEnd, targetEnd - respectively pointers to the ends of the
|
||||
two buffers, for overflow checking only.
|
||||
|
||||
These conversion functions take a ConversionFlags argument. When this
|
||||
flag is set to strict, both irregular sequences and isolated surrogates
|
||||
will cause an error. When the flag is set to lenient, both irregular
|
||||
sequences and isolated surrogates are converted.
|
||||
|
||||
Whether the flag is strict or lenient, all illegal sequences will cause
|
||||
an error return. This includes sequences such as: <F4 90 80 80>, <C0 80>,
|
||||
or <A0> in UTF-8, and values above 0x10FFFF in UTF-32. Conformant code
|
||||
must check for illegal sequences.
|
||||
|
||||
When the flag is set to lenient, characters over 0x10FFFF are converted
|
||||
to the replacement character; otherwise (when the flag is set to strict)
|
||||
they constitute an error.
|
||||
|
||||
Output parameters:
|
||||
The value "sourceIllegal" is returned from some routines if the input
|
||||
sequence is malformed. When "sourceIllegal" is returned, the source
|
||||
value will point to the illegal value that caused the problem. E.g.,
|
||||
in UTF-8 when a sequence is malformed, it points to the start of the
|
||||
malformed sequence.
|
||||
|
||||
Author: Mark E. Davis, 1994.
|
||||
Rev History: Rick McGowan, fixes & updates May 2001.
|
||||
Fixes & updates, Sept 2001.
|
||||
|
||||
------------------------------------------------------------------------ */
|
||||
|
||||
/* ---------------------------------------------------------------------
|
||||
The following 4 definitions are compiler-specific.
|
||||
The C standard does not guarantee that wchar_t has at least
|
||||
16 bits, so wchar_t is no less portable than unsigned short!
|
||||
All should be unsigned values to avoid sign extension during
|
||||
bit mask & shift operations.
|
||||
------------------------------------------------------------------------ */
|
||||
|
||||
typedef unsigned int UTF32; /* at least 32 bits */
|
||||
typedef unsigned short UTF16; /* at least 16 bits */
|
||||
typedef unsigned char UTF8; /* typically 8 bits */
|
||||
typedef unsigned char Boolean; /* 0 or 1 */
|
||||
|
||||
/* Some fundamental constants */
|
||||
#define UNI_REPLACEMENT_CHAR (UTF32)0x0000FFFD
|
||||
#define UNI_MAX_BMP (UTF32)0x0000FFFF
|
||||
#define UNI_MAX_UTF16 (UTF32)0x0010FFFF
|
||||
#define UNI_MAX_UTF32 (UTF32)0x7FFFFFFF
|
||||
#define UNI_MAX_LEGAL_UTF32 (UTF32)0x0010FFFF
|
||||
|
||||
typedef enum {
|
||||
conversionOK, /* conversion successful */
|
||||
sourceExhausted, /* partial character in source, but hit end */
|
||||
targetExhausted, /* insuff. room in target for conversion */
|
||||
sourceIllegal /* source sequence is illegal/malformed */
|
||||
} ConversionResult;
|
||||
|
||||
typedef enum {
|
||||
strictConversion = 0,
|
||||
lenientConversion
|
||||
} ConversionFlags;
|
||||
|
||||
/* This is for C++ and does no harm in C */
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
ConversionResult ConvertUTF8toUTF16 (
|
||||
const UTF8** sourceStart, const UTF8* sourceEnd,
|
||||
UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags);
|
||||
|
||||
ConversionResult ConvertUTF16toUTF8 (
|
||||
const UTF16** sourceStart, const UTF16* sourceEnd,
|
||||
UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags);
|
||||
|
||||
ConversionResult ConvertUTF8toUTF32 (
|
||||
const UTF8** sourceStart, const UTF8* sourceEnd,
|
||||
UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags);
|
||||
|
||||
ConversionResult ConvertUTF32toUTF8 (
|
||||
const UTF32** sourceStart, const UTF32* sourceEnd,
|
||||
UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags);
|
||||
|
||||
ConversionResult ConvertUTF16toUTF32 (
|
||||
const UTF16** sourceStart, const UTF16* sourceEnd,
|
||||
UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags);
|
||||
|
||||
ConversionResult ConvertUTF32toUTF16 (
|
||||
const UTF32** sourceStart, const UTF32* sourceEnd,
|
||||
UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags);
|
||||
|
||||
Boolean isLegalUTF8Sequence(const UTF8 *source, const UTF8 *sourceEnd);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
|
@ -13,6 +13,7 @@ QMAKE_CXXFLAGS_DEBUG += -Werror=return-type
|
|||
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
|
||||
|
||||
SOURCES += \
|
||||
ConvertUTF.c \
|
||||
HighlighterManager.cpp \
|
||||
autolinkmanager.cpp \
|
||||
caretlist.cpp \
|
||||
|
@ -92,8 +93,9 @@ SOURCES += \
|
|||
widgets/searchresultview.cpp
|
||||
|
||||
HEADERS += \
|
||||
ini.h \
|
||||
ConvertUTF.h \
|
||||
HighlighterManager.h \
|
||||
SimpleIni.h \
|
||||
autolinkmanager.h \
|
||||
caretlist.h \
|
||||
codeformatter.h \
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,761 +0,0 @@
|
|||
/*
|
||||
* The MIT License (MIT)
|
||||
* Copyright (c) 2018 Danijel Durakovic
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is furnished to do
|
||||
* so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// /mINI/ v0.9.10
|
||||
// An INI file reader and writer for the modern age.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// A tiny utility library for manipulating INI files with a straightforward
|
||||
// API and a minimal footprint. It conforms to the (somewhat) standard INI
|
||||
// format - sections and keys are case insensitive and all leading and
|
||||
// trailing whitespace is ignored. Comments are lines that begin with a
|
||||
// semicolon. Trailing comments are allowed on section lines.
|
||||
//
|
||||
// Files are read on demand, upon which data is kept in memory and the file
|
||||
// is closed. This utility supports lazy writing, which only writes changes
|
||||
// and updates to a file and preserves custom formatting and comments. A lazy
|
||||
// write invoked by a write() call will read the output file, find what
|
||||
// changes have been made and update the file accordingly. If you only need to
|
||||
// generate files, use generate() instead. Section and key order is preserved
|
||||
// on read, write and insert.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// /* BASIC USAGE EXAMPLE: */
|
||||
//
|
||||
// /* read from file */
|
||||
// mINI::INIFile file("myfile.ini");
|
||||
// mINI::INIStructure ini;
|
||||
// file.read(ini);
|
||||
//
|
||||
// /* read value; gets a reference to actual value in the structure.
|
||||
// if key or section don't exist, a new empty value will be created */
|
||||
// std::string& value = ini["section"]["key"];
|
||||
//
|
||||
// /* read value safely; gets a copy of value in the structure.
|
||||
// does not alter the structure */
|
||||
// std::string value = ini.get("section").get("key");
|
||||
//
|
||||
// /* set or update values */
|
||||
// ini["section"]["key"] = "value";
|
||||
//
|
||||
// /* set multiple values */
|
||||
// ini["section2"].set({
|
||||
// {"key1", "value1"},
|
||||
// {"key2", "value2"}
|
||||
// });
|
||||
//
|
||||
// /* write updates back to file, preserving comments and formatting */
|
||||
// file.write(ini);
|
||||
//
|
||||
// /* or generate a file (overwrites the original) */
|
||||
// file.generate(ini);
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Long live the INI file!!!
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef MINI_INI_H_
|
||||
#define MINI_INI_H_
|
||||
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <algorithm>
|
||||
#include <utility>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include <fstream>
|
||||
#include <sys/stat.h>
|
||||
#include <cctype>
|
||||
|
||||
namespace mINI
|
||||
{
|
||||
namespace INIStringUtil
|
||||
{
|
||||
const char* const whitespaceDelimiters = " \t\n\r\f\v";
|
||||
inline void trim(std::string& str)
|
||||
{
|
||||
str.erase(str.find_last_not_of(whitespaceDelimiters) + 1);
|
||||
str.erase(0, str.find_first_not_of(whitespaceDelimiters));
|
||||
}
|
||||
#ifndef MINI_CASE_SENSITIVE
|
||||
inline void toLower(std::string& str)
|
||||
{
|
||||
std::transform(str.begin(), str.end(), str.begin(), [](const char c) {
|
||||
return static_cast<const char>(std::tolower(c));
|
||||
});
|
||||
}
|
||||
#endif
|
||||
inline void replace(std::string& str, std::string const& a, std::string const& b)
|
||||
{
|
||||
if (!a.empty())
|
||||
{
|
||||
std::size_t pos = 0;
|
||||
while ((pos = str.find(a, pos)) != std::string::npos)
|
||||
{
|
||||
str.replace(pos, a.size(), b);
|
||||
pos += b.size();
|
||||
}
|
||||
}
|
||||
}
|
||||
#ifdef _WIN32
|
||||
const char* const endl = "\r\n";
|
||||
#else
|
||||
const char* const endl = "\n";
|
||||
#endif
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class INIMap
|
||||
{
|
||||
private:
|
||||
using T_DataIndexMap = std::unordered_map<std::string, std::size_t>;
|
||||
using T_DataItem = std::pair<std::string, T>;
|
||||
using T_DataContainer = std::vector<T_DataItem>;
|
||||
using T_MultiArgs = typename std::vector<std::pair<std::string, T>>;
|
||||
|
||||
T_DataIndexMap dataIndexMap;
|
||||
T_DataContainer data;
|
||||
|
||||
inline std::size_t setEmpty(std::string& key)
|
||||
{
|
||||
std::size_t index = data.size();
|
||||
dataIndexMap[key] = index;
|
||||
data.emplace_back(key, T());
|
||||
return index;
|
||||
}
|
||||
|
||||
public:
|
||||
using const_iterator = typename T_DataContainer::const_iterator;
|
||||
|
||||
INIMap() { }
|
||||
|
||||
INIMap(INIMap const& other)
|
||||
{
|
||||
std::size_t data_size = other.data.size();
|
||||
for (std::size_t i = 0; i < data_size; ++i)
|
||||
{
|
||||
auto const& key = other.data[i].first;
|
||||
auto const& obj = other.data[i].second;
|
||||
data.emplace_back(key, obj);
|
||||
}
|
||||
dataIndexMap = T_DataIndexMap(other.dataIndexMap);
|
||||
}
|
||||
|
||||
T& operator[](std::string key)
|
||||
{
|
||||
INIStringUtil::trim(key);
|
||||
#ifndef MINI_CASE_SENSITIVE
|
||||
INIStringUtil::toLower(key);
|
||||
#endif
|
||||
auto it = dataIndexMap.find(key);
|
||||
bool hasIt = (it != dataIndexMap.end());
|
||||
std::size_t index = (hasIt) ? it->second : setEmpty(key);
|
||||
return data[index].second;
|
||||
}
|
||||
T get(std::string key) const
|
||||
{
|
||||
INIStringUtil::trim(key);
|
||||
#ifndef MINI_CASE_SENSITIVE
|
||||
INIStringUtil::toLower(key);
|
||||
#endif
|
||||
auto it = dataIndexMap.find(key);
|
||||
if (it == dataIndexMap.end())
|
||||
{
|
||||
return T();
|
||||
}
|
||||
return T(data[it->second].second);
|
||||
}
|
||||
bool has(std::string key) const
|
||||
{
|
||||
INIStringUtil::trim(key);
|
||||
#ifndef MINI_CASE_SENSITIVE
|
||||
INIStringUtil::toLower(key);
|
||||
#endif
|
||||
return (dataIndexMap.count(key) == 1);
|
||||
}
|
||||
void set(std::string key, T obj)
|
||||
{
|
||||
INIStringUtil::trim(key);
|
||||
#ifndef MINI_CASE_SENSITIVE
|
||||
INIStringUtil::toLower(key);
|
||||
#endif
|
||||
auto it = dataIndexMap.find(key);
|
||||
if (it != dataIndexMap.end())
|
||||
{
|
||||
data[it->second].second = obj;
|
||||
}
|
||||
else
|
||||
{
|
||||
dataIndexMap[key] = data.size();
|
||||
data.emplace_back(key, obj);
|
||||
}
|
||||
}
|
||||
void set(T_MultiArgs const& multiArgs)
|
||||
{
|
||||
for (auto const& it : multiArgs)
|
||||
{
|
||||
auto const& key = it.first;
|
||||
auto const& obj = it.second;
|
||||
set(key, obj);
|
||||
}
|
||||
}
|
||||
bool remove(std::string key)
|
||||
{
|
||||
INIStringUtil::trim(key);
|
||||
#ifndef MINI_CASE_SENSITIVE
|
||||
INIStringUtil::toLower(key);
|
||||
#endif
|
||||
auto it = dataIndexMap.find(key);
|
||||
if (it != dataIndexMap.end())
|
||||
{
|
||||
std::size_t index = it->second;
|
||||
data.erase(data.begin() + index);
|
||||
dataIndexMap.erase(it);
|
||||
for (auto& it2 : dataIndexMap)
|
||||
{
|
||||
auto& vi = it2.second;
|
||||
if (vi > index)
|
||||
{
|
||||
vi--;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
void clear()
|
||||
{
|
||||
data.clear();
|
||||
dataIndexMap.clear();
|
||||
}
|
||||
std::size_t size() const
|
||||
{
|
||||
return data.size();
|
||||
}
|
||||
const_iterator begin() const { return data.begin(); }
|
||||
const_iterator end() const { return data.end(); }
|
||||
};
|
||||
|
||||
using INIStructure = INIMap<INIMap<std::string>>;
|
||||
|
||||
namespace INIParser
|
||||
{
|
||||
using T_ParseValues = std::pair<std::string, std::string>;
|
||||
|
||||
enum class PDataType : char
|
||||
{
|
||||
PDATA_NONE,
|
||||
PDATA_COMMENT,
|
||||
PDATA_SECTION,
|
||||
PDATA_KEYVALUE,
|
||||
PDATA_UNKNOWN
|
||||
};
|
||||
|
||||
inline PDataType parseLine(std::string line, T_ParseValues& parseData)
|
||||
{
|
||||
parseData.first.clear();
|
||||
parseData.second.clear();
|
||||
INIStringUtil::trim(line);
|
||||
if (line.empty())
|
||||
{
|
||||
return PDataType::PDATA_NONE;
|
||||
}
|
||||
char firstCharacter = line[0];
|
||||
if (firstCharacter == ';')
|
||||
{
|
||||
return PDataType::PDATA_COMMENT;
|
||||
}
|
||||
if (firstCharacter == '[')
|
||||
{
|
||||
auto commentAt = line.find_first_of(';');
|
||||
if (commentAt != std::string::npos)
|
||||
{
|
||||
line = line.substr(0, commentAt);
|
||||
}
|
||||
auto closingBracketAt = line.find_last_of(']');
|
||||
if (closingBracketAt != std::string::npos)
|
||||
{
|
||||
auto section = line.substr(1, closingBracketAt - 1);
|
||||
INIStringUtil::trim(section);
|
||||
parseData.first = section;
|
||||
return PDataType::PDATA_SECTION;
|
||||
}
|
||||
}
|
||||
auto lineNorm = line;
|
||||
INIStringUtil::replace(lineNorm, "\\=", " ");
|
||||
auto equalsAt = lineNorm.find_first_of('=');
|
||||
if (equalsAt != std::string::npos)
|
||||
{
|
||||
auto key = line.substr(0, equalsAt);
|
||||
INIStringUtil::trim(key);
|
||||
INIStringUtil::replace(key, "\\=", "=");
|
||||
auto value = line.substr(equalsAt + 1);
|
||||
INIStringUtil::trim(value);
|
||||
parseData.first = key;
|
||||
parseData.second = value;
|
||||
return PDataType::PDATA_KEYVALUE;
|
||||
}
|
||||
return PDataType::PDATA_UNKNOWN;
|
||||
}
|
||||
};
|
||||
|
||||
class INIReader
|
||||
{
|
||||
public:
|
||||
using T_LineData = std::vector<std::string>;
|
||||
using T_LineDataPtr = std::shared_ptr<T_LineData>;
|
||||
|
||||
private:
|
||||
std::ifstream fileReadStream;
|
||||
T_LineDataPtr lineData;
|
||||
|
||||
T_LineData readFile()
|
||||
{
|
||||
std::string fileContents;
|
||||
fileReadStream.seekg(0, std::ios::end);
|
||||
fileContents.resize(fileReadStream.tellg());
|
||||
fileReadStream.seekg(0, std::ios::beg);
|
||||
std::size_t fileSize = fileContents.size();
|
||||
fileReadStream.read(&fileContents[0], fileSize);
|
||||
fileReadStream.close();
|
||||
T_LineData output;
|
||||
if (fileSize == 0)
|
||||
{
|
||||
return output;
|
||||
}
|
||||
std::string buffer;
|
||||
buffer.reserve(50);
|
||||
for (std::size_t i = 0; i < fileSize; ++i)
|
||||
{
|
||||
char& c = fileContents[i];
|
||||
if (c == '\n')
|
||||
{
|
||||
output.emplace_back(buffer);
|
||||
buffer.clear();
|
||||
continue;
|
||||
}
|
||||
if (c != '\0' && c != '\r')
|
||||
{
|
||||
buffer += c;
|
||||
}
|
||||
}
|
||||
output.emplace_back(buffer);
|
||||
return output;
|
||||
}
|
||||
|
||||
public:
|
||||
INIReader(std::string const& filename, bool keepLineData = false)
|
||||
{
|
||||
fileReadStream.open(filename, std::ios::in | std::ios::binary);
|
||||
if (keepLineData)
|
||||
{
|
||||
lineData = std::make_shared<T_LineData>();
|
||||
}
|
||||
}
|
||||
~INIReader() { }
|
||||
|
||||
bool operator>>(INIStructure& data)
|
||||
{
|
||||
if (!fileReadStream.is_open())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
T_LineData fileLines = readFile();
|
||||
std::string section;
|
||||
bool inSection = false;
|
||||
INIParser::T_ParseValues parseData;
|
||||
for (auto const& line : fileLines)
|
||||
{
|
||||
auto parseResult = INIParser::parseLine(line, parseData);
|
||||
if (parseResult == INIParser::PDataType::PDATA_SECTION)
|
||||
{
|
||||
inSection = true;
|
||||
data[section = parseData.first];
|
||||
}
|
||||
else if (inSection && parseResult == INIParser::PDataType::PDATA_KEYVALUE)
|
||||
{
|
||||
auto const& key = parseData.first;
|
||||
auto const& value = parseData.second;
|
||||
data[section][key] = value;
|
||||
}
|
||||
if (lineData && parseResult != INIParser::PDataType::PDATA_UNKNOWN)
|
||||
{
|
||||
if (parseResult == INIParser::PDataType::PDATA_KEYVALUE && !inSection)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
lineData->emplace_back(line);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
T_LineDataPtr getLines()
|
||||
{
|
||||
return lineData;
|
||||
}
|
||||
};
|
||||
|
||||
class INIGenerator
|
||||
{
|
||||
private:
|
||||
std::ofstream fileWriteStream;
|
||||
|
||||
public:
|
||||
bool prettyPrint = false;
|
||||
|
||||
INIGenerator(std::string const& filename)
|
||||
{
|
||||
fileWriteStream.open(filename, std::ios::out | std::ios::binary);
|
||||
}
|
||||
~INIGenerator() { }
|
||||
|
||||
bool operator<<(INIStructure const& data)
|
||||
{
|
||||
if (!fileWriteStream.is_open())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (!data.size())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
auto it = data.begin();
|
||||
for (;;)
|
||||
{
|
||||
auto const& section = it->first;
|
||||
auto const& collection = it->second;
|
||||
fileWriteStream
|
||||
<< "["
|
||||
<< section
|
||||
<< "]";
|
||||
if (collection.size())
|
||||
{
|
||||
fileWriteStream << INIStringUtil::endl;
|
||||
auto it2 = collection.begin();
|
||||
for (;;)
|
||||
{
|
||||
auto key = it2->first;
|
||||
INIStringUtil::replace(key, "=", "\\=");
|
||||
auto value = it2->second;
|
||||
INIStringUtil::trim(value);
|
||||
fileWriteStream
|
||||
<< key
|
||||
<< ((prettyPrint) ? " = " : "=")
|
||||
<< value;
|
||||
if (++it2 == collection.end())
|
||||
{
|
||||
break;
|
||||
}
|
||||
fileWriteStream << INIStringUtil::endl;
|
||||
}
|
||||
}
|
||||
if (++it == data.end())
|
||||
{
|
||||
break;
|
||||
}
|
||||
fileWriteStream << INIStringUtil::endl;
|
||||
if (prettyPrint)
|
||||
{
|
||||
fileWriteStream << INIStringUtil::endl;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
class INIWriter
|
||||
{
|
||||
private:
|
||||
using T_LineData = std::vector<std::string>;
|
||||
using T_LineDataPtr = std::shared_ptr<T_LineData>;
|
||||
|
||||
std::string filename;
|
||||
|
||||
T_LineData getLazyOutput(T_LineDataPtr const& lineData, INIStructure& data, INIStructure& original)
|
||||
{
|
||||
T_LineData output;
|
||||
INIParser::T_ParseValues parseData;
|
||||
std::string sectionCurrent;
|
||||
bool parsingSection = false;
|
||||
bool continueToNextSection = false;
|
||||
bool discardNextEmpty = false;
|
||||
bool writeNewKeys = false;
|
||||
std::size_t lastKeyLine = 0;
|
||||
for (auto line = lineData->begin(); line != lineData->end(); ++line)
|
||||
{
|
||||
if (!writeNewKeys)
|
||||
{
|
||||
auto parseResult = INIParser::parseLine(*line, parseData);
|
||||
if (parseResult == INIParser::PDataType::PDATA_SECTION)
|
||||
{
|
||||
if (parsingSection)
|
||||
{
|
||||
writeNewKeys = true;
|
||||
parsingSection = false;
|
||||
--line;
|
||||
continue;
|
||||
}
|
||||
sectionCurrent = parseData.first;
|
||||
if (data.has(sectionCurrent))
|
||||
{
|
||||
parsingSection = true;
|
||||
continueToNextSection = false;
|
||||
discardNextEmpty = false;
|
||||
output.emplace_back(*line);
|
||||
lastKeyLine = output.size();
|
||||
}
|
||||
else
|
||||
{
|
||||
continueToNextSection = true;
|
||||
discardNextEmpty = true;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else if (parseResult == INIParser::PDataType::PDATA_KEYVALUE)
|
||||
{
|
||||
if (continueToNextSection)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (data.has(sectionCurrent))
|
||||
{
|
||||
auto& collection = data[sectionCurrent];
|
||||
auto const& key = parseData.first;
|
||||
auto const& value = parseData.second;
|
||||
if (collection.has(key))
|
||||
{
|
||||
auto outputValue = collection[key];
|
||||
if (value == outputValue)
|
||||
{
|
||||
output.emplace_back(*line);
|
||||
}
|
||||
else
|
||||
{
|
||||
INIStringUtil::trim(outputValue);
|
||||
auto lineNorm = *line;
|
||||
INIStringUtil::replace(lineNorm, "\\=", " ");
|
||||
auto equalsAt = lineNorm.find_first_of('=');
|
||||
auto valueAt = lineNorm.find_first_not_of(
|
||||
INIStringUtil::whitespaceDelimiters,
|
||||
equalsAt + 1
|
||||
);
|
||||
std::string outputLine = line->substr(0, valueAt);
|
||||
if (prettyPrint && equalsAt + 1 == valueAt)
|
||||
{
|
||||
outputLine += " ";
|
||||
}
|
||||
outputLine += outputValue;
|
||||
output.emplace_back(outputLine);
|
||||
}
|
||||
lastKeyLine = output.size();
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (discardNextEmpty && line->empty())
|
||||
{
|
||||
discardNextEmpty = false;
|
||||
}
|
||||
else if (parseResult != INIParser::PDataType::PDATA_UNKNOWN)
|
||||
{
|
||||
output.emplace_back(*line);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (writeNewKeys || std::next(line) == lineData->end())
|
||||
{
|
||||
T_LineData linesToAdd;
|
||||
if (data.has(sectionCurrent) && original.has(sectionCurrent))
|
||||
{
|
||||
auto const& collection = data[sectionCurrent];
|
||||
auto const& collectionOriginal = original[sectionCurrent];
|
||||
for (auto const& it : collection)
|
||||
{
|
||||
auto key = it.first;
|
||||
if (collectionOriginal.has(key))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
auto value = it.second;
|
||||
INIStringUtil::replace(key, "=", "\\=");
|
||||
INIStringUtil::trim(value);
|
||||
linesToAdd.emplace_back(
|
||||
key + ((prettyPrint) ? " = " : "=") + value
|
||||
);
|
||||
}
|
||||
}
|
||||
if (!linesToAdd.empty())
|
||||
{
|
||||
output.insert(
|
||||
output.begin() + lastKeyLine,
|
||||
linesToAdd.begin(),
|
||||
linesToAdd.end()
|
||||
);
|
||||
}
|
||||
if (writeNewKeys)
|
||||
{
|
||||
writeNewKeys = false;
|
||||
--line;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (auto const& it : data)
|
||||
{
|
||||
auto const& section = it.first;
|
||||
if (original.has(section))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (prettyPrint && output.size() > 0 && !output.back().empty())
|
||||
{
|
||||
output.emplace_back();
|
||||
}
|
||||
output.emplace_back("[" + section + "]");
|
||||
auto const& collection = it.second;
|
||||
for (auto const& it2 : collection)
|
||||
{
|
||||
auto key = it2.first;
|
||||
auto value = it2.second;
|
||||
INIStringUtil::replace(key, "=", "\\=");
|
||||
INIStringUtil::trim(value);
|
||||
output.emplace_back(
|
||||
key + ((prettyPrint) ? " = " : "=") + value
|
||||
);
|
||||
}
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
public:
|
||||
bool prettyPrint = false;
|
||||
|
||||
INIWriter(std::string const& filename)
|
||||
: filename(filename)
|
||||
{
|
||||
}
|
||||
~INIWriter() { }
|
||||
|
||||
bool operator<<(INIStructure& data)
|
||||
{
|
||||
struct stat buf;
|
||||
bool fileExists = (stat(filename.c_str(), &buf) == 0);
|
||||
if (!fileExists)
|
||||
{
|
||||
INIGenerator generator(filename);
|
||||
generator.prettyPrint = prettyPrint;
|
||||
return generator << data;
|
||||
}
|
||||
INIStructure originalData;
|
||||
T_LineDataPtr lineData;
|
||||
bool readSuccess = false;
|
||||
{
|
||||
INIReader reader(filename, true);
|
||||
if ((readSuccess = reader >> originalData))
|
||||
{
|
||||
lineData = reader.getLines();
|
||||
}
|
||||
}
|
||||
if (!readSuccess)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
T_LineData output = getLazyOutput(lineData, data, originalData);
|
||||
std::ofstream fileWriteStream(filename, std::ios::out | std::ios::binary);
|
||||
if (fileWriteStream.is_open())
|
||||
{
|
||||
if (output.size())
|
||||
{
|
||||
auto line = output.begin();
|
||||
for (;;)
|
||||
{
|
||||
fileWriteStream << *line;
|
||||
if (++line == output.end())
|
||||
{
|
||||
break;
|
||||
}
|
||||
fileWriteStream << INIStringUtil::endl;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
class INIFile
|
||||
{
|
||||
private:
|
||||
std::string filename;
|
||||
|
||||
public:
|
||||
INIFile(std::string const& filename)
|
||||
: filename(filename)
|
||||
{ }
|
||||
|
||||
~INIFile() { }
|
||||
|
||||
bool read(INIStructure& data) const
|
||||
{
|
||||
if (data.size())
|
||||
{
|
||||
data.clear();
|
||||
}
|
||||
if (filename.empty())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
INIReader reader(filename);
|
||||
return reader >> data;
|
||||
}
|
||||
bool generate(INIStructure const& data, bool pretty = false) const
|
||||
{
|
||||
if (filename.empty())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
INIGenerator generator(filename);
|
||||
generator.prettyPrint = pretty;
|
||||
return generator << data;
|
||||
}
|
||||
bool write(INIStructure& data, bool pretty = false) const
|
||||
{
|
||||
if (filename.empty())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
INIWriter writer(filename);
|
||||
writer.prettyPrint = pretty;
|
||||
return writer << data;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif // MINI_INI_H_
|
|
@ -15,14 +15,12 @@
|
|||
#include <QTextCodec>
|
||||
#include "settings.h"
|
||||
#include <QDebug>
|
||||
|
||||
#include "SimpleIni.h"
|
||||
Project::Project(const QString &filename, const QString &name, QObject *parent) :
|
||||
QObject(parent),
|
||||
mModel(this)
|
||||
{
|
||||
mFilename = filename;
|
||||
mIniFile = std::make_shared<QSettings>(filename,QSettings::IniFormat);
|
||||
mIniFile->setIniCodec(QTextCodec::codecForName(getDefaultSystemEncoding()));
|
||||
mParser = std::make_shared<CppParser>();
|
||||
mParser->setOnGetFileStream(
|
||||
std::bind(
|
||||
|
@ -33,10 +31,10 @@ Project::Project(const QString &filename, const QString &name, QObject *parent)
|
|||
open();
|
||||
else {
|
||||
mName = name;
|
||||
mIniFile->beginGroup("Project");
|
||||
mIniFile->setValue("filename", mFilename);
|
||||
mIniFile->setValue("name", mName);
|
||||
mIniFile->endGroup();
|
||||
SimpleIni ini;
|
||||
ini.SetValue("Project","filename", toByteArray(extractRelativePath(directory(),mFilename)));
|
||||
ini.SetValue("Project","name", toByteArray(mName));
|
||||
ini.SaveFile(mFilename.toLocal8Bit());
|
||||
mNode = makeProjectNode();
|
||||
}
|
||||
}
|
||||
|
@ -115,21 +113,23 @@ void Project::open()
|
|||
auto action = finally([this]{
|
||||
mModel.endUpdate();
|
||||
});
|
||||
QFile fileInfo(mFilename);
|
||||
loadOptions();
|
||||
// QFile fileInfo(mFilename);
|
||||
SimpleIni ini;
|
||||
ini.LoadFile(mFilename.toLocal8Bit());
|
||||
loadOptions(ini);
|
||||
|
||||
mNode = makeProjectNode();
|
||||
|
||||
checkProjectFileForUpdate();
|
||||
qDebug()<<"ini filename:"<<mIniFile->fileName();
|
||||
int uCount = mIniFile->value("UnitCount",0).toInt();
|
||||
mIniFile->endGroup();
|
||||
checkProjectFileForUpdate(ini);
|
||||
int uCount = ini.GetLongValue("Project","UnitCount",0);
|
||||
//createFolderNodes;
|
||||
QDir dir(directory());
|
||||
for (int i=0;i<uCount;i++) {
|
||||
PProjectUnit newUnit = std::make_shared<ProjectUnit>(this);
|
||||
mIniFile->beginGroup(QString("Unit%1").arg(i+1));
|
||||
newUnit->setFileName(dir.absoluteFilePath(mIniFile->value("FileName","").toString()));
|
||||
QByteArray groupName = toByteArray(QString("Unit%1").arg(i+1));
|
||||
newUnit->setFileName(
|
||||
dir.absoluteFilePath(
|
||||
fromByteArray(ini.GetValue(groupName,"FileName",""))));
|
||||
if (!QFileInfo(newUnit->fileName()).exists()) {
|
||||
QMessageBox::critical(pMainWindow,
|
||||
tr("File Not Found"),
|
||||
|
@ -138,17 +138,20 @@ void Project::open()
|
|||
QMessageBox::Ok);
|
||||
newUnit->setModified(true);
|
||||
} else {
|
||||
newUnit->setFolder(mIniFile->value("Folder","").toString());
|
||||
newUnit->setCompile(mIniFile->value("Compile", true).toBool());
|
||||
newUnit->setFolder(fromByteArray(ini.GetValue(groupName,"Folder","")));
|
||||
newUnit->setCompile(ini.GetBoolValue(groupName,"Compile", true));
|
||||
newUnit->setCompileCpp(
|
||||
mIniFile->value("CompileCpp",mOptions.useGPP).toBool());
|
||||
|
||||
newUnit->setLink(mIniFile->value("Link", true).toBool());
|
||||
newUnit->setPriority(mIniFile->value("Priority", 1000).toInt());
|
||||
newUnit->setOverrideBuildCmd(mIniFile->value("OverrideBuildCmd", false).toInt());
|
||||
newUnit->setBuildCmd(mIniFile->value("BuildCmd", "").toString());
|
||||
newUnit->setEncoding(mIniFile->value("FileEncoding",ENCODING_SYSTEM_DEFAULT).toByteArray());
|
||||
ini.GetBoolValue(groupName,"CompileCpp",mOptions.useGPP));
|
||||
|
||||
newUnit->setLink(ini.GetBoolValue(groupName,"Link", true));
|
||||
newUnit->setPriority(ini.GetLongValue(groupName,"Priority", 1000));
|
||||
newUnit->setOverrideBuildCmd(ini.GetBoolValue(groupName,"OverrideBuildCmd", false));
|
||||
newUnit->setBuildCmd(fromByteArray(ini.GetValue(groupName,"BuildCmd", "")));
|
||||
QByteArray defaultEncoding = ENCODING_SYSTEM_DEFAULT;
|
||||
if (ini.GetBoolValue(groupName,"DetectEncoding",true)){
|
||||
defaultEncoding = ENCODING_AUTO_DETECT;
|
||||
}
|
||||
newUnit->setEncoding(ini.GetValue(groupName, "FileEncoding",defaultEncoding));
|
||||
newUnit->setEditor(nullptr);
|
||||
newUnit->setNew(false);
|
||||
newUnit->setParent(this);
|
||||
|
@ -156,7 +159,6 @@ void Project::open()
|
|||
newUnit->node()->unitIndex = mUnits.count();
|
||||
mUnits.append(newUnit);
|
||||
}
|
||||
mIniFile->endGroup();
|
||||
}
|
||||
rebuildNodes();
|
||||
}
|
||||
|
@ -164,13 +166,9 @@ void Project::open()
|
|||
void Project::setFileName(const QString &value)
|
||||
{
|
||||
if (mFilename!=value) {
|
||||
mIniFile->sync();
|
||||
mIniFile.reset();
|
||||
QFile::rename(mFilename,value);
|
||||
mFilename = value;
|
||||
setModified(true);
|
||||
mIniFile = std::make_shared<QSettings>(mFilename, QSettings::IniFormat);
|
||||
mIniFile->setIniCodec(QTextCodec::codecForName(getDefaultSystemEncoding()));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -343,7 +341,6 @@ bool Project::removeEditor(int index, bool doClose)
|
|||
}
|
||||
|
||||
//if not fUnits.GetItem(index).fNew then
|
||||
mIniFile->remove("Unit"+QString("%1").arg(index+1));
|
||||
PFolderNode node = unit->node();
|
||||
PFolderNode parent = node->parent.lock();
|
||||
if (parent) {
|
||||
|
@ -433,14 +430,16 @@ void Project::saveLayout()
|
|||
}
|
||||
layIni.endGroup();
|
||||
// remove old data from project file
|
||||
mIniFile->beginGroup(QString("Unit%1").arg(i+1));
|
||||
mIniFile->remove("Open");
|
||||
mIniFile->remove("Top");
|
||||
mIniFile->remove("CursorCol");
|
||||
mIniFile->remove("CursorRow");
|
||||
mIniFile->remove("TopLine");
|
||||
mIniFile->remove("LeftChar");
|
||||
mIniFile->endGroup();
|
||||
SimpleIni ini;
|
||||
ini.LoadFile(mFilename.toLocal8Bit());
|
||||
QByteArray groupName = toByteArray(QString("Unit%1").arg(i+1));
|
||||
ini.Delete(groupName,"Open");
|
||||
ini.Delete(groupName,"Top");
|
||||
ini.Delete(groupName,"CursorCol");
|
||||
ini.Delete(groupName,"CursorRow");
|
||||
ini.Delete(groupName,"TopLine");
|
||||
ini.Delete(groupName,"LeftChar");
|
||||
ini.SaveFile(mFilename.toLocal8Bit());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -454,13 +453,17 @@ void Project::saveUnitAs(int i, const QString &sFileName)
|
|||
// }
|
||||
unit->setNew(false);
|
||||
unit->setFileName(sFileName);
|
||||
mIniFile->beginGroup(QString("Unit%1").arg(i+1));
|
||||
mIniFile->setValue("FileName",
|
||||
extractRelativePath(
|
||||
directory(),
|
||||
sFileName));
|
||||
mIniFile->endGroup();
|
||||
mIniFile->sync();
|
||||
SimpleIni ini;
|
||||
ini.LoadFile(mFilename.toLocal8Bit());
|
||||
QByteArray groupName = toByteArray(QString("Unit%1").arg(i+1));
|
||||
ini.SetValue(
|
||||
groupName,
|
||||
"FileName",
|
||||
toByteArray(
|
||||
extractRelativePath(
|
||||
directory(),
|
||||
sFileName)));
|
||||
ini.SaveFile(mFilename.toLocal8Bit());
|
||||
setModified(true);
|
||||
}
|
||||
|
||||
|
@ -480,10 +483,12 @@ void Project::saveUnitLayout(Editor *e, int index)
|
|||
bool Project::saveUnits()
|
||||
{
|
||||
int count = 0;
|
||||
SimpleIni ini;
|
||||
ini.LoadFile(mFilename.toLocal8Bit());
|
||||
for (int idx = 0; idx < mUnits.count(); idx++) {
|
||||
PProjectUnit unit = mUnits[idx];
|
||||
bool rd_only = false;
|
||||
mIniFile->beginGroup(QString("Unit%1").arg(count+1));
|
||||
QByteArray groupName = toByteArray(QString("Unit%1").arg(count+1));
|
||||
if (unit->modified() && fileExists(unit->fileName())
|
||||
&& isReadOnly(unit->fileName())) {
|
||||
// file is read-only
|
||||
|
@ -500,37 +505,36 @@ bool Project::saveUnits()
|
|||
}
|
||||
|
||||
// saved new file or an existing file add to project file
|
||||
|
||||
mIniFile->setValue("FileName",
|
||||
extractRelativePath(
|
||||
directory(),
|
||||
unit->fileName()));
|
||||
ini.SetValue(
|
||||
groupName,
|
||||
"FileName",
|
||||
toByteArray(
|
||||
extractRelativePath(
|
||||
directory(),
|
||||
unit->fileName())));
|
||||
count++;
|
||||
switch(getFileType(unit->fileName())) {
|
||||
case FileType::CHeader:
|
||||
case FileType::CSource:
|
||||
case FileType::CppHeader:
|
||||
case FileType::CppSource:
|
||||
mIniFile->setValue("CompileCpp", unit->compileCpp());
|
||||
ini.SetBoolValue(groupName,"CompileCpp", unit->compileCpp());
|
||||
break;
|
||||
case FileType::WindowsResourceSource:
|
||||
unit->setFolder("Resources");
|
||||
}
|
||||
|
||||
mIniFile->setValue("Folder", unit->folder());
|
||||
mIniFile->setValue("Compile", unit->compile());
|
||||
mIniFile->setValue("Link", unit->link());
|
||||
mIniFile->setValue("Priority", unit->priority());
|
||||
mIniFile->setValue("OverrideBuildCmd", unit->overrideBuildCmd());
|
||||
mIniFile->setValue("BuildCmd", unit->buildCmd());
|
||||
mIniFile->setValue("DetectEncoding", unit->encoding()==ENCODING_AUTO_DETECT);
|
||||
mIniFile->setValue("FileEncoding", unit->encoding());
|
||||
mIniFile->endGroup();
|
||||
ini.SetValue(groupName,"Folder", toByteArray(unit->folder()));
|
||||
ini.SetBoolValue(groupName,"Compile", unit->compile());
|
||||
ini.SetBoolValue(groupName,"Link", unit->link());
|
||||
ini.SetLongValue(groupName,"Priority", unit->priority());
|
||||
ini.SetBoolValue(groupName,"OverrideBuildCmd", unit->overrideBuildCmd());
|
||||
ini.SetValue(groupName,"BuildCmd", toByteArray(unit->buildCmd()));
|
||||
ini.SetBoolValue(groupName,"DetectEncoding", unit->encoding()==ENCODING_AUTO_DETECT);
|
||||
ini.SetValue(groupName,"FileEncoding", toByteArray(unit->encoding()));
|
||||
}
|
||||
mIniFile->beginGroup("Project");
|
||||
mIniFile->setValue("UnitCount",count);
|
||||
mIniFile->endGroup();
|
||||
mIniFile->sync();
|
||||
ini.SetLongValue("Project","UnitCount",count);
|
||||
ini.SaveFile(mFilename.toLocal8Bit());
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -568,79 +572,74 @@ void Project::updateNodeIndexes()
|
|||
|
||||
void Project::saveOptions()
|
||||
{
|
||||
mIniFile->beginGroup("Project");
|
||||
mIniFile->setValue("FileName", extractRelativePath(directory(), mFilename));
|
||||
mIniFile->setValue("Name", mName);
|
||||
mIniFile->setValue("Type", static_cast<int>(mOptions.type));
|
||||
mIniFile->setValue("Ver", 3); // Is 3 as of Red Panda Dev-C++ 7.0
|
||||
mIniFile->setValue("ObjFiles", mOptions.objFiles.join(";"));
|
||||
mIniFile->setValue("Includes", mOptions.includes.join(";"));
|
||||
mIniFile->setValue("Libs", mOptions.libs.join(";"));
|
||||
mIniFile->setValue("PrivateResource", mOptions.privateResource);
|
||||
mIniFile->setValue("ResourceIncludes", mOptions.resourceIncludes.join(";"));
|
||||
mIniFile->setValue("MakeIncludes", mOptions.makeIncludes.join(";"));
|
||||
mIniFile->setValue("Compiler", mOptions.compilerCmd);
|
||||
mIniFile->setValue("CppCompiler", mOptions.cppCompilerCmd);
|
||||
mIniFile->setValue("Linker", mOptions.linkerCmd);
|
||||
mIniFile->setValue("IsCpp", mOptions.useGPP);
|
||||
mIniFile->setValue("Icon", extractRelativePath(directory(), mOptions.icon));
|
||||
mIniFile->setValue("ExeOutput", mOptions.exeOutput);
|
||||
mIniFile->setValue("ObjectOutput", mOptions.objectOutput);
|
||||
mIniFile->setValue("LogOutput", mOptions.logOutput);
|
||||
mIniFile->setValue("LogOutputEnabled", mOptions.logOutputEnabled);
|
||||
mIniFile->setValue("OverrideOutput", mOptions.overrideOutput);
|
||||
mIniFile->setValue("OverrideOutputName", mOptions.overridenOutput);
|
||||
mIniFile->setValue("HostApplication", mOptions.hostApplication);
|
||||
mIniFile->setValue("UseCustomMakefile", mOptions.useCustomMakefile);
|
||||
mIniFile->setValue("CustomMakefile", mOptions.customMakefile);
|
||||
mIniFile->setValue("UsePrecompiledHeader", mOptions.usePrecompiledHeader);
|
||||
mIniFile->setValue("PrecompiledHeader", mOptions.precompiledHeader);
|
||||
mIniFile->setValue("CommandLine", mOptions.cmdLineArgs);
|
||||
mIniFile->setValue("Folders", mFolders.join(";"));
|
||||
mIniFile->setValue("IncludeVersionInfo", mOptions.includeVersionInfo);
|
||||
mIniFile->setValue("SupportXPThemes", mOptions.supportXPThemes);
|
||||
mIniFile->setValue("CompilerSet", mOptions.compilerSet);
|
||||
mIniFile->setValue("CompilerSettings", mOptions.compilerOptions);
|
||||
mIniFile->setValue("StaticLink", mOptions.staticLink);
|
||||
mIniFile->setValue("AddCharset", mOptions.addCharset);
|
||||
mIniFile->setValue("Encoding",mOptions.encoding);
|
||||
SimpleIni ini;
|
||||
ini.LoadFile(mFilename.toLocal8Bit());
|
||||
ini.SetValue("Project","FileName", toByteArray(extractRelativePath(directory(), mFilename)));
|
||||
ini.SetValue("Project","Name", toByteArray(mName));
|
||||
ini.SetLongValue("Project","Type", static_cast<int>(mOptions.type));
|
||||
ini.SetLongValue("Project","Ver", 3); // Is 3 as of Red Panda Dev-C++ 7.0
|
||||
ini.SetValue("Project","ObjFiles", toByteArray(mOptions.objFiles.join(";")));
|
||||
ini.SetValue("Project","Includes", toByteArray(mOptions.includes.join(";")));
|
||||
ini.SetValue("Project","Libs", toByteArray(mOptions.libs.join(";")));
|
||||
ini.SetValue("Project","PrivateResource", toByteArray(mOptions.privateResource));
|
||||
ini.SetValue("Project","ResourceIncludes", toByteArray(mOptions.resourceIncludes.join(";")));
|
||||
ini.SetValue("Project","MakeIncludes", toByteArray(mOptions.makeIncludes.join(";")));
|
||||
ini.SetValue("Project","Compiler", toByteArray(mOptions.compilerCmd));
|
||||
ini.SetValue("Project","CppCompiler", toByteArray(mOptions.cppCompilerCmd));
|
||||
ini.SetValue("Project","Linker", toByteArray(mOptions.linkerCmd));
|
||||
ini.SetBoolValue("Project","IsCpp", mOptions.useGPP);
|
||||
ini.SetValue("Project","Icon", toByteArray(extractRelativePath(directory(), mOptions.icon)));
|
||||
ini.SetValue("Project","ExeOutput", toByteArray(mOptions.exeOutput));
|
||||
ini.SetValue("Project","ObjectOutput", toByteArray(mOptions.objectOutput));
|
||||
ini.SetValue("Project","LogOutput", toByteArray(mOptions.logOutput));
|
||||
ini.SetBoolValue("Project","LogOutputEnabled", mOptions.logOutputEnabled);
|
||||
ini.SetBoolValue("Project","OverrideOutput", mOptions.overrideOutput);
|
||||
ini.SetValue("Project","OverrideOutputName", toByteArray(mOptions.overridenOutput));
|
||||
ini.SetValue("Project","HostApplication", toByteArray(mOptions.hostApplication));
|
||||
ini.SetBoolValue("Project","UseCustomMakefile", mOptions.useCustomMakefile);
|
||||
ini.SetValue("Project","CustomMakefile", toByteArray(mOptions.customMakefile));
|
||||
ini.SetBoolValue("Project","UsePrecompiledHeader", mOptions.usePrecompiledHeader);
|
||||
ini.SetValue("Project","PrecompiledHeader", toByteArray(mOptions.precompiledHeader));
|
||||
ini.SetValue("Project","CommandLine", toByteArray(mOptions.cmdLineArgs));
|
||||
ini.SetValue("Project","Folders", toByteArray(mFolders.join(";")));
|
||||
ini.SetBoolValue("Project","IncludeVersionInfo", mOptions.includeVersionInfo);
|
||||
ini.SetBoolValue("Project","SupportXPThemes", mOptions.supportXPThemes);
|
||||
ini.SetLongValue("Project","CompilerSet", mOptions.compilerSet);
|
||||
ini.SetValue("Project","CompilerSettings", toByteArray(mOptions.compilerOptions));
|
||||
ini.SetBoolValue("Project","StaticLink", mOptions.staticLink);
|
||||
ini.SetBoolValue("Project","AddCharset", mOptions.addCharset);
|
||||
ini.SetValue("Project","Encoding",toByteArray(mOptions.encoding));
|
||||
//for Red Panda Dev C++ 6 compatibility
|
||||
mIniFile->setValue("UseUTF8",mOptions.encoding == ENCODING_UTF8);
|
||||
mIniFile->endGroup();
|
||||
ini.SetBoolValue("Project","UseUTF8",mOptions.encoding == ENCODING_UTF8);
|
||||
|
||||
mIniFile->beginGroup("VersionInfo");
|
||||
mIniFile->setValue("Major", mOptions.versionInfo.major);
|
||||
ini.SetLongValue("VersionInfo","Major", mOptions.versionInfo.major);
|
||||
ini.SetLongValue("VersionInfo","Minor", mOptions.versionInfo.minor);
|
||||
ini.SetLongValue("VersionInfo","Release", mOptions.versionInfo.release);
|
||||
ini.SetLongValue("VersionInfo","Build", mOptions.versionInfo.build);
|
||||
ini.SetLongValue("VersionInfo","LanguageID", mOptions.versionInfo.languageID);
|
||||
ini.SetLongValue("VersionInfo","CharsetID", mOptions.versionInfo.charsetID);
|
||||
ini.SetValue("VersionInfo","CompanyName", toByteArray(mOptions.versionInfo.companyName));
|
||||
ini.SetValue("VersionInfo","FileVersion", toByteArray(mOptions.versionInfo.fileVersion));
|
||||
ini.SetValue("VersionInfo","FileDescription", toByteArray(mOptions.versionInfo.fileDescription));
|
||||
ini.SetValue("VersionInfo","InternalName", toByteArray(mOptions.versionInfo.internalName));
|
||||
ini.SetValue("VersionInfo","LegalCopyright", toByteArray(mOptions.versionInfo.legalCopyright));
|
||||
ini.SetValue("VersionInfo","LegalTrademarks", toByteArray(mOptions.versionInfo.legalTrademarks));
|
||||
ini.SetValue("VersionInfo","OriginalFilename", toByteArray(mOptions.versionInfo.originalFilename));
|
||||
ini.SetValue("VersionInfo","ProductName", toByteArray(mOptions.versionInfo.productName));
|
||||
ini.SetValue("VersionInfo","ProductVersion", toByteArray(mOptions.versionInfo.productVersion));
|
||||
ini.SetBoolValue("VersionInfo","AutoIncBuildNr", mOptions.versionInfo.autoIncBuildNr);
|
||||
ini.SetBoolValue("VersionInfo","SyncProduct", mOptions.versionInfo.syncProduct);
|
||||
|
||||
mIniFile->setValue("Minor", mOptions.versionInfo.minor);
|
||||
mIniFile->setValue("Release", mOptions.versionInfo.release);
|
||||
mIniFile->setValue("Build", mOptions.versionInfo.build);
|
||||
mIniFile->setValue("LanguageID", mOptions.versionInfo.languageID);
|
||||
mIniFile->setValue("CharsetID", mOptions.versionInfo.charsetID);
|
||||
mIniFile->setValue("CompanyName", mOptions.versionInfo.companyName);
|
||||
mIniFile->setValue("FileVersion", mOptions.versionInfo.fileVersion);
|
||||
mIniFile->setValue("FileDescription", mOptions.versionInfo.fileDescription);
|
||||
mIniFile->setValue("InternalName", mOptions.versionInfo.internalName);
|
||||
mIniFile->setValue("LegalCopyright", mOptions.versionInfo.legalCopyright);
|
||||
mIniFile->setValue("LegalTrademarks", mOptions.versionInfo.legalTrademarks);
|
||||
mIniFile->setValue("OriginalFilename", mOptions.versionInfo.originalFilename);
|
||||
mIniFile->setValue("ProductName", mOptions.versionInfo.productName);
|
||||
mIniFile->setValue("ProductVersion", mOptions.versionInfo.productVersion);
|
||||
mIniFile->setValue("AutoIncBuildNr", mOptions.versionInfo.autoIncBuildNr);
|
||||
mIniFile->setValue("SyncProduct", mOptions.versionInfo.syncProduct);
|
||||
mIniFile->endGroup();
|
||||
|
||||
//delete outdated dev4 project options
|
||||
mIniFile->beginGroup("Project");
|
||||
mIniFile->remove("NoConsole");
|
||||
mIniFile->remove("IsDLL");
|
||||
mIniFile->remove("ResFiles");
|
||||
mIniFile->remove("IncludeDirs");
|
||||
mIniFile->remove("CompilerOptions");
|
||||
mIniFile->remove("Use_GPP");
|
||||
mIniFile->endGroup();
|
||||
|
||||
mIniFile->sync(); // force flush
|
||||
ini.Delete("Project","NoConsole");
|
||||
ini.Delete("Project","IsDLL");
|
||||
ini.Delete("Project","ResFiles");
|
||||
ini.Delete("Project","IncludeDirs");
|
||||
ini.Delete("Project","CompilerOptions");
|
||||
ini.Delete("Project","Use_GPP");
|
||||
|
||||
ini.SaveFile(mFilename.toLocal8Bit());
|
||||
}
|
||||
|
||||
void Project::addFolder(const QString &s)
|
||||
|
@ -984,44 +983,39 @@ void Project::buildPrivateResource(bool forceSave)
|
|||
StringsToFile(contents,hFile);
|
||||
}
|
||||
|
||||
void Project::checkProjectFileForUpdate()
|
||||
void Project::checkProjectFileForUpdate(SimpleIni &ini)
|
||||
{
|
||||
bool cnvt = false;
|
||||
mIniFile->beginGroup("Project");
|
||||
int uCount = mIniFile->value("UnitCount", 0).toInt();
|
||||
mIniFile->endGroup();
|
||||
int uCount = ini.GetLongValue("Project","UnitCount", 0);
|
||||
// check if using old way to store resources and fix it
|
||||
QString oldRes = mIniFile->value("Resources", "").toString();
|
||||
QString oldRes = QString::fromLocal8Bit(ini.GetValue("Project","Resources", ""));
|
||||
if (!oldRes.isEmpty()) {
|
||||
QFile::copy(mFilename,mFilename+".bak");
|
||||
QStringList sl;
|
||||
sl = oldRes.split(';',Qt::SkipEmptyParts);
|
||||
for (int i=0;i<sl.count();i++){
|
||||
const QString& s = sl[i];
|
||||
mIniFile->beginGroup(QString("Unit%1").arg(uCount+i));
|
||||
mIniFile->setValue("Filename", s);
|
||||
mIniFile->setValue("Folder", "Resources");
|
||||
mIniFile->setValue("Compile",true);
|
||||
mIniFile->endGroup();
|
||||
QByteArray groupName = toByteArray(QString("Unit%1").arg(uCount+i));
|
||||
ini.SetValue(groupName,"Filename", toByteArray(s));
|
||||
ini.SetValue(groupName,"Folder", "Resources");
|
||||
ini.SetBoolValue(groupName,"Compile",true);
|
||||
}
|
||||
mIniFile->beginGroup("Project");
|
||||
mIniFile->setValue("UnitCount",uCount+sl.count());
|
||||
QString folders = mIniFile->value("Folders","").toString();
|
||||
ini.SetLongValue("Project","UnitCount",uCount+sl.count());
|
||||
QString folders = QString::fromLocal8Bit(ini.GetValue("Project","Folders",""));
|
||||
if (!folders.isEmpty())
|
||||
folders += ",Resources";
|
||||
else
|
||||
folders = "Resources";
|
||||
mIniFile->setValue("Folders",folders);
|
||||
mIniFile->endGroup();
|
||||
ini.SetValue("Project","Folders",toByteArray(folders));
|
||||
cnvt = true;
|
||||
ini.Delete("Project","Resources");
|
||||
ini.Delete("Project","Focused");
|
||||
ini.Delete("Project","Order");
|
||||
ini.Delete("Project","DebugInfo");
|
||||
ini.Delete("Project","ProfileInfo");
|
||||
ini.SaveFile(mFilename.toLocal8Bit());
|
||||
}
|
||||
|
||||
mIniFile->beginGroup("Project");
|
||||
mIniFile->remove("Resources");
|
||||
mIniFile->remove("Focused");
|
||||
mIniFile->remove("Order");
|
||||
mIniFile->remove("DebugInfo");
|
||||
mIniFile->remove("ProfileInfo");
|
||||
|
||||
if (cnvt)
|
||||
QMessageBox::information(
|
||||
pMainWindow,
|
||||
|
@ -1188,13 +1182,11 @@ void Project::loadLayout()
|
|||
|
||||
}
|
||||
|
||||
void Project::loadOptions()
|
||||
void Project::loadOptions(SimpleIni& ini)
|
||||
{
|
||||
mIniFile->beginGroup("Project");
|
||||
mName = mIniFile->value("name", "").toString();
|
||||
mOptions.icon = mIniFile->value("icon", "").toString();
|
||||
mOptions.version = mIniFile->value("Ver", 0).toInt();
|
||||
mIniFile->endGroup();
|
||||
mName = fromByteArray(ini.GetValue("Project","name", ""));
|
||||
mOptions.icon = fromByteArray(ini.GetValue("Project", "icon", ""));
|
||||
mOptions.version = ini.GetLongValue("Project", "Ver", 0);
|
||||
if (mOptions.version > 0) { // ver > 0 is at least a v5 project
|
||||
if (mOptions.version < 2) {
|
||||
mOptions.version = 2;
|
||||
|
@ -1206,34 +1198,33 @@ void Project::loadOptions()
|
|||
QMessageBox::Ok);
|
||||
}
|
||||
|
||||
mIniFile->beginGroup("Project");
|
||||
mOptions.type = static_cast<ProjectType>(mIniFile->value("type", 0).toInt());
|
||||
mOptions.compilerCmd = mIniFile->value("Compiler", "").toString();
|
||||
mOptions.cppCompilerCmd = mIniFile->value("CppCompiler", "").toString();
|
||||
mOptions.linkerCmd = mIniFile->value("Linker", "").toString();
|
||||
mOptions.objFiles = mIniFile->value("ObjFiles", "").toString().split(";",Qt::SkipEmptyParts);
|
||||
mOptions.libs = mIniFile->value("Libs", "").toString().split(";",Qt::SkipEmptyParts);
|
||||
mOptions.includes = mIniFile->value("Includes", "").toString().split(";",Qt::SkipEmptyParts);
|
||||
mOptions.privateResource = mIniFile->value("PrivateResource", "").toString();
|
||||
mOptions.resourceIncludes = mIniFile->value("ResourceIncludes", "").toString().split(";",Qt::SkipEmptyParts);
|
||||
mOptions.makeIncludes = mIniFile->value("MakeIncludes","").toString().split(";",Qt::SkipEmptyParts);
|
||||
mOptions.useGPP = mIniFile->value("IsCpp", false).toBool();
|
||||
mOptions.exeOutput = mIniFile->value("ExeOutput", "").toString();
|
||||
mOptions.objectOutput = mIniFile->value("ObjectOutput", "").toString();
|
||||
mOptions.logOutput = mIniFile->value("LogOutput","").toString();
|
||||
mOptions.logOutputEnabled = mIniFile->value("LogOutputEnabled", false).toBool();
|
||||
mOptions.overrideOutput = mIniFile->value("OverrideOutput", false).toBool();
|
||||
mOptions.overridenOutput = mIniFile->value("OverrideOutputName","").toString();
|
||||
mOptions.hostApplication = mIniFile->value("HostApplication","").toString();
|
||||
mOptions.useCustomMakefile = mIniFile->value("UseCustomMakefile", false).toBool();
|
||||
mOptions.customMakefile = mIniFile->value("CustomMakefile","").toString();
|
||||
mOptions.usePrecompiledHeader = mIniFile->value("UsePrecompiledHeader", false).toBool();
|
||||
mOptions.precompiledHeader = mIniFile->value("PrecompiledHeader","").toString();
|
||||
mOptions.cmdLineArgs = mIniFile->value("CommandLine","").toString();
|
||||
mFolders = mIniFile->value("Folders","").toString().split(";",Qt::SkipEmptyParts);
|
||||
mOptions.includeVersionInfo = mIniFile->value("IncludeVersionInfo", false).toBool();
|
||||
mOptions.supportXPThemes = mIniFile->value("SupportXPThemes", false).toBool();
|
||||
mOptions.compilerSet = mIniFile->value("CompilerSet", pSettings->compilerSets().defaultIndex()).toInt();
|
||||
mOptions.type = static_cast<ProjectType>(ini.GetLongValue("Project", "type", 0));
|
||||
mOptions.compilerCmd = fromByteArray(ini.GetValue("Project", "Compiler", ""));
|
||||
mOptions.cppCompilerCmd = fromByteArray(ini.GetValue("Project", "CppCompiler", ""));
|
||||
mOptions.linkerCmd = fromByteArray(ini.GetValue("Project", "Linker", ""));
|
||||
mOptions.objFiles = fromByteArray(ini.GetValue("Project", "ObjFiles", "")).split(";",Qt::SkipEmptyParts);
|
||||
mOptions.libs = fromByteArray(ini.GetValue("Project", "Libs", "")).split(";",Qt::SkipEmptyParts);
|
||||
mOptions.includes = fromByteArray(ini.GetValue("Project", "Includes", "")).split(";",Qt::SkipEmptyParts);
|
||||
mOptions.privateResource = fromByteArray(ini.GetValue("Project", "PrivateResource", ""));
|
||||
mOptions.resourceIncludes = fromByteArray(ini.GetValue("Project", "ResourceIncludes", "")).split(";",Qt::SkipEmptyParts);
|
||||
mOptions.makeIncludes = fromByteArray(ini.GetValue("Project", "MakeIncludes", "")).split(";",Qt::SkipEmptyParts);
|
||||
mOptions.useGPP = ini.GetBoolValue("Project", "IsCpp", false);
|
||||
mOptions.exeOutput = fromByteArray(ini.GetValue("Project", "ExeOutput", ""));
|
||||
mOptions.objectOutput = fromByteArray(ini.GetValue("Project", "ObjectOutput", ""));
|
||||
mOptions.logOutput = fromByteArray(ini.GetValue("Project", "LogOutput", ""));
|
||||
mOptions.logOutputEnabled = ini.GetBoolValue("Project", "LogOutputEnabled", false);
|
||||
mOptions.overrideOutput = ini.GetBoolValue("Project", "OverrideOutput", false);
|
||||
mOptions.overridenOutput = fromByteArray(ini.GetValue("Project", "OverrideOutputName", ""));
|
||||
mOptions.hostApplication = fromByteArray(ini.GetValue("Project", "HostApplication", ""));
|
||||
mOptions.useCustomMakefile = ini.GetBoolValue("Project", "UseCustomMakefile", false);
|
||||
mOptions.customMakefile = fromByteArray(ini.GetValue("Project", "CustomMakefile", ""));
|
||||
mOptions.usePrecompiledHeader = ini.GetBoolValue("Project", "UsePrecompiledHeader", false);
|
||||
mOptions.precompiledHeader = fromByteArray(ini.GetValue("Project", "PrecompiledHeader", ""));
|
||||
mOptions.cmdLineArgs = fromByteArray(ini.GetValue("Project", "CommandLine", ""));
|
||||
mFolders = fromByteArray(ini.GetValue("Project", "Folders", "")).split(";",Qt::SkipEmptyParts);
|
||||
mOptions.includeVersionInfo = ini.GetBoolValue("Project", "IncludeVersionInfo", false);
|
||||
mOptions.supportXPThemes = ini.GetBoolValue("Project", "SupportXPThemes", false);
|
||||
mOptions.compilerSet = ini.GetLongValue("Project", "CompilerSet", pSettings->compilerSets().defaultIndex());
|
||||
|
||||
if (mOptions.compilerSet >= pSettings->compilerSets().size()
|
||||
|| mOptions.compilerSet < 0) { // TODO: change from indices to names
|
||||
|
@ -1248,60 +1239,56 @@ void Project::loadOptions()
|
|||
mOptions.compilerSet = pSettings->compilerSets().defaultIndex();
|
||||
setModified(true);
|
||||
}
|
||||
mOptions.compilerOptions = mIniFile->value("CompilerSettings","").toString();
|
||||
mOptions.staticLink = mIniFile->value("StaticLink", true).toBool();
|
||||
mOptions.addCharset = mIniFile->value("AddCharset", true).toBool();
|
||||
bool useUTF8 = mIniFile->value("UseUTF8", false).toBool();
|
||||
mOptions.compilerOptions = fromByteArray(ini.GetValue("Project", "CompilerSettings", ""));
|
||||
mOptions.staticLink = ini.GetBoolValue("Project", "StaticLink", true);
|
||||
mOptions.addCharset = ini.GetBoolValue("Project", "AddCharset", true);
|
||||
bool useUTF8 = ini.GetBoolValue("Project", "UseUTF8", false);
|
||||
if (useUTF8) {
|
||||
mOptions.encoding = mIniFile->value("Encoding", ENCODING_SYSTEM_DEFAULT).toString();
|
||||
mOptions.encoding = fromByteArray(ini.GetValue("Project","Encoding", ENCODING_SYSTEM_DEFAULT));
|
||||
} else {
|
||||
mOptions.encoding = mIniFile->value("Encoding", ENCODING_UTF8).toString();
|
||||
mOptions.encoding = fromByteArray(ini.GetValue("Project","Encoding", ENCODING_UTF8));
|
||||
}
|
||||
mIniFile->endGroup();
|
||||
|
||||
mIniFile->beginGroup("VersionInfo");
|
||||
mOptions.versionInfo.major = mIniFile->value("Major", 0).toInt();
|
||||
mOptions.versionInfo.minor = mIniFile->value("Minor", 1).toInt();
|
||||
mOptions.versionInfo.release = mIniFile->value("Release", 1).toInt();
|
||||
mOptions.versionInfo.build = mIniFile->value("Build", 1).toInt();
|
||||
mOptions.versionInfo.languageID = mIniFile->value("LanguageID", 0x0409).toInt();
|
||||
mOptions.versionInfo.charsetID = mIniFile->value("CharsetID", 0x04E4).toInt();
|
||||
mOptions.versionInfo.companyName = mIniFile->value("CompanyName","").toString();
|
||||
mOptions.versionInfo.fileVersion = mIniFile->value("FileVersion", "0.1").toString();
|
||||
mOptions.versionInfo.fileDescription = mIniFile->value("FileDescription",
|
||||
tr("Developed using the Red Panda Dev-C++ IDE")).toString();
|
||||
mOptions.versionInfo.internalName = mIniFile->value("InternalName","").toString();
|
||||
mOptions.versionInfo.legalCopyright = mIniFile->value("LegalCopyright","").toString();
|
||||
mOptions.versionInfo.legalTrademarks = mIniFile->value("LegalTrademarks","").toString();
|
||||
mOptions.versionInfo.originalFilename = mIniFile->value("OriginalFilename",
|
||||
extractFileName(executable())).toString();
|
||||
mOptions.versionInfo.productName = mIniFile->value("ProductName", mName).toString();
|
||||
mOptions.versionInfo.productVersion = mIniFile->value("ProductVersion", "0.1.1.1").toString();
|
||||
mOptions.versionInfo.autoIncBuildNr = mIniFile->value("AutoIncBuildNr", false).toBool();
|
||||
mOptions.versionInfo.syncProduct = mIniFile->value("SyncProduct", false).toBool();
|
||||
mIniFile->endGroup();
|
||||
mOptions.versionInfo.major = ini.GetLongValue("VersionInfo", "Major", 0);
|
||||
mOptions.versionInfo.minor = ini.GetLongValue("VersionInfo", "Minor", 1);
|
||||
mOptions.versionInfo.release = ini.GetLongValue("VersionInfo", "Release", 1);
|
||||
mOptions.versionInfo.build = ini.GetLongValue("VersionInfo", "Build", 1);
|
||||
mOptions.versionInfo.languageID = ini.GetLongValue("VersionInfo", "LanguageID", 0x0409);
|
||||
mOptions.versionInfo.charsetID = ini.GetLongValue("VersionInfo", "CharsetID", 0x04E4);
|
||||
mOptions.versionInfo.companyName = fromByteArray(ini.GetValue("VersionInfo", "CompanyName", ""));
|
||||
mOptions.versionInfo.fileVersion = fromByteArray(ini.GetValue("VersionInfo", "FileVersion", "0.1"));
|
||||
mOptions.versionInfo.fileDescription = fromByteArray(ini.GetValue("VersionInfo", "FileDescription",
|
||||
toByteArray(tr("Developed using the Red Panda Dev-C++ IDE"))));
|
||||
mOptions.versionInfo.internalName = fromByteArray(ini.GetValue("VersionInfo", "InternalName", ""));
|
||||
mOptions.versionInfo.legalCopyright = fromByteArray(ini.GetValue("VersionInfo", "LegalCopyright", ""));
|
||||
mOptions.versionInfo.legalTrademarks = fromByteArray(ini.GetValue("VersionInfo", "LegalTrademarks", ""));
|
||||
mOptions.versionInfo.originalFilename = fromByteArray(ini.GetValue("VersionInfo", "OriginalFilename",
|
||||
toByteArray(extractFileName(executable()))));
|
||||
mOptions.versionInfo.productName = fromByteArray(ini.GetValue("VersionInfo", "ProductName", toByteArray(mName)));
|
||||
mOptions.versionInfo.productVersion = fromByteArray(ini.GetValue("VersionInfo", "ProductVersion", "0.1.1.1"));
|
||||
mOptions.versionInfo.autoIncBuildNr = ini.GetBoolValue("VersionInfo", "AutoIncBuildNr", false);
|
||||
mOptions.versionInfo.syncProduct = ini.GetBoolValue("VersionInfo", "SyncProduct", false);
|
||||
|
||||
} else { // dev-c < 4
|
||||
mOptions.version = 2;
|
||||
mIniFile->beginGroup("Project");
|
||||
if (!mIniFile->value("NoConsole", true).toBool())
|
||||
if (!ini.GetBoolValue("VersionInfo", "NoConsole", true))
|
||||
mOptions.type = ProjectType::Console;
|
||||
else if (mIniFile->value("IsDLL", false).toBool())
|
||||
else if (ini.GetBoolValue("VersionInfo", "IsDLL", false))
|
||||
mOptions.type = ProjectType::DynamicLib;
|
||||
else
|
||||
mOptions.type = ProjectType::GUI;
|
||||
|
||||
mOptions.privateResource = mIniFile->value("PrivateResource","").toString();
|
||||
mOptions.resourceIncludes = mIniFile->value("ResourceIncludes","").toString().split(";",Qt::SkipEmptyParts);
|
||||
mOptions.objFiles = mIniFile->value("ObjFiles","").toString().split(";",Qt::SkipEmptyParts);
|
||||
mOptions.includes = mIniFile->value("IncludeDirs","").toString().split(";",Qt::SkipEmptyParts);
|
||||
mOptions.compilerCmd = mIniFile->value("CompilerOptions","").toString();
|
||||
mOptions.useGPP = mIniFile->value("Use_GPP", false).toBool();
|
||||
mOptions.exeOutput = mIniFile->value("ExeOutput","").toString();
|
||||
mOptions.objectOutput = mIniFile->value("ObjectOutput","").toString();
|
||||
mOptions.overrideOutput = mIniFile->value("OverrideOutput", false).toBool();
|
||||
mOptions.overridenOutput = mIniFile->value("OverrideOutputName","").toString();
|
||||
mOptions.hostApplication = mIniFile->value("HostApplication","").toString();
|
||||
mIniFile->endGroup();
|
||||
mOptions.privateResource = fromByteArray(ini.GetValue("Project", "PrivateResource", ""));
|
||||
mOptions.resourceIncludes = fromByteArray(ini.GetValue("Project", "ResourceIncludes", "")).split(";",Qt::SkipEmptyParts);
|
||||
mOptions.objFiles = fromByteArray(ini.GetValue("Project", "ObjFiles", "")).split(";",Qt::SkipEmptyParts);
|
||||
mOptions.includes = fromByteArray(ini.GetValue("Project", "IncludeDirs", "")).split(";",Qt::SkipEmptyParts);
|
||||
mOptions.compilerCmd = fromByteArray(ini.GetValue("Project", "CompilerOptions", ""));
|
||||
mOptions.useGPP = ini.GetBoolValue("Project", "Use_GPP", false);
|
||||
mOptions.exeOutput = fromByteArray(ini.GetValue("Project", "ExeOutput", ""));
|
||||
mOptions.objectOutput = fromByteArray(ini.GetValue("Project", "ObjectOutput", ""));
|
||||
mOptions.overrideOutput = ini.GetBoolValue("Project", "OverrideOutput", false);
|
||||
mOptions.overridenOutput = fromByteArray(ini.GetValue("Project", "OverrideOutputName", ""));
|
||||
mOptions.hostApplication = fromByteArray(ini.GetValue("Project", "HostApplication", ""));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1401,6 +1388,16 @@ void Project::updateFolderNode(PFolderNode node)
|
|||
}
|
||||
}
|
||||
|
||||
QByteArray Project::toByteArray(const QString &s)
|
||||
{
|
||||
return s.toLocal8Bit();
|
||||
}
|
||||
|
||||
QString Project::fromByteArray(const QByteArray &s)
|
||||
{
|
||||
return QString::fromLocal8Bit(s);
|
||||
}
|
||||
|
||||
const QList<PProjectUnit> &Project::units() const
|
||||
{
|
||||
return mUnits;
|
||||
|
@ -1441,16 +1438,6 @@ void Project::setName(const QString &newName)
|
|||
mName = newName;
|
||||
}
|
||||
|
||||
std::shared_ptr<QSettings> &Project::iniFile()
|
||||
{
|
||||
return mIniFile;
|
||||
}
|
||||
|
||||
void Project::setIniFile(const std::shared_ptr<QSettings> &newIniFile)
|
||||
{
|
||||
mIniFile = newIniFile;
|
||||
}
|
||||
|
||||
const QString &Project::filename() const
|
||||
{
|
||||
return mFilename;
|
||||
|
|
|
@ -5,7 +5,9 @@
|
|||
#include <QObject>
|
||||
#include <QSettings>
|
||||
#include <memory>
|
||||
#include "SimpleIni.h"
|
||||
|
||||
using SimpleIni = CSimpleIniA;
|
||||
enum class ProjectType {
|
||||
GUI=0,
|
||||
Console=1,
|
||||
|
@ -173,7 +175,7 @@ public:
|
|||
PFolderNode parentNode,
|
||||
bool rebuild);
|
||||
void buildPrivateResource(bool forceSave);
|
||||
void checkProjectFileForUpdate();
|
||||
void checkProjectFileForUpdate(SimpleIni& ini);
|
||||
void closeUnit(int index);
|
||||
void createFolderNodes();
|
||||
void doAutoOpen();
|
||||
|
@ -187,7 +189,7 @@ public:
|
|||
int indexInUnits(const Editor* editor) const;
|
||||
QString listUnitStr(const QChar& separator);
|
||||
void loadLayout(); // load all [UnitX]
|
||||
void loadOptions();
|
||||
void loadOptions(SimpleIni& ini);
|
||||
void loadUnitLayout(Editor *e, int index); // load single [UnitX] cursor positions
|
||||
PFolderNode makeNewFileNode(const QString& s, bool isFolder, PFolderNode newParent);
|
||||
PFolderNode makeProjectNode();
|
||||
|
@ -217,9 +219,6 @@ public:
|
|||
std::shared_ptr<CppParser> cppParser();
|
||||
const QString &filename() const;
|
||||
|
||||
std::shared_ptr<QSettings> &iniFile();
|
||||
void setIniFile(const std::shared_ptr<QSettings> &newIniFile);
|
||||
|
||||
const QString &name() const;
|
||||
void setName(const QString &newName);
|
||||
|
||||
|
@ -240,10 +239,12 @@ private:
|
|||
void open();
|
||||
void removeFolderRecurse(PFolderNode node);
|
||||
void updateFolderNode(PFolderNode node);
|
||||
QByteArray toByteArray(const QString& s);
|
||||
QString fromByteArray(const QByteArray& s);
|
||||
|
||||
private:
|
||||
QList<PProjectUnit> mUnits;
|
||||
ProjectOptions mOptions;
|
||||
std::shared_ptr<QSettings> mIniFile;
|
||||
QString mFilename;
|
||||
QString mName;
|
||||
bool mModified;
|
||||
|
|
|
@ -630,9 +630,9 @@ QString extractRelativePath(const QString &base, const QString &dest)
|
|||
QFileInfo baseInfo(base);
|
||||
QDir baseDir;
|
||||
if (baseInfo.isDir()) {
|
||||
baseDir = baseInfo.absoluteDir();
|
||||
baseDir = QDir(baseInfo.absoluteFilePath());
|
||||
} else {
|
||||
baseDir = baseInfo.dir();
|
||||
baseDir = baseInfo.absoluteDir();
|
||||
}
|
||||
return baseDir.relativeFilePath(dest);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue