| 108 |
static gboolean is_kakko_or_kokka(gunichar ch, gpointer); |
static gboolean is_kakko_or_kokka(gunichar ch, gpointer); |
| 109 |
static gboolean is_kakko(gunichar ch, gpointer); |
static gboolean is_kakko(gunichar ch, gpointer); |
| 110 |
static gboolean is_kokka(gunichar ch, gpointer); |
static gboolean is_kokka(gunichar ch, gpointer); |
| 111 |
static gboolean search_sexp_kokka(GtkTextIter *start); |
static gboolean search_sexp(GtkTextIter *start, GtkTextIter *end); |
| 112 |
|
static gboolean search_sexp_kokka(GtkTextIter *end); |
| 113 |
|
static gboolean search_last_sexp(GtkTextIter *start, GtkTextIter *end); |
| 114 |
static gboolean search_last_sexp_kakko(GtkTextIter *start); |
static gboolean search_last_sexp_kakko(GtkTextIter *start); |
| 115 |
static gint get_parent_nest_level_at_cursor(GtkTextBuffer *buffer); |
static gint get_parent_nest_level_at_cursor(GtkTextBuffer *buffer); |
| 116 |
|
|
| 543 |
static gboolean is_kakko(gunichar ch, gpointer p) {return ch == '(';} |
static gboolean is_kakko(gunichar ch, gpointer p) {return ch == '(';} |
| 544 |
static gboolean is_kokka(gunichar ch, gpointer p) {return ch == ')';} |
static gboolean is_kokka(gunichar ch, gpointer p) {return ch == ')';} |
| 545 |
|
|
| 546 |
/* '(' に対応する ')' までの文字列 (S 式) を切り出す */ |
/* カーソル以降の '(' に対応する ')' までの文字列 (S 式) を切り出す */ |
| 547 |
static gboolean search_sexp_kokka(GtkTextIter *start) { |
static gboolean search_sexp(GtkTextIter *start, GtkTextIter *end) { |
| 548 |
|
|
| 549 |
|
/* カーソルの位置を取得 */ |
| 550 |
|
gtk_text_buffer_get_iter_at_mark(Shiki_CURRENT_TEXT_BUFFER, start, gtk_text_buffer_get_insert(Shiki_CURRENT_TEXT_BUFFER)); |
| 551 |
|
|
| 552 |
|
if(gtk_text_iter_get_char(start) != '(') |
| 553 |
|
gtk_text_iter_forward_find_char(start, is_kakko, NULL, NULL); |
| 554 |
|
|
| 555 |
|
*end = *start; |
| 556 |
|
|
| 557 |
|
/* カーソル位置の前にある S 式を切り出す */ |
| 558 |
|
if(!search_sexp_kokka(end)) return FALSE; |
| 559 |
|
gtk_text_iter_forward_char(end); |
| 560 |
|
return TRUE; |
| 561 |
|
} |
| 562 |
|
|
| 563 |
|
static gboolean search_sexp_kokka(GtkTextIter *end) { |
| 564 |
gint nest_level = 0; |
gint nest_level = 0; |
| 565 |
/* カーソル位置の後にある S 式を切り出す */ |
|
| 566 |
|
/* 対応する ')' を探す */ |
| 567 |
while(1) { |
while(1) { |
| 568 |
if(!gtk_text_iter_forward_find_char(start, is_kakko_or_kokka, NULL, NULL)) |
if(!gtk_text_iter_forward_find_char(end, is_kakko_or_kokka, NULL, NULL)) |
| 569 |
return FALSE; |
return FALSE; |
| 570 |
|
|
| 571 |
if(gtk_text_iter_get_char(start) == '(') |
if(gtk_text_iter_get_char(end) == '(') |
| 572 |
nest_level++; |
nest_level++; |
| 573 |
else { |
else { |
| 574 |
if(!nest_level) |
if(!nest_level) |
| 580 |
return TRUE; |
return TRUE; |
| 581 |
} |
} |
| 582 |
|
|
| 583 |
|
/* カーソル以前の ')' に対応する '(' までの文字列 (S 式) を切り出す */ |
| 584 |
|
static gboolean search_last_sexp(GtkTextIter *start, GtkTextIter *end) { |
| 585 |
|
|
| 586 |
|
/* カーソルの位置を取得 */ |
| 587 |
|
gtk_text_buffer_get_iter_at_mark(Shiki_CURRENT_TEXT_BUFFER, end, gtk_text_buffer_get_insert(Shiki_CURRENT_TEXT_BUFFER)); |
| 588 |
|
|
| 589 |
|
gtk_text_iter_backward_char(end); |
| 590 |
|
|
| 591 |
|
if(gtk_text_iter_get_char(end) != ')') |
| 592 |
|
gtk_text_iter_backward_find_char(end, is_kokka, NULL, NULL); |
| 593 |
|
*start = *end; |
| 594 |
|
gtk_text_iter_forward_char(end); |
| 595 |
|
|
| 596 |
|
/* カーソル位置の前にある S 式を切り出す */ |
| 597 |
|
if(!search_last_sexp_kakko(start)) return FALSE; |
| 598 |
|
|
| 599 |
|
return TRUE; |
| 600 |
|
} |
| 601 |
|
|
| 602 |
/* ')' に対応する '(' までの文字列 (S 式) を切り出す */ |
/* ')' に対応する '(' までの文字列 (S 式) を切り出す */ |
| 603 |
static gboolean search_last_sexp_kakko(GtkTextIter *start) { |
static gboolean search_last_sexp_kakko(GtkTextIter *start) { |
| 604 |
gint nest_level = 0; |
gint nest_level = 0; |
| 605 |
/* カーソル位置の前にある S 式を切り出す */ |
/* ネストレベルを計算しながら ')' を探す */ |
| 606 |
while(1) { |
while(1) { |
| 607 |
if(!gtk_text_iter_backward_find_char(start, is_kakko_or_kokka, NULL, NULL)) |
if(!gtk_text_iter_backward_find_char(start, is_kakko_or_kokka, NULL, NULL)) |
| 608 |
return FALSE; |
return FALSE; |
| 709 |
gtk_text_buffer_get_start_iter(Shiki_CURRENT_TEXT_BUFFER, &start); |
gtk_text_buffer_get_start_iter(Shiki_CURRENT_TEXT_BUFFER, &start); |
| 710 |
gtk_text_buffer_get_end_iter(Shiki_CURRENT_TEXT_BUFFER, &end); |
gtk_text_buffer_get_end_iter(Shiki_CURRENT_TEXT_BUFFER, &end); |
| 711 |
gtk_text_buffer_remove_tag_by_name(Shiki_CURRENT_TEXT_BUFFER, "parent_emphasis_background", &start, &end); |
gtk_text_buffer_remove_tag_by_name(Shiki_CURRENT_TEXT_BUFFER, "parent_emphasis_background", &start, &end); |
| 712 |
|
if(event->state & GDK_CONTROL_MASK && event->state & GDK_MOD1_MASK) { |
| 713 |
|
switch(event->keyval) { |
| 714 |
|
case GDK_at : /* C-M-SPC */ |
| 715 |
|
{ GtkTextIter start, end; |
| 716 |
|
if(!search_sexp(&start, &end)) return FALSE; |
| 717 |
|
gtk_text_buffer_select_range(Shiki_CURRENT_TEXT_BUFFER, &start, &end); |
| 718 |
|
} |
| 719 |
|
break; |
| 720 |
|
case GDK_space : /* C-M-SPC */ |
| 721 |
|
{ GtkTextIter start, end; |
| 722 |
|
if(!search_last_sexp(&start, &end)) return FALSE; |
| 723 |
|
gtk_text_buffer_select_range(Shiki_CURRENT_TEXT_BUFFER, &start, &end); |
| 724 |
|
} |
| 725 |
|
break; |
| 726 |
|
} |
| 727 |
|
} |
| 728 |
if(event->state & GDK_CONTROL_MASK) { |
if(event->state & GDK_CONTROL_MASK) { |
| 729 |
switch(event->keyval) { |
switch(event->keyval) { |
| 730 |
case GDK_f : /* Ctrl + f : forward */ |
case GDK_f : /* Ctrl + f : forward */ |
| 751 |
gchar *code; |
gchar *code; |
| 752 |
GtkTextIter start, end; |
GtkTextIter start, end; |
| 753 |
|
|
| 754 |
/* カーソルの位置を取得 */ |
if(!search_sexp(&start, &end)) return FALSE; |
|
gtk_text_buffer_get_iter_at_mark(Shiki_CURRENT_TEXT_BUFFER, &start, gtk_text_buffer_get_insert(Shiki_CURRENT_TEXT_BUFFER)); |
|
|
|
|
|
if(gtk_text_iter_get_char(&start) != '(') |
|
|
gtk_text_iter_forward_find_char(&start, is_kakko, NULL, NULL); |
|
|
|
|
|
end = start; |
|
|
|
|
|
/* カーソル位置の前にある S 式を切り出す */ |
|
|
if(!search_sexp_kokka(&end)) return FALSE; |
|
|
gtk_text_iter_forward_char(&end); |
|
| 755 |
|
|
| 756 |
code = gtk_text_buffer_get_text(Shiki_CURRENT_TEXT_BUFFER, &start, &end, FALSE); |
code = gtk_text_buffer_get_text(Shiki_CURRENT_TEXT_BUFFER, &start, &end, FALSE); |
| 757 |
gtk_text_buffer_insert(Shiki_CURRENT_TEXT_BUFFER, &end, "\n\n", -1); |
gtk_text_buffer_insert(Shiki_CURRENT_TEXT_BUFFER, &end, "\n\n", -1); |
| 765 |
gchar *code; |
gchar *code; |
| 766 |
GtkTextIter start, end; |
GtkTextIter start, end; |
| 767 |
|
|
| 768 |
/* カーソルの位置を取得 */ |
if(!search_last_sexp(&start, &end)) return FALSE; |
|
gtk_text_buffer_get_iter_at_mark(Shiki_CURRENT_TEXT_BUFFER, &end, gtk_text_buffer_get_insert(Shiki_CURRENT_TEXT_BUFFER)); |
|
|
|
|
|
if(gtk_text_iter_get_char(&end) != ')') |
|
|
gtk_text_iter_backward_find_char(&end, is_kokka, NULL, NULL); |
|
|
start = end; |
|
|
gtk_text_iter_forward_char(&end); |
|
|
|
|
|
/* カーソル位置の前にある S 式を切り出す */ |
|
|
if(!search_last_sexp_kakko(&start)) return FALSE; |
|
| 769 |
|
|
| 770 |
code = gtk_text_buffer_get_text(Shiki_CURRENT_TEXT_BUFFER, &start, &end, FALSE); |
code = gtk_text_buffer_get_text(Shiki_CURRENT_TEXT_BUFFER, &start, &end, FALSE); |
| 771 |
gtk_text_buffer_insert(Shiki_CURRENT_TEXT_BUFFER, &end, "\n\n", -1); |
gtk_text_buffer_insert(Shiki_CURRENT_TEXT_BUFFER, &end, "\n\n", -1); |
| 868 |
GtkTextIter p; |
GtkTextIter p; |
| 869 |
append_tabpage(g_strdup("*help*")); |
append_tabpage(g_strdup("*help*")); |
| 870 |
gtk_text_buffer_set_text(Shiki_CURRENT_TEXT_BUFFER, |
gtk_text_buffer_set_text(Shiki_CURRENT_TEXT_BUFFER, |
| 871 |
"起動\n" |
"起動\n" |
| 872 |
"$ ./shiki [file1 file2 ....]\n\n" |
"$ ./shiki [file1 file2 ....]\n\n" |
| 873 |
"[フォルダのアイコン] ファイルを開く (C-x C-f)\n" |
"[フォルダのアイコン] ファイルを開く (C-x C-f)\n" |
| 874 |
"[フロッピーディスクのアイコン] バッファを保存 (C-x C-s)\n" |
"[フロッピーディスクのアイコン] バッファを保存 (C-x C-s)\n" |
| 875 |
"[フロッピーとえんぴつのアイコン] バッファを別名保存 (C-x C-w)\n" |
"[フロッピーとえんぴつのアイコン] バッファを別名保存 (C-x C-w)\n" |
| 876 |
"[ギアのアイコン] 選択領域を gauche にロード (region-compile)\n" |
"[ギアのアイコン] 選択領域を gauche にロード (region-compile)\n" |
| 877 |
"[マーキング (ちょん) のアイコン] タブの on/off\n" |
"[マーキング (ちょん) のアイコン] タブの on/off\n" |
| 878 |
"[工具 (スパナ) のアイコン] タブの位置の調整\n" |
"[工具 (スパナ) のアイコン] タブの位置の調整\n" |
| 879 |
"[まる + アイコン] 新規バッファを開く (Ctrl + t) (tab)\n" |
"[まる + アイコン] 新規バッファを開く (Ctrl + t) (tab)\n" |
| 880 |
"[ゴミ箱アイコン] バッファをクリア\n" |
"[ゴミ箱アイコン] バッファをクリア\n" |
| 881 |
"[× アイコン] バッファを閉じる (Ctrl + k) (kill buffer)\n" |
"[× アイコン] バッファを閉じる (Ctrl + k) (kill buffer)\n" |
| 882 |
"[A アイコン] フォントの選択\n" |
"[A アイコン] フォントの選択\n" |
| 883 |
"[顔みたいなアイコン] Scheme ファイルのロード\n" |
"[顔みたいなアイコン] Scheme ファイルのロード\n" |
| 884 |
"[緑っぽい,変換アイコン] バッファの内容を全てロード\n" |
"[緑っぽい,変換アイコン] バッファの内容を全てロード\n" |
| 885 |
"[ヘルプ (?) アイコン] このヘルプ画面を表示します\n" |
"[ヘルプ (?) アイコン] このヘルプ画面を表示します\n" |
| 886 |
"[info アイコン] このアプリケーションについての情報\n\n" |
"[info アイコン] このアプリケーションについての情報\n\n" |
| 887 |
"C-f : → に移動 (forward)\n" |
"C-f : → に移動 (forward)\n" |
| 888 |
"C-b : ← に移動 (backward)\n" |
"C-b : ← に移動 (backward)\n" |
| 889 |
"C-n : ↓ に移動 (next line)\n" |
"C-n : ↓ に移動 (next line)\n" |
| 890 |
"C-p : ↑ に移動 (previous line)\n\n" |
"C-p : ↑ に移動 (previous line)\n\n" |
| 891 |
"C-h : バックスペース\n\n" |
"C-h : バックスペース\n\n" |
| 892 |
"C-e : カーソル後ろの S 式を評価 (eval-expression)\n" |
"C-e : カーソル後ろの S 式を評価 (eval-expression)\n" |
| 893 |
"C-j : カーソル手前の S 式を評価 (eval-last-sexp)\n" |
"C-j : カーソル手前の S 式を評価 (eval-last-sexp)\n" |
| 894 |
"(emacs/xyzzy の *scratch* バッファと同じ)\n\n" |
"(emacs/xyzzy の *scratch* バッファと同じ)\n\n" |
| 895 |
|
|
| 896 |
"C-x C-c : 終了.ウィンドウの × ボタンを押したのと同じ\n\n" |
"C-x C-c : 終了.ウィンドウの × ボタンを押したのと同じ\n\n" |
| 897 |
|
|
| 898 |
"また,内容が失われる恐れがあるときには全て「Really Quit ?」のように警告します.\n", -1); |
"また,内容が失われる恐れがあるときには全て「Really Quit ?」のように警告します.\n", -1); |
| 899 |
gtk_text_buffer_set_modified(Shiki_CURRENT_TEXT_BUFFER, FALSE); |
gtk_text_buffer_set_modified(Shiki_CURRENT_TEXT_BUFFER, FALSE); |
| 900 |
/* カーソル位置を先頭に */ |
/* カーソル位置を先頭に */ |
| 901 |
gtk_text_buffer_get_start_iter(Shiki_CURRENT_TEXT_BUFFER, &p); |
gtk_text_buffer_get_start_iter(Shiki_CURRENT_TEXT_BUFFER, &p); |
| 902 |
gtk_text_buffer_place_cursor(Shiki_CURRENT_TEXT_BUFFER, &p); |
gtk_text_buffer_place_cursor(Shiki_CURRENT_TEXT_BUFFER, &p); |
| 903 |
} |
} |
| 904 |
|
|
| 905 |
/* エディタの編集画面の初期化 */ |
/* エディタの編集画面の初期化 */ |