Browse CVS Repository
Diff of /shiki/shiki/shiki.c
Parent Directory
| Revision Log
| Revision Graph
| Patch
| 55 |
} ShikiTabInfo; |
} ShikiTabInfo; |
| 56 |
|
|
| 57 |
/* エディタ全体に関する情報と,現在表示されているタブ情報へのキャッシュを管理する構造体 */ |
/* エディタ全体に関する情報と,現在表示されているタブ情報へのキャッシュを管理する構造体 */ |
| 58 |
struct { |
static struct { |
| 59 |
GtkWidget *editor_window; |
GtkWidget *editor_window; |
| 60 |
GtkClipboard *clipboard; |
GtkClipboard *clipboard; |
| 61 |
GtkNotebook *notebook; |
GtkNotebook *notebook; |
| 85 |
#define Shiki_CURRENT_FILENAME (shiki_editor.current_tabpage_info)->filename |
#define Shiki_CURRENT_FILENAME (shiki_editor.current_tabpage_info)->filename |
| 86 |
#define Shiki_CURRENT_BUFFER_ENV (shiki_editor.current_tabpage_info)->env |
#define Shiki_CURRENT_BUFFER_ENV (shiki_editor.current_tabpage_info)->env |
| 87 |
|
|
| 88 |
|
static gchar *R5RS_keywords[] = {"and", "begin", "case", "cond-expand", "cond", "define-accessor", "define-class", "defined?", "define-generic", "define", "define-macro", "define-method", "define-module", "define-private", "define-public", "define-reader-ctor", "define-syntax", "define-syntax-macro", "defmacro", "defmacro*-public", "delay", "do", "else", "fluid-let", "if", "lambda", "let", "let*", "letrec", "letrec-syntax", "let-syntax", "or", "quasiquote", "quote", "set!", "syntax-rules", "unquote", NULL}; |
| 89 |
|
|
| 90 |
|
static gchar *R5RS_functions[] = { |
| 91 |
|
"*", "+", "-", "/", "<", ">", "<=", ">=", "?", "`", "=", "abs", "acos", "angle", "append", "apply", "asin", "assoc", "assq", "assv", "atan", "boolean?", "caaar", "caadr", "caar", "cadar", "caddr", "cadr", "call/cc", "call-with-current-continuation", "call-with-input-file", "call-with-output-file", "call-with-values", "car", "catch", "cdaar", "cdadr", "cdar", "cddar", "cdddr", "cddr", "cdr", "ceiling", "char-alphabetic?", "char-ci>=?", "char-ci>?", "char-ci=?", "char-ci<=?", "char-ci<?", "char-downcase", "char->integer", "char>=?", "char>?", "char=?", "char?", "char-lower-case?", "char<=?", "char<?", "char-numeric?", "char-ready?", "char-upcase", "char-upper-case?", "char-whitespace?", "close-input-port", "close-output-port", "complex?", "cons", "cos", "current-input-port", "current-output-port", "delete-file", "display", "dynamic-wind", "eof-object?", "eq?", "equal?", "eqv?", "eval", "even?", "exact->inexact", "exact?", "exit", "exp", "expt", "file-exists?", "file-or-directory-modify-seconds", "floor", "force", "for-each", "gcd", "gensym", "getenv", "get-output-string", "imag-part", "inexact?", "input-port?", "integer->char", "integer?", "lcm", "length", "list->string", "list->vector", "list", "list?", "list-ref", "list-tail", "load", "log", "magnitude", "make-polar", "make-rectangular", "make-string", "make-vector", "map", "max", "member", "memq", "memv", "min", "modulo", "negative?", "newline", "nil", "not", "null?", "number->string", "number?", "odd?", "open-input-file", "open-input-string", "open-output-file", "open-output-string", "output-port?", "pair?", "peek-char", "port?", "positive?", "procedure?", "quotient", "rational?", "read-char", "read", "read-line", "real?", "real-part", "remainder", "reverse", "reverse!", "round", "set-car!", "set-cdr!", "sin", "sqrt", "string-append", "string-ci>=?", "string-ci>?", "string-ci=?", "string-ci<=?", "string-ci<?", "string-copy", "string-fill!", "string>=?", "string>?", "string->list", "string->number", "string->symbol", "string", "string=?", "string?", "string-length", "string<=?", "string<?", "string-ref", "string-set!", "substring", "symbol->string", "symbol?", "system", "tan", "truncate", "values", "vector-fill!", "vector->list", "vector", "vector?", "vector-length", "vector-ref", "vector-set!", "with-input-from-file", "with-output-to-file", "write-char", "write", "zero", NULL}; |
| 92 |
|
|
| 93 |
|
static GHashTable *keywords_hash = NULL; |
| 94 |
|
|
| 95 |
|
typedef enum { |
| 96 |
|
R5RS_KEYWORD_COLOR = 1, |
| 97 |
|
R5RS_FUNCTION_COLOR, |
| 98 |
|
GAUCHE_KEYWORD_COLOR, |
| 99 |
|
GAUCHE_FUNCTION_COLOR |
| 100 |
|
} HIGHILIGHT_COLOR; |
| 101 |
|
|
| 102 |
/* プロトタイプ */ |
/* プロトタイプ */ |
| 103 |
|
|
| 104 |
/* タブの生成と削除 : 基本的に,ShikiTabInfo の中身に格納する情報を増やしたかったら,この 2 つの関数だけを変更すれば良い (ようにする…) */ |
/* タブの生成と削除 : 基本的に,ShikiTabInfo の中身に格納する情報を増やしたかったら,この 2 つの関数だけを変更すれば良い (ようにする…) */ |
| 174 |
/* エディタの初期化 */ |
/* エディタの初期化 */ |
| 175 |
static void shiki_editor_window_init(int argc, char **argv); |
static void shiki_editor_window_init(int argc, char **argv); |
| 176 |
|
|
| 177 |
|
static gboolean is_not_scheme_delimita_p(gunichar ch, gpointer user_data) { |
| 178 |
|
return ch != '(' && ch != ')' && !g_unichar_isspace(ch); |
| 179 |
|
} |
| 180 |
|
|
| 181 |
|
static gboolean is_scheme_delimita_p(gunichar ch, gpointer user_data) { |
| 182 |
|
return ch == ' ' || ch == '(' || ch == ')' || g_unichar_isspace(ch); |
| 183 |
|
} |
| 184 |
|
|
| 185 |
|
/* ソースコードの色分け */ |
| 186 |
|
static void scheme_keyword_highlighting_current_buffer() { |
| 187 |
|
GtkTextIter s, e; |
| 188 |
|
HIGHILIGHT_COLOR c; |
| 189 |
|
gchar *word; |
| 190 |
|
|
| 191 |
|
if(!keywords_hash) { |
| 192 |
|
keywords_hash = g_hash_table_new(g_str_hash, g_str_equal); |
| 193 |
|
int i = 0; |
| 194 |
|
while(R5RS_keywords[i] != NULL) |
| 195 |
|
g_hash_table_insert(keywords_hash, R5RS_keywords[i++], GINT_TO_POINTER(R5RS_KEYWORD_COLOR)); |
| 196 |
|
i = 0; |
| 197 |
|
while(R5RS_functions[i] != NULL) |
| 198 |
|
g_hash_table_insert(keywords_hash, R5RS_functions[i++], GINT_TO_POINTER(R5RS_FUNCTION_COLOR)); |
| 199 |
|
} |
| 200 |
|
gtk_text_buffer_get_start_iter(Shiki_CURRENT_TEXT_BUFFER, &s); |
| 201 |
|
gtk_text_buffer_get_end_iter(Shiki_CURRENT_TEXT_BUFFER, &e); |
| 202 |
|
gtk_text_buffer_apply_tag_by_name(Shiki_CURRENT_TEXT_BUFFER, "default_background", &s, &e); |
| 203 |
|
gtk_text_buffer_apply_tag_by_name(Shiki_CURRENT_TEXT_BUFFER, "default_foreground", &s, &e); |
| 204 |
|
|
| 205 |
|
gtk_text_buffer_get_start_iter(Shiki_CURRENT_TEXT_BUFFER, &s); |
| 206 |
|
|
| 207 |
|
/* 簡単な Scheme レキシカルアナライザ */ |
| 208 |
|
while(TRUE) { |
| 209 |
|
gboolean is_comment = FALSE; |
| 210 |
|
if(gtk_text_iter_get_char(&s) != ';') |
| 211 |
|
gtk_text_iter_forward_find_char(&s, is_not_scheme_delimita_p, NULL, NULL); |
| 212 |
|
e = s; |
| 213 |
|
if(gtk_text_iter_get_char(&s) == ';') { |
| 214 |
|
gtk_text_iter_forward_line(&e); |
| 215 |
|
gtk_text_iter_backward_char(&e); |
| 216 |
|
is_comment = TRUE; |
| 217 |
|
} else |
| 218 |
|
gtk_text_iter_forward_find_char(&e, is_scheme_delimita_p, NULL, NULL); |
| 219 |
|
|
| 220 |
|
word = gtk_text_buffer_get_text(Shiki_CURRENT_TEXT_BUFFER, &s, &e, FALSE); |
| 221 |
|
if(is_comment) |
| 222 |
|
gtk_text_buffer_apply_tag_by_name(Shiki_CURRENT_TEXT_BUFFER, "comment_highlighting", &s, &e); |
| 223 |
|
/* 切り取った文字列がキーワードならば色を付ける */ |
| 224 |
|
else if(R5RS_KEYWORD_COLOR == (c = GPOINTER_TO_INT(g_hash_table_lookup(keywords_hash, word)))) |
| 225 |
|
gtk_text_buffer_apply_tag_by_name(Shiki_CURRENT_TEXT_BUFFER, "keyword_highlighting", &s, &e); |
| 226 |
|
else if(R5RS_FUNCTION_COLOR == c) |
| 227 |
|
gtk_text_buffer_apply_tag_by_name(Shiki_CURRENT_TEXT_BUFFER, "function_highlighting", &s, &e); |
| 228 |
|
|
| 229 |
|
g_free(word); |
| 230 |
|
|
| 231 |
|
if(gtk_text_iter_is_end(&e)) break; |
| 232 |
|
s = e; |
| 233 |
|
} |
| 234 |
|
/* XXX : 正規表現を試している途中 |
| 235 |
|
static ScmRegexp *rx = NULL; |
| 236 |
|
gchar *buf = get_all_buffer_contents(Shiki_CURRENT_TEXT_BUFFER); |
| 237 |
|
ScmString *input = SCM_STRING(SCM_MAKE_STR(buf)); |
| 238 |
|
ScmRegMatch *regmatch; |
| 239 |
|
ScmObj n, s, e; |
| 240 |
|
GtkTextIter start, end; |
| 241 |
|
if(!rx) { |
| 242 |
|
rx = SCM_REGEXP(Scm_RegComp(SCM_STRING(SCM_MAKE_STR(";. - #[\x0d\x0a]*")), 0)); |
| 243 |
|
g_return_if_fail(SCM_REGEXPP(rx)); |
| 244 |
|
} |
| 245 |
|
regmatch = SCM_REGMATCH(Scm_RegExec(rx, input)); |
| 246 |
|
if(!SCM_REGMATCHP(regmatch)) |
| 247 |
|
return; |
| 248 |
|
|
| 249 |
|
gtk_text_buffer_create_tag (Shiki_CURRENT_TEXT_BUFFER, "comment_highlighting", "foreground", "red", NULL); |
| 250 |
|
|
| 251 |
|
n = Scm_MakeInteger(0); |
| 252 |
|
s = Scm_RegMatchStart(regmatch, n); |
| 253 |
|
e = Scm_RegMatchEnd(regmatch, n); |
| 254 |
|
gtk_text_buffer_get_iter_at_offset(Shiki_CURRENT_TEXT_BUFFER, &start, SCM_INT_VALUE(s)); |
| 255 |
|
gtk_text_buffer_get_iter_at_offset(Shiki_CURRENT_TEXT_BUFFER, &end, SCM_INT_VALUE(e)); |
| 256 |
|
gtk_text_buffer_apply_tag_by_name(Shiki_CURRENT_TEXT_BUFFER, "comment_highlighting", &start, &end); |
| 257 |
|
//g_print("start : %ld, end : %ld", SCM_INT_VALUE(start), SCM_INT_VALUE(end)); |
| 258 |
|
Scm_RegMatchDump(regmatch); |
| 259 |
|
g_free(buf); |
| 260 |
|
*/ |
| 261 |
|
} |
| 262 |
|
|
| 263 |
/* バッファにテキストが挿入された */ |
/* バッファにテキストが挿入された */ |
| 264 |
static void insert_text_handler(GtkTextBuffer *buffer, GtkTextIter *iter, gchar *str, gint len) { |
static void insert_text_handler(GtkTextBuffer *buffer, GtkTextIter *iter, gchar *str, gint len) { |
| 265 |
/* Undo のための情報を記録 */ |
/* Undo のための情報を記録 */ |
| 271 |
undoInfo->start = gtk_text_iter_get_offset(iter); |
undoInfo->start = gtk_text_iter_get_offset(iter); |
| 272 |
undoInfo->end = undoInfo->start + undoInfo->strlen; |
undoInfo->end = undoInfo->start + undoInfo->strlen; |
| 273 |
Shiki_CURRENT_UNDO_INFO_LIST = g_list_prepend(Shiki_CURRENT_UNDO_INFO_LIST, undoInfo); |
Shiki_CURRENT_UNDO_INFO_LIST = g_list_prepend(Shiki_CURRENT_UNDO_INFO_LIST, undoInfo); |
| 274 |
g_print("insert : %s, len : %d, start : %d, end : %d\n", undoInfo->str, undoInfo->strlen, undoInfo->start, undoInfo->end); |
/* g_print("insert : %s, len : %d, start : %d, end : %d\n", undoInfo->str, undoInfo->strlen, undoInfo->start, undoInfo->end); */ |
| 275 |
} |
} |
| 276 |
|
|
| 277 |
/* バッファからテキストが消去された */ |
/* バッファからテキストが消去された */ |
| 285 |
undoInfo->end = gtk_text_iter_get_offset(end); |
undoInfo->end = gtk_text_iter_get_offset(end); |
| 286 |
undoInfo->strlen = end - start; |
undoInfo->strlen = end - start; |
| 287 |
Shiki_CURRENT_UNDO_INFO_LIST = g_list_prepend(Shiki_CURRENT_UNDO_INFO_LIST, undoInfo); |
Shiki_CURRENT_UNDO_INFO_LIST = g_list_prepend(Shiki_CURRENT_UNDO_INFO_LIST, undoInfo); |
| 288 |
g_print("delete : %s %d\n", undoInfo->str, undoInfo->strlen); |
/* g_print("delete : %s %d\n", undoInfo->str, undoInfo->strlen); */ |
| 289 |
} |
} |
| 290 |
|
|
| 291 |
/* タブが切り替わる時のイベントハンドリング */ |
/* タブが切り替わる時のイベントハンドリング */ |
| 438 |
tabinfo->filename = filename; |
tabinfo->filename = filename; |
| 439 |
tabinfo->tabpage_label = g_path_get_basename(filename); |
tabinfo->tabpage_label = g_path_get_basename(filename); |
| 440 |
tabinfo->env = Scm_MakeModule(NULL, FALSE); |
tabinfo->env = Scm_MakeModule(NULL, FALSE); |
| 441 |
|
|
| 442 |
g_return_if_fail(tabinfo->env != SCM_FALSE); |
g_return_if_fail(tabinfo->env != SCM_FALSE); |
| 443 |
|
|
| 444 |
/* スクロールウィンドウ (タブの中身の大外) を作る */ |
/* スクロールウィンドウ (タブの中身の大外) を作る */ |
| 459 |
tabinfo->delete_handler_id = g_signal_connect(Shiki_EDITOR_WINDOW, "delete_event", G_CALLBACK(delete_event_handler), tabinfo->text_buffer); |
tabinfo->delete_handler_id = g_signal_connect(Shiki_EDITOR_WINDOW, "delete_event", G_CALLBACK(delete_event_handler), tabinfo->text_buffer); |
| 460 |
|
|
| 461 |
/* 様々な初期化処理 */ |
/* 様々な初期化処理 */ |
| 462 |
|
/* デフォルトの背景色と文字の色 */ |
| 463 |
|
gtk_text_buffer_create_tag(tabinfo->text_buffer, "default_background", "background", "black", NULL); |
| 464 |
|
gtk_text_buffer_create_tag(tabinfo->text_buffer, "default_foreground", "foreground", "green", NULL); |
| 465 |
/* 括弧の強調表示のためのタグを作る */ |
/* 括弧の強調表示のためのタグを作る */ |
| 466 |
gtk_text_buffer_create_tag (tabinfo->text_buffer, "parent_emphasis_background", "background", "green", NULL); |
gtk_text_buffer_create_tag(tabinfo->text_buffer, "parent_emphasis_background", "background", "pink", NULL); |
| 467 |
|
|
| 468 |
|
/* キーワードハイライティング */ |
| 469 |
|
gtk_text_buffer_create_tag(tabinfo->text_buffer, "keyword_highlighting", "foreground", "blue", NULL); |
| 470 |
|
/* 関数 */ |
| 471 |
|
gtk_text_buffer_create_tag(tabinfo->text_buffer, "function_highlighting", "foreground", "red", NULL); |
| 472 |
|
/* コメント */ |
| 473 |
|
gtk_text_buffer_create_tag (tabinfo->text_buffer, "comment_highlighting", "foreground", "orange", NULL); |
| 474 |
|
|
| 475 |
/* タブをノートブックに登録する */ |
/* タブをノートブックに登録する */ |
| 476 |
gtk_notebook_append_page(Shiki_EDITOR_NOTEBOOK, GTK_WIDGET(tabinfo->tabpage), gtk_label_new(tabinfo->tabpage_label)); |
gtk_notebook_append_page(Shiki_EDITOR_NOTEBOOK, GTK_WIDGET(tabinfo->tabpage), gtk_label_new(tabinfo->tabpage_label)); |
| 790 |
gtk_window_set_title (GTK_WINDOW (Shiki_EDITOR_WINDOW), filename); |
gtk_window_set_title (GTK_WINDOW (Shiki_EDITOR_WINDOW), filename); |
| 791 |
gtk_widget_show_all(GTK_WIDGET(Shiki_EDITOR_NOTEBOOK)); |
gtk_widget_show_all(GTK_WIDGET(Shiki_EDITOR_NOTEBOOK)); |
| 792 |
g_free(contents); g_free(text); g_free(filename); |
g_free(contents); g_free(text); g_free(filename); |
| 793 |
|
|
| 794 |
|
/* キーワードを色分けする */ |
| 795 |
|
scheme_keyword_highlighting_current_buffer(); |
| 796 |
} else |
} else |
| 797 |
g_printerr("Get file contents error !\n"); |
g_printerr("Get file contents error !\n"); |
| 798 |
} |
} |
|
|
Legend:
| Removed from v.1.34 |
|
| changed lines |
| |
Added in v.1.35 |
|
|
| |