| 52 |
|
|
| 53 |
/* プロトタイプ */ |
/* プロトタイプ */ |
| 54 |
|
|
|
/* タブの生成と削除 : 基本的に,ShikiBuffer の中身に格納する情報を増やしたかったら,この 2 つの関数だけを変更すれば良い (ようにする…) */ |
|
|
extern void Scm_Init_xyzzylisp(ScmModule *module); |
|
|
|
|
| 55 |
/* foo_bar_handler() は,イベントハンドラのためのラッパー */ |
/* foo_bar_handler() は,イベントハンドラのためのラッパー */ |
| 56 |
static void kill_buffer_handler(); |
static void kill_buffer_handler(); |
| 57 |
static void append_default_tabpage_handler(); |
static void append_default_tabpage_handler(); |
| 68 |
static void clear_current_buffer_handler(); |
static void clear_current_buffer_handler(); |
| 69 |
static void undo(); |
static void undo(); |
| 70 |
static void search_current_buffer(); |
static void search_current_buffer(); |
|
static void insert_text_handler(GtkTextBuffer *buffer, GtkTextIter *p, gchar *str, gint len); |
|
|
static void delete_range_handler(GtkTextBuffer *buffer, GtkTextIter *start, GtkTextIter *end); |
|
|
|
|
|
/* モードライン */ |
|
|
static void update_modeline_label(); |
|
|
static void text_buffer_cursor_moved_handler(); |
|
|
|
|
|
/* 確認 */ |
|
|
static gboolean delete_event_handler(GtkWidget *widget, GdkEvent *event, GtkTextBuffer *buffer); |
|
| 71 |
|
|
| 72 |
/* Gauche と S 式操作やインデント・キーワードハイライティング関連 */ |
/* Gauche と S 式操作やインデント・キーワードハイライティング関連 */ |
| 73 |
static gchar *eval_cstring_by_gauche(gchar *s); |
static gchar *eval_cstring_by_gauche(gchar *s); |
| 117 |
*flag = !*flag; |
*flag = !*flag; |
| 118 |
} |
} |
| 119 |
|
|
| 120 |
|
/* バッファの状態に合わせてモードラインを変更 */ |
| 121 |
|
static void update_modeline_label() { |
| 122 |
|
static gchar label[1024]; |
| 123 |
|
GtkTextIter p; |
| 124 |
|
gtk_text_buffer_get_iter_at_mark(Shiki_CURRENT_TEXT_BUFFER, &p, gtk_text_buffer_get_insert(Shiki_CURRENT_TEXT_BUFFER)); |
| 125 |
|
|
| 126 |
|
g_snprintf(label, 1024, "--%s- %-10s (Gauche Interaction) [%s] L%d:%d ", |
| 127 |
|
gtk_text_buffer_get_modified(Shiki_CURRENT_TEXT_BUFFER) ? "**" : "--", |
| 128 |
|
Shiki_CURRENT_BASENAME, |
| 129 |
|
Shiki_CURRENT_CES, |
| 130 |
|
gtk_text_iter_get_line(&p) + 1, |
| 131 |
|
gtk_text_iter_get_line_offset (&p) + 1); |
| 132 |
|
gtk_label_set_text(GTK_LABEL(Shiki_EDITOR_MODELINE_LABEL), label); |
| 133 |
|
} |
| 134 |
|
|
| 135 |
static void replace_current_buffer() { |
static void replace_current_buffer() { |
| 136 |
GtkWidget *dialog = gtk_dialog_new_with_buttons ("文字列の置換", GTK_WINDOW(Shiki_EDITOR_WINDOW), GTK_DIALOG_DESTROY_WITH_PARENT, NULL); |
GtkWidget *dialog = gtk_dialog_new_with_buttons ("文字列の置換", GTK_WINDOW(Shiki_EDITOR_WINDOW), GTK_DIALOG_DESTROY_WITH_PARENT, NULL); |
| 137 |
GtkWidget *table = gtk_table_new(7, 3, FALSE); |
GtkWidget *table = gtk_table_new(7, 3, FALSE); |
| 295 |
} |
} |
| 296 |
} |
} |
| 297 |
|
|
|
/* バッファにテキストが挿入された */ |
|
|
static void insert_text_handler(GtkTextBuffer *buffer, GtkTextIter *iter, gchar *str, gint len) { |
|
|
/* Undo のための情報を記録 */ |
|
|
ShikiUndoInfo *undoInfo = g_malloc(sizeof(ShikiUndoInfo)); |
|
|
g_return_if_fail(undoInfo != NULL); |
|
|
undoInfo->action = SHIKI_UNDO_INSERT; |
|
|
undoInfo->str = g_strdup(str); |
|
|
undoInfo->strlen = len; |
|
|
undoInfo->start = gtk_text_iter_get_offset(iter); |
|
|
undoInfo->end = undoInfo->start + undoInfo->strlen; |
|
|
Shiki_CURRENT_UNDO_INFO_LIST = g_list_prepend(Shiki_CURRENT_UNDO_INFO_LIST, undoInfo); |
|
|
/* g_print("insert : %s, len : %d, start : %d, end : %d\n", undoInfo->str, undoInfo->strlen, undoInfo->start, undoInfo->end); */ |
|
|
} |
|
|
|
|
|
/* バッファからテキストが消去された */ |
|
|
static void delete_range_handler(GtkTextBuffer *buffer, GtkTextIter *start, GtkTextIter *end) { |
|
|
/* Undo のための情報を記録 */ |
|
|
ShikiUndoInfo *undoInfo = g_malloc(sizeof(ShikiUndoInfo)); |
|
|
g_return_if_fail(undoInfo != NULL); |
|
|
undoInfo->action = SHIKI_UNDO_DELETE; |
|
|
undoInfo->str = gtk_text_buffer_get_text(buffer, start, end, FALSE); |
|
|
undoInfo->start = gtk_text_iter_get_offset(start); |
|
|
undoInfo->end = gtk_text_iter_get_offset(end); |
|
|
undoInfo->strlen = end - start; |
|
|
Shiki_CURRENT_UNDO_INFO_LIST = g_list_prepend(Shiki_CURRENT_UNDO_INFO_LIST, undoInfo); |
|
|
/* g_print("delete : %s %d\n", undoInfo->str, undoInfo->strlen); */ |
|
|
} |
|
|
|
|
| 298 |
/* タブが切り替わる時のイベントハンドリング */ |
/* タブが切り替わる時のイベントハンドリング */ |
| 299 |
static void switch_tabpage_handler(GtkNotebook *notebook, GtkNotebookPage *page, guint pagenum) { |
static void switch_tabpage_handler(GtkNotebook *notebook, GtkNotebookPage *page, guint pagenum) { |
| 300 |
/* タブに対応する情報が格納された構造体を切替える */ |
/* タブに対応する情報が格納された構造体を切替える */ |
| 445 |
return FALSE; |
return FALSE; |
| 446 |
} |
} |
| 447 |
|
|
|
ScmClass *ShikiBufferClass; |
|
|
|
|
|
static gint compBuffer(gconstpointer a, gconstpointer b) { |
|
|
return ((ShikiBuffer *)a)->text_buffer == b ? 0 : 1; |
|
|
} |
|
|
|
|
|
static void buffer_print(ScmObj obj, ScmPort *out, ScmWriteContext *ctx) { |
|
|
GtkTextBuffer *b = SHIKI_BUFFER_UNBOX(obj); |
|
|
GList *l = g_list_find_custom(Shiki_EDITOR_BUFFER_LIST, b, compBuffer); |
|
|
if(l) |
|
|
Scm_Printf(out, "#<buffer: %s>", ((ShikiBuffer *)(l->data))->name); |
|
|
else |
|
|
Scm_Printf(out, "#<deleted buffer: %p>", b); |
|
|
} |
|
|
|
|
|
static void buffer_cleanup(ScmObj obj) |
|
|
{ |
|
|
g_object_unref(SHIKI_BUFFER_UNBOX(obj)); |
|
|
} |
|
|
|
|
|
/* ノートブックにタブとページ (バッファ) を追加 */ |
|
|
GtkTextBuffer *Shiki_new_buffer_create(gchar *filename) { |
|
|
/*-------------------- 新しいタブを作る ----------------------------------*/ |
|
|
/* ShikiBuffer には,タブに関連する情報が全て保持されている */ |
|
|
ShikiBuffer *tabinfo = g_malloc(sizeof(ShikiBuffer)); |
|
|
tabinfo->locale = "Gtk Default (utf8)"; |
|
|
tabinfo->undoInfoList = NULL; |
|
|
tabinfo->filename = filename; |
|
|
tabinfo->name = g_path_get_basename(filename); |
|
|
tabinfo->tabpage_label = g_strndup(tabinfo->name, 7); |
|
|
tabinfo->env = Scm_MakeModule(NULL, FALSE); |
|
|
|
|
|
ShikiBufferClass = Scm_MakeForeignPointerClass(SCM_MODULE(tabinfo->env), |
|
|
"<buffer>", buffer_print, buffer_cleanup, |
|
|
SCM_FOREIGN_POINTER_KEEP_IDENTITY |
|
|
| |
|
|
SCM_FOREIGN_POINTER_MAP_NULL); |
|
|
|
|
|
/* xyzzy lisp 関数を登録 */ |
|
|
Scm_Init_xyzzylisp(SCM_MODULE(tabinfo->env)); |
|
|
|
|
|
/* スクロールウィンドウ (タブの中身の大外) を作る */ |
|
|
tabinfo->tabpage = GTK_SCROLLED_WINDOW(gtk_scrolled_window_new(NULL, NULL)); |
|
|
gtk_scrolled_window_set_policy (tabinfo->tabpage, GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); |
|
|
|
|
|
/* 枠の中に格納するテキストビューワと,テキストバッファを作る */ |
|
|
tabinfo->text_view = GTK_TEXT_VIEW(gtk_text_view_new()); |
|
|
gtk_text_view_set_wrap_mode(tabinfo->text_view, GTK_WRAP_WORD); |
|
|
tabinfo->text_buffer = gtk_text_view_get_buffer(tabinfo->text_view); |
|
|
|
|
|
gtk_container_add(GTK_CONTAINER(tabinfo->tabpage), GTK_WIDGET(tabinfo->text_view)); |
|
|
gtk_widget_set_size_request(GTK_WIDGET(tabinfo->text_view), 680, 700); |
|
|
g_signal_connect(tabinfo->text_buffer, "mark_set", G_CALLBACK(text_buffer_cursor_moved_handler), tabinfo->text_view); |
|
|
g_signal_connect(tabinfo->text_buffer, "insert-text", G_CALLBACK(insert_text_handler), NULL); |
|
|
g_signal_connect(tabinfo->text_buffer, "delete-range", G_CALLBACK(delete_range_handler), NULL); |
|
|
|
|
|
/* タブを削除する際,デリートハンドラを削除しておかないと警告が出るから */ |
|
|
tabinfo->delete_handler_id = g_signal_connect(Shiki_EDITOR_WINDOW, "delete_event", G_CALLBACK(delete_event_handler), tabinfo->text_buffer); |
|
|
|
|
|
/* 様々な初期化処理 */ |
|
|
|
|
|
/* 括弧の強調表示のためのタグを作る */ |
|
|
gtk_text_buffer_create_tag(tabinfo->text_buffer, "parent_emphasis_background", "background", "green", NULL); |
|
|
|
|
|
/* キーワードハイライティング */ |
|
|
gtk_text_buffer_create_tag(tabinfo->text_buffer, "keyword_highlighting", "foreground", "blue", NULL); |
|
|
/* 関数 */ |
|
|
gtk_text_buffer_create_tag(tabinfo->text_buffer, "function_highlighting", "foreground", "red", NULL); |
|
|
/* コメント */ |
|
|
gtk_text_buffer_create_tag (tabinfo->text_buffer, "comment_highlighting", "foreground", "purple", NULL); |
|
|
/* 文字列 */ |
|
|
gtk_text_buffer_create_tag (tabinfo->text_buffer, "string_highlighting", "foreground", "orange", NULL); |
|
|
/* タブをノートブックに登録する */ |
|
|
gtk_notebook_append_page(Shiki_EDITOR_NOTEBOOK, GTK_WIDGET(tabinfo->tabpage), gtk_label_new(tabinfo->tabpage_label)); |
|
|
/* 対応するタブ情報を大域テーブルに保存しておく */ |
|
|
Shiki_EDITOR_BUFFER_LIST = g_list_append(Shiki_EDITOR_BUFFER_LIST, tabinfo); |
|
|
|
|
|
gtk_widget_show_all(GTK_WIDGET(Shiki_EDITOR_NOTEBOOK)); |
|
|
/* 開いたページに移動する */ |
|
|
gtk_notebook_set_current_page(Shiki_EDITOR_NOTEBOOK, g_list_length(Shiki_EDITOR_BUFFER_LIST) - 1); |
|
|
//Shiki_CURRENT_TAB_INFO = tabinfo; |
|
|
return tabinfo->text_buffer; |
|
|
} |
|
|
|
|
| 448 |
static void append_default_tabpage_handler() { |
static void append_default_tabpage_handler() { |
| 449 |
Shiki_new_buffer_create(g_strdup("*scratch*")); |
Shiki_new_buffer_create(g_strdup("*scratch*")); |
| 450 |
} |
} |
| 561 |
gtk_widget_destroy(dummy); |
gtk_widget_destroy(dummy); |
| 562 |
} |
} |
| 563 |
|
|
|
/* バッファの状態に合わせてモードラインを変更 */ |
|
|
static void update_modeline_label() { |
|
|
static gchar label[1024]; |
|
|
GtkTextIter p; |
|
|
gtk_text_buffer_get_iter_at_mark(Shiki_CURRENT_TEXT_BUFFER, &p, gtk_text_buffer_get_insert(Shiki_CURRENT_TEXT_BUFFER)); |
|
|
|
|
|
g_snprintf(label, 1024, "--%s- %-10s (Gauche Interaction) [%s] L%d:%d ", |
|
|
gtk_text_buffer_get_modified(Shiki_CURRENT_TEXT_BUFFER) ? "**" : "--", |
|
|
Shiki_CURRENT_BASENAME, |
|
|
Shiki_CURRENT_CES, |
|
|
gtk_text_iter_get_line(&p) + 1, |
|
|
gtk_text_iter_get_line_offset (&p) + 1); |
|
|
gtk_label_set_text(GTK_LABEL(Shiki_EDITOR_MODELINE_LABEL), label); |
|
|
} |
|
|
|
|
|
static void text_buffer_cursor_moved_handler(){ |
|
|
update_modeline_label(); |
|
|
} |
|
|
|
|
| 564 |
/* テキストバッファから全ての文字列を取り出す */ |
/* テキストバッファから全ての文字列を取り出す */ |
| 565 |
static gchar* get_all_buffer_contents(GtkTextBuffer *buffer) { |
static gchar* get_all_buffer_contents(GtkTextBuffer *buffer) { |
| 566 |
GtkTextIter start, end; |
GtkTextIter start, end; |
| 596 |
if(!gtk_text_buffer_get_modified(Shiki_CURRENT_TEXT_BUFFER)) return; |
if(!gtk_text_buffer_get_modified(Shiki_CURRENT_TEXT_BUFFER)) return; |
| 597 |
|
|
| 598 |
/* まだファイル名が設定されていなかったら,ダイアログを開いて入力させる */ |
/* まだファイル名が設定されていなかったら,ダイアログを開いて入力させる */ |
| 599 |
if(g_ascii_strcasecmp("*scratch*", Shiki_CURRENT_TAB_TITLE) == 0) { |
if(g_ascii_strcasecmp("*scratch*", Shiki_CURRENT_FILENAME) == 0) { |
| 600 |
const gchar *filename = Shiki_file_name_dialog("Save File As ..."); |
const gchar *filename = Shiki_file_name_dialog("Save File As ..."); |
| 601 |
if(!filename) return; |
if(!filename) return; |
| 602 |
if(!save_text_buffer(filename, Shiki_CURRENT_TEXT_BUFFER)) return; |
if(!save_text_buffer(filename, Shiki_CURRENT_TEXT_BUFFER)) return; |
| 617 |
gtk_window_set_title (GTK_WINDOW (Shiki_EDITOR_WINDOW), filename); |
gtk_window_set_title (GTK_WINDOW (Shiki_EDITOR_WINDOW), filename); |
| 618 |
} |
} |
| 619 |
|
|
|
/* バッファがまだ保存されていないのに本当に終了するのかを尋ねる */ |
|
|
static gboolean delete_event_handler(GtkWidget *widget, GdkEvent *event, GtkTextBuffer *buffer){ |
|
|
/* delete-event が発行された際,FALSE を返したらバッファは破棄される */ |
|
|
return Shiki_need_buffer_save_p(buffer) && !Shiki_yes_or_no_p("バッファは変更されています.変更内容を破棄しますか ?"); |
|
|
} |
|
|
|
|
| 620 |
/* ファイルを開く */ |
/* ファイルを開く */ |
| 621 |
static void open_file(const gchar *filename) { |
static void open_file(const gchar *filename) { |
| 622 |
gchar *text; |
gchar *text; |