Skip to content

Commit

Permalink
Simplify file variables parsing, support VIM fileencoding and MySQL d…
Browse files Browse the repository at this point in the history
…ump "SET NAMES" comment.
  • Loading branch information
zufuliu committed Sep 17, 2020
1 parent 97174af commit 8019597
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 97 deletions.
140 changes: 45 additions & 95 deletions src/Edit.c
Original file line number Diff line number Diff line change
Expand Up @@ -7215,10 +7215,10 @@ void EditOpenSelection(int type) {
extern BOOL bNoEncodingTags;
extern int fNoFileVariables;

BOOL FileVars_Init(LPCSTR lpData, DWORD cbData, LPFILEVARS lpfv) {
void FileVars_Init(LPCSTR lpData, DWORD cbData, LPFILEVARS lpfv) {
ZeroMemory(lpfv, sizeof(FILEVARS));
if ((fNoFileVariables && bNoEncodingTags) || !lpData || !cbData) {
return TRUE;
return;
}

char tch[512];
Expand All @@ -7227,62 +7227,11 @@ BOOL FileVars_Init(LPCSTR lpData, DWORD cbData, LPFILEVARS lpfv) {
const BOOL utf8Sig = IsUTF8Signature(lpData);
BOOL bDisableFileVariables = FALSE;

if (!fNoFileVariables) {
int i;
if (FileVars_ParseInt(tch, "enable-local-variables", &i) && (!i)) {
bDisableFileVariables = TRUE;
}

if (!bDisableFileVariables) {
if (FileVars_ParseInt(tch, "tab-width", &i)) {
lpfv->iTabWidth = clamp_i(i, 1, 256);
lpfv->mask |= FV_TABWIDTH;
}

if (FileVars_ParseInt(tch, "c-basic-indent", &i)) {
lpfv->iIndentWidth = clamp_i(i, 0, 256);
lpfv->mask |= FV_INDENTWIDTH;
}

if (FileVars_ParseInt(tch, "indent-tabs-mode", &i)) {
lpfv->bTabsAsSpaces = i == 0;
lpfv->mask |= FV_TABSASSPACES;
}

if (FileVars_ParseInt(tch, "c-tab-always-indent", &i)) {
lpfv->bTabIndents = i != 0;
lpfv->mask |= FV_TABINDENTS;
}

if (FileVars_ParseInt(tch, "truncate-lines", &i)) {
lpfv->fWordWrap = i == 0;
lpfv->mask |= FV_WORDWRAP;
}

if (FileVars_ParseInt(tch, "fill-column", &i)) {
lpfv->iLongLinesLimit = clamp_i(i, 0, NP2_LONG_LINE_LIMIT);
lpfv->mask |= FV_LONGLINESLIMIT;
}
}
}

if (!utf8Sig && !bNoEncodingTags && !bDisableFileVariables) {
if (FileVars_ParseStr(tch, "encoding", lpfv->tchEncoding, COUNTOF(lpfv->tchEncoding)) ||
FileVars_ParseStr(tch, "charset", lpfv->tchEncoding, COUNTOF(lpfv->tchEncoding)) ||
FileVars_ParseStr(tch, "coding", lpfv->tchEncoding, COUNTOF(lpfv->tchEncoding))) {
lpfv->mask |= FV_ENCODING;
}
}

if (!fNoFileVariables && !bDisableFileVariables) {
if (FileVars_ParseStr(tch, "mode", lpfv->tchMode, COUNTOF(lpfv->tchMode))) {
lpfv->mask |= FV_MODE;
}
}

if (lpfv->mask == 0 && cbData > COUNTOF(tch)) {
strncpy(tch, lpData + cbData - COUNTOF(tch) + 1, COUNTOF(tch) - 1);
// parse file variables at the beginning or end of the file.
BOOL beginning = TRUE;
while (TRUE) {
if (!fNoFileVariables) {
// Emacs file variables
int i;
if (FileVars_ParseInt(tch, "enable-local-variables", &i) && (!i)) {
bDisableFileVariables = TRUE;
Expand All @@ -7294,7 +7243,7 @@ BOOL FileVars_Init(LPCSTR lpData, DWORD cbData, LPFILEVARS lpfv) {
lpfv->mask |= FV_TABWIDTH;
}

if (FileVars_ParseInt(tch, "c-basic-indent", &i)) {
if (FileVars_ParseInt(tch, "*basic-indent", &i)) {
lpfv->iIndentWidth = clamp_i(i, 0, 256);
lpfv->mask |= FV_INDENTWIDTH;
}
Expand All @@ -7304,7 +7253,7 @@ BOOL FileVars_Init(LPCSTR lpData, DWORD cbData, LPFILEVARS lpfv) {
lpfv->mask |= FV_TABSASSPACES;
}

if (FileVars_ParseInt(tch, "c-tab-always-indent", &i)) {
if (FileVars_ParseInt(tch, "*tab-always-indent", &i)) {
lpfv->bTabIndents = i != 0;
lpfv->mask |= FV_TABINDENTS;
}
Expand All @@ -7324,23 +7273,32 @@ BOOL FileVars_Init(LPCSTR lpData, DWORD cbData, LPFILEVARS lpfv) {
if (!utf8Sig && !bNoEncodingTags && !bDisableFileVariables) {
if (FileVars_ParseStr(tch, "encoding", lpfv->tchEncoding, COUNTOF(lpfv->tchEncoding)) ||
FileVars_ParseStr(tch, "charset", lpfv->tchEncoding, COUNTOF(lpfv->tchEncoding)) ||
FileVars_ParseStr(tch, "coding", lpfv->tchEncoding, COUNTOF(lpfv->tchEncoding))) {
FileVars_ParseStr(tch, "coding", lpfv->tchEncoding, COUNTOF(lpfv->tchEncoding)) || // Emacs
FileVars_ParseStr(tch, "fileencoding", lpfv->tchEncoding, COUNTOF(lpfv->tchEncoding)) || // VIM
FileVars_ParseStr(tch, "/*!40101 SET NAMES ", lpfv->tchEncoding, COUNTOF(lpfv->tchEncoding))) {
// MySQL dump: /*!40101 SET NAMES utf8mb4 */;
lpfv->mask |= FV_ENCODING;
break;
}
}

if (!fNoFileVariables && !bDisableFileVariables) {
if (FileVars_ParseStr(tch, "mode", lpfv->tchMode, COUNTOF(lpfv->tchMode))) {
if (FileVars_ParseStr(tch, "mode", lpfv->tchMode, COUNTOF(lpfv->tchMode))) { // Emacs
lpfv->mask |= FV_MODE;
}
}

if (beginning && lpfv->mask == 0 && cbData > COUNTOF(tch)) {
strncpy(tch, lpData + cbData - COUNTOF(tch) + 1, COUNTOF(tch) - 1);
beginning = FALSE;
} else {
break;
}
}

if (lpfv->mask & FV_ENCODING) {
lpfv->iEncoding = Encoding_MatchA(lpfv->tchEncoding);
}

return TRUE;
}

//=============================================================================
Expand All @@ -7355,7 +7313,7 @@ extern int iLongLinesLimit;
extern int iLongLinesLimitG;
extern int iWrapCol;

BOOL FileVars_Apply(LPCFILEVARS lpfv) {
void FileVars_Apply(LPCFILEVARS lpfv) {
if (lpfv->mask & FV_TABWIDTH) {
iTabWidth = lpfv->iTabWidth;
} else {
Expand Down Expand Up @@ -7402,32 +7360,40 @@ BOOL FileVars_Apply(LPCFILEVARS lpfv) {
SciCall_SetEdgeColumn(iLongLinesLimit);

iWrapCol = 0;

return TRUE;
}

//=============================================================================
//
// FileVars_ParseInt()
//
BOOL FileVars_ParseInt(LPCSTR pszData, LPCSTR pszName, int *piValue) {
LPCSTR pvStart = pszData;
static LPCSTR FileVars_Find(LPCSTR pszData, LPCSTR pszName) {
const BOOL suffix = *pszName == '*';
if (suffix) {
++pszName;
}

LPCSTR pvStart = pszData;
while ((pvStart = strstr(pvStart, pszName)) != NULL) {
const unsigned char chPrev = (pvStart > pszData) ? *(pvStart - 1) : 0;
if (!(IsAlpha(chPrev) || chPrev == '-' || chPrev == '_')) {
pvStart += strlen(pszName);
while (*pvStart == ' ') {
const size_t len = strlen(pszName);
pvStart += len;
// match full name or suffix after hyphen
if (!(IsAlphaNumeric(chPrev) || chPrev == '-' || chPrev == '_' || chPrev == '.')
|| (suffix && chPrev == '-')) {
while (*pvStart == ' ' || *pvStart == '\t') {
pvStart++;
}
if (*pvStart == ':' || *pvStart == '=') {
if (*pvStart == ':' || *pvStart == '=' || pszName[len - 1] == ' ') {
break;
}
} else {
pvStart += strlen(pszName);
}
}

return pvStart;
}

//=============================================================================
//
// FileVars_ParseInt()
//
BOOL FileVars_ParseInt(LPCSTR pszData, LPCSTR pszName, int *piValue) {
LPCSTR pvStart = FileVars_Find(pszData, pszName);
if (pvStart) {
while (*pvStart == ':' || *pvStart == '=' || *pvStart == '\"' || *pvStart == '\'' || *pvStart == ' ' || *pvStart == '\t') {
pvStart++;
Expand Down Expand Up @@ -7459,23 +7425,7 @@ BOOL FileVars_ParseInt(LPCSTR pszData, LPCSTR pszName, int *piValue) {
// FileVars_ParseStr()
//
BOOL FileVars_ParseStr(LPCSTR pszData, LPCSTR pszName, char *pszValue, int cchValue) {
LPCSTR pvStart = pszData;

while ((pvStart = strstr(pvStart, pszName)) != NULL) {
const unsigned char chPrev = (pvStart > pszData) ? *(pvStart - 1) : 0;
if (!(IsAlpha(chPrev) || chPrev == '-' || chPrev == '_')) {
pvStart += strlen(pszName);
while (*pvStart == ' ') {
pvStart++;
}
if (*pvStart == ':' || *pvStart == '=') {
break;
}
} else {
pvStart += strlen(pszName);
}
}

LPCSTR pvStart = FileVars_Find(pszData, pszName);
if (pvStart) {
BOOL bQuoted = FALSE;

Expand Down
4 changes: 2 additions & 2 deletions src/Edit.h
Original file line number Diff line number Diff line change
Expand Up @@ -399,8 +399,8 @@ typedef struct FILEVARS {

typedef const FILEVARS * LPCFILEVARS;

BOOL FileVars_Init(LPCSTR lpData, DWORD cbData, LPFILEVARS lpfv);
BOOL FileVars_Apply(LPCFILEVARS lpfv);
void FileVars_Init(LPCSTR lpData, DWORD cbData, LPFILEVARS lpfv);
void FileVars_Apply(LPCFILEVARS lpfv);
BOOL FileVars_ParseInt(LPCSTR pszData, LPCSTR pszName, int *piValue);
BOOL FileVars_ParseStr(LPCSTR pszData, LPCSTR pszName, char *pszValue, int cchValue);
// in EditEncoding.c
Expand Down

0 comments on commit 8019597

Please sign in to comment.