gambas-source-code/main/lib/eval/CHighlight.c
Benoît Minisini bfde7da5de [DEVELOPMENT ENVIRONMENT]
* NEW: A menu entry and a button for showing/hiding the menu bar.

[GB.EVAL]
* BUG: Highlight.Purge() now correctly handle non-ASCII characters inside 
  strings and comments.

[GB.QT]
* NEW: Window.Menus.Hide, Window.Menus.Show and Window.Menus.Visible are 
  two methods and one property for showing and hiding the menu bar of the 
  window.


git-svn-id: svn://localhost/gambas/trunk@1706 867c0c6c-44f3-4631-809d-bfa615b0a4ec
2008-11-20 22:09:51 +00:00

356 lines
8 KiB
C

/***************************************************************************
CHighlight.cpp
(c) 2000-2007 Benoit Minisini <gambas@users.sourceforge.net>
WIDGET program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 1, or (at your option)
any later version.
WIDGET program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with WIDGET program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
***************************************************************************/
#define __CHIGHLIGHT_CPP
#include "gb_common.h"
#include "main.h"
#include "gb.eval.h"
#include "eval_analyze.h"
#include "CHighlight.h"
static void *_analyze_symbol = 0;
static void *_analyze_type = 0;
static void *_analyze_pos = 0;
static char *_purged_line = NULL;
static int get_char_length(unsigned char c)
{
int n = 1;
if (c & 0x80)
{
for (;;)
{
c <<= 1;
if (!(c & 0x80))
break;
n++;
}
}
return n;
}
static char *purge(const char *s, int len_s, bool comment, bool string)
{
char c;
uint i;
int lc, ls;
bool in_comment = FALSE;
char wait = 0;
char *r = NULL;
for (i = 0; i < len_s; i += ls)
{
c = s[i];
ls = lc = get_char_length((unsigned char)c);
switch(wait)
{
case 0:
if (in_comment)
{
if (!comment)
c = ' ', lc = 1;
}
else if (c == '"')
wait = '"';
else if (c == '\'')
in_comment = TRUE;
break;
case '"':
if (c == '"')
wait = 0;
else if (c == '\\')
{
if (string)
{
if (i < len_s)
GB.AddString(&r, &c, 1);
//r += c;
i++;
c = s[i];
lc = get_char_length((unsigned char)c);
}
else
{
i++;
if (i < len_s)
GB.AddString(&r, " ", 1);
//r += ' ';
c = ' ', lc = 1;
}
}
else
{
if (!string)
c = ' ', lc = 1;
}
break;
}
if (lc == 1)
GB.AddString(&r, &c, 1);
else
GB.AddString(&r, &s[i], lc);
}
GB.FreeString(&_purged_line);
_purged_line = r;
return r;
}
static int convState(int state)
{
switch(state)
{
case EVAL_TYPE_END: return HIGHLIGHT_NORMAL;
case EVAL_TYPE_RESERVED: return HIGHLIGHT_KEYWORD;
case EVAL_TYPE_IDENTIFIER: return HIGHLIGHT_SYMBOL;
case EVAL_TYPE_CLASS: return HIGHLIGHT_DATATYPE;
case EVAL_TYPE_NUMBER: return HIGHLIGHT_NUMBER;
case EVAL_TYPE_STRING: return HIGHLIGHT_STRING;
case EVAL_TYPE_SUBR: return HIGHLIGHT_SUBR;
case EVAL_TYPE_COMMENT: return HIGHLIGHT_COMMENT;
case EVAL_TYPE_OPERATOR: return HIGHLIGHT_OPERATOR;
case EVAL_TYPE_DATATYPE: return HIGHLIGHT_DATATYPE;
case EVAL_TYPE_ERROR: return HIGHLIGHT_ERROR;
default: return HIGHLIGHT_NORMAL;
}
}
static void analyze(const char *src, int len_src)
{
GB_ARRAY garray, tarray, parray;
int i, n, pos, len, p;
char *str;
EVAL_ANALYZE result;
EVAL_analyze(src, len_src, &result, FALSE);
n = 0;
for (i = 0; i < result.len; i++)
{
if (result.color[i].state != EVAL_TYPE_END)
n++;
}
GB.Array.New(&garray, GB_T_STRING, n);
GB.Array.New(&tarray, GB_T_INTEGER, n);
GB.Array.New(&parray, GB_T_INTEGER, n);
pos = 0;
i = 0;
for (p = 0; p < result.len; p++)
{
len = result.color[p].len;
if (result.color[p].state != EVAL_TYPE_END)
{
GB.NewString(&str, &result.str[pos], len);
*((char **)GB.Array.Get(garray, i)) = str;
*((int *)GB.Array.Get(tarray, i)) = convState(result.color[p].state);
*((int *)GB.Array.Get(parray, i)) = pos;
i++;
}
pos += len;
}
GB.Unref(&_analyze_symbol);
_analyze_symbol = garray;
GB.Ref(garray);
GB.Unref(&_analyze_type);
_analyze_type = tarray;
GB.Ref(tarray);
GB.Unref(&_analyze_pos);
_analyze_pos = parray;
GB.Ref(parray);
GB.FreeString(&result.str);
}
BEGIN_METHOD_VOID(CHIGHLIGHT_exit)
GB.Unref(&_analyze_symbol);
GB.Unref(&_analyze_type);
GB.Unref(&_analyze_pos);
GB.FreeString(&_purged_line);
END_METHOD
#if 0
BEGIN_PROPERTY(CHIGHLIGHT_state)
if (READ_PROPERTY)
GB.ReturnInteger(_highlight_state);
else
_highlight_state = VPROP(GB_INTEGER);
END_PROPERTY
BEGIN_PROPERTY(CHIGHLIGHT_tag)
if (READ_PROPERTY)
GB.ReturnInteger(_highlight_tag);
else
_highlight_tag = VPROP(GB_INTEGER);
END_PROPERTY
BEGIN_PROPERTY(CHIGHLIGHT_show_limit)
if (READ_PROPERTY)
GB.ReturnBoolean(_highlight_show_limit);
else
_highlight_show_limit = VPROP(GB_BOOLEAN);
END_PROPERTY
BEGIN_PROPERTY(CHIGHLIGHT_text)
if (READ_PROPERTY)
GB.ReturnNewZeroString(TO_UTF8(_highlight_text));
else
_highlight_text = QSTRING_PROP();
END_PROPERTY
BEGIN_METHOD(CHIGHLIGHT_add, GB_INTEGER state; GB_INTEGER len)
GHighlight *h;
if (!_highlight_data)
return;
int count = GB.Count(*_highlight_data) - 1;
int state = VARG(state);
int len = VARGOPT(len, 1);
if (len < 1)
return;
if (count < 0 || (*_highlight_data)[count].state != (uint)state)
{
count++;
h = (GHighlight *)GB.Add(_highlight_data);
h->state = state;
h->len = len;
}
else
(*_highlight_data)[count].len += len;
END_METHOD
#endif
BEGIN_METHOD(CHIGHLIGHT_purge, GB_STRING text; GB_BOOLEAN comment; GB_BOOLEAN string)
bool comment = VARGOPT(comment, FALSE);
bool string = VARGOPT(string, FALSE);
if (comment && string)
GB.ReturnNewString(STRING(text), LENGTH(text));
else
{
GB.ReturnString(purge(STRING(text), LENGTH(text), comment, string));
}
END_METHOD
BEGIN_METHOD(CHIGHLIGHT_analyze, GB_STRING text)
analyze(STRING(text), LENGTH(text));
GB.ReturnObject(_analyze_symbol);
END_METHOD
BEGIN_PROPERTY(CHIGHLIGHT_analyze_symbols)
GB.ReturnObject(_analyze_symbol);
END_PROPERTY
BEGIN_PROPERTY(CHIGHLIGHT_analyze_types)
GB.ReturnObject(_analyze_type);
END_PROPERTY
BEGIN_PROPERTY(CHIGHLIGHT_analyze_positions)
GB.ReturnObject(_analyze_pos);
END_PROPERTY
GB_DESC CHighlightDesc[] =
{
GB_DECLARE("Highlight", 0), GB_VIRTUAL_CLASS(),
/*GB_CONSTANT("None", "i", GDocument::None),
GB_CONSTANT("Gambas", "i", GDocument::Gambas),
GB_CONSTANT("Custom", "i", GDocument::Custom),*/
GB_CONSTANT("Background", "i", HIGHLIGHT_BACKGROUND),
GB_CONSTANT("Normal", "i", HIGHLIGHT_NORMAL),
GB_CONSTANT("Keyword", "i", HIGHLIGHT_KEYWORD),
GB_CONSTANT("Function", "i", HIGHLIGHT_SUBR),
GB_CONSTANT("Operator", "i", HIGHLIGHT_OPERATOR),
GB_CONSTANT("Symbol", "i", HIGHLIGHT_SYMBOL),
GB_CONSTANT("Number", "i", HIGHLIGHT_NUMBER),
GB_CONSTANT("String", "i", HIGHLIGHT_STRING),
GB_CONSTANT("Comment", "i", HIGHLIGHT_COMMENT),
GB_CONSTANT("Breakpoint", "i", HIGHLIGHT_BREAKPOINT),
GB_CONSTANT("Current", "i", HIGHLIGHT_CURRENT),
GB_CONSTANT("DataType", "i", HIGHLIGHT_DATATYPE),
GB_CONSTANT("Selection", "i", HIGHLIGHT_SELECTION),
GB_CONSTANT("Highlight", "i", HIGHLIGHT_HIGHLIGHT),
GB_CONSTANT("CurrentLine", "i", HIGHLIGHT_LINE),
GB_CONSTANT("Error", "i", HIGHLIGHT_ERROR),
GB_STATIC_METHOD("_exit", NULL, CHIGHLIGHT_exit, NULL),
GB_STATIC_METHOD("Analyze", "String[]", CHIGHLIGHT_analyze, "(Code)s"),
GB_STATIC_PROPERTY_READ("Symbols", "String[]", CHIGHLIGHT_analyze_symbols),
GB_STATIC_PROPERTY_READ("Types", "Integer[]", CHIGHLIGHT_analyze_types),
GB_STATIC_PROPERTY_READ("Positions", "Integer[]", CHIGHLIGHT_analyze_positions),
GB_STATIC_METHOD("Purge", "s", CHIGHLIGHT_purge, "(Code)s[(Comment)b(String)b]"),
/*GB_STATIC_PROPERTY("State", "i", CHIGHLIGHT_state),
GB_STATIC_PROPERTY("Tag", "i", CHIGHLIGHT_tag),
GB_STATIC_PROPERTY("ShowLimit", "b", CHIGHLIGHT_show_limit),
GB_STATIC_PROPERTY("Text", "s", CHIGHLIGHT_text),
GB_STATIC_METHOD("Add", NULL, CHIGHLIGHT_add, "(State)i[(Count)i]"),*/
GB_END_DECLARE
};