| 31 |
|
|
| 32 |
static gint editor_indent_width = 2; |
static gint editor_indent_width = 2; |
| 33 |
|
|
| 34 |
|
/* Undo/Redo のための情報 */ |
| 35 |
|
typedef enum {SHIKI_UNDO_INSERT, SHIKI_UNDO_DELETE} ShikiAction; |
| 36 |
|
|
| 37 |
|
typedef struct { |
| 38 |
|
ShikiAction action; |
| 39 |
|
gchar *str; |
| 40 |
|
gint strlen; |
| 41 |
|
gint start; |
| 42 |
|
gint end; |
| 43 |
|
} ShikiUndoInfo; |
| 44 |
|
|
| 45 |
/* タブごとの情報を管理する構造体 */ |
/* タブごとの情報を管理する構造体 */ |
| 46 |
typedef struct { |
typedef struct { |
| 47 |
GtkScrolledWindow *tabpage; /* タブ */ |
GtkScrolledWindow *tabpage; /* タブ */ |
| 49 |
GtkTextView *text_view; /* タブの表示 */ |
GtkTextView *text_view; /* タブの表示 */ |
| 50 |
GtkTextBuffer *text_buffer; /* タブのテキストバッファ */ |
GtkTextBuffer *text_buffer; /* タブのテキストバッファ */ |
| 51 |
gchar *filename; /* ファイル名のフルパス */ |
gchar *filename; /* ファイル名のフルパス */ |
| 52 |
|
GList *undoInfoList; /* タブごとのバッファ変更履歴 */ |
| 53 |
ScmObj env; /* タブごとに独立した Scheme 環境 */ |
ScmObj env; /* タブごとに独立した Scheme 環境 */ |
| 54 |
guint delete_handler_id; /* トップレベルに登録したハンドラ ID */ |
guint delete_handler_id; /* トップレベルに登録したハンドラ ID */ |
| 55 |
} ShikiTabInfo; |
} ShikiTabInfo; |
| 67 |
} shiki_editor; |
} shiki_editor; |
| 68 |
|
|
| 69 |
/* シングルトンオブジェクトの定義 */ |
/* シングルトンオブジェクトの定義 */ |
| 70 |
#define Shiki_EDITOR_WINDOW shiki_editor.editor_window |
#define Shiki_EDITOR_WINDOW shiki_editor.editor_window |
| 71 |
#define Shiki_EDITOR_CLIPBOARD shiki_editor.clipboard |
#define Shiki_EDITOR_CLIPBOARD shiki_editor.clipboard |
| 72 |
#define Shiki_EDITOR_NOTEBOOK shiki_editor.notebook |
#define Shiki_EDITOR_NOTEBOOK shiki_editor.notebook |
| 73 |
#define Shiki_EDITOR_STATUSBAR shiki_editor.statusbar |
#define Shiki_EDITOR_STATUSBAR shiki_editor.statusbar |
| 74 |
#define Shiki_EDITOR_MODELINE_LABEL shiki_editor.modeline_label |
#define Shiki_EDITOR_MODELINE_LABEL shiki_editor.modeline_label |
| 75 |
#define Shiki_EDITOR_TAB_INFO_LIST shiki_editor.tabInfoList |
#define Shiki_EDITOR_TAB_INFO_LIST shiki_editor.tabInfoList |
| 76 |
|
|
| 77 |
/* 現在表示されているタブに対するアクセス用各種キャッシュ情報 */ |
/* 現在表示されているタブに対するアクセス用各種キャッシュ情報 */ |
| 78 |
#define Shiki_CURRENT_TAB_NUM shiki_editor.current_tabpage_num |
#define Shiki_CURRENT_TAB_NUM shiki_editor.current_tabpage_num |
| 79 |
#define Shiki_CURRENT_TAB_INFO shiki_editor.current_tabpage_info |
#define Shiki_CURRENT_TAB_INFO shiki_editor.current_tabpage_info |
| 80 |
#define Shiki_CURRENT_TAB (shiki_editor.current_tabpage_info)->tabpage |
#define Shiki_CURRENT_UNDO_INFO_LIST (shiki_editor.current_tabpage_info)->undoInfoList |
| 81 |
#define Shiki_CURRENT_TAB_TITLE (shiki_editor.current_tabpage_info)->tabpage_label |
#define Shiki_CURRENT_TAB (shiki_editor.current_tabpage_info)->tabpage |
| 82 |
#define Shiki_CURRENT_TEXT_VIEW (shiki_editor.current_tabpage_info)->text_view |
#define Shiki_CURRENT_TAB_TITLE (shiki_editor.current_tabpage_info)->tabpage_label |
| 83 |
#define Shiki_CURRENT_TEXT_BUFFER (shiki_editor.current_tabpage_info)->text_buffer |
#define Shiki_CURRENT_TEXT_VIEW (shiki_editor.current_tabpage_info)->text_view |
| 84 |
#define Shiki_CURRENT_FILENAME (shiki_editor.current_tabpage_info)->filename |
#define Shiki_CURRENT_TEXT_BUFFER (shiki_editor.current_tabpage_info)->text_buffer |
| 85 |
#define Shiki_CURRENT_SCHEME_ENV (shiki_editor.current_tabpage_info)->env |
#define Shiki_CURRENT_FILENAME (shiki_editor.current_tabpage_info)->filename |
| 86 |
|
#define Shiki_CURRENT_SCHEME_ENV (shiki_editor.current_tabpage_info)->env |
| 87 |
|
|
| 88 |
/* プロトタイプ */ |
/* プロトタイプ */ |
| 89 |
|
|
| 103 |
static gboolean save_text_buffer(const gchar *filename, GtkTextBuffer *buffer); |
static gboolean save_text_buffer(const gchar *filename, GtkTextBuffer *buffer); |
| 104 |
static void clear_current_buffer(); |
static void clear_current_buffer(); |
| 105 |
|
|
| 106 |
|
static void insert_text_handler(GtkTextBuffer *buffer, GtkTextIter *p, gchar *str, gint len); |
| 107 |
|
static void delete_range_handler(GtkTextBuffer *buffer, GtkTextIter *start, GtkTextIter *end); |
| 108 |
|
|
| 109 |
/* モードライン */ |
/* モードライン */ |
| 110 |
static gint get_current_line_number(GtkTextBuffer *buffer); |
static gint get_current_line_number(GtkTextBuffer *buffer); |
| 111 |
static void update_modeline_label(); |
static void update_modeline_label(); |
| 156 |
/* エディタの初期化 */ |
/* エディタの初期化 */ |
| 157 |
static void shiki_editor_window_init(int argc, char **argv); |
static void shiki_editor_window_init(int argc, char **argv); |
| 158 |
|
|
| 159 |
|
/* バッファにテキストが挿入された */ |
| 160 |
|
static void insert_text_handler(GtkTextBuffer *buffer, GtkTextIter *iter, gchar *str, gint len) { |
| 161 |
|
/* Undo のための情報を記録 */ |
| 162 |
|
ShikiUndoInfo *undoInfo = g_malloc(sizeof(ShikiUndoInfo)); |
| 163 |
|
g_return_if_fail(undoInfo != NULL); |
| 164 |
|
undoInfo->action = SHIKI_UNDO_INSERT; |
| 165 |
|
undoInfo->str = g_strdup(str); |
| 166 |
|
undoInfo->strlen = len; |
| 167 |
|
undoInfo->start = gtk_text_iter_get_offset(iter); |
| 168 |
|
undoInfo->end = undoInfo->start + undoInfo->strlen; |
| 169 |
|
Shiki_CURRENT_UNDO_INFO_LIST = g_list_prepend(Shiki_CURRENT_UNDO_INFO_LIST, undoInfo); |
| 170 |
|
g_print("insert : %s, len : %d, start : %d, end : %d\n", undoInfo->str, undoInfo->strlen, undoInfo->start, undoInfo->end); |
| 171 |
|
} |
| 172 |
|
|
| 173 |
|
/* バッファからテキストが消去された */ |
| 174 |
|
static void delete_range_handler(GtkTextBuffer *buffer, GtkTextIter *start, GtkTextIter *end) { |
| 175 |
|
/* Undo のための情報を記録 */ |
| 176 |
|
ShikiUndoInfo *undoInfo = g_malloc(sizeof(ShikiUndoInfo)); |
| 177 |
|
g_return_if_fail(undoInfo != NULL); |
| 178 |
|
undoInfo->action = SHIKI_UNDO_DELETE; |
| 179 |
|
undoInfo->str = gtk_text_buffer_get_text(buffer, start, end, FALSE); |
| 180 |
|
undoInfo->start = gtk_text_iter_get_offset(start); |
| 181 |
|
undoInfo->end = gtk_text_iter_get_offset(end); |
| 182 |
|
undoInfo->strlen = end - start; |
| 183 |
|
Shiki_CURRENT_UNDO_INFO_LIST = g_list_prepend(Shiki_CURRENT_UNDO_INFO_LIST, undoInfo); |
| 184 |
|
g_print("delete : %s %d\n", undoInfo->str, undoInfo->strlen); |
| 185 |
|
} |
| 186 |
|
|
| 187 |
|
/* タブが切り替わる時のイベントハンドリング */ |
| 188 |
|
static void switch_tabpage_handler(GtkNotebook *notebook, GtkNotebookPage *page, guint pagenum) { |
| 189 |
|
/* タブに対応する情報が格納された構造体を切替える */ |
| 190 |
|
Shiki_CURRENT_TAB_INFO = (ShikiTabInfo *)g_list_nth_data(Shiki_EDITOR_TAB_INFO_LIST, pagenum); |
| 191 |
|
|
| 192 |
|
/* 現在のタブ番号を切替える */ |
| 193 |
|
Shiki_CURRENT_TAB_NUM = pagenum; |
| 194 |
|
|
| 195 |
|
/* タブのラベルをウィンドウのタイトルに */ |
| 196 |
|
if(!Shiki_CURRENT_TAB_INFO) return; |
| 197 |
|
gtk_window_set_title (GTK_WINDOW(Shiki_EDITOR_WINDOW), Shiki_CURRENT_FILENAME); |
| 198 |
|
|
| 199 |
|
update_modeline_label(); |
| 200 |
|
} |
| 201 |
|
|
| 202 |
|
/* キーが押された */ |
| 203 |
|
static gboolean signal_key_press_handler (GtkWidget *notebook, GdkEventKey *event, gpointer contextid) { |
| 204 |
|
GtkTextIter start, end; |
| 205 |
|
|
| 206 |
|
/* 括弧の対応の強調を無効に */ |
| 207 |
|
gtk_text_buffer_get_start_iter(Shiki_CURRENT_TEXT_BUFFER, &start); |
| 208 |
|
gtk_text_buffer_get_end_iter(Shiki_CURRENT_TEXT_BUFFER, &end); |
| 209 |
|
gtk_text_buffer_remove_tag_by_name(Shiki_CURRENT_TEXT_BUFFER, "parent_emphasis_background", &start, &end); |
| 210 |
|
|
| 211 |
|
if(event->state & GDK_CONTROL_MASK && event->state & GDK_MOD1_MASK) { |
| 212 |
|
switch(event->keyval) { |
| 213 |
|
case GDK_at : /* C-M-SPC */ |
| 214 |
|
{ GtkTextIter start, end; |
| 215 |
|
if(!search_sexp(&start, &end)) return FALSE; |
| 216 |
|
gtk_text_buffer_select_range(Shiki_CURRENT_TEXT_BUFFER, &start, &end); |
| 217 |
|
} |
| 218 |
|
break; |
| 219 |
|
case GDK_space : /* C-M-SPC */ |
| 220 |
|
{ GtkTextIter start, end; |
| 221 |
|
if(!search_last_sexp(&start, &end)) return FALSE; |
| 222 |
|
gtk_text_buffer_select_range(Shiki_CURRENT_TEXT_BUFFER, &start, &end); |
| 223 |
|
} |
| 224 |
|
break; |
| 225 |
|
} |
| 226 |
|
} else if(event->state & GDK_CONTROL_MASK) { |
| 227 |
|
switch(event->keyval) { |
| 228 |
|
case GDK_f : /* Ctrl + f : forward */ |
| 229 |
|
forward_current_buffer(); |
| 230 |
|
break; |
| 231 |
|
case GDK_b : /* Ctrl + b : backward */ |
| 232 |
|
backward_current_buffer(); |
| 233 |
|
break; |
| 234 |
|
case GDK_n : /* Ctrl + n : next line */ |
| 235 |
|
line_forward_current_buffer(); |
| 236 |
|
break; |
| 237 |
|
case GDK_p : /* Ctrl + p : previous line */ |
| 238 |
|
line_backward_current_buffer(); |
| 239 |
|
break; |
| 240 |
|
case GDK_h : |
| 241 |
|
{ GtkTextIter p; |
| 242 |
|
gtk_text_buffer_get_iter_at_mark(Shiki_CURRENT_TEXT_BUFFER,&p, gtk_text_buffer_get_insert(Shiki_CURRENT_TEXT_BUFFER)); |
| 243 |
|
gtk_text_buffer_backspace(Shiki_CURRENT_TEXT_BUFFER, &p, FALSE, TRUE); |
| 244 |
|
} |
| 245 |
|
break; |
| 246 |
|
|
| 247 |
|
case GDK_e : /* Ctrl + e : eval-expression */ |
| 248 |
|
{ |
| 249 |
|
gchar *code; |
| 250 |
|
GtkTextIter start, end; |
| 251 |
|
|
| 252 |
|
if(!search_sexp(&start, &end)) return FALSE; |
| 253 |
|
|
| 254 |
|
code = gtk_text_buffer_get_text(Shiki_CURRENT_TEXT_BUFFER, &start, &end, FALSE); |
| 255 |
|
gtk_text_buffer_insert(Shiki_CURRENT_TEXT_BUFFER, &end, "\n\n", -1); |
| 256 |
|
gtk_text_buffer_insert(Shiki_CURRENT_TEXT_BUFFER, &end, eval_cstring_by_gauche(code), -1); |
| 257 |
|
g_free(code); |
| 258 |
|
} |
| 259 |
|
break; |
| 260 |
|
|
| 261 |
|
case GDK_j : /* Ctrl + j : eval-last-sexp */ |
| 262 |
|
{ |
| 263 |
|
gchar *code; |
| 264 |
|
GtkTextIter start, end; |
| 265 |
|
|
| 266 |
|
if(!search_last_sexp(&start, &end)) return FALSE; |
| 267 |
|
|
| 268 |
|
code = gtk_text_buffer_get_text(Shiki_CURRENT_TEXT_BUFFER, &start, &end, FALSE); |
| 269 |
|
gtk_text_buffer_insert(Shiki_CURRENT_TEXT_BUFFER, &end, "\n\n", -1); |
| 270 |
|
gtk_text_buffer_insert(Shiki_CURRENT_TEXT_BUFFER, &end, eval_cstring_by_gauche(code), -1); |
| 271 |
|
g_free(code); |
| 272 |
|
} |
| 273 |
|
break; |
| 274 |
|
|
| 275 |
|
case GDK_underscore : /* Ctrl + _ : Undo */ |
| 276 |
|
{ |
| 277 |
|
g_print("undo\n"); |
| 278 |
|
GtkTextIter start, end; |
| 279 |
|
ShikiUndoInfo *undoInfo = g_list_nth_data(Shiki_CURRENT_UNDO_INFO_LIST, 0); |
| 280 |
|
if(!undoInfo) { |
| 281 |
|
g_print("これ以上 Undo できません\n"); |
| 282 |
|
return FALSE; |
| 283 |
|
} |
| 284 |
|
gtk_text_buffer_get_iter_at_offset(Shiki_CURRENT_TEXT_BUFFER, &start, undoInfo->start); |
| 285 |
|
gtk_text_buffer_get_iter_at_offset(Shiki_CURRENT_TEXT_BUFFER, &end, undoInfo->end); |
| 286 |
|
|
| 287 |
|
if(undoInfo->action == SHIKI_UNDO_INSERT) { |
| 288 |
|
Shiki_CURRENT_UNDO_INFO_LIST = g_list_delete_link(Shiki_CURRENT_UNDO_INFO_LIST, g_list_first(Shiki_CURRENT_UNDO_INFO_LIST)); |
| 289 |
|
gtk_text_buffer_delete(Shiki_CURRENT_TEXT_BUFFER, &start, &end); |
| 290 |
|
g_free(undoInfo->str); |
| 291 |
|
g_free(undoInfo); |
| 292 |
|
} else if(undoInfo->action == SHIKI_UNDO_DELETE) { |
| 293 |
|
Shiki_CURRENT_UNDO_INFO_LIST = g_list_delete_link(Shiki_CURRENT_UNDO_INFO_LIST, g_list_first(Shiki_CURRENT_UNDO_INFO_LIST)); |
| 294 |
|
gtk_text_buffer_insert(Shiki_CURRENT_TEXT_BUFFER, &start, undoInfo->str, -1); |
| 295 |
|
g_free(undoInfo->str); |
| 296 |
|
g_free(undoInfo); |
| 297 |
|
} |
| 298 |
|
} |
| 299 |
|
break; |
| 300 |
|
|
| 301 |
|
case GDK_t : /* Ctrl + t : タブを開く */ |
| 302 |
|
append_tabpage(g_strdup("*scratch*")); |
| 303 |
|
break; |
| 304 |
|
|
| 305 |
|
case GDK_k : /* Ctrl + k : タブを閉じる */ |
| 306 |
|
remove_tabpage(); |
| 307 |
|
break; |
| 308 |
|
|
| 309 |
|
case GDK_w : /* Ctrl + w : カット */ |
| 310 |
|
gtk_text_buffer_cut_clipboard(Shiki_CURRENT_TEXT_BUFFER, Shiki_EDITOR_CLIPBOARD, TRUE); |
| 311 |
|
break; |
| 312 |
|
|
| 313 |
|
case GDK_y : /* Ctrl + y : ヤンク */ |
| 314 |
|
{GtkTextIter p; |
| 315 |
|
gtk_text_buffer_get_iter_at_mark(Shiki_CURRENT_TEXT_BUFFER,&p, gtk_text_buffer_get_insert(Shiki_CURRENT_TEXT_BUFFER)); |
| 316 |
|
gtk_text_buffer_paste_clipboard(Shiki_CURRENT_TEXT_BUFFER, Shiki_EDITOR_CLIPBOARD, &p, TRUE); |
| 317 |
|
} |
| 318 |
|
break; |
| 319 |
|
} |
| 320 |
|
} |
| 321 |
|
return FALSE; |
| 322 |
|
} |
| 323 |
|
|
| 324 |
|
|
| 325 |
/* ノートブックにタブとページ (バッファ) を追加 */ |
/* ノートブックにタブとページ (バッファ) を追加 */ |
| 326 |
static void append_tabpage(gchar *filename) { |
static void append_tabpage(gchar *filename) { |
| 327 |
/*-------------------- 新しいタブを作る ----------------------------------*/ |
/*-------------------- 新しいタブを作る ----------------------------------*/ |
| 328 |
/* ShikiTabInfo には,タブに関連する情報が全て保持されている */ |
/* ShikiTabInfo には,タブに関連する情報が全て保持されている */ |
| 329 |
ShikiTabInfo *tabinfo = g_malloc(sizeof(ShikiTabInfo)); |
ShikiTabInfo *tabinfo = g_malloc(sizeof(ShikiTabInfo)); |
| 330 |
|
tabinfo->undoInfoList = NULL; |
| 331 |
tabinfo->filename = filename; |
tabinfo->filename = filename; |
| 332 |
tabinfo->tabpage_label = g_path_get_basename(filename); |
tabinfo->tabpage_label = g_path_get_basename(filename); |
| 333 |
|
|
| 342 |
gtk_container_add(GTK_CONTAINER(tabinfo->tabpage), GTK_WIDGET(tabinfo->text_view)); |
gtk_container_add(GTK_CONTAINER(tabinfo->tabpage), GTK_WIDGET(tabinfo->text_view)); |
| 343 |
gtk_widget_set_size_request(GTK_WIDGET(tabinfo->text_view), 500, 500); |
gtk_widget_set_size_request(GTK_WIDGET(tabinfo->text_view), 500, 500); |
| 344 |
g_signal_connect(tabinfo->text_buffer, "mark_set", G_CALLBACK(text_buffer_cursor_moved_handler), tabinfo->text_view); |
g_signal_connect(tabinfo->text_buffer, "mark_set", G_CALLBACK(text_buffer_cursor_moved_handler), tabinfo->text_view); |
| 345 |
|
g_signal_connect(tabinfo->text_buffer, "insert-text", G_CALLBACK(insert_text_handler), NULL); |
| 346 |
|
g_signal_connect(tabinfo->text_buffer, "delete-range", G_CALLBACK(delete_range_handler), NULL); |
| 347 |
|
|
| 348 |
/* タブを削除する際,デリートハンドラを削除しておかないと警告が出るから */ |
/* タブを削除する際,デリートハンドラを削除しておかないと警告が出るから */ |
| 349 |
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); |
| 350 |
|
|
| 356 |
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)); |
| 357 |
/* 対応するタブ情報を大域テーブルに保存しておく */ |
/* 対応するタブ情報を大域テーブルに保存しておく */ |
| 358 |
Shiki_EDITOR_TAB_INFO_LIST = g_list_append(Shiki_EDITOR_TAB_INFO_LIST, tabinfo); |
Shiki_EDITOR_TAB_INFO_LIST = g_list_append(Shiki_EDITOR_TAB_INFO_LIST, tabinfo); |
| 359 |
|
|
| 360 |
gtk_widget_show_all(GTK_WIDGET(Shiki_EDITOR_NOTEBOOK)); |
gtk_widget_show_all(GTK_WIDGET(Shiki_EDITOR_NOTEBOOK)); |
| 361 |
/* 開いたページに移動する */ |
/* 開いたページに移動する */ |
| 362 |
gtk_notebook_set_current_page(Shiki_EDITOR_NOTEBOOK, g_list_length(Shiki_EDITOR_TAB_INFO_LIST) - 1); |
gtk_notebook_set_current_page(Shiki_EDITOR_NOTEBOOK, g_list_length(Shiki_EDITOR_TAB_INFO_LIST) - 1); |
| 829 |
} |
} |
| 830 |
} |
} |
| 831 |
|
|
|
/* タブが切り替わる時のイベントハンドリング */ |
|
|
static void switch_tabpage_handler(GtkNotebook *notebook, GtkNotebookPage *page, guint pagenum) { |
|
|
/* タブに対応する情報が格納された構造体を切替える */ |
|
|
Shiki_CURRENT_TAB_INFO = (ShikiTabInfo *)g_list_nth_data(Shiki_EDITOR_TAB_INFO_LIST, pagenum); |
|
|
/* 現在のタブ番号を切替える */ |
|
|
Shiki_CURRENT_TAB_NUM = pagenum; |
|
|
|
|
|
/* タブのラベルをウィンドウのタイトルに */ |
|
|
if(!Shiki_CURRENT_TAB_INFO) return; |
|
|
gtk_window_set_title (GTK_WINDOW(Shiki_EDITOR_WINDOW), Shiki_CURRENT_FILENAME); |
|
|
|
|
|
update_modeline_label(); |
|
|
} |
|
|
|
|
| 832 |
/* ページのタブと境界線を on/off */ |
/* ページのタブと境界線を on/off */ |
| 833 |
static void tabsborder_on_off(GtkButton *button, GtkNotebook *notebook) { |
static void tabsborder_on_off(GtkButton *button, GtkNotebook *notebook) { |
| 834 |
gint tval = FALSE; |
gint tval = FALSE; |
| 875 |
gtk_text_buffer_place_cursor(Shiki_CURRENT_TEXT_BUFFER, &p); |
gtk_text_buffer_place_cursor(Shiki_CURRENT_TEXT_BUFFER, &p); |
| 876 |
} |
} |
| 877 |
|
|
|
/* キーが押された */ |
|
|
static gboolean signal_key_press_handler (GtkWidget *notebook, GdkEventKey *event, gpointer contextid) { |
|
|
GtkTextIter start, end; |
|
|
|
|
|
/* 括弧の対応の強調を無効に */ |
|
|
gtk_text_buffer_get_start_iter(Shiki_CURRENT_TEXT_BUFFER, &start); |
|
|
gtk_text_buffer_get_end_iter(Shiki_CURRENT_TEXT_BUFFER, &end); |
|
|
gtk_text_buffer_remove_tag_by_name(Shiki_CURRENT_TEXT_BUFFER, "parent_emphasis_background", &start, &end); |
|
|
|
|
|
if(event->state & GDK_CONTROL_MASK && event->state & GDK_MOD1_MASK) { |
|
|
switch(event->keyval) { |
|
|
case GDK_at : /* C-M-SPC */ |
|
|
{ GtkTextIter start, end; |
|
|
if(!search_sexp(&start, &end)) return FALSE; |
|
|
gtk_text_buffer_select_range(Shiki_CURRENT_TEXT_BUFFER, &start, &end); |
|
|
} |
|
|
break; |
|
|
case GDK_space : /* C-M-SPC */ |
|
|
{ GtkTextIter start, end; |
|
|
if(!search_last_sexp(&start, &end)) return FALSE; |
|
|
gtk_text_buffer_select_range(Shiki_CURRENT_TEXT_BUFFER, &start, &end); |
|
|
} |
|
|
break; |
|
|
} |
|
|
} else if(event->state & GDK_CONTROL_MASK) { |
|
|
switch(event->keyval) { |
|
|
case GDK_f : /* Ctrl + f : forward */ |
|
|
forward_current_buffer(); |
|
|
break; |
|
|
case GDK_b : /* Ctrl + b : backward */ |
|
|
backward_current_buffer(); |
|
|
break; |
|
|
case GDK_n : /* Ctrl + n : next line */ |
|
|
line_forward_current_buffer(); |
|
|
break; |
|
|
case GDK_p : /* Ctrl + p : previous line */ |
|
|
line_backward_current_buffer(); |
|
|
break; |
|
|
case GDK_h : |
|
|
{ GtkTextIter p; |
|
|
gtk_text_buffer_get_iter_at_mark(Shiki_CURRENT_TEXT_BUFFER,&p, gtk_text_buffer_get_insert(Shiki_CURRENT_TEXT_BUFFER)); |
|
|
gtk_text_buffer_backspace(Shiki_CURRENT_TEXT_BUFFER, &p, FALSE, TRUE); |
|
|
} |
|
|
break; |
|
|
|
|
|
case GDK_e : /* Ctrl + e : eval-expression */ |
|
|
{ |
|
|
gchar *code; |
|
|
GtkTextIter start, end; |
|
|
|
|
|
if(!search_sexp(&start, &end)) return FALSE; |
|
|
|
|
|
code = gtk_text_buffer_get_text(Shiki_CURRENT_TEXT_BUFFER, &start, &end, FALSE); |
|
|
gtk_text_buffer_insert(Shiki_CURRENT_TEXT_BUFFER, &end, "\n\n", -1); |
|
|
gtk_text_buffer_insert(Shiki_CURRENT_TEXT_BUFFER, &end, eval_cstring_by_gauche(code), -1); |
|
|
g_free(code); |
|
|
} |
|
|
break; |
|
|
|
|
|
case GDK_j : /* Ctrl + j : eval-last-sexp */ |
|
|
{ |
|
|
gchar *code; |
|
|
GtkTextIter start, end; |
|
|
|
|
|
if(!search_last_sexp(&start, &end)) return FALSE; |
|
|
|
|
|
code = gtk_text_buffer_get_text(Shiki_CURRENT_TEXT_BUFFER, &start, &end, FALSE); |
|
|
gtk_text_buffer_insert(Shiki_CURRENT_TEXT_BUFFER, &end, "\n\n", -1); |
|
|
gtk_text_buffer_insert(Shiki_CURRENT_TEXT_BUFFER, &end, eval_cstring_by_gauche(code), -1); |
|
|
g_free(code); |
|
|
} |
|
|
break; |
|
|
|
|
|
case GDK_t : /* Ctrl + t : タブを開く */ |
|
|
append_tabpage(g_strdup("*scratch*")); |
|
|
break; |
|
|
|
|
|
case GDK_k : /* Ctrl + k : タブを閉じる */ |
|
|
remove_tabpage(); |
|
|
break; |
|
|
|
|
|
case GDK_w : /* Ctrl + w : カット */ |
|
|
gtk_text_buffer_cut_clipboard(Shiki_CURRENT_TEXT_BUFFER, Shiki_EDITOR_CLIPBOARD, TRUE); |
|
|
break; |
|
|
|
|
|
case GDK_y : /* Ctrl + y : ヤンク */ |
|
|
{GtkTextIter p; |
|
|
gtk_text_buffer_get_iter_at_mark(Shiki_CURRENT_TEXT_BUFFER,&p, gtk_text_buffer_get_insert(Shiki_CURRENT_TEXT_BUFFER)); |
|
|
gtk_text_buffer_paste_clipboard(Shiki_CURRENT_TEXT_BUFFER, Shiki_EDITOR_CLIPBOARD, &p, TRUE); |
|
|
} |
|
|
break; |
|
|
} |
|
|
} |
|
|
return FALSE; |
|
|
} |
|
|
|
|
| 878 |
/* キーが離された */ |
/* キーが離された */ |
| 879 |
static gboolean signal_key_release_handler (GtkWidget *notebook, GdkEventKey *event, gpointer contextid) { |
static gboolean signal_key_release_handler (GtkWidget *notebook, GdkEventKey *event, gpointer contextid) { |
| 880 |
static gint metakey_pressed = 0; |
static gint metakey_pressed = 0; |